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
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
|
|
|