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.

797 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: laylkb.cxx
  7. //
  8. // Contents: File ILockBytes implementation for layout storage
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 19-Feb-96 SusiA Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "layouthd.cxx"
  18. #pragma hdrstop
  19. #include "laylkb.hxx"
  20. #include <valid.h>
  21. #include <dfver.h>
  22. class CSafeCriticalSection
  23. {
  24. public:
  25. inline CSafeCriticalSection(CRITICAL_SECTION *pcs);
  26. inline ~CSafeCriticalSection();
  27. private:
  28. CRITICAL_SECTION *_pcs;
  29. };
  30. inline CSafeCriticalSection::CSafeCriticalSection(CRITICAL_SECTION *pcs)
  31. {
  32. _pcs = pcs;
  33. EnterCriticalSection(_pcs);
  34. }
  35. inline CSafeCriticalSection::~CSafeCriticalSection()
  36. {
  37. LeaveCriticalSection(_pcs);
  38. #if DBG == 1
  39. _pcs = NULL;
  40. #endif
  41. }
  42. #define TAKE_CS CSafeCriticalSection scs(&_cs);
  43. //+---------------------------------------------------------------------------
  44. //
  45. // Member: CLayoutLockBytes::CLayoutLockBytes, public
  46. //
  47. // Synopsis: Default constructor
  48. //
  49. // Arguments:
  50. //
  51. // Returns: Appropriate status code
  52. //
  53. // Modifies:
  54. //
  55. // History: 20-Feb-96 SusiA Created
  56. //
  57. // Notes:
  58. //
  59. //----------------------------------------------------------------------------
  60. CLayoutLockBytes::CLayoutLockBytes(void)
  61. {
  62. _cReferences = 1;
  63. _h = INVALID_HANDLE_VALUE;
  64. _hScript = INVALID_HANDLE_VALUE;
  65. _fLogging = FALSE;
  66. _cbSectorShift = 0;
  67. _atcScriptName[0] = TEXT('\0');
  68. _awcName[0] = L'\0';
  69. _fCSInitialized = FALSE;
  70. }
  71. //+---------------------------------------------------------------------------
  72. //
  73. // Member: CLayoutLockBytes::~CLayoutLockBytes, public
  74. //
  75. // Synopsis: Destructor
  76. //
  77. // Returns: Appropriate status code
  78. //
  79. // History: 20-Feb-96 SusiA Created
  80. //
  81. //----------------------------------------------------------------------------
  82. CLayoutLockBytes::~CLayoutLockBytes()
  83. {
  84. if (_h != INVALID_HANDLE_VALUE)
  85. {
  86. CloseHandle(_h);
  87. _h = INVALID_HANDLE_VALUE;
  88. }
  89. if (_hScript != INVALID_HANDLE_VALUE)
  90. {
  91. CloseHandle(_hScript);
  92. _hScript = INVALID_HANDLE_VALUE;
  93. }
  94. if (_fCSInitialized)
  95. DeleteCriticalSection(&_cs);
  96. }
  97. //+---------------------------------------------------------------------------
  98. //
  99. // Member: CLayoutLockBytes::Init, public
  100. //
  101. // Synopsis: Initialization function
  102. //
  103. // Arguments:
  104. //
  105. // Returns: Appropriate status code
  106. //
  107. // History: 20-Feb-96 SusiA Created
  108. //
  109. // Notes:
  110. //
  111. //----------------------------------------------------------------------------
  112. SCODE CLayoutLockBytes::Init(OLECHAR const *pwcsName,
  113. DWORD grfMode)
  114. {
  115. SCODE sc = S_OK;
  116. BYTE abHeader[sizeof(CMSFHeaderData)];
  117. ULONG cbRead;
  118. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Init:%p()\n", this));
  119. if (pwcsName == NULL)
  120. return STG_E_INVALIDNAME;
  121. if (FALSE == _fCSInitialized)
  122. {
  123. __try
  124. {
  125. InitializeCriticalSection(&_cs);
  126. }
  127. __except( EXCEPTION_EXECUTE_HANDLER )
  128. {
  129. return HRESULT_FROM_WIN32( GetExceptionCode() );
  130. }
  131. _fCSInitialized = TRUE;
  132. }
  133. _grfMode = grfMode;
  134. #ifndef UNICODE
  135. TCHAR atcPath[MAX_PATH + 1];
  136. UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  137. if (!WideCharToMultiByte(
  138. uCodePage,
  139. 0,
  140. pwcsName,
  141. -1,
  142. atcPath,
  143. MAX_PATH + 1,
  144. NULL,
  145. NULL))
  146. {
  147. return STG_E_INVALIDNAME;
  148. }
  149. _h = CreateFileA(atcPath,
  150. GENERIC_READ | GENERIC_WRITE, //Read-write
  151. 0, // No sharing
  152. NULL,
  153. OPEN_EXISTING,
  154. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
  155. NULL);
  156. #else
  157. _h = CreateFile(pwcsName,
  158. GENERIC_READ | GENERIC_WRITE, //Read-write
  159. 0, // No sharing
  160. NULL,
  161. OPEN_EXISTING,
  162. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
  163. NULL);
  164. #endif
  165. if (_h == INVALID_HANDLE_VALUE)
  166. {
  167. layErr(Err, Win32ErrorToScode(GetLastError()));
  168. }
  169. layChk(StringCbCopyW(_awcName, sizeof(_awcName), pwcsName));
  170. //Get the sector size
  171. boolChk(ReadFile(_h, abHeader, sizeof(CMSFHeaderData), &cbRead, NULL));
  172. if (cbRead != sizeof(CMSFHeaderData))
  173. {
  174. return STG_E_READFAULT;
  175. }
  176. _cbSectorShift = ((CMSFHeaderData *)abHeader)->_uSectorShift;
  177. if (((CMSFHeaderData*)abHeader)->_uDllVersion > rmjlarge)
  178. return STG_E_OLDDLL;
  179. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Init\n"));
  180. Err:
  181. return ResultFromScode(sc);
  182. }
  183. //+--------------------------------------------------------------
  184. //
  185. // Member: CLayoutLockBytes::QueryInterface, public
  186. //
  187. // Synopsis: Returns an object for the requested interface
  188. //
  189. // Arguments: [iid] - Interface ID
  190. // [ppvObj] - Object return
  191. //
  192. // Returns: Appropriate status code
  193. //
  194. // Modifies: [ppvObj]
  195. //
  196. // History: 26-Mar-92 DrewB Created
  197. //
  198. //---------------------------------------------------------------
  199. STDMETHODIMP CLayoutLockBytes::QueryInterface(REFIID iid, void **ppvObj)
  200. {
  201. SCODE sc;
  202. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::QueryInterface(?, %p)\n",
  203. ppvObj));
  204. layChk(ValidateOutPtrBuffer(ppvObj));
  205. *ppvObj = NULL;
  206. sc = S_OK;
  207. if (IsEqualIID(iid, IID_IUnknown))
  208. {
  209. *ppvObj = (IUnknown *)this;
  210. CLayoutLockBytes::AddRef();
  211. }
  212. else if (IsEqualIID(iid, IID_ILockBytes))
  213. {
  214. *ppvObj = (ILockBytes *)this;
  215. CLayoutLockBytes::AddRef();
  216. }
  217. else
  218. {
  219. sc = E_NOINTERFACE;
  220. }
  221. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::QueryInterface => %p\n",
  222. ppvObj));
  223. Err:
  224. return ResultFromScode(sc);
  225. }
  226. //+--------------------------------------------------------------
  227. //
  228. // Member: CLayoutLockBytes::AddRef, public
  229. //
  230. // Synopsis: Increments the ref count
  231. //
  232. // Returns: Appropriate status code
  233. //
  234. // History: 16-Mar-92 DrewB Created
  235. //
  236. //---------------------------------------------------------------
  237. STDMETHODIMP_(ULONG) CLayoutLockBytes::AddRef(void)
  238. {
  239. LONG lRet;
  240. layDebugOut((DEB_TRACE, "In CLayoutLockBytes::AddRef()\n"));
  241. lRet = InterlockedIncrement(&_cReferences);
  242. layDebugOut((DEB_TRACE, "Out CLayoutLockBytes::AddRef\n"));
  243. return lRet;
  244. }
  245. //+---------------------------------------------------------------------------
  246. //
  247. // Member: CLayoutLockBytes::Release, public
  248. //
  249. // History: 20-Feb-96 SusiA Created
  250. //
  251. //----------------------------------------------------------------------------
  252. STDMETHODIMP_(ULONG) CLayoutLockBytes::Release(void)
  253. {
  254. LONG lRet;
  255. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Release:%p()\n", this));
  256. lRet = InterlockedDecrement(&_cReferences);
  257. if (lRet == 0)
  258. {
  259. delete this;
  260. }
  261. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Release\n"));
  262. return lRet;
  263. }
  264. //+---------------------------------------------------------------------------
  265. //
  266. // Member: CLayoutLockBytes::ReadAt, public
  267. //
  268. // Synopsis:
  269. //
  270. // Arguments:
  271. //
  272. // Returns: Appropriate status code
  273. //
  274. // Modifies:
  275. //
  276. // History: 20-Feb-96 SusiA Created
  277. //
  278. // Notes:
  279. //
  280. //----------------------------------------------------------------------------
  281. STDMETHODIMP CLayoutLockBytes::ReadAt(ULARGE_INTEGER ulOffset,
  282. VOID HUGEP *pv,
  283. ULONG cb,
  284. ULONG *pcbRead)
  285. {
  286. CSafeCriticalSection scs(&_cs);
  287. SCODE sc = S_OK;
  288. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::ReadAt:%p()\n", this));
  289. ULONG ulLow = ulOffset.LowPart;
  290. LONG lHigh = (LONG)ulOffset.HighPart;
  291. if ((_fLogging)&&(ulOffset.QuadPart >= sizeof(CMSFHeaderData)))
  292. {
  293. if (_hScript == INVALID_HANDLE_VALUE)
  294. {
  295. return STG_E_INVALIDHANDLE;
  296. }
  297. ULONG ulFirstSector = (ULONG) ((ulOffset.QuadPart -
  298. ((ULONGLONG)1 << _cbSectorShift))
  299. >> _cbSectorShift);
  300. ULONG ulLastSector = (ULONG) ((ulOffset.QuadPart + (cb - 1) -
  301. ((ULONGLONG)1 << _cbSectorShift))
  302. >> _cbSectorShift);
  303. ULONG ulSect;
  304. ULONG cbScriptWritten;
  305. for (ulSect = ulFirstSector; ulSect <= ulLastSector; ulSect++)
  306. {
  307. layAssert(_hScript !=INVALID_HANDLE_VALUE);
  308. boolChk(WriteFile(_hScript,
  309. (VOID *)&ulSect,
  310. sizeof(ULONG),
  311. &cbScriptWritten,
  312. NULL));
  313. if (cbScriptWritten != sizeof(ULONG))
  314. {
  315. return STG_E_WRITEFAULT;
  316. }
  317. }
  318. }
  319. negChk(SetFilePointer(_h,
  320. ulLow,
  321. &lHigh,
  322. FILE_BEGIN));
  323. boolChk(ReadFile(_h, pv, cb, pcbRead, NULL));
  324. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::ReadAt\n"));
  325. Err:
  326. return sc;
  327. }
  328. //+---------------------------------------------------------------------------
  329. //
  330. // Member: CLayoutLockBytes::WriteAt, public
  331. //
  332. // Synopsis:
  333. //
  334. // Arguments:
  335. //
  336. // Returns: Appropriate status code
  337. //
  338. // Modifies:
  339. //
  340. // History: 20-Feb-96 SusiA Created
  341. //
  342. // Notes:
  343. //
  344. //----------------------------------------------------------------------------
  345. STDMETHODIMP CLayoutLockBytes::WriteAt(ULARGE_INTEGER ulOffset,
  346. VOID const HUGEP *pv,
  347. ULONG cb,
  348. ULONG *pcbWritten)
  349. {
  350. CSafeCriticalSection scs(&_cs);
  351. SCODE sc = S_OK;
  352. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::WriteAt:%p()\n", this));
  353. ULONG ulLow = ulOffset.LowPart;
  354. LONG lHigh = (LONG)ulOffset.HighPart;
  355. if ((_fLogging)&&(ulOffset.QuadPart >= sizeof(CMSFHeaderData)))
  356. {
  357. if (_hScript == INVALID_HANDLE_VALUE)
  358. {
  359. return STG_E_INVALIDHANDLE;
  360. }
  361. ULONG ulFirstSector = (ULONG) ((ulOffset.QuadPart -
  362. ((ULONGLONG)1 << _cbSectorShift))
  363. >> _cbSectorShift);
  364. ULONG ulLastSector = (ULONG) ((ulOffset.QuadPart + (cb - 1) -
  365. ((ULONGLONG)1 << _cbSectorShift))
  366. >> _cbSectorShift);
  367. ULONG ulSect;
  368. ULONG cbScriptWritten;
  369. for (ulSect = ulFirstSector; ulSect <= ulLastSector; ulSect++)
  370. {
  371. boolChk(WriteFile(_hScript,
  372. (VOID *)&ulSect,
  373. sizeof(ULONG),
  374. &cbScriptWritten,
  375. NULL));
  376. if (cbScriptWritten != sizeof(ULONG))
  377. {
  378. return STG_E_WRITEFAULT;
  379. }
  380. }
  381. }
  382. negChk(SetFilePointer(_h,
  383. ulLow,
  384. &lHigh,
  385. FILE_BEGIN));
  386. boolChk(WriteFile(_h, pv, cb, pcbWritten, NULL));
  387. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::WriteAt\n"));
  388. Err:
  389. return sc;
  390. }
  391. //+---------------------------------------------------------------------------
  392. //
  393. // Member: CLayoutLockBytes::Flush, public
  394. //
  395. // Synopsis:
  396. //
  397. // Arguments:
  398. //
  399. // Returns: Appropriate status code
  400. //
  401. // Modifies:
  402. //
  403. // History: 20-Feb-96 SusiA Created
  404. //
  405. // Notes:
  406. //
  407. //----------------------------------------------------------------------------
  408. STDMETHODIMP CLayoutLockBytes::Flush(void)
  409. {
  410. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Flush:%p()\n", this));
  411. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Flush\n"));
  412. return S_OK;
  413. }
  414. //+---------------------------------------------------------------------------
  415. //
  416. // Member: CLayoutLockBytes::SetSize, public
  417. //
  418. // Synopsis:
  419. //
  420. // Arguments:
  421. //
  422. // Returns: Appropriate status code
  423. //
  424. // Modifies:
  425. //
  426. // History: 20-Feb-96 SusiA Created
  427. //
  428. // Notes:
  429. //
  430. //----------------------------------------------------------------------------
  431. STDMETHODIMP CLayoutLockBytes::SetSize(ULARGE_INTEGER cb)
  432. {
  433. CSafeCriticalSection scs(&_cs);
  434. SCODE sc = S_OK;
  435. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::SetSize:%p()\n", this));
  436. LONG lHigh = (LONG)cb.HighPart;
  437. ULONG ulLow = cb.LowPart;
  438. negChk(SetFilePointer(_h, ulLow, &lHigh, FILE_BEGIN));
  439. boolChk(SetEndOfFile(_h));
  440. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::SetSize\n"));
  441. Err:
  442. return sc;
  443. }
  444. //+---------------------------------------------------------------------------
  445. //
  446. // Member: CLayoutLockBytes::LockRegion, public
  447. //
  448. // Synopsis:
  449. //
  450. // Arguments:
  451. //
  452. // Returns: Appropriate status code
  453. //
  454. // Modifies:
  455. //
  456. // History: 20-Feb-96 SusiA Created
  457. //
  458. // Notes:
  459. //
  460. //----------------------------------------------------------------------------
  461. STDMETHODIMP CLayoutLockBytes::LockRegion(ULARGE_INTEGER libOffset,
  462. ULARGE_INTEGER cb,
  463. DWORD dwLockType)
  464. {
  465. CSafeCriticalSection scs(&_cs);
  466. SCODE sc = S_OK;
  467. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::LockRegion:%p()\n", this));
  468. if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
  469. {
  470. return STG_E_INVALIDFUNCTION;
  471. }
  472. boolChk(LockFile(_h,
  473. libOffset.LowPart,
  474. libOffset.HighPart,
  475. cb.LowPart,
  476. cb.HighPart));
  477. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::LockRegion\n"));
  478. Err:
  479. return sc;
  480. }
  481. //+---------------------------------------------------------------------------
  482. //
  483. // Member: CLayoutLockBytes::UnlockRegion, public
  484. //
  485. // Synopsis:
  486. //
  487. // Arguments:
  488. //
  489. // Returns: Appropriate status code
  490. //
  491. // Modifies:
  492. //
  493. // History: 20-Feb-96 SusiA Created
  494. //
  495. // Notes:
  496. //
  497. //----------------------------------------------------------------------------
  498. STDMETHODIMP CLayoutLockBytes::UnlockRegion(ULARGE_INTEGER libOffset,
  499. ULARGE_INTEGER cb,
  500. DWORD dwLockType)
  501. {
  502. CSafeCriticalSection scs(&_cs);
  503. SCODE sc = S_OK;
  504. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::UnlockRegion:%p()\n", this));
  505. if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
  506. {
  507. return STG_E_INVALIDFUNCTION;
  508. }
  509. boolChk(UnlockFile(_h,
  510. libOffset.LowPart,
  511. libOffset.HighPart,
  512. cb.LowPart,
  513. cb.HighPart));
  514. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::UnlockRegion\n"));
  515. Err:
  516. return sc;
  517. }
  518. //+---------------------------------------------------------------------------
  519. //
  520. // Member: CLayoutLockBytes::Stat, public
  521. //
  522. // Synopsis:
  523. //
  524. // Arguments:
  525. //
  526. // Returns: Appropriate status code
  527. //
  528. // Modifies:
  529. //
  530. // History: 20-Feb-96 SusiA Created
  531. //
  532. // Notes:
  533. //
  534. //----------------------------------------------------------------------------
  535. STDMETHODIMP CLayoutLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  536. {
  537. CSafeCriticalSection scs(&_cs);
  538. SCODE sc;
  539. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Stat:%p()\n", this));
  540. negChk(pstatstg->cbSize.LowPart =
  541. GetFileSize(_h, &pstatstg->cbSize.HighPart));
  542. boolChk(GetFileTime(_h, &pstatstg->ctime, &pstatstg->atime,
  543. &pstatstg->mtime));
  544. pstatstg->grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
  545. pstatstg->type = STGTY_LOCKBYTES;
  546. pstatstg->grfMode = _grfMode;
  547. pstatstg->pwcsName = NULL;
  548. if ((grfStatFlag & STATFLAG_NONAME) == 0)
  549. {
  550. pstatstg->pwcsName = (OLECHAR *)CoTaskMemAlloc(
  551. (lstrlenW(_awcName) + 1) * sizeof(OLECHAR));
  552. if (pstatstg->pwcsName == NULL)
  553. return STG_E_INSUFFICIENTMEMORY;
  554. StringCchCopyW (pstatstg->pwcsName, lstrlenW(_awcName)+1, _awcName);
  555. }
  556. sc = S_OK;
  557. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Stat\n"));
  558. return NOERROR;
  559. Err:
  560. return sc;
  561. }
  562. //+---------------------------------------------------------------------------
  563. //
  564. // Member: CLayoutLockBytes::StartLogging, public
  565. //
  566. // Returns: Appropriate status code
  567. //
  568. // Modifies: _fLogging
  569. //
  570. // History: 24-Feb-96 SusiA Created
  571. //
  572. // Notes:
  573. //
  574. //----------------------------------------------------------------------------
  575. SCODE CLayoutLockBytes::StartLogging(void)
  576. {
  577. CSafeCriticalSection scs(&_cs);
  578. OLECHAR acTempPathName[MAX_PATH + 1];
  579. SCODE sc = S_OK;
  580. if (_fLogging)
  581. {
  582. return STG_E_INUSE; //logging already started!
  583. }
  584. if (_atcScriptName[0] != TEXT('\0'))
  585. {
  586. LONG dwDistanceToMoveHigh = 0;
  587. //Script has already been started. Need to reopen it and seek
  588. // to the end.
  589. #ifndef UNICODE
  590. _hScript = CreateFileA
  591. #else
  592. _hScript = CreateFile
  593. #endif
  594. (_atcScriptName,
  595. GENERIC_WRITE, //Read-write
  596. 0, // No sharing
  597. NULL,
  598. OPEN_EXISTING,
  599. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
  600. NULL);
  601. if (_hScript == INVALID_HANDLE_VALUE)
  602. {
  603. return LAST_STG_SCODE;
  604. }
  605. negChk(SetFilePointer(_hScript, 0, &dwDistanceToMoveHigh, FILE_END));
  606. }
  607. else
  608. {
  609. TCHAR atcPath[MAX_PATH + 1];
  610. //Generate the script name, then create it.
  611. UINT ui = GetTempPath(MAX_PATH, atcPath);
  612. if (0 == ui)
  613. {
  614. layErr(Err, Win32ErrorToScode(GetLastError()));
  615. }
  616. else if (ui > MAX_PATH)
  617. {
  618. layErr(Err, STG_E_PATHNOTFOUND);
  619. }
  620. boolChk(GetTempFileName(atcPath, TEXT("SCR"), 0, _atcScriptName));
  621. //GetTempFileName actually creates the file, so we open with
  622. // OPEN_EXISTING
  623. #ifndef UNICODE
  624. _hScript = CreateFileA
  625. #else
  626. _hScript = CreateFile
  627. #endif
  628. (_atcScriptName,
  629. GENERIC_READ | GENERIC_WRITE, //Read-write
  630. 0, // No sharing
  631. NULL,
  632. OPEN_EXISTING,
  633. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
  634. NULL);
  635. if (_hScript == INVALID_HANDLE_VALUE)
  636. {
  637. return LAST_STG_SCODE;
  638. }
  639. }
  640. _fLogging = TRUE;
  641. Err:
  642. return sc;
  643. }
  644. //+---------------------------------------------------------------------------
  645. //
  646. // Member: CLayoutLockBytes::StopLogging, public
  647. //
  648. // Returns: Appropriate status code
  649. //
  650. // Modifies: _fLogging
  651. //
  652. // History: 24-Feb-96 SusiA Created
  653. //
  654. // Notes:
  655. //
  656. //-----------------------------------------------------------------------------
  657. SCODE CLayoutLockBytes::StopLogging(void)
  658. {
  659. SCODE sc = S_OK;
  660. CSafeCriticalSection scs(&_cs);
  661. if (!_fLogging)
  662. {
  663. return STG_E_UNKNOWN;
  664. }
  665. boolChk(CloseHandle(_hScript));
  666. _hScript = INVALID_HANDLE_VALUE;
  667. _fLogging = FALSE;
  668. Err:
  669. return sc;
  670. }