/****************************** 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 * curts created portable version for WIN16/32 * \***************************************************************************/ #include #include "cmacs.h" #include #include "ole.h" #include "dde.h" #include "srvr.h" #define KB_64 65536 extern ATOM aTrue; extern ATOM aFalse; #ifdef WIN16 extern BOOL bWLO; extern BOOL bWin30; #endif 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 ( LPSTR lpbuf, HANDLE hdata ){ int i; char ch; *lpbuf++ = '@'; for ( i = sizeof(HANDLE)*2 - 1; i >= 0; i--) { ch = (char) ((((DWORD_PTR)hdata) >> (i * 4)) & 0x0000000f); if(ch > '9') ch += 'A' - 10; else ch += '0'; *lpbuf++ = ch; } *lpbuf++ = '\0'; } void INTERNAL UtilMemCpy ( LPSTR lpdst, LPCSTR lpsrc, DWORD dwCount ){ UINT HUGE_T * hpdst; UINT HUGE_T * hpsrc; UINT FAR * lpwDst; UINT FAR * lpwSrc; DWORD words; DWORD bytes; bytes = dwCount % MAPVALUE(2,4); words = dwCount >> MAPVALUE(1,2); //* we compare DWORDS //* in the 32 bit version #ifdef WIN16 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 #else UNREFERENCED_PARAMETER(lpwDst); UNREFERENCED_PARAMETER(lpwSrc); #endif { hpdst = (UINT HUGE_T *) lpdst; hpsrc = (UINT HUGE_T *) lpsrc; for(;words--;) *hpdst++ = *hpsrc++; lpdst = (LPSTR) hpdst; lpsrc = (LPSTR) hpsrc; for(;bytes--;) *lpdst++ = *lpsrc++; } } //DuplicateData: Duplicates a given Global data handle. HANDLE INTERNAL DuplicateData ( HANDLE hdata ){ LPSTR lpsrc = NULL; LPSTR lpdst = NULL; HANDLE hdup = NULL; DWORD size; BOOL err = TRUE; if(!(lpsrc = GlobalLock (hdata))) return NULL; DEBUG_OUT (lpsrc, 0) hdup = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, (size = (DWORD)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 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 == '\0') return NULL; *lpstr++ = '\0'; // 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 != '\0') 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 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 ){ // !!! 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 == '\0') return NULL; *lpstr++ = '\0'; // 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 != '\0') 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 lpstr, UINT 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 == '\0') return 0; ch = *lpstr; *lpstr++ = '\0'; // set the end of command *lpAtom = GlobalFindAtom (lptemp); if (!IsOleCommand (*lpAtom, wType)) return NON_OLE_COMMAND; if (ch == '(') { ch = *lpstr++; if (ch == ')') { if (*lpstr++ != ']') return 0; } else { if (ch != '\"') return 0; } *lplpnextcmd = lpstr; return OLE_COMMAND; } // terminated by ']' if (*(*lplpnextcmd = lpstr)) // if no nul termination, then it is error. return 0; return OLE_COMMAND; } //MakeDataAtom: Creates a data atom from the item string //and the item data otions. ATOM INTERNAL MakeDataAtom ( ATOM aItem, int options ){ char buf[MAX_STR]; if (options == OLE_CHANGED) return DuplicateAtom (aItem); if (!aItem) buf[0] = '\0'; 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 (ATOM)0; } //DuplicateAtom: Duplicates an atom ATOM INTERNAL DuplicateAtom ( ATOM atom ){ char buf[MAX_STR]; Puts ("DuplicateAtom"); if (!atom) return (ATOM)0; GlobalGetAtomName (atom, buf, MAX_STR); return GlobalAddAtom (buf); } // MakeGlobal: makes global out of strings. // works only for << 64k HANDLE INTERNAL MakeGlobal ( LPCSTR 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 ){ 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 ){ if (!CheckPointer(lpdoc, WRITE_ACCESS)) return FALSE; if ((lpdoc->sig[0] == 'S') && (lpdoc->sig[1] == 'D')) return TRUE; return FALSE; } BOOL INTERNAL PostMessageToClientWithBlock ( HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM 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 hWnd, UINT wMsg, WPARAM wParam, LPARAM 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 ){ #define TASK_OFFSET 0x00FA LPSTR lptask; HANDLE htask; if (!IsWindow (hwnd)) return FALSE; #ifdef WIN32 UNREFERENCED_PARAMETER(lptask); UNREFERENCED_PARAMETER(htask); return TRUE;//HACK #endif #ifdef WIN16 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; } #endif return FALSE; } BOOL INTERNAL UtilQueryProtocol ( 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 ( ATOM aCmd, UINT 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; }