Leaked source code of windows server 2003
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.

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