/****************************** 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 * curts created portable version for WIN16/32 * \***************************************************************************/ #include "windows.h" #include "cmacs.h" #include "dde.h" #include "ole.h" #include "srvr.h" OLESTATUS APIENTRY OleBlockServer ( 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 APIENTRY OleUnblockServer ( 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; if (pq->wType) DocWndProc (pq->hwnd, pq->msg, pq->wParam, pq->lParam); else SrvrWndProc (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 hwnd, UINT msg, WPARAM wParam, LPARAM 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) GetWindowLongPtr ((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->wType = wType; 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 hwnd, BOOL bPeek ){ HANDLE hq = NULL; PQUE pq = NULL; LPSRVR lpsrvr; HWND hwndTmp; UNREFERENCED_PARAMETER(bPeek); // get the parent windows while (hwndTmp = GetParent (hwnd)) hwnd = hwndTmp; lpsrvr = (LPSRVR) GetWindowLongPtr (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 hwnd, UINT msg, WPARAM wParam, LPARAM 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) GetWindowLongPtr (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 ){ LPSRVR lpsrvr; HWND hwndTmp; // get the parent windows while (hwndTmp = GetParent ((HWND)hwnd)) hwnd= hwndTmp; lpsrvr = (LPSRVR) GetWindowLongPtr (hwnd, 0); return (!lpsrvr->hqPostHead); }