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.

2546 lines
61 KiB

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