/****************************** 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 #include "cmacs.h" #include #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; }