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.

764 lines
17 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. FaxQueueInner.h
  5. Abstract:
  6. Declaration and Implementation of Fax Queue Inner Template Class.
  7. Author:
  8. Iv Garber (IvG) May, 2000
  9. Revision History:
  10. --*/
  11. #ifndef __FAXQUEUEINNER_H_
  12. #define __FAXQUEUEINNER_H_
  13. #include "resource.h" // main symbols
  14. #include "FaxCommon.h"
  15. //
  16. //================ FAX QUEUE INNER =========================================
  17. //
  18. // Implementation of Commonality for Fax Incoming and Outgoing Queues
  19. //
  20. template <class T, const IID* piid, const CLSID* pcid, VARIANT_BOOL bIncoming,
  21. class JobIfc, class JobType, class CollectionIfc, class CollectionType>
  22. class CFaxQueueInner :
  23. public IDispatchImpl<T, piid, &LIBID_FAXCOMEXLib>,
  24. public CFaxInitInner
  25. {
  26. public:
  27. CFaxQueueInner() : CFaxInitInner(_T("FAX QUEUE INNER"))
  28. {
  29. m_bInited = FALSE;
  30. }
  31. virtual ~CFaxQueueInner()
  32. {};
  33. // Interfaces
  34. STDMETHOD(Save)();
  35. STDMETHOD(Refresh)();
  36. STDMETHOD(get_Blocked)(/*[out, retval]*/ VARIANT_BOOL *pbBlocked);
  37. STDMETHOD(put_Blocked)(/*[in]*/ VARIANT_BOOL bBlocked);
  38. STDMETHOD(get_Paused)(VARIANT_BOOL *pbPaused);
  39. STDMETHOD(put_Paused)(VARIANT_BOOL bPaused);
  40. STDMETHOD(GetJob)(/*[in]*/ BSTR bstrJobId, /*[out, retval]*/ JobIfc **pFaxJob);
  41. STDMETHOD(GetJobs)(/*[out, retval]*/CollectionIfc ** ppFaxJobsCollection);
  42. private:
  43. bool m_bInited;
  44. VARIANT_BOOL m_bBlocked;
  45. VARIANT_BOOL m_bPaused;
  46. };
  47. //
  48. //==================== BLOCKED ==========================================
  49. //
  50. template <class T, const IID* piid, const CLSID* pcid, VARIANT_BOOL bIncoming,
  51. class JobIfc, class JobType, class CollectionIfc, class CollectionType>
  52. STDMETHODIMP
  53. CFaxQueueInner<T, piid, pcid, bIncoming, JobIfc, JobType, CollectionIfc, CollectionType>
  54. ::get_Blocked(
  55. VARIANT_BOOL *pbBlocked
  56. )
  57. /*++
  58. Routine name : CFaxQueueInner::get_Blocked
  59. Routine description:
  60. Return Flag indicating whether or not the Queue is blocked
  61. Author:
  62. Iv Garber (IvG), May, 2000
  63. Arguments:
  64. pbBlocked [out] - Ptr to the Place to put Current value of the Flag
  65. Return Value:
  66. Standard HRESULT code
  67. --*/
  68. {
  69. HRESULT hr = S_OK;
  70. DBG_ENTER (TEXT("CFaxQueueInner::get_Blocked"), hr);
  71. //
  72. // sync first
  73. //
  74. if (!m_bInited)
  75. {
  76. hr = Refresh();
  77. if (FAILED(hr))
  78. {
  79. return hr;
  80. }
  81. }
  82. hr = GetVariantBool(pbBlocked, m_bBlocked);
  83. if (FAILED(hr))
  84. {
  85. AtlReportError(CLSID_FaxOutgoingQueue,GetErrorMsgId(hr), IID_IFaxOutgoingQueue, hr);
  86. return hr;
  87. }
  88. return hr;
  89. }
  90. template <class T, const IID* piid, const CLSID* pcid, VARIANT_BOOL bIncoming,
  91. class JobIfc, class JobType, class CollectionIfc, class CollectionType>
  92. STDMETHODIMP
  93. CFaxQueueInner<T, piid, pcid, bIncoming, JobIfc, JobType, CollectionIfc, CollectionType>
  94. ::put_Blocked(
  95. VARIANT_BOOL bBlocked
  96. )
  97. /*++
  98. Routine name : CFaxQueueInner::put_Blocked
  99. Routine description:
  100. Set new value for the Blocked flag
  101. Author:
  102. Iv Garber (IvG), May, 2000
  103. Arguments:
  104. bBlocked [in] - the new Value for the Blocked Flag
  105. Return Value:
  106. Standard HRESULT code
  107. --*/
  108. {
  109. HRESULT hr = S_OK;
  110. DBG_ENTER (_T("CFaxQueueInner::put_Blocked"), hr, _T("%d"), bBlocked);
  111. //
  112. // sync first
  113. //
  114. if (!m_bInited)
  115. {
  116. hr = Refresh();
  117. if (FAILED(hr))
  118. {
  119. return hr;
  120. }
  121. }
  122. m_bBlocked = bBlocked;
  123. return hr;
  124. }
  125. //
  126. //==================== REFRESH ==========================================
  127. //
  128. template <class T, const IID* piid, const CLSID* pcid, VARIANT_BOOL bIncoming,
  129. class JobIfc, class JobType, class CollectionIfc, class CollectionType>
  130. STDMETHODIMP
  131. CFaxQueueInner<T, piid, pcid, bIncoming, JobIfc, JobType, CollectionIfc, CollectionType>
  132. ::Refresh(
  133. )
  134. /*++
  135. Routine name : CFaxQueueInner::Refresh
  136. Routine description:
  137. Bring the Queue Configuration from the Fax Server.
  138. Author:
  139. Iv Garber (IvG), May, 2000
  140. Return Value:
  141. Standard HRESULT code.
  142. --*/
  143. {
  144. HRESULT hr = S_OK;
  145. DBG_ENTER (_T("CFaxQueueInner::Refresh"), hr);
  146. //
  147. // Get Fax Handle
  148. //
  149. HANDLE hFaxHandle = NULL;
  150. hr = GetFaxHandle(&hFaxHandle);
  151. if (FAILED(hr))
  152. {
  153. AtlReportError(*pcid, GetErrorMsgId(hr), *piid, hr);
  154. return hr;
  155. }
  156. //
  157. // Get Queue Status
  158. //
  159. DWORD dwQueueStates = 0;
  160. if (!FaxGetQueueStates(hFaxHandle, &dwQueueStates))
  161. {
  162. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  163. CALL_FAIL(GENERAL_ERR, _T("FaxGetQueueStates"), hr);
  164. AtlReportError(*pcid, GetErrorMsgId(hr), *piid, hr);
  165. return hr;
  166. }
  167. //
  168. // Extract the values
  169. //
  170. DWORD dwBlockState = (bIncoming) ? FAX_INCOMING_BLOCKED : FAX_OUTBOX_BLOCKED;
  171. m_bBlocked = (dwQueueStates & dwBlockState) ? VARIANT_TRUE : VARIANT_FALSE;
  172. if (!bIncoming)
  173. {
  174. m_bPaused = (dwQueueStates & FAX_OUTBOX_PAUSED) ? VARIANT_TRUE : VARIANT_FALSE;
  175. }
  176. m_bInited = true;
  177. return hr;
  178. }
  179. //
  180. //==================== SAVE ==========================================
  181. //
  182. template <class T, const IID* piid, const CLSID* pcid, VARIANT_BOOL bIncoming,
  183. class JobIfc, class JobType, class CollectionIfc, class CollectionType>
  184. STDMETHODIMP
  185. CFaxQueueInner<T, piid, pcid, bIncoming, JobIfc, JobType, CollectionIfc, CollectionType>
  186. ::Save(
  187. )
  188. /*++
  189. Routine name : CFaxQueueInner::Save
  190. Routine description:
  191. Save the current Queue Configuration to the Fax Server.
  192. Author:
  193. Iv Garber (IvG), May, 2000
  194. Return Value:
  195. Standard HRESULT code.
  196. --*/
  197. {
  198. HRESULT hr = S_OK;
  199. DBG_ENTER (_T("CFaxQueueInner::Save"), hr);
  200. //
  201. // Nothing changed
  202. //
  203. if (!m_bInited)
  204. {
  205. return hr;
  206. }
  207. //
  208. // Get Fax Handle
  209. //
  210. HANDLE hFaxHandle = NULL;
  211. hr = GetFaxHandle(&hFaxHandle);
  212. if (FAILED(hr))
  213. {
  214. AtlReportError(*pcid, GetErrorMsgId(hr), *piid, hr);
  215. return hr;
  216. }
  217. //
  218. // Get current Queue Status
  219. //
  220. DWORD dwQueueStates;
  221. if (!FaxGetQueueStates(hFaxHandle, &dwQueueStates))
  222. {
  223. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  224. CALL_FAIL(GENERAL_ERR, _T("FaxGetQueueStates"), hr);
  225. AtlReportError(*pcid, GetErrorMsgId(hr), *piid, hr);
  226. return hr;
  227. }
  228. //
  229. // Update it with our current state
  230. //
  231. DWORD dwBlockState = (bIncoming) ? FAX_INCOMING_BLOCKED : FAX_OUTBOX_BLOCKED;
  232. if (m_bBlocked == VARIANT_TRUE)
  233. {
  234. dwQueueStates |= dwBlockState;
  235. }
  236. else
  237. {
  238. dwQueueStates &= ~dwBlockState;
  239. }
  240. if (!bIncoming)
  241. {
  242. if (m_bPaused == VARIANT_TRUE)
  243. {
  244. dwQueueStates |= FAX_OUTBOX_PAUSED;
  245. }
  246. else
  247. {
  248. dwQueueStates &= ~FAX_OUTBOX_PAUSED;
  249. }
  250. }
  251. //
  252. // Store in the Server
  253. //
  254. if (!FaxSetQueue(hFaxHandle, dwQueueStates))
  255. {
  256. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  257. CALL_FAIL(GENERAL_ERR, _T("FaxSetQueue"), hr);
  258. AtlReportError(*pcid, GetErrorMsgId(hr), *piid, hr);
  259. return hr;
  260. }
  261. return hr;
  262. }
  263. //
  264. //==================== PAUSED ==========================================
  265. //
  266. template <class T, const IID* piid, const CLSID* pcid, VARIANT_BOOL bIncoming,
  267. class JobIfc, class JobType, class CollectionIfc, class CollectionType>
  268. STDMETHODIMP
  269. CFaxQueueInner<T, piid, pcid, bIncoming, JobIfc, JobType, CollectionIfc, CollectionType>
  270. ::get_Paused(
  271. VARIANT_BOOL *pbPaused
  272. )
  273. /*++
  274. Routine name : CFaxQueueInner::get_Paused
  275. Routine description:
  276. Return Flag indicating whether or not the Queue is paused
  277. Author:
  278. Iv Garber (IvG), May, 2000
  279. Arguments:
  280. pbPaused [out] - Ptr to the Place to put Current value of the Flag
  281. Return Value:
  282. Standard HRESULT code
  283. --*/
  284. {
  285. HRESULT hr = S_OK;
  286. DBG_ENTER (TEXT("CFaxQueueInner::get_Paused"), hr);
  287. //
  288. // sync first
  289. //
  290. if (!m_bInited)
  291. {
  292. hr = Refresh();
  293. if (FAILED(hr))
  294. {
  295. return hr;
  296. }
  297. }
  298. hr = GetVariantBool(pbPaused, m_bPaused);
  299. if (FAILED(hr))
  300. {
  301. AtlReportError(CLSID_FaxOutgoingQueue,GetErrorMsgId(hr), IID_IFaxOutgoingQueue, hr);
  302. return hr;
  303. }
  304. return hr;
  305. }
  306. template <class T, const IID* piid, const CLSID* pcid, VARIANT_BOOL bIncoming,
  307. class JobIfc, class JobType, class CollectionIfc, class CollectionType>
  308. STDMETHODIMP
  309. CFaxQueueInner<T, piid, pcid, bIncoming, JobIfc, JobType, CollectionIfc, CollectionType>
  310. ::put_Paused(
  311. VARIANT_BOOL bPaused
  312. )
  313. /*++
  314. Routine name : CFaxQueueInner::put_Paused
  315. Routine description:
  316. Set new value for the Paused flag
  317. Author:
  318. Iv Garber (IvG), May, 2000
  319. Arguments:
  320. bPaused [in] - the new Value for the Paused Flag
  321. Return Value:
  322. Standard HRESULT code
  323. --*/
  324. {
  325. HRESULT hr = S_OK;
  326. DBG_ENTER (_T("CFaxQueueInner::put_Paused"), hr, _T("%d"), bPaused);
  327. //
  328. // sync first
  329. //
  330. if (!m_bInited)
  331. {
  332. hr = Refresh();
  333. if (FAILED(hr))
  334. {
  335. return hr;
  336. }
  337. }
  338. m_bPaused = bPaused;
  339. return hr;
  340. }
  341. //
  342. //==================== GET JOB ==========================================
  343. //
  344. template <class T, const IID* piid, const CLSID* pcid, VARIANT_BOOL bIncoming,
  345. class JobIfc, class JobType, class CollectionIfc, class CollectionType>
  346. STDMETHODIMP
  347. CFaxQueueInner<T, piid, pcid, bIncoming, JobIfc, JobType, CollectionIfc, CollectionType>
  348. ::GetJob(
  349. /*[in]*/ BSTR bstrJobId,
  350. /*[out, retval]*/ JobIfc **ppFaxJob
  351. )
  352. /*++
  353. Routine name : CFaxQueueInner::GetJob
  354. Routine description:
  355. Return Job object corresponding to the given Job Id
  356. Author:
  357. Iv Garber (IvG), May, 2000
  358. Arguments:
  359. bstrJobId [in] - Id of the Job
  360. pFaxJob [out] - resulting Job Object
  361. Return Value:
  362. Standard HRESULT code
  363. --*/
  364. {
  365. HRESULT hr = S_OK;
  366. DBG_ENTER (TEXT("CFaxQueueInner::GetJob"), hr, _T("Job ID : %s"), bstrJobId);
  367. //
  368. // Check that we can write to the given pointer
  369. //
  370. if (::IsBadWritePtr(ppFaxJob, sizeof(JobIfc *)))
  371. {
  372. //
  373. // Got Bad Return Pointer
  374. //
  375. hr = E_POINTER;
  376. AtlReportError(*pcid, IDS_ERROR_INVALID_ARGUMENT, *piid, hr);
  377. CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr()"), hr);
  378. return hr;
  379. }
  380. //
  381. // no need to sync first
  382. //
  383. //
  384. // Get Fax Server Handle
  385. //
  386. HANDLE hFaxHandle = NULL;
  387. hr = GetFaxHandle(&hFaxHandle);
  388. if (FAILED(hr))
  389. {
  390. AtlReportError(*pcid, GetErrorMsgId(hr), *piid, hr);
  391. return hr;
  392. }
  393. //
  394. // convert Job Id that we've got to hexadecimal DWORDLONG
  395. //
  396. DWORDLONG dwlJobId;
  397. int iParsed = _stscanf (bstrJobId, _T("%I64x"), &dwlJobId);
  398. if ( iParsed != 1)
  399. {
  400. //
  401. // Failed to conver the number
  402. //
  403. hr = E_INVALIDARG;
  404. CALL_FAIL(GENERAL_ERR, _T("_stscanf()"), hr);
  405. AtlReportError(*pcid, IDS_ERROR_INVALIDMSGID, *piid, hr);
  406. return hr;
  407. }
  408. //
  409. // Get the Job Info from the Server
  410. //
  411. CFaxPtr<FAX_JOB_ENTRY_EX> pJobInfo;
  412. if (!FaxGetJobEx(hFaxHandle, dwlJobId, &pJobInfo))
  413. {
  414. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  415. AtlReportError(*pcid, GetErrorMsgId(hr), *piid, hr);
  416. CALL_FAIL(GENERAL_ERR, _T("FaxGetJobEx(hFaxHandle, m_JobInfo->dwlMessageId, &m_JobInfo)"), hr);
  417. return hr;
  418. }
  419. //
  420. // Check that pJobInfo is valid
  421. //
  422. if (!pJobInfo || pJobInfo->dwSizeOfStruct != sizeof(FAX_JOB_ENTRY_EX))
  423. {
  424. //
  425. // Failed to Get Job
  426. //
  427. hr = E_FAIL;
  428. AtlReportError(*pcid, IDS_ERROR_OPERATION_FAILED, *piid, hr);
  429. CALL_FAIL(GENERAL_ERR, _T("Invalid pJobInfo"), hr);
  430. return hr;
  431. }
  432. //
  433. // Check that Type of the Job is compatible with the Type of the Queue
  434. //
  435. if (bIncoming)
  436. {
  437. if ( !((pJobInfo->pStatus->dwJobType) & JT_RECEIVE) &&
  438. !((pJobInfo->pStatus->dwJobType) & JT_ROUTING) )
  439. {
  440. //
  441. // the desired Job is not Incoming
  442. //
  443. hr = Fax_HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  444. AtlReportError(*pcid, IDS_ERROR_INVALIDMSGID, *piid, hr);
  445. CALL_FAIL(GENERAL_ERR, _T("The desired Job is NOT Incoming"), hr);
  446. return hr;
  447. }
  448. }
  449. else
  450. {
  451. if ( !((pJobInfo->pStatus->dwJobType) & JT_SEND) )
  452. {
  453. //
  454. // the desired Job is not Outgoing
  455. //
  456. hr = Fax_HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  457. AtlReportError(*pcid, IDS_ERROR_INVALIDMSGID, *piid, hr);
  458. CALL_FAIL(GENERAL_ERR, _T("The desired Job is NOT Outgoing"), hr);
  459. return hr;
  460. }
  461. }
  462. //
  463. // Create Job Object
  464. //
  465. CComPtr<JobIfc> pTmpJob;
  466. hr = JobType::Create(&pTmpJob);
  467. if (FAILED(hr))
  468. {
  469. //
  470. // Failed to create the Job object
  471. //
  472. AtlReportError(*pcid, IDS_ERROR_OPERATION_FAILED, *piid, hr);
  473. CALL_FAIL(GENERAL_ERR, _T("JobType::Create()"), hr);
  474. return hr;
  475. }
  476. //
  477. // Initialize the Job Object
  478. //
  479. // Job will free the Job Info struct
  480. //
  481. hr = ((JobType *)((JobIfc *)pTmpJob))->Init(pJobInfo, m_pIFaxServerInner);
  482. if (FAILED(hr))
  483. {
  484. //
  485. // Failed to Init the Job Object
  486. //
  487. AtlReportError(*pcid, IDS_ERROR_OPERATION_FAILED, *piid, hr);
  488. CALL_FAIL(GENERAL_ERR, _T("<casted>pTmpJob->Init(pJobInfo, m_pIFaxServerInner)"), hr);
  489. return hr;
  490. }
  491. //
  492. // Return Job Object to the Caller
  493. //
  494. hr = pTmpJob.CopyTo(ppFaxJob);
  495. if (FAILED(hr))
  496. {
  497. //
  498. // Failed to Copy Interface
  499. //
  500. AtlReportError(*pcid, IDS_ERROR_OPERATION_FAILED, *piid, hr);
  501. CALL_FAIL(GENERAL_ERR, _T("CComPtr::CopyTo"), hr);
  502. return hr;
  503. }
  504. //
  505. // ppFaxJob uses this Job Info. Do not free the memory yet
  506. //
  507. pJobInfo.Detach();
  508. return hr;
  509. }
  510. //
  511. //==================== GET JOBS ==========================================
  512. //
  513. template <class T, const IID* piid, const CLSID* pcid, VARIANT_BOOL bIncoming,
  514. class JobIfc, class JobType, class CollectionIfc, class CollectionType>
  515. STDMETHODIMP
  516. CFaxQueueInner<T, piid, pcid, bIncoming, JobIfc, JobType, CollectionIfc, CollectionType>
  517. ::GetJobs(
  518. /*[out, retval]*/CollectionIfc ** ppJobsCollection)
  519. /*++
  520. Routine name : CFaxQueueInner::GetJobs
  521. Routine description:
  522. Return Jobs Collection
  523. Author:
  524. Iv Garber (IvG), May, 2000
  525. Arguments:
  526. ppFaxJobsCollection [out, retval] - the Jobs Collection
  527. Return Value:
  528. Standard HRESULT code
  529. --*/
  530. {
  531. HRESULT hr = S_OK;
  532. DBG_ENTER (TEXT("CFaxQueueInner::GetJobs"), hr);
  533. //
  534. // Check that we can write to the given pointer
  535. //
  536. if (::IsBadWritePtr(ppJobsCollection, sizeof(CollectionIfc *)))
  537. {
  538. //
  539. // Got Bad Return Pointer
  540. //
  541. hr = E_POINTER;
  542. AtlReportError(*pcid, IDS_ERROR_INVALID_ARGUMENT, *piid, hr);
  543. CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr()"), hr);
  544. return hr;
  545. }
  546. //
  547. // Get Fax Server Handle
  548. //
  549. HANDLE hFaxHandle = NULL;
  550. hr = GetFaxHandle(&hFaxHandle);
  551. if (FAILED(hr))
  552. {
  553. AtlReportError(*pcid, GetErrorMsgId(hr), *piid, hr);
  554. return hr;
  555. }
  556. //
  557. // Bring the Jobs from the Server
  558. //
  559. DWORD dwJobTypes;
  560. dwJobTypes = (bIncoming) ? (JT_RECEIVE | JT_ROUTING) : (JT_SEND);
  561. DWORD dwJobCount;
  562. CFaxPtr<FAX_JOB_ENTRY_EX> pJobCollection;
  563. if (!FaxEnumJobsEx(hFaxHandle, dwJobTypes, &pJobCollection, &dwJobCount))
  564. {
  565. //
  566. // Failed to Get the Job Collection
  567. //
  568. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  569. AtlReportError(*pcid, GetErrorMsgId(hr), *piid, hr);
  570. CALL_FAIL(GENERAL_ERR, _T("FaxEnumJobEx(hFaxHandle, dwJobTypes, &m_pJobCollection,...)"), hr);
  571. return hr;
  572. }
  573. //
  574. // Create Jobs Collection
  575. //
  576. CComPtr<CollectionIfc> pTmpJobCollection;
  577. hr = CollectionType::Create(&pTmpJobCollection);
  578. if (FAILED(hr))
  579. {
  580. //
  581. // Failed to create the Job Collection
  582. //
  583. AtlReportError(*pcid, IDS_ERROR_OPERATION_FAILED, *piid, hr);
  584. CALL_FAIL(GENERAL_ERR, _T("CollectionType::Create()"), hr);
  585. return hr;
  586. }
  587. //
  588. // Initialize the Job Collection
  589. // Job Collection will COPY all the data from pJobCollection
  590. //
  591. hr = ((CollectionType *)((CollectionIfc *)pTmpJobCollection))->Init(pJobCollection,
  592. dwJobCount,
  593. m_pIFaxServerInner);
  594. if (FAILED(hr))
  595. {
  596. //
  597. // Failed to Init the Job Collection
  598. //
  599. AtlReportError(*pcid, IDS_ERROR_OPERATION_FAILED, *piid, hr);
  600. CALL_FAIL(GENERAL_ERR, _T("pTmpJobCollection->Init(m_pJobCollection, m_pIFaxServerInner)"), hr);
  601. return hr;
  602. }
  603. //
  604. // Return Job Object to the Caller
  605. //
  606. hr = pTmpJobCollection.CopyTo(ppJobsCollection);
  607. if (FAILED(hr))
  608. {
  609. //
  610. // Failed to Copy Interface
  611. //
  612. AtlReportError(*pcid, IDS_ERROR_OPERATION_FAILED, *piid, hr);
  613. CALL_FAIL(GENERAL_ERR, _T("CComPtr::CopyTo"), hr);
  614. return hr;
  615. }
  616. return hr;
  617. }
  618. #endif //__FAXQUEUEINNER_H_