1463 lines
40 KiB
C
1463 lines
40 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
|
|
|
|
|
|
|
|
BOOL
|
|
BuildRouteInfo(
|
|
LPWSTR TiffFileName,
|
|
PROUTE_FAILURE_INFO RouteFailure,
|
|
DWORD RouteFailureCount,
|
|
LPWSTR ReceiverName,
|
|
LPWSTR ReceiverNumber,
|
|
LPWSTR DeviceName,
|
|
LPWSTR Tsid,
|
|
LPWSTR Csid,
|
|
LPWSTR CallerId,
|
|
LPWSTR RoutingInfo,
|
|
DWORDLONG ElapsedTime
|
|
);
|
|
|
|
extern DWORD FaxPrinters;
|
|
|
|
LPVOID InboundProfileInfo;
|
|
LPTSTR InboundProfileName;
|
|
LIST_ENTRY RoutingExtensions;
|
|
LIST_ENTRY RoutingMethods;
|
|
DWORD CountRoutingMethods;
|
|
CRITICAL_SECTION CsRouting;
|
|
BOOL RoutingIsInitialized = FALSE;
|
|
|
|
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,&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( &CsJob );
|
|
EnterCriticalSection( &CsQueue );
|
|
JobQueueEntry->CountFaxRouteFiles += 1;
|
|
Count = JobQueueEntry->CountFaxRouteFiles;
|
|
LeaveCriticalSection( &CsQueue );
|
|
LeaveCriticalSection( &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( &CsJob );
|
|
EnterCriticalSection( &CsQueue );
|
|
JobQueueEntry->CountFaxRouteFiles -= 1;
|
|
LeaveCriticalSection( &CsQueue );
|
|
LeaveCriticalSection( &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 NextMethod;
|
|
PROUTING_METHOD RoutingMethod;
|
|
GUID RoutingGuid;
|
|
|
|
|
|
IIDFromString( (LPWSTR)RoutingGuidString, &RoutingGuid );
|
|
|
|
EnterCriticalSection( &CsRouting );
|
|
|
|
NextMethod = RoutingMethods.Flink;
|
|
if (NextMethod == NULL) {
|
|
LeaveCriticalSection( &CsRouting );
|
|
return NULL;
|
|
}
|
|
|
|
while ((ULONG_PTR)NextMethod != (ULONG_PTR)&RoutingMethods) {
|
|
RoutingMethod = CONTAINING_RECORD( NextMethod, ROUTING_METHOD, ListEntryMethod );
|
|
NextMethod = RoutingMethod->ListEntryMethod.Flink;
|
|
if (IsEqualGUID( &RoutingGuid, &RoutingMethod->Guid )) {
|
|
LeaveCriticalSection( &CsRouting );
|
|
return RoutingMethod;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection( &CsRouting );
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
DWORD
|
|
EnumerateRoutingMethods(
|
|
IN PFAXROUTEMETHODENUM Enumerator,
|
|
IN LPVOID Context
|
|
)
|
|
{
|
|
PLIST_ENTRY NextMethod;
|
|
PROUTING_METHOD RoutingMethod;
|
|
DWORD Count = 0;
|
|
|
|
|
|
EnterCriticalSection( &CsRouting );
|
|
|
|
__try {
|
|
|
|
NextMethod = RoutingMethods.Flink;
|
|
if (NextMethod == NULL) {
|
|
LeaveCriticalSection( &CsRouting );
|
|
return Count;
|
|
}
|
|
|
|
|
|
while ((ULONG_PTR)NextMethod != (ULONG_PTR)&RoutingMethods) {
|
|
RoutingMethod = CONTAINING_RECORD( NextMethod, ROUTING_METHOD, ListEntryMethod );
|
|
NextMethod = RoutingMethod->ListEntryMethod.Flink;
|
|
if (!Enumerator( RoutingMethod, Context )) {
|
|
LeaveCriticalSection( &CsRouting );
|
|
return Count;
|
|
}
|
|
Count += 1;
|
|
}
|
|
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
DebugPrint(( TEXT("EnumerateRoutingMethods crashed, ec = %x\n"), GetExceptionCode() ));
|
|
}
|
|
|
|
LeaveCriticalSection( &CsRouting );
|
|
|
|
return Count;
|
|
}
|
|
|
|
|
|
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 Next;
|
|
PROUTING_METHOD RoutingMethod;
|
|
PMETHOD_SORT MethodSort;
|
|
DWORD i;
|
|
|
|
|
|
EnterCriticalSection( &CsRouting );
|
|
|
|
Next = RoutingMethods.Flink;
|
|
if (Next == NULL) {
|
|
LeaveCriticalSection( &CsRouting );
|
|
return FALSE;
|
|
}
|
|
|
|
MethodSort = (PMETHOD_SORT) MemAlloc( CountRoutingMethods * sizeof(METHOD_SORT) );
|
|
if (MethodSort == NULL) {
|
|
LeaveCriticalSection( &CsRouting );
|
|
return FALSE;
|
|
}
|
|
|
|
i = 0;
|
|
|
|
while ((ULONG_PTR)Next != (ULONG_PTR)&RoutingMethods) {
|
|
RoutingMethod = CONTAINING_RECORD( Next, ROUTING_METHOD, ListEntryMethod );
|
|
Next = RoutingMethod->ListEntryMethod.Flink;
|
|
MethodSort[i].Priority = RoutingMethod->Priority;
|
|
MethodSort[i].RoutingMethod = RoutingMethod;
|
|
i += 1;
|
|
}
|
|
|
|
qsort(
|
|
(PVOID)MethodSort,
|
|
(int)CountRoutingMethods,
|
|
sizeof(METHOD_SORT),
|
|
MethodPriorityCompare
|
|
);
|
|
|
|
InitializeListHead( &RoutingMethods );
|
|
|
|
for (i=0; i<CountRoutingMethods; i++) {
|
|
MethodSort[i].RoutingMethod->Priority = i + 1;
|
|
MethodSort[i].RoutingMethod->ListEntryMethod.Flink = NULL;
|
|
MethodSort[i].RoutingMethod->ListEntryMethod.Blink = NULL;
|
|
InsertTailList( &RoutingMethods, &MethodSort[i].RoutingMethod->ListEntryMethod );
|
|
}
|
|
|
|
MemFree( MethodSort );
|
|
|
|
LeaveCriticalSection( &CsRouting );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CommitMethodChanges(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
sticks changes to routing into the registry
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Return Value:
|
|
|
|
TRUE for success
|
|
|
|
--*/
|
|
{
|
|
PLIST_ENTRY Next;
|
|
PROUTING_METHOD RoutingMethod;
|
|
TCHAR StrGuid[100];
|
|
|
|
__try {
|
|
EnterCriticalSection(&CsRouting);
|
|
|
|
Next = RoutingMethods.Flink;
|
|
|
|
while ((UINT_PTR)Next != (UINT_PTR)&RoutingMethods) {
|
|
|
|
RoutingMethod = CONTAINING_RECORD( Next, ROUTING_METHOD , ListEntryMethod );
|
|
Next = RoutingMethod->ListEntryMethod.Flink;
|
|
|
|
StringFromGUID2( &RoutingMethod->Guid,
|
|
StrGuid,
|
|
sizeof(StrGuid)/sizeof(TCHAR)
|
|
);
|
|
|
|
SetFaxRoutingInfo( RoutingMethod->RoutingExtension->InternalName,
|
|
RoutingMethod->InternalName,
|
|
StrGuid,
|
|
RoutingMethod->Priority,
|
|
RoutingMethod->FunctionName,
|
|
RoutingMethod->FriendlyName
|
|
);
|
|
}
|
|
|
|
LeaveCriticalSection(&CsRouting);
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
LeaveCriticalSection(&CsRouting);
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
BOOL
|
|
InitializeRouting(
|
|
PREG_FAX_SERVICE FaxReg
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initializes routing
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD i,j;
|
|
HMODULE hModule;
|
|
PROUTING_EXTENSION RoutingExtension;
|
|
PROUTING_METHOD RoutingMethod;
|
|
LPSTR ProcName;
|
|
FAX_ROUTE_CALLBACKROUTINES Callbacks;
|
|
BOOL InitializationSuccess;
|
|
|
|
|
|
FaxMapiInitialize( FaxSvcHeapHandle, ServiceMessageBox, ServiceDebug );
|
|
|
|
InitializeListHead( &RoutingExtensions );
|
|
InitializeListHead( &RoutingMethods );
|
|
|
|
Callbacks.SizeOfStruct = sizeof(FAX_ROUTE_CALLBACKROUTINES);
|
|
Callbacks.FaxRouteAddFile = FaxRouteAddFile;
|
|
Callbacks.FaxRouteDeleteFile = FaxRouteDeleteFile;
|
|
Callbacks.FaxRouteGetFile = FaxRouteGetFile;
|
|
Callbacks.FaxRouteEnumFiles = FaxRouteEnumFiles;
|
|
Callbacks.FaxRouteModifyRoutingData = FaxRouteModifyRoutingData;
|
|
|
|
InitializationSuccess = TRUE;
|
|
for (i=0; i<FaxReg->RoutingExtensionsCount; i++) {
|
|
|
|
|
|
hModule = LoadLibrary( FaxReg->RoutingExtensions[i].ImageName );
|
|
if (!hModule) {
|
|
DebugStop(( L"LoadLibrary() failed: [%s], ec=%d", FaxReg->RoutingExtensions[i].ImageName, GetLastError() ));
|
|
goto InitializationFailed;
|
|
}
|
|
|
|
RoutingExtension = (PROUTING_EXTENSION) MemAlloc( sizeof(ROUTING_EXTENSION) );
|
|
if (!RoutingExtension) {
|
|
FreeLibrary( hModule );
|
|
DebugStop(( L"Could not allocate memory for routing extension %s", FaxReg->RoutingExtensions[i].ImageName ));
|
|
goto InitializationFailed;
|
|
}
|
|
|
|
RoutingExtension->hModule = hModule;
|
|
|
|
wcscpy( RoutingExtension->FriendlyName, FaxReg->RoutingExtensions[i].FriendlyName );
|
|
wcscpy( RoutingExtension->ImageName, FaxReg->RoutingExtensions[i].ImageName );
|
|
wcscpy( RoutingExtension->InternalName, FaxReg->RoutingExtensions[i].InternalName );
|
|
|
|
if (wcscmp( RoutingExtension->FriendlyName, FAX_EXTENSION_NAME ) == 0) {
|
|
RoutingExtension->MicrosoftExtension = TRUE;
|
|
}
|
|
|
|
RoutingExtension->FaxRouteInitialize = (PFAXROUTEINITIALIZE) GetProcAddress(
|
|
hModule,
|
|
"FaxRouteInitialize"
|
|
);
|
|
|
|
RoutingExtension->FaxRouteGetRoutingInfo = (PFAXROUTEGETROUTINGINFO) GetProcAddress(
|
|
hModule,
|
|
"FaxRouteGetRoutingInfo"
|
|
);
|
|
|
|
RoutingExtension->FaxRouteSetRoutingInfo = (PFAXROUTESETROUTINGINFO) GetProcAddress(
|
|
hModule,
|
|
"FaxRouteSetRoutingInfo"
|
|
);
|
|
|
|
RoutingExtension->FaxRouteDeviceEnable = (PFAXROUTEDEVICEENABLE) GetProcAddress(
|
|
hModule,
|
|
"FaxRouteDeviceEnable"
|
|
);
|
|
|
|
RoutingExtension->FaxRouteDeviceChangeNotification = (PFAXROUTEDEVICECHANGENOTIFICATION) GetProcAddress(
|
|
hModule,
|
|
"FaxRouteDeviceChangeNotification"
|
|
);
|
|
|
|
if (RoutingExtension->FaxRouteInitialize == NULL ||
|
|
RoutingExtension->FaxRouteGetRoutingInfo == NULL ||
|
|
RoutingExtension->FaxRouteSetRoutingInfo == NULL ||
|
|
RoutingExtension->FaxRouteDeviceChangeNotification == NULL ||
|
|
RoutingExtension->FaxRouteDeviceEnable == NULL)
|
|
{
|
|
//
|
|
// the routing extension dll does not have a complete export list
|
|
//
|
|
|
|
MemFree( RoutingExtension );
|
|
FreeLibrary( hModule );
|
|
DebugStop(( L"Routing extension FAILED to initialized [%s]", FaxReg->RoutingExtensions[i].FriendlyName ));
|
|
goto InitializationFailed;
|
|
|
|
}
|
|
|
|
//
|
|
// create the routing extension's heap and add it to the list
|
|
//
|
|
|
|
RoutingExtension->HeapHandle = RoutingExtension->MicrosoftExtension ? FaxSvcHeapHandle : HeapCreate( 0, 1024*100, 1024*1024*2 );
|
|
if (!RoutingExtension->HeapHandle) {
|
|
|
|
FreeLibrary( hModule );
|
|
MemFree( RoutingExtension );
|
|
goto InitializationFailed;
|
|
|
|
} else {
|
|
|
|
__try {
|
|
if (RoutingExtension->FaxRouteInitialize( RoutingExtension->HeapHandle, &Callbacks )) {
|
|
|
|
InsertTailList( &RoutingExtensions, &RoutingExtension->ListEntry );
|
|
InitializeListHead( &RoutingExtension->RoutingMethods );
|
|
for (j=0; j<FaxReg->RoutingExtensions[i].RoutingMethodsCount; j++) {
|
|
|
|
RoutingMethod = (PROUTING_METHOD) MemAlloc( sizeof(ROUTING_METHOD) );
|
|
if (!RoutingMethod) {
|
|
DebugStop(( L"Could not allocate memory for routing method %s", FaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName ));
|
|
goto InitializationFailed;
|
|
}
|
|
|
|
RoutingMethod->RoutingExtension = RoutingExtension;
|
|
|
|
RoutingMethod->Priority = FaxReg->RoutingExtensions[i].RoutingMethods[j].Priority;
|
|
|
|
RoutingMethod->FriendlyName = StringDup( FaxReg->RoutingExtensions[i].RoutingMethods[j].FriendlyName );
|
|
if (!RoutingMethod->FriendlyName) {
|
|
DebugStop(( L"Could not create routing function name [%s]", FaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName ));
|
|
MemFree( RoutingMethod );
|
|
goto InitializationFailed;
|
|
}
|
|
|
|
RoutingMethod->FunctionName = StringDup( FaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName );
|
|
if (!RoutingMethod->FunctionName) {
|
|
DebugStop(( L"Could not create routing function name [%s]", FaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName ));
|
|
MemFree( RoutingMethod );
|
|
goto InitializationFailed;
|
|
}
|
|
|
|
RoutingMethod->InternalName = StringDup( FaxReg->RoutingExtensions[i].RoutingMethods[j].InternalName );
|
|
if (!RoutingMethod->InternalName) {
|
|
DebugStop(( L"Could not create routing internal name [%s]", FaxReg->RoutingExtensions[i].RoutingMethods[j].InternalName ));
|
|
MemFree( RoutingMethod );
|
|
goto InitializationFailed;
|
|
}
|
|
|
|
ProcName = UnicodeStringToAnsiString( RoutingMethod->FunctionName );
|
|
if (!ProcName) {
|
|
DebugStop(( L"Could not create routing function name [%s]", RoutingMethod->FunctionName ));
|
|
MemFree( RoutingMethod );
|
|
goto InitializationFailed;
|
|
}
|
|
|
|
if (IIDFromString( FaxReg->RoutingExtensions[i].RoutingMethods[j].Guid, &RoutingMethod->Guid ) != S_OK) {
|
|
DebugStop(( L"Invalid GUID string [%s]", FaxReg->RoutingExtensions[i].RoutingMethods[j].Guid ));
|
|
MemFree( RoutingMethod );
|
|
goto InitializationFailed;
|
|
}
|
|
|
|
RoutingMethod->FaxRouteMethod = (PFAXROUTEMETHOD) GetProcAddress(
|
|
hModule,
|
|
ProcName
|
|
);
|
|
if (!RoutingMethod->FaxRouteMethod) {
|
|
|
|
DebugStop(( L"Could not get function address [%s]", ProcName ));
|
|
MemFree( RoutingMethod );
|
|
MemFree( ProcName );
|
|
|
|
} else {
|
|
|
|
MemFree( ProcName );
|
|
InsertTailList( &RoutingExtension->RoutingMethods, &RoutingMethod->ListEntry );
|
|
InsertTailList( &RoutingMethods, &RoutingMethod->ListEntryMethod );
|
|
CountRoutingMethods += 1;
|
|
|
|
}
|
|
}
|
|
|
|
} else {
|
|
FreeLibrary( hModule );
|
|
MemFree( RoutingExtension );
|
|
}
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
DebugStop(( L"FaxRouteInitialize() faulted: 0x%08x", GetExceptionCode() ));
|
|
goto InitializationFailed;
|
|
}
|
|
}
|
|
//
|
|
// success initializing this extension
|
|
//
|
|
goto next;
|
|
|
|
InitializationFailed:
|
|
FaxLog(
|
|
FAXLOG_CATEGORY_INIT,
|
|
FAXLOG_LEVEL_NONE,
|
|
2,
|
|
MSG_ROUTE_INIT_FAILED,
|
|
FaxReg->RoutingExtensions[i].FriendlyName,
|
|
FaxReg->RoutingExtensions[i].ImageName
|
|
);
|
|
|
|
next:
|
|
;
|
|
}
|
|
|
|
if (FaxReg->InboundProfile && FaxReg->InboundProfile[0]) {
|
|
InboundProfileName = StringDup( FaxReg->InboundProfile );
|
|
InboundProfileInfo = AddNewMapiProfile( FaxReg->InboundProfile, TRUE, TRUE );
|
|
if (!InboundProfileInfo) {
|
|
DebugStop(( L"Could not initialize inbound mapi profile [%s]", FaxReg->InboundProfile ));
|
|
}
|
|
}
|
|
|
|
SortMethodPriorities();
|
|
|
|
RoutingIsInitialized = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
LPWSTR
|
|
TiffFileNameToRouteFileName(
|
|
LPWSTR TiffFileName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert a tiff file name to a routing information file name. The call MUST free
|
|
the memory allocated by this routine.
|
|
|
|
Arguments:
|
|
|
|
TiffFileName - pointer to tiff file name
|
|
|
|
Return value:
|
|
|
|
A pointer to a routing information file name on success, NULL on fail.
|
|
|
|
--*/
|
|
|
|
{
|
|
LPWSTR RouteFileName;
|
|
LPWSTR Ext;
|
|
|
|
RouteFileName = StringDup( TiffFileName );
|
|
|
|
if (!RouteFileName) {
|
|
return NULL;
|
|
}
|
|
|
|
Ext = wcsrchr( RouteFileName, L'.' );
|
|
|
|
if (Ext) {
|
|
|
|
wcscpy( Ext, L".rte" );
|
|
return RouteFileName;
|
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
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:
|
|
|
|
ignored for now
|
|
|
|
--*/
|
|
|
|
{
|
|
LPWSTR FullPath = NULL;
|
|
LPWSTR RouteFileName = TiffFileNameToRouteFileName( TiffFileName );
|
|
LPJOB_INFO_2 JobInfo = NULL;
|
|
PLIST_ENTRY NextMethod;
|
|
PROUTING_METHOD RoutingMethod;
|
|
DWORD FailureCount = 0;
|
|
PROUTE_FAILURE_INFO RouteFailure;
|
|
PLIST_ENTRY NextRoutingOverride;
|
|
PROUTING_DATA_OVERRIDE RoutingDataOverride;
|
|
BOOL RetVal = TRUE;
|
|
|
|
*RouteFailureInfo = NULL;
|
|
*RouteFailureCount = 0;
|
|
|
|
//
|
|
// if the tiff file has been deleted, delete the routing info file and return
|
|
//
|
|
|
|
if (GetFileAttributes( TiffFileName ) == 0xffffffff) {
|
|
DeleteFile( RouteFileName );
|
|
MemFree( RouteFileName );
|
|
return FALSE;
|
|
}
|
|
|
|
EnterCriticalSection( &CsRouting );
|
|
|
|
NextMethod = RoutingMethods.Flink;
|
|
if (NextMethod) {
|
|
|
|
//
|
|
// allocate memory to record the GUIDs of the failed routing methods
|
|
//
|
|
|
|
RouteFailure = (PROUTE_FAILURE_INFO) MemAlloc( CountRoutingMethods * sizeof(ROUTE_FAILURE_INFO) );
|
|
if (RouteFailure == NULL) {
|
|
MemFree( RouteFileName );
|
|
LeaveCriticalSection( &CsRouting );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// add the tiff file as the first file
|
|
// in the file name list, the owner is the fax service
|
|
//
|
|
|
|
if (FaxRouteAddFile( FaxRoute->JobId, TiffFileName, &FaxSvcGuid ) < 1) {
|
|
LeaveCriticalSection( &CsRouting );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// walk thru all of the routing methods and call them
|
|
//
|
|
|
|
while ((ULONG_PTR)NextMethod != (ULONG_PTR)&RoutingMethods) {
|
|
RoutingMethod = CONTAINING_RECORD( NextMethod, ROUTING_METHOD, ListEntryMethod );
|
|
NextMethod = RoutingMethod->ListEntryMethod.Flink;
|
|
|
|
__try {
|
|
|
|
FaxRoute->RoutingInfoData = NULL;
|
|
FaxRoute->RoutingInfoDataSize = 0;
|
|
|
|
EnterCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
|
|
|
|
NextRoutingOverride = JobQueueEntry->RoutingDataOverride.Flink;
|
|
if (NextRoutingOverride != NULL) {
|
|
while ((ULONG_PTR)NextRoutingOverride != (ULONG_PTR)&JobQueueEntry->RoutingDataOverride) {
|
|
RoutingDataOverride = CONTAINING_RECORD( NextRoutingOverride, ROUTING_DATA_OVERRIDE, ListEntry );
|
|
NextRoutingOverride = RoutingDataOverride->ListEntry.Flink;
|
|
if (RoutingDataOverride->RoutingMethod == RoutingMethod) {
|
|
FaxRoute->RoutingInfoData = RoutingDataOverride->RoutingData;
|
|
FaxRoute->RoutingInfoDataSize = RoutingDataOverride->RoutingDataSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
|
|
|
|
RouteFailure[FailureCount].FailureData = NULL;
|
|
RouteFailure[FailureCount].FailureSize = 0;
|
|
|
|
if (!RoutingMethod->FaxRouteMethod(
|
|
FaxRoute,
|
|
&RouteFailure[FailureCount].FailureData,
|
|
&RouteFailure[FailureCount].FailureSize ))
|
|
{
|
|
StringFromGUID2(
|
|
&RoutingMethod->Guid,
|
|
RouteFailure[FailureCount++].GuidString,
|
|
MAX_GUID_STRING_LEN
|
|
);
|
|
RetVal = FALSE;
|
|
}
|
|
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
DebugStop(( L"FaxRouteProcess() faulted: 0x%08x", GetExceptionCode() ));
|
|
StringFromGUID2(
|
|
&RoutingMethod->Guid,
|
|
RouteFailure[FailureCount++].GuidString,
|
|
MAX_GUID_STRING_LEN
|
|
);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FailureCount == 0) {
|
|
|
|
DeleteFile( TiffFileName );
|
|
MemFree( RouteFailure );
|
|
|
|
} else {
|
|
*RouteFailureInfo = RouteFailure;
|
|
*RouteFailureCount = FailureCount;
|
|
}
|
|
|
|
MemFree( JobInfo );
|
|
MemFree( RouteFileName );
|
|
|
|
LeaveCriticalSection( &CsRouting );
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
#if 0
|
|
HANDLE RouteHandle;
|
|
PROUTE_INFO pRouteInfo = NULL;
|
|
DWORD FileSize;
|
|
DWORD BytesRead;
|
|
LPBYTE Buffer;
|
|
PROUTE_FAILURE_INFO pRouteFailure = NULL;
|
|
DWORD pRouteFailureCount = 0;
|
|
|
|
|
|
RouteHandle = CreateFile(
|
|
RouteFileName,
|
|
GENERIC_READ,
|
|
0,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (RouteHandle == INVALID_HANDLE_VALUE) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// the size of the file is the size of the structure
|
|
//
|
|
|
|
FileSize = GetFileSize( RouteHandle, NULL );
|
|
if (FileSize == 0xffffffff) {
|
|
CloseHandle( RouteHandle );
|
|
return FALSE;
|
|
}
|
|
|
|
Buffer = MemAlloc( FileSize );
|
|
pRouteInfo = (PROUTE_INFO) Buffer;
|
|
if (Buffer == NULL) {
|
|
CloseHandle( RouteHandle );
|
|
return FALSE;
|
|
}
|
|
|
|
if (!ReadFile( RouteHandle, Buffer, FileSize, &BytesRead, NULL) || BytesRead != FileSize ) {
|
|
CloseHandle( RouteHandle );
|
|
return FALSE;
|
|
}
|
|
|
|
CloseHandle( RouteHandle );
|
|
|
|
if (pRouteInfo->Signature != ROUTING_SIGNATURE) {
|
|
CloseHandle( RouteHandle );
|
|
return FALSE;
|
|
}
|
|
|
|
pRouteInfo->TiffFileName = OffsetToString( pRouteInfo->TiffFileName, Buffer );
|
|
pRouteInfo->ReceiverName = OffsetToString( pRouteInfo->ReceiverName, Buffer );
|
|
pRouteInfo->ReceiverNumber = OffsetToString( pRouteInfo->ReceiverNumber, Buffer );
|
|
pRouteInfo->Csid = OffsetToString( pRouteInfo->Csid, Buffer );
|
|
pRouteInfo->CallerId = OffsetToString( pRouteInfo->CallerId, Buffer );
|
|
pRouteInfo->RoutingInfo = OffsetToString( pRouteInfo->RoutingInfo, Buffer );
|
|
pRouteInfo->DeviceName = OffsetToString( pRouteInfo->DeviceName, Buffer );
|
|
pRouteInfo->Tsid = OffsetToString( pRouteInfo->Tsid, Buffer );
|
|
|
|
|
|
//
|
|
// return the data
|
|
//
|
|
|
|
RouteInfo = pRouteInfo;
|
|
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
BuildRouteInfo(
|
|
LPWSTR TiffFileName,
|
|
PROUTE_FAILURE_INFO RouteFailure,
|
|
DWORD RouteFailureCount,
|
|
LPWSTR ReceiverName,
|
|
LPWSTR ReceiverNumber,
|
|
LPWSTR DeviceName,
|
|
LPWSTR Tsid,
|
|
LPWSTR Csid,
|
|
LPWSTR CallerId,
|
|
LPWSTR RoutingInfo,
|
|
DWORDLONG ElapsedTime
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build a routing info structure. The caller MUST free the memory allocated by this routine.
|
|
|
|
Arguments:
|
|
|
|
TiffFileName - File containing the fax tiff data
|
|
ReceiverName - Receiver's name
|
|
ReceiverNumber - Receiver's fax number
|
|
DeviceName - Device name on which the fax was received
|
|
Tsid - Transmitting station identifier
|
|
Csid - Calling station's identifier
|
|
CallerId - Caller id data, if any
|
|
RoutingInfo - Routing info, such as DID, T.30 subaddress, etc
|
|
|
|
Return value:
|
|
|
|
A pointer to a ROUTE_INFO struct on success, NULL on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL Rval = FALSE;
|
|
LPWSTR RouteFileName = NULL;
|
|
HANDLE RouteHandle = INVALID_HANDLE_VALUE;
|
|
DWORD StringSize = 0;
|
|
DWORD FailureSize = 0;
|
|
LPBYTE Buffer = NULL;
|
|
ULONG_PTR Offset = 0;
|
|
PROUTE_INFO RouteInfo = NULL;
|
|
DWORD i = 0;
|
|
|
|
|
|
StringSize += StringSize( TiffFileName );
|
|
StringSize += StringSize( ReceiverName );
|
|
StringSize += StringSize( ReceiverNumber );
|
|
|
|
StringSize += StringSize( Csid );
|
|
StringSize += StringSize( CallerId );
|
|
StringSize += StringSize( RoutingInfo );
|
|
|
|
StringSize += StringSize( DeviceName );
|
|
StringSize += StringSize( Tsid );
|
|
|
|
for (i=0; i<RouteFailureCount; i++) {
|
|
FailureSize += RouteFailure[i].FailureSize;
|
|
FailureSize += MAX_GUID_STRING_LEN;
|
|
}
|
|
|
|
Buffer = MemAlloc( sizeof(ROUTE_INFO) + StringSize + FailureSize );
|
|
if (!Buffer) {
|
|
goto exit;
|
|
}
|
|
|
|
RouteInfo = (PROUTE_INFO) Buffer;
|
|
|
|
RouteInfo->Signature = ROUTING_SIGNATURE;
|
|
RouteInfo->StringSize = StringSize;
|
|
RouteInfo->FailureSize = FailureSize;
|
|
RouteInfo->ElapsedTime = ElapsedTime;
|
|
|
|
Offset = sizeof(ROUTE_INFO);
|
|
|
|
//
|
|
// convert string pointers to offsets
|
|
// and store the strings at the end of the buffer
|
|
//
|
|
|
|
StoreString(
|
|
TiffFileName,
|
|
(PULONG_PTR) &RouteInfo->TiffFileName,
|
|
Buffer,
|
|
&Offset
|
|
);
|
|
|
|
StoreString(
|
|
ReceiverName,
|
|
(PULONG_PTR) &RouteInfo->ReceiverName,
|
|
Buffer,
|
|
&Offset
|
|
);
|
|
|
|
StoreString(
|
|
ReceiverNumber,
|
|
(PULONG_PTR) &RouteInfo->ReceiverNumber,
|
|
Buffer,
|
|
&Offset
|
|
);
|
|
|
|
StoreString(
|
|
Csid,
|
|
(PULONG_PTR) &RouteInfo->Csid,
|
|
Buffer,
|
|
&Offset
|
|
);
|
|
|
|
StoreString(
|
|
Tsid,
|
|
(PULONG_PTR) &RouteInfo->Tsid,
|
|
Buffer,
|
|
&Offset
|
|
);
|
|
|
|
StoreString(
|
|
CallerId,
|
|
(PULONG_PTR) &RouteInfo->CallerId,
|
|
Buffer,
|
|
&Offset
|
|
);
|
|
|
|
StoreString(
|
|
RoutingInfo,
|
|
(PULONG_PTR) &RouteInfo->RoutingInfo,
|
|
Buffer,
|
|
&Offset
|
|
);
|
|
|
|
StoreString(
|
|
DeviceName,
|
|
(PULONG_PTR) &RouteInfo->DeviceName,
|
|
Buffer,
|
|
&Offset
|
|
);
|
|
|
|
//
|
|
// store the routing failure data
|
|
//
|
|
|
|
*(LPDWORD) (Buffer + Offset) = RouteFailureCount;
|
|
Offset += sizeof(DWORD);
|
|
|
|
for (i=0; i<RouteFailureCount; i++) {
|
|
CopyMemory( Buffer+Offset, RouteFailure[i].FailureData, RouteFailure[i].FailureSize );
|
|
Offset += RouteFailure[i].FailureSize;
|
|
}
|
|
|
|
|
|
RouteFileName = TiffFileNameToRouteFileName( TiffFileName );
|
|
|
|
RouteHandle = CreateFile(
|
|
RouteFileName,
|
|
GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (RouteHandle == INVALID_HANDLE_VALUE) {
|
|
goto exit;
|
|
}
|
|
|
|
WriteFile(
|
|
RouteHandle,
|
|
Buffer,
|
|
sizeof(ROUTE_INFO) + StringSize + FailureSize,
|
|
&i,
|
|
NULL
|
|
);
|
|
|
|
Rval = TRUE;
|
|
|
|
exit:
|
|
|
|
if (RouteHandle != INVALID_HANDLE_VALUE) {
|
|
CloseHandle( RouteHandle );
|
|
}
|
|
|
|
MemFree( Buffer );
|
|
MemFree( RouteFileName );
|
|
|
|
return Rval;
|
|
}
|
|
|
|
BOOL
|
|
FaxRouteRetry(
|
|
PFAX_ROUTE FaxRoute,
|
|
PROUTE_FAILURE_INFO RouteFailureInfo
|
|
)
|
|
{
|
|
PROUTING_METHOD RoutingMethod;
|
|
DWORD FailureCount = 0;
|
|
BOOL RetVal = TRUE;
|
|
|
|
|
|
//
|
|
// in this case, we've already retried this method and it succeeded.
|
|
//
|
|
if (!*RouteFailureInfo->GuidString) {
|
|
return TRUE;
|
|
}
|
|
|
|
RoutingMethod = FindRoutingMethodByGuid( RouteFailureInfo->GuidString );
|
|
|
|
if (RoutingMethod) {
|
|
__try {
|
|
|
|
if (!RoutingMethod->FaxRouteMethod(
|
|
FaxRoute,
|
|
&RouteFailureInfo->FailureData,
|
|
&RouteFailureInfo->FailureSize ))
|
|
{
|
|
RetVal = 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(RouteFailureInfo->GuidString, MAX_GUID_STRING_LEN*sizeof(WCHAR) );
|
|
}
|
|
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
DebugStop(( L"FaxRouteProcess() faulted: 0x%08x", GetExceptionCode() ));
|
|
|
|
}
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
|
|
return RetVal;
|
|
}
|
|
|
|
PFAX_ROUTE
|
|
SerializeFaxRoute(
|
|
PFAX_ROUTE FaxRoute,
|
|
LPDWORD Size
|
|
)
|
|
{
|
|
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;
|
|
|
|
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 );
|
|
StoreString( FaxRoute->Tsid, (PDWORD_PTR)&SerFaxRoute->Tsid, (LPBYTE) SerFaxRoute, &Offset );
|
|
StoreString( FaxRoute->CallerId, (PDWORD_PTR)&SerFaxRoute->CallerId, (LPBYTE) SerFaxRoute, &Offset );
|
|
StoreString( FaxRoute->RoutingInfo, (PDWORD_PTR)&SerFaxRoute->RoutingInfo, (LPBYTE) SerFaxRoute, &Offset );
|
|
StoreString( FaxRoute->ReceiverName, (PDWORD_PTR)&SerFaxRoute->ReceiverName, (LPBYTE) SerFaxRoute, &Offset );
|
|
StoreString( FaxRoute->ReceiverNumber, (PDWORD_PTR)&SerFaxRoute->ReceiverNumber, (LPBYTE) SerFaxRoute, &Offset );
|
|
StoreString( FaxRoute->DeviceName, (PDWORD_PTR)&SerFaxRoute->DeviceName, (LPBYTE) SerFaxRoute, &Offset );
|
|
|
|
FaxRoute->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;
|
|
|
|
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 = MemAlloc( sizeof( FAX_ROUTE ) );
|
|
|
|
if (NewFaxRoute) {
|
|
|
|
CopyMemory( (LPBYTE) NewFaxRoute, (LPBYTE) FaxRoute, sizeof(FAX_ROUTE) );
|
|
|
|
NewFaxRoute->Csid = StringDup( FaxRoute->Csid );
|
|
NewFaxRoute->Tsid = StringDup( FaxRoute->Tsid );
|
|
NewFaxRoute->CallerId = StringDup( FaxRoute->CallerId );
|
|
NewFaxRoute->RoutingInfo = StringDup( FaxRoute->RoutingInfo );
|
|
NewFaxRoute->ReceiverName = StringDup( FaxRoute->ReceiverName );
|
|
NewFaxRoute->DeviceName = StringDup( FaxRoute->DeviceName );
|
|
NewFaxRoute->ReceiverNumber = StringDup( FaxRoute->ReceiverNumber );
|
|
|
|
NewFaxRoute->RoutingInfoData = MemAlloc( FaxRoute->RoutingInfoDataSize );
|
|
|
|
if (NewFaxRoute->RoutingInfoData) {
|
|
CopyMemory( NewFaxRoute->RoutingInfoData, FaxRoute->RoutingInfoData, FaxRoute->RoutingInfoDataSize );
|
|
}
|
|
|
|
}
|
|
|
|
MemFree( FaxRoute );
|
|
|
|
return NewFaxRoute;
|
|
}
|
|
|