windows-nt/Source/XPSP1/NT/com/winole/samples/srvrdemo/server.c
2020-09-26 16:20:57 +08:00

539 lines
16 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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