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.

873 lines
19 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. FaxCommon.cpp
  5. Abstract:
  6. Implementation of common Interfaces and Functions.
  7. Author:
  8. Iv Garber (IvG) May, 2000
  9. Revision History:
  10. --*/
  11. #include "StdAfx.h"
  12. #include "resource.h"
  13. #include "FaxComEx.h"
  14. #include "FaxCommon.h"
  15. #include "faxutil.h"
  16. #include "FaxServer.h"
  17. //
  18. //============= GET BSTR FROM DWORDLONG ==========================================
  19. //
  20. HRESULT
  21. GetBstrFromDwordlong(
  22. /*[in]*/ DWORDLONG dwlFrom,
  23. /*[out]*/ BSTR *pbstrTo
  24. )
  25. /*++
  26. Routine name : GetBstrFromDwordlong
  27. Routine description:
  28. Convert DWORDLONG into BSTR. Used in Message, and in Events in Server.
  29. Author:
  30. Iv Garber (IvG), Jul, 2000
  31. Arguments:
  32. dwlFrom [in] - DWORDLONG value to convert to BSTR
  33. pbstrTo [out] - ptr to the BSTR to return
  34. Return Value:
  35. Standard HRESULT code
  36. --*/
  37. {
  38. HRESULT hr = S_OK;
  39. DBG_ENTER(_T("GetBstrFromDwordlong"), hr, _T("DWORDLONG=%ld"), dwlFrom);
  40. //
  41. // Convert DWORDLONG into buffer of TCHARs
  42. //
  43. TCHAR tcBuffer[25];
  44. ::_i64tot(dwlFrom, tcBuffer, 16);
  45. //
  46. // Create BSTR from that buffer
  47. //
  48. BSTR bstrTemp;
  49. bstrTemp = ::SysAllocString(tcBuffer);
  50. if (!bstrTemp)
  51. {
  52. //
  53. // Not enough memory
  54. //
  55. hr = E_OUTOFMEMORY;
  56. CALL_FAIL(MEM_ERR, _T("SysAllocString()"), hr);
  57. return hr;
  58. }
  59. //
  60. // Return created BSTR
  61. //
  62. *pbstrTo = bstrTemp;
  63. return hr;
  64. }
  65. //
  66. //===================== GET EXTENSION PROPERTY ===============================================
  67. //
  68. HRESULT
  69. GetExtensionProperty(
  70. /*[in]*/ IFaxServerInner *pServer,
  71. /*[in]*/ long lDeviceId,
  72. /*[in]*/ BSTR bstrGUID,
  73. /*[out, retval]*/ VARIANT *pvProperty
  74. )
  75. /*++
  76. Routine name : GetExtensionProperty
  77. Routine description:
  78. Retrieves the Extension Data by given GUID from the Server.
  79. Used by FaxServer and FaxDevice Classes.
  80. Author:
  81. Iv Garber (IvG), Jun, 2000
  82. Arguments:
  83. pServer [in] -- Ptr to the Fax Server Object
  84. lDeviceId [in] -- Device Id with which the Extension Property is assosiated
  85. bstrGUID [in] -- Extension's Data GUID
  86. pvProperty [out] -- Variant with the Blob to Return
  87. Return Value:
  88. Standard HRESULT code
  89. --*/
  90. {
  91. HRESULT hr = S_OK;
  92. DBG_ENTER(_T("GetExtensionProperty"), hr, _T("GUID=%s"), bstrGUID);
  93. //
  94. // Check the pointer we have got
  95. //
  96. if (!pvProperty)
  97. {
  98. hr = E_POINTER;
  99. CALL_FAIL(GENERAL_ERR, _T("!pvProperty"), hr);
  100. return hr;
  101. }
  102. //
  103. // Get Fax Server Handle
  104. //
  105. HANDLE faxHandle;
  106. hr = pServer->GetHandle(&faxHandle);
  107. ATLASSERT(SUCCEEDED(hr));
  108. if (faxHandle == NULL)
  109. {
  110. //
  111. // Fax Server is not connected
  112. //
  113. hr = Fax_HRESULT_FROM_WIN32(ERROR_NOT_CONNECTED);
  114. CALL_FAIL(GENERAL_ERR, _T("faxHandle == NULL"), hr);
  115. return hr;
  116. }
  117. //
  118. // Ask Server to Get the Extension Property we want
  119. //
  120. CFaxPtrBase<void> pData;
  121. DWORD dwSize = 0;
  122. if (!FaxGetExtensionData(faxHandle, lDeviceId, bstrGUID, &pData, &dwSize))
  123. {
  124. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  125. CALL_FAIL(GENERAL_ERR, _T("FaxGetExtensionData(faxHandle, m_lID, bstrGUID, &pData, &dwSize)"), hr);
  126. return hr;
  127. }
  128. //
  129. // Create SafeArray to Return to User
  130. //
  131. hr = Binary2VarByteSA(((BYTE *)(pData.p)), pvProperty, dwSize);
  132. SecureZeroMemory(pData, dwSize);
  133. return hr;
  134. };
  135. //
  136. //===================== SET EXTENSION PROPERTY ===============================================
  137. // TODO: should work with empty vProperty
  138. //
  139. HRESULT
  140. SetExtensionProperty(
  141. /*[in]*/ IFaxServerInner *pServer,
  142. /*[in]*/ long lDeviceId,
  143. /*[in]*/ BSTR bstrGUID,
  144. /*[in]*/ VARIANT vProperty
  145. )
  146. /*++
  147. Routine name : SetExtensionProperty
  148. Routine description:
  149. Used by FaxDevice and FaxServer Classes, to Set the Extension Data by given GUID on the Server.
  150. Author:
  151. Iv Garber (IvG), Jun, 2000
  152. Arguments:
  153. pServer [in] -- Ptr to the Fax Server Object
  154. lDeviceId [in] -- Device Id with which the Extension Property is assosiated
  155. bstrGUID [in] -- Extension's Data GUID
  156. vProperty [in] -- Variant with the Blob to Set
  157. Return Value:
  158. Standard HRESULT code
  159. --*/
  160. {
  161. HRESULT hr = S_OK;
  162. DBG_ENTER(_T("SetExtensionProperty"), hr, _T("GUID=%s"), bstrGUID);
  163. //
  164. // Get Fax Server Handle
  165. //
  166. HANDLE faxHandle;
  167. hr = pServer->GetHandle(&faxHandle);
  168. ATLASSERT(SUCCEEDED(hr));
  169. if (faxHandle == NULL)
  170. {
  171. //
  172. // Fax Server is not connected
  173. //
  174. hr = Fax_HRESULT_FROM_WIN32(ERROR_NOT_CONNECTED);
  175. CALL_FAIL(GENERAL_ERR, _T("faxHandle == NULL"), hr);
  176. return hr;
  177. }
  178. //
  179. // check that Variant contains SafeArray
  180. //
  181. if (vProperty.vt != (VT_ARRAY | VT_UI1))
  182. {
  183. hr = E_INVALIDARG;
  184. CALL_FAIL(GENERAL_ERR, _T("(vProperty.vt != VT_ARRAY | VT_BYTE)"), hr);
  185. return hr;
  186. }
  187. //
  188. // Create Binary from the SafeArray we got
  189. //
  190. CFaxPtrLocal<void> pData;
  191. hr = VarByteSA2Binary(vProperty, (BYTE **)&pData);
  192. if (FAILED(hr))
  193. {
  194. return hr;
  195. }
  196. //
  197. // Ask Server to Set the Extension Property we want
  198. //
  199. DWORD dwLength = vProperty.parray->rgsabound[0].cElements;
  200. if (!FaxSetExtensionData(faxHandle, lDeviceId, bstrGUID, pData, dwLength))
  201. {
  202. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  203. CALL_FAIL(GENERAL_ERR, _T("FaxSetExtensionData(faxHandle, m_lID, bstrGUID, &pData, dwLength)"), hr);
  204. }
  205. SecureZeroMemory(pData, dwLength);
  206. return hr;
  207. };
  208. //
  209. //========================= GET LONG ========================================
  210. //
  211. HRESULT GetLong(
  212. long *plTo,
  213. long lFrom
  214. )
  215. /*++
  216. Routine name : GetLong
  217. Routine description:
  218. Check that plTo is valid
  219. Copy the given lFrom into plTo
  220. Author:
  221. Iv Garber (IvG), Jun, 2000
  222. Arguments:
  223. plTo [out] - Ptr to put the value
  224. lFrom [in] - value to put
  225. Return Value:
  226. Standard HRESULT code
  227. --*/
  228. {
  229. HRESULT hr = S_OK;
  230. DBG_ENTER (TEXT("GetLong"), hr, _T("lFrom=%d"), lFrom);
  231. //
  232. // Check that we have got good Ptr
  233. //
  234. if (::IsBadWritePtr(plTo, sizeof(long)))
  235. {
  236. hr = E_POINTER;
  237. CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr(plTo, sizeof(long))"), hr);
  238. return hr;
  239. }
  240. *plTo = lFrom;
  241. return hr;
  242. }
  243. //
  244. //========================= GET VARIANT BOOL ========================================
  245. //
  246. HRESULT GetVariantBool(
  247. VARIANT_BOOL *pbTo,
  248. VARIANT_BOOL bFrom
  249. )
  250. /*++
  251. Routine name : GetVariantBool
  252. Routine description:
  253. Check that pbTo is valid
  254. Copy the given bFrom into pbTo
  255. Author:
  256. Iv Garber (IvG), Jun, 2000
  257. Arguments:
  258. pbTo [out] - Ptr to put the value
  259. bFrom [in] - value to put
  260. Return Value:
  261. Standard HRESULT code
  262. --*/
  263. {
  264. HRESULT hr = S_OK;
  265. DBG_ENTER (TEXT("GetVariantBool"), hr, _T("bFrom=%d"), bFrom);
  266. //
  267. // Check that we have got good Ptr
  268. //
  269. if (::IsBadWritePtr(pbTo, sizeof(VARIANT_BOOL)))
  270. {
  271. hr = E_POINTER;
  272. CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr(pbTo, sizeof(VARIANT_BOOL))"), hr);
  273. return hr;
  274. }
  275. *pbTo = bFrom;
  276. return hr;
  277. }
  278. //
  279. //========================= GET BSTR ========================================
  280. //
  281. HRESULT GetBstr(
  282. BSTR *pbstrTo,
  283. BSTR bstrFrom
  284. )
  285. /*++
  286. Routine name : GetBstr
  287. Routine description:
  288. Check that pbstTo is valid
  289. SysAllocString for bstrFrom
  290. Copy the newly created string into pbstrTo
  291. Author:
  292. Iv Garber (IvG), Jun, 2000
  293. Arguments:
  294. pbstrTo [out] - Ptr to put the value
  295. bstrFrom [in] - Ptr to the string to return
  296. Return Value:
  297. Standard HRESULT code
  298. --*/
  299. {
  300. HRESULT hr = S_OK;
  301. DBG_ENTER (TEXT("GetBstr"), hr, _T("String=%s"), bstrFrom);
  302. //
  303. // Check that we have got good Ptr
  304. //
  305. if (::IsBadWritePtr(pbstrTo, sizeof(BSTR)))
  306. {
  307. hr = E_POINTER;
  308. CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr(pbstrTo, sizeof(BSTR))"), hr);
  309. return hr;
  310. }
  311. //
  312. // First copy the string locally
  313. //
  314. BSTR bstrTemp;
  315. bstrTemp = ::SysAllocString(bstrFrom);
  316. if (!bstrTemp && bstrFrom)
  317. {
  318. hr = E_OUTOFMEMORY;
  319. CALL_FAIL(MEM_ERR, _T("::SysAllocString(bstrFrom)"), hr);
  320. return hr;
  321. }
  322. *pbstrTo = bstrTemp;
  323. return hr;
  324. }
  325. //
  326. //======= CONVERNT BYTE BLOB INTO VARIANT CONTAINING BYTE SAFE ARRAY ============
  327. //
  328. HRESULT Binary2VarByteSA(
  329. BYTE *pbDataFrom,
  330. VARIANT *pvarTo,
  331. DWORD dwLength
  332. )
  333. {
  334. HRESULT hr = S_OK;
  335. DBG_ENTER(_T("Binary2VarByteSA"), hr, _T("Size=%d"), dwLength);
  336. //
  337. // Allocate the safe array : vector of Unsigned Chars
  338. //
  339. SAFEARRAY *pSafeArray;
  340. pSafeArray = ::SafeArrayCreateVector(VT_UI1, 0, dwLength);
  341. if (pSafeArray == NULL)
  342. {
  343. //
  344. // Not Enough Memory
  345. //
  346. hr = E_OUTOFMEMORY;
  347. CALL_FAIL(MEM_ERR, _T("::SafeArrayCreateVector(VT_UI1, 0, dwLength)"), hr);
  348. return hr;
  349. }
  350. //
  351. // get Access to the elements of the Safe Array
  352. //
  353. BYTE *pbElement;
  354. hr = ::SafeArrayAccessData(pSafeArray, (void **) &pbElement);
  355. if (FAILED(hr))
  356. {
  357. //
  358. // Failed to access safearray
  359. //
  360. hr = E_FAIL;
  361. CALL_FAIL(GENERAL_ERR, _T("::SafeArrayAccessData(pSafeArray, &pbElement)"), hr);
  362. SafeArrayDestroy(pSafeArray);
  363. return hr;
  364. }
  365. //
  366. // Fill the Safe Array with the bytes from pbDataFrom
  367. //
  368. memcpy(pbElement, pbDataFrom, dwLength);
  369. hr = ::SafeArrayUnaccessData(pSafeArray);
  370. if (FAILED(hr))
  371. {
  372. CALL_FAIL(GENERAL_ERR, _T("::SafeArrayUnaccessData(pSafeArray)"), hr);
  373. }
  374. //
  375. // Return the Safe Array inside the VARIANT we got
  376. //
  377. VariantInit(pvarTo);
  378. pvarTo->vt = VT_UI1 | VT_ARRAY;
  379. pvarTo->parray = pSafeArray;
  380. return hr;
  381. }
  382. //
  383. //======= CONVERNT VARIANT CONTAINING BYTE SAFE ARRAY INTO POINTER TO BYTES BLOB =========
  384. //
  385. HRESULT
  386. VarByteSA2Binary(
  387. VARIANT varFrom,
  388. BYTE **ppbData
  389. )
  390. {
  391. HRESULT hr = S_OK;
  392. DBG_ENTER(_T("VarByteSA2Binary"), hr);
  393. //
  394. // Check that Variant has right type
  395. //
  396. if ((varFrom.vt != VT_UI1) && (varFrom.vt != (VT_UI1 | VT_ARRAY)))
  397. {
  398. hr = E_INVALIDARG;
  399. CALL_FAIL(GENERAL_ERR, _T("pVarFrom->vt not VT_UI1 or VT_UI1 | VT_ARRAY"), hr);
  400. return hr;
  401. }
  402. ULONG ulNum = 0;
  403. SAFEARRAY *pSafeArray = NULL;
  404. //
  405. // Is there is only one member ?
  406. //
  407. if (varFrom.vt == VT_UI1)
  408. {
  409. ulNum = 1;
  410. }
  411. else
  412. {
  413. //
  414. // Get safe array values
  415. //
  416. pSafeArray = varFrom.parray;
  417. if (!pSafeArray)
  418. {
  419. hr = E_INVALIDARG;
  420. CALL_FAIL(GENERAL_ERR, _T("!pSafeArray ( = varFrom.parray )"), hr);
  421. return hr;
  422. }
  423. if (SafeArrayGetDim(pSafeArray) != 1)
  424. {
  425. hr = E_INVALIDARG;
  426. CALL_FAIL(GENERAL_ERR, _T("SafeArrayGetDim(pSafeArray) != 1"), hr);
  427. return hr;
  428. }
  429. if (pSafeArray->rgsabound[0].lLbound != 0)
  430. {
  431. hr = E_INVALIDARG;
  432. CALL_FAIL(GENERAL_ERR, _T("pSafeArray->rgsabound[0].lLbound != 0"), hr);
  433. return hr;
  434. }
  435. ulNum = pSafeArray->rgsabound[0].cElements;
  436. }
  437. //
  438. // Allocate memory for the safearray
  439. //
  440. *ppbData = (BYTE *)MemAlloc(ulNum);
  441. if (!*ppbData)
  442. {
  443. //
  444. // Not enough memory
  445. //
  446. hr = E_OUTOFMEMORY;
  447. CALL_FAIL(MEM_ERR, _T("MemAlloc(sizeof(ulNum)"), hr);
  448. return hr;
  449. }
  450. ZeroMemory(*ppbData, ulNum);
  451. //
  452. // Fill pbData with the values from the pSafeArray
  453. //
  454. if (!pSafeArray)
  455. {
  456. *ppbData[0] = varFrom.bVal;
  457. }
  458. else
  459. {
  460. //
  461. // Get Access to the Safe Array
  462. //
  463. BYTE *pbElement;
  464. hr = ::SafeArrayAccessData(pSafeArray, (void **) &pbElement);
  465. if (FAILED(hr))
  466. {
  467. hr = E_FAIL;
  468. MemFree (*ppbData);
  469. CALL_FAIL(GENERAL_ERR, _T("::SafeArrayAccessData(pSafeArray, &pbElement)"), hr);
  470. return hr;
  471. }
  472. //
  473. // Fill pbData with the values from the Safe Array
  474. //
  475. memcpy(*ppbData, pbElement, ulNum);
  476. hr = ::SafeArrayUnaccessData(pSafeArray);
  477. if (FAILED(hr))
  478. {
  479. CALL_FAIL(GENERAL_ERR, _T("::SafeArrayUnaccessData(pSafeArray)"), hr);
  480. }
  481. }
  482. return hr;
  483. } // VarByteSA2Binary
  484. //
  485. //======================= INIT ============================================
  486. //
  487. STDMETHODIMP
  488. CFaxInitInner::Init(
  489. /*[in]*/ IFaxServerInner* pServer
  490. )
  491. /*++
  492. Routine name : CFaxInitInner::Init
  493. Routine description:
  494. Store Ptr to the Fax Server. Used in most of the objects
  495. Author:
  496. Iv Garber (IvG), Apr, 2000
  497. Arguments:
  498. pServer [in] - Ptr to the Fax Server
  499. Return Value:
  500. Standard HRESULT code
  501. --*/
  502. {
  503. HRESULT hr = S_OK;
  504. DBG_ENTER (TEXT("CFaxInitInner::Init"), hr);
  505. m_pIFaxServerInner = pServer;
  506. return hr;
  507. }
  508. //
  509. //======================= GET FAX HANDLE ============================================
  510. //
  511. STDMETHODIMP
  512. CFaxInitInner::GetFaxHandle(
  513. /*[in]*/ HANDLE* pFaxHandle
  514. )
  515. /*++
  516. Routine name : CFaxInitInner::GetFaxHandle
  517. Routine description:
  518. Ask m_pIServerInner for handle to the fax server and handle error
  519. Author:
  520. Iv Garber (IvG), May, 2000
  521. Arguments:
  522. pFaxHandle [out] - Ptr to the returned Fax Handle
  523. Return Value:
  524. Standard HRESULT code
  525. --*/
  526. {
  527. HRESULT hr = S_OK;
  528. DBG_ENTER (TEXT("CFaxInitInner::GetFaxHandle"), hr);
  529. //
  530. // Get Fax Server Handle
  531. //
  532. hr = m_pIFaxServerInner->GetHandle(pFaxHandle);
  533. ATLASSERT(SUCCEEDED(hr));
  534. if (*pFaxHandle == NULL)
  535. {
  536. //
  537. // Fax Server is not connected
  538. //
  539. hr = Fax_HRESULT_FROM_WIN32(ERROR_NOT_CONNECTED);
  540. CALL_FAIL(GENERAL_ERR, _T("hFaxHandle==NULL"), hr);
  541. return hr;
  542. }
  543. return hr;
  544. }
  545. //
  546. //======================= GET ERROR MESSAGE ID ================================
  547. //
  548. LPCTSTR
  549. GetErrorMsgId(
  550. HRESULT hRes
  551. )
  552. /*++
  553. Routine name : GetErrorMsgId
  554. Routine description:
  555. Return IDS of the Message according to the given result of the RPC call
  556. and not only RPC
  557. Author:
  558. Iv Garber (IvG), May, 2000
  559. Arguments:
  560. hRes [in] - the RPC call result
  561. Return Value:
  562. UINT IDS of the Message to show to the User
  563. --*/
  564. {
  565. switch(hRes)
  566. {
  567. case E_POINTER:
  568. case HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER):
  569. return IDS_ERROR_INVALID_ARGUMENT;
  570. case E_OUTOFMEMORY:
  571. case HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY):
  572. return IDS_ERROR_OUTOFMEMORY;
  573. case HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED):
  574. return IDS_ERROR_ACCESSDENIED;
  575. case E_HANDLE:
  576. case HRESULT_FROM_WIN32(ERROR_NOT_CONNECTED):
  577. return IDS_ERROR_SERVER_NOT_CONNECTED;
  578. case HRESULT_FROM_WIN32(ERROR_UNSUPPORTED_TYPE):
  579. return IDS_ERROR_UNSUPPORTED_RECEIPT_TYPE;
  580. case HRESULT_FROM_WIN32(RPC_S_INVALID_BINDING):
  581. case HRESULT_FROM_WIN32(EPT_S_CANT_PERFORM_OP):
  582. case HRESULT_FROM_WIN32(RPC_S_ADDRESS_ERROR):
  583. case HRESULT_FROM_WIN32(RPC_S_CALL_CANCELLED):
  584. case HRESULT_FROM_WIN32(RPC_S_CALL_FAILED):
  585. case HRESULT_FROM_WIN32(RPC_S_CALL_FAILED_DNE):
  586. case HRESULT_FROM_WIN32(RPC_S_COMM_FAILURE):
  587. case HRESULT_FROM_WIN32(RPC_S_NO_BINDINGS):
  588. case HRESULT_FROM_WIN32(RPC_S_SERVER_TOO_BUSY):
  589. case HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE):
  590. return IDS_ERROR_CONNECTION_FAILED;
  591. case HRESULT_FROM_WIN32(ERROR_WRITE_PROTECT):
  592. return IDS_ERROR_QUEUE_BLOCKED;
  593. case FAX_E_FILE_ACCESS_DENIED:
  594. return IDS_ERROR_FILE_ACCESS_DENIED;
  595. case FAX_E_SRV_OUTOFMEMORY:
  596. return IDS_ERROR_SRV_OUTOFMEMORY;
  597. case FAX_E_GROUP_NOT_FOUND:
  598. return IDS_ERROR_GROUP_NOT_FOUND;
  599. case FAX_E_BAD_GROUP_CONFIGURATION:
  600. return IDS_ERROR_BAD_GROUP_CONFIGURATION;
  601. case FAX_E_GROUP_IN_USE:
  602. return IDS_ERROR_GROUP_IN_USE;
  603. case FAX_E_RULE_NOT_FOUND:
  604. return IDS_ERROR_RULE_NOT_FOUND;
  605. case FAX_E_NOT_NTFS:
  606. return IDS_ERROR_NOT_NTFS;
  607. case FAX_E_DIRECTORY_IN_USE:
  608. return IDS_ERROR_DIRECTORY_IN_USE;
  609. case FAX_E_MESSAGE_NOT_FOUND:
  610. return IDS_ERROR_MESSAGE_NOT_FOUND;
  611. case FAX_E_DEVICE_NUM_LIMIT_EXCEEDED:
  612. return IDS_ERROR_DEVICE_NUM_LIMIT_EXCEEDED;
  613. case FAX_E_NOT_SUPPORTED_ON_THIS_SKU:
  614. return IDS_ERROR_NOT_SUPPORTED_ON_THIS_SKU;
  615. case FAX_E_VERSION_MISMATCH:
  616. return IDS_ERROR_VERSION_MISMATCH;
  617. case FAX_E_RECIPIENTS_LIMIT:
  618. return IDS_ERROR_RECIPIENTS_LIMIT;
  619. default:
  620. return IDS_ERROR_OPERATION_FAILED;
  621. }
  622. }
  623. //
  624. //====================== SYSTEM TIME TO LOCAL DATE ============================================
  625. //
  626. HRESULT
  627. SystemTime2LocalDate(
  628. SYSTEMTIME sysTimeFrom,
  629. DATE *pdtTo
  630. )
  631. /*++
  632. Routine name : SystemTime2LocalDate
  633. Routine description:
  634. Convert the System Time stored in FAX_MESSAGE struct to the DATE understood by client
  635. Author:
  636. Iv Garber (IvG), May, 2000
  637. Arguments:
  638. tmFrom [in] - the System time to convert
  639. pdtTo [out] - the Date to return
  640. Return Value:
  641. Standard HRESULT code
  642. --*/
  643. {
  644. HRESULT hr = S_OK;
  645. DBG_ENTER (TEXT("SystemTime2LocalDate"), hr);
  646. //
  647. // convert System Time to File Time
  648. //
  649. FILETIME fileSysTime;
  650. if(!SystemTimeToFileTime(&sysTimeFrom, &fileSysTime))
  651. {
  652. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  653. CALL_FAIL (GENERAL_ERR, _T("SystemTimeToFileTime"), hr);
  654. return hr;
  655. }
  656. //
  657. // convert File Time to Local File Time
  658. //
  659. FILETIME fileLocalTime;
  660. if(!FileTimeToLocalFileTime(&fileSysTime, &fileLocalTime))
  661. {
  662. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  663. CALL_FAIL (GENERAL_ERR, _T("FileTimeToLocalFileTime"), hr);
  664. return hr;
  665. }
  666. //
  667. // convert Local File Time back to System Time
  668. //
  669. if(!FileTimeToSystemTime(&fileLocalTime, &sysTimeFrom))
  670. {
  671. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  672. CALL_FAIL (GENERAL_ERR, _T("FileTimeToSystemTime"), hr);
  673. return hr;
  674. }
  675. //
  676. // finally, convert now local System Time to Variant Time
  677. //
  678. if (!SystemTimeToVariantTime(&sysTimeFrom, pdtTo))
  679. {
  680. hr = Fax_HRESULT_FROM_WIN32(GetLastError());
  681. CALL_FAIL (GENERAL_ERR, _T("SystemTimeToVariantTime"), hr);
  682. return hr;
  683. }
  684. return hr;
  685. }