Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

538 lines
16 KiB

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