Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

760 lines
13 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. faxport.cpp
  5. Abstract:
  6. This module implements the port interface/object.
  7. Author:
  8. Wesley Witt (wesw) 20-May-1997
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "faxport.h"
  13. #include "faxroute.h"
  14. #include "status.h"
  15. CFaxPort::CFaxPort()
  16. {
  17. m_pFaxServer = NULL;
  18. m_FaxPortHandle = NULL;
  19. m_LastFaxError = NO_ERROR;
  20. m_DeviceId = 0;
  21. m_Rings = 0;
  22. m_Send = FALSE;
  23. m_Receive = FALSE;
  24. m_Name = NULL;
  25. m_Csid = NULL;
  26. m_Tsid = NULL;
  27. m_Modify = FALSE;
  28. }
  29. CFaxPort::~CFaxPort()
  30. {
  31. if (m_FaxPortHandle) {
  32. FaxClose( m_FaxPortHandle );
  33. }
  34. if (m_pFaxServer) {
  35. m_pFaxServer->Release();
  36. }
  37. if (m_Name) {
  38. SysFreeString( m_Name );
  39. }
  40. if (m_Csid) {
  41. SysFreeString( m_Csid );
  42. }
  43. if (m_Tsid) {
  44. SysFreeString( m_Tsid );
  45. }
  46. }
  47. BOOL
  48. CFaxPort::Initialize(
  49. CFaxServer *i_pFaxServer,
  50. DWORD i_DeviceId,
  51. DWORD i_Rings,
  52. DWORD i_Priority,
  53. DWORD i_Flags,
  54. LPCWSTR i_Csid,
  55. LPCWSTR i_Tsid,
  56. LPCWSTR i_DeviceName
  57. )
  58. {
  59. HRESULT hr;
  60. m_pFaxServer = i_pFaxServer;
  61. m_DeviceId = i_DeviceId;
  62. m_Rings = i_Rings;
  63. m_Priority = i_Priority;
  64. m_Csid = SysAllocString( i_Csid);
  65. m_Tsid = SysAllocString( i_Tsid);
  66. m_Name = SysAllocString( i_DeviceName );
  67. m_Send = i_Flags & FPF_SEND;
  68. m_Receive = i_Flags & FPF_RECEIVE;
  69. if ((!m_Csid && i_Csid) ||
  70. (!m_Tsid && i_Tsid) ||
  71. (!m_Name && i_DeviceName)) {
  72. SysFreeString( m_Csid );
  73. SysFreeString( m_Tsid );
  74. SysFreeString( m_Name );
  75. return FALSE;
  76. }
  77. if (!m_pFaxServer) {
  78. return FALSE;
  79. }
  80. hr = m_pFaxServer->AddRef();
  81. if (FAILED(hr)) {
  82. m_pFaxServer = NULL;
  83. return FALSE;
  84. }
  85. if (!FaxOpenPort( m_pFaxServer->GetFaxHandle(), m_DeviceId, PORT_OPEN_MODIFY | PORT_OPEN_QUERY, &m_FaxPortHandle )) {
  86. if (GetLastError() == ERROR_ACCESS_DENIED) {
  87. if (!FaxOpenPort( m_pFaxServer->GetFaxHandle(), m_DeviceId, PORT_OPEN_QUERY, &m_FaxPortHandle )) {
  88. m_LastFaxError = GetLastError();
  89. return FALSE;
  90. }
  91. } else {
  92. m_LastFaxError = GetLastError();
  93. return FALSE;
  94. }
  95. } else {
  96. m_Modify = TRUE;
  97. }
  98. return TRUE;
  99. }
  100. STDMETHODIMP CFaxPort::get_CanModify(BOOL * pVal)
  101. {
  102. if (!pVal) {
  103. return E_POINTER;
  104. }
  105. __try {
  106. *pVal = m_Modify;
  107. return S_OK;
  108. } __except (EXCEPTION_EXECUTE_HANDLER) {
  109. }
  110. return E_UNEXPECTED;
  111. }
  112. BOOL CFaxPort::ChangePort()
  113. {
  114. if (!m_Modify) {
  115. return FALSE;
  116. }
  117. //
  118. // get the current port configuration
  119. //
  120. PFAX_PORT_INFOW PortInfo = NULL;
  121. DWORD PortInfoSize = 0;
  122. if (!FaxGetPort( m_FaxPortHandle, &PortInfo )) {
  123. m_LastFaxError = GetLastError();
  124. return FALSE;
  125. }
  126. //
  127. // set the values
  128. //
  129. PortInfo->Rings = m_Rings;
  130. PortInfo->Priority = m_Priority;
  131. PortInfo->Flags = (PortInfo->Flags &~ (FPF_SEND | FPF_RECEIVE)) | (m_Send ? FPF_SEND : 0) | (m_Receive ? FPF_RECEIVE : 0);
  132. PortInfo->Csid = m_Csid;
  133. PortInfo->Tsid = m_Tsid;
  134. //
  135. // change the server's port configuration
  136. //
  137. if (!FaxSetPort( m_FaxPortHandle, PortInfo )) {
  138. m_LastFaxError = GetLastError();
  139. FaxFreeBuffer( PortInfo );
  140. return FALSE;
  141. }
  142. //
  143. // clean up and bail
  144. //
  145. FaxFreeBuffer( PortInfo );
  146. return TRUE;
  147. }
  148. STDMETHODIMP CFaxPort::get_Name(BSTR *pVal)
  149. {
  150. if (!pVal) {
  151. return E_POINTER;
  152. }
  153. BSTR Copy = SysAllocString(m_Name);
  154. if (!Copy && m_Name) {
  155. return E_OUTOFMEMORY;
  156. }
  157. __try {
  158. *pVal = Copy;
  159. return S_OK;
  160. } __except (EXCEPTION_EXECUTE_HANDLER) {
  161. SysFreeString(Copy);
  162. }
  163. return E_UNEXPECTED;
  164. }
  165. STDMETHODIMP CFaxPort::get_DeviceId(long * pVal)
  166. {
  167. if (!pVal) {
  168. return E_POINTER;
  169. }
  170. __try {
  171. *pVal = m_DeviceId;
  172. return S_OK;
  173. } __except (EXCEPTION_EXECUTE_HANDLER) {
  174. }
  175. return E_UNEXPECTED;
  176. }
  177. STDMETHODIMP CFaxPort::get_Rings(long * pVal)
  178. {
  179. if (!pVal) {
  180. return E_POINTER;
  181. }
  182. __try {
  183. *pVal = m_Rings;
  184. return S_OK;
  185. } __except (EXCEPTION_EXECUTE_HANDLER) {
  186. }
  187. return E_UNEXPECTED;
  188. }
  189. STDMETHODIMP CFaxPort::put_Rings(long newVal)
  190. {
  191. long old = m_Rings;
  192. if (!m_Modify) {
  193. return E_ACCESSDENIED;
  194. }
  195. m_Rings = newVal;
  196. if (!ChangePort()) {
  197. m_Rings = old;
  198. return HRESULT_FROM_WIN32(m_LastFaxError);
  199. }
  200. return S_OK;
  201. }
  202. STDMETHODIMP CFaxPort::get_Csid(BSTR * pVal)
  203. {
  204. if (!pVal) {
  205. return E_POINTER;
  206. }
  207. BSTR Copy = SysAllocString(m_Csid);
  208. if (!Copy && m_Csid) {
  209. return E_OUTOFMEMORY;
  210. }
  211. __try {
  212. *pVal = Copy;
  213. return S_OK;
  214. } __except (EXCEPTION_EXECUTE_HANDLER) {
  215. SysFreeString(Copy);
  216. }
  217. return E_UNEXPECTED;
  218. }
  219. STDMETHODIMP CFaxPort::put_Csid(BSTR newVal)
  220. {
  221. BSTR old = m_Csid;
  222. if (!m_Modify) {
  223. return E_ACCESSDENIED;
  224. }
  225. BSTR tmp = SysAllocString(newVal);
  226. if (!tmp && newVal) {
  227. return E_OUTOFMEMORY;
  228. }
  229. m_Csid = tmp;
  230. if (!ChangePort()) {
  231. m_Csid = old;
  232. SysFreeString(tmp);
  233. return HRESULT_FROM_WIN32(m_LastFaxError);
  234. }
  235. SysFreeString(old);
  236. return S_OK;
  237. }
  238. STDMETHODIMP CFaxPort::get_Tsid(BSTR * pVal)
  239. {
  240. if (!pVal) {
  241. return E_POINTER;
  242. }
  243. BSTR Copy = SysAllocString(m_Tsid);
  244. if (!Copy && m_Tsid) {
  245. return E_OUTOFMEMORY;
  246. }
  247. __try {
  248. *pVal = Copy;
  249. return S_OK;
  250. } __except (EXCEPTION_EXECUTE_HANDLER) {
  251. SysFreeString( m_Csid );
  252. }
  253. return E_UNEXPECTED;
  254. }
  255. STDMETHODIMP CFaxPort::put_Tsid(BSTR newVal)
  256. {
  257. BSTR old = m_Tsid;
  258. if (!m_Modify) {
  259. return E_ACCESSDENIED;
  260. }
  261. BSTR tmp = SysAllocString(newVal);
  262. if (!tmp && newVal) {
  263. return E_OUTOFMEMORY;
  264. }
  265. m_Tsid = tmp;
  266. if (!ChangePort()) {
  267. m_Tsid = old;
  268. SysFreeString(tmp);
  269. return HRESULT_FROM_WIN32(m_LastFaxError);
  270. }
  271. SysFreeString(old);
  272. return S_OK;
  273. }
  274. STDMETHODIMP CFaxPort::get_Send(BOOL * pVal)
  275. {
  276. if (!pVal) {
  277. return E_POINTER;
  278. }
  279. __try {
  280. *pVal = m_Send;
  281. return S_OK;
  282. } __except (EXCEPTION_EXECUTE_HANDLER) {
  283. }
  284. return E_UNEXPECTED;
  285. }
  286. STDMETHODIMP CFaxPort::put_Send(BOOL newVal)
  287. {
  288. BOOL old = m_Send;
  289. if (!m_Modify) {
  290. return E_ACCESSDENIED;
  291. }
  292. m_Send = newVal;
  293. if (!ChangePort()) {
  294. m_Send = old;
  295. return HRESULT_FROM_WIN32(m_LastFaxError);
  296. }
  297. return S_OK;
  298. }
  299. STDMETHODIMP CFaxPort::get_Receive(BOOL * pVal)
  300. {
  301. if (!pVal) {
  302. return E_POINTER;
  303. }
  304. __try {
  305. *pVal = m_Receive;
  306. return S_OK;
  307. } __except (EXCEPTION_EXECUTE_HANDLER) {
  308. }
  309. return E_UNEXPECTED;
  310. }
  311. STDMETHODIMP CFaxPort::put_Receive(BOOL newVal)
  312. {
  313. BOOL old = m_Receive;
  314. if (!m_Modify) {
  315. return E_ACCESSDENIED;
  316. }
  317. m_Receive = newVal;
  318. if (!ChangePort()) {
  319. m_Receive = old;
  320. return HRESULT_FROM_WIN32(m_LastFaxError);
  321. }
  322. return S_OK;
  323. }
  324. STDMETHODIMP CFaxPort::get_Priority(long * pVal)
  325. {
  326. if (!pVal) {
  327. return E_POINTER;
  328. }
  329. __try {
  330. *pVal = m_Priority;
  331. return S_OK;
  332. } __except (EXCEPTION_EXECUTE_HANDLER) {
  333. }
  334. return E_UNEXPECTED;
  335. }
  336. STDMETHODIMP CFaxPort::put_Priority(long newVal)
  337. {
  338. long old = m_Priority;
  339. if (!m_Modify) {
  340. return E_ACCESSDENIED;
  341. }
  342. m_Priority = newVal;
  343. if (!ChangePort()) {
  344. m_Priority = old;
  345. return HRESULT_FROM_WIN32(m_LastFaxError);
  346. }
  347. return S_OK;
  348. }
  349. STDMETHODIMP CFaxPort::GetRoutingMethods(VARIANT * retval)
  350. {
  351. HRESULT hr;
  352. if (!retval) {
  353. return E_POINTER;
  354. }
  355. CComObject<CFaxRoutingMethods>* p = new CComObject<CFaxRoutingMethods>;
  356. if (!p) {
  357. return E_OUTOFMEMORY;
  358. }
  359. if (!p->Init(this)) {
  360. delete p;
  361. return E_FAIL;
  362. }
  363. IDispatch* pDisp;
  364. hr = p->QueryInterface(IID_IDispatch, (void**)&pDisp);
  365. if (FAILED(hr)) {
  366. delete p;
  367. return hr;
  368. }
  369. __try {
  370. VariantInit(retval);
  371. retval->vt = VT_DISPATCH;
  372. retval->pdispVal = pDisp;
  373. return S_OK;
  374. } __except (EXCEPTION_EXECUTE_HANDLER) {
  375. }
  376. pDisp->Release();
  377. delete p;
  378. return E_UNEXPECTED;
  379. }
  380. STDMETHODIMP CFaxPort::GetStatus(VARIANT * retval)
  381. {
  382. HRESULT hr;
  383. if (!retval) {
  384. return E_POINTER;
  385. }
  386. CComObject<CFaxStatus>* p = new CComObject<CFaxStatus>;
  387. if (!p) {
  388. return E_OUTOFMEMORY;
  389. }
  390. if (!p->Init(this)) {
  391. delete p;
  392. return E_FAIL;
  393. }
  394. IDispatch* pDisp;
  395. hr = p->QueryInterface(IID_IDispatch, (void**)&pDisp);
  396. if (FAILED(hr)) {
  397. delete p;
  398. return hr;
  399. }
  400. __try {
  401. VariantInit(retval);
  402. retval->vt = VT_DISPATCH;
  403. retval->pdispVal = pDisp;
  404. return S_OK;
  405. } __except (EXCEPTION_EXECUTE_HANDLER) {
  406. }
  407. pDisp->Release();
  408. delete p;
  409. return E_UNEXPECTED;
  410. }
  411. CFaxPorts::CFaxPorts()
  412. {
  413. m_pFaxServer = NULL;
  414. m_LastFaxError = 0;
  415. m_PortCount = 0;
  416. m_VarVect = NULL;
  417. }
  418. CFaxPorts::~CFaxPorts()
  419. {
  420. if (m_pFaxServer) {
  421. m_pFaxServer->Release();
  422. }
  423. if (m_VarVect) {
  424. delete [] m_VarVect;
  425. }
  426. }
  427. BOOL CFaxPorts::Init(CFaxServer *pFaxServer)
  428. {
  429. PFAX_PORT_INFOW PortInfo = NULL;
  430. DWORD PortInfoSize = 0;
  431. HRESULT hr;
  432. //
  433. // get the ports from the server
  434. //
  435. if (!pFaxServer) {
  436. return FALSE;
  437. }
  438. m_pFaxServer = pFaxServer;
  439. hr = m_pFaxServer->AddRef();
  440. if (FAILED(hr)) {
  441. m_pFaxServer = NULL;
  442. return FALSE;
  443. }
  444. if (!FaxEnumPortsW( m_pFaxServer->GetFaxHandle(), &PortInfo, &m_PortCount )) {
  445. m_LastFaxError = GetLastError();
  446. return FALSE;
  447. }
  448. //
  449. // enumerate the ports
  450. //
  451. m_VarVect = new CComVariant[m_PortCount];
  452. if (!m_VarVect) {
  453. m_LastFaxError = ERROR_OUTOFMEMORY;
  454. FaxFreeBuffer( PortInfo );
  455. return FALSE;
  456. }
  457. for (DWORD i=0; i<m_PortCount; i++) {
  458. //
  459. // create the object
  460. //
  461. CComObject<CFaxPort> *pFaxPort;
  462. HRESULT hr = CComObject<CFaxPort>::CreateInstance( &pFaxPort );
  463. if (FAILED(hr)) {
  464. delete [] m_VarVect;
  465. m_VarVect = NULL;
  466. m_LastFaxError = hr;
  467. FaxFreeBuffer( PortInfo );
  468. return FALSE;
  469. }
  470. if (!pFaxPort->Initialize(
  471. pFaxServer,
  472. PortInfo[i].DeviceId,
  473. PortInfo[i].Rings,
  474. PortInfo[i].Priority,
  475. PortInfo[i].Flags,
  476. PortInfo[i].Csid,
  477. PortInfo[i].Tsid,
  478. PortInfo[i].DeviceName
  479. ))
  480. {
  481. delete [] m_VarVect;
  482. m_VarVect = NULL;
  483. m_LastFaxError = GetLastError();
  484. FaxFreeBuffer( PortInfo );
  485. return FALSE;
  486. }
  487. //
  488. // get IDispatch pointer
  489. //
  490. LPDISPATCH lpDisp = NULL;
  491. hr = pFaxPort->QueryInterface( IID_IDispatch, (void**)&lpDisp );
  492. if (FAILED(hr)) {
  493. delete [] m_VarVect;
  494. m_VarVect = NULL;
  495. m_LastFaxError = hr;
  496. FaxFreeBuffer( PortInfo );
  497. return FALSE;
  498. }
  499. //
  500. // create a variant and add it to the collection
  501. //
  502. __try {
  503. CComVariant &var = m_VarVect[i];
  504. var.vt = VT_DISPATCH;
  505. var.pdispVal = lpDisp;
  506. hr = S_OK;
  507. } __except (EXCEPTION_EXECUTE_HANDLER) {
  508. hr = E_UNEXPECTED;
  509. }
  510. if (FAILED(hr)) {
  511. delete [] m_VarVect;
  512. m_VarVect = NULL;
  513. m_LastFaxError = hr;
  514. FaxFreeBuffer( PortInfo );
  515. return FALSE;
  516. }
  517. }
  518. FaxFreeBuffer( PortInfo );
  519. return TRUE;
  520. }
  521. STDMETHODIMP CFaxPorts::get_Count(long * pVal)
  522. {
  523. if (!pVal) {
  524. return E_POINTER;
  525. }
  526. __try {
  527. *pVal = m_PortCount;
  528. return S_OK;
  529. } __except (EXCEPTION_EXECUTE_HANDLER) {
  530. }
  531. return E_UNEXPECTED;
  532. }
  533. STDMETHODIMP CFaxPorts::get_Item(long Index, VARIANT *retval)
  534. {
  535. if (!retval) {
  536. return E_POINTER;
  537. }
  538. if ((Index < 1) || (Index > (long) m_PortCount)) {
  539. return E_INVALIDARG;
  540. }
  541. __try {
  542. VariantInit( retval );
  543. retval->vt = VT_UNKNOWN;
  544. retval->punkVal = NULL;
  545. //
  546. // use 1-based index, VB like
  547. //
  548. return VariantCopy( retval, &m_VarVect[Index-1] );
  549. } __except (EXCEPTION_EXECUTE_HANDLER) {
  550. }
  551. return E_UNEXPECTED;
  552. }