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;
|
||
}
|
||
|