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.

791 lines
19 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. lstrcpyW(_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. ULONG ulRet;
  240. layDebugOut((DEB_TRACE, "In CLayoutLockBytes::AddRef()\n"));
  241. InterlockedIncrement(&_cReferences);
  242. ulRet = _cReferences;
  243. layDebugOut((DEB_TRACE, "Out CLayoutLockBytes::AddRef\n"));
  244. return ulRet;
  245. }
  246. //+---------------------------------------------------------------------------
  247. //
  248. // Member: CLayoutLockBytes::Release, public
  249. //
  250. // History: 20-Feb-96 SusiA Created
  251. //
  252. //----------------------------------------------------------------------------
  253. STDMETHODIMP_(ULONG) CLayoutLockBytes::Release(void)
  254. {
  255. LONG lRet;
  256. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Release:%p()\n", this));
  257. lRet = InterlockedDecrement(&_cReferences);
  258. if (lRet == 0)
  259. {
  260. delete this;
  261. }
  262. else if (lRet < 0)
  263. {
  264. lRet = 0;
  265. }
  266. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Release\n"));
  267. return lRet;
  268. }
  269. //+---------------------------------------------------------------------------
  270. //
  271. // Member: CLayoutLockBytes::ReadAt, public
  272. //
  273. // Synopsis:
  274. //
  275. // Arguments:
  276. //
  277. // Returns: Appropriate status code
  278. //
  279. // Modifies:
  280. //
  281. // History: 20-Feb-96 SusiA Created
  282. //
  283. // Notes:
  284. //
  285. //----------------------------------------------------------------------------
  286. STDMETHODIMP CLayoutLockBytes::ReadAt(ULARGE_INTEGER ulOffset,
  287. VOID HUGEP *pv,
  288. ULONG cb,
  289. ULONG *pcbRead)
  290. {
  291. CSafeCriticalSection scs(&_cs);
  292. SCODE sc = S_OK;
  293. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::ReadAt:%p()\n", this));
  294. ULONG ulLow = ulOffset.LowPart;
  295. LONG lHigh = (LONG)ulOffset.HighPart;
  296. if ((_fLogging)&&(ulOffset.QuadPart >= sizeof(CMSFHeaderData)))
  297. {
  298. if (_hScript == INVALID_HANDLE_VALUE)
  299. {
  300. return STG_E_INVALIDHANDLE;
  301. }
  302. ULONG ulFirstSector = (ULONG) ((ulOffset.QuadPart -
  303. (1 << _cbSectorShift))
  304. >> _cbSectorShift);
  305. ULONG ulLastSector = (ULONG) ((ulOffset.QuadPart + (cb - 1) -
  306. (1 << _cbSectorShift))
  307. >> _cbSectorShift);
  308. ULONG ulSect;
  309. ULONG cbScriptWritten;
  310. for (ulSect = ulFirstSector; ulSect <= ulLastSector; ulSect++)
  311. {
  312. layAssert(_hScript !=INVALID_HANDLE_VALUE);
  313. boolChk(WriteFile(_hScript,
  314. (VOID *)&ulSect,
  315. sizeof(ULONG),
  316. &cbScriptWritten,
  317. NULL));
  318. if (cbScriptWritten != sizeof(ULONG))
  319. {
  320. return STG_E_WRITEFAULT;
  321. }
  322. }
  323. }
  324. negChk(SetFilePointer(_h,
  325. ulLow,
  326. &lHigh,
  327. FILE_BEGIN));
  328. boolChk(ReadFile(_h, pv, cb, pcbRead, NULL));
  329. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::ReadAt\n"));
  330. Err:
  331. return sc;
  332. }
  333. //+---------------------------------------------------------------------------
  334. //
  335. // Member: CLayoutLockBytes::WriteAt, public
  336. //
  337. // Synopsis:
  338. //
  339. // Arguments:
  340. //
  341. // Returns: Appropriate status code
  342. //
  343. // Modifies:
  344. //
  345. // History: 20-Feb-96 SusiA Created
  346. //
  347. // Notes:
  348. //
  349. //----------------------------------------------------------------------------
  350. STDMETHODIMP CLayoutLockBytes::WriteAt(ULARGE_INTEGER ulOffset,
  351. VOID const HUGEP *pv,
  352. ULONG cb,
  353. ULONG *pcbWritten)
  354. {
  355. CSafeCriticalSection scs(&_cs);
  356. SCODE sc = S_OK;
  357. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::WriteAt:%p()\n", this));
  358. ULONG ulLow = ulOffset.LowPart;
  359. LONG lHigh = (LONG)ulOffset.HighPart;
  360. if ((_fLogging)&&(ulOffset.QuadPart >= sizeof(CMSFHeaderData)))
  361. {
  362. if (_hScript == INVALID_HANDLE_VALUE)
  363. {
  364. return STG_E_INVALIDHANDLE;
  365. }
  366. ULONG ulFirstSector = (ULONG) ((ulOffset.QuadPart -
  367. (1 << _cbSectorShift))
  368. >> _cbSectorShift);
  369. ULONG ulLastSector = (ULONG) ((ulOffset.QuadPart + (cb - 1) -
  370. (1 << _cbSectorShift))
  371. >> _cbSectorShift);
  372. ULONG ulSect;
  373. ULONG cbScriptWritten;
  374. for (ulSect = ulFirstSector; ulSect <= ulLastSector; ulSect++)
  375. {
  376. boolChk(WriteFile(_hScript,
  377. (VOID *)&ulSect,
  378. sizeof(ULONG),
  379. &cbScriptWritten,
  380. NULL));
  381. if (cbScriptWritten != sizeof(ULONG))
  382. {
  383. return STG_E_WRITEFAULT;
  384. }
  385. }
  386. }
  387. negChk(SetFilePointer(_h,
  388. ulLow,
  389. &lHigh,
  390. FILE_BEGIN));
  391. boolChk(WriteFile(_h, pv, cb, pcbWritten, NULL));
  392. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::WriteAt\n"));
  393. Err:
  394. return sc;
  395. }
  396. //+---------------------------------------------------------------------------
  397. //
  398. // Member: CLayoutLockBytes::Flush, public
  399. //
  400. // Synopsis:
  401. //
  402. // Arguments:
  403. //
  404. // Returns: Appropriate status code
  405. //
  406. // Modifies:
  407. //
  408. // History: 20-Feb-96 SusiA Created
  409. //
  410. // Notes:
  411. //
  412. //----------------------------------------------------------------------------
  413. STDMETHODIMP CLayoutLockBytes::Flush(void)
  414. {
  415. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Flush:%p()\n", this));
  416. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Flush\n"));
  417. return S_OK;
  418. }
  419. //+---------------------------------------------------------------------------
  420. //
  421. // Member: CLayoutLockBytes::SetSize, public
  422. //
  423. // Synopsis:
  424. //
  425. // Arguments:
  426. //
  427. // Returns: Appropriate status code
  428. //
  429. // Modifies:
  430. //
  431. // History: 20-Feb-96 SusiA Created
  432. //
  433. // Notes:
  434. //
  435. //----------------------------------------------------------------------------
  436. STDMETHODIMP CLayoutLockBytes::SetSize(ULARGE_INTEGER cb)
  437. {
  438. CSafeCriticalSection scs(&_cs);
  439. SCODE sc = S_OK;
  440. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::SetSize:%p()\n", this));
  441. LONG lHigh = (LONG)cb.HighPart;
  442. ULONG ulLow = cb.LowPart;
  443. negChk(SetFilePointer(_h, ulLow, &lHigh, FILE_BEGIN));
  444. boolChk(SetEndOfFile(_h));
  445. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::SetSize\n"));
  446. Err:
  447. return sc;
  448. }
  449. //+---------------------------------------------------------------------------
  450. //
  451. // Member: CLayoutLockBytes::LockRegion, public
  452. //
  453. // Synopsis:
  454. //
  455. // Arguments:
  456. //
  457. // Returns: Appropriate status code
  458. //
  459. // Modifies:
  460. //
  461. // History: 20-Feb-96 SusiA Created
  462. //
  463. // Notes:
  464. //
  465. //----------------------------------------------------------------------------
  466. STDMETHODIMP CLayoutLockBytes::LockRegion(ULARGE_INTEGER libOffset,
  467. ULARGE_INTEGER cb,
  468. DWORD dwLockType)
  469. {
  470. CSafeCriticalSection scs(&_cs);
  471. SCODE sc = S_OK;
  472. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::LockRegion:%p()\n", this));
  473. if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
  474. {
  475. return STG_E_INVALIDFUNCTION;
  476. }
  477. boolChk(LockFile(_h,
  478. libOffset.LowPart,
  479. libOffset.HighPart,
  480. cb.LowPart,
  481. cb.HighPart));
  482. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::LockRegion\n"));
  483. Err:
  484. return sc;
  485. }
  486. //+---------------------------------------------------------------------------
  487. //
  488. // Member: CLayoutLockBytes::UnlockRegion, public
  489. //
  490. // Synopsis:
  491. //
  492. // Arguments:
  493. //
  494. // Returns: Appropriate status code
  495. //
  496. // Modifies:
  497. //
  498. // History: 20-Feb-96 SusiA Created
  499. //
  500. // Notes:
  501. //
  502. //----------------------------------------------------------------------------
  503. STDMETHODIMP CLayoutLockBytes::UnlockRegion(ULARGE_INTEGER libOffset,
  504. ULARGE_INTEGER cb,
  505. DWORD dwLockType)
  506. {
  507. CSafeCriticalSection scs(&_cs);
  508. SCODE sc = S_OK;
  509. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::UnlockRegion:%p()\n", this));
  510. if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
  511. {
  512. return STG_E_INVALIDFUNCTION;
  513. }
  514. boolChk(UnlockFile(_h,
  515. libOffset.LowPart,
  516. libOffset.HighPart,
  517. cb.LowPart,
  518. cb.HighPart));
  519. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::UnlockRegion\n"));
  520. Err:
  521. return sc;
  522. }
  523. //+---------------------------------------------------------------------------
  524. //
  525. // Member: CLayoutLockBytes::Stat, public
  526. //
  527. // Synopsis:
  528. //
  529. // Arguments:
  530. //
  531. // Returns: Appropriate status code
  532. //
  533. // Modifies:
  534. //
  535. // History: 20-Feb-96 SusiA Created
  536. //
  537. // Notes:
  538. //
  539. //----------------------------------------------------------------------------
  540. STDMETHODIMP CLayoutLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  541. {
  542. CSafeCriticalSection scs(&_cs);
  543. SCODE sc;
  544. layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Stat:%p()\n", this));
  545. negChk(pstatstg->cbSize.LowPart =
  546. GetFileSize(_h, &pstatstg->cbSize.HighPart));
  547. boolChk(GetFileTime(_h, &pstatstg->ctime, &pstatstg->atime,
  548. &pstatstg->mtime));
  549. pstatstg->grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
  550. pstatstg->type = STGTY_LOCKBYTES;
  551. pstatstg->grfMode = _grfMode;
  552. pstatstg->pwcsName = NULL;
  553. if ((grfStatFlag & STATFLAG_NONAME) == 0)
  554. {
  555. pstatstg->pwcsName = (OLECHAR *)CoTaskMemAlloc(
  556. (lstrlenW(_awcName) + 1) * sizeof(OLECHAR));
  557. if (pstatstg->pwcsName == NULL)
  558. return STG_E_INSUFFICIENTMEMORY;
  559. lstrcpyW(pstatstg->pwcsName, _awcName);
  560. }
  561. sc = S_OK;
  562. layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Stat\n"));
  563. return NOERROR;
  564. Err:
  565. return sc;
  566. }
  567. //+---------------------------------------------------------------------------
  568. //
  569. // Member: CLayoutLockBytes::StartLogging, public
  570. //
  571. // Returns: Appropriate status code
  572. //
  573. // Modifies: _fLogging
  574. //
  575. // History: 24-Feb-96 SusiA Created
  576. //
  577. // Notes:
  578. //
  579. //----------------------------------------------------------------------------
  580. SCODE CLayoutLockBytes::StartLogging(void)
  581. {
  582. CSafeCriticalSection scs(&_cs);
  583. OLECHAR acTempPathName[MAX_PATH + 1];
  584. SCODE sc = S_OK;
  585. if (_fLogging)
  586. {
  587. return STG_E_INUSE; //logging already started!
  588. }
  589. if (_atcScriptName[0] != TEXT('\0'))
  590. {
  591. LONG dwDistanceToMoveHigh = 0;
  592. //Script has already been started. Need to reopen it and seek
  593. // to the end.
  594. #ifndef UNICODE
  595. _hScript = CreateFileA
  596. #else
  597. _hScript = CreateFile
  598. #endif
  599. (_atcScriptName,
  600. GENERIC_WRITE, //Read-write
  601. 0, // No sharing
  602. NULL,
  603. OPEN_EXISTING,
  604. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
  605. NULL);
  606. if (_hScript == INVALID_HANDLE_VALUE)
  607. {
  608. return LAST_STG_SCODE;
  609. }
  610. negChk(SetFilePointer(_hScript, 0, &dwDistanceToMoveHigh, FILE_END));
  611. }
  612. else
  613. {
  614. TCHAR atcPath[MAX_PATH + 1];
  615. //Generate the script name, then create it.
  616. boolChk(GetTempPath(MAX_PATH, atcPath));
  617. boolChk(GetTempFileName(atcPath, TEXT("SCR"), 0, _atcScriptName));
  618. //GetTempFileName actually creates the file, so we open with
  619. // OPEN_EXISTING
  620. #ifndef UNICODE
  621. _hScript = CreateFileA
  622. #else
  623. _hScript = CreateFile
  624. #endif
  625. (_atcScriptName,
  626. GENERIC_READ | GENERIC_WRITE, //Read-write
  627. 0, // No sharing
  628. NULL,
  629. OPEN_EXISTING,
  630. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
  631. NULL);
  632. if (_hScript == INVALID_HANDLE_VALUE)
  633. {
  634. return LAST_STG_SCODE;
  635. }
  636. }
  637. _fLogging = TRUE;
  638. Err:
  639. return sc;
  640. }
  641. //+---------------------------------------------------------------------------
  642. //
  643. // Member: CLayoutLockBytes::StopLogging, public
  644. //
  645. // Returns: Appropriate status code
  646. //
  647. // Modifies: _fLogging
  648. //
  649. // History: 24-Feb-96 SusiA Created
  650. //
  651. // Notes:
  652. //
  653. //-----------------------------------------------------------------------------
  654. SCODE CLayoutLockBytes::StopLogging(void)
  655. {
  656. SCODE sc = S_OK;
  657. CSafeCriticalSection scs(&_cs);
  658. if (!_fLogging)
  659. {
  660. return STG_E_UNKNOWN;
  661. }
  662. boolChk(CloseHandle(_hScript));
  663. _hScript = INVALID_HANDLE_VALUE;
  664. _fLogging = FALSE;
  665. Err:
  666. return sc;
  667. }