1942 lines
62 KiB
C
1942 lines
62 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1996 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
route.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module implements the inbound routing rules.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Wesley Witt (wesw) 1-Apr-1997
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "faxsvc.h"
|
||
|
#include "tiff.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "..\faxroute\FaxRouteP.h"
|
||
|
|
||
|
|
||
|
extern DWORD FaxPrinters;
|
||
|
|
||
|
LIST_ENTRY g_lstRoutingExtensions;
|
||
|
LIST_ENTRY g_lstRoutingMethods;
|
||
|
DWORD g_dwCountRoutingMethods;
|
||
|
CFaxCriticalSection g_CsRouting;
|
||
|
|
||
|
LONG WINAPI
|
||
|
FaxRouteAddFile(
|
||
|
IN DWORD JobId,
|
||
|
IN LPCWSTR FileName,
|
||
|
IN GUID *Guid
|
||
|
)
|
||
|
{
|
||
|
PJOB_QUEUE JobQueueEntry;
|
||
|
PFAX_ROUTE_FILE FaxRouteFile;
|
||
|
WCHAR FullPathName[MAX_PATH];
|
||
|
LPWSTR fnp;
|
||
|
DWORD Count;
|
||
|
WCHAR RouteGuid[MAX_GUID_STRING_LEN];
|
||
|
|
||
|
StringFromGUID2( *Guid, RouteGuid, MAX_GUID_STRING_LEN );
|
||
|
|
||
|
if (!JobId || !Guid || !FileName) {
|
||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
JobQueueEntry = FindJobQueueEntry( JobId );
|
||
|
if (!JobQueueEntry) {
|
||
|
SetLastError( ERROR_INVALID_DATA );
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if ((!IsEqualGUID(*Guid,gc_FaxSvcGuid)) && (!FindRoutingMethodByGuid(RouteGuid))) {
|
||
|
SetLastError( ERROR_INVALID_DATA );
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (!GetFullPathName( FileName, sizeof(FullPathName)/sizeof(WCHAR), FullPathName, &fnp )) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
FaxRouteFile = (PFAX_ROUTE_FILE) MemAlloc( sizeof(FAX_ROUTE_FILE) );
|
||
|
if (!FaxRouteFile) {
|
||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
FaxRouteFile->FileName = StringDup( FullPathName );
|
||
|
|
||
|
CopyMemory( &FaxRouteFile->Guid, Guid, sizeof(GUID) );
|
||
|
|
||
|
EnterCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
|
||
|
InsertTailList( &JobQueueEntry->FaxRouteFiles, &FaxRouteFile->ListEntry );
|
||
|
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
|
||
|
//
|
||
|
// increment file count
|
||
|
//
|
||
|
EnterCriticalSection( &g_CsJob );
|
||
|
EnterCriticalSection( &g_CsQueue );
|
||
|
JobQueueEntry->CountFaxRouteFiles += 1;
|
||
|
Count = JobQueueEntry->CountFaxRouteFiles;
|
||
|
LeaveCriticalSection( &g_CsQueue );
|
||
|
LeaveCriticalSection( &g_CsJob );
|
||
|
|
||
|
|
||
|
|
||
|
return Count;
|
||
|
}
|
||
|
|
||
|
|
||
|
LONG WINAPI
|
||
|
FaxRouteDeleteFile(
|
||
|
IN DWORD JobId,
|
||
|
IN LPCWSTR FileName
|
||
|
)
|
||
|
{
|
||
|
PJOB_QUEUE JobQueueEntry;
|
||
|
PFAX_ROUTE_FILE FaxRouteFile;
|
||
|
PLIST_ENTRY Next;
|
||
|
LONG Index = 1;
|
||
|
|
||
|
if (!FileName) {
|
||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
JobQueueEntry = FindJobQueueEntry( JobId );
|
||
|
if (!JobQueueEntry) {
|
||
|
SetLastError( ERROR_INVALID_DATA );
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
Next = JobQueueEntry->FaxRouteFiles.Flink;
|
||
|
if (Next == &JobQueueEntry->FaxRouteFiles) {
|
||
|
SetLastError( ERROR_NO_MORE_FILES );
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
EnterCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
|
||
|
while ((ULONG_PTR)Next != (ULONG_PTR)&JobQueueEntry->FaxRouteFiles) {
|
||
|
FaxRouteFile = CONTAINING_RECORD( Next, FAX_ROUTE_FILE, ListEntry );
|
||
|
Next = FaxRouteFile->ListEntry.Flink;
|
||
|
if (_wcsicmp( FileName, FaxRouteFile->FileName ) == 0) {
|
||
|
//
|
||
|
// the initial file is read-only for all extensions
|
||
|
//
|
||
|
if (Index == 1) {
|
||
|
SetLastError( ERROR_INVALID_DATA );
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// remove from list, delete the file, cleanup memory
|
||
|
//
|
||
|
RemoveEntryList( &FaxRouteFile->ListEntry );
|
||
|
DeleteFile( FaxRouteFile->FileName );
|
||
|
MemFree ( FaxRouteFile->FileName ) ;
|
||
|
MemFree ( FaxRouteFile );
|
||
|
|
||
|
//
|
||
|
// decrement file count
|
||
|
//
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
EnterCriticalSection( &g_CsJob );
|
||
|
EnterCriticalSection( &g_CsQueue );
|
||
|
JobQueueEntry->CountFaxRouteFiles -= 1;
|
||
|
LeaveCriticalSection( &g_CsQueue );
|
||
|
LeaveCriticalSection( &g_CsJob );
|
||
|
|
||
|
return Index;
|
||
|
}
|
||
|
Index += 1;
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
SetLastError( ERROR_FILE_NOT_FOUND );
|
||
|
return -1;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL WINAPI
|
||
|
FaxRouteGetFile(
|
||
|
IN DWORD JobId,
|
||
|
IN DWORD FileNumber,
|
||
|
OUT LPWSTR FileNameBuffer,
|
||
|
OUT LPDWORD RequiredSize
|
||
|
)
|
||
|
{
|
||
|
PJOB_QUEUE JobQueueEntry;
|
||
|
PFAX_ROUTE_FILE FaxRouteFile;
|
||
|
PLIST_ENTRY Next;
|
||
|
ULONG Index = 1;
|
||
|
|
||
|
if (RequiredSize == NULL) {
|
||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
JobQueueEntry = FindJobQueueEntry( JobId );
|
||
|
if (!JobQueueEntry) {
|
||
|
SetLastError( ERROR_INVALID_DATA );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (JobQueueEntry->CountFaxRouteFiles < Index) {
|
||
|
SetLastError( ERROR_INVALID_DATA );
|
||
|
}
|
||
|
|
||
|
Next = JobQueueEntry->FaxRouteFiles.Flink;
|
||
|
//
|
||
|
// make sure list isn't empty
|
||
|
//
|
||
|
if (Next == &JobQueueEntry->FaxRouteFiles) {
|
||
|
SetLastError( ERROR_NO_MORE_FILES );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
EnterCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
|
||
|
while ((ULONG_PTR)Next != (ULONG_PTR)&JobQueueEntry->FaxRouteFiles) {
|
||
|
FaxRouteFile = CONTAINING_RECORD( Next, FAX_ROUTE_FILE, ListEntry );
|
||
|
Next = FaxRouteFile->ListEntry.Flink;
|
||
|
if (Index == FileNumber) {
|
||
|
if (*RequiredSize < (wcslen(FaxRouteFile->FileName)+1)*sizeof(WCHAR)) {
|
||
|
if (FileNameBuffer == NULL) {
|
||
|
*RequiredSize = (wcslen(FaxRouteFile->FileName) + 1)*sizeof(WCHAR);
|
||
|
}
|
||
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
return FALSE;
|
||
|
} else if (FileNameBuffer) {
|
||
|
wcscpy( FileNameBuffer, FaxRouteFile->FileName );
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
return TRUE;
|
||
|
} else {
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
Index += 1;
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
SetLastError( ERROR_NO_MORE_FILES );
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL WINAPI
|
||
|
FaxRouteEnumFiles(
|
||
|
IN DWORD JobId,
|
||
|
IN GUID *Guid,
|
||
|
IN PFAXROUTEENUMFILE FileEnumerator,
|
||
|
IN PVOID Context
|
||
|
)
|
||
|
{
|
||
|
PJOB_QUEUE JobQueueEntry;
|
||
|
PFAX_ROUTE_FILE FaxRouteFile;
|
||
|
PLIST_ENTRY Next;
|
||
|
|
||
|
if (!FileEnumerator) {
|
||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
JobQueueEntry = FindJobQueueEntry( JobId );
|
||
|
if (!JobQueueEntry) {
|
||
|
SetLastError( ERROR_INVALID_DATA );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Next = JobQueueEntry->FaxRouteFiles.Flink;
|
||
|
if (Next == &JobQueueEntry->FaxRouteFiles) {
|
||
|
SetLastError( ERROR_NO_MORE_FILES );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
EnterCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
|
||
|
while ((ULONG_PTR)Next != (ULONG_PTR)&JobQueueEntry->FaxRouteFiles) {
|
||
|
FaxRouteFile = CONTAINING_RECORD( Next, FAX_ROUTE_FILE, ListEntry );
|
||
|
Next = FaxRouteFile->ListEntry.Flink;
|
||
|
if (!FileEnumerator( JobId, &FaxRouteFile->Guid, Guid, FaxRouteFile->FileName, Context )) {
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsFileList );
|
||
|
|
||
|
SetLastError( ERROR_NO_MORE_FILES );
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
PROUTING_METHOD
|
||
|
FindRoutingMethodByGuid(
|
||
|
IN LPCWSTR RoutingGuidString
|
||
|
)
|
||
|
{
|
||
|
PLIST_ENTRY pNextMethod;
|
||
|
PROUTING_METHOD pRoutingMethod;
|
||
|
GUID RoutingGuid;
|
||
|
|
||
|
|
||
|
IIDFromString( (LPWSTR)RoutingGuidString, &RoutingGuid );
|
||
|
|
||
|
EnterCriticalSection( &g_CsRouting );
|
||
|
|
||
|
pNextMethod = g_lstRoutingMethods.Flink;
|
||
|
if (pNextMethod == NULL)
|
||
|
{
|
||
|
LeaveCriticalSection( &g_CsRouting );
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
while ((ULONG_PTR)pNextMethod != (ULONG_PTR)&g_lstRoutingMethods) {
|
||
|
pRoutingMethod = CONTAINING_RECORD( pNextMethod, ROUTING_METHOD, ListEntryMethod );
|
||
|
pNextMethod = pRoutingMethod->ListEntryMethod.Flink;
|
||
|
if (IsEqualGUID( RoutingGuid, pRoutingMethod->Guid ))
|
||
|
{
|
||
|
LeaveCriticalSection( &g_CsRouting );
|
||
|
return pRoutingMethod;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection( &g_CsRouting );
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
EnumerateRoutingMethods(
|
||
|
IN PFAXROUTEMETHODENUM Enumerator,
|
||
|
IN LPVOID Context
|
||
|
)
|
||
|
{
|
||
|
PLIST_ENTRY pNextMethod;
|
||
|
PROUTING_METHOD pRoutingMethod;
|
||
|
DWORD dwCount = 0;
|
||
|
|
||
|
EnterCriticalSection( &g_CsRouting );
|
||
|
|
||
|
pNextMethod = g_lstRoutingMethods.Flink;
|
||
|
Assert(pNextMethod != NULL);
|
||
|
|
||
|
while ((ULONG_PTR)pNextMethod != (ULONG_PTR)&g_lstRoutingMethods)
|
||
|
{
|
||
|
pRoutingMethod = CONTAINING_RECORD( pNextMethod, ROUTING_METHOD, ListEntryMethod );
|
||
|
pNextMethod = pRoutingMethod->ListEntryMethod.Flink;
|
||
|
if (!Enumerator( pRoutingMethod, Context ))
|
||
|
{
|
||
|
LeaveCriticalSection( &g_CsRouting );
|
||
|
SetLastError(ERROR_INVALID_FUNCTION);
|
||
|
return dwCount;
|
||
|
}
|
||
|
dwCount += 1;
|
||
|
}
|
||
|
LeaveCriticalSection(&g_CsRouting);
|
||
|
SetLastError(ERROR_SUCCESS);
|
||
|
return dwCount;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
FaxRouteModifyRoutingData(
|
||
|
DWORD JobId,
|
||
|
LPCWSTR RoutingGuid,
|
||
|
LPBYTE RoutingData,
|
||
|
DWORD RoutingDataSize
|
||
|
)
|
||
|
{
|
||
|
PJOB_QUEUE JobQueueEntry = NULL;
|
||
|
PROUTING_METHOD RoutingMethod = NULL;
|
||
|
PROUTING_DATA_OVERRIDE RoutingDataOverride = NULL;
|
||
|
|
||
|
|
||
|
if (JobId == 0 || RoutingGuid == NULL || RoutingData == NULL || RoutingDataSize == 0) {
|
||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
JobQueueEntry = FindJobQueueEntry( JobId );
|
||
|
if (!JobQueueEntry) {
|
||
|
SetLastError( ERROR_INVALID_DATA );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
RoutingMethod = FindRoutingMethodByGuid( RoutingGuid );
|
||
|
if (RoutingMethod == NULL) {
|
||
|
SetLastError( ERROR_INVALID_DATA );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
RoutingDataOverride = (PROUTING_DATA_OVERRIDE) MemAlloc( sizeof(ROUTING_DATA_OVERRIDE) );
|
||
|
if (RoutingDataOverride == NULL) {
|
||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
RoutingDataOverride->RoutingData = (LPBYTE)MemAlloc( RoutingDataSize );
|
||
|
if (RoutingDataOverride->RoutingData == NULL) {
|
||
|
MemFree( RoutingDataOverride );
|
||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
RoutingDataOverride->RoutingDataSize = RoutingDataSize;
|
||
|
RoutingDataOverride->RoutingMethod = RoutingMethod;
|
||
|
|
||
|
CopyMemory( RoutingDataOverride->RoutingData, RoutingData, RoutingDataSize );
|
||
|
|
||
|
EnterCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
|
||
|
InsertTailList( &JobQueueEntry->RoutingDataOverride, &RoutingDataOverride->ListEntry );
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
__cdecl
|
||
|
MethodPriorityCompare(
|
||
|
const void *arg1,
|
||
|
const void *arg2
|
||
|
)
|
||
|
{
|
||
|
if (((PMETHOD_SORT)arg1)->Priority < ((PMETHOD_SORT)arg2)->Priority) {
|
||
|
return -1;
|
||
|
}
|
||
|
if (((PMETHOD_SORT)arg1)->Priority > ((PMETHOD_SORT)arg2)->Priority) {
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
SortMethodPriorities(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
PLIST_ENTRY pNext;
|
||
|
PROUTING_METHOD pRoutingMethod;
|
||
|
PMETHOD_SORT pMethodSort;
|
||
|
DWORD i;
|
||
|
|
||
|
EnterCriticalSection( &g_CsRouting );
|
||
|
|
||
|
pNext = g_lstRoutingMethods.Flink;
|
||
|
if (pNext == NULL)
|
||
|
{
|
||
|
LeaveCriticalSection( &g_CsRouting );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pMethodSort = (PMETHOD_SORT) MemAlloc( g_dwCountRoutingMethods * sizeof(METHOD_SORT) );
|
||
|
if (pMethodSort == NULL)
|
||
|
{
|
||
|
LeaveCriticalSection( &g_CsRouting );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
i = 0;
|
||
|
|
||
|
while ((ULONG_PTR)pNext != (ULONG_PTR)&g_lstRoutingMethods)
|
||
|
{
|
||
|
pRoutingMethod = CONTAINING_RECORD( pNext, ROUTING_METHOD, ListEntryMethod );
|
||
|
pNext = pRoutingMethod->ListEntryMethod.Flink;
|
||
|
pMethodSort[i].Priority = pRoutingMethod->Priority;
|
||
|
pMethodSort[i].RoutingMethod = pRoutingMethod;
|
||
|
i += 1;
|
||
|
}
|
||
|
|
||
|
qsort(
|
||
|
(PVOID)pMethodSort,
|
||
|
(int)g_dwCountRoutingMethods,
|
||
|
sizeof(METHOD_SORT),
|
||
|
MethodPriorityCompare
|
||
|
);
|
||
|
|
||
|
InitializeListHead( &g_lstRoutingMethods );
|
||
|
|
||
|
for (i=0; i<g_dwCountRoutingMethods; i++)
|
||
|
{
|
||
|
pMethodSort[i].RoutingMethod->Priority = i + 1;
|
||
|
pMethodSort[i].RoutingMethod->ListEntryMethod.Flink = NULL;
|
||
|
pMethodSort[i].RoutingMethod->ListEntryMethod.Blink = NULL;
|
||
|
InsertTailList( &g_lstRoutingMethods, &pMethodSort[i].RoutingMethod->ListEntryMethod );
|
||
|
}
|
||
|
|
||
|
MemFree( pMethodSort );
|
||
|
|
||
|
LeaveCriticalSection( &g_CsRouting );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
CommitMethodChanges(
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
sticks changes to routing into the registry
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
NONE
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE for success
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PLIST_ENTRY pNext;
|
||
|
PROUTING_METHOD pRoutingMethod;
|
||
|
TCHAR StrGuid[100];
|
||
|
|
||
|
EnterCriticalSection(&g_CsRouting);
|
||
|
|
||
|
pNext = g_lstRoutingMethods.Flink;
|
||
|
|
||
|
while ((UINT_PTR)pNext != (UINT_PTR)&g_lstRoutingMethods)
|
||
|
{
|
||
|
pRoutingMethod = CONTAINING_RECORD( pNext, ROUTING_METHOD , ListEntryMethod );
|
||
|
pNext = pRoutingMethod->ListEntryMethod.Flink;
|
||
|
|
||
|
StringFromGUID2( pRoutingMethod->Guid,
|
||
|
StrGuid,
|
||
|
sizeof(StrGuid)/sizeof(TCHAR)
|
||
|
);
|
||
|
|
||
|
SetFaxRoutingInfo( pRoutingMethod->RoutingExtension->InternalName,
|
||
|
pRoutingMethod->InternalName,
|
||
|
StrGuid,
|
||
|
pRoutingMethod->Priority,
|
||
|
pRoutingMethod->FunctionName,
|
||
|
pRoutingMethod->FriendlyName
|
||
|
);
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection(&g_CsRouting);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FreeRoutingMethod(
|
||
|
PROUTING_METHOD pRoutingMethod
|
||
|
)
|
||
|
{
|
||
|
Assert (pRoutingMethod);
|
||
|
|
||
|
MemFree(pRoutingMethod->FriendlyName);
|
||
|
MemFree(pRoutingMethod->FunctionName);
|
||
|
MemFree(pRoutingMethod->InternalName);
|
||
|
MemFree(pRoutingMethod);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FreeRoutingExtension(
|
||
|
PROUTING_EXTENSION pRoutingExtension
|
||
|
)
|
||
|
{
|
||
|
DEBUG_FUNCTION_NAME(TEXT("FreeRoutingExtension"));
|
||
|
|
||
|
Assert (pRoutingExtension);
|
||
|
|
||
|
if (pRoutingExtension->hModule)
|
||
|
{
|
||
|
FreeLibrary (pRoutingExtension->hModule);
|
||
|
}
|
||
|
|
||
|
if (pRoutingExtension->HeapHandle &&
|
||
|
FALSE == pRoutingExtension->MicrosoftExtension)
|
||
|
{
|
||
|
HeapDestroy(pRoutingExtension->HeapHandle);
|
||
|
}
|
||
|
|
||
|
MemFree(pRoutingExtension);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
FreeRoutingExtensions(
|
||
|
void
|
||
|
)
|
||
|
{
|
||
|
PLIST_ENTRY pNext;
|
||
|
PROUTING_EXTENSION pRoutingExtension;
|
||
|
PROUTING_METHOD pRoutingMethod;
|
||
|
|
||
|
//
|
||
|
// Free routing methods
|
||
|
//
|
||
|
pNext = g_lstRoutingMethods.Flink;
|
||
|
while ((ULONG_PTR)pNext != (ULONG_PTR)&g_lstRoutingMethods)
|
||
|
{
|
||
|
pRoutingMethod = CONTAINING_RECORD( pNext, ROUTING_METHOD, ListEntryMethod );
|
||
|
pNext = pRoutingMethod->ListEntryMethod.Flink;
|
||
|
RemoveEntryList(&pRoutingMethod->ListEntryMethod);
|
||
|
FreeRoutingMethod(pRoutingMethod);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Free routing extensions
|
||
|
//
|
||
|
pNext = g_lstRoutingExtensions.Flink;
|
||
|
while ((ULONG_PTR)pNext != (ULONG_PTR)&g_lstRoutingExtensions)
|
||
|
{
|
||
|
pRoutingExtension = CONTAINING_RECORD( pNext, ROUTING_EXTENSION, ListEntry );
|
||
|
pNext = pRoutingExtension->ListEntry.Flink;
|
||
|
RemoveEntryList(&pRoutingExtension->ListEntry);
|
||
|
FreeRoutingExtension(pRoutingExtension);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
InitializeRouting(
|
||
|
PREG_FAX_SERVICE pFaxReg
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Initializes routing
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
NONE
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NONE
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD i,j;
|
||
|
DWORD dwRes;
|
||
|
BOOL bRes;
|
||
|
PROUTING_EXTENSION pRoutingExtension;
|
||
|
PROUTING_METHOD pRoutingMethod;
|
||
|
FAX_ROUTE_CALLBACKROUTINES Callbacks;
|
||
|
FAX_ROUTE_CALLBACKROUTINES_P Callbacks_private;
|
||
|
HRESULT hr = NOERROR;
|
||
|
PLIST_ENTRY ple;
|
||
|
DEBUG_FUNCTION_NAME(TEXT("InitializeRouting"));
|
||
|
|
||
|
Assert (wcslen (g_wszFaxQueueDir));
|
||
|
|
||
|
Callbacks.SizeOfStruct = sizeof(FAX_ROUTE_CALLBACKROUTINES);
|
||
|
Callbacks.FaxRouteAddFile = FaxRouteAddFile;
|
||
|
Callbacks.FaxRouteDeleteFile = FaxRouteDeleteFile;
|
||
|
Callbacks.FaxRouteGetFile = FaxRouteGetFile;
|
||
|
Callbacks.FaxRouteEnumFiles = FaxRouteEnumFiles;
|
||
|
Callbacks.FaxRouteModifyRoutingData = FaxRouteModifyRoutingData;
|
||
|
|
||
|
Callbacks_private.SizeOfStruct = sizeof(FAX_ROUTE_CALLBACKROUTINES_P);
|
||
|
Callbacks_private.FaxRouteAddFile = FaxRouteAddFile;
|
||
|
Callbacks_private.FaxRouteDeleteFile = FaxRouteDeleteFile;
|
||
|
Callbacks_private.FaxRouteGetFile = FaxRouteGetFile;
|
||
|
Callbacks_private.FaxRouteEnumFiles = FaxRouteEnumFiles;
|
||
|
Callbacks_private.FaxRouteModifyRoutingData = FaxRouteModifyRoutingData;
|
||
|
Callbacks_private.GetRecieptsConfiguration = GetRecieptsConfiguration;
|
||
|
Callbacks_private.FreeRecieptsConfiguration = FreeRecieptsConfiguration;
|
||
|
Callbacks_private.lptstrFaxQueueDir = g_wszFaxQueueDir;
|
||
|
|
||
|
for (i = 0; i < pFaxReg->RoutingExtensionsCount; i++)
|
||
|
{
|
||
|
HMODULE hModule = NULL;
|
||
|
WCHAR wszImageFileName[_MAX_FNAME] = {0};
|
||
|
WCHAR wszImageFileExt[_MAX_EXT] = {0};
|
||
|
|
||
|
pRoutingExtension = (PROUTING_EXTENSION) MemAlloc( sizeof(ROUTING_EXTENSION) );
|
||
|
if (!pRoutingExtension)
|
||
|
{
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("Could not allocate memory for routing extension %s"),
|
||
|
pFaxReg->RoutingExtensions[i].ImageName );
|
||
|
goto InitializationFailed;
|
||
|
}
|
||
|
memset(pRoutingExtension, 0, sizeof(ROUTING_EXTENSION));
|
||
|
InitializeListHead( &pRoutingExtension->RoutingMethods );
|
||
|
//
|
||
|
// Copy registry constant info
|
||
|
//
|
||
|
wcsncpy( pRoutingExtension->FriendlyName,
|
||
|
pFaxReg->RoutingExtensions[i].FriendlyName ?
|
||
|
pFaxReg->RoutingExtensions[i].FriendlyName : EMPTY_STRING ,
|
||
|
sizeof (pRoutingExtension->FriendlyName) / sizeof (TCHAR) );
|
||
|
pRoutingExtension->FriendlyName[(sizeof (pRoutingExtension->FriendlyName) / sizeof (TCHAR)) - 1] = TEXT('\0');
|
||
|
wcsncpy( pRoutingExtension->ImageName,
|
||
|
pFaxReg->RoutingExtensions[i].ImageName ?
|
||
|
pFaxReg->RoutingExtensions[i].ImageName : EMPTY_STRING,
|
||
|
sizeof (pRoutingExtension->ImageName) / sizeof (TCHAR) );
|
||
|
pRoutingExtension->ImageName[(sizeof (pRoutingExtension->ImageName) / sizeof (TCHAR)) - 1] = TEXT('\0');
|
||
|
wcsncpy( pRoutingExtension->InternalName,
|
||
|
pFaxReg->RoutingExtensions[i].InternalName ?
|
||
|
pFaxReg->RoutingExtensions[i].InternalName : EMPTY_STRING,
|
||
|
sizeof (pRoutingExtension->InternalName) / sizeof (TCHAR) );
|
||
|
pRoutingExtension->InternalName[(sizeof (pRoutingExtension->InternalName) / sizeof (TCHAR)) - 1] = TEXT('\0');
|
||
|
|
||
|
_wsplitpath( pRoutingExtension->ImageName, NULL, NULL, wszImageFileName, wszImageFileExt );
|
||
|
if (_wcsicmp( wszImageFileName, FAX_ROUTE_MODULE_NAME ) == 0 &&
|
||
|
_wcsicmp( wszImageFileExt, TEXT(".DLL") ) == 0)
|
||
|
{
|
||
|
pRoutingExtension->MicrosoftExtension = TRUE;
|
||
|
}
|
||
|
|
||
|
hModule = LoadLibrary( pFaxReg->RoutingExtensions[i].ImageName );
|
||
|
if (!hModule)
|
||
|
{
|
||
|
dwRes = GetLastError ();
|
||
|
DebugPrintEx(
|
||
|
DEBUG_WRN,
|
||
|
TEXT("LoadLibrary() failed: [%s], ec=%d"),
|
||
|
pFaxReg->RoutingExtensions[i].ImageName,
|
||
|
dwRes);
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_CANT_LOAD;
|
||
|
pRoutingExtension->dwLastError = dwRes;
|
||
|
goto InitializationFailed;
|
||
|
}
|
||
|
pRoutingExtension->hModule = hModule;
|
||
|
//
|
||
|
// Retrieve the routing extension's version from the DLL
|
||
|
//
|
||
|
pRoutingExtension->Version.dwSizeOfStruct = sizeof (FAX_VERSION);
|
||
|
dwRes = GetFileVersion ( pFaxReg->RoutingExtensions[i].ImageName,
|
||
|
&pRoutingExtension->Version);
|
||
|
if (ERROR_SUCCESS != dwRes)
|
||
|
{
|
||
|
//
|
||
|
// If the routing extension's DLL does not have version data or the
|
||
|
// version data is non-retrievable, we consider this a
|
||
|
// warning (debug print) but carry on with the DLL's load.
|
||
|
//
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("GetFileVersion() failed: [%s] (ec: %ld)"),
|
||
|
pFaxReg->RoutingExtensions[i].ImageName,
|
||
|
dwRes);
|
||
|
}
|
||
|
|
||
|
pRoutingExtension->FaxRouteInitialize = (PFAXROUTEINITIALIZE) GetProcAddress(
|
||
|
hModule,
|
||
|
"FaxRouteInitialize"
|
||
|
);
|
||
|
|
||
|
pRoutingExtension->FaxRouteGetRoutingInfo = (PFAXROUTEGETROUTINGINFO) GetProcAddress(
|
||
|
hModule,
|
||
|
"FaxRouteGetRoutingInfo"
|
||
|
);
|
||
|
|
||
|
pRoutingExtension->FaxRouteSetRoutingInfo = (PFAXROUTESETROUTINGINFO) GetProcAddress(
|
||
|
hModule,
|
||
|
"FaxRouteSetRoutingInfo"
|
||
|
);
|
||
|
|
||
|
pRoutingExtension->FaxRouteDeviceEnable = (PFAXROUTEDEVICEENABLE) GetProcAddress(
|
||
|
hModule,
|
||
|
"FaxRouteDeviceEnable"
|
||
|
);
|
||
|
|
||
|
pRoutingExtension->FaxRouteDeviceChangeNotification = (PFAXROUTEDEVICECHANGENOTIFICATION) GetProcAddress(
|
||
|
hModule,
|
||
|
"FaxRouteDeviceChangeNotification"
|
||
|
);
|
||
|
|
||
|
if (pRoutingExtension->FaxRouteInitialize == NULL ||
|
||
|
pRoutingExtension->FaxRouteGetRoutingInfo == NULL ||
|
||
|
pRoutingExtension->FaxRouteSetRoutingInfo == NULL ||
|
||
|
pRoutingExtension->FaxRouteDeviceChangeNotification == NULL ||
|
||
|
pRoutingExtension->FaxRouteDeviceEnable == NULL)
|
||
|
{
|
||
|
//
|
||
|
// the routing extension dll does not have a complete export list
|
||
|
//
|
||
|
dwRes = GetLastError ();
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("Routing extension FAILED to initialized [%s], ec=%ld"),
|
||
|
pFaxReg->RoutingExtensions[i].FriendlyName,
|
||
|
dwRes);
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_CANT_LINK;
|
||
|
pRoutingExtension->dwLastError = dwRes;
|
||
|
goto InitializationFailed;
|
||
|
}
|
||
|
//
|
||
|
// Link to the extension configuration and notification init functions
|
||
|
//
|
||
|
pRoutingExtension->pFaxExtInitializeConfig = (PFAX_EXT_INITIALIZE_CONFIG) GetProcAddress(
|
||
|
hModule,
|
||
|
"FaxExtInitializeConfig"
|
||
|
);
|
||
|
if (!pRoutingExtension->pFaxExtInitializeConfig)
|
||
|
{
|
||
|
//
|
||
|
// Optional function
|
||
|
//
|
||
|
DebugPrintEx(
|
||
|
DEBUG_MSG,
|
||
|
TEXT("FaxExtInitializeConfig() not found for routing extension %s. This is not an error."),
|
||
|
pRoutingExtension->FriendlyName);
|
||
|
}
|
||
|
//
|
||
|
// create the routing extension's heap and add it to the list
|
||
|
//
|
||
|
pRoutingExtension->HeapHandle = pRoutingExtension->MicrosoftExtension ?
|
||
|
GetProcessHeap() : HeapCreate( 0, 1024*100, 1024*1024*2 );
|
||
|
if (!pRoutingExtension->HeapHandle)
|
||
|
{
|
||
|
dwRes = GetLastError();
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("Can't create heap, ec=%ld"),
|
||
|
dwRes);
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
|
||
|
pRoutingExtension->dwLastError = dwRes;
|
||
|
goto InitializationFailed;
|
||
|
}
|
||
|
//
|
||
|
// We 1st call the RoutingExtension->pFaxExtInitializeConfig function (if exported)
|
||
|
//
|
||
|
if (pRoutingExtension->pFaxExtInitializeConfig)
|
||
|
{
|
||
|
__try
|
||
|
{
|
||
|
|
||
|
hr = pRoutingExtension->pFaxExtInitializeConfig(
|
||
|
FaxExtGetData,
|
||
|
FaxExtSetData,
|
||
|
FaxExtRegisterForEvents,
|
||
|
FaxExtUnregisterForEvents,
|
||
|
FaxExtFreeBuffer);
|
||
|
}
|
||
|
__except (HandleFaxExtensionFault(EXCEPTION_SOURCE_ROUTING_EXT, pRoutingExtension->FriendlyName, GetExceptionCode()))
|
||
|
{
|
||
|
ASSERT_FALSE;
|
||
|
}
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
//
|
||
|
// Failed to init ext. config.
|
||
|
//
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("FaxExtInitializeConfig() failed (hr = 0x%08x) for extension [%s]"),
|
||
|
hr,
|
||
|
pRoutingExtension->FriendlyName );
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_CANT_INIT;
|
||
|
pRoutingExtension->dwLastError = hr;
|
||
|
goto InitializationFailed;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Next, call the initialization routing of the routing ext.
|
||
|
//
|
||
|
__try
|
||
|
{
|
||
|
if (pRoutingExtension->MicrosoftExtension)
|
||
|
{
|
||
|
//
|
||
|
// Special hack - for the MS routing extension, pass the extra private structure which
|
||
|
// contains a pointer to the service's g_CsConfig.
|
||
|
//
|
||
|
bRes = pRoutingExtension->FaxRouteInitialize( pRoutingExtension->HeapHandle, (PFAX_ROUTE_CALLBACKROUTINES)(&Callbacks_private) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bRes = pRoutingExtension->FaxRouteInitialize( pRoutingExtension->HeapHandle, &Callbacks );
|
||
|
}
|
||
|
}
|
||
|
__except (HandleFaxExtensionFault(EXCEPTION_SOURCE_ROUTING_EXT, pRoutingExtension->FriendlyName, GetExceptionCode()))
|
||
|
{
|
||
|
ASSERT_FALSE;
|
||
|
}
|
||
|
if (!bRes)
|
||
|
{
|
||
|
//
|
||
|
// Either init faulted or failed
|
||
|
//
|
||
|
dwRes = GetLastError ();
|
||
|
DebugPrintEx(DEBUG_ERR,
|
||
|
TEXT("FaxRouteInitialize() failed / faulted: ec=%ld"),
|
||
|
dwRes);
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_CANT_INIT;
|
||
|
pRoutingExtension->dwLastError = dwRes;
|
||
|
goto InitializationFailed;
|
||
|
}
|
||
|
//
|
||
|
// All initialization succeeded - proceed with routing methods.
|
||
|
//
|
||
|
for (j = 0; j < pFaxReg->RoutingExtensions[i].RoutingMethodsCount; j++)
|
||
|
{
|
||
|
LPSTR lpstrProcName = NULL;
|
||
|
|
||
|
//
|
||
|
// Send mail is not supported on desktop SKUs
|
||
|
//
|
||
|
if (0 == _wcsicmp(pFaxReg->RoutingExtensions[i].RoutingMethods[j].Guid, REGVAL_RM_EMAIL_GUID) &&
|
||
|
TRUE == IsDesktopSKU())
|
||
|
{
|
||
|
DebugPrintEx(
|
||
|
DEBUG_MSG,
|
||
|
TEXT("Email is not supported on desktop SKU."));
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
pRoutingMethod = (PROUTING_METHOD) MemAlloc( sizeof(ROUTING_METHOD) );
|
||
|
if (!pRoutingMethod)
|
||
|
{
|
||
|
dwRes = GetLastError ();
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("Could not allocate memory for routing method %s"),
|
||
|
pFaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName);
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
|
||
|
pRoutingExtension->dwLastError = dwRes;
|
||
|
goto InitializationFailed;
|
||
|
}
|
||
|
memset (pRoutingMethod, 0, sizeof (ROUTING_METHOD));
|
||
|
|
||
|
pRoutingMethod->RoutingExtension = pRoutingExtension;
|
||
|
|
||
|
pRoutingMethod->Priority = pFaxReg->RoutingExtensions[i].RoutingMethods[j].Priority;
|
||
|
pRoutingMethod->FriendlyName =
|
||
|
StringDup( pFaxReg->RoutingExtensions[i].RoutingMethods[j].FriendlyName ?
|
||
|
pFaxReg->RoutingExtensions[i].RoutingMethods[j].FriendlyName : EMPTY_STRING );
|
||
|
if (!pRoutingMethod->FriendlyName)
|
||
|
{
|
||
|
dwRes = GetLastError ();
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("Could not create routing function name [%s]"),
|
||
|
pFaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName);
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
|
||
|
pRoutingExtension->dwLastError = dwRes;
|
||
|
goto MethodError;
|
||
|
}
|
||
|
|
||
|
pRoutingMethod->FunctionName =
|
||
|
StringDup( pFaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName ?
|
||
|
pFaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName : EMPTY_STRING);
|
||
|
if (!pRoutingMethod->FunctionName)
|
||
|
{
|
||
|
dwRes = GetLastError ();
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("Could not create routing function name [%s]"),
|
||
|
pFaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName );
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
|
||
|
pRoutingExtension->dwLastError = dwRes;
|
||
|
goto MethodError;
|
||
|
}
|
||
|
|
||
|
pRoutingMethod->InternalName =
|
||
|
StringDup( pFaxReg->RoutingExtensions[i].RoutingMethods[j].InternalName ?
|
||
|
pFaxReg->RoutingExtensions[i].RoutingMethods[j].InternalName : EMPTY_STRING);
|
||
|
if (!pRoutingMethod->InternalName)
|
||
|
{
|
||
|
dwRes = GetLastError ();
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("Could not create routing internal name [%s]"),
|
||
|
pFaxReg->RoutingExtensions[i].RoutingMethods[j].InternalName );
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
|
||
|
pRoutingExtension->dwLastError = dwRes;
|
||
|
goto MethodError;
|
||
|
}
|
||
|
|
||
|
hr = IIDFromString( pFaxReg->RoutingExtensions[i].RoutingMethods[j].Guid, &pRoutingMethod->Guid );
|
||
|
if (S_OK != hr)
|
||
|
{
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("Invalid GUID string [%s], hr = 0x%x"),
|
||
|
pFaxReg->RoutingExtensions[i].RoutingMethods[j].Guid,
|
||
|
hr );
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_BAD_GUID;
|
||
|
pRoutingExtension->dwLastError = hr;
|
||
|
goto MethodError;
|
||
|
}
|
||
|
|
||
|
lpstrProcName = UnicodeStringToAnsiString( pRoutingMethod->FunctionName );
|
||
|
if (!lpstrProcName)
|
||
|
{
|
||
|
dwRes = GetLastError ();
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("Could not create routing function name [%s]"),
|
||
|
pRoutingMethod->FunctionName );
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
|
||
|
pRoutingExtension->dwLastError = dwRes;
|
||
|
goto MethodError;
|
||
|
}
|
||
|
|
||
|
pRoutingMethod->FaxRouteMethod = (PFAXROUTEMETHOD) GetProcAddress(
|
||
|
hModule,
|
||
|
lpstrProcName
|
||
|
);
|
||
|
if (!pRoutingMethod->FaxRouteMethod)
|
||
|
{
|
||
|
dwRes = GetLastError ();
|
||
|
DebugPrintEx(DEBUG_ERR,
|
||
|
TEXT("Could not get function address [%S], ec=%ld"),
|
||
|
lpstrProcName,
|
||
|
dwRes
|
||
|
);
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_CANT_LINK;
|
||
|
pRoutingExtension->dwLastError = dwRes;
|
||
|
goto MethodError;
|
||
|
}
|
||
|
MemFree( lpstrProcName );
|
||
|
goto MethodOk;
|
||
|
|
||
|
MethodError:
|
||
|
MemFree( pRoutingMethod->FriendlyName );
|
||
|
MemFree( pRoutingMethod->FunctionName );
|
||
|
MemFree( pRoutingMethod->InternalName );
|
||
|
MemFree( pRoutingMethod );
|
||
|
MemFree( lpstrProcName );
|
||
|
goto InitializationFailed;
|
||
|
|
||
|
MethodOk:
|
||
|
//
|
||
|
// Success - add this routing method to the routing extension's list of methods
|
||
|
//
|
||
|
InsertTailList( &pRoutingExtension->RoutingMethods, &pRoutingMethod->ListEntry );
|
||
|
} // Loop of extension's routing methods
|
||
|
//
|
||
|
// Success while loading and initializing this extension
|
||
|
//
|
||
|
pRoutingExtension->Status = FAX_PROVIDER_STATUS_SUCCESS;
|
||
|
pRoutingExtension->dwLastError = ERROR_SUCCESS;
|
||
|
//
|
||
|
// All methods successfully initialized.
|
||
|
// Add all methods to global list of methods (and increase global counter)
|
||
|
//
|
||
|
ple = pRoutingExtension->RoutingMethods.Flink;
|
||
|
while ((ULONG_PTR)ple != (ULONG_PTR)&pRoutingExtension->RoutingMethods)
|
||
|
{
|
||
|
pRoutingMethod = CONTAINING_RECORD( ple, ROUTING_METHOD, ListEntry );
|
||
|
ple = ple->Flink;
|
||
|
InsertTailList( &g_lstRoutingMethods, &pRoutingMethod->ListEntryMethod );
|
||
|
g_dwCountRoutingMethods++;
|
||
|
}
|
||
|
goto next;
|
||
|
|
||
|
InitializationFailed:
|
||
|
{
|
||
|
FaxLog(
|
||
|
FAXLOG_CATEGORY_INIT,
|
||
|
FAXLOG_LEVEL_MIN,
|
||
|
4,
|
||
|
MSG_ROUTE_INIT_FAILED,
|
||
|
pFaxReg->RoutingExtensions[i].FriendlyName,
|
||
|
pFaxReg->RoutingExtensions[i].ImageName,
|
||
|
pRoutingExtension ? DWORD2DECIMAL(pRoutingExtension->Status) : NULL,
|
||
|
pRoutingExtension ? DWORD2DECIMAL(pRoutingExtension->dwLastError) : DWORD2DECIMAL(ERROR_OUTOFMEMORY)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (pRoutingExtension)
|
||
|
{
|
||
|
if (pRoutingExtension->hModule)
|
||
|
{
|
||
|
FreeLibrary (pRoutingExtension->hModule);
|
||
|
pRoutingExtension->hModule = NULL;
|
||
|
}
|
||
|
//
|
||
|
// If we created a heap for the routing extension, destroy it
|
||
|
//
|
||
|
if ((pRoutingExtension->HeapHandle) &&
|
||
|
(FALSE == pRoutingExtension->MicrosoftExtension))
|
||
|
{
|
||
|
HeapDestroy (pRoutingExtension->HeapHandle);
|
||
|
pRoutingExtension->HeapHandle = NULL;
|
||
|
}
|
||
|
//
|
||
|
// Clear the list of routing methods and free method structures.
|
||
|
//
|
||
|
ple = pRoutingExtension->RoutingMethods.Flink;
|
||
|
while ((ULONG_PTR)ple != (ULONG_PTR)&pRoutingExtension->RoutingMethods)
|
||
|
{
|
||
|
pRoutingMethod = CONTAINING_RECORD(ple, ROUTING_METHOD, ListEntry);
|
||
|
ple = ple->Flink;
|
||
|
MemFree( pRoutingMethod->FriendlyName );
|
||
|
MemFree( pRoutingMethod->FunctionName );
|
||
|
MemFree( pRoutingMethod->InternalName );
|
||
|
MemFree( pRoutingMethod );
|
||
|
}
|
||
|
//
|
||
|
// Make the extension have an empty list of methods.
|
||
|
//
|
||
|
InitializeListHead( &pRoutingExtension->RoutingMethods );
|
||
|
}
|
||
|
|
||
|
next:
|
||
|
if (pRoutingExtension)
|
||
|
{
|
||
|
//
|
||
|
// we have a routing extension object (successful or not), add it to the list
|
||
|
//
|
||
|
InsertTailList( &g_lstRoutingExtensions, &pRoutingExtension->ListEntry );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SortMethodPriorities();
|
||
|
|
||
|
if (0 == g_dwCountRoutingMethods)
|
||
|
{
|
||
|
//
|
||
|
// No routing methods available
|
||
|
//
|
||
|
DebugPrintEx(DEBUG_WRN,
|
||
|
TEXT("No routing methods are available on the server !!!!"));
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
} // InitializeRouting
|
||
|
|
||
|
BOOL
|
||
|
FaxRoute(
|
||
|
PJOB_QUEUE JobQueueEntry,
|
||
|
LPTSTR TiffFileName,
|
||
|
PFAX_ROUTE FaxRoute,
|
||
|
PROUTE_FAILURE_INFO *RouteFailureInfo,
|
||
|
LPDWORD RouteFailureCount
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Routes a FAX.
|
||
|
|
||
|
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
JobQueueEntry - the job queue entry for the job
|
||
|
TiffFileName - filename of the received fax
|
||
|
FaxRoute - struct describing received FAX
|
||
|
RouteFailureInfo - pointer to receive pointr to eceive buffer ROUTE_FAILURE_INFO structures
|
||
|
RouteFailureCount - receives the total number of route failures recorded
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE
|
||
|
if fax routing succeded ( some methods may still fail )
|
||
|
check RouteFailureCount to see how many Routing Methods failed
|
||
|
FALSE
|
||
|
if the function itself failed ( MemAlloc etc. )
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PLIST_ENTRY pNextMethod;
|
||
|
PROUTING_METHOD pRoutingMethod;
|
||
|
DWORD FailureCount = 0;
|
||
|
PROUTE_FAILURE_INFO pRouteFailure;
|
||
|
PLIST_ENTRY pNextRoutingOverride;
|
||
|
PROUTING_DATA_OVERRIDE pRoutingDataOverride;
|
||
|
BOOL RetVal = TRUE;
|
||
|
DEBUG_FUNCTION_NAME(TEXT("FaxRoute"));
|
||
|
|
||
|
*RouteFailureInfo = NULL;
|
||
|
*RouteFailureCount = 0;
|
||
|
|
||
|
//
|
||
|
// if the tiff file has been deleted ==> return
|
||
|
//
|
||
|
if (GetFileAttributes( TiffFileName ) == 0xffffffff)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
EnterCriticalSection( &g_CsRouting );
|
||
|
|
||
|
pNextMethod = g_lstRoutingMethods.Flink;
|
||
|
if (pNextMethod)
|
||
|
{
|
||
|
//
|
||
|
// allocate memory to record the GUIDs of the failed routing methods
|
||
|
//
|
||
|
pRouteFailure = (PROUTE_FAILURE_INFO) MemAlloc( g_dwCountRoutingMethods * sizeof(ROUTE_FAILURE_INFO) );
|
||
|
if (pRouteFailure == NULL)
|
||
|
{
|
||
|
RetVal = FALSE;
|
||
|
goto Exit;
|
||
|
}
|
||
|
//
|
||
|
// add the tiff file as the first file
|
||
|
// in the file name list, the owner is the fax service
|
||
|
//
|
||
|
if (FaxRouteAddFile( FaxRoute->JobId, TiffFileName, const_cast<GUID*>(&gc_FaxSvcGuid) ) < 1)
|
||
|
{
|
||
|
RetVal = FALSE;
|
||
|
goto Exit;
|
||
|
}
|
||
|
//
|
||
|
// walk thru all of the routing methods and call them
|
||
|
//
|
||
|
while ((ULONG_PTR)pNextMethod != (ULONG_PTR)&g_lstRoutingMethods)
|
||
|
{
|
||
|
BOOL bSuccess;
|
||
|
pRoutingMethod = CONTAINING_RECORD( pNextMethod, ROUTING_METHOD, ListEntryMethod );
|
||
|
pNextMethod = pRoutingMethod->ListEntryMethod.Flink;
|
||
|
|
||
|
FaxRoute->RoutingInfoData = NULL;
|
||
|
FaxRoute->RoutingInfoDataSize = 0;
|
||
|
|
||
|
EnterCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
|
||
|
|
||
|
pNextRoutingOverride = JobQueueEntry->RoutingDataOverride.Flink;
|
||
|
if (pNextRoutingOverride != NULL)
|
||
|
{
|
||
|
while ((ULONG_PTR)pNextRoutingOverride != (ULONG_PTR)&JobQueueEntry->RoutingDataOverride)
|
||
|
{
|
||
|
pRoutingDataOverride = CONTAINING_RECORD( pNextRoutingOverride, ROUTING_DATA_OVERRIDE, ListEntry );
|
||
|
pNextRoutingOverride = pRoutingDataOverride->ListEntry.Flink;
|
||
|
if (pRoutingDataOverride->RoutingMethod == pRoutingMethod)
|
||
|
{
|
||
|
FaxRoute->RoutingInfoData = (LPBYTE)MemAlloc(pRoutingDataOverride->RoutingDataSize);
|
||
|
if (NULL == FaxRoute->RoutingInfoData)
|
||
|
{
|
||
|
DebugPrintEx(DEBUG_ERR,
|
||
|
_T("MemAlloc Failed (ec: %ld)"),
|
||
|
GetLastError());
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
|
||
|
RetVal = FALSE;
|
||
|
goto Exit;
|
||
|
}
|
||
|
CopyMemory (FaxRoute->RoutingInfoData,
|
||
|
pRoutingDataOverride->RoutingData,
|
||
|
pRoutingDataOverride->RoutingDataSize);
|
||
|
FaxRoute->RoutingInfoDataSize = pRoutingDataOverride->RoutingDataSize;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
|
||
|
pRouteFailure[FailureCount].FailureData = NULL;
|
||
|
pRouteFailure[FailureCount].FailureSize = 0;
|
||
|
__try
|
||
|
{
|
||
|
bSuccess = pRoutingMethod->FaxRouteMethod(
|
||
|
FaxRoute,
|
||
|
&pRouteFailure[FailureCount].FailureData,
|
||
|
&pRouteFailure[FailureCount].FailureSize );
|
||
|
}
|
||
|
__except (HandleFaxExtensionFault(EXCEPTION_SOURCE_ROUTING_EXT, pRoutingMethod->RoutingExtension->FriendlyName, GetExceptionCode()))
|
||
|
{
|
||
|
ASSERT_FALSE;
|
||
|
}
|
||
|
if (!bSuccess)
|
||
|
{
|
||
|
WCHAR TmpStr[20] = {0};
|
||
|
swprintf(TmpStr,TEXT("0x%016I64x"), JobQueueEntry->UniqueId);
|
||
|
|
||
|
FaxLog(FAXLOG_CATEGORY_INBOUND,
|
||
|
FAXLOG_LEVEL_MIN,
|
||
|
6,
|
||
|
MSG_FAX_ROUTE_METHOD_FAILED,
|
||
|
TmpStr,
|
||
|
JobQueueEntry->FaxRoute->DeviceName,
|
||
|
JobQueueEntry->FaxRoute->Tsid,
|
||
|
JobQueueEntry->FileName,
|
||
|
pRoutingMethod->RoutingExtension->FriendlyName,
|
||
|
pRoutingMethod->FriendlyName
|
||
|
);
|
||
|
|
||
|
StringFromGUID2(pRoutingMethod->Guid,
|
||
|
pRouteFailure[FailureCount].GuidString,
|
||
|
MAX_GUID_STRING_LEN);
|
||
|
|
||
|
//
|
||
|
// Allocate failure data using MemAlloc
|
||
|
//
|
||
|
if (pRouteFailure[FailureCount].FailureSize)
|
||
|
{
|
||
|
PVOID pOriginalFailureData = pRouteFailure[FailureCount].FailureData;
|
||
|
pRouteFailure[FailureCount].FailureData = MemAlloc (pRouteFailure[FailureCount].FailureSize);
|
||
|
if (pRouteFailure[FailureCount].FailureData)
|
||
|
{
|
||
|
CopyMemory (pRouteFailure[FailureCount].FailureData,
|
||
|
pOriginalFailureData,
|
||
|
pRouteFailure[FailureCount].FailureSize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Failed to allocate retry failure data - data will be lost.
|
||
|
//
|
||
|
DebugPrintEx(DEBUG_ERR,
|
||
|
_T("Failed to allocate failure date"));
|
||
|
RetVal = FALSE;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if (!HeapFree(pRoutingMethod->RoutingExtension->HeapHandle, // handle to extension heap
|
||
|
0,
|
||
|
pOriginalFailureData
|
||
|
))
|
||
|
{
|
||
|
//
|
||
|
// Failed to free retry failure data from extension heap - data will be lost.
|
||
|
//
|
||
|
DebugPrintEx(DEBUG_ERR,
|
||
|
_T("HeapFree Failed (ec: %ld)"),
|
||
|
GetLastError());
|
||
|
RetVal = FALSE;
|
||
|
goto Exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (0 == pRouteFailure[FailureCount].FailureSize ||
|
||
|
NULL == pRouteFailure[FailureCount].FailureData)
|
||
|
{
|
||
|
//
|
||
|
// Make sure failure data will not be freed
|
||
|
//
|
||
|
pRouteFailure[FailureCount].FailureData = NULL;
|
||
|
pRouteFailure[FailureCount].FailureSize = 0;
|
||
|
}
|
||
|
|
||
|
FailureCount++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Assert (RetVal == TRUE);
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
LeaveCriticalSection( &g_CsRouting );
|
||
|
|
||
|
if (pRouteFailure && FailureCount == 0)
|
||
|
{
|
||
|
//
|
||
|
// We do not delete the routed TIFF file here.
|
||
|
// RemoveReceiveJob() will take care of that.
|
||
|
//
|
||
|
MemFree( pRouteFailure );
|
||
|
pRouteFailure = NULL;
|
||
|
}
|
||
|
|
||
|
*RouteFailureInfo = pRouteFailure;
|
||
|
*RouteFailureCount = FailureCount;
|
||
|
|
||
|
return RetVal;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
LoadRouteInfo(
|
||
|
IN LPWSTR RouteFileName,
|
||
|
OUT PROUTE_INFO *RouteInfo,
|
||
|
OUT PROUTE_FAILURE_INFO *RouteFailure,
|
||
|
OUT LPDWORD RouteFailureCount
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Load routing information from a routing information file.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RouteFileName - Name of routing information file.
|
||
|
|
||
|
Return value:
|
||
|
|
||
|
Pointer to routing information structure if success. NULL if fail.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
FaxRouteRetry(
|
||
|
PFAX_ROUTE FaxRoute,
|
||
|
PROUTE_FAILURE_INFO pRouteFailureInfo
|
||
|
)
|
||
|
{
|
||
|
PROUTING_METHOD RoutingMethod;
|
||
|
BOOL RetVal = TRUE;
|
||
|
DEBUG_FUNCTION_NAME(TEXT("FaxRouteRetry"));
|
||
|
|
||
|
//
|
||
|
// in this case, we've already retried this method and it succeeded.
|
||
|
//
|
||
|
if (!*pRouteFailureInfo->GuidString) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
RoutingMethod = FindRoutingMethodByGuid( pRouteFailureInfo->GuidString );
|
||
|
|
||
|
if (RoutingMethod)
|
||
|
{
|
||
|
BOOL bSuccess;
|
||
|
|
||
|
PVOID pOriginalFailureData = NULL;
|
||
|
PVOID pFailureData = pRouteFailureInfo->FailureData;
|
||
|
//
|
||
|
// Allocate failure data using the extension heap
|
||
|
//
|
||
|
if (pRouteFailureInfo->FailureSize)
|
||
|
{
|
||
|
pOriginalFailureData = HeapAlloc (RoutingMethod->RoutingExtension->HeapHandle,
|
||
|
HEAP_ZERO_MEMORY,
|
||
|
pRouteFailureInfo->FailureSize);
|
||
|
if (!pOriginalFailureData)
|
||
|
{
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("Failed to allocate failure date")
|
||
|
);
|
||
|
return FALSE;
|
||
|
}
|
||
|
pRouteFailureInfo->FailureData = pOriginalFailureData;
|
||
|
CopyMemory (pRouteFailureInfo->FailureData,
|
||
|
pFailureData,
|
||
|
pRouteFailureInfo->FailureSize);
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Assert (NULL == pRouteFailureInfo->FailureData);
|
||
|
}
|
||
|
MemFree (pFailureData);
|
||
|
__try
|
||
|
{
|
||
|
bSuccess = RoutingMethod->FaxRouteMethod(
|
||
|
FaxRoute,
|
||
|
&(pRouteFailureInfo->FailureData),
|
||
|
&(pRouteFailureInfo->FailureSize));
|
||
|
}
|
||
|
__except (HandleFaxExtensionFault(EXCEPTION_SOURCE_ROUTING_EXT, RoutingMethod->RoutingExtension->FriendlyName, GetExceptionCode()))
|
||
|
{
|
||
|
ASSERT_FALSE;
|
||
|
}
|
||
|
if (!bSuccess)
|
||
|
{
|
||
|
RetVal = FALSE;
|
||
|
//
|
||
|
// Allocate failure data using MemAlloc
|
||
|
//
|
||
|
if (pRouteFailureInfo->FailureSize)
|
||
|
{
|
||
|
pOriginalFailureData = pRouteFailureInfo->FailureData;
|
||
|
pRouteFailureInfo->FailureData = MemAlloc (pRouteFailureInfo->FailureSize);
|
||
|
if (pRouteFailureInfo->FailureData)
|
||
|
{
|
||
|
CopyMemory (pRouteFailureInfo->FailureData,
|
||
|
pOriginalFailureData,
|
||
|
pRouteFailureInfo->FailureSize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Failed to allocate retry failure data - data will be lost.
|
||
|
//
|
||
|
DebugPrintEx(DEBUG_ERR,
|
||
|
_T("Failed to allocate failure date"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!HeapFree(RoutingMethod->RoutingExtension->HeapHandle, // handle to extension heap
|
||
|
0,
|
||
|
pOriginalFailureData
|
||
|
))
|
||
|
{
|
||
|
//
|
||
|
// Failed to free retry failure data from extension heap - data will be lost.
|
||
|
//
|
||
|
DebugPrintEx(DEBUG_ERR,
|
||
|
_T("HeapFree Failed (ec: %ld)"),
|
||
|
GetLastError());
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// set the routing guid to zero so we don't try to route this guy again. He is
|
||
|
// deallocated when we delete the queue entry.
|
||
|
//
|
||
|
ZeroMemory(pRouteFailureInfo->GuidString, MAX_GUID_STRING_LEN*sizeof(WCHAR) );
|
||
|
}
|
||
|
|
||
|
if (0 == pRouteFailureInfo->FailureSize ||
|
||
|
NULL == pRouteFailureInfo->FailureData ||
|
||
|
TRUE == RetVal)
|
||
|
{
|
||
|
//
|
||
|
// Make sure failure data will not be freed
|
||
|
//
|
||
|
pRouteFailureInfo->FailureData = NULL;
|
||
|
pRouteFailureInfo->FailureSize = 0;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return RetVal;
|
||
|
}
|
||
|
|
||
|
|
||
|
PFAX_ROUTE
|
||
|
SerializeFaxRoute(
|
||
|
PFAX_ROUTE FaxRoute,
|
||
|
LPDWORD Size,
|
||
|
BOOL bSizeOnly
|
||
|
)
|
||
|
{
|
||
|
DWORD ByteCount = sizeof(FAX_ROUTE);
|
||
|
DWORD_PTR Offset;
|
||
|
PFAX_ROUTE SerFaxRoute; // the serialized version
|
||
|
|
||
|
|
||
|
*Size = 0;
|
||
|
|
||
|
// Add the size of the strings
|
||
|
|
||
|
ByteCount += StringSize( FaxRoute->Csid );
|
||
|
ByteCount += StringSize( FaxRoute->Tsid );
|
||
|
ByteCount += StringSize( FaxRoute->CallerId );
|
||
|
ByteCount += StringSize( FaxRoute->RoutingInfo );
|
||
|
ByteCount += StringSize( FaxRoute->ReceiverName );
|
||
|
ByteCount += StringSize( FaxRoute->ReceiverNumber );
|
||
|
ByteCount += StringSize( FaxRoute->DeviceName );
|
||
|
ByteCount += FaxRoute->RoutingInfoDataSize;
|
||
|
|
||
|
if (bSizeOnly) {
|
||
|
*Size = ByteCount;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
SerFaxRoute = (PFAX_ROUTE) MemAlloc( ByteCount );
|
||
|
|
||
|
if (SerFaxRoute == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
*Size = ByteCount;
|
||
|
|
||
|
CopyMemory( (PVOID) SerFaxRoute, (PVOID) FaxRoute, sizeof(FAX_ROUTE) );
|
||
|
|
||
|
Offset = sizeof( FAX_ROUTE );
|
||
|
|
||
|
StoreString( FaxRoute->Csid, (PDWORD_PTR)&SerFaxRoute->Csid, (LPBYTE) SerFaxRoute, &Offset, *Size);
|
||
|
StoreString( FaxRoute->Tsid, (PDWORD_PTR)&SerFaxRoute->Tsid, (LPBYTE) SerFaxRoute, &Offset, *Size);
|
||
|
StoreString( FaxRoute->CallerId, (PDWORD_PTR)&SerFaxRoute->CallerId, (LPBYTE) SerFaxRoute, &Offset, *Size);
|
||
|
StoreString( FaxRoute->RoutingInfo, (PDWORD_PTR)&SerFaxRoute->RoutingInfo, (LPBYTE) SerFaxRoute, &Offset, *Size);
|
||
|
StoreString( FaxRoute->ReceiverName, (PDWORD_PTR)&SerFaxRoute->ReceiverName, (LPBYTE) SerFaxRoute, &Offset, *Size);
|
||
|
StoreString( FaxRoute->ReceiverNumber, (PDWORD_PTR)&SerFaxRoute->ReceiverNumber, (LPBYTE) SerFaxRoute, &Offset, *Size);
|
||
|
StoreString( FaxRoute->DeviceName, (PDWORD_PTR)&SerFaxRoute->DeviceName, (LPBYTE) SerFaxRoute, &Offset, *Size);
|
||
|
|
||
|
SerFaxRoute->RoutingInfoData = (LPBYTE) Offset;
|
||
|
Offset += FaxRoute->RoutingInfoDataSize;
|
||
|
|
||
|
CopyMemory(
|
||
|
(PVOID) ((LPBYTE) &SerFaxRoute + Offset),
|
||
|
(PVOID) FaxRoute->RoutingInfoData,
|
||
|
FaxRoute->RoutingInfoDataSize
|
||
|
);
|
||
|
|
||
|
return SerFaxRoute;
|
||
|
}
|
||
|
|
||
|
PFAX_ROUTE
|
||
|
DeSerializeFaxRoute(
|
||
|
PFAX_ROUTE FaxRoute
|
||
|
)
|
||
|
{
|
||
|
PFAX_ROUTE NewFaxRoute = NULL;
|
||
|
DEBUG_FUNCTION_NAME(TEXT("DeSerializeFaxRoute"));
|
||
|
|
||
|
FixupString( FaxRoute, FaxRoute->Csid );
|
||
|
FixupString( FaxRoute, FaxRoute->Tsid );
|
||
|
FixupString( FaxRoute, FaxRoute->CallerId );
|
||
|
FixupString( FaxRoute, FaxRoute->RoutingInfo );
|
||
|
FixupString( FaxRoute, FaxRoute->ReceiverName );
|
||
|
FixupString( FaxRoute, FaxRoute->DeviceName );
|
||
|
FixupString( FaxRoute, FaxRoute->ReceiverNumber );
|
||
|
|
||
|
FaxRoute->RoutingInfoData = (LPBYTE) FaxRoute + (ULONG_PTR) FaxRoute->RoutingInfoData;
|
||
|
|
||
|
//
|
||
|
// Make a copy where each item is individually malloced so it can be freed properly
|
||
|
//
|
||
|
NewFaxRoute = (PFAX_ROUTE)MemAlloc( sizeof( FAX_ROUTE ) );
|
||
|
if (NULL == NewFaxRoute)
|
||
|
{
|
||
|
DebugPrintEx(DEBUG_ERR,TEXT("Failed to allocate FAX_ROUTE"));
|
||
|
return NULL;
|
||
|
}
|
||
|
ZeroMemory (NewFaxRoute, sizeof( FAX_ROUTE ));
|
||
|
|
||
|
NewFaxRoute->SizeOfStruct = sizeof( FAX_ROUTE );
|
||
|
NewFaxRoute->JobId = FaxRoute->JobId;
|
||
|
NewFaxRoute->ElapsedTime = FaxRoute->ElapsedTime;
|
||
|
NewFaxRoute->ReceiveTime = FaxRoute->ReceiveTime;
|
||
|
NewFaxRoute->PageCount = FaxRoute->PageCount;
|
||
|
NewFaxRoute->DeviceId = FaxRoute->DeviceId;
|
||
|
NewFaxRoute->RoutingInfoDataSize = FaxRoute->RoutingInfoDataSize;
|
||
|
|
||
|
int nRes;
|
||
|
STRING_PAIR pairs[] =
|
||
|
{
|
||
|
{ (LPWSTR)FaxRoute->Csid, (LPWSTR*)&(NewFaxRoute->Csid)},
|
||
|
{ (LPWSTR)FaxRoute->Tsid, (LPWSTR*)&(NewFaxRoute->Tsid)},
|
||
|
{ (LPWSTR)FaxRoute->CallerId, (LPWSTR*)&(NewFaxRoute->CallerId)},
|
||
|
{ (LPWSTR)FaxRoute->RoutingInfo, (LPWSTR*)&(NewFaxRoute->RoutingInfo)},
|
||
|
{ (LPWSTR)FaxRoute->ReceiverName, (LPWSTR*)&(NewFaxRoute->ReceiverName)},
|
||
|
{ (LPWSTR)FaxRoute->DeviceName, (LPWSTR*)&(NewFaxRoute->DeviceName)},
|
||
|
{ (LPWSTR)FaxRoute->ReceiverNumber, (LPWSTR*)&(NewFaxRoute->ReceiverNumber)}
|
||
|
};
|
||
|
|
||
|
nRes = MultiStringDup(pairs, sizeof(pairs)/sizeof(STRING_PAIR));
|
||
|
if (nRes != 0)
|
||
|
{
|
||
|
// MultiStringDup takes care of freeing the memory for the pairs for which the copy succeeded
|
||
|
DebugPrintEx(DEBUG_ERR,TEXT("Failed to copy string with index %d"), nRes-1);
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
NewFaxRoute->RoutingInfoData = (LPBYTE)MemAlloc( FaxRoute->RoutingInfoDataSize );
|
||
|
if (NULL == NewFaxRoute->RoutingInfoData)
|
||
|
{
|
||
|
DebugPrintEx(DEBUG_ERR,TEXT("Failed to allocate RoutingInfoData"));
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
CopyMemory( NewFaxRoute->RoutingInfoData, FaxRoute->RoutingInfoData, FaxRoute->RoutingInfoDataSize );
|
||
|
return NewFaxRoute;
|
||
|
|
||
|
Error:
|
||
|
MemFree ((void*)NewFaxRoute->Csid);
|
||
|
MemFree ((void*)NewFaxRoute->Tsid);
|
||
|
MemFree ((void*)NewFaxRoute->CallerId);
|
||
|
MemFree ((void*)NewFaxRoute->RoutingInfo);
|
||
|
MemFree ((void*)NewFaxRoute->ReceiverName);
|
||
|
MemFree ((void*)NewFaxRoute->DeviceName);
|
||
|
MemFree ((void*)NewFaxRoute->ReceiverNumber);
|
||
|
MemFree ((void*)NewFaxRoute->RoutingInfoData);
|
||
|
MemFree ((void*)NewFaxRoute);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
extern "C"
|
||
|
DWORD
|
||
|
GetRecieptsConfiguration(
|
||
|
PFAX_SERVER_RECEIPTS_CONFIGW* ppServerRecieptConfig,
|
||
|
BOOL bNeedNTLMToken
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine name : GetRecieptsConfiguration
|
||
|
|
||
|
Routine description:
|
||
|
|
||
|
Private callback used by MS Routing Extension to get the server reciept configuration. Also used by the service SendReceipt()
|
||
|
Used to get a copy of the receipts configuration.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Oded Sacher (OdedS), Mar, 2001
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ppServerRecieptConfig [out] - Address to a pointer to a private server reciepts configuration struct.
|
||
|
The caller should free the resources by calling FreeRecieptsConfiguration()
|
||
|
|
||
|
bNeedNTLMToken [in] - If TRUE, the caller is interested in the user token for NTLM authentication
|
||
|
for SMTP connections. The token is returned in the hLoggedOnUser member
|
||
|
of the FAX_SERVER_RECEIPTS_CONFIGW structure.
|
||
|
|
||
|
if FALSE, the caller is only interested in the receipts configuration and
|
||
|
is not about to perform any activity based on that configration
|
||
|
(such as sending mail via CDO2).
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Win32 error code
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
HKEY hReceiptsKey = NULL;
|
||
|
DWORD dwRes = ERROR_SUCCESS;
|
||
|
PFAX_SERVER_RECEIPTS_CONFIGW pServerRecieptConfig = NULL;
|
||
|
|
||
|
DEBUG_FUNCTION_NAME(TEXT("GetRecieptsConfiguration"));
|
||
|
|
||
|
Assert (ppServerRecieptConfig);
|
||
|
|
||
|
pServerRecieptConfig = (PFAX_SERVER_RECEIPTS_CONFIGW)MemAlloc(sizeof(FAX_SERVER_RECEIPTS_CONFIGW));
|
||
|
if (NULL == pServerRecieptConfig)
|
||
|
{
|
||
|
DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed"));
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
ZeroMemory (pServerRecieptConfig, sizeof(FAX_SERVER_RECEIPTS_CONFIGW));
|
||
|
|
||
|
EnterCriticalSection (&g_CsConfig);
|
||
|
|
||
|
pServerRecieptConfig->dwSizeOfStruct = sizeof (FAX_SERVER_RECEIPTS_CONFIGW);
|
||
|
pServerRecieptConfig->bIsToUseForMSRouteThroughEmailMethod = g_ReceiptsConfig.bIsToUseForMSRouteThroughEmailMethod;
|
||
|
pServerRecieptConfig->dwSMTPPort = g_ReceiptsConfig.dwSMTPPort;
|
||
|
pServerRecieptConfig->dwAllowedReceipts = g_ReceiptsConfig.dwAllowedReceipts;
|
||
|
pServerRecieptConfig->SMTPAuthOption = g_ReceiptsConfig.SMTPAuthOption;
|
||
|
pServerRecieptConfig->lptstrReserved = NULL;
|
||
|
|
||
|
if (NULL != g_ReceiptsConfig.lptstrSMTPServer &&
|
||
|
NULL == (pServerRecieptConfig->lptstrSMTPServer = StringDup(g_ReceiptsConfig.lptstrSMTPServer)))
|
||
|
{
|
||
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed"));
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if (NULL != g_ReceiptsConfig.lptstrSMTPFrom &&
|
||
|
NULL == (pServerRecieptConfig->lptstrSMTPFrom = StringDup(g_ReceiptsConfig.lptstrSMTPFrom)))
|
||
|
{
|
||
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed"));
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if (NULL != g_ReceiptsConfig.lptstrSMTPUserName &&
|
||
|
NULL == (pServerRecieptConfig->lptstrSMTPUserName = StringDup(g_ReceiptsConfig.lptstrSMTPUserName)))
|
||
|
{
|
||
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed"));
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Read stored password
|
||
|
//
|
||
|
hReceiptsKey = OpenRegistryKey(
|
||
|
HKEY_LOCAL_MACHINE,
|
||
|
REGKEY_SOFTWARE TEXT("\\") REGKEY_RECEIPTS_CONFIG,
|
||
|
FALSE,
|
||
|
KEY_READ | KEY_WRITE);
|
||
|
if (NULL == hReceiptsKey)
|
||
|
{
|
||
|
dwRes = GetLastError ();
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("OpenRegistryKey failed. (ec=%lu)"),
|
||
|
dwRes);
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if ( NULL == (pServerRecieptConfig->lptstrSMTPPassword = GetRegistrySecureString(hReceiptsKey, REGVAL_RECEIPTS_PASSWORD, EMPTY_STRING, TRUE, NULL) ) )
|
||
|
{
|
||
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed"));
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if (bNeedNTLMToken &&
|
||
|
FAX_SMTP_AUTH_NTLM == g_ReceiptsConfig.SMTPAuthOption)
|
||
|
{
|
||
|
//
|
||
|
// User needs the NTLM token and NTLM authentication is configured.
|
||
|
//
|
||
|
HANDLE hDupToken;
|
||
|
|
||
|
if (NULL == g_ReceiptsConfig.hLoggedOnUser)
|
||
|
{
|
||
|
HANDLE hLoggedOnUserToken;
|
||
|
WCHAR wszUser[CREDUI_MAX_USERNAME_LENGTH] = {0};
|
||
|
WCHAR wszDomain[CREDUI_MAX_DOMAIN_TARGET_LENGTH] = {0};
|
||
|
|
||
|
//
|
||
|
// Parse user name into user name and domain
|
||
|
//
|
||
|
dwRes = CredUIParseUserName (g_ReceiptsConfig.lptstrSMTPUserName,
|
||
|
wszUser,
|
||
|
ARR_SIZE(wszUser),
|
||
|
wszDomain,
|
||
|
ARR_SIZE(wszDomain));
|
||
|
if (ERROR_SUCCESS != dwRes)
|
||
|
{
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("CredUIParseUserName failed. (ec: %ld)"),
|
||
|
dwRes);
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We get the a logged on user token
|
||
|
//
|
||
|
if (!LogonUser (wszUser,
|
||
|
wszDomain,
|
||
|
pServerRecieptConfig->lptstrSMTPPassword,
|
||
|
LOGON32_LOGON_INTERACTIVE,
|
||
|
LOGON32_PROVIDER_DEFAULT,
|
||
|
&hLoggedOnUserToken))
|
||
|
{
|
||
|
dwRes = GetLastError();
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("LogonUser failed. (ec: %ld)"),
|
||
|
dwRes);
|
||
|
goto exit;
|
||
|
}
|
||
|
g_ReceiptsConfig.hLoggedOnUser = hLoggedOnUserToken;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Duplicate that Token
|
||
|
//
|
||
|
if (!DuplicateToken(g_ReceiptsConfig.hLoggedOnUser, // Source token
|
||
|
SecurityDelegation, // The server process can impersonate the client's security context on remote systems
|
||
|
&hDupToken)) // Duplicate token
|
||
|
{
|
||
|
dwRes = GetLastError();
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("DuplicateToken failed. (ec: %ld)"),
|
||
|
dwRes);
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
pServerRecieptConfig->hLoggedOnUser = hDupToken;
|
||
|
}
|
||
|
|
||
|
*ppServerRecieptConfig = pServerRecieptConfig;
|
||
|
Assert (ERROR_SUCCESS == dwRes);
|
||
|
|
||
|
exit:
|
||
|
LeaveCriticalSection (&g_CsConfig);
|
||
|
|
||
|
if (NULL != hReceiptsKey)
|
||
|
{
|
||
|
DWORD ec = RegCloseKey(hReceiptsKey);
|
||
|
if (ERROR_SUCCESS != ec)
|
||
|
{
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("RegCloseKey failed (ec: %lu)"),
|
||
|
ec);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ERROR_SUCCESS != dwRes)
|
||
|
{
|
||
|
FreeRecieptsConfiguration( pServerRecieptConfig, TRUE);
|
||
|
}
|
||
|
return dwRes;
|
||
|
} // GetRecieptsConfiguration
|
||
|
|
||
|
|
||
|
extern "C"
|
||
|
void
|
||
|
FreeRecieptsConfiguration(
|
||
|
PFAX_SERVER_RECEIPTS_CONFIGW pServerRecieptConfig,
|
||
|
BOOL fDestroy
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine name : FreeRecieptsConfiguration
|
||
|
|
||
|
Routine description:
|
||
|
|
||
|
Private callback used by MS Routing Extension to get the server reciept configuration.
|
||
|
Used by the extension to decide on the authentication when sending mail.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Oded Sacher (OdedS), Mar, 2001
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pServerRecieptConfig [in ] - Pointer to a private server reciepts configuration struct to be freed.
|
||
|
fDestroy [in ] - TRUE if to free the struct as well
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Win32 error code
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DEBUG_FUNCTION_NAME(TEXT("FreeRecieptsConfiguration"));
|
||
|
|
||
|
Assert (pServerRecieptConfig);
|
||
|
|
||
|
MemFree(pServerRecieptConfig->lptstrSMTPServer);
|
||
|
pServerRecieptConfig->lptstrSMTPServer = NULL;
|
||
|
|
||
|
MemFree(pServerRecieptConfig->lptstrSMTPFrom);
|
||
|
pServerRecieptConfig->lptstrSMTPFrom = NULL;
|
||
|
|
||
|
MemFree(pServerRecieptConfig->lptstrSMTPUserName);
|
||
|
pServerRecieptConfig->lptstrSMTPUserName = NULL;
|
||
|
|
||
|
if (NULL != pServerRecieptConfig->lptstrSMTPPassword)
|
||
|
{
|
||
|
SecureZeroMemory(pServerRecieptConfig->lptstrSMTPPassword, _tcslen(pServerRecieptConfig->lptstrSMTPPassword)*sizeof(TCHAR));
|
||
|
MemFree(pServerRecieptConfig->lptstrSMTPPassword);
|
||
|
pServerRecieptConfig->lptstrSMTPPassword = NULL;
|
||
|
}
|
||
|
|
||
|
if (NULL != pServerRecieptConfig->hLoggedOnUser )
|
||
|
{
|
||
|
if (!CloseHandle(pServerRecieptConfig->hLoggedOnUser))
|
||
|
{
|
||
|
DebugPrintEx(
|
||
|
DEBUG_ERR,
|
||
|
TEXT("CloseHandle failed. (ec: %ld)"),
|
||
|
GetLastError());
|
||
|
}
|
||
|
pServerRecieptConfig->hLoggedOnUser = NULL;
|
||
|
}
|
||
|
if (TRUE == fDestroy)
|
||
|
{
|
||
|
MemFree (pServerRecieptConfig);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|