Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2587 lines
65 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
RouteRule.cpp
Abstract:
This file provides implementation of the service
outbound routing rules.
Author:
Oded Sacher (OdedS) Dec, 1999
Revision History:
--*/
#include "faxsvc.h"
#define STRSAFE_NO_DEPRECATE // This allows using unsafe functions
#include <strsafe.h>
BOOL
EnumOutboundRoutingRulesCB(
HKEY hSubKey,
LPWSTR SubKeyName,
DWORD Index,
LPVOID pContext
);
/************************************
* *
* Globals *
* *
************************************/
COutboundRulesMap* g_pRulesMap; // Map of dialing location to rule
/***********************************
* *
* CDialingLocation Methodes *
* *
***********************************/
bool
CDialingLocation::operator < ( const CDialingLocation &other ) const
/*++
Routine name : operator <
Class: CDialingLocation
Routine description:
Compares myself with another Dialing location key
Author:
Oded Sacher (Odeds), Dec, 1999
Arguments:
other [in] - Other key
Return Value:
true only is i'm less than the other key
--*/
{
if (m_dwCountryCode < other.m_dwCountryCode)
{
return true;
}
if (m_dwCountryCode > other.m_dwCountryCode)
{
return false;
}
//
// Equal country code , comapre area code
//
if (m_dwAreaCode < other.m_dwAreaCode)
{
return true;
}
return false;
} // CDialingLocation::operator <
BOOL
CDialingLocation::IsValid () const
/*++
Routine name : CDialingLocation::IsValid
Routine description:
Validates a dialing location object
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
Return Value:
BOOL
--*/
{
DEBUG_FUNCTION_NAME(TEXT("CDialingLocation::IsValid"));
if (m_dwCountryCode == ROUTING_RULE_COUNTRY_CODE_ANY &&
m_dwAreaCode != ROUTING_RULE_AREA_CODE_ANY)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Not a valid Country and Area code combination"));
return FALSE;
}
return TRUE;
} // CDialingLocation::IsValidDialingLocation
LPCWSTR
CDialingLocation::GetCountryName () const
/*++
Routine name : CDialingLocation::GetCountryName
Routine description:
Returns a pointer to the country name specifies by its country dialing code (based on TAPI).
The caller must call MemFree() to deallocate memory.
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
Return Value:
Pointer to the country name.
If this is NULL the function failed, call GetLastError() for more info.
--*/
{
DEBUG_FUNCTION_NAME(TEXT("CDialingLocation::GetCountryName"));
LPLINECOUNTRYLIST lpCountryList = NULL;
LPLINECOUNTRYENTRY lpEntry = NULL;
DWORD dwIndex;
//
// Get the cached all countries list.
//
if (!(lpCountryList = GetCountryList()))
{
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
goto exit;
}
lpEntry = (LPLINECOUNTRYENTRY) // init array of entries
((PBYTE) lpCountryList + lpCountryList->dwCountryListOffset);
for (dwIndex=0; dwIndex < lpCountryList->dwNumCountries; dwIndex++)
{
if (lpEntry[dwIndex].dwCountryCode == m_dwCountryCode)
{
//
// Matching country code - copy Country name.
//
if (lpEntry[dwIndex].dwCountryNameSize && lpEntry[dwIndex].dwCountryNameOffset)
{
return StringDup ((LPWSTR) ((LPBYTE)lpCountryList + lpEntry[dwIndex].dwCountryNameOffset));
}
}
}
SetLastError (ERROR_NOT_FOUND);
exit:
return NULL;
} // CDialingLocation::GetCountryName
/*************************************
* *
* COutboundRoutingRule Methodes *
* *
*************************************/
DWORD
COutboundRoutingRule::Init (CDialingLocation DialingLocation, wstring wstrGroupName)
/*++
Routine name : COutboundRoutingRule::Init
Routine description:
Initialize an OutboundRoutingRule object
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
DialingLocation [in ] - Dialing location object to use as the rule's dialing location
wstrGroupName [in ] - The group name to use as the rule's destination group
Return Value:
Standard Win32 error code
--*/
{
DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::Init"));
try
{
m_wstrGroupName = wstrGroupName;
m_bUseGroup = TRUE;
m_DialingLocation = DialingLocation;
return ERROR_SUCCESS;
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("wstring caused exception (%S)"),
ex.what());
return ERROR_GEN_FAILURE;
}
}
DWORD
COutboundRoutingRule::Save(HKEY hRuleKey) const
/*++
Routine name : COutboundRoutingRule::Save
Routine description:
Saves an outbound routing rule value to the registry
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
hRuleKey [in] - Handle to the opened rule registry key
Return Value:
Standard Win32 error code
--*/
{
DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::Save"));
DWORD dwRes = ERROR_SUCCESS;
Assert (hRuleKey);
// Save country code
if (!SetRegistryDword( hRuleKey,
REGVAL_ROUTING_RULE_COUNTRY_CODE,
m_DialingLocation.GetCountryCode()))
{
dwRes = GetLastError();
DebugPrintEx(
DEBUG_ERR,
TEXT("SetRegistryDword failed , ec %ld"), dwRes);
goto exit;
}
// Save area code
if (!SetRegistryDword( hRuleKey,
REGVAL_ROUTING_RULE_AREA_CODE,
m_DialingLocation.GetAreaCode()))
{
dwRes = GetLastError();
DebugPrintEx(
DEBUG_ERR,
TEXT("SetRegistryDword failed , ec %ld"), dwRes);
goto exit;
}
// // Save boolen flag whether to use group
if (!SetRegistryDword( hRuleKey,
REGVAL_ROUTING_RULE_USE_GROUP,
m_bUseGroup ? TRUE : FALSE))
{
dwRes = GetLastError();
DebugPrintEx(
DEBUG_ERR,
TEXT("SetRegistryDword failed , ec %ld"), dwRes);
goto exit;
}
if (FALSE == m_bUseGroup)
{
// Save the device ID as the rule destination
if (!SetRegistryDword( hRuleKey,
REGVAL_ROUTING_RULE_DEVICE_ID,
m_dwDevice))
{
dwRes = GetLastError();
DebugPrintEx(
DEBUG_ERR,
TEXT("SetRegistryDword failed , ec %ld"), dwRes);
goto exit;
}
}
else
{
// Save the group name as the rule destination
try
{
if (!SetRegistryString( hRuleKey,
REGVAL_ROUTING_RULE_GROUP_NAME,
m_wstrGroupName.c_str()))
{
dwRes = GetLastError();
DebugPrintEx(
DEBUG_ERR,
TEXT("SetRegistryDword failed , ec %ld"), dwRes);
goto exit;
}
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("wstring caused exception (%S)"),
ex.what());
dwRes = ERROR_GEN_FAILURE;
goto exit;
}
}
Assert (dwRes == ERROR_SUCCESS);
exit:
return dwRes;
} // COutboundRoutingRule::Save
DWORD
COutboundRoutingRule::Load(HKEY hRuleKey)
/*++
Routine name : COutboundRoutingRule::Load
Routine description:
Loads an outboundrouting rule value settings from the registry
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
hRuleKey [in] - Handle to the opened registry key
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes, dwType, dwSize;
DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::Load"));
DWORD dwCountryCode = 0;
DWORD dwAreaCode = 0;
Assert (hRuleKey);
// Read the boolen flag whether to use group
dwRes = GetRegistryDwordEx (hRuleKey,
REGVAL_ROUTING_RULE_USE_GROUP,
(LPDWORD)&m_bUseGroup);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading UseGroup - GetRegistryDwordEx failed with %ld"),
dwRes);
goto exit;
}
if (FALSE == m_bUseGroup)
{
// read the device ID as the rule destination
dwRes = GetRegistryDwordEx (hRuleKey,
REGVAL_ROUTING_RULE_DEVICE_ID,
&m_dwDevice);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading device ID - GetRegistryDwordEx failed with %ld"),
dwRes);
goto exit;
}
if (0 == m_dwDevice)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Invalid device ID"));
dwRes = ERROR_BADDB;
goto exit;
}
}
else
{
// Read the group name as the rule destination
WCHAR wszGroupName[MAX_ROUTING_GROUP_NAME + 1] = {0};
dwRes = RegQueryValueEx(
hRuleKey,
REGVAL_ROUTING_RULE_GROUP_NAME,
NULL,
&dwType,
NULL,
&dwSize
);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("RegQueryValueEx failed with %ld"),
dwRes);
goto exit;
}
if (REG_SZ != dwType || dwSize > (sizeof(wszGroupName) - sizeof(WCHAR)))
{
// We expect only string data here
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading group name"));
dwRes = ERROR_BADDB; // The configuration registry database is corrupt.
goto exit;
}
dwRes = RegQueryValueEx(
hRuleKey,
REGVAL_ROUTING_RULE_GROUP_NAME,
NULL,
&dwType,
(LPBYTE)wszGroupName,
&dwSize
);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("RegQueryValueEx failed with %ld"),
dwRes);
goto exit;
}
// Validate that the group exist
PCGROUP pCGroup = g_pGroupsMap->FindGroup (wszGroupName);
if (NULL == pCGroup)
{
dwRes = GetLastError();
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingGropsMap::FindGroup, with error - %ld"),
dwRes);
goto exit;
}
try
{
m_wstrGroupName = wszGroupName;
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("wstring caused exception (%S)"),
ex.what());
dwRes = ERROR_GEN_FAILURE;
goto exit;
}
}
// Read the country code
dwRes = GetRegistryDwordEx (hRuleKey,
REGVAL_ROUTING_RULE_COUNTRY_CODE,
&dwCountryCode);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading Country code - GetRegistryDwordEx failed with %ld"),
dwRes);
goto exit;
}
// Read the area code
dwRes = GetRegistryDwordEx (hRuleKey,
REGVAL_ROUTING_RULE_AREA_CODE,
&dwAreaCode);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading Area code - GetRegistryDwordEx failed with %ld"),
dwRes);
goto exit;
}
//
// Create the DialingLocation object
//
m_DialingLocation = CDialingLocation (dwCountryCode, dwAreaCode);
if (!m_DialingLocation.IsValid())
{
dwRes = ERROR_INVALID_PARAMETER;
DebugPrintEx(
DEBUG_ERR,
TEXT("IsValidDialingLocation failed"));
goto exit;
}
Assert (ERROR_SUCCESS == dwRes);
exit:
return dwRes;
} // COutboundRoutingRule::Load
DWORD
COutboundRoutingRule::GetStatus (FAX_ENUM_RULE_STATUS* lpdwStatus) const
/*++
Routine name : COutboundRoutingRule::GetStatus
Routine description:
Reports the rule's status. Can be one of FAX_ENUM_RULE_STATUS.
Enter Critical Section (g_CsLine , g_CsConfig) before calling this function.
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
lpdwStatus [out ] - Gets the rule's status on return
Return Value:
Standard Win32 error code
--*/
{
DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::GetStatus"));
FAX_ENUM_RULE_STATUS dwRuleStatus = FAX_RULE_STATUS_VALID;
DWORD dwRes = ERROR_SUCCESS;
PCGROUP pCGroup;
if (TRUE == m_bUseGroup)
{
// Find the rule's destination group in the goups map
try
{
pCGroup = g_pGroupsMap->FindGroup (m_wstrGroupName.c_str());
if (NULL == pCGroup)
{
dwRes = GetLastError();
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingGroupsMap::FindGroup failed , ec %ld"), dwRes);
goto exit;
}
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("wstring caused exception (%S)"),
ex.what());
dwRes = ERROR_GEN_FAILURE;
goto exit;
}
// Get the group's status.
FAX_ENUM_GROUP_STATUS GroupStatus;
dwRes = pCGroup->GetStatus(&GroupStatus);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingGroup::GetStatus failed , ec %ld"), dwRes);
goto exit;
}
switch (GroupStatus)
{
case FAX_GROUP_STATUS_SOME_DEV_NOT_VALID:
dwRuleStatus = FAX_RULE_STATUS_SOME_GROUP_DEV_NOT_VALID;
break;
case FAX_GROUP_STATUS_ALL_DEV_NOT_VALID:
dwRuleStatus = FAX_RULE_STATUS_ALL_GROUP_DEV_NOT_VALID;
break;
case FAX_GROUP_STATUS_EMPTY:
dwRuleStatus = FAX_RULE_STATUS_EMPTY_GROUP;
break;
default:
Assert (FAX_GROUP_STATUS_ALL_DEV_VALID == GroupStatus);
}
}
else
{
// A device is the rule's destination
if (!IsDeviceInstalled (m_dwDevice))
{
// Device not installed
dwRuleStatus = FAX_RULE_STATUS_BAD_DEVICE;
}
}
Assert (ERROR_SUCCESS == dwRes);
exit:
if (ERROR_SUCCESS == dwRes)
{
*lpdwStatus = dwRuleStatus;
}
return dwRes;
} // COutboundRoutingRule::GetStatus
DWORD
COutboundRoutingRule::GetDeviceList (LPDWORD* lppdwDevices, LPDWORD lpdwNumDevices) const
/*++
Routine name : COutboundRoutingRule::GetDeviceList
Routine description:
Returns an ordered device list, which are the rule's destination devices.
The caller must call MemFree() to deallocate the memory.
Enter Critical Section (g_CsConfig) before calling this function.
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
lppdwDevices [out ] - Pointer to pointer to a DWORD buffer to recieve the devices list.
lpdwNumDevices [out ] - Pointer to a DWORD to recieve the number of devices returned
Return Value:
Standard Win32 error code
--*/
{
DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::GetDeviceList"));
DWORD dwRes = ERROR_SUCCESS;
PCGROUP pCGroup;
Assert (lppdwDevices && lpdwNumDevices);
*lppdwDevices = NULL;
*lpdwNumDevices = 0;
if (TRUE == m_bUseGroup)
{
// A group is the rule's destination
try
{
pCGroup = g_pGroupsMap->FindGroup (m_wstrGroupName.c_str());
if (NULL == pCGroup)
{
dwRes = GetLastError();
Assert (FAX_ERR_GROUP_NOT_FOUND != dwRes);
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingGroupsMap::FindGroup failed , ec %ld"), dwRes);
goto exit;
}
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("wstring caused exception (%S)"),
ex.what());
dwRes = ERROR_GEN_FAILURE;
goto exit;
}
// Get the group's device list
dwRes = pCGroup->SerializeDevices (lppdwDevices, lpdwNumDevices);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingGroup::SerializeDevices failed with %ld"),
dwRes);
goto exit;
}
}
else
{
// A single device
*lppdwDevices = (LPDWORD) MemAlloc(sizeof(DWORD));
if (*lppdwDevices == NULL)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Cannot allocate devices buffer"));
dwRes = ERROR_NOT_ENOUGH_MEMORY;
goto exit;
}
*(*lppdwDevices) = m_dwDevice;
*lpdwNumDevices = 1;
}
Assert (ERROR_SUCCESS == dwRes);
exit:
return dwRes;
} // COutboundRoutingRule::GetDeviceList
DWORD
COutboundRoutingRule::Serialize (LPBYTE lpBuffer,
PFAX_OUTBOUND_ROUTING_RULEW pFaxRule,
PULONG_PTR pupOffset,
DWORD dwBufferSize) const
/*++
Routine name : COutboundRoutingRule::Serialize
Routine description:
Serializes a rule's info based on FAX_OUTBOUND_ROUTING_RULEW structure.
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
lpBuffer [in] - Pointer to a pre-allocated buffer. If this parameter is NULL lpdwOffset will get the required buffer size.
pFaxRule [in] - Pointer to a specific FAX_OUTBOUND_ROUTING_RULEW structure in the buffer
pupOffset [in/out] - Offset from the begining of the buffer where variable length info is stored
DWORD dwBufferSize [in] - the size of input buffer, lpBuffer.
Return Value:
Standard Win32 error code
--*/
{
DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::Serialize"));
DWORD dwRes = ERROR_SUCCESS;
const CDialingLocation DialingLocation = GetDialingLocation();
LPCWSTR lpcwstrCountryName = NULL;
LPCWSTR lpwstrGroupName;
Assert (pupOffset);
if (NULL != lpBuffer)
{
Assert (0 != dwBufferSize);
}
if (ROUTING_RULE_COUNTRY_CODE_ANY != DialingLocation.GetCountryCode())
{
// Get the country name
lpcwstrCountryName = DialingLocation.GetCountryName();
if (NULL == lpcwstrCountryName)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::GetCountryName failed , ec %ld"), GetLastError());
}
}
try
{
lpwstrGroupName = m_bUseGroup ? m_wstrGroupName.c_str() : NULL;
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("wstring caused exception (%S)"),
ex.what());
MemFree ((void*)lpcwstrCountryName);
return ERROR_GEN_FAILURE;
}
StoreString (lpcwstrCountryName,
(PULONG_PTR)&(pFaxRule->lpctstrCountryName),
lpBuffer,
pupOffset,
dwBufferSize);
if (TRUE == m_bUseGroup)
{
StoreString (lpwstrGroupName,
(PULONG_PTR)&((pFaxRule->Destination).lpcstrGroupName),
lpBuffer,
pupOffset,
dwBufferSize);
}
if (NULL != lpBuffer)
{
// Write the data
Assert (pFaxRule);
if (FALSE == m_bUseGroup)
{
Assert (m_dwDevice);
(pFaxRule->Destination).dwDeviceId = m_dwDevice;
}
pFaxRule->dwSizeOfStruct = sizeof (FAX_OUTBOUND_ROUTING_RULEW);
pFaxRule->dwAreaCode = DialingLocation.GetAreaCode();
pFaxRule->dwCountryCode = DialingLocation.GetCountryCode();
pFaxRule->bUseGroup = m_bUseGroup;
dwRes = GetStatus (&(pFaxRule->Status));
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::GetStatus failed , ec %ld"), dwRes);
}
}
MemFree ((void*)lpcwstrCountryName);
return dwRes;
} // COutboundRoutingRule::Serialize
LPCWSTR
COutboundRoutingRule::GetGroupName () const
/*++
Routine name : COutboundRoutingRule::GetGroupName
Routine description:
Returns the group name if the rule's destination is a group.
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
Return Value:
The group name. If it is NULL call GetLastError() for more info.
If it is ERROR_SUCCESS the rule's destination is single device.
--*/
{
DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::GetGroupName"));
try
{
SetLastError (ERROR_SUCCESS);
if (TRUE == m_bUseGroup)
{
return m_wstrGroupName.c_str();
}
return NULL;
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("wstring caused exception (%S)"),
ex.what());
SetLastError (ERROR_GEN_FAILURE);
return NULL;
}
} // GetGroupName
#if DBG
void COutboundRoutingRule::Dump () const
{
DEBUG_FUNCTION_NAME(TEXT("COutboundRoutingRule::Dump"));
WCHAR Buffer[512] = {0};
DWORD dwBufferSize = sizeof (Buffer)/ sizeof (Buffer[0]);
try
{
if (TRUE == m_bUseGroup)
{
_snwprintf (Buffer, dwBufferSize -1, TEXT("\tCountry Code - %ld,\tArea Code - %ld,\tGroup name - %s"),
m_DialingLocation.GetCountryCode(),
m_DialingLocation.GetAreaCode(),
m_wstrGroupName.c_str());
}
else
{
_snwprintf (Buffer, dwBufferSize -1, TEXT("\tCountry Code - %ld,\tArea Code - %ld,\tDevice ID - %ld"),
m_DialingLocation.GetCountryCode(),
m_DialingLocation.GetAreaCode(),
m_dwDevice);
}
OutputDebugString (Buffer);
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("wstring caused exception (%S)"),
ex.what());
}
return;
}
#endif // #if DBG
/***********************************
* *
* COutboundRulesMap Methodes *
* *
***********************************/
DWORD
COutboundRulesMap::Load ()
/*++
Routine name : COutboundRulesMap::Load
Routine description:
Loads all outbound routing rules from the registry
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
Return Value:
Standard Win32 error code
--*/
{
DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::Load"));
DWORD dwRes = ERROR_SUCCESS;
HKEY hRuleskey = NULL;
DWORD dwCount = 0;
hRuleskey = OpenRegistryKey( HKEY_LOCAL_MACHINE,
REGKEY_FAX_OUTBOUND_ROUTING,
FALSE,
KEY_READ | KEY_WRITE );
if (NULL == hRuleskey)
{
dwRes = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("OpenRegistryKey, error %ld"),
dwRes);
return dwRes;
}
dwCount = EnumerateRegistryKeys( hRuleskey,
REGKEY_OUTBOUND_ROUTING_RULES,
FALSE,
EnumOutboundRoutingRulesCB,
&dwRes
);
if (dwRes != ERROR_SUCCESS)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("EnumerateRegistryKeys failed, error %ld"),
dwRes);
}
RegCloseKey (hRuleskey);
return dwRes;
} // COutboundRulesMap::Load
DWORD
COutboundRulesMap::AddRule (COutboundRoutingRule& Rule)
/*++
Routine name : COutboundRulesMap::AddRule
Routine description:
Adds a new rule to the global map
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
Rule [in ] - A reference to the new rule object
Return Value:
Standard Win32 error code
--*/
{
RULES_MAP::iterator it;
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("COutboundRoulesMap::AddRule"));
pair <RULES_MAP::iterator, bool> p;
try
{
//
// Add new map entry
//
p = m_RulesMap.insert (RULES_MAP::value_type(Rule.GetDialingLocation(), Rule));
//
// See if entry exists in map
//
if (p.second == FALSE)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Rule allready in the rules map"));
dwRes = ERROR_DUP_NAME;
goto exit;
}
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("map caused exception (%S)"),
ex.what());
dwRes = ERROR_GEN_FAILURE;
goto exit;
}
Assert (ERROR_SUCCESS == dwRes);
exit:
return dwRes;
} // COutboundRulesMap::AddRule
DWORD
COutboundRulesMap::DelRule (CDialingLocation& DialingLocation)
/*++
Routine name : COutboundRulesMap::DelRule
Routine description:
Deletes a group from the global rules map
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
DialingLocation [in ] - Pointer to the dialing location key
Return Value:
Standard Win32 error code
--*/
{
RULES_MAP::iterator it;
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::DelRule"));
try
{
//
// See if entry exists in map
//
if((it = m_RulesMap.find(DialingLocation)) == m_RulesMap.end())
{
DebugPrintEx(
DEBUG_ERR,
TEXT("rule is not in the rules map"));
dwRes = FAX_ERR_RULE_NOT_FOUND;
goto exit;
}
//
// Delete the map entry
//
m_RulesMap.erase (it);
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("map caused exception (%S)"),
ex.what());
dwRes = ERROR_GEN_FAILURE;
goto exit;
}
Assert (ERROR_SUCCESS == dwRes);
exit:
return dwRes;
} // COutboundRulesMap::DelRule
PCRULE
COutboundRulesMap::FindRule (CDialingLocation& DialingLocation) const
/*++
Routine name : COutboundRulesMap::FindRule
Routine description:
Returns a pointer to a rule object specified by its name
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
DialingLocation [in] - The rule's dialing location
Return Value:
Pointer to the found rule object. If it is null the rule was not found
--*/
{
RULES_MAP::iterator it;
DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::FindRule"));
try
{
//
// See if entry exists in map
//
if((it = m_RulesMap.find(DialingLocation)) == m_RulesMap.end())
{
SetLastError (FAX_ERR_RULE_NOT_FOUND);
return NULL;
}
return &((*it).second);
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("map caused exception (%S)"),
ex.what());
SetLastError (ERROR_GEN_FAILURE);
return NULL;
}
} // COutboundRulesMap::FindRule
DWORD
COutboundRulesMap::SerializeRules (PFAX_OUTBOUND_ROUTING_RULEW* ppRules,
LPDWORD lpdwNumRules,
LPDWORD lpdwBufferSize) const
/*++
Routine name : COutboundRulesMap::SerializeRules
Routine description:
Serializes all the rules in the rules map.
the caller must call MemFree() to deallocate memory.
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
ppRules [out ] - Pointer to a pointer to recieve the FAX_OUTBOUND_ROUTING_RULEW buffer
lpdwNumRules [out ] - Pointer to a DWORD to recieve the number of rules serialized
lpdwBufferSize [out ] - Pointer to DWORD to recieve the size of the allocated buffer
Return Value:
Standard Win32 error code
--*/
{
RULES_MAP::iterator it;
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::SerializeRules"));
DWORD_PTR dwSize = 0;
DWORD dwCount = 0;
PCRULE pCRule;
Assert (ppRules && lpdwNumRules && lpdwBufferSize);
*ppRules = NULL;
*lpdwNumRules = 0;
try
{
// Calculate buffer size
for (it = m_RulesMap.begin(); it != m_RulesMap.end(); ++it)
{
pCRule = &((*it).second);
dwSize += sizeof (FAX_OUTBOUND_ROUTING_RULEW);
dwRes = pCRule->Serialize (NULL, NULL, &dwSize, 0);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::Serialize failed with %ld"),
dwRes);
goto exit;
}
dwCount ++;
}
//
// dwCount can't be 0 - there is always a default rule
//
Assert ( dwCount != 0 );
if ( 0 == dwCount )
{
//
// Somthing wrong we have no outbound routing rule
//
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRulesMap::SerializeRules, No outbound rules have been found."));
dwRes = ERROR_INVALID_DATA;
goto exit;
}
// Allocate buffer
*ppRules = (PFAX_OUTBOUND_ROUTING_RULEW) MemAlloc (dwSize);
if (NULL == *ppRules)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Cannot allocate rules buffer"));
dwRes = ERROR_NOT_ENOUGH_MEMORY;
goto exit;
}
ZeroMemory(*ppRules, dwSize);
DWORD_PTR dwOffset = dwCount * sizeof (FAX_OUTBOUND_ROUTING_RULEW);
dwCount = 0;
// Fill buffer with serialized info
for (it = m_RulesMap.begin(); it != m_RulesMap.end(); it++)
{
pCRule = &((*it).second);
(*ppRules)[dwCount].dwSizeOfStruct = DWORD(sizeof (FAX_OUTBOUND_ROUTING_RULEW));
dwRes = pCRule->Serialize ((LPBYTE)*ppRules, &((*ppRules)[dwCount]), &dwOffset, dwSize);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::Serialize failed with %ld"),
dwRes);
goto exit;
}
dwCount++;
}
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("map caused exception (%S)"),
ex.what());
dwRes = ERROR_GEN_FAILURE;
goto exit;
}
*lpdwNumRules = dwCount;
// until MIDL accepts [out, size_is(,__int64*)]
*lpdwBufferSize = (DWORD)dwSize;
Assert (ERROR_SUCCESS == dwRes);
exit:
if (ERROR_SUCCESS != dwRes)
{
MemFree (*ppRules);
}
return dwRes;
} // COutboundRulesMap::SerializeRules
BOOL
COutboundRulesMap::CreateDefaultRule (void)
/*++
Routine name : COutboundRulesMap::CreateDefaultRule
Routine description:
Creates the default mandatory rule (All CountryCodes, All AreaCodes) if does not exist.
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
Return Value:
BOOL , Call GetLastError () for more info
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::CreateDefaultRule"));
PCRULE pCRule;
CDialingLocation Dialinglocation (ROUTING_RULE_COUNTRY_CODE_ANY, ROUTING_RULE_AREA_CODE_ANY);
FAX_ENUM_RULE_STATUS dwRuleStatus;
HKEY hRuleKey = NULL;
DWORD rVal;
pCRule = FindRule (Dialinglocation);
if (NULL != pCRule)
{
// Rule exist
return TRUE;
}
dwRes = GetLastError();
if (FAX_ERR_RULE_NOT_FOUND != dwRes)
{
// general failure
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRulesMap::FindRule failed , ec %ld"), dwRes);
return FALSE;
}
dwRes = ERROR_SUCCESS;
//
// Rule does not exist - Create it
//
// Create the rule registry key
hRuleKey = OpenOutboundRuleKey( ROUTING_RULE_COUNTRY_CODE_ANY, ROUTING_RULE_AREA_CODE_ANY, TRUE, KEY_READ | KEY_WRITE );
if (NULL == hRuleKey)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Can't create rule key, OpenRegistryKey failed : %ld"),
GetLastError ());
return FALSE;
}
COutboundRoutingRule Rule;
try
{
wstring wstrGroupName (ROUTING_GROUP_ALL_DEVICES);
dwRes = Rule.Init (Dialinglocation, wstrGroupName);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::Init failed , ec %ld"), dwRes);
goto exit;
}
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("wstring caused exception (%S)"),
ex.what());
dwRes = ERROR_GEN_FAILURE;
goto exit;
}
dwRes = AddRule (Rule);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::AddRule failed , ec %ld"), dwRes);
goto exit;
}
// Save the new rule to the registry
dwRes = Rule.Save (hRuleKey);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::Save failed, with %ld"),
dwRes);
g_pRulesMap->DelRule (Dialinglocation);
goto exit;
}
rVal = Rule.GetStatus (&dwRuleStatus);
if (ERROR_SUCCESS != rVal)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::GetStatus failed , ec %ld"), rVal);
}
else
{
if (dwRuleStatus != FAX_RULE_STATUS_VALID &&
dwRuleStatus != FAX_RULE_STATUS_SOME_GROUP_DEV_NOT_VALID)
{
// Can be if <All devices> is empty (The service has no devices).
DebugPrintEx(
DEBUG_MSG,
TEXT("Bad default rule configuration, FAX_RULE_STATUS %ld"), dwRuleStatus);
FaxLog(
FAXLOG_CATEGORY_INIT,
FAXLOG_LEVEL_MED,
2,
MSG_BAD_OUTBOUND_ROUTING_RULE_CONFIGUTATION,
TEXT("*"),
TEXT("*")
);
}
}
Assert (ERROR_SUCCESS == dwRes);
exit:
if (NULL != hRuleKey)
{
RegCloseKey (hRuleKey);
}
if (ERROR_SUCCESS != dwRes)
{
SetLastError(dwRes);
}
return (ERROR_SUCCESS == dwRes);
} // CreateDefaultRule
DWORD
COutboundRulesMap::IsGroupInRuleDest (LPCWSTR lpcwstrGroupName , BOOL* lpbGroupInRule) const
/*++
Routine name : COutboundRulesMap::IsGroupInRuleDest
Routine description:
Checks if a specific group is a destination of one of the rules
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
lpcwstrGroupName [in ] - Group name
lpbGroupInRule [out] - Pointer to a BOOL. Gets TRUE if the group is in rule, else FALSE
Return Value:
Standard Win32 error code.
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("COutboundRulesMap::IsGroupInRuleDest"));
RULES_MAP::iterator it;
Assert (lpbGroupInRule);
try
{
for (it = m_RulesMap.begin(); it != m_RulesMap.end(); it++)
{
PCRULE pCRule = &((*it).second);
LPCWSTR lpcwstrRuleGroupName = pCRule->GetGroupName();
if (NULL == lpcwstrRuleGroupName)
{
dwRes = GetLastError();
if (dwRes != ERROR_SUCCESS)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::GetGroupName failed , ec %ld"), dwRes);
return dwRes;
}
else
{
// This rule uses a single device as its destination
}
continue;
}
if (wcscmp (lpcwstrGroupName, lpcwstrRuleGroupName) == 0)
{
*lpbGroupInRule = TRUE;
return ERROR_SUCCESS;
}
}
*lpbGroupInRule = FALSE;
return ERROR_SUCCESS;
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("map or wstring caused exception (%S)"),
ex.what());
return ERROR_GEN_FAILURE;
}
} // IsGroupInRuleDest
#if DBG
void COutboundRulesMap::Dump () const
{
RULES_MAP::iterator it;
WCHAR Buffer[512] = {0};
DWORD dwBufferSize = sizeof (Buffer)/ sizeof (Buffer[0]);
_snwprintf (Buffer, dwBufferSize -1, TEXT("DUMP - Outbound routing rules\n"));
OutputDebugString (Buffer);
for (it = m_RulesMap.begin(); it != m_RulesMap.end(); it++)
{
((*it).second).Dump();
OutputDebugString (TEXT("\n"));
}
return;
}
#endif // #if DBG
void
FaxLogOutboundRule (LPCWSTR lpcwstrRuleName,
DWORD dwMessageID)
{
WCHAR wszRuleName[MAX_PATH] = {0};
LPWSTR lpwstrCountryCode;
LPWSTR lpwstrAreaCode;
LPWSTR lpwstrDelim = NULL;
DWORD dwLevel = FAXLOG_LEVEL_MIN;
Assert (lpcwstrRuleName);
Assert (dwMessageID == MSG_BAD_OUTBOUND_ROUTING_RULE_CONFIGUTATION ||
dwMessageID == MSG_OUTBOUND_ROUTING_RULE_NOT_LOADED ||
dwMessageID == MSG_OUTBOUND_ROUTING_RULE_NOT_ADDED);
if (dwMessageID == MSG_BAD_OUTBOUND_ROUTING_RULE_CONFIGUTATION)
{
dwLevel = FAXLOG_LEVEL_MED;
}
if (FAILED(StringCchCopy(wszRuleName, ARR_SIZE(wszRuleName), lpcwstrRuleName)))
{
ASSERT_FALSE;
return;
}
lpwstrDelim = wcschr (wszRuleName, L':');
if (NULL == lpwstrDelim)
{
//
// Registry corruption
//
ASSERT_FALSE;
return;
}
lpwstrCountryCode = wszRuleName;
*lpwstrDelim = L'\0';
lpwstrDelim ++;
lpwstrAreaCode = lpwstrDelim;
if (wcscmp( lpwstrAreaCode, TEXT("0")) == 0 )
{
wcscpy ( lpwstrAreaCode, TEXT("*"));
}
if (wcscmp( lpwstrCountryCode, TEXT("0")) == 0 )
{
wcscpy ( lpwstrCountryCode, TEXT("*"));
}
FaxLog(
FAXLOG_CATEGORY_INIT,
dwLevel,
2,
dwMessageID,
lpwstrCountryCode,
lpwstrAreaCode
);
return;
}
/************************************
* *
* Registry *
* *
************************************/
BOOL
EnumOutboundRoutingRulesCB(
HKEY hSubKey,
LPWSTR SubKeyName,
DWORD Index,
LPVOID pContext
)
{
DEBUG_FUNCTION_NAME(TEXT("EnumOutboundRoutingGroupsCB"));
DWORD dwRes;
COutboundRoutingRule Rule;
BOOL bRuleDeleted = FALSE;
if (!SubKeyName)
{
return TRUE;
}
//
// Add rule
//
dwRes = Rule.Load (hSubKey);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::Load failed, rule - %s, error %ld"),
SubKeyName,
dwRes);
// Open Outbound Routing\Rules key
HKEY hRulesKey = OpenRegistryKey( HKEY_LOCAL_MACHINE,
REGKEY_FAX_OUTBOUND_ROUTING_RULES,
FALSE,
KEY_READ | KEY_WRITE | DELETE);
if (NULL == hRulesKey)
{
dwRes = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("OpenRegistryKey, error %ld"),
dwRes);
}
else
{
DWORD dwRetVal = RegDeleteKey (hRulesKey, SubKeyName);
if (ERROR_SUCCESS != dwRetVal)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("RegDeleteKey failed, Rule name - %s, error %ld"),
SubKeyName,
dwRetVal);
}
else
{
bRuleDeleted = TRUE;
}
}
goto exit;
}
//
// Check on which platform are we running
//
if ((Rule.GetDialingLocation()).GetCountryCode() != ROUTING_RULE_COUNTRY_CODE_ANY &&
TRUE == IsDesktopSKU())
{
//
// We do not support outbound routing on desktop SKUs. Only load default rule *.* (*.AreaCode is not loaded anyway)
//
goto exit;
}
FAX_ENUM_RULE_STATUS RuleStatus;
dwRes = Rule.GetStatus(&RuleStatus);
if (ERROR_SUCCESS == dwRes)
{
if (RuleStatus != FAX_RULE_STATUS_VALID &&
RuleStatus != FAX_RULE_STATUS_SOME_GROUP_DEV_NOT_VALID)
{
FaxLogOutboundRule (SubKeyName, MSG_BAD_OUTBOUND_ROUTING_RULE_CONFIGUTATION);
}
}
else
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::GetStatus failed, error %ld"),
dwRes);
}
dwRes = g_pRulesMap->AddRule (Rule);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundrulesMap::Addrule failed, rule name - %s, error %ld"),
SubKeyName,
dwRes);
goto exit;
}
Assert (ERROR_SUCCESS == dwRes);
exit:
if (ERROR_SUCCESS != dwRes)
{
if (bRuleDeleted == FALSE)
{
FaxLogOutboundRule (SubKeyName, MSG_OUTBOUND_ROUTING_RULE_NOT_ADDED);
}
else
{
FaxLogOutboundRule (SubKeyName, MSG_OUTBOUND_ROUTING_RULE_NOT_LOADED);
}
}
*(LPDWORD)pContext = ERROR_SUCCESS; // Let the service start
return TRUE; // Let the service start
} // EnumOutboundRoutingRulesCB
/************************************
* *
* RPC handlers *
* *
************************************/
error_status_t
FAX_AddOutboundRule(
HANDLE hFaxHandle,
DWORD dwAreaCode,
DWORD dwCountryCode,
DWORD dwDeviceID,
LPCWSTR lpcwstrGroupName,
BOOL bUseGroup
)
/*++
Routine name : FAX_AddOutboundRule
Routine description:
Adds a new rule to the rules map and to the registry
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
hFaxHandle [in ] - Fax handle
dwAreaCode [in ] - The rule area code
dwCountryCode [in ] - The rule country code
dwDeviceID [in ] - The rule's destinationis device ID. Valid only if bUseGroup is FALSE
lpcwstrGroupName [in ] - The rule's destination group name. Valid only if bUseGroup is TRUE.
bUseGroup [in ] - Flag that indicates whether to use the group as the rule destination
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("FAX_AddOutboundRule"));
HKEY hRuleKey = NULL;
DWORD rVal;
BOOL fAccess;
//
// 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 (dwCountryCode == ROUTING_RULE_COUNTRY_CODE_ANY)
{
//
// *.* can not be added; *.AreaCode is not a valid rule dialing location.
//
DebugPrintEx(
DEBUG_ERR,
TEXT("dwCountryCode = 0; *.* can not be added; *.AreaCode is not a valid rule dialing location"));
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;
}
}
if (TRUE == bUseGroup)
{
if (!lpcwstrGroupName)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("lpctstrGroupName is NULL"));
return ERROR_INVALID_PARAMETER;
}
if (wcslen (lpcwstrGroupName) >= MAX_ROUTING_GROUP_NAME)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Group name length exceeded MAX_ROUTING_GROUP_NAME"));
return ERROR_BUFFER_OVERFLOW;
}
}
else
{
if (!dwDeviceID)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("dwDeviceId = 0; Not a valid device ID"));
return ERROR_INVALID_PARAMETER;
}
}
// Create a new Dialinglocation object
CDialingLocation Dialinglocation (dwCountryCode, dwAreaCode);
if (!Dialinglocation.IsValid())
{
DebugPrintEx(
DEBUG_ERR,
TEXT("CDialingLocation::IsValidDialingLocation failed, \
Area code %ld, Country code %ld"),
dwAreaCode,
dwCountryCode);
return ERROR_INVALID_PARAMETER;
}
// Create a new rule object
COutboundRoutingRule Rule;
if (TRUE == bUseGroup)
{
try
{
wstring wstrGroupName(lpcwstrGroupName);
dwRes = Rule.Init (Dialinglocation, wstrGroupName);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::Init failed , ec %ld"), dwRes);
return GetServerErrorCode(dwRes);
}
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("wstring caused exception (%S)"),
ex.what());
return ERROR_GEN_FAILURE;
}
}
else
{
Rule.Init (Dialinglocation ,dwDeviceID);
}
EnterCriticalSection (&g_CsLine);
EnterCriticalSection (&g_CsConfig);
FAX_ENUM_RULE_STATUS RuleStatus;
dwRes = Rule.GetStatus(&RuleStatus);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoule::GetStatus failed, error %ld"),
dwRes);
goto exit;
}
if (FAX_GROUP_STATUS_ALL_DEV_NOT_VALID == RuleStatus ||
FAX_RULE_STATUS_EMPTY_GROUP == RuleStatus)
{
// Empty group device list
DebugPrintEx(
DEBUG_ERR,
TEXT("Bad rule configutation, FAX_RULE_STATUS %ld"), RuleStatus);
dwRes = FAX_ERR_BAD_GROUP_CONFIGURATION;
goto exit;
}
if (FAX_RULE_STATUS_BAD_DEVICE == RuleStatus)
{
// Bad device
DebugPrintEx(
DEBUG_ERR,
TEXT("Bad rule configutation, FAX_RULE_STATUS %ld"), RuleStatus);
dwRes = ERROR_BAD_UNIT;
goto exit;
}
// Create the rule registry key
hRuleKey = OpenOutboundRuleKey( dwCountryCode, dwAreaCode, TRUE, KEY_READ | KEY_WRITE );
if (NULL == hRuleKey)
{
dwRes = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("Can't create rule key, OpenRegistryKey failed : %ld"),
dwRes);
dwRes = ERROR_REGISTRY_CORRUPT;
goto exit;
}
// Add the new rule to the map
dwRes = g_pRulesMap->AddRule (Rule);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoulesMap::AddRule failed, error %ld"),
dwRes);
goto exit;
}
// Save the new rule to the registry
dwRes = Rule.Save (hRuleKey);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::Save failed, with %ld"),
dwRes);
g_pRulesMap->DelRule (Dialinglocation);
dwRes = ERROR_REGISTRY_CORRUPT;
goto exit;
}
#if DBG
DebugPrintEx(
DEBUG_MSG,
TEXT("Dump outbound routing rules - after change"));
g_pRulesMap->Dump();
#endif
rVal = CreateConfigEvent (FAX_CONFIG_TYPE_OUT_RULES);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("CreateConfigEvent(FAX_CONFIG_TYPE_OUT_RULES) (ec: %lc)"),
rVal);
}
Assert (ERROR_SUCCESS == dwRes);
exit:
if (NULL != hRuleKey)
{
RegCloseKey (hRuleKey);
}
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);
} // FAX_AddOutboundRule
error_status_t
FAX_RemoveOutboundRule (
IN handle_t hFaxHandle,
IN DWORD dwAreaCode,
IN DWORD dwCountryCode
)
/*++
Routine name : FAX_RemoveOutboundRule
Routine description:
Removes an existing rule from the rules map and from the registry.
Author:
Oded Sacher (OdedS), Dec, 1999
Arguments:
hFaxHandle [in] - Fax handle
dwAreaCode [in] - The rule area code
dwCountryCode [in] - The rule country code
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("FAX_RemoveOutboundRule"));
DWORD rVal;
PCRULE pCRule = NULL;
BOOL fAccess;
//
// 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 (dwCountryCode == ROUTING_RULE_COUNTRY_CODE_ANY)
{
//
// *.* can not be removed; *.AreaCode is not a valid rule dialing location.
//
DebugPrintEx(
DEBUG_ERR,
TEXT("dwCountryCode = 0; *.* can not be added; *.AreaCode is not a valid rule dialing location"));
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;
}
}
CDialingLocation Dialinglocation (dwCountryCode, dwAreaCode);
EnterCriticalSection (&g_CsConfig);
pCRule = g_pRulesMap->FindRule (Dialinglocation);
if (NULL == pCRule)
{
dwRes = GetLastError();
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoulesMap::FindRule failed, error %ld"),
dwRes);
goto exit;
}
// Delete the specified rule key
dwRes = DeleteOutboundRuleKey (dwCountryCode, dwAreaCode);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("DeleteOutboundRuleKey failed, CountryCode - %ld, AreaCode - %ld, error %ld"),
dwCountryCode,
dwAreaCode,
dwRes);
dwRes = ERROR_REGISTRY_CORRUPT;
goto exit;
}
// Delete the rule from the memory
dwRes = g_pRulesMap->DelRule (Dialinglocation);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRulesMap::DelRule failed, error %ld"),
dwRes);
goto exit;
}
#if DBG
DebugPrintEx(
DEBUG_MSG,
TEXT("Dump outbound routing rules - after change"));
g_pRulesMap->Dump();
#endif
rVal = CreateConfigEvent (FAX_CONFIG_TYPE_OUT_RULES);
if (ERROR_SUCCESS != rVal)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("CreateConfigEvent(FAX_CONFIG_TYPE_OUT_RULES) (ec: %lc)"),
rVal);
}
Assert (ERROR_SUCCESS == dwRes);
exit:
LeaveCriticalSection (&g_CsConfig);
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 dwRes;
} // FAX_RemoveOutboundRule
error_status_t
FAX_SetOutboundRule(
HANDLE hFaxHandle,
PRPC_FAX_OUTBOUND_ROUTING_RULEW pRule
)
{
DWORD dwRes = ERROR_SUCCESS;
DWORD rVal;
DEBUG_FUNCTION_NAME(TEXT("FAX_SetOutboundRule"));
HKEY hRuleKey = NULL;
PCRULE pCRule = NULL;
FAX_ENUM_RULE_STATUS dwRuleStatus;
BOOL fAccess;
Assert (pRule);
//
// 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 (TRUE == pRule->bUseGroup)
{
if (!(pRule->Destination).lpwstrGroupName)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("lpwstrGroupName is NULL"));
return ERROR_INVALID_PARAMETER;
}
if (wcslen ((pRule->Destination).lpwstrGroupName) >= MAX_ROUTING_GROUP_NAME)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Group name length exceeded MAX_ROUTING_GROUP_NAME"));
return ERROR_BUFFER_OVERFLOW;
}
}
else
{
if (!(pRule->Destination).dwDeviceId)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("dwDeviceId = 0; Not a valid device ID"));
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;
}
}
CDialingLocation Dialinglocation (pRule->dwCountryCode, pRule->dwAreaCode);
COutboundRoutingRule Rule, OldRule;
if (TRUE == pRule->bUseGroup)
{
try
{
wstring wstrGroupName((pRule->Destination).lpwstrGroupName);
dwRes = Rule.Init (Dialinglocation, wstrGroupName);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::Init failed , ec %ld"), dwRes);
return GetServerErrorCode(dwRes);
}
}
catch (exception &ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("wstring caused exception (%S)"),
ex.what());
return ERROR_GEN_FAILURE;
}
}
else
{
Rule.Init (Dialinglocation ,(pRule->Destination).dwDeviceId);
}
EnterCriticalSection (&g_CsLine);
EnterCriticalSection (&g_CsConfig);
// Check the new rule status
dwRes = Rule.GetStatus (&dwRuleStatus);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::GetStatus failed , ec %ld"), dwRes);
goto exit;
}
if (FAX_GROUP_STATUS_ALL_DEV_NOT_VALID == dwRuleStatus ||
FAX_RULE_STATUS_EMPTY_GROUP == dwRuleStatus)
{
// Empty group device list
DebugPrintEx(
DEBUG_ERR,
TEXT("Bad rule configutation, FAX_RULE_STATUS %ld"), dwRuleStatus);
dwRes = FAX_ERR_BAD_GROUP_CONFIGURATION;
goto exit;
}
if (FAX_RULE_STATUS_BAD_DEVICE == dwRuleStatus)
{
// Bad device
DebugPrintEx(
DEBUG_ERR,
TEXT("Bad rule configutation, FAX_RULE_STATUS %ld"), dwRuleStatus);
dwRes = ERROR_BAD_UNIT;
goto exit;
}
pCRule = g_pRulesMap->FindRule (Dialinglocation);
if (NULL == pCRule)
{
dwRes = GetLastError();
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoulesMap::FindRule failed, error %ld"),
dwRes);
goto exit;
}
// Open the rule registry key
hRuleKey = OpenOutboundRuleKey( pRule->dwCountryCode, pRule->dwAreaCode, FALSE, KEY_READ | KEY_WRITE );
if (NULL == hRuleKey)
{
dwRes = GetLastError ();
DebugPrintEx(
DEBUG_ERR,
TEXT("Can't open rule key, OpenRegistryKey failed : %ld"),
dwRes);
dwRes = ERROR_REGISTRY_CORRUPT;
goto exit;
}
OldRule = *pCRule;
*pCRule = Rule;
dwRes = pCRule->Save (hRuleKey);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRule::Save failed, with %ld"),
dwRes);
*pCRule = OldRule;
dwRes = ERROR_REGISTRY_CORRUPT;
goto exit;
}
#if DBG
DebugPrintEx(
DEBUG_MSG,
TEXT("Dump outbound routing rules - after change"));
g_pRulesMap->Dump();
#endif
rVal = CreateConfigEvent (FAX_CONFIG_TYPE_OUT_RULES);
if (ERROR_SUCCESS != rVal)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("CreateConfigEvent(FAX_CONFIG_TYPE_OUT_RULES) (ec: %lc)"),
rVal);
}
Assert (ERROR_SUCCESS == dwRes);
exit:
if (NULL != hRuleKey)
{
RegCloseKey (hRuleKey);
}
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);
} // FAX_FaxSetOutboundRule
error_status_t
FAX_EnumOutboundRules (
handle_t hFaxHandle,
LPBYTE* ppBuffer,
LPDWORD lpdwBufferSize,
LPDWORD lpdwNumRules
)
/*++
Routine name : FAX_EnumOutboundRules
Routine description:
Enumurates all outbound routing rules
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 rules returned
Return Value:
error_status_t
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("FAX_EnumOutboundRules"));
BOOL fAccess;
Assert (lpdwNumRules && lpdwBufferSize); // 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;
*lpdwNumRules = 0;
EnterCriticalSection (&g_CsLine);
EnterCriticalSection (&g_CsConfig);
dwRes = g_pRulesMap->SerializeRules ((PFAX_OUTBOUND_ROUTING_RULEW*)ppBuffer,
lpdwNumRules,
lpdwBufferSize);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("COutboundRoutingRulesMap::SerializeRules failed, error %ld"),
dwRes);
goto exit;
}
Assert (ERROR_SUCCESS == dwRes);
exit:
LeaveCriticalSection (&g_CsConfig);
LeaveCriticalSection (&g_CsLine);
UNREFERENCED_PARAMETER (hFaxHandle);
return GetServerErrorCode(dwRes);
} //FAX_EnumOutboundGroups