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.

1264 lines
33 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: tstream.cxx
  7. //
  8. // Contents: Transacted stream functions
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 23-Jan-92 PhilipLa Created.
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "msfhead.cxx"
  18. #pragma hdrstop
  19. #include "tstream.hxx"
  20. #include "dl.hxx"
  21. #include "mread.hxx"
  22. #include <handle.hxx>
  23. #include <memory.h>
  24. #include <dfdeb.hxx>
  25. #define DEB_TSTREAM (DEB_ITRACE | 0x00200000)
  26. //+--------------------------------------------------------------
  27. //
  28. // Member: CTransactedStream::CTransactedStream, public
  29. //
  30. // Synopsis: Empty object ctor
  31. //
  32. // Arguments: [pdfn] - Name
  33. // [dl] - LUID
  34. // [df] -- Permissions flags
  35. // [dwType] - Entry type
  36. // [pmsScratch] -- Scratch multistream
  37. //
  38. // History: 31-Jul-92 DrewB Created
  39. //
  40. //---------------------------------------------------------------
  41. CTransactedStream::CTransactedStream(CDfName const *pdfn,
  42. DFLUID dl,
  43. DFLAGS df,
  44. CMStream *pms,
  45. CMStream *pmsScratch)
  46. : PTSetMember(pdfn, STGTY_STREAM),
  47. PSStream(dl),
  48. _dl(pms, pmsScratch)
  49. {
  50. msfDebugOut((DEB_ITRACE, "In CTransactedStream::CTransactedStream:%p("
  51. "%lu)\n", this, dl));
  52. _pssBase = NULL;
  53. _pdlOld = NULL;
  54. _df = df;
  55. _cReferences = 0;
  56. _fDirty = 0;
  57. _fBeginCommit = FALSE;
  58. PBasicEntry::_sig = CTRANSACTEDSTREAM_SIG;
  59. PTSetMember::_sig = CTRANSACTEDSTREAM_SIG;
  60. msfDebugOut((DEB_ITRACE, "Out CTransactedStream::CTransactedStream\n"));
  61. }
  62. //+-------------------------------------------------------------------------
  63. //
  64. // Method: CTransactedStream::Init, public
  65. //
  66. // Synopsis: CTransactedStream constructor
  67. //
  68. // Arguments: [pssBase] -- Pointer to base stream
  69. //
  70. // Returns: Appropriate status code
  71. //
  72. // History: 23-Jan-92 PhilipLa Created.
  73. // 31-Jul-92 DrewB Converted to Init from ctor
  74. //
  75. // Notes:
  76. //
  77. //--------------------------------------------------------------------------
  78. SCODE CTransactedStream::Init(PSStream *pssBase)
  79. {
  80. SCODE sc;
  81. msfDebugOut((DEB_ITRACE,"In %p:CTransactedStream constructor(%p)\n",
  82. this, pssBase));
  83. msfChk(SetInitialState(pssBase));
  84. _pssBase = P_TO_BP(CBasedSStreamPtr, pssBase);
  85. _sectLastUsed = 0;
  86. AddRef();
  87. msfDebugOut((DEB_ITRACE,"Out CTransactedStream constructor\n"));
  88. // Fall through
  89. Err:
  90. return sc;
  91. }
  92. //+-------------------------------------------------------------------------
  93. //
  94. // Method: CTransactedStream::~CTransactedStream, public
  95. //
  96. // Synopsis: CTransactedStream destructor
  97. //
  98. // History: 23-Jan-92 PhilipLa Created.
  99. //
  100. //--------------------------------------------------------------------------
  101. CTransactedStream::~CTransactedStream()
  102. {
  103. msfDebugOut((DEB_ITRACE,"In CTransactedStream Destructor\n"));
  104. msfAssert(_cReferences == 0);
  105. PBasicEntry::_sig = CTRANSACTEDSTREAM_SIGDEL;
  106. PTSetMember::_sig = CTRANSACTEDSTREAM_SIGDEL;
  107. _dl.Empty();
  108. if (_pssBase)
  109. {
  110. _pssBase->Release();
  111. }
  112. msfDebugOut((DEB_ITRACE,"Out CTransactedStream Destructor\n"));
  113. }
  114. //+-------------------------------------------------------------------------
  115. //
  116. // Member: CTransactedStream::ReadAt, public
  117. //
  118. // Synposis: Reads binary data from a transacted stream
  119. //
  120. // Arguments: [ulOffset] -- Position to be read from
  121. //
  122. // [pBuffer] -- Pointer to the area into which the data
  123. // will be read.
  124. // [ulCount] -- Indicates the number of bytes to be read
  125. // [pulRetval] -- Area into which return value will be stored
  126. //
  127. // Returns: S_OK if call completed OK.
  128. //
  129. // Algorithm: *Finish This*
  130. //
  131. // History: 22-Jan-92 PhilipLa Created.
  132. //
  133. // Notes: [pBuffer] may be unsafe memory
  134. //
  135. //---------------------------------------------------------------------------
  136. SCODE CTransactedStream::ReadAt(
  137. #ifdef LARGE_STREAMS
  138. ULONGLONG ulOffset,
  139. #else
  140. ULONG ulOffset,
  141. #endif
  142. VOID HUGEP *pBuffer,
  143. ULONG ulCount,
  144. ULONG STACKBASED *pulRetval)
  145. {
  146. msfDebugOut((DEB_ITRACE,"In %p:CTransactedStream::ReadAt(%lu,%p,%lu)\n",this,ulOffset,pBuffer,ulCount));
  147. SCODE sc;
  148. if (ulOffset + ulCount > _ulSize)
  149. {
  150. #ifdef LARGE_STREAMS
  151. if (_ulSize - ulOffset > ULONG_MAX) // too far past the end
  152. ulCount = 0;
  153. else
  154. #endif
  155. ulCount = (ULONG)(_ulSize - ulOffset);
  156. }
  157. if ((ulCount == 0) || (ulOffset > _ulSize))
  158. {
  159. *pulRetval = 0;
  160. return S_OK;
  161. }
  162. msfAssert(P_TRANSACTED(_df));
  163. if (_dl.IsEmpty())
  164. {
  165. //If we have an empty delta list, either our size is 0 (in which
  166. // case we'll never get to this line), or we have a parent.
  167. msfAssert(_pssBase != NULL);
  168. msfDebugOut((DEB_ITRACE,"Calling up to _pssBase\n"));
  169. sc = _pssBase->ReadAt(ulOffset,pBuffer,ulCount,pulRetval);
  170. msfDebugOut((DEB_ITRACE,
  171. "Out CTransactedStream::ReadAt()=>%lu, ret is %lu\n",
  172. sc, *pulRetval));
  173. return sc;
  174. }
  175. ILockBytes *pilbDirty = _dl.GetDataILB();
  176. USHORT cbSector = _dl.GetDataSectorSize();
  177. USHORT uSectorShift = _dl.GetDataSectorShift();
  178. ULONG temp = 0;
  179. ULONG cb = 0;
  180. SECT snow =(SECT)(ulOffset / cbSector);
  181. OFFSET off = (OFFSET)(ulOffset % cbSector);
  182. SECT send = (SECT)((ulOffset + ulCount - 1) / cbSector);
  183. OFFSET offEnd = (OFFSET)((ulOffset + ulCount - 1) % cbSector);
  184. USHORT csect = 0;
  185. SECT sectNext1;
  186. SECT sectCurrent = snow;
  187. BYTE HUGEP *pb = (BYTE HUGEP *)pBuffer;
  188. USHORT oStart = off;
  189. USHORT oEnd = 0;
  190. SECT sectLast = ENDOFCHAIN;
  191. SECT sectFirst = ENDOFCHAIN;
  192. const USHORT ISDIRTY = 0;
  193. const USHORT ISBASE = 1;
  194. USHORT uLast;
  195. msfChk(_dl.GetMap(sectCurrent, DL_READ, &sectNext1));
  196. if (sectNext1 != ENDOFCHAIN)
  197. {
  198. uLast = ISDIRTY;
  199. sectLast = sectFirst = sectNext1;
  200. }
  201. else
  202. {
  203. uLast = ISBASE;
  204. sectLast = sectFirst = sectCurrent;
  205. }
  206. sectCurrent++;
  207. while (sectCurrent <= send)
  208. {
  209. SECT sectNext;
  210. msfChk(_dl.GetMap(sectCurrent, DL_READ, &sectNext));
  211. //If any of the following occur, read the current segment:
  212. // 1) Sector has mapping and current segment is in base
  213. // 2) Sector has mapping and is not contiguous with
  214. // current segment.
  215. // 3) Sector has no mapping and current segment is in dirty.
  216. if (((sectNext != ENDOFCHAIN) && (uLast == ISBASE)) ||
  217. ((sectNext != ENDOFCHAIN) && (sectNext != sectLast + 1)) ||
  218. ((sectNext == ENDOFCHAIN) && (uLast == ISDIRTY)))
  219. {
  220. msfDebugOut((DEB_ITRACE,"Reading block from pssLast\n"));
  221. if (uLast == ISDIRTY)
  222. {
  223. ULARGE_INTEGER ulTmp;
  224. #ifdef LARGE_DOCFILE
  225. ulTmp.QuadPart = ConvertSectOffset(
  226. sectFirst,
  227. oStart,
  228. uSectorShift);
  229. #else
  230. ULISet32(ulTmp, ConvertSectOffset(
  231. sectFirst,
  232. oStart,
  233. uSectorShift));
  234. #endif
  235. msfHChk(pilbDirty->ReadAt(
  236. ulTmp,
  237. pb,
  238. (sectLast - sectFirst + 1) * cbSector - oStart - oEnd,
  239. &temp));
  240. }
  241. else
  242. {
  243. msfChk(_pssBase->ReadAt(
  244. sectFirst * cbSector + oStart,
  245. pb,
  246. (sectLast - sectFirst + 1) * cbSector - oStart - oEnd,
  247. (ULONG STACKBASED *)&temp));
  248. }
  249. pb += temp;
  250. cb += temp;
  251. oStart = 0;
  252. if (sectNext == ENDOFCHAIN)
  253. {
  254. sectFirst = sectCurrent;
  255. uLast = ISBASE;
  256. }
  257. else
  258. {
  259. sectFirst = sectNext;
  260. uLast = ISDIRTY;
  261. }
  262. }
  263. sectLast = (sectNext == ENDOFCHAIN) ? sectCurrent : sectNext;
  264. sectCurrent++;
  265. }
  266. oEnd = (cbSector - 1) - offEnd;
  267. msfDebugOut((DEB_ITRACE,"Reading last sector block\n"));
  268. if (uLast == ISDIRTY)
  269. {
  270. ULARGE_INTEGER ulTmp;
  271. #ifdef LARGE_DOCFILE
  272. ulTmp.QuadPart = ConvertSectOffset(sectFirst, oStart, uSectorShift);
  273. #else
  274. ULISet32(ulTmp,
  275. ConvertSectOffset(sectFirst, oStart, uSectorShift));
  276. #endif
  277. msfHChk(pilbDirty->ReadAt(
  278. ulTmp,
  279. pb,
  280. (sectLast - sectFirst + 1) * cbSector - oStart - oEnd,
  281. &temp));
  282. }
  283. else
  284. {
  285. msfChk(_pssBase->ReadAt(
  286. sectFirst * cbSector + oStart,
  287. pb,
  288. (sectLast - sectFirst + 1) * cbSector - oStart - oEnd,
  289. (ULONG STACKBASED *)&temp));
  290. }
  291. pb += temp;
  292. cb += temp;
  293. oStart = 0;
  294. *pulRetval = cb;
  295. msfDebugOut((DEB_ITRACE,"Out CTransactedStream::ReadAt()=>%lu, ret is %lu\n",(ULONG)S_OK,*pulRetval));
  296. Err:
  297. return sc;
  298. }
  299. //+-------------------------------------------------------------------------
  300. //
  301. // Member: CTransactedStream::WriteAt, public
  302. //
  303. // Synposis: Writes binary data to a linear single stream
  304. //
  305. // Effects: Modifies _ulSeekPos. May cause modification in parent
  306. // MStream.
  307. //
  308. // Arguments: [pBuffer] -- Pointer to the area from which the data
  309. // will be written.
  310. // [ulCount] -- Indicates the number of bytes to be written
  311. // [pulRetval] -- Pointer to area in which number of bytes
  312. // will be returned
  313. //
  314. // Returns: Error code of MStream call.
  315. //
  316. // Algorithm: Calculate sector and offset for beginning and end of
  317. // write, then pass call up to MStream.
  318. //
  319. //
  320. // History: 18-Jul-91 PhilipLa Created.
  321. // 16-Aug-91 PhilipLa Converted to use multi-sect write
  322. // 23-Aug-91 PhilipLa Brought into compliance with protocol
  323. // 11-Sep-91 PhilipLa Moved most functionality up
  324. // to MStream level.
  325. //
  326. // Notes: [pBuffer] may be unsafe memory
  327. //
  328. //---------------------------------------------------------------------------
  329. SCODE CTransactedStream::WriteAt(
  330. #ifdef LARGE_STREAMS
  331. ULONGLONG ulOffset,
  332. #else
  333. ULONG ulOffset,
  334. #endif
  335. VOID const HUGEP *pBuffer,
  336. ULONG ulCount,
  337. ULONG STACKBASED *pulRetval)
  338. {
  339. msfDebugOut((DEB_ITRACE,"In CTransactedStream::WriteAt(%lu,%p,%lu)\n",ulOffset,pBuffer,ulCount));
  340. SCODE sc = S_OK;
  341. msfAssert(P_TRANSACTED(_df));
  342. USHORT cbSector = _dl.GetDataSectorSize();
  343. USHORT uSectorShift = _dl.GetDataSectorShift();
  344. BYTE *pbDirty;
  345. pbDirty = NULL;
  346. ULONG temp;
  347. temp = 0;
  348. if (ulCount == 0)
  349. {
  350. msfDebugOut((DEB_ITRACE,"ulCount==0. Returning.\n"));
  351. *pulRetval = 0;
  352. return S_OK;
  353. }
  354. //If size after the write will be greater than the current
  355. //size, we may need a new delta list.
  356. if (ulOffset + ulCount > _ulSize)
  357. {
  358. msfChk(SetSize(ulOffset + ulCount));
  359. }
  360. if (_dl.IsEmpty())
  361. {
  362. msfChk(_dl.Init(_ulSize, this));
  363. }
  364. ILockBytes *pilbDirty;
  365. pilbDirty = _dl.GetDataILB();
  366. SECT sectStart;
  367. sectStart = (SECT)(ulOffset / cbSector);
  368. OFFSET oStart;
  369. oStart = (OFFSET)(ulOffset % cbSector);
  370. SECT send;
  371. send = (SECT)((ulOffset + ulCount - 1) / cbSector);
  372. OFFSET offEnd;
  373. offEnd = (OFFSET)((ulOffset + ulCount - 1) % cbSector) + 1;
  374. OFFSET oEnd;
  375. oEnd = 0;
  376. BYTE const HUGEP *pb;
  377. pb = (BYTE const HUGEP *)pBuffer;
  378. ULONG cb;
  379. cb = 0;
  380. USHORT cbBlock;
  381. cbBlock = 0;
  382. SECT sectMap = 0;
  383. SECT sectFirst,sectLast;
  384. if (sectStart == send)
  385. {
  386. oEnd = cbSector - offEnd;
  387. }
  388. SECT sectBlockStart;
  389. msfChk(_dl.GetMap(sectStart, DL_GET, &sectBlockStart));
  390. //This handles partial first sector and
  391. // one sector only writes.
  392. while ((oStart) || (sectStart == send))
  393. {
  394. cbBlock = cbSector - oStart - oEnd;
  395. if (sectBlockStart == ENDOFCHAIN)
  396. {
  397. msfDebugOut((DEB_ITRACE,"Unmapped partial first sector\n"));
  398. msfChk(_dl.GetMap(sectStart, DL_CREATE, &sectMap));
  399. msfChk(PartialWrite(
  400. sectStart,
  401. sectMap,
  402. pb,
  403. oStart,
  404. cbBlock));
  405. }
  406. else
  407. {
  408. sectMap = sectBlockStart;
  409. ULARGE_INTEGER ulTmp;
  410. #ifdef LARGE_DOCFILE
  411. ulTmp.QuadPart = ConvertSectOffset(sectMap, oStart, uSectorShift);
  412. #else
  413. ULISet32 (ulTmp,
  414. ConvertSectOffset(sectMap, oStart, uSectorShift));
  415. #endif
  416. msfHChk(pilbDirty->WriteAt(
  417. ulTmp,
  418. pb,
  419. cbBlock,
  420. &temp));
  421. }
  422. pb += cbBlock;
  423. cb += cbBlock;
  424. //If it was one-sector only, we can return here.
  425. if (sectStart == send)
  426. {
  427. *pulRetval = cb;
  428. return S_OK;
  429. }
  430. sectStart++;
  431. oStart = 0;
  432. msfChk(_dl.GetMap(sectStart, DL_GET, &sectBlockStart));
  433. if (sectStart == send)
  434. {
  435. oEnd = cbSector - offEnd;
  436. }
  437. }
  438. if (sectBlockStart == ENDOFCHAIN)
  439. {
  440. msfChk(_dl.GetMap(sectStart, DL_CREATE, &sectMap));
  441. }
  442. sectLast = sectFirst = (sectBlockStart == ENDOFCHAIN) ? sectMap
  443. : sectBlockStart;
  444. SECT sectCurrent;
  445. sectCurrent = sectStart + 1;
  446. while (sectCurrent < send)
  447. {
  448. msfDebugOut((DEB_ITRACE,"In main loop: sectCurrent = %lu\n",sectCurrent));
  449. msfChk(_dl.GetMap(sectCurrent, DL_CREATE, &sectMap));
  450. if (sectMap != sectLast + 1)
  451. {
  452. ULARGE_INTEGER ulTmp;
  453. #ifdef LARGE_DOCFILE
  454. ulTmp.QuadPart = ConvertSectOffset(sectFirst, oStart, uSectorShift);
  455. #else
  456. ULISet32 (ulTmp,
  457. ConvertSectOffset(sectFirst, oStart, uSectorShift));
  458. #endif
  459. msfHChk(pilbDirty->WriteAt(
  460. ulTmp,
  461. pb,
  462. (sectLast - sectFirst + 1) * cbSector - oStart,
  463. &temp));
  464. pb += temp;
  465. cb += temp;
  466. oStart = 0;
  467. sectFirst = sectMap;
  468. }
  469. sectLast = sectMap;
  470. sectCurrent++;
  471. }
  472. msfAssert(oStart == 0);
  473. msfChk(_dl.GetMap(sectCurrent, DL_GET, &sectMap));
  474. oEnd = cbSector - offEnd;
  475. BOOL fIsMapped;
  476. if (sectMap == ENDOFCHAIN)
  477. {
  478. fIsMapped = FALSE;
  479. msfChk(_dl.GetMap(sectCurrent,DL_CREATE, &sectMap));
  480. }
  481. else
  482. {
  483. fIsMapped = TRUE;
  484. }
  485. if ((sectMap != sectLast + 1) || (oEnd != 0))
  486. {
  487. ULARGE_INTEGER ulTmp;
  488. #ifdef LARGE_DOCFILE
  489. ulTmp.QuadPart = ConvertSectOffset(sectFirst, oStart, uSectorShift);
  490. #else
  491. ULISet32 (ulTmp,
  492. ConvertSectOffset(sectFirst, oStart, uSectorShift));
  493. #endif
  494. msfHChk(pilbDirty->WriteAt(
  495. ulTmp,
  496. pb,
  497. (sectLast - sectFirst + 1) * cbSector - oStart,
  498. &temp));
  499. pb += temp;
  500. cb += temp;
  501. oStart = 0;
  502. sectFirst = sectMap;
  503. }
  504. if (oEnd == 0)
  505. {
  506. ULARGE_INTEGER ulTmp;
  507. #ifdef LARGE_DOCFILE
  508. ulTmp.QuadPart = ConvertSectOffset(sectFirst, oStart, uSectorShift);
  509. #else
  510. ULISet32 (ulTmp,
  511. ConvertSectOffset(sectFirst, oStart, uSectorShift));
  512. #endif
  513. msfHChk(pilbDirty->WriteAt(
  514. ulTmp,
  515. pb,
  516. (sectMap - sectFirst + 1) * cbSector - oStart - oEnd,
  517. &temp));
  518. pb += temp;
  519. cb += temp;
  520. oStart = 0;
  521. }
  522. else
  523. {
  524. cbBlock = cbSector - oEnd;
  525. if (!fIsMapped)
  526. {
  527. msfChk(PartialWrite(
  528. sectCurrent,
  529. sectMap,
  530. pb,
  531. 0,
  532. cbBlock));
  533. }
  534. else
  535. {
  536. ULARGE_INTEGER ulTmp;
  537. #ifdef LARGE_DOCFILE
  538. ulTmp.QuadPart = ConvertSectOffset(sectMap, oStart, uSectorShift);
  539. #else
  540. ULISet32 (ulTmp,
  541. ConvertSectOffset(sectMap, oStart, uSectorShift));
  542. #endif
  543. msfHChk(pilbDirty->WriteAt(
  544. ulTmp,
  545. pb,
  546. cbBlock,
  547. &temp));
  548. }
  549. pb += cbBlock;
  550. cb += cbBlock;
  551. }
  552. *pulRetval = cb;
  553. msfDebugOut((DEB_ITRACE,"Leaving CTransactedStream::WriteAt()==>%lu, ret is %lu\n",(ULONG)S_OK,*pulRetval));
  554. Err:
  555. return sc;
  556. }
  557. //+-------------------------------------------------------------------------
  558. //
  559. // Member: CTransactedStream::SetSize, public
  560. //
  561. // Synposis: Set the size of a linear stream
  562. //
  563. // Effects: Modifies _ulSize. May cause change in parent MStream.
  564. //
  565. // Arguments: [ulNewSize] -- New size for stream
  566. //
  567. // Returns: Error code returned by MStream call.
  568. //
  569. // Algorithm: Pass call up to parent.
  570. //
  571. // History: 29-Jul-91 PhilipLa Created.
  572. //
  573. // Notes:
  574. //
  575. //---------------------------------------------------------------------------
  576. #ifdef LARGE_STREAMS
  577. SCODE CTransactedStream::SetSize(ULONGLONG ulNewSize)
  578. #else
  579. SCODE CTransactedStream::SetSize(ULONG ulNewSize)
  580. #endif
  581. {
  582. SCODE sc = S_OK;
  583. BYTE *pb = NULL;
  584. SECT sectMaxValid;
  585. msfDebugOut((DEB_ITRACE,"In CTransactedStream::SetSize(%lu)\n",ulNewSize));
  586. msfAssert(P_TRANSACTED(_df));
  587. if (ulNewSize == 0)
  588. {
  589. _dl.Empty();
  590. }
  591. else if (!_dl.IsEmpty())
  592. {
  593. msfChk(_dl.InitResize(ulNewSize));
  594. }
  595. else
  596. {
  597. msfChk(_dl.Init(ulNewSize, this));
  598. }
  599. if (ulNewSize > _ulSize)
  600. {
  601. USHORT cbSector = _dl.GetDataSectorSize();
  602. USHORT uSectorShift = _dl.GetDataSectorShift();
  603. SECT sectStart, sectEnd, sect, sectNew;
  604. if (_ulSize == 0)
  605. {
  606. sectStart = 0;
  607. }
  608. else
  609. {
  610. sectStart = (SECT)((_ulSize - 1) / cbSector);
  611. }
  612. sectEnd = (SECT)((ulNewSize - 1 ) / cbSector);
  613. //First, make sure the first sector is copied over OK if necessary.
  614. msfChk(_dl.GetMap(sectStart, DL_GET, &sectNew));
  615. if ((sectNew == ENDOFCHAIN) && (_pssBase != NULL) &&
  616. (_ulSize != 0))
  617. {
  618. ULONG cbNull;
  619. GetSafeBuffer(cbSector, cbSector, &pb, &cbNull);
  620. msfAssert((pb != NULL) && aMsg("Couldn't get scratch buffer"));
  621. ULONG dummy;
  622. msfChk(_pssBase->ReadAt(
  623. (ULONGLONG)(sectStart) << uSectorShift,
  624. pb,
  625. cbSector,
  626. (ULONG STACKBASED *)&dummy));
  627. msfChk(_dl.GetMap(sectStart, DL_CREATE, &sectNew));
  628. ULARGE_INTEGER ulTmp;
  629. #ifdef LARGE_DOCFILE
  630. ulTmp.QuadPart = ConvertSectOffset(sectNew, 0, uSectorShift);
  631. #else
  632. ULISet32 (ulTmp, ConvertSectOffset(sectNew, 0, uSectorShift));
  633. #endif
  634. msfHChk(_dl.GetDataILB()->WriteAt(
  635. ulTmp,
  636. pb,
  637. cbSector,
  638. &dummy));
  639. sectStart++;
  640. }
  641. //
  642. // Get the current last valid sector in case there is an error
  643. // allocating the delta list or MStream space.
  644. // Warning: FindMaxSect() returns the Max Allocated Sect, Plus One.
  645. //
  646. msfChk(_dl.GetDataFat()->FindMaxSect(&sectMaxValid));
  647. --sectMaxValid;
  648. //
  649. // Allocate new sectors one at a time.
  650. // GetMap() in DL_CREATE mode does not actually grow the MStream.
  651. // It allocates FAT entries.
  652. //
  653. for (sect = sectStart; sect <= sectEnd; sect ++)
  654. {
  655. if(FAILED(sc = _dl.GetMap(sect, DL_CREATE, &sectNew)))
  656. break;
  657. }
  658. //
  659. // Grow the MStream (which in turn grows the ILB) to include
  660. // any newly allocated SECTs. If that fails then release entries
  661. // in the FAT that couldn't be allocated in the ILB.
  662. // ie. Beyond the previous recorded Max SECT of the MStream.
  663. //
  664. if(FAILED(sc) || FAILED(_dl.GetMStream()->SetSize()))
  665. {
  666. _dl.ReleaseInvalidSects(sectMaxValid);
  667. goto Err;
  668. }
  669. }
  670. _ulSize = ulNewSize;
  671. msfDebugOut((DEB_ITRACE,"Out CTransactedStream::SetSize()\n"));
  672. Err:
  673. FreeBuffer(pb);
  674. return sc;
  675. }
  676. //+-------------------------------------------------------------------------
  677. //
  678. // Method: CTransactedStream::BeginCommitFromChild, public
  679. //
  680. // Synopsis: Begin a commit from a child TStream
  681. //
  682. // Arguments: [ulSize] - New size
  683. // [pDelta] - Delta list
  684. // [pstChild] - Child
  685. //
  686. // Returns: S_OK if call completed OK.
  687. //
  688. // Algorithm: *Finish This*
  689. //
  690. // History: 22-Jan-92 PhilipLa Created.
  691. //
  692. //--------------------------------------------------------------------------
  693. SCODE CTransactedStream::BeginCommitFromChild(
  694. #ifdef LARGE_STREAMS
  695. ULONGLONG ulSize,
  696. #else
  697. ULONG ulSize,
  698. #endif
  699. CDeltaList *pDelta,
  700. CTransactedStream *pstChild)
  701. {
  702. msfDebugOut((DEB_ITRACE,"In CTransactedStream::BeginCommitFromChild:%p("
  703. "%lu, %p, %p)\n", this, ulSize, pDelta, pstChild));
  704. msfAssert(P_TRANSACTED(_df));
  705. _dl.BeginCommit(this);
  706. _pdlOld = P_TO_BP(CBasedDeltaListPtr, pDelta);
  707. _ulOldSize = _ulSize;
  708. _ulSize = ulSize;
  709. msfDebugOut((DEB_ITRACE,"Out CTransactedStream::BeginCommitFromChild()\n"));
  710. return S_OK;
  711. }
  712. //+-------------------------------------------------------------------------
  713. //
  714. // Method: CTransactedStream::EndCommitFromChild, public
  715. //
  716. // Synopsis: End a commit from child.
  717. //
  718. // Arguments: [df] -- Flags to determine whether to commit or revert
  719. // [pstChild] - Child
  720. //
  721. // Returns: Void. This can't fail.
  722. //
  723. // Algorithm: *Finish This*
  724. //
  725. // History: 22-Jan-92 PhilipLa Created.
  726. //
  727. // Notes:
  728. //
  729. //--------------------------------------------------------------------------
  730. void CTransactedStream::EndCommitFromChild(DFLAGS df,
  731. CTransactedStream *pstChild)
  732. {
  733. msfDebugOut((DEB_ITRACE,"In CTransactedStream::EndCommitFromChild:%p("
  734. "%lu, %p)\n", this, df, pstChild));
  735. msfAssert(P_TRANSACTED(_df));
  736. _dl.EndCommit(BP_TO_P(CDeltaList *, _pdlOld), df);
  737. //NOTE: Possible cleanup: Move _pdlOld into the delta list itself.
  738. _pdlOld = NULL;
  739. if (P_COMMIT(df))
  740. {
  741. _ulOldSize = 0;
  742. }
  743. else
  744. {
  745. _ulSize = _ulOldSize;
  746. }
  747. msfDebugOut((DEB_ITRACE,"Out CTransactedStream::EndCommitFromChild()\n"));
  748. }
  749. //+-------------------------------------------------------------------------
  750. //
  751. // Method: CTransactedStream::BeginCommit, public
  752. //
  753. // Synopsis: Begin a commit of a transacted stream object
  754. //
  755. // Arguments: [dwFlags] -- Currently not used (future expansion)
  756. //
  757. // Returns: S_OK if call completed OK.
  758. //
  759. // Algorithm: Call BeginCommitFromChild on base
  760. //
  761. // History: 22-Jan-92 PhilipLa Created.
  762. //
  763. // Notes: This is only called by the Transaction Level object.
  764. //
  765. //--------------------------------------------------------------------------
  766. SCODE CTransactedStream::BeginCommit(DWORD const dwFlags)
  767. {
  768. SCODE sc = S_OK;
  769. msfDebugOut((DEB_ITRACE,"In CTransactedStream::BeginCommit(%lu)\n",
  770. dwFlags));
  771. msfAssert(_pssBase != NULL);
  772. msfAssert(P_TRANSACTED(_df));
  773. #if DBG == 1
  774. if (!HaveResource(DBR_XSCOMMITS, 1))
  775. msfErr(Err, STG_E_ABNORMALAPIEXIT);
  776. #endif
  777. _fBeginCommit = TRUE;
  778. msfChk(_pssBase->BeginCommitFromChild(_ulSize, &_dl, this));
  779. msfDebugOut((DEB_ITRACE,"Out CTransactedStream::BeginCommit()\n"));
  780. Err:
  781. return sc;
  782. }
  783. //+-------------------------------------------------------------------------
  784. //
  785. // Method: CTransactedStream::EndCommit, public
  786. //
  787. // Synopsis: End a commit on a transacted stream object
  788. //
  789. // Arguments: [df] -- Indicator of whether to commit or revert
  790. //
  791. // Returns: void. This can't fail.
  792. //
  793. // Algorithm: Call EndCommitFromChild on base.
  794. // If committing, NULL out all previously passed up
  795. // dirty information.
  796. //
  797. // History: 22-Jan-92 PhilipLa Created.
  798. //
  799. // Notes:
  800. //
  801. //--------------------------------------------------------------------------
  802. void CTransactedStream::EndCommit(DFLAGS const df)
  803. {
  804. msfDebugOut((DEB_ITRACE,"In CTransactedStream::EndCommit(%lu)\n",df));
  805. msfAssert(P_TRANSACTED(_df));
  806. msfAssert((_pssBase != NULL) || (P_ABORT(df)));
  807. if (!_fBeginCommit)
  808. return;
  809. _fBeginCommit = FALSE;
  810. #if DBG == 1
  811. if (P_COMMIT(df))
  812. ModifyResLimit(DBR_XSCOMMITS, 1);
  813. #endif
  814. if (_pssBase != NULL)
  815. {
  816. _pssBase->EndCommitFromChild(df, this);
  817. }
  818. if (P_COMMIT(df))
  819. {
  820. _dl.Empty();
  821. SetClean();
  822. }
  823. msfDebugOut((DEB_ITRACE,"Out CTransactedStream::EndCommit()\n"));
  824. }
  825. //+-------------------------------------------------------------------------
  826. //
  827. // Method: CTransactedStream::Revert, public
  828. //
  829. // Synopsis: Revert a transacted stream instance.
  830. //
  831. // Algorithm: Destroy dirty stream and delta list.
  832. // Retrieve size from base.
  833. // Mark object as Invalid if specified in the flags.
  834. //
  835. // History: 22-Jan-92 PhilipLa Created.
  836. //
  837. // Notes: This is only called from the Transaction Level.
  838. //
  839. //--------------------------------------------------------------------------
  840. void CTransactedStream::Revert(void)
  841. {
  842. msfDebugOut((DEB_ITRACE,"In CTransactedStream::Revert(%lu): This == %p\n",this));
  843. _dl.Empty();
  844. msfVerify(SUCCEEDED(SetInitialState(BP_TO_P(PSStream *, _pssBase))));
  845. _sectLastUsed = 0;
  846. SetClean();
  847. msfDebugOut((DEB_ITRACE,"Out CTransactedStream::Revert()\n"));
  848. }
  849. //+--------------------------------------------------------------
  850. //
  851. // Member: CTransactedStream::SetBase, public
  852. //
  853. // Synopsis: Sets a new base
  854. //
  855. // Arguments: [psst] - New base
  856. //
  857. // Returns: Appropriate status code
  858. //
  859. // History: 31-Jul-92 DrewB Created
  860. //
  861. //---------------------------------------------------------------
  862. SCODE CTransactedStream::SetBase(PSStream *psst)
  863. {
  864. msfAssert(_pssBase == NULL || psst == NULL);
  865. if (_pssBase)
  866. _pssBase->Release();
  867. _pssBase = P_TO_BP(CBasedSStreamPtr, psst);
  868. return S_OK;
  869. }
  870. //+-------------------------------------------------------------------------
  871. //
  872. // Method: CTransactedStream::PartialWrite, private
  873. //
  874. // Synopsis: Do a write of a partial sector
  875. //
  876. // Arguments: [sectBase] -- Sector in base to copy
  877. // [sectDirty] -- Sector in dirty to write to
  878. // [pb] -- Buffer containing data to be writte
  879. // [offset] -- Offset into buffer to begin copy
  880. // [uLen] -- Number of bytes to copy
  881. //
  882. // Returns: S_OK if call completed OK.
  883. //
  884. // Algorithm: *Finish This*
  885. //
  886. // History: 30-Jun-92 PhilipLa Created.
  887. //
  888. // Notes: [pb] may be unsafe memory
  889. //
  890. //--------------------------------------------------------------------------
  891. SCODE CTransactedStream::PartialWrite(
  892. SECT sectBase,
  893. SECT sectDirty,
  894. BYTE const HUGEP *pb,
  895. USHORT offset,
  896. USHORT uLen)
  897. {
  898. msfDebugOut((DEB_ITRACE,"In CTransactedStream::PartialWrite()\n"));
  899. BYTE *pbMem = NULL;
  900. SCODE sc;
  901. ULONG temp;
  902. USHORT cbSector = _dl.GetDataSectorSize();
  903. USHORT uSectorShift = _dl.GetDataSectorShift();
  904. if (uLen != cbSector)
  905. {
  906. ULONG cbNull;
  907. GetSafeBuffer(cbSector, cbSector, &pbMem, &cbNull);
  908. msfAssert((pbMem != NULL) && aMsg("Couldn't get scratch buffer"));
  909. if (_pssBase != NULL)
  910. {
  911. msfChk(_pssBase->ReadAt(
  912. (ULONGLONG)(sectBase) << uSectorShift,
  913. pbMem,
  914. cbSector,
  915. (ULONG STACKBASED *)&temp));
  916. }
  917. TRY
  918. {
  919. memcpy(pbMem + offset, pb, uLen);
  920. }
  921. CATCH(CException, e)
  922. {
  923. UNREFERENCED_PARM(e);
  924. msfErr(Err, STG_E_INVALIDPOINTER);
  925. }
  926. END_CATCH
  927. pb = pbMem;
  928. }
  929. ULARGE_INTEGER ulTmp;
  930. #ifdef LARGE_DOCFILE
  931. ulTmp.QuadPart = ConvertSectOffset(sectDirty, 0, uSectorShift);
  932. #else
  933. ULISet32 (ulTmp,
  934. ConvertSectOffset(sectDirty, 0, uSectorShift));
  935. #endif
  936. sc = DfGetScode((_dl.GetDataILB())->WriteAt(
  937. ulTmp,
  938. pb,
  939. cbSector,
  940. &temp));
  941. Err:
  942. FreeBuffer(pbMem);
  943. msfDebugOut((DEB_ITRACE,"Out CTransactedStream::PartialWrite()\n"));
  944. return sc;
  945. }
  946. //+-------------------------------------------------------------------------
  947. //
  948. // Method: CTransactedStream::GetCommitInfo, public
  949. //
  950. // Synopsis: Return the current size of the stream and the size of
  951. // its base.
  952. //
  953. // Arguments: [pulRet1] -- Pointer to return location for old size
  954. // [pulRet2] -- Pointer to return location for current size
  955. //
  956. // History: 08-Jul-92 PhilipLa Created.
  957. //
  958. //--------------------------------------------------------------------------
  959. #ifdef LARGE_STREAMS
  960. void CTransactedStream::GetCommitInfo(ULONGLONG *pulRet1, ULONGLONG *pulRet2)
  961. #else
  962. void CTransactedStream::GetCommitInfo(ULONG *pulRet1, ULONG *pulRet2)
  963. #endif
  964. {
  965. if (_pssBase != NULL)
  966. _pssBase->GetSize(pulRet1);
  967. else
  968. *pulRet1 = 0;
  969. *pulRet2 = _ulSize;
  970. }
  971. //+-------------------------------------------------------------------------
  972. //
  973. // Method: CTransactedStream::GetSize, public
  974. //
  975. // Synopsis: Returns the size of the stream.
  976. //
  977. // Arguments: [pulSize] -- Pointer to return location for size.
  978. //
  979. // Returns: S_OK
  980. //
  981. // History: 22-Jan-92 PhilipLa Created.
  982. //
  983. //--------------------------------------------------------------------------
  984. #ifdef LARGE_STREAMS
  985. void CTransactedStream::GetSize(ULONGLONG *pulSize)
  986. #else
  987. void CTransactedStream::GetSize(ULONG *pulSize)
  988. #endif
  989. {
  990. msfAssert(P_TRANSACTED(_df));
  991. *pulSize = _ulSize;
  992. msfDebugOut((DEB_ITRACE,"CTransactedStream::GetSize()==>%lu\n",*pulSize));
  993. }
  994. //+---------------------------------------------------------------------------
  995. //
  996. // Member: CTransactedStream::SetInitialState, public
  997. //
  998. // Synopsis: Sets the initial state from a base or defaults
  999. //
  1000. // Arguments: [pssBase] - Base or NULL
  1001. //
  1002. // Returns: Appropriate status code
  1003. //
  1004. // History: 11-Nov-92 DrewB Created
  1005. //
  1006. //----------------------------------------------------------------------------
  1007. SCODE CTransactedStream::SetInitialState(PSStream *pssBase)
  1008. {
  1009. olDebugOut((DEB_ITRACE, "In CTransactedStream::SetInitialState:%p(%p)\n",
  1010. this, pssBase));
  1011. if (pssBase == NULL)
  1012. {
  1013. _ulSize = 0;
  1014. }
  1015. else
  1016. {
  1017. pssBase->GetSize(&_ulSize);
  1018. }
  1019. olDebugOut((DEB_ITRACE, "Out CTransactedStream::SetInitialState\n"));
  1020. return S_OK;
  1021. }
  1022. //+---------------------------------------------------------------------------
  1023. //
  1024. // Member: CTransactedStream::GetDeltaList, public
  1025. //
  1026. // Synopsis: Return a pointer to the delta list if it is not empty.
  1027. // If it is empty, call GetDeltaList on the parent and
  1028. // return that.
  1029. //
  1030. // Arguments: None.
  1031. //
  1032. // Returns: Pointer as above.
  1033. //
  1034. // History: 30-Jul-93 PhilipLa Created
  1035. //
  1036. //----------------------------------------------------------------------------
  1037. CDeltaList * CTransactedStream::GetDeltaList(void)
  1038. {
  1039. if (_dl.IsEmpty())
  1040. {
  1041. if (_pssBase != NULL)
  1042. {
  1043. return _pssBase->GetDeltaList();
  1044. }
  1045. else
  1046. {
  1047. //This case will only be hit if someone creates a new
  1048. // stream, then commits it to its parent without writing
  1049. // anything to it. The parent then has an empty delta
  1050. // list with no parent set on it.
  1051. msfAssert(_ulSize == 0);
  1052. return NULL;
  1053. }
  1054. }
  1055. else
  1056. return &_dl;
  1057. }