summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow32/wdde.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/mvdm/wow32/wdde.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/mvdm/wow32/wdde.c')
-rw-r--r--private/mvdm/wow32/wdde.c1138
1 files changed, 1138 insertions, 0 deletions
diff --git a/private/mvdm/wow32/wdde.c b/private/mvdm/wow32/wdde.c
new file mode 100644
index 000000000..1fbdbf5bb
--- /dev/null
+++ b/private/mvdm/wow32/wdde.c
@@ -0,0 +1,1138 @@
+/*++
+ *
+ * WOW v1.0
+ *
+ * Copyright (c) 1991, Microsoft Corporation
+ *
+ * WDDE.C
+ * WOW32 DDE worker routines.
+ *
+ * History:
+ * WOW DDE support designed and developed by ChandanC
+ *
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+LPDDENODE DDEInitiateList = NULL;
+STATIC PHDDE phDDEFirst = NULL; // pointer to first hDDE entry
+STATIC PCPDATA pCPDataFirst = NULL; // pointer to first CopyData entry
+
+MODNAME(wdde.c);
+
+
+// This routine maintains a list of client windows that are in
+// Initiate mode. This is called from THUNKING of DDE_INITIATE
+// message (from both the WMDISP32.C and WMSG16.C).
+//
+
+VOID WI32DDEAddInitiator (HAND16 Initiator)
+{
+ LPDDENODE Node;
+
+ Node = (LPDDENODE) malloc_w(sizeof(DDENODE));
+
+ if (Node) {
+
+ //
+ // Initialize Node with the Initiator's window handle
+ //
+
+ Node->Initiator = Initiator;
+
+ //
+ // Insert this Node into the linked list of DDE_Initiate message
+ // in progress.
+ //
+
+ Node->Next = DDEInitiateList;
+ DDEInitiateList = Node;
+
+ LOGDEBUG(12, ("WOW::WI32DDEInitiator(): thunking -- adding an Initiator %04lX\n", Initiator));
+ }
+ else {
+
+ //
+ // We could not allocate memory.
+ //
+
+ LOGDEBUG(12, ("WOW::WI32DDEInitiator(): thunking -- Couldn't allocate memory\n"));
+ WOW32ASSERT (FALSE);
+ }
+}
+
+
+// This routine deletes the client window that was in Initiate mode. Because
+// the initiate message is completed now. This is called from UNTHUNKING
+// of DDE_INITIATE message (from both the WMDISP32.C and WMSG16.C).
+//
+
+VOID WI32DDEDeleteInitiator(HAND16 Initiator)
+{
+ LPDDENODE Node, Temp1;
+
+ Node = DDEInitiateList;
+
+ if (Node) {
+
+ while (Node) {
+ if (Node->Initiator == Initiator) {
+
+ if (Node == DDEInitiateList) {
+
+ //
+ // first guy in the list
+ //
+
+ DDEInitiateList = Node->Next;
+ }
+ else {
+
+ //
+ // update the list
+ //
+
+ Temp1->Next = Node->Next;
+ }
+
+ LOGDEBUG(12, ("WOW::WI32DDEDeleteInitiator(): unthunking -- deleting an Initiator %08lX\n", Initiator));
+
+ //
+ // free up the memory
+ //
+
+ free_w(Node);
+ Node = NULL;
+ }
+ else {
+
+ //
+ // traverse the list
+ //
+
+ Temp1 = Node;
+ Node = Node->Next;
+ }
+ }
+
+ }
+ else {
+
+ // This is an ERROR condition, which should never occur. If it does
+ // talk to CHANDANC as soon as possible.
+ //
+
+ LOGDEBUG(0, ("WOW::WI32DDEDeletInitiator(): unthunking -- no Initiator\n"));
+ WOW32ASSERT (FALSE);
+ }
+}
+
+
+// This routine is used by DDE_ACK thunk to figure out how to thunk the
+// DDE_ACK message, ie, whether lParam is a combination of 2 atoms or
+// its a pointer to 32 bit packed structure.
+//
+
+BOOL WI32DDEInitiate(HAND16 Initiator)
+{
+ LPDDENODE Node;
+
+ Node = DDEInitiateList;
+
+ while (Node) {
+ if (Node->Initiator == Initiator) {
+ //
+ // DDE_Initiate is in progress for this Window
+ //
+
+ LOGDEBUG(12, ("WOW::WI32DDEInitiate(): thunking -- found an Initiator %08lX\n", Initiator));
+ return (TRUE);
+ }
+ else {
+ Node = Node->Next;
+ }
+ }
+ LOGDEBUG(12, ("WOW::WI32DDEInitiate(): thunking -- did not find an Initiator %08lX\n", Initiator));
+
+ //
+ // DDE_Initiate is not in progress for this Window
+ //
+
+ return (FALSE);
+}
+
+
+//
+// This routine determines if the current dde operation is a poke to MSDRAW
+// Pokes to MSDRAW for metafilepicts are special because the metafile pict
+// is part of the POKE block.
+//
+
+BOOL DDEIsTargetMSDraw(HAND16 To_hwnd)
+{
+ BOOL fStatus = FALSE;
+ HANDLE hInst;
+ HAND16 hModuleName;
+ LPSTR lpszModuleName16, lpszMsDraw = "MSDRAW.EXE";
+ WORD cchModuleName = MAX_PATH, cchMsDraw = 10;
+ VPVOID vp;
+ LPSTR lpszNewMsDrawKey = "MSDRAW\\protocol\\StdFileEditing\\verb";
+ HKEY hKey = NULL;
+ LONG Status;
+
+ //
+ // To check if the target is msdraw, check the following.
+ //
+ // - That the destination window hInst is that of a 16 bit task (this is
+ // checking to see if the LOWORD of the hInst is not 0.
+ // - That the module name is MSDRAW.
+ //
+ // NOTE: THERE ARE THREE CALLBACK16 ROUTINES IN THIS CALL, MAKING IT AN
+ // EXPENSIVE CALL. HOWEVER THIS CALL IS RARELY MADE.
+ //
+
+ if (
+ (hInst = (HANDLE)GetWindowLong((HWND)HWND32(To_hwnd),GWL_HINSTANCE))
+ && (LOWORD(hInst) != 0 )
+ && (vp = GlobalAllocLock16(GMEM_MOVEABLE, cchModuleName, &hModuleName))
+ ) {
+
+ //
+ // Callback 16 to get the module name of the current hInst
+ //
+
+ if (cchModuleName = GetModuleFileName16( LOWORD(hInst), vp, cchModuleName )) {
+ GETMISCPTR(vp, lpszModuleName16);
+ fStatus = (cchModuleName >= cchMsDraw)
+ && !_stricmp( lpszModuleName16 + (cchModuleName - cchMsDraw), lpszMsDraw )
+ && (Status = RegOpenKeyEx( HKEY_CLASSES_ROOT, lpszNewMsDrawKey, 0, KEY_READ, &hKey)) != ERROR_SUCCESS;
+
+ if (hKey) {
+ RegCloseKey( hKey );
+ }
+ FREEMISCPTR(lpszModuleName16);
+ }
+
+ //
+ // Cleanup
+ //
+
+ GlobalUnlockFree16(vp);
+ }
+ return ( fStatus );
+}
+
+
+
+// This routine converts a 32 bit DDE memory object into a 16 bit DDE
+// memory object. It also, does the data conversion from 32 bit to 16 bit
+// for the type of data.
+//
+// WARNING: The Copyh32Toh16() calls may cause 16-bit memory movement
+//
+
+HAND16 DDECopyhData16(HAND16 To_hwnd, HAND16 From_hwnd, HANDLE h32, PDDEINFO pDdeInfo)
+{
+ HAND16 h16 = 0;
+ VPVOID vp1, vp2;
+ DDEDATA *lpMem32;
+ DDEDATA16 *lpMem16;
+ int cb;
+
+ //
+ // NULL handle ?
+ //
+
+ if (!h32) {
+ LOGDEBUG(12, ("WOW::DDECopyhData16(): h32 is %08x\n", h32));
+ return 0;
+ }
+
+ cb = GlobalSize(h32);
+ lpMem32 = GlobalLock(h32);
+ LOGDEBUG(12, ("WOW::DDECopyhData16(): CF_FORMAT is %04x\n", lpMem32->cfFormat));
+
+ switch (lpMem32->cfFormat) {
+
+ default:
+
+ // This is intentional to let it thru to "case statements".
+ // ChandanC 5/11/92.
+
+ case CF_TEXT:
+ case CF_DSPTEXT:
+ case CF_SYLK:
+ case CF_DIF:
+ case CF_TIFF:
+ case CF_OEMTEXT:
+ case CF_PENDATA:
+ case CF_RIFF:
+ case CF_WAVE:
+ case CF_OWNERDISPLAY:
+ h16 = Copyh32Toh16 (cb, (LPBYTE) lpMem32);
+
+ pDdeInfo->Format = lpMem32->cfFormat;
+ break;
+
+ case CF_BITMAP:
+ case CF_DSPBITMAP:
+ vp1 = GlobalAllocLock16(GMEM_DDESHARE, (sizeof(DDEDATA)-1+sizeof(HAND16)), &h16);
+ if (vp1) {
+ pDdeInfo->Format = lpMem32->cfFormat;
+ GETMISCPTR(vp1, lpMem16);
+ RtlCopyMemory(lpMem16, lpMem32, 4);
+ STOREWORD(lpMem16->Value, GETHBITMAP16(*((HANDLE *)lpMem32->Value)));
+ FLUSHVDMPTR(vp1, (sizeof(DDEDATA)-1+sizeof(HAND16)), lpMem16);
+ FREEMISCPTR(lpMem16);
+ GlobalUnlock16(h16);
+ }
+ break;
+
+ case CF_PALETTE:
+ vp1 = GlobalAllocLock16(GMEM_DDESHARE, (sizeof(DDEDATA)-1+sizeof(HAND16)), &h16);
+ if (vp1) {
+ pDdeInfo->Format = lpMem32->cfFormat;
+ GETMISCPTR(vp1, lpMem16);
+ RtlCopyMemory(lpMem16, lpMem32, 4);
+ STOREWORD(lpMem16->Value, GETHPALETTE16(*((HANDLE *)lpMem32->Value)));
+ FLUSHVDMPTR(vp1, (sizeof(DDEDATA)-1+sizeof(HAND16)), lpMem16);
+ FREEMISCPTR(lpMem16);
+ GlobalUnlock16(h16);
+ }
+ break;
+
+ case CF_DIB:
+ {
+ LPBYTE lpMemDib32;
+ HAND16 hDib16 = 0;
+ HANDLE hDib32;
+
+ vp1 = GlobalAllocLock16(GMEM_DDESHARE, (sizeof(DDEDATA)-1+sizeof(HAND16)), &h16);
+ if (vp1) {
+
+ GETMISCPTR(vp1, lpMem16);
+ RtlCopyMemory(lpMem16, lpMem32, 4);
+ FREEMISCPTR(lpMem16);
+
+ hDib32 = (*((HANDLE *)lpMem32->Value));
+ if (hDib32) {
+ lpMemDib32 = GlobalLock(hDib32);
+ cb = GlobalSize(hDib32);
+ hDib16 = Copyh32Toh16 (cb, (LPBYTE) lpMemDib32);
+ GlobalUnlock(hDib32);
+ pDdeInfo->Format = lpMem32->cfFormat;
+ pDdeInfo->Flags = 0;
+ pDdeInfo->h16 = 0;
+ DDEAddhandle(To_hwnd, From_hwnd, (HAND16) hDib16, hDib32, pDdeInfo);
+
+ }
+
+ GETMISCPTR(vp1, lpMem16);
+ STOREWORD(lpMem16->Value, hDib16);
+ GlobalUnlock16(h16);
+ FLUSHVDMPTR(vp1, (sizeof(DDEDATA)-1+sizeof(HAND16)), lpMem16);
+ FREEMISCPTR(lpMem16);
+ }
+ }
+ break;
+
+ case CF_METAFILEPICT:
+ case CF_DSPMETAFILEPICT:
+ {
+ HANDLE hMeta32, hMF32 = NULL;
+ HAND16 hMeta16 = 0, hMF16 = 0;
+ LPMETAFILEPICT lpMemMeta32;
+ LPMETAFILEPICT16 lpMemMeta16;
+ BOOL IsMSDRAWPoke;
+
+ //
+ // We need to find out if the to_handle is MSDRAW, in which case
+ // we should copy the METAFILEPICT data to the DDEPOKE instead
+ // of a handle to the METAFILEPICT.
+
+ if( IsMSDRAWPoke = ((pDdeInfo->Msg == WM_DDE_POKE) && DDEIsTargetMSDraw(To_hwnd)) ) {
+ cb = sizeof(DDEPOKE)-1+sizeof(METAFILEPICT16);
+ }
+ else {
+ cb = sizeof(DDEDATA)-1+sizeof(HAND16);
+ }
+ vp1 = GlobalAllocLock16(GMEM_DDESHARE, cb, &h16);
+
+
+ if (vp1) {
+ GETMISCPTR(vp1, lpMem16);
+ RtlCopyMemory(lpMem16, lpMem32, 4);
+ hMeta32 = (*((HANDLE *)lpMem32->Value));
+
+ if ( IsMSDRAWPoke ) {
+
+ lpMemMeta16 = (LPMETAFILEPICT16)((PBYTE)lpMem16 + sizeof(DDEPOKE) - 1);
+ RtlZeroMemory( (PVOID)lpMemMeta16, sizeof (METAFILEPICT16) );
+ if (hMeta32) {
+ lpMemMeta32 = GlobalLock(hMeta32);
+ FixMetafile32To16 (lpMemMeta32, lpMemMeta16);
+ FREEMISCPTR(lpMem16);
+
+ hMF32 = lpMemMeta32->hMF;
+ if (hMF32) {
+ hMF16 = WinMetaFileFromHMF(hMF32, FALSE);
+ pDdeInfo->Format = lpMem32->cfFormat;
+ pDdeInfo->h16 = 0;
+ pDdeInfo->Flags = DDE_METAFILE;
+ DDEAddhandle(To_hwnd, From_hwnd, (HAND16) hMF16, hMF32, pDdeInfo);
+ }
+
+ GETMISCPTR(vp1, lpMem16);
+ lpMemMeta16 = (LPMETAFILEPICT16)((PBYTE)lpMem16 + sizeof(DDEPOKE) - 1);
+ STOREWORD(lpMemMeta16->hMF, hMF16);
+ GlobalUnlock(hMeta32);
+ }
+
+ }
+ else {
+ if (hMeta32) {
+ lpMemMeta32 = GlobalLock(hMeta32);
+ FREEMISCPTR(lpMem16);
+ vp2 = GlobalAllocLock16(GMEM_DDESHARE, sizeof(METAFILEPICT16), &hMeta16);
+ WOW32ASSERT(vp2);
+ if (vp2) {
+ GETMISCPTR(vp2, lpMemMeta16);
+ FixMetafile32To16 (lpMemMeta32, lpMemMeta16);
+ FREEMISCPTR(lpMemMeta16);
+
+ pDdeInfo->Format = lpMem32->cfFormat;
+ pDdeInfo->Flags = 0;
+ pDdeInfo->h16 = 0;
+ DDEAddhandle(To_hwnd, From_hwnd, (HAND16) hMeta16, hMeta32, pDdeInfo);
+ hMF32 = lpMemMeta32->hMF;
+ if (hMF32) {
+ hMF16 = WinMetaFileFromHMF(hMF32, FALSE);
+ pDdeInfo->Flags = DDE_METAFILE;
+ DDEAddhandle(To_hwnd, From_hwnd, (HAND16) hMF16, hMF32, pDdeInfo);
+ }
+
+ GETMISCPTR(vp2, lpMemMeta16);
+ STOREWORD(lpMemMeta16->hMF, hMF16);
+ GlobalUnlock16(hMeta16);
+ FLUSHVDMPTR(vp2, 8, lpMemMeta16);
+ FREEMISCPTR(lpMemMeta16);
+ }
+ GlobalUnlock(hMeta32);
+ }
+ GETMISCPTR(vp1, lpMem16);
+ STOREWORD(lpMem16->Value, hMeta16);
+ }
+
+ GlobalUnlock16(h16);
+ FLUSHVDMPTR(vp1, cb, lpMem16);
+ FREEMISCPTR(lpMem16);
+ }
+ }
+ break;
+ }
+
+ GlobalUnlock(h32);
+
+ return (h16);
+}
+
+
+
+
+// This routine converts a 16 bit DDE memory object into a 32 bit DDE
+// memory object. It also, does the data conversion from 16 bit to 32 bit
+// for the type of data.
+//
+
+HANDLE DDECopyhData32(HAND16 To_hwnd, HAND16 From_hwnd, HAND16 h16, PDDEINFO pDdeInfo)
+{
+ HANDLE h32 = NULL;
+ INT cb;
+ VPVOID vp;
+ DDEDATA *lpMem16;
+ DDEDATA32 *lpMem32;
+
+ //
+ // AmiPro passes a NULL handle.
+ //
+
+ if (!h16) {
+ LOGDEBUG(12, ("WOW::DDECopyhData16(): h16 is %04x\n", h16));
+ return (HANDLE) NULL;
+ }
+
+ vp = GlobalLock16(h16, &cb);
+ GETMISCPTR(vp, lpMem16);
+ LOGDEBUG(12, ("WOW::DDECopyhData32(): CF_FORMAT is %04x\n", lpMem16->cfFormat));
+
+ switch(lpMem16->cfFormat) {
+
+ default:
+
+ // This is intentional to let it thru to the "case statements".
+ // ChandanC 5/11/92.
+
+ case CF_TEXT:
+ case CF_DSPTEXT:
+ case CF_SYLK:
+ case CF_DIF:
+ case CF_TIFF:
+ case CF_OEMTEXT:
+ case CF_PENDATA:
+ case CF_RIFF:
+ case CF_WAVE:
+ case CF_OWNERDISPLAY:
+ h32 = Copyh16Toh32 (cb, (LPBYTE) lpMem16);
+
+ pDdeInfo->Format = lpMem16->cfFormat;
+ break;
+
+ case CF_BITMAP:
+ case CF_DSPBITMAP:
+ h32 = GlobalAlloc(GMEM_DDESHARE, (sizeof(DDEDATA)-1+sizeof(HANDLE)));
+ if (h32) {
+ pDdeInfo->Format = lpMem16->cfFormat;
+ lpMem32 = GlobalLock(h32);
+ RtlCopyMemory(lpMem32, lpMem16, 4);
+ lpMem32->Value = HBITMAP32(FETCHWORD(*((WORD *)lpMem16->Value)));
+ GlobalUnlock(h32);
+ }
+ break;
+
+ case CF_PALETTE:
+ h32 = GlobalAlloc(GMEM_DDESHARE, (sizeof(DDEDATA)-1+sizeof(HANDLE)));
+ if (h32) {
+ pDdeInfo->Format = lpMem16->cfFormat;
+ lpMem32 = GlobalLock(h32);
+ RtlCopyMemory(lpMem32, lpMem16, 4);
+ lpMem32->Value = HPALETTE32(FETCHWORD(*((WORD *)lpMem16->Value)));
+ GlobalUnlock(h32);
+ }
+ break;
+
+ case CF_DIB:
+ {
+ LPBYTE lpMemDib16;
+ HAND16 hDib16;
+ HANDLE hDib32 = NULL;
+
+ h32 = GlobalAlloc(GMEM_DDESHARE, (sizeof(DDEDATA)-1+sizeof(HANDLE)));
+ if (h32) {
+ lpMem32 = GlobalLock(h32);
+ RtlCopyMemory(lpMem32, lpMem16, 4);
+
+ hDib16 = FETCHWORD(*((WORD *)lpMem16->Value));
+ if (hDib16) {
+ vp = GlobalLock16(hDib16, &cb);
+ GETMISCPTR(vp, lpMemDib16);
+ hDib32 = Copyh16Toh32 (cb, (LPBYTE) lpMemDib16);
+
+ pDdeInfo->Format = lpMem16->cfFormat;
+ pDdeInfo->Flags = 0;
+ pDdeInfo->h16 = 0;
+ DDEAddhandle(To_hwnd, From_hwnd, (HAND16) hDib16, hDib32, pDdeInfo);
+
+ GlobalUnlock16(hDib16);
+ FREEMISCPTR(lpMemDib16);
+ }
+ lpMem32->Value = hDib32;
+ GlobalUnlock(h32);
+ }
+ }
+ break;
+
+ case CF_METAFILEPICT:
+ case CF_DSPMETAFILEPICT:
+ {
+ HANDLE hMeta32 = NULL, hMF32 = NULL;
+ HAND16 hMeta16, hMF16 = 0;
+ LPMETAFILEPICT lpMemMeta32;
+ LPMETAFILEPICT16 lpMemMeta16;
+
+ h32 = GlobalAlloc(GMEM_DDESHARE, (sizeof(DDEDATA)-1+sizeof(HANDLE)));
+ if (h32) {
+ lpMem32 = GlobalLock(h32);
+ RtlCopyMemory(lpMem32, lpMem16, 4);
+
+ //
+ // MSDRAW has the METAFILEPICT in the DDEPOKE block instead of
+ // a handle to the METAFILEPICT. So we need to find out if the
+ // to handle belongs to MSDRAW. Since MSDRAW is a 16 bit
+ // server we needn't thunk the metafilepict at all, we will just
+ // use NULL as the 32 bit handle to the metafilepict.
+ //
+
+ hMeta32 = NULL;
+ if( !((pDdeInfo->Msg == WM_DDE_POKE) && DDEIsTargetMSDraw(To_hwnd)) ) {
+
+ hMeta16 = FETCHWORD(*((WORD *)lpMem16->Value));
+
+ //
+ // Make sure that a valid metafile pict handle has been
+ // passed in otherwise use NULL again as the hMeta32.
+ //
+
+ if (hMeta16 && (vp = GlobalLock16(hMeta16, &cb))) {
+ GETMISCPTR(vp, lpMemMeta16);
+ hMeta32 = GlobalAlloc(GMEM_DDESHARE, sizeof(METAFILEPICT));
+ WOW32ASSERT(hMeta32);
+ if (hMeta32) {
+ lpMemMeta32 = GlobalLock(hMeta32);
+ lpMemMeta32->mm = (LONG) FETCHSHORT(lpMemMeta16->mm);
+ lpMemMeta32->xExt = (LONG) FETCHSHORT(lpMemMeta16->xExt);
+ lpMemMeta32->yExt = (LONG) FETCHSHORT(lpMemMeta16->yExt);
+ pDdeInfo->Format = lpMem16->cfFormat;
+ pDdeInfo->Flags = 0;
+ pDdeInfo->h16 = 0;
+ DDEAddhandle(To_hwnd, From_hwnd, (HAND16) hMeta16, hMeta32, pDdeInfo);
+
+ hMF16 = FETCHWORD(lpMemMeta16->hMF);
+
+ if (hMF16) {
+ hMF32 = (HMETAFILE) HMFFromWinMetaFile(hMF16, FALSE);
+ pDdeInfo->Flags = DDE_METAFILE;
+ DDEAddhandle(To_hwnd, From_hwnd, (HAND16) hMF16, hMF32, pDdeInfo);
+ }
+
+ lpMemMeta32->hMF = (HMETAFILE) hMF32;
+ GlobalUnlock(hMeta32);
+ }
+ GlobalUnlock16(hMeta16);
+ FREEMISCPTR(lpMemMeta16);
+ }
+ }
+ lpMem32->Value = hMeta32;
+ GlobalUnlock(h32);
+ }
+ }
+ break;
+ }
+
+ GlobalUnlock16(h16);
+
+ FREEMISCPTR(lpMem16);
+ return (h32);
+}
+
+
+/****** These routines maintain a linked list of dde handles, which
+******* are the h16 and h32 pairs.
+******/
+
+
+
+// This routine adds the given h16-h32 pair to the linked list, and updates
+// the list.
+//
+
+BOOL DDEAddhandle(HAND16 To_hwnd, HAND16 From_hwnd, HAND16 hMem16, HANDLE hMem32, PDDEINFO pDdeInfo)
+{
+ PHDDE phTemp;
+
+ if (hMem16 && hMem32) {
+ if (phTemp = malloc_w (sizeof(HDDE))) {
+ phTemp->hMem16 = hMem16;
+ phTemp->hMem32 = hMem32;
+ phTemp->To_hwnd = To_hwnd;
+ phTemp->From_hwnd = From_hwnd;
+
+ phTemp->DdeMsg = pDdeInfo->Msg;
+ phTemp->DdeFormat = pDdeInfo->Format;
+ phTemp->DdeFlags = pDdeInfo->Flags;
+
+ phTemp->h16 = pDdeInfo->h16;
+
+ phTemp->pDDENext = phDDEFirst; // insert at the top
+ phDDEFirst = phTemp; // update list head
+
+ // Mark the GAH_WOWDDEFREEHANDLE (ie GAH_PAHTOM) bit in the global
+ // arena of this handle.
+
+ W32MarkDDEHandle (hMem16);
+
+ return (TRUE);
+ }
+ else {
+ LOGDEBUG(2, ("WOW::DDEAddhandle(): *** memory allocation failed *** \n"));
+ return (FALSE);
+ }
+ }
+
+ LOGDEBUG(2,("WOW::DDEAddhandle(): *** ERROR *** one of the handles is NULL \n"));
+ return (FALSE);
+}
+
+
+// This routine deletes the given h16-h32 pair from the list and frees up
+// the memory.
+//
+
+BOOL DDEDeletehandle(HAND16 h16, HANDLE h32)
+{
+ PHDDE phTemp1, phTemp2;
+
+ phTemp1 = phDDEFirst;
+
+ if ((phTemp1->hMem16 == h16) && (phTemp1->hMem32 == h32)) { // first node
+ phDDEFirst = phTemp1->pDDENext;
+ free_w(phTemp1);
+ return (TRUE);
+ }
+ else { // rest of the list
+ phTemp2 = phTemp1;
+ phTemp1 = phTemp1->pDDENext;
+
+ while (phTemp1) {
+ if ((phTemp1->hMem16 == h16) && (phTemp1->hMem32 == h32)) {
+ phTemp2->pDDENext = phTemp1->pDDENext;
+ free_w(phTemp1);
+ return (TRUE);
+ }
+ phTemp2 = phTemp1;
+ phTemp1 = phTemp1->pDDENext;
+ }
+
+ LOGDEBUG (2, ("WOW::DDEDeleteHandle : Can't find a 16-32 memory pair\n"));
+// WOW32ASSERT (FALSE);
+
+ return (FALSE);
+ }
+}
+
+
+// This routine finds a hMem16 for a DDE conversation, if one exists.
+//
+
+HAND16 DDEFindPair16(HAND16 To_hwnd, HAND16 From_hwnd, HANDLE hMem32)
+{
+ PHDDE phTemp;
+
+ phTemp = phDDEFirst;
+
+ while (phTemp) {
+ if ((phTemp->To_hwnd == To_hwnd) &&
+ (phTemp->From_hwnd == From_hwnd) &&
+ (phTemp->hMem32 == hMem32)) {
+ return (phTemp->hMem16);
+ }
+ else {
+ phTemp = phTemp->pDDENext;
+ }
+ }
+ return (HAND16) NULL;
+}
+
+
+// This routine finds a hMem32 for a DDE conversation, if one exists.
+//
+
+HANDLE DDEFindPair32(HAND16 To_hwnd, HAND16 From_hwnd, HAND16 hMem16)
+{
+ PHDDE phTemp;
+
+ phTemp = phDDEFirst;
+
+ while (phTemp) {
+ if ((phTemp->To_hwnd == To_hwnd) &&
+ (phTemp->From_hwnd == From_hwnd) &&
+ (phTemp->hMem16 == hMem16)) {
+ return (phTemp->hMem32);
+ }
+ else {
+ phTemp = phTemp->pDDENext;
+ }
+ }
+ return (HANDLE) NULL;
+}
+
+
+// This routine find the DDE node that is doing DDE conversation
+//
+
+PHDDE DDEFindNode16 (HAND16 h16)
+{
+ PHDDE phTemp;
+
+ phTemp = phDDEFirst;
+
+ while (phTemp) {
+ if (phTemp->hMem16 == h16) {
+ return (phTemp);
+ }
+ phTemp = phTemp->pDDENext;
+ }
+
+ return (NULL);
+}
+
+
+// This routine find the DDE node that is doing DDE conversation
+//
+
+PHDDE DDEFindNode32 (HANDLE h32)
+{
+ PHDDE phTemp;
+
+ phTemp = phDDEFirst;
+
+ while (phTemp) {
+ if (phTemp->hMem32 == h32) {
+ return (phTemp);
+ }
+ phTemp = phTemp->pDDENext;
+ }
+
+ return (NULL);
+}
+
+
+// This routine returns a pointer to the DDE node, if the conversation exists,
+// else it retunrs NULL
+
+PHDDE DDEFindAckNode (HAND16 To_hwnd, HAND16 From_hwnd, HANDLE hMem32)
+{
+ PHDDE phTemp;
+
+ phTemp = phDDEFirst;
+
+ while (phTemp) {
+ if ((phTemp->To_hwnd == To_hwnd) &&
+ (phTemp->From_hwnd == From_hwnd) &&
+ (phTemp->hMem32 == hMem32)) {
+ return (phTemp);
+ }
+ else {
+ phTemp = phTemp->pDDENext;
+ }
+ }
+ return (PHDDE) NULL;
+}
+
+
+// This function marks GAH_WOWDDEFREEHANDLE bit in the global arena of the
+// hMem16.
+//
+
+VOID W32MarkDDEHandle (HAND16 hMem16)
+{
+ PARM16 Parm16;
+ VPVOID vp = 0;
+
+ Parm16.WndProc.wParam = hMem16;
+ Parm16.WndProc.wMsg = 1;
+ CallBack16(RET_WOWDDEFREEHANDLE, &Parm16, 0, &vp);
+}
+
+VOID W32UnMarkDDEHandle (HAND16 hMem16)
+{
+ PARM16 Parm16;
+ VPVOID vp = 0;
+
+ Parm16.WndProc.wParam = hMem16;
+ Parm16.WndProc.wMsg = 0;
+ CallBack16(RET_WOWDDEFREEHANDLE, &Parm16, 0, &vp);
+}
+
+// This function frees the 32 and 16 bit memory. It is called by 32 bit
+// BASE by GlobalFree.
+//
+
+BOOL W32DDEFreeGlobalMem32 (HANDLE h32)
+{
+ HAND16 h16;
+ PHDDE pDdeNode;
+ BOOL fOkToFree = TRUE;
+
+ if (h32) {
+ if (pDdeNode = DDEFindNode32(h32)) {
+
+ if (pDdeNode->DdeFlags & DDE_METAFILE) {
+ LOGDEBUG (12, ("WOW32: W32DDEFreeGlobalMem32: Freeing MetaFile hMF32 %x\n", h32));
+ DeleteMetaFile (h32);
+ fOkToFree = FALSE;
+ }
+
+ while ((pDdeNode) && (h16 = pDdeNode->hMem16)) {
+ W32UnMarkDDEHandle (h16);
+ GlobalUnlockFree16(GlobalLock16(h16, NULL));
+ DDEDeletehandle(h16, h32);
+ pDdeNode = DDEFindNode32(h32);
+ }
+ }
+ else {
+
+ LOGDEBUG (2, ("WOW32: W32DDEFreeGlobalMem32: Can't find a 16-32 memory pair\n"));
+ }
+ }
+ else {
+ WOW32ASSERTMSG(FALSE, "WOW32: W32DDEFreeGlobalMem32: h32 is NULL to Win32 GlobalFree\n");
+ /*
+ * since in this case the Failure and Success return values from
+ * GlobalFree are NULL, just return false so things are faster
+ * in GlobalFree.
+ */
+ fOkToFree = FALSE;
+ }
+
+ return(fOkToFree);
+}
+
+
+// This function frees only the 32 bit memory because the 16 bit memory
+// is being free'd by the 16 bit app. We are just getting the
+// notification of this fact. So free the corresponding 32 bit memory.
+//
+
+BOOL FASTCALL W32WowDdeFreeHandle (PVDMFRAME pFrame)
+{
+ ULONG ul;
+ HAND16 h16;
+ PWOWDDEFREEHANDLE16 parg16;
+
+ GETARGPTR(pFrame, sizeof(WOWDDEFREEHANDLE16), parg16);
+
+ h16 = (HAND16) parg16->h16;
+
+ ul = W32DdeFreeHandle16 (h16);
+
+ FREEARGPTR(parg16);
+ RETURN (ul);
+}
+
+
+BOOL W32DdeFreeHandle16 (HAND16 h16)
+{
+ HANDLE h32;
+ PHDDE pDdeNode;
+
+ if (!(pDdeNode = DDEFindNode16(h16))) {
+ LOGDEBUG (12, ("WOW::W32DdeFreeHandle16 : Not found h16 -> %04x\n", h16));
+ return (TRUE);
+ }
+
+ LOGDEBUG (12, ("WOW::W32DdeFreeHandle16 : Entering... h16 -> %04x\n", h16));
+
+ if (pDdeNode->DdeMsg == WM_DDE_EXECUTE) {
+ LOGDEBUG (12, ("WOW::W32DdeFreeHandle16 : App TRYING !!! to freeing EXECUTE h16 -> %04x\n", h16));
+ pDdeNode->DdeFlags = pDdeNode->DdeFlags | DDE_EXECUTE_FREE_MEM;
+ return (FALSE);
+ }
+ else {
+ while ((pDdeNode) && (h32 = pDdeNode->hMem32)) {
+ if (pDdeNode->DdeFlags & DDE_METAFILE) {
+ DDEDeletehandle(h16, h32);
+ DeleteMetaFile (h32);
+ }
+ else {
+ /*
+ * REMOVE THE PAIR FIRST!!!
+ * Since GlobalFree will hook back to W32DDEFreeGlobalMem32
+ * we want to remove the handle from our tables before
+ * the call.
+ */
+ DDEDeletehandle(h16, h32);
+ GlobalFree(h32);
+ }
+
+ pDdeNode = DDEFindNode16(h16);
+ }
+ }
+
+ LOGDEBUG (12, ("WOW::W32DdeFreeHandle16 : Leaving ...\n"));
+ return (TRUE);
+}
+
+
+// This routine adds the given h16-h32 CopyData pair to the linked list,
+// and updates the list.
+//
+
+BOOL CopyDataAddNode (HAND16 To_hwnd, HAND16 From_hwnd, DWORD Mem16, DWORD Mem32, DWORD Flags)
+{
+ PCPDATA pTemp;
+
+ if (Mem16 && Mem32) {
+ if (pTemp = malloc_w (sizeof(CPDATA))) {
+ pTemp->Mem16 = Mem16;
+ pTemp->Mem32 = Mem32;
+ pTemp->To_hwnd = To_hwnd;
+ pTemp->From_hwnd= From_hwnd;
+ pTemp->Flags = Flags;
+ pTemp->Next = pCPDataFirst; // insert at the top
+ pCPDataFirst = pTemp; // update list head
+
+ return (TRUE);
+ }
+ else {
+ LOGDEBUG(2, ("WOW::CopyDataAddNode: *** memory allocation failed *** \n"));
+ return (FALSE);
+ }
+ }
+
+ LOGDEBUG(2,("WOW::CopyDataAddNode: *** ERROR *** one of the memory pointers is NULL \n"));
+ return (FALSE);
+}
+
+
+VPVOID CopyDataFindData16 (HWND16 To_hwnd, HWND16 From_hwnd, DWORD Mem)
+{
+ PCPDATA pTemp;
+
+ pTemp = pCPDataFirst;
+
+ while (pTemp) {
+ if ((pTemp->To_hwnd == To_hwnd) &&
+ (pTemp->From_hwnd == From_hwnd) &&
+ (pTemp->Mem32 == Mem)) {
+ return (pTemp->Mem16);
+ }
+ else {
+ pTemp = pTemp->Next;
+ }
+ }
+ return 0;
+}
+
+
+PCPDATA CopyDataFindData32 (HWND16 To_hwnd, HWND16 From_hwnd, DWORD Mem)
+{
+ PCPDATA pTemp;
+
+ pTemp = pCPDataFirst;
+
+ while (pTemp) {
+ if ((pTemp->To_hwnd == To_hwnd) &&
+ (pTemp->From_hwnd == From_hwnd) &&
+ (pTemp->Mem16 == Mem)) {
+ return (pTemp);
+ }
+ else {
+ pTemp = pTemp->Next;
+ }
+ }
+ return 0;
+}
+
+
+// This routine deletes the given h16-h32 pair from the list.
+//
+//
+
+BOOL CopyDataDeleteNode (HWND16 To_hwnd, HWND16 From_hwnd, DWORD Mem)
+{
+ PCPDATA pTemp1;
+ PCPDATA pTemp2;
+
+ pTemp1 = pCPDataFirst;
+
+ if ((pTemp1->To_hwnd == To_hwnd) &&
+ (pTemp1->From_hwnd == From_hwnd) &&
+ (pTemp1->Mem32 == Mem)) {
+ pCPDataFirst = pTemp1->Next;
+ free_w (pTemp1);
+ return (TRUE);
+ }
+ else {
+ pTemp2 = pTemp1;
+ pTemp1 = pTemp1->Next;
+
+ while (pTemp1) {
+ if ((pTemp1->To_hwnd == To_hwnd) &&
+ (pTemp1->From_hwnd == From_hwnd) &&
+ (pTemp1->Mem32 == Mem)) {
+ pTemp2->Next = pTemp1->Next;
+ free_w (pTemp1);
+ return (TRUE);
+ }
+
+ pTemp2 = pTemp1;
+ pTemp1 = pTemp1->Next;
+ }
+ return (FALSE);
+ }
+
+}
+
+
+// While allocating GMEM_DDESHARE memory object should we have GMEM_MOVEABLE
+// flag or not ???????????????????
+// ChandanC Sept 23rd 1993.
+//
+// WARNING: This function may cause 16-bit memory movement.
+//
+
+HAND16 Copyh32Toh16 (int cb, LPBYTE lpMem32)
+{
+ HAND16 h16 = 0;
+ LPBYTE lpMem16;
+ VPVOID vp;
+
+ vp = GlobalAllocLock16(GMEM_DDESHARE | GMEM_MOVEABLE, cb, &h16);
+ WOW32ASSERT(vp);
+ if (vp) {
+ GETMISCPTR(vp, lpMem16);
+ RtlCopyMemory(lpMem16, lpMem32, cb);
+ GlobalUnlock16(h16);
+ FLUSHVDMPTR(vp, cb, lpMem16);
+ FREEMISCPTR(lpMem16);
+ }
+
+ return (h16);
+}
+
+
+HANDLE Copyh16Toh32 (int cb, LPBYTE lpMem16)
+{
+ HANDLE hMem32;
+ LPBYTE lpMem32;
+
+ hMem32 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cb);
+ WOW32ASSERT(hMem32);
+ if (hMem32) {
+ lpMem32 = GlobalLock(hMem32);
+ RtlCopyMemory (lpMem32, lpMem16, cb);
+ GlobalUnlock(hMem32);
+ }
+
+ return (hMem32);
+}
+
+
+VOID FixMetafile32To16 (LPMETAFILEPICT lpMemMeta32, LPMETAFILEPICT16 lpMemMeta16)
+{
+
+ if (lpMemMeta32->mm == MM_ANISOTROPIC) {
+ LONG xExt = lpMemMeta32->xExt;
+ LONG yExt = lpMemMeta32->yExt;
+
+ while (xExt < (LONG)(SHORT)MINSHORT
+ || xExt > (LONG)(SHORT)MAXSHORT
+ || yExt < (LONG)(SHORT)MINSHORT
+ || yExt > (LONG)(SHORT)MAXSHORT) {
+ xExt = xExt / 2;
+ yExt = yExt / 2;
+ }
+ STORESHORT(lpMemMeta16->mm, MM_ANISOTROPIC);
+ STORESHORT(lpMemMeta16->xExt, xExt);
+ STORESHORT(lpMemMeta16->yExt, yExt);
+ }
+ else {
+ STORESHORT(lpMemMeta16->mm, lpMemMeta32->mm);
+ STORESHORT(lpMemMeta16->xExt, lpMemMeta32->xExt);
+ STORESHORT(lpMemMeta16->yExt, lpMemMeta32->yExt);
+ }
+}
+
+//
+// CHEESE ALERT: This function is exported for the OLE DDE code
+// to call so it can correctly free up metafile handle pairs in
+// a VDM. This function is NOT found in any header files. If you
+// change this, you need to find its use in the OLE project.
+// Probably best to just leave it alone.
+//
+BOOL WINAPI WOWFreeMetafile( HANDLE h32 )
+{
+ return( W32DDEFreeGlobalMem32( h32 ) );
+}