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.

386 lines
9.4 KiB

  1. /*---------------------------------------------------------------------------
  2. | PERS.C
  3. | This file has the IPersistStorage and IPersistfile interface implementation.
  4. |
  5. | Created By: Vij Rajarajan (VijR)
  6. +---------------------------------------------------------------------------*/
  7. #define SERVERONLY
  8. #include <Windows.h>
  9. #include "mpole.h"
  10. #include "mplayer.h"
  11. #define STGM_SALL (STGM_READWRITE | STGM_SHARE_EXCLUSIVE)
  12. /**************************************************************************
  13. *************** IPersistStorage INTERFACE IMPLEMENTATION.
  14. **************************************************************************/
  15. //delegate to the common IUnknown implementation.
  16. STDMETHODIMP PSQueryInterface(
  17. LPPERSISTSTORAGE lpPersStg, // persist storage object ptr
  18. REFIID riidReq, // IID required
  19. LPVOID FAR * lplpUnk // pre for returning the interface
  20. )
  21. {
  22. return UnkQueryInterface((LPUNKNOWN)lpPersStg, riidReq, lplpUnk);
  23. }
  24. STDMETHODIMP_(ULONG) PSAddRef(
  25. LPPERSISTSTORAGE lpPersStg // persist storage object ptr
  26. )
  27. {
  28. return UnkAddRef((LPUNKNOWN) lpPersStg);
  29. }
  30. STDMETHODIMP_(ULONG) PSRelease (
  31. LPPERSISTSTORAGE lpPersStg // persist storage object ptr
  32. )
  33. {
  34. return UnkRelease((LPUNKNOWN) lpPersStg);
  35. }
  36. STDMETHODIMP PSGetClassID (
  37. LPPERSISTSTORAGE lpPersStg,
  38. CLSID FAR* pClsid
  39. )
  40. {
  41. DPF("PSGetClassID\n");
  42. /* Return the actual class ID that gets stored:
  43. */
  44. *pClsid = gClsIDOLE1Compat;
  45. return NOERROR;
  46. }
  47. STDMETHODIMP PSIsDirty (
  48. LPPERSISTSTORAGE lpPersStg
  49. )
  50. {DPF("PSIsDirty\n");
  51. RETURN_RESULT( (fDocChanged && !(gfPlayingInPlace || gfOle2IPPlaying))
  52. ? S_OK : S_FALSE);
  53. }
  54. STDMETHODIMP PSInitNew (
  55. LPPERSISTSTORAGE lpPersStg,
  56. LPSTORAGE lpStorage
  57. )
  58. {
  59. return NOERROR;
  60. }
  61. /**************************************************************************
  62. * PSLoad:
  63. * The Load method reads the embedded data from the "\1Ole10Native"
  64. * stream of the IStorage passed as an argument. This is because
  65. * we always pretend to be an OLE1 server when transferring data.
  66. * ItemSetData is called with this embedded data to to run the required
  67. * object.
  68. **************************************************************************/
  69. STDMETHODIMP PSLoad (
  70. LPPERSISTSTORAGE lpPersStg,
  71. LPSTORAGE lpStorage
  72. )
  73. {
  74. LPDOC lpdoc;
  75. SCODE error;
  76. LPSTREAM pstm;
  77. ULONG cbRead;
  78. DWORD size = 0;
  79. HGLOBAL hNative = NULL;
  80. LPTSTR lpnative = NULL;
  81. DPF("\nPSLoad is being called\n");
  82. lpdoc = ((struct CPersistStorageImpl FAR*)lpPersStg)->lpdoc;
  83. error = GetScode(IStorage_OpenStream(lpStorage, sz1Ole10Native,
  84. NULL, STGM_SALL, 0, &pstm));
  85. if (error == S_OK)
  86. {
  87. error = GetScode(IStream_Read(pstm, &size, 4, &cbRead));
  88. }
  89. if (error == S_OK)
  90. {
  91. hNative = GlobalAlloc(GMEM_DDESHARE |GMEM_ZEROINIT, (LONG)size);
  92. if (hNative)
  93. lpdoc->native = GLOBALLOCK(hNative);
  94. }
  95. if(lpdoc->native )
  96. {
  97. error = GetScode(IStream_Read(pstm, lpdoc->native, size, &cbRead));
  98. if (cbRead != size) error = E_FAIL; // REVIEW SCODE stream size error
  99. IStream_Release(pstm);
  100. }
  101. else error = E_OUTOFMEMORY;
  102. if (error == S_OK)
  103. {
  104. error = ItemSetData((LPBYTE)lpdoc->native);
  105. fDocChanged = FALSE;
  106. lpdoc->doctype = doctypeEmbedded;
  107. }
  108. if(hNative)
  109. {
  110. GLOBALUNLOCK(hNative);
  111. GLOBALFREE(hNative);
  112. }
  113. RETURN_RESULT( error);
  114. }
  115. /**************************************************************************
  116. * PSSave:
  117. * The Save method saves the native data in "\1Ole10Native" stream.
  118. * This is because we always pretend to be an OLE1 server when transferring
  119. * data. This ensures backward compatibility. GetLink is called to get
  120. * the embedding data.
  121. **************************************************************************/
  122. STDMETHODIMP PSSave (
  123. LPPERSISTSTORAGE lpPersStg,
  124. LPSTORAGE lpStorage,
  125. BOOL fSameAsLoad
  126. )
  127. {
  128. LPDOC lpdoc;
  129. SCODE error;
  130. LPSTREAM pstm = NULL;
  131. ULONG cbWritten;
  132. DWORD_PTR size;
  133. HGLOBAL hNative = NULL;
  134. LPTSTR lpnative = NULL;
  135. LPWSTR lpszUserType;
  136. DPF("* in pssave *");
  137. lpdoc = ((struct CPersistStorageImpl FAR*)lpPersStg)->lpdoc;
  138. #if 0
  139. // Allow saves if we're playing so that broken links can be fixed.
  140. if (fSameAsLoad && (gfOle2IPPlaying || gfPlayingInPlace))
  141. RETURN_RESULT(S_OK);
  142. #endif
  143. //Mark as OLE1 mplayer object.
  144. #ifndef UNICODE
  145. lpszUserType = AllocateUnicodeString(gachClassRoot);
  146. #else
  147. lpszUserType = gachClassRoot;
  148. #endif
  149. error = GetScode(WriteClassStg(lpStorage, &gClsIDOLE1Compat));
  150. error = GetScode(WriteFmtUserTypeStg(lpStorage, cfMPlayer, lpszUserType));
  151. #ifndef UNICODE
  152. FreeUnicodeString(lpszUserType);
  153. #endif
  154. if(error != S_OK)
  155. RETURN_RESULT(error);
  156. error = GetScode(IStorage_CreateStream(lpStorage, sz1Ole10Native,
  157. STGM_SALL | STGM_FAILIFTHERE, 0,0, &pstm));
  158. if (error == STG_E_FILEALREADYEXISTS)
  159. {
  160. error = GetScode(IStorage_OpenStream(lpStorage, sz1Ole10Native,
  161. NULL, STGM_SALL, 0,&pstm));
  162. DPF("*pssave--openstream*");
  163. }
  164. if(pstm && (error == S_OK))
  165. hNative = GetLink();
  166. if (hNative)
  167. {
  168. lpnative = GLOBALLOCK(hNative);
  169. size = GlobalSize(hNative);
  170. }
  171. else
  172. error = E_OUTOFMEMORY;
  173. if (lpnative && (size != 0L))
  174. {
  175. error = GetScode(IStream_Write(pstm, &size, 4, &cbWritten));
  176. error = GetScode(IStream_Write(pstm, lpnative, (ULONG)size, &cbWritten));
  177. DPF("\n*After pssave write");
  178. if (cbWritten != size) error = E_FAIL ; // REVIEW SCODE stream full error
  179. IStream_Release(pstm);
  180. }
  181. CleanObject();
  182. GLOBALUNLOCK(hNative);
  183. GLOBALFREE(hNative);
  184. RETURN_RESULT(error);
  185. }
  186. /* InPowerPointSlideView
  187. *
  188. * Check the class name of the container window to see if we're in PowerPoint.
  189. * This is to support the horrible hack to get around problem of PowerPoint
  190. * crashing if we delete an empty Media Clip.
  191. *
  192. */
  193. STATICFN BOOL InPowerPointSlideView()
  194. {
  195. TCHAR ClassName[256];
  196. if (GetClassName(ghwndCntr, ClassName, CHAR_COUNT(ClassName)) > 0)
  197. {
  198. if (lstrcmp(ClassName, TEXT("paneClassDC")) == 0)
  199. {
  200. return TRUE;
  201. }
  202. }
  203. return FALSE;
  204. }
  205. STDMETHODIMP PSSaveCompleted (
  206. LPPERSISTSTORAGE lpPersStg,
  207. LPSTORAGE lpStorage
  208. )
  209. {
  210. LPDOC lpdoc;
  211. DPF("\n**pssavecompleted**");
  212. lpdoc = ((struct CPersistStorageImpl FAR*)lpPersStg)->lpdoc;
  213. /* Win95 HOT bug #11142
  214. *
  215. * Stop PowerPoint crashing horribly:
  216. */
  217. if ((gwDeviceID == 0) && InPowerPointSlideView())
  218. SendDocMsg(lpdoc, OLE_CHANGED);
  219. // inform clients that the object has been saved
  220. return SendDocMsg (lpdoc, OLE_SAVED);
  221. }
  222. STDMETHODIMP PSHandsOffStorage (
  223. LPPERSISTSTORAGE lpPersStg
  224. )
  225. {
  226. return NOERROR;
  227. }
  228. /**************************************************************************
  229. ************ IPersistFile INTERFACE IMPLEMENTATION.
  230. **************************************************************************/
  231. //delegate to common IUnknown implementation.
  232. STDMETHODIMP PFQueryInterface(
  233. LPPERSISTFILE lpPersFile, // persist storage object ptr
  234. REFIID riidReq, // IID required
  235. LPVOID FAR * lplpUnk // pre for returning the interface
  236. )
  237. {
  238. return UnkQueryInterface((LPUNKNOWN)lpPersFile, riidReq, lplpUnk);
  239. }
  240. STDMETHODIMP_(ULONG) PFAddRef(
  241. LPPERSISTFILE lpPersFile // persist storage object ptr
  242. )
  243. {
  244. return UnkAddRef((LPUNKNOWN) lpPersFile);
  245. }
  246. STDMETHODIMP_(ULONG) PFRelease (
  247. LPPERSISTFILE lpPersFile // persist storage object ptr
  248. )
  249. {
  250. return UnkRelease((LPUNKNOWN) lpPersFile);
  251. }
  252. STDMETHODIMP PFGetClassID (
  253. LPPERSISTFILE lpPersFile,
  254. CLSID FAR* pCid
  255. )
  256. {
  257. DPF("\n* PFGetclassid");
  258. /* The docs are confusing here, but apparently IPersist interfaces
  259. * should return the old class ID:
  260. */
  261. *pCid = gClsIDOLE1Compat;
  262. return NOERROR;
  263. }
  264. STDMETHODIMP PFIsDirty (
  265. LPPERSISTFILE lpPersFile
  266. )
  267. {
  268. RETURN_RESULT( gfDirty ? S_OK : S_FALSE);
  269. }
  270. //This will be called when the user does a "Insert->Create from file".
  271. //Open the file with OpenMciDevice and we will be ready to transfer the
  272. //object.
  273. STDMETHODIMP PFLoad (
  274. LPPERSISTFILE lpPersFile,
  275. LPCWSTR lpszFileName,
  276. DWORD grfMode
  277. )
  278. {
  279. LPDOC lpdoc;
  280. TCHAR szFileName[256];
  281. lpdoc = ((struct CPersistStorageImpl FAR*)lpPersFile)->lpdoc;
  282. DPF("\n***IN PFLOAD: "DTS"\n", lpszFileName);
  283. #if UNICODE
  284. lstrcpy(szFileName, lpszFileName);
  285. #else
  286. UnicodeToAnsiString(lpszFileName, szFileName, UNKNOWN_LENGTH);
  287. #endif
  288. if(OpenMciDevice(szFileName, NULL))
  289. RETURN_RESULT(S_OK);
  290. else
  291. RETURN_RESULT(E_FAIL);
  292. }
  293. STDMETHODIMP PFSave (
  294. LPPERSISTFILE lpPersFile,
  295. LPCWSTR lpszFileName,
  296. BOOL fRemember
  297. )
  298. {
  299. return NOERROR;
  300. }
  301. STDMETHODIMP PFSaveCompleted (
  302. LPPERSISTFILE lpPersFile,
  303. LPCWSTR lpszFileName
  304. )
  305. {
  306. LPDOC lpdoc;
  307. lpdoc = ((struct CPersistStorageImpl FAR*)lpPersFile)->lpdoc;
  308. // inform clients that the object has been saved
  309. return SendDocMsg(lpdoc, OLE_SAVED);
  310. }
  311. STDMETHODIMP PFGetCurFile (
  312. LPPERSISTFILE lpPersFile,
  313. LPWSTR FAR* lplpszFileName
  314. )
  315. {
  316. RETURN_RESULT( E_NOTIMPL);
  317. }
  318.