summaryrefslogtreecommitdiffstats
path: root/private/ole32/com/remote/dde/client/ddeworkr.cxx
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/ole32/com/remote/dde/client/ddeworkr.cxx
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/ole32/com/remote/dde/client/ddeworkr.cxx')
-rw-r--r--private/ole32/com/remote/dde/client/ddeworkr.cxx1331
1 files changed, 1331 insertions, 0 deletions
diff --git a/private/ole32/com/remote/dde/client/ddeworkr.cxx b/private/ole32/com/remote/dde/client/ddeworkr.cxx
new file mode 100644
index 000000000..9d117db18
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddeworkr.cxx
@@ -0,0 +1,1331 @@
+/*++
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeworkr.cpp
+
+Abstract:
+
+ This module contains the code for the worker routines
+
+Author:
+
+ Srini Koppolu (srinik) 22-June-1992
+ Jason Fuller (jasonful) 24-July-1992
+
+Revision History:
+ Kevin Ross (KevinRo) 10-May-1994
+ Mostly added comments, and attempted to clean
+ it up.
+
+--*/
+#include "ddeproxy.h"
+
+ASSERTDATA
+
+/*
+ * WORKER ROUTINES
+ *
+ */
+
+
+INTERNAL_(BOOL) wPostMessageToServer(LPDDE_CHANNEL pChannel,
+ WORD wMsg,
+ LONG lParam,
+ BOOL fFreeOnError)
+{
+ int c=0;
+ intrDebugOut((DEB_ITRACE,
+ "wPostMessageToServer(pChannel=%x,wMsg=%x,lParam=%x,fFreeOnError=%x\n",
+ pChannel,
+ wMsg,
+ lParam,
+ fFreeOnError));
+ if (NULL==pChannel)
+ {
+ AssertSz (0, "Channel missing");
+ return FALSE;
+ }
+ pChannel->wMsg = wMsg;
+ pChannel->lParam = lParam;
+ pChannel->hres = NOERROR;
+
+ while (TRUE && c<10 )
+ {
+ if (!IsWindow (pChannel->hwndSvr))
+ {
+ intrDebugOut((DEB_IWARN,
+ "wPostMessageToServer: invalid window %x\n",
+ pChannel->hwndSvr));
+ goto errRet;
+ }
+ if (wTerminateIsComing (pChannel)
+ && wMsg != WM_DDE_ACK
+ && wMsg != WM_DDE_TERMINATE)
+ {
+ intrDebugOut((DEB_IWARN,"Server sent terminate, cannot post\n"));
+ goto errRet;
+ }
+ if (!PostMessage (pChannel->hwndSvr, wMsg, (WPARAM) pChannel->hwndCli, lParam))
+ {
+ intrDebugOut((DEB_IWARN,
+ "wPostMessageToServer: PostMessageFailed, yielding\n"));
+ Yield ();
+ c++;
+ }
+ else
+ return TRUE;
+ }
+ AssertSz (0, "PostMessage failed");
+
+errRet:
+ intrDebugOut((DEB_IWARN,"wPostMessageToServer returns FALSE\n"));
+ if (fFreeOnError)
+ {
+ DDEFREE(wMsg,lParam);
+ }
+
+ return FALSE;
+}
+
+
+// call Ole1ClassFromCLSID then global add atom; returns NULL if error.
+INTERNAL_(ATOM) wAtomFromCLSID(REFCLSID rclsid)
+{
+ WCHAR szClass[MAX_STR];
+ ATOM aCls;
+
+ if (Ole1ClassFromCLSID2(rclsid, szClass, sizeof(szClass)) == 0)
+ return NULL;
+ aCls = wGlobalAddAtom(szClass);
+ intrAssert(wIsValidAtom(aCls));
+ return aCls;
+}
+
+INTERNAL_(ATOM) wGlobalAddAtom(LPCOLESTR sz)
+{
+ if (sz==NULL || sz[0] == '\0')
+ {
+ return NULL;
+ }
+
+ ATOM a = GlobalAddAtom(sz);
+ intrAssert(wIsValidAtom(a));
+ return a;
+}
+
+INTERNAL_(ATOM) wGlobalAddAtomA(LPCSTR sz)
+{
+ if (sz==NULL || sz[0] == '\0')
+ return NULL;
+ ATOM a = GlobalAddAtomA(sz);
+ intrAssert(wIsValidAtom(a));
+ return a;
+}
+
+
+INTERNAL_(ATOM) wGetExeNameAtom (REFCLSID rclsid)
+{
+ LONG cb = MAX_STR;
+ WCHAR key[MAX_STR];
+ ATOM a;
+
+ if (Ole1ClassFromCLSID2(rclsid, key, sizeof(key)) == 0)
+ return NULL;
+
+ lstrcatW (key, OLESTR("\\protocol\\StdFileEditing\\server"));
+
+ if (RegQueryValue (HKEY_CLASSES_ROOT, key, key, &cb))
+ {
+ Puts ("ERROR: wGetExeNameAtom failed\n");
+ return NULL;
+ }
+ a = wGlobalAddAtom (key);
+ intrAssert(wIsValidAtom(a));
+ return a;
+}
+
+INTERNAL_(void) wFreeData (HANDLE hData, CLIPFORMAT cfFormat,
+ BOOL fFreeNonGdiHandle)
+{
+ intrDebugOut((DEB_ITRACE,
+ "wFreeData(hData=%x,cfFormat=%x,FreeNonGDIHandle=%x\n",
+ hData,
+ (USHORT)cfFormat,
+ fFreeNonGdiHandle));
+
+ AssertSz (hData != NULL, "Trying to free NULL handle");
+ AssertSz (hData != (HANDLE) 0xcccccccc, "Trying to free handle from a deleted object");
+
+ switch (cfFormat) {
+ case CF_METAFILEPICT:
+ LPMETAFILEPICT lpMfp;
+
+ if (lpMfp = (LPMETAFILEPICT) GlobalLock (hData))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "wFreeData freeing metafile %x\n",
+ lpMfp->hMF));
+
+ OleDdeDeleteMetaFile(lpMfp->hMF);
+ GlobalUnlock (hData);
+ }
+ GlobalFree (hData);
+ break;
+
+ case CF_BITMAP:
+ case CF_PALETTE:
+ Verify(DeleteObject (hData));
+ break;
+
+ case CF_DIB:
+ GlobalFree (hData);
+ break;
+
+ default:
+ if (fFreeNonGdiHandle)
+ GlobalFree (hData);
+ break;
+ }
+}
+
+
+
+INTERNAL_(BOOL) wInitiate (LPDDE_CHANNEL pChannel, ATOM aLow, ATOM aHigh)
+{
+ intrDebugOut((DEB_ITRACE,"wInitiate(pChannel=%x,aLow=%x,aHigh=%x)\n",
+ pChannel, aLow, aHigh));
+
+ intrAssert(wIsValidAtom(aLow));
+ if (aLow == (ATOM)0)
+ {
+ intrDebugOut((DEB_IERROR,"wInitiate Failed, aLow == 0\n"));
+ return FALSE;
+ }
+
+ pChannel->iAwaitAck = AA_INITIATE;
+
+ SSSendMessage ((HWND)-1, WM_DDE_INITIATE, (WPARAM) pChannel->hwndCli,
+ MAKE_DDE_LPARAM (WM_DDE_INITIATE, aLow, aHigh));
+
+ pChannel->iAwaitAck = NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "wInitiate pChannel->hwndSrvr = %x\n",
+ pChannel->hwndSvr));
+
+ return (pChannel->hwndSvr != NULL);
+}
+
+
+
+INTERNAL_(HRESULT) wScanItemOptions (ATOM aItem, int FAR* lpoptions)
+{
+ ATOM aModifier;
+ LPOLESTR lpbuf;
+ WCHAR buf[MAX_STR];
+
+ *lpoptions = ON_CHANGE; // default
+
+ if (!aItem) {
+ // NULL item with no modifier means ON_CHANGE for NULL item
+ return NOERROR;
+ }
+
+ intrAssert(wIsValidAtom(aItem));
+ GlobalGetAtomName (aItem, buf, MAX_STR);
+ lpbuf = buf;
+
+ while ( *lpbuf && *lpbuf != '/')
+ IncLpch (lpbuf);
+
+ // no modifier same as /change
+
+ if (*lpbuf == NULL)
+ return NOERROR;
+
+ *lpbuf++ = NULL; // seperate out the item string
+ // We are using this in the caller.
+
+ if (!(aModifier = GlobalFindAtom (lpbuf)))
+ {
+ Puts ("ERROR: wScanItemOptions found non-atom modifier\n");
+ return ReportResult(0, RPC_E_DDE_SYNTAX_ITEM, 0, 0);
+ }
+
+ intrAssert(wIsValidAtom(aModifier));
+
+ if (aModifier == aChange)
+ return NOERROR;
+
+ // Is it a save?
+ if (aModifier == aSave){
+ *lpoptions = ON_SAVE;
+ return NOERROR;
+ }
+ // Is it a Close?
+ if (aModifier == aClose){
+ *lpoptions = ON_CLOSE;
+ return NOERROR;
+ }
+
+ // unknown modifier
+ Puts ("ERROR: wScanItemOptions found bad modifier\n");
+ return ReportResult(0, RPC_E_DDE_SYNTAX_ITEM, 0, 0);
+}
+
+
+INTERNAL_(BOOL) wClearWaitState (LPDDE_CHANNEL pChannel)
+{
+ Assert (pChannel);
+ // kill if any timer active.
+ if (pChannel->wTimer) {
+ KillTimer (pChannel->hwndCli, 1);
+ pChannel->wTimer = 0;
+
+ if (pChannel->hDdePoke) {
+ GlobalFree (pChannel->hDdePoke);
+ pChannel->hDdePoke = NULL;
+ }
+
+ if (pChannel->hopt) {
+ GlobalFree (pChannel->hopt);
+ pChannel->hopt = NULL;
+ }
+
+ //
+ // If the channel is waiting on an Ack, and there is an
+ // lParam, then we may need to cleanup the data.
+
+ if (pChannel->iAwaitAck && (pChannel->lParam)) {
+ if (pChannel->iAwaitAck == AA_EXECUTE)
+ {
+ //
+ // KevinRo: Found the following comment in the code.
+ // ; // BUGBUG32 - get hData from GET_WM_DDE_EXECUTE_HADATA ??
+ // It appears, by looking at what the 16-bit code does,
+ // that the goal is to free the handle that was passed as
+ // part of the EXECUTE message. Judging by what the 16-bit
+ // code did, I have determined that this is correct.
+ //
+ // The macro used below wanted two parameters. The first was
+ // the WPARAM, the second the LPARAM. We don't have the WPARAM.
+ // However, it isn't actually used by the macro, so I have
+ // cheated and provided 0 as a default
+ //
+ GlobalFree(GET_WM_DDE_EXECUTE_HDATA(0,pChannel->lParam));
+
+#ifdef KEVINRO_HERE_IS_THE_16_BIT_CODE
+ GlobalFree (HIWORD (pChannel->lParam));
+#endif
+ }
+ else
+ {
+ //
+ // All of the other DDE messages pass an Atom in the high word.
+ // Therefore, we should delete the atom.
+ //
+ //
+ ATOM aTmp;
+
+ aTmp = MGetDDElParamHi(pChannel->wMsg,pChannel->lParam);
+
+ intrAssert(wIsValidAtom(aTmp));
+ if (aTmp)
+ {
+ GlobalDeleteAtom (aTmp);
+ }
+ }
+ DDEFREE(pChannel->wMsg,pChannel->lParam);
+
+ // we want to wipe out the lParam
+ pChannel->lParam = 0x0;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+// wNewHandle (LPSTR, DWORD)
+//
+// Copy cb bytes from lpstr into a new memory block and return a handle to it.
+// If lpstr is an ASCIIZ string, cb must include 1 for the null terminator.
+//
+
+INTERNAL_(HANDLE) wNewHandle (LPSTR lpstr, DWORD cb)
+{
+
+ HANDLE hdata = NULL;
+ LPSTR lpdata = NULL;
+
+ hdata = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, cb);
+ if (hdata == NULL || (lpdata = (LPSTR) GlobalLock (hdata)) == NULL)
+ goto errRtn;
+
+ memcpy (lpdata, lpstr, cb);
+ GlobalUnlock (hdata);
+ return hdata;
+
+errRtn:
+ Puts ("ERROR: wNewHandle\n");
+ Assert (0);
+ if (lpdata)
+ GlobalUnlock (hdata);
+
+ if (hdata)
+ GlobalFree (hdata);
+ return NULL;
+}
+
+
+
+// wDupData
+//
+// Copy data from handle h into a new handle which is returned as *ph.
+//
+
+INTERNAL wDupData (LPHANDLE ph, HANDLE h, CLIPFORMAT cf)
+{
+ Assert (ph);
+ RetZ (wIsValidHandle(h, cf));
+ *ph = OleDuplicateData (h, cf, GMEM_DDESHARE | GMEM_MOVEABLE);
+ RetZ (wIsValidHandle (*ph, cf));
+ return NOERROR;
+}
+
+
+// wTransferHandle
+//
+//
+INTERNAL wTransferHandle
+ (LPHANDLE phDst,
+ LPHANDLE phSrc,
+ CLIPFORMAT cf)
+{
+ RetErr (wDupData (phDst, *phSrc, cf));
+ wFreeData (*phSrc, cf, TRUE);
+ *phSrc = (HANDLE)0;
+ return NOERROR;
+}
+
+
+// wHandleCopy
+//
+// copy data from hSrc to hDst.
+// Both handles must already have memory allocated to them.
+//
+
+INTERNAL wHandleCopy (HANDLE hDst, HANDLE hSrc)
+{
+ LPSTR lpDst, lpSrc;
+ DWORD dwSrc;
+
+ if (NULL==hDst || NULL==hSrc)
+ return ResultFromScode (E_INVALIDARG);
+ if (GlobalSize(hDst) < (dwSrc=GlobalSize(hSrc)))
+ {
+ HANDLE hDstNew = GlobalReAlloc (hDst, dwSrc, GMEM_DDESHARE | GMEM_MOVEABLE);
+ if (hDstNew != hDst)
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+ if (!(lpDst = (LPSTR) GlobalLock(hDst)))
+ {
+ intrAssert(!"ERROR: wHandleCopy hDst");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ if (!(lpSrc = (LPSTR) GlobalLock(hSrc)))
+ {
+ GlobalUnlock(hDst);
+ intrAssert (!"ERROR: wHandleCopy hSrc");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ memcpy (lpDst, lpSrc, dwSrc);
+ GlobalUnlock(hDst);
+ GlobalUnlock(hSrc);
+ return NOERROR;
+}
+
+
+// ExtendAtom: Create a new atom, which is the old one plus extension
+
+INTERNAL_(ATOM) wExtendAtom (ATOM aItem, int iAdvOn)
+{
+ WCHAR buffer[MAX_STR+1];
+ LPOLESTR lpext;
+
+ buffer[0] = 0;
+ // aItem==NULL for embedded objects.
+ // If so, there is no item name before the slash.
+ if (aItem)
+ GlobalGetAtomName (aItem, buffer, MAX_STR);
+
+ switch (iAdvOn) {
+ case ON_CHANGE:
+ lpext = OLESTR("");
+ break;
+
+ case ON_SAVE:
+ lpext = OLESTR("/Save");
+ break;
+
+ case ON_CLOSE:
+ lpext = OLESTR("/Close");
+ break;
+
+ default:
+ AssertSz (FALSE, "Unknown Advise option");
+ break;
+
+ }
+
+ lstrcatW (buffer, lpext);
+ if (buffer[0])
+ return wGlobalAddAtom (buffer);
+ else
+ return NULL;
+ // not an error. For embedded object on-change, aItem==NULL
+}
+
+
+
+
+INTERNAL_(ATOM) wDupAtom (ATOM a)
+{
+ WCHAR sz[MAX_STR];
+
+ if (!a)
+ return NULL;
+
+ Assert (wIsValidAtom (a));
+ GlobalGetAtomName (a, sz, MAX_STR);
+ return wGlobalAddAtom (sz);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomLen
+//
+// Synopsis: Return the length, in characters, of the atom name.
+// The length includes the NULL. This function returns the
+// length of the UNICODE version of the atom.
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(int) wAtomLen (ATOM atom)
+{
+ WCHAR buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ return (GlobalGetAtomName (atom, buf, MAX_STR));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomLenA
+//
+// Synopsis: Return the length, in characters, of the atom name.
+// The length includes the NULL This function returns the
+// length of the ANSI version of the atom,
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(int) wAtomLenA (ATOM atom)
+{
+ char buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ return (GlobalGetAtomNameA (atom, (LPSTR)buf, MAX_STR));
+}
+
+
+
+// NOTE: returns address of static buffer. Use return value immediately.
+//
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomName
+//
+// Synopsis: Returns a STATIC BUFFER that holds the string name of the
+// atom.
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Commented
+//
+// Notes:
+//
+// WARNING: This uses a static buffer, so don't depend on the pointer for
+// very long.
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPOLESTR) wAtomName (ATOM atom)
+{
+ static WCHAR buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ if (0==GlobalGetAtomName (atom, buf, MAX_STR))
+ return NULL;
+
+ return buf;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomName
+//
+// Synopsis: Returns a STATIC BUFFER that holds the string name of the
+// atom.
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Commented
+//
+// Notes:
+//
+// WARNING: This uses a static buffer, so don't depend on the pointer for
+// very long.
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPSTR) wAtomNameA (ATOM atom)
+{
+ static char buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ if (0==GlobalGetAtomNameA (atom, (LPSTR)buf, MAX_STR))
+ return NULL;
+
+ return buf;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: wHandleFromDdeData
+//
+// Synopsis: Return a handle from the DDEDATA passed in.
+//
+// Effects: This function will return the correct data from the
+// DDEDATA that is referenced by the handle passed in.
+//
+// DDEDATA is a small structure that is used in DDE to
+// specify the data type of the buffer, its release
+// semantics, and the actual data.
+//
+// In the case of a known format, the handle to the
+// data is extracted from the DDEDATA structure, and
+// the hDdeData is released.
+//
+// If its a Native format, the data is either moved
+// within the memory block allocated, or is copied to
+// another block, depending on the fRelease flag in
+// the hDdeData.
+//
+// Arguments: [hDdeData] -- Handle to DDEDATA
+//
+// Requires:
+//
+// Returns: A handle to the data. hDdeData will be invalidated
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-13-94 kevinro Commented
+//
+// Notes:
+//
+// hDdeData is invalid after calling this function
+//
+//----------------------------------------------------------------------------
+
+
+INTERNAL_(HANDLE) wHandleFromDdeData
+ (HANDLE hDdeData)
+{
+ intrDebugOut((DEB_ITRACE,"wHandleFromDdeData(%x)\n",hDdeData));
+ BOOL fRelease;
+ HGLOBAL h = NULL; // return value
+
+ DDEDATA FAR* lpDdeData = (DDEDATA FAR *) GlobalLock (hDdeData);
+
+ //
+ // If the handle is invalid, then the lpDdeData will be NULL
+ //
+ if (!lpDdeData)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "\twHandleFromDdeData(%x) invalid handle\n",
+ hDdeData));
+ return NULL;
+ }
+
+
+ //
+ // The header section of a DDEDATA consists of 2 shorts.
+ // That makes it 4 bytes. Due to the new packing values,
+ // it turns out that doing a sizeof(DDEDATA) won't work,
+ // because the size gets rounded up to a multple of 2
+ //
+ // We will just hard code the 4 here, since it cannot change
+ // for all time anyway.
+ //
+ #define cbHeader 4
+ Assert (cbHeader==4);
+
+ //
+ // If the cfFormat is BITMAP or METAFILEPICT, then the
+ // handle will be retrieved from the first DWORD of the
+ // buffer
+ //
+ if (lpDdeData->cfFormat == CF_BITMAP ||
+ lpDdeData->cfFormat == CF_METAFILEPICT)
+ {
+ //
+ // The alignment here should be fine, since the Value
+ // field is DWORD aligned. So, we trust this cast
+ //
+ h = *(LPHANDLE)lpDdeData->Value;
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ fRelease = lpDdeData->fRelease;
+ GlobalUnlock (hDdeData);
+ if (fRelease)
+ {
+ GlobalFree (hDdeData);
+ }
+
+ return h;
+ }
+ else if (lpDdeData->cfFormat == CF_DIB)
+ {
+ //
+ // The alignment here should be fine, since the Value
+ // field is DWORD aligned.
+ //
+ // This changes the memory from fixed to moveable.
+ //
+ h = GlobalReAlloc (*(LPHANDLE)lpDdeData->Value, 0L,
+ GMEM_MODIFY|GMEM_MOVEABLE);
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ fRelease = lpDdeData->fRelease;
+ GlobalUnlock (hDdeData);
+ if (fRelease)
+ GlobalFree (hDdeData);
+ return h;
+ }
+
+
+ // Native and other data case
+ // dwSize = size of Value array, ie, size of the data itself
+ const DWORD dwSize = GlobalSize (hDdeData) - cbHeader;
+
+ if (lpDdeData->fRelease)
+ {
+ // Move the Value data up over the DDE_DATA header flags.
+ memcpy ((LPSTR)lpDdeData, ((LPSTR)lpDdeData)+cbHeader, dwSize);
+ GlobalUnlock (hDdeData);
+ h = GlobalReAlloc (hDdeData, dwSize, GMEM_MOVEABLE);
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ return h;
+ }
+ else
+ {
+ // Duplicate the data because the server will free the original.
+ h = wNewHandle (((LPSTR)lpDdeData)+cbHeader, dwSize);
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ GlobalUnlock (hDdeData);
+ return h;
+ }
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::CanCallBack
+//
+// Synopsis: This routine apparently was supposed to determine if a
+// call back could be made. However, the PeekMessage stuff
+// was commented out.
+//
+// So, it returns TRUE if 0 or 1, FALSE but increments lpCount
+// if 2, returns true but decrements lpCount if > 3. Why?
+// Dunno. Need to ask JasonFul
+//
+// Effects:
+//
+// Arguments: [lpCount] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-16-94 kevinro Commented, confused, and disgusted
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(BOOL) CDdeObject::CanCallBack (LPINT lpCount)
+{
+ switch (*lpCount) {
+ case 0:
+ case 1:
+ return TRUE;
+
+ case 2:
+ {
+// MSG msg;
+ if (0)
+ //!PeekMessage (&msg, m_pDocChannel->hwndCli,0,0, PM_NOREMOVE) ||
+ // msg.message != WM_DDE_DATA)
+ {
+ Puts ("Server only sent one format (hopefully presentation)\n");
+ return TRUE;
+ }
+ else
+ {
+ ++(*lpCount);
+ return FALSE;
+ }
+ }
+
+ case 3:
+ --(*lpCount);
+ return TRUE;
+
+ default:
+ AssertSz (FALSE, "012345" + *lpCount);
+ return FALSE;
+ }
+}
+
+
+INTERNAL_(BOOL) wIsOldServer (ATOM aClass)
+{
+ LONG cb = MAX_STR;
+ WCHAR key[MAX_STR];
+ int len;
+
+ if (aClass==(ATOM)0)
+ return FALSE;
+
+ if (!GlobalGetAtomName (aClass, key, sizeof(key)))
+ return TRUE;
+
+ lstrcatW (key, OLESTR("\\protocol\\StdFileEditing\\verb\\"));
+ len = lstrlenW (key);
+ key [len++] = (char) ('0');
+ key [len++] = 0;
+
+ if (RegQueryValue (HKEY_CLASSES_ROOT, key, key, &cb))
+ return TRUE; // no verbs registered
+
+ return FALSE;
+}
+
+
+
+
+INTERNAL_(void) wFreePokeData
+ (LPDDE_CHANNEL pChannel,
+ BOOL fMSDrawBug)
+{
+ DDEPOKE FAR * lpdde;
+
+ if (!pChannel )
+ return;
+
+ if (!pChannel->hDdePoke)
+ return;
+
+ if (lpdde = (DDEPOKE FAR *) GlobalLock (pChannel->hDdePoke)) {
+
+ // The old version of MSDraw expects the _contents_ of METAFILEPICT
+ // structure, rather than the handle to it, to be part of DDEPOKE.
+
+ if (fMSDrawBug && lpdde->cfFormat==CF_METAFILEPICT) {
+ intrDebugOut((DEB_ITRACE,
+ "wFreePokeData is accomodating MSDraw bug\n"));
+ //
+ // This meta file was created in 32-bits, and was not passed
+ // into us by DDE. Therefore, this metafile should not need to
+ // call WOW to be free'd.
+ //
+ DeleteMetaFile (((LPMETAFILEPICT) ((LPVOID) &lpdde->Value))->hMF);
+ }
+ // If there is a normal metafile handle in the Value field,
+ // it will be freed (if necessary) by the ReleaseStgMedium()
+ // in DO::SetData
+ GlobalUnlock (pChannel->hDdePoke);
+ }
+ GlobalFree (pChannel->hDdePoke);
+ pChannel->hDdePoke = NULL;
+}
+
+
+
+
+INTERNAL_(HANDLE) wPreparePokeBlock
+ (HANDLE hData, CLIPFORMAT cfFormat, ATOM aClass, BOOL bOldSvr)
+{
+ HANDLE hDdePoke;
+ LPSTR lpBuf;
+
+ if (!hData)
+ return NULL;
+
+ // The old version of MSDraw expects the contents of METAFILEPICT
+ // structure to be part of DDEPOKE, rather than the handle to it.
+ if ((cfFormat==CF_METAFILEPICT && !(aClass==aMSDraw && bOldSvr))
+ || (cfFormat == CF_DIB)
+ || (cfFormat == CF_BITMAP)) {
+
+ Verify (lpBuf = wAllocDdePokeBlock (4, cfFormat, &hDdePoke));
+ *((HANDLE FAR*)lpBuf) = hData;
+
+ }
+ else {
+ // Handle the non-metafile case and the MS-Draw bug
+ DWORD dwSize = GlobalSize (hData);
+
+ if ((aClass == aMSDraw) && bOldSvr)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "wPreparePokeBlock is accomodating MSDraw bug\n"));
+ }
+
+ if (lpBuf = wAllocDdePokeBlock (dwSize, cfFormat, &hDdePoke)) {
+ memcpy (lpBuf, GlobalLock(hData), dwSize);
+ GlobalUnlock (hData);
+ }
+ }
+ GlobalUnlock (hDdePoke);
+ return hDdePoke;
+}
+
+
+// wAllocDdePokeBlock
+// The caller must unlock *phDdePoke when it is done using the return value
+// of this function but before a DDe message is sent using *phDdePoke.
+//
+
+INTERNAL_(LPSTR) wAllocDdePokeBlock
+ (DWORD dwSize, CLIPFORMAT cfFormat, LPHANDLE phDdePoke)
+{
+ HANDLE hdde = NULL;
+ DDEPOKE FAR * lpdde = NULL;
+
+ if (!(hdde = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT,
+ (dwSize + sizeof(DDEPOKE) - sizeof(BYTE) ))))
+ return NULL;
+
+ if (!(lpdde = (DDEPOKE FAR*)GlobalLock (hdde))) {
+ GlobalFree (hdde);
+ return NULL;
+ }
+ // hdde will be UnLock'ed in wPreparePokeBlock and Free'd in wFreePokeData
+ lpdde->fRelease = FALSE;
+ lpdde->cfFormat = cfFormat;
+ *phDdePoke = hdde;
+ return (LPSTR) &(lpdde->Value);
+}
+
+
+#ifdef OLD
+INTERNAL_(ULONG) wPixelsToHiMetric
+ (ULONG cPixels,
+ ULONG cPixelsPerInch)
+{
+ return cPixels * HIMETRIC_PER_INCH / cPixelsPerInch;
+}
+#endif
+
+// Can ask for icon based on either CLSID or filename
+//
+
+INTERNAL GetDefaultIcon (REFCLSID clsidIn, LPCOLESTR szFile, HANDLE FAR* phmfp)
+{
+ if (!(*phmfp = OleGetIconOfClass(clsidIn, NULL, TRUE)))
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ return NOERROR;
+}
+
+#ifdef OLD
+ VDATEPTROUT (phmfp, HICON);
+ VDATEPTRIN (szFile, char);
+ WCHAR szExe[MAX_STR];
+ HICON hicon;
+ HDC hdc;
+ METAFILEPICT FAR* pmfp=NULL;
+ HRESULT hresult;
+ static int cxIcon = 0;
+ static int cyIcon = 0;
+ static int cxIconHiMetric = 0;
+ static int cyIconHiMetric = 0;
+
+ *phmfp = NULL;
+ CLSID clsid;
+ if (clsidIn != CLSID_NULL)
+ {
+ clsid = clsidIn;
+ }
+ else
+ {
+ RetErr (GetClassFile (szFile, &clsid));
+ }
+ ATOM aExe = wGetExeNameAtom (clsid);
+ if (0==GlobalGetAtomName (aExe, szExe, MAX_STR))
+ {
+ Assert (0);
+ return ReportResult(0, E_UNEXPECTED, 0, 0);
+ }
+ hicon = ExtractIcon (hmodOLE2, szExe, 0/*first icon*/);
+ if (((HICON) 1)==hicon || NULL==hicon)
+ {
+ // ExtractIcon failed, so we can't support DVASPECT_ICON
+ return ResultFromScode (DV_E_DVASPECT);
+ }
+ *phmfp = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT));
+ ErrZS (*phmfp, E_OUTOFMEMORY);
+ pmfp = (METAFILEPICT FAR*) GlobalLock (*phmfp);
+ ErrZS (pmfp, E_OUTOFMEMORY);
+ if (0==cxIcon)
+ {
+ // In units of pixels
+ Verify (cxIcon = GetSystemMetrics (SM_CXICON));
+ Verify (cyIcon = GetSystemMetrics (SM_CYICON));
+ // In units of .01 millimeter
+ cxIconHiMetric = (int)(long)wPixelsToHiMetric (cxIcon, giPpliX) ;
+ cyIconHiMetric = (int)(long)wPixelsToHiMetric (cyIcon, giPpliY) ;
+ }
+ pmfp->mm = MM_ANISOTROPIC;
+ pmfp->xExt = cxIconHiMetric;
+ pmfp->yExt = cyIconHiMetric;
+ hdc = CreateMetaFile (NULL);
+ SetWindowOrg (hdc, 0, 0);
+ SetWindowExt (hdc, cxIcon, cyIcon);
+ DrawIcon (hdc, 0, 0, hicon);
+ pmfp->hMF = CloseMetaFile (hdc);
+ ErrZ (pmfp->hMF);
+ Assert (wIsValidHandle (pmfp->hMF, NULL));
+ GlobalUnlock (*phmfp);
+ Assert (wIsValidHandle (*phmfp, CF_METAFILEPICT));
+ return NOERROR;
+
+ errRtn:
+ if (pmfp)
+ GlobalUnlock (*phmfp);
+ if (*phmfp)
+ GlobalFree (*phmfp);
+ return hresult;
+}
+#endif
+
+#define DWTIMEOUT 1000L
+
+INTERNAL wTimedGetMessage
+ (LPMSG pmsg,
+ HWND hwnd,
+ WORD wFirst,
+ WORD wLast)
+{
+ DWORD dwStartTickCount = GetTickCount();
+ while (!SSPeekMessage (pmsg, hwnd, wFirst, wLast, PM_REMOVE))
+ {
+ if (GetTickCount() - dwStartTickCount > DWTIMEOUT)
+ {
+ if (!IsWindow (hwnd))
+ return ResultFromScode (RPC_E_CONNECTION_LOST);
+ else
+ return ResultFromScode (RPC_E_SERVER_DIED);
+ }
+ }
+ return NOERROR;
+}
+
+
+INTERNAL wNormalize
+ (LPFORMATETC pformatetcIn,
+ LPFORMATETC pformatetcOut)
+{
+ if (pformatetcIn->cfFormat == 0
+ && pformatetcIn->ptd == NULL // Is WildCard
+ && pformatetcIn->dwAspect == -1L
+ && pformatetcIn->lindex == -1L
+ && pformatetcIn->tymed == -1L)
+ {
+ pformatetcOut->cfFormat = CF_METAFILEPICT;
+ pformatetcOut->ptd = NULL;
+ pformatetcOut->dwAspect = DVASPECT_CONTENT;
+ pformatetcOut->lindex = DEF_LINDEX;
+ pformatetcOut->tymed = TYMED_MFPICT;
+ }
+ else
+ {
+ memcpy (pformatetcOut, pformatetcIn, sizeof(FORMATETC));
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL wVerifyFormatEtc
+ (LPFORMATETC pformatetc)
+{
+ intrDebugOut((DEB_ITRACE,
+ "wVerifyFormatEtc(pformatetc=%x)\n",
+ pformatetc));
+
+ VDATEPTRIN (pformatetc, FORMATETC);
+ if (!HasValidLINDEX(pformatetc))
+ {
+ intrDebugOut((DEB_IERROR, "\t!HasValidLINDEX(pformatetc)\n"));
+ return(DV_E_LINDEX);
+ }
+
+ if (0==(pformatetc->tymed & (TYMED_HGLOBAL | TYMED_MFPICT | TYMED_GDI)))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(pformatetc->tymed & (TYMED_HGLOBAL | TYMED_MFPICT | TYMED_GDI))\n"));
+ return ResultFromScode (DV_E_TYMED);
+ }
+ if (0==(UtFormatToTymed (pformatetc->cfFormat) & pformatetc->tymed))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(UtFormatToTymed (pformatetc->cfFormat) & pformatetc->tymed)\n"));
+ return ResultFromScode (DV_E_TYMED);
+ }
+ if (0==(pformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_ICON)))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(pformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_ICON))\n"));
+
+ return ResultFromScode (DV_E_DVASPECT);
+ }
+ if (pformatetc->dwAspect & DVASPECT_ICON)
+ {
+ if (CF_METAFILEPICT != pformatetc->cfFormat)
+ {
+ intrDebugOut((DEB_IERROR,
+ "\tCF_METAFILEPICT != pformatetc->cfFormat\n"));
+ return ResultFromScode (DV_E_CLIPFORMAT);
+ }
+
+ if (0==(pformatetc->tymed & TYMED_MFPICT))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(pformatetc->tymed & TYMED_MFPICT)\n"));
+ return ResultFromScode (DV_E_TYMED);
+ }
+ }
+ if (pformatetc->ptd)
+ {
+ if (IsBadReadPtr (pformatetc->ptd, sizeof (DWORD))
+ || IsBadReadPtr (pformatetc->ptd, (size_t)pformatetc->ptd->tdSize))
+ {
+ intrDebugOut((DEB_IERROR,"\tDV_E_DVTARGETDEVICE\n"));
+
+ return ResultFromScode (DV_E_DVTARGETDEVICE);
+ }
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL wClassesMatch
+ (REFCLSID clsidIn,
+ LPOLESTR szFile)
+{
+ CLSID clsid;
+ if (NOERROR==GetClassFile (szFile, &clsid))
+ {
+ return clsid==clsidIn ? NOERROR : ResultFromScode (S_FALSE);
+ }
+ else
+ {
+ // If we can't determine the class of the file (because it's
+ // not a real file) then OK. Bug 3937.
+ return NOERROR;
+ }
+}
+
+
+
+#ifdef KEVINRO_DUPLICATECODE
+
+This routine also appears in ole1.lib in the OLE232\OLE1 directory
+
+INTERNAL wWriteFmtUserType
+ (LPSTORAGE pstg,
+ REFCLSID clsid)
+{
+ HRESULT hresult = NOERROR;
+ LPOLESTR szProgID = NULL;
+ LPOLESTR szUserType = NULL;
+
+ ErrRtnH (ProgIDFromCLSID (clsid, &szProgID));
+ ErrRtnH (OleRegGetUserType (clsid, USERCLASSTYPE_FULL, &szUserType));
+ ErrRtnH (WriteFmtUserTypeStg (pstg, RegisterClipboardFormat (szProgID),
+ szUserType));
+ errRtn:
+ delete szProgID;
+ delete szUserType;
+ return hresult;
+}
+#endif
+
+#if DBG == 1
+
+INTERNAL_(BOOL) wIsValidHandle
+ (HANDLE h,
+ CLIPFORMAT cf) // cf==NULL means normal memory
+{
+ LPVOID p;
+ if (CF_BITMAP == cf)
+ {
+ BITMAP bm;
+ return (0 != GetObject (h, sizeof(BITMAP), (LPVOID) &bm));
+ }
+ if (CF_PALETTE == cf)
+ {
+ WORD w;
+ return (0 != GetObject (h, sizeof(w), (LPVOID) &w));
+ }
+ if (!(p=GlobalLock(h)))
+ {
+ Puts ("Invalid handle");
+ Puth (h);
+ Putn();
+ return FALSE;
+ }
+ if (IsBadReadPtr (p, (WPARAM) min (UINT_MAX, GlobalSize(h))))
+ {
+ GlobalUnlock (h);
+ return FALSE;
+ }
+ GlobalUnlock (h);
+ return TRUE;
+}
+INTERNAL_(BOOL) wIsValidAtom (ATOM a)
+{
+ WCHAR sz[MAX_STR];
+ if (a==0)
+ return TRUE;
+ if (a < 0xC000)
+ return FALSE;
+ if (0==GlobalGetAtomName (a, sz, MAX_STR))
+ return FALSE;
+ if ('\0'==sz[0])
+ return FALSE;
+ return TRUE;
+}
+
+
+// A "gentle" assert used in reterr.h
+//
+
+
+INTERNAL_(void) wWarn
+ (LPSTR sz,
+ LPSTR szFile,
+ int iLine)
+{
+ intrDebugOut((DEB_WARN,
+ "Warning: %s:%u %s\n",
+ szFile,iLine,sz));
+}
+
+#endif // DBG
+
+