diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ole32/com/remote/dde/client/ddeworkr.cxx | |
download | NT4.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.cxx | 1331 |
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 + + |