310 lines
6.8 KiB
C
310 lines
6.8 KiB
C
/****************************** Module Header ******************************\
|
|
* Module Name: Block.c
|
|
*
|
|
* Purpose: Includes OleServerBlock(), OleServerUnblock() and related routines.
|
|
*
|
|
* Created: Dec. 1990.
|
|
*
|
|
* Copyright (c) 1990, 1991 Microsoft Corporation
|
|
*
|
|
* History:
|
|
* Srinik (../12/1990) Designed, coded
|
|
*
|
|
\***************************************************************************/
|
|
|
|
|
|
#include "cmacs.h"
|
|
#include "windows.h"
|
|
#include "dde.h"
|
|
#include "ole.h"
|
|
#include "srvr.h"
|
|
|
|
|
|
OLESTATUS FAR PASCAL OleBlockServer (lhsrvr)
|
|
LHSERVER lhsrvr;
|
|
{
|
|
LPSRVR lpsrvr;
|
|
|
|
if (!CheckServer (lpsrvr = (LPSRVR) lhsrvr))
|
|
return OLE_ERROR_HANDLE;
|
|
|
|
PROBE_BLOCK(lpsrvr);
|
|
lpsrvr->bBlock = TRUE;
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
// On return from this routine, if *lpStatus is TRUE it means that more
|
|
// messages are to be unblocked.
|
|
|
|
OLESTATUS FAR PASCAL OleUnblockServer (lhsrvr, lpStatus)
|
|
LHSERVER lhsrvr;
|
|
BOOL FAR * lpStatus;
|
|
{
|
|
HANDLE hq;
|
|
PQUE pq;
|
|
LPSRVR lpsrvr;
|
|
|
|
if (!CheckServer (lpsrvr = (LPSRVR) lhsrvr))
|
|
return OLE_ERROR_HANDLE;
|
|
|
|
PROBE_WRITE(lpStatus);
|
|
|
|
*lpStatus = lpsrvr->bBlock;
|
|
if (hq = lpsrvr->hqHead) {
|
|
if (!(pq = (PQUE) LocalLock (hq)))
|
|
return OLE_ERROR_MEMORY;
|
|
lpsrvr->bBlockedMsg = TRUE;
|
|
lpsrvr->hqHead = pq->hqNext;
|
|
SendMessage (pq->hwnd, pq->msg, pq->wParam, pq->lParam);
|
|
LocalUnlock (hq);
|
|
LocalFree (hq);
|
|
|
|
// Server could've got freed up as a result of the above SendMessage
|
|
// Validate server handle before trying to access it.
|
|
if (CheckServer (lpsrvr)) {
|
|
lpsrvr->bBlockedMsg = FALSE;
|
|
|
|
if (!lpsrvr->hqHead) {
|
|
lpsrvr->hqTail = NULL;
|
|
*lpStatus = lpsrvr->bBlock = FALSE;
|
|
}
|
|
}
|
|
else {
|
|
*lpStatus = FALSE;
|
|
}
|
|
}
|
|
else {
|
|
*lpStatus = lpsrvr->bBlock = FALSE;
|
|
}
|
|
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
BOOL INTERNAL AddMessage (hwnd, msg, wParam, lParam, wType)
|
|
HWND hwnd;
|
|
unsigned msg;
|
|
WORD wParam;
|
|
LONG lParam;
|
|
int wType;
|
|
{
|
|
LPSRVR lpsrvr;
|
|
HANDLE hq = NULL;
|
|
PQUE pq = NULL, pqTmp = NULL;
|
|
BOOL bBlocked = TRUE;
|
|
|
|
if ((msg <= WM_DDE_INITIATE) || (msg > WM_DDE_LAST))
|
|
return FALSE;
|
|
|
|
|
|
if (!(lpsrvr = (LPSRVR) GetWindowLong ((wType == WT_DOC) ? GetParent (hwnd) : hwnd, 0)))
|
|
return FALSE;
|
|
|
|
if (lpsrvr->bBlockedMsg || !lpsrvr->bBlock)
|
|
return FALSE;
|
|
|
|
#ifdef LATER
|
|
if ((msg == WM_DDE_INITIATE) && (lpsrvr->useFlags == OLE_SERVER_MULTI))
|
|
return TRUE;
|
|
#endif
|
|
|
|
// Create a queue node and fill up with data
|
|
|
|
if (!(hq = LocalAlloc (LMEM_MOVEABLE, sizeof(QUE))))
|
|
goto errRet;
|
|
|
|
if (!(pq = (PQUE) LocalLock (hq)))
|
|
goto errRet;
|
|
|
|
pq->hwnd = hwnd;
|
|
pq->msg = msg;
|
|
pq->wParam = wParam;
|
|
pq->lParam = lParam;
|
|
pq->hqNext = NULL;
|
|
LocalUnlock (hq);
|
|
|
|
// Now we got a node that we can add to the queue
|
|
|
|
if (!lpsrvr->hqHead) {
|
|
// Queue is empty.
|
|
#ifdef FIREWALLS
|
|
ASSERT (!lpsrvr->hqTail, "Tail is unexpectedly non NULL")
|
|
#endif
|
|
lpsrvr->hqHead = lpsrvr->hqTail = hq;
|
|
}
|
|
else {
|
|
if (!(pqTmp = (PQUE) LocalLock (lpsrvr->hqTail)))
|
|
goto errRet;
|
|
pqTmp->hqNext = hq;
|
|
LocalUnlock(lpsrvr->hqTail);
|
|
lpsrvr->hqTail = hq;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
errRet:
|
|
|
|
if (pq)
|
|
LocalUnlock (hq);
|
|
|
|
if (hq)
|
|
LocalFree (hq);
|
|
|
|
while (bBlocked && !OleUnblockServer ((LHSERVER) lpsrvr, &bBlocked))
|
|
;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
// dispatches the queued message, till all the messages are posted
|
|
// does yielding if necessary. if bPeek is true, may allow some of
|
|
// incoming messages to get in.
|
|
|
|
|
|
BOOL INTERNAL UnblockPostMsgs (hwnd, bPeek)
|
|
HWND hwnd;
|
|
BOOL bPeek;
|
|
{
|
|
HANDLE hq = NULL;
|
|
PQUE pq = NULL;
|
|
LPSRVR lpsrvr;
|
|
HWND hwndTmp;
|
|
|
|
// get the parent windows
|
|
while (hwndTmp = GetParent (hwnd))
|
|
hwnd = hwndTmp;
|
|
|
|
lpsrvr = (LPSRVR) GetWindowLong (hwnd, 0);
|
|
|
|
#ifdef FIREWALLS
|
|
ASSERT (lpsrvr, "No server window handle in server window");
|
|
ASSERT (lpsrvr->hqPostHead, "Unexpectedly blocked queue is empty");
|
|
#endif
|
|
|
|
|
|
while (hq = lpsrvr->hqPostHead) {
|
|
|
|
if (!(pq = (PQUE) LocalLock (hq))) {
|
|
|
|
#ifdef FIREWALLS
|
|
ASSERT (FALSE, "Local lock failed for blocked messages");
|
|
#endif
|
|
break;
|
|
}
|
|
if (IsWindowValid (pq->hwnd)) {
|
|
if (!PostMessage (pq->hwnd, pq->msg, pq->wParam, pq->lParam)) {
|
|
LocalUnlock (hq);
|
|
break;
|
|
}
|
|
}
|
|
|
|
lpsrvr->hqPostHead = pq->hqNext;
|
|
LocalUnlock (hq);
|
|
LocalFree (hq);
|
|
}
|
|
|
|
|
|
if (!lpsrvr->hqPostHead)
|
|
lpsrvr->hqPostTail = NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Moves a message which can not be posted to a server to
|
|
// the internal queue. We use this when we have to enumerate
|
|
// the properties. When we change the properties stuff to
|
|
// some other form, this may not be necassry.
|
|
|
|
BOOL INTERNAL BlockPostMsg (hwnd, msg, wParam, lParam)
|
|
HWND hwnd;
|
|
WORD msg;
|
|
WORD wParam;
|
|
LONG lParam;
|
|
{
|
|
LPSRVR lpsrvr;
|
|
HANDLE hq = NULL;
|
|
PQUE pq = NULL, pqTmp = NULL;
|
|
HWND hwndTmp;
|
|
HWND hwndParent;
|
|
|
|
hwndParent = (HWND)wParam;
|
|
// get the parent windows
|
|
while (hwndTmp = GetParent ((HWND)hwndParent))
|
|
hwndParent = hwndTmp;
|
|
|
|
lpsrvr = (LPSRVR) GetWindowLong (hwndParent, 0);
|
|
|
|
#ifdef FIREWALLS
|
|
ASSERT (lpsrvr, "No server window handle in server window");
|
|
#endif
|
|
|
|
// Create a queue node and fill up with data
|
|
|
|
if (!(hq = LocalAlloc (LMEM_MOVEABLE, sizeof(QUE))))
|
|
goto errRet;
|
|
|
|
if (!(pq = (PQUE) LocalLock (hq)))
|
|
goto errRet;
|
|
|
|
pq->hwnd = hwnd;
|
|
pq->msg = msg;
|
|
pq->wParam = wParam;
|
|
pq->lParam = lParam;
|
|
pq->hqNext = NULL;
|
|
LocalUnlock (hq);
|
|
|
|
// Now we got a node that we can add to the queue
|
|
|
|
if (!lpsrvr->hqPostHead) {
|
|
// Queue is empty.
|
|
#ifdef FIREWALLS
|
|
ASSERT (!lpsrvr->hqPostTail, "Tail is unexpectedly non NULL")
|
|
#endif
|
|
lpsrvr->hqPostHead = lpsrvr->hqPostTail = hq;
|
|
|
|
// create a timer.
|
|
if (!SetTimer (lpsrvr->hwnd, 1, 100, NULL))
|
|
return FALSE;
|
|
|
|
}
|
|
else {
|
|
if (!(pqTmp = (PQUE) LocalLock (lpsrvr->hqPostTail)))
|
|
goto errRet;
|
|
pqTmp->hqNext = hq;
|
|
LocalUnlock(lpsrvr->hqPostTail);
|
|
lpsrvr->hqPostTail = hq;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
errRet:
|
|
|
|
if (pq)
|
|
LocalUnlock (hq);
|
|
|
|
if (hq)
|
|
LocalFree (hq);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL INTERNAL IsBlockQueueEmpty (hwnd)
|
|
HWND hwnd;
|
|
{
|
|
|
|
LPSRVR lpsrvr;
|
|
HWND hwndTmp;
|
|
|
|
// get the parent windows
|
|
while (hwndTmp = GetParent ((HWND)hwnd))
|
|
hwnd= hwndTmp;
|
|
lpsrvr = (LPSRVR) GetWindowLong (hwnd, 0);
|
|
return (!lpsrvr->hqPostHead);
|
|
|
|
|
|
}
|