|
|
/*
OLE SERVER DEMO Server.c This file contains server methods and various server-related support functions. (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved */
#define SERVERONLY
#include <windows.h>
#include <ole.h>
#include "srvrdemo.h"
CLASS_STRINGS ClassStrings = { "ServerDemo", "*.sd", "Server Demo", "srvrdemo.exe" };
/*
Important Note:
No method should ever dispatch a DDE message or allow a DDE message to be dispatched. Therefore, no method should ever enter a message dispatch loop. Also, a method should not show a dialog or message box, because the processing of the dialog box messages will allow DDE messages to be dispatched. */ BOOL RegServer(){
LONG fRet; HKEY hKey; CHAR szKeyName[300]; //Get better value
BOOL retVal = FALSE; lstrcpy(szKeyName, ClassStrings.pClassName); lstrcat(szKeyName, "\\protocol\\StdFileEditing\\verb");
//Check if Class is installed, following should hold correct if class is installed.
if ((fRet = RegOpenKey(HKEY_CLASSES_ROOT, szKeyName, &hKey)) == ERROR_SUCCESS) return FALSE;
RegCloseKey(hKey);
if ((fRet = RegSetValue(HKEY_CLASSES_ROOT, (LPSTR)(ClassStrings.pFileSpec+1), REG_SZ, ClassStrings.pClassName, 7)) != ERROR_SUCCESS) return FALSE;
if((fRet = RegSetValue(HKEY_CLASSES_ROOT, ClassStrings.pClassName, REG_SZ, ClassStrings.pHumanReadable, 7)) != ERROR_SUCCESS) return FALSE;
lstrcat(szKeyName, "\\0"); if((fRet = RegSetValue(HKEY_CLASSES_ROOT, (LPSTR)szKeyName, REG_SZ, "PLAY", 4)) != ERROR_SUCCESS) return FALSE;
szKeyName[lstrlen(szKeyName) - 1] = '1'; if((fRet = RegSetValue(HKEY_CLASSES_ROOT, (LPSTR)szKeyName, REG_SZ, "EDIT", 4)) != ERROR_SUCCESS) return FALSE;
lstrcpy(szKeyName, ClassStrings.pClassName); lstrcat(szKeyName, "\\protocol\\StdFileEditing\\Server"); if((fRet = RegSetValue(HKEY_CLASSES_ROOT, (LPSTR)szKeyName, REG_SZ, ClassStrings.pExeName, 11)) != ERROR_SUCCESS) return FALSE;
lstrcpy(szKeyName, ClassStrings.pClassName); lstrcat(szKeyName, "\\protocol\\StdExecute\\Server"); if((fRet = RegSetValue(HKEY_CLASSES_ROOT, (LPSTR)szKeyName, REG_SZ, ClassStrings.pExeName, 11)) != ERROR_SUCCESS) return FALSE;
return TRUE;
}
/* Abbrev
* ------ * * Return a pointer to the filename part of a fully-qualified pathname. * * LPSTR lpsz - Fully qualified pathname * * CUSTOMIZATION: May be useful, but not necessary. * */ LPSTR Abbrev (LPSTR lpsz) { LPSTR lpszTemp; lpszTemp = lpsz + lstrlen(lpsz) - 1; while (lpszTemp > lpsz && lpszTemp[-1] != '\\') lpszTemp--; return lpszTemp; }
/* InitServer
* ---------- * * Initialize the server by allocating memory for it, and calling * the OleRegisterServer method. Requires that the server method table * has been properly initialized. * * HWND hwnd - Handle to the main window * LPSTR lpszLine - The Windows command line * * RETURNS: TRUE if the memory could be allocated, and the server * was properly registered. * FALSE otherwise * * CUSTOMIZATION: Your application might not use a global variable * for srvrMain. * */ BOOL InitServer (HWND hwnd, HANDLE hInst) { RegServer(); srvrMain.olesrvr.lpvtbl = &srvrvtbl;
if (OLE_OK != OleRegisterServer (szClassName, (LPOLESERVER) &srvrMain, &srvrMain.lhsrvr, hInst, OLE_SERVER_MULTI)) return FALSE; else return TRUE; }
/* InitVTbls
* --------- * * Create procedure instances for all the OLE methods. * * * CUSTOMIZATION: Your application might not use global variables for srvrvtbl, * docvtbl, and objvtbl. */ VOID InitVTbls (VOID) { typedef LPVOID ( APIENTRY *LPVOIDPROC) (LPOLEOBJECT, LPSTR);
// Server method table
srvrvtbl.Create = SrvrCreate; srvrvtbl.CreateFromTemplate = SrvrCreateFromTemplate; srvrvtbl.Edit = SrvrEdit; srvrvtbl.Execute = SrvrExecute; srvrvtbl.Exit = SrvrExit; srvrvtbl.Open = SrvrOpen; srvrvtbl.Release = SrvrRelease;
// Document method table
docvtbl.Close = DocClose; docvtbl.GetObject = DocGetObject; docvtbl.Execute = DocExecute; docvtbl.Release = DocRelease; docvtbl.Save = DocSave; docvtbl.SetColorScheme = DocSetColorScheme; docvtbl.SetDocDimensions = DocSetDocDimensions; docvtbl.SetHostNames = DocSetHostNames;
// Object method table
objvtbl.DoVerb = ObjDoVerb; objvtbl.EnumFormats = ObjEnumFormats; objvtbl.GetData = ObjGetData; objvtbl.QueryProtocol = ObjQueryProtocol; objvtbl.Release = ObjRelease; objvtbl.SetBounds = ObjSetBounds; objvtbl.SetColorScheme = ObjSetColorScheme; objvtbl.SetData = ObjSetData; objvtbl.SetTargetDevice = ObjSetTargetDevice; objvtbl.Show = ObjShow;
}
/* SetTitle
* -------- * * Sets the main window's title bar. The format of the title bar is as follows * * If embedded * <Server App name> - <object type> in <client doc name> * * Example: "Server Demo - SrvrDemo Shape in OLECLI.DOC" * where OLECLI.DOC is a Winword document * * otherwise * <Server App name> - <server document name> * * Example: "Server Demo - OLESVR.SD" * where OLESVR.SD is a Server demo document * * LPSTR lpszDoc - document name * BOOL fEmbedded - If TRUE embedded document, else normal document * * RETURNS: OLE_OK * * * CUSTOMIZATION: Your application may store the document's name somewhere * other than docMain.aName. Other than that, you may * find this a useful utility function as is. * */ VOID SetTitle (LPSTR lpszDoc, BOOL fEmbedded) { CHAR szBuf[cchFilenameMax];
if (lpszDoc && lpszDoc[0]) { // Change document name.
if (docMain.aName) GlobalDeleteAtom (docMain.aName); docMain.aName = GlobalAddAtom (lpszDoc); }
if (fEmbedded) { //
if (lpszDoc && lpszDoc[0]) { wsprintf (szBuf, "%s - SrvrDemo Shape in %s", (LPSTR) szAppName, Abbrev (lpszDoc)); } else { // Use name from docMain
CHAR szDoc [cchFilenameMax]; GlobalGetAtomName (docMain.aName, szDoc, cchFilenameMax); wsprintf (szBuf, "%s - SrvrDemo Shape in %s", (LPSTR) szAppName, Abbrev (szDoc)); } SetWindowText (hwndMain, (LPSTR)szBuf); } else if (lpszDoc && lpszDoc[0]) { wsprintf (szBuf, "%s - %s", (LPSTR) szAppName, Abbrev(lpszDoc)); SetWindowText (hwndMain, szBuf); } }
/* SrvrCreate SERVER "Create" METHOD
* ---------- * * Create a document, allocate and initialize the OLESERVERDOC structure, * and associate the library's handle with it. * In this demo server, we also create an object for the user to edit. * * LPOLESERVER lpolesrvr - The server structure registered by * the application * LHSERVERDOC lhdoc - The library's handle * OLE_LPCSTR lpszClassName - The class of document to create * OLE_LPCSTR lpszDoc - The name of the document * LPOLESERVERDOC FAR *lplpoledoc - Indicates the server doc structure to be * created * * RETURNS: OLE_OK if the named document was created. * OLE_ERROR_NEW if the document could not be created. * * CUSTOMIZATION: Your application might not call CreateNewObj. * */ OLESTATUS APIENTRY SrvrCreate (LPOLESERVER lpolesrvr, LHSERVERDOC lhdoc, OLE_LPCSTR lpszClassName, OLE_LPCSTR lpszDoc, LPOLESERVERDOC FAR *lplpoledoc) { if (!CreateNewDoc (lhdoc, (LPSTR) lpszDoc, doctypeEmbedded)) return OLE_ERROR_NEW;
// Although the document has not actually been changed, the client has not
// received any data from the server yet, so the client will need to be
// updated. Therefore, CreateNewObj sets fDocChanged to TRUE.
CreateNewObj (TRUE); *lplpoledoc = (LPOLESERVERDOC) &docMain; EmbeddingModeOn(); return OLE_OK; }
/* SrvrCreateFromTemplate SERVER "CreateFromTemplate" METHOD
* ---------------------- * * Create a document, allocate and initialize the OLESERVERDOC structure, * initializing the document with the contents named in the template name, * and associate the library's handle with the document structure. * * LPOLESERVER lpolesrvr - The server structure registered by * the application * LHSERVERDOC lhdoc - The library's handle * OLE_LPCSTR lpszClassName - The class of document to create * OLE_LPCSTR lpszDoc - The name of the document * OLE_LPCSTR lpszTemplate - The name of the template * LPOLESERVERDOC FAR *lplpoledoc - Indicates the server doc structure * to be created * * RETURNS: OLE_OK if the named document was created. * OLE_ERROR_TEMPLATE if the document could not be created. * * CUSTOMIZATION: None * */ OLESTATUS APIENTRY SrvrCreateFromTemplate (LPOLESERVER lpolesrvr, LHSERVERDOC lhdoc, OLE_LPCSTR lpszClassName, OLE_LPCSTR lpszDoc, OLE_LPCSTR lpszTemplate, LPOLESERVERDOC FAR *lplpoledoc) { if (!CreateDocFromFile((LPSTR) lpszTemplate, (LHSERVERDOC) lhdoc, doctypeEmbedded)) return OLE_ERROR_TEMPLATE;
*lplpoledoc = (LPOLESERVERDOC) &docMain;
// Although the document has not actually been changed, the client has not
// received any data from the server yet, so the client will need to be
// updated.
fDocChanged = TRUE; EmbeddingModeOn(); return OLE_OK; }
/* SrvrEdit SERVER "Edit" METHOD
* -------- * * A request by the libraries to create a document, allocate and * initialize the OLESERVERDOC structure, and associate the * library's handle with the document structure. * We create an object which will be modified by the SetData method * before the user has a chance to touch it. * * LPOLESERVER lpolesrvr - The server structure registered by * the application * LHSERVERDOC lhdoc - The library's handle * OLE_LPCSTR lpszClassName - The class of document to create * OLE_LPCSTR lpszDoc - The name of the document * LPOLESERVERDOC FAR *lplpoledoc - Indicates the server doc structure to be * created * * RETURNS: OLE_OK if the named document was created. * OLE_ERROR_EDIT if the document could not be created. * * CUSTOMIZATION: None * */ OLESTATUS APIENTRY SrvrEdit (LPOLESERVER lpolesrvr, LHSERVERDOC lhdoc, OLE_LPCSTR lpszClassName, OLE_LPCSTR lpszDoc, LPOLESERVERDOC FAR *lplpoledoc) { if (!CreateNewDoc ((LONG)lhdoc, (LPSTR)lpszDoc, doctypeEmbedded)) return OLE_ERROR_EDIT;
// The client is creating an embedded object for the server to edit,
// so initially the client and server are in sync.
fDocChanged = FALSE; *lplpoledoc = (LPOLESERVERDOC) &docMain; EmbeddingModeOn(); return OLE_OK;
}
/* SrvrExecute SERVER "Execute" METHOD
* -------- * * This application does not support the execution of DDE execution commands. * * LPOLESERVER lpolesrvr - The server structure registered by * the application * HANDLE hCommands - DDE execute commands * * RETURNS: OLE_ERROR_COMMAND * * CUSTOMIZATION: Re-implement if your application supports the execution of * DDE commands. * */ OLESTATUS APIENTRY SrvrExecute (LPOLESERVER lpolesrvr, HANDLE hCommands) { return OLE_ERROR_COMMAND; }
/* SrvrExit SERVER "Exit" METHOD
* -------- * * This method is called the library to instruct the server to exit. * * LPOLESERVER lpolesrvr - The server structure registered by * the application * * RETURNS: OLE_OK * * CUSTOMIZATION: None * */ OLESTATUS APIENTRY SrvrExit (LPOLESERVER lpolesrvr) { if (srvrMain.lhsrvr) // If we haven't already tried to revoke the server.
{ StartRevokingServer(); } return OLE_OK; }
/* SrvrOpen SERVER "Open" METHOD
* -------- * * Open the named document, allocate and initialize the OLESERVERDOC * structure, and associate the library's handle with it. * * LPOLESERVER lpolesrvr - The server structure registered by * the application * LHSERVERDOC lhdoc - The library's handle * OLE_LPCSTR lpszDoc - The name of the document * LPOLESERVERDOC FAR *lplpoledoc - Indicates server doc structure to be * created * * RETURNS: OLE_OK if the named document was opened. * OLE_ERROR_OPEN if document could not be opened correctly. * * CUSTOMIZATION: None * */ OLESTATUS APIENTRY SrvrOpen (LPOLESERVER lpolesrvr, LHSERVERDOC lhdoc, OLE_LPCSTR lpszDoc, LPOLESERVERDOC FAR *lplpoledoc) { if (!CreateDocFromFile ((LPSTR)lpszDoc, (LHSERVERDOC)lhdoc, doctypeFromFile)) return OLE_ERROR_OPEN;
*lplpoledoc = (LPOLESERVERDOC) &docMain; return OLE_OK; }
/* SrvrRelease SERVER "Release" METHOD
* ----------- * * This library calls the SrvrRelease method when it is safe to quit the * application. Note that the server application is not required to quit. * * srvrMain.lhsrvr != NULL indicates that SrvrRelease has been called * because the client is no longer connected, not because the server called * OleRevokeServer. * Therefore, only start the revoking process if the document is of type * doctypeEmbedded or if the server was opened for an invisible update. * * srvrmain.lhsrvr == NULL indicates that OleRevokeServer has already * been called (by the server application), and srvrMain is bad. * It is safe to quit now because SrvrRelease has just been called. * * Note that this method may be called twice: when OleRevokeServer is * called in StartRevokingServer, SrvrRelease is called again. * Therefore we need to be reentrant. * * LPOLESERVER lpolesrvr - The server structure to release * * RETURNS: OLE_OK * * CUSTOMIZATION: None * */ OLESTATUS APIENTRY SrvrRelease (LPOLESERVER lpolesrvr) { if (srvrMain.lhsrvr) { if (fRevokeSrvrOnSrvrRelease && (docMain.doctype == doctypeEmbedded || !IsWindowVisible (hwndMain))) StartRevokingServer(); } else { fWaitingForSrvrRelease = FALSE; // Here you should free any memory that had been allocated for the server.
PostQuitMessage (0); } return OLE_OK; }
/* StartRevokingServer
* ------------------- * * Hide the window, and start to revoke the server. * Revoking the server will let the library close any registered documents. * OleRevokeServer may return OLE_WAIT_FOR_RELEASE. * Calling StartRevokingServer starts a chain of events that will eventually * lead to the application being terminated. * * RETURNS: The return value from OleRevokeServer * * CUSTOMIZATION: None * */ OLESTATUS StartRevokingServer (VOID) { OLESTATUS olestatus;
if (srvrMain.lhsrvr) { LHSERVER lhserver; // Hide the window so user can do nothing while we are waiting.
ShowWindow (hwndMain, SW_HIDE); lhserver = srvrMain.lhsrvr; // Set lhsrvr to NULL to indicate that srvrMain is a bad and that
// if SrvrRelease is called, then it is ok to quit the application.
srvrMain.lhsrvr = 0; olestatus = OleRevokeServer (lhserver); } else // The programmer should ensure that this never happens.
ErrorBox ("Fatal Error: StartRevokingServer called on NULL server."); return olestatus; }
|