mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1013 lines
20 KiB
1013 lines
20 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: ddeutils.c
|
|
*
|
|
* Purpose: Conatains all the utility routines
|
|
*
|
|
* Created: 1990
|
|
*
|
|
* Copyright (c) 1990, 1991 Microsoft Corporation
|
|
*
|
|
* History:
|
|
* Raor, Srinik (../../1990) Designed and coded
|
|
*
|
|
\***************************************************************************/
|
|
#include "ole2int.h"
|
|
#include <dde.h>
|
|
#include "srvr.h"
|
|
#include "ddesrvr.h"
|
|
#include "ddedebug.h"
|
|
ASSERTDATA
|
|
|
|
|
|
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
|
|
#define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
|
|
|
|
|
|
|
|
#define KB_64 65536
|
|
|
|
extern ATOM aTrue;
|
|
extern ATOM aFalse;
|
|
|
|
extern ATOM aStdCreateFromTemplate;
|
|
extern ATOM aStdCreate;
|
|
extern ATOM aStdOpen;
|
|
extern ATOM aStdEdit;
|
|
extern ATOM aStdShowItem;
|
|
extern ATOM aStdClose;
|
|
extern ATOM aStdExit;
|
|
extern ATOM aStdDoVerbItem;
|
|
|
|
|
|
//ScanBoolArg: scans the argument which is not included in
|
|
//the quotes. These args could be only TRUE or FALSE for
|
|
//the time being. !!!The scanning routines should be
|
|
//merged and it should be generalized.
|
|
|
|
INTERNAL_(LPSTR) ScanBoolArg
|
|
(
|
|
LPSTR lpstr,
|
|
BOOL FAR *lpflag
|
|
)
|
|
{
|
|
|
|
|
|
LPSTR lpbool;
|
|
ATOM aShow;
|
|
char ch;
|
|
|
|
lpbool = lpstr;
|
|
|
|
// !!! These routines does not take care of quoted quotes.
|
|
|
|
while((ch = *lpstr) && (!(ch == ')' || ch == ',')))
|
|
lpstr++;
|
|
|
|
if(ch == NULL)
|
|
return NULL;
|
|
|
|
*lpstr++ = NULL; // terminate the arg by null
|
|
|
|
// if terminated by paren, then check for end of command
|
|
// syntax.
|
|
|
|
// Check for the end of the command string.
|
|
if (ch == ')') {
|
|
if (*lpstr++ != ']')
|
|
return NULL;
|
|
|
|
if(*lpstr != NULL)
|
|
return NULL; //finally should be terminated by null.
|
|
|
|
}
|
|
|
|
aShow = GlobalFindAtomA (lpbool);
|
|
if (aShow == aTrue)
|
|
*lpflag = TRUE;
|
|
|
|
else {
|
|
if (aShow ==aFalse)
|
|
*lpflag = FALSE;
|
|
else
|
|
return NULL;;
|
|
}
|
|
return lpstr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateUnicodeFromAnsi
|
|
//
|
|
// Synopsis: Creates a UNICODE string from an ANSI string
|
|
//
|
|
// Effects: Makes a new UNICODE string from the given ANSI string.
|
|
// The new UNICODE string is returned. Memory is allocated
|
|
// using PrivMemAlloc
|
|
//
|
|
// Arguments: [lpAnsi] -- Ansi version of string
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns: NULL if cannot create new string.
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 6-07-94 kevinro Commented/cleaned
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
LPOLESTR CreateUnicodeFromAnsi( LPCSTR lpAnsi)
|
|
{
|
|
WCHAR buf[MAX_PATH];
|
|
ULONG ccbuf;
|
|
LPOLESTR lpWideStr;
|
|
|
|
if ((ccbuf=MultiByteToWideChar(CP_ACP,0,lpAnsi,-1,buf,MAX_PATH))
|
|
== FALSE)
|
|
{
|
|
intrAssert(!"Unable to convert characters");
|
|
return NULL;
|
|
}
|
|
|
|
lpWideStr = (LPOLESTR) PrivMemAlloc(ccbuf * sizeof(WCHAR));
|
|
|
|
if (lpWideStr != NULL)
|
|
{
|
|
memcpy(lpWideStr,buf,ccbuf*sizeof(WCHAR));
|
|
}
|
|
return(lpWideStr);
|
|
}
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateAnsiFromUnicode
|
|
//
|
|
// Synopsis: Creates an Ansi string from a UNICODE string
|
|
//
|
|
// Effects: Makes a new ANSI string from the given UNICODE string.
|
|
// The new string is returned. Memory is allocated
|
|
// using PrivMemAlloc
|
|
//
|
|
// Arguments: [lpUnicode] -- Unicode version of string
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns: NULL if cannot create new string.
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 6-07-94 kevinro Commented/cleaned
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
LPSTR CreateAnsiFromUnicode( LPCOLESTR lpUnicode)
|
|
{
|
|
char buf[MAX_PATH];
|
|
ULONG ccbuf;
|
|
LPSTR lpAnsiStr;
|
|
|
|
ccbuf = WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
lpUnicode,
|
|
-1,
|
|
buf,
|
|
MAX_PATH,
|
|
NULL,
|
|
NULL);
|
|
|
|
|
|
if (ccbuf == FALSE)
|
|
{
|
|
intrAssert(!"Unable to convert characters");
|
|
return NULL;
|
|
}
|
|
|
|
lpAnsiStr = (LPSTR) PrivMemAlloc(ccbuf * sizeof(char));
|
|
|
|
if (lpAnsiStr != NULL)
|
|
{
|
|
memcpy(lpAnsiStr,buf,ccbuf);
|
|
}
|
|
return(lpAnsiStr);
|
|
}
|
|
|
|
//ScannumArg: Checks for the syntax of num arg in Execute and if
|
|
//the arg is syntactically correct, returns the ptr to the
|
|
//beginning of the next arg and also, returns the number
|
|
//Does not take care of the last num arg in the list.
|
|
|
|
INTERNAL_(LPSTR) ScanNumArg
|
|
(
|
|
LPSTR lpstr,
|
|
LPINT lpnum
|
|
)
|
|
{
|
|
|
|
WORD val = 0;
|
|
char ch;
|
|
|
|
while((ch = *lpstr++) && (ch != ',')) {
|
|
if (ch < '0' || ch >'9')
|
|
return NULL;
|
|
val += val * 10 + (ch - '0');
|
|
|
|
}
|
|
|
|
if(!ch)
|
|
return NULL;
|
|
|
|
*lpnum = val;
|
|
return lpstr;
|
|
}
|
|
|
|
|
|
|
|
|
|
//ScanArg: Checks for the syntax of arg in Execute and if
|
|
//the arg is syntactically correct, returns the ptr to the
|
|
//beginning of the next arg or to the end of the excute string.
|
|
|
|
INTERNAL_(LPSTR) ScanArg
|
|
(
|
|
LPSTR lpstr
|
|
)
|
|
{
|
|
|
|
|
|
// !!! These routines does not take care of quoted quotes.
|
|
|
|
// first char should be quote.
|
|
|
|
if (*(lpstr-1) != '\"')
|
|
return NULL;
|
|
|
|
while(*lpstr && *lpstr != '\"')
|
|
lpstr++;
|
|
|
|
if(*lpstr == NULL)
|
|
return NULL;
|
|
|
|
*lpstr++ = NULL; // terminate the arg by null
|
|
|
|
if(!(*lpstr == ',' || *lpstr == ')'))
|
|
return NULL;
|
|
|
|
|
|
if(*lpstr++ == ','){
|
|
|
|
if(*lpstr == '\"')
|
|
return ++lpstr;
|
|
// If it is not quote, leave the ptr on the first char
|
|
return lpstr;
|
|
}
|
|
|
|
// terminated by paren
|
|
// already skiped right paren
|
|
|
|
// Check for the end of the command string.
|
|
if (*lpstr++ != ']')
|
|
return NULL;
|
|
|
|
if(*lpstr != NULL)
|
|
return NULL; //finally should be terminated by null.
|
|
|
|
return lpstr;
|
|
}
|
|
|
|
// ScanCommand: scanns the command string for the syntax
|
|
// correctness. If syntactically correct, returns the ptr
|
|
// to the first arg or to the end of the string.
|
|
|
|
INTERNAL_(WORD) ScanCommand
|
|
(
|
|
LPSTR lpstr,
|
|
WORD wType,
|
|
LPSTR FAR * lplpnextcmd,
|
|
ATOM FAR * lpAtom
|
|
)
|
|
{
|
|
// !!! These routines does not take care of quoted quotes.
|
|
// and not taking care of blanks arround the operators
|
|
|
|
// !!! We are not allowing blanks after operators.
|
|
// Should be allright! since this is arestricted syntax.
|
|
|
|
char ch;
|
|
LPSTR lptemp = lpstr;
|
|
|
|
|
|
while(*lpstr && (!(*lpstr == '(' || *lpstr == ']')))
|
|
lpstr++;
|
|
|
|
if(*lpstr == NULL)
|
|
return NULL;
|
|
|
|
ch = *lpstr;
|
|
*lpstr++ = NULL; // set the end of command
|
|
|
|
*lpAtom = GlobalFindAtomA (lptemp);
|
|
|
|
if (!IsOleCommand (*lpAtom, wType))
|
|
return NON_OLE_COMMAND;
|
|
|
|
if (ch == '(') {
|
|
ch = *lpstr++;
|
|
|
|
if (ch == ')') {
|
|
if (*lpstr++ != ']')
|
|
return NULL;
|
|
}
|
|
else {
|
|
if (ch != '\"')
|
|
return NULL;
|
|
}
|
|
|
|
*lplpnextcmd = lpstr;
|
|
return OLE_COMMAND;
|
|
}
|
|
|
|
// terminated by ']'
|
|
|
|
if (*(*lplpnextcmd = lpstr)) // if no nul termination, then it is error.
|
|
return NULL;
|
|
|
|
return OLE_COMMAND;
|
|
}
|
|
|
|
|
|
//MakeDataAtom: Creates a data atom from the item string
|
|
//and the item data otions.
|
|
|
|
INTERNAL_(ATOM) MakeDataAtom
|
|
(
|
|
ATOM aItem,
|
|
int options
|
|
)
|
|
{
|
|
WCHAR buf[MAX_STR];
|
|
|
|
if (options == OLE_CHANGED)
|
|
return DuplicateAtom (aItem);
|
|
|
|
if (!aItem)
|
|
buf[0] = NULL;
|
|
else
|
|
GlobalGetAtomName (aItem, buf, MAX_STR);
|
|
|
|
if (options == OLE_CLOSED)
|
|
lstrcatW (buf, OLESTR("/Close"));
|
|
else {
|
|
if (options == OLE_SAVED)
|
|
lstrcatW (buf, OLESTR("/Save"));
|
|
else
|
|
AssertSz (0, "Bad option\n");
|
|
}
|
|
|
|
Puts ("MakeDataAtom "); Puts(buf); Putn();
|
|
if (buf[0])
|
|
return wGlobalAddAtom (buf);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
//DuplicateAtom: Duplicates an atom
|
|
INTERNAL_(ATOM) DuplicateAtom
|
|
(
|
|
ATOM atom
|
|
)
|
|
{
|
|
WCHAR buf[MAX_STR];
|
|
|
|
if (!atom)
|
|
return NULL;
|
|
|
|
GlobalGetAtomName (atom, buf, MAX_STR);
|
|
return wGlobalAddAtom (buf);
|
|
}
|
|
|
|
// MakeGlobal: makes global out of strings.
|
|
// works only for << 64k
|
|
|
|
INTERNAL_(HANDLE) MakeGlobal
|
|
(
|
|
LPSTR lpstr
|
|
)
|
|
{
|
|
|
|
int len = 0;
|
|
HANDLE hdata = NULL;
|
|
LPSTR lpdata = NULL;
|
|
|
|
len = strlen (lpstr) + 1;
|
|
|
|
hdata = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, len);
|
|
|
|
if (hdata == NULL || (lpdata = (LPSTR) GlobalLock (hdata)) == NULL)
|
|
goto errRtn;
|
|
|
|
|
|
memcpy(lpdata, lpstr, (DWORD)len);
|
|
GlobalUnlock (hdata);
|
|
return hdata;
|
|
|
|
errRtn:
|
|
Assert (0);
|
|
if (lpdata)
|
|
GlobalUnlock (hdata);
|
|
|
|
|
|
if (hdata)
|
|
GlobalFree (hdata);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
INTERNAL_(BOOL) CLSIDFromAtom(ATOM aClass, LPCLSID lpclsid)
|
|
{
|
|
WCHAR szProgID[MAX_STR];
|
|
if (!ISATOM (aClass))
|
|
return FALSE;
|
|
WORD cb=GlobalGetAtomName (aClass, szProgID, MAX_STR);
|
|
Assert (cb>0 && cb < (MAX_STR - 1));
|
|
|
|
return CLSIDFromProgID(szProgID, lpclsid) == S_OK;
|
|
}
|
|
|
|
// CLSIDFromAtomWithTreatAs
|
|
//
|
|
// Input: *paClass
|
|
// Output: *pclsid == corresponding CLSID, taking into account TreatAs and
|
|
// AutoConvert
|
|
// *paClass == atom correpsonding to *pclsid
|
|
//
|
|
#pragma SEG(CLSIDFromAtomWithTreatAs)
|
|
INTERNAL CLSIDFromAtomWithTreatAs
|
|
(ATOM FAR* paClass,
|
|
LPCLSID pclsid,
|
|
CNVTYP FAR* pcnvtyp)
|
|
{
|
|
HRESULT hr;
|
|
|
|
|
|
intrDebugOut((DEB_ITRACE,
|
|
"%p _IN CLSIDFromAtomWithTreatAs(paClass=%x,"
|
|
"pclsid=%x,pcnvtyp=%x)\n",0,
|
|
paClass,pclsid,pcnvtyp));
|
|
|
|
LPOLESTR szProgID = NULL;
|
|
CLSID clsidNew;
|
|
|
|
if (!CLSIDFromAtom (*paClass, pclsid))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exitRtn;
|
|
}
|
|
|
|
DEBUG_GUIDSTR(clsidStr,pclsid);
|
|
|
|
intrDebugOut((DEB_ITRACE,"Guid %ws",clsidStr));
|
|
if (CoGetTreatAsClass (*pclsid, &clsidNew) == NOERROR)
|
|
{
|
|
DEBUG_GUIDSTR(newStr,pclsid);
|
|
|
|
intrDebugOut((DEB_ITRACE," cnvtypTreatAs %ws\n",newStr));
|
|
if (pcnvtyp)
|
|
*pcnvtyp = cnvtypTreatAs;
|
|
}
|
|
else if (OleGetAutoConvert (*pclsid, &clsidNew) == NOERROR)
|
|
{
|
|
DEBUG_GUIDSTR(newStr,pclsid);
|
|
intrDebugOut((DEB_ITRACE," cnvtypConvertTo %ws\n",newStr));
|
|
if (pcnvtyp)
|
|
*pcnvtyp = cnvtypConvertTo;
|
|
}
|
|
else
|
|
{
|
|
intrDebugOut((DEB_ITRACE," no conversion\n"));
|
|
if (pcnvtyp)
|
|
*pcnvtyp = cnvtypNone;
|
|
clsidNew = *pclsid; // no translation
|
|
}
|
|
|
|
hr = ProgIDFromCLSID(clsidNew, &szProgID);
|
|
if (FAILED(hr))
|
|
{
|
|
intrDebugOut((DEB_ITRACE," ProgIDFromCLSID failed\n"));
|
|
goto exitRtn;
|
|
}
|
|
|
|
intrDebugOut((DEB_ITRACE,"ProgIDFromCLSID returns %ws\n",szProgID));
|
|
*paClass = GlobalAddAtom (szProgID);
|
|
*pclsid = clsidNew;
|
|
CoTaskMemFree(szProgID);
|
|
|
|
exitRtn:
|
|
intrDebugOut((DEB_ITRACE,
|
|
"%p OUT CLSIDFromAtomWithTreatAs returns %x\n",
|
|
0,hr));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
INTERNAL_(BOOL) PostMessageToClientWithReply
|
|
(
|
|
HWND hWnd,
|
|
UINT wMsg,
|
|
WPARAM wParam, // posting window
|
|
LPARAM lParam,
|
|
UINT wReplyMsg
|
|
)
|
|
{
|
|
MSG msg;
|
|
|
|
if (!IsWindowValid (hWnd))
|
|
{
|
|
AssertSz(FALSE, "Client's window is missing");
|
|
return FALSE;
|
|
}
|
|
|
|
if (!IsWindowValid ((HWND)wParam))
|
|
{
|
|
AssertSz (0, "Posting window is invalid");
|
|
return FALSE;
|
|
}
|
|
|
|
// Post message to client failed. Treat it as if we got the reply.
|
|
if (!PostMessageToClient (hWnd, wMsg, wParam, lParam))
|
|
return FALSE;
|
|
|
|
return NOERROR == wTimedGetMessage (&msg, (HWND)wParam, WM_DDE_TERMINATE,
|
|
WM_DDE_TERMINATE);
|
|
}
|
|
|
|
|
|
|
|
INTERNAL_(BOOL) PostMessageToClient
|
|
(
|
|
HWND hWnd,
|
|
UINT wMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
UINT c=0;
|
|
|
|
while (c < 10)
|
|
{
|
|
if (!IsWindowValid (hWnd)) {
|
|
Warn ("Client's window is missing");
|
|
return FALSE;
|
|
}
|
|
Puts ("Posting"); Puth(wMsg); Puts("to"); Puth(hWnd); Putn();
|
|
if (PostMessage (hWnd, wMsg, wParam, lParam))
|
|
return TRUE; // success
|
|
else
|
|
{
|
|
Yield();
|
|
c++; // try again
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
INTERNAL_(BOOL) IsWindowValid
|
|
(HWND hwnd)
|
|
{
|
|
HTASK htask;
|
|
|
|
if (!IsWindow (hwnd))
|
|
return FALSE;
|
|
|
|
htask = GetWindowThreadProcessId(hwnd, NULL);
|
|
|
|
#ifndef WIN32
|
|
if (IsTask(htask))
|
|
#endif
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
INTERNAL_(BOOL) UtilQueryProtocol
|
|
(
|
|
ATOM aClass,
|
|
LPOLESTR lpprotocol
|
|
)
|
|
{
|
|
HKEY hKey;
|
|
WCHAR key[MAX_STR];
|
|
WCHAR cclass[MAX_STR];
|
|
|
|
if (!aClass)
|
|
return FALSE;
|
|
|
|
if (!GlobalGetAtomName (aClass, cclass, MAX_STR))
|
|
return FALSE;
|
|
|
|
lstrcpyW (key, cclass);
|
|
lstrcatW (key, OLESTR("\\protocol\\"));
|
|
lstrcatW (key, lpprotocol);
|
|
lstrcatW (key, OLESTR("\\server"));
|
|
if (RegOpenKey (HKEY_CLASSES_ROOT, key, &hKey) != ERROR_SUCCESS)
|
|
return FALSE;
|
|
RegCloseKey (hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
INTERNAL_(BOOL) IsOleCommand
|
|
(
|
|
ATOM aCmd,
|
|
WORD wType
|
|
)
|
|
{
|
|
if (wType == WT_SRVR) {
|
|
if ((aCmd == aStdCreateFromTemplate)
|
|
|| (aCmd == aStdCreate)
|
|
|| (aCmd == aStdOpen)
|
|
|| (aCmd == aStdEdit)
|
|
|| (aCmd == aStdShowItem)
|
|
|| (aCmd == aStdClose)
|
|
|| (aCmd == aStdExit))
|
|
return TRUE;
|
|
}
|
|
else {
|
|
if ((aCmd == aStdClose)
|
|
|| (aCmd == aStdDoVerbItem)
|
|
|| (aCmd == aStdShowItem))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
INTERNAL wFileBind
|
|
(LPOLESTR szFile,
|
|
LPUNKNOWN FAR* ppUnk)
|
|
{
|
|
HRESULT hresult = NOERROR;
|
|
LPBC pbc = NULL;
|
|
LPMONIKER pmk = NULL;
|
|
*ppUnk = NULL;
|
|
ErrRtnH (CreateBindCtx (0, &pbc));
|
|
ErrRtnH (CreateFileMoniker (szFile, &pmk));
|
|
ErrRtnH (pmk->BindToObject (pbc, NULL, IID_IUnknown, (LPLPVOID) ppUnk));
|
|
errRtn:
|
|
// AssertOutPtrIface(hresult, *ppUnk);
|
|
if (pbc)
|
|
pbc->Release();
|
|
if (pmk)
|
|
pmk->Release();
|
|
return hresult;
|
|
}
|
|
|
|
// SynchronousPostMessage
|
|
//
|
|
// Post a message and wait for the ack.
|
|
// (jasonful)
|
|
//
|
|
INTERNAL SynchronousPostMessage
|
|
(HWND hWndTo, // also who you expect the reply from
|
|
UINT wMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
#ifdef _MAC
|
|
#else
|
|
|
|
HRESULT hresult = NOERROR;
|
|
|
|
static unsigned iCounter;
|
|
|
|
|
|
HWND hWndFrom = (HWND) wParam;
|
|
|
|
|
|
|
|
RetZ (IsWindowValid(hWndFrom));
|
|
RetZ (IsWindowValid(hWndTo));
|
|
|
|
Assert (wMsg != WM_DDE_INITIATE); // can't check for positive ack.
|
|
|
|
RetZS (PostMessage (hWndTo, wMsg, wParam, lParam), RPC_E_SERVER_DIED);
|
|
|
|
MSG msg;
|
|
RetErr (wTimedGetMessage (&msg, hWndFrom, WM_DDE_ACK, WM_DDE_ACK));
|
|
Assert (msg.message == WM_DDE_ACK);
|
|
if (!( GET_WM_DDE_ACK_STATUS(msg.wParam,msg.lParam) & POSITIVE_ACK))
|
|
hresult = ResultFromScode (RPC_E_DDE_NACK);
|
|
if (msg.hwnd != hWndFrom)
|
|
hresult = ResultFromScode (RPC_E_DDE_UNEXP_MSG);
|
|
|
|
|
|
|
|
return hresult;
|
|
#endif _MAC
|
|
}
|
|
|
|
|
|
INTERNAL wFileIsRunning
|
|
(LPOLESTR szFile)
|
|
{
|
|
LPMONIKER pmk = NULL;
|
|
LPBINDCTX pbc=NULL;
|
|
HRESULT hresult;
|
|
|
|
RetErr (CreateBindCtx (0, &pbc));
|
|
ErrRtnH (CreateFileMoniker (szFile, &pmk));
|
|
hresult = pmk->IsRunning (pbc, NULL, NULL);
|
|
errRtn:
|
|
if (pbc)
|
|
pbc->Release();
|
|
if (pmk)
|
|
pmk->Release();
|
|
return hresult;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: IsFile
|
|
//
|
|
// Synopsis: Given a handle to an atom, determine if it is a file
|
|
//
|
|
// Effects: Attempts to get the files attributes. If there are no
|
|
// attributes, then the file doesn't exist.
|
|
//
|
|
// Arguments: [a] -- Atom for filename
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 5-03-94 kevinro Commented/cleaned
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
INTERNAL_ (BOOL) IsFile
|
|
(ATOM a, BOOL FAR* pfUnsavedDoc)
|
|
{
|
|
LPMONIKER pmk = NULL;
|
|
LPBC pbc = NULL;
|
|
LPRUNNINGOBJECTTABLE pROT=NULL;
|
|
|
|
WCHAR szFile [MAX_STR];
|
|
if (0==GlobalGetAtomName (a, szFile, MAX_STR))
|
|
return FALSE;
|
|
|
|
DWORD dwAttribs = GetFileAttributes(szFile);
|
|
|
|
/* flags prevent sharing violation*/
|
|
if (dwAttribs != 0xFFFFFFFF)
|
|
{
|
|
if (pfUnsavedDoc)
|
|
*pfUnsavedDoc = FALSE;
|
|
return TRUE;
|
|
}
|
|
// This will deal with unsaved documents in the ROT.
|
|
// We do NOT want to call pmk->IsRunning because if a 2.0 client called
|
|
// DdeIsRunning, we do not want call it here, because then we get stuck
|
|
// in an infinite loop. We only care about true 2.0 running objects.
|
|
|
|
|
|
//
|
|
// BUGBUG: KevinRo There is a function (GetPathFromRot) that could replace
|
|
// the following code sequence.
|
|
//
|
|
|
|
BOOL f= NOERROR==CreateBindCtx (0, &pbc) &&
|
|
NOERROR==CreateFileMoniker (szFile, &pmk) &&
|
|
NOERROR==pbc->GetRunningObjectTable (&pROT) &&
|
|
NOERROR==pROT->IsRunning (pmk) ;
|
|
if (pROT)
|
|
pROT->Release();
|
|
if (pmk)
|
|
pmk->Release();
|
|
if (pbc)
|
|
pbc->Release();
|
|
if (pfUnsavedDoc)
|
|
*pfUnsavedDoc = TRUE;
|
|
return f;
|
|
|
|
|
|
}
|
|
|
|
// wCompatibleClasses
|
|
//
|
|
// Determine if class "aClient" is Auto-Converted to class "aSrvr" or
|
|
// Treated-As class "aSrvr".
|
|
// (Does not check if aClient==aSrvr)
|
|
//
|
|
#pragma SEG(wCompatibleClasses)
|
|
INTERNAL wCompatibleClasses
|
|
(ATOM aClient,
|
|
ATOM aSrvr)
|
|
{
|
|
CLSID clsidClient, clsidSrvr, clsidTo;
|
|
HRESULT hresult;
|
|
RetZS (CLSIDFromAtom (aClient, &clsidClient), S_FALSE);
|
|
RetZS (CLSIDFromAtom (aSrvr, &clsidSrvr ), S_FALSE);
|
|
if (NOERROR==OleGetAutoConvert (clsidClient, &clsidTo)
|
|
&& clsidTo == clsidSrvr)
|
|
{
|
|
// aClient is Auto-Converted to aSrvr
|
|
return NOERROR;
|
|
}
|
|
hresult = CoGetTreatAsClass(clsidClient, &clsidTo);
|
|
if (hresult != NOERROR)
|
|
{
|
|
intrDebugOut((DEB_IERROR,
|
|
"wCompatibleClasses CoGetTreatAs returns %x\n",
|
|
hresult));
|
|
return(hresult);
|
|
}
|
|
|
|
if (clsidTo == clsidSrvr)
|
|
{
|
|
// aClient is Treated-As aSrvr
|
|
return NOERROR;
|
|
}
|
|
return ResultFromScode (S_FALSE); // not compatible
|
|
}
|
|
|
|
|
|
|
|
// wCreateStgAroundNative
|
|
//
|
|
// Build an OLE2 storage around 1.0 native data by putting it in
|
|
// stream "\1Ole10Native" and creating valid CompObj and OLE streams.
|
|
// Return the IStorage and the ILockBytes it is built on.
|
|
//
|
|
INTERNAL wCreateStgAroundNative
|
|
(HANDLE hNative,
|
|
ATOM aClassOld,
|
|
ATOM aClassNew,
|
|
CNVTYP cnvtyp,
|
|
ATOM aItem,
|
|
LPSTORAGE FAR* ppstg,
|
|
LPLOCKBYTES FAR* pplkbyt)
|
|
{
|
|
HRESULT hresult;
|
|
LPSTORAGE pstg = NULL;
|
|
LPLOCKBYTES plkbyt = NULL;
|
|
LPOLESTR szUserType = NULL;
|
|
WCHAR szClassOld [256];
|
|
CLSID clsid;
|
|
ATOM aClass;
|
|
*ppstg = NULL;
|
|
|
|
intrDebugOut((DEB_ITRACE,
|
|
"%p wCreateStgAroundNative(hNative=%x,aClassOld=%x"
|
|
",aClassNew=%x cnvtyp=%x,aItem=%x)\n",
|
|
0,hNative,aClassOld,aClassNew,cnvtyp,aItem));
|
|
|
|
// Create temporary docfile on our ILockBytes
|
|
ErrRtnH (CreateILockBytesOnHGlobal (NULL,/*fDeleteOnRelease*/TRUE,&plkbyt));
|
|
|
|
Assert (plkbyt);
|
|
|
|
ErrRtnH (StgCreateDocfileOnILockBytes (plkbyt, grfCreateStg, 0, &pstg));
|
|
|
|
RetZ (pstg);
|
|
Assert (NOERROR==StgIsStorageILockBytes(plkbyt));
|
|
|
|
aClass = (cnvtyp == cnvtypConvertTo)?aClassNew:aClassOld;
|
|
|
|
if (CLSIDFromAtom (aClass,(LPCLSID)&clsid) == FALSE)
|
|
{
|
|
hresult = REGDB_E_CLASSNOTREG;
|
|
goto errRtn;
|
|
}
|
|
|
|
ErrRtnH (WriteClassStg (pstg, clsid));
|
|
|
|
// The UserType always corresponds to the clsid.
|
|
ErrRtnH (OleRegGetUserType (clsid, USERCLASSTYPE_FULL, &szUserType));
|
|
|
|
// The format is always the 1.0 format (classname/progid)
|
|
ErrZS (GlobalGetAtomName (aClassOld, szClassOld, 256), E_UNEXPECTED);
|
|
|
|
ErrRtnH (WriteFmtUserTypeStg (pstg, RegisterClipboardFormat(szClassOld),
|
|
szUserType));
|
|
|
|
|
|
if (cnvtyp == cnvtypConvertTo)
|
|
{
|
|
// SetConvertStg also writes a complete default Ole Stream
|
|
ErrRtnH (SetConvertStg (pstg, TRUE));
|
|
}
|
|
else
|
|
{
|
|
ErrRtnH (WriteOleStg (pstg, NULL, (CLIPFORMAT)0, NULL));
|
|
}
|
|
ErrRtnH (StSave10NativeData (pstg, hNative, FALSE));
|
|
if (aItem)
|
|
{
|
|
ErrRtnH (StSave10ItemName (pstg, wAtomNameA (aItem)));
|
|
}
|
|
*ppstg = pstg;
|
|
*pplkbyt = plkbyt;
|
|
return NOERROR;
|
|
|
|
errRtn:
|
|
if (pstg)
|
|
pstg->Release();
|
|
if (plkbyt)
|
|
plkbyt->Release();
|
|
CoTaskMemFree(szUserType);
|
|
return hresult;
|
|
}
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
|
INTERNAL_ (BOOL) IsAtom (ATOM a)
|
|
{
|
|
WCHAR sz[256]= {0};
|
|
if (a < 0xc000)
|
|
return FALSE;
|
|
WORD cb=GlobalGetAtomName (a, sz, 256);
|
|
Assert (lstrlenW(sz) == (int) cb);
|
|
return cb>0 && cb < MAX_STR;
|
|
}
|
|
|
|
|
|
#include <limits.h>
|
|
#undef GlobalFree
|
|
|
|
|
|
|
|
|
|
INTERNAL_(HANDLE) wGlobalFree (HANDLE h)
|
|
{
|
|
LPVOID p;
|
|
Assert ((GlobalFlags(h) & GMEM_LOCKCOUNT)==0);
|
|
if (!(p=GlobalLock(h)))
|
|
{
|
|
Puts ("Cannot free handle");
|
|
Puth (h);
|
|
Putn();
|
|
AssertSz(0, "Invalid Handle\r\n");
|
|
}
|
|
Assert (!IsBadReadPtr (p, (UINT) min (UINT_MAX, GlobalSize(h))));
|
|
Assert (GlobalUnlock(h)==0);
|
|
Verify (!GlobalFree (h));
|
|
Puts ("FREEING ");
|
|
Puth (h);
|
|
Putn ();
|
|
return NULL; // success
|
|
}
|
|
|
|
|
|
|
|
#undef GlobalDeleteAtom
|
|
|
|
INTERNAL_(ATOM) wGlobalDeleteAtom (ATOM a)
|
|
{
|
|
WCHAR sz[256];
|
|
Assert (0 != GlobalGetAtomName (a, sz, 256));
|
|
Assert (0==GlobalDeleteAtom (a));
|
|
return (ATOM)0;
|
|
}
|
|
|
|
INTERNAL_(int) wCountChildren
|
|
(HWND h)
|
|
{
|
|
int c = 0;
|
|
HWND hwndChild = GetWindow (h, GW_CHILD);
|
|
while (hwndChild)
|
|
{
|
|
c++;
|
|
hwndChild = GetWindow (hwndChild, GW_HWNDNEXT);
|
|
}
|
|
return c;
|
|
}
|
|
|
|
|
|
#endif // _DEBUG
|