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.

1736 lines
51 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: stdptcl.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * DDE Manager DDE protocol transaction management functions
  7. *
  8. * NITTY GRITTY GUCK of DDE
  9. *
  10. * Created: 11/3/91 Sanford Staab
  11. \***************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. /*
  15. StartFunctions:
  16. These are used to fill in a preallocated pxi with transaction
  17. specific data. They then start the desired transaction and
  18. link the pxi into the conversation's transaction queue.
  19. fSuccess is return ed. On error, SetLastDDEMLError is called
  20. by these functions and the pxi is untouched, ready for
  21. reuse on a subsequent call. Note that the pxi->gaItem field
  22. is a global atom and needs to be deleted by the caller on
  23. failure as apropriate. Success implies the transaction
  24. is started successfully.
  25. RespFunctions:
  26. These are called via the pxi->pfnRespnose field in response
  27. to expected DDE messages. If the msg parameter is 0, these
  28. functions assume transaction cleanup is being done. FALSE
  29. is only return ed if CBR_BLOCK was returned from a callback.
  30. SpontFunctions:
  31. These are called in response to a spontaneous (unexpected) DDE
  32. message. These functions may create a pxi and link it into the
  33. conversation's transaction queue to properly handle expected
  34. replies. FALSE is only return ed if CBR_BLOCK was returned
  35. from a callback.
  36. The prefixes Sv and Cl indicate which side of the DDE conversation
  37. is doing the work.
  38. Weaknesses: Can't deal well with failed PostMessage() or
  39. lParam acessing/allocation failures. Hoping these
  40. are rare enough (ie never) to not matter. If they
  41. do fail, the tracking layer will eventually shut down
  42. the conversation.
  43. */
  44. //--------------------------------ADVISE-------------------------------//
  45. /***************************************************************************\
  46. * ClStartAdvise
  47. *
  48. * Description:
  49. * CLIENT side Advise link processing
  50. * Post WM_DDE_ADVISE message
  51. * Link pxi for responding WM_DDE_ACK message.
  52. *
  53. * History:
  54. * 11-12-91 sanfords Created.
  55. \***************************************************************************/
  56. BOOL ClStartAdvise(
  57. PXACT_INFO pxi)
  58. {
  59. DWORD dwError;
  60. //
  61. // protocol quirk: DDE_FRELEASE is always assumed set in a WM_DDE_ADVISE
  62. // message. We set it here just in case the person on the other end
  63. // pays attention to it.
  64. //
  65. pxi->hDDESent = AllocAndSetDDEData(NULL, sizeof(DDE_DATA),
  66. (WORD)(((pxi->wType << 12) & (DDE_FDEFERUPD | DDE_FACKREQ)) | DDE_FRELEASE),
  67. pxi->wFmt);
  68. if (!pxi->hDDESent) {
  69. SetLastDDEMLError(pxi->pcoi->pcii, DMLERR_MEMORY_ERROR);
  70. return (FALSE);
  71. }
  72. IncGlobalAtomCount(pxi->gaItem); // message copy
  73. dwError = PackAndPostMessage(pxi->pcoi->hwndPartner, 0, WM_DDE_ADVISE,
  74. pxi->pcoi->hwndConv, 0, (UINT_PTR)pxi->hDDESent, pxi->gaItem);
  75. if (dwError) {
  76. SetLastDDEMLError(pxi->pcoi->pcii, dwError);
  77. WOWGLOBALFREE(pxi->hDDESent);
  78. pxi->hDDESent = 0;
  79. GlobalDeleteAtom(pxi->gaItem); // message copy
  80. return (FALSE);
  81. }
  82. pxi->state = XST_ADVSENT;
  83. pxi->pfnResponse = (FNRESPONSE)ClRespAdviseAck;
  84. LinkTransaction(pxi);
  85. return (TRUE);
  86. }
  87. /***************************************************************************\
  88. * SvSpontAdvise
  89. *
  90. * Description:
  91. * SERVER side WM_DDE_ADVISE processing
  92. *
  93. * History:
  94. * 11-12-91 sanfords Created.
  95. \***************************************************************************/
  96. BOOL SvSpontAdvise(
  97. PSVR_CONV_INFO psi,
  98. LPARAM lParam)
  99. {
  100. UINT_PTR uiHi;
  101. HANDLE hDDE;
  102. WORD wFmt, wStatus;
  103. ULONG_PTR dwRet = 0;
  104. DWORD dwError;
  105. LATOM la;
  106. UnpackDDElParam(WM_DDE_ADVISE, lParam, (PUINT_PTR)&hDDE, &uiHi);
  107. if (psi->ci.pcii->afCmd & CBF_FAIL_ADVISES) {
  108. goto Ack;
  109. }
  110. if (!ExtractDDEDataInfo(hDDE, &wStatus, &wFmt)) {
  111. goto Ack;
  112. }
  113. if (wStatus & DDE_FDEFERUPD) {
  114. wStatus &= ~DDE_FACKREQ; // warm links shouldn't have this flag set
  115. }
  116. la = GlobalToLocalAtom((GATOM)uiHi);
  117. dwRet = (ULONG_PTR)DoCallback(psi->ci.pcii,
  118. XTYP_ADVSTART,
  119. wFmt, psi->ci.hConv,
  120. NORMAL_HSZ_FROM_LATOM(psi->ci.laTopic),
  121. NORMAL_HSZ_FROM_LATOM(la),
  122. (HDDEDATA)0, 0, 0);
  123. DeleteAtom(la);
  124. // check CBR_BLOCK case
  125. if (dwRet == (ULONG_PTR)CBR_BLOCK) {
  126. return (FALSE);
  127. }
  128. if (dwRet) {
  129. //
  130. // If we fail to add the link internally, dwRet == 0 -> NACK
  131. //
  132. dwRet = AddLink((PCONV_INFO)psi, (GATOM)uiHi, wFmt,
  133. (WORD)(wStatus & (WORD)(DDE_FDEFERUPD | DDE_FACKREQ)));
  134. if (dwRet) {
  135. MONLINK(psi->ci.pcii, TRUE, wStatus & DDE_FDEFERUPD, psi->ci.laService,
  136. psi->ci.laTopic, (GATOM)uiHi, wFmt, TRUE,
  137. (HCONV)psi->ci.hwndConv, (HCONV)psi->ci.hwndPartner);
  138. }
  139. }
  140. Ack:
  141. if (dwRet) {
  142. WOWGLOBALFREE(hDDE); // hOptions - NACK -> HE frees it.
  143. }
  144. // IncGlobalAtomCount((GATOM)uiHi); // message copy - reuse
  145. dwError = PackAndPostMessage(psi->ci.hwndPartner, WM_DDE_ADVISE, WM_DDE_ACK,
  146. psi->ci.hwndConv, lParam, dwRet ? DDE_FACK : 0, uiHi);
  147. if (dwError) {
  148. SetLastDDEMLError(psi->ci.pcii, dwError);
  149. GlobalDeleteAtom((ATOM)uiHi); // message copy
  150. }
  151. return (TRUE);
  152. }
  153. /***************************************************************************\
  154. * ClRespAdviseAck
  155. *
  156. * Description:
  157. * Client's response to an expected Advise Ack.
  158. *
  159. * History:
  160. * 11-12-91 sanfords Created.
  161. \***************************************************************************/
  162. BOOL ClRespAdviseAck(
  163. PXACT_INFO pxi,
  164. UINT msg,
  165. LPARAM lParam)
  166. {
  167. UINT_PTR uiLo, uiHi;
  168. if (msg) {
  169. if (msg != WM_DDE_ACK) {
  170. return (SpontaneousClientMessage((PCL_CONV_INFO)pxi->pcoi, msg, lParam));
  171. }
  172. UnpackDDElParam(WM_DDE_ACK, lParam, &uiLo, &uiHi);
  173. #if DBG
  174. if ((GATOM)uiHi != pxi->gaItem) {
  175. return (SpontaneousClientMessage((PCL_CONV_INFO)pxi->pcoi, msg, lParam));
  176. }
  177. #endif
  178. GlobalDeleteAtom((ATOM)uiHi); // message copy
  179. pxi->state = XST_ADVACKRCVD;
  180. pxi->wStatus = (WORD)uiLo;
  181. if (pxi->wStatus & DDE_FACK) {
  182. if (AddLink(pxi->pcoi, pxi->gaItem, pxi->wFmt,
  183. (WORD)((pxi->wType << 12) & (DDE_FACKREQ | DDE_FDEFERUPD)))) {
  184. //
  185. // only server side reports links on local conversations.
  186. //
  187. if (!(pxi->pcoi->state & ST_ISLOCAL)) {
  188. MONLINK(pxi->pcoi->pcii, TRUE, (WORD)uiLo & DDE_FDEFERUPD,
  189. pxi->pcoi->laService, pxi->pcoi->laTopic, pxi->gaItem,
  190. pxi->wFmt, FALSE, (HCONV)pxi->pcoi->hwndPartner,
  191. (HCONV)pxi->pcoi->hwndConv);
  192. }
  193. } else {
  194. pxi->wStatus = 0; // memory failure - fake a NACK.
  195. }
  196. } else {
  197. WOWGLOBALFREE(pxi->hDDESent); // Nack free.
  198. }
  199. if (TransactionComplete(pxi,
  200. (pxi->wStatus & DDE_FACK) ? (HDDEDATA)1L : (HDDEDATA)0L)) {
  201. goto Cleanup;
  202. }
  203. } else {
  204. Cleanup:
  205. GlobalDeleteAtom(pxi->gaItem); // pxi copy
  206. UnlinkTransaction(pxi);
  207. DDEMLFree(pxi);
  208. }
  209. if (msg) {
  210. FreeDDElParam(msg, lParam);
  211. }
  212. return (TRUE);
  213. }
  214. //-------------------------ADVISE LINK UPDATE--------------------------//
  215. /***************************************************************************\
  216. * SvStartAdviseUpdate
  217. *
  218. * Description:
  219. * Starts a single link update transaction. The return value is TRUE only
  220. * if pxi was queued.
  221. *
  222. * History:
  223. * 11-19-91 sanfords Created.
  224. * 8-24-92 sanfords Added cLinksToGo
  225. \***************************************************************************/
  226. BOOL SvStartAdviseUpdate(
  227. PXACT_INFO pxi,
  228. DWORD cLinksToGo)
  229. {
  230. HDDEDATA hData = NULL;
  231. PDDE_DATA pdde;
  232. DWORD dwError;
  233. HANDLE hDDE;
  234. LATOM al;
  235. CheckDDECritIn;
  236. if (pxi->wType & DDE_FDEFERUPD) {
  237. hDDE = 0;
  238. } else {
  239. al = GlobalToLocalAtom(pxi->gaItem);
  240. hData = DoCallback(pxi->pcoi->pcii,
  241. XTYP_ADVREQ,
  242. pxi->wFmt,
  243. pxi->pcoi->hConv,
  244. NORMAL_HSZ_FROM_LATOM(pxi->pcoi->laTopic),
  245. NORMAL_HSZ_FROM_LATOM(al),
  246. (HDDEDATA)0,
  247. MAKELONG(cLinksToGo, 0),
  248. 0);
  249. DeleteAtom(al);
  250. if (!hData) {
  251. // app doesn't honor the advise.
  252. return (FALSE); // reuse pxi
  253. }
  254. hDDE = UnpackAndFreeDDEMLDataHandle(hData, FALSE);
  255. if (!hDDE) {
  256. /*
  257. * failed - must be execute type data
  258. */
  259. InternalFreeDataHandle(hData, FALSE);
  260. SetLastDDEMLError(pxi->pcoi->pcii, DMLERR_DLL_USAGE);
  261. return (FALSE);
  262. }
  263. /*
  264. * Set fAckReq bit apropriately - note APPOWNED handles will already
  265. * have the fAckReq bit set so this will not change their state.
  266. */
  267. USERGLOBALLOCK(hDDE, pdde);
  268. if (pdde == NULL) {
  269. return (FALSE);
  270. }
  271. if (pdde->wFmt != pxi->wFmt) {
  272. /*
  273. * bogus data - wrong format!
  274. */
  275. USERGLOBALUNLOCK(hDDE);
  276. InternalFreeDataHandle(hData, FALSE);
  277. SetLastDDEMLError(pxi->pcoi->pcii, DMLERR_DLL_USAGE);
  278. return (FALSE);
  279. }
  280. if (!(pdde->wStatus & DDE_FRELEASE)) {
  281. pxi->wType |= DDE_FACKREQ; // dare not allow neither flag set!
  282. }
  283. pdde->wStatus |= (pxi->wType & DDE_FACKREQ);
  284. USERGLOBALUNLOCK(hDDE);
  285. }
  286. IncGlobalAtomCount(pxi->gaItem); // message copy
  287. dwError = PackAndPostMessage(pxi->pcoi->hwndPartner, 0, WM_DDE_DATA,
  288. pxi->pcoi->hwndConv, 0, (UINT_PTR)hDDE, pxi->gaItem);
  289. if (dwError) {
  290. if (hData) {
  291. InternalFreeDataHandle(hData, FALSE);
  292. }
  293. SetLastDDEMLError(pxi->pcoi->pcii, dwError);
  294. GlobalDeleteAtom(pxi->gaItem); // message copy
  295. return (FALSE);
  296. }
  297. pxi->state = XST_ADVDATASENT;
  298. if (pxi->wType & DDE_FACKREQ) {
  299. pxi->hDDESent = hDDE;
  300. pxi->pfnResponse = (FNRESPONSE)SvRespAdviseDataAck;
  301. LinkTransaction(pxi);
  302. return (TRUE); // prevents reuse - since its queued.
  303. } else {
  304. return (FALSE); // causes pxi to be reused for next advdata message.
  305. }
  306. }
  307. /***************************************************************************\
  308. * ClSpontAdviseData
  309. *
  310. * Description:
  311. * Handles WM_DDE_DATA messages that are not request data.
  312. *
  313. * History:
  314. * 11-19-91 sanfords Created.
  315. \***************************************************************************/
  316. BOOL ClSpontAdviseData(
  317. PCL_CONV_INFO pci,
  318. LPARAM lParam)
  319. {
  320. UINT_PTR uiHi;
  321. DWORD dwError;
  322. HANDLE hDDE = 0;
  323. HDDEDATA hData, hDataReturn;
  324. PDDE_DATA pdde;
  325. WORD wFmt;
  326. WORD wStatus;
  327. LATOM la;
  328. PADVISE_LINK paLink;
  329. int iLink;
  330. UnpackDDElParam(WM_DDE_DATA, lParam, (PUINT_PTR)&hDDE, &uiHi);
  331. UserAssert(!hDDE || GlobalSize(hDDE));
  332. wFmt = 0;
  333. wStatus = 0;
  334. hDataReturn = 0;
  335. la = GlobalToLocalAtom((GATOM)uiHi);
  336. if (hDDE) {
  337. USERGLOBALLOCK(hDDE, pdde);
  338. if (pdde == NULL) {
  339. hData = 0;
  340. } else {
  341. wFmt = pdde->wFmt;
  342. wStatus = pdde->wStatus;
  343. USERGLOBALUNLOCK(hDDE);
  344. /*
  345. * if data is coming in, create a data handle for the app
  346. */
  347. hData = InternalCreateDataHandle(pci->ci.pcii, (LPBYTE)hDDE,
  348. (DWORD)-1, 0, HDATA_NOAPPFREE | HDATA_READONLY, 0, 0);
  349. }
  350. if (hData) {
  351. hDataReturn = DoCallback(pci->ci.pcii, XTYP_ADVDATA,
  352. wFmt, pci->ci.hConv,
  353. NORMAL_HSZ_FROM_LATOM(pci->ci.laTopic),
  354. NORMAL_HSZ_FROM_LATOM(la),
  355. hData, 0, 0);
  356. if (hDataReturn != CBR_BLOCK) {
  357. UnpackAndFreeDDEMLDataHandle(hData, FALSE);
  358. if (((ULONG_PTR)hDataReturn & DDE_FACK) || !(wStatus & DDE_FACKREQ)) {
  359. /*
  360. * Nacked Advise data with fAckReq set is server's
  361. * responsibility to free!
  362. */
  363. FreeDDEData(hDDE, FALSE, TRUE);
  364. }
  365. }
  366. }
  367. } else {
  368. /*
  369. * WARM LINK CASE
  370. *
  371. * Search through the client's link info to find what formats this
  372. * puppy is on. We let the client know for each format being supported
  373. * on this item that is warm-linked. The last hDataReturn determines
  374. * the ACK returned - for lack of a better method.
  375. */
  376. for (paLink = pci->ci.aLinks, iLink = 0; iLink < pci->ci.cLinks; iLink++, paLink++) {
  377. if ((paLink->laItem == la) && (paLink->wType & DDE_FDEFERUPD)) {
  378. hDataReturn = DoCallback(pci->ci.pcii, XTYP_ADVDATA,
  379. paLink->wFmt, pci->ci.hConv,
  380. NORMAL_HSZ_FROM_LATOM(pci->ci.laTopic),
  381. NORMAL_HSZ_FROM_LATOM(la),
  382. 0, 0, 0);
  383. if (hDataReturn == CBR_BLOCK) {
  384. DeleteAtom(la);
  385. return (FALSE);
  386. }
  387. }
  388. }
  389. }
  390. DeleteAtom(la);
  391. if (hDataReturn == CBR_BLOCK) {
  392. return (FALSE);
  393. }
  394. if (wStatus & DDE_FACKREQ) {
  395. (ULONG_PTR)hDataReturn &= ~DDE_FACKRESERVED;
  396. // reuse uiHi
  397. if (dwError = PackAndPostMessage(pci->ci.hwndPartner, WM_DDE_DATA,
  398. WM_DDE_ACK, pci->ci.hwndConv, lParam, (UINT_PTR)hDataReturn, uiHi)) {
  399. SetLastDDEMLError(pci->ci.pcii, dwError);
  400. }
  401. } else {
  402. GlobalDeleteAtom((ATOM)uiHi); // data message copy
  403. FreeDDElParam(WM_DDE_DATA, lParam); // not reused so free it.
  404. }
  405. return (TRUE);
  406. }
  407. /***************************************************************************\
  408. * SvRespAdviseDataAck
  409. *
  410. * Description:
  411. * Handles expected Advise Data ACK message.
  412. *
  413. * History:
  414. * 11-19-91 sanfords Created.
  415. \***************************************************************************/
  416. BOOL SvRespAdviseDataAck(
  417. PXACT_INFO pxi,
  418. UINT msg,
  419. LPARAM lParam)
  420. {
  421. UINT_PTR uiLo, uiHi;
  422. int iLink;
  423. PADVISE_LINK paLink;
  424. PXACT_INFO pxiNew;
  425. LATOM la;
  426. BOOL fSwapped;
  427. #if DBG
  428. int cLinks;
  429. #endif
  430. if (msg) {
  431. if (msg != WM_DDE_ACK) {
  432. return (SpontaneousServerMessage((PSVR_CONV_INFO)pxi->pcoi, msg, lParam));
  433. }
  434. UnpackDDElParam(WM_DDE_ACK, lParam, &uiLo, &uiHi);
  435. if ((GATOM)uiHi != pxi->gaItem) {
  436. RIPMSG0(RIP_ERROR, "DDE Protocol violation: Data ACK had wrong item");
  437. return (SpontaneousServerMessage((PSVR_CONV_INFO)pxi->pcoi, msg, lParam));
  438. }
  439. GlobalDeleteAtom((ATOM)uiHi); // message copy
  440. FreeDDElParam(WM_DDE_ACK, lParam);
  441. if (!((uiLo & DDE_FACK) && pxi->hDDESent)) {
  442. FreeDDEData(pxi->hDDESent, FALSE, TRUE);
  443. }
  444. #if DBG
  445. /*
  446. * Rememeber the number of links so we can assert if they change during the loop below
  447. */
  448. cLinks = pxi->pcoi->cLinks;
  449. #endif
  450. /*
  451. * locate link info and clear ADVST_WAITING bit
  452. */
  453. la = GlobalToLocalAtom((GATOM)uiHi);
  454. paLink = pxi->pcoi->aLinks;
  455. for (iLink = 0; iLink < pxi->pcoi->cLinks; iLink++, paLink++) {
  456. if (paLink->laItem == la &&
  457. paLink->state & ADVST_WAITING) {
  458. paLink->state &= ~ADVST_WAITING;
  459. /*
  460. * We have to allocate pxiNew because it may become linked
  461. * into pcoi->pxiIn.
  462. */
  463. pxiNew = (PXACT_INFO)DDEMLAlloc(sizeof(XACT_INFO));
  464. if (pxiNew && !UpdateLinkIfChanged(paLink, pxiNew, pxi->pcoi,
  465. &pxi->pcoi->aLinks[pxi->pcoi->cLinks - 1], &fSwapped,
  466. CADV_LATEACK)) {
  467. /*
  468. * Not used, free it.
  469. */
  470. DDEMLFree(pxiNew);
  471. }
  472. break;
  473. }
  474. }
  475. #if DBG
  476. if (cLinks != pxi->pcoi->cLinks) {
  477. RIPMSG1(RIP_ERROR, "SvRespAdviseDataAck: cLinks changed. pxi:%#p", pxi);
  478. }
  479. #endif
  480. DeleteAtom(la);
  481. }
  482. GlobalDeleteAtom(pxi->gaItem); // pxi copy
  483. UnlinkTransaction(pxi);
  484. DDEMLFree(pxi);
  485. return (TRUE);
  486. }
  487. //------------------------------UNADVISE-------------------------------//
  488. /***************************************************************************\
  489. * ClStartUnadvise
  490. *
  491. * Description:
  492. * Starts a WM_DDE_UNADVISE transaction.
  493. *
  494. * History:
  495. * 11-19-91 sanfords Created.
  496. \***************************************************************************/
  497. BOOL ClStartUnadvise(
  498. PXACT_INFO pxi)
  499. {
  500. DWORD dwError;
  501. IncGlobalAtomCount(pxi->gaItem); // message copy
  502. dwError = PackAndPostMessage(pxi->pcoi->hwndPartner, 0, WM_DDE_UNADVISE,
  503. pxi->pcoi->hwndConv, 0, pxi->wFmt, pxi->gaItem);
  504. if (dwError) {
  505. SetLastDDEMLError(pxi->pcoi->pcii, dwError);
  506. GlobalDeleteAtom(pxi->gaItem); // message copy
  507. return (FALSE);
  508. }
  509. //
  510. // only server side reports links on local conversations.
  511. //
  512. if (!(pxi->pcoi->state & ST_ISLOCAL)) {
  513. MONLINK(pxi->pcoi->pcii, FALSE, 0,
  514. pxi->pcoi->laService, pxi->pcoi->laTopic, pxi->gaItem,
  515. pxi->wFmt, FALSE, (HCONV)pxi->pcoi->hwndPartner,
  516. (HCONV)pxi->pcoi->hwndConv);
  517. }
  518. pxi->state = XST_UNADVSENT;
  519. pxi->pfnResponse = (FNRESPONSE)ClRespUnadviseAck;
  520. LinkTransaction(pxi);
  521. return (TRUE);
  522. }
  523. /***************************************************************************\
  524. * CloseTransaction
  525. *
  526. * Description:
  527. * Remove all outstanding pxi coresponding to the transaction
  528. * that will be closed in responds to a WM_DDE_UNADVISE message.
  529. *
  530. * History:
  531. * 6-4-96 clupu Created.
  532. \***************************************************************************/
  533. void CloseTransaction(
  534. PCONV_INFO pci,
  535. ATOM atom)
  536. {
  537. PXACT_INFO pxi;
  538. PXACT_INFO pxiD;
  539. pxi = pci->pxiOut;
  540. while (pxi && (pxi->gaItem == atom)) {
  541. pxiD = pxi;
  542. pxi = pxi->next;
  543. DDEMLFree(pxiD);
  544. }
  545. pci->pxiOut = pxi;
  546. if (pxi == NULL) {
  547. pci->pxiIn = NULL;
  548. return;
  549. }
  550. while (pxi->next) {
  551. if (pxi->next->gaItem == atom) {
  552. pxiD = pxi->next;
  553. pxi->next = pxiD->next;
  554. DDEMLFree(pxiD);
  555. } else
  556. pxi = pxi->next;
  557. }
  558. pci->pxiIn = pxi;
  559. }
  560. /***************************************************************************\
  561. * SvSpontUnadvise
  562. *
  563. * Description:
  564. * Responds to a WM_DDE_UNADVISE message.
  565. *
  566. * History:
  567. * 11-19-91 sanfords Created.
  568. \***************************************************************************/
  569. BOOL SvSpontUnadvise(
  570. PSVR_CONV_INFO psi,
  571. LPARAM lParam)
  572. {
  573. ULONG_PTR dwRet = 0;
  574. DWORD dwError;
  575. INT iLink;
  576. PADVISE_LINK aLink;
  577. LATOM la;
  578. la = GlobalToLocalAtom((GATOM)HIWORD(lParam));
  579. CloseTransaction(&psi->ci, HIWORD(lParam));
  580. for (aLink = psi->ci.aLinks, iLink = 0; iLink < psi->ci.cLinks;) {
  581. if (la == 0 || aLink->laItem == la &&
  582. (LOWORD(lParam) == 0 || LOWORD(lParam) == aLink->wFmt)) {
  583. if (!(psi->ci.pcii->afCmd & CBF_FAIL_ADVISES)) {
  584. /*
  585. * Only do the callbacks if he wants them.
  586. */
  587. dwRet = (ULONG_PTR)DoCallback(psi->ci.pcii,
  588. (WORD)XTYP_ADVSTOP, aLink->wFmt, psi->ci.hConv,
  589. NORMAL_HSZ_FROM_LATOM(psi->ci.laTopic),
  590. NORMAL_HSZ_FROM_LATOM(la),
  591. (HDDEDATA)0, 0L, 0L);
  592. if (dwRet == (ULONG_PTR)CBR_BLOCK) {
  593. DeleteAtom(la);
  594. return(FALSE);
  595. }
  596. }
  597. /*
  598. * Notify any DDESPY apps.
  599. */
  600. MONLINK(psi->ci.pcii, TRUE, 0, psi->ci.laService,
  601. psi->ci.laTopic, HIWORD(lParam), aLink->wFmt, TRUE,
  602. (HCONV)psi->ci.hwndConv, (HCONV)psi->ci.hwndPartner);
  603. /*
  604. * Remove link info
  605. */
  606. DeleteAtom(aLink->laItem); // aLink copy
  607. DeleteLinkCount(psi->ci.pcii, aLink->pLinkCount);
  608. if (--psi->ci.cLinks) {
  609. memmove((LPSTR)aLink, (LPSTR)(aLink + 1),
  610. sizeof(ADVISE_LINK) * (psi->ci.cLinks - iLink));
  611. }
  612. } else {
  613. aLink++;
  614. iLink++;
  615. }
  616. }
  617. DeleteAtom(la);
  618. /*
  619. * Now ACK the unadvise message.
  620. */
  621. dwError = PackAndPostMessage(psi->ci.hwndPartner, 0,
  622. WM_DDE_ACK, psi->ci.hwndConv, 0, DDE_FACK, HIWORD(lParam));
  623. if (dwError) {
  624. SetLastDDEMLError(psi->ci.pcii, dwError);
  625. GlobalDeleteAtom((ATOM)HIWORD(lParam)); // message copy
  626. // FreeDDElParam(WM_DDE_UNADVISE, lParam); // no unpack needed
  627. }
  628. return (TRUE);
  629. }
  630. /***************************************************************************\
  631. * ClRespUnadviseAck
  632. *
  633. * Description:
  634. * Client's response to an expected Unadvise Ack.
  635. *
  636. * History:
  637. * 11-12-91 sanfords Created.
  638. \***************************************************************************/
  639. BOOL ClRespUnadviseAck(
  640. PXACT_INFO pxi,
  641. UINT msg,
  642. LPARAM lParam)
  643. {
  644. UINT_PTR uiLo, uiHi;
  645. LATOM al;
  646. PADVISE_LINK aLink;
  647. int iLink;
  648. if (msg) {
  649. if (msg != WM_DDE_ACK) {
  650. return (SpontaneousClientMessage((PCL_CONV_INFO)pxi->pcoi, msg, lParam));
  651. }
  652. UnpackDDElParam(WM_DDE_ACK, lParam, &uiLo, &uiHi);
  653. if ((GATOM)uiHi != pxi->gaItem) {
  654. return (SpontaneousClientMessage((PCL_CONV_INFO)pxi->pcoi, msg, lParam));
  655. }
  656. al = GlobalToLocalAtom((ATOM)uiHi);
  657. for (aLink = pxi->pcoi->aLinks, iLink = 0;
  658. iLink < pxi->pcoi->cLinks;
  659. ) {
  660. if (aLink->laItem == al &&
  661. (pxi->wFmt == 0 || aLink->wFmt == pxi->wFmt)) {
  662. DeleteAtom(al); // aLink copy
  663. if (--pxi->pcoi->cLinks) {
  664. memmove((LPSTR)aLink, (LPSTR)(aLink + 1),
  665. sizeof(ADVISE_LINK) * (pxi->pcoi->cLinks - iLink));
  666. }
  667. } else {
  668. aLink++;
  669. iLink++;
  670. }
  671. }
  672. DeleteAtom(al); // local copy
  673. GlobalDeleteAtom((ATOM)uiHi); // message copy
  674. pxi->state = XST_UNADVACKRCVD;
  675. pxi->wStatus = (WORD)uiLo;
  676. if (TransactionComplete(pxi, (HDDEDATA)1)) {
  677. goto Cleanup;
  678. }
  679. } else {
  680. Cleanup:
  681. GlobalDeleteAtom(pxi->gaItem); // pxi copy
  682. UnlinkTransaction(pxi);
  683. if (pxi->hXact) {
  684. DestroyHandle(pxi->hXact);
  685. }
  686. DDEMLFree(pxi);
  687. }
  688. if (msg) {
  689. FreeDDElParam(msg, lParam);
  690. }
  691. return (TRUE);
  692. }
  693. //-------------------------------EXECUTE-------------------------------//
  694. /***************************************************************************\
  695. * MaybeTranslateExecuteData
  696. *
  697. * Description:
  698. * Translates DDE execute data if needed.
  699. *
  700. * History:
  701. * 1/28/92 sanfords created
  702. \***************************************************************************/
  703. HANDLE MaybeTranslateExecuteData(
  704. HANDLE hDDE,
  705. BOOL fUnicodeFrom,
  706. BOOL fUnicodeTo,
  707. BOOL fFreeSource)
  708. {
  709. PSTR pstr;
  710. PWSTR pwstr;
  711. DWORD cb;
  712. HANDLE hDDEnew;
  713. if (fUnicodeFrom && !fUnicodeTo) {
  714. USERGLOBALLOCK(hDDE, pwstr);
  715. // translate data from UNICODE to ANSII
  716. cb = WideCharToMultiByte(0, 0, (LPCWSTR)pwstr, -1, NULL, 0, NULL, NULL);
  717. hDDEnew = UserGlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cb);
  718. USERGLOBALLOCK(hDDEnew, pstr);
  719. if (pstr != NULL && pwstr != NULL) {
  720. WCSToMB(pwstr, -1, &pstr, cb, FALSE);
  721. }
  722. if (pwstr) {
  723. USERGLOBALUNLOCK(hDDE);
  724. }
  725. if (pstr) {
  726. USERGLOBALUNLOCK(hDDEnew);
  727. }
  728. } else if (!fUnicodeFrom && fUnicodeTo) {
  729. USERGLOBALLOCK(hDDE, pstr);
  730. // translate data from ANSII to UNICODE
  731. cb = 2 * MultiByteToWideChar(0, 0, (LPCSTR)pstr, -1, NULL, 0);
  732. hDDEnew = UserGlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cb);
  733. USERGLOBALLOCK(hDDEnew, pwstr);
  734. if (pwstr != NULL && pstr != NULL) {
  735. MBToWCS(pstr, -1, &pwstr, cb, FALSE);
  736. }
  737. if (pstr) {
  738. USERGLOBALUNLOCK(hDDE);
  739. }
  740. if (pwstr) {
  741. USERGLOBALUNLOCK(hDDEnew);
  742. }
  743. } else {
  744. return (hDDE); // no translation needed.
  745. }
  746. if (fFreeSource) {
  747. WOWGLOBALFREE(hDDE);
  748. }
  749. return (hDDEnew);
  750. }
  751. /***************************************************************************\
  752. * ClStartExecute
  753. *
  754. * Description:
  755. * Starts an execute transaction.
  756. *
  757. * History:
  758. * 11-19-91 sanfords Created.
  759. * 1/28/92 sanfords added UNICODE support.
  760. \***************************************************************************/
  761. BOOL ClStartExecute(
  762. PXACT_INFO pxi)
  763. {
  764. DWORD dwError;
  765. pxi->hDDESent = MaybeTranslateExecuteData(pxi->hDDESent,
  766. pxi->pcoi->pcii->flags & IIF_UNICODE,
  767. pxi->pcoi->state & ST_UNICODE_EXECUTE,
  768. TRUE);
  769. dwError = PackAndPostMessage(pxi->pcoi->hwndPartner, 0, WM_DDE_EXECUTE,
  770. pxi->pcoi->hwndConv, 0, 0, (UINT_PTR)pxi->hDDESent);
  771. if (dwError) {
  772. SetLastDDEMLError(pxi->pcoi->pcii, dwError);
  773. return (FALSE);
  774. }
  775. pxi->state = XST_EXECSENT;
  776. pxi->pfnResponse = (FNRESPONSE)ClRespExecuteAck;
  777. LinkTransaction(pxi);
  778. return (TRUE);
  779. }
  780. /***************************************************************************\
  781. * SvSpontExecute
  782. *
  783. * Description:
  784. * Responds to a WM_DDE_EXECUTE message.
  785. *
  786. * History:
  787. * 11-19-91 sanfords Created.
  788. * 1/28/92 sanfords added UNICODE support.
  789. \***************************************************************************/
  790. BOOL SvSpontExecute(
  791. PSVR_CONV_INFO psi,
  792. LPARAM lParam)
  793. {
  794. HANDLE hDDE, hDDEx;
  795. ULONG_PTR dwRet = 0;
  796. DWORD dwError;
  797. HDDEDATA hData = 0;
  798. hDDEx = hDDE = (HANDLE)lParam; // UnpackDDElParam(msg, lParam, NULL, &hDDE);
  799. if (psi->ci.pcii->afCmd & CBF_FAIL_EXECUTES) {
  800. goto Ack;
  801. }
  802. /*
  803. * Note that if unicode translation is needed, we use the translated
  804. * handle for the callback and then destroy it but the ACK is always
  805. * the original hDDE so that the protocol isn't violated:
  806. *
  807. * DDE COMMANDMENT #324: Thou shalt pass back the exact same data
  808. * handle in an execute ACK that you were given by the execute
  809. * message.
  810. */
  811. hDDEx = MaybeTranslateExecuteData(hDDE,
  812. psi->ci.state & ST_UNICODE_EXECUTE,
  813. psi->ci.pcii->flags & IIF_UNICODE,
  814. FALSE);
  815. hData = InternalCreateDataHandle(psi->ci.pcii, (LPBYTE)hDDEx, (DWORD)-1, 0,
  816. HDATA_EXECUTE | HDATA_READONLY | HDATA_NOAPPFREE, 0, 0);
  817. if (!hData) {
  818. SetLastDDEMLError(psi->ci.pcii, DMLERR_MEMORY_ERROR);
  819. goto Ack;
  820. }
  821. dwRet = (ULONG_PTR)DoCallback(psi->ci.pcii,
  822. XTYP_EXECUTE, 0, psi->ci.hConv,
  823. NORMAL_HSZ_FROM_LATOM(psi->ci.laTopic), 0, hData, 0, 0);
  824. UnpackAndFreeDDEMLDataHandle(hData, TRUE);
  825. if (dwRet == (ULONG_PTR)CBR_BLOCK) {
  826. if (hDDEx != hDDE) {
  827. WOWGLOBALFREE(hDDEx);
  828. }
  829. return (FALSE);
  830. }
  831. Ack:
  832. dwRet &= ~DDE_FACKRESERVED;
  833. dwError = PackAndPostMessage(psi->ci.hwndPartner, WM_DDE_EXECUTE,
  834. WM_DDE_ACK, psi->ci.hwndConv, lParam, dwRet, (UINT_PTR)hDDE);
  835. if (dwError) {
  836. SetLastDDEMLError(psi->ci.pcii, dwError);
  837. }
  838. if (hDDEx != hDDE) {
  839. WOWGLOBALFREE(hDDEx);
  840. }
  841. return (TRUE);
  842. }
  843. /***************************************************************************\
  844. * ClRespExecuteAck
  845. *
  846. * Description:
  847. * Responds to a WM_DDE_ACK in response to a WM_DDE_EXECUTE message.
  848. *
  849. * History:
  850. * 11-19-91 sanfords Created.
  851. \***************************************************************************/
  852. BOOL ClRespExecuteAck(
  853. PXACT_INFO pxi,
  854. UINT msg,
  855. LPARAM lParam)
  856. {
  857. UINT_PTR uiLo, uiHi;
  858. if (msg) {
  859. if (msg != WM_DDE_ACK) {
  860. return (SpontaneousClientMessage((PCL_CONV_INFO)pxi->pcoi, msg, lParam));
  861. }
  862. UnpackDDElParam(WM_DDE_ACK, lParam, &uiLo, &uiHi);
  863. if (uiHi != (UINT_PTR)pxi->hDDESent) {
  864. return (SpontaneousClientMessage((PCL_CONV_INFO)pxi->pcoi, msg, lParam));
  865. }
  866. WOWGLOBALFREE((HANDLE)uiHi);
  867. pxi->state = XST_EXECACKRCVD;
  868. pxi->wStatus = (WORD)uiLo;
  869. if (TransactionComplete(pxi, (HDDEDATA)((ULONG_PTR)(pxi->wStatus & DDE_FACK ? 1 : 0)))) {
  870. goto Cleanup;
  871. }
  872. } else {
  873. Cleanup:
  874. GlobalDeleteAtom(pxi->gaItem); // pxi copy
  875. UnlinkTransaction(pxi);
  876. if (pxi->hXact) {
  877. DestroyHandle(pxi->hXact);
  878. }
  879. DDEMLFree(pxi);
  880. }
  881. if (msg) {
  882. FreeDDElParam(msg, lParam);
  883. }
  884. return (TRUE);
  885. }
  886. //----------------------------------POKE-------------------------------//
  887. /***************************************************************************\
  888. * ClStartPoke
  889. *
  890. * Description:
  891. * Initiates a poke transaction.
  892. *
  893. * History:
  894. * 11-19-91 sanfords Created.
  895. \***************************************************************************/
  896. BOOL ClStartPoke(
  897. PXACT_INFO pxi)
  898. {
  899. DWORD dwError;
  900. IncGlobalAtomCount(pxi->gaItem); // message copy
  901. dwError = PackAndPostMessage(pxi->pcoi->hwndPartner, 0, WM_DDE_POKE,
  902. pxi->pcoi->hwndConv, 0, (UINT_PTR)pxi->hDDESent, pxi->gaItem);
  903. if (dwError) {
  904. SetLastDDEMLError(pxi->pcoi->pcii, dwError);
  905. GlobalDeleteAtom(pxi->gaItem); // message copy
  906. return (FALSE);
  907. }
  908. pxi->state = XST_POKESENT;
  909. pxi->pfnResponse = (FNRESPONSE)ClRespPokeAck;
  910. LinkTransaction(pxi);
  911. return (TRUE);
  912. }
  913. /***************************************************************************\
  914. * SvSpontPoke
  915. *
  916. * Description:
  917. * Handles WM_DDE_POKE messages.
  918. *
  919. * History:
  920. * 11-19-91 sanfords Created.
  921. \***************************************************************************/
  922. BOOL SvSpontPoke(
  923. PSVR_CONV_INFO psi,
  924. LPARAM lParam)
  925. {
  926. UINT_PTR uiHi;
  927. HANDLE hDDE = 0;
  928. HDDEDATA hData;
  929. ULONG_PTR dwRet = 0;
  930. DWORD dwError;
  931. WORD wFmt, wStatus;
  932. LATOM al;
  933. // See what we have
  934. UnpackDDElParam(WM_DDE_DATA, lParam, (PUINT_PTR)&hDDE, &uiHi);
  935. if (!(psi->ci.pcii->afCmd & CBF_FAIL_POKES)) {
  936. if (!hDDE) {
  937. goto Ack;
  938. }
  939. if (!ExtractDDEDataInfo(hDDE, &wStatus, &wFmt)) {
  940. FreeDDEData(hDDE, FALSE, TRUE); // free message data
  941. goto Ack;
  942. }
  943. hData = InternalCreateDataHandle(psi->ci.pcii, (LPBYTE)hDDE, (DWORD)-1, 0,
  944. HDATA_NOAPPFREE | HDATA_READONLY, 0, 0);
  945. if (!hData) {
  946. SetLastDDEMLError(psi->ci.pcii, DMLERR_MEMORY_ERROR);
  947. FreeDDEData(hDDE, FALSE, TRUE); // free message data
  948. goto Ack; // Nack it.
  949. return(TRUE);
  950. }
  951. al = GlobalToLocalAtom((GATOM)uiHi);
  952. dwRet = (ULONG_PTR)DoCallback(psi->ci.pcii, XTYP_POKE,
  953. wFmt, psi->ci.hConv,
  954. NORMAL_HSZ_FROM_LATOM(psi->ci.laTopic),
  955. NORMAL_HSZ_FROM_LATOM(al),
  956. hData, 0, 0);
  957. DeleteAtom(al);
  958. UnpackAndFreeDDEMLDataHandle(hData, FALSE);
  959. }
  960. if (dwRet == (ULONG_PTR)CBR_BLOCK) {
  961. // Note: this code makes an app that return s CBR_BLOCK unable to
  962. // access the data after the callback return .
  963. return (FALSE);
  964. }
  965. if (dwRet & DDE_FACK) {
  966. FreeDDEData(hDDE, FALSE, TRUE);
  967. }
  968. Ack:
  969. dwRet &= ~DDE_FACKRESERVED;
  970. dwError = PackAndPostMessage(psi->ci.hwndPartner, WM_DDE_POKE, WM_DDE_ACK,
  971. psi->ci.hwndConv, lParam, dwRet, uiHi);
  972. if (dwError) {
  973. SetLastDDEMLError(psi->ci.pcii, dwError);
  974. }
  975. return (TRUE);
  976. }
  977. /***************************************************************************\
  978. * ClRespPokeAck
  979. *
  980. * Description:
  981. * Response to a WM_DDE_ACK message in response to a WM_DDE_POKE message.
  982. *
  983. * History:
  984. * 11-19-91 sanfords Created.
  985. \***************************************************************************/
  986. BOOL ClRespPokeAck(
  987. PXACT_INFO pxi,
  988. UINT msg,
  989. LPARAM lParam)
  990. {
  991. UINT_PTR uiLo, uiHi;
  992. if (msg) {
  993. if (msg != WM_DDE_ACK) {
  994. return (SpontaneousClientMessage((PCL_CONV_INFO)pxi->pcoi, msg, lParam));
  995. }
  996. UnpackDDElParam(WM_DDE_ACK, lParam, &uiLo, &uiHi);
  997. if ((GATOM)uiHi != pxi->gaItem) {
  998. return (SpontaneousClientMessage((PCL_CONV_INFO)pxi->pcoi, msg, lParam));
  999. }
  1000. GlobalDeleteAtom((ATOM)uiHi); // message copy
  1001. pxi->state = XST_POKEACKRCVD;
  1002. pxi->wStatus = (WORD)uiLo;
  1003. if (!((WORD)uiLo & DDE_FACK)) {
  1004. //
  1005. // NACKs make it our business to free the poked data.
  1006. //
  1007. FreeDDEData(pxi->hDDESent, FALSE, TRUE);
  1008. }
  1009. if (TransactionComplete(pxi,
  1010. (HDDEDATA)((ULONG_PTR)(pxi->wStatus & DDE_FACK ? 1 : 0)))) {
  1011. goto Cleanup;
  1012. }
  1013. } else {
  1014. Cleanup:
  1015. GlobalDeleteAtom(pxi->gaItem); // pxi copy
  1016. UnlinkTransaction(pxi);
  1017. if (pxi->hXact) {
  1018. DestroyHandle(pxi->hXact);
  1019. }
  1020. DDEMLFree(pxi);
  1021. }
  1022. if (msg) {
  1023. FreeDDElParam(msg, lParam);
  1024. }
  1025. return (TRUE);
  1026. }
  1027. //-------------------------------REQUEST-------------------------------//
  1028. /***************************************************************************\
  1029. * ClStartRequest
  1030. *
  1031. * Description:
  1032. * Start a request transaction.
  1033. *
  1034. * History:
  1035. * 11-19-91 sanfords Created.
  1036. \***************************************************************************/
  1037. BOOL ClStartRequest(
  1038. PXACT_INFO pxi)
  1039. {
  1040. DWORD dwError;
  1041. IncGlobalAtomCount(pxi->gaItem); // message copy
  1042. dwError = PackAndPostMessage(pxi->pcoi->hwndPartner, 0, WM_DDE_REQUEST,
  1043. pxi->pcoi->hwndConv, 0, pxi->wFmt, pxi->gaItem);
  1044. if (dwError) {
  1045. SetLastDDEMLError(pxi->pcoi->pcii, dwError);
  1046. GlobalDeleteAtom(pxi->gaItem); // message copy
  1047. return (FALSE);
  1048. }
  1049. pxi->state = XST_REQSENT;
  1050. pxi->pfnResponse = (FNRESPONSE)ClRespRequestData;
  1051. LinkTransaction(pxi);
  1052. return (TRUE);
  1053. }
  1054. /***************************************************************************\
  1055. * SvSpontRequest
  1056. *
  1057. * Description:
  1058. * Respond to a WM_DDE_REQUEST message.
  1059. *
  1060. * History:
  1061. * 11-19-91 sanfords Created.
  1062. \***************************************************************************/
  1063. BOOL SvSpontRequest(
  1064. PSVR_CONV_INFO psi,
  1065. LPARAM lParam)
  1066. {
  1067. HANDLE hDDE = 0;
  1068. HDDEDATA hDataRet;
  1069. WORD wFmt, wStatus;
  1070. DWORD dwError;
  1071. LATOM la;
  1072. if (psi->ci.pcii->afCmd & CBF_FAIL_REQUESTS) {
  1073. goto Nack;
  1074. }
  1075. // See what we have
  1076. // UnpackDDElParam(lParam, WM_DDE_REQUEST, .... Requests arn't packed
  1077. wFmt = LOWORD(lParam);
  1078. la = GlobalToLocalAtom((GATOM)HIWORD(lParam));
  1079. hDataRet = DoCallback(psi->ci.pcii, XTYP_REQUEST,
  1080. wFmt, psi->ci.hConv,
  1081. NORMAL_HSZ_FROM_LATOM(psi->ci.laTopic),
  1082. NORMAL_HSZ_FROM_LATOM(la),
  1083. (HDDEDATA)0, 0, 0);
  1084. DeleteAtom(la);
  1085. if (hDataRet == CBR_BLOCK) {
  1086. return (FALSE);
  1087. }
  1088. if (hDataRet) {
  1089. hDDE = UnpackAndFreeDDEMLDataHandle(hDataRet, FALSE);
  1090. if (!hDDE) {
  1091. SetLastDDEMLError(psi->ci.pcii, DMLERR_DLL_USAGE);
  1092. goto Nack;
  1093. }
  1094. if (!ExtractDDEDataInfo(hDDE, &wStatus, &wFmt)) {
  1095. SetLastDDEMLError(psi->ci.pcii, DMLERR_DLL_USAGE);
  1096. goto Nack;
  1097. }
  1098. if (!(wStatus & DDE_FRELEASE)) {
  1099. // Its APPOWNED or relayed from another server - only safe
  1100. // thing to do is use a copy.
  1101. hDDE = CopyDDEData(hDDE, FALSE);
  1102. if (!hDDE) {
  1103. SetLastDDEMLError(psi->ci.pcii, DMLERR_MEMORY_ERROR);
  1104. goto Nack;
  1105. }
  1106. }
  1107. // Keep it simple, DDEML servers never ask for acks from requests.
  1108. wStatus = DDE_FRELEASE | DDE_FREQUESTED;
  1109. AllocAndSetDDEData((LPBYTE)hDDE, (DWORD)-1, wStatus, wFmt);
  1110. // just reuse HIWORD(lParam) (aItem) - message copy
  1111. if (dwError = PackAndPostMessage(psi->ci.hwndPartner, WM_DDE_REQUEST,
  1112. WM_DDE_DATA, psi->ci.hwndConv, 0, (UINT_PTR)hDDE, HIWORD(lParam))) {
  1113. SetLastDDEMLError(psi->ci.pcii, dwError);
  1114. GlobalDeleteAtom(HIWORD(lParam)); // message copy
  1115. }
  1116. } else {
  1117. Nack:
  1118. // just reuse HIWORD(lParam) (aItem) - message copy
  1119. dwError = PackAndPostMessage(psi->ci.hwndPartner, WM_DDE_REQUEST,
  1120. WM_DDE_ACK, psi->ci.hwndConv, 0, 0, HIWORD(lParam));
  1121. if (dwError) {
  1122. SetLastDDEMLError(psi->ci.pcii, dwError);
  1123. GlobalDeleteAtom(HIWORD(lParam)); // message copy
  1124. }
  1125. }
  1126. return (TRUE);
  1127. }
  1128. /***************************************************************************\
  1129. * ClRespRequestData
  1130. *
  1131. * Description:
  1132. * Handles response to either a WM_DDE_ACK or WM_DDE_DATA in response to
  1133. * a WM_DDE_REQUEST message.
  1134. *
  1135. * History:
  1136. * 11-19-91 sanfords Created.
  1137. \***************************************************************************/
  1138. BOOL ClRespRequestData(
  1139. PXACT_INFO pxi,
  1140. UINT msg,
  1141. LPARAM lParam)
  1142. {
  1143. UINT_PTR uiLo, uiHi;
  1144. WORD wFmt, wStatus;
  1145. DWORD dwError;
  1146. if (msg) {
  1147. switch (msg) {
  1148. case WM_DDE_DATA:
  1149. UnpackDDElParam(WM_DDE_DATA, lParam, (PUINT_PTR)&pxi->hDDEResult, &uiHi);
  1150. if (!pxi->hDDEResult) {
  1151. // must be an advise data message with NODATA.
  1152. return (ClSpontAdviseData((PCL_CONV_INFO)pxi->pcoi, lParam));
  1153. }
  1154. if (!ExtractDDEDataInfo(pxi->hDDEResult, &wStatus, &wFmt)) {
  1155. return (ClSpontAdviseData((PCL_CONV_INFO)pxi->pcoi, lParam));
  1156. }
  1157. if (!(wStatus & DDE_FREQUESTED)) {
  1158. // must be advise data
  1159. return (ClSpontAdviseData((PCL_CONV_INFO)pxi->pcoi, lParam));
  1160. }
  1161. if (wStatus & DDE_FACKREQ) {
  1162. // if DDE_FRELEASE is not set, and this is a synchronous
  1163. // transaction, we need to make a copy here so the user
  1164. // can free at his leisure.
  1165. // reuse uiHi - message copy
  1166. dwError = PackAndPostMessage(pxi->pcoi->hwndPartner,
  1167. WM_DDE_DATA, WM_DDE_ACK, pxi->pcoi->hwndConv, 0,
  1168. pxi->wFmt == wFmt && pxi->gaItem == (GATOM)uiHi ?
  1169. DDE_FACK : 0, uiHi);
  1170. if (dwError) {
  1171. SetLastDDEMLError(pxi->pcoi->pcii, dwError);
  1172. }
  1173. } else {
  1174. GlobalDeleteAtom((GATOM)uiHi); // message copy
  1175. }
  1176. if (wFmt != pxi->wFmt || (GATOM)uiHi != pxi->gaItem) {
  1177. /*
  1178. * BOGUS returned data! Just free it and make it look like
  1179. * a NACK
  1180. */
  1181. FreeDDEData(pxi->hDDEResult, FALSE, TRUE);
  1182. pxi->hDDEResult = 0;
  1183. if (TransactionComplete(pxi, 0)) {
  1184. goto Cleanup;
  1185. }
  1186. } else {
  1187. if (TransactionComplete(pxi, (HDDEDATA)-1)) {
  1188. goto Cleanup;
  1189. }
  1190. }
  1191. break;
  1192. case WM_DDE_ACK:
  1193. UnpackDDElParam(WM_DDE_ACK, lParam, &uiLo, &uiHi);
  1194. if ((GATOM)uiHi != pxi->gaItem) {
  1195. return(SpontaneousClientMessage((PCL_CONV_INFO)pxi->pcoi, msg, lParam));
  1196. }
  1197. pxi->state = XST_DATARCVD;
  1198. pxi->wStatus = (WORD)uiLo;
  1199. GlobalDeleteAtom((GATOM)uiHi); // message copy
  1200. if (TransactionComplete(pxi, 0)) {
  1201. goto Cleanup;
  1202. }
  1203. break;
  1204. default:
  1205. return (SpontaneousClientMessage((PCL_CONV_INFO)pxi->pcoi, msg, lParam));
  1206. }
  1207. } else {
  1208. Cleanup:
  1209. GlobalDeleteAtom(pxi->gaItem); // pxi copy
  1210. if (pxi->hDDEResult) {
  1211. FreeDDEData(pxi->hDDEResult, FALSE, TRUE); // free message data
  1212. }
  1213. UnlinkTransaction(pxi);
  1214. DDEMLFree(pxi);
  1215. }
  1216. if (msg) {
  1217. FreeDDElParam(msg, lParam);
  1218. }
  1219. return (TRUE);
  1220. }
  1221. //----------------------SPONTANEOUS CLIENT MESSAGE---------------------//
  1222. /***************************************************************************\
  1223. * SpontaneousClientMessage
  1224. *
  1225. * Description:
  1226. * General unexpected message client side handler.
  1227. *
  1228. * History:
  1229. * 11-19-91 sanfords Created.
  1230. \***************************************************************************/
  1231. BOOL SpontaneousClientMessage(
  1232. PCL_CONV_INFO pci,
  1233. UINT msg,
  1234. LPARAM lParam)
  1235. {
  1236. switch (msg) {
  1237. case WM_DDE_DATA:
  1238. return (ClSpontAdviseData(pci, lParam));
  1239. break;
  1240. default:
  1241. DumpDDEMessage(!(pci->ci.state & ST_INTRA_PROCESS), msg, lParam);
  1242. ShutdownConversation((PCONV_INFO)pci, TRUE);
  1243. return (TRUE);
  1244. }
  1245. }
  1246. //----------------------SPONTANEOUS SERVER MESSAGE---------------------//
  1247. /***************************************************************************\
  1248. * SpontaneousServerMessage
  1249. *
  1250. * Description:
  1251. * General unexpected message server side handler.
  1252. *
  1253. * History:
  1254. * 11-19-91 sanfords Created.
  1255. \***************************************************************************/
  1256. BOOL SpontaneousServerMessage(
  1257. PSVR_CONV_INFO psi,
  1258. UINT msg,
  1259. LPARAM lParam)
  1260. {
  1261. switch (msg) {
  1262. case WM_DDE_ADVISE:
  1263. return (SvSpontAdvise(psi, lParam));
  1264. break;
  1265. case WM_DDE_UNADVISE:
  1266. return (SvSpontUnadvise(psi, lParam));
  1267. break;
  1268. case WM_DDE_EXECUTE:
  1269. return (SvSpontExecute(psi, lParam));
  1270. break;
  1271. case WM_DDE_POKE:
  1272. return (SvSpontPoke(psi, lParam));
  1273. break;
  1274. case WM_DDE_REQUEST:
  1275. return (SvSpontRequest(psi, lParam));
  1276. break;
  1277. default:
  1278. DumpDDEMessage(!(psi->ci.state & ST_INTRA_PROCESS), msg, lParam);
  1279. /*
  1280. * It use to call ShutdownConversation here. Don't call it
  1281. * anymore. Fix for bugs: 49063, 70906
  1282. */
  1283. //ShutdownConversation((PCONV_INFO)psi, TRUE);
  1284. return (TRUE);
  1285. }
  1286. }
  1287. //-------------------------HELPER FUNCTIONS----------------------------//
  1288. /***************************************************************************\
  1289. * AllocAndSetDDEData
  1290. *
  1291. * Description:
  1292. * Worker function to create a data handle of size cb with wStatus and
  1293. * wFmt initialized. If cb == -1 pSrc is assumed to be a valid hDDE
  1294. * that is to have its data set.
  1295. *
  1296. * History:
  1297. * 11-19-91 sanfords Created.
  1298. \***************************************************************************/
  1299. HANDLE AllocAndSetDDEData(
  1300. LPBYTE pSrc,
  1301. DWORD cb,
  1302. WORD wStatus,
  1303. WORD wFmt) // a 0 format implied execute data
  1304. {
  1305. HANDLE hDDE;
  1306. DWORD cbOff;
  1307. PDDE_DATA pdde;
  1308. DWORD fCopyIt;
  1309. if (cb == -1) {
  1310. hDDE = (HANDLE)pSrc;
  1311. cb = (DWORD)GlobalSize(hDDE);
  1312. fCopyIt = FALSE;
  1313. } else {
  1314. hDDE = UserGlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT,
  1315. (wFmt ? (cb + 4) : cb));
  1316. fCopyIt = (pSrc != NULL);
  1317. }
  1318. if (hDDE == NULL) {
  1319. return(0);
  1320. }
  1321. USERGLOBALLOCK(hDDE, pdde);
  1322. if (pdde == NULL) {
  1323. WOWGLOBALFREE(hDDE);
  1324. return (0);
  1325. }
  1326. if (wFmt) {
  1327. pdde->wStatus = wStatus;
  1328. pdde->wFmt = wFmt;
  1329. cbOff = 4;
  1330. } else {
  1331. cbOff = 0;
  1332. }
  1333. if (fCopyIt) {
  1334. RtlCopyMemory((PBYTE)pdde + cbOff, pSrc, cb);
  1335. }
  1336. USERGLOBALUNLOCK(hDDE);
  1337. return (hDDE);
  1338. }
  1339. /***************************************************************************\
  1340. * PackAndPostMessage
  1341. *
  1342. * Description:
  1343. * Worker function to provide common functionality. An error code is
  1344. * return ed on failure. 0 on success.
  1345. *
  1346. * History:
  1347. * 11-19-91 sanfords Created.
  1348. \***************************************************************************/
  1349. DWORD PackAndPostMessage(
  1350. HWND hwndTo,
  1351. UINT msgIn,
  1352. UINT msgOut,
  1353. HWND hwndFrom,
  1354. LPARAM lParam,
  1355. UINT_PTR uiLo,
  1356. UINT_PTR uiHi)
  1357. {
  1358. DWORD retval;
  1359. lParam = ReuseDDElParam(lParam, msgIn, msgOut, uiLo, uiHi);
  1360. if (!lParam) {
  1361. return (DMLERR_MEMORY_ERROR);
  1362. }
  1363. CheckDDECritIn;
  1364. LeaveDDECrit;
  1365. CheckDDECritOut;
  1366. retval = (DWORD)PostMessage(hwndTo, msgOut, (WPARAM)hwndFrom, lParam);
  1367. switch (retval) {
  1368. case FAIL_POST:
  1369. #if (FAIL_POST != FALSE)
  1370. #error FAIL_POST must be defined as PostMessage's failure return value.
  1371. #endif
  1372. FreeDDElParam(msgOut, lParam);
  1373. RIPMSG0(RIP_WARNING, "PostMessage failed.");
  1374. /* Fall through */
  1375. case FAILNOFREE_POST:
  1376. retval = DMLERR_POSTMSG_FAILED;
  1377. break;
  1378. default:
  1379. #if (FAKE_POST != TRUE)
  1380. #error FAKE_POST must be defined as PostMessage's success return value.
  1381. #endif
  1382. UserAssert(retval == TRUE);
  1383. retval = 0;
  1384. }
  1385. EnterDDECrit;
  1386. return (retval);
  1387. }
  1388. /***************************************************************************\
  1389. * ExtractDDEDataInfo
  1390. *
  1391. * Description:
  1392. * Worker function to retrieve wStatus and wFmt from a standard DDE data
  1393. * handle - NOT FOR EXECUTE HANDLES.
  1394. *
  1395. * History:
  1396. * 11-19-91 sanfords Created.
  1397. \***************************************************************************/
  1398. BOOL ExtractDDEDataInfo(
  1399. HANDLE hDDE,
  1400. LPWORD pwStatus,
  1401. LPWORD pwFmt)
  1402. {
  1403. PDDE_DATA pdde;
  1404. USERGLOBALLOCK(hDDE, pdde);
  1405. if (pdde == NULL) {
  1406. return (FALSE);
  1407. }
  1408. *pwStatus = pdde->wStatus;
  1409. *pwFmt = pdde->wFmt;
  1410. USERGLOBALUNLOCK(hDDE);
  1411. return (TRUE);
  1412. }
  1413. /***************************************************************************\
  1414. * TransactionComplete
  1415. *
  1416. * Description:
  1417. * Called when a response function completes a transaction. pxi->wStatus,
  1418. * pxi->flags, pxi->wFmt, pxi->gaItem, pxi->hXact, and hData are expected
  1419. * to be set apropriately for a XTYP_XACT_COMPLETE callback.
  1420. *
  1421. * fCleanup is returned - TRUE implies the calling function needs to
  1422. * cleanup its pxi before returning. (fAsync case.)
  1423. *
  1424. * History:
  1425. * 11-19-91 sanfords Created.
  1426. \***************************************************************************/
  1427. BOOL TransactionComplete(
  1428. PXACT_INFO pxi,
  1429. HDDEDATA hData)
  1430. {
  1431. LATOM al;
  1432. BOOL fMustFree;
  1433. if (pxi->flags & XIF_ABANDONED) {
  1434. UserAssert(!(pxi->flags & XIF_SYNCHRONOUS));
  1435. return (TRUE);
  1436. }
  1437. pxi->flags |= XIF_COMPLETE;
  1438. if (pxi->flags & XIF_SYNCHRONOUS) {
  1439. PostMessage(pxi->pcoi->hwndConv, WM_TIMER, TID_TIMEOUT, 0);
  1440. return (FALSE);
  1441. } else {
  1442. if (hData == (HDDEDATA)(-1)) {
  1443. fMustFree = TRUE;
  1444. hData = InternalCreateDataHandle(pxi->pcoi->pcii,
  1445. (LPBYTE)pxi->hDDEResult, (DWORD)-1, 0,
  1446. HDATA_NOAPPFREE | HDATA_READONLY, 0, 0);
  1447. } else {
  1448. fMustFree = FALSE;
  1449. }
  1450. al = GlobalToLocalAtom(pxi->gaItem);
  1451. if (!(pxi->wStatus & DDE_FACK)) {
  1452. if (pxi->wStatus & DDE_FBUSY) {
  1453. SetLastDDEMLError(pxi->pcoi->pcii, DMLERR_BUSY);
  1454. } else {
  1455. SetLastDDEMLError(pxi->pcoi->pcii, DMLERR_NOTPROCESSED);
  1456. }
  1457. }
  1458. /*
  1459. * During the callback the app may disconnect or otherwise kill
  1460. * this conversation so we unlink the pxi FIRST so cleanup code
  1461. * doesn't destroy it before this transaction code exits.
  1462. */
  1463. UnlinkTransaction(pxi);
  1464. DoCallback(
  1465. pxi->pcoi->pcii,
  1466. (WORD)XTYP_XACT_COMPLETE,
  1467. pxi->wFmt,
  1468. pxi->pcoi->hConv,
  1469. NORMAL_HSZ_FROM_LATOM(pxi->pcoi->laTopic),
  1470. (HSZ)al,
  1471. hData,
  1472. (ULONG_PTR)pxi->hXact,
  1473. (DWORD)pxi->wStatus);
  1474. DeleteAtom(al);
  1475. if (fMustFree) {
  1476. InternalFreeDataHandle(hData, FALSE);
  1477. pxi->hDDEResult = 0;
  1478. }
  1479. /*
  1480. * during the callback is the only time the app has to access the
  1481. * transaction information. pxi->hXact will be invalid once he
  1482. * returns.
  1483. */
  1484. if (pxi->hXact) {
  1485. DestroyHandle(pxi->hXact);
  1486. pxi->hXact = 0;
  1487. }
  1488. return (TRUE);
  1489. }
  1490. }
  1491. /***************************************************************************\
  1492. * UnpackAndFreeDDEMLDataHandle
  1493. *
  1494. * Description:
  1495. * Removes DDEML data handle wrapping from a DDE data handle. If the
  1496. * data handle is APPOWNED the wrapping is NOT freed. The hDDE is
  1497. * return ed or 0 on failure. If fExec is FALSE, this call fails on
  1498. * HDATA_EXECUTE type handles.
  1499. *
  1500. * History:
  1501. * 11-19-91 sanfords Created.
  1502. \***************************************************************************/
  1503. HANDLE UnpackAndFreeDDEMLDataHandle(
  1504. HDDEDATA hData,
  1505. BOOL fExec)
  1506. {
  1507. PDDEMLDATA pdd;
  1508. HANDLE hDDE;
  1509. CheckDDECritIn;
  1510. if (hData == 0) {
  1511. return (0);
  1512. }
  1513. pdd = (PDDEMLDATA)ValidateCHandle((HANDLE)hData, HTYPE_DATA_HANDLE,
  1514. HINST_ANY);
  1515. if (pdd == NULL) {
  1516. return (0);
  1517. }
  1518. if (!fExec && pdd->flags & HDATA_EXECUTE) {
  1519. return (0);
  1520. }
  1521. hDDE = pdd->hDDE;
  1522. if (pdd->flags & HDATA_APPOWNED) {
  1523. return (hDDE); // don't destroy appowned data handles
  1524. }
  1525. DDEMLFree(pdd);
  1526. DestroyHandle((HANDLE)hData);
  1527. return (hDDE);
  1528. }