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.

740 lines
22 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: ddetrack.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * client sied DDE tracking routines
  7. *
  8. * 10-22-91 sanfords created
  9. \***************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #if defined(BUILD_WOW6432)
  13. #define DDEDATA_WITH_HANDLE_SIZE (sizeof (DDEDATA_WOW6432))
  14. #else
  15. #define DDEDATA_WITH_HANDLE_SIZE (sizeof (DDE_DATA))
  16. #endif
  17. DWORD _ClientCopyDDEIn1(
  18. HANDLE hClient, // client handle to dde data or ddepack data
  19. PINTDDEINFO pi) // info for transfer
  20. {
  21. PBYTE pData;
  22. DWORD flags;
  23. //
  24. // zero out everything but the flags
  25. //
  26. flags = pi->flags;
  27. RtlZeroMemory(pi, sizeof(INTDDEINFO));
  28. pi->flags = flags;
  29. USERGLOBALLOCK(hClient, pData);
  30. if (pData == NULL) { // bad hClient
  31. RIPMSG0(RIP_WARNING, "_ClientCopyDDEIn1:GlobalLock failed.");
  32. return (FAIL_POST);
  33. }
  34. if (flags & XS_PACKED) {
  35. if (UserGlobalSize(hClient) < sizeof(DDEPACK)) {
  36. /*
  37. * must be a low memory condition. fail.
  38. */
  39. return(FAIL_POST);
  40. }
  41. pi->DdePack = *(PDDEPACK)pData;
  42. USERGLOBALUNLOCK(hClient);
  43. UserGlobalFree(hClient); // packed data handles are not WOW matched.
  44. hClient = NULL;
  45. if (!(flags & (XS_LOHANDLE | XS_HIHANDLE))) {
  46. if (flags & XS_EXECUTE && flags & XS_FREESRC) {
  47. /*
  48. * free execute ACK data
  49. */
  50. WOWGLOBALFREE((HANDLE)pi->DdePack.uiHi);
  51. }
  52. return (DO_POST); // no direct data
  53. }
  54. if (flags & XS_LOHANDLE) {
  55. pi->hDirect = (HANDLE)pi->DdePack.uiLo;
  56. } else {
  57. pi->hDirect = (HANDLE)pi->DdePack.uiHi;
  58. }
  59. if (pi->hDirect == 0) {
  60. return (DO_POST); // must be warm link
  61. }
  62. USERGLOBALLOCK(pi->hDirect, pi->pDirect);
  63. if (pi->pDirect == NULL) {
  64. RIPMSG1(RIP_ERROR, "_ClientCopyDDEIn1:GlobalLock failed for hDirect %p.",pi->hDirect);
  65. return FAILNOFREE_POST;
  66. }
  67. pData = pi->pDirect;
  68. pi->cbDirect = (UINT)UserGlobalSize(pi->hDirect);
  69. } else { // not packed - must be execute data or we wouldn't be called
  70. UserAssert(flags & XS_EXECUTE);
  71. pi->cbDirect = (UINT)UserGlobalSize(hClient);
  72. pi->hDirect = hClient;
  73. pi->pDirect = pData;
  74. hClient = NULL;
  75. }
  76. if (flags & XS_DATA) {
  77. PDDE_DATA pDdeData = (PDDE_DATA)pData;
  78. /*
  79. * Assert that the hClient has been freed. If not this code will return
  80. * the wrong thing on failure
  81. */
  82. UserAssert(flags & XS_PACKED);
  83. //
  84. // check here for indirect data
  85. //
  86. switch (pDdeData->wFmt) {
  87. case CF_BITMAP:
  88. case CF_DSPBITMAP:
  89. //
  90. // Imediately following the dde data header is a bitmap handle.
  91. //
  92. UserAssert(pi->cbDirect >= DDEDATA_WITH_HANDLE_SIZE);
  93. pi->hIndirect = (HANDLE)pDdeData->Data;
  94. if (pi->hIndirect == 0) {
  95. RIPMSG0(RIP_WARNING, "_ClientCopyDDEIn1:GdiConvertBitmap failed");
  96. return(FAILNOFREE_POST);
  97. }
  98. // pi->cbIndirect = 0; // zero init.
  99. // pi->pIndirect = NULL; // zero init.
  100. pi->flags |= XS_BITMAP;
  101. break;
  102. case CF_DIB:
  103. //
  104. // Imediately following the dde data header is a global data handle
  105. // to the DIB bits.
  106. //
  107. UserAssert(pi->cbDirect >= DDEDATA_WITH_HANDLE_SIZE);
  108. pi->flags |= XS_DIB;
  109. pi->hIndirect = (HANDLE)pDdeData->Data;
  110. USERGLOBALLOCK(pi->hIndirect, pi->pIndirect);
  111. if (pi->pIndirect == NULL) {
  112. RIPMSG0(RIP_WARNING, "_ClientCopyDDEIn1:CF_DIB GlobalLock failed.");
  113. return (FAILNOFREE_POST);
  114. }
  115. pi->cbIndirect = (UINT)UserGlobalSize(pi->hIndirect);
  116. break;
  117. case CF_PALETTE:
  118. UserAssert(pi->cbDirect >= DDEDATA_WITH_HANDLE_SIZE);
  119. pi->hIndirect = (HANDLE) pDdeData->Data;
  120. if (pi->hIndirect == 0) {
  121. RIPMSG0(RIP_WARNING, "_ClientCopyDDEIn1:GdiConvertPalette failed.");
  122. return(FAILNOFREE_POST);
  123. }
  124. // pi->cbIndirect = 0; // zero init.
  125. // pi->pIndirect = NULL; // zero init.
  126. pi->flags |= XS_PALETTE;
  127. break;
  128. case CF_DSPMETAFILEPICT:
  129. case CF_METAFILEPICT:
  130. //
  131. // This format holds a global data handle which contains
  132. // a METAFILEPICT structure that in turn contains
  133. // a GDI metafile.
  134. //
  135. UserAssert(pi->cbDirect >= DDEDATA_WITH_HANDLE_SIZE);
  136. pi->hIndirect = GdiConvertMetaFilePict((HANDLE)pDdeData->Data);
  137. if (pi->hIndirect == 0) {
  138. RIPMSG0(RIP_WARNING, "_ClientCopyDDEIn1:GdiConvertMetaFilePict failed");
  139. return(FAILNOFREE_POST);
  140. }
  141. // pi->cbIndirect = 0; // zero init.
  142. // pi->pIndirect = NULL; // zero init.
  143. pi->flags |= XS_METAFILEPICT;
  144. break;
  145. case CF_ENHMETAFILE:
  146. case CF_DSPENHMETAFILE:
  147. UserAssert(pi->cbDirect >= DDEDATA_WITH_HANDLE_SIZE);
  148. pi->hIndirect = GdiConvertEnhMetaFile((HENHMETAFILE)pDdeData->Data);
  149. if (pi->hIndirect == 0) {
  150. RIPMSG0(RIP_WARNING, "_ClientCopyDDEIn1:GdiConvertEnhMetaFile failed");
  151. return(FAILNOFREE_POST);
  152. }
  153. // pi->cbIndirect = 0; // zero init.
  154. // pi->pIndirect = NULL; // zero init.
  155. pi->flags |= XS_ENHMETAFILE;
  156. break;
  157. }
  158. }
  159. return (DO_POST);
  160. }
  161. /*
  162. * unlocks and frees DDE data pointers as appropriate
  163. */
  164. VOID _ClientCopyDDEIn2(
  165. PINTDDEINFO pi)
  166. {
  167. if (pi->cbDirect) {
  168. USERGLOBALUNLOCK(pi->hDirect);
  169. if (pi->flags & XS_FREESRC) {
  170. WOWGLOBALFREE(pi->hDirect);
  171. }
  172. }
  173. if (pi->cbIndirect) {
  174. USERGLOBALUNLOCK(pi->hIndirect);
  175. if (pi->flags & XS_FREESRC) {
  176. WOWGLOBALFREE(pi->hIndirect);
  177. }
  178. }
  179. }
  180. /*
  181. * returns fHandleValueChanged.
  182. */
  183. BOOL FixupDdeExecuteIfNecessary(
  184. HGLOBAL *phCommands,
  185. BOOL fNeedUnicode)
  186. {
  187. UINT cbLen;
  188. UINT cbSrc = (UINT)GlobalSize(*phCommands);
  189. LPVOID pstr;
  190. HGLOBAL hTemp;
  191. BOOL fHandleValueChanged = FALSE;
  192. USERGLOBALLOCK(*phCommands, pstr);
  193. if (cbSrc && pstr != NULL) {
  194. BOOL fIsUnicodeText;
  195. #ifdef ISTEXTUNICODE_WORKS
  196. int flags;
  197. flags = (IS_TEXT_UNICODE_UNICODE_MASK |
  198. IS_TEXT_UNICODE_REVERSE_MASK |
  199. (IS_TEXT_UNICODE_NOT_UNICODE_MASK &
  200. (~IS_TEXT_UNICODE_ILLEGAL_CHARS)) |
  201. IS_TEXT_UNICODE_NOT_ASCII_MASK);
  202. fIsUnicodeText = RtlIsTextUnicode(pstr, cbSrc - 2, &flags);
  203. #else
  204. fIsUnicodeText = ((cbSrc >= sizeof(WCHAR)) && (((LPSTR)pstr)[1] == '\0'));
  205. #endif
  206. if (!fIsUnicodeText && fNeedUnicode) {
  207. LPWSTR pwsz;
  208. /*
  209. * Contents needs to be UNICODE.
  210. */
  211. cbLen = strlen(pstr) + 1;
  212. cbSrc = min(cbSrc, cbLen);
  213. pwsz = UserLocalAlloc(HEAP_ZERO_MEMORY, cbSrc * sizeof(WCHAR));
  214. if (pwsz != NULL) {
  215. if (NT_SUCCESS(RtlMultiByteToUnicodeN(
  216. pwsz,
  217. cbSrc * sizeof(WCHAR),
  218. NULL,
  219. (PCHAR)pstr,
  220. cbSrc))) {
  221. USERGLOBALUNLOCK(*phCommands);
  222. if ((hTemp = GlobalReAlloc(
  223. *phCommands,
  224. cbSrc * sizeof(WCHAR),
  225. GMEM_MOVEABLE)) != NULL) {
  226. fHandleValueChanged = (hTemp != *phCommands);
  227. *phCommands = hTemp;
  228. USERGLOBALLOCK(*phCommands, pstr);
  229. pwsz[cbSrc - 1] = L'\0';
  230. wcscpy(pstr, pwsz);
  231. }
  232. }
  233. UserLocalFree(pwsz);
  234. }
  235. } else if (fIsUnicodeText && !fNeedUnicode) {
  236. LPSTR psz;
  237. /*
  238. * Contents needs to be ANSI.
  239. */
  240. cbLen = (wcslen(pstr) + 1) * sizeof(WCHAR);
  241. cbSrc = min(cbSrc, cbLen);
  242. psz = UserLocalAlloc(HEAP_ZERO_MEMORY, cbSrc);
  243. if (psz != NULL) {
  244. if (NT_SUCCESS(RtlUnicodeToMultiByteN(
  245. psz,
  246. cbSrc,
  247. NULL,
  248. (PWSTR)pstr,
  249. cbSrc))) {
  250. USERGLOBALUNLOCK(*phCommands);
  251. if ((hTemp = GlobalReAlloc(
  252. *phCommands,
  253. cbSrc / sizeof(WCHAR),
  254. GMEM_MOVEABLE)) != NULL) {
  255. fHandleValueChanged = (hTemp != *phCommands);
  256. *phCommands = hTemp;
  257. USERGLOBALLOCK(*phCommands, pstr);
  258. UserAssert(pstr);
  259. psz[cbSrc - 1] = '\0';
  260. strcpy(pstr, psz);
  261. }
  262. }
  263. UserLocalFree(psz);
  264. }
  265. }
  266. USERGLOBALUNLOCK(*phCommands);
  267. }
  268. return(fHandleValueChanged);
  269. }
  270. /*
  271. * Allocates and locks global handles as appropriate in preperation
  272. * for thunk copying.
  273. */
  274. HANDLE _ClientCopyDDEOut1(
  275. PINTDDEINFO pi)
  276. {
  277. HANDLE hDdePack = NULL;
  278. PDDEPACK pDdePack = NULL;
  279. if (pi->flags & XS_PACKED) {
  280. /*
  281. * make a wrapper for the data
  282. */
  283. hDdePack = UserGlobalAlloc(GMEM_DDESHARE | GMEM_FIXED,
  284. sizeof(DDEPACK));
  285. pDdePack = (PDDEPACK)hDdePack;
  286. if (pDdePack == NULL) {
  287. RIPMSG0(RIP_WARNING, "_ClientCopyDDEOut1:Couldn't allocate DDEPACK");
  288. return (NULL);
  289. }
  290. *pDdePack = pi->DdePack;
  291. }
  292. if (pi->cbDirect) {
  293. pi->hDirect = UserGlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, pi->cbDirect);
  294. if (pi->hDirect == NULL) {
  295. RIPMSG0(RIP_WARNING, "_ClientCopyDDEOut1:Couldn't allocate hDirect");
  296. if (hDdePack) {
  297. UserGlobalFree(hDdePack);
  298. }
  299. return (NULL);
  300. }
  301. USERGLOBALLOCK(pi->hDirect, pi->pDirect);
  302. UserAssert(pi->pDirect);
  303. // fixup packed data reference to direct data
  304. if (pDdePack != NULL) {
  305. if (pi->flags & XS_LOHANDLE) {
  306. pDdePack->uiLo = (UINT_PTR)pi->hDirect;
  307. UserAssert((ULONG_PTR)pDdePack->uiLo == (ULONG_PTR)pi->hDirect);
  308. } else if (pi->flags & XS_HIHANDLE) {
  309. pDdePack->uiHi = (UINT_PTR)pi->hDirect;
  310. UserAssert((ULONG_PTR)pDdePack->uiHi == (ULONG_PTR)pi->hDirect);
  311. }
  312. }
  313. if (pi->cbIndirect) {
  314. pi->hIndirect = UserGlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE,
  315. pi->cbIndirect);
  316. if (pi->hIndirect == NULL) {
  317. RIPMSG0(RIP_WARNING, "_ClientCopyDDEOut1:Couldn't allocate hIndirect");
  318. USERGLOBALUNLOCK(pi->hDirect);
  319. UserGlobalFree(pi->hDirect);
  320. if (hDdePack) {
  321. UserGlobalFree(hDdePack);
  322. }
  323. return (NULL);
  324. }
  325. USERGLOBALLOCK(pi->hIndirect, pi->pIndirect);
  326. UserAssert(pi->pIndirect);
  327. }
  328. }
  329. if (hDdePack) {
  330. return (hDdePack);
  331. } else {
  332. return (pi->hDirect);
  333. }
  334. }
  335. /*
  336. * Fixes up internal poniters after thunk copy and unlocks handles.
  337. */
  338. BOOL _ClientCopyDDEOut2(
  339. PINTDDEINFO pi)
  340. {
  341. BOOL fSuccess = TRUE;
  342. /*
  343. * done with copies - now fixup indirect references
  344. */
  345. if (pi->hIndirect) {
  346. PDDE_DATA pDdeData = (PDDE_DATA)pi->pDirect;
  347. switch (pDdeData->wFmt) {
  348. case CF_BITMAP:
  349. case CF_DSPBITMAP:
  350. case CF_PALETTE:
  351. pDdeData->Data = (KERNEL_PVOID)pi->hIndirect;
  352. fSuccess = (pDdeData->Data != NULL);
  353. break;
  354. case CF_METAFILEPICT:
  355. case CF_DSPMETAFILEPICT:
  356. pDdeData->Data = (KERNEL_PVOID)GdiCreateLocalMetaFilePict(pi->hIndirect);
  357. fSuccess = (pDdeData->Data != NULL);
  358. break;
  359. case CF_DIB:
  360. pDdeData->Data = (KERNEL_PVOID)pi->hIndirect;
  361. fSuccess = (pDdeData->Data != NULL);
  362. USERGLOBALUNLOCK(pi->hIndirect);
  363. break;
  364. case CF_ENHMETAFILE:
  365. case CF_DSPENHMETAFILE:
  366. pDdeData->Data = (KERNEL_PVOID)GdiCreateLocalEnhMetaFile(pi->hIndirect);
  367. fSuccess = (pDdeData->Data != NULL);
  368. break;
  369. default:
  370. RIPMSG0(RIP_WARNING, "_ClientCopyDDEOut2:Unknown format w/indirect data.");
  371. fSuccess = FALSE;
  372. USERGLOBALUNLOCK(pi->hIndirect);
  373. }
  374. }
  375. UserAssert(pi->hDirect); // if its null, we didn't need to call this function.
  376. USERGLOBALUNLOCK(pi->hDirect);
  377. if (pi->flags & XS_EXECUTE) {
  378. /*
  379. * Its possible that in RAW DDE cases where the app allocated the
  380. * execute data as non-moveable, we have a different hDirect
  381. * than we started with. This needs to be noted and passed
  382. * back to the server. (Very RARE case)
  383. */
  384. FixupDdeExecuteIfNecessary(&pi->hDirect,
  385. pi->flags & XS_UNICODE);
  386. }
  387. return fSuccess;
  388. }
  389. /*
  390. * This routine is called by the tracking layer when it frees DDE objects
  391. * on behalf of a client. This cleans up the LOCAL objects associated
  392. * with the DDE objects. It should NOT remove truely global objects such
  393. * as bitmaps or palettes except in the XS_DUMPMSG case which is for
  394. * faked Posts.
  395. */
  396. #if DBG
  397. /*
  398. * Help track down a bug where I suspect the xxxFreeListFree is
  399. * freeing a handle already freed by some other means which has
  400. * since been reallocated and is trashing the client heap. (SAS)
  401. */
  402. HANDLE DDEHandleLastFreed = 0;
  403. #endif
  404. BOOL _ClientFreeDDEHandle(
  405. HANDLE hDDE,
  406. DWORD flags)
  407. {
  408. PDDEPACK pDdePack;
  409. HANDLE hNew;
  410. if (flags & XS_PACKED) {
  411. pDdePack = (PDDEPACK)hDDE;
  412. if (pDdePack == NULL) {
  413. return (FALSE);
  414. }
  415. if (flags & XS_LOHANDLE) {
  416. hNew = (HANDLE)pDdePack->uiLo;
  417. } else {
  418. hNew = (HANDLE)pDdePack->uiHi;
  419. }
  420. WOWGLOBALFREE(hDDE);
  421. hDDE = hNew;
  422. }
  423. /*
  424. * Do a range check and call GlobalFlags to validate, just to prevent heap checking
  425. * from complaining during the GlobalSize call.
  426. * Is this leaking atoms??
  427. */
  428. if ((hDDE <= (HANDLE)0xFFFF)
  429. || (GlobalFlags(hDDE) == GMEM_INVALID_HANDLE)
  430. || !GlobalSize(hDDE)) {
  431. /*
  432. * There may be cases where apps improperly freed stuff
  433. * when they shouldn't have so make sure this handle
  434. * is valid by the time it gets here.
  435. *
  436. * See SvSpontAdvise; it posts a message with an atom in uiHi. Then from _PostMessage
  437. * in the kernel side, we might end up here. So it's not only for apps...
  438. */
  439. return(FALSE);
  440. }
  441. if (flags & XS_DUMPMSG) {
  442. if (flags & XS_PACKED) {
  443. if (!IS_PTR(hNew)) {
  444. GlobalDeleteAtom(LOWORD((ULONG_PTR)hNew));
  445. if (!(flags & XS_DATA)) {
  446. return(TRUE); // ACK
  447. }
  448. }
  449. } else {
  450. if (!(flags & XS_EXECUTE)) {
  451. GlobalDeleteAtom(LOWORD((ULONG_PTR)hDDE)); // REQUEST, UNADVISE
  452. return(TRUE);
  453. }
  454. }
  455. }
  456. if (flags & XS_DATA) {
  457. // POKE, DATA
  458. #if DBG
  459. DDEHandleLastFreed = hDDE;
  460. #endif
  461. FreeDDEData(hDDE,
  462. (flags & XS_DUMPMSG) ? FALSE : TRUE, // fIgnorefRelease
  463. (flags & XS_DUMPMSG) ? TRUE : FALSE); // fDestroyTruelyGlobalObjects
  464. } else {
  465. // ADVISE, EXECUTE
  466. #if DBG
  467. DDEHandleLastFreed = hDDE;
  468. #endif
  469. WOWGLOBALFREE(hDDE); // covers ADVISE case (fmt but no data)
  470. }
  471. return (TRUE);
  472. }
  473. DWORD _ClientGetDDEFlags(
  474. HANDLE hDDE,
  475. DWORD flags)
  476. {
  477. PDDEPACK pDdePack;
  478. PWORD pw;
  479. HANDLE hData;
  480. DWORD retval = 0;
  481. pDdePack = (PDDEPACK)hDDE;
  482. if (pDdePack == NULL) {
  483. return (0);
  484. }
  485. if (flags & XS_DATA) {
  486. if (pDdePack->uiLo) {
  487. hData = (HANDLE)pDdePack->uiLo;
  488. USERGLOBALLOCK(hData, pw);
  489. if (pw != NULL) {
  490. retval = (DWORD)*pw; // first word is hData is wStatus
  491. USERGLOBALUNLOCK(hData);
  492. }
  493. }
  494. } else {
  495. retval = (DWORD)pDdePack->uiLo;
  496. }
  497. return (retval);
  498. }
  499. FUNCLOG3(LOG_GENERAL, LPARAM, APIENTRY, PackDDElParam, UINT, msg, UINT_PTR, uiLo, UINT_PTR, uiHi)
  500. LPARAM APIENTRY PackDDElParam(
  501. UINT msg,
  502. UINT_PTR uiLo,
  503. UINT_PTR uiHi)
  504. {
  505. PDDEPACK pDdePack;
  506. HANDLE h;
  507. switch (msg) {
  508. case WM_DDE_EXECUTE:
  509. return((LPARAM)uiHi);
  510. case WM_DDE_ACK:
  511. case WM_DDE_ADVISE:
  512. case WM_DDE_DATA:
  513. case WM_DDE_POKE:
  514. h = UserGlobalAlloc(GMEM_DDESHARE | GMEM_FIXED, sizeof(DDEPACK));
  515. pDdePack = (PDDEPACK)h;
  516. if (pDdePack == NULL) {
  517. return(0);
  518. }
  519. pDdePack->uiLo = uiLo;
  520. pDdePack->uiHi = uiHi;
  521. return((LPARAM)h);
  522. default:
  523. return(MAKELONG((WORD)uiLo, (WORD)uiHi));
  524. }
  525. }
  526. FUNCLOG4(LOG_GENERAL, BOOL, APIENTRY, UnpackDDElParam, UINT, msg, LPARAM, lParam, PUINT_PTR, puiLo, PUINT_PTR, puiHi)
  527. BOOL APIENTRY UnpackDDElParam(
  528. UINT msg,
  529. LPARAM lParam,
  530. PUINT_PTR puiLo,
  531. PUINT_PTR puiHi)
  532. {
  533. PDDEPACK pDdePack;
  534. switch (msg) {
  535. case WM_DDE_EXECUTE:
  536. if (puiLo != NULL) {
  537. *puiLo = 0L;
  538. }
  539. if (puiHi != NULL) {
  540. *puiHi = (UINT_PTR)lParam;
  541. }
  542. return(TRUE);
  543. case WM_DDE_ACK:
  544. case WM_DDE_ADVISE:
  545. case WM_DDE_DATA:
  546. case WM_DDE_POKE:
  547. pDdePack = (PDDEPACK)lParam;
  548. if (pDdePack == NULL || !GlobalHandle(pDdePack)) {
  549. if (puiLo != NULL) {
  550. *puiLo = 0L;
  551. }
  552. if (puiHi != NULL) {
  553. *puiHi = 0L;
  554. }
  555. return(FALSE);
  556. }
  557. if (puiLo != NULL) {
  558. *puiLo = pDdePack->uiLo;
  559. }
  560. if (puiHi != NULL) {
  561. *puiHi = pDdePack->uiHi;
  562. }
  563. return(TRUE);
  564. default:
  565. if (puiLo != NULL) {
  566. *puiLo = (UINT)LOWORD(lParam);
  567. }
  568. if (puiHi != NULL) {
  569. *puiHi = (UINT)HIWORD(lParam);
  570. }
  571. return(TRUE);
  572. }
  573. }
  574. FUNCLOG2(LOG_GENERAL, BOOL, APIENTRY, FreeDDElParam, UINT, msg, LPARAM, lParam)
  575. BOOL APIENTRY FreeDDElParam(
  576. UINT msg,
  577. LPARAM lParam)
  578. {
  579. switch (msg) {
  580. case WM_DDE_ACK:
  581. case WM_DDE_ADVISE:
  582. case WM_DDE_DATA:
  583. case WM_DDE_POKE:
  584. /*
  585. * Do a range check and call GlobalFlags to validate,
  586. * just to prevent heap checking from complaining
  587. */
  588. if ((lParam > (LPARAM)0xFFFF) && GlobalFlags((HANDLE)lParam) != GMEM_INVALID_HANDLE) {
  589. if (GlobalHandle((HANDLE)lParam))
  590. return(UserGlobalFree((HANDLE)lParam) == NULL);
  591. }
  592. default:
  593. return(TRUE);
  594. }
  595. }
  596. FUNCLOG5(LOG_GENERAL, LPARAM, APIENTRY, ReuseDDElParam, LPARAM, lParam, UINT, msgIn, UINT, msgOut, UINT_PTR, uiLo, UINT_PTR, uiHi)
  597. LPARAM APIENTRY ReuseDDElParam(
  598. LPARAM lParam,
  599. UINT msgIn,
  600. UINT msgOut,
  601. UINT_PTR uiLo,
  602. UINT_PTR uiHi)
  603. {
  604. PDDEPACK pDdePack;
  605. switch (msgIn) {
  606. case WM_DDE_ACK:
  607. case WM_DDE_DATA:
  608. case WM_DDE_POKE:
  609. case WM_DDE_ADVISE:
  610. //
  611. // Incoming message was packed...
  612. //
  613. switch (msgOut) {
  614. case WM_DDE_EXECUTE:
  615. FreeDDElParam(msgIn, lParam);
  616. return((LPARAM)uiHi);
  617. case WM_DDE_ACK:
  618. case WM_DDE_ADVISE:
  619. case WM_DDE_DATA:
  620. case WM_DDE_POKE:
  621. /*
  622. * This must be a valid handle
  623. */
  624. UserAssert(GlobalFlags((HANDLE)lParam) != GMEM_INVALID_HANDLE);
  625. UserAssert(GlobalSize((HANDLE)lParam) == sizeof(DDEPACK));
  626. //
  627. // Actual cases where lParam can be reused.
  628. //
  629. pDdePack = (PDDEPACK)lParam;
  630. if (pDdePack == NULL) {
  631. return(0); // the only error case
  632. }
  633. pDdePack->uiLo = uiLo;
  634. pDdePack->uiHi = uiHi;
  635. return(lParam);
  636. default:
  637. FreeDDElParam(msgIn, lParam);
  638. return(MAKELONG((WORD)uiLo, (WORD)uiHi));
  639. }
  640. default:
  641. //
  642. // Incoming message was not packed ==> PackDDElParam()
  643. //
  644. return(PackDDElParam(msgOut, uiLo, uiHi));
  645. }
  646. }