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.

1266 lines
38 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 1992.
  5. //
  6. // File: docfile.c
  7. //
  8. // Contents: DocFile root functions (Stg* functions)
  9. //
  10. // History: 10-Dec-91 DrewB Created
  11. //
  12. //---------------------------------------------------------------
  13. #include <exphead.cxx>
  14. #pragma hdrstop
  15. #include <rpubdf.hxx>
  16. #include <expdf.hxx>
  17. #include <expst.hxx>
  18. #include <dfentry.hxx>
  19. #include <logfile.hxx>
  20. #include <dirfunc.hxx>
  21. #include <wdocfile.hxx>
  22. #include <ole2sp.h>
  23. #include <ole2com.h>
  24. #include <hkole32.h>
  25. #ifdef COORD
  26. #include <resource.hxx>
  27. #endif
  28. #ifdef _MAC
  29. #include <ole2sp.h>
  30. #endif
  31. HRESULT IsNffAppropriate(const LPCWSTR pwcsName);
  32. //+--------------------------------------------------------------
  33. //
  34. // Function: DfFromLB, private
  35. //
  36. // Synopsis: Starts a root Docfile on an ILockBytes
  37. //
  38. // Arguments: [plst] - LStream to start on
  39. // [df] - Permissions
  40. // [dwStartFlags] - Startup flags
  41. // [snbExclude] - Partial instantiation list
  42. // [ppdfExp] - DocFile return
  43. // [pcid] - Class ID return for opens
  44. //
  45. // Returns: Appropriate status code
  46. //
  47. // Modifies: [ppdfExp]
  48. // [pcid]
  49. //
  50. // History: 19-Mar-92 DrewB Created
  51. // 18-May-93 AlexT Added pMalloc
  52. //
  53. // Algorithm: Create and initialize a root transaction level
  54. // Create and initialize a public docfile
  55. // Create and initialize an exposed docfile
  56. //
  57. //---------------------------------------------------------------
  58. #ifdef COORD
  59. SCODE DfFromLB(CPerContext *ppc,
  60. ILockBytes *plst,
  61. DFLAGS df,
  62. DWORD dwStartFlags,
  63. SNBW snbExclude,
  64. ITransaction *pTransaction,
  65. CExposedDocFile **ppdfExp,
  66. CLSID *pcid)
  67. #else
  68. SCODE DfFromLB(CPerContext *ppc,
  69. ILockBytes *plst,
  70. DFLAGS df,
  71. DWORD dwStartFlags,
  72. SNBW snbExclude,
  73. CExposedDocFile **ppdfExp,
  74. CLSID *pcid)
  75. #endif //COORD
  76. {
  77. SCODE sc, scConv;
  78. CRootPubDocFile *prpdf;
  79. #ifdef COORD
  80. CPubDocFile *ppubdf;
  81. CPubDocFile *ppubReturn;
  82. CWrappedDocFile *pwdf;
  83. CDocfileResource *pdfr = NULL;
  84. #endif
  85. CDFBasis *pdfb;
  86. ULONG ulOpenLock;
  87. IMalloc *pMalloc = ppc->GetMalloc();
  88. ppc->AddRef();
  89. olDebugOut((DEB_ITRACE, "In DfFromLB(%p, %p, %X, %lX, %p, %p, %p)\n",
  90. pMalloc, plst, df, dwStartFlags, snbExclude, ppdfExp, pcid));
  91. //Take the mutex in the CPerContext, in case there is an IFillLockBytes
  92. // trying to write data while we're trying to open.
  93. CSafeSem _ss(ppc);
  94. olChk(_ss.Take());
  95. #ifdef CHECKCID
  96. ULONG cbRead;
  97. olChk(plst->ReadAt(CBCLSIDOFFSET, pcid, sizeof(CLSID), &cbRead));
  98. if (cbRead != sizeof(CLSID))
  99. olErr(EH_Err, STG_E_INVALIDHEADER);
  100. if (!REFCLSIDEQ(*pcid, DOCFILE_CLASSID))
  101. olErr(EH_Err, STG_E_INVALIDHEADER);
  102. #endif
  103. #ifdef COORD
  104. if (pTransaction != NULL)
  105. {
  106. //If we've passed in an ITransaction pointer, it indicates that we
  107. // want to open or create this docfile as part of a coordinated
  108. // transaction. First, we need to find out if there's a docfile
  109. // resource manager for that transaction currently existing in
  110. // this process.
  111. //First, check if we're opening transacted. If we aren't, then we're
  112. // not going to allow this docfile to participate in the
  113. // transaction.
  114. if (!P_TRANSACTED(df))
  115. {
  116. //Is this the right error?
  117. olErr(EH_Err, STG_E_INVALIDFUNCTION);
  118. }
  119. XACTTRANSINFO xti;
  120. olChk(pTransaction->GetTransactionInfo(&xti));
  121. EnterCriticalSection(&g_csResourceList);
  122. CDocfileResource *pdfrTemp = g_dfrHead.GetNext();
  123. while (pdfrTemp != NULL)
  124. {
  125. if (IsEqualBOID(pdfrTemp->GetUOW(), xti.uow))
  126. {
  127. //Direct hit.
  128. pdfr = pdfrTemp;
  129. break;
  130. }
  131. pdfrTemp = pdfrTemp->GetNext();
  132. }
  133. if (pdfr == NULL)
  134. {
  135. ITransactionCoordinator *ptc;
  136. //If there isn't, we need to create one.
  137. olChkTo(EH_cs, pTransaction->QueryInterface(
  138. IID_ITransactionCoordinator,
  139. (void **)&ptc));
  140. pdfr = new CDocfileResource;
  141. if (pdfr == NULL)
  142. {
  143. ptc->Release();
  144. olErr(EH_cs, STG_E_INSUFFICIENTMEMORY);
  145. }
  146. sc = pdfr->Enlist(ptc);
  147. ptc->Release();
  148. if (FAILED(sc))
  149. {
  150. pdfr->Release();;
  151. olErr(EH_cs, sc);
  152. }
  153. //Add to list.
  154. pdfr->SetNext(g_dfrHead.GetNext());
  155. if (g_dfrHead.GetNext() != NULL)
  156. g_dfrHead.GetNext()->SetPrev(pdfr);
  157. g_dfrHead.SetNext(pdfr);
  158. pdfr->SetPrev(&g_dfrHead);
  159. }
  160. else
  161. {
  162. //We'll release this reference below.
  163. pdfr->AddRef();
  164. }
  165. LeaveCriticalSection(&g_csResourceList);
  166. }
  167. #endif
  168. // Make root
  169. olMem(prpdf = new (pMalloc) CRootPubDocFile(pMalloc));
  170. olChkTo(EH_prpdf, scConv = prpdf->InitRoot(plst, dwStartFlags, df,
  171. snbExclude, &pdfb,
  172. &ulOpenLock,
  173. ppc->GetGlobal()));
  174. #ifdef COORD
  175. if (pTransaction != NULL)
  176. {
  177. //Set up a fake transaction level at the root. A pointer to
  178. // this will be held by the resource manager. The storage pointer
  179. // that is passed back to the caller will be a pointer to the
  180. // transaction level (non-root) below it. This will allow the
  181. // client to write and commit as many times as desired without
  182. // the changes ever actually hitting the file.
  183. CDfName dfnNull; // auto-initialized to 0
  184. WCHAR wcZero = 0;
  185. dfnNull.Set(2, (BYTE *)&wcZero);
  186. olMemTo(EH_prpdfInit, pwdf = new (pMalloc) CWrappedDocFile(
  187. &dfnNull,
  188. ROOT_LUID,
  189. (df & ~DF_INDEPENDENT),
  190. pdfb,
  191. NULL));
  192. olChkTo(EH_pwdf, pwdf->Init(prpdf->GetDF()));
  193. prpdf->GetDF()->AddRef();
  194. olMemTo(EH_pwdfInit, ppubdf = new (pMalloc) CPubDocFile(
  195. prpdf,
  196. pwdf,
  197. (df | DF_COORD) & ~DF_INDEPENDENT,
  198. ROOT_LUID,
  199. pdfb,
  200. &dfnNull,
  201. 2,
  202. pdfb->GetBaseMultiStream()));
  203. olChkTo(EH_ppubdf, pwdf->InitPub(ppubdf));
  204. ppubdf->AddXSMember(NULL, pwdf, ROOT_LUID);
  205. ppubReturn = ppubdf;
  206. }
  207. else
  208. {
  209. ppubReturn = prpdf;
  210. }
  211. #endif //COORD
  212. ppc->SetILBInfo(pdfb->GetBase(),
  213. pdfb->GetDirty(),
  214. pdfb->GetOriginal(),
  215. ulOpenLock);
  216. ppc->SetLockInfo(ulOpenLock != 0, df);
  217. // Make exposed
  218. #ifdef COORD
  219. //We don't need to AddRef ppc since it starts with a refcount of 1.
  220. olMemTo(EH_ppcInit,
  221. *ppdfExp = new (pMalloc) CExposedDocFile(
  222. ppubReturn,
  223. pdfb,
  224. ppc));
  225. if (pTransaction != NULL)
  226. {
  227. CExposedDocFile *pexpdf;
  228. olMemTo(EH_ppcInit, pexpdf = new (pMalloc) CExposedDocFile(
  229. prpdf,
  230. pdfb,
  231. ppc));
  232. ppc->AddRef();
  233. sc = pdfr->Join(pexpdf);
  234. if (FAILED(sc))
  235. {
  236. pexpdf->Release();
  237. olErr(EH_ppcInit, sc);
  238. }
  239. pdfr->Release();
  240. }
  241. #else
  242. olMemTo(EH_ppcInit,
  243. *ppdfExp = new (pMalloc) CExposedDocFile(
  244. prpdf,
  245. pdfb,
  246. ppc));
  247. #endif //COORD
  248. olDebugOut((DEB_ITRACE, "Out DfFromLB => %p\n", *ppdfExp));
  249. return scConv;
  250. EH_ppcInit:
  251. // The context will release this but we want to keep it around
  252. // so take a reference
  253. pdfb->GetOriginal()->AddRef();
  254. pdfb->GetBase()->AddRef();
  255. pdfb->GetDirty()->AddRef();
  256. if (ulOpenLock > 0 && ppc->GetGlobal() == NULL)
  257. {
  258. // The global context doesn't exist, so we need to release
  259. // the open lock explicitly.
  260. ReleaseOpen(pdfb->GetOriginal(), df, ulOpenLock);
  261. }
  262. // The open lock has now been released (either explicitly or by ppc)
  263. ulOpenLock = 0;
  264. #ifdef COORD
  265. EH_ppubdf:
  266. if (pTransaction != NULL)
  267. {
  268. ppubdf->vRelease();
  269. }
  270. EH_pwdfInit:
  271. if (pTransaction != NULL)
  272. {
  273. prpdf->GetDF()->Release();
  274. }
  275. EH_pwdf:
  276. if (pTransaction != NULL)
  277. {
  278. pwdf->Release();
  279. }
  280. EH_prpdfInit:
  281. #endif //COORD
  282. pdfb->GetDirty()->Release();
  283. pdfb->GetBase()->Release();
  284. if (ulOpenLock > 0)
  285. ReleaseOpen(pdfb->GetOriginal(), df, ulOpenLock);
  286. pdfb->SetDirty(NULL);
  287. pdfb->SetBase(NULL);
  288. EH_prpdf:
  289. prpdf->ReleaseLocks(plst);
  290. prpdf->vRelease();
  291. #ifdef COORD
  292. if ((pTransaction != NULL) && (pdfr != NULL))
  293. {
  294. pdfr->Release();
  295. }
  296. goto EH_Err;
  297. EH_cs:
  298. LeaveCriticalSection(&g_csResourceList);
  299. #endif
  300. EH_Err:
  301. ppc->Release();
  302. return sc;
  303. }
  304. //+--------------------------------------------------------------
  305. //
  306. // Function: DfFromName, private
  307. //
  308. // Synopsis: Starts a root DocFile from a base name
  309. //
  310. // Arguments: [pwcsName] - Name
  311. // [df] - Permissions
  312. // [dwStartFlags] - Startup flags
  313. // [snbExclude] - Partial instantiation list
  314. // [ppdfExp] - Docfile return
  315. // [pcid] - Class ID return for opens
  316. //
  317. // Returns: Appropriate status code
  318. //
  319. // Modifies: [ppdfExp]
  320. // [pcid]
  321. //
  322. // History: 19-Mar-92 DrewB Created
  323. // 18-May-93 AlexT Add per file allocator
  324. //
  325. // Notes: [pwcsName] is treated as unsafe memory
  326. //
  327. //---------------------------------------------------------------
  328. // This set of root startup flags is handled by the multistream
  329. // and doesn't need to be set for filestreams
  330. #define RSF_MSF (RSF_CONVERT | RSF_TRUNCATE | RSF_ENCRYPTED)
  331. #ifdef COORD
  332. SCODE DfFromName(WCHAR const *pwcsName,
  333. DFLAGS df,
  334. DWORD dwStartFlags,
  335. SNBW snbExclude,
  336. ITransaction *pTransaction,
  337. CExposedDocFile **ppdfExp,
  338. ULONG *pulSectorSize,
  339. CLSID *pcid)
  340. #else
  341. SCODE DfFromName(WCHAR const *pwcsName,
  342. DFLAGS df,
  343. DWORD dwStartFlags,
  344. SNBW snbExclude,
  345. CExposedDocFile **ppdfExp,
  346. ULONG *pulSectorSize,
  347. CLSID *pcid)
  348. #endif
  349. {
  350. IMalloc *pMalloc;
  351. CFileStream *plst;
  352. CPerContext *ppc;
  353. CFileStream *plst2 = NULL;
  354. SCODE sc;
  355. CMSFHeader *phdr = NULL;
  356. BOOL fCreated;
  357. olDebugOut((DEB_ITRACE, "In DfFromName(%ws, %lX, %lX, %p, %p, %p)\n",
  358. pwcsName, df, dwStartFlags, snbExclude, ppdfExp, pcid));
  359. olHChk(DfCreateSharedAllocator(&pMalloc, df & DF_LARGE));
  360. // Start an ILockBytes from the named file
  361. olMemTo(EH_Malloc, plst = new (pMalloc) CFileStream(pMalloc));
  362. olChkTo(EH_plst, plst->InitGlobal(dwStartFlags & ~RSF_MSF, df));
  363. sc = plst->InitFile(pwcsName);
  364. fCreated = SUCCEEDED(sc) &&
  365. ((dwStartFlags & RSF_CREATE) || pwcsName == NULL);
  366. if (sc == STG_E_FILEALREADYEXISTS && (dwStartFlags & RSF_MSF))
  367. {
  368. plst->SetStartFlags(dwStartFlags & ~(RSF_MSF | RSF_CREATE));
  369. sc = plst->InitFile(pwcsName);
  370. }
  371. olChkTo(EH_plst, sc);
  372. if (!(dwStartFlags & RSF_CREATE))
  373. {
  374. ULONG cbDiskSector = (dwStartFlags & RSF_NO_BUFFERING) ?
  375. plst->GetSectorSize() : HEADERSIZE;
  376. olMemTo (EH_plstInit, phdr = (CMSFHeader*) TaskMemAlloc (cbDiskSector));
  377. ULARGE_INTEGER ulOffset = {0,0};
  378. ULONG ulRead;
  379. olChkTo (EH_plstInit, plst->ReadAt(ulOffset,phdr,cbDiskSector,&ulRead));
  380. if (ulRead < sizeof(CMSFHeaderData))
  381. olErr (EH_plstInit, STG_E_FILEALREADYEXISTS);
  382. sc = phdr->Validate();
  383. if (sc == STG_E_INVALIDHEADER)
  384. sc = STG_E_FILEALREADYEXISTS;
  385. olChkTo (EH_plstInit, sc);
  386. if (phdr->GetSectorShift() > SECTORSHIFT512)
  387. {
  388. IMalloc *pMalloc2 = NULL;
  389. CGlobalFileStream *pgfst = plst->GetGlobal();
  390. #ifdef MULTIHEAP
  391. CSharedMemoryBlock *psmb;
  392. BYTE *pbBase;
  393. ULONG ulHeapName;
  394. #endif
  395. df |= DF_LARGE; // reallocate objects from task memory
  396. dwStartFlags |= (phdr->GetSectorShift() <<12) & RSF_SECTORSIZE_MASK;
  397. // create and initialize the task allocator
  398. #ifdef MULTIHEAP
  399. g_smAllocator.GetState (&psmb, &pbBase, &ulHeapName);
  400. #endif
  401. olChkTo(EH_taskmem, DfCreateSharedAllocator(&pMalloc2, TRUE));
  402. pMalloc->Release();
  403. pMalloc = pMalloc2;
  404. olMemTo(EH_taskmem, plst2 = new (pMalloc2) CFileStream(pMalloc2));
  405. olChkTo(EH_taskmem, plst2->InitGlobal(dwStartFlags & ~RSF_MSF, df));
  406. plst2->InitFromFileStream (plst);
  407. plst2->GetGlobal()->InitFromGlobalFileStream (pgfst);
  408. #ifdef MULTIHEAP
  409. g_smAllocator.SetState (psmb, pbBase, ulHeapName, NULL, NULL);
  410. g_smAllocator.Uninit(); // unmap newly created heap
  411. g_smAllocator.SetState (NULL, NULL, 0, NULL, NULL);
  412. #endif
  413. plst = plst2; // CFileStream was destroyed by Uninit
  414. }
  415. TaskMemFree ((BYTE*)phdr);
  416. phdr = NULL;
  417. }
  418. //Create the per context
  419. olMemTo(EH_plstInit, ppc = new (pMalloc) CPerContext(pMalloc));
  420. olChkTo(EH_ppc, ppc->InitNewContext());
  421. {
  422. #ifdef MULTIHEAP
  423. CSafeMultiHeap smh(ppc);
  424. #endif
  425. // Start up the docfile
  426. #ifdef COORD
  427. sc = DfFromLB(ppc, plst, df, dwStartFlags,
  428. snbExclude, pTransaction,
  429. ppdfExp, pcid);
  430. #else
  431. sc = DfFromLB(ppc, plst, df, dwStartFlags,
  432. snbExclude, ppdfExp, pcid);
  433. #endif //COORD
  434. //Either DfFromLB has AddRef'ed the per context or it has failed.
  435. //Either way we want to release our reference here.
  436. LONG lRet;
  437. lRet = ppc->Release();
  438. #ifdef MULTIHEAP
  439. olAssert((FAILED(sc)) || (lRet != 0));
  440. #endif
  441. if (FAILED(sc))
  442. {
  443. if (fCreated || ((dwStartFlags & RSF_CREATE) && !P_TRANSACTED(df)))
  444. plst->Delete();
  445. plst->Release();
  446. #ifdef MULTIHEAP
  447. if (lRet == 0)
  448. {
  449. g_smAllocator.Uninit();
  450. }
  451. #endif
  452. }
  453. else if (pulSectorSize != NULL)
  454. {
  455. *pulSectorSize = (*ppdfExp)->GetPub()->GetBaseMS()->GetSectorSize();
  456. }
  457. }
  458. pMalloc->Release();
  459. olDebugOut((DEB_ITRACE, "Out DfFromName => %p\n", *ppdfExp));
  460. return sc;
  461. EH_ppc:
  462. delete ppc;
  463. EH_taskmem:
  464. if (plst2) plst2->Release();
  465. EH_plstInit:
  466. if (fCreated || ((dwStartFlags & RSF_CREATE) && !P_TRANSACTED(df)))
  467. plst->Delete();
  468. EH_plst:
  469. plst->Release();
  470. EH_Malloc:
  471. #ifdef MULTIHEAP
  472. g_smAllocator.Uninit(); // unmap newly created heap
  473. #endif
  474. pMalloc->Release();
  475. EH_Err:
  476. if (phdr != NULL)
  477. TaskMemFree ((BYTE*)phdr);
  478. return sc;
  479. }
  480. //+--------------------------------------------------------------
  481. //
  482. // Function: DfCreateDocfile, public
  483. //
  484. // Synopsis: Creates a root Docfile on a file
  485. //
  486. // Arguments: [pwcsName] - Filename
  487. // [grfMode] - Permissions
  488. // [reserved] - security attributes
  489. // [grfAttrs] - Win32 CreateFile attributes
  490. // [ppstgOpen] - Docfile return
  491. //
  492. // Returns: Appropriate status code
  493. //
  494. // Modifies: [ppstgOpen]
  495. //
  496. // History: 14-Jan-92 DrewB Created
  497. //
  498. //---------------------------------------------------------------
  499. STDAPI DfCreateDocfile (WCHAR const *pwcsName,
  500. #ifdef COORD
  501. ITransaction *pTransaction,
  502. #else
  503. void *pTransaction,
  504. #endif
  505. DWORD grfMode,
  506. #if WIN32 == 300
  507. LPSECURITY_ATTRIBUTES reserved,
  508. #else
  509. LPSTGSECURITY reserved,
  510. #endif
  511. ULONG ulSectorSize,
  512. DWORD grfAttrs,
  513. IStorage **ppstgOpen)
  514. {
  515. SafeCExposedDocFile pdfExp;
  516. SCODE sc;
  517. DFLAGS df;
  518. DWORD dwSectorFlag = 0;
  519. OLETRACEIN((API_StgCreateDocfile,
  520. PARAMFMT("pwcsName= %ws, grfMode= %x, reserved=%p, ppstgOpen= %p"),
  521. pwcsName, grfMode, reserved, ppstgOpen));
  522. olLog(("--------::In StgCreateDocFile(%ws, %lX, %lu, %p)\n",
  523. pwcsName, grfMode, reserved, ppstgOpen));
  524. olDebugOut((DEB_TRACE, "In StgCreateDocfile(%ws, %lX, %lu, %p)\n",
  525. pwcsName, grfMode, reserved, ppstgOpen));
  526. olAssert(sizeof(LPSTGSECURITY) == sizeof(DWORD));
  527. olChkTo(EH_BadPtr, ValidatePtrBuffer(ppstgOpen));
  528. *ppstgOpen = NULL;
  529. if (pwcsName)
  530. olChk(ValidateNameW(pwcsName, _MAX_PATH));
  531. if (reserved != 0)
  532. olErr(EH_Err, STG_E_INVALIDPARAMETER);
  533. if (grfMode & STGM_SIMPLE)
  534. {
  535. if (pTransaction != NULL)
  536. {
  537. olErr(EH_Err, STG_E_INVALIDFLAG);
  538. }
  539. if (ulSectorSize > 512)
  540. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  541. sc = DfCreateSimpDocfile(pwcsName, grfMode, 0, ppstgOpen);
  542. goto EH_Err;
  543. }
  544. olChk(VerifyPerms(grfMode, TRUE));
  545. if ((grfMode & STGM_RDWR) == STGM_READ ||
  546. (grfMode & (STGM_DELETEONRELEASE | STGM_CONVERT)) ==
  547. (STGM_DELETEONRELEASE | STGM_CONVERT))
  548. olErr(EH_Err, STG_E_INVALIDFLAG);
  549. df = ModeToDFlags(grfMode);
  550. if ((grfMode & (STGM_TRANSACTED | STGM_CONVERT)) ==
  551. (STGM_TRANSACTED | STGM_CONVERT))
  552. df |= DF_INDEPENDENT;
  553. if (ulSectorSize > 512)
  554. {
  555. df |= DF_LARGE;
  556. switch (ulSectorSize)
  557. {
  558. case 4096 : dwSectorFlag = RSF_SECTORSIZE4K; break;
  559. case 8192 : dwSectorFlag = RSF_SECTORSIZE8K; break;
  560. case 16384 : dwSectorFlag = RSF_SECTORSIZE16K; break;
  561. case 32768 : dwSectorFlag = RSF_SECTORSIZE32K; break;
  562. default : olErr (EH_Err, STG_E_INVALIDPARAMETER);
  563. }
  564. }
  565. else if (ulSectorSize != 0 && ulSectorSize != 512)
  566. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  567. #if WIN32 != 200
  568. //
  569. // When we create over NFF files, delete them first.
  570. // except when we want to preserve encryption information
  571. //
  572. if( (STGM_CREATE & grfMode) && !(FILE_ATTRIBUTE_ENCRYPTED & grfAttrs))
  573. {
  574. if( SUCCEEDED( IsNffAppropriate( pwcsName ) ) )
  575. {
  576. if(FALSE == DeleteFileW( pwcsName ) )
  577. {
  578. DWORD dwErr = GetLastError();
  579. if( dwErr != ERROR_FILE_NOT_FOUND &&
  580. dwErr != ERROR_PATH_NOT_FOUND )
  581. {
  582. olErr( EH_Err, Win32ErrorToScode( dwErr ) );
  583. }
  584. }
  585. }
  586. }
  587. #endif // _CHICAGO_
  588. DfInitSharedMemBase();
  589. #ifdef COORD
  590. olChk(sc = DfFromName(pwcsName, df,
  591. RSF_CREATE |
  592. ((grfMode & STGM_CREATE) ? RSF_TRUNCATE : 0) |
  593. ((grfMode & STGM_CONVERT) ? RSF_CONVERT : 0) |
  594. ((grfMode & STGM_DELETEONRELEASE) ?
  595. RSF_DELETEONRELEASE : 0) |
  596. (dwSectorFlag) |
  597. ((grfAttrs & FILE_FLAG_NO_BUFFERING) ?
  598. RSF_NO_BUFFERING : 0) |
  599. ((grfAttrs & FILE_ATTRIBUTE_ENCRYPTED) ?
  600. RSF_ENCRYPTED : 0),
  601. NULL, pTransaction, &pdfExp, NULL, NULL));
  602. #else
  603. olChk(sc = DfFromName(pwcsName, df,
  604. RSF_CREATE |
  605. ((grfMode & STGM_CREATE) ? RSF_TRUNCATE : 0) |
  606. ((grfMode & STGM_CONVERT) ? RSF_CONVERT : 0) |
  607. ((grfMode & STGM_DELETEONRELEASE) ?
  608. RSF_DELETEONRELEASE : 0) |
  609. (dwSectorFlag) |
  610. ((grfAttrs & FILE_FLAG_NO_BUFFERING) ?
  611. RSF_NO_BUFFERING : 0) |
  612. ((grfAttrs & FILE_ATTRIBUTE_ENCRYPTED) ?
  613. RSF_ENCRYPTED : 0),
  614. NULL, &pdfExp, NULL, NULL));
  615. #endif //COORD
  616. TRANSFER_INTERFACE(pdfExp, IStorage, ppstgOpen);
  617. EH_Err:
  618. olDebugOut((DEB_TRACE, "Out StgCreateDocfile => %p, ret == %lx\n",
  619. *ppstgOpen, sc));
  620. olLog(("--------::Out StgCreateDocFile(). *ppstgOpen == %p, ret == %lx\n",
  621. *ppstgOpen, sc));
  622. OLETRACEOUT(( API_StgCreateDocfile, _OLERETURN(sc)));
  623. EH_BadPtr:
  624. FreeLogFile();
  625. return _OLERETURN(sc);
  626. }
  627. //+--------------------------------------------------------------
  628. //
  629. // Function: StgCreateDocfile, public
  630. //
  631. // Synopsis: Creates a root Docfile on a file
  632. //
  633. // Arguments: [pwcsName] - Filename
  634. // [grfMode] - Permissions
  635. // [reserved] - security attributes
  636. // [ppstgOpen] - Docfile return
  637. //
  638. // Returns: Appropriate status code
  639. //
  640. // Modifies: [ppstgOpen]
  641. //
  642. // History: 14-Jan-92 DrewB Created
  643. //
  644. //---------------------------------------------------------------
  645. STDAPI StgCreateDocfile(WCHAR const *pwcsName,
  646. DWORD grfMode,
  647. LPSTGSECURITY reserved,
  648. IStorage **ppstgOpen)
  649. {
  650. return DfCreateDocfile(pwcsName, NULL, grfMode, reserved, 0, 0, ppstgOpen);
  651. }
  652. //+--------------------------------------------------------------
  653. //
  654. // Function: StgCreateDocfileOnILockBytes, public
  655. //
  656. // Synopsis: Creates a root Docfile on an lstream
  657. //
  658. // Arguments: [plkbyt] - LStream
  659. // [grfMode] - Permissions
  660. // [reserved] - Unused
  661. // [ppstgOpen] - Docfile return
  662. //
  663. // Returns: Appropriate status code
  664. //
  665. // Modifies: [ppstgOpen]
  666. //
  667. // History: 14-Jan-92 DrewB Created
  668. //
  669. //---------------------------------------------------------------
  670. STDAPI StgCreateDocfileOnILockBytes(ILockBytes *plkbyt,
  671. DWORD grfMode,
  672. DWORD reserved,
  673. IStorage **ppstgOpen)
  674. {
  675. IMalloc *pMalloc;
  676. CPerContext *ppc;
  677. SafeCExposedDocFile pdfExp;
  678. SCODE sc;
  679. DFLAGS df;
  680. #ifdef MULTIHEAP
  681. CPerContext pcSharedMemory (NULL);
  682. #endif
  683. OLETRACEIN((API_StgCreateDocfileOnILockBytes,
  684. PARAMFMT("plkbyt= %p, grfMode= %x, reserved= %ud, ppstgOpen= %p"),
  685. plkbyt, grfMode, reserved, ppstgOpen));
  686. olLog(("--------::In StgCreateDocFileOnILockBytes(%p, %lX, %lu, %p)\n",
  687. plkbyt, grfMode, reserved, ppstgOpen));
  688. olDebugOut((DEB_TRACE, "In StgCreateDocfileOnILockBytes("
  689. "%p, %lX, %lu, %p)\n",
  690. plkbyt, grfMode, reserved, ppstgOpen));
  691. olChk(ValidatePtrBuffer(ppstgOpen));
  692. *ppstgOpen = NULL;
  693. olChk(ValidateInterface(plkbyt, IID_ILockBytes));
  694. if (reserved != 0)
  695. olErr(EH_Err, STG_E_INVALIDPARAMETER);
  696. if ((grfMode & (STGM_CREATE | STGM_CONVERT)) == 0)
  697. olErr(EH_Err, STG_E_FILEALREADYEXISTS);
  698. olChk(VerifyPerms(grfMode, TRUE));
  699. if (grfMode & STGM_DELETEONRELEASE)
  700. olErr(EH_Err, STG_E_INVALIDFUNCTION);
  701. df = ModeToDFlags(grfMode);
  702. if ((grfMode & (STGM_TRANSACTED | STGM_CONVERT)) ==
  703. (STGM_TRANSACTED | STGM_CONVERT))
  704. df |= DF_INDEPENDENT;
  705. DfInitSharedMemBase();
  706. olHChk(DfCreateSharedAllocator(&pMalloc, TRUE));
  707. #ifdef MULTIHEAP
  708. // Because a custom ILockbytes can call back into storage code,
  709. // possibly using another shared heap, we need a temporary
  710. // owner until the real CPerContext is allocated
  711. // new stack frame for CSafeMultiHeap constructor/destructor
  712. {
  713. pcSharedMemory.GetThreadAllocatorState();
  714. CSafeMultiHeap smh(&pcSharedMemory);
  715. #endif
  716. //Create the per context
  717. olMem(ppc = new (pMalloc) CPerContext(pMalloc));
  718. olChkTo(EH_ppc, ppc->InitNewContext());
  719. #ifdef COORD
  720. sc = DfFromLB(ppc, plkbyt, df,
  721. RSF_CREATE |
  722. ((grfMode & STGM_CREATE) ? RSF_TRUNCATE : 0) |
  723. ((grfMode & STGM_CONVERT) ? RSF_CONVERT : 0),
  724. NULL, NULL, &pdfExp, NULL);
  725. #else
  726. sc = DfFromLB(ppc, plkbyt, df,
  727. RSF_CREATE |
  728. ((grfMode & STGM_CREATE) ? RSF_TRUNCATE : 0) |
  729. ((grfMode & STGM_CONVERT) ? RSF_CONVERT : 0),
  730. NULL, &pdfExp, NULL);
  731. #endif //COORD
  732. pMalloc->Release();
  733. //Either DfFromLB has AddRef'ed the per context or it has failed.
  734. //Either way we want to release our reference here.
  735. ppc->Release();
  736. olChkTo(EH_Truncate, sc);
  737. TRANSFER_INTERFACE(pdfExp, IStorage, ppstgOpen);
  738. // Success; since we hold on to the ILockBytes interface,
  739. // we must take a reference to it.
  740. plkbyt->AddRef();
  741. olDebugOut((DEB_TRACE, "Out StgCreateDocfileOnILockBytes => %p\n",
  742. *ppstgOpen));
  743. #ifdef MULTIHEAP
  744. }
  745. #endif
  746. EH_Err:
  747. OLETRACEOUT((API_StgCreateDocfileOnILockBytes, ResultFromScode(sc)));
  748. olLog(("--------::Out StgCreateDocFileOnILockBytes(). "
  749. "*ppstgOpen == %p, ret == %lx\n", *ppstgOpen, sc));
  750. FreeLogFile();
  751. return ResultFromScode(sc);
  752. EH_ppc:
  753. delete ppc;
  754. goto EH_Err;
  755. EH_Truncate:
  756. if ((grfMode & STGM_CREATE) && (grfMode & STGM_TRANSACTED) == 0)
  757. {
  758. ULARGE_INTEGER ulSize;
  759. ULISet32(ulSize, 0);
  760. olHVerSucc(plkbyt->SetSize(ulSize));
  761. }
  762. goto EH_Err;
  763. }
  764. //+--------------------------------------------------------------
  765. //
  766. // Function: DfOpenDocfile, public
  767. //
  768. // Synopsis: Instantiates a root Docfile from a file,
  769. // converting if necessary
  770. //
  771. // Arguments: [pwcsName] - Name
  772. // [pstgPriority] - Priority mode reopen IStorage
  773. // [grfMode] - Permissions
  774. // [snbExclude] - Exclusions for priority reopen
  775. // [reserved] - security attributes
  776. // [grfAttrs] - Win32 CreateFile attributes
  777. // [ppstgOpen] - Docfile return
  778. //
  779. // Returns: Appropriate status code
  780. //
  781. // Modifies: [ppstgOpen]
  782. //
  783. // History: 14-Jan-92 DrewB Created
  784. //
  785. //---------------------------------------------------------------
  786. STDAPI DfOpenDocfile(OLECHAR const *pwcsName,
  787. #ifdef COORD
  788. ITransaction *pTransaction,
  789. #else
  790. void *pTransaction,
  791. #endif
  792. IStorage *pstgPriority,
  793. DWORD grfMode,
  794. SNB snbExclude,
  795. LPSTGSECURITY reserved,
  796. ULONG *pulSectorSize,
  797. DWORD grfAttrs,
  798. IStorage **ppstgOpen)
  799. {
  800. SafeCExposedDocFile pdfExp;
  801. SCODE sc;
  802. WCHAR awcName[_MAX_PATH];
  803. CLSID cid;
  804. OLETRACEIN((API_StgOpenStorage,
  805. PARAMFMT("pstgPriority= %p, grfMode= %x, snbExclude= %p, reserved= %p, ppStgOpen= %p"),
  806. pstgPriority, grfMode,snbExclude, reserved, ppstgOpen));
  807. olLog(("--------::In StgOpenStorage(%ws, %p, %lX, %p, %lu, %p)\n",
  808. pwcsName, pstgPriority, grfMode, snbExclude, reserved, ppstgOpen));
  809. olDebugOut((DEB_TRACE, "In StgOpenStorage("
  810. "%ws, %p, %lX, %p, %lu, %p)\n", pwcsName, pstgPriority,
  811. grfMode, snbExclude, reserved, ppstgOpen));
  812. olAssert(sizeof(LPSTGSECURITY) == sizeof(DWORD));
  813. olChk(ValidatePtrBuffer(ppstgOpen));
  814. *ppstgOpen = NULL;
  815. if (pstgPriority == NULL)
  816. {
  817. olChk(ValidateNameW(pwcsName, _MAX_PATH));
  818. lstrcpyW(awcName, pwcsName);
  819. }
  820. if (pstgPriority)
  821. {
  822. STATSTG stat;
  823. olChk(ValidateInterface(pstgPriority, IID_IStorage));
  824. olHChk(pstgPriority->Stat(&stat, 0));
  825. if (lstrlenW (stat.pwcsName) > _MAX_PATH)
  826. olErr (EH_Err, STG_E_INVALIDNAME);
  827. lstrcpyW(awcName, stat.pwcsName);
  828. TaskMemFree(stat.pwcsName);
  829. }
  830. #if WIN32 != 200
  831. if (grfMode & STGM_SIMPLE)
  832. {
  833. sc = DfOpenSimpDocfile(pwcsName, grfMode, 0, ppstgOpen);
  834. goto EH_Err;
  835. }
  836. #endif
  837. olChk(VerifyPerms(grfMode, TRUE));
  838. if (grfMode & (STGM_CREATE | STGM_CONVERT))
  839. olErr(EH_Err, STG_E_INVALIDFLAG);
  840. if (snbExclude)
  841. {
  842. if ((grfMode & STGM_RDWR) != STGM_READWRITE)
  843. olErr(EH_Err, STG_E_ACCESSDENIED);
  844. olChk(ValidateSNB(snbExclude));
  845. }
  846. if (reserved != 0)
  847. olErr(EH_Err, STG_E_INVALIDPARAMETER);
  848. if (grfMode & STGM_DELETEONRELEASE)
  849. olErr(EH_Err, STG_E_INVALIDFUNCTION);
  850. //Otherwise, try it as a docfile
  851. if (pstgPriority)
  852. olChk(pstgPriority->Release());
  853. DfInitSharedMemBase();
  854. #ifdef COORD
  855. olChk(DfFromName(awcName, ModeToDFlags(grfMode), RSF_OPEN |
  856. ((grfMode & STGM_DELETEONRELEASE) ?
  857. RSF_DELETEONRELEASE : 0) |
  858. ((grfAttrs & FILE_FLAG_NO_BUFFERING) ?
  859. RSF_NO_BUFFERING : 0),
  860. snbExclude, pTransaction, &pdfExp, pulSectorSize, &cid));
  861. #else
  862. olChk(DfFromName(awcName, ModeToDFlags(grfMode), RSF_OPEN |
  863. ((grfMode & STGM_DELETEONRELEASE) ?
  864. RSF_DELETEONRELEASE : 0) |
  865. ((grfAttrs & FILE_FLAG_NO_BUFFERING) ?
  866. RSF_NO_BUFFERING : 0),
  867. snbExclude, &pdfExp, pulSectorSize, &cid));
  868. #endif //COORD
  869. TRANSFER_INTERFACE(pdfExp, IStorage, ppstgOpen);
  870. olDebugOut((DEB_TRACE, "Out StgOpenStorage => %p\n", *ppstgOpen));
  871. EH_Err:
  872. olLog(("--------::Out StgOpenStorage(). *ppstgOpen == %p, ret == %lx\n",
  873. *ppstgOpen, sc));
  874. FreeLogFile();
  875. OLETRACEOUT((API_StgOpenStorage, sc));
  876. return sc;
  877. }
  878. //+--------------------------------------------------------------
  879. //
  880. // Function: StgOpenStorageOnILockBytes, public
  881. //
  882. // Synopsis: Instantiates a root Docfile from an LStream,
  883. // converting if necessary
  884. //
  885. // Arguments: [plkbyt] - Source LStream
  886. // [pstgPriority] - For priority reopens
  887. // [grfMode] - Permissions
  888. // [snbExclude] - For priority reopens
  889. // [reserved]
  890. // [ppstgOpen] - Docfile return
  891. //
  892. // Returns: Appropriate status code
  893. //
  894. // Modifies: [ppstgOpen]
  895. //
  896. // History: 14-Jan-92 DrewB Created
  897. //
  898. //---------------------------------------------------------------
  899. STDAPI StgOpenStorageOnILockBytes(ILockBytes *plkbyt,
  900. IStorage *pstgPriority,
  901. DWORD grfMode,
  902. SNB snbExclude,
  903. DWORD reserved,
  904. IStorage **ppstgOpen)
  905. {
  906. IMalloc *pMalloc;
  907. CPerContext *ppc;
  908. SCODE sc;
  909. SafeCExposedDocFile pdfExp;
  910. #ifdef MULTIHEAP
  911. CPerContext pcSharedMemory(NULL);
  912. #endif
  913. CLSID cid;
  914. OLETRACEIN((API_StgOpenStorageOnILockBytes,
  915. PARAMFMT("pstgPriority= %p, grfMode= %x, snbExclude= %p, reserved= %ud, ppstgOpen= %p"),
  916. pstgPriority, grfMode, snbExclude, reserved, ppstgOpen));
  917. olLog(("--------::In StgOpenStorageOnILockBytes("
  918. "%p, %p, %lX, %p, %lu, %p)\n",
  919. plkbyt, pstgPriority, grfMode, snbExclude, reserved, ppstgOpen));
  920. olDebugOut((DEB_TRACE, "In StgOpenStorageOnILockBytes("
  921. "%p, %p, %lX, %p, %lu, %p)\n", plkbyt, pstgPriority,
  922. grfMode, snbExclude, reserved, ppstgOpen));
  923. olChk(ValidatePtrBuffer(ppstgOpen));
  924. *ppstgOpen = NULL;
  925. olChk(ValidateInterface(plkbyt, IID_ILockBytes));
  926. if (pstgPriority)
  927. olChk(ValidateInterface(pstgPriority, IID_IStorage));
  928. olChk(VerifyPerms(grfMode, TRUE));
  929. if (grfMode & (STGM_CREATE | STGM_CONVERT))
  930. olErr(EH_Err, STG_E_INVALIDFLAG);
  931. if (grfMode & STGM_DELETEONRELEASE)
  932. olErr(EH_Err, STG_E_INVALIDFUNCTION);
  933. if (snbExclude)
  934. {
  935. if ((grfMode & STGM_RDWR) != STGM_READWRITE)
  936. olErr(EH_Err, STG_E_ACCESSDENIED);
  937. olChk(ValidateSNB(snbExclude));
  938. }
  939. if (reserved != 0)
  940. olErr(EH_Err, STG_E_INVALIDPARAMETER);
  941. if (pstgPriority)
  942. olChk(pstgPriority->Release());
  943. IFileLockBytes *pfl;
  944. if (SUCCEEDED(plkbyt->QueryInterface(IID_IFileLockBytes,
  945. (void **)&pfl)) &&
  946. ((CFileStream *)plkbyt)->GetContextPointer() != NULL)
  947. {
  948. //Someone passed us the ILockBytes we gave them from
  949. //StgGetIFillLockBytesOnFile. It already contains a
  950. //context pointer, so reuse that rather than creating
  951. //a whole new shared heap.
  952. pfl->Release();
  953. CFileStream *pfst = (CFileStream *)plkbyt;
  954. CPerContext *ppc = pfst->GetContextPointer();
  955. #ifdef MULTIHEAP
  956. CSafeMultiHeap smh(ppc);
  957. #endif
  958. #ifdef COORD
  959. olChk(DfFromLB(ppc,
  960. pfst,
  961. ModeToDFlags(grfMode),
  962. pfst->GetStartFlags(),
  963. NULL,
  964. NULL,
  965. &pdfExp,
  966. NULL));
  967. #else
  968. olChk(DfFromLB(ppc,
  969. pfst,
  970. ModeToDFlags(grfMode),
  971. pfst->GetStartFlags(),
  972. NULL,
  973. &pdfExp,
  974. NULL));
  975. #endif
  976. }
  977. else
  978. {
  979. DfInitSharedMemBase();
  980. olHChk(DfCreateSharedAllocator(&pMalloc, TRUE));
  981. #ifdef MULTIHEAP
  982. // Because a custom ILockbytes can call back into storage code,
  983. // possibly using another shared heap, we need a temporary
  984. // owner until the real CPerContext is allocated
  985. // new stack frame for CSafeMultiHeap constructor/destructor
  986. {
  987. pcSharedMemory.GetThreadAllocatorState();
  988. CSafeMultiHeap smh(&pcSharedMemory);
  989. #endif
  990. //Create the per context
  991. olMem(ppc = new (pMalloc) CPerContext(pMalloc));
  992. sc = ppc->InitNewContext();
  993. if (FAILED(sc))
  994. {
  995. delete ppc;
  996. olErr(EH_Err, sc);
  997. }
  998. #ifdef COORD
  999. sc = DfFromLB(ppc,
  1000. plkbyt, ModeToDFlags(grfMode), RSF_OPEN, snbExclude,
  1001. NULL, &pdfExp, &cid);
  1002. #else
  1003. sc = DfFromLB(ppc,
  1004. plkbyt, ModeToDFlags(grfMode), RSF_OPEN, snbExclude,
  1005. &pdfExp, &cid);
  1006. #endif //COORD
  1007. pMalloc->Release();
  1008. //Either DfFromLB has AddRef'ed the per context or it has failed.
  1009. //Either way we want to release our reference here.
  1010. ppc->Release();
  1011. olChk(sc);
  1012. #ifdef MULTIHEAP
  1013. }
  1014. #endif
  1015. }
  1016. TRANSFER_INTERFACE(pdfExp, IStorage, ppstgOpen);
  1017. // Success; since we hold on to the ILockBytes interface,
  1018. // we must take a reference to it.
  1019. plkbyt->AddRef();
  1020. olDebugOut((DEB_TRACE, "Out StgOpenStorageOnILockBytes => %p\n",
  1021. *ppstgOpen));
  1022. EH_Err:
  1023. olLog(("--------::Out StgOpenStorageOnILockBytes(). "
  1024. "*ppstgOpen == %p, ret == %lx\n", *ppstgOpen, sc));
  1025. FreeLogFile();
  1026. OLETRACEOUT((API_StgOpenStorageOnILockBytes, sc));
  1027. return sc;
  1028. }
  1029. //+---------------------------------------------------------------------------
  1030. //
  1031. // Function: DfGetClass, public
  1032. //
  1033. // Synopsis: Retrieves the class ID of the root entry of a docfile
  1034. //
  1035. // Arguments: [hFile] - Docfile file handle
  1036. // [pclsid] - Class ID return
  1037. //
  1038. // Returns: Appropriate status code
  1039. //
  1040. // Modifies: [pclsid]
  1041. //
  1042. // History: 09-Feb-94 DrewB Created
  1043. //
  1044. //----------------------------------------------------------------------------
  1045. STDAPI DfGetClass(HANDLE hFile,
  1046. CLSID *pclsid)
  1047. {
  1048. SCODE sc;
  1049. DWORD dwCb;
  1050. IMalloc *pMalloc;
  1051. CFileStream *pfst;
  1052. ULARGE_INTEGER uliOffset;
  1053. ULONG ulOpenLock, ulAccessLock;
  1054. BYTE bBuffer[sizeof(CMSFHeader)];
  1055. CMSFHeader *pmsh;
  1056. CDirEntry *pde;
  1057. olDebugOut((DEB_ITRACE, "In DfGetClass(%p, %p)\n", hFile, pclsid));
  1058. olAssert(sizeof(bBuffer) >= sizeof(CMSFHeader));
  1059. pmsh = (CMSFHeader *)bBuffer;
  1060. olAssert(sizeof(bBuffer) >= sizeof(CDirEntry));
  1061. pde = (CDirEntry *)bBuffer;
  1062. if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0)
  1063. {
  1064. olErr(EH_Err, LAST_STG_SCODE);
  1065. }
  1066. if (!ReadFile(hFile, pmsh->GetData(), sizeof(CMSFHeaderData), &dwCb, NULL))
  1067. {
  1068. olErr(EH_Err, LAST_STG_SCODE);
  1069. }
  1070. if (dwCb != sizeof(CMSFHeaderData))
  1071. {
  1072. olErr(EH_Err, STG_E_INVALIDHEADER);
  1073. }
  1074. sc = pmsh->Validate();
  1075. olChk(sc);
  1076. // Now we know it's a docfile
  1077. DfInitSharedMemBase();
  1078. olHChk(DfCreateSharedAllocator(&pMalloc, FALSE));
  1079. olMemTo(EH_pMalloc, pfst = new (pMalloc) CFileStream(pMalloc));
  1080. olChkTo(EH_pfst, pfst->InitGlobal(0, 0));
  1081. olChkTo(EH_pfst, pfst->InitFromHandle(hFile));
  1082. // Take open and access locks to ensure that we're cooperating
  1083. // with real opens
  1084. olChkTo(EH_pfst, GetOpen(pfst, DF_READ, TRUE, &ulOpenLock));
  1085. olChkTo(EH_open, GetAccess(pfst, DF_READ, &ulAccessLock));
  1086. uliOffset.HighPart = 0;
  1087. uliOffset.LowPart = (pmsh->GetDirStart() << pmsh->GetSectorShift())+
  1088. HEADERSIZE;
  1089. // The root directory entry is always the first directory entry
  1090. // in the first directory sector
  1091. // Ideally, we could read just the class ID directly into
  1092. // pclsid. In practice, all the important things are declared
  1093. // private or protected so it's easier to read the whole entry
  1094. olChkTo(EH_access, GetScode(pfst->ReadAt(uliOffset, pde,
  1095. sizeof(CDirEntry), &dwCb)));
  1096. if (dwCb != sizeof(CDirEntry))
  1097. {
  1098. sc = STG_E_READFAULT;
  1099. }
  1100. else
  1101. {
  1102. sc = S_OK;
  1103. }
  1104. *pclsid = pde->GetClassId();
  1105. olDebugOut((DEB_ITRACE, "Out DfGetClass\n"));
  1106. EH_access:
  1107. ReleaseAccess(pfst, DF_READ, ulAccessLock);
  1108. EH_open:
  1109. ReleaseOpen(pfst, DF_READ, ulOpenLock);
  1110. EH_pfst:
  1111. pfst->Release();
  1112. EH_pMalloc:
  1113. pMalloc->Release();
  1114. EH_Err:
  1115. return ResultFromScode(sc);
  1116. }