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

/*++
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 <All Devices> 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<DWORD> ValidationSet;
pair < set<DWORD>::iterator, bool> p;
DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingGroup::ValidateDevices"));
try
{
if (TRUE == fAllDevicesGroup)
{
//
// <All Devices> group - validate that we do not miss or add a device.
//
if (m_DeviceList.size() != dwNumDevices)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("<All Devices> 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 <GROUPS_MAP::iterator, bool> 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 <All devices> 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 <All Devices> 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