598 lines
12 KiB
C
598 lines
12 KiB
C
|
/****************************** Module Header ******************************\
|
|||
|
* Module Name: utils.c
|
|||
|
*
|
|||
|
* Purpose: Conatains all the utility routines
|
|||
|
*
|
|||
|
* Created: 1990
|
|||
|
*
|
|||
|
* Copyright (c) 1990, 1991 Microsoft Corporation
|
|||
|
*
|
|||
|
* History:
|
|||
|
* Raor, Srinik (../../1990) Designed and coded
|
|||
|
*
|
|||
|
\***************************************************************************/
|
|||
|
|
|||
|
#include <windows.h>
|
|||
|
#include "cmacs.h"
|
|||
|
#include <shellapi.h>
|
|||
|
|
|||
|
#include "ole.h"
|
|||
|
#include "dde.h"
|
|||
|
#include "srvr.h"
|
|||
|
|
|||
|
|
|||
|
#ifndef HUGE
|
|||
|
#define HUGE huge
|
|||
|
#endif
|
|||
|
|
|||
|
#define KB_64 65536
|
|||
|
|
|||
|
extern ATOM aTrue;
|
|||
|
extern ATOM aFalse;
|
|||
|
extern BOOL bWLO;
|
|||
|
extern BOOL bWin30;
|
|||
|
|
|||
|
extern ATOM aStdCreateFromTemplate;
|
|||
|
extern ATOM aStdCreate;
|
|||
|
extern ATOM aStdOpen;
|
|||
|
extern ATOM aStdEdit;
|
|||
|
extern ATOM aStdShowItem;
|
|||
|
extern ATOM aStdClose;
|
|||
|
extern ATOM aStdExit;
|
|||
|
extern ATOM aStdDoVerbItem;
|
|||
|
|
|||
|
extern BOOL (FAR PASCAL *lpfnIsTask) (HANDLE);
|
|||
|
|
|||
|
// MapToHexStr: Converts WORD to hex string.
|
|||
|
void INTERNAL MapToHexStr (lpbuf, hdata)
|
|||
|
LPSTR lpbuf;
|
|||
|
HANDLE hdata;
|
|||
|
{
|
|||
|
int i;
|
|||
|
char ch;
|
|||
|
|
|||
|
*lpbuf++ = '@';
|
|||
|
for ( i = 3; i >= 0; i--) {
|
|||
|
|
|||
|
ch = (char) ((((WORD)hdata) >> (i * 4)) & 0x000f);
|
|||
|
if(ch > '9')
|
|||
|
ch += 'A' - 10;
|
|||
|
else
|
|||
|
ch += '0';
|
|||
|
|
|||
|
*lpbuf++ = ch;
|
|||
|
}
|
|||
|
|
|||
|
*lpbuf++ = NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void INTERNAL UtilMemCpy (lpdst, lpsrc, dwCount)
|
|||
|
LPSTR lpdst;
|
|||
|
LPSTR lpsrc;
|
|||
|
DWORD dwCount;
|
|||
|
{
|
|||
|
WORD HUGE * hpdst;
|
|||
|
WORD HUGE * hpsrc;
|
|||
|
WORD FAR * lpwDst;
|
|||
|
WORD FAR * lpwSrc;
|
|||
|
DWORD words;
|
|||
|
DWORD bytes;
|
|||
|
|
|||
|
bytes = dwCount % 2;
|
|||
|
words = dwCount >> 1; //* we should compare DWORDS
|
|||
|
//* in the 32 bit version
|
|||
|
if (dwCount <= KB_64) {
|
|||
|
lpwDst = (WORD FAR *) lpdst;
|
|||
|
lpwSrc = (WORD FAR *) lpsrc;
|
|||
|
|
|||
|
while (words--)
|
|||
|
*lpwDst++ = *lpwSrc++;
|
|||
|
|
|||
|
if (bytes)
|
|||
|
* (char FAR *) lpwDst = * (char FAR *) lpwSrc;
|
|||
|
}
|
|||
|
else {
|
|||
|
hpdst = (WORD HUGE *) lpdst;
|
|||
|
hpsrc = (WORD HUGE *) lpsrc;
|
|||
|
|
|||
|
while (words--)
|
|||
|
*hpdst++ = *hpsrc++;
|
|||
|
|
|||
|
if (bytes)
|
|||
|
*(char HUGE *) hpdst = * (char HUGE *) hpsrc;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//DuplicateData: Duplicates a given Global data handle.
|
|||
|
HANDLE INTERNAL DuplicateData (hdata)
|
|||
|
HANDLE hdata;
|
|||
|
{
|
|||
|
LPSTR lpsrc = NULL;
|
|||
|
LPSTR lpdst = NULL;
|
|||
|
HANDLE hdup = NULL;
|
|||
|
DWORD size;
|
|||
|
BOOL err = TRUE;
|
|||
|
|
|||
|
if(!(lpsrc = GlobalLock (hdata)))
|
|||
|
return NULL;
|
|||
|
|
|||
|
hdup = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, (size = GlobalSize(hdata)));
|
|||
|
|
|||
|
if(!(lpdst = GlobalLock (hdup)))
|
|||
|
goto errRtn;;
|
|||
|
|
|||
|
err = FALSE;
|
|||
|
UtilMemCpy (lpdst, lpsrc, size);
|
|||
|
|
|||
|
errRtn:
|
|||
|
if(lpsrc)
|
|||
|
GlobalUnlock (hdata);
|
|||
|
|
|||
|
if(lpdst)
|
|||
|
GlobalUnlock (hdup);
|
|||
|
|
|||
|
if (err && hdup)
|
|||
|
GlobalFree (hdup);
|
|||
|
|
|||
|
return hdup;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//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.
|
|||
|
|
|||
|
LPSTR INTERNAL ScanBoolArg (lpstr, lpflag)
|
|||
|
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 == ',')))
|
|||
|
{ //[J1]
|
|||
|
#if defined(FE_SB) //[J1]
|
|||
|
lpstr = AnsiNext( lpstr ); //[J1]
|
|||
|
#else //[J1]
|
|||
|
lpstr++;
|
|||
|
#endif //[J1]
|
|||
|
} //[J1]
|
|||
|
|
|||
|
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 = GlobalFindAtom (lpbool);
|
|||
|
if (aShow == aTrue)
|
|||
|
*lpflag = TRUE;
|
|||
|
|
|||
|
else {
|
|||
|
if (aShow ==aFalse)
|
|||
|
*lpflag = FALSE;
|
|||
|
else
|
|||
|
return NULL;;
|
|||
|
}
|
|||
|
return lpstr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//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.
|
|||
|
|
|||
|
LPSTR INTERNAL ScanNumArg (lpstr, lpnum)
|
|||
|
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.
|
|||
|
|
|||
|
LPSTR INTERNAL ScanArg (lpstr)
|
|||
|
LPSTR lpstr;
|
|||
|
{
|
|||
|
|
|||
|
|
|||
|
// !!! These routines does not take care of quoted quotes.
|
|||
|
|
|||
|
// first char should be quote.
|
|||
|
|
|||
|
if (*(lpstr-1) != '\"')
|
|||
|
return NULL;
|
|||
|
|
|||
|
while(*lpstr && *lpstr != '\"')
|
|||
|
{ //[J1]
|
|||
|
#if defined(FE_SB) //[J1]
|
|||
|
lpstr = AnsiNext( lpstr ); //[J1]
|
|||
|
#else //[J1]
|
|||
|
lpstr++;
|
|||
|
#endif //[J1]
|
|||
|
} //[J1]
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
WORD INTERNAL ScanCommand (lpstr, wType, lplpnextcmd, lpAtom)
|
|||
|
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 == ']')))
|
|||
|
{ //[J1]
|
|||
|
#if defined(FE_SB) //[J1]
|
|||
|
lpstr = AnsiNext( lpstr ); //[J1]
|
|||
|
#else //[J1]
|
|||
|
lpstr++;
|
|||
|
#endif //[J1]
|
|||
|
} //[J1]
|
|||
|
|
|||
|
if(*lpstr == NULL)
|
|||
|
return NULL;
|
|||
|
|
|||
|
ch = *lpstr;
|
|||
|
*lpstr++ = NULL; // set the end of command
|
|||
|
|
|||
|
*lpAtom = GlobalFindAtom (lptemp);
|
|||
|
|
|||
|
if (!IsOleCommand (*lpAtom, wType))
|
|||
|
return NON_OLE_COMMAND;
|
|||
|
|
|||
|
if (ch == '(') {
|
|||
|
|
|||
|
#if defined(FE_SB) //[J1]
|
|||
|
ch = *lpstr; //[J1]
|
|||
|
lpstr = AnsiNext( lpstr ); //[J1]
|
|||
|
#else //[J1]
|
|||
|
ch = *lpstr++;
|
|||
|
#endif //[J1]
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
ATOM INTERNAL MakeDataAtom (aItem, options)
|
|||
|
ATOM aItem;
|
|||
|
int options;
|
|||
|
{
|
|||
|
char buf[MAX_STR];
|
|||
|
|
|||
|
if (options == OLE_CHANGED)
|
|||
|
return DuplicateAtom (aItem);
|
|||
|
|
|||
|
if (!aItem)
|
|||
|
buf[0] = NULL;
|
|||
|
else
|
|||
|
GlobalGetAtomName (aItem, (LPSTR)buf, MAX_STR);
|
|||
|
|
|||
|
if (options == OLE_CLOSED)
|
|||
|
lstrcat ((LPSTR)buf, (LPSTR) "/Close");
|
|||
|
else {
|
|||
|
if (options == OLE_SAVED)
|
|||
|
lstrcat ((LPSTR)buf, (LPSTR) "/Save");
|
|||
|
}
|
|||
|
|
|||
|
if (buf[0])
|
|||
|
return GlobalAddAtom ((LPSTR)buf);
|
|||
|
else
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
//DuplicateAtom: Duplicates an atom
|
|||
|
ATOM INTERNAL DuplicateAtom (atom)
|
|||
|
ATOM atom;
|
|||
|
{
|
|||
|
char buf[MAX_STR];
|
|||
|
|
|||
|
Puts ("DuplicateAtom");
|
|||
|
|
|||
|
if (!atom)
|
|||
|
return NULL;
|
|||
|
|
|||
|
GlobalGetAtomName (atom, buf, MAX_STR);
|
|||
|
return GlobalAddAtom (buf);
|
|||
|
}
|
|||
|
|
|||
|
// MakeGlobal: makes global out of strings.
|
|||
|
// works only for << 64k
|
|||
|
|
|||
|
HANDLE INTERNAL MakeGlobal (lpstr)
|
|||
|
LPSTR lpstr;
|
|||
|
{
|
|||
|
|
|||
|
int len = 0;
|
|||
|
HANDLE hdata = NULL;
|
|||
|
LPSTR lpdata = NULL;
|
|||
|
|
|||
|
len = lstrlen (lpstr) + 1;
|
|||
|
|
|||
|
hdata = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, len);
|
|||
|
if (hdata == NULL || (lpdata = (LPSTR) GlobalLock (hdata)) == NULL)
|
|||
|
goto errRtn;
|
|||
|
|
|||
|
|
|||
|
UtilMemCpy (lpdata, lpstr, (DWORD)len);
|
|||
|
GlobalUnlock (hdata);
|
|||
|
return hdata;
|
|||
|
|
|||
|
errRtn:
|
|||
|
|
|||
|
if (lpdata)
|
|||
|
GlobalUnlock (hdata);
|
|||
|
|
|||
|
|
|||
|
if (hdata)
|
|||
|
GlobalFree (hdata);
|
|||
|
|
|||
|
return NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL INTERNAL CheckServer (lpsrvr)
|
|||
|
LPSRVR lpsrvr;
|
|||
|
{
|
|||
|
if (!CheckPointer(lpsrvr, WRITE_ACCESS))
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if ((lpsrvr->sig[0] == 'S') && (lpsrvr->sig[1] == 'R'))
|
|||
|
return TRUE;
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL INTERNAL CheckServerDoc (lpdoc)
|
|||
|
LPDOC lpdoc;
|
|||
|
{
|
|||
|
if (!CheckPointer(lpdoc, WRITE_ACCESS))
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if ((lpdoc->sig[0] == 'S') && (lpdoc->sig[1] == 'D'))
|
|||
|
return TRUE;
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL INTERNAL PostMessageToClientWithBlock (hWnd, wMsg, wParam, lParam)
|
|||
|
HWND hWnd;
|
|||
|
WORD wMsg;
|
|||
|
WORD wParam;
|
|||
|
DWORD lParam;
|
|||
|
{
|
|||
|
if (!IsWindowValid (hWnd)) {
|
|||
|
ASSERT(FALSE, "Client's window is missing");
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (IsBlockQueueEmpty ((HWND)wParam) && PostMessage (hWnd, wMsg, wParam, lParam))
|
|||
|
return TRUE;
|
|||
|
|
|||
|
BlockPostMsg (hWnd, wMsg, wParam, lParam);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL INTERNAL PostMessageToClient (hWnd, wMsg, wParam, lParam)
|
|||
|
HWND hWnd;
|
|||
|
WORD wMsg;
|
|||
|
WORD wParam;
|
|||
|
DWORD lParam;
|
|||
|
{
|
|||
|
if (!IsWindowValid (hWnd)) {
|
|||
|
ASSERT(FALSE, "Client's window is missing");
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (IsBlockQueueEmpty ((HWND)wParam) && PostMessage (hWnd, wMsg, wParam, lParam))
|
|||
|
return TRUE;
|
|||
|
|
|||
|
BlockPostMsg (hWnd, wMsg, wParam, lParam);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL INTERNAL IsWindowValid (hwnd)
|
|||
|
HWND hwnd;
|
|||
|
{
|
|||
|
|
|||
|
#define TASK_OFFSET 0x00FA
|
|||
|
|
|||
|
LPSTR lptask;
|
|||
|
HANDLE htask;
|
|||
|
|
|||
|
if (!IsWindow (hwnd))
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if (bWLO)
|
|||
|
return TRUE;
|
|||
|
|
|||
|
// now get the task handle and find out it is valid.
|
|||
|
htask = GetWindowTask (hwnd);
|
|||
|
|
|||
|
if (bWin30 || !lpfnIsTask) {
|
|||
|
lptask = (LPSTR)(MAKELONG (TASK_OFFSET, htask));
|
|||
|
|
|||
|
if (!CheckPointer(lptask, READ_ACCESS))
|
|||
|
return FALSE;
|
|||
|
|
|||
|
// now check for the signature bytes of task block in kernel
|
|||
|
if (*lptask++ == 'T' && *lptask == 'D')
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
else {
|
|||
|
// From win31 onwards the API IsTask() can be used for task validation
|
|||
|
if ((*lpfnIsTask)(htask))
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL INTERNAL UtilQueryProtocol (aClass, lpprotocol)
|
|||
|
ATOM aClass;
|
|||
|
LPSTR lpprotocol;
|
|||
|
{
|
|||
|
HKEY hKey;
|
|||
|
char key[MAX_STR];
|
|||
|
char class[MAX_STR];
|
|||
|
|
|||
|
if (!aClass)
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if (!GlobalGetAtomName (aClass, class, MAX_STR))
|
|||
|
return FALSE;
|
|||
|
|
|||
|
lstrcpy (key, class);
|
|||
|
lstrcat (key, "\\protocol\\");
|
|||
|
lstrcat (key, lpprotocol);
|
|||
|
lstrcat (key, "\\server");
|
|||
|
|
|||
|
if (RegOpenKey (HKEY_CLASSES_ROOT, key, &hKey))
|
|||
|
return FALSE;
|
|||
|
|
|||
|
RegCloseKey (hKey);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL INTERNAL IsOleCommand (aCmd, wType)
|
|||
|
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;
|
|||
|
}
|
|||
|
|