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.

2765 lines
72 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. Events.cpp
  5. Abstract:
  6. This file provides implementation of the service
  7. notification mechanism.
  8. Author:
  9. Oded Sacher (OdedS) Jan, 2000
  10. Revision History:
  11. --*/
  12. #include "faxsvc.h"
  13. static
  14. DWORD
  15. FaxCloseConnection(
  16. HANDLE hContext
  17. )
  18. {
  19. DWORD rVal = ERROR_SUCCESS;
  20. HANDLE hClientContext = hContext;
  21. DEBUG_FUNCTION_NAME(TEXT("FaxCloseConnection"));
  22. RpcTryExcept
  23. {
  24. //
  25. // Close the context handle
  26. //
  27. rVal = FAX_CloseConnection( &hClientContext );
  28. if (ERROR_SUCCESS != rVal)
  29. {
  30. DumpRPCExtendedStatus();
  31. DebugPrintEx(DEBUG_ERR,TEXT("FAX_CloseConnection() failed, ec=0x%08x"), rVal );
  32. }
  33. }
  34. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  35. {
  36. DumpRPCExtendedStatus();
  37. rVal = GetExceptionCode();
  38. DebugPrintEx(
  39. DEBUG_ERR,
  40. TEXT("FAX_CloseConnection failed (exception = %ld)"),
  41. rVal);
  42. }
  43. RpcEndExcept
  44. return rVal;
  45. }
  46. /************************************
  47. * *
  48. * Globals *
  49. * *
  50. ************************************/
  51. CClientsMap* g_pClientsMap; // Map of clients ID to client.
  52. HANDLE g_hDispatchEventsCompPort; // Events completion port. Te events are dispatched to the client in the client map.
  53. HANDLE g_hSendEventsCompPort; // Completion port of client IDs that have events in their queue.
  54. DWORDLONG g_dwlClientID; // Client ID
  55. /***********************************
  56. * *
  57. * CFaxEventExtended Methodes *
  58. * *
  59. ***********************************/
  60. void
  61. CFaxEventExtended::RemoveOffendingExtendedJobStatus ()
  62. {
  63. //
  64. // Client talks with API version 0
  65. // We can't send JS_EX_CALL_COMPLETED and JS_EX_CALL_ABORTED
  66. //
  67. if ((FAX_EVENT_TYPE_IN_QUEUE == m_pEvent->EventType) ||
  68. (FAX_EVENT_TYPE_OUT_QUEUE == m_pEvent->EventType))
  69. {
  70. //
  71. // Queue event
  72. //
  73. if (FAX_JOB_EVENT_TYPE_STATUS == m_pEvent->EventInfo.JobInfo.Type)
  74. {
  75. //
  76. // This is a status event
  77. //
  78. PFAX_JOB_STATUS pStatus = PFAX_JOB_STATUS(DWORD_PTR(m_pEvent) + DWORD_PTR(m_pEvent->EventInfo.JobInfo.pJobData));
  79. if (FAX_API_VER_0_MAX_JS_EX < pStatus->dwExtendedStatus)
  80. {
  81. //
  82. // Offending extended status - clear it
  83. //
  84. pStatus->dwExtendedStatus = 0;
  85. pStatus->dwValidityMask &= ~FAX_JOB_FIELD_STATUS_EX;
  86. }
  87. }
  88. }
  89. return;
  90. }
  91. DWORD
  92. CFaxEventExtended::GetEvent (LPBYTE* lppBuffer, LPDWORD lpdwBufferSize) const
  93. /*++
  94. Routine name : CFaxEventExtended::GetEvent
  95. Routine description:
  96. Returns a buffer filled with serialized FAX_EVENT_EX.
  97. The caller must call MemFree to deallocate memory.
  98. Must be called inside critical section g_CsClients.
  99. Author:
  100. Oded Sacher (OdedS), Jan, 2000
  101. Arguments:
  102. lppBuffer [out] - Address of a pointer to a buffer to recieve the serialized info.
  103. lpdwBufferSize [out] - Pointer to a DWORD to recieve the allocated buffer size.
  104. Return Value:
  105. Standard Win32 error code.
  106. --*/
  107. {
  108. DEBUG_FUNCTION_NAME(TEXT("CFaxEventExtended::GetEvent"));
  109. Assert (lppBuffer && lpdwBufferSize);
  110. *lppBuffer = (LPBYTE)MemAlloc(m_dwEventSize);
  111. if (NULL == *lppBuffer)
  112. {
  113. DebugPrintEx(
  114. DEBUG_ERR,
  115. TEXT("Error allocating event buffer"));
  116. return ERROR_OUTOFMEMORY;
  117. }
  118. CopyMemory (*lppBuffer, m_pEvent, m_dwEventSize);
  119. *lpdwBufferSize = m_dwEventSize;
  120. return ERROR_SUCCESS;
  121. } // CFaxEventExtended::GetEvent
  122. CFaxEventExtended::CFaxEventExtended(
  123. const FAX_EVENT_EX* pEvent,
  124. DWORD dwEventSize,
  125. PSID pSid) : m_dwEventSize(dwEventSize), m_pSid(NULL)
  126. {
  127. Assert (pEvent != NULL);
  128. Assert (dwEventSize != 0);
  129. m_pEvent = (PFAX_EVENT_EX)MemAlloc (dwEventSize);
  130. if (NULL == m_pEvent)
  131. {
  132. throw runtime_error("CFaxEventExtended::CFaxEventExtended Can not allocate FAX_EVENT_EX");
  133. }
  134. CopyMemory ((void*)m_pEvent, pEvent, dwEventSize);
  135. if (NULL != pSid)
  136. {
  137. if (!IsValidSid(pSid))
  138. {
  139. MemFree ((void*)m_pEvent);
  140. throw runtime_error ("CFaxEventExtended:: CFaxEventExtended Invalid Sid");
  141. }
  142. DWORD dwSidLength = GetLengthSid(pSid);
  143. m_pSid = (PSID)MemAlloc (dwSidLength);
  144. if (NULL == m_pSid)
  145. {
  146. MemFree ((void*)m_pEvent);
  147. throw runtime_error ("CFaxEventExtended:: CFaxEventExtended Can not allocate Sid");
  148. }
  149. if (!CopySid(dwSidLength, m_pSid, pSid))
  150. {
  151. MemFree ((void*)m_pEvent);
  152. MemFree (m_pSid);
  153. throw runtime_error ("CFaxEventExtended:: CFaxEventExtended CopySid failed Sid");
  154. }
  155. }
  156. }
  157. BOOL
  158. CFaxEventExtended::MatchEvent(PSID pUserSid, DWORD dwEventTypes, BOOL bAllQueueMessages, BOOL bAllOutArchiveMessages) const
  159. {
  160. BOOL bViewAllMessages;
  161. //
  162. // Extended event
  163. //
  164. if (0 == (m_pEvent->EventType & dwEventTypes))
  165. {
  166. //
  167. // Client is not registered for this kind of evevnts
  168. //
  169. return FALSE;
  170. }
  171. //
  172. // Client is registered for this kind of evevnts
  173. //
  174. switch (m_pEvent->EventType)
  175. {
  176. case FAX_EVENT_TYPE_OUT_QUEUE:
  177. bViewAllMessages = bAllQueueMessages;
  178. break;
  179. case FAX_EVENT_TYPE_OUT_ARCHIVE:
  180. bViewAllMessages = bAllOutArchiveMessages;
  181. break;
  182. default:
  183. // Other kind of event - bViewAllMessages is not relevant
  184. bViewAllMessages = TRUE;
  185. }
  186. //
  187. // Check if the user is allowed to see this event
  188. //
  189. if (FALSE == bViewAllMessages)
  190. {
  191. Assert (pUserSid && m_pSid);
  192. //
  193. // The user is not allowed to see all messages
  194. //
  195. if (!EqualSid (pUserSid, m_pSid))
  196. {
  197. //
  198. // Do not send the event to this client.
  199. //
  200. return FALSE;
  201. }
  202. }
  203. return TRUE;
  204. }
  205. /***********************************
  206. * *
  207. * CFaxEventLegacy Methodes *
  208. * *
  209. ***********************************/
  210. DWORD
  211. CFaxEventLegacy::GetEvent (LPBYTE* lppBuffer, LPDWORD lpdwBufferSize) const
  212. /*++
  213. Routine name : CFaxEventLegacy::GetEvent
  214. Routine description:
  215. Returns a buffer filled with serialized FAX_EVENT.
  216. The caller must call MemFree to deallocate memory.
  217. Must be called inside critical section g_CsClients.
  218. Author:
  219. Oded Sacher (OdedS), Jan, 2000
  220. Arguments:
  221. lppBuffer [out] - Address of a pointer to a buffer to recieve the serialized info.
  222. lpdwBufferSize [out] - Pointer to a DWORD to recieve the allocated buffer size.
  223. Return Value:
  224. Standard Win32 error code.
  225. --*/
  226. {
  227. DEBUG_FUNCTION_NAME(TEXT("CFaxEventLegacy::GetEvent"));
  228. Assert (lppBuffer && lpdwBufferSize);
  229. *lppBuffer = (LPBYTE)MemAlloc(sizeof(FAX_EVENT));
  230. if (NULL == *lppBuffer)
  231. {
  232. DebugPrintEx(
  233. DEBUG_ERR,
  234. TEXT("Error allocating event buffer"));
  235. return ERROR_OUTOFMEMORY;
  236. }
  237. CopyMemory (*lppBuffer, m_pEvent, sizeof(FAX_EVENT));
  238. *lpdwBufferSize = sizeof(FAX_EVENT);
  239. return ERROR_SUCCESS;
  240. } // CFaxEventLegacy::GetEvent
  241. CFaxEventLegacy::CFaxEventLegacy(
  242. const FAX_EVENT* pEvent)
  243. {
  244. Assert (pEvent != NULL);
  245. m_pEvent = (PFAX_EVENT)MemAlloc (sizeof(FAX_EVENT));
  246. if (NULL == m_pEvent)
  247. {
  248. throw runtime_error("CFaxEventExtended::CFaxEventExtended Can not allocate FAX_EVENT_EX");
  249. }
  250. CopyMemory ((void*)m_pEvent, pEvent, sizeof(FAX_EVENT));
  251. }
  252. BOOL
  253. CFaxEventLegacy::MatchEvent(PSID pUserSid, DWORD dwEventTypes, BOOL bAllQueueMessages, BOOL bAllOutArchiveMessages) const
  254. {
  255. if (FAX_EVENT_TYPE_LEGACY == dwEventTypes)
  256. {
  257. //
  258. // Client is registered for this kind of evevnts
  259. //
  260. return TRUE;
  261. }
  262. return FALSE;
  263. }
  264. /***********************************
  265. * *
  266. * CClientID Methodes *
  267. * *
  268. ***********************************/
  269. bool
  270. CClientID::operator < ( const CClientID &other ) const
  271. /*++
  272. Routine name : operator <
  273. Class: CClientID
  274. Routine description:
  275. Compares myself with another client ID key
  276. Author:
  277. Oded Sacher (Odeds), Jan, 2000
  278. Arguments:
  279. other [in] - Other key
  280. Return Value:
  281. true only is i'm less than the other key
  282. --*/
  283. {
  284. if (m_dwlClientID < other.m_dwlClientID)
  285. {
  286. return true;
  287. }
  288. return false;
  289. } // CClientID::operator <
  290. /***********************************
  291. * *
  292. * CClient Methodes *
  293. * *
  294. ***********************************/
  295. //
  296. // Ctor
  297. //
  298. CClient::CClient (CClientID ClientID,
  299. PSID pUserSid,
  300. DWORD dwEventTypes,
  301. handle_t hFaxHandle,
  302. BOOL bAllQueueMessages,
  303. BOOL bAllOutArchiveMessages,
  304. DWORD dwAPIVersion) :
  305. m_dwEventTypes(dwEventTypes),
  306. m_ClientID(ClientID),
  307. m_bPostClientID(TRUE),
  308. m_bAllQueueMessages(bAllQueueMessages),
  309. m_bAllOutArchiveMessages(bAllOutArchiveMessages),
  310. m_dwAPIVersion(dwAPIVersion),
  311. m_dwRefCount(1)
  312. {
  313. m_FaxHandle = hFaxHandle;
  314. m_hFaxClientContext = NULL;
  315. m_pUserSid = NULL;
  316. if (NULL != pUserSid)
  317. {
  318. if (!IsValidSid(pUserSid))
  319. {
  320. throw runtime_error ("CClient:: CClient Invalid Sid");
  321. }
  322. DWORD dwSidLength = GetLengthSid(pUserSid);
  323. m_pUserSid = (PSID)MemAlloc (dwSidLength);
  324. if (NULL == m_pUserSid)
  325. {
  326. throw runtime_error ("CClient:: CClient Can not allocate Sid");
  327. }
  328. if (!CopySid(dwSidLength, m_pUserSid, pUserSid))
  329. {
  330. MemFree (m_pUserSid);
  331. m_pUserSid = NULL;
  332. throw runtime_error ("CClient:: CClient CopySid failed Sid");
  333. }
  334. }
  335. }
  336. //
  337. // Assignment
  338. //
  339. CClient& CClient::operator= (const CClient& rhs)
  340. {
  341. if (this == &rhs)
  342. {
  343. return *this;
  344. }
  345. m_FaxHandle = rhs.m_FaxHandle;
  346. m_dwEventTypes = rhs.m_dwEventTypes;
  347. m_Events = rhs.m_Events;
  348. m_ClientID = rhs.m_ClientID;
  349. m_hFaxClientContext = rhs.m_hFaxClientContext;
  350. m_bPostClientID = rhs.m_bPostClientID;
  351. m_bAllQueueMessages = rhs.m_bAllQueueMessages;
  352. m_bAllOutArchiveMessages = rhs.m_bAllOutArchiveMessages;
  353. m_dwAPIVersion = rhs.m_dwAPIVersion;
  354. m_dwRefCount = rhs.m_dwRefCount;
  355. MemFree (m_pUserSid);
  356. m_pUserSid = NULL;
  357. if (NULL != rhs.m_pUserSid)
  358. {
  359. if (!IsValidSid(rhs.m_pUserSid))
  360. {
  361. throw runtime_error ("CClient::operator= Invalid Sid");
  362. }
  363. DWORD dwSidLength = GetLengthSid(rhs.m_pUserSid);
  364. m_pUserSid = (PSID)MemAlloc (dwSidLength);
  365. if (NULL == m_pUserSid)
  366. {
  367. throw runtime_error ("CClient::operator= Can not allocate Sid");
  368. }
  369. if (!CopySid(dwSidLength, m_pUserSid, rhs.m_pUserSid))
  370. {
  371. throw runtime_error ("CClient::operator= CopySid failed Sid");
  372. }
  373. }
  374. return *this;
  375. }
  376. //
  377. // Copy Ctor
  378. //
  379. CClient::CClient (const CClient& rhs) : m_ClientID(rhs.m_ClientID)
  380. {
  381. m_FaxHandle = rhs.m_FaxHandle;
  382. m_dwEventTypes = rhs.m_dwEventTypes;
  383. m_Events = rhs.m_Events;
  384. m_hFaxClientContext = rhs.m_hFaxClientContext;
  385. m_bPostClientID = rhs.m_bPostClientID;
  386. m_bAllQueueMessages = rhs.m_bAllQueueMessages;
  387. m_bAllOutArchiveMessages = rhs.m_bAllOutArchiveMessages;
  388. m_dwAPIVersion = rhs.m_dwAPIVersion;
  389. m_dwRefCount = rhs.m_dwRefCount;
  390. m_pUserSid = NULL;
  391. if (NULL != rhs.m_pUserSid)
  392. {
  393. if (!IsValidSid(rhs.m_pUserSid))
  394. {
  395. throw runtime_error("CClient::CopyCtor Invalid Sid");
  396. }
  397. DWORD dwSidLength = GetLengthSid(rhs.m_pUserSid);
  398. m_pUserSid = (PSID)MemAlloc (dwSidLength);
  399. if (NULL == m_pUserSid)
  400. {
  401. throw runtime_error("CClient::CopyCtor Can not allocate Sid");
  402. }
  403. if (!CopySid(dwSidLength, m_pUserSid, rhs.m_pUserSid))
  404. {
  405. throw runtime_error("CClient::CopyCtor CopySid failed");
  406. }
  407. }
  408. return;
  409. }
  410. //
  411. // Dtor
  412. //
  413. CClient::~CClient ()
  414. {
  415. DEBUG_FUNCTION_NAME(TEXT("CClient::~CClient"));
  416. try
  417. {
  418. while (FALSE == m_Events.empty())
  419. {
  420. CFaxEvent* pFaxEvent = m_Events.front();
  421. m_Events.pop();
  422. delete pFaxEvent;
  423. }
  424. }
  425. catch (exception &ex)
  426. {
  427. DebugPrintEx(
  428. DEBUG_ERR,
  429. TEXT("queue or CFaxEvent caused exception (%S)"),
  430. ex.what());
  431. }
  432. MemFree (m_pUserSid);
  433. m_pUserSid = NULL;
  434. return;
  435. }
  436. DWORD
  437. CClient::AddEvent(CFaxEvent* pFaxEvent)
  438. /*++
  439. Routine name : CClient::AddEvent
  440. Routine description:
  441. Adds CFaxEvent object to the client's events queue.
  442. Must be called inside critical section g_CsClients.
  443. The function frees pFaxEvent if it is not added to the client queue.
  444. Author:
  445. Oded Sacher (OdedS), Jan, 2000
  446. Arguments:
  447. pFaxEvent [in] - Pointer to CFaxEvnet object
  448. Return Value:
  449. Standard Win32 error code
  450. --*/
  451. {
  452. DWORD dwRes = ERROR_SUCCESS;
  453. DEBUG_FUNCTION_NAME(TEXT("CClient::AddEvent"));
  454. BOOL bEventAdded = FALSE;
  455. if (!pFaxEvent->MatchEvent(m_pUserSid, m_dwEventTypes, m_bAllQueueMessages, m_bAllOutArchiveMessages))
  456. {
  457. //
  458. // Client is not registered for this event. Free the event report success
  459. //
  460. goto exit;
  461. }
  462. if (FAX_API_VERSION_1 > m_dwAPIVersion)
  463. {
  464. //
  465. // Client talks with API version 0
  466. // We can't send JS_EX_CALL_COMPLETED and JS_EX_CALL_ABORTED
  467. pFaxEvent->RemoveOffendingExtendedJobStatus();
  468. }
  469. try
  470. {
  471. //
  472. // Add the event to the client queue
  473. //
  474. m_Events.push(pFaxEvent);
  475. if (TRUE == m_bPostClientID)
  476. {
  477. //
  478. // events in queue - Notify the completion port threads of the client's queued events
  479. //
  480. CClientID* pClientID = new (std::nothrow) CClientID(m_ClientID);
  481. if (NULL == pClientID)
  482. {
  483. DebugPrintEx(
  484. DEBUG_ERR,
  485. TEXT("Can not allocate CClientID object"));
  486. dwRes = ERROR_OUTOFMEMORY;
  487. m_Events.pop();
  488. goto exit;
  489. }
  490. //
  491. // post CLIENT_COMPLETION_KEY to the completion port
  492. //
  493. if (!PostQueuedCompletionStatus( g_hSendEventsCompPort,
  494. sizeof(CClientID),
  495. CLIENT_COMPLETION_KEY,
  496. (LPOVERLAPPED) pClientID))
  497. {
  498. dwRes = GetLastError();
  499. DebugPrintEx(
  500. DEBUG_ERR,
  501. TEXT("PostQueuedCompletionStatus failed. (ec: %ld)"),
  502. dwRes);
  503. delete pClientID;
  504. pClientID = NULL;
  505. m_Events.pop();
  506. goto exit;
  507. }
  508. m_bPostClientID = FALSE;
  509. }
  510. }
  511. catch (exception &ex)
  512. {
  513. DebugPrintEx(
  514. DEBUG_ERR,
  515. TEXT("queue or CFaxEvent caused exception (%S)"),
  516. ex.what());
  517. dwRes = ERROR_GEN_FAILURE;
  518. goto exit;
  519. }
  520. bEventAdded = TRUE;
  521. Assert (ERROR_SUCCESS == dwRes);
  522. exit:
  523. if (FALSE == bEventAdded)
  524. {
  525. delete pFaxEvent;
  526. }
  527. return dwRes;
  528. } // CClient::AddEvent
  529. DWORD
  530. CClient::GetEvent (LPBYTE* lppBuffer, LPDWORD lpdwBufferSize, PHANDLE phClientContext) const
  531. /*++
  532. Routine name : CClient::GetEvent
  533. Routine description:
  534. Gets a serialized FAX_EVENT_EX buffer to be sent
  535. to a client using the client context handle (obtained from OpenConnection()).
  536. The caller must call MemFree to deallocate memory.
  537. Must be called inside critical section g_CsClients.
  538. Author:
  539. Oded Sacher (OdedS), Jan, 2000
  540. Arguments:
  541. lppBuffer [out] - Address of a pointer to a buffer to recieve the serialized info.
  542. lpdwBufferSize [out] - Pointer to a DWORD to recieve the allocated buffer size.
  543. phClientContext [out] - Pointer to a HANDLE to recieve the client context handle.
  544. Return Value:
  545. Standard Win32 error code.
  546. --*/
  547. {
  548. DWORD dwRes = ERROR_SUCCESS;
  549. DEBUG_FUNCTION_NAME(TEXT("CClient::GetEvent"));
  550. Assert ( lppBuffer && phClientContext);
  551. try
  552. {
  553. // get a reference to the top event
  554. const CFaxEvent* pFaxEvent = m_Events.front();
  555. //
  556. // get the serialized FAX_EVENT_EX or FAX_EVENT buffer
  557. //
  558. dwRes = pFaxEvent->GetEvent(lppBuffer ,lpdwBufferSize);
  559. if (ERROR_SUCCESS != dwRes)
  560. {
  561. DebugPrintEx(
  562. DEBUG_ERR,
  563. TEXT("CFaxEvent::GetEvent failed with error = %ld)"),
  564. dwRes);
  565. goto exit;
  566. }
  567. }
  568. catch (exception &ex)
  569. {
  570. DebugPrintEx(
  571. DEBUG_ERR,
  572. TEXT("queue or CFaxEvent caused exception (%S)"),
  573. ex.what());
  574. dwRes = ERROR_GEN_FAILURE;
  575. goto exit;
  576. }
  577. //
  578. // Get the client context handle
  579. //
  580. *phClientContext = m_hFaxClientContext;
  581. Assert (ERROR_SUCCESS == dwRes);
  582. exit:
  583. return dwRes;
  584. } // CClient::GetEvent
  585. DWORD
  586. CClient::DelEvent ()
  587. /*++
  588. Routine name : CClient::DelEvent
  589. Routine description:
  590. Removes the first event from the queue.
  591. Must be called inside critical section g_CsClients.
  592. Author:
  593. Oded Sacher (OdedS), Jan, 2000
  594. Arguments:
  595. Return Value:
  596. Standard Win32 error code
  597. --*/
  598. {
  599. DWORD dwRes = ERROR_SUCCESS;
  600. DEBUG_FUNCTION_NAME(TEXT("CClient::DelEvent"));
  601. Assert (m_bPostClientID == FALSE);
  602. try
  603. {
  604. CFaxEvent* pFaxEvent = m_Events.front();
  605. m_Events.pop();
  606. delete pFaxEvent;
  607. if (m_Events.empty())
  608. {
  609. // last event was poped ,next event will notify of client queued events
  610. m_bPostClientID = TRUE;
  611. }
  612. else
  613. {
  614. //
  615. // More events in queue - Notify the completion port of queued events
  616. //
  617. CClientID* pClientID = new (std::nothrow) CClientID(m_ClientID);
  618. if (NULL == pClientID)
  619. {
  620. DebugPrintEx(
  621. DEBUG_ERR,
  622. TEXT("Can not allocate CClientID object"));
  623. dwRes = ERROR_OUTOFMEMORY;
  624. goto exit;
  625. }
  626. if (!PostQueuedCompletionStatus( g_hSendEventsCompPort,
  627. sizeof(CClientID),
  628. CLIENT_COMPLETION_KEY,
  629. (LPOVERLAPPED) pClientID))
  630. {
  631. dwRes = GetLastError();
  632. DebugPrintEx(
  633. DEBUG_ERR,
  634. TEXT("PostQueuedCompletionStatus failed. (ec: %ld)"),
  635. dwRes);
  636. delete pClientID;
  637. pClientID = NULL;
  638. m_bPostClientID = TRUE; // try to notify when the next event is queued
  639. goto exit;
  640. }
  641. m_bPostClientID = FALSE;
  642. }
  643. }
  644. catch (exception &ex)
  645. {
  646. DebugPrintEx(
  647. DEBUG_ERR,
  648. TEXT("queue caused exception (%S)"),
  649. ex.what());
  650. dwRes = ERROR_GEN_FAILURE;
  651. }
  652. Assert (ERROR_SUCCESS == dwRes);
  653. exit:
  654. return dwRes;
  655. } // CClient::DelEvent
  656. /***********************************
  657. * *
  658. * CClientsMap Methodes *
  659. * *
  660. ***********************************/
  661. DWORD
  662. CClientsMap::AddClient (const CClient& Client)
  663. /*++
  664. Routine name : CClientsMap::AddClient
  665. Routine description:
  666. Adds a new client to the global map.
  667. Must be called inside critical section g_CsClients.
  668. Author:
  669. Oded Sacher (OdedS), Jan, 2000
  670. Arguments:
  671. Client [in ] - A reference to the new client object
  672. Return Value:
  673. Standard Win32 error code
  674. --*/
  675. {
  676. CLIENTS_MAP::iterator it;
  677. DWORD dwRes = ERROR_SUCCESS;
  678. DEBUG_FUNCTION_NAME(TEXT("CClientsMap::AddClient"));
  679. pair <CLIENTS_MAP::iterator, bool> p;
  680. try
  681. {
  682. //
  683. // Add new map entry
  684. //
  685. p = m_ClientsMap.insert (CLIENTS_MAP::value_type(Client.GetClientID(), Client));
  686. //
  687. // See if entry exists in map
  688. //
  689. if (p.second == FALSE)
  690. {
  691. DebugPrintEx(
  692. DEBUG_ERR,
  693. TEXT("Client allready in the clients map"));
  694. dwRes = ERROR_DUP_NAME;
  695. Assert (p.second == TRUE); // Assert FALSE
  696. goto exit;
  697. }
  698. }
  699. catch (exception &ex)
  700. {
  701. DebugPrintEx(
  702. DEBUG_ERR,
  703. TEXT("map or Client caused exception (%S)"),
  704. ex.what());
  705. dwRes = ERROR_GEN_FAILURE;
  706. goto exit;
  707. }
  708. Assert (ERROR_SUCCESS == dwRes);
  709. exit:
  710. return dwRes;
  711. } // CClientsMap::AddClient
  712. DWORD
  713. CClientsMap::ReleaseClient (const CClientID& ClientID, BOOL fRunDown /* = FALSE */)
  714. /*++
  715. Routine name : CClientsMap::ReleaseClient
  716. Routine description:
  717. Decrease a client refertnce count. If refcount is 0, Deletes it from the global clients map.
  718. DO NOT call ReleaseClient when holding g_CsClients!
  719. A call to ReleaseClient can cause FaxCloseConnection to be called. As FaxCloseConnection is
  720. a RPC call, it (ReleaseClient) must be called when g_CsClients is NOT held.
  721. Author:
  722. Oded Sacher (OdedS), Jan, 2000
  723. Arguments:
  724. ClientID [in ] - Reference to the client ID key
  725. fRunDown [in ] - The call is a result of RPC rundown
  726. Return Value:
  727. Standard Win32 error code
  728. --*/
  729. {
  730. DWORD dwRes = ERROR_SUCCESS;
  731. CClient* pClient = NULL;
  732. CLIENTS_MAP::iterator it;
  733. DWORD dwRefCount;
  734. HANDLE hClientContext = NULL;
  735. HANDLE hBindingHandle = NULL;
  736. DWORD rVal = ERROR_SUCCESS;
  737. DEBUG_FUNCTION_NAME(TEXT("CClientsMap::ReleaseClient"));
  738. //
  739. // Enter g_CsClients while searching for the client.
  740. //
  741. EnterCriticalSection (&g_CsClients);
  742. try
  743. {
  744. //
  745. // See if entry exists in map
  746. //
  747. if((it = m_ClientsMap.find(ClientID)) == m_ClientsMap.end())
  748. {
  749. dwRes = ERROR_SUCCESS; // Client was removed from map
  750. DebugPrintEx(
  751. DEBUG_WRN,
  752. TEXT("client not found, Client ID %I64"),
  753. ClientID.GetID());
  754. goto exit;
  755. }
  756. }
  757. catch (exception &ex)
  758. {
  759. DebugPrintEx(
  760. DEBUG_ERR,
  761. TEXT("map caused exception (%S)"),
  762. ex.what());
  763. dwRes = ERROR_GEN_FAILURE;
  764. goto exit;
  765. }
  766. pClient = &((*it).second);
  767. Assert (pClient);
  768. if (TRUE == fRunDown)
  769. {
  770. //
  771. // Prevent further RPC calls to this client
  772. //
  773. pClient->SetContextHandle(NULL);
  774. }
  775. dwRefCount = pClient->Release();
  776. if (dwRefCount > 0)
  777. {
  778. //
  779. // Client can not be removed from the map yet
  780. //
  781. goto exit;
  782. }
  783. hClientContext = pClient->GetContextHandle();
  784. if (NULL != hClientContext)
  785. {
  786. //
  787. // Block other threads from sending events to this client
  788. //
  789. pClient->SetContextHandle(NULL);
  790. //
  791. // A connection to the client was opened.
  792. // leave g_CsClients while trying to close the connection
  793. //
  794. LeaveCriticalSection (&g_CsClients);
  795. rVal = FaxCloseConnection(hClientContext);
  796. if (ERROR_SUCCESS != rVal)
  797. {
  798. DebugPrintEx(
  799. DEBUG_ERR,
  800. TEXT("FaxCloseConnection failed with ec = %ld"),
  801. rVal);
  802. }
  803. EnterCriticalSection (&g_CsClients);
  804. }
  805. hBindingHandle = pClient->GetFaxHandle();
  806. Assert (hBindingHandle);
  807. dwRes = RpcBindingFree(&hBindingHandle);
  808. if (ERROR_SUCCESS != dwRes)
  809. {
  810. DebugPrintEx(
  811. DEBUG_WRN,
  812. TEXT("RpcBindingFree failed, ec: %ld"),
  813. dwRes);
  814. }
  815. //
  816. // Delete the map entry
  817. //
  818. m_ClientsMap.erase (it);
  819. exit:
  820. LeaveCriticalSection (&g_CsClients);
  821. return ((ERROR_SUCCESS != rVal) ? rVal : dwRes);
  822. } // CClientsMap::ReleaseClient
  823. PCCLIENT
  824. CClientsMap::FindClient (const CClientID& ClientID) const
  825. /*++
  826. Routine name : CClientsMap::FindClient
  827. Routine description:
  828. Returns a pointer to a client object specified by its ID object.
  829. Author:
  830. Oded Sacher (OdedS), Jan, 2000
  831. Arguments:
  832. ClientID [in] - The clients's ID object
  833. Return Value:
  834. Pointer to the found rule object. If it is null the client was not found.
  835. If the client object was returned, the caller must call CClientsMap::ReleaseClient to release the client object.
  836. --*/
  837. {
  838. CLIENTS_MAP::iterator it;
  839. PCCLIENT pClient = NULL;
  840. DWORD ec = ERROR_SUCCESS;
  841. DEBUG_FUNCTION_NAME(TEXT("CClientsMap::FindClient"));
  842. EnterCriticalSection (&g_CsClients);
  843. try
  844. {
  845. //
  846. // See if entry exists in map
  847. //
  848. if((it = m_ClientsMap.find(ClientID)) == m_ClientsMap.end())
  849. {
  850. ec = ERROR_NOT_FOUND;
  851. goto exit;
  852. }
  853. pClient = &((*it).second);
  854. if (0 != pClient->GetRefCount())
  855. {
  856. //
  857. // Increase the client reference count, so it will not be deleted.
  858. //
  859. pClient->Lock();
  860. }
  861. else
  862. {
  863. //
  864. // The client is being deleted.
  865. //
  866. pClient = NULL;
  867. ec = ERROR_NOT_FOUND;
  868. }
  869. goto exit;
  870. }
  871. catch (exception &ex)
  872. {
  873. DebugPrintEx(
  874. DEBUG_ERR,
  875. TEXT("map caused exception (%S)"),
  876. ex.what());
  877. ec = ERROR_GEN_FAILURE;
  878. }
  879. exit:
  880. LeaveCriticalSection (&g_CsClients);
  881. if (NULL == pClient)
  882. {
  883. Assert (ERROR_SUCCESS != ec);
  884. SetLastError(ec);
  885. }
  886. return pClient;
  887. } // CClientsMap::FindClient
  888. DWORD
  889. CClientsMap::AddEvent(CFaxEvent* pFaxEvent)
  890. /*++
  891. Routine name : CClientsMap::AddEvent
  892. Routine description:
  893. Adds event to the events queue of each client that is registered for this kind of event
  894. Author:
  895. Oded Sacher (OdedS), Jan, 2000
  896. Arguments:
  897. pFaxEvent [in] - Pointer to CFaxEvnet object
  898. Return Value:
  899. Standard Win32 error code
  900. --*/
  901. {
  902. CLIENTS_MAP::iterator it;
  903. DWORD dwRes = ERROR_SUCCESS;
  904. DEBUG_FUNCTION_NAME(TEXT("CClientsMap::AddEvent"));
  905. CClient* pClient;
  906. EnterCriticalSection (&g_CsClients);
  907. try
  908. {
  909. for (it = m_ClientsMap.begin(); it != m_ClientsMap.end(); it++)
  910. {
  911. pClient = &((*it).second);
  912. if (pClient->IsConnectionOpened())
  913. {
  914. CFaxEvent* pNewFaxEvent = pFaxEvent->Clone();
  915. if (NULL == pNewFaxEvent)
  916. {
  917. dwRes = ERROR_OUTOFMEMORY;
  918. DebugPrintEx(
  919. DEBUG_ERR,
  920. TEXT("CCLient::AddEvent failed)"));
  921. goto exit;
  922. }
  923. else
  924. {
  925. dwRes = pClient->AddEvent (pNewFaxEvent);
  926. if (ERROR_SUCCESS != dwRes)
  927. {
  928. DebugPrintEx(
  929. DEBUG_ERR,
  930. TEXT("CCLient::AddEvent failed with error = %ld)"),
  931. dwRes);
  932. goto exit;
  933. }
  934. }
  935. }
  936. }
  937. }
  938. catch (exception &ex)
  939. {
  940. DebugPrintEx(
  941. DEBUG_ERR,
  942. TEXT("map caused exception (%S)"),
  943. ex.what());
  944. dwRes = ERROR_GEN_FAILURE;
  945. goto exit;
  946. }
  947. Assert (ERROR_SUCCESS == dwRes);
  948. exit:
  949. LeaveCriticalSection (&g_CsClients);
  950. return dwRes;
  951. } // CClientsMap::AddEvent
  952. DWORD
  953. CClientsMap::Notify (const CClientID& ClientID)
  954. /*++
  955. Routine name : CClientsMap::Notify
  956. Routine description:
  957. Sends the first event in the specified client events queue
  958. Author:
  959. Oded Sacher (OdedS), Jan, 2000
  960. Arguments:
  961. pClientID [in ] - Pointer to the client ID object
  962. Return Value:
  963. Standard Win32 error code
  964. --*/
  965. {
  966. DWORD dwRes = ERROR_SUCCESS;
  967. DWORD rVal = ERROR_SUCCESS;
  968. DEBUG_FUNCTION_NAME(TEXT("CClientsMap::Notify"));
  969. CClient* pClient = NULL;
  970. HANDLE hClientContext;
  971. LPBYTE pBuffer = NULL;
  972. DWORD dwBufferSize = 0;
  973. BOOL fLegacyClient;
  974. //
  975. // Find the client in the map, this will also lock the client
  976. //
  977. pClient = FindClient (ClientID);
  978. if (NULL == pClient)
  979. {
  980. dwRes = GetLastError();
  981. if (ERROR_NOT_FOUND != dwRes)
  982. {
  983. DebugPrintEx(
  984. DEBUG_ERR,
  985. TEXT("CClientsMap::FindClient failed with ec = %ld"),
  986. dwRes);
  987. }
  988. else
  989. {
  990. dwRes = ERROR_SUCCESS; // Client was removed from map
  991. DebugPrintEx(
  992. DEBUG_WRN,
  993. TEXT("CClientsMap::FindClient client not found, Client ID %I64"),
  994. ClientID.GetID());
  995. }
  996. return dwRes;
  997. }
  998. //
  999. // Client is locked (will not be deleted), we must call ReleaseClient
  1000. // When getting the client data (event and context handle, we must lock g_CsClients as well).
  1001. //
  1002. EnterCriticalSection (&g_CsClients);
  1003. if (FALSE == pClient->IsConnectionOpened())
  1004. {
  1005. dwRes = ERROR_SUCCESS; // Client closed the connection
  1006. DebugPrintEx(
  1007. DEBUG_WRN,
  1008. TEXT("Client already closed the connection, Client ID %I64"),
  1009. ClientID.GetID());
  1010. LeaveCriticalSection (&g_CsClients);
  1011. goto exit;
  1012. }
  1013. dwRes = pClient->GetEvent (&pBuffer, &dwBufferSize, &hClientContext);
  1014. if (ERROR_SUCCESS != dwRes)
  1015. {
  1016. DebugPrintEx(
  1017. DEBUG_ERR,
  1018. TEXT("CClient::GetEvent failed with ec = %ld"),
  1019. dwRes);
  1020. LeaveCriticalSection (&g_CsClients);
  1021. goto exit;
  1022. }
  1023. fLegacyClient = pClient->IsLegacyClient();
  1024. //
  1025. // Leave g_CsClients before calling RPC
  1026. //
  1027. LeaveCriticalSection (&g_CsClients);
  1028. RpcTryExcept
  1029. {
  1030. //
  1031. // post the event to the client
  1032. //
  1033. if (FALSE == fLegacyClient)
  1034. {
  1035. dwRes = FAX_ClientEventQueueEx( hClientContext, pBuffer, dwBufferSize);
  1036. if (ERROR_SUCCESS != dwRes)
  1037. {
  1038. DumpRPCExtendedStatus ();
  1039. DebugPrintEx(DEBUG_ERR,TEXT("FAX_ClientEventQueueEX() failed, ec=0x%08x"), dwRes );
  1040. }
  1041. }
  1042. else
  1043. {
  1044. dwRes = FAX_ClientEventQueue( hClientContext, *((PFAX_EVENT)pBuffer));
  1045. if (ERROR_SUCCESS != dwRes)
  1046. {
  1047. DumpRPCExtendedStatus ();
  1048. DebugPrintEx(DEBUG_ERR,TEXT("FAX_ClientEventQueue() failed, ec=0x%08x"), dwRes );
  1049. }
  1050. }
  1051. }
  1052. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  1053. {
  1054. DumpRPCExtendedStatus ();
  1055. dwRes = GetExceptionCode();
  1056. DebugPrintEx(
  1057. DEBUG_ERR,
  1058. TEXT("FAX_ClientEventQueueEX failed (exception = %ld)"),
  1059. dwRes);
  1060. }
  1061. RpcEndExcept
  1062. if (ERROR_SUCCESS != dwRes)
  1063. {
  1064. DebugPrintEx(
  1065. DEBUG_ERR,
  1066. TEXT("Failed to post event, Client context handle 0X%x, (ec: %ld)"),
  1067. hClientContext,
  1068. dwRes);
  1069. }
  1070. rVal = dwRes;
  1071. exit:
  1072. //
  1073. // Remove the event from the client's queue. CClient::DelEvent must be called so CClient::m_bPostClientID will be set.
  1074. //
  1075. EnterCriticalSection (&g_CsClients);
  1076. dwRes = pClient->DelEvent ();
  1077. if (ERROR_SUCCESS != dwRes)
  1078. {
  1079. DebugPrintEx(
  1080. DEBUG_ERR,
  1081. TEXT("CClient::DelEvent failed with ec = %ld"),
  1082. dwRes);
  1083. }
  1084. LeaveCriticalSection (&g_CsClients);
  1085. DWORD ec = ReleaseClient(ClientID);
  1086. if (ERROR_SUCCESS != ec)
  1087. {
  1088. DebugPrintEx(
  1089. DEBUG_ERR,
  1090. TEXT("CClientsMap::ReleaseClient failed with ec = %ld"),
  1091. ec);
  1092. }
  1093. MemFree(pBuffer);
  1094. pBuffer = NULL;
  1095. return ((ERROR_SUCCESS != rVal) ? rVal : dwRes);
  1096. } // CClientsMap::Notify
  1097. DWORD
  1098. CClientsMap::OpenClientConnection (const CClientID& ClientID)
  1099. /*++
  1100. Routine name : CClientsMap::OpenClientConnection
  1101. Routine description:
  1102. Opens a connection to a client
  1103. Author:
  1104. Oded Sacher (OdedS), Sep, 2000
  1105. Arguments:
  1106. pClientID [in ] - Pointer to the client ID object
  1107. Return Value:
  1108. Standard Win32 error code
  1109. --*/
  1110. {
  1111. DWORD dwRes = ERROR_SUCCESS;
  1112. DEBUG_FUNCTION_NAME(TEXT("CClientsMap::OpenClientConnection"));
  1113. CClient* pClient;
  1114. handle_t hFaxHandle = NULL;
  1115. ULONG64 Context = 0;
  1116. HANDLE hFaxClientContext = NULL;
  1117. BOOL fLegacyClient;
  1118. pClient = FindClient (ClientID);
  1119. if (NULL == pClient)
  1120. {
  1121. dwRes = GetLastError();
  1122. if (ERROR_NOT_FOUND != dwRes)
  1123. {
  1124. DebugPrintEx(
  1125. DEBUG_ERR,
  1126. TEXT("CClientsMap::FindClient failed with ec = %ld"),
  1127. dwRes);
  1128. }
  1129. else
  1130. {
  1131. dwRes = ERROR_SUCCESS; // Client was removed from map
  1132. DebugPrintEx(
  1133. DEBUG_WRN,
  1134. TEXT("CClientsMap::FindClient client not found, Client ID %I64"),
  1135. ClientID.GetID());
  1136. }
  1137. return dwRes;
  1138. }
  1139. //
  1140. // Client is now locked, we must call ReleaseClient
  1141. // Aquire g_CsClients when reading the client data
  1142. //
  1143. EnterCriticalSection (&g_CsClients);
  1144. hFaxHandle = pClient->GetFaxHandle();
  1145. Context = (pClient->GetClientID()).GetContext();
  1146. fLegacyClient = pClient->IsLegacyClient();
  1147. //
  1148. // leave g_CsClients while trying to send the notification
  1149. //
  1150. LeaveCriticalSection (&g_CsClients);
  1151. RpcTryExcept
  1152. {
  1153. //
  1154. // Get a context handle from the client
  1155. //
  1156. dwRes = FAX_OpenConnection( hFaxHandle, Context, &hFaxClientContext );
  1157. if (ERROR_SUCCESS != dwRes)
  1158. {
  1159. DumpRPCExtendedStatus();
  1160. DebugPrintEx(DEBUG_WRN,TEXT("First attempt of FAX_OpenConnection() failed, ec=0x%08x"), dwRes );
  1161. //
  1162. // We are trying again.
  1163. //
  1164. // This is why we shuld retry,
  1165. //
  1166. // When using secure channle we sometimes manage to establish a connection, but failing when we checke the state of the connection.
  1167. // This is usually indicative of old connections to the server which we just discovered were broken
  1168. //
  1169. // The server could have come down, but RPC still save the connection (for ~2 minutes).
  1170. // On secure channel the RPC can't retry the connection attemp, so we must try to connect again.
  1171. //
  1172. //
  1173. // Retry to open connection to fax client
  1174. //
  1175. dwRes = FAX_OpenConnection( hFaxHandle, Context, &hFaxClientContext );
  1176. if (ERROR_SUCCESS != dwRes)
  1177. {
  1178. DumpRPCExtendedStatus();
  1179. DebugPrintEx(DEBUG_WRN,TEXT("second attempt of FAX_OpenConnection() failed, ec=0x%08x"), dwRes );
  1180. //
  1181. // We are dropping the authenticate level to RPC_C_AUTHN_LEVEL_NONE trying again.
  1182. // We probably talking to a down-level client running on Windows 2000 RTM (SP1 and above are excluded) or earlier OS.
  1183. //
  1184. //
  1185. // We might get access denied while trying to connect to a remote fax server.
  1186. // This is probably the RPC infrastructure failing us.
  1187. // This only happens because we're using RPC_C_AUTHN_LEVEL_PKT_PRIVACY authentication level
  1188. // and the calling user is not trusted.
  1189. // This is usally happens when talking to Windows NT4 (all flavors) and Windows 2000 RTM (SP1 and above are excluded).
  1190. //
  1191. // We might get RPC_S_INVALID_AUTH_IDENTITY:
  1192. // This means the client cannot get credentials to authenticate.
  1193. // In this case, drop the RPC authentication level back to RPC_C_AUTHN_LEVEL_NONE
  1194. //
  1195. // We might get RPC_S_UNKNOWN_AUTHN_SERVICE:
  1196. // We probably dealing with Win9x or winMe OS.
  1197. // Drop the authenticate level to RPC_C_AUTHN_LEVEL_NONE when talking to this downlevel client
  1198. //
  1199. // Or we might get another error code and we should try to drop the auth level
  1200. //
  1201. // There is no security hole here - the down level clients that supports private channel will
  1202. // reject unsecured notifications
  1203. //
  1204. // Ask for no privacy.
  1205. //
  1206. RPC_SECURITY_QOS rpcSecurityQOS = { RPC_C_SECURITY_QOS_VERSION,
  1207. RPC_C_QOS_CAPABILITIES_DEFAULT,
  1208. RPC_C_QOS_IDENTITY_STATIC,
  1209. RPC_C_IMP_LEVEL_IDENTIFY // Server can obtain information about
  1210. // client security identifiers and privileges,
  1211. // but cannot impersonate the client.
  1212. };
  1213. dwRes = RpcBindingSetAuthInfoEx (
  1214. hFaxHandle, // RPC binding handle
  1215. TEXT(""), // Server principal name - ignored for RPC_C_AUTHN_WINNT
  1216. RPC_C_AUTHN_LEVEL_NONE, // Authentication level - NONE
  1217. // Authenticates, verifies, and privacy-encrypts the arguments passed
  1218. // to every remote call.
  1219. RPC_C_AUTHN_WINNT, // Authentication service (NTLMSSP)
  1220. NULL, // Authentication identity - use currently logged on user
  1221. 0, // Unused when Authentication service == RPC_C_AUTHN_WINNT
  1222. &rpcSecurityQOS); // Defines the security quality-of-service
  1223. if (RPC_S_OK != dwRes)
  1224. {
  1225. //
  1226. // Couldn't set RPC authentication mode
  1227. //
  1228. DebugPrintEx(
  1229. DEBUG_ERR,
  1230. TEXT("RpcBindingSetAuthInfoEx (RPC_C_AUTHN_LEVEL_NONE) failed. (ec: %lu)"),
  1231. dwRes);
  1232. }
  1233. else
  1234. {
  1235. dwRes = FAX_OpenConnection( hFaxHandle, Context, &hFaxClientContext );
  1236. if (ERROR_SUCCESS != dwRes)
  1237. {
  1238. DumpRPCExtendedStatus();
  1239. DebugPrintEx(DEBUG_ERR,TEXT("third attempt of FAX_OpenConnection() with RPC_C_AUTHN_LEVEL_NONE failed, ec=0x%08x"), dwRes );
  1240. }
  1241. }
  1242. }
  1243. }
  1244. }
  1245. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  1246. {
  1247. dwRes = GetExceptionCode();
  1248. DebugPrintEx(
  1249. DEBUG_ERR,
  1250. TEXT("FAX_OpenConnection failed (exception = %ld)"),
  1251. dwRes);
  1252. }
  1253. RpcEndExcept
  1254. if (ERROR_SUCCESS != dwRes)
  1255. {
  1256. DumpRPCExtendedStatus();
  1257. DebugPrintEx(
  1258. DEBUG_ERR,
  1259. TEXT("Failed to open connection with ec=0x%08x"),
  1260. dwRes);
  1261. goto exit;
  1262. }
  1263. //
  1264. // For legacy clients we need to send FEI_FAXSVC_STARTED
  1265. //
  1266. if (TRUE == fLegacyClient)
  1267. {
  1268. FAX_EVENT FaxEvent = {0};
  1269. DWORD ec;
  1270. FaxEvent.SizeOfStruct = sizeof(FAX_EVENT);
  1271. GetSystemTimeAsFileTime( &FaxEvent.TimeStamp );
  1272. FaxEvent.EventId = FEI_FAXSVC_STARTED;
  1273. FaxEvent.DeviceId = 0;
  1274. FaxEvent.JobId = 0xffffffff;
  1275. RpcTryExcept
  1276. {
  1277. //
  1278. // Send FEI_FAXSVC_STARTED to the client
  1279. //
  1280. ec = FAX_ClientEventQueue( hFaxClientContext, FaxEvent );
  1281. }
  1282. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  1283. {
  1284. ec = GetExceptionCode();
  1285. DebugPrintEx(
  1286. DEBUG_ERR,
  1287. TEXT("FAX_ClientEventQueue failed (exception = %ld)"),
  1288. ec);
  1289. }
  1290. RpcEndExcept
  1291. if (ERROR_SUCCESS != ec)
  1292. {
  1293. DumpRPCExtendedStatus ();
  1294. DebugPrintEx(
  1295. DEBUG_ERR,
  1296. TEXT("FAX_ClientEventQueue Failed with ec = %ld"),
  1297. ec);
  1298. }
  1299. }
  1300. //
  1301. // success - Set the context handle in the client object
  1302. //
  1303. EnterCriticalSection (&g_CsClients);
  1304. pClient->SetContextHandle(hFaxClientContext);
  1305. LeaveCriticalSection (&g_CsClients);
  1306. Assert (ERROR_SUCCESS == dwRes);
  1307. exit:
  1308. DWORD rVal = ReleaseClient(ClientID);
  1309. if (ERROR_SUCCESS != rVal)
  1310. {
  1311. DebugPrintEx(
  1312. DEBUG_ERR,
  1313. TEXT("CClientsMap::ReleaseClient Failed with ec = %ld"),
  1314. rVal);
  1315. }
  1316. return dwRes;
  1317. } // CClientsMap::OpenClientConnection
  1318. /************************************
  1319. * *
  1320. * Functions *
  1321. * *
  1322. ************************************/
  1323. DWORD
  1324. FaxSendEventThread(
  1325. LPVOID UnUsed
  1326. )
  1327. /*++
  1328. Routine Description:
  1329. This fuction runs asychronously as a separate thread to
  1330. query the send events completion port
  1331. Arguments:
  1332. UnUsed - UnUsed pointer
  1333. Return Value:
  1334. Always zero.
  1335. --*/
  1336. {
  1337. DWORD dwBytes;
  1338. ULONG_PTR CompletionKey;
  1339. DWORD dwRes;
  1340. CClientID* pClientID=NULL;
  1341. DEBUG_FUNCTION_NAME(TEXT("FaxSendEventThread"));
  1342. while( TRUE )
  1343. {
  1344. if (!GetQueuedCompletionStatus( g_hSendEventsCompPort,
  1345. &dwBytes,
  1346. &CompletionKey,
  1347. (LPOVERLAPPED*) &pClientID,
  1348. INFINITE
  1349. ))
  1350. {
  1351. DebugPrintEx(
  1352. DEBUG_ERR,
  1353. TEXT("GetQueuedCompletionStatus() failed, ec=0x%08x"),
  1354. GetLastError());
  1355. continue;
  1356. }
  1357. Assert (CLIENT_COMPLETION_KEY == CompletionKey ||
  1358. CLIENT_OPEN_CONN_COMPLETION_KEY == CompletionKey ||
  1359. SERVICE_SHUT_DOWN_KEY == CompletionKey);
  1360. //
  1361. // if service is going down skip the notification
  1362. //
  1363. if (CLIENT_COMPLETION_KEY == CompletionKey &&
  1364. FALSE == g_bServiceIsDown )
  1365. {
  1366. //
  1367. // Send notification to the client
  1368. //
  1369. dwRes = g_pClientsMap->Notify (*pClientID);
  1370. if (ERROR_SUCCESS != dwRes)
  1371. {
  1372. DebugPrintEx(
  1373. DEBUG_ERR,
  1374. TEXT("CClientsMap::Notify() failed, ec=0x%08x"),
  1375. dwRes);
  1376. }
  1377. delete pClientID;
  1378. pClientID = NULL;
  1379. continue;
  1380. }
  1381. else if (CLIENT_OPEN_CONN_COMPLETION_KEY == CompletionKey &&
  1382. FALSE == g_bServiceIsDown )
  1383. {
  1384. //
  1385. // Open connection to the client - Get context handle
  1386. //
  1387. dwRes = g_pClientsMap->OpenClientConnection (*pClientID);
  1388. if (ERROR_SUCCESS != dwRes)
  1389. {
  1390. DebugPrintEx(
  1391. DEBUG_ERR,
  1392. TEXT("CClientsMap::OpenClientConnection() failed, ec=0x%08x"),
  1393. dwRes);
  1394. //
  1395. // Remove this client fromm the map
  1396. //
  1397. dwRes = g_pClientsMap->ReleaseClient(*pClientID);
  1398. if (ERROR_SUCCESS != dwRes)
  1399. {
  1400. DebugPrintEx(
  1401. DEBUG_ERR,
  1402. TEXT("CClientsMap::ReleaseClient() failed, ec=0x%08x"),
  1403. dwRes);
  1404. }
  1405. }
  1406. delete pClientID;
  1407. pClientID = NULL;
  1408. continue;
  1409. }
  1410. else if (SERVICE_SHUT_DOWN_KEY == CompletionKey)
  1411. {
  1412. //
  1413. // Terminate events thread - Notify another event thread
  1414. //
  1415. if (!PostQueuedCompletionStatus(
  1416. g_hSendEventsCompPort,
  1417. 0,
  1418. SERVICE_SHUT_DOWN_KEY,
  1419. (LPOVERLAPPED) NULL))
  1420. {
  1421. dwRes = GetLastError();
  1422. DebugPrintEx(
  1423. DEBUG_ERR,
  1424. TEXT("PostQueuedCompletionStatus failed (SERVICE_SHUT_DOWN_KEY). (ec: %ld)"),
  1425. dwRes);
  1426. }
  1427. break;
  1428. }
  1429. else
  1430. {
  1431. //
  1432. // if service is going down skip the event adding
  1433. //
  1434. delete pClientID;
  1435. pClientID = NULL;
  1436. }
  1437. }
  1438. if (!DecreaseServiceThreadsCount())
  1439. {
  1440. DebugPrintEx(
  1441. DEBUG_ERR,
  1442. TEXT("DecreaseServiceThreadsCount() failed (ec: %ld)"),
  1443. GetLastError());
  1444. }
  1445. return ERROR_SUCCESS;
  1446. } // FaxSendEventThread
  1447. DWORD
  1448. FaxDispatchEventThread(
  1449. LPVOID UnUsed
  1450. )
  1451. /*++
  1452. Routine Description:
  1453. This fuction runs asychronously as a separate thread to
  1454. query the dispatch events completion port
  1455. Arguments:
  1456. UnUsed - UnUsed pointer
  1457. Return Value:
  1458. Always zero.
  1459. --*/
  1460. {
  1461. DWORD dwBytes;
  1462. ULONG_PTR CompletionKey;
  1463. DWORD dwRes;
  1464. CFaxEvent* pFaxEvent = NULL;
  1465. DEBUG_FUNCTION_NAME(TEXT("FaxDispatchEventThread"));
  1466. while( TRUE )
  1467. {
  1468. if (!GetQueuedCompletionStatus( g_hDispatchEventsCompPort,
  1469. &dwBytes,
  1470. &CompletionKey,
  1471. (LPOVERLAPPED*) &pFaxEvent,
  1472. INFINITE
  1473. ))
  1474. {
  1475. DebugPrintEx(
  1476. DEBUG_ERR,
  1477. TEXT("GetQueuedCompletionStatus() failed, ec=0x%08x"),
  1478. GetLastError());
  1479. continue;
  1480. }
  1481. Assert (EVENT_COMPLETION_KEY == CompletionKey ||
  1482. SERVICE_SHUT_DOWN_KEY == CompletionKey);
  1483. //
  1484. // if service is going down skip the notification
  1485. //
  1486. if (EVENT_COMPLETION_KEY == CompletionKey &&
  1487. FALSE == g_bServiceIsDown )
  1488. {
  1489. //
  1490. // Add event to the clients in the clients map
  1491. //
  1492. dwRes = g_pClientsMap->AddEvent(pFaxEvent);
  1493. if (ERROR_SUCCESS != dwRes)
  1494. {
  1495. DebugPrintEx(
  1496. DEBUG_ERR,
  1497. TEXT("GetQueuedCompletionStatus() failed, ec=0x%08x"),
  1498. dwRes);
  1499. }
  1500. delete pFaxEvent;
  1501. pFaxEvent = NULL;
  1502. continue;
  1503. }
  1504. else if (SERVICE_SHUT_DOWN_KEY == CompletionKey)
  1505. {
  1506. break;
  1507. }
  1508. else
  1509. {
  1510. //
  1511. // if service is going down skip the event adding
  1512. //
  1513. delete pFaxEvent;
  1514. pFaxEvent = NULL;
  1515. }
  1516. }
  1517. if (!DecreaseServiceThreadsCount())
  1518. {
  1519. DebugPrintEx(
  1520. DEBUG_ERR,
  1521. TEXT("DecreaseServiceThreadsCount() failed (ec: %ld)"),
  1522. GetLastError());
  1523. }
  1524. return ERROR_SUCCESS;
  1525. } // FaxDispatchEventThread
  1526. DWORD
  1527. InitializeServerEvents ()
  1528. /*++
  1529. Routine name : InitializeServerEvents
  1530. Routine description:
  1531. Creates the events completion ports and the Event Threads
  1532. Author:
  1533. Oded Sacher (OdedS), Jan, 2000
  1534. Arguments:
  1535. Return Value:
  1536. Standard Win32 error code
  1537. --*/
  1538. {
  1539. DWORD dwRes = ERROR_SUCCESS;
  1540. DEBUG_FUNCTION_NAME(TEXT("InitializeServerEvents"));
  1541. DWORD i;
  1542. DWORD ThreadId;
  1543. HANDLE hSendEventThreads[TOTAL_EVENTS_THREADS] = {0};
  1544. HANDLE hDispatchEventThread = NULL;
  1545. //
  1546. // create send event completion port.
  1547. //
  1548. g_hSendEventsCompPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE,
  1549. NULL,
  1550. 0,
  1551. MAX_EVENTS_THREADS
  1552. );
  1553. if (!g_hSendEventsCompPort)
  1554. {
  1555. dwRes = GetLastError();
  1556. DebugPrintEx(
  1557. DEBUG_ERR,
  1558. TEXT("Failed to create g_hSendEventsCompPort (ec: %ld)"),
  1559. dwRes);
  1560. return dwRes;
  1561. }
  1562. //
  1563. // create dispatch event completion port.
  1564. //
  1565. g_hDispatchEventsCompPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE,
  1566. NULL,
  1567. 0,
  1568. 1);
  1569. if (!g_hDispatchEventsCompPort)
  1570. {
  1571. dwRes = GetLastError();
  1572. DebugPrintEx(
  1573. DEBUG_ERR,
  1574. TEXT("Failed to create g_hDispatchEventsCompPort (ec: %ld)"),
  1575. dwRes);
  1576. return dwRes;
  1577. }
  1578. //
  1579. // Create FaxSendEventThread
  1580. //
  1581. for (i = 0; i < TOTAL_EVENTS_THREADS; i++)
  1582. {
  1583. hSendEventThreads[i] = CreateThreadAndRefCount(
  1584. NULL,
  1585. 0,
  1586. (LPTHREAD_START_ROUTINE) FaxSendEventThread,
  1587. NULL,
  1588. 0,
  1589. &ThreadId
  1590. );
  1591. if (!hSendEventThreads[i])
  1592. {
  1593. dwRes = GetLastError();
  1594. DebugPrintEx(
  1595. DEBUG_ERR,
  1596. TEXT("Failed to create send event thread %d (CreateThreadAndRefCount)(ec=0x%08x)."),
  1597. i,
  1598. dwRes);
  1599. goto exit;
  1600. }
  1601. }
  1602. //
  1603. // Create FaxDispatchEventThread
  1604. //
  1605. hDispatchEventThread = CreateThreadAndRefCount(
  1606. NULL,
  1607. 0,
  1608. (LPTHREAD_START_ROUTINE) FaxDispatchEventThread,
  1609. NULL,
  1610. 0,
  1611. &ThreadId
  1612. );
  1613. if (!hDispatchEventThread)
  1614. {
  1615. dwRes = GetLastError();
  1616. DebugPrintEx(
  1617. DEBUG_ERR,
  1618. TEXT("Failed to create dispatch event(CreateThreadAndRefCount)(ec=0x%08x)."),
  1619. dwRes);
  1620. goto exit;
  1621. }
  1622. Assert (ERROR_SUCCESS == dwRes);
  1623. exit:
  1624. //
  1625. // Close the thread handles we no longer need them
  1626. //
  1627. for (i = 0; i < TOTAL_EVENTS_THREADS; i++)
  1628. {
  1629. if (NULL != hSendEventThreads[i])
  1630. {
  1631. if (!CloseHandle(hSendEventThreads[i]))
  1632. {
  1633. DebugPrintEx(
  1634. DEBUG_ERR,
  1635. TEXT("Failed to close thread handle at index %ld [handle = 0x%08X] (ec=0x%08x)."),
  1636. i,
  1637. hSendEventThreads[i],
  1638. GetLastError());
  1639. }
  1640. }
  1641. }
  1642. if (NULL != hDispatchEventThread)
  1643. {
  1644. if (!CloseHandle(hDispatchEventThread))
  1645. {
  1646. DebugPrintEx(
  1647. DEBUG_ERR,
  1648. TEXT("Failed to close thread handle [handle = 0x%08X] (ec=0x%08x)."),
  1649. hDispatchEventThread,
  1650. GetLastError());
  1651. }
  1652. }
  1653. return dwRes;
  1654. } // InitializeServerEvents
  1655. DWORD
  1656. PostFaxEventEx (
  1657. PFAX_EVENT_EX pFaxEvent,
  1658. DWORD dwEventSize,
  1659. PSID pUserSid)
  1660. /*++
  1661. Routine name : PostFaxEventEx
  1662. Routine description:
  1663. Posts a CFaxEventExtended object to the events completion port.
  1664. FaxSendEventThread must call delete to deallocate the object.
  1665. Author:
  1666. Oded Sacher (OdedS), Jan, 2000
  1667. Arguments:
  1668. pFaxEvent [in] - Pointer to the serialized FAX_EVENT_EX buffer
  1669. dwEventSize [in] - The FAX_EVENT_EX buffer size
  1670. pUserSid [in] - The user sid to associate with the event
  1671. Return Value:
  1672. Standard Win32 error code
  1673. --*/
  1674. {
  1675. DEBUG_FUNCTION_NAME(TEXT("PostFaxEventEx"));
  1676. Assert (pFaxEvent && (dwEventSize >= sizeof(FAX_EVENT_EX)));
  1677. DWORD dwRes = ERROR_SUCCESS;
  1678. if (TRUE == g_bServiceIsDown)
  1679. {
  1680. //
  1681. // The service is going down, no need to post this Event
  1682. //
  1683. DebugPrintEx(
  1684. DEBUG_WRN,
  1685. TEXT("Service is going down, no need to post this Event.")
  1686. );
  1687. return ERROR_SERVICE_NOT_ACTIVE;
  1688. }
  1689. CFaxEventExtended* pExtendedEvent = NULL;
  1690. try
  1691. {
  1692. pExtendedEvent = new (std::nothrow) CFaxEventExtended(
  1693. pFaxEvent,
  1694. dwEventSize,
  1695. pUserSid);
  1696. }
  1697. catch (exception &ex)
  1698. {
  1699. DebugPrintEx(
  1700. DEBUG_ERR,
  1701. TEXT("CFaxEventExtended caused exception (%S)"),
  1702. ex.what());
  1703. }
  1704. if (NULL == pExtendedEvent)
  1705. {
  1706. DebugPrintEx(
  1707. DEBUG_ERR,
  1708. TEXT("Failed to allocate new CFaxEventExtended"));
  1709. return ERROR_OUTOFMEMORY;
  1710. }
  1711. //
  1712. // post the CFaxEventExtended object to the event completion port
  1713. //
  1714. if (!PostQueuedCompletionStatus( g_hDispatchEventsCompPort,
  1715. sizeof(CFaxEventExtended*),
  1716. EVENT_COMPLETION_KEY,
  1717. (LPOVERLAPPED) pExtendedEvent))
  1718. {
  1719. dwRes = GetLastError();
  1720. DebugPrintEx(
  1721. DEBUG_ERR,
  1722. TEXT("PostQueuedCompletionStatus failed. (ec: %ld)"),
  1723. dwRes);
  1724. goto exit;
  1725. }
  1726. Assert (ERROR_SUCCESS == dwRes);
  1727. exit:
  1728. if (ERROR_SUCCESS != dwRes)
  1729. {
  1730. delete pExtendedEvent;
  1731. }
  1732. return dwRes;
  1733. } // PostFaxEventEx
  1734. DWORD
  1735. CreateQueueEvent (
  1736. FAX_ENUM_JOB_EVENT_TYPE JobEventType,
  1737. const PJOB_QUEUE lpcJobQueue
  1738. )
  1739. /*++
  1740. Routine name : CreateQueueEvent
  1741. Routine description:
  1742. Creates FAX_EVENT_TYPE_*_QUEUE event.
  1743. Must be called inside critical section and g_CsQueue and if there is job status inside g_CsJob also.
  1744. Author:
  1745. Oded Sacher (OdedS), Jan, 2000
  1746. Arguments:
  1747. JobEventType [in] - Specifies the job event type FAX_ENUM_JOB_EVENT_TYPE
  1748. lpcJobQueue [in] - Pointer to the job queue entry
  1749. Return Value:
  1750. Standard Win32 error code
  1751. --*/
  1752. {
  1753. DEBUG_FUNCTION_NAME(TEXT("CreateQueueEvent"));
  1754. ULONG_PTR dwOffset = sizeof(FAX_EVENT_EX);
  1755. DWORD dwRes = ERROR_SUCCESS;
  1756. PFAX_EVENT_EXW pEvent = NULL;
  1757. FAX_ENUM_EVENT_TYPE EventType;
  1758. PSID pUserSid = NULL;
  1759. DWORDLONG dwlMessageId;
  1760. Assert (lpcJobQueue);
  1761. dwlMessageId = lpcJobQueue->UniqueId;
  1762. if (JT_SEND == lpcJobQueue->JobType)
  1763. {
  1764. // outbound job
  1765. Assert (lpcJobQueue->lpParentJob);
  1766. EventType = FAX_EVENT_TYPE_OUT_QUEUE;
  1767. pUserSid = lpcJobQueue->lpParentJob->UserSid;
  1768. }
  1769. else
  1770. {
  1771. // Inbound job
  1772. Assert (JT_RECEIVE == lpcJobQueue->JobType ||
  1773. JT_ROUTING == lpcJobQueue->JobType);
  1774. EventType = FAX_EVENT_TYPE_IN_QUEUE;
  1775. }
  1776. if (FAX_JOB_EVENT_TYPE_ADDED == JobEventType ||
  1777. FAX_JOB_EVENT_TYPE_REMOVED == JobEventType)
  1778. {
  1779. // No job status
  1780. pEvent = (PFAX_EVENT_EX)MemAlloc (dwOffset);
  1781. if (NULL == pEvent)
  1782. {
  1783. DebugPrintEx(
  1784. DEBUG_ERR,
  1785. TEXT("Error allocatin FAX_EVENT_EX"));
  1786. return ERROR_OUTOFMEMORY;
  1787. }
  1788. (pEvent->EventInfo).JobInfo.pJobData = NULL;
  1789. }
  1790. else
  1791. {
  1792. //
  1793. // Status change
  1794. //
  1795. Assert (FAX_JOB_EVENT_TYPE_STATUS == JobEventType);
  1796. //
  1797. // Get the needed buffer size to hold FAX_JOB_STATUSW serialized info
  1798. //
  1799. if (!GetJobStatusDataEx (NULL,
  1800. NULL,
  1801. FAX_API_VERSION_1, // Always pick full data
  1802. lpcJobQueue,
  1803. &dwOffset,
  1804. 0))
  1805. {
  1806. dwRes = GetLastError();
  1807. DebugPrintEx(
  1808. DEBUG_ERR,
  1809. TEXT("GetJobStatusDataEx failed (ec: %ld)"),
  1810. dwRes);
  1811. return dwRes;
  1812. }
  1813. //
  1814. // Allocate the buffer
  1815. //
  1816. DWORD dwEventSize = dwOffset;
  1817. pEvent = (PFAX_EVENT_EXW)MemAlloc (dwEventSize);
  1818. if (NULL == pEvent)
  1819. {
  1820. DebugPrintEx(
  1821. DEBUG_ERR,
  1822. TEXT("Error allocatin FAX_EVENT_EX"));
  1823. return ERROR_OUTOFMEMORY;
  1824. }
  1825. //
  1826. // Fill the buffer
  1827. //
  1828. dwOffset = sizeof(FAX_EVENT_EXW);
  1829. (pEvent->EventInfo).JobInfo.pJobData = (PFAX_JOB_STATUSW)dwOffset;
  1830. PFAX_JOB_STATUSW pFaxStatus = (PFAX_JOB_STATUSW) ((LPBYTE)pEvent + (ULONG_PTR)dwOffset);
  1831. dwOffset += sizeof(FAX_JOB_STATUSW);
  1832. if (!GetJobStatusDataEx ((LPBYTE)pEvent,
  1833. pFaxStatus,
  1834. FAX_API_VERSION_1, // Always pick full data
  1835. lpcJobQueue,
  1836. &dwOffset,
  1837. dwEventSize
  1838. ))
  1839. {
  1840. dwRes = GetLastError();
  1841. DebugPrintEx(
  1842. DEBUG_ERR,
  1843. TEXT("GetJobStatusDataEx failed (ec: %ld)"),
  1844. dwRes);
  1845. goto exit;
  1846. }
  1847. }
  1848. pEvent->dwSizeOfStruct = sizeof(FAX_EVENT_EXW);
  1849. GetSystemTimeAsFileTime( &(pEvent->TimeStamp) );
  1850. pEvent->EventType = EventType;
  1851. (pEvent->EventInfo).JobInfo.dwlMessageId = dwlMessageId;
  1852. (pEvent->EventInfo).JobInfo.Type = JobEventType;
  1853. dwRes = PostFaxEventEx (pEvent, dwOffset, pUserSid);
  1854. if (ERROR_SUCCESS != dwRes)
  1855. {
  1856. DebugPrintEx(
  1857. DEBUG_ERR,
  1858. TEXT("PostFaxEventEx failed (ec: %ld)"),
  1859. dwRes);
  1860. goto exit;
  1861. }
  1862. Assert (ERROR_SUCCESS == dwRes);
  1863. exit:
  1864. MemFree (pEvent);
  1865. return dwRes;
  1866. } // CreateQueueEvent
  1867. DWORD
  1868. CreateConfigEvent (
  1869. FAX_ENUM_CONFIG_TYPE ConfigType
  1870. )
  1871. /*++
  1872. Routine name : CreateConfigEvent
  1873. Routine description:
  1874. Creates FAX_EVENT_TYPE_CONFIG event.
  1875. Author:
  1876. Oded Sacher (OdedS), Jan, 2000
  1877. Arguments:
  1878. ConfigType [in ] - The configuration event type FAX_ENUM_CONFIG_TYPE
  1879. Return Value:
  1880. Standard Win32 error code
  1881. --*/
  1882. {
  1883. DEBUG_FUNCTION_NAME(TEXT("CreateConfigEvent"));
  1884. PFAX_EVENT_EX pEvent = NULL;
  1885. DWORD dwRes = ERROR_SUCCESS;
  1886. DWORD dwEventSize = sizeof(FAX_EVENT_EX);
  1887. pEvent = (PFAX_EVENT_EX)MemAlloc (dwEventSize);
  1888. if (NULL == pEvent)
  1889. {
  1890. DebugPrintEx(
  1891. DEBUG_ERR,
  1892. TEXT("Error allocatin FAX_EVENT_EX"));
  1893. return ERROR_OUTOFMEMORY;
  1894. }
  1895. pEvent->dwSizeOfStruct = sizeof(FAX_EVENT_EX);
  1896. GetSystemTimeAsFileTime( &(pEvent->TimeStamp) );
  1897. pEvent->EventType = FAX_EVENT_TYPE_CONFIG;
  1898. (pEvent->EventInfo).ConfigType = ConfigType;
  1899. dwRes = PostFaxEventEx (pEvent, dwEventSize, NULL);
  1900. if (ERROR_SUCCESS != dwRes)
  1901. {
  1902. DebugPrintEx(
  1903. DEBUG_ERR,
  1904. TEXT("PostFaxEventEx failed (ec: %ld)"),
  1905. dwRes);
  1906. goto exit;
  1907. }
  1908. Assert (ERROR_SUCCESS == dwRes);
  1909. exit:
  1910. MemFree (pEvent);
  1911. return dwRes;
  1912. } // CreateConfigEvent
  1913. DWORD
  1914. CreateQueueStateEvent (
  1915. DWORD dwQueueState
  1916. )
  1917. /*++
  1918. Routine name : CreateQueueStateEvent
  1919. Routine description:
  1920. Creates FAX_EVENT_TYPE_QUEUE_STATE event.
  1921. Author:
  1922. Oded Sacher (OdedS), Jan, 2000
  1923. Arguments:
  1924. dwQueueState [in ] - The new queue state
  1925. Return Value:
  1926. Standard Win32 error code
  1927. --*/
  1928. {
  1929. DEBUG_FUNCTION_NAME(TEXT("CreateQueueStateEvent"));
  1930. DWORD dwRes = ERROR_SUCCESS;
  1931. DWORD dwEventSize = sizeof(FAX_EVENT_EX);
  1932. PFAX_EVENT_EX pEvent = NULL;
  1933. Assert ( (dwQueueState == 0) ||
  1934. (dwQueueState & FAX_INCOMING_BLOCKED) ||
  1935. (dwQueueState & FAX_OUTBOX_BLOCKED) ||
  1936. (dwQueueState & FAX_OUTBOX_PAUSED) );
  1937. pEvent = (PFAX_EVENT_EX)MemAlloc (dwEventSize);
  1938. if (NULL == pEvent)
  1939. {
  1940. DebugPrintEx(
  1941. DEBUG_ERR,
  1942. TEXT("Error allocatin FAX_EVENT_EX"));
  1943. return ERROR_OUTOFMEMORY;
  1944. }
  1945. pEvent->dwSizeOfStruct = sizeof(FAX_EVENT_EX);
  1946. GetSystemTimeAsFileTime( &(pEvent->TimeStamp) );
  1947. pEvent->EventType = FAX_EVENT_TYPE_QUEUE_STATE;
  1948. (pEvent->EventInfo).dwQueueStates = dwQueueState;
  1949. dwRes = PostFaxEventEx (pEvent, dwEventSize, NULL);
  1950. if (ERROR_SUCCESS != dwRes)
  1951. {
  1952. DebugPrintEx(
  1953. DEBUG_ERR,
  1954. TEXT("PostFaxEventEx failed (ec: %ld)"),
  1955. dwRes);
  1956. goto exit;
  1957. }
  1958. Assert (ERROR_SUCCESS == dwRes);
  1959. exit:
  1960. MemFree (pEvent);
  1961. return dwRes;
  1962. } // CreateQueueStateEvent
  1963. DWORD
  1964. CreateDeviceEvent (
  1965. PLINE_INFO pLine,
  1966. BOOL bRinging
  1967. )
  1968. /*++
  1969. Routine name : CreateDeviceEvent
  1970. Routine description:
  1971. Creates FAX_EVENT_TYPE_DEVICE_STATUS event.
  1972. Author:
  1973. Eran Yariv (EranY), July, 2000
  1974. Arguments:
  1975. pLine [in] - Device
  1976. bRinging [in] - Is the device ringing now?
  1977. Return Value:
  1978. Standard Win32 error code
  1979. --*/
  1980. {
  1981. DEBUG_FUNCTION_NAME(TEXT("CreateDeviceEvent"));
  1982. DWORD dwRes = ERROR_SUCCESS;
  1983. DWORD dwEventSize = sizeof(FAX_EVENT_EX);
  1984. PFAX_EVENT_EX pEvent = NULL;
  1985. pEvent = (PFAX_EVENT_EX)MemAlloc (dwEventSize);
  1986. if (NULL == pEvent)
  1987. {
  1988. DebugPrintEx(
  1989. DEBUG_ERR,
  1990. TEXT("Error allocatin FAX_EVENT_EX"));
  1991. return ERROR_OUTOFMEMORY;
  1992. }
  1993. pEvent->dwSizeOfStruct = sizeof(FAX_EVENT_EX);
  1994. GetSystemTimeAsFileTime( &(pEvent->TimeStamp) );
  1995. pEvent->EventType = FAX_EVENT_TYPE_DEVICE_STATUS;
  1996. EnterCriticalSection (&g_CsLine);
  1997. (pEvent->EventInfo).DeviceStatus.dwDeviceId = pLine->PermanentLineID;;
  1998. (pEvent->EventInfo).DeviceStatus.dwNewStatus =
  1999. (pLine->dwReceivingJobsCount ? FAX_DEVICE_STATUS_RECEIVING : 0) |
  2000. (pLine->dwSendingJobsCount ? FAX_DEVICE_STATUS_SENDING : 0) |
  2001. (bRinging ? FAX_DEVICE_STATUS_RINGING : 0);
  2002. LeaveCriticalSection (&g_CsLine);
  2003. dwRes = PostFaxEventEx (pEvent, dwEventSize, NULL);
  2004. if (ERROR_SUCCESS != dwRes)
  2005. {
  2006. DebugPrintEx(
  2007. DEBUG_ERR,
  2008. TEXT("PostFaxEventEx failed (ec: %ld)"),
  2009. dwRes);
  2010. goto exit;
  2011. }
  2012. Assert (ERROR_SUCCESS == dwRes);
  2013. exit:
  2014. MemFree (pEvent);
  2015. return dwRes;
  2016. } // CreateDeviceEvent
  2017. DWORD
  2018. CreateArchiveEvent (
  2019. DWORDLONG dwlMessageId,
  2020. FAX_ENUM_EVENT_TYPE EventType,
  2021. FAX_ENUM_JOB_EVENT_TYPE MessageEventType,
  2022. PSID pUserSid
  2023. )
  2024. /*++
  2025. Routine name : CreateArchiveEvent
  2026. Routine description:
  2027. Creates archive event.
  2028. Author:
  2029. Oded Sacher (OdedS), Jan, 2000
  2030. Arguments:
  2031. dwlMessageId [in] - The message unique id
  2032. EventType [in] - Specifies the event type (In or Out archive)
  2033. pUserSid [in] - The user sid to associate with the event
  2034. MessageEventType [in] - Message event type (added or removed).
  2035. Return Value:
  2036. Standard Win32 error code
  2037. --*/
  2038. {
  2039. DEBUG_FUNCTION_NAME(TEXT("CreateArchiveEvent"));
  2040. DWORD dwRes = ERROR_SUCCESS;
  2041. DWORD dwEventSize = sizeof(FAX_EVENT_EX);
  2042. PFAX_EVENT_EX pEvent = NULL;
  2043. Assert ( EventType == FAX_EVENT_TYPE_IN_ARCHIVE ||
  2044. EventType == FAX_EVENT_TYPE_OUT_ARCHIVE);
  2045. Assert ( MessageEventType == FAX_JOB_EVENT_TYPE_ADDED ||
  2046. MessageEventType == FAX_JOB_EVENT_TYPE_REMOVED );
  2047. pEvent = (PFAX_EVENT_EX)MemAlloc (dwEventSize);
  2048. if (NULL == pEvent)
  2049. {
  2050. DebugPrintEx(
  2051. DEBUG_ERR,
  2052. TEXT("Error allocatin FAX_EVENT_EX"));
  2053. return ERROR_OUTOFMEMORY;
  2054. }
  2055. pEvent->dwSizeOfStruct = sizeof(FAX_EVENT_EX);
  2056. GetSystemTimeAsFileTime( &(pEvent->TimeStamp) );
  2057. pEvent->EventType = EventType;
  2058. (pEvent->EventInfo).JobInfo.pJobData = NULL;
  2059. (pEvent->EventInfo).JobInfo.dwlMessageId = dwlMessageId;
  2060. (pEvent->EventInfo).JobInfo.Type = MessageEventType;
  2061. dwRes = PostFaxEventEx (pEvent, dwEventSize, pUserSid);
  2062. if (ERROR_SUCCESS != dwRes)
  2063. {
  2064. DebugPrintEx(
  2065. DEBUG_ERR,
  2066. TEXT("PostFaxEventEx failed (ec: %ld)"),
  2067. dwRes);
  2068. goto exit;
  2069. }
  2070. Assert (ERROR_SUCCESS == dwRes);
  2071. exit:
  2072. MemFree (pEvent);
  2073. return dwRes;
  2074. } // CreateArchiveEvent
  2075. DWORD
  2076. CreateActivityEvent ()
  2077. /*++
  2078. Routine name : CreateActivityEvent
  2079. Routine description:
  2080. Creates FAX_EVENT_TYPE_ACTIVITY event.
  2081. Must be called inside critical section g_CsActivity
  2082. Author:
  2083. Oded Sacher (OdedS), Jan, 2000
  2084. Arguments:
  2085. None
  2086. Return Value:
  2087. Standard Win32 error code
  2088. --*/
  2089. {
  2090. DEBUG_FUNCTION_NAME(TEXT("CreateActivityEvent"));
  2091. DWORD dwRes = ERROR_SUCCESS;
  2092. DWORD dwEventSize = sizeof(FAX_EVENT_EX);
  2093. PFAX_EVENT_EX pEvent = NULL;
  2094. pEvent = (PFAX_EVENT_EX)MemAlloc (dwEventSize);
  2095. if (NULL == pEvent)
  2096. {
  2097. DebugPrintEx(
  2098. DEBUG_ERR,
  2099. TEXT("Error allocatin FAX_EVENT_EX"));
  2100. return ERROR_OUTOFMEMORY;
  2101. }
  2102. pEvent->dwSizeOfStruct = sizeof(FAX_EVENT_EX);
  2103. GetSystemTimeAsFileTime( &(pEvent->TimeStamp) );
  2104. pEvent->EventType = FAX_EVENT_TYPE_ACTIVITY;
  2105. CopyMemory (&((pEvent->EventInfo).ActivityInfo), &g_ServerActivity, sizeof(FAX_SERVER_ACTIVITY));
  2106. GetEventsCounters ( &((pEvent->EventInfo).ActivityInfo.dwErrorEvents),
  2107. &((pEvent->EventInfo).ActivityInfo.dwWarningEvents),
  2108. &((pEvent->EventInfo).ActivityInfo.dwInformationEvents));
  2109. dwRes = PostFaxEventEx (pEvent, dwEventSize, NULL);
  2110. if (ERROR_SUCCESS != dwRes)
  2111. {
  2112. DebugPrintEx(
  2113. DEBUG_ERR,
  2114. TEXT("PostFaxEventEx failed (ec: %ld)"),
  2115. dwRes);
  2116. goto exit;
  2117. }
  2118. Assert (ERROR_SUCCESS == dwRes);
  2119. exit:
  2120. MemFree (pEvent);
  2121. return dwRes;
  2122. } // CreateActivityEvent
  2123. #ifdef DBG
  2124. LPWSTR lpszEventCodes[]= {
  2125. L"FEI_DIALING",
  2126. L"FEI_SENDING",
  2127. L"FEI_RECEIVING",
  2128. L"FEI_COMPLETED",
  2129. L"FEI_BUSY",
  2130. L"FEI_NO_ANSWER",
  2131. L"FEI_BAD_ADDRESS",
  2132. L"FEI_NO_DIAL_TONE",
  2133. L"FEI_DISCONNECTED",
  2134. L"FEI_FATAL_ERROR",
  2135. L"FEI_NOT_FAX_CALL",
  2136. L"FEI_CALL_DELAYED",
  2137. L"FEI_CALL_BLACKLISTED",
  2138. L"FEI_RINGING",
  2139. L"FEI_ABORTING",
  2140. L"FEI_ROUTING",
  2141. L"FEI_MODEM_POWERED_ON",
  2142. L"FEI_MODEM_POWERED_OFF",
  2143. L"FEI_IDLE",
  2144. L"FEI_FAXSVC_ENDED",
  2145. L"FEI_ANSWERED",
  2146. L"FEI_JOB_QUEUED",
  2147. L"FEI_DELETED",
  2148. L"FEI_INITIALIZING",
  2149. L"FEI_LINE_UNAVAILABLE",
  2150. L"FEI_HANDLED",
  2151. L"FEI_FAXSVC_STARTED"};
  2152. LPTSTR GetEventCodeString(DWORD dwEventCode)
  2153. {
  2154. if (dwEventCode<FEI_DIALING || dwEventCode>FEI_FAXSVC_STARTED)
  2155. {
  2156. return L"*** INVALID EVENT CODE ***";
  2157. }
  2158. else
  2159. {
  2160. return lpszEventCodes[dwEventCode-1];
  2161. }
  2162. }
  2163. #endif
  2164. //*********************************************************************************
  2165. //* Name: CreateFaxEvent()
  2166. //* Author: Ronen Barenboim
  2167. //* Date: March 21, 1999
  2168. //*********************************************************************************
  2169. //* DESCRIPTION:
  2170. //* Creates a CFaxEventLegacy object. Initializes it and posts it to the
  2171. //* events completion port with completion key EVENT_COMPLETION_KEY.
  2172. //* FaxDispatchEventThread should call delete to deallocate the object.
  2173. //* PARAMETERS:
  2174. //* DeviceId
  2175. //*
  2176. //* EventId
  2177. //*
  2178. //* DWORD JobId
  2179. //*
  2180. //* RETURN VALUE:
  2181. //* FALSE
  2182. //* If not enough memory is available to allocated the FAX_EVENT structure
  2183. //* TRUE
  2184. //* If the operation completed successfully
  2185. //*
  2186. //* To get extended error information, call GetLastError .
  2187. //*
  2188. //* REMARKS:
  2189. //*
  2190. //*********************************************************************************
  2191. BOOL CreateFaxEvent(
  2192. DWORD DeviceId,
  2193. DWORD EventId,
  2194. DWORD JobId
  2195. )
  2196. {
  2197. CFaxEventLegacy* pFaxLegacyEvent = NULL;
  2198. FAX_EVENT FaxEvent = {0};
  2199. DEBUG_FUNCTION_NAME(TEXT("CreateFaxEvent"));
  2200. if (TRUE == g_bServiceIsDown)
  2201. {
  2202. //
  2203. // The service is going down, no need to post this Event
  2204. //
  2205. DebugPrintEx(
  2206. DEBUG_WRN,
  2207. TEXT("Service is going down, no need to post this Event.")
  2208. );
  2209. return FALSE;
  2210. }
  2211. if (NULL == g_hDispatchEventsCompPort)
  2212. {
  2213. //
  2214. // Events mechanism is not yet initialized
  2215. //
  2216. DebugPrintEx(
  2217. DEBUG_WRN,
  2218. TEXT("Events mechanism is not yet initialized"));
  2219. return TRUE;
  2220. }
  2221. //
  2222. // Note: W2K Fax did issue notifications with EventId == 0 whenever an
  2223. // FSP reported proprietry status code. To keep backward compatability
  2224. // we keep up this behaviour although it might be regarded as a bug
  2225. //
  2226. FaxEvent.SizeOfStruct = sizeof(FAX_EVENT);
  2227. GetSystemTimeAsFileTime( &FaxEvent.TimeStamp );
  2228. FaxEvent.EventId = EventId;
  2229. FaxEvent.DeviceId = DeviceId;
  2230. FaxEvent.JobId = JobId;
  2231. #if DBG
  2232. WCHAR szTime[256] = {0};
  2233. DebugDateTime(*(DWORDLONG *)&FaxEvent.TimeStamp, szTime, ARR_SIZE(szTime));
  2234. DebugPrintEx(DEBUG_MSG,TEXT("Sending notification. Event = %s(0x%0X), Device Id = 0x%0X , Time = %s"), GetEventCodeString(EventId), EventId, DeviceId, szTime);
  2235. #endif
  2236. try
  2237. {
  2238. pFaxLegacyEvent = new (std::nothrow) CFaxEventLegacy(&FaxEvent);
  2239. }
  2240. catch (exception &ex)
  2241. {
  2242. DebugPrintEx(
  2243. DEBUG_ERR,
  2244. TEXT("CFaxEventLegacy caused exception (%S)"),
  2245. ex.what());
  2246. }
  2247. if (NULL == pFaxLegacyEvent)
  2248. {
  2249. DebugPrintEx(
  2250. DEBUG_ERR,
  2251. TEXT("Failed to allocate new pFaxLegacyEvent"));
  2252. return FALSE;
  2253. }
  2254. if (!PostQueuedCompletionStatus(
  2255. g_hDispatchEventsCompPort,
  2256. sizeof(CFaxEventLegacy*),
  2257. EVENT_COMPLETION_KEY,
  2258. (LPOVERLAPPED) pFaxLegacyEvent))
  2259. {
  2260. DebugPrintEx(
  2261. DEBUG_ERR,
  2262. TEXT("PostQueuedCompletionStatus failed. (ec: %ld)"),
  2263. GetLastError());
  2264. delete pFaxLegacyEvent;
  2265. return FALSE;
  2266. }
  2267. return TRUE;
  2268. }