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.

474 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: msf.cxx
  7. //
  8. // Contents: Entry points for MSF DLL
  9. //
  10. // Classes: None.
  11. //
  12. // Functions: DllMuliStreamFromStream
  13. // DllConvertStreamToMultiStream
  14. // DllReleaseMultiStream
  15. // DllGetScratchMultiStream
  16. // DllIsMultiStream
  17. //
  18. // History: 17-Aug-91 PhilipLa Created.
  19. //
  20. //--------------------------------------------------------------------------
  21. #include "msfhead.cxx"
  22. #pragma hdrstop
  23. #include <handle.hxx>
  24. #include <filelkb.hxx>
  25. #include <ole.hxx>
  26. #include <entry.hxx>
  27. #include <smalloc.hxx>
  28. //+-------------------------------------------------------------------------
  29. //
  30. // Function: DllMultiStreamFromStream
  31. //
  32. // Synopsis: Create a new multistream instance from an existing stream.
  33. // This is used to reopen a stored multi-stream.
  34. //
  35. // Effects: Creates a new CMStream instance
  36. //
  37. // Arguments: [ppms] -- Pointer to storage for return of multistream
  38. // [pplstStream] -- Stream to be used by multi-stream for
  39. // reads and writes
  40. // [dwFlags] - Startup flags
  41. //
  42. // Returns: STG_E_INVALIDHEADER if signature on pStream does not
  43. // match.
  44. // STG_E_UNKNOWN if there was a problem in setup.
  45. // S_OK if call completed OK.
  46. //
  47. // Algorithm: Check the signature on the pStream and on the contents
  48. // of the pStream. If either is a mismatch, return
  49. // STG_E_INVALIDHEADER.
  50. // Create a new CMStream instance and run the setup function.
  51. // If the setup function fails, return STG_E_UNKNOWN.
  52. // Otherwise, return S_OK.
  53. //
  54. // History: 17-Aug-91 PhilipLa Created.
  55. //
  56. // Notes:
  57. //
  58. //--------------------------------------------------------------------------
  59. SCODE DllMultiStreamFromStream(IMalloc *pMalloc,
  60. CMStream **ppms,
  61. ILockBytes **pplstStream,
  62. DWORD dwStartFlags,
  63. DFLAGS df)
  64. {
  65. SCODE sc;
  66. CMStream *temp;
  67. BOOL fConvert = ((dwStartFlags & RSF_CONVERT) != 0);
  68. BOOL fDelay = ((dwStartFlags & RSF_DELAY) != 0);
  69. BOOL fTruncate = ((dwStartFlags & RSF_TRUNCATE) != 0);
  70. BOOL fCreate = ((dwStartFlags & RSF_CREATE) != 0);
  71. msfDebugOut((DEB_ITRACE,"In DllMultiStreamFromStream\n"));
  72. #ifdef USE_NOSCRATCH
  73. msfMem(temp = new (pMalloc)
  74. CMStream(pMalloc, pplstStream,
  75. FALSE,
  76. (df & ~DF_NOSCRATCH),
  77. (dwStartFlags & RSF_SECTORSIZE_MASK) ?
  78. (USHORT)((dwStartFlags & RSF_SECTORSIZE_MASK) >> 12) :
  79. SECTORSHIFT512));
  80. #else
  81. msfMem(temp = new (pMalloc)
  82. CMStream(pMalloc, pplstStream,
  83. FALSE,
  84. (dwStartFlags & RSF_SECTORSIZE_MASK) ?
  85. (USHORT)((dwStartFlags & RSF_SECTORSIZE_MASK) >> 12) :
  86. SECTORSHIFT512));
  87. #endif //USE_NOSCRATCH
  88. STATSTG stat;
  89. HRESULT hr;
  90. IFileLockBytes *pfl;
  91. // ILockBytes::Stat is an expensive operation; for our own file
  92. // stream we call our faster GetSize method.
  93. if (SUCCEEDED((*pplstStream)->QueryInterface(IID_IFileLockBytes,
  94. (void**) &pfl)))
  95. {
  96. msfAssert(pfl != NULL &&
  97. aMsg("ILockBytes::QueryInterface succeeded but returned NULL"));
  98. hr = pfl->GetSize(&stat.cbSize);
  99. pfl->Release();
  100. }
  101. else
  102. hr = (*pplstStream)->Stat(&stat, STATFLAG_NONAME);
  103. msfHChk(hr);
  104. msfDebugOut((DEB_ITRACE,"Size is: %lu\n",ULIGetLow(stat.cbSize)));
  105. do
  106. {
  107. if ((stat.cbSize.QuadPart != 0) && (fConvert))
  108. {
  109. msfChk(temp->InitConvert(fDelay));
  110. break;
  111. }
  112. if ((stat.cbSize.QuadPart == 0 && fCreate) || (fTruncate))
  113. {
  114. msfChk(temp->InitNew(fDelay, stat.cbSize));
  115. break;
  116. }
  117. msfChk(temp->Init());
  118. }
  119. while (FALSE);
  120. *ppms = temp;
  121. msfDebugOut((DEB_ITRACE,"Leaving DllMultiStreamFromStream\n"));
  122. if (fConvert && (stat.cbSize.QuadPart != 0) && !fDelay)
  123. {
  124. return STG_S_CONVERTED;
  125. }
  126. return S_OK;
  127. Err:
  128. #if !defined(MULTIHEAP)
  129. //take the mutex here instead of in the allocator.
  130. g_smAllocator.GetMutex()->Take(DFM_TIMEOUT);
  131. #endif
  132. delete temp;
  133. #if !defined(MULTIHEAP)
  134. g_smAllocator.GetMutex()->Release();
  135. #endif
  136. return sc;
  137. }
  138. //+-------------------------------------------------------------------------
  139. //
  140. // Function: DllReleaseMultiStream
  141. //
  142. // Synopsis: Release a CMStream instance
  143. //
  144. // Effects: Deletes a multi-stream instance
  145. //
  146. // Arguments: [pms] -- pointer to object to be deleted
  147. //
  148. // Returns: S_OK.
  149. //
  150. // Modifies: Deletes the object pointed to by pMultiStream
  151. //
  152. // Algorithm: Delete the passed in pointer.
  153. //
  154. // History: 17-Aug-91 PhilipLa Created.
  155. //
  156. // Notes:
  157. //
  158. //--------------------------------------------------------------------------
  159. void DllReleaseMultiStream(CMStream *pms)
  160. {
  161. msfDebugOut((DEB_ITRACE,"In DllReleaseMultiStream(%p)\n",pms));
  162. #if !defined(MULTIHEAP)
  163. //take the mutex here instead of in the allocator.
  164. g_smAllocator.GetMutex()->Take(DFM_TIMEOUT);
  165. #endif
  166. delete pms;
  167. #if !defined(MULTIHEAP)
  168. g_smAllocator.GetMutex()->Release();
  169. #endif
  170. msfDebugOut((DEB_ITRACE,"Out DllReleaseMultiStream()\n"));
  171. }
  172. //+-------------------------------------------------------------------------
  173. //
  174. // Function: DllGetScratchMultiStream
  175. //
  176. // Synopsis: Get a scratch multistream for a given LStream
  177. //
  178. // Effects: Creates new MStream instance and new handle
  179. //
  180. // Arguments: [ppms] -- pointer to location in which root
  181. // handle is to be returned.
  182. // [pplstStream] -- pointer to LStream object to be used
  183. // [pmsMaster] - Multistream to pattern scratch after
  184. //
  185. // Returns: S_OK if call completed OK.
  186. // STG_E_UNKNOWN if there was a problem in setup.
  187. //
  188. // Algorithm: *Finish This*
  189. //
  190. // History: 08-Jan-91 PhilipLa Created.
  191. //
  192. // Notes:
  193. //
  194. //--------------------------------------------------------------------------
  195. SCODE DllGetScratchMultiStream(CMStream **ppms,
  196. #ifdef USE_NOSCRATCH
  197. BOOL fIsNoScratch,
  198. #endif
  199. ILockBytes **pplstStream,
  200. CMStream *pmsMaster)
  201. {
  202. msfDebugOut((DEB_ITRACE,"In DllGetScratchMultiStream(%p,%p,%p)\n",ppms,pplstStream,pmsMaster));
  203. SCODE sc;
  204. ULARGE_INTEGER uliZero;
  205. CMStream *temp = NULL;
  206. #ifdef USE_NOSCRATCH
  207. msfMem(temp = new (pmsMaster->GetMalloc())
  208. CMStream(pmsMaster->GetMalloc(), pplstStream,
  209. TRUE,
  210. (fIsNoScratch) ? DF_NOSCRATCH : 0,
  211. SCRATCHSECTORSHIFT));
  212. #else
  213. msfMem(temp = new (pmsMaster->GetMalloc())
  214. CMStream(pmsMaster->GetMalloc(), pplstStream,
  215. TRUE,
  216. SCRATCHSECTORSHIFT));
  217. #endif
  218. ULISetHigh(uliZero, 0);
  219. ULISetLow(uliZero, 0);
  220. msfChk(temp->InitNew(FALSE, uliZero));
  221. *ppms = temp;
  222. msfDebugOut((DEB_ITRACE,"Out DllGetScratchMultiStream()\n"));
  223. return S_OK;
  224. Err:
  225. #if !defined(MULTIHEAP)
  226. //take the mutex here instead of in the allocator
  227. g_smAllocator.GetMutex()->Take(DFM_TIMEOUT);
  228. #endif
  229. delete temp;
  230. #if !defined(MULTIHEAP)
  231. g_smAllocator.GetMutex()->Release();
  232. #endif
  233. return sc;
  234. }
  235. //+-------------------------------------------------------------------------
  236. //
  237. // Function: DllIsMultiStream
  238. //
  239. // Synopsis: Check a given Lstream to determine if it is a valid
  240. // multistream.
  241. //
  242. // Arguments: [plst] -- Pointer to lstream to check
  243. //
  244. // Returns: S_OK if lstream is a valid multistream
  245. // STG_E_UNKNOWN otherwise
  246. //
  247. // History: 20-Feb-92 PhilipLa Created.
  248. //
  249. // Notes:
  250. //
  251. //--------------------------------------------------------------------------
  252. SCODE DllIsMultiStream(ILockBytes *plst)
  253. {
  254. SCODE sc;
  255. CMSFHeader *phdr;
  256. ULONG ul;
  257. ULONG ulSectorSize = HEADERSIZE;
  258. IFileLockBytes *pfl;
  259. if (SUCCEEDED(plst->QueryInterface(IID_IFileLockBytes, (void**) &pfl)))
  260. {
  261. ulSectorSize = pfl->GetSectorSize();
  262. pfl->Release();
  263. }
  264. // CMSFHeader can be larger than a sector due to its dirty flag
  265. ul = ulSectorSize < sizeof(CMSFHeader) ? sizeof(CMSFHeader) : ulSectorSize;
  266. GetSafeBuffer(ul, ul, (BYTE **) &phdr, &ul);
  267. ULONG ulTemp;
  268. ULARGE_INTEGER ulOffset;
  269. ULISet32(ulOffset, 0);
  270. msfHChk(plst->ReadAt(
  271. ulOffset,
  272. phdr->GetData(),
  273. ulSectorSize,
  274. &ulTemp));
  275. if (ulTemp != ulSectorSize)
  276. {
  277. msfErr(Err, STG_E_UNKNOWN);
  278. }
  279. msfChk(phdr->Validate());
  280. Err:
  281. FreeBuffer((BYTE *) phdr);
  282. return sc;
  283. }
  284. //+-------------------------------------------------------------------------
  285. //
  286. // Function: DllSetCommitSig
  287. //
  288. // Synopsis: Set the commit signature on a given lstream, for use
  289. // in OnlyIfCurrent support
  290. //
  291. // Arguments: [plst] -- Pointer to the LStream to modify.
  292. // [sig] -- New signature
  293. //
  294. // Returns: S_OK if call completed OK.
  295. //
  296. // Algorithm:
  297. //
  298. // History: 22-Apr-92 PhilipLa Created.
  299. //
  300. // Notes:
  301. //
  302. //--------------------------------------------------------------------------
  303. SCODE DllSetCommitSig(ILockBytes *plst, DFSIGNATURE sig)
  304. {
  305. SCODE sc;
  306. CMSFHeader *phdr;
  307. ULONG ul;
  308. ULONG ulSectorSize = HEADERSIZE;
  309. IFileLockBytes *pfl;
  310. if (SUCCEEDED(plst->QueryInterface(IID_IFileLockBytes, (void**) &pfl)))
  311. {
  312. ulSectorSize = pfl->GetSectorSize();
  313. pfl->Release();
  314. }
  315. // CMSFHeader can be larger than a sector due to its dirty flag
  316. ul = ulSectorSize < sizeof(CMSFHeader) ? sizeof(CMSFHeader) : ulSectorSize;
  317. GetSafeBuffer(ul, ul, (BYTE **) &phdr, &ul);
  318. ULONG ulTemp;
  319. ULARGE_INTEGER ulOffset;
  320. ULISet32(ulOffset, 0);
  321. msfHChk(plst->ReadAt(
  322. ulOffset,
  323. phdr->GetData(),
  324. ulSectorSize,
  325. &ulTemp));
  326. if (ulTemp != ulSectorSize)
  327. {
  328. msfErr(Err, STG_E_UNKNOWN);
  329. }
  330. msfChk(phdr->Validate());
  331. phdr->SetCommitSig(sig);
  332. msfHChk(plst->WriteAt(ulOffset,
  333. phdr->GetData(),
  334. ulSectorSize,
  335. &ulTemp));
  336. if (ulTemp != ulSectorSize)
  337. {
  338. msfErr(Err,STG_E_UNKNOWN);
  339. }
  340. Err:
  341. FreeBuffer((BYTE *) phdr);
  342. return sc;
  343. }
  344. //+-------------------------------------------------------------------------
  345. //
  346. // Function: DllGetCommitSig
  347. //
  348. // Synopsis: Get the commit signature from an lstream
  349. //
  350. // Arguments: [plst] -- Pointer to lstream to be operated on
  351. // [psig] -- Storage place for signature return
  352. //
  353. // Returns: S_OK if call completed OK.
  354. //
  355. // Algorithm:
  356. //
  357. // History: 22-Apr-92 PhilipLa Created.
  358. //
  359. // Notes:
  360. //
  361. //--------------------------------------------------------------------------
  362. SCODE DllGetCommitSig(ILockBytes *plst, DFSIGNATURE *psig)
  363. {
  364. CMSFHeader *phdr;
  365. SCODE sc;
  366. ULONG ul;
  367. ULONG ulSectorSize = HEADERSIZE;
  368. IFileLockBytes *pfl;
  369. if (SUCCEEDED(plst->QueryInterface(IID_IFileLockBytes, (void**) &pfl)))
  370. {
  371. ulSectorSize = pfl->GetSectorSize();
  372. pfl->Release();
  373. }
  374. // CMSFHeader can be larger than a sector due to its dirty flag
  375. ul = ulSectorSize < sizeof(CMSFHeader) ? sizeof(CMSFHeader) : ulSectorSize;
  376. GetSafeBuffer(ul, ul, (BYTE **) &phdr, &ul);
  377. ULONG ulTemp;
  378. ULARGE_INTEGER ulOffset;
  379. ULISet32(ulOffset, 0);
  380. msfHChk(plst->ReadAt(
  381. ulOffset,
  382. phdr->GetData(),
  383. ulSectorSize,
  384. &ulTemp));
  385. if (ulTemp != ulSectorSize)
  386. {
  387. msfErr(Err, STG_E_UNKNOWN);
  388. }
  389. msfChk(phdr->Validate());
  390. *psig = phdr->GetCommitSig();
  391. Err:
  392. FreeBuffer((BYTE *) phdr);
  393. return sc;
  394. }
  395. #if DBG == 1
  396. //The following is a private function so I can set the debug level easily.
  397. VOID SetInfoLevel(ULONG x)
  398. {
  399. #if DBG == 1
  400. msfInfoLevel=x;
  401. _SetWin4InfoLevel(0xFFFFFFFF);
  402. #endif
  403. }
  404. #endif