diff options
Diffstat (limited to 'private/mvdm/wow16/ddeml/hdata.c')
-rw-r--r-- | private/mvdm/wow16/ddeml/hdata.c | 487 |
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); +} |