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.

534 lines
13 KiB

  1. /*
  2. OLE SERVER DEMO
  3. File.c
  4. This file contains file input/output functions for for the OLE server demo.
  5. (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
  6. */
  7. #include <windows.h>
  8. #include <commDlg.h>
  9. #include <ole.h>
  10. #include "srvrdemo.h"
  11. // File signature stored in the file.
  12. #define szSignature "ServerDemo"
  13. #define cchSigLen (10+1)
  14. // Delimiter for fields in the file
  15. #define chDelim ':'
  16. // Default file extension
  17. #define szDefExt "sd"
  18. // File header structure
  19. typedef struct
  20. {
  21. CHAR szSig [cchSigLen];
  22. CHAR chDelim1;
  23. VERSION version;
  24. CHAR chDelim2;
  25. CHAR rgfObjNums [cfObjNums+1];
  26. } HEADER;
  27. // BOOL GetFileSaveFilename (LPSTR lpszFilename);
  28. static VOID InitOfn (OPENFILENAME *pofn);
  29. static BOOL SaveDocIntoFile (PSTR);
  30. static LPOBJ ReadObj (INT fh);
  31. /* CreateDocFromFile
  32. * -----------------
  33. *
  34. * Read a document from the specified file.
  35. *
  36. * LPSTR lpszDoc - Name of the file containing the document
  37. * LHSERVERDOC lhdoc - Handle to the document
  38. * DOCTYPE doctype - In what state the document is created
  39. *
  40. * RETURNS: TRUE if successful, FALSE otherwise
  41. *
  42. * CUSTOMIZATION: Re-implement
  43. * This function will need to be completely re-implemented
  44. * to support your application's file format.
  45. *
  46. */
  47. BOOL CreateDocFromFile (LPSTR lpszDoc, LHSERVERDOC lhdoc, DOCTYPE doctype)
  48. {
  49. INT fh; // File handle
  50. HEADER hdr;
  51. INT i;
  52. if ((fh =_lopen(lpszDoc, OF_READ)) == -1)
  53. return FALSE;
  54. // Read header from file.
  55. if (_lread(fh, (LPSTR) &hdr, (UINT)sizeof(HEADER)) < sizeof (HEADER))
  56. goto Error;
  57. // Check to see if file is a server demo file.
  58. if (lstrcmp(hdr.szSig, szSignature))
  59. goto Error;
  60. if (hdr.chDelim1 != chDelim)
  61. goto Error;
  62. // Check to see if file was saved under the most recent version.
  63. // Here is where you would handle reading in old versions.
  64. if (hdr.version != version)
  65. goto Error;
  66. if (hdr.chDelim2 != chDelim)
  67. goto Error;
  68. if (!CreateNewDoc (lhdoc, lpszDoc, doctype))
  69. goto Error;
  70. // Get the array indicating which object numbers have been used.
  71. for (i=1; i <= cfObjNums; i++)
  72. docMain.rgfObjNums[i] = hdr.rgfObjNums[i];
  73. // Read in object data.
  74. for (i=0; ReadObj (fh); i++);
  75. if (!i)
  76. {
  77. OLESTATUS olestatus;
  78. fRevokeSrvrOnSrvrRelease = FALSE;
  79. if ((olestatus = RevokeDoc()) > OLE_WAIT_FOR_RELEASE)
  80. goto Error;
  81. else if (olestatus == OLE_WAIT_FOR_RELEASE)
  82. Wait (&fWaitingForDocRelease);
  83. fRevokeSrvrOnSrvrRelease = TRUE;
  84. EmbeddingModeOff();
  85. goto Error;
  86. }
  87. _lclose(fh);
  88. fDocChanged = FALSE;
  89. return TRUE;
  90. Error:
  91. _lclose(fh);
  92. return FALSE;
  93. }
  94. /* OpenDoc
  95. * -------
  96. *
  97. * Prompt the user for which document he wants to open
  98. *
  99. * RETURNS: TRUE if successful, FALSE otherwise.
  100. *
  101. * CUSTOMIZATION: None, except your application may or may not call
  102. * CreateNewObj to create a default object.
  103. *
  104. */
  105. BOOL OpenDoc (VOID)
  106. {
  107. CHAR szDoc[cchFilenameMax];
  108. BOOL fUpdateLater;
  109. OLESTATUS olestatus;
  110. if (SaveChangesOption (&fUpdateLater) == IDCANCEL)
  111. return FALSE;
  112. if (!GetFileOpenFilename (szDoc))
  113. {
  114. if (fUpdateLater)
  115. {
  116. // The user chose the "Yes, Update" button but the
  117. // File Open dialog box failed for some reason
  118. // (perhaps the user chose Cancel).
  119. // Even though the user chose "Yes, Update", there is no way
  120. // to update a client that does not accept updates
  121. // except when the document is closed.
  122. }
  123. return FALSE;
  124. }
  125. if (fUpdateLater)
  126. {
  127. // The non-standard OLE client did not accept the update when
  128. // we requested it, so we are sending the client OLE_CLOSED now that
  129. // we are closing the document.
  130. SendDocMsg (OLE_CLOSED);
  131. }
  132. fRevokeSrvrOnSrvrRelease = FALSE;
  133. if ((olestatus = RevokeDoc()) > OLE_WAIT_FOR_RELEASE)
  134. return FALSE;
  135. else if (olestatus == OLE_WAIT_FOR_RELEASE)
  136. Wait (&fWaitingForDocRelease);
  137. fRevokeSrvrOnSrvrRelease = TRUE;
  138. EmbeddingModeOff();
  139. if (!CreateDocFromFile (szDoc, 0, doctypeFromFile))
  140. {
  141. MessageBox (hwndMain,
  142. "Reading from file failed.\r\nFile may not be in proper file format.",
  143. szAppName,
  144. MB_ICONEXCLAMATION | MB_OK);
  145. // We already revoked the document, so give the user a new one to edit.
  146. CreateNewDoc (0, "(Untitled)", doctypeNew);
  147. CreateNewObj (FALSE);
  148. return FALSE;
  149. }
  150. fDocChanged = FALSE;
  151. return TRUE;
  152. }
  153. /* ReadObj
  154. * --------
  155. *
  156. * Read the next object from a file, allocate memory for it, and return
  157. * a pointer to it.
  158. *
  159. * int fh - File handle
  160. *
  161. * RETURNS: A pointer to the object
  162. *
  163. * CUSTOMIZATION: Server Demo specific
  164. *
  165. */
  166. static LPOBJ ReadObj (INT fh)
  167. {
  168. HANDLE hObj = NULL;
  169. LPOBJ lpobj = NULL;
  170. hObj = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof (OBJ));
  171. if (hObj == NULL)
  172. return NULL;
  173. lpobj = (LPOBJ) LocalLock (hObj);
  174. if (lpobj==NULL)
  175. {
  176. LocalFree (hObj);
  177. return NULL;
  178. }
  179. if (_lread(fh, (LPSTR) &lpobj->native, (UINT)sizeof(NATIVE)) < sizeof (NATIVE))
  180. {
  181. LocalUnlock (hObj);
  182. LocalFree (hObj);
  183. return NULL;
  184. }
  185. lpobj->hObj = hObj;
  186. lpobj->oleobject.lpvtbl = &objvtbl;
  187. lpobj->aName = GlobalAddAtom (lpobj->native.szName);
  188. if (!CreateWindow(
  189. "ObjClass",
  190. "Obj",
  191. WS_THICKFRAME | WS_BORDER | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE ,
  192. lpobj->native.nX,
  193. lpobj->native.nY,
  194. lpobj->native.nWidth,
  195. lpobj->native.nHeight,
  196. hwndMain,
  197. NULL,
  198. hInst,
  199. (LPSTR) lpobj ))
  200. {
  201. LocalUnlock (hObj);
  202. LocalFree (hObj);
  203. return NULL;
  204. }
  205. return lpobj;
  206. }
  207. /* SaveDoc
  208. * -------
  209. *
  210. * Save the document.
  211. *
  212. * CUSTOMIZATION: None
  213. *
  214. */
  215. BOOL SaveDoc (VOID)
  216. {
  217. if (docMain.doctype == doctypeNew)
  218. return SaveDocAs();
  219. else
  220. {
  221. CHAR szDoc [cchFilenameMax];
  222. GlobalGetAtomName (docMain.aName, szDoc, cchFilenameMax);
  223. return SaveDocIntoFile(szDoc);
  224. }
  225. }
  226. /* SaveDocAs
  227. * ---------
  228. *
  229. * Prompt the user for a filename, and save the document under that filename.
  230. *
  231. * RETURNS: TRUE if successful or user chose CANCEL
  232. * FALSE if SaveDocIntoFile fails
  233. *
  234. * CUSTOMIZATION: None
  235. *
  236. */
  237. BOOL SaveDocAs (VOID)
  238. {
  239. CHAR szDoc[cchFilenameMax];
  240. BOOL fUpdateLater = FALSE;
  241. CHAR szDocOld[cchFilenameMax];
  242. // If document is embedded, give user a chance to update.
  243. // Save old document name in case the save fails.
  244. if (!GlobalGetAtomName (docMain.aName, szDocOld, cchFilenameMax))
  245. ErrorBox ("Fatal Error: Document name is invalid.");
  246. if (GetFileSaveFilename (szDoc))
  247. {
  248. if (docMain.doctype == doctypeEmbedded)
  249. return SaveDocIntoFile(szDoc);
  250. if (fUpdateLater)
  251. {
  252. // The non-standard OLE client did not accept the update when
  253. // we requested it, so we are sending the client OLE_CLOSED now that
  254. // we are closing the document.
  255. SendDocMsg (OLE_CLOSED);
  256. }
  257. // Set the window title bar.
  258. SetTitle (szDoc, FALSE);
  259. OleRenameServerDoc(docMain.lhdoc, szDoc);
  260. if (SaveDocIntoFile(szDoc))
  261. return TRUE;
  262. else
  263. { // Restore old name
  264. SetTitle (szDocOld, FALSE);
  265. OleRenameServerDoc(docMain.lhdoc, szDocOld);
  266. return FALSE;
  267. }
  268. }
  269. else // user chose Cancel
  270. return FALSE;
  271. // The user chose the "Yes, Update" button but the
  272. // File Open dialog box failed for some reason
  273. // (perhaps the user chose Cancel).
  274. // Even though the user chose "Yes, Update", there is no way
  275. // to update a non-standard OLE client that does not accept updates
  276. // except when the document is closed.
  277. }
  278. /* SaveDocIntoFile
  279. * ---------------
  280. *
  281. * Save the document into a file whose name is determined from docMain.aName.
  282. *
  283. * RETURNS: TRUE if successful
  284. * FALSE otherwise
  285. *
  286. * CUSTOMIZATION: Re-implement
  287. *
  288. */
  289. static BOOL SaveDocIntoFile (PSTR pDoc)
  290. {
  291. HWND hwnd;
  292. INT fh; // File handle
  293. LPOBJ lpobj;
  294. HEADER hdr;
  295. INT i;
  296. hwnd = GetWindow (hwndMain, GW_CHILD);
  297. if (!hwnd)
  298. {
  299. ErrorBox ("Could not save NULL file.");
  300. return FALSE;
  301. }
  302. // Get document name.
  303. if ((fh =_lcreat(pDoc, 0)) == -1)
  304. {
  305. ErrorBox ("Could not save file.");
  306. return FALSE;
  307. }
  308. // Fill in header.
  309. lstrcpy (hdr.szSig, szSignature);
  310. hdr.chDelim1 = chDelim;
  311. hdr.version = version;
  312. hdr.chDelim2 = chDelim;
  313. for (i=1; i <= cfObjNums; i++)
  314. hdr.rgfObjNums[i] = docMain.rgfObjNums[i];
  315. // Write header to file.
  316. if (_lwrite(fh, (LPSTR) &hdr, (UINT)sizeof(HEADER)) < sizeof(HEADER))
  317. goto Error; // Error writing file header
  318. // Write each object's native data.
  319. while (hwnd)
  320. {
  321. lpobj = (LPOBJ) GetWindowLong (hwnd, ibLpobj);
  322. if (_lwrite(fh, (LPSTR)&lpobj->native, (UINT)sizeof (NATIVE))
  323. < sizeof(NATIVE))
  324. goto Error; // Error writing file header
  325. hwnd = GetWindow (hwnd, GW_HWNDNEXT);
  326. }
  327. _lclose(fh);
  328. if (docMain.doctype != doctypeEmbedded)
  329. {
  330. docMain.doctype = doctypeFromFile;
  331. OleSavedServerDoc(docMain.lhdoc);
  332. fDocChanged = FALSE;
  333. }
  334. return TRUE;
  335. Error:
  336. _lclose(fh);
  337. ErrorBox ("Could not save file.");
  338. return FALSE;
  339. }
  340. /* Common Dialog functions */
  341. /* InitOfn
  342. * -------
  343. *
  344. * Initialize an OPENFILENAME structure with default values.
  345. * OPENFILENAME is defined in CommDlg.h.
  346. *
  347. *
  348. * CUSTOMIZATION: Change lpstrFilter. You may also customize the common
  349. * dialog box if you wish. (See the Windows SDK documentation.)
  350. *
  351. */
  352. static VOID InitOfn (OPENFILENAME *pofn)
  353. {
  354. // GetOpenFileName or GetSaveFileName will put the 8.3 filename into
  355. // szFileTitle[].
  356. // SrvrDemo does not use this filename, but rather uses the fully qualified
  357. // pathname in pofn->lpstrFile[].
  358. static CHAR szFileTitle[13];
  359. pofn->Flags = 0;
  360. pofn->hInstance = hInst;
  361. pofn->hwndOwner = hwndMain;
  362. pofn->lCustData = 0;
  363. pofn->lpfnHook = NULL;
  364. pofn->lpstrCustomFilter = NULL;
  365. pofn->lpstrDefExt = szDefExt;
  366. // lpstrFile[] is the initial filespec that appears in the edit control.
  367. // Must be set to non-NULL before calling the common dialog box function.
  368. // On return, lpstrFile[] will contain the fully-qualified pathname
  369. // corresponding to the file the user chose.
  370. pofn->lpstrFile = NULL;
  371. pofn->lpstrFilter = "Server Demo (*." szDefExt ")\0*." szDefExt "\0" ;
  372. // lpstrFileTitle[] will contain the user's chosen filename without a path.
  373. pofn->lpstrFileTitle = szFileTitle;
  374. pofn->lpstrInitialDir= NULL;
  375. // Title Bar. NULL means use default title.
  376. pofn->lpstrTitle = NULL;
  377. pofn->lpTemplateName = NULL;
  378. pofn->lStructSize = sizeof (OPENFILENAME);
  379. pofn->nFilterIndex = 1L;
  380. pofn->nFileOffset = 0;
  381. pofn->nFileExtension = 0;
  382. pofn->nMaxFile = cchFilenameMax;
  383. pofn->nMaxCustFilter = 0L;
  384. }
  385. /* GetFileOpenFilename
  386. * -------------------
  387. *
  388. * Call the common dialog box function GetOpenFileName to get a file name
  389. * from the user when the user chooses the "File Open" menu item.
  390. *
  391. * LPSTR lpszFilename - will contain the fully-qualified pathname on exit.
  392. *
  393. * RETURNS: TRUE if successful, FALSE otherwise.
  394. *
  395. * CUSTOMIZATION: None
  396. *
  397. */
  398. BOOL GetFileOpenFilename (LPSTR lpszFilename)
  399. {
  400. OPENFILENAME ofn;
  401. InitOfn (&ofn);
  402. ofn.Flags |= OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  403. // Create initial filespec.
  404. wsprintf (lpszFilename, "*.%s", (LPSTR) szDefExt);
  405. // Have the common dialog function return the filename in lpszFilename.
  406. ofn.lpstrFile = lpszFilename;
  407. if (!GetOpenFileName (&ofn))
  408. return FALSE;
  409. return TRUE;
  410. }
  411. /* GetFileSaveFilename
  412. * -------------------
  413. *
  414. * Call the common dialog box function GetSaveFileName to get a file name
  415. * from the user when the user chooses the "File Save As" menu item, or the
  416. * "File Save" menu item for an unnamed document.
  417. *
  418. * LPSTR lpszFilename - will contain the fully-qualified pathname on exit.
  419. *
  420. * RETURNS: TRUE if successful, FALSE otherwise.
  421. *
  422. * CUSTOMIZATION: None
  423. *
  424. */
  425. BOOL GetFileSaveFilename (LPSTR lpszFilename)
  426. {
  427. OPENFILENAME ofn;
  428. InitOfn (&ofn);
  429. ofn.Flags |= OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  430. // Create initial filespec.
  431. wsprintf (lpszFilename, "*.%s", (LPSTR) szDefExt);
  432. // Have the common dialog function return the filename in lpszFilename.
  433. ofn.lpstrFile = lpszFilename;
  434. if (!GetSaveFileName (&ofn))
  435. return FALSE;
  436. return TRUE;
  437. }