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.

2587 lines
65 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. RouteRule.cpp
  5. Abstract:
  6. This file provides implementation of the service
  7. outbound routing rules.
  8. Author:
  9. Oded Sacher (OdedS) Dec, 1999
  10. Revision History:
  11. --*/
  12. #include "faxsvc.h"
  13. #define STRSAFE_NO_DEPRECATE // This allows using unsafe functions
  14. #include <strsafe.h>
  15. BOOL
  16. EnumOutboundRoutingRulesCB(
  17. HKEY hSubKey,
  18. LPWSTR SubKeyName,
  19. DWORD Index,
  20. LPVOID pContext
  21. );
  22. /************************************
  23. * *
  24. * Globals *
  25. * *
  26. ************************************/
  27. COutboundRulesMap* g_pRulesMap; // Map of dialing location to rule
  28. /***********************************
  29. * *
  30. * CDialingLocation Methodes *
  31. * *
  32. ***********************************/
  33. bool
  34. CDialingLocation::operator < ( const CDialingLocation &other ) const
  35. /*++
  36. Routine name : operator <
  37. Class: CDialingLocation
  38. Routine description:
  39. Compares myself with another Dialing location key
  40. Author:
  41. Oded Sacher (Odeds), Dec, 1999
  42. Arguments:
  43. other [in] - Other key
  44. Return Value:
  45. true only is i'm less than the other key
  46. --*/
  47. {
  48. if (m_dwCountryCode < other.m_dwCountryCode)
  49. {
  50. return true;
  51. }
  52. if (m_dwCountryCode > other.m_dwCountryCode)
  53. {
  54. return false;
  55. }
  56. //
  57. // Equal country code , comapre area code
  58. //
  59. if (m_dwAreaCode < other.m_dwAreaCode)
  60. {
  61. return true;
  62. }
  63. return false;
  64. } // CDialingLocation::operator <
  65. BOOL
  66. CDialingLocation::IsValid () const
  67. /*++
  68. Routine name : CDialingLocation::IsValid
  69. Routine description:
  70. Validates a dialing location object
  71. Author:
  72. Oded Sacher (OdedS), Dec, 1999
  73. Arguments:
  74. Return Value:
  75. BOOL
  76. --*/
  77. {
  78. DEBUG_FUNCTION_NAME(TEXT("CDialingLocation::IsValid"));
  79. if (m_dwCountryCode == ROUTING_RULE_COUNTRY_CODE_ANY &&
  80. m_dwAreaCode != ROUTING_RULE_AREA_CODE_ANY)
  81. {
  82. DebugPrintEx(
  83. DEBUG_ERR,
  84. TEXT("Not a valid Country and Area code combination"));
  85. return FALSE;
  86. }
  87. return TRUE;
  88. } // CDialingLocation::IsValidDialingLocation
  89. LPCWSTR
  90. CDialingLocation::GetCountryName () const
  91. /*++
  92. Routine name : CDialingLocation::GetCountryName
  93. Routine description:
  94. Returns a pointer to the country name specifies by its country dialing code (based on TAPI).
  95. The caller must call MemFree() to deallocate memory.
  96. Author:
  97. Oded Sacher (OdedS), Dec, 1999
  98. Arguments:
  99. Return Value:
  100. Pointer to the country name.
  101. If this is NULL the function failed, call GetLastError() for more info.
  102. --*/
  103. {
  104. DEBUG_FUNCTION_NAME(TEXT("CDialingLocation::GetCountryName"));
  105. LPLINECOUNTRYLIST lpCountryList = NULL;
  106. LPLINECOUNTRYENTRY lpEntry = NULL;
  107. DWORD dwIndex;
  108. //
  109. // Get the cached all countries list.
  110. //
  111. if (!(lpCountryList = GetCountryList()))
  112. {
  113. SetLastError (ERROR_NOT_ENOUGH_MEMORY);
  114. goto exit;
  115. }
  116. lpEntry = (LPLINECOUNTRYENTRY) // init array of entries
  117. ((PBYTE) lpCountryList + lpCountryList->dwCountryListOffset);
  118. for (dwIndex=0; dwIndex < lpCountryList->dwNumCountries; dwIndex++)
  119. {
  120. if (lpEntry[dwIndex].dwCountryCode == m_dwCountryCode)
  121. {
  122. //
  123. // Matching country code - copy Country name.
  124. //
  125. if (lpEntry[dwIndex].dwCountryNameSize && lpEntry[dwIndex].dwCountryNameOffset)
  126. {
  127. return StringDup ((LPWSTR) ((LPBYTE)lpCountryList + lpEntry[dwIndex].dwCountryNameOffset));
  128. }
  129. }
  130. }
  131. SetLastError (ERROR_NOT_FOUND);
  132. exit:
  133. return NULL;
  134. } // CDialingLocation::GetCountryName
  135. /*************************************
  136. * *
  137. * COutboundRoutingRule Methodes *
  138. * *
  139. *************************************/
  140. DWORD
  141. COutboundRoutingRule::Init (CDialingLocation DialingLocation, wstring wstrGroupName)
  142. /*++
  143. Routine name : COutboundRoutingRule::Init
  144. Routine description:
  145. Initialize an OutboundRoutingRule object
  146. Author:
  147. Oded Sacher (OdedS), Dec, 1999
  148. Arguments:
  149. DialingLocation [in ] - Dialing location object to use as the rule's dialing location
  150. wstrGroupName [in ] - The group name to use as the rule's destination group
  151. Return Value:
  152. Standard Win32 error code
  153. --*/
  154. {
  155. DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::Init"));
  156. try
  157. {
  158. m_wstrGroupName = wstrGroupName;
  159. m_bUseGroup = TRUE;
  160. m_DialingLocation = DialingLocation;
  161. return ERROR_SUCCESS;
  162. }
  163. catch (exception &ex)
  164. {
  165. DebugPrintEx(
  166. DEBUG_ERR,
  167. TEXT("wstring caused exception (%S)"),
  168. ex.what());
  169. return ERROR_GEN_FAILURE;
  170. }
  171. }
  172. DWORD
  173. COutboundRoutingRule::Save(HKEY hRuleKey) const
  174. /*++
  175. Routine name : COutboundRoutingRule::Save
  176. Routine description:
  177. Saves an outbound routing rule value to the registry
  178. Author:
  179. Oded Sacher (OdedS), Dec, 1999
  180. Arguments:
  181. hRuleKey [in] - Handle to the opened rule registry key
  182. Return Value:
  183. Standard Win32 error code
  184. --*/
  185. {
  186. DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::Save"));
  187. DWORD dwRes = ERROR_SUCCESS;
  188. Assert (hRuleKey);
  189. // Save country code
  190. if (!SetRegistryDword( hRuleKey,
  191. REGVAL_ROUTING_RULE_COUNTRY_CODE,
  192. m_DialingLocation.GetCountryCode()))
  193. {
  194. dwRes = GetLastError();
  195. DebugPrintEx(
  196. DEBUG_ERR,
  197. TEXT("SetRegistryDword failed , ec %ld"), dwRes);
  198. goto exit;
  199. }
  200. // Save area code
  201. if (!SetRegistryDword( hRuleKey,
  202. REGVAL_ROUTING_RULE_AREA_CODE,
  203. m_DialingLocation.GetAreaCode()))
  204. {
  205. dwRes = GetLastError();
  206. DebugPrintEx(
  207. DEBUG_ERR,
  208. TEXT("SetRegistryDword failed , ec %ld"), dwRes);
  209. goto exit;
  210. }
  211. // // Save boolen flag whether to use group
  212. if (!SetRegistryDword( hRuleKey,
  213. REGVAL_ROUTING_RULE_USE_GROUP,
  214. m_bUseGroup ? TRUE : FALSE))
  215. {
  216. dwRes = GetLastError();
  217. DebugPrintEx(
  218. DEBUG_ERR,
  219. TEXT("SetRegistryDword failed , ec %ld"), dwRes);
  220. goto exit;
  221. }
  222. if (FALSE == m_bUseGroup)
  223. {
  224. // Save the device ID as the rule destination
  225. if (!SetRegistryDword( hRuleKey,
  226. REGVAL_ROUTING_RULE_DEVICE_ID,
  227. m_dwDevice))
  228. {
  229. dwRes = GetLastError();
  230. DebugPrintEx(
  231. DEBUG_ERR,
  232. TEXT("SetRegistryDword failed , ec %ld"), dwRes);
  233. goto exit;
  234. }
  235. }
  236. else
  237. {
  238. // Save the group name as the rule destination
  239. try
  240. {
  241. if (!SetRegistryString( hRuleKey,
  242. REGVAL_ROUTING_RULE_GROUP_NAME,
  243. m_wstrGroupName.c_str()))
  244. {
  245. dwRes = GetLastError();
  246. DebugPrintEx(
  247. DEBUG_ERR,
  248. TEXT("SetRegistryDword failed , ec %ld"), dwRes);
  249. goto exit;
  250. }
  251. }
  252. catch (exception &ex)
  253. {
  254. DebugPrintEx(
  255. DEBUG_ERR,
  256. TEXT("wstring caused exception (%S)"),
  257. ex.what());
  258. dwRes = ERROR_GEN_FAILURE;
  259. goto exit;
  260. }
  261. }
  262. Assert (dwRes == ERROR_SUCCESS);
  263. exit:
  264. return dwRes;
  265. } // COutboundRoutingRule::Save
  266. DWORD
  267. COutboundRoutingRule::Load(HKEY hRuleKey)
  268. /*++
  269. Routine name : COutboundRoutingRule::Load
  270. Routine description:
  271. Loads an outboundrouting rule value settings from the registry
  272. Author:
  273. Oded Sacher (OdedS), Dec, 1999
  274. Arguments:
  275. hRuleKey [in] - Handle to the opened registry key
  276. Return Value:
  277. Standard Win32 error code
  278. --*/
  279. {
  280. DWORD dwRes, dwType, dwSize;
  281. DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::Load"));
  282. DWORD dwCountryCode = 0;
  283. DWORD dwAreaCode = 0;
  284. Assert (hRuleKey);
  285. // Read the boolen flag whether to use group
  286. dwRes = GetRegistryDwordEx (hRuleKey,
  287. REGVAL_ROUTING_RULE_USE_GROUP,
  288. (LPDWORD)&m_bUseGroup);
  289. if (ERROR_SUCCESS != dwRes)
  290. {
  291. DebugPrintEx(
  292. DEBUG_ERR,
  293. TEXT("Error reading UseGroup - GetRegistryDwordEx failed with %ld"),
  294. dwRes);
  295. goto exit;
  296. }
  297. if (FALSE == m_bUseGroup)
  298. {
  299. // read the device ID as the rule destination
  300. dwRes = GetRegistryDwordEx (hRuleKey,
  301. REGVAL_ROUTING_RULE_DEVICE_ID,
  302. &m_dwDevice);
  303. if (ERROR_SUCCESS != dwRes)
  304. {
  305. DebugPrintEx(
  306. DEBUG_ERR,
  307. TEXT("Error reading device ID - GetRegistryDwordEx failed with %ld"),
  308. dwRes);
  309. goto exit;
  310. }
  311. if (0 == m_dwDevice)
  312. {
  313. DebugPrintEx(
  314. DEBUG_ERR,
  315. TEXT("Invalid device ID"));
  316. dwRes = ERROR_BADDB;
  317. goto exit;
  318. }
  319. }
  320. else
  321. {
  322. // Read the group name as the rule destination
  323. WCHAR wszGroupName[MAX_ROUTING_GROUP_NAME + 1] = {0};
  324. dwRes = RegQueryValueEx(
  325. hRuleKey,
  326. REGVAL_ROUTING_RULE_GROUP_NAME,
  327. NULL,
  328. &dwType,
  329. NULL,
  330. &dwSize
  331. );
  332. if (ERROR_SUCCESS != dwRes)
  333. {
  334. DebugPrintEx(
  335. DEBUG_ERR,
  336. TEXT("RegQueryValueEx failed with %ld"),
  337. dwRes);
  338. goto exit;
  339. }
  340. if (REG_SZ != dwType || dwSize > (sizeof(wszGroupName) - sizeof(WCHAR)))
  341. {
  342. // We expect only string data here
  343. DebugPrintEx(
  344. DEBUG_ERR,
  345. TEXT("Error reading group name"));
  346. dwRes = ERROR_BADDB; // The configuration registry database is corrupt.
  347. goto exit;
  348. }
  349. dwRes = RegQueryValueEx(
  350. hRuleKey,
  351. REGVAL_ROUTING_RULE_GROUP_NAME,
  352. NULL,
  353. &dwType,
  354. (LPBYTE)wszGroupName,
  355. &dwSize
  356. );
  357. if (ERROR_SUCCESS != dwRes)
  358. {
  359. DebugPrintEx(
  360. DEBUG_ERR,
  361. TEXT("RegQueryValueEx failed with %ld"),
  362. dwRes);
  363. goto exit;
  364. }
  365. // Validate that the group exist
  366. PCGROUP pCGroup = g_pGroupsMap->FindGroup (wszGroupName);
  367. if (NULL == pCGroup)
  368. {
  369. dwRes = GetLastError();
  370. DebugPrintEx(
  371. DEBUG_ERR,
  372. TEXT("COutboundRoutingGropsMap::FindGroup, with error - %ld"),
  373. dwRes);
  374. goto exit;
  375. }
  376. try
  377. {
  378. m_wstrGroupName = wszGroupName;
  379. }
  380. catch (exception &ex)
  381. {
  382. DebugPrintEx(
  383. DEBUG_ERR,
  384. TEXT("wstring caused exception (%S)"),
  385. ex.what());
  386. dwRes = ERROR_GEN_FAILURE;
  387. goto exit;
  388. }
  389. }
  390. // Read the country code
  391. dwRes = GetRegistryDwordEx (hRuleKey,
  392. REGVAL_ROUTING_RULE_COUNTRY_CODE,
  393. &dwCountryCode);
  394. if (ERROR_SUCCESS != dwRes)
  395. {
  396. DebugPrintEx(
  397. DEBUG_ERR,
  398. TEXT("Error reading Country code - GetRegistryDwordEx failed with %ld"),
  399. dwRes);
  400. goto exit;
  401. }
  402. // Read the area code
  403. dwRes = GetRegistryDwordEx (hRuleKey,
  404. REGVAL_ROUTING_RULE_AREA_CODE,
  405. &dwAreaCode);
  406. if (ERROR_SUCCESS != dwRes)
  407. {
  408. DebugPrintEx(
  409. DEBUG_ERR,
  410. TEXT("Error reading Area code - GetRegistryDwordEx failed with %ld"),
  411. dwRes);
  412. goto exit;
  413. }
  414. //
  415. // Create the DialingLocation object
  416. //
  417. m_DialingLocation = CDialingLocation (dwCountryCode, dwAreaCode);
  418. if (!m_DialingLocation.IsValid())
  419. {
  420. dwRes = ERROR_INVALID_PARAMETER;
  421. DebugPrintEx(
  422. DEBUG_ERR,
  423. TEXT("IsValidDialingLocation failed"));
  424. goto exit;
  425. }
  426. Assert (ERROR_SUCCESS == dwRes);
  427. exit:
  428. return dwRes;
  429. } // COutboundRoutingRule::Load
  430. DWORD
  431. COutboundRoutingRule::GetStatus (FAX_ENUM_RULE_STATUS* lpdwStatus) const
  432. /*++
  433. Routine name : COutboundRoutingRule::GetStatus
  434. Routine description:
  435. Reports the rule's status. Can be one of FAX_ENUM_RULE_STATUS.
  436. Enter Critical Section (g_CsLine , g_CsConfig) before calling this function.
  437. Author:
  438. Oded Sacher (OdedS), Dec, 1999
  439. Arguments:
  440. lpdwStatus [out ] - Gets the rule's status on return
  441. Return Value:
  442. Standard Win32 error code
  443. --*/
  444. {
  445. DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::GetStatus"));
  446. FAX_ENUM_RULE_STATUS dwRuleStatus = FAX_RULE_STATUS_VALID;
  447. DWORD dwRes = ERROR_SUCCESS;
  448. PCGROUP pCGroup;
  449. if (TRUE == m_bUseGroup)
  450. {
  451. // Find the rule's destination group in the goups map
  452. try
  453. {
  454. pCGroup = g_pGroupsMap->FindGroup (m_wstrGroupName.c_str());
  455. if (NULL == pCGroup)
  456. {
  457. dwRes = GetLastError();
  458. DebugPrintEx(
  459. DEBUG_ERR,
  460. TEXT("COutboundRoutingGroupsMap::FindGroup failed , ec %ld"), dwRes);
  461. goto exit;
  462. }
  463. }
  464. catch (exception &ex)
  465. {
  466. DebugPrintEx(
  467. DEBUG_ERR,
  468. TEXT("wstring caused exception (%S)"),
  469. ex.what());
  470. dwRes = ERROR_GEN_FAILURE;
  471. goto exit;
  472. }
  473. // Get the group's status.
  474. FAX_ENUM_GROUP_STATUS GroupStatus;
  475. dwRes = pCGroup->GetStatus(&GroupStatus);
  476. if (ERROR_SUCCESS != dwRes)
  477. {
  478. DebugPrintEx(
  479. DEBUG_ERR,
  480. TEXT("COutboundRoutingGroup::GetStatus failed , ec %ld"), dwRes);
  481. goto exit;
  482. }
  483. switch (GroupStatus)
  484. {
  485. case FAX_GROUP_STATUS_SOME_DEV_NOT_VALID:
  486. dwRuleStatus = FAX_RULE_STATUS_SOME_GROUP_DEV_NOT_VALID;
  487. break;
  488. case FAX_GROUP_STATUS_ALL_DEV_NOT_VALID:
  489. dwRuleStatus = FAX_RULE_STATUS_ALL_GROUP_DEV_NOT_VALID;
  490. break;
  491. case FAX_GROUP_STATUS_EMPTY:
  492. dwRuleStatus = FAX_RULE_STATUS_EMPTY_GROUP;
  493. break;
  494. default:
  495. Assert (FAX_GROUP_STATUS_ALL_DEV_VALID == GroupStatus);
  496. }
  497. }
  498. else
  499. {
  500. // A device is the rule's destination
  501. if (!IsDeviceInstalled (m_dwDevice))
  502. {
  503. // Device not installed
  504. dwRuleStatus = FAX_RULE_STATUS_BAD_DEVICE;
  505. }
  506. }
  507. Assert (ERROR_SUCCESS == dwRes);
  508. exit:
  509. if (ERROR_SUCCESS == dwRes)
  510. {
  511. *lpdwStatus = dwRuleStatus;
  512. }
  513. return dwRes;
  514. } // COutboundRoutingRule::GetStatus
  515. DWORD
  516. COutboundRoutingRule::GetDeviceList (LPDWORD* lppdwDevices, LPDWORD lpdwNumDevices) const
  517. /*++
  518. Routine name : COutboundRoutingRule::GetDeviceList
  519. Routine description:
  520. Returns an ordered device list, which are the rule's destination devices.
  521. The caller must call MemFree() to deallocate the memory.
  522. Enter Critical Section (g_CsConfig) before calling this function.
  523. Author:
  524. Oded Sacher (OdedS), Dec, 1999
  525. Arguments:
  526. lppdwDevices [out ] - Pointer to pointer to a DWORD buffer to recieve the devices list.
  527. lpdwNumDevices [out ] - Pointer to a DWORD to recieve the number of devices returned
  528. Return Value:
  529. Standard Win32 error code
  530. --*/
  531. {
  532. DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::GetDeviceList"));
  533. DWORD dwRes = ERROR_SUCCESS;
  534. PCGROUP pCGroup;
  535. Assert (lppdwDevices && lpdwNumDevices);
  536. *lppdwDevices = NULL;
  537. *lpdwNumDevices = 0;
  538. if (TRUE == m_bUseGroup)
  539. {
  540. // A group is the rule's destination
  541. try
  542. {
  543. pCGroup = g_pGroupsMap->FindGroup (m_wstrGroupName.c_str());
  544. if (NULL == pCGroup)
  545. {
  546. dwRes = GetLastError();
  547. Assert (FAX_ERR_GROUP_NOT_FOUND != dwRes);
  548. DebugPrintEx(
  549. DEBUG_ERR,
  550. TEXT("COutboundRoutingGroupsMap::FindGroup failed , ec %ld"), dwRes);
  551. goto exit;
  552. }
  553. }
  554. catch (exception &ex)
  555. {
  556. DebugPrintEx(
  557. DEBUG_ERR,
  558. TEXT("wstring caused exception (%S)"),
  559. ex.what());
  560. dwRes = ERROR_GEN_FAILURE;
  561. goto exit;
  562. }
  563. // Get the group's device list
  564. dwRes = pCGroup->SerializeDevices (lppdwDevices, lpdwNumDevices);
  565. if (ERROR_SUCCESS != dwRes)
  566. {
  567. DebugPrintEx(
  568. DEBUG_ERR,
  569. TEXT("COutboundRoutingGroup::SerializeDevices failed with %ld"),
  570. dwRes);
  571. goto exit;
  572. }
  573. }
  574. else
  575. {
  576. // A single device
  577. *lppdwDevices = (LPDWORD) MemAlloc(sizeof(DWORD));
  578. if (*lppdwDevices == NULL)
  579. {
  580. DebugPrintEx(
  581. DEBUG_ERR,
  582. TEXT("Cannot allocate devices buffer"));
  583. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  584. goto exit;
  585. }
  586. *(*lppdwDevices) = m_dwDevice;
  587. *lpdwNumDevices = 1;
  588. }
  589. Assert (ERROR_SUCCESS == dwRes);
  590. exit:
  591. return dwRes;
  592. } // COutboundRoutingRule::GetDeviceList
  593. DWORD
  594. COutboundRoutingRule::Serialize (LPBYTE lpBuffer,
  595. PFAX_OUTBOUND_ROUTING_RULEW pFaxRule,
  596. PULONG_PTR pupOffset,
  597. DWORD dwBufferSize) const
  598. /*++
  599. Routine name : COutboundRoutingRule::Serialize
  600. Routine description:
  601. Serializes a rule's info based on FAX_OUTBOUND_ROUTING_RULEW structure.
  602. Author:
  603. Oded Sacher (OdedS), Dec, 1999
  604. Arguments:
  605. lpBuffer [in] - Pointer to a pre-allocated buffer. If this parameter is NULL lpdwOffset will get the required buffer size.
  606. pFaxRule [in] - Pointer to a specific FAX_OUTBOUND_ROUTING_RULEW structure in the buffer
  607. pupOffset [in/out] - Offset from the begining of the buffer where variable length info is stored
  608. DWORD dwBufferSize [in] - the size of input buffer, lpBuffer.
  609. Return Value:
  610. Standard Win32 error code
  611. --*/
  612. {
  613. DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::Serialize"));
  614. DWORD dwRes = ERROR_SUCCESS;
  615. const CDialingLocation DialingLocation = GetDialingLocation();
  616. LPCWSTR lpcwstrCountryName = NULL;
  617. LPCWSTR lpwstrGroupName;
  618. Assert (pupOffset);
  619. if (NULL != lpBuffer)
  620. {
  621. Assert (0 != dwBufferSize);
  622. }
  623. if (ROUTING_RULE_COUNTRY_CODE_ANY != DialingLocation.GetCountryCode())
  624. {
  625. // Get the country name
  626. lpcwstrCountryName = DialingLocation.GetCountryName();
  627. if (NULL == lpcwstrCountryName)
  628. {
  629. DebugPrintEx(
  630. DEBUG_ERR,
  631. TEXT("COutboundRoutingRule::GetCountryName failed , ec %ld"), GetLastError());
  632. }
  633. }
  634. try
  635. {
  636. lpwstrGroupName = m_bUseGroup ? m_wstrGroupName.c_str() : NULL;
  637. }
  638. catch (exception &ex)
  639. {
  640. DebugPrintEx(
  641. DEBUG_ERR,
  642. TEXT("wstring caused exception (%S)"),
  643. ex.what());
  644. MemFree ((void*)lpcwstrCountryName);
  645. return ERROR_GEN_FAILURE;
  646. }
  647. StoreString (lpcwstrCountryName,
  648. (PULONG_PTR)&(pFaxRule->lpctstrCountryName),
  649. lpBuffer,
  650. pupOffset,
  651. dwBufferSize);
  652. if (TRUE == m_bUseGroup)
  653. {
  654. StoreString (lpwstrGroupName,
  655. (PULONG_PTR)&((pFaxRule->Destination).lpcstrGroupName),
  656. lpBuffer,
  657. pupOffset,
  658. dwBufferSize);
  659. }
  660. if (NULL != lpBuffer)
  661. {
  662. // Write the data
  663. Assert (pFaxRule);
  664. if (FALSE == m_bUseGroup)
  665. {
  666. Assert (m_dwDevice);
  667. (pFaxRule->Destination).dwDeviceId = m_dwDevice;
  668. }
  669. pFaxRule->dwSizeOfStruct = sizeof (FAX_OUTBOUND_ROUTING_RULEW);
  670. pFaxRule->dwAreaCode = DialingLocation.GetAreaCode();
  671. pFaxRule->dwCountryCode = DialingLocation.GetCountryCode();
  672. pFaxRule->bUseGroup = m_bUseGroup;
  673. dwRes = GetStatus (&(pFaxRule->Status));
  674. if (ERROR_SUCCESS != dwRes)
  675. {
  676. DebugPrintEx(
  677. DEBUG_ERR,
  678. TEXT("COutboundRoutingRule::GetStatus failed , ec %ld"), dwRes);
  679. }
  680. }
  681. MemFree ((void*)lpcwstrCountryName);
  682. return dwRes;
  683. } // COutboundRoutingRule::Serialize
  684. LPCWSTR
  685. COutboundRoutingRule::GetGroupName () const
  686. /*++
  687. Routine name : COutboundRoutingRule::GetGroupName
  688. Routine description:
  689. Returns the group name if the rule's destination is a group.
  690. Author:
  691. Oded Sacher (OdedS), Dec, 1999
  692. Arguments:
  693. Return Value:
  694. The group name. If it is NULL call GetLastError() for more info.
  695. If it is ERROR_SUCCESS the rule's destination is single device.
  696. --*/
  697. {
  698. DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::GetGroupName"));
  699. try
  700. {
  701. SetLastError (ERROR_SUCCESS);
  702. if (TRUE == m_bUseGroup)
  703. {
  704. return m_wstrGroupName.c_str();
  705. }
  706. return NULL;
  707. }
  708. catch (exception &ex)
  709. {
  710. DebugPrintEx(
  711. DEBUG_ERR,
  712. TEXT("wstring caused exception (%S)"),
  713. ex.what());
  714. SetLastError (ERROR_GEN_FAILURE);
  715. return NULL;
  716. }
  717. } // GetGroupName
  718. #if DBG
  719. void COutboundRoutingRule::Dump () const
  720. {
  721. DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::Dump"));
  722. WCHAR Buffer[512] = {0};
  723. DWORD dwBufferSize = sizeof (Buffer)/ sizeof (Buffer[0]);
  724. try
  725. {
  726. if (TRUE == m_bUseGroup)
  727. {
  728. _snwprintf (Buffer, dwBufferSize -1, TEXT("\tCountry Code - %ld,\tArea Code - %ld,\tGroup name - %s"),
  729. m_DialingLocation.GetCountryCode(),
  730. m_DialingLocation.GetAreaCode(),
  731. m_wstrGroupName.c_str());
  732. }
  733. else
  734. {
  735. _snwprintf (Buffer, dwBufferSize -1, TEXT("\tCountry Code - %ld,\tArea Code - %ld,\tDevice ID - %ld"),
  736. m_DialingLocation.GetCountryCode(),
  737. m_DialingLocation.GetAreaCode(),
  738. m_dwDevice);
  739. }
  740. OutputDebugString (Buffer);
  741. }
  742. catch (exception &ex)
  743. {
  744. DebugPrintEx(
  745. DEBUG_ERR,
  746. TEXT("wstring caused exception (%S)"),
  747. ex.what());
  748. }
  749. return;
  750. }
  751. #endif // #if DBG
  752. /***********************************
  753. * *
  754. * COutboundRulesMap Methodes *
  755. * *
  756. ***********************************/
  757. DWORD
  758. COutboundRulesMap::Load ()
  759. /*++
  760. Routine name : COutboundRulesMap::Load
  761. Routine description:
  762. Loads all outbound routing rules from the registry
  763. Author:
  764. Oded Sacher (OdedS), Dec, 1999
  765. Arguments:
  766. Return Value:
  767. Standard Win32 error code
  768. --*/
  769. {
  770. DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::Load"));
  771. DWORD dwRes = ERROR_SUCCESS;
  772. HKEY hRuleskey = NULL;
  773. DWORD dwCount = 0;
  774. hRuleskey = OpenRegistryKey( HKEY_LOCAL_MACHINE,
  775. REGKEY_FAX_OUTBOUND_ROUTING,
  776. FALSE,
  777. KEY_READ | KEY_WRITE );
  778. if (NULL == hRuleskey)
  779. {
  780. dwRes = GetLastError ();
  781. DebugPrintEx(
  782. DEBUG_ERR,
  783. TEXT("OpenRegistryKey, error %ld"),
  784. dwRes);
  785. return dwRes;
  786. }
  787. dwCount = EnumerateRegistryKeys( hRuleskey,
  788. REGKEY_OUTBOUND_ROUTING_RULES,
  789. FALSE,
  790. EnumOutboundRoutingRulesCB,
  791. &dwRes
  792. );
  793. if (dwRes != ERROR_SUCCESS)
  794. {
  795. DebugPrintEx(
  796. DEBUG_ERR,
  797. TEXT("EnumerateRegistryKeys failed, error %ld"),
  798. dwRes);
  799. }
  800. RegCloseKey (hRuleskey);
  801. return dwRes;
  802. } // COutboundRulesMap::Load
  803. DWORD
  804. COutboundRulesMap::AddRule (COutboundRoutingRule& Rule)
  805. /*++
  806. Routine name : COutboundRulesMap::AddRule
  807. Routine description:
  808. Adds a new rule to the global map
  809. Author:
  810. Oded Sacher (OdedS), Dec, 1999
  811. Arguments:
  812. Rule [in ] - A reference to the new rule object
  813. Return Value:
  814. Standard Win32 error code
  815. --*/
  816. {
  817. RULES_MAP::iterator it;
  818. DWORD dwRes = ERROR_SUCCESS;
  819. DEBUG_FUNCTION_NAME(TEXT("COutboundRoulesMap::AddRule"));
  820. pair <RULES_MAP::iterator, bool> p;
  821. try
  822. {
  823. //
  824. // Add new map entry
  825. //
  826. p = m_RulesMap.insert (RULES_MAP::value_type(Rule.GetDialingLocation(), Rule));
  827. //
  828. // See if entry exists in map
  829. //
  830. if (p.second == FALSE)
  831. {
  832. DebugPrintEx(
  833. DEBUG_ERR,
  834. TEXT("Rule allready in the rules map"));
  835. dwRes = ERROR_DUP_NAME;
  836. goto exit;
  837. }
  838. }
  839. catch (exception &ex)
  840. {
  841. DebugPrintEx(
  842. DEBUG_ERR,
  843. TEXT("map caused exception (%S)"),
  844. ex.what());
  845. dwRes = ERROR_GEN_FAILURE;
  846. goto exit;
  847. }
  848. Assert (ERROR_SUCCESS == dwRes);
  849. exit:
  850. return dwRes;
  851. } // COutboundRulesMap::AddRule
  852. DWORD
  853. COutboundRulesMap::DelRule (CDialingLocation& DialingLocation)
  854. /*++
  855. Routine name : COutboundRulesMap::DelRule
  856. Routine description:
  857. Deletes a group from the global rules map
  858. Author:
  859. Oded Sacher (OdedS), Dec, 1999
  860. Arguments:
  861. DialingLocation [in ] - Pointer to the dialing location key
  862. Return Value:
  863. Standard Win32 error code
  864. --*/
  865. {
  866. RULES_MAP::iterator it;
  867. DWORD dwRes = ERROR_SUCCESS;
  868. DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::DelRule"));
  869. try
  870. {
  871. //
  872. // See if entry exists in map
  873. //
  874. if((it = m_RulesMap.find(DialingLocation)) == m_RulesMap.end())
  875. {
  876. DebugPrintEx(
  877. DEBUG_ERR,
  878. TEXT("rule is not in the rules map"));
  879. dwRes = FAX_ERR_RULE_NOT_FOUND;
  880. goto exit;
  881. }
  882. //
  883. // Delete the map entry
  884. //
  885. m_RulesMap.erase (it);
  886. }
  887. catch (exception &ex)
  888. {
  889. DebugPrintEx(
  890. DEBUG_ERR,
  891. TEXT("map caused exception (%S)"),
  892. ex.what());
  893. dwRes = ERROR_GEN_FAILURE;
  894. goto exit;
  895. }
  896. Assert (ERROR_SUCCESS == dwRes);
  897. exit:
  898. return dwRes;
  899. } // COutboundRulesMap::DelRule
  900. PCRULE
  901. COutboundRulesMap::FindRule (CDialingLocation& DialingLocation) const
  902. /*++
  903. Routine name : COutboundRulesMap::FindRule
  904. Routine description:
  905. Returns a pointer to a rule object specified by its name
  906. Author:
  907. Oded Sacher (OdedS), Dec, 1999
  908. Arguments:
  909. DialingLocation [in] - The rule's dialing location
  910. Return Value:
  911. Pointer to the found rule object. If it is null the rule was not found
  912. --*/
  913. {
  914. RULES_MAP::iterator it;
  915. DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::FindRule"));
  916. try
  917. {
  918. //
  919. // See if entry exists in map
  920. //
  921. if((it = m_RulesMap.find(DialingLocation)) == m_RulesMap.end())
  922. {
  923. SetLastError (FAX_ERR_RULE_NOT_FOUND);
  924. return NULL;
  925. }
  926. return &((*it).second);
  927. }
  928. catch (exception &ex)
  929. {
  930. DebugPrintEx(
  931. DEBUG_ERR,
  932. TEXT("map caused exception (%S)"),
  933. ex.what());
  934. SetLastError (ERROR_GEN_FAILURE);
  935. return NULL;
  936. }
  937. } // COutboundRulesMap::FindRule
  938. DWORD
  939. COutboundRulesMap::SerializeRules (PFAX_OUTBOUND_ROUTING_RULEW* ppRules,
  940. LPDWORD lpdwNumRules,
  941. LPDWORD lpdwBufferSize) const
  942. /*++
  943. Routine name : COutboundRulesMap::SerializeRules
  944. Routine description:
  945. Serializes all the rules in the rules map.
  946. the caller must call MemFree() to deallocate memory.
  947. Author:
  948. Oded Sacher (OdedS), Dec, 1999
  949. Arguments:
  950. ppRules [out ] - Pointer to a pointer to recieve the FAX_OUTBOUND_ROUTING_RULEW buffer
  951. lpdwNumRules [out ] - Pointer to a DWORD to recieve the number of rules serialized
  952. lpdwBufferSize [out ] - Pointer to DWORD to recieve the size of the allocated buffer
  953. Return Value:
  954. Standard Win32 error code
  955. --*/
  956. {
  957. RULES_MAP::iterator it;
  958. DWORD dwRes = ERROR_SUCCESS;
  959. DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::SerializeRules"));
  960. DWORD_PTR dwSize = 0;
  961. DWORD dwCount = 0;
  962. PCRULE pCRule;
  963. Assert (ppRules && lpdwNumRules && lpdwBufferSize);
  964. *ppRules = NULL;
  965. *lpdwNumRules = 0;
  966. try
  967. {
  968. // Calculate buffer size
  969. for (it = m_RulesMap.begin(); it != m_RulesMap.end(); ++it)
  970. {
  971. pCRule = &((*it).second);
  972. dwSize += sizeof (FAX_OUTBOUND_ROUTING_RULEW);
  973. dwRes = pCRule->Serialize (NULL, NULL, &dwSize, 0);
  974. if (ERROR_SUCCESS != dwRes)
  975. {
  976. DebugPrintEx(
  977. DEBUG_ERR,
  978. TEXT("COutboundRoutingRule::Serialize failed with %ld"),
  979. dwRes);
  980. goto exit;
  981. }
  982. dwCount ++;
  983. }
  984. //
  985. // dwCount can't be 0 - there is always a default rule
  986. //
  987. Assert ( dwCount != 0 );
  988. if ( 0 == dwCount )
  989. {
  990. //
  991. // Somthing wrong we have no outbound routing rule
  992. //
  993. DebugPrintEx(
  994. DEBUG_ERR,
  995. TEXT("COutboundRulesMap::SerializeRules, No outbound rules have been found."));
  996. dwRes = ERROR_INVALID_DATA;
  997. goto exit;
  998. }
  999. // Allocate buffer
  1000. *ppRules = (PFAX_OUTBOUND_ROUTING_RULEW) MemAlloc (dwSize);
  1001. if (NULL == *ppRules)
  1002. {
  1003. DebugPrintEx(
  1004. DEBUG_ERR,
  1005. TEXT("Cannot allocate rules buffer"));
  1006. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1007. goto exit;
  1008. }
  1009. ZeroMemory(*ppRules, dwSize);
  1010. DWORD_PTR dwOffset = dwCount * sizeof (FAX_OUTBOUND_ROUTING_RULEW);
  1011. dwCount = 0;
  1012. // Fill buffer with serialized info
  1013. for (it = m_RulesMap.begin(); it != m_RulesMap.end(); it++)
  1014. {
  1015. pCRule = &((*it).second);
  1016. (*ppRules)[dwCount].dwSizeOfStruct = DWORD(sizeof (FAX_OUTBOUND_ROUTING_RULEW));
  1017. dwRes = pCRule->Serialize ((LPBYTE)*ppRules, &((*ppRules)[dwCount]), &dwOffset, dwSize);
  1018. if (ERROR_SUCCESS != dwRes)
  1019. {
  1020. DebugPrintEx(
  1021. DEBUG_ERR,
  1022. TEXT("COutboundRoutingRule::Serialize failed with %ld"),
  1023. dwRes);
  1024. goto exit;
  1025. }
  1026. dwCount++;
  1027. }
  1028. }
  1029. catch (exception &ex)
  1030. {
  1031. DebugPrintEx(
  1032. DEBUG_ERR,
  1033. TEXT("map caused exception (%S)"),
  1034. ex.what());
  1035. dwRes = ERROR_GEN_FAILURE;
  1036. goto exit;
  1037. }
  1038. *lpdwNumRules = dwCount;
  1039. // until MIDL accepts [out, size_is(,__int64*)]
  1040. *lpdwBufferSize = (DWORD)dwSize;
  1041. Assert (ERROR_SUCCESS == dwRes);
  1042. exit:
  1043. if (ERROR_SUCCESS != dwRes)
  1044. {
  1045. MemFree (*ppRules);
  1046. }
  1047. return dwRes;
  1048. } // COutboundRulesMap::SerializeRules
  1049. BOOL
  1050. COutboundRulesMap::CreateDefaultRule (void)
  1051. /*++
  1052. Routine name : COutboundRulesMap::CreateDefaultRule
  1053. Routine description:
  1054. Creates the default mandatory rule (All CountryCodes, All AreaCodes) if does not exist.
  1055. Author:
  1056. Oded Sacher (OdedS), Dec, 1999
  1057. Arguments:
  1058. Return Value:
  1059. BOOL , Call GetLastError () for more info
  1060. --*/
  1061. {
  1062. DWORD dwRes = ERROR_SUCCESS;
  1063. DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::CreateDefaultRule"));
  1064. PCRULE pCRule;
  1065. CDialingLocation Dialinglocation (ROUTING_RULE_COUNTRY_CODE_ANY, ROUTING_RULE_AREA_CODE_ANY);
  1066. FAX_ENUM_RULE_STATUS dwRuleStatus;
  1067. HKEY hRuleKey = NULL;
  1068. DWORD rVal;
  1069. pCRule = FindRule (Dialinglocation);
  1070. if (NULL != pCRule)
  1071. {
  1072. // Rule exist
  1073. return TRUE;
  1074. }
  1075. dwRes = GetLastError();
  1076. if (FAX_ERR_RULE_NOT_FOUND != dwRes)
  1077. {
  1078. // general failure
  1079. DebugPrintEx(
  1080. DEBUG_ERR,
  1081. TEXT("COutboundRulesMap::FindRule failed , ec %ld"), dwRes);
  1082. return FALSE;
  1083. }
  1084. dwRes = ERROR_SUCCESS;
  1085. //
  1086. // Rule does not exist - Create it
  1087. //
  1088. // Create the rule registry key
  1089. hRuleKey = OpenOutboundRuleKey( ROUTING_RULE_COUNTRY_CODE_ANY, ROUTING_RULE_AREA_CODE_ANY, TRUE, KEY_READ | KEY_WRITE );
  1090. if (NULL == hRuleKey)
  1091. {
  1092. DebugPrintEx(
  1093. DEBUG_ERR,
  1094. TEXT("Can't create rule key, OpenRegistryKey failed : %ld"),
  1095. GetLastError ());
  1096. return FALSE;
  1097. }
  1098. COutboundRoutingRule Rule;
  1099. try
  1100. {
  1101. wstring wstrGroupName (ROUTING_GROUP_ALL_DEVICES);
  1102. dwRes = Rule.Init (Dialinglocation, wstrGroupName);
  1103. if (ERROR_SUCCESS != dwRes)
  1104. {
  1105. DebugPrintEx(
  1106. DEBUG_ERR,
  1107. TEXT("COutboundRoutingRule::Init failed , ec %ld"), dwRes);
  1108. goto exit;
  1109. }
  1110. }
  1111. catch (exception &ex)
  1112. {
  1113. DebugPrintEx(
  1114. DEBUG_ERR,
  1115. TEXT("wstring caused exception (%S)"),
  1116. ex.what());
  1117. dwRes = ERROR_GEN_FAILURE;
  1118. goto exit;
  1119. }
  1120. dwRes = AddRule (Rule);
  1121. if (ERROR_SUCCESS != dwRes)
  1122. {
  1123. DebugPrintEx(
  1124. DEBUG_ERR,
  1125. TEXT("COutboundRoutingRule::AddRule failed , ec %ld"), dwRes);
  1126. goto exit;
  1127. }
  1128. // Save the new rule to the registry
  1129. dwRes = Rule.Save (hRuleKey);
  1130. if (ERROR_SUCCESS != dwRes)
  1131. {
  1132. DebugPrintEx(
  1133. DEBUG_ERR,
  1134. TEXT("COutboundRoutingRule::Save failed, with %ld"),
  1135. dwRes);
  1136. g_pRulesMap->DelRule (Dialinglocation);
  1137. goto exit;
  1138. }
  1139. rVal = Rule.GetStatus (&dwRuleStatus);
  1140. if (ERROR_SUCCESS != rVal)
  1141. {
  1142. DebugPrintEx(
  1143. DEBUG_ERR,
  1144. TEXT("COutboundRoutingRule::GetStatus failed , ec %ld"), rVal);
  1145. }
  1146. else
  1147. {
  1148. if (dwRuleStatus != FAX_RULE_STATUS_VALID &&
  1149. dwRuleStatus != FAX_RULE_STATUS_SOME_GROUP_DEV_NOT_VALID)
  1150. {
  1151. // Can be if <All devices> is empty (The service has no devices).
  1152. DebugPrintEx(
  1153. DEBUG_MSG,
  1154. TEXT("Bad default rule configuration, FAX_RULE_STATUS %ld"), dwRuleStatus);
  1155. FaxLog(
  1156. FAXLOG_CATEGORY_INIT,
  1157. FAXLOG_LEVEL_MED,
  1158. 2,
  1159. MSG_BAD_OUTBOUND_ROUTING_RULE_CONFIGUTATION,
  1160. TEXT("*"),
  1161. TEXT("*")
  1162. );
  1163. }
  1164. }
  1165. Assert (ERROR_SUCCESS == dwRes);
  1166. exit:
  1167. if (NULL != hRuleKey)
  1168. {
  1169. RegCloseKey (hRuleKey);
  1170. }
  1171. if (ERROR_SUCCESS != dwRes)
  1172. {
  1173. SetLastError(dwRes);
  1174. }
  1175. return (ERROR_SUCCESS == dwRes);
  1176. } // CreateDefaultRule
  1177. DWORD
  1178. COutboundRulesMap::IsGroupInRuleDest (LPCWSTR lpcwstrGroupName , BOOL* lpbGroupInRule) const
  1179. /*++
  1180. Routine name : COutboundRulesMap::IsGroupInRuleDest
  1181. Routine description:
  1182. Checks if a specific group is a destination of one of the rules
  1183. Author:
  1184. Oded Sacher (OdedS), Dec, 1999
  1185. Arguments:
  1186. lpcwstrGroupName [in ] - Group name
  1187. lpbGroupInRule [out] - Pointer to a BOOL. Gets TRUE if the group is in rule, else FALSE
  1188. Return Value:
  1189. Standard Win32 error code.
  1190. --*/
  1191. {
  1192. DWORD dwRes = ERROR_SUCCESS;
  1193. DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::IsGroupInRuleDest"));
  1194. RULES_MAP::iterator it;
  1195. Assert (lpbGroupInRule);
  1196. try
  1197. {
  1198. for (it = m_RulesMap.begin(); it != m_RulesMap.end(); it++)
  1199. {
  1200. PCRULE pCRule = &((*it).second);
  1201. LPCWSTR lpcwstrRuleGroupName = pCRule->GetGroupName();
  1202. if (NULL == lpcwstrRuleGroupName)
  1203. {
  1204. dwRes = GetLastError();
  1205. if (dwRes != ERROR_SUCCESS)
  1206. {
  1207. DebugPrintEx(
  1208. DEBUG_ERR,
  1209. TEXT("COutboundRoutingRule::GetGroupName failed , ec %ld"), dwRes);
  1210. return dwRes;
  1211. }
  1212. else
  1213. {
  1214. // This rule uses a single device as its destination
  1215. }
  1216. continue;
  1217. }
  1218. if (wcscmp (lpcwstrGroupName, lpcwstrRuleGroupName) == 0)
  1219. {
  1220. *lpbGroupInRule = TRUE;
  1221. return ERROR_SUCCESS;
  1222. }
  1223. }
  1224. *lpbGroupInRule = FALSE;
  1225. return ERROR_SUCCESS;
  1226. }
  1227. catch (exception &ex)
  1228. {
  1229. DebugPrintEx(
  1230. DEBUG_ERR,
  1231. TEXT("map or wstring caused exception (%S)"),
  1232. ex.what());
  1233. return ERROR_GEN_FAILURE;
  1234. }
  1235. } // IsGroupInRuleDest
  1236. #if DBG
  1237. void COutboundRulesMap::Dump () const
  1238. {
  1239. RULES_MAP::iterator it;
  1240. WCHAR Buffer[512] = {0};
  1241. DWORD dwBufferSize = sizeof (Buffer)/ sizeof (Buffer[0]);
  1242. _snwprintf (Buffer, dwBufferSize -1, TEXT("DUMP - Outbound routing rules\n"));
  1243. OutputDebugString (Buffer);
  1244. for (it = m_RulesMap.begin(); it != m_RulesMap.end(); it++)
  1245. {
  1246. ((*it).second).Dump();
  1247. OutputDebugString (TEXT("\n"));
  1248. }
  1249. return;
  1250. }
  1251. #endif // #if DBG
  1252. void
  1253. FaxLogOutboundRule (LPCWSTR lpcwstrRuleName,
  1254. DWORD dwMessageID)
  1255. {
  1256. WCHAR wszRuleName[MAX_PATH] = {0};
  1257. LPWSTR lpwstrCountryCode;
  1258. LPWSTR lpwstrAreaCode;
  1259. LPWSTR lpwstrDelim = NULL;
  1260. DWORD dwLevel = FAXLOG_LEVEL_MIN;
  1261. Assert (lpcwstrRuleName);
  1262. Assert (dwMessageID == MSG_BAD_OUTBOUND_ROUTING_RULE_CONFIGUTATION ||
  1263. dwMessageID == MSG_OUTBOUND_ROUTING_RULE_NOT_LOADED ||
  1264. dwMessageID == MSG_OUTBOUND_ROUTING_RULE_NOT_ADDED);
  1265. if (dwMessageID == MSG_BAD_OUTBOUND_ROUTING_RULE_CONFIGUTATION)
  1266. {
  1267. dwLevel = FAXLOG_LEVEL_MED;
  1268. }
  1269. if (FAILED(StringCchCopy(wszRuleName, ARR_SIZE(wszRuleName), lpcwstrRuleName)))
  1270. {
  1271. ASSERT_FALSE;
  1272. return;
  1273. }
  1274. lpwstrDelim = wcschr (wszRuleName, L':');
  1275. if (NULL == lpwstrDelim)
  1276. {
  1277. //
  1278. // Registry corruption
  1279. //
  1280. ASSERT_FALSE;
  1281. return;
  1282. }
  1283. lpwstrCountryCode = wszRuleName;
  1284. *lpwstrDelim = L'\0';
  1285. lpwstrDelim ++;
  1286. lpwstrAreaCode = lpwstrDelim;
  1287. if (wcscmp( lpwstrAreaCode, TEXT("0")) == 0 )
  1288. {
  1289. wcscpy ( lpwstrAreaCode, TEXT("*"));
  1290. }
  1291. if (wcscmp( lpwstrCountryCode, TEXT("0")) == 0 )
  1292. {
  1293. wcscpy ( lpwstrCountryCode, TEXT("*"));
  1294. }
  1295. FaxLog(
  1296. FAXLOG_CATEGORY_INIT,
  1297. dwLevel,
  1298. 2,
  1299. dwMessageID,
  1300. lpwstrCountryCode,
  1301. lpwstrAreaCode
  1302. );
  1303. return;
  1304. }
  1305. /************************************
  1306. * *
  1307. * Registry *
  1308. * *
  1309. ************************************/
  1310. BOOL
  1311. EnumOutboundRoutingRulesCB(
  1312. HKEY hSubKey,
  1313. LPWSTR SubKeyName,
  1314. DWORD Index,
  1315. LPVOID pContext
  1316. )
  1317. {
  1318. DEBUG_FUNCTION_NAME(TEXT("EnumOutboundRoutingGroupsCB"));
  1319. DWORD dwRes;
  1320. COutboundRoutingRule Rule;
  1321. BOOL bRuleDeleted = FALSE;
  1322. if (!SubKeyName)
  1323. {
  1324. return TRUE;
  1325. }
  1326. //
  1327. // Add rule
  1328. //
  1329. dwRes = Rule.Load (hSubKey);
  1330. if (ERROR_SUCCESS != dwRes)
  1331. {
  1332. DebugPrintEx(
  1333. DEBUG_ERR,
  1334. TEXT("COutboundRoutingRule::Load failed, rule - %s, error %ld"),
  1335. SubKeyName,
  1336. dwRes);
  1337. // Open Outbound Routing\Rules key
  1338. HKEY hRulesKey = OpenRegistryKey( HKEY_LOCAL_MACHINE,
  1339. REGKEY_FAX_OUTBOUND_ROUTING_RULES,
  1340. FALSE,
  1341. KEY_READ | KEY_WRITE | DELETE);
  1342. if (NULL == hRulesKey)
  1343. {
  1344. dwRes = GetLastError ();
  1345. DebugPrintEx(
  1346. DEBUG_ERR,
  1347. TEXT("OpenRegistryKey, error %ld"),
  1348. dwRes);
  1349. }
  1350. else
  1351. {
  1352. DWORD dwRetVal = RegDeleteKey (hRulesKey, SubKeyName);
  1353. if (ERROR_SUCCESS != dwRetVal)
  1354. {
  1355. DebugPrintEx(
  1356. DEBUG_ERR,
  1357. TEXT("RegDeleteKey failed, Rule name - %s, error %ld"),
  1358. SubKeyName,
  1359. dwRetVal);
  1360. }
  1361. else
  1362. {
  1363. bRuleDeleted = TRUE;
  1364. }
  1365. }
  1366. goto exit;
  1367. }
  1368. //
  1369. // Check on which platform are we running
  1370. //
  1371. if ((Rule.GetDialingLocation()).GetCountryCode() != ROUTING_RULE_COUNTRY_CODE_ANY &&
  1372. TRUE == IsDesktopSKU())
  1373. {
  1374. //
  1375. // We do not support outbound routing on desktop SKUs. Only load default rule *.* (*.AreaCode is not loaded anyway)
  1376. //
  1377. goto exit;
  1378. }
  1379. FAX_ENUM_RULE_STATUS RuleStatus;
  1380. dwRes = Rule.GetStatus(&RuleStatus);
  1381. if (ERROR_SUCCESS == dwRes)
  1382. {
  1383. if (RuleStatus != FAX_RULE_STATUS_VALID &&
  1384. RuleStatus != FAX_RULE_STATUS_SOME_GROUP_DEV_NOT_VALID)
  1385. {
  1386. FaxLogOutboundRule (SubKeyName, MSG_BAD_OUTBOUND_ROUTING_RULE_CONFIGUTATION);
  1387. }
  1388. }
  1389. else
  1390. {
  1391. DebugPrintEx(
  1392. DEBUG_ERR,
  1393. TEXT("COutboundRoutingRule::GetStatus failed, error %ld"),
  1394. dwRes);
  1395. }
  1396. dwRes = g_pRulesMap->AddRule (Rule);
  1397. if (ERROR_SUCCESS != dwRes)
  1398. {
  1399. DebugPrintEx(
  1400. DEBUG_ERR,
  1401. TEXT("COutboundrulesMap::Addrule failed, rule name - %s, error %ld"),
  1402. SubKeyName,
  1403. dwRes);
  1404. goto exit;
  1405. }
  1406. Assert (ERROR_SUCCESS == dwRes);
  1407. exit:
  1408. if (ERROR_SUCCESS != dwRes)
  1409. {
  1410. if (bRuleDeleted == FALSE)
  1411. {
  1412. FaxLogOutboundRule (SubKeyName, MSG_OUTBOUND_ROUTING_RULE_NOT_ADDED);
  1413. }
  1414. else
  1415. {
  1416. FaxLogOutboundRule (SubKeyName, MSG_OUTBOUND_ROUTING_RULE_NOT_LOADED);
  1417. }
  1418. }
  1419. *(LPDWORD)pContext = ERROR_SUCCESS; // Let the service start
  1420. return TRUE; // Let the service start
  1421. } // EnumOutboundRoutingRulesCB
  1422. /************************************
  1423. * *
  1424. * RPC handlers *
  1425. * *
  1426. ************************************/
  1427. error_status_t
  1428. FAX_AddOutboundRule(
  1429. HANDLE hFaxHandle,
  1430. DWORD dwAreaCode,
  1431. DWORD dwCountryCode,
  1432. DWORD dwDeviceID,
  1433. LPCWSTR lpcwstrGroupName,
  1434. BOOL bUseGroup
  1435. )
  1436. /*++
  1437. Routine name : FAX_AddOutboundRule
  1438. Routine description:
  1439. Adds a new rule to the rules map and to the registry
  1440. Author:
  1441. Oded Sacher (OdedS), Dec, 1999
  1442. Arguments:
  1443. hFaxHandle [in ] - Fax handle
  1444. dwAreaCode [in ] - The rule area code
  1445. dwCountryCode [in ] - The rule country code
  1446. dwDeviceID [in ] - The rule's destinationis device ID. Valid only if bUseGroup is FALSE
  1447. lpcwstrGroupName [in ] - The rule's destination group name. Valid only if bUseGroup is TRUE.
  1448. bUseGroup [in ] - Flag that indicates whether to use the group as the rule destination
  1449. Return Value:
  1450. Standard Win32 error code
  1451. --*/
  1452. {
  1453. DWORD dwRes = ERROR_SUCCESS;
  1454. DEBUG_FUNCTION_NAME(TEXT("FAX_AddOutboundRule"));
  1455. HKEY hRuleKey = NULL;
  1456. DWORD rVal;
  1457. BOOL fAccess;
  1458. //
  1459. // Access check
  1460. //
  1461. dwRes = FaxSvcAccessCheck (FAX_ACCESS_MANAGE_CONFIG, &fAccess, NULL);
  1462. if (ERROR_SUCCESS != dwRes)
  1463. {
  1464. DebugPrintEx(DEBUG_ERR,
  1465. TEXT("FaxSvcAccessCheck Failed, Error : %ld"),
  1466. dwRes);
  1467. return GetServerErrorCode(dwRes);
  1468. }
  1469. if (FALSE == fAccess)
  1470. {
  1471. DebugPrintEx(DEBUG_ERR,
  1472. TEXT("The user does not have the FAX_ACCESS_MANAGE_CONFIG right"));
  1473. return ERROR_ACCESS_DENIED;
  1474. }
  1475. if (dwCountryCode == ROUTING_RULE_COUNTRY_CODE_ANY)
  1476. {
  1477. //
  1478. // *.* can not be added; *.AreaCode is not a valid rule dialing location.
  1479. //
  1480. DebugPrintEx(
  1481. DEBUG_ERR,
  1482. TEXT("dwCountryCode = 0; *.* can not be added; *.AreaCode is not a valid rule dialing location"));
  1483. return ERROR_INVALID_PARAMETER;
  1484. }
  1485. if (TRUE == IsDesktopSKU())
  1486. {
  1487. //
  1488. // We do not support outbound routing on desktop SKUs.
  1489. //
  1490. if (FAX_API_VERSION_1 > FindClientAPIVersion (hFaxHandle))
  1491. {
  1492. //
  1493. // API version 0 clients don't know about FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU
  1494. //
  1495. return ERROR_INVALID_PARAMETER;
  1496. }
  1497. else
  1498. {
  1499. return FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU;
  1500. }
  1501. }
  1502. if (TRUE == bUseGroup)
  1503. {
  1504. if (!lpcwstrGroupName)
  1505. {
  1506. DebugPrintEx(
  1507. DEBUG_ERR,
  1508. TEXT("lpctstrGroupName is NULL"));
  1509. return ERROR_INVALID_PARAMETER;
  1510. }
  1511. if (wcslen (lpcwstrGroupName) >= MAX_ROUTING_GROUP_NAME)
  1512. {
  1513. DebugPrintEx(
  1514. DEBUG_ERR,
  1515. TEXT("Group name length exceeded MAX_ROUTING_GROUP_NAME"));
  1516. return ERROR_BUFFER_OVERFLOW;
  1517. }
  1518. }
  1519. else
  1520. {
  1521. if (!dwDeviceID)
  1522. {
  1523. DebugPrintEx(
  1524. DEBUG_ERR,
  1525. TEXT("dwDeviceId = 0; Not a valid device ID"));
  1526. return ERROR_INVALID_PARAMETER;
  1527. }
  1528. }
  1529. // Create a new Dialinglocation object
  1530. CDialingLocation Dialinglocation (dwCountryCode, dwAreaCode);
  1531. if (!Dialinglocation.IsValid())
  1532. {
  1533. DebugPrintEx(
  1534. DEBUG_ERR,
  1535. TEXT("CDialingLocation::IsValidDialingLocation failed, \
  1536. Area code %ld, Country code %ld"),
  1537. dwAreaCode,
  1538. dwCountryCode);
  1539. return ERROR_INVALID_PARAMETER;
  1540. }
  1541. // Create a new rule object
  1542. COutboundRoutingRule Rule;
  1543. if (TRUE == bUseGroup)
  1544. {
  1545. try
  1546. {
  1547. wstring wstrGroupName(lpcwstrGroupName);
  1548. dwRes = Rule.Init (Dialinglocation, wstrGroupName);
  1549. if (ERROR_SUCCESS != dwRes)
  1550. {
  1551. DebugPrintEx(
  1552. DEBUG_ERR,
  1553. TEXT("COutboundRoutingRule::Init failed , ec %ld"), dwRes);
  1554. return GetServerErrorCode(dwRes);
  1555. }
  1556. }
  1557. catch (exception &ex)
  1558. {
  1559. DebugPrintEx(
  1560. DEBUG_ERR,
  1561. TEXT("wstring caused exception (%S)"),
  1562. ex.what());
  1563. return ERROR_GEN_FAILURE;
  1564. }
  1565. }
  1566. else
  1567. {
  1568. Rule.Init (Dialinglocation ,dwDeviceID);
  1569. }
  1570. EnterCriticalSection (&g_CsLine);
  1571. EnterCriticalSection (&g_CsConfig);
  1572. FAX_ENUM_RULE_STATUS RuleStatus;
  1573. dwRes = Rule.GetStatus(&RuleStatus);
  1574. if (ERROR_SUCCESS != dwRes)
  1575. {
  1576. DebugPrintEx(
  1577. DEBUG_ERR,
  1578. TEXT("COutboundRoule::GetStatus failed, error %ld"),
  1579. dwRes);
  1580. goto exit;
  1581. }
  1582. if (FAX_GROUP_STATUS_ALL_DEV_NOT_VALID == RuleStatus ||
  1583. FAX_RULE_STATUS_EMPTY_GROUP == RuleStatus)
  1584. {
  1585. // Empty group device list
  1586. DebugPrintEx(
  1587. DEBUG_ERR,
  1588. TEXT("Bad rule configutation, FAX_RULE_STATUS %ld"), RuleStatus);
  1589. dwRes = FAX_ERR_BAD_GROUP_CONFIGURATION;
  1590. goto exit;
  1591. }
  1592. if (FAX_RULE_STATUS_BAD_DEVICE == RuleStatus)
  1593. {
  1594. // Bad device
  1595. DebugPrintEx(
  1596. DEBUG_ERR,
  1597. TEXT("Bad rule configutation, FAX_RULE_STATUS %ld"), RuleStatus);
  1598. dwRes = ERROR_BAD_UNIT;
  1599. goto exit;
  1600. }
  1601. // Create the rule registry key
  1602. hRuleKey = OpenOutboundRuleKey( dwCountryCode, dwAreaCode, TRUE, KEY_READ | KEY_WRITE );
  1603. if (NULL == hRuleKey)
  1604. {
  1605. dwRes = GetLastError ();
  1606. DebugPrintEx(
  1607. DEBUG_ERR,
  1608. TEXT("Can't create rule key, OpenRegistryKey failed : %ld"),
  1609. dwRes);
  1610. dwRes = ERROR_REGISTRY_CORRUPT;
  1611. goto exit;
  1612. }
  1613. // Add the new rule to the map
  1614. dwRes = g_pRulesMap->AddRule (Rule);
  1615. if (ERROR_SUCCESS != dwRes)
  1616. {
  1617. DebugPrintEx(
  1618. DEBUG_ERR,
  1619. TEXT("COutboundRoulesMap::AddRule failed, error %ld"),
  1620. dwRes);
  1621. goto exit;
  1622. }
  1623. // Save the new rule to the registry
  1624. dwRes = Rule.Save (hRuleKey);
  1625. if (ERROR_SUCCESS != dwRes)
  1626. {
  1627. DebugPrintEx(
  1628. DEBUG_ERR,
  1629. TEXT("COutboundRoutingRule::Save failed, with %ld"),
  1630. dwRes);
  1631. g_pRulesMap->DelRule (Dialinglocation);
  1632. dwRes = ERROR_REGISTRY_CORRUPT;
  1633. goto exit;
  1634. }
  1635. #if DBG
  1636. DebugPrintEx(
  1637. DEBUG_MSG,
  1638. TEXT("Dump outbound routing rules - after change"));
  1639. g_pRulesMap->Dump();
  1640. #endif
  1641. rVal = CreateConfigEvent (FAX_CONFIG_TYPE_OUT_RULES);
  1642. if (ERROR_SUCCESS != dwRes)
  1643. {
  1644. DebugPrintEx(
  1645. DEBUG_ERR,
  1646. TEXT("CreateConfigEvent(FAX_CONFIG_TYPE_OUT_RULES) (ec: %lc)"),
  1647. rVal);
  1648. }
  1649. Assert (ERROR_SUCCESS == dwRes);
  1650. exit:
  1651. if (NULL != hRuleKey)
  1652. {
  1653. RegCloseKey (hRuleKey);
  1654. }
  1655. LeaveCriticalSection (&g_CsConfig);
  1656. LeaveCriticalSection (&g_CsLine);
  1657. if (ERROR_SUCCESS == dwRes)
  1658. {
  1659. //
  1660. // We might find a line for a pending job. Wake up JobQueueThread
  1661. //
  1662. if (!SetEvent( g_hJobQueueEvent ))
  1663. {
  1664. DebugPrintEx(
  1665. DEBUG_ERR,
  1666. TEXT("Failed to set g_hJobQueueEvent. (ec: %ld)"),
  1667. GetLastError());
  1668. EnterCriticalSection (&g_CsQueue);
  1669. g_ScanQueueAfterTimeout = TRUE;
  1670. LeaveCriticalSection (&g_CsQueue);
  1671. }
  1672. }
  1673. UNREFERENCED_PARAMETER (hFaxHandle);
  1674. return GetServerErrorCode(dwRes);
  1675. } // FAX_AddOutboundRule
  1676. error_status_t
  1677. FAX_RemoveOutboundRule (
  1678. IN handle_t hFaxHandle,
  1679. IN DWORD dwAreaCode,
  1680. IN DWORD dwCountryCode
  1681. )
  1682. /*++
  1683. Routine name : FAX_RemoveOutboundRule
  1684. Routine description:
  1685. Removes an existing rule from the rules map and from the registry.
  1686. Author:
  1687. Oded Sacher (OdedS), Dec, 1999
  1688. Arguments:
  1689. hFaxHandle [in] - Fax handle
  1690. dwAreaCode [in] - The rule area code
  1691. dwCountryCode [in] - The rule country code
  1692. Return Value:
  1693. Standard Win32 error code
  1694. --*/
  1695. {
  1696. DWORD dwRes = ERROR_SUCCESS;
  1697. DEBUG_FUNCTION_NAME(TEXT("FAX_RemoveOutboundRule"));
  1698. DWORD rVal;
  1699. PCRULE pCRule = NULL;
  1700. BOOL fAccess;
  1701. //
  1702. // Access check
  1703. //
  1704. dwRes = FaxSvcAccessCheck (FAX_ACCESS_MANAGE_CONFIG, &fAccess, NULL);
  1705. if (ERROR_SUCCESS != dwRes)
  1706. {
  1707. DebugPrintEx(DEBUG_ERR,
  1708. TEXT("FaxSvcAccessCheck Failed, Error : %ld"),
  1709. dwRes);
  1710. return GetServerErrorCode(dwRes);
  1711. }
  1712. if (FALSE == fAccess)
  1713. {
  1714. DebugPrintEx(DEBUG_ERR,
  1715. TEXT("The user does not have the FAX_ACCESS_MANAGE_CONFIG right"));
  1716. return ERROR_ACCESS_DENIED;
  1717. }
  1718. if (dwCountryCode == ROUTING_RULE_COUNTRY_CODE_ANY)
  1719. {
  1720. //
  1721. // *.* can not be removed; *.AreaCode is not a valid rule dialing location.
  1722. //
  1723. DebugPrintEx(
  1724. DEBUG_ERR,
  1725. TEXT("dwCountryCode = 0; *.* can not be added; *.AreaCode is not a valid rule dialing location"));
  1726. return ERROR_INVALID_PARAMETER;
  1727. }
  1728. if (TRUE == IsDesktopSKU())
  1729. {
  1730. //
  1731. // We do not support outbound routing on desktop SKUs.
  1732. //
  1733. if (FAX_API_VERSION_1 > FindClientAPIVersion (hFaxHandle))
  1734. {
  1735. //
  1736. // API version 0 clients don't know about FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU
  1737. //
  1738. return ERROR_INVALID_PARAMETER;
  1739. }
  1740. else
  1741. {
  1742. return FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU;
  1743. }
  1744. }
  1745. CDialingLocation Dialinglocation (dwCountryCode, dwAreaCode);
  1746. EnterCriticalSection (&g_CsConfig);
  1747. pCRule = g_pRulesMap->FindRule (Dialinglocation);
  1748. if (NULL == pCRule)
  1749. {
  1750. dwRes = GetLastError();
  1751. DebugPrintEx(
  1752. DEBUG_ERR,
  1753. TEXT("COutboundRoulesMap::FindRule failed, error %ld"),
  1754. dwRes);
  1755. goto exit;
  1756. }
  1757. // Delete the specified rule key
  1758. dwRes = DeleteOutboundRuleKey (dwCountryCode, dwAreaCode);
  1759. if (ERROR_SUCCESS != dwRes)
  1760. {
  1761. DebugPrintEx(
  1762. DEBUG_ERR,
  1763. TEXT("DeleteOutboundRuleKey failed, CountryCode - %ld, AreaCode - %ld, error %ld"),
  1764. dwCountryCode,
  1765. dwAreaCode,
  1766. dwRes);
  1767. dwRes = ERROR_REGISTRY_CORRUPT;
  1768. goto exit;
  1769. }
  1770. // Delete the rule from the memory
  1771. dwRes = g_pRulesMap->DelRule (Dialinglocation);
  1772. if (ERROR_SUCCESS != dwRes)
  1773. {
  1774. DebugPrintEx(
  1775. DEBUG_ERR,
  1776. TEXT("COutboundRulesMap::DelRule failed, error %ld"),
  1777. dwRes);
  1778. goto exit;
  1779. }
  1780. #if DBG
  1781. DebugPrintEx(
  1782. DEBUG_MSG,
  1783. TEXT("Dump outbound routing rules - after change"));
  1784. g_pRulesMap->Dump();
  1785. #endif
  1786. rVal = CreateConfigEvent (FAX_CONFIG_TYPE_OUT_RULES);
  1787. if (ERROR_SUCCESS != rVal)
  1788. {
  1789. DebugPrintEx(
  1790. DEBUG_ERR,
  1791. TEXT("CreateConfigEvent(FAX_CONFIG_TYPE_OUT_RULES) (ec: %lc)"),
  1792. rVal);
  1793. }
  1794. Assert (ERROR_SUCCESS == dwRes);
  1795. exit:
  1796. LeaveCriticalSection (&g_CsConfig);
  1797. if (ERROR_SUCCESS == dwRes)
  1798. {
  1799. //
  1800. // We might find a line for a pending job. Wake up JobQueueThread
  1801. //
  1802. if (!SetEvent( g_hJobQueueEvent ))
  1803. {
  1804. DebugPrintEx(
  1805. DEBUG_ERR,
  1806. TEXT("Failed to set g_hJobQueueEvent. (ec: %ld)"),
  1807. GetLastError());
  1808. EnterCriticalSection (&g_CsQueue);
  1809. g_ScanQueueAfterTimeout = TRUE;
  1810. LeaveCriticalSection (&g_CsQueue);
  1811. }
  1812. }
  1813. UNREFERENCED_PARAMETER (hFaxHandle);
  1814. return dwRes;
  1815. } // FAX_RemoveOutboundRule
  1816. error_status_t
  1817. FAX_SetOutboundRule(
  1818. HANDLE hFaxHandle,
  1819. PRPC_FAX_OUTBOUND_ROUTING_RULEW pRule
  1820. )
  1821. {
  1822. DWORD dwRes = ERROR_SUCCESS;
  1823. DWORD rVal;
  1824. DEBUG_FUNCTION_NAME(TEXT("FAX_SetOutboundRule"));
  1825. HKEY hRuleKey = NULL;
  1826. PCRULE pCRule = NULL;
  1827. FAX_ENUM_RULE_STATUS dwRuleStatus;
  1828. BOOL fAccess;
  1829. Assert (pRule);
  1830. //
  1831. // Access check
  1832. //
  1833. dwRes = FaxSvcAccessCheck (FAX_ACCESS_MANAGE_CONFIG, &fAccess, NULL);
  1834. if (ERROR_SUCCESS != dwRes)
  1835. {
  1836. DebugPrintEx(DEBUG_ERR,
  1837. TEXT("FaxSvcAccessCheck Failed, Error : %ld"),
  1838. dwRes);
  1839. return GetServerErrorCode(dwRes);
  1840. }
  1841. if (FALSE == fAccess)
  1842. {
  1843. DebugPrintEx(DEBUG_ERR,
  1844. TEXT("The user does not have the FAX_ACCESS_MANAGE_CONFIG right"));
  1845. return ERROR_ACCESS_DENIED;
  1846. }
  1847. if (TRUE == pRule->bUseGroup)
  1848. {
  1849. if (!(pRule->Destination).lpwstrGroupName)
  1850. {
  1851. DebugPrintEx(
  1852. DEBUG_ERR,
  1853. TEXT("lpwstrGroupName is NULL"));
  1854. return ERROR_INVALID_PARAMETER;
  1855. }
  1856. if (wcslen ((pRule->Destination).lpwstrGroupName) >= MAX_ROUTING_GROUP_NAME)
  1857. {
  1858. DebugPrintEx(
  1859. DEBUG_ERR,
  1860. TEXT("Group name length exceeded MAX_ROUTING_GROUP_NAME"));
  1861. return ERROR_BUFFER_OVERFLOW;
  1862. }
  1863. }
  1864. else
  1865. {
  1866. if (!(pRule->Destination).dwDeviceId)
  1867. {
  1868. DebugPrintEx(
  1869. DEBUG_ERR,
  1870. TEXT("dwDeviceId = 0; Not a valid device ID"));
  1871. return ERROR_INVALID_PARAMETER;
  1872. }
  1873. }
  1874. if (TRUE == IsDesktopSKU())
  1875. {
  1876. //
  1877. // We do not support outbound routing on desktop SKUs.
  1878. //
  1879. if (FAX_API_VERSION_1 > FindClientAPIVersion (hFaxHandle))
  1880. {
  1881. //
  1882. // API version 0 clients don't know about FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU
  1883. //
  1884. return ERROR_INVALID_PARAMETER;
  1885. }
  1886. else
  1887. {
  1888. return FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU;
  1889. }
  1890. }
  1891. CDialingLocation Dialinglocation (pRule->dwCountryCode, pRule->dwAreaCode);
  1892. COutboundRoutingRule Rule, OldRule;
  1893. if (TRUE == pRule->bUseGroup)
  1894. {
  1895. try
  1896. {
  1897. wstring wstrGroupName((pRule->Destination).lpwstrGroupName);
  1898. dwRes = Rule.Init (Dialinglocation, wstrGroupName);
  1899. if (ERROR_SUCCESS != dwRes)
  1900. {
  1901. DebugPrintEx(
  1902. DEBUG_ERR,
  1903. TEXT("COutboundRoutingRule::Init failed , ec %ld"), dwRes);
  1904. return GetServerErrorCode(dwRes);
  1905. }
  1906. }
  1907. catch (exception &ex)
  1908. {
  1909. DebugPrintEx(
  1910. DEBUG_ERR,
  1911. TEXT("wstring caused exception (%S)"),
  1912. ex.what());
  1913. return ERROR_GEN_FAILURE;
  1914. }
  1915. }
  1916. else
  1917. {
  1918. Rule.Init (Dialinglocation ,(pRule->Destination).dwDeviceId);
  1919. }
  1920. EnterCriticalSection (&g_CsLine);
  1921. EnterCriticalSection (&g_CsConfig);
  1922. // Check the new rule status
  1923. dwRes = Rule.GetStatus (&dwRuleStatus);
  1924. if (ERROR_SUCCESS != dwRes)
  1925. {
  1926. DebugPrintEx(
  1927. DEBUG_ERR,
  1928. TEXT("COutboundRoutingRule::GetStatus failed , ec %ld"), dwRes);
  1929. goto exit;
  1930. }
  1931. if (FAX_GROUP_STATUS_ALL_DEV_NOT_VALID == dwRuleStatus ||
  1932. FAX_RULE_STATUS_EMPTY_GROUP == dwRuleStatus)
  1933. {
  1934. // Empty group device list
  1935. DebugPrintEx(
  1936. DEBUG_ERR,
  1937. TEXT("Bad rule configutation, FAX_RULE_STATUS %ld"), dwRuleStatus);
  1938. dwRes = FAX_ERR_BAD_GROUP_CONFIGURATION;
  1939. goto exit;
  1940. }
  1941. if (FAX_RULE_STATUS_BAD_DEVICE == dwRuleStatus)
  1942. {
  1943. // Bad device
  1944. DebugPrintEx(
  1945. DEBUG_ERR,
  1946. TEXT("Bad rule configutation, FAX_RULE_STATUS %ld"), dwRuleStatus);
  1947. dwRes = ERROR_BAD_UNIT;
  1948. goto exit;
  1949. }
  1950. pCRule = g_pRulesMap->FindRule (Dialinglocation);
  1951. if (NULL == pCRule)
  1952. {
  1953. dwRes = GetLastError();
  1954. DebugPrintEx(
  1955. DEBUG_ERR,
  1956. TEXT("COutboundRoulesMap::FindRule failed, error %ld"),
  1957. dwRes);
  1958. goto exit;
  1959. }
  1960. // Open the rule registry key
  1961. hRuleKey = OpenOutboundRuleKey( pRule->dwCountryCode, pRule->dwAreaCode, FALSE, KEY_READ | KEY_WRITE );
  1962. if (NULL == hRuleKey)
  1963. {
  1964. dwRes = GetLastError ();
  1965. DebugPrintEx(
  1966. DEBUG_ERR,
  1967. TEXT("Can't open rule key, OpenRegistryKey failed : %ld"),
  1968. dwRes);
  1969. dwRes = ERROR_REGISTRY_CORRUPT;
  1970. goto exit;
  1971. }
  1972. OldRule = *pCRule;
  1973. *pCRule = Rule;
  1974. dwRes = pCRule->Save (hRuleKey);
  1975. if (ERROR_SUCCESS != dwRes)
  1976. {
  1977. DebugPrintEx(
  1978. DEBUG_ERR,
  1979. TEXT("COutboundRoutingRule::Save failed, with %ld"),
  1980. dwRes);
  1981. *pCRule = OldRule;
  1982. dwRes = ERROR_REGISTRY_CORRUPT;
  1983. goto exit;
  1984. }
  1985. #if DBG
  1986. DebugPrintEx(
  1987. DEBUG_MSG,
  1988. TEXT("Dump outbound routing rules - after change"));
  1989. g_pRulesMap->Dump();
  1990. #endif
  1991. rVal = CreateConfigEvent (FAX_CONFIG_TYPE_OUT_RULES);
  1992. if (ERROR_SUCCESS != rVal)
  1993. {
  1994. DebugPrintEx(
  1995. DEBUG_ERR,
  1996. TEXT("CreateConfigEvent(FAX_CONFIG_TYPE_OUT_RULES) (ec: %lc)"),
  1997. rVal);
  1998. }
  1999. Assert (ERROR_SUCCESS == dwRes);
  2000. exit:
  2001. if (NULL != hRuleKey)
  2002. {
  2003. RegCloseKey (hRuleKey);
  2004. }
  2005. LeaveCriticalSection (&g_CsConfig);
  2006. LeaveCriticalSection (&g_CsLine);
  2007. if (ERROR_SUCCESS == dwRes)
  2008. {
  2009. //
  2010. // We might find a line for a pending job. Wake up JobQueueThread
  2011. //
  2012. if (!SetEvent( g_hJobQueueEvent ))
  2013. {
  2014. DebugPrintEx(
  2015. DEBUG_ERR,
  2016. TEXT("Failed to set g_hJobQueueEvent. (ec: %ld)"),
  2017. GetLastError());
  2018. EnterCriticalSection (&g_CsQueue);
  2019. g_ScanQueueAfterTimeout = TRUE;
  2020. LeaveCriticalSection (&g_CsQueue);
  2021. }
  2022. }
  2023. UNREFERENCED_PARAMETER (hFaxHandle);
  2024. return GetServerErrorCode(dwRes);
  2025. } // FAX_FaxSetOutboundRule
  2026. error_status_t
  2027. FAX_EnumOutboundRules (
  2028. handle_t hFaxHandle,
  2029. LPBYTE* ppBuffer,
  2030. LPDWORD lpdwBufferSize,
  2031. LPDWORD lpdwNumRules
  2032. )
  2033. /*++
  2034. Routine name : FAX_EnumOutboundRules
  2035. Routine description:
  2036. Enumurates all outbound routing rules
  2037. Author:
  2038. Oded Sacher (OdedS), Dec, 1999
  2039. Arguments:
  2040. hFaxHandle [in ] - Fax server handle
  2041. ppBuffer [out ] - Adress of a pointer to a buffer to be filled with info
  2042. lpdwBufferSize [in/out] - The buffer size
  2043. lpdwNumGroups [out ] - Number of rules returned
  2044. Return Value:
  2045. error_status_t
  2046. --*/
  2047. {
  2048. DWORD dwRes = ERROR_SUCCESS;
  2049. DEBUG_FUNCTION_NAME(TEXT("FAX_EnumOutboundRules"));
  2050. BOOL fAccess;
  2051. Assert (lpdwNumRules && lpdwBufferSize); // ref pointer in idl
  2052. if (!ppBuffer) // unique pointer in idl
  2053. {
  2054. return ERROR_INVALID_PARAMETER;
  2055. }
  2056. if (TRUE == IsDesktopSKU())
  2057. {
  2058. //
  2059. // We do not support outbound routing on desktop SKUs.
  2060. //
  2061. if (FAX_API_VERSION_1 > FindClientAPIVersion (hFaxHandle))
  2062. {
  2063. //
  2064. // API version 0 clients don't know about FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU
  2065. //
  2066. return ERROR_INVALID_PARAMETER;
  2067. }
  2068. else
  2069. {
  2070. return FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU;
  2071. }
  2072. }
  2073. //
  2074. // Access check
  2075. //
  2076. dwRes = FaxSvcAccessCheck (FAX_ACCESS_QUERY_CONFIG, &fAccess, NULL);
  2077. if (ERROR_SUCCESS != dwRes)
  2078. {
  2079. DebugPrintEx(DEBUG_ERR,
  2080. TEXT("FaxSvcAccessCheck Failed, Error : %ld"),
  2081. dwRes);
  2082. return GetServerErrorCode(dwRes);
  2083. }
  2084. if (FALSE == fAccess)
  2085. {
  2086. DebugPrintEx(DEBUG_ERR,
  2087. TEXT("The user does not have the FAX_ACCESS_QUERY_CONFIG right"));
  2088. return ERROR_ACCESS_DENIED;
  2089. }
  2090. *ppBuffer = NULL;
  2091. *lpdwNumRules = 0;
  2092. EnterCriticalSection (&g_CsLine);
  2093. EnterCriticalSection (&g_CsConfig);
  2094. dwRes = g_pRulesMap->SerializeRules ((PFAX_OUTBOUND_ROUTING_RULEW*)ppBuffer,
  2095. lpdwNumRules,
  2096. lpdwBufferSize);
  2097. if (ERROR_SUCCESS != dwRes)
  2098. {
  2099. DebugPrintEx(
  2100. DEBUG_ERR,
  2101. TEXT("COutboundRoutingRulesMap::SerializeRules failed, error %ld"),
  2102. dwRes);
  2103. goto exit;
  2104. }
  2105. Assert (ERROR_SUCCESS == dwRes);
  2106. exit:
  2107. LeaveCriticalSection (&g_CsConfig);
  2108. LeaveCriticalSection (&g_CsLine);
  2109. UNREFERENCED_PARAMETER (hFaxHandle);
  2110. return GetServerErrorCode(dwRes);
  2111. } //FAX_EnumOutboundGroups