/****************************** Module Header ******************************\ * Module Name: Doc.c Document Main module * * Purpose: Includes All the document communication related routines. * * Created: Oct 1990. * * Copyright (c) 1990, 1991 Microsoft Corporation * * History: * Raor (../10/1990) Designed, coded * curts created portable version for WIN16/32 * \***************************************************************************/ #include "windows.h" #include "cmacs.h" #include "ole.h" #include "dde.h" #include "srvr.h" extern ATOM cfBinary; extern ATOM aStdClose; extern ATOM aStdShowItem; extern ATOM aStdDoVerbItem; extern ATOM aStdDocName; extern ATOM aTrue; extern ATOM aFalse; extern FARPROC lpTerminateDocClients; extern FARPROC lpSendRenameMsg; extern FARPROC lpFindItemWnd; extern FARPROC lpEnumForTerminate; extern HANDLE hdllInst; extern HANDLE hddeRename; extern HWND hwndRename; extern BOOL fAdviseSaveDoc; // ### Do we have to create a seperate window for each doc conversation. // EDF thinks so. /***************************** Public Function ****************************\ * * OLESTATUS FAR PASCAL OleRegisterServerDoc (lhsrvr, lpdocname, lpoledoc, lplhdoc) * * OleRegisterServerDoc: Registers the Document with the server lib. * * Parameters: * 1. Server long handle(server with which the document should * be registered) * 2. Document name. * 3. Handle to the doc of the server app (private to the server app). * 4. Ptr for returning the Doc handle of the lib (private to the lib). * * return values: * returns OLE_OK if the server is successfully registered . * else returns the corresponding error. * * History: * Raor: Wrote it, \***************************************************************************/ OLESTATUS FAR PASCAL OleRegisterServerDoc ( LHSRVR lhsrvr, // handle we passed back as part of registration. LPCSTR lpdocname, // document name LPOLESERVERDOC lpoledoc, // Private doc handle of the server app. LHDOC FAR * lplhdoc // where we will be passing our doc private handle ){ LPSRVR lpsrvr = NULL; LPDOC lpdoc = NULL; HANDLE hdoc = NULL; Puts ("OleRegisterServerDoc"); if (!CheckServer (lpsrvr = (LPSRVR)lhsrvr)) return OLE_ERROR_HANDLE; // server's termination has already started. if (lpsrvr->bTerminate) return OLE_ERROR_TERMINATE; PROBE_READ(lpdocname); PROBE_WRITE(lplhdoc); // we are using the null from inside the server lib if (lpoledoc) PROBE_WRITE(lpoledoc); hdoc = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_DDESHARE, sizeof (DOC)); if (!(hdoc && (lpdoc = (LPDOC)GlobalLock (hdoc)))) goto errReturn; // set the signature, handle and the doc atom. lpdoc->sig[0] = 'S'; lpdoc->sig[1] = 'D'; lpdoc->hdoc = hdoc; lpdoc->aDoc = GlobalAddAtom (lpdocname); lpdoc->lpoledoc = lpoledoc; if (!(lpdoc->hwnd = CreateWindow ("DocWndClass", "Doc", WS_CHILD,0,0,0,0,lpsrvr->hwnd,NULL, hdllInst, NULL))) goto errReturn; // save the ptr to the struct in the window. SetWindowLongPtr (lpdoc->hwnd, 0, (LONG_PTR)lpdoc); SetWindowWord (lpdoc->hwnd, WW_LE, WC_LE); SetWindowLongPtr (lpdoc->hwnd, WW_HANDLE, GetWindowLongPtr(lpsrvr->hwnd, WW_HANDLE)); *lplhdoc = (LONG_PTR)lpdoc; return OLE_OK; errReturn: if (lpdoc){ if (lpdoc->hwnd) DestroyWindow (lpsrvr->hwnd); if (lpdoc->aDoc) GlobalDeleteAtom (lpdoc->aDoc); GlobalUnlock(hdoc); } if (hdoc) GlobalFree (hdoc); return OLE_ERROR_MEMORY; } /***************************** Public Function ****************************\ * OLESTATUS FAR PASCAL OleRevokeServerDoc (lhdoc) * * OleRevokeServerDoc: Unregisters the document which has been registered. * * Parameters: * 1. DLL Doc handle. * * return values: * returns OLE_OK if the document is successfully unregisterd. * ( It is Ok for the app to free the associated space). * If the unregistration is intiated, returns OLE_STARTED. * Calls the Doc class release entry point when the doc * can be released. App should wait till the Release is called * * History: * Raor: Wrote it, \***************************************************************************/ OLESTATUS FAR PASCAL OleRevokeServerDoc ( LHDOC lhdoc ){ HWND hwndSrvr; LPSRVR lpsrvr; HWND hwndDoc; LPDOC lpdoc; Puts ("OleRevokeServerDoc"); if (!CheckServerDoc (lpdoc = (LPDOC)lhdoc)) return OLE_ERROR_HANDLE; if (lpdoc->bTerminate && lpdoc->termNo) return OLE_WAIT_FOR_RELEASE; // ### this code is very similar to the srvr code. // we should optimize. hwndDoc = lpdoc->hwnd; #ifdef FIREWALLS ASSERT (hwndDoc, "No doc window") #endif hwndSrvr = GetParent (hwndDoc); lpsrvr = (LPSRVR) GetWindowLongPtr (hwndSrvr, 0); #ifdef FIREWALLS ASSERT (hwndSrvr, "No srvr window") ASSERT (lpsrvr, "No srvr structure") #endif // delete all the items(objects) for this doc DeleteAllItems (lpdoc->hwnd); // we are terminating. lpdoc->bTerminate = TRUE; lpdoc->termNo = 0; // send ack if Revoke is done as a result of StdClose if (lpdoc->fAckClose) { // Post the acknowledge to the client LPARAM lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK, 0x8000, lpdoc->hDataClose); if (!PostMessageToClient (lpdoc->hwndClose, WM_DDE_ACK, (WPARAM)lpdoc->hwnd,lparamNew)) { // if the window died or post failed, delete the atom. GlobalFree (lpdoc->hDataClose); DDEFREE(WM_DDE_ACK,lparamNew); } } // Post termination for each of the doc clients. EnumProps(hwndDoc, (PROPENUMPROC)lpTerminateDocClients); // post all the messages with yield which have been collected in enum // UnblockPostMsgs (hwndDoc, TRUE); #ifdef WAIT_DDE if (lpdoc->termNo) WaitForTerminate((LPSRVR)lpdoc); #endif return ReleaseDoc (lpdoc); } /***************************** Public Function ****************************\ * OLESTATUS FAR PASCAL OleRenameServerDoc (lhdoc, lpNewName) * * OleRenameServerDoc: Changes the name of the document * * Parameters: * 1. DLL Doc handle. * 2. New name for document * * return values: * returns OLE_OK if the document is successfully renamed * * History: * Srinik: Wrote it, \***************************************************************************/ OLESTATUS FAR PASCAL OleRenameServerDoc ( LHDOC lhdoc, LPCSTR lpNewName ){ LPDOC lpdoc; OLESTATUS retVal = OLE_OK; HANDLE hdata; HWND hStdWnd; if (!CheckServerDoc (lpdoc = (LPDOC)lhdoc)) return OLE_ERROR_HANDLE; PROBE_READ(lpNewName); if (!(hdata = MakeGlobal (lpNewName))) return OLE_ERROR_MEMORY; if (lpdoc->aDoc) GlobalDeleteAtom (lpdoc->aDoc); lpdoc->aDoc = GlobalAddAtom (lpNewName); // if StdDocName item is present send rename to relevant clients if (hStdWnd = SearchItem (lpdoc, (LPSTR) MAKEINTATOM(aStdDocName))) { if (!MakeDDEData (hdata, cfBinary, (LPHANDLE)&hddeRename,FALSE)) retVal = OLE_ERROR_MEMORY; else { EnumProps(hStdWnd, (PROPENUMPROC)lpSendRenameMsg); // post all the messages with yield which have been collected in enum // UnblockPostMsgs (hStdWnd, FALSE); GlobalFree (hddeRename); } } hwndRename = hStdWnd; // Post termination for each of the doc clients. EnumProps(lpdoc->hwnd, (PROPENUMPROC)lpEnumForTerminate); // post all the messages with yield which have been collected in enum // UnblockPostMsgs (lpdoc->hwnd, TRUE); // If it was an embedded object, from now on it won't be lpdoc->fEmbed = FALSE; if (!hStdWnd || retVal != OLE_OK) GlobalFree(hdata); // Do link manager stuff return retVal; } /***************************** Public Function ****************************\ * OLESTATUS FAR PASCAL OleSavedServerDoc (lhdoc) * * OleSavedServerDoc: Changes the name of the document * * Parameters: * 1. DLL Doc handle. * * return values: * returns OLE_OK if the link manager is successfully notified * * History: * Srinik: Wrote it, \***************************************************************************/ OLESTATUS FAR PASCAL OleSavedServerDoc ( LHDOC lhdoc ){ LPDOC lpdoc; if (!CheckServerDoc (lpdoc = (LPDOC)lhdoc)) return OLE_ERROR_HANDLE; fAdviseSaveDoc = TRUE; EnumChildWindows (lpdoc->hwnd, (WNDENUMPROC)lpFindItemWnd, MAKELONG (NULL, ITEM_SAVED)); if (lpdoc->fEmbed && !fAdviseSaveDoc) return OLE_ERROR_CANT_UPDATE_CLIENT; return OLE_OK; } /***************************** Public Function ****************************\ * OLESTATUS FAR PASCAL OleRevertServerDoc (lhdoc) * * OleRevertServerDoc: Changes the name of the document * * Parameters: * 1. DLL Doc handle. * * return values: * returns OLE_OK if the link manager has been successfully informed * * History: * Srinik: Wrote it, \***************************************************************************/ OLESTATUS FAR PASCAL OleRevertServerDoc ( LHDOC lhdoc ){ LPDOC lpdoc; if (!CheckServerDoc (lpdoc = (LPDOC)lhdoc)) return OLE_ERROR_HANDLE; return OLE_OK; } // TerminateDocClients: Call back for the document window for // enumerating all the clients. Posts terminate for each of // the clients. BOOL FAR PASCAL TerminateDocClients ( HWND hwnd, LPSTR lpstr, HANDLE hdata ){ LPDOC lpdoc; UNREFERENCED_PARAMETER(lpstr); lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0); if (IsWindowValid ((HWND)hdata)){ lpdoc->termNo++; // irrespective of the post, incremet the count, so // that client does not die. PostMessageToClientWithBlock ((HWND)hdata, WM_DDE_TERMINATE, (WPARAM)hwnd, (LPARAM)0); } else ASSERT(FALSE, "TERMINATE: Client's Doc channel is missing"); return TRUE; } // ReleaseDoc: If there are no more matching terminates pending // Call the server for its release. (Server might be waiting for the // docs to be terminated. Called thru OleRevokeServer). int INTERNAL ReleaseDoc ( LPDOC lpdoc ){ HWND hwndSrvr; HANDLE hdoc; LPSRVR lpsrvr; // release srvr is called only when everything is // cleaned and srvr app can post WM_QUIT. if (lpdoc->bTerminate && lpdoc->termNo) return OLE_WAIT_FOR_RELEASE; // Call Release for the app to release its space. if (lpdoc->lpoledoc){ #ifdef FIREWALLS if (!CheckPointer (lpdoc->lpoledoc, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLESERVERDOC") else if (!CheckPointer (lpdoc->lpoledoc->lpvtbl, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLESERVERDOCVTBL") else ASSERT (lpdoc->lpoledoc->lpvtbl->Release, "Invalid pointer to Release method") #endif (*lpdoc->lpoledoc->lpvtbl->Release) (lpdoc->lpoledoc); } if (lpdoc->aDoc) { GlobalDeleteAtom (lpdoc->aDoc); lpdoc->aDoc = (ATOM)0; } hwndSrvr = GetParent (lpdoc->hwnd); DestroyWindow (lpdoc->hwnd); lpsrvr = (LPSRVR)GetWindowLongPtr (hwndSrvr, 0); // if the server is waiting for us, inform the server // we are done if (!lpsrvr->bTerminate) { // if we are not in terminate mode, then send advise to the server // if server can be revoked. raor (04/09) if (QueryRelease (lpsrvr)){ #ifdef FIREWALLS if (!CheckPointer (lpsrvr->lpolesrvr, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLESERVER") else if (!CheckPointer (lpsrvr->lpolesrvr->lpvtbl, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLESERVERVTBL") else ASSERT (lpsrvr->lpolesrvr->lpvtbl->Release, "Invalid pointer to Release method") #endif (*lpsrvr->lpolesrvr->lpvtbl->Release) (lpsrvr->lpolesrvr); } } else ReleaseSrvr (lpsrvr); GlobalUnlock (hdoc = lpdoc->hdoc); GlobalFree (hdoc); return OLE_OK; } //RevokeAllDocs : revokes all the documents attached to a given //server. int INTERNAL RevokeAllDocs ( LPSRVR lpsrvr ){ HWND hwnd; HWND hwndnext; hwnd = GetWindow (lpsrvr->hwnd, GW_CHILD); // Go thru each of the child windows and revoke the corresponding // document. Doc windows are child windows for the server window. while (hwnd){ // sequence is important hwndnext = GetWindow (hwnd, GW_HWNDNEXT); OleRevokeServerDoc ((LHDOC)GetWindowLongPtr (hwnd, 0)); hwnd = hwndnext; } return OLE_OK; } // FindDoc: Given a document, searches for the document // in the given server document tree. returns true if the // document is available. LPDOC INTERNAL FindDoc ( LPSRVR lpsrvr, LPSTR lpdocname ){ ATOM aDoc; HWND hwnd; LPDOC lpdoc; aDoc = (ATOM)GlobalFindAtom (lpdocname); hwnd = GetWindow (lpsrvr->hwnd, GW_CHILD); while (hwnd){ lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0); if (lpdoc->aDoc == aDoc) return lpdoc; hwnd = GetWindow (hwnd, GW_HWNDNEXT); } return NULL; } // DocWndProc: document window procedure. // ### We might be able to merge this code with // the server window proc. LRESULT FAR PASCAL DocWndProc ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ){ LPDOC lpdoc; WORD status = 0; BOOL fack; HANDLE hdata = NULL; OLESTATUS retval; LPSRVR lpsrvr; #ifdef FIREWALLS HWND hwndClient; #endif if (AddMessage (hwnd, msg, wParam, lParam, (int)WT_DOC)) return 0L; lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0); switch (msg){ case WM_CREATE: DEBUG_OUT ("doc create window", 0) break; case WM_DDE_INITIATE: DEBUG_OUT ("doc: DDE init",0); if (lpdoc->bTerminate){ DEBUG_OUT ("doc: No action due to termination process",0) break; } // if we are the documnet then respond. if (! (lpdoc->aDoc == (ATOM)(HIWORD(lParam)))) break; // We can enterain this client. Put this window in the client list // and acknowledge the initiate. if (!AddClient (hwnd, (HWND)wParam, (HWND)wParam)) break; lpdoc->cClients++; lpsrvr = (LPSRVR) GetWindowLongPtr (GetParent(lpdoc->hwnd), 0); lpsrvr->bnoRelease = FALSE; // post the acknowledge DuplicateAtom (LOWORD(lParam)); DuplicateAtom (HIWORD(lParam)); SendMessage ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lParam); break; case WM_DDE_EXECUTE: { HANDLE hData = GET_WM_DDE_EXECUTE_HDATA(wParam,lParam); DEBUG_OUT ("doc: execute", 0) #ifdef FIREWALLS // find the client in the client list. hwndClient = FindClient (lpdoc->hwnd, (HWND)wParam); ASSERT (hwndClient, "Client is missing from the server") #endif // Are we terminating if (lpdoc->bTerminate || !IsWindowValid ((HWND)wParam)) { DEBUG_OUT ("doc: execute after terminate posted",0) // !!! are we supposed to free the data GlobalFree (hData); break; } retval = DocExecute (hwnd, hData, (HWND)wParam); SET_MSG_STATUS (retval, status); #ifdef OLD // if we posted the terminate because of execute, do not send // ack. if (lpdoc->bTerminate) { // !!! We got close but, we are posting the // the terminate. Excel does not complain about // this. But powerpoint complains. #ifdef POWERPNT_BUG GlobalFree (hData); #endif break; } #endif if (!lpdoc->bTerminate) { // Post the acknowledge to the client LPARAM lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK, status, hData); if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lparamNew)){ // the window either died or post failed, delete the data GlobalFree (hData); DDEFREE(WM_DDE_ACK,lparamNew); } } break; } case WM_DDE_TERMINATE: DEBUG_OUT ("doc: DDE terminate",0) #ifdef FIREWALLS // find the client in the client list. hwndClient = FindClient (lpdoc->hwnd,(HWND)wParam); ASSERT(hwndClient || lpdoc->termNo, "Client is missing from the server") #endif // We do not need this client any more. Delete him from the // client list. DeleteClient (lpdoc->hwnd, (HWND)wParam); lpdoc->cClients--; if (lpdoc->bTerminate){ lpsrvr = (LPSRVR) GetWindowLongPtr (GetParent(lpdoc->hwnd), 0); if (!--lpdoc->termNo) // Release this Doc and may be the server also // if the server is waiting to be released also. ReleaseDoc (lpdoc); } else { if (lpdoc->termNo == 0){ // If client intiated the terminate. Post matching terminate PostMessageToClient ((HWND)wParam, WM_DDE_TERMINATE, (WPARAM)hwnd, (LPARAM)0); } else lpdoc->termNo--; //Client initiated the termination. So, we shoudl take him // out from any of our items client lists. DeleteFromItemsList (lpdoc->hwnd, (HWND)wParam); lpsrvr = (LPSRVR)GetWindowLongPtr (GetParent (lpdoc->hwnd), 0); if (QueryRelease (lpsrvr)){ #ifdef FIREWALLS if (!CheckPointer (lpsrvr->lpolesrvr, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLESERVER") else if (!CheckPointer (lpsrvr->lpolesrvr->lpvtbl, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLESERVERVTBL") else ASSERT (lpsrvr->lpolesrvr->lpvtbl->Release, "Invalid pointer to Release method") #endif (*lpsrvr->lpolesrvr->lpvtbl->Release) (lpsrvr->lpolesrvr); } } break; case WM_DESTROY: DEBUG_OUT ("doc: Destroy window",0) break; case WM_DDE_POKE: { int iStdItem; LPARAM lparamNew; ATOM aItem = GET_WM_DDE_POKE_ITEM(wParam,lParam); HANDLE hData = GET_WM_DDE_POKE_HDATA(wParam,lParam); DEBUG_OUT ("doc: Poke", 0) if (lpdoc->bTerminate || !IsWindowValid ((HWND) wParam)) { // we are getting pke message after we have posted the // the termination or the client got deleted. /* * This path is valid for POKE, DATA, and ADVISE transactions * only! */ FreePokeData (GET_WM_DDE_POKE_HDATA(wParam,lParam)); #ifdef OLD GlobalFree (GET_WM_DDE_POKE_HDATA(wParam,lParam)); #endif // !!! Are we supposed to delete the atoms also. PokeErr1: /* * This path is valid for POKE, DATA, ADVISE and * ACK transactions only! */ if (GET_WM_DDE_POKE_ITEM(wParam,lParam)) GlobalDeleteAtom (GET_WM_DDE_POKE_ITEM(wParam,lParam)); DDEFREE(msg,lParam); break; } if (iStdItem = GetStdItemIndex (aItem)) retval = PokeStdItems (lpdoc, (HWND)wParam, hData, iStdItem); else retval = PokeData (lpdoc, (HWND)wParam, lParam); SET_MSG_STATUS (retval, status); // !!! If the fRelease is false and the post fails // then we are not freeing the hdata. Are we supposed to lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem); if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd,lparamNew)) { DDEFREE(WM_DDE_ACK,lparamNew); goto PokeErr1; } break; } case WM_DDE_ADVISE: { ATOM aItem = GET_WM_DDE_ADVISE_ITEM(wParam, lParam); DEBUG_OUT ("doc: Advise", 0) fack = TRUE; if (lpdoc->bTerminate || !IsWindowValid ((HWND)wParam)) goto PokeErr1; if (IsAdviseStdItems (aItem)) retval = AdviseStdItems (lpdoc, (HWND)wParam, lParam, (BOOL FAR *)&fack); else // advise data will not have any OLE_BUSY retval = AdviseData (lpdoc, (HWND)wParam, lParam, (BOOL FAR *)&fack); SET_MSG_STATUS (retval, status); if (fack) { LPARAM lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem); if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lparamNew)) { DDEFREE(WM_DDE_ACK,lparamNew); goto PokeErr1; } } else if ((ATOM)(HIWORD (lParam))) GlobalDeleteAtom (aItem); break; } case WM_DDE_UNADVISE: { LPARAM lparamNew; ATOM aItem = GET_WM_DDE_UNADVISE_ITEM(wParam, lParam); DEBUG_OUT ("doc: Unadvise", 0) if (lpdoc->bTerminate || !IsWindowValid ((HWND)wParam)) { goto PokeErr1; } retval = UnAdviseData (lpdoc, (HWND)wParam, lParam); SET_MSG_STATUS (retval, status); lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status, aItem); if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd,lparamNew)) { DDEFREE(WM_DDE_ACK,lparamNew); UnadviseErr: /* * This path is valid for UNADVISE and REQUEST transaction only! */ if (GET_WM_DDE_UNADVISE_ITEM(wParam,lParam)) GlobalDeleteAtom (GET_WM_DDE_UNADVISE_ITEM(wParam,lParam)); DDEFREE(msg,lParam); break; } break; } case WM_DDE_REQUEST: { LPARAM lparamNew; ATOM aItem = GET_WM_DDE_REQUEST_ITEM(wParam,lParam); DEBUG_OUT ("doc: Request", 0) if (lpdoc->bTerminate || !IsWindowValid ((HWND) wParam)) goto UnadviseErr; retval = RequestData (lpdoc, (HWND)wParam, lParam, (HANDLE FAR *)&hdata); if(retval == OLE_OK) { // post the data message and we are not asking for any // acknowledge. lparamNew = MAKE_DDE_LPARAM(WM_DDE_DATA,hdata,aItem); if (!PostMessageToClient ((HWND)wParam, WM_DDE_DATA, (WPARAM)hwnd, lparamNew)) { GlobalFree (hdata); DDEFREE(WM_DDE_DATA,lparamNew); goto UnadviseErr; } break; } if (retval == OLE_BUSY) status = 0x4000; else status = 0; lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem); // if request failed, then acknowledge with error. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lparamNew)) { DDEFREE(WM_DDE_ACK,lparamNew); goto UnadviseErr; } break; } default: DEBUG_OUT("doc: Default message",0) return DefWindowProc (hwnd, msg, wParam, lParam); } return 0L; } //DocExecute: Interprets the execute command for the //document conversation. OLESTATUS INTERNAL DocExecute( HWND hwnd, HANDLE hdata, HWND hwndClient ){ ATOM acmd; BOOL fShow; BOOL fActivate; HANDLE hdup = NULL; int retval = OLE_ERROR_MEMORY; LPDOC lpdoc; LPOLESERVERDOC lpoledoc; LPCLIENT lpclient = NULL; LPSTR lpitemname; LPSTR lpopt; LPSTR lpnextarg; LPSTR lpdata = NULL; LPSTR lpverb = NULL; UINT verb; WORD wCmdType; // !!!Can we modify the string which has been passed to us // rather than duplicating the data. This will get some speed // and save some space. if(!(hdup = DuplicateData(hdata))) goto errRtn; if (!(lpdata = GlobalLock (hdup))) goto errRtn; DEBUG_OUT (lpdata, 0) lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0); #ifdef FIREWALLS ASSERT (lpdoc, "doc: doc does not exist"); #endif lpoledoc = lpdoc->lpoledoc; retval = OLE_ERROR_SYNTAX; if(*lpdata++ != '[') // commands start with the left sqaure bracket goto errRtn; // scan the command and scan upto the first arg. if (!(wCmdType = ScanCommand(lpdata, WT_DOC, &lpnextarg, &acmd))) goto errRtn; if (wCmdType == NON_OLE_COMMAND) { LPSRVR lpsrvr; if (lpsrvr = (LPSRVR) GetWindowLongPtr (GetParent (hwnd), 0)) { if (!UtilQueryProtocol (lpsrvr->aClass, PROTOCOL_EXECUTE)) retval = OLE_ERROR_PROTOCOL; else { #ifdef FIREWALLS if (!CheckPointer (lpoledoc, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLESERVERDOC") else if (!CheckPointer (lpoledoc->lpvtbl, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLESERVERDOCVTBL") else ASSERT (lpoledoc->lpvtbl->Execute, "Invalid pointer to Execute method") #endif retval = (*lpoledoc->lpvtbl->Execute) (lpoledoc, hdata); } } goto errRtn; } ////////////////////////////////////////////////////////////////////////// // // [StdCloseDocument] // ////////////////////////////////////////////////////////////////////////// if (acmd == aStdClose){ // if not terminated by NULL error if (*lpnextarg) goto errRtn; #ifdef FIREWALLS if (!CheckPointer (lpoledoc, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLESERVERDOC") else if (!CheckPointer (lpoledoc->lpvtbl, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLESERVERDOCVTBL") else ASSERT (lpoledoc->lpvtbl->Close,"Invalid pointer to Close method") #endif lpdoc->fAckClose = TRUE; lpdoc->hwndClose = hwndClient; lpdoc->hDataClose = hdata; retval = (*lpoledoc->lpvtbl->Close) (lpoledoc); lpdoc->fAckClose = FALSE; goto end; } ////////////////////////////////////////////////////////////////////////// // // [StdDoVerbItem("itemname", verb, BOOL, BOOL] // ////////////////////////////////////////////////////////////////////////// if (acmd == aStdDoVerbItem){ lpitemname = lpnextarg; if(!(lpverb = ScanArg(lpnextarg))) goto errRtn; if(!(lpnextarg = ScanNumArg(lpverb, (LPINT)&verb))) goto errRtn; #ifdef FIREWALLS ASSERT (verb < 9 , "Unexpected verb number"); #endif // now scan the show BOOL if (!(lpnextarg = ScanBoolArg (lpnextarg, (BOOL FAR *)&fShow))) goto errRtn; fActivate = FALSE; // if activate BOOL is present, scan it. if (*lpnextarg) { if (!(lpnextarg = ScanBoolArg (lpnextarg, (BOOL FAR *)&fActivate))) goto errRtn; } if (*lpnextarg) goto errRtn; retval = DocDoVerbItem (lpdoc, lpitemname, verb, fShow, !fActivate); goto end; } ////////////////////////////////////////////////////////////////////////// // // [StdShowItem("itemname"[, "true"])] // ////////////////////////////////////////////////////////////////////////// if (acmd != aStdShowItem) goto errRtn; lpitemname = lpnextarg; if(!(lpopt = ScanArg(lpitemname))) goto errRtn; // Now scan for optional parameter. fActivate = FALSE; if (*lpopt) { if(!(lpnextarg = ScanBoolArg (lpopt, (BOOL FAR *)&fActivate))) goto errRtn; if (*lpnextarg) goto errRtn; } retval = DocShowItem (lpdoc, lpitemname, !fActivate); end: errRtn: if (lpdata) GlobalUnlock (hdup); if (hdup) GlobalFree (hdup); return retval; } int INTERNAL DocShowItem ( LPDOC lpdoc, LPSTR lpitemname, BOOL fAct ){ LPCLIENT lpclient; int retval; if ((retval = FindItem (lpdoc, lpitemname, (LPCLIENT FAR *)&lpclient)) != OLE_OK) return retval; #ifdef FIREWALLS if (!CheckPointer (lpclient->lpoleobject->lpvtbl, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLEOBJECTVTBL") else ASSERT (lpclient->lpoleobject->lpvtbl->Show, "Invalid pointer to Show method") #endif // protocol sends false for activating and TRUE for not activating. // for api send TRUE for avtivating and FALSE for not activating. return (*lpclient->lpoleobject->lpvtbl->Show)(lpclient->lpoleobject, fAct); } int INTERNAL DocDoVerbItem ( LPDOC lpdoc, LPSTR lpitemname, UINT verb, BOOL fShow, BOOL fAct ){ LPCLIENT lpclient; int retval = OLE_ERROR_PROTOCOL; if ((retval = FindItem (lpdoc, lpitemname, (LPCLIENT FAR *)&lpclient)) != OLE_OK) return retval; #ifdef FIREWALLS if (!CheckPointer (lpclient->lpoleobject->lpvtbl, WRITE_ACCESS)) ASSERT (0, "Invalid LPOLEOBJECTVTBL") else ASSERT (lpclient->lpoleobject->lpvtbl->DoVerb, "Invalid pointer to Run method") #endif // pass TRUE to activate and False not to activate. Differnt from // protocol. retval = (*lpclient->lpoleobject->lpvtbl->DoVerb)(lpclient->lpoleobject, verb, fShow, fAct); return retval; } // FreePokeData: Frees the poked dats. void INTERNAL FreePokeData ( HANDLE hdde ){ DDEPOKE FAR * lpdde; if (hdde) { if (lpdde = (DDEPOKE FAR *) GlobalLock (hdde)) { if (lpdde->cfFormat == CF_METAFILEPICT) #ifdef _WIN64 FreeGDIdata (*(void* _unaligned*)lpdde->Value, lpdde->cfFormat); #else FreeGDIdata (*(LPHANDLE)lpdde->Value, lpdde->cfFormat); #endif else FreeGDIdata (LongToHandle(*(LONG*)lpdde->Value), lpdde->cfFormat); GlobalUnlock (hdde); } GlobalFree (hdde); } } // Returns TRUE if GDI format else returns FALSE BOOL INTERNAL FreeGDIdata ( HANDLE hData, OLECLIPFORMAT cfFormat ){ if (cfFormat == CF_METAFILEPICT) { LPMETAFILEPICT lpMfp; if (lpMfp = (LPMETAFILEPICT) GlobalLock (hData)) { GlobalUnlock (hData); DeleteMetaFile (lpMfp->hMF); } GlobalFree (hData); } else if (cfFormat == CF_BITMAP) DeleteObject (hData); else if (cfFormat == CF_DIB) GlobalFree (hData); else if (cfFormat == CF_ENHMETAFILE) DeleteEnhMetaFile(hData); else return FALSE; return TRUE; }