Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

318 lines
6.9 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: Block.c
  3. *
  4. * Purpose: Includes OleServerBlock(), OleServerUnblock() and related routines.
  5. *
  6. * Created: Dec. 1990.
  7. *
  8. * Copyright (c) 1990, 1991 Microsoft Corporation
  9. *
  10. * History:
  11. * Srinik (../12/1990) Designed, coded
  12. * curts created portable version for WIN16/32
  13. *
  14. \***************************************************************************/
  15. #include "windows.h"
  16. #include "cmacs.h"
  17. #include "dde.h"
  18. #include "ole.h"
  19. #include "srvr.h"
  20. OLESTATUS APIENTRY OleBlockServer (
  21. LHSERVER lhsrvr
  22. ){
  23. LPSRVR lpsrvr;
  24. if (!CheckServer (lpsrvr = (LPSRVR) lhsrvr))
  25. return OLE_ERROR_HANDLE;
  26. PROBE_BLOCK(lpsrvr);
  27. lpsrvr->bBlock = TRUE;
  28. return OLE_OK;
  29. }
  30. // On return from this routine, if *lpStatus is TRUE it means that more
  31. // messages are to be unblocked.
  32. OLESTATUS APIENTRY OleUnblockServer (
  33. LHSERVER lhsrvr,
  34. BOOL FAR * lpStatus
  35. ){
  36. HANDLE hq;
  37. PQUE pq;
  38. LPSRVR lpsrvr;
  39. if (!CheckServer (lpsrvr = (LPSRVR) lhsrvr))
  40. return OLE_ERROR_HANDLE;
  41. PROBE_WRITE(lpStatus);
  42. *lpStatus = lpsrvr->bBlock;
  43. if (hq = lpsrvr->hqHead) {
  44. if (!(pq = (PQUE) LocalLock (hq)))
  45. return OLE_ERROR_MEMORY;
  46. lpsrvr->bBlockedMsg = TRUE;
  47. lpsrvr->hqHead = pq->hqNext;
  48. if (pq->wType)
  49. DocWndProc (pq->hwnd, pq->msg, pq->wParam, pq->lParam);
  50. else
  51. SrvrWndProc (pq->hwnd, pq->msg, pq->wParam, pq->lParam);
  52. LocalUnlock (hq);
  53. LocalFree (hq);
  54. // Server could've got freed up as a result of the above SendMessage
  55. // Validate server handle before trying to access it.
  56. if (CheckServer (lpsrvr)) {
  57. lpsrvr->bBlockedMsg = FALSE;
  58. if (!lpsrvr->hqHead) {
  59. lpsrvr->hqTail = NULL;
  60. *lpStatus = lpsrvr->bBlock = FALSE;
  61. }
  62. }
  63. else {
  64. *lpStatus = FALSE;
  65. }
  66. }
  67. else {
  68. *lpStatus = lpsrvr->bBlock = FALSE;
  69. }
  70. return OLE_OK;
  71. }
  72. BOOL INTERNAL AddMessage (
  73. HWND hwnd,
  74. UINT msg,
  75. WPARAM wParam,
  76. LPARAM lParam,
  77. int wType
  78. ){
  79. LPSRVR lpsrvr;
  80. HANDLE hq = NULL;
  81. PQUE pq = NULL, pqTmp = NULL;
  82. BOOL bBlocked = TRUE;
  83. if ((msg <= WM_DDE_INITIATE) || (msg > WM_DDE_LAST))
  84. return FALSE;
  85. if (!(lpsrvr = (LPSRVR) GetWindowLongPtr ((wType == WT_DOC) ? GetParent (hwnd) : hwnd, 0)))
  86. return FALSE;
  87. if (lpsrvr->bBlockedMsg || !lpsrvr->bBlock)
  88. return FALSE;
  89. #ifdef LATER
  90. if ((msg == WM_DDE_INITIATE) && (lpsrvr->useFlags == OLE_SERVER_MULTI))
  91. return TRUE;
  92. #endif
  93. // Create a queue node and fill up with data
  94. if (!(hq = LocalAlloc (LMEM_MOVEABLE, sizeof(QUE))))
  95. goto errRet;
  96. if (!(pq = (PQUE) LocalLock (hq)))
  97. goto errRet;
  98. pq->hwnd = hwnd;
  99. pq->msg = msg;
  100. pq->wParam = wParam;
  101. pq->lParam = lParam;
  102. pq->wType = wType;
  103. pq->hqNext = NULL;
  104. LocalUnlock (hq);
  105. // Now we got a node that we can add to the queue
  106. if (!lpsrvr->hqHead) {
  107. // Queue is empty.
  108. #ifdef FIREWALLS
  109. ASSERT (!lpsrvr->hqTail, "Tail is unexpectedly non NULL")
  110. #endif
  111. lpsrvr->hqHead = lpsrvr->hqTail = hq;
  112. }
  113. else {
  114. if (!(pqTmp = (PQUE) LocalLock (lpsrvr->hqTail)))
  115. goto errRet;
  116. pqTmp->hqNext = hq;
  117. LocalUnlock(lpsrvr->hqTail);
  118. lpsrvr->hqTail = hq;
  119. }
  120. return TRUE;
  121. errRet:
  122. if (pq)
  123. LocalUnlock (hq);
  124. if (hq)
  125. LocalFree (hq);
  126. while (bBlocked && !OleUnblockServer ((LHSERVER) lpsrvr, &bBlocked))
  127. ;
  128. return FALSE;
  129. }
  130. // dispatches the queued message, till all the messages are posted
  131. // does yielding if necessary. if bPeek is true, may allow some of
  132. // incoming messages to get in.
  133. BOOL INTERNAL UnblockPostMsgs (
  134. HWND hwnd,
  135. BOOL bPeek
  136. ){
  137. HANDLE hq = NULL;
  138. PQUE pq = NULL;
  139. LPSRVR lpsrvr;
  140. HWND hwndTmp;
  141. UNREFERENCED_PARAMETER(bPeek);
  142. // get the parent windows
  143. while (hwndTmp = GetParent (hwnd))
  144. hwnd = hwndTmp;
  145. lpsrvr = (LPSRVR) GetWindowLongPtr (hwnd, 0);
  146. #ifdef FIREWALLS
  147. ASSERT (lpsrvr, "No server window handle in server window");
  148. ASSERT (lpsrvr->hqPostHead, "Unexpectedly blocked queue is empty");
  149. #endif
  150. while (hq = lpsrvr->hqPostHead) {
  151. if (!(pq = (PQUE) LocalLock (hq))) {
  152. #ifdef FIREWALLS
  153. ASSERT (FALSE, "Local lock failed for blocked messages");
  154. #endif
  155. break;
  156. }
  157. if (IsWindowValid (pq->hwnd)) {
  158. if (!PostMessage (pq->hwnd, pq->msg, pq->wParam, pq->lParam)) {
  159. LocalUnlock (hq);
  160. break;
  161. }
  162. }
  163. lpsrvr->hqPostHead = pq->hqNext;
  164. LocalUnlock (hq);
  165. LocalFree (hq);
  166. }
  167. if (!lpsrvr->hqPostHead)
  168. lpsrvr->hqPostTail = NULL;
  169. return TRUE;
  170. }
  171. // Moves a message which can not be posted to a server to
  172. // the internal queue. We use this when we have to enumerate
  173. // the properties. When we change the properties stuff to
  174. // some other form, this may not be necassry.
  175. BOOL INTERNAL BlockPostMsg (
  176. HWND hwnd,
  177. UINT msg,
  178. WPARAM wParam,
  179. LPARAM lParam
  180. ){
  181. LPSRVR lpsrvr;
  182. HANDLE hq = NULL;
  183. PQUE pq = NULL, pqTmp = NULL;
  184. HWND hwndTmp;
  185. HWND hwndParent;
  186. hwndParent = (HWND)wParam;
  187. // get the parent windows
  188. while (hwndTmp = GetParent ((HWND)hwndParent))
  189. hwndParent = hwndTmp;
  190. lpsrvr = (LPSRVR) GetWindowLongPtr (hwndParent, 0);
  191. #ifdef FIREWALLS
  192. ASSERT (lpsrvr, "No server window handle in server window");
  193. #endif
  194. // Create a queue node and fill up with data
  195. if (!(hq = LocalAlloc (LMEM_MOVEABLE, sizeof(QUE))))
  196. goto errRet;
  197. if (!(pq = (PQUE) LocalLock (hq)))
  198. goto errRet;
  199. pq->hwnd = hwnd;
  200. pq->msg = msg;
  201. pq->wParam = wParam;
  202. pq->lParam = lParam;
  203. pq->hqNext = NULL;
  204. LocalUnlock (hq);
  205. // Now we got a node that we can add to the queue
  206. if (!lpsrvr->hqPostHead) {
  207. // Queue is empty.
  208. #ifdef FIREWALLS
  209. ASSERT (!lpsrvr->hqPostTail, "Tail is unexpectedly non NULL")
  210. #endif
  211. lpsrvr->hqPostHead = lpsrvr->hqPostTail = hq;
  212. // create a timer.
  213. if (!SetTimer (lpsrvr->hwnd, 1, 100, NULL))
  214. return FALSE;
  215. }
  216. else {
  217. if (!(pqTmp = (PQUE) LocalLock (lpsrvr->hqPostTail)))
  218. goto errRet;
  219. pqTmp->hqNext = hq;
  220. LocalUnlock(lpsrvr->hqPostTail);
  221. lpsrvr->hqPostTail = hq;
  222. }
  223. return TRUE;
  224. errRet:
  225. if (pq)
  226. LocalUnlock (hq);
  227. if (hq)
  228. LocalFree (hq);
  229. return FALSE;
  230. }
  231. BOOL INTERNAL IsBlockQueueEmpty (
  232. HWND hwnd
  233. ){
  234. LPSRVR lpsrvr;
  235. HWND hwndTmp;
  236. // get the parent windows
  237. while (hwndTmp = GetParent ((HWND)hwnd))
  238. hwnd= hwndTmp;
  239. lpsrvr = (LPSRVR) GetWindowLongPtr (hwnd, 0);
  240. return (!lpsrvr->hqPostHead);
  241. }