|
|
1.1 root 1: /*
2: OLE SERVER DEMO
3: Server.c
4:
5: This file contains server methods and various server-related support
6: functions.
7:
8: (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
9: */
10:
11:
12:
13: #define SERVERONLY
14: #include <windows.h>
15: #include <ole.h>
16:
17: #include "srvrdemo.h"
18:
19: CLASS_STRINGS ClassStrings = {
20: "ServerDemo", "*.sd", "Server Demo", "srvrdemo.exe"
21: };
22:
23: /*
24: Important Note:
25:
26: No method should ever dispatch a DDE message or allow a DDE message to
27: be dispatched.
28: Therefore, no method should ever enter a message dispatch loop.
29: Also, a method should not show a dialog or message box, because the
30: processing of the dialog box messages will allow DDE messages to be
31: dispatched.
32: */
33: BOOL RegServer(){
34:
35: LONG fRet;
36: HKEY hKey;
37: CHAR szKeyName[300]; //Get better value
38: BOOL retVal = FALSE;
39:
40: lstrcpy(szKeyName, ClassStrings.pClassName);
41: lstrcat(szKeyName, "\\protocol\\StdFileEditing\\verb");
42:
43: //Check if Class is installed, following should hold correct if class is installed.
44: if ((fRet = RegOpenKey(HKEY_CLASSES_ROOT, szKeyName, &hKey)) == ERROR_SUCCESS)
45: return FALSE;
46:
47: RegCloseKey(hKey);
48:
49: if ((fRet = RegSetValue(HKEY_CLASSES_ROOT, (LPSTR)(ClassStrings.pFileSpec+1),
50: REG_SZ, ClassStrings.pClassName, 7)) != ERROR_SUCCESS)
51: return FALSE;
52:
53: if((fRet = RegSetValue(HKEY_CLASSES_ROOT, ClassStrings.pClassName, REG_SZ,
54: ClassStrings.pHumanReadable, 7)) != ERROR_SUCCESS)
55: return FALSE;
56:
57: lstrcat(szKeyName, "\\0");
58: if((fRet = RegSetValue(HKEY_CLASSES_ROOT, (LPSTR)szKeyName, REG_SZ, "PLAY", 4))
59: != ERROR_SUCCESS)
60: return FALSE;
61:
62: szKeyName[lstrlen(szKeyName) - 1] = '1';
63: if((fRet = RegSetValue(HKEY_CLASSES_ROOT, (LPSTR)szKeyName, REG_SZ, "EDIT", 4))
64: != ERROR_SUCCESS)
65: return FALSE;
66:
67: lstrcpy(szKeyName, ClassStrings.pClassName);
68: lstrcat(szKeyName, "\\protocol\\StdFileEditing\\Server");
69: if((fRet = RegSetValue(HKEY_CLASSES_ROOT, (LPSTR)szKeyName, REG_SZ, ClassStrings.pExeName, 11))
70: != ERROR_SUCCESS)
71: return FALSE;
72:
73: lstrcpy(szKeyName, ClassStrings.pClassName);
74: lstrcat(szKeyName, "\\protocol\\StdExecute\\Server");
75: if((fRet = RegSetValue(HKEY_CLASSES_ROOT, (LPSTR)szKeyName, REG_SZ, ClassStrings.pExeName, 11))
76: != ERROR_SUCCESS)
77: return FALSE;
78:
79:
80: return TRUE;
81:
82: }
83:
84:
85: /* Abbrev
86: * ------
87: *
88: * Return a pointer to the filename part of a fully-qualified pathname.
89: *
90: * LPSTR lpsz - Fully qualified pathname
91: *
92: * CUSTOMIZATION: May be useful, but not necessary.
93: *
94: */
95: LPSTR Abbrev (LPSTR lpsz)
96: {
97: LPSTR lpszTemp;
98:
99: lpszTemp = lpsz + lstrlen(lpsz) - 1;
100: while (lpszTemp > lpsz && lpszTemp[-1] != '\\')
101: lpszTemp--;
102: return lpszTemp;
103: }
104:
105:
106:
107:
108:
109: /* InitServer
110: * ----------
111: *
112: * Initialize the server by allocating memory for it, and calling
113: * the OleRegisterServer method. Requires that the server method table
114: * has been properly initialized.
115: *
116: * HWND hwnd - Handle to the main window
117: * LPSTR lpszLine - The Windows command line
118: *
119: * RETURNS: TRUE if the memory could be allocated, and the server
120: * was properly registered.
121: * FALSE otherwise
122: *
123: * CUSTOMIZATION: Your application might not use a global variable
124: * for srvrMain.
125: *
126: */
127: BOOL InitServer (HWND hwnd, HANDLE hInst)
128: {
129: RegServer();
130: srvrMain.olesrvr.lpvtbl = &srvrvtbl;
131:
132: if (OLE_OK != OleRegisterServer
133: (szClassName, (LPOLESERVER) &srvrMain, &srvrMain.lhsrvr, hInst,
134: OLE_SERVER_MULTI))
135: return FALSE;
136: else
137: return TRUE;
138: }
139:
140:
141:
142: /* InitVTbls
143: * ---------
144: *
145: * Create procedure instances for all the OLE methods.
146: *
147: *
148: * CUSTOMIZATION: Your application might not use global variables for srvrvtbl,
149: * docvtbl, and objvtbl.
150: */
151: VOID InitVTbls (VOID)
152: {
153: typedef LPVOID ( APIENTRY *LPVOIDPROC) (LPOLEOBJECT, LPSTR);
154:
155: // Server method table
156: srvrvtbl.Create = SrvrCreate;
157: srvrvtbl.CreateFromTemplate = SrvrCreateFromTemplate;
158: srvrvtbl.Edit = SrvrEdit;
159: srvrvtbl.Execute = SrvrExecute;
160: srvrvtbl.Exit = SrvrExit;
161: srvrvtbl.Open = SrvrOpen;
162: srvrvtbl.Release = SrvrRelease;
163:
164: // Document method table
165: docvtbl.Close = DocClose;
166: docvtbl.GetObject = DocGetObject;
167: docvtbl.Execute = DocExecute;
168: docvtbl.Release = DocRelease;
169: docvtbl.Save = DocSave;
170: docvtbl.SetColorScheme = DocSetColorScheme;
171: docvtbl.SetDocDimensions = DocSetDocDimensions;
172: docvtbl.SetHostNames = DocSetHostNames;
173:
174: // Object method table
175: objvtbl.DoVerb = ObjDoVerb;
176: objvtbl.EnumFormats = ObjEnumFormats;
177: objvtbl.GetData = ObjGetData;
178: objvtbl.QueryProtocol = ObjQueryProtocol;
179: objvtbl.Release = ObjRelease;
180: objvtbl.SetBounds = ObjSetBounds;
181: objvtbl.SetColorScheme = ObjSetColorScheme;
182: objvtbl.SetData = ObjSetData;
183: objvtbl.SetTargetDevice = ObjSetTargetDevice;
184: objvtbl.Show = ObjShow;
185:
186: }
187:
188:
189:
190: /* SetTitle
191: * --------
192: *
193: * Sets the main window's title bar. The format of the title bar is as follows
194: *
195: * If embedded
196: * <Server App name> - <object type> in <client doc name>
197: *
198: * Example: "Server Demo - SrvrDemo Shape in OLECLI.DOC"
199: * where OLECLI.DOC is a Winword document
200: *
201: * otherwise
202: * <Server App name> - <server document name>
203: *
204: * Example: "Server Demo - OLESVR.SD"
205: * where OLESVR.SD is a Server demo document
206: *
207: * LPSTR lpszDoc - document name
208: * BOOL fEmbedded - If TRUE embedded document, else normal document
209: *
210: * RETURNS: OLE_OK
211: *
212: *
213: * CUSTOMIZATION: Your application may store the document's name somewhere
214: * other than docMain.aName. Other than that, you may
215: * find this a useful utility function as is.
216: *
217: */
218: VOID SetTitle (LPSTR lpszDoc, BOOL fEmbedded)
219: {
220: CHAR szBuf[cchFilenameMax];
221:
222: if (lpszDoc && lpszDoc[0])
223: {
224: // Change document name.
225: if (docMain.aName)
226: GlobalDeleteAtom (docMain.aName);
227: docMain.aName = GlobalAddAtom (lpszDoc);
228: }
229:
230: if (fEmbedded)
231: {
232: //
233: if (lpszDoc && lpszDoc[0])
234: {
235: wsprintf (szBuf, "%s - SrvrDemo Shape in %s", (LPSTR) szAppName,
236: Abbrev (lpszDoc));
237: }
238: else
239: {
240: // Use name from docMain
241: CHAR szDoc [cchFilenameMax];
242:
243: GlobalGetAtomName (docMain.aName, szDoc, cchFilenameMax);
244: wsprintf (szBuf, "%s - SrvrDemo Shape in %s", (LPSTR) szAppName,
245: Abbrev (szDoc));
246: }
247: SetWindowText (hwndMain, (LPSTR)szBuf);
248: }
249: else if (lpszDoc && lpszDoc[0])
250: {
251: wsprintf (szBuf, "%s - %s", (LPSTR) szAppName, Abbrev(lpszDoc));
252: SetWindowText (hwndMain, szBuf);
253: }
254: }
255:
256:
257:
258:
259: /* SrvrCreate SERVER "Create" METHOD
260: * ----------
261: *
262: * Create a document, allocate and initialize the OLESERVERDOC structure,
263: * and associate the library's handle with it.
264: * In this demo server, we also create an object for the user to edit.
265: *
266: * LPOLESERVER lpolesrvr - The server structure registered by
267: * the application
268: * LHSERVERDOC lhdoc - The library's handle
1.1.1.2 ! root 269: * OLE_LPCSTR lpszClassName - The class of document to create
! 270: * OLE_LPCSTR lpszDoc - The name of the document
1.1 root 271: * LPOLESERVERDOC FAR *lplpoledoc - Indicates the server doc structure to be
272: * created
273: *
274: * RETURNS: OLE_OK if the named document was created.
275: * OLE_ERROR_NEW if the document could not be created.
276: *
277: * CUSTOMIZATION: Your application might not call CreateNewObj.
278: *
279: */
280: OLESTATUS APIENTRY SrvrCreate
1.1.1.2 ! root 281: (LPOLESERVER lpolesrvr, LHSERVERDOC lhdoc, OLE_LPCSTR lpszClassName,
! 282: OLE_LPCSTR lpszDoc, LPOLESERVERDOC FAR *lplpoledoc)
1.1 root 283: {
1.1.1.2 ! root 284: if (!CreateNewDoc (lhdoc, (LPSTR) lpszDoc, doctypeEmbedded))
1.1 root 285: return OLE_ERROR_NEW;
286:
287: // Although the document has not actually been changed, the client has not
288: // received any data from the server yet, so the client will need to be
289: // updated. Therefore, CreateNewObj sets fDocChanged to TRUE.
290: CreateNewObj (TRUE);
291: *lplpoledoc = (LPOLESERVERDOC) &docMain;
292: EmbeddingModeOn();
293: return OLE_OK;
294: }
295:
296:
297:
298: /* SrvrCreateFromTemplate SERVER "CreateFromTemplate" METHOD
299: * ----------------------
300: *
301: * Create a document, allocate and initialize the OLESERVERDOC structure,
302: * initializing the document with the contents named in the template name,
303: * and associate the library's handle with the document structure.
304: *
305: * LPOLESERVER lpolesrvr - The server structure registered by
306: * the application
307: * LHSERVERDOC lhdoc - The library's handle
1.1.1.2 ! root 308: * OLE_LPCSTR lpszClassName - The class of document to create
! 309: * OLE_LPCSTR lpszDoc - The name of the document
! 310: * OLE_LPCSTR lpszTemplate - The name of the template
1.1 root 311: * LPOLESERVERDOC FAR *lplpoledoc - Indicates the server doc structure
312: * to be created
313: *
314: * RETURNS: OLE_OK if the named document was created.
315: * OLE_ERROR_TEMPLATE if the document could not be created.
316: *
317: * CUSTOMIZATION: None
318: *
319: */
320: OLESTATUS APIENTRY SrvrCreateFromTemplate
1.1.1.2 ! root 321: (LPOLESERVER lpolesrvr, LHSERVERDOC lhdoc, OLE_LPCSTR lpszClassName,
! 322: OLE_LPCSTR lpszDoc, OLE_LPCSTR lpszTemplate, LPOLESERVERDOC FAR *lplpoledoc)
1.1 root 323: {
1.1.1.2 ! root 324: if (!CreateDocFromFile((LPSTR) lpszTemplate, (LHSERVERDOC) lhdoc, doctypeEmbedded))
1.1 root 325: return OLE_ERROR_TEMPLATE;
326:
327: *lplpoledoc = (LPOLESERVERDOC) &docMain;
328:
329: // Although the document has not actually been changed, the client has not
330: // received any data from the server yet, so the client will need to be
331: // updated.
332: fDocChanged = TRUE;
333: EmbeddingModeOn();
334: return OLE_OK;
335: }
336:
337:
338:
339: /* SrvrEdit SERVER "Edit" METHOD
340: * --------
341: *
342: * A request by the libraries to create a document, allocate and
343: * initialize the OLESERVERDOC structure, and associate the
344: * library's handle with the document structure.
345: * We create an object which will be modified by the SetData method
346: * before the user has a chance to touch it.
347: *
348: * LPOLESERVER lpolesrvr - The server structure registered by
349: * the application
350: * LHSERVERDOC lhdoc - The library's handle
1.1.1.2 ! root 351: * OLE_LPCSTR lpszClassName - The class of document to create
! 352: * OLE_LPCSTR lpszDoc - The name of the document
1.1 root 353: * LPOLESERVERDOC FAR *lplpoledoc - Indicates the server doc structure to be
354: * created
355: *
356: * RETURNS: OLE_OK if the named document was created.
357: * OLE_ERROR_EDIT if the document could not be created.
358: *
359: * CUSTOMIZATION: None
360: *
361: */
362: OLESTATUS APIENTRY SrvrEdit
1.1.1.2 ! root 363: (LPOLESERVER lpolesrvr, LHSERVERDOC lhdoc, OLE_LPCSTR lpszClassName,
! 364: OLE_LPCSTR lpszDoc, LPOLESERVERDOC FAR *lplpoledoc)
1.1 root 365: {
1.1.1.2 ! root 366: if (!CreateNewDoc ((LONG)lhdoc, (LPSTR)lpszDoc, doctypeEmbedded))
1.1 root 367: return OLE_ERROR_EDIT;
368:
369: // The client is creating an embedded object for the server to edit,
370: // so initially the client and server are in sync.
371: fDocChanged = FALSE;
372: *lplpoledoc = (LPOLESERVERDOC) &docMain;
373: EmbeddingModeOn();
374: return OLE_OK;
375:
376: }
377:
378:
379: /* SrvrExecute SERVER "Execute" METHOD
380: * --------
381: *
382: * This application does not support the execution of DDE execution commands.
383: *
384: * LPOLESERVER lpolesrvr - The server structure registered by
385: * the application
386: * HANDLE hCommands - DDE execute commands
387: *
388: * RETURNS: OLE_ERROR_COMMAND
389: *
390: * CUSTOMIZATION: Re-implement if your application supports the execution of
391: * DDE commands.
392: *
393: */
394: OLESTATUS APIENTRY SrvrExecute (LPOLESERVER lpolesrvr, HANDLE hCommands)
395: {
396: return OLE_ERROR_COMMAND;
397: }
398:
399:
400:
401: /* SrvrExit SERVER "Exit" METHOD
402: * --------
403: *
404: * This method is called the library to instruct the server to exit.
405: *
406: * LPOLESERVER lpolesrvr - The server structure registered by
407: * the application
408: *
409: * RETURNS: OLE_OK
410: *
411: * CUSTOMIZATION: None
412: *
413: */
414: OLESTATUS APIENTRY SrvrExit (LPOLESERVER lpolesrvr)
415: {
416: if (srvrMain.lhsrvr)
417: // If we haven't already tried to revoke the server.
418: {
419: StartRevokingServer();
420: }
421: return OLE_OK;
422: }
423:
424:
425:
426: /* SrvrOpen SERVER "Open" METHOD
427: * --------
428: *
429: * Open the named document, allocate and initialize the OLESERVERDOC
430: * structure, and associate the library's handle with it.
431: *
432: * LPOLESERVER lpolesrvr - The server structure registered by
433: * the application
434: * LHSERVERDOC lhdoc - The library's handle
1.1.1.2 ! root 435: * OLE_LPCSTR lpszDoc - The name of the document
1.1 root 436: * LPOLESERVERDOC FAR *lplpoledoc - Indicates server doc structure to be
437: * created
438: *
439: * RETURNS: OLE_OK if the named document was opened.
440: * OLE_ERROR_OPEN if document could not be opened correctly.
441: *
442: * CUSTOMIZATION: None
443: *
444: */
445: OLESTATUS APIENTRY SrvrOpen (LPOLESERVER lpolesrvr, LHSERVERDOC lhdoc,
1.1.1.2 ! root 446: OLE_LPCSTR lpszDoc, LPOLESERVERDOC FAR *lplpoledoc)
1.1 root 447: {
1.1.1.2 ! root 448: if (!CreateDocFromFile ((LPSTR)lpszDoc, (LHSERVERDOC)lhdoc, doctypeFromFile))
1.1 root 449: return OLE_ERROR_OPEN;
450:
451: *lplpoledoc = (LPOLESERVERDOC) &docMain;
452: return OLE_OK;
453: }
454:
455:
456:
457: /* SrvrRelease SERVER "Release" METHOD
458: * -----------
459: *
460: * This library calls the SrvrRelease method when it is safe to quit the
461: * application. Note that the server application is not required to quit.
462: *
463: * srvrMain.lhsrvr != NULL indicates that SrvrRelease has been called
464: * because the client is no longer connected, not because the server called
465: * OleRevokeServer.
466: * Therefore, only start the revoking process if the document is of type
467: * doctypeEmbedded or if the server was opened for an invisible update.
468: *
469: * srvrmain.lhsrvr == NULL indicates that OleRevokeServer has already
470: * been called (by the server application), and srvrMain is a lame duck.
471: * It is safe to quit now because SrvrRelease has just been called.
472: *
473: * Note that this method may be called twice: when OleRevokeServer is
474: * called in StartRevokingServer, SrvrRelease is called again.
475: * Therefore we need to be reentrant.
476: *
477: * LPOLESERVER lpolesrvr - The server structure to release
478: *
479: * RETURNS: OLE_OK
480: *
481: * CUSTOMIZATION: None
482: *
483: */
484: OLESTATUS APIENTRY SrvrRelease (LPOLESERVER lpolesrvr)
485: {
486: if (srvrMain.lhsrvr)
487: {
488: if (fRevokeSrvrOnSrvrRelease
489: && (docMain.doctype == doctypeEmbedded
490: || !IsWindowVisible (hwndMain)))
491: StartRevokingServer();
492: }
493: else
494: {
495: fWaitingForSrvrRelease = FALSE;
496: // Here you should free any memory that had been allocated for the server.
497: PostQuitMessage (0);
498: }
499: return OLE_OK;
500: }
501:
502:
503:
504: /* StartRevokingServer
505: * -------------------
506: *
507: * Hide the window, and start to revoke the server.
508: * Revoking the server will let the library close any registered documents.
509: * OleRevokeServer may return OLE_WAIT_FOR_RELEASE.
510: * Calling StartRevokingServer starts a chain of events that will eventually
511: * lead to the application being terminated.
512: *
513: * RETURNS: The return value from OleRevokeServer
514: *
515: * CUSTOMIZATION: None
516: *
517: */
518: OLESTATUS StartRevokingServer (VOID)
519: {
520: OLESTATUS olestatus;
521:
522: if (srvrMain.lhsrvr)
523: {
524: LHSERVER lhserver;
525: // Hide the window so user can do nothing while we are waiting.
526: ShowWindow (hwndMain, SW_HIDE);
527: lhserver = srvrMain.lhsrvr;
528: // Set lhsrvr to NULL to indicate that srvrMain is a lame duck and that
529: // if SrvrRelease is called, then it is ok to quit the application.
1.1.1.2 ! root 530: srvrMain.lhsrvr = 0;
1.1 root 531: olestatus = OleRevokeServer (lhserver);
532: }
533: else
534: // The programmer should ensure that this never happens.
535: ErrorBox ("Fatal Error: StartRevokingServer called on NULL server.");
536: return olestatus;
537: }
538:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.