/*++ Copyright (c) 1999 Microsoft Corporation Module Name: OutRoute.cpp Abstract: This file provides implementation of the service outbound routing. Author: Oded Sacher (OdedS) Nov, 1999 Revision History: --*/ #include "faxsvc.h" BOOL EnumOutboundRoutingGroupsCB( HKEY hSubKey, LPWSTR SubKeyName, DWORD Index, LPVOID pContext ); inline BOOL IsDeviceInstalled (DWORD dwDeviceId) { // Make sure to lock g_CsLine return (GetTapiLineFromDeviceId (dwDeviceId, FALSE)) ? TRUE : FALSE; } /************************************ * * * Globals * * * ************************************/ COutboundRoutingGroupsMap* g_pGroupsMap; // Map of group name to list of device IDs /*********************************** * * * COutboundRoutingGroup Methodes * * * ***********************************/ DWORD COutboundRoutingGroup::Load(HKEY hGroupKey, LPCWSTR lpcwstrGroupName) /*++ Routine name : COutboundRoutingGroup::Load Routine description: Loads an outboundrouting group's settings from the registry Author: Oded Sacher (OdedS), Dec, 1999 Arguments: hGroupKey [in] - Handle to the opened registry key lpcwstrGroupName [in] - Group name Return Value: Standard Win32 error code --*/ { LPBYTE lpBuffer = NULL; DWORD dwRes; DWORD dwType; DWORD dwSize=0; DWORD i; DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroup::Load")); Assert (hGroupKey); dwRes = RegQueryValueEx( hGroupKey, REGVAL_ROUTING_GROUP_DEVICES, NULL, &dwType, NULL, &dwSize ); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("RegQueryValueEx failed with %ld"), dwRes); goto exit; } if (REG_BINARY != dwType) { // // We expect only binary data here // // DebugPrintEx( DEBUG_ERR, TEXT("Error reading devices list, not a binary type")); dwRes = ERROR_BADDB; // The configuration registry database is corrupt. goto exit; } if (0 != dwSize) { // // Allocate required buffer // lpBuffer = (LPBYTE) MemAlloc( dwSize ); if (!lpBuffer) { dwRes = ERROR_NOT_ENOUGH_MEMORY; DebugPrintEx( DEBUG_ERR, TEXT("Failed to allocate group devices buffer")); goto exit; } // // Read the data // dwRes = RegQueryValueEx( hGroupKey, REGVAL_ROUTING_GROUP_DEVICES, NULL, &dwType, lpBuffer, &dwSize ); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("RegQueryValueEx failed with %ld"), dwRes); goto exit; } LPDWORD lpdwDevices = (LPDWORD)lpBuffer; DWORD dwNumDevices = dwSize/sizeof(DWORD); BOOL fDeviceInstalled = TRUE; for (i = 0; i < dwNumDevices; i++) { if (IsDeviceInstalled(lpdwDevices[i])) { // // Add the device only if it is installed // dwRes = AddDevice (lpdwDevices[i]); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::AddDevice failed with %ld"), dwRes); goto exit; } } else { fDeviceInstalled = FALSE; } } if (FALSE == fDeviceInstalled) { // // Save the new configuration // DWORD ec = Save(hGroupKey); if (ERROR_SUCCESS != ec) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::Save failed with %ld"), ec); } FaxLog( FAXLOG_CATEGORY_INIT, FAXLOG_LEVEL_MED, 1, MSG_BAD_OUTBOUND_ROUTING_GROUP_CONFIGURATION, lpcwstrGroupName ); } } Assert (ERROR_SUCCESS == dwRes); exit: MemFree (lpBuffer); return dwRes; } DWORD COutboundRoutingGroup::GetStatus (FAX_ENUM_GROUP_STATUS* lpStatus) const /*++ Routine name : COutboundRoutingGroup::GetStatus Routine description: Retrieves the group status. Caller must lock g_CsConfig Author: Oded Sacher (OdedS), Dec, 1999 Arguments: lpStatus [out] - Pointer to a FAX_ENUM_GROUP_STATUS to recieve the group status Return Value: Standard Win32 error code --*/ { DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroup::GetStatus")); DWORD dwNumDevices; Assert (lpStatus); try { if ((dwNumDevices = m_DeviceList.size()) == 0) { // // Empty group // *lpStatus = FAX_GROUP_STATUS_EMPTY; } else { // // We remove invalid devices from groups - All devices are valid. // *lpStatus = FAX_GROUP_STATUS_ALL_DEV_VALID; } return ERROR_SUCCESS; } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("list caused exception (%S)"), ex.what()); return ERROR_GEN_FAILURE; } } // GetStatus DWORD COutboundRoutingGroup::Save(HKEY hGroupKey) const /*++ Routine name : COutboundRoutingGroup::Save Routine description: Saves an outbound routing group to the registry Author: Oded Sacher (OdedS), Dec, 1999 Arguments: hGroupKey [in] - Handle to the opened group registry key Return Value: Standard Win32 error code --*/ { DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroup::Save")); DWORD dwRes = ERROR_SUCCESS; LPDWORD lpdwDevices = NULL; DWORD dwNumDevices = 0; Assert (hGroupKey); dwRes = SerializeDevices (&lpdwDevices, &dwNumDevices); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::EnumDevices failed , ec %ld"), dwRes); goto exit; } if (!SetRegistryBinary( hGroupKey, REGVAL_ROUTING_GROUP_DEVICES, (LPBYTE) lpdwDevices, dwNumDevices * sizeof(DWORD))) { dwRes = GetLastError(); DebugPrintEx( DEBUG_ERR, TEXT("SetRegistryBinary failed , ec %ld"), dwRes); goto exit; } Assert (dwRes == ERROR_SUCCESS); exit: MemFree (lpdwDevices); return dwRes; } DWORD COutboundRoutingGroup::SerializeDevices (LPDWORD* lppDevices, LPDWORD lpdwNumDevices, BOOL bAllocate) const /*++ Routine name : COutboundRoutingGroup::SerializeDevices Routine description: Serializes all group devices to an array. The caller must call MemFree to deallocate memory if bAllocate is TRUE. Author: Oded Sacher (OdedS), Dec, 1999 Arguments: lppDevices [out] - Pointer to recieve the pointer to the allocated devices buffer. If this parameter is NULL, lpdwNumDevices will return the numner of devices in the list. lpdwNumDevices [out] - Pointer to a DWORD to recieve the number of devices in the buffer bAllocate [in] - Flag to indicate if the function should allocate the memory. Return Value: Standard Win32 error code --*/ { DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroup::SerializeDevices")); DWORD dwRes = ERROR_SUCCESS; GROUP_DEVICES::iterator it; DWORD dwCount = 0; Assert (lpdwNumDevices); if (NULL == lppDevices ) { try { *lpdwNumDevices = m_DeviceList.size(); return ERROR_SUCCESS; } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("list caused exception (%S)"), ex.what()); return ERROR_GEN_FAILURE; } } if (bAllocate == TRUE) { *lppDevices = NULL; } try { dwCount = m_DeviceList.size(); if (0 == dwCount) { *lppDevices = NULL; *lpdwNumDevices = 0; return dwRes; } if (TRUE == bAllocate) { *lppDevices = (LPDWORD) MemAlloc(dwCount * sizeof(DWORD)); if (*lppDevices == NULL) { DebugPrintEx( DEBUG_ERR, TEXT("Cannot allocate devices buffer")); dwRes = ERROR_NOT_ENOUGH_MEMORY; goto exit; } } dwCount = 0; for (it = m_DeviceList.begin(); it != m_DeviceList.end(); it++) { (*lppDevices)[dwCount++] = *it; } if (0 == dwCount) { *lppDevices = NULL; } *lpdwNumDevices = dwCount; } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("list caused exception (%S)"), ex.what()); dwRes = ERROR_GEN_FAILURE; goto exit; } Assert (ERROR_SUCCESS == dwRes); exit: if (ERROR_SUCCESS != dwRes) { if (bAllocate == TRUE) { MemFree (*lppDevices); } *lppDevices = NULL; *lpdwNumDevices = 0; } return dwRes; } BOOL COutboundRoutingGroup::IsDeviceInGroup (DWORD dwDevice) const /*++ Routine name : COutboundRoutingGroup::IsDeviceInGroup Routine description: Check if device is in the group Author: Oded Sacher (OdedS), Dec, 1999 Arguments: dwDevice [in] - Permanent device ID Return Value: BOOL. If the function fails, Call GetLastError for detailed info. --*/ { DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroup::IsDeviceInGroup")); GROUP_DEVICES::iterator location; BOOL bFound = FALSE; Assert (dwDevice); try { location = find(m_DeviceList.begin(), m_DeviceList.end(), dwDevice); if (location != m_DeviceList.end()) { bFound = TRUE; } SetLastError (ERROR_SUCCESS); return bFound; } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("list caused exception (%S)"), ex.what()); SetLastError (ERROR_GEN_FAILURE); return FALSE; } } DWORD COutboundRoutingGroup::AddDevice (DWORD dwDevice) /*++ Routine name : COutboundRoutingGroup::AddDevice Routine description: Adds a new device to group Author: Oded Sacher (OdedS), Dec, 1999 Arguments: dwDevice [in ] - Permanent device ID Return Value: Standard Win32 error code --*/ { DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroup::AddDevice")); GROUP_DEVICES::iterator it; DWORD dwRes; Assert (dwDevice); if (IsDeviceInGroup(dwDevice)) { return ERROR_SUCCESS; } else { dwRes = GetLastError(); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::IsDeviceInList failed, error %ld"), dwRes); return dwRes; } } // // Device not in list - Add it // try { if (!IsDeviceInstalled(dwDevice)) { DebugPrintEx( DEBUG_ERR, TEXT("Device id: %ld is not installed."), dwDevice); return ERROR_BAD_UNIT; } m_DeviceList.push_back (dwDevice); } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("list caused exception (%S)"), ex.what()); return ERROR_GEN_FAILURE; } return ERROR_SUCCESS; } DWORD COutboundRoutingGroup::DelDevice (DWORD dwDevice) /*++ Routine name : COutboundRoutingGroup::DelDevice Routine description: Deletes a device from the group Author: Oded Sacher (OdedS), Dec, 1999 Arguments: dwDevice [in ] - Permanent device ID Return Value: Standard Win32 error code --*/ { DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroup::DelDevice")); GROUP_DEVICES::iterator location; BOOL bFound = FALSE; Assert (dwDevice); try { location = find(m_DeviceList.begin(), m_DeviceList.end(), dwDevice); if (location == m_DeviceList.end()) { return ERROR_SUCCESS; } m_DeviceList.erase (location); } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("list caused exception (%S)"), ex.what()); return ERROR_GEN_FAILURE; } return ERROR_SUCCESS; } DWORD COutboundRoutingGroup::SetDevices (LPDWORD lpdwDevices, DWORD dwNumDevices, BOOL fAllDevicesGroup) /*++ Routine name : COutboundRoutingGroup::SetDevices Routine description: Sets a new device list to the group Author: Oded Sacher (OdedS), Dec, 1999 Arguments: lpdwDevices [in] - Pointer to a list of devices dwNumDevices [in] - Number of devices in the list fAllDevicesGroup [in] - TRUE if group. Return Value: Standard Win32 error code --*/ { DWORD dwRes = ERROR_SUCCESS; DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroup::SetDevices")); dwRes = ValidateDevices( lpdwDevices, dwNumDevices, fAllDevicesGroup); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::ValidateDevices failed , ec %ld"), dwRes); return dwRes; } try { m_DeviceList.erase (m_DeviceList.begin(), m_DeviceList.end()); for (DWORD i = 0; i < dwNumDevices; i++) { m_DeviceList.push_back (lpdwDevices[i]); } } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("list caused exception (%S)"), ex.what()); dwRes = ERROR_GEN_FAILURE; } return dwRes; } DWORD COutboundRoutingGroup::ValidateDevices (const LPDWORD lpdwDevices, DWORD dwNumDevices, BOOL fAllDevicesGroup) const /*++ Routine name : COutboundRoutingGroup::ValidateDevices Routine description: Validates a list of devices (No duplicates, All devices installed) Author: Oded Sacher (OdedS), Dec, 1999 Arguments: lpdwDevices [in ] - Pointer to alist of devices dwNumDevices [in ] - Number of devices in the list Return Value: Standard Win32 error code --*/ { set ValidationSet; pair < set::iterator, bool> p; DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroup::ValidateDevices")); try { if (TRUE == fAllDevicesGroup) { // // group - validate that we do not miss or add a device. // if (m_DeviceList.size() != dwNumDevices) { DebugPrintEx( DEBUG_ERR, TEXT(" group contains diffrent number of devices, (old group - %ld, new group - %ld)"), m_DeviceList.size(), dwNumDevices); return FAX_ERR_BAD_GROUP_CONFIGURATION; } } for (DWORD i = 0; i < dwNumDevices; i++) { p = ValidationSet.insert(lpdwDevices[i]); if (p.second == FALSE) { DebugPrintEx( DEBUG_ERR, TEXT("Duplicate device IDs, ID = %ld"), lpdwDevices[i]); return FAX_ERR_BAD_GROUP_CONFIGURATION; } if (!IsDeviceInstalled (lpdwDevices[i])) { DebugPrintEx( DEBUG_ERR, TEXT("Device ID %ld, is not installed"), lpdwDevices[i]); return ERROR_BAD_UNIT; } } } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("set caused exception (%S)"), ex.what()); return ERROR_GEN_FAILURE; } return ERROR_SUCCESS; } #if DBG void COutboundRoutingGroup::Dump () const { GROUP_DEVICES::iterator it; WCHAR Buffer[128] = {0}; DWORD dwBufferSize = sizeof (Buffer)/ sizeof (Buffer[0]); for (it = m_DeviceList.begin(); it != m_DeviceList.end(); it++) { _snwprintf (Buffer, dwBufferSize - 1, TEXT("\tDevice ID = %ld \n"), *it); OutputDebugString (Buffer); } return; } #endif DWORD COutboundRoutingGroup::SetDeviceOrder (DWORD dwDevice, DWORD dwOrder) /*++ Routine name : COutboundRoutingGroup::SetDeviceOrder Routine description: Sest the order of a single device in a group of outbound routing devices. Author: Oded Sacher (OdedS), Dec, 1999 Arguments: dwDevice [in] - The device ID to be set dwOrder [in] - The device new order Return Value: Standard Win32 error code --*/ { DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroup::SetDeviceOrder")); GROUP_DEVICES::iterator it; DWORD i = 1; Assert (dwDevice); try { // Check if dwOrder is bigger than number of devices in the list if (dwOrder > m_DeviceList.size()) { DebugPrintEx( DEBUG_ERR, TEXT("Device ID %ld, is not found in group"), dwDevice); return FAX_ERR_BAD_GROUP_CONFIGURATION; } it = find(m_DeviceList.begin(), m_DeviceList.end(), dwDevice); if (it == m_DeviceList.end()) { DebugPrintEx( DEBUG_ERR, TEXT("Device ID %ld, is not found in group"), dwDevice); return FAX_ERR_BAD_GROUP_CONFIGURATION; } m_DeviceList.erase (it); for (i = 1, it = m_DeviceList.begin(); i < dwOrder; i++, it++) { ; } m_DeviceList.insert (it, dwDevice); return ERROR_SUCCESS; } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("list caused exception (%S)"), ex.what()); return ERROR_GEN_FAILURE; } } /**************************************** * * * COutboundRoutingGroupsMap Methodes * * * ****************************************/ DWORD COutboundRoutingGroupsMap::Load () /*++ Routine name : COutboundRoutingGroupsMap::Load Routine description: Loads all outbound routing groups from the registry Author: Oded Sacher (OdedS), Dec, 1999 Arguments: Return Value: Standard Win32 error code --*/ { DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroupsMap::Load")); DWORD dwRes = ERROR_SUCCESS; HKEY hGroupskey = NULL; DWORD dwCount = 0; hGroupskey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_FAX_OUTBOUND_ROUTING, FALSE, KEY_READ | KEY_WRITE ); if (NULL == hGroupskey) { dwRes = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("OpenRegistryKey, error %ld"), dwRes); return dwRes; } dwCount = EnumerateRegistryKeys( hGroupskey, REGKEY_OUTBOUND_ROUTING_GROUPS, TRUE, // We might want to change values EnumOutboundRoutingGroupsCB, &dwRes ); if (dwRes != ERROR_SUCCESS) { DebugPrintEx( DEBUG_ERR, TEXT("EnumerateRegistryKeys failed, error %ld"), dwRes); } RegCloseKey (hGroupskey); return dwRes; } DWORD COutboundRoutingGroupsMap::AddGroup (LPCWSTR lpcwstrGroupName, PCGROUP pCGroup) /*++ Routine name : COutboundRoutingGroupsMap::AddGroup Routine description: Add a new group to the global groups map Author: Oded Sacher (OdedS), Dec, 1999 Arguments: lpcwstrGroupName [ ] - Group name pCGroup [ ] - Pointer to a group object Return Value: Standard Win32 error code --*/ { GROUPS_MAP::iterator it; DWORD dwRes = ERROR_SUCCESS; DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroupsMap::AddGroup")); pair p; Assert (pCGroup && lpcwstrGroupName); try { wstring wstrGroupName(lpcwstrGroupName); // // Add new map entry // p = m_GroupsMap.insert (GROUPS_MAP::value_type(wstrGroupName, *pCGroup)); // // See if entry exists in map // if (p.second == FALSE) { DebugPrintEx( DEBUG_ERR, TEXT("Group %S is allready in the group map"), lpcwstrGroupName); dwRes = ERROR_DUP_NAME; goto exit; } } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("map or wstring caused exception (%S)"), ex.what()); dwRes = ERROR_GEN_FAILURE; } exit: return dwRes; } DWORD COutboundRoutingGroupsMap::DelGroup (LPCWSTR lpcwstrGroupName) /*++ Routine name : COutboundRoutingGroupsMap::DelGroup Routine description: Deletes a group from the global groups map Author: Oded Sacher (OdedS), Dec, 1999 Arguments: lpcwstrGroupName [ ] - The group name Return Value: Standard Win32 error code --*/ { GROUPS_MAP::iterator it; DWORD dwRes = ERROR_SUCCESS; DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroupsMap::DelGroup")); try { wstring wstrGroupName(lpcwstrGroupName); // // See if entry exists in map // if((it = m_GroupsMap.find(wstrGroupName)) == m_GroupsMap.end()) { DebugPrintEx( DEBUG_ERR, TEXT("Group %S not is not in the group map"), lpcwstrGroupName); dwRes = FAX_ERR_GROUP_NOT_FOUND; goto exit; } // // Delete the map entry // m_GroupsMap.erase (it); } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("map or wstring caused exception (%S)"), ex.what()); dwRes = ERROR_GEN_FAILURE; goto exit; } Assert (ERROR_SUCCESS == dwRes); exit: return dwRes; } PCGROUP COutboundRoutingGroupsMap::FindGroup ( LPCWSTR lpcwstrGroupName ) const /*++ Routine name : COutboundRoutingGroupsMap::FindGroup Routine description: Returns a pointer to a group object specified by its name Author: Oded Sacher (OdedS), Dec, 1999 Arguments: lpcwstrGroupName [in ] - The group name Return Value: Pointer to the found group object. If it is null the group was not found --*/ { GROUPS_MAP::iterator it; DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroupsMap::FindGroup")); try { wstring wstrGroupName(lpcwstrGroupName); // // See if entry exists in map // if((it = m_GroupsMap.find(wstrGroupName)) == m_GroupsMap.end()) { SetLastError (FAX_ERR_GROUP_NOT_FOUND); return NULL; } return &((*it).second); } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("map or wstring caused exception (%S)"), ex.what()); SetLastError (ERROR_GEN_FAILURE); return NULL; } } #if DBG void COutboundRoutingGroupsMap::Dump () const { DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroupsMap::Dump")); GROUPS_MAP::iterator it; WCHAR Buffer [512] = {0}; DWORD dwBufferSize = sizeof (Buffer)/ sizeof (Buffer[0]); try { _snwprintf (Buffer, dwBufferSize - 1, TEXT("DUMP - Outbound routing groups\n")); OutputDebugString (Buffer); for (it = m_GroupsMap.begin(); it != m_GroupsMap.end(); it++) { _snwprintf (Buffer, dwBufferSize - 1, TEXT("Group Name - %s\n"), ((*it).first).c_str()); OutputDebugString (Buffer); ((*it).second).Dump(); } } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("map or wstring caused exception (%S)"), ex.what()); } return; } #endif DWORD COutboundRoutingGroupsMap::SerializeGroups ( PFAX_OUTBOUND_ROUTING_GROUPW* ppGroups, LPDWORD lpdwNumGroups, LPDWORD lpdwBufferSize) const { GROUPS_MAP::iterator it; DWORD dwRes = ERROR_SUCCESS; DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroupsMap::SerializeGroups")); DWORD dwSize = 0; DWORD dwNumDevices; DWORD dwCount = 0; LPCWSTR lpcwstrGroupName; PCGROUP pCGroup; Assert (ppGroups && lpdwNumGroups && lpdwBufferSize); *ppGroups = NULL; *lpdwNumGroups = 0; try { // Calculate buffer size for (it = m_GroupsMap.begin(); it != m_GroupsMap.end(); it++) { lpcwstrGroupName = ((*it).first).c_str(); pCGroup = &((*it).second); dwSize += sizeof (FAX_OUTBOUND_ROUTING_GROUPW); dwSize += StringSizeW(lpcwstrGroupName); dwRes = pCGroup->SerializeDevices(NULL, &dwNumDevices); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::SerializeDevices failed, error %ld"), dwRes); goto exit; } dwSize += dwNumDevices * sizeof(DWORD); dwCount ++; } // Allocate buffer *ppGroups = (PFAX_OUTBOUND_ROUTING_GROUPW) MemAlloc (dwSize); if (NULL == *ppGroups) { DebugPrintEx( DEBUG_ERR, TEXT("Cannot allocate groups buffer")); dwRes = ERROR_NOT_ENOUGH_MEMORY; goto exit; } DWORD_PTR dwOffset = dwCount * sizeof (FAX_OUTBOUND_ROUTING_GROUPW); dwCount = 0; // Fill buffer with serialized info for (it = m_GroupsMap.begin(); it != m_GroupsMap.end(); it++) { lpcwstrGroupName = ((*it).first).c_str(); pCGroup = &((*it).second); LPDWORD lpdwDevices; (*ppGroups)[dwCount].dwSizeOfStruct = sizeof (FAX_OUTBOUND_ROUTING_GROUPW); dwRes = pCGroup->GetStatus(&(*ppGroups)[dwCount].Status); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::GetStatus failed, error %ld"), dwRes); goto exit; } StoreString (lpcwstrGroupName, (PULONG_PTR)&(*ppGroups)[dwCount].lpctstrGroupName, (LPBYTE)*ppGroups, &dwOffset, dwSize); lpdwDevices = (LPDWORD)((LPBYTE)*ppGroups + dwOffset); dwRes = pCGroup->SerializeDevices(&lpdwDevices, &dwNumDevices, FALSE); // Do not allocate if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::SerializeDevices failed, error %ld"), dwRes); goto exit; } if (dwNumDevices != 0) { (*ppGroups)[dwCount].lpdwDevices = (LPDWORD)dwOffset; dwOffset += dwNumDevices * sizeof(DWORD); } else { (*ppGroups)[dwCount].lpdwDevices = NULL; } (*ppGroups)[dwCount].dwNumDevices = dwNumDevices; dwCount++; } } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("map or wstring caused exception (%S)"), ex.what()); dwRes = ERROR_GEN_FAILURE; goto exit; } *lpdwNumGroups = dwCount; *lpdwBufferSize = dwSize; Assert (ERROR_SUCCESS == dwRes); exit: if (ERROR_SUCCESS != dwRes) { MemFree (*ppGroups); } return dwRes; } BOOL COutboundRoutingGroupsMap::UpdateAllDevicesGroup (void) /*++ Routine name : COutboundRoutingGroupsMap::UpdateAllDevicesGroup Routine description: Updates group with installed devices Author: Oded Sacher (OdedS), Dec, 1999 Arguments: Return Value: BOOL --*/ { DWORD dwRes = ERROR_SUCCESS; PLIST_ENTRY Next; PLINE_INFO pLineInfo; DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroupsMap::UpdateAllDevicesGroup")); HKEY hGroupKey = NULL; LPDWORD lpdwDevices = NULL; DWORD dwNumDevices = 0; DWORD i; PCGROUP pCGroup; pCGroup = FindGroup (ROUTING_GROUP_ALL_DEVICESW); if (NULL == pCGroup) { dwRes = GetLastError(); if (FAX_ERR_GROUP_NOT_FOUND != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroupsMap::FindGroup failed , ec %ld"), dwRes); return FALSE; } COutboundRoutingGroup CGroup; dwRes = AddGroup (ROUTING_GROUP_ALL_DEVICESW, &CGroup); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::AddGroup failed , ec %ld"), dwRes); SetLastError (dwRes); return FALSE; } pCGroup = FindGroup (ROUTING_GROUP_ALL_DEVICESW); if (NULL == pCGroup) { dwRes = GetLastError(); DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroupsMap::FindGroup failed , ec %ld"), dwRes); return FALSE; } } dwRes = pCGroup->SerializeDevices (&lpdwDevices, &dwNumDevices); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::EnumDevices failed , ec %ld"), dwRes); SetLastError (dwRes); return FALSE; } EnterCriticalSection( &g_CsLine ); Next = g_TapiLinesListHead.Flink; Assert (Next); // // Remove unavailable devices from the group // for (i = 0; i < dwNumDevices; i++) { if (IsDeviceInstalled (lpdwDevices[i])) { continue; } // // Device is not installed - remove it // dwRes = pCGroup->DelDevice (lpdwDevices[i]); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::DelDevice failed , ec %ld"), dwRes); goto exit; } } // // Add missing devices from TapiLinesList list // Next = g_TapiLinesListHead.Flink; while ((ULONG_PTR)Next != (ULONG_PTR)&g_TapiLinesListHead) { pLineInfo = CONTAINING_RECORD( Next, LINE_INFO, ListEntry ); Next = pLineInfo->ListEntry.Flink; Assert (Next && pLineInfo->PermanentLineID); dwRes = pCGroup->AddDevice (pLineInfo->PermanentLineID); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::AddDevice failed, error %ld"), dwRes); goto exit; } } // // Save changes // hGroupKey = OpenOutboundGroupKey( ROUTING_GROUP_ALL_DEVICESW, TRUE, KEY_READ | KEY_WRITE ); if (NULL == hGroupKey) { dwRes = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("Can't create group key, OpenRegistryKey failed : %ld"), dwRes); goto exit; } dwRes = pCGroup->Save (hGroupKey); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::Save failed, Group name - %s, failed with %ld"), ROUTING_GROUP_ALL_DEVICES, dwRes); goto exit; } Assert (ERROR_SUCCESS == dwRes); exit: MemFree (lpdwDevices); if (NULL != hGroupKey) { RegCloseKey (hGroupKey); } LeaveCriticalSection( &g_CsLine ); if (ERROR_SUCCESS != dwRes) { SetLastError (dwRes); } return (ERROR_SUCCESS == dwRes); } DWORD COutboundRoutingGroupsMap::RemoveDevice (DWORD dwDeviceId) /*++ Routine name : COutboundRoutingGroupsMap::RemoveDevice Routine description: Deletes a device from all of the groups in the map Author: Oded Sacher (OdedS), Sep, 2000 Arguments: dwDeviceId [in ] - The device id to remove Return Value: Standard Win32 error code --*/ { GROUPS_MAP::iterator it; DWORD dwRes = ERROR_SUCCESS; HKEY hGroupKey = NULL; DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroupsMap::RemoveDevice")); Assert (dwDeviceId); try { // // Delete the device from each group // for (it = m_GroupsMap.begin(); it != m_GroupsMap.end(); it++) { PCGROUP pCGroup = &((*it).second); LPCWSTR lpcwstrGroupName = ((*it).first).c_str(); // // Open the group registry key // hGroupKey = OpenOutboundGroupKey( lpcwstrGroupName, FALSE, KEY_READ | KEY_WRITE ); if (NULL == hGroupKey) { dwRes = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("Can't open group key, OpenOutboundGroupKey failed : %ld"), dwRes); goto exit; } dwRes = pCGroup->DelDevice (dwDeviceId); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::DelDevice failed : %ld"), dwRes); goto exit; } dwRes = pCGroup->Save(hGroupKey); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::Save failed : %ld"), dwRes); goto exit; } RegCloseKey (hGroupKey); hGroupKey = NULL; } } catch (exception &ex) { DebugPrintEx( DEBUG_ERR, TEXT("map or wstring caused exception (%S)"), ex.what()); dwRes = ERROR_GEN_FAILURE; goto exit; } Assert (ERROR_SUCCESS == dwRes); exit: if (NULL != hGroupKey) { RegCloseKey (hGroupKey); } return dwRes; } // RemoveDevice /************************************ * * * Registry * * * ************************************/ BOOL EnumOutboundRoutingGroupsCB( HKEY hSubKey, LPWSTR SubKeyName, DWORD Index, LPVOID pContext ) { DEBUG_FUNCTION_NAME(TEXT("EnumOutboundRoutingGroupsCB")); DWORD dwRes; COutboundRoutingGroup CGroup; BOOL bGroupDeleted = FALSE; if (!SubKeyName) { return TRUE; } if ((_wcsicmp (SubKeyName, ROUTING_GROUP_ALL_DEVICESW) != 0) && IsDesktopSKU()) { // // We do not support outbound routing on desktop SKUs. Do not load group information. // return TRUE; } // // Add group // dwRes = CGroup.Load (hSubKey, SubKeyName); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::Load failed, group name - %s, error %ld"), SubKeyName, dwRes); // Open Outbound Routing\Groups key HKEY hGroupsKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_FAX_OUTBOUND_ROUTING_GROUPS, FALSE, KEY_READ | KEY_WRITE | DELETE); if (NULL == hGroupsKey) { dwRes = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("OpenRegistryKey, error %ld"), dwRes); } else { DWORD dwRetVal = RegDeleteKey (hGroupsKey, SubKeyName); if (ERROR_SUCCESS != dwRetVal) { DebugPrintEx( DEBUG_ERR, TEXT("RegDeleteKey failed, Group name - %s, error %ld"), SubKeyName, dwRetVal); } else { bGroupDeleted = TRUE; } } goto exit; } dwRes = g_pGroupsMap->AddGroup (SubKeyName, &CGroup); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroupsMap::AddGroup failed, group name - %s, error %ld"), SubKeyName, dwRes); goto exit; } Assert (ERROR_SUCCESS == dwRes); exit: if (ERROR_SUCCESS != dwRes) { if (bGroupDeleted == FALSE) { FaxLog( FAXLOG_CATEGORY_INIT, FAXLOG_LEVEL_MIN, 1, MSG_OUTBOUND_ROUTING_GROUP_NOT_ADDED, SubKeyName ); } else { FaxLog( FAXLOG_CATEGORY_INIT, FAXLOG_LEVEL_MIN, 1, MSG_OUTBOUND_ROUTING_GROUP_NOT_LOADED, SubKeyName ); } } *(LPDWORD)pContext = ERROR_SUCCESS; // Let the service start return TRUE; // Let the service start } /************************************ * * * RPC handlers * * * ************************************/ extern "C" error_status_t FAX_AddOutboundGroup ( IN handle_t hFaxHandle, IN LPCWSTR lpwstrGroupName ) /*++ Routine name : FAX_AddOutboundGroup Routine description: Adds a new Outbound routing group to the fax server Author: Oded Sacher (OdedS), Dec, 1999 Arguments: hFaxHandle [in ] - FaxServer handle lpwstrGroupName [in ] - The new group name Return Value: error_status_t --*/ { DWORD dwRes = ERROR_SUCCESS; DEBUG_FUNCTION_NAME(TEXT("FAX_AddOutboundGroup")); HKEY hGroupKey = NULL; COutboundRoutingGroup CGroup; DWORD rVal; BOOL fAccess; Assert (lpwstrGroupName); if (_wcsicmp (lpwstrGroupName, ROUTING_GROUP_ALL_DEVICESW) == 0) { return ERROR_DUP_NAME; } if (TRUE == IsDesktopSKU()) { // // We do not support outbound routing on desktop SKUs. // if (FAX_API_VERSION_1 > FindClientAPIVersion (hFaxHandle)) { // // API version 0 clients don't know about FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU // return ERROR_INVALID_PARAMETER; } else { return FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU; } } if (wcslen (lpwstrGroupName) >= MAX_ROUTING_GROUP_NAME) { return ERROR_BUFFER_OVERFLOW; } // // Access check // dwRes = FaxSvcAccessCheck (FAX_ACCESS_MANAGE_CONFIG, &fAccess, NULL); if (ERROR_SUCCESS != dwRes) { DebugPrintEx(DEBUG_ERR, TEXT("FaxSvcAccessCheck Failed, Error : %ld"), dwRes); return GetServerErrorCode(dwRes); } if (FALSE == fAccess) { DebugPrintEx(DEBUG_ERR, TEXT("The user does not have the FAX_ACCESS_MANAGE_CONFIG right")); return ERROR_ACCESS_DENIED; } EnterCriticalSection (&g_CsConfig); // Empty group, no need to lock g_CsLine #if DBG DebugPrintEx( DEBUG_MSG, TEXT("Dump outbound routing groups -before change")); g_pGroupsMap->Dump(); #endif hGroupKey = OpenOutboundGroupKey( lpwstrGroupName, TRUE, KEY_READ | KEY_WRITE ); if (NULL == hGroupKey) { dwRes = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("Can't create group key, OpenRegistryKey failed : %ld"), dwRes); dwRes = ERROR_REGISTRY_CORRUPT; goto exit; } dwRes = g_pGroupsMap->AddGroup (lpwstrGroupName, &CGroup); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroupsMap::AddGroup failed, Group name - %s, error %ld"), lpwstrGroupName, dwRes); goto exit; } dwRes = CGroup.Save (hGroupKey); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::Save failed, Group name - %s, failed with %ld"), lpwstrGroupName, dwRes); g_pGroupsMap->DelGroup (lpwstrGroupName); dwRes = ERROR_REGISTRY_CORRUPT; goto exit; } rVal = CreateConfigEvent (FAX_CONFIG_TYPE_OUT_GROUPS); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("CreateConfigEvent(FAX_CONFIG_TYPE_OUT_GROUPS) (ec: %lc)"), rVal); } Assert (ERROR_SUCCESS == dwRes); #if DBG DebugPrintEx( DEBUG_MSG, TEXT("Dump outbound routing groups -before change")); g_pGroupsMap->Dump(); #endif exit: if (NULL != hGroupKey) { RegCloseKey (hGroupKey); } LeaveCriticalSection (&g_CsConfig); UNREFERENCED_PARAMETER (hFaxHandle); return GetServerErrorCode(dwRes); } extern "C" error_status_t FAX_SetOutboundGroup ( IN handle_t hFaxHandle, IN PRPC_FAX_OUTBOUND_ROUTING_GROUPW pGroup ) /*++ Routine name : FAX_SetOutboundGroup Routine description: Sets a new device list to an existing group Author: Oded Sacher (OdedS), Dec, 1999 Arguments: hFaxHandle [in] - Fax server handle pGroup [in] - Pointer to a PRPC_FAX_OUTBOUND_ROUTING_GROUPW contaning group info Return Value: error_status_t --*/ { DWORD dwRes = ERROR_SUCCESS; DEBUG_FUNCTION_NAME(TEXT("FAX_SetOutboundGroup")); HKEY hGroupKey = NULL; PCGROUP pCGroup = NULL; COutboundRoutingGroup OldGroup; DWORD rVal; BOOL fAccess; BOOL fAllDevicesGroup = FALSE; Assert (pGroup); if (sizeof (FAX_OUTBOUND_ROUTING_GROUPW) != pGroup->dwSizeOfStruct) { // // Size mismatch // return ERROR_INVALID_PARAMETER; } if (!pGroup->lpwstrGroupName) { return ERROR_INVALID_PARAMETER; } if (wcslen (pGroup->lpwstrGroupName) >= MAX_ROUTING_GROUP_NAME) { return ERROR_BUFFER_OVERFLOW; } if (!pGroup->lpdwDevices && pGroup->dwNumDevices) { return ERROR_INVALID_PARAMETER; } if (TRUE == IsDesktopSKU()) { // // We do not support outbound routing on desktop SKUs. // if (FAX_API_VERSION_1 > FindClientAPIVersion (hFaxHandle)) { // // API version 0 clients don't know about FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU // return ERROR_INVALID_PARAMETER; } else { return FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU; } } // // Access check // dwRes = FaxSvcAccessCheck (FAX_ACCESS_MANAGE_CONFIG, &fAccess, NULL); if (ERROR_SUCCESS != dwRes) { DebugPrintEx(DEBUG_ERR, TEXT("FaxSvcAccessCheck Failed, Error : %ld"), dwRes); return GetServerErrorCode(dwRes); } if (FALSE == fAccess) { DebugPrintEx(DEBUG_ERR, TEXT("The user does not have the FAX_ACCESS_MANAGE_CONFIG right")); return ERROR_ACCESS_DENIED; } if (_wcsicmp (pGroup->lpwstrGroupName, ROUTING_GROUP_ALL_DEVICESW) == 0) { // // If it is group we should validate that no device is missing, // and that the new group contains all installed devices. // fAllDevicesGroup = TRUE; } EnterCriticalSection (&g_CsLine); EnterCriticalSection (&g_CsConfig); #if DBG DebugPrintEx( DEBUG_MSG, TEXT("Dump outbound routing groups -before change")); g_pGroupsMap->Dump(); #endif pCGroup = g_pGroupsMap->FindGroup (pGroup->lpwstrGroupName); if (!pCGroup) { dwRes = GetLastError(); DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroupsMap::SetGroup failed, Group name - %s, error %ld"), pGroup->lpwstrGroupName, dwRes); goto exit; } hGroupKey = OpenOutboundGroupKey( pGroup->lpwstrGroupName, FALSE, KEY_READ | KEY_WRITE ); if (NULL == hGroupKey) { dwRes = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("Can't create group key, OpenRegistryKey failed : %ld"), dwRes); dwRes = ERROR_REGISTRY_CORRUPT; goto exit; } OldGroup = *pCGroup; dwRes = pCGroup->SetDevices (pGroup->lpdwDevices, pGroup->dwNumDevices, fAllDevicesGroup); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::SetDevices failed, Group name - %s, failed with %ld"), pGroup->lpwstrGroupName, dwRes); goto exit; } dwRes = pCGroup->Save (hGroupKey); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::Save failed, Group name - %s, failed with %ld"), pGroup->lpwstrGroupName, dwRes); *pCGroup = OldGroup; dwRes = ERROR_REGISTRY_CORRUPT; goto exit; } rVal = CreateConfigEvent (FAX_CONFIG_TYPE_OUT_GROUPS); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("CreateConfigEvent(FAX_CONFIG_TYPE_OUT_GROUPS) (ec: %lc)"), rVal); } Assert (ERROR_SUCCESS == dwRes); #if DBG DebugPrintEx( DEBUG_MSG, TEXT("Dump outbound routing groups -before change")); g_pGroupsMap->Dump(); #endif exit: if (NULL != hGroupKey) { RegCloseKey (hGroupKey); } LeaveCriticalSection (&g_CsConfig); LeaveCriticalSection (&g_CsLine); if (ERROR_SUCCESS == dwRes) { // // We might find a line for a pending job. Wake up JobQueueThread // if (!SetEvent( g_hJobQueueEvent )) { DebugPrintEx( DEBUG_ERR, TEXT("Failed to set g_hJobQueueEvent. (ec: %ld)"), GetLastError()); EnterCriticalSection (&g_CsQueue); g_ScanQueueAfterTimeout = TRUE; LeaveCriticalSection (&g_CsQueue); } } UNREFERENCED_PARAMETER (hFaxHandle); return GetServerErrorCode(dwRes); } extern "C" error_status_t FAX_RemoveOutboundGroup ( IN handle_t hFaxHandle, IN LPCWSTR lpwstrGroupName ) /*++ Routine name : FAX_RemoveOutboundGroup Routine description: Removes an existing Outbound routing group from the fax server Author: Oded Sacher (OdedS), Dec, 1999 Arguments: hFaxHandle [in ] - FaxServer handle lpwstrGroupName [in ] - The group name Return Value: error_status_t --*/ { DWORD dwRes = ERROR_SUCCESS; DEBUG_FUNCTION_NAME(TEXT("FAX_RemoveOutboundGroup")); HKEY hGroupsKey = NULL; DWORD rVal; BOOL fAccess; PCGROUP pCGroup = NULL; Assert (lpwstrGroupName); if (_wcsicmp (lpwstrGroupName, ROUTING_GROUP_ALL_DEVICESW) == 0) { return ERROR_INVALID_OPERATION; } if (TRUE == IsDesktopSKU()) { // // We do not support outbound routing on desktop SKUs. // if (FAX_API_VERSION_1 > FindClientAPIVersion (hFaxHandle)) { // // API version 0 clients don't know about FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU // return ERROR_INVALID_PARAMETER; } else { return FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU; } } if (wcslen (lpwstrGroupName) >= MAX_ROUTING_GROUP_NAME) { return ERROR_BUFFER_OVERFLOW; } // // Access check // dwRes = FaxSvcAccessCheck (FAX_ACCESS_MANAGE_CONFIG, &fAccess, NULL); if (ERROR_SUCCESS != dwRes) { DebugPrintEx(DEBUG_ERR, TEXT("FaxSvcAccessCheck Failed, Error : %ld"), dwRes); return GetServerErrorCode(dwRes); } if (FALSE == fAccess) { DebugPrintEx(DEBUG_ERR, TEXT("The user does not have the FAX_ACCESS_MANAGE_CONFIG right")); return ERROR_ACCESS_DENIED; } EnterCriticalSection (&g_CsConfig); #if DBG DebugPrintEx( DEBUG_MSG, TEXT("Dump outbound routing groups -before delete")); g_pGroupsMap->Dump(); #endif BOOL bGroupInRule; dwRes = g_pRulesMap->IsGroupInRuleDest(lpwstrGroupName, &bGroupInRule); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroupsMap::IsGroupInRuleDest failed, Group name - %s, error %ld"), lpwstrGroupName, dwRes); goto exit; } if (TRUE == bGroupInRule) { DebugPrintEx( DEBUG_ERR, TEXT("Group is a rule destination, Can not be deleted, Group name - %s"), lpwstrGroupName); dwRes = FAX_ERR_GROUP_IN_USE; goto exit; } // // See if the group exists in the map // pCGroup = g_pGroupsMap->FindGroup (lpwstrGroupName); if (!pCGroup) { dwRes = GetLastError(); DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroupsMap::SetGroup failed, Group name - %s, error %ld"), lpwstrGroupName, dwRes); goto exit; } // Open Outbound Routing\Groups key hGroupsKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_FAX_OUTBOUND_ROUTING_GROUPS, FALSE, KEY_READ | KEY_WRITE | DELETE); if (NULL == hGroupsKey) { dwRes = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("OpenRegistryKey, error %ld"), dwRes); dwRes = ERROR_REGISTRY_CORRUPT; goto exit; } // Delete the specified group key dwRes = RegDeleteKey (hGroupsKey, lpwstrGroupName); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("RegDeleteKey failed, Group name - %s, error %ld"), lpwstrGroupName, dwRes); goto exit; } // Delete the group from the memory dwRes = g_pGroupsMap->DelGroup (lpwstrGroupName); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroupsMap::DelGroup failed, Group name - %s, error %ld"), lpwstrGroupName, dwRes); goto exit; } rVal = CreateConfigEvent (FAX_CONFIG_TYPE_OUT_GROUPS); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("CreateConfigEvent(FAX_CONFIG_TYPE_OUT_GROUPS) (ec: %lc)"), rVal); } Assert (ERROR_SUCCESS == dwRes); #if DBG DebugPrintEx( DEBUG_MSG, TEXT("Dump outbound routing groups -after delete")); g_pGroupsMap->Dump(); #endif exit: if (NULL != hGroupsKey) { RegCloseKey (hGroupsKey); } LeaveCriticalSection (&g_CsConfig); UNREFERENCED_PARAMETER (hFaxHandle); return GetServerErrorCode(dwRes); } //FAX_RemoveOutboundGroup error_status_t FAX_EnumOutboundGroups ( handle_t hFaxHandle, LPBYTE* ppBuffer, LPDWORD lpdwBufferSize, LPDWORD lpdwNumGroups ) /*++ Routine name : FAX_EnumOutboundGroups Routine description: Enumurates all outbound routing groups Author: Oded Sacher (OdedS), Dec, 1999 Arguments: hFaxHandle [in ] - Fax server handle ppBuffer [out ] - Adress of a pointer to a buffer to be filled with info lpdwBufferSize [in/out] - The buffer size lpdwNumGroups [out ] - Number of groups returned Return Value: error_status_t --*/ { DWORD dwRes = ERROR_SUCCESS; DEBUG_FUNCTION_NAME(TEXT("FAX_EnumOutboundGroups")); BOOL fAccess; Assert (lpdwNumGroups && lpdwNumGroups); // ref pointer in idl if (!ppBuffer) // unique pointer in idl { return ERROR_INVALID_PARAMETER; } if (TRUE == IsDesktopSKU()) { // // We do not support outbound routing on desktop SKUs. // if (FAX_API_VERSION_1 > FindClientAPIVersion (hFaxHandle)) { // // API version 0 clients don't know about FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU // return ERROR_INVALID_PARAMETER; } else { return FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU; } } // // Access check // dwRes = FaxSvcAccessCheck (FAX_ACCESS_QUERY_CONFIG, &fAccess, NULL); if (ERROR_SUCCESS != dwRes) { DebugPrintEx(DEBUG_ERR, TEXT("FaxSvcAccessCheck Failed, Error : %ld"), dwRes); return GetServerErrorCode(dwRes); } if (FALSE == fAccess) { DebugPrintEx(DEBUG_ERR, TEXT("The user does not have the FAX_ACCESS_QUERY_CONFIG right")); return ERROR_ACCESS_DENIED; } *ppBuffer = NULL; *lpdwNumGroups = 0; EnterCriticalSection (&g_CsConfig); dwRes = g_pGroupsMap->SerializeGroups ((PFAX_OUTBOUND_ROUTING_GROUPW*)ppBuffer, lpdwNumGroups, lpdwBufferSize); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroupsMap::SerializeGroups failed, error %ld"), dwRes); goto exit; } Assert (ERROR_SUCCESS == dwRes); exit: LeaveCriticalSection (&g_CsConfig); UNREFERENCED_PARAMETER (hFaxHandle); return GetServerErrorCode(dwRes); } //FAX_EnumOutboundGroups error_status_t FAX_SetDeviceOrderInGroup ( handle_t hFaxHandle, LPCWSTR lpwstrGroupName, DWORD dwDeviceId, DWORD dwNewOrder ) /*++ Routine name : FAX_SetDeviceOrderInGroup Routine description: Sets the order of the specified device in the group Author: Oded Sacher (OdedS), Dec, 1999 Arguments: hFaxHandle [in] - Fax server handle lpwstrGroupName [in] - The group name dwDeviceId [in] - The device permanent ID dwNewOrder [in] - The device new order Return Value: error_status_t --*/ { DWORD dwRes = ERROR_SUCCESS; DEBUG_FUNCTION_NAME(TEXT("FAX_SetDeviceOrderInGroup")); HKEY hGroupKey = NULL; PCGROUP pCGroup = NULL; COutboundRoutingGroup OldGroup; DWORD rVal; BOOL fAccess; Assert (lpwstrGroupName); if (!dwDeviceId || !dwNewOrder) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (wcslen (lpwstrGroupName) >= MAX_ROUTING_GROUP_NAME) { SetLastError(ERROR_BUFFER_OVERFLOW); return FALSE; } if (TRUE == IsDesktopSKU()) { // // We do not support outbound routing on desktop SKUs. // if (FAX_API_VERSION_1 > FindClientAPIVersion (hFaxHandle)) { // // API version 0 clients don't know about FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU // return ERROR_INVALID_PARAMETER; } else { return FAX_ERR_NOT_SUPPORTED_ON_THIS_SKU; } } // // Access check // dwRes = FaxSvcAccessCheck (FAX_ACCESS_MANAGE_CONFIG, &fAccess, NULL); if (ERROR_SUCCESS != dwRes) { DebugPrintEx(DEBUG_ERR, TEXT("FaxSvcAccessCheck Failed, Error : %ld"), dwRes); return GetServerErrorCode(dwRes); } if (FALSE == fAccess) { DebugPrintEx(DEBUG_ERR, TEXT("The user does not have the FAX_ACCESS_MANAGE_CONFIG right")); return ERROR_ACCESS_DENIED; } EnterCriticalSection (&g_CsConfig); #if DBG DebugPrintEx( DEBUG_MSG, TEXT("Dump outbound routing groups -before changing order")); g_pGroupsMap->Dump(); #endif // Find the group in memory pCGroup = g_pGroupsMap->FindGroup (lpwstrGroupName); if (!pCGroup) { dwRes = GetLastError(); DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroupsMap::FindGroup failed, Group name - %s, error %ld"), lpwstrGroupName, dwRes); goto exit; } // Open the group registry key hGroupKey = OpenOutboundGroupKey( lpwstrGroupName, FALSE, KEY_READ | KEY_WRITE ); if (NULL == hGroupKey) { dwRes = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("Can't open group key, OpenOutboundGroupKey failed : %ld"), dwRes); dwRes = ERROR_REGISTRY_CORRUPT; goto exit; } // Save a copy of the old group OldGroup = *pCGroup; // Cahnge the device order in the group dwRes = pCGroup->SetDeviceOrder(dwDeviceId, dwNewOrder); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroupsMap::SetDeviceOrder failed, Group name - %s,\ Device Id %ld, new order %ld, error %ld"), lpwstrGroupName, dwDeviceId, dwNewOrder, dwRes); goto exit; } // save changes to the registry dwRes = pCGroup->Save (hGroupKey); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("COutboundRoutingGroup::Save failed, Group name - %s, failed with %ld"), lpwstrGroupName, dwRes); // Rollback memory *pCGroup = OldGroup; dwRes = ERROR_REGISTRY_CORRUPT; goto exit; } rVal = CreateConfigEvent (FAX_CONFIG_TYPE_OUT_GROUPS); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("CreateConfigEvent(FAX_CONFIG_TYPE_OUT_GROUPS) (ec: %lc)"), rVal); } Assert (ERROR_SUCCESS == dwRes); #if DBG DebugPrintEx( DEBUG_MSG, TEXT("Dump outbound routing groups -after change")); g_pGroupsMap->Dump(); #endif exit: if (NULL != hGroupKey) { RegCloseKey (hGroupKey); } LeaveCriticalSection (&g_CsConfig); UNREFERENCED_PARAMETER (hFaxHandle); return GetServerErrorCode(dwRes); }// FAX_SetDeviceOrderInGroup