/*++
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