summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow16/ddeml/hdata.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/wow16/ddeml/hdata.c')
-rw-r--r--private/mvdm/wow16/ddeml/hdata.c487
1 files changed, 487 insertions, 0 deletions
diff --git a/private/mvdm/wow16/ddeml/hdata.c b/private/mvdm/wow16/ddeml/hdata.c
new file mode 100644
index 000000000..4631209d2
--- /dev/null
+++ b/private/mvdm/wow16/ddeml/hdata.c
@@ -0,0 +1,487 @@
+/****************************** Module Header ******************************\
+* Module Name: HDATA.C
+*
+* DDE manager data handle handling routines
+*
+* Created: 12/14/90 Sanford Staab
+*
+* Copyright (c) 1988, 1989, 1990 Microsoft Corporation
+\***************************************************************************/
+
+#include "ddemlp.h"
+
+HDDEDATA PutData(pSrc, cb, cbOff, aItem, wFmt, afCmd, pai)
+LPBYTE pSrc;
+DWORD cb;
+DWORD cbOff;
+ATOM aItem;
+WORD wFmt;
+WORD afCmd;
+PAPPINFO pai;
+{
+ HANDLE hMem;
+ HDDEDATA hdT;
+ DIP dip;
+
+ /* HACK ALERT!
+ * make sure the first two words req'd by windows dde is there,
+ * UNLESS aItem is null in which case we assume it is EXECUTE
+ * data and don't bother.
+ */
+ if (aItem)
+ cbOff += 4L;
+ else
+ afCmd |= HDATA_EXEC;
+
+ if ((hMem = AllocDDESel(
+ (afCmd & HDATA_APPOWNED) ? DDE_FACKREQ : DDE_FRELEASE,
+ wFmt, cb + cbOff)) == NULL) {
+ SETLASTERROR(pai, DMLERR_MEMORY_ERROR);
+ return(0L);
+ }
+
+
+ // add to local list - make sure a similar handle isn't already there.
+
+ hdT = MAKELONG(afCmd, hMem);
+#ifdef DEBUG
+ if (FindPileItem(pai->pHDataPile, CmpHIWORD, (LPBYTE)&hdT, FPI_DELETE)) {
+ AssertF(FALSE, "PutData - unexpected handle in hDataPile");
+ }
+#endif // DEBUG
+
+ if (AddPileItem(pai->pHDataPile, (LPBYTE)&hdT, CmpHIWORD) == API_ERROR) {
+ GLOBALFREE(hMem);
+ SETLASTERROR(pai, DMLERR_MEMORY_ERROR);
+ return(0L);
+ }
+
+ // add to global list if appowned
+
+ if (afCmd & HDATA_APPOWNED) {
+ dip.hData = hMem;
+ dip.hTask = pai->hTask;
+ dip.cCount = 1;
+ dip.fFlags = afCmd;
+ if (AddPileItem(pDataInfoPile, (LPBYTE)&dip, CmpWORD) == API_ERROR) {
+ GLOBALFREE(hMem);
+ SETLASTERROR(pai, DMLERR_MEMORY_ERROR);
+ return(0L);
+ }
+ }
+
+ if (pSrc)
+ CopyHugeBlock(pSrc, HugeOffset(GLOBALLOCK(hMem), cbOff), cb);
+
+ // LOWORD(hData) always == afCmd flags
+
+ return(MAKELONG(afCmd, hMem));
+}
+
+
+
+/*
+ * This is the internal data handle freeing function. fInternal is TRUE if
+ * this is called from within the DDEML (vs called via DdeFreeDataHandle())
+ * It only frees the handle if it is in the local list.
+ * Appowned data handles are only freed internally if a non-owner task is
+ * doing the freeing.
+ * It is important that the LOWORD(hData) be set properly.
+ *
+ * These features give this function the folowing desired characteristics:
+ * 1) Apps cannot free data handles more than once.
+ * 2) The DDEML cannot free APPOWNED data handles on behalf of the owner
+ * task. (except on cleanup)
+ */
+VOID FreeDataHandle(
+PAPPINFO pai,
+HDDEDATA hData,
+BOOL fInternal)
+{
+ DIP *pDip;
+ BOOL fRelease = 0;
+ DDEPOKE FAR *pDdeMem;
+ WORD fmt;
+
+ TRACEAPIIN((szT, "FreeDataHandle(%lx, %lx, %d)\n", pai, hData, fInternal));
+
+ // appowned data handles are not freed till their count reaches 0.
+
+ if ((LOWORD(hData) & HDATA_APPOWNED) &&
+ (pDip = (DIP *)(DWORD)FindPileItem(pDataInfoPile, CmpWORD, PHMEM(hData), 0))) {
+
+ // don't internally free if in the context of the owner
+
+ if (fInternal && (pDip->hTask == pai->hTask)) {
+ TRACEAPIOUT((szT, "FreeDataHandle: Internal and of this task - not freed.\n"));
+ return;
+ }
+
+ if (--pDip->cCount != 0) {
+ TRACEAPIOUT((szT, "FreeDataHandle: Ref count not 0 - not freed.\n"));
+ return;
+ }
+
+ FindPileItem(pDataInfoPile, CmpWORD, PHMEM(hData), FPI_DELETE);
+ fRelease = TRUE;
+ }
+
+ /*
+ * Apps can only free handles in their local list - this guards against
+ * multiple frees by an app. (my arnt we nice)
+ */
+ if (!HIWORD(hData) ||
+ !FindPileItem(pai->pHDataPile, CmpHIWORD, (LPBYTE)&hData, FPI_DELETE)) {
+ TRACEAPIOUT((szT, "FreeDataHandle: Not in local list - not freed.\n"));
+ return;
+ }
+
+ if (LOWORD(hData) & HDATA_EXEC) {
+ fRelease |= !(LOWORD(hData) & HDATA_APPOWNED);
+ } else {
+ pDdeMem = (DDEPOKE FAR *)GLOBALLOCK(HIWORD(hData));
+ if (pDdeMem == NULL) {
+ TRACEAPIOUT((szT, "FreeDataHandle: Lock failed - not freed.\n"));
+ return;
+ }
+ fRelease |= pDdeMem->fRelease;
+ fmt = pDdeMem->cfFormat;
+ GLOBALUNLOCK(HIWORD(hData));
+ }
+
+ if (fRelease) {
+ if (LOWORD(hData) & HDATA_EXEC)
+ GLOBALFREE(HIWORD(hData));
+ else
+ FreeDDEData(HIWORD(hData), fmt);
+ }
+ TRACEAPIOUT((szT, "FreeDataHandle: freed.\n"));
+}
+
+
+
+
+
+/*
+ * This function prepairs data handles on entry into the DDEML API. It has
+ * the following characteristics:
+ * 1) APPOWNED data handles are copied to a non-appowned handle if being
+ * passed to a non-local app.
+ * 2) non-APPOWNED data handles on loan to a callback are copied so they
+ * don't get prematurely freed.
+ * 3) The READONLY bit is set. (in the local list)
+ */
+HDDEDATA DllEntry(
+PCOMMONINFO pcomi,
+HDDEDATA hData)
+{
+ if ((!(pcomi->fs & ST_ISLOCAL)) && (LOWORD(hData) & HDATA_APPOWNED) ||
+ LOWORD(hData) & HDATA_NOAPPFREE && !(LOWORD(hData) & HDATA_APPOWNED)) {
+
+ // copy APPOWNED data handles to a fresh handle if not a local conv.
+ // copy app loaned, non appowned handles as well (this is the
+ // relay server case)
+
+ hData = CopyHDDEDATA(pcomi->pai, hData);
+ }
+
+ LOWORD(hData) |= HDATA_READONLY;
+
+ AddPileItem(pcomi->pai->pHDataPile, (LPBYTE)&hData, CmpHIWORD);
+
+ // NOTE: the global lists READONLY flag set but thats
+ // ok because any hData received from a transaction will always be in
+ // the local list due to RecvPrep().
+
+ return(hData);
+}
+
+
+
+/*
+ * removes the data handle from the local list. This removes responsibility
+ * for the data handle from the sending app. APPOWNED handles are not
+ * removed.
+ */
+VOID XmitPrep(
+HDDEDATA hData,
+PAPPINFO pai)
+{
+ if (!(LOWORD(hData) & HDATA_APPOWNED)) {
+ FindPileItem(pai->pHDataPile, CmpHIWORD, (LPBYTE)&hData, FPI_DELETE);
+ }
+}
+
+
+
+/*
+ * Places the received data handle into the apropriate lists and returns
+ * it with the proper flags set. Returns 0 if invalid hMem. afCmd should
+ * contain any extra flags desired.
+ */
+HDDEDATA RecvPrep(
+PAPPINFO pai,
+HANDLE hMem,
+WORD afCmd)
+{
+ DIP *pdip;
+ HDDEDATA hData;
+
+ if (!hMem)
+ return(0);
+
+ // check if its an APPOWNED one, if so, log entry.
+
+ if (pdip = (DIP *)(DWORD)FindPileItem(pDataInfoPile, CmpWORD, (LPBYTE)&hMem, 0)) {
+ afCmd |= pdip->fFlags;
+ pdip->cCount++;
+ }
+
+ // if we got one that isnt fRelease, treat it as appowed.
+
+ if (!(*(LPWORD)GLOBALLOCK(hMem) & DDE_FRELEASE))
+ afCmd |= HDATA_APPOWNED;
+
+ GLOBALUNLOCK(hMem);
+
+ // all received handles are readonly.
+
+ hData = (HDDEDATA)MAKELONG(afCmd | HDATA_READONLY, hMem);
+ /*
+ * Add (or replace) into local list
+ */
+ AddPileItem(pai->pHDataPile, (LPBYTE)&hData, CmpHIWORD);
+
+ return(hData);
+}
+
+
+HANDLE CopyDDEShareHandle(
+HANDLE hMem)
+{
+ DWORD cb;
+ LPBYTE pMem;
+
+ cb = GlobalSize(hMem);
+ pMem = GLOBALLOCK(hMem);
+ if (pMem == NULL) {
+ return(0);
+ }
+ hMem = GLOBALALLOC(GMEM_DDESHARE, cb);
+ CopyHugeBlock(pMem, GLOBALPTR(hMem), cb);
+ return(hMem);
+}
+
+
+
+HBITMAP CopyBitmap(
+PAPPINFO pai,
+HBITMAP hbm)
+{
+ BITMAP bm;
+ HBITMAP hbm2, hbmOld1, hbmOld2;
+ HDC hdc, hdcMem1, hdcMem2;
+
+ if (!GetObject(hbm, sizeof(BITMAP), &bm)) {
+ return(0);
+ }
+ hdc = GetDC(pai->hwndDmg);
+ if (!hdc) {
+ return(0);
+ }
+ hdcMem1 = CreateCompatibleDC(hdc);
+ if (!hdcMem1) {
+ goto Cleanup3;
+ }
+ hdcMem2 = CreateCompatibleDC(hdc);
+ if (!hdcMem2) {
+ goto Cleanup2;
+ }
+ hbmOld1 = SelectObject(hdcMem1, hbm);
+ hbm2 = CreateCompatibleBitmap(hdcMem1, bm.bmWidth, bm.bmHeight);
+ if (!hbm2) {
+ goto Cleanup1;
+ }
+ hbmOld2 = SelectObject(hdcMem2, hbm2);
+ BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem1, 0, 0, SRCCOPY);
+ SelectObject(hdcMem1, hbmOld1);
+ SelectObject(hdcMem2, hbmOld2);
+Cleanup1:
+ DeleteDC(hdcMem2);
+Cleanup2:
+ DeleteDC(hdcMem1);
+Cleanup3:
+ ReleaseDC(pai->hwndDmg, hdc);
+ return(hbm2);
+}
+
+
+
+HPALETTE CopyPalette(
+HPALETTE hpal)
+{
+ int cPalEntries;
+ LOGPALETTE *plp;
+
+ if (!GetObject(hpal, sizeof(int), &cPalEntries)) {
+ return(0);
+ }
+ plp = (LOGPALETTE *)LocalAlloc(LPTR, sizeof(LOGPALETTE) +
+ (cPalEntries - 1) * sizeof(PALETTEENTRY));
+ if (!plp) {
+ return(0);
+ }
+ if (!GetPaletteEntries(hpal, 0, cPalEntries, plp->palPalEntry)) {
+ LocalFree((HLOCAL)plp);
+ return(0);
+ }
+ plp->palVersion = 0x300;
+ plp->palNumEntries = (WORD)cPalEntries;
+ hpal = CreatePalette(plp);
+ if (hpal &&
+ !SetPaletteEntries(hpal, 0, cPalEntries, plp->palPalEntry)) {
+ hpal = 0;
+ }
+ LocalFree((HLOCAL)plp);
+ return(hpal);
+}
+
+
+
+
+HDDEDATA CopyHDDEDATA(
+PAPPINFO pai,
+HDDEDATA hData)
+{
+ HANDLE hMem;
+ LPDDE_DATA lpdded;
+ HDDEDATA hdT;
+ LPMETAFILEPICT pmfPict;
+
+ if (!HIWORD(hData))
+ return(hData);
+ hMem = CopyDDEShareHandle((HANDLE)HIWORD(hData));
+
+ if (!hMem)
+ return(NULL);
+
+ if (!(LOWORD(hData) & HDATA_EXEC)) {
+ lpdded = (LPDDE_DATA)GLOBALLOCK(hMem);
+ if (lpdded == NULL) {
+ return(NULL);
+ }
+ lpdded->wStatus |= DDE_FRELEASE;
+ if (lpdded != NULL) {
+ switch (lpdded->wFmt) {
+ case CF_BITMAP:
+ case CF_DSPBITMAP:
+ lpdded->wData = CopyBitmap(pai, lpdded->wData);
+ break;
+
+ case CF_PALETTE:
+ lpdded->wData = (WORD)CopyPalette((HPALETTE)lpdded->wData);
+ break;
+
+ case CF_DIB:
+ lpdded->wData = (WORD)CopyDDEShareHandle((HANDLE)lpdded->wData);
+ break;
+
+ case CF_METAFILEPICT:
+ case CF_DSPMETAFILEPICT:
+ lpdded->wData = (WORD)CopyDDEShareHandle((HANDLE)lpdded->wData);
+ if (lpdded->wData) {
+ pmfPict = (LPMETAFILEPICT)GLOBALLOCK((HANDLE)lpdded->wData);
+ if (pmfPict != NULL) {
+ pmfPict->hMF = CopyMetaFile(pmfPict->hMF, NULL);
+ GLOBALUNLOCK((HANDLE)lpdded->wData);
+ }
+ GLOBALUNLOCK((HANDLE)lpdded->wData);
+ }
+ break;
+#ifdef CF_ENHMETAFILE
+ case CF_ENHMETAFILE:
+ lpdded->wData = (WORD)CopyEnhMetaFile(*((HENHMETAFILE FAR *)(&lpdded->wData)), NULL);
+ break;
+#endif // bad because it makes chicago and NT binaries different.
+ }
+ GLOBALUNLOCK(hMem);
+ }
+ }
+
+ hdT = MAKELONG(LOWORD(hData) & ~(HDATA_APPOWNED | HDATA_NOAPPFREE), hMem);
+ AddPileItem(pai->pHDataPile, (LPBYTE)&hdT, NULL);
+
+ return(hdT);
+}
+
+
+VOID FreeDDEData(
+HANDLE hMem,
+WORD wFmt)
+{
+ DDEDATA FAR *pDdeData;
+
+ /*
+ * This handles the special cases for formats that hold imbedded
+ * objects. (CF_BITMAP, CF_METAFILEPICT).
+ *
+ * The data handle is assumed to be unlocked.
+ */
+
+ // may need to add "Printer_Picture" for excel/word interaction" but
+ // this is just between the two of them and they don't use DDEML.
+ // raor says OLE only worries about these formats as well.
+
+ pDdeData = (DDEDATA FAR *)GLOBALLOCK(hMem);
+ if (pDdeData == NULL) {
+ return;
+ }
+
+ switch (wFmt) {
+ case CF_BITMAP:
+ case CF_DSPBITMAP:
+ case CF_PALETTE:
+ DeleteObject(*(HANDLE FAR *)(&pDdeData->Value));
+ break;
+
+ case CF_DIB:
+ /*
+ * DIBs are allocated by app so we don't use the macro here.
+ */
+ GlobalFree(*(HANDLE FAR *)(&pDdeData->Value));
+ break;
+
+ case CF_METAFILEPICT:
+ case CF_DSPMETAFILEPICT:
+ {
+ HANDLE hmfPict;
+ LPMETAFILEPICT pmfPict;
+
+ /*
+ * EXCEL sickness - metafile is a handle to a METAFILEPICT
+ * struct which holds a metafile. (2 levels of indirection!)
+ *
+ * We don't use the GLOBAL macros here because these objects
+ * are allocated by the app. DDEML knows not their history.
+ */
+
+ hmfPict = *(HANDLE FAR *)(&pDdeData->Value);
+ pmfPict = (LPMETAFILEPICT)GlobalLock(hmfPict);
+ if (pmfPict != NULL) {
+ DeleteMetaFile(pmfPict->hMF);
+ }
+ GlobalUnlock(hmfPict);
+ GlobalFree(hmfPict);
+ }
+ break;
+
+#ifdef CF_ENHMETAFILE
+ case CF_ENHMETAFILE:
+ DeleteEnhMetaFile(*(HENHMETAFILE FAR *)(&pDdeData->Value));
+ break;
+#endif // This is bad - it forces different binaries for chicago and NT!
+ }
+
+ GLOBALUNLOCK(hMem);
+ GLOBALFREE(hMem);
+}