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.

1237 lines
34 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: simpstg.cxx
  7. //
  8. // Contents: SimpStorage class implementation
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 04-Aug-94 PhilipLa Created
  15. // 26-Feb-97 Danl QI support for IID_IPropertySetStorage
  16. //
  17. //----------------------------------------------------------------------------
  18. #include "simphead.cxx"
  19. #pragma hdrstop
  20. #include <ole.hxx>
  21. #include <logfile.hxx>
  22. #include <expparam.hxx>
  23. #ifdef SECURE_BUFFER
  24. BYTE s_bufSecure[MINISTREAMSIZE];
  25. #endif
  26. ULONG ConvertSect(SECT sect)
  27. {
  28. return (ULONG)(sect << SECTORSHIFT512) + SECTORSIZE;
  29. }
  30. //+---------------------------------------------------------------------------
  31. //
  32. // Member: CSimpStorage::Init, public
  33. //
  34. // Synopsis: Init function
  35. //
  36. // Arguments: [psdh] -- Pointer to hints structure
  37. //
  38. // Returns: Appropriate status code
  39. //
  40. // History: 04-Aug-94 PhilipLa Created
  41. //
  42. //----------------------------------------------------------------------------
  43. SCODE CSimpStorage::Init(WCHAR const * pwcsName, SSimpDocfileHints *psdh)
  44. {
  45. simpDebugOut((DEB_ITRACE,
  46. "In CSimpStorage::Init:%p(%ws)\n", this, pwcsName));
  47. #ifdef UNICODE
  48. TCHAR const *atcPath = pwcsName;
  49. #else
  50. TCHAR atcPath[_MAX_PATH+1];
  51. UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  52. if (!WideCharToMultiByte(
  53. uCodePage,
  54. 0,
  55. pwcsName,
  56. -1,
  57. atcPath,
  58. _MAX_PATH + 1,
  59. NULL,
  60. NULL))
  61. {
  62. return STG_E_INVALIDNAME;
  63. }
  64. #endif
  65. _hFile = CreateFileT(atcPath,
  66. GENERIC_READ | GENERIC_WRITE,
  67. 0,
  68. NULL,
  69. OPEN_ALWAYS,
  70. FILE_ATTRIBUTE_NORMAL,
  71. NULL);
  72. if (_hFile == INVALID_HANDLE_VALUE)
  73. {
  74. return STG_SCODE(GetLastError());
  75. }
  76. if (FALSE == SetEndOfFile (_hFile))
  77. {
  78. return STG_SCODE(GetLastError());
  79. }
  80. _sectMax = 0;
  81. //From this point on, we need to try to produce a docfile.
  82. _fDirty = TRUE;
  83. _clsid = IID_NULL;
  84. #ifdef SECURE_SIMPLE_MODE
  85. memset(s_bufSecure, SECURECHAR, MINISTREAMSIZE);
  86. #endif
  87. simpDebugOut((DEB_ITRACE, "Out CSimpStorage::Init\n"));
  88. return S_OK;
  89. }
  90. //+--------------------------------------------------------------
  91. //
  92. // Member: CSimpStorage::Release, public
  93. //
  94. // Synopsis: Releases resources for a CSimpStorage
  95. //
  96. // Returns: Appropriate status code
  97. //
  98. // History: 04-Aug-94 PhilipLa Created
  99. //
  100. //---------------------------------------------------------------
  101. STDMETHODIMP_(ULONG) CSimpStorage::Release(void)
  102. {
  103. LONG lRet;
  104. olLog(("%p::In CSimpStorage::Release()\n", this));
  105. simpDebugOut((DEB_TRACE, "In CSimpStorage::Release()\n"));
  106. simpAssert(_cReferences > 0);
  107. lRet = AtomicDec(&_cReferences);
  108. if (lRet == 0)
  109. {
  110. //Clean up
  111. if (_hFile != INVALID_HANDLE_VALUE)
  112. {
  113. if (_fDirty)
  114. Commit(STGC_DEFAULT);
  115. CloseHandle(_hFile);
  116. }
  117. delete this;
  118. }
  119. simpDebugOut((DEB_TRACE, "Out CSimpStorage::Release()\n"));
  120. olLog(("%p::Out CSimpStorage::Release(). ret == %lu\n", this, lRet));
  121. FreeLogFile();
  122. return (ULONG)lRet;
  123. }
  124. //+--------------------------------------------------------------
  125. //
  126. // Member: CSimpStorage::CreateStream, public
  127. //
  128. // Synopsis: Creates a stream
  129. //
  130. // Arguments: [pwcsName] - Name
  131. // [grfMode] - Permissions
  132. // [reserved1]
  133. // [reserved2]
  134. // [ppstm] - Stream return
  135. //
  136. // Returns: Appropriate status code
  137. //
  138. // Modifies: [ppstm]
  139. //
  140. // History: 04-Aug-94 PhilipLa Created
  141. //
  142. //---------------------------------------------------------------
  143. _OLESTDMETHODIMP CSimpStorage::CreateStream(WCHAR const *pwcsName,
  144. DWORD grfMode,
  145. DWORD reserved1,
  146. DWORD reserved2,
  147. IStream **ppstm)
  148. {
  149. SCODE sc;
  150. CSimpStream *pstm;
  151. CDfNameList *pdfl, *pdflPrev = NULL;
  152. CDfNameList *pdflLoop = _pdfl;
  153. int iCmp;
  154. olLog(("%p::In CSimpStorage::CreateStream(%ws, %lX, %lu, %lu, %p)\n",
  155. this, pwcsName, grfMode, reserved1, reserved2, ppstm));
  156. SIMP_VALIDATE(CreateStream(pwcsName,
  157. grfMode,
  158. reserved1,
  159. reserved2,
  160. ppstm));
  161. if (grfMode != (STGM_READWRITE | STGM_SHARE_EXCLUSIVE))
  162. return STG_E_INVALIDFLAG;
  163. if (_pdflCurrent != NULL)
  164. {
  165. return STG_E_INVALIDFUNCTION;
  166. }
  167. //Check the name. If it isn't already in the list, create a new
  168. // CDfNameList object (in pdfl), and create a new stream object for it.
  169. pdfl = new CDfNameList;
  170. if (pdfl == NULL)
  171. {
  172. return STG_E_INSUFFICIENTMEMORY;
  173. }
  174. pstm = new CSimpStream;
  175. if (pstm == NULL)
  176. {
  177. delete pdfl;
  178. return STG_E_INSUFFICIENTMEMORY;
  179. }
  180. pdfl->SetName(pwcsName);
  181. pdfl->SetStart(_sectMax);
  182. pdfl->SetSize(0);
  183. while (pdflLoop != NULL)
  184. {
  185. iCmp = CDirectory::NameCompare(pdfl->GetName(), pdflLoop->GetName());
  186. if (iCmp == 0)
  187. {
  188. //Already have a stream of this name.
  189. delete pdfl;
  190. delete pstm;
  191. return STG_E_FILEALREADYEXISTS;
  192. }
  193. if (iCmp < 0)
  194. {
  195. //We found the right spot.
  196. break;
  197. }
  198. pdflPrev = pdflLoop;
  199. pdflLoop = pdflLoop->GetNext();
  200. }
  201. if (FAILED(sc = pstm->Init(this, _hFile, ConvertSect(_sectMax))))
  202. {
  203. delete pdfl;
  204. delete pstm;
  205. return sc;
  206. }
  207. //Insert pdfl into list.
  208. pdfl->Insert(&_pdfl, pdflPrev, pdflLoop);
  209. _pdflCurrent = pdfl;
  210. _fDirty = TRUE;
  211. _cStreams++;
  212. *ppstm = pstm;
  213. olLog(("%p::Out CSimpStorage::CreateStream(). "
  214. "*ppstm == %p, ret == %lx\n", this, *ppstm, S_OK));
  215. return S_OK;
  216. }
  217. //+---------------------------------------------------------------------------
  218. //
  219. // Member: CSimpStorage::ReleaseCurrentStream, public
  220. //
  221. // Synopsis: Signal release of the current open stream
  222. //
  223. // Arguments: None.
  224. //
  225. // Returns: void.
  226. //
  227. // History: 05-Aug-94 PhilipLa Created
  228. //
  229. //----------------------------------------------------------------------------
  230. #ifdef SECURE_SIMPLE_MODE
  231. void CSimpStorage::ReleaseCurrentStream(ULONG ulHighWater)
  232. #else
  233. void CSimpStorage::ReleaseCurrentStream(void)
  234. #endif
  235. {
  236. simpDebugOut((DEB_ITRACE,
  237. "In CSimpStorage::ReleaseCurrentStream:%p()\n", this));
  238. ULONG cbSize;
  239. ULONG ulEndOfFile;
  240. ulEndOfFile = GetFileSize(_hFile, NULL);
  241. cbSize = ulEndOfFile - ConvertSect(_sectMax);
  242. cbSize = max(cbSize, MINISTREAMSIZE);
  243. _pdflCurrent->SetSize(cbSize);
  244. ULONG sectUsed;
  245. sectUsed = (cbSize + SECTORSIZE - 1) / SECTORSIZE;
  246. #ifdef SECURE_SIMPLE_MODE
  247. ULONG cbBytesToWrite = ConvertSect(sectUsed + _sectMax) - ulHighWater;
  248. simpAssert(ConvertSect(sectUsed + _sectMax) >= ulHighWater);
  249. ULONG cbWritten;
  250. if ((cbBytesToWrite > 0) &&
  251. (SetFilePointer(_hFile, ulHighWater, NULL, FILE_BEGIN) != 0xFFFFFFFF))
  252. {
  253. while (cbBytesToWrite > 0)
  254. {
  255. if (!WriteFile(_hFile,
  256. s_bufSecure,
  257. min(MINISTREAMSIZE, cbBytesToWrite),
  258. &cbWritten,
  259. NULL))
  260. {
  261. break;
  262. }
  263. cbBytesToWrite -= cbWritten;
  264. }
  265. }
  266. #endif
  267. _sectMax += sectUsed;
  268. _pdflCurrent = NULL;
  269. simpDebugOut((DEB_ITRACE, "Out CSimpStorage::ReleaseCurrentStream\n"));
  270. }
  271. //+--------------------------------------------------------------
  272. //
  273. // Member: CSimpStorage::OpenStream, public
  274. //
  275. // Synopsis: Opens an existing stream
  276. //
  277. // Arguments: [pwcsName] - Name
  278. // [reserved1]
  279. // [grfMode] - Permissions
  280. // [reserved2]
  281. // [ppstm] - Stream return
  282. //
  283. // Returns: Appropriate status code
  284. //
  285. // Modifies: [ppstm]
  286. //
  287. // History: 04-Aug-94 PhilipLa Created
  288. //
  289. //---------------------------------------------------------------
  290. _OLESTDMETHODIMP CSimpStorage::OpenStream(WCHAR const *pwcsName,
  291. void *reserved1,
  292. DWORD grfMode,
  293. DWORD reserved2,
  294. IStream **ppstm)
  295. {
  296. return STG_E_INVALIDFUNCTION;
  297. }
  298. //+--------------------------------------------------------------
  299. //
  300. // Member: CSimpStorage::CreateStorage, public
  301. //
  302. // Synopsis: Creates an embedded DocFile
  303. //
  304. // Arguments: [pwcsName] - Name
  305. // [grfMode] - Permissions
  306. // [reserved1]
  307. // [reserved2]
  308. // [ppstg] - New DocFile return
  309. //
  310. // Returns: Appropriate status code
  311. //
  312. // Modifies: [ppstg]
  313. //
  314. // History: 04-Aug-94 PhilipLa Created
  315. //
  316. //---------------------------------------------------------------
  317. _OLESTDMETHODIMP CSimpStorage::CreateStorage(WCHAR const *pwcsName,
  318. DWORD grfMode,
  319. DWORD reserved1,
  320. LPSTGSECURITY reserved2,
  321. IStorage **ppstg)
  322. {
  323. return STG_E_INVALIDFUNCTION;
  324. }
  325. //+--------------------------------------------------------------
  326. //
  327. // Member: CSimpStorage::OpenStorage, public
  328. //
  329. // Synopsis: Gets an existing embedded DocFile
  330. //
  331. // Arguments: [pwcsName] - Name
  332. // [pstgPriority] - Priority reopens
  333. // [grfMode] - Permissions
  334. // [snbExclude] - Priority reopens
  335. // [reserved]
  336. // [ppstg] - DocFile return
  337. //
  338. // Returns: Appropriate status code
  339. //
  340. // Modifies: [ppstg]
  341. //
  342. // History: 04-Aug-94 PhilipLa Created
  343. //
  344. //---------------------------------------------------------------
  345. _OLESTDMETHODIMP CSimpStorage::OpenStorage(WCHAR const *pwcsName,
  346. IStorage *pstgPriority,
  347. DWORD grfMode,
  348. SNBW snbExclude,
  349. DWORD reserved,
  350. IStorage **ppstg)
  351. {
  352. return STG_E_INVALIDFUNCTION;
  353. }
  354. //+--------------------------------------------------------------
  355. //
  356. // Member: CSimpStorage::CopyTo, public
  357. //
  358. // Synopsis: Makes a copy of a DocFile
  359. //
  360. // Arguments: [ciidExclude] - Length of rgiid array
  361. // [rgiidExclude] - Array of IIDs to exclude
  362. // [snbExclude] - Names to exclude
  363. // [pstgDest] - Parent of copy
  364. //
  365. // Returns: Appropriate status code
  366. //
  367. // History: 04-Aug-94 PhilipLa Created
  368. //
  369. //---------------------------------------------------------------
  370. _OLESTDMETHODIMP CSimpStorage::CopyTo(DWORD ciidExclude,
  371. IID const *rgiidExclude,
  372. SNBW snbExclude,
  373. IStorage *pstgDest)
  374. {
  375. return STG_E_INVALIDFUNCTION;
  376. }
  377. //+---------------------------------------------------------------------------
  378. //
  379. // Member: CSimpStorage::BuildTree, private
  380. //
  381. // Synopsis: Construct the btree given the sorted array of entries.
  382. //
  383. // Arguments: [ade] -- Array of CDirEntry to operate on. These are
  384. // already sorted.
  385. // [sidStart] -- SID of first entry on this segment
  386. // [cStreams] -- Length of segment to process
  387. //
  388. // Returns: SID of root of tree
  389. //
  390. // History: 09-Aug-94 PhilipLa Created
  391. //
  392. // Notes: This is a recursive function. Yes, I know...
  393. //
  394. //----------------------------------------------------------------------------
  395. SID CSimpStorage::BuildTree(CDirEntry *ade, SID sidStart, ULONG cStreams)
  396. {
  397. simpDebugOut((DEB_ITRACE, "In CSimpStorage::BuildTree:%p()\n", this));
  398. if (cStreams > 3)
  399. {
  400. SID sidSplit;
  401. sidSplit = sidStart + (cStreams / 2);
  402. simpAssert(cStreams == 1 + (sidSplit - sidStart) +
  403. (cStreams + sidStart - 1) - sidSplit);
  404. ade[sidSplit].SetLeftSib(BuildTree(ade,
  405. sidStart,
  406. sidSplit - sidStart));
  407. ade[sidSplit].SetRightSib(BuildTree(ade,
  408. sidSplit + 1,
  409. (cStreams + sidStart - 1) -
  410. sidSplit));
  411. return sidSplit;
  412. }
  413. //Base cases:
  414. // cStreams == 1 -- return sidStart
  415. // cStreams == 2 -- Left child of sidStart + 1 == sidStart, return
  416. // sidStart + 1
  417. // cStreams == 3 -- Root is sidStart + 1, with children sidStart and
  418. // sidStart + 2
  419. if (cStreams == 1)
  420. {
  421. return sidStart;
  422. }
  423. if (cStreams == 3)
  424. ade[sidStart + 1].SetRightSib(sidStart + 2);
  425. ade[sidStart + 1].SetLeftSib(sidStart);
  426. return sidStart + 1;
  427. simpDebugOut((DEB_ITRACE, "Out CSimpStorage::BuildTree\n"));
  428. }
  429. //+--------------------------------------------------------------
  430. //
  431. // Member: CSimpStorage::Commit, public
  432. //
  433. // Synopsis: Commits transacted changes
  434. //
  435. // Arguments: [dwFlags] - DFC_*
  436. //
  437. // Returns: Appropriate status code
  438. //
  439. // History: 04-Aug-94 PhilipLa Created
  440. //
  441. //---------------------------------------------------------------
  442. STDMETHODIMP CSimpStorage::Commit(DWORD dwFlags)
  443. {
  444. CDfName const dfnRoot(L"Root Entry");
  445. SCODE sc;
  446. olLog(("%p::In CSimpStorage::Commit(%lX)\n",this, dwFlags));
  447. SIMP_VALIDATE(Commit(dwFlags));
  448. // Simple mode commit does not allow open stream elements
  449. // While we could possibly revert the stream instead of returning an error,
  450. // it would not have the same semantics as normal mode transactions
  451. if (_pdflCurrent != NULL)
  452. return STG_E_INVALIDFUNCTION;
  453. if (!_fDirty)
  454. return S_OK;
  455. //Allocate a buffer big enough for all the control structures.
  456. const USHORT cdePerSect = SECTORSIZE / sizeof(CDirEntry);
  457. const USHORT cSectPerFat = SECTORSIZE / sizeof(SECT);
  458. ULONG cDifSect = 0;
  459. ULONG cFatSect = 0;
  460. ULONG cFatSectOld = (ULONG)-1;
  461. ULONG cDifSectOld = (ULONG)-1;
  462. ULONG cDirSect;
  463. ULONG cSect;
  464. ULONG cbSize;
  465. cDirSect = (_cStreams + 1 + cdePerSect - 1) / cdePerSect;
  466. cSect = _sectMax + cDirSect;
  467. //At this point, csect is the number of sectors needed to hold
  468. // everything but the fat itself (and the DIFat, if necessary).
  469. while ((cFatSect != cFatSectOld) || (cDifSect != cDifSectOld))
  470. {
  471. //Now, compute the number of fat sectors needed to hold everything.
  472. cFatSectOld = cFatSect;
  473. cFatSect = (cSect + cFatSect + cDifSect + cSectPerFat - 1) /
  474. cSectPerFat;
  475. cDifSectOld = cDifSect;
  476. if (cFatSect >= CSECTFAT)
  477. {
  478. cDifSect = (cFatSect - CSECTFAT + cSectPerFat - 2)
  479. / (cSectPerFat - 1);
  480. }
  481. }
  482. //At this point, we know how big the buffer needs to be. Allocate
  483. // it.
  484. _pbBuf = new BYTE[(cFatSect + cDirSect + cDifSect) * SECTORSIZE];
  485. if (_pbBuf == NULL)
  486. {
  487. return STG_E_INSUFFICIENTMEMORY;
  488. }
  489. //The fat is placed in the buffer first, followed by the directory.
  490. SECT sect;
  491. SECT *asectFat;
  492. SECT *asectDif;
  493. CDirEntry *adeDir;
  494. SECT sectDifStart = _sectMax;
  495. SECT sectFatStart = _sectMax + cDifSect;
  496. SECT sectDirStart = _sectMax + cDifSect + cFatSect;
  497. asectDif = (SECT *)_pbBuf;
  498. asectFat = (SECT *)(_pbBuf + (cDifSect * SECTORSIZE));
  499. adeDir = (CDirEntry *)(_pbBuf + ((cFatSect + cDifSect) * SECTORSIZE));
  500. //asectFat and adeDir can be used as arrays.
  501. //Need to get the buffer to a correct 'empty' state.
  502. // 1) Initialize fat and difat to all 0xff.
  503. memset(asectDif, 0xff, cDifSect * SECTORSIZE);
  504. memset(asectFat, 0xff, cFatSect * SECTORSIZE);
  505. // 2) Initialize dir to all empty state
  506. for (USHORT i = 0; i < cDirSect * cdePerSect; i++)
  507. {
  508. adeDir[i].Init(STGTY_INVALID);
  509. simpAssert((BYTE *)&adeDir[i] <
  510. _pbBuf + ((cFatSect + cDifSect + cDirSect) * SECTORSIZE));
  511. }
  512. if (cDifSect > 0)
  513. {
  514. //Put dif into fat.
  515. for (sect = sectDifStart; sect < sectFatStart; sect++)
  516. {
  517. asectFat[sect] = DIFSECT;
  518. simpAssert((BYTE *)&asectFat[sect] < (BYTE *)adeDir);
  519. ULONG ulOffset = sect - sectDifStart;
  520. asectDif[ulOffset * cSectPerFat + (cSectPerFat - 1)] = sect + 1;
  521. }
  522. asectDif[((cDifSect - 1) * cSectPerFat) + (cSectPerFat - 1)] =
  523. ENDOFCHAIN;
  524. _hdr.SetDifStart(sectDifStart);
  525. _hdr.SetDifLength(cDifSect);
  526. }
  527. for (sect = sectFatStart;
  528. sect < sectDirStart;
  529. sect++)
  530. {
  531. asectFat[sect] = FATSECT;
  532. simpAssert((BYTE *)&asectFat[sect] < (BYTE *)adeDir);
  533. ULONG ulOffset = sect - sectFatStart;
  534. if (ulOffset < CSECTFAT)
  535. {
  536. _hdr.SetFatSect(ulOffset, sect);
  537. }
  538. else
  539. {
  540. ulOffset -= CSECTFAT;
  541. asectDif[(ulOffset / (cSectPerFat - 1)) * cSectPerFat +
  542. (ulOffset % (cSectPerFat - 1))] = sect;
  543. }
  544. }
  545. for (sect = sectDirStart;
  546. sect < sectDirStart + cDirSect;
  547. sect++)
  548. {
  549. asectFat[sect] = sect + 1;
  550. simpAssert((BYTE *)&asectFat[sect] < (BYTE *)adeDir);
  551. }
  552. asectFat[sectDirStart + cDirSect - 1] = ENDOFCHAIN;
  553. simpAssert((BYTE *)&asectFat[sectDirStart + cDirSect - 1] <
  554. (BYTE *)adeDir);
  555. _hdr.SetDirStart(sectDirStart);
  556. _hdr.SetFatLength(cFatSect);
  557. //Fat, directory, and header are set up. Woowoo.
  558. //Walk name list and construct directory and fat structures for
  559. // user streams.
  560. //Write them out, then write out header.
  561. CDfNameList *pdfl;
  562. SID sid;
  563. pdfl = _pdfl;
  564. sid = 1;
  565. while (pdfl != NULL)
  566. {
  567. //Set up fat chain.
  568. SECT sectStart = pdfl->GetStart();
  569. ULONG cSect = (pdfl->GetSize() + SECTORSIZE - 1) / SECTORSIZE;
  570. for (sect = sectStart; sect < sectStart + cSect; sect++)
  571. {
  572. asectFat[sect] = sect + 1;
  573. simpAssert((BYTE *)&asectFat[sect] < (BYTE *)adeDir);
  574. }
  575. asectFat[sectStart + cSect - 1] = ENDOFCHAIN;
  576. simpAssert((BYTE *)&asectFat[sectStart + cSect - 1] < (BYTE *)adeDir);
  577. adeDir[sid].SetFlags(STGTY_STREAM);
  578. adeDir[sid].SetName(pdfl->GetName());
  579. adeDir[sid].SetStart(pdfl->GetStart());
  580. adeDir[sid].SetSize(pdfl->GetSize());
  581. adeDir[sid].SetColor(DE_BLACK);
  582. simpAssert((BYTE *)&adeDir[sid] <
  583. _pbBuf + ((cFatSect + cDifSect + cDirSect) * SECTORSIZE));
  584. pdfl = pdfl->GetNext();
  585. sid++;
  586. }
  587. //Set up root entry.
  588. adeDir[0].Init(STGTY_ROOT);
  589. adeDir[0].SetName(&dfnRoot);
  590. adeDir[0].SetClassId(_clsid);
  591. adeDir[0].SetColor(DE_BLACK);
  592. //This recursively builds the btree and sets the root in the child
  593. // of the root entry.
  594. adeDir[0].SetChild(BuildTree(adeDir, 1, _cStreams));
  595. //Write out buffer
  596. ULONG cbWritten;
  597. SetFilePointer(_hFile, ConvertSect(_sectMax), NULL, FILE_BEGIN);
  598. BOOL f= WriteFile(_hFile,
  599. _pbBuf,
  600. (cFatSect + cDifSect + cDirSect) * SECTORSIZE,
  601. &cbWritten,
  602. NULL);
  603. if (!f)
  604. {
  605. sc = STG_SCODE(GetLastError());
  606. delete _pbBuf;
  607. _pbBuf = NULL;
  608. return sc;
  609. }
  610. //Write out header
  611. DWORD dwErr;
  612. dwErr= SetFilePointer(_hFile, 0, NULL, FILE_BEGIN);
  613. if (dwErr == 0xFFFFFFFF)
  614. {
  615. sc = STG_SCODE(GetLastError());
  616. delete _pbBuf;
  617. _pbBuf = NULL;
  618. return sc;
  619. }
  620. f= WriteFile(_hFile,
  621. _hdr.GetData(),
  622. sizeof(CMSFHeaderData),
  623. &cbWritten,
  624. NULL);
  625. if (!f)
  626. {
  627. sc = STG_SCODE(GetLastError());
  628. delete _pbBuf;
  629. _pbBuf = NULL;
  630. return sc;
  631. }
  632. if (!(dwFlags & STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE))
  633. {
  634. f = FlushFileBuffers(_hFile);
  635. if (!f)
  636. {
  637. sc = STG_SCODE(GetLastError());
  638. delete _pbBuf;
  639. _pbBuf = NULL;
  640. return sc;
  641. }
  642. }
  643. delete _pbBuf;
  644. _pbBuf = NULL;
  645. _fDirty = FALSE;
  646. olLog(("%p::Out CSimpStorage::Commit(). ret == %lx\n",this, S_OK));
  647. return S_OK;
  648. }
  649. //+--------------------------------------------------------------
  650. //
  651. // Member: CSimpStorage::Revert, public
  652. //
  653. // Synopsis: Reverts transacted changes
  654. //
  655. // Returns: Appropriate status code
  656. //
  657. // History: 04-Aug-94 PhilipLa Created
  658. //
  659. //---------------------------------------------------------------
  660. STDMETHODIMP CSimpStorage::Revert(void)
  661. {
  662. return STG_E_INVALIDFUNCTION;
  663. }
  664. //+--------------------------------------------------------------
  665. //
  666. // Member: CSimpStorage::EnumElements, public
  667. //
  668. // Synopsis: Starts an iterator
  669. //
  670. // Arguments: [reserved1]
  671. // [reserved2]
  672. // [reserved3]
  673. // [ppenm] - Enumerator return
  674. //
  675. // Returns: Appropriate status code
  676. //
  677. // Modifies: [ppenm]
  678. //
  679. // History: 04-Aug-94 PhilipLa Created
  680. //
  681. //---------------------------------------------------------------
  682. STDMETHODIMP CSimpStorage::EnumElements(DWORD reserved1,
  683. void *reserved2,
  684. DWORD reserved3,
  685. IEnumSTATSTG **ppenm)
  686. {
  687. return STG_E_INVALIDFUNCTION;
  688. }
  689. //+--------------------------------------------------------------
  690. //
  691. // Member: CSimpStorage::DestroyElement, public
  692. //
  693. // Synopsis: Permanently deletes an element of a DocFile
  694. //
  695. // Arguments: [pwcsName] - Name of element
  696. //
  697. // Returns: Appropriate status code
  698. //
  699. // History: 04-Aug-94 PhilipLa Created
  700. //
  701. //---------------------------------------------------------------
  702. _OLESTDMETHODIMP CSimpStorage::DestroyElement(WCHAR const *pwcsName)
  703. {
  704. return STG_E_INVALIDFUNCTION;
  705. }
  706. //+--------------------------------------------------------------
  707. //
  708. // Member: CSimpStorage::MoveElementTo, public
  709. //
  710. // Synopsis: Move an element of a DocFile to an IStorage
  711. //
  712. // Arguments: [pwcsName] - Current name
  713. // [ptcsNewName] - New name
  714. //
  715. // Returns: Appropriate status code
  716. //
  717. // Algorithm: Open source as storage or stream (whatever works)
  718. // Create appropriate destination
  719. // Copy source to destination
  720. // Set create time of destination equal to create time of source
  721. // If appropriate, delete source
  722. //
  723. // History: 04-Aug-94 PhilipLa Created
  724. //
  725. //---------------------------------------------------------------
  726. _OLESTDMETHODIMP CSimpStorage::MoveElementTo(WCHAR const *pwcsName,
  727. IStorage *pstgParent,
  728. OLECHAR const *ptcsNewName,
  729. DWORD grfFlags)
  730. {
  731. return STG_E_INVALIDFUNCTION;
  732. }
  733. //+--------------------------------------------------------------
  734. //
  735. // Member: CSimpStorage::RenameElement, public
  736. //
  737. // Synopsis: Renames an element of a DocFile
  738. //
  739. // Arguments: [pwcsName] - Current name
  740. // [pwcsNewName] - New name
  741. //
  742. // Returns: Appropriate status code
  743. //
  744. // History: 04-Aug-94 PhilipLa Created
  745. //
  746. //---------------------------------------------------------------
  747. _OLESTDMETHODIMP CSimpStorage::RenameElement(WCHAR const *pwcsName,
  748. WCHAR const *pwcsNewName)
  749. {
  750. return STG_E_INVALIDFUNCTION;
  751. }
  752. //+--------------------------------------------------------------
  753. //
  754. // Member: CSimpStorage::SetElementTimes, public
  755. //
  756. // Synopsis: Sets element time stamps
  757. //
  758. // Arguments: [pwcsName] - Name
  759. // [pctime] - create time
  760. // [patime] - access time
  761. // [pmtime] - modify time
  762. //
  763. // Returns: Appropriate status code
  764. //
  765. // History: 04-Aug-94 PhilipLa Created
  766. //
  767. //---------------------------------------------------------------
  768. _OLESTDMETHODIMP CSimpStorage::SetElementTimes(WCHAR const *pwcsName,
  769. FILETIME const *pctime,
  770. FILETIME const *patime,
  771. FILETIME const *pmtime)
  772. {
  773. SCODE sc;
  774. olLog(("%p::In CSimpStorage::SetElementTimes(%ws, %p, %p, %p)\n",
  775. this, pwcsName, pctime, patime, pmtime));
  776. SIMP_VALIDATE(SetElementTimes(pwcsName,
  777. pctime,
  778. patime,
  779. pmtime));
  780. if (pwcsName != NULL)
  781. return STG_E_INVALIDFUNCTION;
  782. if (!SetFileTime(_hFile,
  783. pctime,
  784. patime,
  785. pmtime))
  786. {
  787. return STG_SCODE(GetLastError());
  788. }
  789. olLog(("%p::Out CSimpStorage::SetElementTimes(). ret == %lx\n",
  790. this, S_OK));
  791. return S_OK;
  792. }
  793. //+--------------------------------------------------------------
  794. //
  795. // Member: CSimpStorage::SetClass, public
  796. //
  797. // Synopsis: Sets storage class
  798. //
  799. // Arguments: [clsid] - class id
  800. //
  801. // Returns: Appropriate status code
  802. //
  803. // History: 04-Aug-94 PhilipLa Created
  804. //
  805. //---------------------------------------------------------------
  806. STDMETHODIMP CSimpStorage::SetClass(REFCLSID rclsid)
  807. {
  808. olLog(("%p::In CSimpStorage::SetClass(?)\n", this));
  809. SCODE sc;
  810. SIMP_VALIDATE(SetClass(rclsid));
  811. _clsid = rclsid;
  812. olLog(("%p::Out CSimpStorage::SetClass(). ret == %lx\n",
  813. this, S_OK));
  814. return S_OK;
  815. }
  816. //+--------------------------------------------------------------
  817. //
  818. // Member: CSimpStorage::SetStateBits, public
  819. //
  820. // Synopsis: Sets state bits
  821. //
  822. // Arguments: [grfStateBits] - state bits
  823. // [grfMask] - state bits mask
  824. //
  825. // Returns: Appropriate status code
  826. //
  827. // History: 04-Aug-94 PhilipLa Created
  828. //
  829. //---------------------------------------------------------------
  830. STDMETHODIMP CSimpStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
  831. {
  832. return STG_E_INVALIDFUNCTION;
  833. }
  834. //+--------------------------------------------------------------
  835. //
  836. // Member: CSimpStorage::Stat, public
  837. //
  838. // Synopsis: Fills in a buffer of information about this object
  839. //
  840. // Arguments: [pstatstg] - Buffer
  841. //
  842. // Returns: Appropriate status code
  843. //
  844. // Modifies: [pstatstg]
  845. //
  846. // History: 04-Aug-94 PhilipLa Created
  847. //
  848. //---------------------------------------------------------------
  849. _OLESTDMETHODIMP CSimpStorage::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
  850. {
  851. return STG_E_INVALIDFUNCTION;
  852. }
  853. //+--------------------------------------------------------------
  854. //
  855. // Member: CSimpStorage::AddRef, public
  856. //
  857. // Synopsis: Increments the ref count
  858. //
  859. // Returns: Appropriate status code
  860. //
  861. // History: 04-Aug-94 PhilipLa Created
  862. //
  863. //---------------------------------------------------------------
  864. STDMETHODIMP_(ULONG) CSimpStorage::AddRef(void)
  865. {
  866. ULONG ulRet;
  867. olLog(("%p::In CSimpStorage::AddRef()\n", this));
  868. simpDebugOut((DEB_TRACE, "In CSimpStorage::AddRef()\n"));
  869. AtomicInc(&_cReferences);
  870. ulRet = _cReferences;
  871. simpDebugOut((DEB_TRACE, "Out CSimpStorage::AddRef\n"));
  872. olLog(("%p::Out CSimpStorage::AddRef(). ret == %lu\n", this, ulRet));
  873. return ulRet;
  874. }
  875. //+--------------------------------------------------------------
  876. //
  877. // Member: CSimpStorage::QueryInterface, public
  878. //
  879. // Synopsis: Returns an object for the requested interface
  880. //
  881. // Arguments: [iid] - Interface ID
  882. // [ppvObj] - Object return
  883. //
  884. // Returns: Appropriate status code
  885. //
  886. // Modifies: [ppvObj]
  887. //
  888. // History: 04-Aug-94 PhilipLa Created
  889. //
  890. //---------------------------------------------------------------
  891. STDMETHODIMP CSimpStorage::QueryInterface(REFIID iid, void **ppvObj)
  892. {
  893. SCODE sc;
  894. olLog(("%p::In CSimpStorage::QueryInterface(?, %p)\n",
  895. this, ppvObj));
  896. simpDebugOut((DEB_TRACE, "In CSimpStorage::QueryInterface(?, %p)\n",
  897. ppvObj));
  898. SIMP_VALIDATE(QueryInterface(iid, ppvObj));
  899. sc = S_OK;
  900. if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
  901. {
  902. *ppvObj = (IStorage *)this;
  903. CSimpStorage::AddRef();
  904. }
  905. else if (IsEqualIID(iid, IID_IMarshal))
  906. {
  907. *ppvObj = (IMarshal *)this;
  908. CSimpStorage::AddRef();
  909. }
  910. else if (IsEqualIID(iid, IID_IPropertySetStorage))
  911. {
  912. *ppvObj = (IPropertySetStorage *)this;
  913. CSimpStorage::AddRef();
  914. }
  915. else
  916. sc = E_NOINTERFACE;
  917. olLog(("%p::Out CSimpStorage::QueryInterface(). "
  918. "*ppvObj == %p ret == %lx\n", this, *ppvObj, sc));
  919. simpDebugOut((DEB_TRACE, "Out CSimpStorage::QueryInterface => %p\n",
  920. ppvObj));
  921. return ResultFromScode(sc);
  922. }
  923. //+--------------------------------------------------------------
  924. //
  925. // Member: CSimpStorage::GetUnmarshalClass, public
  926. //
  927. // Synopsis: Returns the class ID
  928. //
  929. // Arguments: [riid] - IID of object
  930. // [pv] - Unreferenced
  931. // [dwDestContext] - Unreferenced
  932. // [pvDestContext] - Unreferenced
  933. // [mshlflags] - Unreferenced
  934. // [pcid] - CLSID return
  935. //
  936. // Returns: Invalid function.
  937. //
  938. // Modifies: [pcid]
  939. //
  940. // History: 04-Aug-94 PhilipLa Created
  941. //
  942. //---------------------------------------------------------------
  943. STDMETHODIMP CSimpStorage::GetUnmarshalClass(REFIID riid,
  944. void *pv,
  945. DWORD dwDestContext,
  946. LPVOID pvDestContext,
  947. DWORD mshlflags,
  948. LPCLSID pcid)
  949. {
  950. return STG_E_INVALIDFUNCTION;
  951. }
  952. //+--------------------------------------------------------------
  953. //
  954. // Member: CSimpStorage::GetMarshalSizeMax, public
  955. //
  956. // Synopsis: Returns the size needed for the marshal buffer
  957. //
  958. // Arguments: [riid] - IID of object being marshaled
  959. // [pv] - Unreferenced
  960. // [dwDestContext] - Unreferenced
  961. // [pvDestContext] - Unreferenced
  962. // [mshlflags] - Unreferenced
  963. // [pcbSize] - Size return
  964. //
  965. // Returns: Appropriate status code
  966. //
  967. // Modifies: [pcbSize]
  968. //
  969. // History: 04-Aug-94 PhilipLa Created
  970. //
  971. //---------------------------------------------------------------
  972. STDMETHODIMP CSimpStorage::GetMarshalSizeMax(REFIID riid,
  973. void *pv,
  974. DWORD dwDestContext,
  975. LPVOID pvDestContext,
  976. DWORD mshlflags,
  977. LPDWORD pcbSize)
  978. {
  979. return STG_E_INVALIDFUNCTION;
  980. }
  981. //+--------------------------------------------------------------
  982. //
  983. // Member: CSimpStorage::MarshalInterface, public
  984. //
  985. // Synopsis: Marshals a given object
  986. //
  987. // Arguments: [pstStm] - Stream to write marshal data into
  988. // [riid] - Interface to marshal
  989. // [pv] - Unreferenced
  990. // [dwDestContext] - Unreferenced
  991. // [pvDestContext] - Unreferenced
  992. // [mshlflags] - Unreferenced
  993. //
  994. // Returns: Appropriate status code
  995. //
  996. // History: 04-Aug-94 PhilipLa Created
  997. //
  998. //---------------------------------------------------------------
  999. STDMETHODIMP CSimpStorage::MarshalInterface(IStream *pstStm,
  1000. REFIID riid,
  1001. void *pv,
  1002. DWORD dwDestContext,
  1003. LPVOID pvDestContext,
  1004. DWORD mshlflags)
  1005. {
  1006. return STG_E_INVALIDFUNCTION;
  1007. }
  1008. //+--------------------------------------------------------------
  1009. //
  1010. // Member: CSimpStorage::UnmarshalInterface, public
  1011. //
  1012. // Synopsis: Non-functional
  1013. //
  1014. // Arguments: [pstStm] -
  1015. // [riid] -
  1016. // [ppvObj] -
  1017. //
  1018. // Returns: Appropriate status code
  1019. //
  1020. // Modifies: [ppvObj]
  1021. //
  1022. // History: 04-Aug-94 PhilipLa Created
  1023. //
  1024. //---------------------------------------------------------------
  1025. STDMETHODIMP CSimpStorage::UnmarshalInterface(IStream *pstStm,
  1026. REFIID riid,
  1027. void **ppvObj)
  1028. {
  1029. return STG_E_INVALIDFUNCTION;
  1030. }
  1031. //+--------------------------------------------------------------
  1032. //
  1033. // Member: CSimpStorage::ReleaseMarshalData, public
  1034. //
  1035. // Synopsis: Non-functional
  1036. //
  1037. // Arguments: [pstStm] -
  1038. //
  1039. // Returns: Appropriate status code
  1040. //
  1041. // History: 18-Sep-92 PhilipLa Created
  1042. //
  1043. //---------------------------------------------------------------
  1044. STDMETHODIMP CSimpStorage::ReleaseMarshalData(IStream *pstStm)
  1045. {
  1046. return STG_E_INVALIDFUNCTION;
  1047. }
  1048. //+--------------------------------------------------------------
  1049. //
  1050. // Member: CSimpStorage::DisconnectObject, public
  1051. //
  1052. // Synopsis: Non-functional
  1053. //
  1054. // Arguments: [dwRevserved] -
  1055. //
  1056. // Returns: Appropriate status code
  1057. //
  1058. // History: 18-Sep-92 PhilipLa Created
  1059. //
  1060. //---------------------------------------------------------------
  1061. STDMETHODIMP CSimpStorage::DisconnectObject(DWORD dwReserved)
  1062. {
  1063. return STG_E_INVALIDFUNCTION;
  1064. }