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.

2400 lines
55 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. FaxServer.cpp
  5. Abstract:
  6. Implementation of CFaxServer
  7. Author:
  8. Iv Garber (IvG) Apr, 2000
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "FaxComEx.h"
  13. #include "FaxServer.h"
  14. #include "FaxDevices.h"
  15. #include "FaxDeviceProviders.h"
  16. #include <new>
  17. //
  18. //================== GET API VERSION ==============================
  19. //
  20. STDMETHODIMP
  21. CFaxServer::get_APIVersion(
  22. /*[out, retval]*/ FAX_SERVER_APIVERSION_ENUM *pAPIVersion
  23. )
  24. /*++
  25. Routine name : CFaxServer::get_APIVersion
  26. Routine description:
  27. Return API Version of the Fax Server.
  28. Author:
  29. Iv Garber (IvG), May, 2001
  30. Arguments:
  31. pAPIVersion [out] - ptr to the place to put the API Version of the Fax Server
  32. Return Value:
  33. Standard HRESULT code
  34. --*/
  35. {
  36. HRESULT hr = S_OK;
  37. DBG_ENTER(_T("CFaxServer::get_APIVersion"), hr);
  38. if (!m_bVersionValid)
  39. {
  40. //
  41. // get Version of the Server
  42. //
  43. hr = GetVersion();
  44. if (FAILED(hr))
  45. {
  46. return hr;
  47. }
  48. }
  49. //
  50. // Check the pointer we have got
  51. //
  52. if (::IsBadWritePtr(pAPIVersion, sizeof(FAX_SERVER_APIVERSION_ENUM)))
  53. {
  54. //
  55. // Got a bad return pointer
  56. //
  57. hr = E_POINTER;
  58. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  59. CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr()"), hr);
  60. return hr;
  61. }
  62. *pAPIVersion = m_APIVersion;
  63. return hr;
  64. }
  65. //
  66. //====================== CLEAR NOTIFY WINDOW ============================
  67. //
  68. void
  69. CFaxServer::ClearNotifyWindow(void)
  70. /*++
  71. Routine name : CFaxServer::ClearNotifyWindow
  72. Routine description:
  73. Clear Notify Window.
  74. Author:
  75. Iv Garber (IvG), Jul, 2000
  76. Arguments:
  77. None.
  78. Return Value:
  79. None.
  80. --*/
  81. {
  82. if (m_pNotifyWindow && ::IsWindow(m_pNotifyWindow->m_hWnd))
  83. {
  84. m_pNotifyWindow->DestroyWindow();
  85. }
  86. if (m_pNotifyWindow)
  87. {
  88. delete m_pNotifyWindow;
  89. m_pNotifyWindow = NULL;
  90. }
  91. return;
  92. }
  93. //
  94. //====================== PROCESS JOB NOTIFICATION =======================
  95. //
  96. HRESULT
  97. CFaxServer::ProcessJobNotification(
  98. /*[in]*/ DWORDLONG dwlJobId,
  99. /*[in]*/ FAX_ENUM_JOB_EVENT_TYPE eventType,
  100. /*[in]*/ LOCATION place,
  101. /*[in]*/ FAX_JOB_STATUS *pJobStatus
  102. )
  103. /*++
  104. Routine name : CFaxServer::ProcessJobNotification
  105. Routine description:
  106. Call appropriate Fire Method, for Jobs/Messages in Queues/Archives.
  107. Author:
  108. Iv Garber (IvG), Jul, 2000
  109. Arguments:
  110. dwlJobId [in] - Id of the Job/Message
  111. eventType [in] - Type of the Event
  112. place [in] - Where the Job/Message sits
  113. pJobStatus [in] - FAX_JOB_STATUS structure
  114. Return Value:
  115. Standard HRESULT value.
  116. --*/
  117. {
  118. HRESULT hr = S_OK;
  119. DBG_ENTER(_T("CFaxServer::ProcessJobNotification"),
  120. hr,
  121. _T("JOBID=%ld EVENTTYPE=%ld PLACE=%d"),
  122. dwlJobId,
  123. eventType,
  124. place);
  125. //
  126. // Convert JobId from DWORDLONG into BSTR
  127. //
  128. CComBSTR bstrJobId;
  129. hr = GetBstrFromDwordlong(dwlJobId, &bstrJobId);
  130. if (FAILED(hr))
  131. {
  132. CALL_FAIL(GENERAL_ERR, _T("GetBstrFromDwordlong(dwlJobId, &bstrJobId)"), hr);
  133. return hr;
  134. }
  135. //
  136. // Check Type of the Event that happened
  137. //
  138. switch (eventType)
  139. {
  140. case FAX_JOB_EVENT_TYPE_ADDED:
  141. switch (place)
  142. {
  143. case IN_QUEUE:
  144. hr = Fire_OnIncomingJobAdded(this, bstrJobId);
  145. break;
  146. case OUT_QUEUE:
  147. hr = Fire_OnOutgoingJobAdded(this, bstrJobId);
  148. break;
  149. case IN_ARCHIVE:
  150. hr = Fire_OnIncomingMessageAdded(this, bstrJobId);
  151. break;
  152. case OUT_ARCHIVE:
  153. hr = Fire_OnOutgoingMessageAdded(this, bstrJobId);
  154. break;
  155. default:
  156. //
  157. // assert (FALSE)
  158. //
  159. ATLASSERT(place == IN_QUEUE);
  160. hr = E_FAIL;
  161. return hr;
  162. }
  163. if (FAILED(hr))
  164. {
  165. CALL_FAIL(GENERAL_ERR, _T("Fire_On In/Out Job/Message Added(this, bstrJobId)"), hr);
  166. return hr;
  167. }
  168. break;
  169. case FAX_JOB_EVENT_TYPE_REMOVED:
  170. switch (place)
  171. {
  172. case IN_QUEUE:
  173. hr = Fire_OnIncomingJobRemoved(this, bstrJobId);
  174. break;
  175. case OUT_QUEUE:
  176. hr = Fire_OnOutgoingJobRemoved(this, bstrJobId);
  177. break;
  178. case IN_ARCHIVE:
  179. hr = Fire_OnIncomingMessageRemoved(this, bstrJobId);
  180. break;
  181. case OUT_ARCHIVE:
  182. hr = Fire_OnOutgoingMessageRemoved(this, bstrJobId);
  183. break;
  184. default:
  185. //
  186. // assert (FALSE)
  187. //
  188. ATLASSERT(place == IN_QUEUE);
  189. hr = E_FAIL;
  190. return hr;
  191. }
  192. if (FAILED(hr))
  193. {
  194. CALL_FAIL(GENERAL_ERR, _T("Fire_On In/Out Job/Message Removed(this, bstrJobId)"), hr);
  195. return hr;
  196. }
  197. break;
  198. case FAX_JOB_EVENT_TYPE_STATUS:
  199. {
  200. if (!pJobStatus)
  201. {
  202. ATLASSERT(pJobStatus);
  203. hr = E_FAIL;
  204. return hr;
  205. }
  206. //
  207. // Create Job Status Object to pass to the Events
  208. //
  209. CComObject<CFaxJobStatus> *pJobStatusClass = NULL;
  210. pJobStatusClass = new (std::nothrow) CComObject<CFaxJobStatus>;
  211. if (!pJobStatusClass)
  212. {
  213. //
  214. // Out of Memory
  215. //
  216. CALL_FAIL(MEM_ERR, _T("new CComObject<CFaxJobStatus>"), hr);
  217. return hr;
  218. }
  219. //
  220. // Init the Object
  221. //
  222. hr = pJobStatusClass->Init(pJobStatus);
  223. if (FAILED(hr))
  224. {
  225. CALL_FAIL(GENERAL_ERR, _T("pJobStatusClass->Init(pJobStatus)"), hr);
  226. delete pJobStatusClass;
  227. return hr;
  228. }
  229. //
  230. // Query the Interface from the Object
  231. //
  232. CComPtr<IFaxJobStatus> pFaxJobStatus = NULL;
  233. hr = pJobStatusClass->QueryInterface(IID_IFaxJobStatus, (void **) &pFaxJobStatus);
  234. if (FAILED(hr) || !pFaxJobStatus)
  235. {
  236. CALL_FAIL(GENERAL_ERR, _T("pJobStatusClass->QueryInterface(pFaxJobStatus)"), hr);
  237. delete pJobStatusClass;
  238. return hr;
  239. }
  240. switch (place)
  241. {
  242. case IN_QUEUE:
  243. hr = Fire_OnIncomingJobChanged(this, bstrJobId, pFaxJobStatus);
  244. break;
  245. case OUT_QUEUE:
  246. hr = Fire_OnOutgoingJobChanged(this, bstrJobId, pFaxJobStatus);
  247. break;
  248. default:
  249. //
  250. // assert (FALSE)
  251. //
  252. ATLASSERT(place == IN_QUEUE);
  253. hr = E_FAIL;
  254. return hr;
  255. }
  256. if (FAILED(hr))
  257. {
  258. CALL_FAIL(GENERAL_ERR, _T("Fire_On In/Out JobChanged(this, bstrJobId)"), hr);
  259. return hr;
  260. }
  261. }
  262. break;
  263. default:
  264. //
  265. // assert (FALSE)
  266. //
  267. ATLASSERT(eventType == FAX_JOB_EVENT_TYPE_STATUS);
  268. hr = E_FAIL;
  269. return hr;
  270. }
  271. return hr;
  272. }
  273. //
  274. //================= PROCESS MESSAGE ============================================
  275. //
  276. HRESULT
  277. CFaxServer::ProcessMessage(
  278. FAX_EVENT_EX *pFaxEventInfo
  279. )
  280. /*++
  281. Routine name : CFaxServer::ProcessMessage
  282. Routine description:
  283. Fire appropriate Message
  284. Author:
  285. Iv Garber (IvG), Jul, 2000
  286. Arguments:
  287. pFaxEventInfo [TBD] - Information about current Event
  288. Return Value:
  289. None.
  290. --*/
  291. {
  292. HRESULT hr = S_OK;
  293. DBG_ENTER(_T("CFaxServer::ProcessMessage"), hr);
  294. if (!m_faxHandle)
  295. {
  296. //
  297. // Fax Server already disconnected
  298. //
  299. VERBOSE(DBG_WARNING, _T("FaxServer already disconnected."));
  300. return hr;
  301. }
  302. switch (pFaxEventInfo->EventType)
  303. {
  304. case FAX_EVENT_TYPE_IN_QUEUE:
  305. ProcessJobNotification(pFaxEventInfo->EventInfo.JobInfo.dwlMessageId,
  306. pFaxEventInfo->EventInfo.JobInfo.Type,
  307. IN_QUEUE,
  308. pFaxEventInfo->EventInfo.JobInfo.pJobData);
  309. break;
  310. case FAX_EVENT_TYPE_OUT_QUEUE:
  311. ProcessJobNotification(pFaxEventInfo->EventInfo.JobInfo.dwlMessageId,
  312. pFaxEventInfo->EventInfo.JobInfo.Type,
  313. OUT_QUEUE,
  314. pFaxEventInfo->EventInfo.JobInfo.pJobData);
  315. break;
  316. case FAX_EVENT_TYPE_IN_ARCHIVE:
  317. ProcessJobNotification(pFaxEventInfo->EventInfo.JobInfo.dwlMessageId,
  318. pFaxEventInfo->EventInfo.JobInfo.Type,
  319. IN_ARCHIVE);
  320. break;
  321. case FAX_EVENT_TYPE_OUT_ARCHIVE:
  322. ProcessJobNotification(pFaxEventInfo->EventInfo.JobInfo.dwlMessageId,
  323. pFaxEventInfo->EventInfo.JobInfo.Type,
  324. OUT_ARCHIVE);
  325. break;
  326. case FAX_EVENT_TYPE_CONFIG:
  327. switch (pFaxEventInfo->EventInfo.ConfigType)
  328. {
  329. case FAX_CONFIG_TYPE_RECEIPTS:
  330. hr = Fire_OnReceiptOptionsChange(this);
  331. break;
  332. case FAX_CONFIG_TYPE_ACTIVITY_LOGGING:
  333. hr = Fire_OnActivityLoggingConfigChange(this);
  334. break;
  335. case FAX_CONFIG_TYPE_OUTBOX:
  336. hr = Fire_OnOutgoingQueueConfigChange(this);
  337. break;
  338. case FAX_CONFIG_TYPE_SENTITEMS:
  339. hr = Fire_OnOutgoingArchiveConfigChange(this);
  340. break;
  341. case FAX_CONFIG_TYPE_INBOX:
  342. hr = Fire_OnIncomingArchiveConfigChange(this);
  343. break;
  344. case FAX_CONFIG_TYPE_SECURITY:
  345. hr = Fire_OnSecurityConfigChange(this);
  346. break;
  347. case FAX_CONFIG_TYPE_EVENTLOGS:
  348. hr = Fire_OnEventLoggingConfigChange(this);
  349. break;
  350. case FAX_CONFIG_TYPE_DEVICES:
  351. hr = Fire_OnDevicesConfigChange(this);
  352. break;
  353. case FAX_CONFIG_TYPE_OUT_GROUPS:
  354. hr = Fire_OnOutboundRoutingGroupsConfigChange(this);
  355. break;
  356. case FAX_CONFIG_TYPE_OUT_RULES:
  357. hr = Fire_OnOutboundRoutingRulesConfigChange(this);
  358. break;
  359. default:
  360. //
  361. // assert (FALSE)
  362. //
  363. ATLASSERT(pFaxEventInfo->EventInfo.ConfigType == FAX_CONFIG_TYPE_OUT_RULES);
  364. hr = E_FAIL;
  365. return hr;
  366. }
  367. if (FAILED(hr))
  368. {
  369. CALL_FAIL(GENERAL_ERR, _T("Fire_On <...> ConfigChange(this)"), hr);
  370. return hr;
  371. }
  372. break;
  373. case FAX_EVENT_TYPE_ACTIVITY:
  374. hr = Fire_OnServerActivityChange(this,
  375. pFaxEventInfo->EventInfo.ActivityInfo.dwIncomingMessages,
  376. pFaxEventInfo->EventInfo.ActivityInfo.dwRoutingMessages,
  377. pFaxEventInfo->EventInfo.ActivityInfo.dwOutgoingMessages,
  378. pFaxEventInfo->EventInfo.ActivityInfo.dwQueuedMessages);
  379. if (FAILED(hr))
  380. {
  381. CALL_FAIL(GENERAL_ERR, _T("Fire_OnServerActivityChange(this, ...)"), hr);
  382. return hr;
  383. }
  384. break;
  385. case FAX_EVENT_TYPE_QUEUE_STATE:
  386. hr = Fire_OnQueuesStatusChange(this,
  387. bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.dwQueueStates & FAX_OUTBOX_BLOCKED),
  388. bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.dwQueueStates & FAX_OUTBOX_PAUSED),
  389. bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.dwQueueStates & FAX_INCOMING_BLOCKED));
  390. if (FAILED(hr))
  391. {
  392. CALL_FAIL(GENERAL_ERR, _T("Fire_OnQueueStatusChange(this, ...)"), hr);
  393. return hr;
  394. }
  395. break;
  396. case FAX_EVENT_TYPE_NEW_CALL:
  397. {
  398. CComBSTR bstrCallerId = pFaxEventInfo->EventInfo.NewCall.lptstrCallerId;
  399. if (pFaxEventInfo->EventInfo.NewCall.lptstrCallerId && !bstrCallerId)
  400. {
  401. CALL_FAIL(MEM_ERR, _T("CComBSTR::operator=()"), E_OUTOFMEMORY);
  402. return hr;
  403. }
  404. hr = Fire_OnNewCall(this,
  405. pFaxEventInfo->EventInfo.NewCall.hCall,
  406. pFaxEventInfo->EventInfo.NewCall.dwDeviceId,
  407. bstrCallerId);
  408. if (FAILED(hr))
  409. {
  410. CALL_FAIL(GENERAL_ERR, _T("Fire_OnNewCall(this, ...)"), hr);
  411. return hr;
  412. }
  413. }
  414. break;
  415. case FAX_EVENT_TYPE_FXSSVC_ENDED:
  416. hr = Fire_OnServerShutDown(this);
  417. if (FAILED(hr))
  418. {
  419. CALL_FAIL(GENERAL_ERR, _T("Fire_OnServerShutDown(this)"), hr);
  420. return hr;
  421. }
  422. break;
  423. case FAX_EVENT_TYPE_DEVICE_STATUS:
  424. hr = Fire_OnDeviceStatusChange(this,
  425. pFaxEventInfo->EventInfo.DeviceStatus.dwDeviceId,
  426. bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.DeviceStatus.dwNewStatus & FAX_DEVICE_STATUS_POWERED_OFF),
  427. bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.DeviceStatus.dwNewStatus & FAX_DEVICE_STATUS_SENDING),
  428. bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.DeviceStatus.dwNewStatus & FAX_DEVICE_STATUS_RECEIVING),
  429. bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.DeviceStatus.dwNewStatus & FAX_DEVICE_STATUS_RINGING));
  430. if (FAILED(hr))
  431. {
  432. CALL_FAIL(GENERAL_ERR, _T("Fire_OnDeviceStatusChange(this, dwDeviceId, ...)"), hr);
  433. return hr;
  434. }
  435. break;
  436. default:
  437. //
  438. // assert (FALSE)
  439. //
  440. ATLASSERT(pFaxEventInfo->EventType == FAX_EVENT_TYPE_FXSSVC_ENDED);
  441. hr = E_FAIL;
  442. return hr;
  443. }
  444. return hr;
  445. }
  446. //
  447. //========== MESSAGE HANDLER FUNCTION ======================================
  448. //
  449. LRESULT
  450. CNotifyWindow::OnMessage(UINT uMsg,
  451. WPARAM wParam,
  452. LPARAM lParam,
  453. BOOL& bHandled
  454. )
  455. /*++
  456. Routine name : CNotifyWindow::OnMessage
  457. Routine description:
  458. Get the Message and call Server's ProcessMessage.
  459. Author:
  460. Iv Garber (IvG), Jul, 2000
  461. Arguments:
  462. uMsg [in] - Msg Id
  463. wParam [in] - wParam
  464. lParam [in] - LParam
  465. bHandled [in,out] - bHandled
  466. Return Value:
  467. Standard result code
  468. --*/
  469. {
  470. DBG_ENTER(_T("CNotifyWindow::OnMessage"));
  471. //
  472. // Check that lParam is valid
  473. //
  474. if (!lParam)
  475. {
  476. CALL_FAIL(GENERAL_ERR, _T("(!lParam)"), E_FAIL);
  477. return 0;
  478. }
  479. if (::IsBadReadPtr((FAX_EVENT_EX *)lParam, sizeof(FAX_EVENT_EX)))
  480. {
  481. CALL_FAIL(GENERAL_ERR, _T("(::IsBadReadPtr((FAX_EVENT_EX *)lParam, sizeof(FAX_EVENT_EX))"), E_FAIL);
  482. return 0;
  483. }
  484. if (((FAX_EVENT_EX *)lParam)->dwSizeOfStruct != sizeof(FAX_EVENT_EX))
  485. {
  486. CALL_FAIL(GENERAL_ERR, _T("(((FAX_EVENT_EX *)lParam)->dwSizeOfStruct != sizeof(FAX_EVENT_EX))"), E_FAIL);
  487. return 0;
  488. }
  489. //
  490. // Call Server to Process the Message
  491. //
  492. if (m_pServer)
  493. {
  494. HRESULT hr = S_OK;
  495. hr = m_pServer->ProcessMessage((FAX_EVENT_EX *)lParam);
  496. if (FAILED(hr))
  497. {
  498. CALL_FAIL(GENERAL_ERR, _T("m_pServer->ProcessMessage()"), hr);
  499. }
  500. }
  501. //
  502. // Free the Buffer
  503. //
  504. FaxFreeBuffer((void *)lParam);
  505. return 0;
  506. }
  507. //
  508. //================ GET METHOD DATA ================================================
  509. //
  510. void
  511. CFaxServer::GetMethodData(
  512. /*[in]*/ BSTR bstrAllString,
  513. /*[out]*/ LPWSTR strWhereToPut
  514. )
  515. /*++
  516. Routine name : CFaxServer::GetMethodData
  517. Routine description:
  518. Read from bstrAllString data upto DELIMITER and store it in strWhereToPut.
  519. Used in GetRegisteredData for Extension Method Registration.
  520. Author:
  521. Iv Garber (IvG), Jul, 2000
  522. Arguments:
  523. bstrAllString [TBD] - in subsequent calls
  524. strWhereToPut [TBD] - where to put the value that was readed from the bstrAllString.
  525. --*/
  526. {
  527. BOOL bRes = TRUE;
  528. DBG_ENTER(_T("CFaxServer::GetMethodData()"));
  529. //
  530. // Find Method Name
  531. //
  532. BSTR bstrTmp;
  533. bstrTmp = _tcstok(bstrAllString, DELIMITER);
  534. if (!bstrTmp)
  535. {
  536. CALL_FAIL(MEM_ERR, _T("_tcstok(bstrAllString, DELIMITER))"), bRes);
  537. RaiseException(EXCEPTION_INVALID_METHOD_DATA, 0, 0, 0);
  538. }
  539. //
  540. // Check that length of the readen data
  541. //
  542. if (_tcslen(bstrTmp) > 100)
  543. {
  544. //
  545. // Error : exceeds the limit
  546. //
  547. CALL_FAIL(GENERAL_ERR, _T("(_tcslen(bstrTmp) > 100)"), E_FAIL);
  548. RaiseException(EXCEPTION_INVALID_METHOD_DATA, 0, 0, 0);
  549. }
  550. memcpy(strWhereToPut, bstrTmp, (sizeof(TCHAR) * (_tcslen(bstrTmp) + 1)));
  551. return;
  552. }
  553. //
  554. //============= GET REGISTERED DATA =========================================
  555. //
  556. BOOL
  557. CFaxServer::GetRegisteredData(
  558. /*[out]*/ LPWSTR MethodName,
  559. /*[out]*/ LPWSTR FriendlyName,
  560. /*[out]*/ LPWSTR FunctionName,
  561. /*[out]*/ LPWSTR Guid
  562. )
  563. /*++
  564. Routine name : CFaxServer::GetRegisteredData
  565. Routine description:
  566. Return data about specific Method being registered.
  567. Author:
  568. Iv Garber (IvG), Jul, 2000
  569. Arguments:
  570. MethodName [TBD] - Name of the Method
  571. FriendlyName [TBD] - Friendly Name of the Method
  572. FunctionName [TBD] - Function Name of the Method
  573. Guid [TBD] - GUID of the Method
  574. Return Value:
  575. TRUE if Method Data is filled ok, FALSE if all the methods already registered.
  576. Notes:
  577. The function raises an exception when any error happens.
  578. --*/
  579. {
  580. BOOL bRes = TRUE;
  581. DBG_ENTER(_T("CFaxServer::GetRegisteredData"), bRes);
  582. //
  583. // Check if we already finished the array
  584. //
  585. if (m_pRegMethods->rgsabound[0].cElements == m_lLastRegisteredMethod)
  586. {
  587. bRes = FALSE;
  588. CALL_FAIL(GENERAL_ERR, _T("We have reached the End of the Array"), bRes);
  589. return bRes;
  590. }
  591. CComBSTR bstrMethodData;
  592. HRESULT hr = SafeArrayGetElement(m_pRegMethods, &m_lLastRegisteredMethod, &bstrMethodData);
  593. if (FAILED(hr))
  594. {
  595. CALL_FAIL(GENERAL_ERR, _T("SafeArrayGetElement(m_pRegMethods, ...)"), hr);
  596. RaiseException(EXCEPTION_INVALID_METHOD_DATA, 0, 0, 0);
  597. }
  598. GetMethodData(bstrMethodData, MethodName);
  599. GetMethodData(NULL, FriendlyName);
  600. GetMethodData(NULL, FunctionName);
  601. GetMethodData(NULL, Guid);
  602. //
  603. // Increase the Index of the SafeArray
  604. //
  605. m_lLastRegisteredMethod++;
  606. return bRes;
  607. }
  608. //
  609. //=================== REGISTER METHOD CALLBACK ===============================
  610. //
  611. BOOL CALLBACK RegisterMethodCallback(
  612. /*[in]*/ HANDLE FaxHandle,
  613. /*[in]*/ LPVOID Context,
  614. /*[out]*/ LPWSTR MethodName,
  615. /*[out]*/ LPWSTR FriendlyName,
  616. /*[out]*/ LPWSTR FunctionName,
  617. /*[out]*/ LPWSTR Guid
  618. )
  619. {
  620. BOOL bRes = TRUE;
  621. DBG_ENTER(_T("RegisterMethodCallback"), bRes);
  622. bRes = ((CFaxServer *)Context)->GetRegisteredData(MethodName, FriendlyName, FunctionName, Guid);
  623. return bRes;
  624. }
  625. //
  626. //=================== LISTEN TO SERVER EVENTS ===============================
  627. //
  628. STDMETHODIMP
  629. CFaxServer::ListenToServerEvents(
  630. /*[in]*/ FAX_SERVER_EVENTS_TYPE_ENUM EventTypes
  631. )
  632. /*++
  633. Routine name : CFaxServer::ListenToServerEvents
  634. Routine description:
  635. Starts or stops listening to Server Events.
  636. Author:
  637. Iv Garber (IvG), Jul, 2000
  638. Arguments:
  639. EventTypes [in] - Events to listen to.
  640. Return Value:
  641. Standard HRESULT code
  642. --*/
  643. {
  644. HRESULT hr = S_OK;
  645. DBG_ENTER(_T("CFaxServer::ListenToServerEvents"), hr, _T("Events=%ld"), EventTypes);
  646. //
  647. // Check Fax Handle
  648. //
  649. if (m_faxHandle == NULL)
  650. {
  651. //
  652. // Server not Connected
  653. //
  654. hr = E_HANDLE;
  655. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  656. CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
  657. return hr;
  658. }
  659. HANDLE hEvent = NULL;
  660. if (EventTypes > fsetNONE)
  661. {
  662. if (!m_pNotifyWindow)
  663. {
  664. //
  665. // Create new Window
  666. //
  667. m_pNotifyWindow = new (std::nothrow) CNotifyWindow(this);
  668. if (!m_pNotifyWindow)
  669. {
  670. //
  671. // Out of Memory
  672. //
  673. hr = E_OUTOFMEMORY;
  674. Error(IDS_ERROR_OUTOFMEMORY, IID_IFaxServer, hr);
  675. CALL_FAIL(MEM_ERR, _T("new CNotifyWindow(this)"), hr);
  676. return hr;
  677. }
  678. RECT rcRect;
  679. ZeroMemory(&rcRect, sizeof(rcRect));
  680. m_pNotifyWindow->Create(NULL, rcRect, NULL, WS_POPUP, 0x0, 0);
  681. if (!::IsWindow(m_pNotifyWindow->m_hWnd))
  682. {
  683. //
  684. // Failed to Create Window
  685. //
  686. hr = E_FAIL;
  687. CALL_FAIL(GENERAL_ERR, _T("m_pNotifyWindow->Create(NULL, rcRect)"), hr);
  688. ClearNotifyWindow();
  689. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  690. return hr;
  691. }
  692. }
  693. //
  694. // Register for new Set of Events
  695. //
  696. if (!FaxRegisterForServerEvents(m_faxHandle,
  697. EventTypes,
  698. NULL,
  699. 0,
  700. m_pNotifyWindow->m_hWnd,
  701. m_pNotifyWindow->GetMessageId(),
  702. &hEvent))
  703. {
  704. //
  705. // Failed to Register given Set of Events
  706. //
  707. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  708. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  709. CALL_FAIL(GENERAL_ERR, _T("FaxRegisterForServerEvents(m_faxHandle, lEventTypes, ...)"), hr);
  710. ClearNotifyWindow();
  711. return hr;
  712. }
  713. }
  714. //
  715. // Unregister from the previous set of Events, if there was one
  716. //
  717. if (m_hEvent)
  718. {
  719. if (!FaxUnregisterForServerEvents(m_hEvent))
  720. {
  721. //
  722. // Failed to Unregister given Set of Events
  723. //
  724. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  725. CALL_FAIL(GENERAL_ERR, _T("FaxUnregisterForServerEvents(m_hEvent)"), hr);
  726. //
  727. // Return Error only when Caller specially wanted to Unregister.
  728. // Otherwise, debug Warning is enough.
  729. //
  730. if (EventTypes == fsetNONE)
  731. {
  732. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  733. }
  734. }
  735. }
  736. //
  737. // store the new Listening HANDLE for future UNRegistration
  738. //
  739. m_hEvent = hEvent;
  740. if (m_hEvent == NULL)
  741. {
  742. //
  743. // We're not listening to any events - dismiss the hidden window
  744. //
  745. ClearNotifyWindow();
  746. }
  747. m_EventTypes = EventTypes;
  748. return hr;
  749. }
  750. //
  751. //=================== GET REGISTERED EVENTS ===============================
  752. //
  753. STDMETHODIMP
  754. CFaxServer::get_RegisteredEvents(
  755. /*[out, retval]*/ FAX_SERVER_EVENTS_TYPE_ENUM *pEventTypes
  756. )
  757. /*++
  758. Routine name : CFaxServer::get_RegisteredEvents
  759. Routine description:
  760. Return Bit-Wise Combination of Events the Fax Server is Listening to
  761. Author:
  762. Iv Garber (IvG), Dec, 2000
  763. Arguments:
  764. pEventTypes [out] - the Event Types to return
  765. Return Value:
  766. Standard HRESULT code
  767. --*/
  768. {
  769. HRESULT hr = S_OK;
  770. DBG_ENTER(_T("CFaxServer::get_RegisteredEvents"), hr);
  771. //
  772. // Check the Fax Service Handle
  773. //
  774. if (m_faxHandle == NULL)
  775. {
  776. //
  777. // Server not Connected
  778. //
  779. hr = E_HANDLE;
  780. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  781. CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
  782. return hr;
  783. }
  784. //
  785. // Check the pointer we have got
  786. //
  787. if (::IsBadWritePtr(pEventTypes, sizeof(FAX_SERVER_EVENTS_TYPE_ENUM)))
  788. {
  789. //
  790. // Got a bad return pointer
  791. //
  792. hr = E_POINTER;
  793. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  794. CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr()"), hr);
  795. return hr;
  796. }
  797. *pEventTypes = m_EventTypes;
  798. return hr;
  799. }
  800. //
  801. //=================== REGISTER DEVICE PROVIDER ===============================
  802. //
  803. STDMETHODIMP
  804. CFaxServer::RegisterDeviceProvider(
  805. /*[in]*/ BSTR bstrGUID,
  806. /*[in]*/ BSTR bstrFriendlyName,
  807. /*[in]*/ BSTR bstrImageName,
  808. /*[in]*/ BSTR bstrTspName,
  809. /*[in]*/ long lFSPIVersion
  810. )
  811. /*++
  812. Routine name : CFaxServer::RegisterDeviceProvider
  813. Routine description:
  814. Register the FSP
  815. Author:
  816. Iv Garber (IvG), Jun, 2000
  817. Arguments:
  818. bstrGUID [in] - GUID of the FSP
  819. bstrFriendlyName [in] - Frienly Name of the FSP
  820. bstrImageName [in] - Image Name of the FSP
  821. TspName [in] - TspName of the FSP
  822. FSPIVersion [in] - Version of the FSP interface
  823. Return Value:
  824. Standard HRESULT code
  825. --*/
  826. {
  827. HRESULT hr = S_OK;
  828. DBG_ENTER(_T("CFaxServer::RegisterDeviceProvider"),
  829. hr,
  830. _T("GUID=%s FriendlyName=%s ImageName=%s TspNameName=%s Version=%d"),
  831. bstrGUID,
  832. bstrFriendlyName,
  833. bstrImageName,
  834. bstrTspName,
  835. lFSPIVersion);
  836. if (m_faxHandle == NULL)
  837. {
  838. //
  839. // Server not Connected
  840. //
  841. hr = E_HANDLE;
  842. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  843. CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
  844. return hr;
  845. }
  846. //
  847. // Check if GUID is valid
  848. //
  849. hr = IsValidGUID(bstrGUID);
  850. if (FAILED(hr))
  851. {
  852. CALL_FAIL(GENERAL_ERR, _T("IsValidGUID(bstrGUID)"), hr);
  853. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  854. return hr;
  855. }
  856. //
  857. // Register the FSP
  858. //
  859. if (!FaxRegisterServiceProviderEx(m_faxHandle,
  860. bstrGUID,
  861. bstrFriendlyName,
  862. bstrImageName,
  863. bstrTspName,
  864. lFSPIVersion,
  865. 0)) // capabilities
  866. {
  867. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  868. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  869. CALL_FAIL(GENERAL_ERR, _T("FaxRegisterServiceProviderEx(m_faxHandle, bstrUniqueName, ...)"), hr);
  870. return hr;
  871. }
  872. return hr;
  873. }
  874. //
  875. //================= REGISTER INBOUND ROUTING EXTENSION ================================
  876. //
  877. STDMETHODIMP
  878. CFaxServer::RegisterInboundRoutingExtension(
  879. /*[in]*/ BSTR bstrExtensionName,
  880. /*[in]*/ BSTR bstrFriendlyName,
  881. /*[in]*/ BSTR bstrImageName,
  882. /*[in]*/ VARIANT vMethods
  883. )
  884. /*++
  885. Routine name : CFaxServer::RegisterInboundRoutingExtension
  886. Routine description:
  887. Register Inbound Routing Extension.
  888. Author:
  889. Iv Garber (IvG), Jun, 2000
  890. Arguments:
  891. bstrExtensionName [in] - Extension Name
  892. bstrFriendlyName [in] - Friendly Name
  893. bstrImageName [in] - Image Name
  894. vMethods [in] - SafeArray of the Methods Data
  895. Return Value:
  896. Standard HRESULT code
  897. --*/
  898. {
  899. HRESULT hr = S_OK;
  900. DBG_ENTER(_T("CFaxServer::RegisterInboundRoutingExtension"), hr, _T("Name=%s Friendly=%s Image=%s"),bstrExtensionName, bstrFriendlyName, bstrImageName);
  901. if (m_faxHandle == NULL)
  902. {
  903. //
  904. // Server not Connected
  905. //
  906. hr = E_HANDLE;
  907. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  908. CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
  909. return hr;
  910. }
  911. //
  912. // Check the Validity of the SafeArray
  913. //
  914. if (vMethods.vt != (VT_ARRAY | VT_BSTR))
  915. {
  916. hr = E_INVALIDARG;
  917. Error(IDS_ERROR_METHODSNOTARRAY, IID_IFaxServer, hr);
  918. CALL_FAIL(GENERAL_ERR, _T("(vMethods.vt != VT_ARRAY | VT_BSTR)"), hr);
  919. return hr;
  920. }
  921. m_pRegMethods = vMethods.parray;
  922. if (!m_pRegMethods)
  923. {
  924. hr = E_INVALIDARG;
  925. CALL_FAIL(GENERAL_ERR, _T("!m_pRegMethods ( = vMethods.parray )"), hr);
  926. Error(IDS_ERROR_METHODSNOTARRAY, IID_IFaxServer, hr);
  927. return hr;
  928. }
  929. if (SafeArrayGetDim(m_pRegMethods) != 1)
  930. {
  931. hr = E_INVALIDARG;
  932. CALL_FAIL(GENERAL_ERR, _T("SafeArrayGetDim(m_pRegMethods) != 1"), hr);
  933. Error(IDS_ERROR_METHODSNOTARRAY, IID_IFaxServer, hr);
  934. return hr;
  935. }
  936. if (m_pRegMethods->rgsabound[0].lLbound != 0)
  937. {
  938. hr = E_INVALIDARG;
  939. Error(IDS_ERROR_METHODSNOTARRAY, IID_IFaxServer, hr);
  940. CALL_FAIL(GENERAL_ERR, _T("m_pRegMethods->rgsabound[0].lLbound != 0"), hr);
  941. return hr;
  942. }
  943. //
  944. // Register the IR Extension
  945. //
  946. m_lLastRegisteredMethod = 0;
  947. if (!FaxRegisterRoutingExtension(m_faxHandle,
  948. bstrExtensionName,
  949. bstrFriendlyName,
  950. bstrImageName,
  951. RegisterMethodCallback,
  952. this))
  953. {
  954. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  955. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  956. CALL_FAIL(GENERAL_ERR, _T("FaxRegisterRoutingExtension(m_faxHandle, bstrExtensionName, ...)"), hr);
  957. return hr;
  958. }
  959. return hr;
  960. }
  961. //
  962. //========== UNREGISTER INBOUND ROUTING EXTENSION ==============================================
  963. //
  964. STDMETHODIMP
  965. CFaxServer::UnregisterInboundRoutingExtension(
  966. /*[in]*/ BSTR bstrExtensionUniqueName
  967. )
  968. /*++
  969. Routine name : CFaxServer::UnregisterExtensionUniqueName
  970. Routine description:
  971. Unregister the Inbound Routing Extension
  972. Author:
  973. Iv Garber (IvG), Jun, 2000
  974. Arguments:
  975. bstrExtensionUniqueName - Unique Name of the IR Extension to Unregister
  976. Return Value:
  977. Standard HRESULT code
  978. --*/
  979. {
  980. HRESULT hr = S_OK;
  981. DBG_ENTER(_T("CFaxServer::UnregisterInboundRoutingExtension"), hr, _T("Unique Name =%s"), bstrExtensionUniqueName);
  982. if (m_faxHandle == NULL)
  983. {
  984. //
  985. // Server not Connected
  986. //
  987. hr = E_HANDLE;
  988. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  989. CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
  990. return hr;
  991. }
  992. //
  993. // Unregister the given Routing Extension
  994. //
  995. if (!FaxUnregisterRoutingExtension(m_faxHandle, bstrExtensionUniqueName))
  996. {
  997. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  998. CALL_FAIL(GENERAL_ERR, _T("FaxUnregisterRoutingExtension(m_faxHandle, bstrExtensionUniqueName)"), hr);
  999. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1000. return hr;
  1001. }
  1002. return hr;
  1003. }
  1004. //
  1005. //========== UNREGISTER DEVICE PROVIDER ==============================================
  1006. //
  1007. STDMETHODIMP
  1008. CFaxServer::UnregisterDeviceProvider(
  1009. /*[in]*/ BSTR bstrUniqueName
  1010. )
  1011. /*++
  1012. Routine name : CFaxServer::UnregisterDeviceProvider
  1013. Routine description:
  1014. Unregister the Device Provider
  1015. Author:
  1016. Iv Garber (IvG), Jun, 2000
  1017. Arguments:
  1018. bstrUniqueName [in] - UniqueName of the Device Provider to Unregister
  1019. Return Value:
  1020. Standard HRESULT code
  1021. --*/
  1022. {
  1023. HRESULT hr = S_OK;
  1024. DBG_ENTER(_T("CFaxServer::UnregisterDeviceProvider"), hr, _T("UniqueName=%s"), bstrUniqueName);
  1025. if (m_faxHandle == NULL)
  1026. {
  1027. //
  1028. // Server not Connected
  1029. //
  1030. hr = E_HANDLE;
  1031. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1032. CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
  1033. return hr;
  1034. }
  1035. //
  1036. // Unregister the given Device Provider
  1037. //
  1038. if (!FaxUnregisterServiceProviderEx(m_faxHandle, bstrUniqueName))
  1039. {
  1040. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  1041. CALL_FAIL(GENERAL_ERR, _T("FaxUnregisterServiceProviderEx(m_faxHandle, bstrUniqueName)"), hr);
  1042. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1043. return hr;
  1044. }
  1045. return hr;
  1046. }
  1047. //
  1048. //===================== GET EXTENSION PROPERTY ===============================================
  1049. //
  1050. STDMETHODIMP
  1051. CFaxServer::GetExtensionProperty(
  1052. /*[in]*/ BSTR bstrGUID,
  1053. /*[out, retval]*/ VARIANT *pvProperty
  1054. )
  1055. /*++
  1056. Routine name : CFaxServer::GetExtensionProperty
  1057. Routine description:
  1058. Retrieves the global Extension Data from the Server.
  1059. Author:
  1060. Iv Garber (IvG), Jun, 2000
  1061. Arguments:
  1062. bstrGUID [in] -- Extension's Data GUID
  1063. pvProperty [out] -- Variant with the Blob to Return
  1064. Return Value:
  1065. Standard HRESULT code
  1066. --*/
  1067. {
  1068. HRESULT hr = S_OK;
  1069. DBG_ENTER(_T("CFaxServer::GetExtensionProperty()"), hr, _T("GUID=%s"), bstrGUID);
  1070. hr = ::GetExtensionProperty(this, 0, bstrGUID, pvProperty);
  1071. if (FAILED(hr))
  1072. {
  1073. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1074. return hr;
  1075. }
  1076. return hr;
  1077. };
  1078. //
  1079. //============= SET EXTENSION PROPERTY =============================
  1080. //
  1081. STDMETHODIMP
  1082. CFaxServer::SetExtensionProperty(
  1083. /*[in]*/ BSTR bstrGUID,
  1084. /*[in]*/ VARIANT vProperty
  1085. )
  1086. /*++
  1087. Routine name : CFaxServer::SetExtensionProperty
  1088. Routine description:
  1089. Stores Extension Configuration Property at Server level.
  1090. Author:
  1091. Iv Garber (IvG), Jun, 2000
  1092. Arguments:
  1093. bstrGUID [in] - GUID of the Property
  1094. vProperty [in] - the Property to Store : SafeArray of Bytes
  1095. Return Value:
  1096. Standard HRESULT code
  1097. --*/
  1098. {
  1099. HRESULT hr = S_OK;
  1100. DBG_ENTER(_T("CFaxServer::SetExtensionProperty()"), hr, _T("GUID=%s"), bstrGUID);
  1101. hr = ::SetExtensionProperty(this, 0, bstrGUID, vProperty);
  1102. if (FAILED(hr))
  1103. {
  1104. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1105. return hr;
  1106. }
  1107. return hr;
  1108. }
  1109. //
  1110. //================== GET DEBUG ==============================
  1111. //
  1112. STDMETHODIMP
  1113. CFaxServer::get_Debug(
  1114. /*[out, retval]*/ VARIANT_BOOL *pbDebug
  1115. )
  1116. /*++
  1117. Routine name : CFaxServer::get_Debug
  1118. Routine description:
  1119. Return Whether Server is in Debug Mode.
  1120. Author:
  1121. Iv Garber (IvG), Jun, 2000
  1122. Arguments:
  1123. pbDebug [out] - the result
  1124. Return Value:
  1125. Standard HRESULT code
  1126. --*/
  1127. {
  1128. HRESULT hr = S_OK;
  1129. DBG_ENTER(_T("CFaxServer::get_Debug"), hr);
  1130. if (!m_bVersionValid)
  1131. {
  1132. //
  1133. // get Version of the Server
  1134. //
  1135. hr = GetVersion();
  1136. if (FAILED(hr))
  1137. {
  1138. return hr;
  1139. }
  1140. }
  1141. //
  1142. // Return the Value
  1143. //
  1144. hr = GetVariantBool(pbDebug, bool2VARIANT_BOOL((m_Version.dwFlags & FAX_VER_FLAG_CHECKED) ? true : false));
  1145. if (FAILED(hr))
  1146. {
  1147. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1148. return hr;
  1149. }
  1150. return hr;
  1151. }
  1152. //
  1153. //================== GET MINOR BUILD ==============================
  1154. //
  1155. STDMETHODIMP
  1156. CFaxServer::get_MinorBuild(
  1157. /*[out, retval]*/ long *plMinorBuild
  1158. )
  1159. /*++
  1160. Routine name : CFaxServer::get_MinorBuild
  1161. Routine description:
  1162. Return Minor Build of the Server.
  1163. Author:
  1164. Iv Garber (IvG), Jun, 2000
  1165. Arguments:
  1166. plMinorBuild [out] - the result
  1167. Return Value:
  1168. Standard HRESULT code
  1169. --*/
  1170. {
  1171. HRESULT hr = S_OK;
  1172. DBG_ENTER(_T("CFaxServer::get_MinorBuild"), hr);
  1173. if (!m_bVersionValid)
  1174. {
  1175. //
  1176. // get Version of the Server
  1177. //
  1178. hr = GetVersion();
  1179. if (FAILED(hr))
  1180. {
  1181. return hr;
  1182. }
  1183. }
  1184. //
  1185. // Return the Value
  1186. //
  1187. hr = GetLong(plMinorBuild, m_Version.wMinorBuildNumber);
  1188. if (FAILED(hr))
  1189. {
  1190. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1191. return hr;
  1192. }
  1193. return hr;
  1194. }
  1195. //
  1196. //================== GET MAJOR BUILD ==============================
  1197. //
  1198. STDMETHODIMP
  1199. CFaxServer::get_MajorBuild(
  1200. /*[out, retval]*/ long *plMajorBuild
  1201. )
  1202. /*++
  1203. Routine name : CFaxServer::get_MajorBuild
  1204. Routine description:
  1205. Return Major Build of the Server.
  1206. Author:
  1207. Iv Garber (IvG), Jun, 2000
  1208. Arguments:
  1209. plMajorBuild [out] - the result
  1210. Return Value:
  1211. Standard HRESULT code
  1212. --*/
  1213. {
  1214. HRESULT hr = S_OK;
  1215. DBG_ENTER(_T("CFaxServer::get_MajorBuild"), hr);
  1216. if (!m_bVersionValid)
  1217. {
  1218. //
  1219. // get Version of the Server
  1220. //
  1221. hr = GetVersion();
  1222. if (FAILED(hr))
  1223. {
  1224. return hr;
  1225. }
  1226. }
  1227. //
  1228. // Return the Value
  1229. //
  1230. hr = GetLong(plMajorBuild, m_Version.wMajorBuildNumber);
  1231. if (FAILED(hr))
  1232. {
  1233. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1234. return hr;
  1235. }
  1236. return hr;
  1237. }
  1238. //
  1239. //================== GET MINOR VERSION ==============================
  1240. //
  1241. STDMETHODIMP
  1242. CFaxServer::get_MinorVersion(
  1243. /*[out, retval]*/ long *plMinorVersion
  1244. )
  1245. /*++
  1246. Routine name : CFaxServer::get_MinorVersion
  1247. Routine description:
  1248. Return Minor Version of the Server.
  1249. Author:
  1250. Iv Garber (IvG), Jun, 2000
  1251. Arguments:
  1252. plMinorVersion [out] - the result
  1253. Return Value:
  1254. Standard HRESULT code
  1255. --*/
  1256. {
  1257. HRESULT hr = S_OK;
  1258. DBG_ENTER(_T("CFaxServer::get_MinorVersion"), hr);
  1259. if (!m_bVersionValid)
  1260. {
  1261. //
  1262. // get Version of the Server
  1263. //
  1264. hr = GetVersion();
  1265. if (FAILED(hr))
  1266. {
  1267. return hr;
  1268. }
  1269. }
  1270. //
  1271. // Return the Value
  1272. //
  1273. hr = GetLong(plMinorVersion, m_Version.wMinorVersion);
  1274. if (FAILED(hr))
  1275. {
  1276. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1277. return hr;
  1278. }
  1279. return hr;
  1280. }
  1281. //
  1282. //================== GET VERSION ==============================
  1283. //
  1284. STDMETHODIMP
  1285. CFaxServer::GetVersion()
  1286. {
  1287. HRESULT hr = S_OK;
  1288. DBG_ENTER(_T("CFaxServer::GetVersion"), hr);
  1289. if (m_faxHandle == NULL)
  1290. {
  1291. //
  1292. // Server not Connected
  1293. //
  1294. hr = E_HANDLE;
  1295. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1296. CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
  1297. return hr;
  1298. }
  1299. //
  1300. // Get Version from the Fax Server
  1301. //
  1302. ZeroMemory(&m_Version, sizeof(FAX_VERSION));
  1303. m_Version.dwSizeOfStruct = sizeof(FAX_VERSION);
  1304. if (!FaxGetVersion(m_faxHandle, &m_Version))
  1305. {
  1306. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  1307. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1308. CALL_FAIL(GENERAL_ERR, _T("FaxGetVersion(m_faxHandle, &m_Version))"), hr);
  1309. return hr;
  1310. }
  1311. //
  1312. // Check that we have got good Version struct
  1313. //
  1314. if (m_Version.dwSizeOfStruct != sizeof(FAX_VERSION))
  1315. {
  1316. hr = E_FAIL;
  1317. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1318. CALL_FAIL(GENERAL_ERR, _T("m_Version.dwSizeOfStruct != sizeof(FAX_VERSION)"), hr);
  1319. return hr;
  1320. }
  1321. ATLASSERT(m_Version.bValid);
  1322. //
  1323. // Get API Version from the Fax Server
  1324. //
  1325. if (!FaxGetReportedServerAPIVersion(m_faxHandle, LPDWORD(&m_APIVersion)))
  1326. {
  1327. hr = HRESULT_FROM_WIN32(GetLastError());
  1328. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1329. CALL_FAIL(GENERAL_ERR, _T("FaxGetReportedServerAPIVersion(m_faxHandle, &m_APIVersion))"), hr);
  1330. return hr;
  1331. }
  1332. //
  1333. // m_Version & m_APIVersion are valid and OK
  1334. //
  1335. m_bVersionValid = true;
  1336. return hr;
  1337. }
  1338. //
  1339. //================== GET MAJOR VERSION ==============================
  1340. //
  1341. STDMETHODIMP
  1342. CFaxServer::get_MajorVersion(
  1343. /*[out, retval]*/ long *plMajorVersion
  1344. )
  1345. /*++
  1346. Routine name : CFaxServer::get_MajorVersion
  1347. Routine description:
  1348. Return Major Version of the Server.
  1349. Author:
  1350. Iv Garber (IvG), Jun, 2000
  1351. Arguments:
  1352. plMajorVersion [out] - the result
  1353. Return Value:
  1354. Standard HRESULT code
  1355. --*/
  1356. {
  1357. HRESULT hr = S_OK;
  1358. DBG_ENTER(_T("CFaxServer::get_MajorVersion"), hr);
  1359. if (!m_bVersionValid)
  1360. {
  1361. //
  1362. // get Version of the Server
  1363. //
  1364. hr = GetVersion();
  1365. if (FAILED(hr))
  1366. {
  1367. return hr;
  1368. }
  1369. }
  1370. //
  1371. // Return the Value
  1372. //
  1373. hr = GetLong(plMajorVersion, m_Version.wMajorVersion);
  1374. if (FAILED(hr))
  1375. {
  1376. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1377. return hr;
  1378. }
  1379. return hr;
  1380. }
  1381. //
  1382. //================== GET OUTBOUND ROUTING OBJECT ==============================
  1383. //
  1384. STDMETHODIMP
  1385. CFaxServer::get_OutboundRouting(
  1386. IFaxOutboundRouting **ppOutboundRouting
  1387. )
  1388. /*++
  1389. Routine name : CFaxServer::get_OutboundRouting
  1390. Routine description:
  1391. Return Outbound Routing Shortcut Object
  1392. Author:
  1393. Iv Garber (IvG), Jun, 2000
  1394. Arguments:
  1395. ppOutboundRouting [out] - the Outbound Routing Object
  1396. Return Value:
  1397. Standard HRESULT code
  1398. Notes:
  1399. FaxOutboundRouting is Contained Object, because of :
  1400. a) It needs Ptr to Fax Server, to create Groups/Rules Collections
  1401. each time it is asked to.
  1402. b) Fax Server caches it, to allow fast dot notation ( Server.OutboundRouting.<...> )
  1403. --*/
  1404. {
  1405. HRESULT hr = S_OK;
  1406. DBG_ENTER (_T("CFaxServer::get_OutboundRouting"), hr);
  1407. CObjectHandler<CFaxOutboundRouting, IFaxOutboundRouting> ObjectCreator;
  1408. hr = ObjectCreator.GetContainedObject(ppOutboundRouting, &m_pOutboundRouting, this);
  1409. if (FAILED(hr))
  1410. {
  1411. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1412. return hr;
  1413. }
  1414. return hr;
  1415. }
  1416. //
  1417. //================== GET DEVICES OBJECT ==============================
  1418. //
  1419. STDMETHODIMP
  1420. CFaxServer::GetDevices(
  1421. IFaxDevices **ppDevices
  1422. )
  1423. /*++
  1424. Routine name : CFaxServer::get_Devices
  1425. Routine description:
  1426. Return Devices Collection Object
  1427. Author:
  1428. Iv Garber (IvG), Jun, 2000
  1429. Arguments:
  1430. ppDevices [out] - the Devices Collection Object
  1431. Return Value:
  1432. Standard HRESULT code
  1433. Notes:
  1434. Devices is a collection. It is not cached by the Server.
  1435. Each time the function is called, the new collection is created.
  1436. This enables the user to refresh the collection.
  1437. --*/
  1438. {
  1439. HRESULT hr = S_OK;
  1440. DBG_ENTER (_T("CFaxServer::get_Devices"), hr);
  1441. CObjectHandler<CFaxDevices, IFaxDevices> ObjectCreator;
  1442. hr = ObjectCreator.GetObject(ppDevices, this);
  1443. if (FAILED(hr))
  1444. {
  1445. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1446. return hr;
  1447. }
  1448. return hr;
  1449. }
  1450. //
  1451. //================== GET DEVICE PROVIDERS OBJECT ==============================
  1452. //
  1453. STDMETHODIMP
  1454. CFaxServer::GetDeviceProviders(
  1455. IFaxDeviceProviders **ppDeviceProviders
  1456. )
  1457. /*++
  1458. Routine name : CFaxServer::get_DeviceProviders
  1459. Routine description:
  1460. Return Device Providers Collection Object
  1461. Author:
  1462. Iv Garber (IvG), Jun, 2000
  1463. Arguments:
  1464. ppDeviceProviders [out] - the Device Providers Collection Object
  1465. Return Value:
  1466. Standard HRESULT code
  1467. Notes:
  1468. Device Providers is a collection. It is not cached by the Server.
  1469. Each time the function is called, the new collection is created.
  1470. This enables the user to refresh the collection.
  1471. --*/
  1472. {
  1473. HRESULT hr = S_OK;
  1474. DBG_ENTER (_T("CFaxServer::get_DeviceProviders"), hr);
  1475. CObjectHandler<CFaxDeviceProviders, IFaxDeviceProviders> ObjectCreator;
  1476. hr = ObjectCreator.GetObject(ppDeviceProviders, this);
  1477. if (FAILED(hr))
  1478. {
  1479. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1480. return hr;
  1481. }
  1482. return hr;
  1483. }
  1484. //
  1485. //================== GET INBOUND ROUTING OBJECT ==============================
  1486. //
  1487. STDMETHODIMP
  1488. CFaxServer::get_InboundRouting(
  1489. IFaxInboundRouting **ppInboundRouting
  1490. )
  1491. /*++
  1492. Routine name : CFaxServer::get_InboundRouting
  1493. Routine description:
  1494. Return Inbound Routing Shortcut Object
  1495. Author:
  1496. Iv Garber (IvG), June, 2000
  1497. Arguments:
  1498. ppInboundRouting [out] - the Inbound Routing Object
  1499. Return Value:
  1500. Standard HRESULT code
  1501. Notes:
  1502. FaxInboundRouting is Contained Object, because of :
  1503. a) It needs Ptr to Fax Server, to create Extensions/Methods Collections
  1504. each time it is asked to.
  1505. b) Fax Server caches it, to allow fast dot notation ( Server.InboundRouting.<...> )
  1506. --*/
  1507. {
  1508. HRESULT hr = S_OK;
  1509. DBG_ENTER (_T("CFaxServer::get_InboundRouting"), hr);
  1510. CObjectHandler<CFaxInboundRouting, IFaxInboundRouting> ObjectCreator;
  1511. hr = ObjectCreator.GetContainedObject(ppInboundRouting, &m_pInboundRouting, this);
  1512. if (FAILED(hr))
  1513. {
  1514. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1515. return hr;
  1516. }
  1517. return hr;
  1518. }
  1519. //
  1520. //================== GET SECURITY OBJECT ==============================
  1521. //
  1522. STDMETHODIMP
  1523. CFaxServer::get_Security(
  1524. IFaxSecurity **ppSecurity
  1525. )
  1526. /*++
  1527. Routine name : CFaxServer::get_Security
  1528. Routine description:
  1529. Return Security Object
  1530. Author:
  1531. Iv Garber (IvG), June, 2000
  1532. Arguments:
  1533. ppSecurity [out] - the Security Object
  1534. Return Value:
  1535. Standard HRESULT code
  1536. --*/
  1537. {
  1538. HRESULT hr = S_OK;
  1539. DBG_ENTER (_T("CFaxServer::get_Security"), hr);
  1540. CObjectHandler<CFaxSecurity, IFaxSecurity> ObjectCreator;
  1541. hr = ObjectCreator.GetContainedObject(ppSecurity, &m_pSecurity, this);
  1542. if (FAILED(hr))
  1543. {
  1544. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1545. return hr;
  1546. }
  1547. return hr;
  1548. }
  1549. //
  1550. //================== GET ACTIVITY OBJECT ==============================
  1551. //
  1552. STDMETHODIMP
  1553. CFaxServer::get_Activity(
  1554. IFaxActivity **ppActivity
  1555. )
  1556. /*++
  1557. Routine name : CFaxServer::get_Activity
  1558. Routine description:
  1559. Return Activity Object
  1560. Author:
  1561. Iv Garber (IvG), June, 2000
  1562. Arguments:
  1563. ppActivity [out] - the Activity Object
  1564. Return Value:
  1565. Standard HRESULT code
  1566. --*/
  1567. {
  1568. HRESULT hr = S_OK;
  1569. DBG_ENTER (_T("CFaxServer::get_Activity"), hr);
  1570. CObjectHandler<CFaxActivity, IFaxActivity> ObjectCreator;
  1571. hr = ObjectCreator.GetContainedObject(ppActivity, &m_pActivity, this);
  1572. if (FAILED(hr))
  1573. {
  1574. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1575. return hr;
  1576. }
  1577. return hr;
  1578. }
  1579. //
  1580. //================== GET LOGGING OPTIONS OBJECT ==============================
  1581. //
  1582. STDMETHODIMP
  1583. CFaxServer::get_LoggingOptions(
  1584. IFaxLoggingOptions **ppLoggingOptions
  1585. )
  1586. /*++
  1587. Routine name : CFaxServer::get_LoggingOptions
  1588. Routine description:
  1589. Return Logging Options Object
  1590. Author:
  1591. Iv Garber (IvG), June, 2000
  1592. Arguments:
  1593. ppLoggingOptions [out] - the Logging Options Object
  1594. Return Value:
  1595. Standard HRESULT code
  1596. --*/
  1597. {
  1598. HRESULT hr = S_OK;
  1599. DBG_ENTER (_T("CFaxServer::get_LoggingOptions"), hr);
  1600. CObjectHandler<CFaxLoggingOptions, IFaxLoggingOptions> ObjectCreator;
  1601. hr = ObjectCreator.GetContainedObject(ppLoggingOptions, &m_pLoggingOptions, this);
  1602. if (FAILED(hr))
  1603. {
  1604. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1605. return hr;
  1606. }
  1607. return hr;
  1608. }
  1609. //
  1610. //==================== GET HANDLE =====================================
  1611. //
  1612. STDMETHODIMP
  1613. CFaxServer::GetHandle(
  1614. /*[out, retval]*/ HANDLE* pFaxHandle
  1615. )
  1616. /*++
  1617. Routine name : CFaxServer::GetHandle
  1618. Routine description:
  1619. Return Handle to the Fax Server, if possible
  1620. Author:
  1621. Iv Garber (IvG), Apr, 2000
  1622. Arguments:
  1623. seqId [in] - the seqId of the Caller
  1624. Return Value:
  1625. HANDLE to the Fax Server
  1626. --*/
  1627. {
  1628. HRESULT hr = S_OK;
  1629. DBG_ENTER (_T("CFaxServer::GetHandle"), hr);
  1630. if (::IsBadWritePtr(pFaxHandle, sizeof(HANDLE *)))
  1631. {
  1632. //
  1633. // Got a bad return pointer
  1634. //
  1635. hr = E_POINTER;
  1636. CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr()"), hr);
  1637. return hr;
  1638. }
  1639. *pFaxHandle = m_faxHandle;
  1640. return hr;
  1641. } // CFaxServer::GetHandle
  1642. //
  1643. //==================== INTERFACE SUPPORT ERROR INFO =====================
  1644. //
  1645. STDMETHODIMP
  1646. CFaxServer::InterfaceSupportsErrorInfo(
  1647. REFIID riid
  1648. )
  1649. /*++
  1650. Routine name : CFaxServer::InterfaceSupportsErrorInfo
  1651. Routine description:
  1652. ATL's implementation of Support Error Info
  1653. Author:
  1654. Iv Garber (IvG), Apr, 2000
  1655. Arguments:
  1656. riid [in] - Reference to the Interface
  1657. Return Value:
  1658. Standard HRESULT code
  1659. --*/
  1660. {
  1661. static const IID* arr[] =
  1662. {
  1663. &IID_IFaxServer,
  1664. &IID_IFaxFolders, // Contained object
  1665. &IID_IFaxActivity, // Contained object
  1666. &IID_IFaxSecurity, // Contained object
  1667. &IID_IFaxReceiptOptions, // Contained object
  1668. &IID_IFaxLoggingOptions, // Contained object
  1669. &IID_IFaxInboundRouting, // Contained object
  1670. &IID_IFaxOutboundRouting // Contained object
  1671. };
  1672. for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
  1673. {
  1674. if (InlineIsEqualGUID(*arr[i],riid))
  1675. return S_OK;
  1676. }
  1677. return S_FALSE;
  1678. }
  1679. //
  1680. //================== GET FOLDERS OBJECT ==============================
  1681. //
  1682. STDMETHODIMP
  1683. CFaxServer::get_Folders(
  1684. IFaxFolders **ppFolders
  1685. )
  1686. /*++
  1687. Routine name : CFaxServer::get_Folders
  1688. Routine description:
  1689. Return Folders Shortcut Object
  1690. Author:
  1691. Iv Garber (IvG), Apr, 2000
  1692. Arguments:
  1693. pFaxFolders [out] - Fax Folders Object
  1694. Return Value:
  1695. Standard HRESULT code
  1696. --*/
  1697. {
  1698. HRESULT hr = S_OK;
  1699. DBG_ENTER (_T("CFaxServer::get_Folders"), hr);
  1700. CObjectHandler<CFaxFolders, IFaxFolders> ObjectCreator;
  1701. hr = ObjectCreator.GetContainedObject(ppFolders, &m_pFolders, this);
  1702. if (FAILED(hr))
  1703. {
  1704. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1705. return hr;
  1706. }
  1707. return hr;
  1708. }
  1709. //
  1710. //================== DISCONNECT =============================================
  1711. // {CR}
  1712. STDMETHODIMP
  1713. CFaxServer::Disconnect()
  1714. {
  1715. HRESULT hr = S_OK;
  1716. DBG_ENTER (_T("CFaxServer::Disconnect"), hr);
  1717. if (!m_faxHandle)
  1718. {
  1719. return hr;
  1720. }
  1721. //
  1722. // first UnListen, while we still connected
  1723. //
  1724. hr = ListenToServerEvents(fsetNONE);
  1725. if (FAILED(hr))
  1726. {
  1727. //
  1728. // Show the error, but continue
  1729. //
  1730. CALL_FAIL(GENERAL_ERR, _T("ListenToServerEvents(fsetNONE)"), hr);
  1731. }
  1732. if (!FaxClose(m_faxHandle))
  1733. {
  1734. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  1735. Error(IDS_ERROR_OPERATION_FAILED, IID_IFaxServer, hr);
  1736. CALL_FAIL(GENERAL_ERR, _T("FaxClose()"), hr);
  1737. return hr;
  1738. }
  1739. m_faxHandle = NULL;
  1740. m_bstrServerName.Empty();
  1741. return hr;
  1742. }
  1743. //
  1744. //=================== CONNECT =======================================
  1745. //{CR}
  1746. STDMETHODIMP CFaxServer::Connect(
  1747. BSTR bstrServerName
  1748. )
  1749. /*++
  1750. Routine name : CFaxServer::Connect
  1751. Routine description:
  1752. Connect to the given Fax Server
  1753. Author:
  1754. Iv Garber (IvG), May, 2000
  1755. Arguments:
  1756. bstrServerName [in] - Name of the Fax Server to Connect to
  1757. Return Value:
  1758. Standard HRESULT code
  1759. --*/
  1760. {
  1761. HANDLE h_tmpFaxHandle;
  1762. DWORD dwServerAPIVersion;
  1763. HRESULT hr = S_OK;
  1764. DBG_ENTER (_T("CFaxServer::Connect"), hr, _T("%s"), bstrServerName);
  1765. if (!FaxConnectFaxServer(m_bstrServerName, &h_tmpFaxHandle))
  1766. {
  1767. //
  1768. // Failed to Connect to the Server
  1769. //
  1770. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  1771. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1772. CALL_FAIL(GENERAL_ERR, _T("FaxConnectFaxServer()"), hr);
  1773. return hr;
  1774. }
  1775. ATLASSERT(h_tmpFaxHandle);
  1776. //
  1777. // Get API Version from the Fax Server
  1778. //
  1779. if (!FaxGetReportedServerAPIVersion(h_tmpFaxHandle, &dwServerAPIVersion))
  1780. {
  1781. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  1782. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1783. CALL_FAIL(GENERAL_ERR, _T("FaxGetReportedServerAPIVersion(h_tmpFaxHandle, &dwServerAPIVersion))"), hr);
  1784. FaxClose(h_tmpFaxHandle);
  1785. return hr;
  1786. }
  1787. //
  1788. // Block Whistler clients from connection to BOS servers
  1789. //
  1790. if (FAX_API_VERSION_1 > dwServerAPIVersion)
  1791. {
  1792. hr = Fax_HRESULT_FROM_WIN32(FAX_ERR_VERSION_MISMATCH);
  1793. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1794. CALL_FAIL(GENERAL_ERR, _T("Mismatch client and server versions"), hr);
  1795. FaxClose(h_tmpFaxHandle);
  1796. return hr;
  1797. }
  1798. if (m_faxHandle)
  1799. {
  1800. //
  1801. // Reconnect
  1802. //
  1803. hr = Disconnect();
  1804. if (FAILED(hr))
  1805. {
  1806. //
  1807. // Failed to DisConnect from the Previous Server
  1808. //
  1809. CALL_FAIL(DBG_MSG, _T("Disconnect()"), hr);
  1810. }
  1811. }
  1812. m_faxHandle = h_tmpFaxHandle;
  1813. m_bstrServerName = bstrServerName;
  1814. return hr;
  1815. }
  1816. //
  1817. //============== GET & PUT PROPERTIES ===============================
  1818. //
  1819. STDMETHODIMP CFaxServer::get_ServerName(
  1820. BSTR *pbstrServerName
  1821. )
  1822. /*++
  1823. Routine name : CFaxServer::get_ServerName
  1824. Routine description:
  1825. Return Name of the Server
  1826. Author:
  1827. Iv Garber (IvG), May, 2000
  1828. Arguments:
  1829. pbstrServerName [out] - Name of the Server to Return
  1830. Return Value:
  1831. Standard HRESULT code
  1832. --*/
  1833. {
  1834. HRESULT hr = S_OK;
  1835. DBG_ENTER(_T("CFaxServer::get_ServerName"), hr);
  1836. hr = GetBstr(pbstrServerName, m_bstrServerName);
  1837. if (FAILED(hr))
  1838. {
  1839. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1840. return hr;
  1841. }
  1842. return hr;
  1843. }
  1844. //
  1845. //============== MAIL OPTIONS OBJECT =========================================
  1846. //
  1847. STDMETHODIMP
  1848. CFaxServer::get_ReceiptOptions(
  1849. IFaxReceiptOptions **ppReceiptOptions
  1850. )
  1851. /*++
  1852. Routine name : CFaxServer::get_ReceiptOptions
  1853. Routine description:
  1854. Return Mail Options Object.
  1855. Author:
  1856. Iv Garber (IvG), May, 2000
  1857. Arguments:
  1858. ppReceiptOptions [out, retval] - Ptr to the place to put the object.
  1859. Return Value:
  1860. Standard HRESULT code
  1861. --*/
  1862. {
  1863. HRESULT hr = S_OK;
  1864. DBG_ENTER (_T("CFaxServer::get_ReceiptOptions"), hr);
  1865. CObjectHandler<CFaxReceiptOptions, IFaxReceiptOptions> ObjectCreator;
  1866. hr = ObjectCreator.GetContainedObject(ppReceiptOptions, &m_pReceiptOptions, this);
  1867. if (FAILED(hr))
  1868. {
  1869. Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
  1870. return hr;
  1871. }
  1872. return hr;
  1873. }