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

487 lines
12 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: HDATA.C
  3. *
  4. * DDE manager data handle handling routines
  5. *
  6. * Created: 12/14/90 Sanford Staab
  7. *
  8. * Copyright (c) 1988, 1989, 1990 Microsoft Corporation
  9. \***************************************************************************/
  10. #include "ddemlp.h"
  11. HDDEDATA PutData(pSrc, cb, cbOff, aItem, wFmt, afCmd, pai)
  12. LPBYTE pSrc;
  13. DWORD cb;
  14. DWORD cbOff;
  15. ATOM aItem;
  16. WORD wFmt;
  17. WORD afCmd;
  18. PAPPINFO pai;
  19. {
  20. HANDLE hMem;
  21. HDDEDATA hdT;
  22. DIP dip;
  23. /* HACK ALERT!
  24. * make sure the first two words req'd by windows dde is there,
  25. * UNLESS aItem is null in which case we assume it is EXECUTE
  26. * data and don't bother.
  27. */
  28. if (aItem)
  29. cbOff += 4L;
  30. else
  31. afCmd |= HDATA_EXEC;
  32. if ((hMem = AllocDDESel(
  33. (afCmd & HDATA_APPOWNED) ? DDE_FACKREQ : DDE_FRELEASE,
  34. wFmt, cb + cbOff)) == NULL) {
  35. SETLASTERROR(pai, DMLERR_MEMORY_ERROR);
  36. return(0L);
  37. }
  38. // add to local list - make sure a similar handle isn't already there.
  39. hdT = MAKELONG(afCmd, hMem);
  40. #ifdef DEBUG
  41. if (FindPileItem(pai->pHDataPile, CmpHIWORD, (LPBYTE)&hdT, FPI_DELETE)) {
  42. AssertF(FALSE, "PutData - unexpected handle in hDataPile");
  43. }
  44. #endif // DEBUG
  45. if (AddPileItem(pai->pHDataPile, (LPBYTE)&hdT, CmpHIWORD) == API_ERROR) {
  46. GLOBALFREE(hMem);
  47. SETLASTERROR(pai, DMLERR_MEMORY_ERROR);
  48. return(0L);
  49. }
  50. // add to global list if appowned
  51. if (afCmd & HDATA_APPOWNED) {
  52. dip.hData = hMem;
  53. dip.hTask = pai->hTask;
  54. dip.cCount = 1;
  55. dip.fFlags = afCmd;
  56. if (AddPileItem(pDataInfoPile, (LPBYTE)&dip, CmpWORD) == API_ERROR) {
  57. GLOBALFREE(hMem);
  58. SETLASTERROR(pai, DMLERR_MEMORY_ERROR);
  59. return(0L);
  60. }
  61. }
  62. if (pSrc)
  63. CopyHugeBlock(pSrc, HugeOffset(GLOBALLOCK(hMem), cbOff), cb);
  64. // LOWORD(hData) always == afCmd flags
  65. return(MAKELONG(afCmd, hMem));
  66. }
  67. /*
  68. * This is the internal data handle freeing function. fInternal is TRUE if
  69. * this is called from within the DDEML (vs called via DdeFreeDataHandle())
  70. * It only frees the handle if it is in the local list.
  71. * Appowned data handles are only freed internally if a non-owner task is
  72. * doing the freeing.
  73. * It is important that the LOWORD(hData) be set properly.
  74. *
  75. * These features give this function the folowing desired characteristics:
  76. * 1) Apps cannot free data handles more than once.
  77. * 2) The DDEML cannot free APPOWNED data handles on behalf of the owner
  78. * task. (except on cleanup)
  79. */
  80. VOID FreeDataHandle(
  81. PAPPINFO pai,
  82. HDDEDATA hData,
  83. BOOL fInternal)
  84. {
  85. DIP *pDip;
  86. BOOL fRelease = 0;
  87. DDEPOKE FAR *pDdeMem;
  88. WORD fmt;
  89. TRACEAPIIN((szT, "FreeDataHandle(%lx, %lx, %d)\n", pai, hData, fInternal));
  90. // appowned data handles are not freed till their count reaches 0.
  91. if ((LOWORD(hData) & HDATA_APPOWNED) &&
  92. (pDip = (DIP *)(DWORD)FindPileItem(pDataInfoPile, CmpWORD, PHMEM(hData), 0))) {
  93. // don't internally free if in the context of the owner
  94. if (fInternal && (pDip->hTask == pai->hTask)) {
  95. TRACEAPIOUT((szT, "FreeDataHandle: Internal and of this task - not freed.\n"));
  96. return;
  97. }
  98. if (--pDip->cCount != 0) {
  99. TRACEAPIOUT((szT, "FreeDataHandle: Ref count not 0 - not freed.\n"));
  100. return;
  101. }
  102. FindPileItem(pDataInfoPile, CmpWORD, PHMEM(hData), FPI_DELETE);
  103. fRelease = TRUE;
  104. }
  105. /*
  106. * Apps can only free handles in their local list - this guards against
  107. * multiple frees by an app. (my arnt we nice)
  108. */
  109. if (!HIWORD(hData) ||
  110. !FindPileItem(pai->pHDataPile, CmpHIWORD, (LPBYTE)&hData, FPI_DELETE)) {
  111. TRACEAPIOUT((szT, "FreeDataHandle: Not in local list - not freed.\n"));
  112. return;
  113. }
  114. if (LOWORD(hData) & HDATA_EXEC) {
  115. fRelease |= !(LOWORD(hData) & HDATA_APPOWNED);
  116. } else {
  117. pDdeMem = (DDEPOKE FAR *)GLOBALLOCK(HIWORD(hData));
  118. if (pDdeMem == NULL) {
  119. TRACEAPIOUT((szT, "FreeDataHandle: Lock failed - not freed.\n"));
  120. return;
  121. }
  122. fRelease |= pDdeMem->fRelease;
  123. fmt = pDdeMem->cfFormat;
  124. GLOBALUNLOCK(HIWORD(hData));
  125. }
  126. if (fRelease) {
  127. if (LOWORD(hData) & HDATA_EXEC)
  128. GLOBALFREE(HIWORD(hData));
  129. else
  130. FreeDDEData(HIWORD(hData), fmt);
  131. }
  132. TRACEAPIOUT((szT, "FreeDataHandle: freed.\n"));
  133. }
  134. /*
  135. * This function prepairs data handles on entry into the DDEML API. It has
  136. * the following characteristics:
  137. * 1) APPOWNED data handles are copied to a non-appowned handle if being
  138. * passed to a non-local app.
  139. * 2) non-APPOWNED data handles on loan to a callback are copied so they
  140. * don't get prematurely freed.
  141. * 3) The READONLY bit is set. (in the local list)
  142. */
  143. HDDEDATA DllEntry(
  144. PCOMMONINFO pcomi,
  145. HDDEDATA hData)
  146. {
  147. if ((!(pcomi->fs & ST_ISLOCAL)) && (LOWORD(hData) & HDATA_APPOWNED) ||
  148. LOWORD(hData) & HDATA_NOAPPFREE && !(LOWORD(hData) & HDATA_APPOWNED)) {
  149. // copy APPOWNED data handles to a fresh handle if not a local conv.
  150. // copy app loaned, non appowned handles as well (this is the
  151. // relay server case)
  152. hData = CopyHDDEDATA(pcomi->pai, hData);
  153. }
  154. LOWORD(hData) |= HDATA_READONLY;
  155. AddPileItem(pcomi->pai->pHDataPile, (LPBYTE)&hData, CmpHIWORD);
  156. // NOTE: the global lists READONLY flag set but thats
  157. // ok because any hData received from a transaction will always be in
  158. // the local list due to RecvPrep().
  159. return(hData);
  160. }
  161. /*
  162. * removes the data handle from the local list. This removes responsibility
  163. * for the data handle from the sending app. APPOWNED handles are not
  164. * removed.
  165. */
  166. VOID XmitPrep(
  167. HDDEDATA hData,
  168. PAPPINFO pai)
  169. {
  170. if (!(LOWORD(hData) & HDATA_APPOWNED)) {
  171. FindPileItem(pai->pHDataPile, CmpHIWORD, (LPBYTE)&hData, FPI_DELETE);
  172. }
  173. }
  174. /*
  175. * Places the received data handle into the apropriate lists and returns
  176. * it with the proper flags set. Returns 0 if invalid hMem. afCmd should
  177. * contain any extra flags desired.
  178. */
  179. HDDEDATA RecvPrep(
  180. PAPPINFO pai,
  181. HANDLE hMem,
  182. WORD afCmd)
  183. {
  184. DIP *pdip;
  185. HDDEDATA hData;
  186. if (!hMem)
  187. return(0);
  188. // check if its an APPOWNED one, if so, log entry.
  189. if (pdip = (DIP *)(DWORD)FindPileItem(pDataInfoPile, CmpWORD, (LPBYTE)&hMem, 0)) {
  190. afCmd |= pdip->fFlags;
  191. pdip->cCount++;
  192. }
  193. // if we got one that isnt fRelease, treat it as appowed.
  194. if (!(*(LPWORD)GLOBALLOCK(hMem) & DDE_FRELEASE))
  195. afCmd |= HDATA_APPOWNED;
  196. GLOBALUNLOCK(hMem);
  197. // all received handles are readonly.
  198. hData = (HDDEDATA)MAKELONG(afCmd | HDATA_READONLY, hMem);
  199. /*
  200. * Add (or replace) into local list
  201. */
  202. AddPileItem(pai->pHDataPile, (LPBYTE)&hData, CmpHIWORD);
  203. return(hData);
  204. }
  205. HANDLE CopyDDEShareHandle(
  206. HANDLE hMem)
  207. {
  208. DWORD cb;
  209. LPBYTE pMem;
  210. cb = GlobalSize(hMem);
  211. pMem = GLOBALLOCK(hMem);
  212. if (pMem == NULL) {
  213. return(0);
  214. }
  215. hMem = GLOBALALLOC(GMEM_DDESHARE, cb);
  216. CopyHugeBlock(pMem, GLOBALPTR(hMem), cb);
  217. return(hMem);
  218. }
  219. HBITMAP CopyBitmap(
  220. PAPPINFO pai,
  221. HBITMAP hbm)
  222. {
  223. BITMAP bm;
  224. HBITMAP hbm2, hbmOld1, hbmOld2;
  225. HDC hdc, hdcMem1, hdcMem2;
  226. if (!GetObject(hbm, sizeof(BITMAP), &bm)) {
  227. return(0);
  228. }
  229. hdc = GetDC(pai->hwndDmg);
  230. if (!hdc) {
  231. return(0);
  232. }
  233. hdcMem1 = CreateCompatibleDC(hdc);
  234. if (!hdcMem1) {
  235. goto Cleanup3;
  236. }
  237. hdcMem2 = CreateCompatibleDC(hdc);
  238. if (!hdcMem2) {
  239. goto Cleanup2;
  240. }
  241. hbmOld1 = SelectObject(hdcMem1, hbm);
  242. hbm2 = CreateCompatibleBitmap(hdcMem1, bm.bmWidth, bm.bmHeight);
  243. if (!hbm2) {
  244. goto Cleanup1;
  245. }
  246. hbmOld2 = SelectObject(hdcMem2, hbm2);
  247. BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem1, 0, 0, SRCCOPY);
  248. SelectObject(hdcMem1, hbmOld1);
  249. SelectObject(hdcMem2, hbmOld2);
  250. Cleanup1:
  251. DeleteDC(hdcMem2);
  252. Cleanup2:
  253. DeleteDC(hdcMem1);
  254. Cleanup3:
  255. ReleaseDC(pai->hwndDmg, hdc);
  256. return(hbm2);
  257. }
  258. HPALETTE CopyPalette(
  259. HPALETTE hpal)
  260. {
  261. int cPalEntries;
  262. LOGPALETTE *plp;
  263. if (!GetObject(hpal, sizeof(int), &cPalEntries)) {
  264. return(0);
  265. }
  266. plp = (LOGPALETTE *)LocalAlloc(LPTR, sizeof(LOGPALETTE) +
  267. (cPalEntries - 1) * sizeof(PALETTEENTRY));
  268. if (!plp) {
  269. return(0);
  270. }
  271. if (!GetPaletteEntries(hpal, 0, cPalEntries, plp->palPalEntry)) {
  272. LocalFree((HLOCAL)plp);
  273. return(0);
  274. }
  275. plp->palVersion = 0x300;
  276. plp->palNumEntries = (WORD)cPalEntries;
  277. hpal = CreatePalette(plp);
  278. if (hpal &&
  279. !SetPaletteEntries(hpal, 0, cPalEntries, plp->palPalEntry)) {
  280. hpal = 0;
  281. }
  282. LocalFree((HLOCAL)plp);
  283. return(hpal);
  284. }
  285. HDDEDATA CopyHDDEDATA(
  286. PAPPINFO pai,
  287. HDDEDATA hData)
  288. {
  289. HANDLE hMem;
  290. LPDDE_DATA lpdded;
  291. HDDEDATA hdT;
  292. LPMETAFILEPICT pmfPict;
  293. if (!HIWORD(hData))
  294. return(hData);
  295. hMem = CopyDDEShareHandle((HANDLE)HIWORD(hData));
  296. if (!hMem)
  297. return(NULL);
  298. if (!(LOWORD(hData) & HDATA_EXEC)) {
  299. lpdded = (LPDDE_DATA)GLOBALLOCK(hMem);
  300. if (lpdded == NULL) {
  301. return(NULL);
  302. }
  303. lpdded->wStatus |= DDE_FRELEASE;
  304. if (lpdded != NULL) {
  305. switch (lpdded->wFmt) {
  306. case CF_BITMAP:
  307. case CF_DSPBITMAP:
  308. lpdded->wData = CopyBitmap(pai, lpdded->wData);
  309. break;
  310. case CF_PALETTE:
  311. lpdded->wData = (WORD)CopyPalette((HPALETTE)lpdded->wData);
  312. break;
  313. case CF_DIB:
  314. lpdded->wData = (WORD)CopyDDEShareHandle((HANDLE)lpdded->wData);
  315. break;
  316. case CF_METAFILEPICT:
  317. case CF_DSPMETAFILEPICT:
  318. lpdded->wData = (WORD)CopyDDEShareHandle((HANDLE)lpdded->wData);
  319. if (lpdded->wData) {
  320. pmfPict = (LPMETAFILEPICT)GLOBALLOCK((HANDLE)lpdded->wData);
  321. if (pmfPict != NULL) {
  322. pmfPict->hMF = CopyMetaFile(pmfPict->hMF, NULL);
  323. GLOBALUNLOCK((HANDLE)lpdded->wData);
  324. }
  325. GLOBALUNLOCK((HANDLE)lpdded->wData);
  326. }
  327. break;
  328. #ifdef CF_ENHMETAFILE
  329. case CF_ENHMETAFILE:
  330. lpdded->wData = (WORD)CopyEnhMetaFile(*((HENHMETAFILE FAR *)(&lpdded->wData)), NULL);
  331. break;
  332. #endif // bad because it makes chicago and NT binaries different.
  333. }
  334. GLOBALUNLOCK(hMem);
  335. }
  336. }
  337. hdT = MAKELONG(LOWORD(hData) & ~(HDATA_APPOWNED | HDATA_NOAPPFREE), hMem);
  338. AddPileItem(pai->pHDataPile, (LPBYTE)&hdT, NULL);
  339. return(hdT);
  340. }
  341. VOID FreeDDEData(
  342. HANDLE hMem,
  343. WORD wFmt)
  344. {
  345. DDEDATA FAR *pDdeData;
  346. /*
  347. * This handles the special cases for formats that hold imbedded
  348. * objects. (CF_BITMAP, CF_METAFILEPICT).
  349. *
  350. * The data handle is assumed to be unlocked.
  351. */
  352. // may need to add "Printer_Picture" for excel/word interaction" but
  353. // this is just between the two of them and they don't use DDEML.
  354. // raor says OLE only worries about these formats as well.
  355. pDdeData = (DDEDATA FAR *)GLOBALLOCK(hMem);
  356. if (pDdeData == NULL) {
  357. return;
  358. }
  359. switch (wFmt) {
  360. case CF_BITMAP:
  361. case CF_DSPBITMAP:
  362. case CF_PALETTE:
  363. DeleteObject(*(HANDLE FAR *)(&pDdeData->Value));
  364. break;
  365. case CF_DIB:
  366. /*
  367. * DIBs are allocated by app so we don't use the macro here.
  368. */
  369. GlobalFree(*(HANDLE FAR *)(&pDdeData->Value));
  370. break;
  371. case CF_METAFILEPICT:
  372. case CF_DSPMETAFILEPICT:
  373. {
  374. HANDLE hmfPict;
  375. LPMETAFILEPICT pmfPict;
  376. /*
  377. * EXCEL sickness - metafile is a handle to a METAFILEPICT
  378. * struct which holds a metafile. (2 levels of indirection!)
  379. *
  380. * We don't use the GLOBAL macros here because these objects
  381. * are allocated by the app. DDEML knows not their history.
  382. */
  383. hmfPict = *(HANDLE FAR *)(&pDdeData->Value);
  384. pmfPict = (LPMETAFILEPICT)GlobalLock(hmfPict);
  385. if (pmfPict != NULL) {
  386. DeleteMetaFile(pmfPict->hMF);
  387. }
  388. GlobalUnlock(hmfPict);
  389. GlobalFree(hmfPict);
  390. }
  391. break;
  392. #ifdef CF_ENHMETAFILE
  393. case CF_ENHMETAFILE:
  394. DeleteEnhMetaFile(*(HENHMETAFILE FAR *)(&pDdeData->Value));
  395. break;
  396. #endif // This is bad - it forces different binaries for chicago and NT!
  397. }
  398. GLOBALUNLOCK(hMem);
  399. GLOBALFREE(hMem);
  400. }