Leaked source code of windows server 2003
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.

852 lines
26 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: ddemlwp.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * DDE Manager client side window procedures
  7. *
  8. * Created: 11/3/91 Sanford Staab
  9. \***************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. VOID ProcessDDEMLInitiate(PCL_INSTANCE_INFO pcii, HWND hwndClient,
  13. GATOM aServer, GATOM aTopic);
  14. /***************************************************************************\
  15. * DDEMLMotherWndProc
  16. *
  17. * Description:
  18. * Handles WM_DDE_INITIATE messages for DDEML and holds all the other windows
  19. * for a DDEML instance.
  20. *
  21. * History:
  22. * 12-29-92 sanfords Created.
  23. \***************************************************************************/
  24. LRESULT DDEMLMotherWndProc(
  25. HWND hwnd,
  26. UINT message,
  27. WPARAM wParam,
  28. LPARAM lParam)
  29. {
  30. switch (message) {
  31. case UM_REGISTER:
  32. case UM_UNREGISTER:
  33. return(ProcessRegistrationMessage(hwnd, message, wParam, lParam));
  34. case WM_DDE_INITIATE:
  35. ProcessDDEMLInitiate((PCL_INSTANCE_INFO)GetWindowLongPtr(hwnd, GWLP_PCI),
  36. (HWND)wParam, (ATOM)LOWORD(lParam), (ATOM)HIWORD(lParam));
  37. return(0);
  38. }
  39. return(DefWindowProc(hwnd, message, wParam, lParam));
  40. }
  41. /***************************************************************************\
  42. * ProcessDDEMLInitiate
  43. *
  44. * Description:
  45. *
  46. * WM_DDE_INITIATE messages are processed here.
  47. *
  48. * History:
  49. * 12-29-92 sanfords Created.
  50. \***************************************************************************/
  51. VOID ProcessDDEMLInitiate(
  52. PCL_INSTANCE_INFO pcii,
  53. HWND hwndClient,
  54. GATOM aServer,
  55. GATOM aTopic)
  56. {
  57. CONVCONTEXT cc = {
  58. sizeof(CONVCONTEXT),
  59. 0,
  60. 0,
  61. CP_WINANSI,
  62. 0L,
  63. 0L,
  64. {
  65. sizeof(SECURITY_QUALITY_OF_SERVICE),
  66. SecurityImpersonation,
  67. SECURITY_STATIC_TRACKING,
  68. TRUE
  69. }
  70. };
  71. BOOL flags = ST_INLIST;
  72. BOOL fWild;
  73. HDDEDATA hData;
  74. HWND hwndServer;
  75. PSERVER_LOOKUP psl;
  76. PHSZPAIR php;
  77. HSZPAIR hp[2];
  78. LATOM laService, laFree1 = 0;
  79. LATOM laTopic, laFree2 = 0;
  80. PSVR_CONV_INFO psi;
  81. LATOM *plaNameService;
  82. PWND pwndClient;
  83. PCLS pcls;
  84. if (pcii == NULL) {
  85. return; // we aren't done being initiated yet.
  86. }
  87. EnterDDECrit;
  88. if (pcii->afCmd & CBF_FAIL_CONNECTIONS || !IsWindow(hwndClient)) {
  89. goto Exit;
  90. }
  91. pwndClient = ValidateHwnd(hwndClient);
  92. if (pwndClient == NULL) goto Exit;
  93. pcls = (PCLS)REBASEALWAYS(pwndClient, pcls);
  94. if (!TestWF(pwndClient, WFANSIPROC)) {
  95. if (pcls->atomClassName == gpsi->atomSysClass[ICLS_DDEMLCLIENTW]) {
  96. flags |= ST_ISLOCAL;
  97. }
  98. } else {
  99. if (pcls->atomClassName == gpsi->atomSysClass[ICLS_DDEMLCLIENTA]) {
  100. flags |= ST_ISLOCAL;
  101. }
  102. }
  103. if (flags & ST_ISLOCAL) {
  104. /*
  105. * Make sure other guy allows self-connections if that's what this is.
  106. */
  107. if (pcii->hInstServer == (HANDLE)GetWindowLongPtr(hwndClient, GWLP_SHINST)) {
  108. if (pcii->afCmd & CBF_FAIL_SELFCONNECTIONS) {
  109. goto Exit;
  110. }
  111. flags |= ST_ISSELF;
  112. }
  113. GetConvContext(hwndClient, (LONG *)&cc);
  114. if (GetWindowLong(hwndClient, GWL_CONVSTATE) & CLST_SINGLE_INITIALIZING) {
  115. flags &= ~ST_INLIST;
  116. }
  117. } else {
  118. NtUserDdeGetQualityOfService(hwndClient, NULL, &cc.qos);
  119. }
  120. /***************************************************************************\
  121. *
  122. * Server window creation is minimized by only creating one window per
  123. * Instance/Service/Topic set. This should be all that is needed and
  124. * duplicate connections (ie where the server/client window pair is identical
  125. * to another conversation) should not happen. However, if some dumb
  126. * server app attempts to create a duplicate conversation by having
  127. * duplicate service/topic pairs passed back from a XTYP_WILD_CONNECT
  128. * callback we will not honor the request.
  129. *
  130. * The INSTANCE_INFO structure holds a pointer to an array of SERVERLOOKUP
  131. * structures each entry of which references the hwndServer that supports
  132. * all conversations on that service/topic pair. The hwndServer windows
  133. * in turn have window words that reference the first member in a linked
  134. * list of SVR_CONV_INFO structures, one for each conversation on that
  135. * service/topic pair.
  136. *
  137. \***************************************************************************/
  138. laFree1 = laService = GlobalToLocalAtom(aServer);
  139. laFree2 = laTopic = GlobalToLocalAtom(aTopic);
  140. plaNameService = pcii->plaNameService;
  141. if (!laService && pcii->afCmd & APPCMD_FILTERINITS && *plaNameService == 0) {
  142. /*
  143. * no WILDCONNECTS to servers with no registered names while filtering.
  144. */
  145. goto Exit;
  146. }
  147. if ((pcii->afCmd & APPCMD_FILTERINITS) && laService) {
  148. /*
  149. * if we can't find the aServer in this instance's service name
  150. * list, don't bother the server.
  151. */
  152. while (*plaNameService != 0 && *plaNameService != laService) {
  153. plaNameService++;
  154. }
  155. if (*plaNameService == 0) {
  156. goto Exit;
  157. }
  158. }
  159. hp[0].hszSvc = NORMAL_HSZ_FROM_LATOM(laService);
  160. hp[0].hszTopic = NORMAL_HSZ_FROM_LATOM(laTopic);
  161. hp[1].hszSvc = 0;
  162. hp[1].hszTopic = 0;
  163. fWild = !laService || !laTopic;
  164. hData = DoCallback(pcii,
  165. (WORD)(fWild ? XTYP_WILDCONNECT : XTYP_CONNECT),
  166. 0,
  167. (HCONV)0,
  168. hp[0].hszTopic,
  169. hp[0].hszSvc,
  170. (HDDEDATA)0,
  171. flags & ST_ISLOCAL ? (ULONG_PTR)&cc : 0,
  172. (DWORD)(flags & ST_ISSELF) ? 1 : 0);
  173. if (!hData) {
  174. goto Exit;
  175. }
  176. if (fWild) {
  177. php = (PHSZPAIR)DdeAccessData(hData, NULL);
  178. if (php == NULL) {
  179. goto Exit;
  180. }
  181. } else {
  182. php = hp;
  183. }
  184. while (php->hszSvc && php->hszTopic) {
  185. psi = (PSVR_CONV_INFO)DDEMLAlloc(sizeof(SVR_CONV_INFO));
  186. if (psi == NULL) {
  187. break;
  188. }
  189. laService = LATOM_FROM_HSZ(php->hszSvc);
  190. laTopic = LATOM_FROM_HSZ(php->hszTopic);
  191. hwndServer = 0;
  192. if (pcii->cServerLookupAlloc) {
  193. int i;
  194. /*
  195. * See if there already exists a server window for this
  196. * aServer/aTopic pair
  197. */
  198. for (i = pcii->cServerLookupAlloc; i; i--) {
  199. if (pcii->aServerLookup[i - 1].laService == laService &&
  200. pcii->aServerLookup[i - 1].laTopic == laTopic) {
  201. PSVR_CONV_INFO psiT;
  202. PCONV_INFO pcoi;
  203. hwndServer = pcii->aServerLookup[i - 1].hwndServer;
  204. /*
  205. * Now make sure this window isn't someone
  206. * trying to create a second conversation from the
  207. * same client window that is already talking to
  208. * our existing server window.
  209. */
  210. psiT = (PSVR_CONV_INFO)GetWindowLongPtr(hwndServer, GWLP_PSI);
  211. for (pcoi = &psiT->ci; pcoi != NULL; pcoi = pcoi->next) {
  212. if (pcoi->hwndPartner == hwndClient) {
  213. hwndServer = NULL;
  214. break;
  215. }
  216. }
  217. break;
  218. }
  219. }
  220. }
  221. if (hwndServer == 0) {
  222. // no server window exists - make one.
  223. LeaveDDECrit;
  224. if (pcii->flags & IIF_UNICODE) {
  225. hwndServer = CreateWindowW((LPWSTR)(gpsi->atomSysClass[ICLS_DDEMLSERVERW]),
  226. L"",
  227. WS_CHILD,
  228. 0, 0, 0, 0,
  229. pcii->hwndMother,
  230. (HMENU)0,
  231. 0,
  232. (LPVOID)NULL);
  233. } else {
  234. hwndServer = CreateWindowA((LPSTR)(gpsi->atomSysClass[ICLS_DDEMLSERVERA]),
  235. "",
  236. WS_CHILD,
  237. 0, 0, 0, 0,
  238. pcii->hwndMother,
  239. (HMENU)0,
  240. 0,
  241. (LPVOID)NULL);
  242. }
  243. EnterDDECrit;
  244. if (hwndServer == 0) {
  245. DDEMLFree(psi);
  246. break;
  247. }
  248. // SetWindowLongPtr(hwndServer, GWLP_PSI, (LONG)NULL); // Zero init.
  249. // put the window into the lookup list
  250. if (pcii->aServerLookup == NULL) {
  251. psl = (PSERVER_LOOKUP)DDEMLAlloc(sizeof(SERVER_LOOKUP));
  252. } else {
  253. psl = (PSERVER_LOOKUP)DDEMLReAlloc(pcii->aServerLookup,
  254. sizeof(SERVER_LOOKUP) * (pcii->cServerLookupAlloc + 1));
  255. }
  256. if (psl == NULL) {
  257. RIPMSG1(RIP_WARNING, "ProcessDDEMLInitiate:hwndServer (%x) destroyed due to low memory.", hwndServer);
  258. NtUserDestroyWindow(hwndServer);
  259. DDEMLFree(psi);
  260. break;
  261. }
  262. IncLocalAtomCount(laService); // for SERVER_LOOKUP
  263. psl[pcii->cServerLookupAlloc].laService = laService;
  264. IncLocalAtomCount(laTopic); // for SERVER_LOOKUP
  265. psl[pcii->cServerLookupAlloc].laTopic = laTopic;
  266. psl[pcii->cServerLookupAlloc].hwndServer = hwndServer;
  267. pcii->aServerLookup = psl;
  268. pcii->cServerLookupAlloc++;
  269. // DumpServerLookupTable("After addition:", hwndServer, psl, pcii->cServerLookupAlloc);
  270. }
  271. psi->ci.next = (PCONV_INFO)GetWindowLongPtr(hwndServer, GWLP_PSI);
  272. SetWindowLongPtr(hwndServer, GWLP_PSI, (LONG_PTR)psi);
  273. psi->ci.pcii = pcii;
  274. // psi->ci.hUser = 0;
  275. psi->ci.hConv = (HCONV)CreateHandle((ULONG_PTR)psi,
  276. HTYPE_SERVER_CONVERSATION, InstFromHandle(pcii->hInstClient));
  277. psi->ci.laService = laService;
  278. IncLocalAtomCount(laService); // for server window
  279. psi->ci.laTopic = laTopic;
  280. IncLocalAtomCount(laTopic); // for server window
  281. psi->ci.hwndPartner = hwndClient;
  282. psi->ci.hwndConv = hwndServer;
  283. psi->ci.state = (WORD)(flags | ST_CONNECTED | pcii->ConvStartupState);
  284. SetCommonStateFlags(hwndClient, hwndServer, &psi->ci.state);
  285. psi->ci.laServiceRequested = laFree1;
  286. IncLocalAtomCount(psi->ci.laServiceRequested); // for server window
  287. // psi->ci.pxiIn = NULL;
  288. // psi->ci.pxiOut = NULL;
  289. // psi->ci.dmqIn = NULL;
  290. // psi->ci.dmqOut = NULL;
  291. // psi->ci.aLinks = NULL;
  292. // psi->ci.cLinks = 0;
  293. // psi->ci.cLocks = 0;
  294. LeaveDDECrit;
  295. CheckDDECritOut;
  296. SendMessage(hwndClient, WM_DDE_ACK, (WPARAM)hwndServer,
  297. MAKELONG(LocalToGlobalAtom(laService), LocalToGlobalAtom(laTopic)));
  298. EnterDDECrit;
  299. if (!(pcii->afCmd & CBF_SKIP_CONNECT_CONFIRMS)) {
  300. DoCallback(pcii,
  301. (WORD)XTYP_CONNECT_CONFIRM,
  302. 0,
  303. psi->ci.hConv,
  304. (HSZ)laTopic,
  305. (HSZ)laService,
  306. (HDDEDATA)0,
  307. 0,
  308. (flags & ST_ISSELF) ? 1L : 0L);
  309. }
  310. MONCONV((PCONV_INFO)psi, TRUE);
  311. if (!(flags & ST_INLIST)) {
  312. break; // our partner's only gonna take the first one anyway.
  313. }
  314. php++;
  315. }
  316. if (fWild) {
  317. DdeUnaccessData(hData);
  318. InternalFreeDataHandle(hData, FALSE);
  319. }
  320. Exit:
  321. DeleteAtom(laFree1);
  322. DeleteAtom(laFree2);
  323. LeaveDDECrit;
  324. return;
  325. }
  326. /***************************************************************************\
  327. * DDEMLClientWndProc
  328. *
  329. * Description:
  330. * Handles DDE client messages for DDEML.
  331. *
  332. * History:
  333. * 11-12-91 sanfords Created.
  334. \***************************************************************************/
  335. LRESULT DDEMLClientWndProc(
  336. HWND hwnd,
  337. UINT message,
  338. WPARAM wParam,
  339. LPARAM lParam)
  340. {
  341. PCL_CONV_INFO pci, pciNew;
  342. LONG lState;
  343. LRESULT lRet = 0;
  344. PWND pwnd;
  345. PCLS pcls;
  346. EnterDDECrit;
  347. pci = (PCL_CONV_INFO)GetWindowLongPtr(hwnd, GWLP_PCI);
  348. UserAssert(pci == NULL || pci->ci.hwndConv == hwnd);
  349. switch (message) {
  350. case WM_DDE_ACK:
  351. lState = GetWindowLong(hwnd, GWL_CONVSTATE);
  352. if (lState != CLST_CONNECTED) {
  353. // Initiation mode
  354. pciNew = (PCL_CONV_INFO)DDEMLAlloc(sizeof(CL_CONV_INFO));
  355. if (pciNew == NULL ||
  356. (pci != NULL && lState == CLST_SINGLE_INITIALIZING)) {
  357. PostMessage((HWND)wParam, WM_DDE_TERMINATE, (WPARAM)hwnd, 0);
  358. goto Exit;
  359. }
  360. // PCL_CONV_INFO initialization
  361. pciNew->ci.pcii = ValidateInstance((HANDLE)GetWindowLongPtr(hwnd, GWLP_CHINST));
  362. if (pciNew->ci.pcii == NULL) {
  363. DDEMLFree(pciNew);
  364. goto Exit;
  365. }
  366. pciNew->ci.next = (PCONV_INFO)pci; // pci may be NULL
  367. //
  368. // Seting GWLP_PCI gives feedback to ConnectConv() which issued
  369. // the WM_DDE_INITIATE message.
  370. //
  371. SetWindowLongPtr(hwnd, GWLP_PCI, (LONG_PTR)pciNew);
  372. // pciNew->hUser = 0; // Zero init.
  373. // BUG: If this fails we can have some nasty problems
  374. pciNew->ci.hConv = (HCONV)CreateHandle((ULONG_PTR)pciNew,
  375. HTYPE_CLIENT_CONVERSATION, InstFromHandle(pciNew->ci.pcii->hInstClient));
  376. pciNew->ci.laService = GlobalToLocalAtom(LOWORD(lParam)); // pci copy
  377. GlobalDeleteAtom(LOWORD(lParam));
  378. pciNew->ci.laTopic = GlobalToLocalAtom(HIWORD(lParam)); // pci copy
  379. GlobalDeleteAtom(HIWORD(lParam));
  380. pciNew->ci.hwndPartner = (HWND)wParam;
  381. pciNew->ci.hwndConv = hwnd;
  382. pciNew->ci.state = (WORD)(ST_CONNECTED | ST_CLIENT |
  383. pciNew->ci.pcii->ConvStartupState);
  384. SetCommonStateFlags(hwnd, (HWND)wParam, &pciNew->ci.state);
  385. pwnd = ValidateHwnd((HWND)wParam);
  386. if (pwnd == NULL) goto Exit;
  387. pcls = (PCLS)REBASEALWAYS(pwnd, pcls);
  388. if (!TestWF(pwnd, WFANSIPROC)) {
  389. if (pcls->atomClassName == gpsi->atomSysClass[ICLS_DDEMLSERVERW]) {
  390. pciNew->ci.state |= ST_ISLOCAL;
  391. }
  392. } else {
  393. if (pcls->atomClassName == gpsi->atomSysClass[ICLS_DDEMLSERVERA]) {
  394. pciNew->ci.state |= ST_ISLOCAL;
  395. }
  396. }
  397. // pciNew->ci.laServiceRequested = 0; // Set by InitiateEnumerationProc()
  398. // pciNew->ci.pxiIn = 0;
  399. // pciNew->ci.pxiOut = 0;
  400. // pciNew->ci.dmqIn = 0;
  401. // pciNew->ci.dmqOut = 0;
  402. // pciNew->ci.aLinks = NULL;
  403. // pciNew->ci.cLinks = 0;
  404. // pciNew->ci.cLocks = 0;
  405. goto Exit;
  406. }
  407. // fall through to handle posted messages here.
  408. case WM_DDE_DATA:
  409. ProcessAsyncDDEMsg((PCONV_INFO)pci, message, (HWND)wParam, lParam);
  410. goto Exit;
  411. case WM_DDE_TERMINATE:
  412. case WM_DESTROY:
  413. {
  414. ProcessTerminateMsg((PCONV_INFO)pci, (HWND)wParam);
  415. break;
  416. }
  417. }
  418. lRet = DefWindowProc(hwnd, message, wParam, lParam);
  419. Exit:
  420. LeaveDDECrit;
  421. return (lRet);
  422. }
  423. /***************************************************************************\
  424. * DDEMLServerWndProc
  425. *
  426. * Description:
  427. * Handles DDE server messages.
  428. *
  429. * History:
  430. * 11-12-91 sanfords Created.
  431. \***************************************************************************/
  432. LRESULT DDEMLServerWndProc(
  433. HWND hwnd,
  434. UINT message,
  435. WPARAM wParam,
  436. LPARAM lParam)
  437. {
  438. PSVR_CONV_INFO psi;
  439. LRESULT lRet = 0;
  440. EnterDDECrit;
  441. psi = (PSVR_CONV_INFO)GetWindowLongPtr(hwnd, GWLP_PSI);
  442. UserAssert(psi == NULL || psi->ci.hwndConv == hwnd);
  443. switch (message) {
  444. case WM_DDE_REQUEST:
  445. case WM_DDE_POKE:
  446. case WM_DDE_ADVISE:
  447. case WM_DDE_EXECUTE:
  448. case WM_DDE_ACK:
  449. case WM_DDE_UNADVISE:
  450. ProcessAsyncDDEMsg((PCONV_INFO)psi, message, (HWND)wParam, lParam);
  451. goto Exit;
  452. case WM_DDE_TERMINATE:
  453. case WM_DESTROY:
  454. ProcessTerminateMsg((PCONV_INFO)psi, (HWND)wParam);
  455. break;
  456. }
  457. lRet = DefWindowProc(hwnd, message, wParam, lParam);
  458. Exit:
  459. LeaveDDECrit;
  460. return (lRet);
  461. }
  462. /***************************************************************************\
  463. * ProcessTerminateMsg
  464. *
  465. * Description:
  466. * Handles WM_DDE_TERMINATE messages for both sides.
  467. *
  468. * History:
  469. * 11-26-91 sanfords Created.
  470. \***************************************************************************/
  471. PCONV_INFO ProcessTerminateMsg(
  472. PCONV_INFO pcoi,
  473. HWND hwndFrom)
  474. {
  475. while (pcoi != NULL && pcoi->hwndPartner != hwndFrom) {
  476. pcoi = pcoi->next;
  477. }
  478. if (pcoi != NULL) {
  479. pcoi->state |= ST_TERMINATE_RECEIVED;
  480. ShutdownConversation(pcoi, TRUE);
  481. }
  482. return (pcoi);
  483. }
  484. /***************************************************************************\
  485. * ProcessAsyncDDEMsg
  486. *
  487. * Description:
  488. * Handles incoming DDE messages by either calling ProcessSyncDDEMessage()
  489. * if the conversation is able to handle callbacks, or by queuing the
  490. * incoming message into the conversations message queue. Doing this
  491. * allows simpler code in that no message is processed unless the code
  492. * can perform synchronous callbacks.
  493. *
  494. * History:
  495. * 11-26-91 sanfords Created.
  496. \***************************************************************************/
  497. VOID ProcessAsyncDDEMsg(
  498. PCONV_INFO pcoi,
  499. UINT msg,
  500. HWND hwndFrom,
  501. LPARAM lParam)
  502. {
  503. PDDE_MESSAGE_QUEUE pdmq;
  504. #if DBG
  505. HWND hwndT = pcoi->hwndConv;
  506. #endif // DBG
  507. while (pcoi != NULL && pcoi->hwndPartner != hwndFrom) {
  508. pcoi = pcoi->next;
  509. }
  510. if (pcoi == NULL) {
  511. RIPMSG3(RIP_WARNING,
  512. "Bogus DDE message %x received from %x by %x. Dumping.",
  513. msg, hwndFrom, hwndT);
  514. DumpDDEMessage(FALSE, msg, lParam);
  515. return ;
  516. }
  517. if (pcoi->state & ST_CONNECTED) {
  518. if (pcoi->dmqOut == NULL &&
  519. !(pcoi->state & ST_BLOCKED)
  520. // && !PctiCurrent()->cInDDEMLCallback
  521. ) {
  522. if (ProcessSyncDDEMessage(pcoi, msg, lParam)) {
  523. return; // not blocked, ok to return.
  524. }
  525. }
  526. // enter into queue
  527. pdmq = DDEMLAlloc(sizeof(DDE_MESSAGE_QUEUE));
  528. if (pdmq == NULL) {
  529. // insufficient memory - we can't process this msg - we MUST
  530. // terminate.
  531. if (pcoi->state & ST_CONNECTED) {
  532. PostMessage(pcoi->hwndPartner, WM_DDE_TERMINATE,
  533. (WPARAM)pcoi->hwndConv, 0);
  534. pcoi->state &= ~ST_CONNECTED;
  535. }
  536. DumpDDEMessage(!(pcoi->state & ST_INTRA_PROCESS), msg, lParam);
  537. return ;
  538. }
  539. pdmq->pcoi = pcoi;
  540. pdmq->msg = msg;
  541. pdmq->lParam = lParam;
  542. pdmq->next = NULL;
  543. // dmqOut->next->next->next->dmqIn->NULL
  544. if (pcoi->dmqIn != NULL) {
  545. pcoi->dmqIn->next = pdmq;
  546. }
  547. pcoi->dmqIn = pdmq;
  548. if (pcoi->dmqOut == NULL) {
  549. pcoi->dmqOut = pcoi->dmqIn;
  550. }
  551. pcoi->cLocks++;
  552. CheckForQueuedMessages(pcoi);
  553. pcoi->cLocks--;
  554. if (pcoi->cLocks == 0 && pcoi->state & ST_FREE_CONV_RES_NOW) {
  555. FreeConversationResources(pcoi);
  556. }
  557. } else {
  558. DumpDDEMessage(!(pcoi->state & ST_INTRA_PROCESS), msg, lParam);
  559. }
  560. }
  561. /***************************************************************************\
  562. * CheckForQueuedMessages
  563. *
  564. * Description:
  565. * Handles processing of DDE messages held in the given conversaion's
  566. * DDE message queue.
  567. *
  568. * Returns: fProcessed.
  569. *
  570. * History:
  571. * 11-12-91 sanfords Created.
  572. \***************************************************************************/
  573. BOOL CheckForQueuedMessages(
  574. PCONV_INFO pcoi)
  575. {
  576. PDDE_MESSAGE_QUEUE pdmq;
  577. BOOL fRet = FALSE;
  578. PCLIENTINFO pci;
  579. CheckDDECritIn;
  580. if (pcoi->state & ST_PROCESSING) { // recursion prevention
  581. return(FALSE);
  582. }
  583. UserAssert(pcoi->cLocks);
  584. pci = GetClientInfo();
  585. pcoi->state |= ST_PROCESSING;
  586. while (!(pcoi->state & ST_BLOCKED) &&
  587. pcoi->dmqOut != NULL &&
  588. !pci->cInDDEMLCallback) {
  589. pci->CI_flags |= CI_PROCESSING_QUEUE;
  590. if (ProcessSyncDDEMessage(pcoi, pcoi->dmqOut->msg, pcoi->dmqOut->lParam)) {
  591. fRet = TRUE;
  592. pdmq = pcoi->dmqOut;
  593. pcoi->dmqOut = pcoi->dmqOut->next;
  594. if (pcoi->dmqOut == NULL) {
  595. pcoi->dmqIn = NULL;
  596. }
  597. DDEMLFree(pdmq);
  598. }
  599. pci->CI_flags &= ~CI_PROCESSING_QUEUE;
  600. }
  601. pcoi->state &= ~ST_PROCESSING;
  602. return(fRet);
  603. }
  604. /***************************************************************************\
  605. * DumpDDEMessage
  606. *
  607. * Description:
  608. * Used to clean up resources referenced by DDE messages that for some
  609. * reason could not be processed.
  610. *
  611. * History:
  612. * 11-12-91 sanfords Created.
  613. \***************************************************************************/
  614. VOID DumpDDEMessage(
  615. BOOL fFreeData,
  616. UINT msg,
  617. LPARAM lParam)
  618. {
  619. UINT_PTR uiLo, uiHi;
  620. RIPMSG2(RIP_WARNING, "Dump DDE msg %x lParam %x", msg, lParam);
  621. switch (msg) {
  622. case WM_DDE_ACK:
  623. case WM_DDE_DATA:
  624. case WM_DDE_POKE:
  625. case WM_DDE_ADVISE:
  626. UnpackDDElParam(msg, lParam, &uiLo, &uiHi);
  627. switch (msg) {
  628. case WM_DDE_DATA:
  629. case WM_DDE_POKE:
  630. if (uiLo) {
  631. if (fFreeData) {
  632. FreeDDEData((HANDLE)uiLo, FALSE, TRUE);
  633. }
  634. GlobalDeleteAtom((ATOM)uiHi);
  635. }
  636. break;
  637. case WM_DDE_ADVISE:
  638. if (uiLo) {
  639. if (fFreeData) {
  640. FreeDDEData((HANDLE)uiLo, FALSE, TRUE);
  641. }
  642. GlobalDeleteAtom((ATOM)uiHi);
  643. }
  644. break;
  645. case WM_DDE_ACK:
  646. // could be EXEC Ack - cant know what to do exactly.
  647. break;
  648. }
  649. FreeDDElParam(msg, lParam);
  650. break;
  651. case WM_DDE_EXECUTE:
  652. if (fFreeData) {
  653. WOWGLOBALFREE((HANDLE)lParam);
  654. }
  655. break;
  656. case WM_DDE_REQUEST:
  657. case WM_DDE_UNADVISE:
  658. GlobalDeleteAtom((ATOM)HIWORD(lParam));
  659. break;
  660. }
  661. }
  662. /***************************************************************************\
  663. * ProcessSyncDDEMessage
  664. *
  665. * Description:
  666. * Handles processing of a received DDE message. TRUE is returned if
  667. * the message was handled. FALSE implies CBR_BLOCK.
  668. *
  669. * History:
  670. * 11-19-91 sanfords Created.
  671. \***************************************************************************/
  672. BOOL ProcessSyncDDEMessage(
  673. PCONV_INFO pcoi,
  674. UINT msg,
  675. LPARAM lParam)
  676. {
  677. BOOL fNotBlocked = TRUE;
  678. PCL_INSTANCE_INFO pcii;
  679. ENABLE_ENUM_STRUCT ees;
  680. BOOL fRet;
  681. CheckDDECritIn;
  682. /*
  683. * lock the conversation so its resources don't go away till we are
  684. * done with them. This function could generate a callback which could
  685. * disconnect the conversation.
  686. */
  687. pcoi->cLocks++;
  688. if (pcoi->state & ST_BLOCKNEXT) {
  689. pcoi->state ^= ST_BLOCKNEXT | ST_BLOCKED;
  690. }
  691. if (pcoi->state & ST_BLOCKALLNEXT) {
  692. ees.pfRet = &fRet;
  693. ees.wCmd = EC_DISABLE;
  694. ees.wCmd2 = 0;
  695. EnumChildWindows(pcoi->pcii->hwndMother, (WNDENUMPROC)EnableEnumProc,
  696. (LPARAM)&ees);
  697. }
  698. if (pcoi->state & ST_CONNECTED) {
  699. if (pcoi->pxiOut == NULL) {
  700. if (pcoi->state & ST_CLIENT) {
  701. fNotBlocked = SpontaneousClientMessage((PCL_CONV_INFO)pcoi, msg, lParam);
  702. } else {
  703. fNotBlocked = SpontaneousServerMessage((PSVR_CONV_INFO)pcoi, msg, lParam);
  704. }
  705. } else {
  706. UserAssert(pcoi->pxiOut->hXact == (HANDLE)0 ||
  707. ValidateCHandle(pcoi->pxiOut->hXact, HTYPE_TRANSACTION,
  708. HINST_ANY)
  709. == (ULONG_PTR)pcoi->pxiOut);
  710. fNotBlocked = (pcoi->pxiOut->pfnResponse)(pcoi->pxiOut, msg, lParam);
  711. }
  712. } else {
  713. DumpDDEMessage(!(pcoi->state & ST_INTRA_PROCESS), msg, lParam);
  714. }
  715. if (!fNotBlocked) {
  716. pcoi->state |= ST_BLOCKED;
  717. pcoi->state &= ~ST_BLOCKNEXT;
  718. }
  719. pcii = pcoi->pcii; // save this incase unlocking makes pcoi go away.
  720. pcoi->cLocks--;
  721. if (pcoi->cLocks == 0 && pcoi->state & ST_FREE_CONV_RES_NOW) {
  722. FreeConversationResources(pcoi);
  723. }
  724. /*
  725. * Because callbacks are capable of blocking DdeUninitialize(), we check
  726. * before exit to see if it needs to be called.
  727. */
  728. if (pcii->afCmd & APPCMD_UNINIT_ASAP &&
  729. !(pcii->flags & IIF_IN_SYNC_XACT) &&
  730. !pcii->cInDDEMLCallback) {
  731. DdeUninitialize(HandleToUlong(pcii->hInstClient));
  732. return(FALSE);
  733. }
  734. return (fNotBlocked);
  735. }