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.

1736 lines
46 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. DeviceProp.cpp
  5. Abstract:
  6. Holds outbound routing configuraton per single device
  7. Author:
  8. Eran Yariv (EranY) Nov, 1999
  9. Revision History:
  10. --*/
  11. #include "faxrtp.h"
  12. #pragma hdrstop
  13. /************************************
  14. * *
  15. * Definitions *
  16. * *
  17. ************************************/
  18. //
  19. // Default values for configuration:
  20. //
  21. #define DEFAULT_FLAGS 0 // No routing method is enabled
  22. #define DEFAULT_STORE_FOLDER TEXT("")
  23. #define DEFAULT_MAIL_PROFILE TEXT("")
  24. #define DEFAULT_PRINTER_NAME TEXT("")
  25. //
  26. // The following array of GUID is used for registration / unregistration of notifications
  27. //
  28. LPCWSTR g_lpcwstrGUIDs[NUM_NOTIFICATIONS] =
  29. {
  30. REGVAL_RM_FLAGS_GUID, // GUID for routing methods usage flags
  31. REGVAL_RM_FOLDER_GUID, // GUID for store method folder
  32. REGVAL_RM_PRINTING_GUID, // GUID for print method printer name
  33. REGVAL_RM_EMAIL_GUID, // GUID for mail method address
  34. };
  35. static
  36. BOOL
  37. IsUnicodeString (
  38. LPBYTE lpData,
  39. DWORD dwDataSize
  40. )
  41. {
  42. if ( 0 != (dwDataSize % sizeof(WCHAR)) ||
  43. TEXT('\0') != ((LPCWSTR)(lpData))[dwDataSize / sizeof(WCHAR) - 1])
  44. {
  45. return FALSE;
  46. }
  47. return TRUE;
  48. } // IsUnicodeString
  49. /************************************
  50. * *
  51. * CDevicesMap *
  52. * *
  53. ************************************/
  54. DWORD
  55. CDevicesMap::Init ()
  56. /*++
  57. Routine name : CDevicesMap::Init
  58. Routine description:
  59. Initializes internal variables.
  60. Call only once before any other calls.
  61. Author:
  62. Eran Yariv (EranY), Nov, 1999
  63. Arguments:
  64. Return Value:
  65. Standard Win32 error code.
  66. --*/
  67. {
  68. DEBUG_FUNCTION_NAME(TEXT("CDevicesMap::Init"));
  69. if (m_bInitialized)
  70. {
  71. DebugPrintEx(
  72. DEBUG_ERR,
  73. TEXT("CDevicesMap::Init called more than once"));
  74. return ERROR_ALREADY_INITIALIZED;
  75. }
  76. m_bInitialized = TRUE;
  77. if (FAILED(SafeInitializeCriticalSection(&m_CsMap)))
  78. {
  79. m_bInitialized = FALSE;
  80. return GetLastError();
  81. }
  82. return ERROR_SUCCESS;
  83. } // CDevicesMap::Init
  84. CDevicesMap::~CDevicesMap ()
  85. {
  86. DEBUG_FUNCTION_NAME(TEXT("CDevicesMap::~CDevicesMap"));
  87. if (m_bInitialized)
  88. {
  89. DeleteCriticalSection (&m_CsMap);
  90. }
  91. try
  92. {
  93. for (DEVICES_MAP::iterator it = m_Map.begin(); it != m_Map.end(); ++it)
  94. {
  95. CDeviceRoutingInfo *pDevInfo = (*it).second;
  96. delete pDevInfo;
  97. }
  98. }
  99. catch (exception ex)
  100. {
  101. DebugPrintEx(
  102. DEBUG_ERR,
  103. TEXT("Got an STL exception while clearing the devices map (%S)"),
  104. ex.what());
  105. }
  106. } // CDevicesMap::~CDevicesMap
  107. CDeviceRoutingInfo *
  108. CDevicesMap::FindDeviceRoutingInfo (
  109. DWORD dwDeviceId
  110. )
  111. /*++
  112. Routine name : CDevicesMap::FindDeviceRoutingInfo
  113. Routine description:
  114. Finds a device in the map
  115. Author:
  116. Eran Yariv (EranY), Nov, 1999
  117. Arguments:
  118. dwDeviceId [in ] - Device id
  119. Return Value:
  120. Pointer to device object.
  121. If NULL, use GetLastError() to retrieve error code.
  122. --*/
  123. {
  124. DEVICES_MAP::iterator it;
  125. CDeviceRoutingInfo *pDevice = NULL;
  126. DEBUG_FUNCTION_NAME(TEXT("CDevicesMap::FindDeviceRoutingInfo"));
  127. if (!m_bInitialized)
  128. {
  129. //
  130. // Critical section failed to initialized
  131. //
  132. DebugPrintEx(
  133. DEBUG_ERR,
  134. TEXT("CDevicesMap::FindDeviceRoutingInfo called but CS is not initialized."));
  135. SetLastError (ERROR_GEN_FAILURE);
  136. return NULL;
  137. }
  138. EnterCriticalSection (&m_CsMap);
  139. try
  140. {
  141. if((it = m_Map.find(dwDeviceId)) == m_Map.end())
  142. {
  143. //
  144. // Device not found in map
  145. //
  146. SetLastError (ERROR_NOT_FOUND);
  147. goto exit;
  148. }
  149. else
  150. {
  151. //
  152. // Device found in map
  153. //
  154. pDevice = (*it).second;
  155. goto exit;
  156. }
  157. }
  158. catch (exception ex)
  159. {
  160. DebugPrintEx(
  161. DEBUG_ERR,
  162. TEXT("Got an STL exception while searching a devices map(%S)"),
  163. ex.what());
  164. SetLastError (ERROR_GEN_FAILURE);
  165. pDevice = NULL;
  166. goto exit;
  167. }
  168. exit:
  169. LeaveCriticalSection (&m_CsMap);
  170. return pDevice;
  171. } // CDevicesMap::FindDeviceRoutingInfo
  172. CDeviceRoutingInfo *
  173. CDevicesMap::GetDeviceRoutingInfo (
  174. DWORD dwDeviceId
  175. )
  176. /*++
  177. Routine name : CDevicesMap::GetDeviceRoutingInfo
  178. Routine description:
  179. Finds a device in the map.
  180. If not exists, attempts to create a new map entry.
  181. Author:
  182. Eran Yariv (EranY), Nov, 1999
  183. Arguments:
  184. dwDeviceId [in] - Device id
  185. Return Value:
  186. Pointer to device object.
  187. If NULL, use GetLastError() to retrieve error code.
  188. --*/
  189. {
  190. DEVICES_MAP::iterator it;
  191. DWORD dwRes;
  192. DEBUG_FUNCTION_NAME(TEXT("CDevicesMap::GetDeviceRoutingInfo"));
  193. if (!m_bInitialized)
  194. {
  195. //
  196. // Critical section failed to initialized
  197. //
  198. DebugPrintEx(
  199. DEBUG_ERR,
  200. TEXT("CDevicesMap::GetDeviceRoutingInfo called but CS is not initialized."));
  201. SetLastError (ERROR_GEN_FAILURE);
  202. return NULL;
  203. }
  204. EnterCriticalSection (&m_CsMap);
  205. //
  206. // Start by looking up the device in the map
  207. //
  208. CDeviceRoutingInfo *pDevice = FindDeviceRoutingInfo (dwDeviceId);
  209. if (NULL == pDevice)
  210. {
  211. //
  212. // Error finding device in map
  213. //
  214. if (ERROR_NOT_FOUND != GetLastError ())
  215. {
  216. //
  217. // Real error
  218. //
  219. goto exit;
  220. }
  221. //
  222. // The device is not in the map - add it now
  223. //
  224. DebugPrintEx(
  225. DEBUG_MSG,
  226. TEXT("Adding device %ld to routing map"),
  227. dwDeviceId);
  228. //
  229. // Allocate device
  230. //
  231. pDevice = new (std::nothrow) CDeviceRoutingInfo (dwDeviceId);
  232. if (!pDevice)
  233. {
  234. DebugPrintEx(
  235. DEBUG_MSG,
  236. TEXT("Cannot allocate memory for a CDeviceRoutingInfo"));
  237. SetLastError (ERROR_NOT_ENOUGH_MEMORY);
  238. goto exit;
  239. }
  240. //
  241. // Read configuration
  242. //
  243. dwRes = pDevice->ReadConfiguration ();
  244. if (ERROR_SUCCESS != dwRes)
  245. {
  246. delete pDevice;
  247. pDevice = NULL;
  248. SetLastError (dwRes);
  249. goto exit;
  250. }
  251. //
  252. // Add notification requests for the device
  253. //
  254. dwRes = pDevice->RegisterForChangeNotifications();
  255. if (ERROR_SUCCESS != dwRes)
  256. {
  257. delete pDevice;
  258. pDevice = NULL;
  259. SetLastError (dwRes);
  260. goto exit;
  261. }
  262. //
  263. // Add device to map
  264. //
  265. try
  266. {
  267. m_Map[dwDeviceId] = pDevice;
  268. }
  269. catch (exception ex)
  270. {
  271. DebugPrintEx(
  272. DEBUG_ERR,
  273. TEXT("Got an STL exception while trying to add a devices map entry (%S)"),
  274. ex.what());
  275. SetLastError (ERROR_GEN_FAILURE);
  276. pDevice->UnregisterForChangeNotifications();
  277. delete pDevice;
  278. pDevice = NULL;
  279. goto exit;
  280. }
  281. }
  282. else
  283. {
  284. //
  285. // Read the device configuration even if it in the map
  286. // to avoid the situation when the configuration change notification
  287. // arrive after the GetDeviceRoutingInfo() request.
  288. //
  289. dwRes = pDevice->ReadConfiguration ();
  290. if (ERROR_SUCCESS != dwRes)
  291. {
  292. DebugPrintEx(DEBUG_ERR, TEXT("CDeviceRoutingInfo::ReadConfiguration() failed with %ld"), dwRes);
  293. SetLastError (dwRes);
  294. goto exit;
  295. }
  296. }
  297. exit:
  298. LeaveCriticalSection (&m_CsMap);
  299. return pDevice;
  300. } // CDevicesMap::GetDeviceRoutingInfo
  301. /************************************
  302. * *
  303. * Pre-declarations *
  304. * *
  305. ************************************/
  306. static
  307. HRESULT
  308. FaxRoutingExtConfigChange (
  309. DWORD dwDeviceId, // The device for which configuration has changed
  310. LPCWSTR lpcwstrNameGUID, // Configuration name
  311. LPBYTE lpData, // New configuration data
  312. DWORD dwDataSize // Size of new configuration data
  313. );
  314. /************************************
  315. * *
  316. * Globals *
  317. * *
  318. ************************************/
  319. CDevicesMap g_DevicesMap; // Global map of known devices (used for late discovery).
  320. //
  321. // Extension data callbacks into the server:
  322. //
  323. PFAX_EXT_GET_DATA g_pFaxExtGetData = NULL;
  324. PFAX_EXT_SET_DATA g_pFaxExtSetData = NULL;
  325. PFAX_EXT_REGISTER_FOR_EVENTS g_pFaxExtRegisterForEvents = NULL;
  326. PFAX_EXT_UNREGISTER_FOR_EVENTS g_pFaxExtUnregisterForEvents = NULL;
  327. PFAX_EXT_FREE_BUFFER g_pFaxExtFreeBuffer = NULL;
  328. /************************************
  329. * *
  330. * Exported DLL function *
  331. * *
  332. ************************************/
  333. HRESULT
  334. FaxExtInitializeConfig (
  335. PFAX_EXT_GET_DATA pFaxExtGetData,
  336. PFAX_EXT_SET_DATA pFaxExtSetData,
  337. PFAX_EXT_REGISTER_FOR_EVENTS pFaxExtRegisterForEvents,
  338. PFAX_EXT_UNREGISTER_FOR_EVENTS pFaxExtUnregisterForEvents,
  339. PFAX_EXT_FREE_BUFFER pFaxExtFreeBuffer
  340. )
  341. /*++
  342. Routine name : FaxExtInitializeConfig
  343. Routine description:
  344. Exported function called by the service to initialize extension data mechanism
  345. Author:
  346. Eran Yariv (EranY), Nov, 1999
  347. Arguments:
  348. pFaxExtGetData [in] - Pointer to FaxExtGetData
  349. pFaxExtSetData [in] - Pointer to FaxExtSetData
  350. pFaxExtRegisterForEvents [in] - Pointer to FaxExtRegisterForEvents
  351. pFaxExtUnregisterForEvents [in] - Pointer to FaxExtUnregisterForEvents
  352. pFaxExtFreeBuffer [in] - Pointer to FaxExtFreeBuffer
  353. Return Value:
  354. Standard HRESULT code
  355. --*/
  356. {
  357. DEBUG_FUNCTION_NAME(TEXT("FaxExtInitializeConfig"));
  358. Assert (pFaxExtGetData &&
  359. pFaxExtSetData &&
  360. pFaxExtRegisterForEvents &&
  361. pFaxExtUnregisterForEvents &&
  362. pFaxExtFreeBuffer);
  363. g_pFaxExtGetData = pFaxExtGetData;
  364. g_pFaxExtSetData = pFaxExtSetData;
  365. g_pFaxExtRegisterForEvents = pFaxExtRegisterForEvents;
  366. g_pFaxExtUnregisterForEvents = pFaxExtUnregisterForEvents;
  367. g_pFaxExtFreeBuffer = pFaxExtFreeBuffer;
  368. return S_OK;
  369. } // FaxExtInitializeConfig
  370. /************************************
  371. * *
  372. * CDeviceRoutingInfo implementation *
  373. * *
  374. ************************************/
  375. CDeviceRoutingInfo::CDeviceRoutingInfo (DWORD dwId) :
  376. m_dwFlags (0),
  377. m_dwId (dwId)
  378. {
  379. memset (m_NotificationHandles, 0, sizeof (m_NotificationHandles));
  380. }
  381. CDeviceRoutingInfo::~CDeviceRoutingInfo ()
  382. {
  383. UnregisterForChangeNotifications ();
  384. }
  385. BOOL
  386. CDeviceRoutingInfo::GetStoreFolder (wstring &strFolder)
  387. {
  388. DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::GetStoreFolder"));
  389. EnterCriticalSection(&g_csRoutingStrings);
  390. try
  391. {
  392. strFolder = m_strStoreFolder;
  393. }
  394. catch(bad_alloc&)
  395. {
  396. LeaveCriticalSection(&g_csRoutingStrings);
  397. DebugPrintEx(
  398. DEBUG_ERR,
  399. TEXT("GetStoreFolder failed - not enough memory."));
  400. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  401. return FALSE;
  402. }
  403. LeaveCriticalSection(&g_csRoutingStrings);
  404. return TRUE;
  405. }
  406. BOOL
  407. CDeviceRoutingInfo::GetPrinter (wstring &strPrinter)
  408. {
  409. DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::GetPrinter"));
  410. EnterCriticalSection(&g_csRoutingStrings);
  411. try
  412. {
  413. strPrinter = m_strPrinter;
  414. }
  415. catch(bad_alloc&)
  416. {
  417. LeaveCriticalSection(&g_csRoutingStrings);
  418. DebugPrintEx(
  419. DEBUG_ERR,
  420. TEXT("GetPrinter failed - not enough memory."));
  421. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  422. return FALSE;
  423. }
  424. LeaveCriticalSection(&g_csRoutingStrings);
  425. return TRUE;
  426. }
  427. BOOL
  428. CDeviceRoutingInfo::GetSMTPTo (wstring &strSMTP)
  429. {
  430. DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::GetSMTPTo"));
  431. EnterCriticalSection(&g_csRoutingStrings);
  432. try
  433. {
  434. strSMTP = m_strSMTPTo;
  435. }
  436. catch(bad_alloc&)
  437. {
  438. LeaveCriticalSection(&g_csRoutingStrings);
  439. DebugPrintEx(
  440. DEBUG_ERR,
  441. TEXT("GetSMTPTo failed - not enough memory."));
  442. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  443. return FALSE;
  444. }
  445. LeaveCriticalSection(&g_csRoutingStrings);
  446. return TRUE;
  447. }
  448. DWORD
  449. CDeviceRoutingInfo::EnableStore (BOOL bEnabled)
  450. {
  451. //
  452. // See if we have a store folder configured
  453. //
  454. if (bEnabled)
  455. {
  456. EnterCriticalSection(&g_csRoutingStrings);
  457. if (0 == m_strStoreFolder.size())
  458. {
  459. //
  460. // Folder path name is ""
  461. //
  462. LeaveCriticalSection(&g_csRoutingStrings);
  463. return ERROR_BAD_CONFIGURATION;
  464. }
  465. DWORD dwRes = IsValidFaxFolder (m_strStoreFolder.c_str());
  466. LeaveCriticalSection(&g_csRoutingStrings);
  467. if (ERROR_SUCCESS != dwRes)
  468. {
  469. return ERROR_BAD_CONFIGURATION;
  470. }
  471. }
  472. return EnableFlag (LR_STORE, bEnabled);
  473. } // CDeviceRoutingInfo::EnableStore
  474. DWORD
  475. CDeviceRoutingInfo::EnablePrint (BOOL bEnabled)
  476. {
  477. //
  478. // See if we have a printer name configured
  479. //
  480. EnterCriticalSection(&g_csRoutingStrings);
  481. if (bEnabled && m_strPrinter.size() == 0)
  482. {
  483. LeaveCriticalSection(&g_csRoutingStrings);
  484. return ERROR_BAD_CONFIGURATION;
  485. }
  486. LeaveCriticalSection(&g_csRoutingStrings);
  487. return EnableFlag (LR_PRINT, bEnabled);
  488. }
  489. DWORD
  490. CDeviceRoutingInfo::EnableEmail (BOOL bEnabled)
  491. {
  492. if(bEnabled)
  493. {
  494. BOOL bMailConfigOK;
  495. DWORD dwRes = CheckMailConfig (&bMailConfigOK);
  496. if (ERROR_SUCCESS != dwRes)
  497. {
  498. return dwRes;
  499. }
  500. EnterCriticalSection(&g_csRoutingStrings);
  501. if (!bMailConfigOK || m_strSMTPTo.size() == 0)
  502. {
  503. LeaveCriticalSection(&g_csRoutingStrings);
  504. return ERROR_BAD_CONFIGURATION;
  505. }
  506. LeaveCriticalSection(&g_csRoutingStrings);
  507. }
  508. return EnableFlag (LR_EMAIL, bEnabled);
  509. }
  510. DWORD
  511. CDeviceRoutingInfo::CheckMailConfig (
  512. LPBOOL lpbConfigOk
  513. )
  514. {
  515. DWORD dwRes = ERROR_SUCCESS;
  516. PFAX_SERVER_RECEIPTS_CONFIGW pReceiptsConfiguration = NULL;
  517. DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::CheckMailConfig"));
  518. extern PGETRECIEPTSCONFIGURATION g_pGetRecieptsConfiguration;
  519. extern PFREERECIEPTSCONFIGURATION g_pFreeRecieptsConfiguration;
  520. *lpbConfigOk = FALSE;
  521. //
  522. // Read current receipts configuration
  523. //
  524. dwRes = g_pGetRecieptsConfiguration (&pReceiptsConfiguration, FALSE);
  525. if (ERROR_SUCCESS != dwRes)
  526. {
  527. DebugPrintEx(
  528. DEBUG_ERR,
  529. TEXT("GetRecieptsConfiguration failed with %ld"),
  530. dwRes);
  531. return dwRes;
  532. }
  533. //
  534. // Check that the user enbaled us (MS route to mail method) to use the receipts configuration
  535. //
  536. if (!pReceiptsConfiguration->bIsToUseForMSRouteThroughEmailMethod)
  537. {
  538. //
  539. // MS mail routing methods cannot use receipts SMTP settings
  540. //
  541. DebugPrintEx(
  542. DEBUG_ERR,
  543. TEXT("MS mail routing methods cannot use receipts SMTP settings"));
  544. goto exit;
  545. }
  546. if (!lstrlen(pReceiptsConfiguration->lptstrSMTPServer))
  547. {
  548. //
  549. // Server name is empty
  550. //
  551. DebugPrintEx(
  552. DEBUG_ERR,
  553. TEXT("Server name is empty"));
  554. goto exit;
  555. }
  556. if (!lstrlen(pReceiptsConfiguration->lptstrSMTPFrom))
  557. {
  558. //
  559. // Sender name is empty
  560. //
  561. DebugPrintEx(
  562. DEBUG_ERR,
  563. TEXT("Sender name is empty"));
  564. goto exit;
  565. }
  566. if (!pReceiptsConfiguration->dwSMTPPort)
  567. {
  568. //
  569. // SMTP port is invalid
  570. //
  571. DebugPrintEx(
  572. DEBUG_ERR,
  573. TEXT("SMTP port is invalid"));
  574. goto exit;
  575. }
  576. if ((FAX_SMTP_AUTH_BASIC == pReceiptsConfiguration->SMTPAuthOption) ||
  577. (FAX_SMTP_AUTH_NTLM == pReceiptsConfiguration->SMTPAuthOption))
  578. {
  579. //
  580. // Basic / NTLM authentication selected
  581. //
  582. if (!lstrlen(pReceiptsConfiguration->lptstrSMTPUserName) ||
  583. !lstrlen(pReceiptsConfiguration->lptstrSMTPPassword))
  584. {
  585. //
  586. // Username / password are bad
  587. //
  588. DebugPrintEx(
  589. DEBUG_ERR,
  590. TEXT("Username / password are bad"));
  591. goto exit;
  592. }
  593. }
  594. //
  595. // All is ok
  596. //
  597. *lpbConfigOk = TRUE;
  598. exit:
  599. if (NULL != pReceiptsConfiguration)
  600. {
  601. g_pFreeRecieptsConfiguration( pReceiptsConfiguration, TRUE);
  602. }
  603. return dwRes;
  604. } // CDeviceRoutingInfo::CheckMailConfig
  605. DWORD
  606. CDeviceRoutingInfo::RegisterForChangeNotifications ()
  607. /*++
  608. Routine name : CDeviceRoutingInfo::RegisterForChangeNotifications
  609. Routine description:
  610. Registres the device for notifications on configuration changes.
  611. Author:
  612. Eran Yariv (EranY), Nov, 1999
  613. Arguments:
  614. Return Value:
  615. Standard Win23 error code.
  616. --*/
  617. {
  618. DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::RegisterForChangeNotifications"));
  619. Assert (g_pFaxExtRegisterForEvents);
  620. memset (m_NotificationHandles, 0, sizeof (m_NotificationHandles));
  621. for (int iCurHandle = 0; iCurHandle < NUM_NOTIFICATIONS; iCurHandle++)
  622. {
  623. m_NotificationHandles[iCurHandle] = g_pFaxExtRegisterForEvents (
  624. g_hModule,
  625. m_dwId,
  626. DEV_ID_SRC_FAX, // Real fax device id
  627. g_lpcwstrGUIDs[iCurHandle],
  628. FaxRoutingExtConfigChange);
  629. if (NULL == m_NotificationHandles[iCurHandle])
  630. {
  631. //
  632. // Couldn't register this configuration object
  633. //
  634. break;
  635. }
  636. }
  637. if (iCurHandle < NUM_NOTIFICATIONS)
  638. {
  639. //
  640. // Error while registering at least one configuration object - undo previous registrations
  641. //
  642. DWORD dwErr = GetLastError ();
  643. UnregisterForChangeNotifications();
  644. return dwErr;
  645. }
  646. return ERROR_SUCCESS;
  647. } // CDeviceRoutingInfo::RegisterForChangeNotifications
  648. DWORD
  649. CDeviceRoutingInfo::UnregisterForChangeNotifications ()
  650. /*++
  651. Routine name : CDeviceRoutingInfo::UnregisterForChangeNotifications
  652. Routine description:
  653. Unregistres the device from notifications on configuration changes.
  654. Author:
  655. Eran Yariv (EranY), Nov, 1999
  656. Arguments:
  657. Return Value:
  658. Standard Win23 error code.
  659. --*/
  660. {
  661. DWORD dwRes;
  662. DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::UnregisterForChangeNotifications"));
  663. Assert (g_pFaxExtUnregisterForEvents);
  664. for (int iCurHandle = 0; iCurHandle < NUM_NOTIFICATIONS; iCurHandle++)
  665. {
  666. if (NULL != m_NotificationHandles[iCurHandle])
  667. {
  668. //
  669. // Found registred notification - unregister it
  670. //
  671. dwRes = g_pFaxExtUnregisterForEvents(m_NotificationHandles[iCurHandle]);
  672. if (ERROR_SUCCESS != dwRes)
  673. {
  674. DebugPrintEx(
  675. DEBUG_ERR,
  676. TEXT("Call to FaxExtUnregisterForEvents on handle 0x%08x failed with %ld"),
  677. m_NotificationHandles[iCurHandle],
  678. dwRes);
  679. return dwRes;
  680. }
  681. m_NotificationHandles[iCurHandle] = NULL;
  682. }
  683. }
  684. return ERROR_SUCCESS;
  685. } // CDeviceRoutingInfo::UnregisterForChangeNotifications
  686. DWORD
  687. CDeviceRoutingInfo::ReadConfiguration ()
  688. /*++
  689. Routine name : CDeviceRoutingInfo::ReadConfiguration
  690. Routine description:
  691. Reasd the routing configuration from the storage.
  692. If the storage doesn't contain configuration, default values are used.
  693. Author:
  694. Eran Yariv (EranY), Nov, 1999
  695. Arguments:
  696. Return Value:
  697. Standard Win23 error code.
  698. --*/
  699. {
  700. DWORD dwRes;
  701. LPBYTE lpData = NULL;
  702. DWORD dwDataSize;
  703. DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::ReadConfiguration"));
  704. //
  705. // Start by reading the flags data
  706. //
  707. dwRes = g_pFaxExtGetData ( m_dwId,
  708. DEV_ID_SRC_FAX, // We always use the Fax Device Id
  709. REGVAL_RM_FLAGS_GUID,
  710. &lpData,
  711. &dwDataSize
  712. );
  713. if (ERROR_SUCCESS != dwRes)
  714. {
  715. if (ERROR_FILE_NOT_FOUND == dwRes)
  716. {
  717. //
  718. // Data does not exist for this device. Try to read default values from unassociated data.
  719. //
  720. dwRes = g_pFaxExtGetData ( 0, // unassociated data
  721. DEV_ID_SRC_FAX, // We always use the Fax Device Id
  722. REGVAL_RM_FLAGS_GUID,
  723. &lpData,
  724. &dwDataSize
  725. );
  726. if (ERROR_FILE_NOT_FOUND == dwRes)
  727. {
  728. //
  729. // Data does not exist for this device. Use default values.
  730. //
  731. DebugPrintEx(
  732. DEBUG_MSG,
  733. TEXT("No routing flags configuration - using defaults"));
  734. m_dwFlags = DEFAULT_FLAGS;
  735. }
  736. }
  737. if (ERROR_SUCCESS != dwRes &&
  738. ERROR_FILE_NOT_FOUND != dwRes)
  739. {
  740. //
  741. // Can't read configuration
  742. //
  743. DebugPrintEx(
  744. DEBUG_ERR,
  745. TEXT("Error reading routing flags (ec = %ld)"),
  746. dwRes);
  747. return dwRes;
  748. }
  749. }
  750. if (NULL != lpData)
  751. {
  752. //
  753. // Data read successfully
  754. //
  755. if (sizeof (DWORD) != dwDataSize)
  756. {
  757. //
  758. // We're expecting a single DWORD here
  759. //
  760. DebugPrintEx(
  761. DEBUG_ERR,
  762. TEXT("Routing flags configuration has bad size (%ld) - expecting %ld"),
  763. dwDataSize,
  764. sizeof (DWORD));
  765. g_pFaxExtFreeBuffer (lpData);
  766. return ERROR_BADDB; // The configuration registry database is corrupt.
  767. }
  768. m_dwFlags = DWORD (*lpData);
  769. g_pFaxExtFreeBuffer (lpData);
  770. }
  771. try
  772. {
  773. lpData = NULL;
  774. //
  775. // Read store directory
  776. //
  777. dwRes = g_pFaxExtGetData ( m_dwId,
  778. DEV_ID_SRC_FAX, // We always use the Fax Device Id
  779. REGVAL_RM_FOLDER_GUID,
  780. &lpData,
  781. &dwDataSize
  782. );
  783. if (ERROR_SUCCESS != dwRes)
  784. {
  785. if (ERROR_FILE_NOT_FOUND == dwRes)
  786. {
  787. //
  788. // Data does not exist for this device. Try to read default values from unassociated data.
  789. //
  790. dwRes = g_pFaxExtGetData ( 0, // unassociated data
  791. DEV_ID_SRC_FAX, // We always use the Fax Device Id
  792. REGVAL_RM_FOLDER_GUID,
  793. &lpData,
  794. &dwDataSize
  795. );
  796. if (ERROR_FILE_NOT_FOUND == dwRes)
  797. {
  798. //
  799. // Data does not exist for this device. Use default values.
  800. //
  801. DebugPrintEx(
  802. DEBUG_MSG,
  803. TEXT("No routing store configuration - using defaults"));
  804. dwRes = SetStringValue(m_strStoreFolder, NULL, DEFAULT_STORE_FOLDER);
  805. if (dwRes != ERROR_SUCCESS)
  806. {
  807. return dwRes;
  808. }
  809. }
  810. }
  811. if (ERROR_SUCCESS != dwRes &&
  812. ERROR_FILE_NOT_FOUND != dwRes)
  813. {
  814. //
  815. // Can't read configuration
  816. //
  817. DebugPrintEx(
  818. DEBUG_ERR,
  819. TEXT("Error reading routing store configuration (ec = %ld)"),
  820. dwRes);
  821. return dwRes;
  822. }
  823. }
  824. if (NULL != lpData)
  825. {
  826. //
  827. // Data read successfully
  828. // make sure we have terminating NULL (defends from registry curruption)
  829. //
  830. if (!IsUnicodeString(lpData, dwDataSize))
  831. {
  832. //
  833. // No NULL terminator, return failure
  834. //
  835. DebugPrintEx(
  836. DEBUG_ERR,
  837. TEXT("Error reading routing store configuration, no NULL terminator.")
  838. );
  839. g_pFaxExtFreeBuffer (lpData);
  840. return ERROR_BAD_CONFIGURATION;
  841. }
  842. dwRes = SetStringValue(m_strStoreFolder, NULL, LPCWSTR(lpData));
  843. if (dwRes != ERROR_SUCCESS)
  844. {
  845. return dwRes;
  846. }
  847. g_pFaxExtFreeBuffer (lpData);
  848. }
  849. lpData = NULL;
  850. //
  851. // Read printer name
  852. //
  853. dwRes = g_pFaxExtGetData ( m_dwId,
  854. DEV_ID_SRC_FAX, // We always use the Fax Device Id
  855. REGVAL_RM_PRINTING_GUID,
  856. &lpData,
  857. &dwDataSize
  858. );
  859. if (ERROR_SUCCESS != dwRes)
  860. {
  861. if (ERROR_FILE_NOT_FOUND == dwRes)
  862. {
  863. //
  864. // Data does not exist for this device. Try to read default values from unassociated data.
  865. //
  866. dwRes = g_pFaxExtGetData ( 0, // unassociated data
  867. DEV_ID_SRC_FAX, // We always use the Fax Device Id
  868. REGVAL_RM_PRINTING_GUID,
  869. &lpData,
  870. &dwDataSize
  871. );
  872. if (ERROR_FILE_NOT_FOUND == dwRes)
  873. {
  874. //
  875. // Data does not exist for this device. Use default values.
  876. //
  877. DebugPrintEx(
  878. DEBUG_MSG,
  879. TEXT("No routing print configuration - using defaults"));
  880. dwRes = SetStringValue(m_strPrinter, NULL, DEFAULT_PRINTER_NAME);
  881. if (dwRes != ERROR_SUCCESS)
  882. {
  883. return dwRes;
  884. }
  885. }
  886. }
  887. if (ERROR_SUCCESS != dwRes &&
  888. ERROR_FILE_NOT_FOUND != dwRes)
  889. {
  890. //
  891. // Can't read configuration
  892. //
  893. DebugPrintEx(
  894. DEBUG_ERR,
  895. TEXT("Error reading routing print configuration (ec = %ld)"),
  896. dwRes);
  897. return dwRes;
  898. }
  899. }
  900. if (NULL != lpData)
  901. {
  902. //
  903. // Data read successfully
  904. // make sure we have terminating NULL (defends from registry curruption)
  905. //
  906. if (!IsUnicodeString(lpData, dwDataSize))
  907. {
  908. //
  909. // No NULL terminator, return failure
  910. //
  911. DebugPrintEx(
  912. DEBUG_ERR,
  913. TEXT("Error reading routing print configuration, no NULL terminator.")
  914. );
  915. g_pFaxExtFreeBuffer (lpData);
  916. return ERROR_BAD_CONFIGURATION;
  917. }
  918. dwRes = SetStringValue(m_strPrinter, NULL, LPCWSTR (lpData));
  919. if (dwRes != ERROR_SUCCESS)
  920. {
  921. return dwRes;
  922. }
  923. g_pFaxExtFreeBuffer (lpData);
  924. }
  925. lpData = NULL;
  926. //
  927. // Read email address
  928. //
  929. dwRes = g_pFaxExtGetData ( m_dwId,
  930. DEV_ID_SRC_FAX, // We always use the Fax Device Id
  931. REGVAL_RM_EMAIL_GUID,
  932. &lpData,
  933. &dwDataSize
  934. );
  935. if (ERROR_SUCCESS != dwRes)
  936. {
  937. if (ERROR_FILE_NOT_FOUND == dwRes)
  938. {
  939. //
  940. // Data does not exist for this device. Try to read default values from unassociated data.
  941. //
  942. dwRes = g_pFaxExtGetData ( 0,
  943. DEV_ID_SRC_FAX, // We always use the Fax Device Id
  944. REGVAL_RM_EMAIL_GUID,
  945. &lpData,
  946. &dwDataSize
  947. );
  948. if (ERROR_FILE_NOT_FOUND == dwRes)
  949. {
  950. //
  951. // Data does not exist for this device. Use default values.
  952. //
  953. DebugPrintEx(
  954. DEBUG_MSG,
  955. TEXT("No routing email configuration - using defaults"));
  956. dwRes = SetStringValue(m_strSMTPTo, NULL, DEFAULT_MAIL_PROFILE);
  957. if (dwRes != ERROR_SUCCESS)
  958. {
  959. return dwRes;
  960. }
  961. }
  962. }
  963. if (ERROR_SUCCESS != dwRes &&
  964. ERROR_FILE_NOT_FOUND != dwRes)
  965. {
  966. //
  967. // Can't read configuration
  968. //
  969. DebugPrintEx(
  970. DEBUG_ERR,
  971. TEXT("Error reading routing email configuration (ec = %ld)"),
  972. dwRes);
  973. return dwRes;
  974. }
  975. }
  976. if (NULL != lpData)
  977. {
  978. //
  979. // Data read successfully
  980. // make sure we have terminating NULL (defends from registry curruption)
  981. //
  982. if (!IsUnicodeString(lpData, dwDataSize))
  983. {
  984. //
  985. // No NULL terminator, return failure
  986. //
  987. DebugPrintEx(
  988. DEBUG_ERR,
  989. TEXT("Error reading routing email configuration, no NULL terminator.")
  990. );
  991. g_pFaxExtFreeBuffer (lpData);
  992. return ERROR_BAD_CONFIGURATION;
  993. }
  994. dwRes = SetStringValue(m_strSMTPTo, NULL, LPCWSTR(lpData));
  995. if (dwRes != ERROR_SUCCESS)
  996. {
  997. return dwRes;
  998. }
  999. g_pFaxExtFreeBuffer (lpData);
  1000. }
  1001. }
  1002. catch (exception ex)
  1003. {
  1004. DebugPrintEx(
  1005. DEBUG_ERR,
  1006. TEXT("Got an STL exception (%S)"),
  1007. ex.what());
  1008. //
  1009. // prevent leak when exception is thrown
  1010. //
  1011. if ( lpData )
  1012. {
  1013. g_pFaxExtFreeBuffer (lpData);
  1014. }
  1015. return ERROR_GEN_FAILURE;
  1016. }
  1017. return ERROR_SUCCESS;
  1018. } // CDeviceRoutingInfo::ReadConfiguration
  1019. HRESULT
  1020. CDeviceRoutingInfo::ConfigChange (
  1021. LPCWSTR lpcwstrNameGUID, // Configuration name
  1022. LPBYTE lpData, // New configuration data
  1023. DWORD dwDataSize // Size of new configuration data
  1024. )
  1025. /*++
  1026. Routine name : CDeviceRoutingInfo::ConfigChange
  1027. Routine description:
  1028. Handles configuration changes (by notification)
  1029. Author:
  1030. Eran Yariv (EranY), Nov, 1999
  1031. Arguments:
  1032. lpcwstrNameGUID [in] - Configuration name
  1033. lpData [in] - New configuration data
  1034. dwDataSize [in] - Size of new configuration data
  1035. Return Value:
  1036. Standard HRESULT code
  1037. --*/
  1038. {
  1039. DWORD dwRes;
  1040. DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::ConfigChange"));
  1041. if (!_tcsicmp (lpcwstrNameGUID, REGVAL_RM_FLAGS_GUID))
  1042. {
  1043. //
  1044. // Flags have changed
  1045. //
  1046. if (sizeof (DWORD) != dwDataSize)
  1047. {
  1048. //
  1049. // We're expecting a single DWORD here
  1050. //
  1051. return HRESULT_FROM_WIN32(ERROR_BADDB); // The configuration registry database is corrupt.
  1052. }
  1053. m_dwFlags = DWORD (*lpData);
  1054. return NOERROR;
  1055. }
  1056. //
  1057. // This is one of our routing method's configuration which changed.
  1058. // Verify the new data is a Unicode string.
  1059. //
  1060. if (!IsUnicodeString(lpData, dwDataSize))
  1061. {
  1062. //
  1063. // No NULL terminator, set to empty string.
  1064. //
  1065. DebugPrintEx(
  1066. DEBUG_ERR,
  1067. TEXT("Error reading routing method %s string configuration, no NULL terminator."),
  1068. lpcwstrNameGUID
  1069. );
  1070. lpData = (LPBYTE)TEXT("");
  1071. }
  1072. if (!_tcsicmp (lpcwstrNameGUID, REGVAL_RM_FOLDER_GUID))
  1073. {
  1074. //
  1075. // Store folder has changed
  1076. //
  1077. dwRes = SetStringValue(m_strStoreFolder, NULL, LPCWSTR(lpData));
  1078. return HRESULT_FROM_WIN32(dwRes);
  1079. }
  1080. if (!_tcsicmp (lpcwstrNameGUID, REGVAL_RM_PRINTING_GUID))
  1081. {
  1082. //
  1083. // Printer name has changed
  1084. //
  1085. dwRes = SetStringValue(m_strPrinter, NULL, LPCWSTR(lpData));
  1086. return HRESULT_FROM_WIN32(dwRes);
  1087. }
  1088. if (!_tcsicmp (lpcwstrNameGUID, REGVAL_RM_EMAIL_GUID))
  1089. {
  1090. //
  1091. // Email address has changed
  1092. //
  1093. dwRes = SetStringValue(m_strSMTPTo, NULL, LPCWSTR(lpData));
  1094. return HRESULT_FROM_WIN32(dwRes);
  1095. }
  1096. DebugPrintEx(
  1097. DEBUG_ERR,
  1098. TEXT("Device %ld got configuration change notification for unknown GUID (%s)"),
  1099. m_dwId,
  1100. lpcwstrNameGUID);
  1101. ASSERT_FALSE
  1102. return HRESULT_FROM_WIN32(ERROR_GEN_FAILURE);
  1103. } // CDeviceRoutingInfo::ConfigChange
  1104. DWORD
  1105. CDeviceRoutingInfo::EnableFlag (
  1106. DWORD dwFlag,
  1107. BOOL bEnable
  1108. )
  1109. /*++
  1110. Routine name : CDeviceRoutingInfo::EnableFlag
  1111. Routine description:
  1112. Sets a new value to the routing methods flags
  1113. Author:
  1114. Eran Yariv (EranY), Nov, 1999
  1115. Arguments:
  1116. dwFlag [in] - Flag id
  1117. bEnable [in] - Is flag enabled?
  1118. Return Value:
  1119. Standard Win32 error code.
  1120. --*/
  1121. {
  1122. DWORD dwRes = ERROR_SUCCESS;
  1123. DWORD dwValue = m_dwFlags;
  1124. DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::EnableFlag"));
  1125. Assert ((LR_STORE == dwFlag) ||
  1126. (LR_PRINT == dwFlag) ||
  1127. (LR_EMAIL == dwFlag));
  1128. if (bEnable == ((dwValue & dwFlag) ? TRUE : FALSE))
  1129. {
  1130. //
  1131. // No change
  1132. //
  1133. return ERROR_SUCCESS;
  1134. }
  1135. //
  1136. // Change temporary flag value
  1137. //
  1138. if (bEnable)
  1139. {
  1140. dwValue |= dwFlag;
  1141. }
  1142. else
  1143. {
  1144. dwValue &= ~dwFlag;
  1145. }
  1146. //
  1147. // Store new value in the extension data storage
  1148. //
  1149. dwRes = g_pFaxExtSetData (g_hModule,
  1150. m_dwId,
  1151. DEV_ID_SRC_FAX, // We always use the Fax Device Id
  1152. REGVAL_RM_FLAGS_GUID,
  1153. (LPBYTE)&dwValue,
  1154. sizeof (DWORD)
  1155. );
  1156. if (ERROR_SUCCESS == dwRes)
  1157. {
  1158. //
  1159. // Registry store successful - Update flags value in memory with new value.
  1160. //
  1161. m_dwFlags = dwValue;
  1162. } return dwRes;
  1163. } // CDeviceRoutingInfo::EnableFlag
  1164. DWORD
  1165. CDeviceRoutingInfo::SetStringValue (
  1166. wstring &wstr,
  1167. LPCWSTR lpcwstrGUID,
  1168. LPCWSTR lpcwstrCfg
  1169. )
  1170. /*++
  1171. Routine name : CDeviceRoutingInfo::SetStringValue
  1172. Routine description:
  1173. Updates a configuration for a device
  1174. Author:
  1175. Eran Yariv (EranY), Dec, 1999
  1176. Arguments:
  1177. wstr [in] - Refrence to internal string configuration
  1178. lpcwstrGUID [in] - GUID of routing method we configure (for storage purposes)
  1179. If this parameter is NULL, only the memory reference of the member is updated but not the persistance one
  1180. lpcwstrCfg [in] - New string configuration
  1181. Return Value:
  1182. Standard Win32 error code
  1183. --*/
  1184. {
  1185. DWORD dwRes = ERROR_SUCCESS;
  1186. DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::SetStringValue"));
  1187. //
  1188. // Persist the data
  1189. //
  1190. if (lpcwstrGUID != NULL)
  1191. {
  1192. dwRes = g_pFaxExtSetData (g_hModule,
  1193. m_dwId,
  1194. DEV_ID_SRC_FAX, // We always use the Fax Device Id
  1195. lpcwstrGUID,
  1196. (LPBYTE)lpcwstrCfg,
  1197. StringSize (lpcwstrCfg)
  1198. );
  1199. }
  1200. //
  1201. // Store the data in memory
  1202. //
  1203. EnterCriticalSection(&g_csRoutingStrings);
  1204. try
  1205. {
  1206. wstr = lpcwstrCfg;
  1207. }
  1208. catch (exception ex)
  1209. {
  1210. LeaveCriticalSection(&g_csRoutingStrings);
  1211. DebugPrintEx(
  1212. DEBUG_ERR,
  1213. TEXT("Got an STL exception while setting a configuration string (%S)"),
  1214. ex.what());
  1215. return ERROR_NOT_ENOUGH_MEMORY;
  1216. }
  1217. LeaveCriticalSection(&g_csRoutingStrings);
  1218. return dwRes;
  1219. } // CDeviceRoutingInfo::SetStringValue
  1220. /************************************
  1221. * *
  1222. * Implementation *
  1223. * *
  1224. ************************************/
  1225. BOOL WINAPI
  1226. FaxRouteSetRoutingInfo(
  1227. IN LPCWSTR lpcwstrRoutingGuid,
  1228. IN DWORD dwDeviceId,
  1229. IN const BYTE *lpbRoutingInfo,
  1230. IN DWORD dwRoutingInfoSize
  1231. )
  1232. /*++
  1233. Routine name : FaxRouteSetRoutingInfo
  1234. Routine description:
  1235. The FaxRouteSetRoutingInfo function modifies routing configuration data
  1236. for a specific fax device.
  1237. Each fax routing extension DLL must export the FaxRouteSetRoutingInfo function
  1238. Author:
  1239. Eran Yariv (EranY), Nov, 1999
  1240. Arguments:
  1241. lpcwstrRoutingGuid [in] - Pointer to the GUID for the routing method
  1242. dwDeviceId [in] - Identifier of the fax device to modify
  1243. lpbRoutingInfo [in] - Pointer to the buffer that provides configuration data
  1244. dwRoutingInfoSize [in] - Size, in bytes, of the buffer
  1245. Return Value:
  1246. If the function succeeds, the return value is a nonzero value.
  1247. If the function fails, the return value is zero.
  1248. To get extended error information, the fax service calls GetLastError().
  1249. --*/
  1250. {
  1251. DWORD dwRes;
  1252. CDeviceRoutingInfo *pDevInfo;
  1253. BOOL bMethodEnabled;
  1254. LPCWSTR lpcwstrMethodConfig = LPCWSTR(&lpbRoutingInfo[sizeof (DWORD)]);
  1255. DEBUG_FUNCTION_NAME(TEXT("FaxRouteSetRoutingInfo"));
  1256. if (dwRoutingInfoSize < sizeof (DWORD))
  1257. {
  1258. DebugPrintEx(
  1259. DEBUG_ERR,
  1260. TEXT("Data size is too small (%ld)"),
  1261. dwRoutingInfoSize);
  1262. SetLastError (ERROR_INVALID_PARAMETER);
  1263. return FALSE;
  1264. }
  1265. pDevInfo = g_DevicesMap.GetDeviceRoutingInfo(dwDeviceId);
  1266. if (NULL == pDevInfo)
  1267. {
  1268. return FALSE;
  1269. }
  1270. //
  1271. // First DWORD tells if method is enabled
  1272. //
  1273. bMethodEnabled = *((LPDWORD)(lpbRoutingInfo)) ? TRUE : FALSE;
  1274. switch( GetMaskBit( lpcwstrRoutingGuid ))
  1275. {
  1276. case LR_PRINT:
  1277. if (bMethodEnabled)
  1278. {
  1279. //
  1280. // Only if the method is enabled, we update the new configuration
  1281. //
  1282. dwRes = pDevInfo->SetPrinter ( lpcwstrMethodConfig );
  1283. if (ERROR_SUCCESS != dwRes)
  1284. {
  1285. SetLastError (dwRes);
  1286. return FALSE;
  1287. }
  1288. }
  1289. dwRes = pDevInfo->EnablePrint (bMethodEnabled);
  1290. if (ERROR_SUCCESS != dwRes)
  1291. {
  1292. SetLastError (dwRes);
  1293. return FALSE;
  1294. }
  1295. break;
  1296. case LR_STORE:
  1297. if (bMethodEnabled)
  1298. {
  1299. //
  1300. // Only if the method is enabled, we update the new configuration
  1301. //
  1302. dwRes = pDevInfo->SetStoreFolder ( lpcwstrMethodConfig );
  1303. if (ERROR_SUCCESS != dwRes)
  1304. {
  1305. SetLastError (dwRes);
  1306. return FALSE;
  1307. }
  1308. }
  1309. dwRes = pDevInfo->EnableStore (bMethodEnabled);
  1310. if (ERROR_SUCCESS != dwRes)
  1311. {
  1312. SetLastError (dwRes);
  1313. return FALSE;
  1314. }
  1315. break;
  1316. case LR_EMAIL:
  1317. if (bMethodEnabled)
  1318. {
  1319. //
  1320. // Only if the method is enabled, we update the new configuration
  1321. //
  1322. dwRes = pDevInfo->SetSMTPTo ( lpcwstrMethodConfig );
  1323. if (ERROR_SUCCESS != dwRes)
  1324. {
  1325. SetLastError (dwRes);
  1326. return FALSE;
  1327. }
  1328. }
  1329. dwRes = pDevInfo->EnableEmail (bMethodEnabled);
  1330. if (ERROR_SUCCESS != dwRes)
  1331. {
  1332. SetLastError (dwRes);
  1333. return FALSE;
  1334. }
  1335. break;
  1336. default:
  1337. //
  1338. // Unknown GUID requested
  1339. //
  1340. DebugPrintEx(
  1341. DEBUG_ERR,
  1342. TEXT("Unknown routing method GUID (%s)"),
  1343. lpcwstrRoutingGuid);
  1344. SetLastError (ERROR_INVALID_PARAMETER);
  1345. return FALSE;
  1346. }
  1347. return TRUE;
  1348. } // FaxRouteSetRoutingInfo
  1349. BOOL WINAPI
  1350. FaxRouteGetRoutingInfo(
  1351. IN LPCWSTR lpcwstrRoutingGuid,
  1352. IN DWORD dwDeviceId,
  1353. IN LPBYTE lpbRoutingInfo,
  1354. OUT LPDWORD lpdwRoutingInfoSize
  1355. )
  1356. /*++
  1357. Routine name : FaxRouteGetRoutingInfo
  1358. Routine description:
  1359. The FaxRouteGetRoutingInfo function queries the fax routing extension
  1360. DLL to obtain routing configuration data for a specific fax device.
  1361. Each fax routing extension DLL must export the FaxRouteGetRoutingInfo function
  1362. Author:
  1363. Eran Yariv (EranY), Nov, 1999
  1364. Arguments:
  1365. lpcwstrRoutingGuid [in ] - Pointer to the GUID for the routing method
  1366. dwDeviceId [in ] - Specifies the identifier of the fax device to query.
  1367. lpbRoutingInfo [in ] - Pointer to a buffer that receives the fax routing configuration data.
  1368. lpdwRoutingInfoSize [out] - Pointer to an unsigned DWORD variable that specifies the size,
  1369. in bytes, of the buffer pointed to by the lpbRoutingInfo parameter.
  1370. Return Value:
  1371. If the function succeeds, the return value is a nonzero value.
  1372. If the function fails, the return value is zero.
  1373. To get extended error information, the fax service calls GetLastError().
  1374. --*/
  1375. {
  1376. wstring strConfigString;
  1377. DWORD dwDataSize = sizeof (DWORD);
  1378. CDeviceRoutingInfo *pDevInfo;
  1379. BOOL bMethodEnabled;
  1380. DEBUG_FUNCTION_NAME(TEXT("FaxRouteGetRoutingInfo"));
  1381. pDevInfo = g_DevicesMap.GetDeviceRoutingInfo(dwDeviceId);
  1382. if (NULL == pDevInfo)
  1383. {
  1384. return FALSE;
  1385. }
  1386. switch( GetMaskBit( lpcwstrRoutingGuid ))
  1387. {
  1388. case LR_PRINT:
  1389. if (!pDevInfo->GetPrinter(strConfigString))
  1390. {
  1391. return FALSE;
  1392. }
  1393. bMethodEnabled = pDevInfo->IsPrintEnabled();
  1394. break;
  1395. case LR_STORE:
  1396. if (!pDevInfo->GetStoreFolder(strConfigString))
  1397. {
  1398. return FALSE;
  1399. }
  1400. bMethodEnabled = pDevInfo->IsStoreEnabled();
  1401. break;
  1402. case LR_EMAIL:
  1403. if (!pDevInfo->GetSMTPTo(strConfigString))
  1404. {
  1405. return FALSE;
  1406. }
  1407. bMethodEnabled = pDevInfo->IsEmailEnabled ();
  1408. break;
  1409. default:
  1410. //
  1411. // Unknown GUID requested
  1412. //
  1413. DebugPrintEx(
  1414. DEBUG_ERR,
  1415. TEXT("Unknown routing method GUID (%s)"),
  1416. lpcwstrRoutingGuid);
  1417. SetLastError (ERROR_INVALID_PARAMETER);
  1418. return FALSE;
  1419. }
  1420. dwDataSize += ((strConfigString.length() + 1) * sizeof(WCHAR));
  1421. if (NULL == lpbRoutingInfo)
  1422. {
  1423. //
  1424. // Caller just wants to know the data size
  1425. //
  1426. *lpdwRoutingInfoSize = dwDataSize;
  1427. return TRUE;
  1428. }
  1429. if (dwDataSize > *lpdwRoutingInfoSize)
  1430. {
  1431. //
  1432. // Caller supplied too small a buffer
  1433. //
  1434. *lpdwRoutingInfoSize = dwDataSize;
  1435. SetLastError (ERROR_INSUFFICIENT_BUFFER);
  1436. return FALSE;
  1437. }
  1438. //
  1439. // First DWORD tells if this method is enabled or not
  1440. //
  1441. *((LPDWORD)lpbRoutingInfo) = bMethodEnabled;
  1442. //
  1443. // Skip to string area
  1444. //
  1445. lpbRoutingInfo += sizeof(DWORD);
  1446. //
  1447. // Copy string
  1448. //
  1449. wcscpy( (LPWSTR)lpbRoutingInfo, strConfigString.c_str());
  1450. //
  1451. // Set actual size used
  1452. //
  1453. *lpdwRoutingInfoSize = dwDataSize;
  1454. return TRUE;
  1455. } // FaxRouteGetRoutingInfo
  1456. HRESULT
  1457. FaxRoutingExtConfigChange (
  1458. DWORD dwDeviceId, // The device for which configuration has changed
  1459. LPCWSTR lpcwstrNameGUID, // Configuration name
  1460. LPBYTE lpData, // New configuration data
  1461. DWORD dwDataSize // Size of new configuration data
  1462. )
  1463. /*++
  1464. Routine name : FaxRoutingExtConfigChange
  1465. Routine description:
  1466. Handles configuration change notifications
  1467. Author:
  1468. Eran Yariv (EranY), Nov, 1999
  1469. Arguments:
  1470. dwDeviceId [in] - The device for which configuration has changed
  1471. lpcwstrNameGUID [in] - Configuration name
  1472. lpData [in] - New configuration data
  1473. data [in] - Size of new configuration data
  1474. Return Value:
  1475. Standard HRESULT code
  1476. --*/
  1477. {
  1478. HRESULT hr;
  1479. DEBUG_FUNCTION_NAME(TEXT("FaxRoutingExtConfigChange"));
  1480. CDeviceRoutingInfo *pDevice = g_DevicesMap.FindDeviceRoutingInfo (dwDeviceId);
  1481. if (!pDevice)
  1482. {
  1483. //
  1484. // Device not found in map - can't be
  1485. //
  1486. hr = HRESULT_FROM_WIN32(GetLastError ());
  1487. DebugPrintEx(
  1488. DEBUG_ERR,
  1489. TEXT("Got a notification but cant find device %ld (hr = 0x%08x) !!!!"),
  1490. dwDeviceId,
  1491. hr);
  1492. ASSERT_FALSE;
  1493. return hr;
  1494. }
  1495. return pDevice->ConfigChange (lpcwstrNameGUID, lpData, dwDataSize);
  1496. } // FaxRoutingExtConfigChange