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.
 
 
 
 
 
 

1736 lines
46 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
DeviceProp.cpp
Abstract:
Holds outbound routing configuraton per single device
Author:
Eran Yariv (EranY) Nov, 1999
Revision History:
--*/
#include "faxrtp.h"
#pragma hdrstop
/************************************
* *
* Definitions *
* *
************************************/
//
// Default values for configuration:
//
#define DEFAULT_FLAGS 0 // No routing method is enabled
#define DEFAULT_STORE_FOLDER TEXT("")
#define DEFAULT_MAIL_PROFILE TEXT("")
#define DEFAULT_PRINTER_NAME TEXT("")
//
// The following array of GUID is used for registration / unregistration of notifications
//
LPCWSTR g_lpcwstrGUIDs[NUM_NOTIFICATIONS] =
{
REGVAL_RM_FLAGS_GUID, // GUID for routing methods usage flags
REGVAL_RM_FOLDER_GUID, // GUID for store method folder
REGVAL_RM_PRINTING_GUID, // GUID for print method printer name
REGVAL_RM_EMAIL_GUID, // GUID for mail method address
};
static
BOOL
IsUnicodeString (
LPBYTE lpData,
DWORD dwDataSize
)
{
if ( 0 != (dwDataSize % sizeof(WCHAR)) ||
TEXT('\0') != ((LPCWSTR)(lpData))[dwDataSize / sizeof(WCHAR) - 1])
{
return FALSE;
}
return TRUE;
} // IsUnicodeString
/************************************
* *
* CDevicesMap *
* *
************************************/
DWORD
CDevicesMap::Init ()
/*++
Routine name : CDevicesMap::Init
Routine description:
Initializes internal variables.
Call only once before any other calls.
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
Return Value:
Standard Win32 error code.
--*/
{
DEBUG_FUNCTION_NAME(TEXT("CDevicesMap::Init"));
if (m_bInitialized)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("CDevicesMap::Init called more than once"));
return ERROR_ALREADY_INITIALIZED;
}
m_bInitialized = TRUE;
if (FAILED(SafeInitializeCriticalSection(&m_CsMap)))
{
m_bInitialized = FALSE;
return GetLastError();
}
return ERROR_SUCCESS;
} // CDevicesMap::Init
CDevicesMap::~CDevicesMap ()
{
DEBUG_FUNCTION_NAME(TEXT("CDevicesMap::~CDevicesMap"));
if (m_bInitialized)
{
DeleteCriticalSection (&m_CsMap);
}
try
{
for (DEVICES_MAP::iterator it = m_Map.begin(); it != m_Map.end(); ++it)
{
CDeviceRoutingInfo *pDevInfo = (*it).second;
delete pDevInfo;
}
}
catch (exception ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Got an STL exception while clearing the devices map (%S)"),
ex.what());
}
} // CDevicesMap::~CDevicesMap
CDeviceRoutingInfo *
CDevicesMap::FindDeviceRoutingInfo (
DWORD dwDeviceId
)
/*++
Routine name : CDevicesMap::FindDeviceRoutingInfo
Routine description:
Finds a device in the map
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
dwDeviceId [in ] - Device id
Return Value:
Pointer to device object.
If NULL, use GetLastError() to retrieve error code.
--*/
{
DEVICES_MAP::iterator it;
CDeviceRoutingInfo *pDevice = NULL;
DEBUG_FUNCTION_NAME(TEXT("CDevicesMap::FindDeviceRoutingInfo"));
if (!m_bInitialized)
{
//
// Critical section failed to initialized
//
DebugPrintEx(
DEBUG_ERR,
TEXT("CDevicesMap::FindDeviceRoutingInfo called but CS is not initialized."));
SetLastError (ERROR_GEN_FAILURE);
return NULL;
}
EnterCriticalSection (&m_CsMap);
try
{
if((it = m_Map.find(dwDeviceId)) == m_Map.end())
{
//
// Device not found in map
//
SetLastError (ERROR_NOT_FOUND);
goto exit;
}
else
{
//
// Device found in map
//
pDevice = (*it).second;
goto exit;
}
}
catch (exception ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Got an STL exception while searching a devices map(%S)"),
ex.what());
SetLastError (ERROR_GEN_FAILURE);
pDevice = NULL;
goto exit;
}
exit:
LeaveCriticalSection (&m_CsMap);
return pDevice;
} // CDevicesMap::FindDeviceRoutingInfo
CDeviceRoutingInfo *
CDevicesMap::GetDeviceRoutingInfo (
DWORD dwDeviceId
)
/*++
Routine name : CDevicesMap::GetDeviceRoutingInfo
Routine description:
Finds a device in the map.
If not exists, attempts to create a new map entry.
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
dwDeviceId [in] - Device id
Return Value:
Pointer to device object.
If NULL, use GetLastError() to retrieve error code.
--*/
{
DEVICES_MAP::iterator it;
DWORD dwRes;
DEBUG_FUNCTION_NAME(TEXT("CDevicesMap::GetDeviceRoutingInfo"));
if (!m_bInitialized)
{
//
// Critical section failed to initialized
//
DebugPrintEx(
DEBUG_ERR,
TEXT("CDevicesMap::GetDeviceRoutingInfo called but CS is not initialized."));
SetLastError (ERROR_GEN_FAILURE);
return NULL;
}
EnterCriticalSection (&m_CsMap);
//
// Start by looking up the device in the map
//
CDeviceRoutingInfo *pDevice = FindDeviceRoutingInfo (dwDeviceId);
if (NULL == pDevice)
{
//
// Error finding device in map
//
if (ERROR_NOT_FOUND != GetLastError ())
{
//
// Real error
//
goto exit;
}
//
// The device is not in the map - add it now
//
DebugPrintEx(
DEBUG_MSG,
TEXT("Adding device %ld to routing map"),
dwDeviceId);
//
// Allocate device
//
pDevice = new (std::nothrow) CDeviceRoutingInfo (dwDeviceId);
if (!pDevice)
{
DebugPrintEx(
DEBUG_MSG,
TEXT("Cannot allocate memory for a CDeviceRoutingInfo"));
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
goto exit;
}
//
// Read configuration
//
dwRes = pDevice->ReadConfiguration ();
if (ERROR_SUCCESS != dwRes)
{
delete pDevice;
pDevice = NULL;
SetLastError (dwRes);
goto exit;
}
//
// Add notification requests for the device
//
dwRes = pDevice->RegisterForChangeNotifications();
if (ERROR_SUCCESS != dwRes)
{
delete pDevice;
pDevice = NULL;
SetLastError (dwRes);
goto exit;
}
//
// Add device to map
//
try
{
m_Map[dwDeviceId] = pDevice;
}
catch (exception ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Got an STL exception while trying to add a devices map entry (%S)"),
ex.what());
SetLastError (ERROR_GEN_FAILURE);
pDevice->UnregisterForChangeNotifications();
delete pDevice;
pDevice = NULL;
goto exit;
}
}
else
{
//
// Read the device configuration even if it in the map
// to avoid the situation when the configuration change notification
// arrive after the GetDeviceRoutingInfo() request.
//
dwRes = pDevice->ReadConfiguration ();
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(DEBUG_ERR, TEXT("CDeviceRoutingInfo::ReadConfiguration() failed with %ld"), dwRes);
SetLastError (dwRes);
goto exit;
}
}
exit:
LeaveCriticalSection (&m_CsMap);
return pDevice;
} // CDevicesMap::GetDeviceRoutingInfo
/************************************
* *
* Pre-declarations *
* *
************************************/
static
HRESULT
FaxRoutingExtConfigChange (
DWORD dwDeviceId, // The device for which configuration has changed
LPCWSTR lpcwstrNameGUID, // Configuration name
LPBYTE lpData, // New configuration data
DWORD dwDataSize // Size of new configuration data
);
/************************************
* *
* Globals *
* *
************************************/
CDevicesMap g_DevicesMap; // Global map of known devices (used for late discovery).
//
// Extension data callbacks into the server:
//
PFAX_EXT_GET_DATA g_pFaxExtGetData = NULL;
PFAX_EXT_SET_DATA g_pFaxExtSetData = NULL;
PFAX_EXT_REGISTER_FOR_EVENTS g_pFaxExtRegisterForEvents = NULL;
PFAX_EXT_UNREGISTER_FOR_EVENTS g_pFaxExtUnregisterForEvents = NULL;
PFAX_EXT_FREE_BUFFER g_pFaxExtFreeBuffer = NULL;
/************************************
* *
* Exported DLL function *
* *
************************************/
HRESULT
FaxExtInitializeConfig (
PFAX_EXT_GET_DATA pFaxExtGetData,
PFAX_EXT_SET_DATA pFaxExtSetData,
PFAX_EXT_REGISTER_FOR_EVENTS pFaxExtRegisterForEvents,
PFAX_EXT_UNREGISTER_FOR_EVENTS pFaxExtUnregisterForEvents,
PFAX_EXT_FREE_BUFFER pFaxExtFreeBuffer
)
/*++
Routine name : FaxExtInitializeConfig
Routine description:
Exported function called by the service to initialize extension data mechanism
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
pFaxExtGetData [in] - Pointer to FaxExtGetData
pFaxExtSetData [in] - Pointer to FaxExtSetData
pFaxExtRegisterForEvents [in] - Pointer to FaxExtRegisterForEvents
pFaxExtUnregisterForEvents [in] - Pointer to FaxExtUnregisterForEvents
pFaxExtFreeBuffer [in] - Pointer to FaxExtFreeBuffer
Return Value:
Standard HRESULT code
--*/
{
DEBUG_FUNCTION_NAME(TEXT("FaxExtInitializeConfig"));
Assert (pFaxExtGetData &&
pFaxExtSetData &&
pFaxExtRegisterForEvents &&
pFaxExtUnregisterForEvents &&
pFaxExtFreeBuffer);
g_pFaxExtGetData = pFaxExtGetData;
g_pFaxExtSetData = pFaxExtSetData;
g_pFaxExtRegisterForEvents = pFaxExtRegisterForEvents;
g_pFaxExtUnregisterForEvents = pFaxExtUnregisterForEvents;
g_pFaxExtFreeBuffer = pFaxExtFreeBuffer;
return S_OK;
} // FaxExtInitializeConfig
/************************************
* *
* CDeviceRoutingInfo implementation *
* *
************************************/
CDeviceRoutingInfo::CDeviceRoutingInfo (DWORD dwId) :
m_dwFlags (0),
m_dwId (dwId)
{
memset (m_NotificationHandles, 0, sizeof (m_NotificationHandles));
}
CDeviceRoutingInfo::~CDeviceRoutingInfo ()
{
UnregisterForChangeNotifications ();
}
BOOL
CDeviceRoutingInfo::GetStoreFolder (wstring &strFolder)
{
DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::GetStoreFolder"));
EnterCriticalSection(&g_csRoutingStrings);
try
{
strFolder = m_strStoreFolder;
}
catch(bad_alloc&)
{
LeaveCriticalSection(&g_csRoutingStrings);
DebugPrintEx(
DEBUG_ERR,
TEXT("GetStoreFolder failed - not enough memory."));
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
LeaveCriticalSection(&g_csRoutingStrings);
return TRUE;
}
BOOL
CDeviceRoutingInfo::GetPrinter (wstring &strPrinter)
{
DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::GetPrinter"));
EnterCriticalSection(&g_csRoutingStrings);
try
{
strPrinter = m_strPrinter;
}
catch(bad_alloc&)
{
LeaveCriticalSection(&g_csRoutingStrings);
DebugPrintEx(
DEBUG_ERR,
TEXT("GetPrinter failed - not enough memory."));
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
LeaveCriticalSection(&g_csRoutingStrings);
return TRUE;
}
BOOL
CDeviceRoutingInfo::GetSMTPTo (wstring &strSMTP)
{
DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::GetSMTPTo"));
EnterCriticalSection(&g_csRoutingStrings);
try
{
strSMTP = m_strSMTPTo;
}
catch(bad_alloc&)
{
LeaveCriticalSection(&g_csRoutingStrings);
DebugPrintEx(
DEBUG_ERR,
TEXT("GetSMTPTo failed - not enough memory."));
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
LeaveCriticalSection(&g_csRoutingStrings);
return TRUE;
}
DWORD
CDeviceRoutingInfo::EnableStore (BOOL bEnabled)
{
//
// See if we have a store folder configured
//
if (bEnabled)
{
EnterCriticalSection(&g_csRoutingStrings);
if (0 == m_strStoreFolder.size())
{
//
// Folder path name is ""
//
LeaveCriticalSection(&g_csRoutingStrings);
return ERROR_BAD_CONFIGURATION;
}
DWORD dwRes = IsValidFaxFolder (m_strStoreFolder.c_str());
LeaveCriticalSection(&g_csRoutingStrings);
if (ERROR_SUCCESS != dwRes)
{
return ERROR_BAD_CONFIGURATION;
}
}
return EnableFlag (LR_STORE, bEnabled);
} // CDeviceRoutingInfo::EnableStore
DWORD
CDeviceRoutingInfo::EnablePrint (BOOL bEnabled)
{
//
// See if we have a printer name configured
//
EnterCriticalSection(&g_csRoutingStrings);
if (bEnabled && m_strPrinter.size() == 0)
{
LeaveCriticalSection(&g_csRoutingStrings);
return ERROR_BAD_CONFIGURATION;
}
LeaveCriticalSection(&g_csRoutingStrings);
return EnableFlag (LR_PRINT, bEnabled);
}
DWORD
CDeviceRoutingInfo::EnableEmail (BOOL bEnabled)
{
if(bEnabled)
{
BOOL bMailConfigOK;
DWORD dwRes = CheckMailConfig (&bMailConfigOK);
if (ERROR_SUCCESS != dwRes)
{
return dwRes;
}
EnterCriticalSection(&g_csRoutingStrings);
if (!bMailConfigOK || m_strSMTPTo.size() == 0)
{
LeaveCriticalSection(&g_csRoutingStrings);
return ERROR_BAD_CONFIGURATION;
}
LeaveCriticalSection(&g_csRoutingStrings);
}
return EnableFlag (LR_EMAIL, bEnabled);
}
DWORD
CDeviceRoutingInfo::CheckMailConfig (
LPBOOL lpbConfigOk
)
{
DWORD dwRes = ERROR_SUCCESS;
PFAX_SERVER_RECEIPTS_CONFIGW pReceiptsConfiguration = NULL;
DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::CheckMailConfig"));
extern PGETRECIEPTSCONFIGURATION g_pGetRecieptsConfiguration;
extern PFREERECIEPTSCONFIGURATION g_pFreeRecieptsConfiguration;
*lpbConfigOk = FALSE;
//
// Read current receipts configuration
//
dwRes = g_pGetRecieptsConfiguration (&pReceiptsConfiguration, FALSE);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("GetRecieptsConfiguration failed with %ld"),
dwRes);
return dwRes;
}
//
// Check that the user enbaled us (MS route to mail method) to use the receipts configuration
//
if (!pReceiptsConfiguration->bIsToUseForMSRouteThroughEmailMethod)
{
//
// MS mail routing methods cannot use receipts SMTP settings
//
DebugPrintEx(
DEBUG_ERR,
TEXT("MS mail routing methods cannot use receipts SMTP settings"));
goto exit;
}
if (!lstrlen(pReceiptsConfiguration->lptstrSMTPServer))
{
//
// Server name is empty
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Server name is empty"));
goto exit;
}
if (!lstrlen(pReceiptsConfiguration->lptstrSMTPFrom))
{
//
// Sender name is empty
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Sender name is empty"));
goto exit;
}
if (!pReceiptsConfiguration->dwSMTPPort)
{
//
// SMTP port is invalid
//
DebugPrintEx(
DEBUG_ERR,
TEXT("SMTP port is invalid"));
goto exit;
}
if ((FAX_SMTP_AUTH_BASIC == pReceiptsConfiguration->SMTPAuthOption) ||
(FAX_SMTP_AUTH_NTLM == pReceiptsConfiguration->SMTPAuthOption))
{
//
// Basic / NTLM authentication selected
//
if (!lstrlen(pReceiptsConfiguration->lptstrSMTPUserName) ||
!lstrlen(pReceiptsConfiguration->lptstrSMTPPassword))
{
//
// Username / password are bad
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Username / password are bad"));
goto exit;
}
}
//
// All is ok
//
*lpbConfigOk = TRUE;
exit:
if (NULL != pReceiptsConfiguration)
{
g_pFreeRecieptsConfiguration( pReceiptsConfiguration, TRUE);
}
return dwRes;
} // CDeviceRoutingInfo::CheckMailConfig
DWORD
CDeviceRoutingInfo::RegisterForChangeNotifications ()
/*++
Routine name : CDeviceRoutingInfo::RegisterForChangeNotifications
Routine description:
Registres the device for notifications on configuration changes.
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
Return Value:
Standard Win23 error code.
--*/
{
DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::RegisterForChangeNotifications"));
Assert (g_pFaxExtRegisterForEvents);
memset (m_NotificationHandles, 0, sizeof (m_NotificationHandles));
for (int iCurHandle = 0; iCurHandle < NUM_NOTIFICATIONS; iCurHandle++)
{
m_NotificationHandles[iCurHandle] = g_pFaxExtRegisterForEvents (
g_hModule,
m_dwId,
DEV_ID_SRC_FAX, // Real fax device id
g_lpcwstrGUIDs[iCurHandle],
FaxRoutingExtConfigChange);
if (NULL == m_NotificationHandles[iCurHandle])
{
//
// Couldn't register this configuration object
//
break;
}
}
if (iCurHandle < NUM_NOTIFICATIONS)
{
//
// Error while registering at least one configuration object - undo previous registrations
//
DWORD dwErr = GetLastError ();
UnregisterForChangeNotifications();
return dwErr;
}
return ERROR_SUCCESS;
} // CDeviceRoutingInfo::RegisterForChangeNotifications
DWORD
CDeviceRoutingInfo::UnregisterForChangeNotifications ()
/*++
Routine name : CDeviceRoutingInfo::UnregisterForChangeNotifications
Routine description:
Unregistres the device from notifications on configuration changes.
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
Return Value:
Standard Win23 error code.
--*/
{
DWORD dwRes;
DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::UnregisterForChangeNotifications"));
Assert (g_pFaxExtUnregisterForEvents);
for (int iCurHandle = 0; iCurHandle < NUM_NOTIFICATIONS; iCurHandle++)
{
if (NULL != m_NotificationHandles[iCurHandle])
{
//
// Found registred notification - unregister it
//
dwRes = g_pFaxExtUnregisterForEvents(m_NotificationHandles[iCurHandle]);
if (ERROR_SUCCESS != dwRes)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Call to FaxExtUnregisterForEvents on handle 0x%08x failed with %ld"),
m_NotificationHandles[iCurHandle],
dwRes);
return dwRes;
}
m_NotificationHandles[iCurHandle] = NULL;
}
}
return ERROR_SUCCESS;
} // CDeviceRoutingInfo::UnregisterForChangeNotifications
DWORD
CDeviceRoutingInfo::ReadConfiguration ()
/*++
Routine name : CDeviceRoutingInfo::ReadConfiguration
Routine description:
Reasd the routing configuration from the storage.
If the storage doesn't contain configuration, default values are used.
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
Return Value:
Standard Win23 error code.
--*/
{
DWORD dwRes;
LPBYTE lpData = NULL;
DWORD dwDataSize;
DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::ReadConfiguration"));
//
// Start by reading the flags data
//
dwRes = g_pFaxExtGetData ( m_dwId,
DEV_ID_SRC_FAX, // We always use the Fax Device Id
REGVAL_RM_FLAGS_GUID,
&lpData,
&dwDataSize
);
if (ERROR_SUCCESS != dwRes)
{
if (ERROR_FILE_NOT_FOUND == dwRes)
{
//
// Data does not exist for this device. Try to read default values from unassociated data.
//
dwRes = g_pFaxExtGetData ( 0, // unassociated data
DEV_ID_SRC_FAX, // We always use the Fax Device Id
REGVAL_RM_FLAGS_GUID,
&lpData,
&dwDataSize
);
if (ERROR_FILE_NOT_FOUND == dwRes)
{
//
// Data does not exist for this device. Use default values.
//
DebugPrintEx(
DEBUG_MSG,
TEXT("No routing flags configuration - using defaults"));
m_dwFlags = DEFAULT_FLAGS;
}
}
if (ERROR_SUCCESS != dwRes &&
ERROR_FILE_NOT_FOUND != dwRes)
{
//
// Can't read configuration
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading routing flags (ec = %ld)"),
dwRes);
return dwRes;
}
}
if (NULL != lpData)
{
//
// Data read successfully
//
if (sizeof (DWORD) != dwDataSize)
{
//
// We're expecting a single DWORD here
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Routing flags configuration has bad size (%ld) - expecting %ld"),
dwDataSize,
sizeof (DWORD));
g_pFaxExtFreeBuffer (lpData);
return ERROR_BADDB; // The configuration registry database is corrupt.
}
m_dwFlags = DWORD (*lpData);
g_pFaxExtFreeBuffer (lpData);
}
try
{
lpData = NULL;
//
// Read store directory
//
dwRes = g_pFaxExtGetData ( m_dwId,
DEV_ID_SRC_FAX, // We always use the Fax Device Id
REGVAL_RM_FOLDER_GUID,
&lpData,
&dwDataSize
);
if (ERROR_SUCCESS != dwRes)
{
if (ERROR_FILE_NOT_FOUND == dwRes)
{
//
// Data does not exist for this device. Try to read default values from unassociated data.
//
dwRes = g_pFaxExtGetData ( 0, // unassociated data
DEV_ID_SRC_FAX, // We always use the Fax Device Id
REGVAL_RM_FOLDER_GUID,
&lpData,
&dwDataSize
);
if (ERROR_FILE_NOT_FOUND == dwRes)
{
//
// Data does not exist for this device. Use default values.
//
DebugPrintEx(
DEBUG_MSG,
TEXT("No routing store configuration - using defaults"));
dwRes = SetStringValue(m_strStoreFolder, NULL, DEFAULT_STORE_FOLDER);
if (dwRes != ERROR_SUCCESS)
{
return dwRes;
}
}
}
if (ERROR_SUCCESS != dwRes &&
ERROR_FILE_NOT_FOUND != dwRes)
{
//
// Can't read configuration
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading routing store configuration (ec = %ld)"),
dwRes);
return dwRes;
}
}
if (NULL != lpData)
{
//
// Data read successfully
// make sure we have terminating NULL (defends from registry curruption)
//
if (!IsUnicodeString(lpData, dwDataSize))
{
//
// No NULL terminator, return failure
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading routing store configuration, no NULL terminator.")
);
g_pFaxExtFreeBuffer (lpData);
return ERROR_BAD_CONFIGURATION;
}
dwRes = SetStringValue(m_strStoreFolder, NULL, LPCWSTR(lpData));
if (dwRes != ERROR_SUCCESS)
{
return dwRes;
}
g_pFaxExtFreeBuffer (lpData);
}
lpData = NULL;
//
// Read printer name
//
dwRes = g_pFaxExtGetData ( m_dwId,
DEV_ID_SRC_FAX, // We always use the Fax Device Id
REGVAL_RM_PRINTING_GUID,
&lpData,
&dwDataSize
);
if (ERROR_SUCCESS != dwRes)
{
if (ERROR_FILE_NOT_FOUND == dwRes)
{
//
// Data does not exist for this device. Try to read default values from unassociated data.
//
dwRes = g_pFaxExtGetData ( 0, // unassociated data
DEV_ID_SRC_FAX, // We always use the Fax Device Id
REGVAL_RM_PRINTING_GUID,
&lpData,
&dwDataSize
);
if (ERROR_FILE_NOT_FOUND == dwRes)
{
//
// Data does not exist for this device. Use default values.
//
DebugPrintEx(
DEBUG_MSG,
TEXT("No routing print configuration - using defaults"));
dwRes = SetStringValue(m_strPrinter, NULL, DEFAULT_PRINTER_NAME);
if (dwRes != ERROR_SUCCESS)
{
return dwRes;
}
}
}
if (ERROR_SUCCESS != dwRes &&
ERROR_FILE_NOT_FOUND != dwRes)
{
//
// Can't read configuration
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading routing print configuration (ec = %ld)"),
dwRes);
return dwRes;
}
}
if (NULL != lpData)
{
//
// Data read successfully
// make sure we have terminating NULL (defends from registry curruption)
//
if (!IsUnicodeString(lpData, dwDataSize))
{
//
// No NULL terminator, return failure
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading routing print configuration, no NULL terminator.")
);
g_pFaxExtFreeBuffer (lpData);
return ERROR_BAD_CONFIGURATION;
}
dwRes = SetStringValue(m_strPrinter, NULL, LPCWSTR (lpData));
if (dwRes != ERROR_SUCCESS)
{
return dwRes;
}
g_pFaxExtFreeBuffer (lpData);
}
lpData = NULL;
//
// Read email address
//
dwRes = g_pFaxExtGetData ( m_dwId,
DEV_ID_SRC_FAX, // We always use the Fax Device Id
REGVAL_RM_EMAIL_GUID,
&lpData,
&dwDataSize
);
if (ERROR_SUCCESS != dwRes)
{
if (ERROR_FILE_NOT_FOUND == dwRes)
{
//
// Data does not exist for this device. Try to read default values from unassociated data.
//
dwRes = g_pFaxExtGetData ( 0,
DEV_ID_SRC_FAX, // We always use the Fax Device Id
REGVAL_RM_EMAIL_GUID,
&lpData,
&dwDataSize
);
if (ERROR_FILE_NOT_FOUND == dwRes)
{
//
// Data does not exist for this device. Use default values.
//
DebugPrintEx(
DEBUG_MSG,
TEXT("No routing email configuration - using defaults"));
dwRes = SetStringValue(m_strSMTPTo, NULL, DEFAULT_MAIL_PROFILE);
if (dwRes != ERROR_SUCCESS)
{
return dwRes;
}
}
}
if (ERROR_SUCCESS != dwRes &&
ERROR_FILE_NOT_FOUND != dwRes)
{
//
// Can't read configuration
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading routing email configuration (ec = %ld)"),
dwRes);
return dwRes;
}
}
if (NULL != lpData)
{
//
// Data read successfully
// make sure we have terminating NULL (defends from registry curruption)
//
if (!IsUnicodeString(lpData, dwDataSize))
{
//
// No NULL terminator, return failure
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading routing email configuration, no NULL terminator.")
);
g_pFaxExtFreeBuffer (lpData);
return ERROR_BAD_CONFIGURATION;
}
dwRes = SetStringValue(m_strSMTPTo, NULL, LPCWSTR(lpData));
if (dwRes != ERROR_SUCCESS)
{
return dwRes;
}
g_pFaxExtFreeBuffer (lpData);
}
}
catch (exception ex)
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Got an STL exception (%S)"),
ex.what());
//
// prevent leak when exception is thrown
//
if ( lpData )
{
g_pFaxExtFreeBuffer (lpData);
}
return ERROR_GEN_FAILURE;
}
return ERROR_SUCCESS;
} // CDeviceRoutingInfo::ReadConfiguration
HRESULT
CDeviceRoutingInfo::ConfigChange (
LPCWSTR lpcwstrNameGUID, // Configuration name
LPBYTE lpData, // New configuration data
DWORD dwDataSize // Size of new configuration data
)
/*++
Routine name : CDeviceRoutingInfo::ConfigChange
Routine description:
Handles configuration changes (by notification)
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
lpcwstrNameGUID [in] - Configuration name
lpData [in] - New configuration data
dwDataSize [in] - Size of new configuration data
Return Value:
Standard HRESULT code
--*/
{
DWORD dwRes;
DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::ConfigChange"));
if (!_tcsicmp (lpcwstrNameGUID, REGVAL_RM_FLAGS_GUID))
{
//
// Flags have changed
//
if (sizeof (DWORD) != dwDataSize)
{
//
// We're expecting a single DWORD here
//
return HRESULT_FROM_WIN32(ERROR_BADDB); // The configuration registry database is corrupt.
}
m_dwFlags = DWORD (*lpData);
return NOERROR;
}
//
// This is one of our routing method's configuration which changed.
// Verify the new data is a Unicode string.
//
if (!IsUnicodeString(lpData, dwDataSize))
{
//
// No NULL terminator, set to empty string.
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Error reading routing method %s string configuration, no NULL terminator."),
lpcwstrNameGUID
);
lpData = (LPBYTE)TEXT("");
}
if (!_tcsicmp (lpcwstrNameGUID, REGVAL_RM_FOLDER_GUID))
{
//
// Store folder has changed
//
dwRes = SetStringValue(m_strStoreFolder, NULL, LPCWSTR(lpData));
return HRESULT_FROM_WIN32(dwRes);
}
if (!_tcsicmp (lpcwstrNameGUID, REGVAL_RM_PRINTING_GUID))
{
//
// Printer name has changed
//
dwRes = SetStringValue(m_strPrinter, NULL, LPCWSTR(lpData));
return HRESULT_FROM_WIN32(dwRes);
}
if (!_tcsicmp (lpcwstrNameGUID, REGVAL_RM_EMAIL_GUID))
{
//
// Email address has changed
//
dwRes = SetStringValue(m_strSMTPTo, NULL, LPCWSTR(lpData));
return HRESULT_FROM_WIN32(dwRes);
}
DebugPrintEx(
DEBUG_ERR,
TEXT("Device %ld got configuration change notification for unknown GUID (%s)"),
m_dwId,
lpcwstrNameGUID);
ASSERT_FALSE
return HRESULT_FROM_WIN32(ERROR_GEN_FAILURE);
} // CDeviceRoutingInfo::ConfigChange
DWORD
CDeviceRoutingInfo::EnableFlag (
DWORD dwFlag,
BOOL bEnable
)
/*++
Routine name : CDeviceRoutingInfo::EnableFlag
Routine description:
Sets a new value to the routing methods flags
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
dwFlag [in] - Flag id
bEnable [in] - Is flag enabled?
Return Value:
Standard Win32 error code.
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DWORD dwValue = m_dwFlags;
DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::EnableFlag"));
Assert ((LR_STORE == dwFlag) ||
(LR_PRINT == dwFlag) ||
(LR_EMAIL == dwFlag));
if (bEnable == ((dwValue & dwFlag) ? TRUE : FALSE))
{
//
// No change
//
return ERROR_SUCCESS;
}
//
// Change temporary flag value
//
if (bEnable)
{
dwValue |= dwFlag;
}
else
{
dwValue &= ~dwFlag;
}
//
// Store new value in the extension data storage
//
dwRes = g_pFaxExtSetData (g_hModule,
m_dwId,
DEV_ID_SRC_FAX, // We always use the Fax Device Id
REGVAL_RM_FLAGS_GUID,
(LPBYTE)&dwValue,
sizeof (DWORD)
);
if (ERROR_SUCCESS == dwRes)
{
//
// Registry store successful - Update flags value in memory with new value.
//
m_dwFlags = dwValue;
} return dwRes;
} // CDeviceRoutingInfo::EnableFlag
DWORD
CDeviceRoutingInfo::SetStringValue (
wstring &wstr,
LPCWSTR lpcwstrGUID,
LPCWSTR lpcwstrCfg
)
/*++
Routine name : CDeviceRoutingInfo::SetStringValue
Routine description:
Updates a configuration for a device
Author:
Eran Yariv (EranY), Dec, 1999
Arguments:
wstr [in] - Refrence to internal string configuration
lpcwstrGUID [in] - GUID of routing method we configure (for storage purposes)
If this parameter is NULL, only the memory reference of the member is updated but not the persistance one
lpcwstrCfg [in] - New string configuration
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DEBUG_FUNCTION_NAME(TEXT("CDeviceRoutingInfo::SetStringValue"));
//
// Persist the data
//
if (lpcwstrGUID != NULL)
{
dwRes = g_pFaxExtSetData (g_hModule,
m_dwId,
DEV_ID_SRC_FAX, // We always use the Fax Device Id
lpcwstrGUID,
(LPBYTE)lpcwstrCfg,
StringSize (lpcwstrCfg)
);
}
//
// Store the data in memory
//
EnterCriticalSection(&g_csRoutingStrings);
try
{
wstr = lpcwstrCfg;
}
catch (exception ex)
{
LeaveCriticalSection(&g_csRoutingStrings);
DebugPrintEx(
DEBUG_ERR,
TEXT("Got an STL exception while setting a configuration string (%S)"),
ex.what());
return ERROR_NOT_ENOUGH_MEMORY;
}
LeaveCriticalSection(&g_csRoutingStrings);
return dwRes;
} // CDeviceRoutingInfo::SetStringValue
/************************************
* *
* Implementation *
* *
************************************/
BOOL WINAPI
FaxRouteSetRoutingInfo(
IN LPCWSTR lpcwstrRoutingGuid,
IN DWORD dwDeviceId,
IN const BYTE *lpbRoutingInfo,
IN DWORD dwRoutingInfoSize
)
/*++
Routine name : FaxRouteSetRoutingInfo
Routine description:
The FaxRouteSetRoutingInfo function modifies routing configuration data
for a specific fax device.
Each fax routing extension DLL must export the FaxRouteSetRoutingInfo function
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
lpcwstrRoutingGuid [in] - Pointer to the GUID for the routing method
dwDeviceId [in] - Identifier of the fax device to modify
lpbRoutingInfo [in] - Pointer to the buffer that provides configuration data
dwRoutingInfoSize [in] - Size, in bytes, of the buffer
Return Value:
If the function succeeds, the return value is a nonzero value.
If the function fails, the return value is zero.
To get extended error information, the fax service calls GetLastError().
--*/
{
DWORD dwRes;
CDeviceRoutingInfo *pDevInfo;
BOOL bMethodEnabled;
LPCWSTR lpcwstrMethodConfig = LPCWSTR(&lpbRoutingInfo[sizeof (DWORD)]);
DEBUG_FUNCTION_NAME(TEXT("FaxRouteSetRoutingInfo"));
if (dwRoutingInfoSize < sizeof (DWORD))
{
DebugPrintEx(
DEBUG_ERR,
TEXT("Data size is too small (%ld)"),
dwRoutingInfoSize);
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
}
pDevInfo = g_DevicesMap.GetDeviceRoutingInfo(dwDeviceId);
if (NULL == pDevInfo)
{
return FALSE;
}
//
// First DWORD tells if method is enabled
//
bMethodEnabled = *((LPDWORD)(lpbRoutingInfo)) ? TRUE : FALSE;
switch( GetMaskBit( lpcwstrRoutingGuid ))
{
case LR_PRINT:
if (bMethodEnabled)
{
//
// Only if the method is enabled, we update the new configuration
//
dwRes = pDevInfo->SetPrinter ( lpcwstrMethodConfig );
if (ERROR_SUCCESS != dwRes)
{
SetLastError (dwRes);
return FALSE;
}
}
dwRes = pDevInfo->EnablePrint (bMethodEnabled);
if (ERROR_SUCCESS != dwRes)
{
SetLastError (dwRes);
return FALSE;
}
break;
case LR_STORE:
if (bMethodEnabled)
{
//
// Only if the method is enabled, we update the new configuration
//
dwRes = pDevInfo->SetStoreFolder ( lpcwstrMethodConfig );
if (ERROR_SUCCESS != dwRes)
{
SetLastError (dwRes);
return FALSE;
}
}
dwRes = pDevInfo->EnableStore (bMethodEnabled);
if (ERROR_SUCCESS != dwRes)
{
SetLastError (dwRes);
return FALSE;
}
break;
case LR_EMAIL:
if (bMethodEnabled)
{
//
// Only if the method is enabled, we update the new configuration
//
dwRes = pDevInfo->SetSMTPTo ( lpcwstrMethodConfig );
if (ERROR_SUCCESS != dwRes)
{
SetLastError (dwRes);
return FALSE;
}
}
dwRes = pDevInfo->EnableEmail (bMethodEnabled);
if (ERROR_SUCCESS != dwRes)
{
SetLastError (dwRes);
return FALSE;
}
break;
default:
//
// Unknown GUID requested
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Unknown routing method GUID (%s)"),
lpcwstrRoutingGuid);
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
}
return TRUE;
} // FaxRouteSetRoutingInfo
BOOL WINAPI
FaxRouteGetRoutingInfo(
IN LPCWSTR lpcwstrRoutingGuid,
IN DWORD dwDeviceId,
IN LPBYTE lpbRoutingInfo,
OUT LPDWORD lpdwRoutingInfoSize
)
/*++
Routine name : FaxRouteGetRoutingInfo
Routine description:
The FaxRouteGetRoutingInfo function queries the fax routing extension
DLL to obtain routing configuration data for a specific fax device.
Each fax routing extension DLL must export the FaxRouteGetRoutingInfo function
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
lpcwstrRoutingGuid [in ] - Pointer to the GUID for the routing method
dwDeviceId [in ] - Specifies the identifier of the fax device to query.
lpbRoutingInfo [in ] - Pointer to a buffer that receives the fax routing configuration data.
lpdwRoutingInfoSize [out] - Pointer to an unsigned DWORD variable that specifies the size,
in bytes, of the buffer pointed to by the lpbRoutingInfo parameter.
Return Value:
If the function succeeds, the return value is a nonzero value.
If the function fails, the return value is zero.
To get extended error information, the fax service calls GetLastError().
--*/
{
wstring strConfigString;
DWORD dwDataSize = sizeof (DWORD);
CDeviceRoutingInfo *pDevInfo;
BOOL bMethodEnabled;
DEBUG_FUNCTION_NAME(TEXT("FaxRouteGetRoutingInfo"));
pDevInfo = g_DevicesMap.GetDeviceRoutingInfo(dwDeviceId);
if (NULL == pDevInfo)
{
return FALSE;
}
switch( GetMaskBit( lpcwstrRoutingGuid ))
{
case LR_PRINT:
if (!pDevInfo->GetPrinter(strConfigString))
{
return FALSE;
}
bMethodEnabled = pDevInfo->IsPrintEnabled();
break;
case LR_STORE:
if (!pDevInfo->GetStoreFolder(strConfigString))
{
return FALSE;
}
bMethodEnabled = pDevInfo->IsStoreEnabled();
break;
case LR_EMAIL:
if (!pDevInfo->GetSMTPTo(strConfigString))
{
return FALSE;
}
bMethodEnabled = pDevInfo->IsEmailEnabled ();
break;
default:
//
// Unknown GUID requested
//
DebugPrintEx(
DEBUG_ERR,
TEXT("Unknown routing method GUID (%s)"),
lpcwstrRoutingGuid);
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
}
dwDataSize += ((strConfigString.length() + 1) * sizeof(WCHAR));
if (NULL == lpbRoutingInfo)
{
//
// Caller just wants to know the data size
//
*lpdwRoutingInfoSize = dwDataSize;
return TRUE;
}
if (dwDataSize > *lpdwRoutingInfoSize)
{
//
// Caller supplied too small a buffer
//
*lpdwRoutingInfoSize = dwDataSize;
SetLastError (ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
//
// First DWORD tells if this method is enabled or not
//
*((LPDWORD)lpbRoutingInfo) = bMethodEnabled;
//
// Skip to string area
//
lpbRoutingInfo += sizeof(DWORD);
//
// Copy string
//
wcscpy( (LPWSTR)lpbRoutingInfo, strConfigString.c_str());
//
// Set actual size used
//
*lpdwRoutingInfoSize = dwDataSize;
return TRUE;
} // FaxRouteGetRoutingInfo
HRESULT
FaxRoutingExtConfigChange (
DWORD dwDeviceId, // The device for which configuration has changed
LPCWSTR lpcwstrNameGUID, // Configuration name
LPBYTE lpData, // New configuration data
DWORD dwDataSize // Size of new configuration data
)
/*++
Routine name : FaxRoutingExtConfigChange
Routine description:
Handles configuration change notifications
Author:
Eran Yariv (EranY), Nov, 1999
Arguments:
dwDeviceId [in] - The device for which configuration has changed
lpcwstrNameGUID [in] - Configuration name
lpData [in] - New configuration data
data [in] - Size of new configuration data
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr;
DEBUG_FUNCTION_NAME(TEXT("FaxRoutingExtConfigChange"));
CDeviceRoutingInfo *pDevice = g_DevicesMap.FindDeviceRoutingInfo (dwDeviceId);
if (!pDevice)
{
//
// Device not found in map - can't be
//
hr = HRESULT_FROM_WIN32(GetLastError ());
DebugPrintEx(
DEBUG_ERR,
TEXT("Got a notification but cant find device %ld (hr = 0x%08x) !!!!"),
dwDeviceId,
hr);
ASSERT_FALSE;
return hr;
}
return pDevice->ConfigChange (lpcwstrNameGUID, lpData, dwDataSize);
} // FaxRoutingExtConfigChange