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.

1245 lines
35 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) != INVALID_SET_FILE_POINTER))
  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. 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. DWORD dwErr;
  598. dwErr = SetFilePointer(_hFile, ConvertSect(_sectMax), NULL, FILE_BEGIN);
  599. if (dwErr == INVALID_SET_FILE_POINTER)
  600. {
  601. sc = STG_SCODE(GetLastError());
  602. delete _pbBuf;
  603. _pbBuf = NULL;
  604. return sc;
  605. }
  606. BOOL f= WriteFile(_hFile,
  607. _pbBuf,
  608. (cFatSect + cDifSect + cDirSect) * SECTORSIZE,
  609. &cbWritten,
  610. NULL);
  611. if (!f)
  612. {
  613. sc = STG_SCODE(GetLastError());
  614. delete _pbBuf;
  615. _pbBuf = NULL;
  616. return sc;
  617. }
  618. //Write out header
  619. dwErr= SetFilePointer(_hFile, 0, NULL, FILE_BEGIN);
  620. if (dwErr == INVALID_SET_FILE_POINTER)
  621. {
  622. sc = STG_SCODE(GetLastError());
  623. delete _pbBuf;
  624. _pbBuf = NULL;
  625. return sc;
  626. }
  627. f= WriteFile(_hFile,
  628. _hdr.GetData(),
  629. sizeof(CMSFHeaderData),
  630. &cbWritten,
  631. NULL);
  632. if (!f)
  633. {
  634. sc = STG_SCODE(GetLastError());
  635. delete _pbBuf;
  636. _pbBuf = NULL;
  637. return sc;
  638. }
  639. if (!(dwFlags & STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE))
  640. {
  641. f = FlushFileBuffers(_hFile);
  642. if (!f)
  643. {
  644. sc = STG_SCODE(GetLastError());
  645. delete _pbBuf;
  646. _pbBuf = NULL;
  647. return sc;
  648. }
  649. }
  650. delete _pbBuf;
  651. _pbBuf = NULL;
  652. _fDirty = FALSE;
  653. olLog(("%p::Out CSimpStorage::Commit(). ret == %lx\n",this, S_OK));
  654. return S_OK;
  655. }
  656. //+--------------------------------------------------------------
  657. //
  658. // Member: CSimpStorage::Revert, public
  659. //
  660. // Synopsis: Reverts transacted changes
  661. //
  662. // Returns: Appropriate status code
  663. //
  664. // History: 04-Aug-94 PhilipLa Created
  665. //
  666. //---------------------------------------------------------------
  667. STDMETHODIMP CSimpStorage::Revert(void)
  668. {
  669. return STG_E_INVALIDFUNCTION;
  670. }
  671. //+--------------------------------------------------------------
  672. //
  673. // Member: CSimpStorage::EnumElements, public
  674. //
  675. // Synopsis: Starts an iterator
  676. //
  677. // Arguments: [reserved1]
  678. // [reserved2]
  679. // [reserved3]
  680. // [ppenm] - Enumerator return
  681. //
  682. // Returns: Appropriate status code
  683. //
  684. // Modifies: [ppenm]
  685. //
  686. // History: 04-Aug-94 PhilipLa Created
  687. //
  688. //---------------------------------------------------------------
  689. STDMETHODIMP CSimpStorage::EnumElements(DWORD reserved1,
  690. void *reserved2,
  691. DWORD reserved3,
  692. IEnumSTATSTG **ppenm)
  693. {
  694. return STG_E_INVALIDFUNCTION;
  695. }
  696. //+--------------------------------------------------------------
  697. //
  698. // Member: CSimpStorage::DestroyElement, public
  699. //
  700. // Synopsis: Permanently deletes an element of a DocFile
  701. //
  702. // Arguments: [pwcsName] - Name of element
  703. //
  704. // Returns: Appropriate status code
  705. //
  706. // History: 04-Aug-94 PhilipLa Created
  707. //
  708. //---------------------------------------------------------------
  709. _OLESTDMETHODIMP CSimpStorage::DestroyElement(WCHAR const *pwcsName)
  710. {
  711. return STG_E_INVALIDFUNCTION;
  712. }
  713. //+--------------------------------------------------------------
  714. //
  715. // Member: CSimpStorage::MoveElementTo, public
  716. //
  717. // Synopsis: Move an element of a DocFile to an IStorage
  718. //
  719. // Arguments: [pwcsName] - Current name
  720. // [ptcsNewName] - New name
  721. //
  722. // Returns: Appropriate status code
  723. //
  724. // Algorithm: Open source as storage or stream (whatever works)
  725. // Create appropriate destination
  726. // Copy source to destination
  727. // Set create time of destination equal to create time of source
  728. // If appropriate, delete source
  729. //
  730. // History: 04-Aug-94 PhilipLa Created
  731. //
  732. //---------------------------------------------------------------
  733. _OLESTDMETHODIMP CSimpStorage::MoveElementTo(WCHAR const *pwcsName,
  734. IStorage *pstgParent,
  735. OLECHAR const *ptcsNewName,
  736. DWORD grfFlags)
  737. {
  738. return STG_E_INVALIDFUNCTION;
  739. }
  740. //+--------------------------------------------------------------
  741. //
  742. // Member: CSimpStorage::RenameElement, public
  743. //
  744. // Synopsis: Renames an element of a DocFile
  745. //
  746. // Arguments: [pwcsName] - Current name
  747. // [pwcsNewName] - New name
  748. //
  749. // Returns: Appropriate status code
  750. //
  751. // History: 04-Aug-94 PhilipLa Created
  752. //
  753. //---------------------------------------------------------------
  754. _OLESTDMETHODIMP CSimpStorage::RenameElement(WCHAR const *pwcsName,
  755. WCHAR const *pwcsNewName)
  756. {
  757. return STG_E_INVALIDFUNCTION;
  758. }
  759. //+--------------------------------------------------------------
  760. //
  761. // Member: CSimpStorage::SetElementTimes, public
  762. //
  763. // Synopsis: Sets element time stamps
  764. //
  765. // Arguments: [pwcsName] - Name
  766. // [pctime] - create time
  767. // [patime] - access time
  768. // [pmtime] - modify time
  769. //
  770. // Returns: Appropriate status code
  771. //
  772. // History: 04-Aug-94 PhilipLa Created
  773. //
  774. //---------------------------------------------------------------
  775. _OLESTDMETHODIMP CSimpStorage::SetElementTimes(WCHAR const *pwcsName,
  776. FILETIME const *pctime,
  777. FILETIME const *patime,
  778. FILETIME const *pmtime)
  779. {
  780. SCODE sc;
  781. olLog(("%p::In CSimpStorage::SetElementTimes(%ws, %p, %p, %p)\n",
  782. this, pwcsName, pctime, patime, pmtime));
  783. SIMP_VALIDATE(SetElementTimes(pwcsName,
  784. pctime,
  785. patime,
  786. pmtime));
  787. if (pwcsName != NULL)
  788. return STG_E_INVALIDFUNCTION;
  789. if (!SetFileTime(_hFile,
  790. pctime,
  791. patime,
  792. pmtime))
  793. {
  794. return STG_SCODE(GetLastError());
  795. }
  796. olLog(("%p::Out CSimpStorage::SetElementTimes(). ret == %lx\n",
  797. this, S_OK));
  798. return S_OK;
  799. }
  800. //+--------------------------------------------------------------
  801. //
  802. // Member: CSimpStorage::SetClass, public
  803. //
  804. // Synopsis: Sets storage class
  805. //
  806. // Arguments: [clsid] - class id
  807. //
  808. // Returns: Appropriate status code
  809. //
  810. // History: 04-Aug-94 PhilipLa Created
  811. //
  812. //---------------------------------------------------------------
  813. STDMETHODIMP CSimpStorage::SetClass(REFCLSID rclsid)
  814. {
  815. olLog(("%p::In CSimpStorage::SetClass(?)\n", this));
  816. SCODE sc;
  817. SIMP_VALIDATE(SetClass(rclsid));
  818. _clsid = rclsid;
  819. _fDirty = TRUE;
  820. olLog(("%p::Out CSimpStorage::SetClass(). ret == %lx\n",
  821. this, S_OK));
  822. return S_OK;
  823. }
  824. //+--------------------------------------------------------------
  825. //
  826. // Member: CSimpStorage::SetStateBits, public
  827. //
  828. // Synopsis: Sets state bits
  829. //
  830. // Arguments: [grfStateBits] - state bits
  831. // [grfMask] - state bits mask
  832. //
  833. // Returns: Appropriate status code
  834. //
  835. // History: 04-Aug-94 PhilipLa Created
  836. //
  837. //---------------------------------------------------------------
  838. STDMETHODIMP CSimpStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
  839. {
  840. return STG_E_INVALIDFUNCTION;
  841. }
  842. //+--------------------------------------------------------------
  843. //
  844. // Member: CSimpStorage::Stat, public
  845. //
  846. // Synopsis: Fills in a buffer of information about this object
  847. //
  848. // Arguments: [pstatstg] - Buffer
  849. //
  850. // Returns: Appropriate status code
  851. //
  852. // Modifies: [pstatstg]
  853. //
  854. // History: 04-Aug-94 PhilipLa Created
  855. //
  856. //---------------------------------------------------------------
  857. _OLESTDMETHODIMP CSimpStorage::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
  858. {
  859. return STG_E_INVALIDFUNCTION;
  860. }
  861. //+--------------------------------------------------------------
  862. //
  863. // Member: CSimpStorage::AddRef, public
  864. //
  865. // Synopsis: Increments the ref count
  866. //
  867. // Returns: Appropriate status code
  868. //
  869. // History: 04-Aug-94 PhilipLa Created
  870. //
  871. //---------------------------------------------------------------
  872. STDMETHODIMP_(ULONG) CSimpStorage::AddRef(void)
  873. {
  874. ULONG ulRet;
  875. olLog(("%p::In CSimpStorage::AddRef()\n", this));
  876. simpDebugOut((DEB_TRACE, "In CSimpStorage::AddRef()\n"));
  877. AtomicInc(&_cReferences);
  878. ulRet = _cReferences;
  879. simpDebugOut((DEB_TRACE, "Out CSimpStorage::AddRef\n"));
  880. olLog(("%p::Out CSimpStorage::AddRef(). ret == %lu\n", this, ulRet));
  881. return ulRet;
  882. }
  883. //+--------------------------------------------------------------
  884. //
  885. // Member: CSimpStorage::QueryInterface, public
  886. //
  887. // Synopsis: Returns an object for the requested interface
  888. //
  889. // Arguments: [iid] - Interface ID
  890. // [ppvObj] - Object return
  891. //
  892. // Returns: Appropriate status code
  893. //
  894. // Modifies: [ppvObj]
  895. //
  896. // History: 04-Aug-94 PhilipLa Created
  897. //
  898. //---------------------------------------------------------------
  899. STDMETHODIMP CSimpStorage::QueryInterface(REFIID iid, void **ppvObj)
  900. {
  901. SCODE sc;
  902. olLog(("%p::In CSimpStorage::QueryInterface(?, %p)\n",
  903. this, ppvObj));
  904. simpDebugOut((DEB_TRACE, "In CSimpStorage::QueryInterface(?, %p)\n",
  905. ppvObj));
  906. SIMP_VALIDATE(QueryInterface(iid, ppvObj));
  907. sc = S_OK;
  908. if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
  909. {
  910. *ppvObj = (IStorage *)this;
  911. CSimpStorage::AddRef();
  912. }
  913. else if (IsEqualIID(iid, IID_IMarshal))
  914. {
  915. *ppvObj = (IMarshal *)this;
  916. CSimpStorage::AddRef();
  917. }
  918. else if (IsEqualIID(iid, IID_IPropertySetStorage))
  919. {
  920. *ppvObj = (IPropertySetStorage *)this;
  921. CSimpStorage::AddRef();
  922. }
  923. else
  924. sc = E_NOINTERFACE;
  925. olLog(("%p::Out CSimpStorage::QueryInterface(). "
  926. "*ppvObj == %p ret == %lx\n", this, *ppvObj, sc));
  927. simpDebugOut((DEB_TRACE, "Out CSimpStorage::QueryInterface => %p\n",
  928. ppvObj));
  929. return ResultFromScode(sc);
  930. }
  931. //+--------------------------------------------------------------
  932. //
  933. // Member: CSimpStorage::GetUnmarshalClass, public
  934. //
  935. // Synopsis: Returns the class ID
  936. //
  937. // Arguments: [riid] - IID of object
  938. // [pv] - Unreferenced
  939. // [dwDestContext] - Unreferenced
  940. // [pvDestContext] - Unreferenced
  941. // [mshlflags] - Unreferenced
  942. // [pcid] - CLSID return
  943. //
  944. // Returns: Invalid function.
  945. //
  946. // Modifies: [pcid]
  947. //
  948. // History: 04-Aug-94 PhilipLa Created
  949. //
  950. //---------------------------------------------------------------
  951. STDMETHODIMP CSimpStorage::GetUnmarshalClass(REFIID riid,
  952. void *pv,
  953. DWORD dwDestContext,
  954. LPVOID pvDestContext,
  955. DWORD mshlflags,
  956. LPCLSID pcid)
  957. {
  958. return STG_E_INVALIDFUNCTION;
  959. }
  960. //+--------------------------------------------------------------
  961. //
  962. // Member: CSimpStorage::GetMarshalSizeMax, public
  963. //
  964. // Synopsis: Returns the size needed for the marshal buffer
  965. //
  966. // Arguments: [riid] - IID of object being marshaled
  967. // [pv] - Unreferenced
  968. // [dwDestContext] - Unreferenced
  969. // [pvDestContext] - Unreferenced
  970. // [mshlflags] - Unreferenced
  971. // [pcbSize] - Size return
  972. //
  973. // Returns: Appropriate status code
  974. //
  975. // Modifies: [pcbSize]
  976. //
  977. // History: 04-Aug-94 PhilipLa Created
  978. //
  979. //---------------------------------------------------------------
  980. STDMETHODIMP CSimpStorage::GetMarshalSizeMax(REFIID riid,
  981. void *pv,
  982. DWORD dwDestContext,
  983. LPVOID pvDestContext,
  984. DWORD mshlflags,
  985. LPDWORD pcbSize)
  986. {
  987. return STG_E_INVALIDFUNCTION;
  988. }
  989. //+--------------------------------------------------------------
  990. //
  991. // Member: CSimpStorage::MarshalInterface, public
  992. //
  993. // Synopsis: Marshals a given object
  994. //
  995. // Arguments: [pstStm] - Stream to write marshal data into
  996. // [riid] - Interface to marshal
  997. // [pv] - Unreferenced
  998. // [dwDestContext] - Unreferenced
  999. // [pvDestContext] - Unreferenced
  1000. // [mshlflags] - Unreferenced
  1001. //
  1002. // Returns: Appropriate status code
  1003. //
  1004. // History: 04-Aug-94 PhilipLa Created
  1005. //
  1006. //---------------------------------------------------------------
  1007. STDMETHODIMP CSimpStorage::MarshalInterface(IStream *pstStm,
  1008. REFIID riid,
  1009. void *pv,
  1010. DWORD dwDestContext,
  1011. LPVOID pvDestContext,
  1012. DWORD mshlflags)
  1013. {
  1014. return STG_E_INVALIDFUNCTION;
  1015. }
  1016. //+--------------------------------------------------------------
  1017. //
  1018. // Member: CSimpStorage::UnmarshalInterface, public
  1019. //
  1020. // Synopsis: Non-functional
  1021. //
  1022. // Arguments: [pstStm] -
  1023. // [riid] -
  1024. // [ppvObj] -
  1025. //
  1026. // Returns: Appropriate status code
  1027. //
  1028. // Modifies: [ppvObj]
  1029. //
  1030. // History: 04-Aug-94 PhilipLa Created
  1031. //
  1032. //---------------------------------------------------------------
  1033. STDMETHODIMP CSimpStorage::UnmarshalInterface(IStream *pstStm,
  1034. REFIID riid,
  1035. void **ppvObj)
  1036. {
  1037. return STG_E_INVALIDFUNCTION;
  1038. }
  1039. //+--------------------------------------------------------------
  1040. //
  1041. // Member: CSimpStorage::ReleaseMarshalData, public
  1042. //
  1043. // Synopsis: Non-functional
  1044. //
  1045. // Arguments: [pstStm] -
  1046. //
  1047. // Returns: Appropriate status code
  1048. //
  1049. // History: 18-Sep-92 PhilipLa Created
  1050. //
  1051. //---------------------------------------------------------------
  1052. STDMETHODIMP CSimpStorage::ReleaseMarshalData(IStream *pstStm)
  1053. {
  1054. return STG_E_INVALIDFUNCTION;
  1055. }
  1056. //+--------------------------------------------------------------
  1057. //
  1058. // Member: CSimpStorage::DisconnectObject, public
  1059. //
  1060. // Synopsis: Non-functional
  1061. //
  1062. // Arguments: [dwRevserved] -
  1063. //
  1064. // Returns: Appropriate status code
  1065. //
  1066. // History: 18-Sep-92 PhilipLa Created
  1067. //
  1068. //---------------------------------------------------------------
  1069. STDMETHODIMP CSimpStorage::DisconnectObject(DWORD dwReserved)
  1070. {
  1071. return STG_E_INVALIDFUNCTION;
  1072. }