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.

799 lines
19 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: filllkb.cxx
  7. //
  8. // Contents: IFillLockBytes and ILockBytes wrapper for async docfiles
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 19-Dec-95 PhilipLa Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "astghead.cxx"
  18. #pragma hdrstop
  19. #include "filllkb.hxx"
  20. #include <valid.h>
  21. #include <utils.hxx>
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Member: CFillLockBytes::CFillLockBytes, public
  25. //
  26. // Synopsis: Default constructor
  27. //
  28. // History: 28-Dec-95 PhilipLa Created
  29. //
  30. //----------------------------------------------------------------------------
  31. CFillLockBytes::CFillLockBytes(ILockBytes *pilb)
  32. {
  33. _pilb = pilb;
  34. pilb->AddRef();
  35. _ulHighWater = 0;
  36. _ulFailurePoint = 0;
  37. _dwTerminate = UNTERMINATED;
  38. #ifdef ASYNC
  39. _ppc = NULL;
  40. #else
  41. _hNotifyEvent = INVALID_HANDLE_VALUE;
  42. #endif
  43. _fCSInitialized = FALSE;
  44. _cRefs = 1;
  45. }
  46. //+---------------------------------------------------------------------------
  47. //
  48. // Member: CFillLockBytes::~CFillLockBytes, public
  49. //
  50. // Synopsis: Destructor
  51. //
  52. // History: 28-Dec-95 PhilipLa Created
  53. //
  54. //----------------------------------------------------------------------------
  55. CFillLockBytes::~CFillLockBytes()
  56. {
  57. astgAssert(_pilb == NULL);
  58. #ifdef ASYNC
  59. #ifdef MULTIHEAP
  60. if (_ppc)
  61. {
  62. CSafeMultiHeap smh(_ppc);
  63. if (_ppc->ReleaseSharedMem() == 0)
  64. g_smAllocator.Uninit();
  65. }
  66. #endif
  67. #else
  68. if (_hNotifyEvent != INVALID_HANDLE_VALUE)
  69. {
  70. CloseHandle(_hNotifyEvent);
  71. }
  72. #endif
  73. if (_fCSInitialized)
  74. DeleteCriticalSection(&_csThreadProtect);
  75. }
  76. //+---------------------------------------------------------------------------
  77. //
  78. // Member: CFillLockBytes::Init, public
  79. //
  80. // Synopsis:
  81. //
  82. // Arguments:
  83. //
  84. // Returns: Appropriate status code
  85. //
  86. // Modifies:
  87. //
  88. // History: 11-Jan-96 PhilipLa Created
  89. //
  90. // Notes:
  91. //
  92. //----------------------------------------------------------------------------
  93. SCODE CFillLockBytes::Init(void)
  94. {
  95. SCODE sc;
  96. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::Init:%p()\n", this));
  97. if (FALSE == _fCSInitialized)
  98. {
  99. __try
  100. {
  101. InitializeCriticalSection(&_csThreadProtect);
  102. _fCSInitialized = TRUE;
  103. }
  104. __except( EXCEPTION_EXECUTE_HANDLER )
  105. {
  106. return HRESULT_FROM_WIN32( GetExceptionCode() );
  107. }
  108. }
  109. #ifndef ASYNC
  110. _hNotifyEvent = CreateEvent(NULL,
  111. TRUE,
  112. FALSE,
  113. NULL);
  114. if (_hNotifyEvent == NULL)
  115. {
  116. return Win32ErrorToScode(GetLastError());
  117. }
  118. #endif
  119. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::Init\n"));
  120. return S_OK;
  121. }
  122. //+--------------------------------------------------------------
  123. //
  124. // Member: CFillLockBytes::QueryInterface, public
  125. //
  126. // Synopsis: Returns an object for the requested interface
  127. //
  128. // Arguments: [iid] - Interface ID
  129. // [ppvObj] - Object return
  130. //
  131. // Returns: Appropriate status code
  132. //
  133. // Modifies: [ppvObj]
  134. //
  135. // History: 26-Mar-92 DrewB Created
  136. //
  137. //---------------------------------------------------------------
  138. STDMETHODIMP CFillLockBytes::QueryInterface(REFIID iid, void **ppvObj)
  139. {
  140. SCODE sc;
  141. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::QueryInterface(?, %p)\n",
  142. ppvObj));
  143. astgChk(ValidateOutPtrBuffer(ppvObj));
  144. *ppvObj = NULL;
  145. sc = S_OK;
  146. if (IsEqualIID(iid, IID_IUnknown))
  147. {
  148. *ppvObj = (ILockBytes *)this;
  149. CFillLockBytes::AddRef();
  150. }
  151. else if (IsEqualIID(iid, IID_ILockBytes))
  152. {
  153. *ppvObj = (ILockBytes *)this;
  154. CFillLockBytes::AddRef();
  155. }
  156. else if (IsEqualIID(iid, IID_IFillLockBytes))
  157. {
  158. *ppvObj = (IFillLockBytes *)this;
  159. CFillLockBytes::AddRef();
  160. }
  161. #ifdef ASYNC
  162. else if (IsEqualIID(iid, IID_IFillInfo))
  163. {
  164. *ppvObj = (IFillInfo *)this;
  165. CFillLockBytes::AddRef();
  166. }
  167. #endif
  168. else if (IsEqualIID(iid, IID_IDefaultFillLockBytes))
  169. {
  170. *ppvObj = (IFillLockBytes *)this;
  171. CFillLockBytes::AddRef();
  172. }
  173. else
  174. {
  175. sc = E_NOINTERFACE;
  176. }
  177. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::QueryInterface => %p\n",
  178. ppvObj));
  179. Err:
  180. return ResultFromScode(sc);
  181. }
  182. //+--------------------------------------------------------------
  183. //
  184. // Member: CFillLockBytes::AddRef, public
  185. //
  186. // Synopsis: Increments the ref count
  187. //
  188. // Returns: Appropriate status code
  189. //
  190. // History: 16-Mar-92 DrewB Created
  191. //
  192. //---------------------------------------------------------------
  193. STDMETHODIMP_(ULONG) CFillLockBytes::AddRef(void)
  194. {
  195. InterlockedIncrement (&_cRefs);
  196. return _cRefs;
  197. }
  198. //+---------------------------------------------------------------------------
  199. //
  200. // Member: CFillLockBytes::Release, public
  201. //
  202. // History: 28-Dec-95 PhilipLa Created
  203. //
  204. //----------------------------------------------------------------------------
  205. STDMETHODIMP_(ULONG) CFillLockBytes::Release(void)
  206. {
  207. LONG lRet;
  208. InterlockedDecrement (&_cRefs);
  209. lRet = _cRefs;
  210. if (lRet == 0)
  211. {
  212. _pilb->Release();
  213. _pilb = NULL;
  214. delete this;
  215. }
  216. return lRet;
  217. }
  218. //+---------------------------------------------------------------------------
  219. //
  220. // Member: CFillLockBytes::ReadAt, public
  221. //
  222. // Synopsis:
  223. //
  224. // Arguments:
  225. //
  226. // Returns: Appropriate status code
  227. //
  228. // Modifies:
  229. //
  230. // History: 28-Dec-95 PhilipLa Created
  231. //
  232. // Notes:
  233. //
  234. //----------------------------------------------------------------------------
  235. STDMETHODIMP CFillLockBytes::ReadAt(ULARGE_INTEGER ulOffset,
  236. VOID HUGEP *pv,
  237. ULONG cb,
  238. ULONG *pcbRead)
  239. {
  240. SCODE sc;
  241. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::ReadAt:%p()\n", this));
  242. if (NULL == pv || NULL == pcbRead)
  243. return STG_E_INVALIDPARAMETER;
  244. if (_dwTerminate == TERMINATED_ABNORMAL)
  245. {
  246. sc = STG_E_INCOMPLETE;
  247. }
  248. else if ((_dwTerminate == TERMINATED_NORMAL) ||
  249. (ULIGetLow(ulOffset) + cb <= _ulHighWater))
  250. {
  251. sc = _pilb->ReadAt(ulOffset, pv, cb, pcbRead);
  252. }
  253. else
  254. {
  255. *pcbRead = 0;
  256. _ulFailurePoint = cb + ULIGetLow(ulOffset);
  257. sc = E_PENDING;
  258. }
  259. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::ReadAt\n"));
  260. return sc;
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // Member: CFillLockBytes::WriteAt, public
  265. //
  266. // Synopsis:
  267. //
  268. // Arguments:
  269. //
  270. // Returns: Appropriate status code
  271. //
  272. // Modifies:
  273. //
  274. // History: 28-Dec-95 PhilipLa Created
  275. //
  276. // Notes:
  277. //
  278. //----------------------------------------------------------------------------
  279. STDMETHODIMP CFillLockBytes::WriteAt(ULARGE_INTEGER ulOffset,
  280. VOID const HUGEP *pv,
  281. ULONG cb,
  282. ULONG *pcbWritten)
  283. {
  284. SCODE sc;
  285. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::WriteAt:%p()\n", this));
  286. if (NULL == pv || NULL == pcbWritten)
  287. return STG_E_INVALIDPARAMETER;
  288. if (_dwTerminate == TERMINATED_ABNORMAL)
  289. {
  290. sc = STG_E_INCOMPLETE;
  291. }
  292. else if ((_dwTerminate == TERMINATED_NORMAL) ||
  293. (ULIGetLow(ulOffset) + cb <= _ulHighWater))
  294. {
  295. sc = _pilb->WriteAt(ulOffset, pv, cb, pcbWritten);
  296. }
  297. else
  298. {
  299. *pcbWritten = 0;
  300. _ulFailurePoint = cb + ULIGetLow(ulOffset);
  301. sc = E_PENDING;
  302. }
  303. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::WriteAt\n"));
  304. return sc;
  305. }
  306. //+---------------------------------------------------------------------------
  307. //
  308. // Member: CFillLockBytes::Flush, public
  309. //
  310. // Synopsis:
  311. //
  312. // Arguments:
  313. //
  314. // Returns: Appropriate status code
  315. //
  316. // Modifies:
  317. //
  318. // History: 28-Dec-95 PhilipLa Created
  319. //
  320. // Notes:
  321. //
  322. //----------------------------------------------------------------------------
  323. STDMETHODIMP CFillLockBytes::Flush(void)
  324. {
  325. SCODE sc;
  326. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::Flush:%p()\n", this));
  327. sc = _pilb->Flush();
  328. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::Flush\n"));
  329. return sc;
  330. }
  331. //+---------------------------------------------------------------------------
  332. //
  333. // Member: CFillLockBytes::SetSize, public
  334. //
  335. // Synopsis:
  336. //
  337. // Arguments:
  338. //
  339. // Returns: Appropriate status code
  340. //
  341. // Modifies:
  342. //
  343. // History: 28-Dec-95 PhilipLa Created
  344. //
  345. // Notes:
  346. //
  347. //----------------------------------------------------------------------------
  348. STDMETHODIMP CFillLockBytes::SetSize(ULARGE_INTEGER cb)
  349. {
  350. SCODE sc;
  351. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::SetSize:%p()\n", this));
  352. if (_dwTerminate == TERMINATED_ABNORMAL)
  353. {
  354. sc = STG_E_INCOMPLETE;
  355. }
  356. else if ((_dwTerminate == TERMINATED_NORMAL) ||
  357. (ULIGetLow(cb) <= _ulHighWater))
  358. {
  359. sc = _pilb->SetSize(cb);
  360. }
  361. else
  362. {
  363. _ulFailurePoint = ULIGetLow(cb);
  364. sc = E_PENDING;
  365. }
  366. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::SetSize\n"));
  367. return sc;
  368. }
  369. //+---------------------------------------------------------------------------
  370. //
  371. // Member: CFillLockBytes::LockRegion, public
  372. //
  373. // Synopsis:
  374. //
  375. // Arguments:
  376. //
  377. // Returns: Appropriate status code
  378. //
  379. // Modifies:
  380. //
  381. // History: 28-Dec-95 PhilipLa Created
  382. //
  383. // Notes:
  384. //
  385. //----------------------------------------------------------------------------
  386. STDMETHODIMP CFillLockBytes::LockRegion(ULARGE_INTEGER libOffset,
  387. ULARGE_INTEGER cb,
  388. DWORD dwLockType)
  389. {
  390. SCODE sc;
  391. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::LockRegion:%p()\n", this));
  392. sc = _pilb->LockRegion(libOffset, cb, dwLockType);
  393. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::LockRegion\n"));
  394. return sc;
  395. }
  396. //+---------------------------------------------------------------------------
  397. //
  398. // Member: CFillLockBytes::UnlockRegion, public
  399. //
  400. // Synopsis:
  401. //
  402. // Arguments:
  403. //
  404. // Returns: Appropriate status code
  405. //
  406. // Modifies:
  407. //
  408. // History: 28-Dec-95 PhilipLa Created
  409. //
  410. // Notes:
  411. //
  412. //----------------------------------------------------------------------------
  413. STDMETHODIMP CFillLockBytes::UnlockRegion(ULARGE_INTEGER libOffset,
  414. ULARGE_INTEGER cb,
  415. DWORD dwLockType)
  416. {
  417. SCODE sc;
  418. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::UnlockRegion:%p()\n", this));
  419. sc = _pilb->UnlockRegion(libOffset, cb, dwLockType);
  420. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::UnlockRegion\n"));
  421. return sc;
  422. }
  423. //+---------------------------------------------------------------------------
  424. //
  425. // Member: CFillLockBytes::Stat, public
  426. //
  427. // Synopsis:
  428. //
  429. // Arguments:
  430. //
  431. // Returns: Appropriate status code
  432. //
  433. // Modifies:
  434. //
  435. // History: 28-Dec-95 PhilipLa Created
  436. //
  437. // Notes:
  438. //
  439. //----------------------------------------------------------------------------
  440. STDMETHODIMP CFillLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  441. {
  442. SCODE sc;
  443. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::Stat:%p()\n", this));
  444. if (_dwTerminate == TERMINATED_ABNORMAL)
  445. {
  446. sc = STG_E_INCOMPLETE;
  447. }
  448. else
  449. {
  450. sc = _pilb->Stat(pstatstg, grfStatFlag);
  451. }
  452. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::Stat\n"));
  453. return sc;
  454. }
  455. //+---------------------------------------------------------------------------
  456. //
  457. // Member: CFillLockBytes::FillAppend, public
  458. //
  459. // Synopsis:
  460. //
  461. // Arguments:
  462. //
  463. // Returns: Appropriate status code
  464. //
  465. // Modifies:
  466. //
  467. // History: 28-Dec-95 PhilipLa Created
  468. //
  469. // Notes:
  470. //
  471. //----------------------------------------------------------------------------
  472. STDMETHODIMP CFillLockBytes::FillAppend(void const *pv,
  473. ULONG cb,
  474. ULONG *pcbWritten)
  475. {
  476. SCODE sc;
  477. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::FillAppend:%p()\n", this));
  478. sc = ValidateBuffer (pv, cb);
  479. if (!SUCCEEDED(sc))
  480. return sc;
  481. if (_dwTerminate != UNTERMINATED)
  482. {
  483. sc = STG_E_TERMINATED;
  484. }
  485. else
  486. {
  487. ULONG cbWritten;
  488. ULARGE_INTEGER uli;
  489. uli.QuadPart = _ulHighWater;
  490. sc = _pilb->WriteAt(uli, pv, cb, &cbWritten);
  491. _ulHighWater += cbWritten;
  492. if (pcbWritten != NULL)
  493. {
  494. *pcbWritten = cbWritten;
  495. }
  496. #ifdef ASYNC
  497. if (_ppc)
  498. {
  499. HANDLE hEvent = _ppc->GetNotificationEvent();
  500. if (!PulseEvent(hEvent))
  501. {
  502. sc = Win32ErrorToScode(GetLastError());
  503. }
  504. }
  505. #else
  506. if (!PulseEvent(_hNotifyEvent))
  507. {
  508. sc = Win32ErrorToScode(GetLastError());
  509. }
  510. #endif
  511. }
  512. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::FillAppend\n"));
  513. return sc;
  514. }
  515. //+---------------------------------------------------------------------------
  516. //
  517. // Member: CFillLockBytes::FillAt, public
  518. //
  519. // Synopsis:
  520. //
  521. // Arguments:
  522. //
  523. // Returns: Appropriate status code
  524. //
  525. // Modifies:
  526. //
  527. // History: 28-Dec-95 PhilipLa Created
  528. //
  529. // Notes:
  530. //
  531. //----------------------------------------------------------------------------
  532. STDMETHODIMP CFillLockBytes::FillAt(ULARGE_INTEGER ulOffset,
  533. void const *pv,
  534. ULONG cb,
  535. ULONG *pcbWritten)
  536. {
  537. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::FillAt:%p()\n", this));
  538. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::FillAt\n"));
  539. return STG_E_UNIMPLEMENTEDFUNCTION;
  540. }
  541. //+---------------------------------------------------------------------------
  542. //
  543. // Member: CFillLockBytes::SetFillSize, public
  544. //
  545. // Synopsis:
  546. //
  547. // Arguments:
  548. //
  549. // Returns: Appropriate status code
  550. //
  551. // Modifies:
  552. //
  553. // History: 28-Dec-95 PhilipLa Created
  554. //
  555. // Notes:
  556. //
  557. //----------------------------------------------------------------------------
  558. STDMETHODIMP CFillLockBytes::SetFillSize(ULARGE_INTEGER ulSize)
  559. {
  560. SCODE sc;
  561. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::SetFillSize:%p()\n", this));
  562. if (_dwTerminate == TERMINATED_ABNORMAL)
  563. {
  564. sc = STG_E_INCOMPLETE;
  565. }
  566. else
  567. {
  568. sc = _pilb->SetSize(ulSize);
  569. }
  570. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::SetFillSize\n"));
  571. return sc;
  572. }
  573. //+---------------------------------------------------------------------------
  574. //
  575. // Member: CFillLockBytes::Terminate, public
  576. //
  577. // Synopsis:
  578. //
  579. // Arguments:
  580. //
  581. // Returns: Appropriate status code
  582. //
  583. // Modifies:
  584. //
  585. // History: 28-Dec-95 PhilipLa Created
  586. //
  587. // Notes:
  588. //
  589. //----------------------------------------------------------------------------
  590. STDMETHODIMP CFillLockBytes::Terminate(BOOL bCanceled)
  591. {
  592. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::Terminate:%p()\n", this));
  593. _dwTerminate = (bCanceled) ? TERMINATED_ABNORMAL : TERMINATED_NORMAL;
  594. #ifdef ASYNC
  595. if (_ppc)
  596. {
  597. HANDLE hEvent = _ppc->GetNotificationEvent();
  598. if (!SetEvent(hEvent))
  599. {
  600. return Win32ErrorToScode(GetLastError());
  601. }
  602. }
  603. #else
  604. if (!SetEvent(_hNotifyEvent))
  605. {
  606. return Win32ErrorToScode(GetLastError());
  607. }
  608. #endif
  609. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::Terminate\n"));
  610. return S_OK;
  611. }
  612. //+---------------------------------------------------------------------------
  613. //
  614. // Member: CFillLockBytes::GetFailureInfo, public
  615. //
  616. // Synopsis:
  617. //
  618. // Arguments:
  619. //
  620. // Returns: Appropriate status code
  621. //
  622. // Modifies:
  623. //
  624. // History: 11-Jan-96 PhilipLa Created
  625. //
  626. // Notes:
  627. //
  628. //----------------------------------------------------------------------------
  629. STDMETHODIMP CFillLockBytes::GetFailureInfo(ULONG *pulWaterMark,
  630. ULONG *pulFailurePoint)
  631. {
  632. astgDebugOut((DEB_ITRACE,
  633. "In CFillLockBytes::GetFailureInfo:%p()\n", this));
  634. *pulWaterMark = _ulHighWater;
  635. *pulFailurePoint = _ulFailurePoint;
  636. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::GetFailureInfo\n"));
  637. return S_OK;
  638. }
  639. #ifndef ASYNC
  640. //+---------------------------------------------------------------------------
  641. //
  642. // Member: CFillLockBytes::GetNotificationEvent, public
  643. //
  644. // Synopsis:
  645. //
  646. // Arguments:
  647. //
  648. // Returns: Appropriate status code
  649. //
  650. // Modifies:
  651. //
  652. // History: 11-Jan-96 PhilipLa Created
  653. //
  654. // Notes:
  655. //
  656. //----------------------------------------------------------------------------
  657. HANDLE CFillLockBytes::GetNotificationEvent(void)
  658. {
  659. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::GetNotificationEvent:%p()\n", this));
  660. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::GetNotificationEvent\n"));
  661. return _hNotifyEvent;
  662. }
  663. #endif
  664. //+---------------------------------------------------------------------------
  665. //
  666. // Member: CFillLockBytes::GetTerminationStatus, public
  667. //
  668. // Synopsis:
  669. //
  670. // Arguments:
  671. //
  672. // Returns: Appropriate status code
  673. //
  674. // Modifies:
  675. //
  676. // History: 11-Jan-96 PhilipLa Created
  677. //
  678. // Notes:
  679. //
  680. //----------------------------------------------------------------------------
  681. STDMETHODIMP CFillLockBytes::GetTerminationStatus(DWORD *pdwFlags)
  682. {
  683. astgDebugOut((DEB_ITRACE,
  684. "In CFillLockBytes::GetTerminationStatus:%p()\n", this));
  685. *pdwFlags = _dwTerminate;
  686. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::GetTerminationStatus\n"));
  687. return S_OK;
  688. }
  689. SCODE CFillLockBytes::SetFailureInfo(ULONG ulWaterMark,
  690. ULONG ulFailurePoint)
  691. {
  692. astgDebugOut((DEB_ITRACE, "In CFillLockBytes::SetFailureInfo:%p()\n", this));
  693. _ulHighWater =ulWaterMark;
  694. _ulFailurePoint = ulFailurePoint ;
  695. astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::SetFailureInfo\n"));
  696. return S_OK;
  697. }
  698. #if DBG==1
  699. void CFillLockBytes::PulseFillEvent()
  700. {
  701. #ifdef ASYNC
  702. if (_ppc)
  703. {
  704. HANDLE hEvent = _ppc->GetNotificationEvent();
  705. PulseEvent(hEvent);
  706. }
  707. #else
  708. PulseEvent(_hNotifyEvent);
  709. #endif
  710. }
  711. #endif