You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1393 lines
41 KiB
1393 lines
41 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
clirpc.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the client side RPC
|
|
functions. These functions are used when the
|
|
WINFAX client runs as an RPC server too. These
|
|
functions are the ones available for the RPC
|
|
clients to call. Currently the only client
|
|
of these functions is the fax service.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 29-Nov-1996
|
|
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "faxapi.h"
|
|
#include "CritSec.h"
|
|
#pragma hdrstop
|
|
|
|
extern CFaxCriticalSection g_CsFaxAssyncInfo; // used to synchronize access to the assync info structures (notification context)
|
|
extern DWORD g_dwFaxClientRpcNumInst;
|
|
extern TCHAR g_tszEndPoint[MAX_ENDPOINT_LEN];
|
|
|
|
static const ASYNC_EVENT_INFO g_scBadAsyncInfo = {0}; // this ASYNC_EVENT_INFO structure will be used as a return value for
|
|
// malicious RPC calls.
|
|
|
|
BOOL
|
|
ValidAsyncInfoSignature (PASYNC_EVENT_INFO pAsyncInfo);
|
|
|
|
|
|
|
|
|
|
VOID
|
|
WINAPI
|
|
FaxFreeBuffer(
|
|
LPVOID Buffer
|
|
)
|
|
{
|
|
MemFree( Buffer );
|
|
}
|
|
|
|
|
|
void *
|
|
MIDL_user_allocate(
|
|
IN size_t NumBytes
|
|
)
|
|
{
|
|
return MemAlloc( NumBytes );
|
|
}
|
|
|
|
|
|
void
|
|
MIDL_user_free(
|
|
IN void *MemPointer
|
|
)
|
|
{
|
|
MemFree( MemPointer );
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FaxStartServerNotification (
|
|
IN HANDLE hFaxHandle,
|
|
IN DWORD dwEventTypes,
|
|
IN HANDLE hCompletionPort,
|
|
IN ULONG_PTR upCompletionKey,
|
|
IN HWND hWnd,
|
|
IN DWORD dwMessage,
|
|
IN BOOL bEventEx,
|
|
OUT LPHANDLE lphEvent
|
|
)
|
|
{
|
|
PASYNC_EVENT_INFO AsyncInfo = NULL;
|
|
error_status_t ec = ERROR_SUCCESS;
|
|
TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
|
|
WCHAR ComputerNameW[MAX_COMPUTERNAME_LENGTH + 1];
|
|
WCHAR wszEndPoint[MAX_ENDPOINT_LEN] = {0};
|
|
DWORD Size;
|
|
BOOL RpcServerStarted = FALSE;
|
|
HANDLE hServerContext;
|
|
DEBUG_FUNCTION_NAME(TEXT("FaxStartServerNotification"));
|
|
|
|
if (!ValidateFaxHandle(hFaxHandle, FHT_SERVICE))
|
|
{
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() failed."));
|
|
return FALSE;
|
|
}
|
|
|
|
if ((hCompletionPort && hWnd) || (!hCompletionPort && !hWnd))
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
DebugPrintEx(DEBUG_ERR, _T("(hCompletionPort && hWnd) || (!hCompletionPort && !hWnd)."));
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef WIN95
|
|
if (NULL != hCompletionPort)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Win95 does not support completion port"));
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
#endif // WIN95
|
|
|
|
if (hWnd && dwMessage < WM_USER)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("dwMessage must be equal to/greater than WM_USER"));
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
|
|
if (TRUE == bEventEx)
|
|
{
|
|
if (!((dwEventTypes & FAX_EVENT_TYPE_IN_QUEUE) ||
|
|
(dwEventTypes & FAX_EVENT_TYPE_OUT_QUEUE) ||
|
|
(dwEventTypes & FAX_EVENT_TYPE_CONFIG) ||
|
|
(dwEventTypes & FAX_EVENT_TYPE_ACTIVITY) ||
|
|
(dwEventTypes & FAX_EVENT_TYPE_QUEUE_STATE) ||
|
|
(dwEventTypes & FAX_EVENT_TYPE_IN_ARCHIVE) ||
|
|
(dwEventTypes & FAX_EVENT_TYPE_OUT_ARCHIVE) ||
|
|
(dwEventTypes & FAX_EVENT_TYPE_FXSSVC_ENDED) ||
|
|
(dwEventTypes & FAX_EVENT_TYPE_DEVICE_STATUS) ||
|
|
(dwEventTypes & FAX_EVENT_TYPE_NEW_CALL)))
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("dwEventTypes is invalid - No valid event type indicated"));
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
|
|
if ( 0 != (dwEventTypes & ~(FAX_EVENT_TYPE_IN_QUEUE |
|
|
FAX_EVENT_TYPE_OUT_QUEUE |
|
|
FAX_EVENT_TYPE_CONFIG |
|
|
FAX_EVENT_TYPE_ACTIVITY |
|
|
FAX_EVENT_TYPE_QUEUE_STATE |
|
|
FAX_EVENT_TYPE_IN_ARCHIVE |
|
|
FAX_EVENT_TYPE_OUT_ARCHIVE |
|
|
FAX_EVENT_TYPE_FXSSVC_ENDED |
|
|
FAX_EVENT_TYPE_DEVICE_STATUS|
|
|
FAX_EVENT_TYPE_NEW_CALL ) ))
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("dwEventTypes is invalid - contains invalid event type bits"));
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Assert (FAX_EVENT_TYPE_LEGACY == dwEventTypes);
|
|
}
|
|
|
|
//
|
|
// Get host name
|
|
//
|
|
Size = sizeof(ComputerName) / sizeof(TCHAR);
|
|
if (!GetComputerName( ComputerName, &Size ))
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("GetComputerName failed (ec = %ld)"),
|
|
GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
AsyncInfo = (PASYNC_EVENT_INFO) MemAlloc( sizeof(ASYNC_EVENT_INFO) );
|
|
if (!AsyncInfo)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Can't allocate ASTNC_EVENT_INFO"));
|
|
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
_tcscpy (AsyncInfo->tszSignature, ASYNC_EVENT_INFO_SIGNATURE);
|
|
AsyncInfo->bEventEx = bEventEx;
|
|
AsyncInfo->CompletionPort = NULL;
|
|
AsyncInfo->hWindow = NULL;
|
|
AsyncInfo->hBinding = NULL;
|
|
AsyncInfo->bLocalNotificationsOnly = FH_DATA(hFaxHandle)->bLocalConnection; // Fax client asked for notification from local or remote fax service.
|
|
AsyncInfo->bInUse = FALSE;
|
|
AsyncInfo->dwServerAPIVersion = FH_DATA(hFaxHandle)->dwServerAPIVersion; // Fax server API version.
|
|
|
|
if (hCompletionPort != NULL)
|
|
{
|
|
//
|
|
// Completion port notifications
|
|
//
|
|
AsyncInfo->CompletionPort = hCompletionPort;
|
|
AsyncInfo->CompletionKey = upCompletionKey;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Window messages notifications
|
|
//
|
|
AsyncInfo->hWindow = hWnd;
|
|
AsyncInfo->MessageStart = dwMessage;
|
|
}
|
|
Assert ((NULL != AsyncInfo->CompletionPort && NULL == AsyncInfo->hWindow) ||
|
|
(NULL == AsyncInfo->CompletionPort && NULL != AsyncInfo->hWindow));
|
|
//
|
|
// We rely on the above assertion when validating the 'Context' parameter (points to this AssyncInfo structure) in
|
|
// Fax_OpenConnection.
|
|
//
|
|
|
|
|
|
//
|
|
// timing: get the server thread up and running before
|
|
// registering with the fax service (our client)
|
|
//
|
|
|
|
ec = StartFaxClientRpcServer();
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("StartFaxClientRpcServer failed (ec = %ld)"),
|
|
ec);
|
|
goto error_exit;
|
|
}
|
|
RpcServerStarted = TRUE;
|
|
Assert (_tcslen(g_tszEndPoint));
|
|
|
|
#ifdef UNICODE
|
|
wcscpy(ComputerNameW,ComputerName);
|
|
wcscpy(wszEndPoint, g_tszEndPoint);
|
|
#else // !UNICODE
|
|
if (0 == MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
ComputerName,
|
|
-1,
|
|
ComputerNameW,
|
|
sizeof(ComputerNameW)/sizeof(ComputerNameW[0])))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("MultiByteToWideChar failed (ec = %ld)"),
|
|
ec);
|
|
goto error_exit;
|
|
}
|
|
|
|
if (0 == MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
g_tszEndPoint,
|
|
-1,
|
|
wszEndPoint,
|
|
sizeof(wszEndPoint)/sizeof(wszEndPoint[0])))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("MultiByteToWideChar failed (ec = %ld)"),
|
|
ec);
|
|
goto error_exit;
|
|
}
|
|
#endif // UNICODE
|
|
|
|
|
|
//
|
|
// Register at the fax server for events
|
|
//
|
|
__try
|
|
{
|
|
ec = FAX_StartServerNotificationEx(
|
|
FH_FAX_HANDLE(hFaxHandle),
|
|
ComputerNameW, // Passed to create RPC binding
|
|
(LPCWSTR)wszEndPoint, // Passed to create RPC binding
|
|
(ULONG64) AsyncInfo, // Passed to the server,
|
|
// the server passes it back to the client with FAX_OpenConnection,
|
|
// and the client returns it back to the server as a context handle.
|
|
L"ncacn_ip_tcp", // For BOS interoperability it must be set to "ncacn_ip_tcp"
|
|
bEventEx, // flag to use FAX_EVENT_EX
|
|
dwEventTypes, // used in FAX_EVENT_EX
|
|
&hServerContext // returns a context handle to the client.
|
|
);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
//
|
|
// For some reason we got an exception.
|
|
//
|
|
ec = GetExceptionCode();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Exception on RPC call to FAX_StartServerNotification/Ex. (ec: %ld)"),
|
|
ec);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
DumpRPCExtendedStatus ();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("FAX_StartServerNotification/Ex failed (ec = %ld)"),
|
|
ec);
|
|
goto error_exit;
|
|
}
|
|
|
|
|
|
if (TRUE == bEventEx)
|
|
{
|
|
*lphEvent = hServerContext;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
error_exit:
|
|
|
|
MemFree(AsyncInfo);
|
|
AsyncInfo = NULL;
|
|
|
|
if (RpcServerStarted)
|
|
{
|
|
//
|
|
// this should also terminate FaxServerThread
|
|
//
|
|
StopFaxClientRpcServer();
|
|
}
|
|
|
|
SetLastError(ec);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FaxRegisterForServerEvents (
|
|
IN HANDLE hFaxHandle,
|
|
IN DWORD dwEventTypes,
|
|
IN HANDLE hCompletionPort,
|
|
IN ULONG_PTR upCompletionKey,
|
|
IN HWND hWnd,
|
|
IN DWORD dwMessage,
|
|
OUT LPHANDLE lphEvent
|
|
)
|
|
{
|
|
return FaxStartServerNotification ( hFaxHandle,
|
|
dwEventTypes,
|
|
hCompletionPort,
|
|
upCompletionKey,
|
|
hWnd,
|
|
dwMessage,
|
|
TRUE, // extended API
|
|
lphEvent
|
|
);
|
|
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
FaxInitializeEventQueue(
|
|
IN HANDLE FaxHandle,
|
|
IN HANDLE CompletionPort,
|
|
IN ULONG_PTR upCompletionKey,
|
|
IN HWND hWnd,
|
|
IN UINT MessageStart
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initializes the client side event queue. There can be one event
|
|
queue initialized for each fax server that the client app is
|
|
connected to.
|
|
|
|
Arguments:
|
|
|
|
FaxHandle - FAX handle obtained from FaxConnectFaxServer.
|
|
CompletionPort - Handle of an existing completion port opened using CreateIoCompletionPort.
|
|
upCompletionKey - A value that will be returned through the upCompletionKey parameter of GetQueuedCompletionStatus.
|
|
hWnd - Window handle to post events to
|
|
MessageStart - Starting message number, message range used is MessageStart + FEI_NEVENTS
|
|
|
|
Return Value:
|
|
|
|
TRUE - Success
|
|
FALSE - Failure, call GetLastError() for more error information.
|
|
|
|
--*/
|
|
|
|
{
|
|
if (hWnd && (upCompletionKey == -1))
|
|
//
|
|
// Backwards compatibility only.
|
|
// See "Receiving Notification Messages from the Fax Service" on MSDN
|
|
//
|
|
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FaxStartServerNotification ( FaxHandle,
|
|
FAX_EVENT_TYPE_LEGACY, //Event type
|
|
CompletionPort,
|
|
upCompletionKey,
|
|
hWnd,
|
|
MessageStart,
|
|
FALSE, // Event Ex
|
|
NULL // Context handle
|
|
);
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FaxUnregisterForServerEvents (
|
|
IN HANDLE hEvent
|
|
)
|
|
/*++
|
|
|
|
Routine name : FaxUnregisterForServerEvents
|
|
|
|
Routine description:
|
|
|
|
A fax client application calls the FaxUnregisterForServerEvents function to stop
|
|
recieving notification.
|
|
|
|
Author:
|
|
|
|
Oded Sacher (OdedS), Dec, 1999
|
|
|
|
Arguments:
|
|
|
|
hEvent [in] - The enumeration handle value.
|
|
This value is obtained by calling FaxRegisterForServerEvents.
|
|
|
|
Return Value:
|
|
|
|
TRUE - Success
|
|
FALSE - Failure, call GetLastError() for more error information.
|
|
|
|
--*/
|
|
{
|
|
error_status_t ec = ERROR_SUCCESS;
|
|
DEBUG_FUNCTION_NAME(TEXT("FaxUnregisterForServerEvents"));
|
|
|
|
if (NULL == hEvent)
|
|
{
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
DebugPrintEx(DEBUG_ERR, _T("hEvent is NULL."));
|
|
return FALSE;
|
|
}
|
|
|
|
__try
|
|
{
|
|
//
|
|
// Attempt to tell the server we are shutting down this notification context
|
|
//
|
|
ec = FAX_EndServerNotification (&hEvent); // this will free Assync info
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
//
|
|
// For some reason we got an exception.
|
|
//
|
|
ec = GetExceptionCode();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Exception on RPC call to FAX_EndServerNotification. (ec: %ld)"),
|
|
ec);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
DumpRPCExtendedStatus ();
|
|
DebugPrintEx(DEBUG_ERR, _T("FAX_EndServerNotification failed. (ec: %ld)"), ec);
|
|
}
|
|
|
|
ec = StopFaxClientRpcServer();
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("StopFaxClientRpcServer failed. (ec: %ld)"),
|
|
ec);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
SetLastError(ec);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
} // FaxUnregisterForServerEvents
|
|
|
|
BOOL
|
|
ValidAsyncInfoSignature (PASYNC_EVENT_INFO pAsyncInfo)
|
|
{
|
|
if (NULL == pAsyncInfo)
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (&g_scBadAsyncInfo == pAsyncInfo)
|
|
{
|
|
//
|
|
// We are under attack!
|
|
//
|
|
return FALSE;
|
|
}
|
|
if (_tcscmp (pAsyncInfo->tszSignature, ASYNC_EVENT_INFO_SIGNATURE))
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
} // ValidAsyncInfoSignature
|
|
|
|
error_status_t
|
|
FAX_OpenConnection(
|
|
IN handle_t hBinding,
|
|
IN ULONG64 Context,
|
|
OUT LPHANDLE FaxHandle
|
|
)
|
|
{
|
|
PASYNC_EVENT_INFO pAsyncInfo = (PASYNC_EVENT_INFO) Context;
|
|
DWORD ec = ERROR_SUCCESS;
|
|
DEBUG_FUNCTION_NAME(TEXT("FAX_OpenConnection"));
|
|
|
|
EnterCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
//
|
|
// Try to access the AssyncInfo structure pointed by 'Context' to verify it is not corrupted.
|
|
//
|
|
if (IsBadReadPtr(
|
|
pAsyncInfo, // memory address,
|
|
sizeof(ASYNC_EVENT_INFO) // size of block
|
|
))
|
|
{
|
|
//
|
|
// We are under attack!!!
|
|
//
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Invalid AssyncInfo structure pointed by 'Context'. We are under attack!!!!"));
|
|
ec = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Looks good, Let's do some more verifications.
|
|
//
|
|
__try
|
|
{
|
|
if ((NULL == pAsyncInfo->CompletionPort && NULL == pAsyncInfo->hWindow) ||
|
|
(NULL != pAsyncInfo->CompletionPort && NULL != pAsyncInfo->hWindow))
|
|
{
|
|
//
|
|
// Invalid AssyncInfo structure pointed by 'Context'. We are under attack!!!!
|
|
//
|
|
ec = ERROR_INVALID_PARAMETER;
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Invalid AssyncInfo structure pointed by 'Context'. We are under attack!!!!"));
|
|
goto exit;
|
|
}
|
|
if (!ValidAsyncInfoSignature(pAsyncInfo))
|
|
{
|
|
//
|
|
// Signature mismatch. We are under attack!!!!
|
|
//
|
|
ec = ERROR_INVALID_PARAMETER;
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Invalid AssyncInfo siganture pointed by 'Context'. We are under attack!!!!"));
|
|
goto exit;
|
|
}
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
//
|
|
// For some reason we got an exception.
|
|
//
|
|
ec = GetExceptionCode();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Exception when trying to access the AssyncInfo structure (ec: %ld)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
|
|
Assert (ERROR_SUCCESS == ec);
|
|
|
|
if (pAsyncInfo->bInUse)
|
|
{
|
|
//
|
|
// This AsynchInfo is already used by another notifier (server). We are under attack!!!!
|
|
//
|
|
ec = ERROR_INVALID_PARAMETER;
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("This AsynchInfo is already used by another notifier (server). We are under attack!!!!"));
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Mark this AsynchInfo as being used.
|
|
//
|
|
pAsyncInfo->bInUse = TRUE;
|
|
|
|
if (IsWinXPOS() &&
|
|
pAsyncInfo->dwServerAPIVersion > FAX_API_VERSION_1)
|
|
{
|
|
// We are running on XP or later OS, and
|
|
// talking to fax server running on OS later then XP (.NET and later),
|
|
// we require at least packet-level privacy (RPC_C_AUTHN_LEVEL_PKT_PRIVACY).
|
|
//
|
|
RPC_AUTHZ_HANDLE hPrivs;
|
|
DWORD dwAuthn;
|
|
RPC_STATUS status = RPC_S_OK;
|
|
|
|
//
|
|
// Query the client's authentication level
|
|
//
|
|
status = RpcBindingInqAuthClient(
|
|
hBinding,
|
|
&hPrivs,
|
|
NULL,
|
|
&dwAuthn,
|
|
NULL,
|
|
NULL);
|
|
if (status != RPC_S_OK)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR,
|
|
TEXT("RpcBindingInqAuthClient returned: 0x%x"),
|
|
status);
|
|
ec = ERROR_ACCESS_DENIED;
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Now check the authentication level.
|
|
// We require at least packet-level privacy (RPC_C_AUTHN_LEVEL_PKT_PRIVACY).
|
|
//
|
|
if (dwAuthn < RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR,
|
|
TEXT("Attempt by client to use weak authentication. - 0x%x"),
|
|
dwAuthn);
|
|
ec = ERROR_ACCESS_DENIED;
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Talking to Fax service running on pre .NET OS, allow anonymous connection
|
|
//
|
|
DebugPrintEx(DEBUG_WRN,
|
|
TEXT("Talking to Fax server, with anonymous RPC connection."));
|
|
}
|
|
|
|
//
|
|
// hBinding is a valid context handle pointing to a real ASYNC_EVENT_INFO object.
|
|
// Save the binding handle for other RPC calls.
|
|
//
|
|
pAsyncInfo->hBinding = hBinding;
|
|
|
|
if ( pAsyncInfo->bLocalNotificationsOnly )
|
|
{
|
|
//
|
|
// Client asked for local events only
|
|
//
|
|
BOOL bIsLocal = FALSE;
|
|
|
|
ec = IsLocalRPCConnectionIpTcp(hBinding,&bIsLocal);
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("IsLocalRPCConnectionIpTcp failed. (ec: %lu)"),
|
|
ec);
|
|
*FaxHandle = NULL;
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
return ec;
|
|
}
|
|
else
|
|
{
|
|
if (FALSE == bIsLocal)
|
|
{
|
|
//
|
|
// Client asked for local events only but the call is from remote location. We are under attack!!!!
|
|
//
|
|
ec = ERROR_INVALID_PARAMETER;
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Client asked for local events only. We are under attack!!!!"));
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
Assert (ERROR_SUCCESS == ec);
|
|
|
|
exit:
|
|
|
|
if (ERROR_SUCCESS == ec)
|
|
{
|
|
*FaxHandle = (HANDLE) Context;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Probably we are under attack, The notification RPC functions should not fail if a wrong (read: malicious)
|
|
// notification context arrives.
|
|
// Instead, it should report success but not process notifications from that AsyncInfo object.
|
|
//
|
|
// This will make it very hard for an attacker to scan the 4G context range and detect the
|
|
// right context for bogus notifications.
|
|
//
|
|
*FaxHandle = (HANDLE)&g_scBadAsyncInfo ;
|
|
ec = ERROR_SUCCESS;
|
|
}
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
|
|
return ec;
|
|
}
|
|
|
|
|
|
error_status_t
|
|
FAX_CloseConnection(
|
|
OUT LPHANDLE pFaxHandle
|
|
)
|
|
{
|
|
PASYNC_EVENT_INFO pAsyncInfo = (PASYNC_EVENT_INFO) *pFaxHandle;
|
|
error_status_t ec = ERROR_SUCCESS;
|
|
|
|
DEBUG_FUNCTION_NAME(TEXT("FAX_CloseConnection"));
|
|
|
|
EnterCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
|
|
if (!ValidAsyncInfoSignature(pAsyncInfo))
|
|
{
|
|
//
|
|
// Probably we are under attack, The notification RPC functions should not fail if a wrong (read: malicious)
|
|
// notification context arrives.
|
|
// Instead, it should report success but not process notifications from that AsyncInfo object.
|
|
//
|
|
// This will make it very hard for an attacker to scan the 4G context range and detect the
|
|
// right context for bogus notifications.
|
|
//
|
|
|
|
DebugPrintEx(DEBUG_ERR, TEXT("Invalid AssyncInfo signature. We are under attack!!!!"));
|
|
|
|
//
|
|
// Don't report the error to the malicious user!
|
|
//
|
|
ec = ERROR_SUCCESS;
|
|
goto exit;
|
|
}
|
|
|
|
if ( pAsyncInfo->bLocalNotificationsOnly)
|
|
{
|
|
//
|
|
// Client asked for local events only
|
|
//
|
|
BOOL bIsLocal = FALSE;
|
|
|
|
ec = IsLocalRPCConnectionIpTcp(pAsyncInfo->hBinding,&bIsLocal);
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("IsLocalRPCConnectionIpTcp failed. (ec: %lu)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
else
|
|
{
|
|
if (FALSE == bIsLocal)
|
|
{
|
|
//
|
|
// Client asked for local events only but the call is from remote location. We are under attack!!!!
|
|
//
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Client asked for local events only. We are under attack!!!!"));
|
|
|
|
//
|
|
// Don't report the error to the malicious user!
|
|
//
|
|
ec = ERROR_SUCCESS;
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ZeroMemory (*pFaxHandle, sizeof(ASYNC_EVENT_INFO));
|
|
MemFree (*pFaxHandle); // Assync info
|
|
*pFaxHandle = NULL; // prevent rundown
|
|
|
|
exit:
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
return ec;
|
|
}
|
|
|
|
|
|
error_status_t
|
|
FAX_ClientEventQueue(
|
|
IN HANDLE FaxHandle,
|
|
IN FAX_EVENT FaxEvent
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called when the a fax server wants
|
|
to deliver a fax event to this client.
|
|
|
|
Arguments:
|
|
|
|
FaxHandle - FAX handle obtained from FaxConnectFaxServer.
|
|
FaxEvent - FAX event structure.
|
|
Context - Context token, really a ASYNC_EVENT_INFO structure pointer
|
|
|
|
Return Value:
|
|
|
|
Win32 error code.
|
|
|
|
--*/
|
|
|
|
{
|
|
PASYNC_EVENT_INFO AsyncInfo = (PASYNC_EVENT_INFO) FaxHandle;
|
|
error_status_t ec = ERROR_SUCCESS;
|
|
DEBUG_FUNCTION_NAME(TEXT("FAX_ClientEventQueue"));
|
|
|
|
EnterCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
if (!ValidAsyncInfoSignature(AsyncInfo))
|
|
{
|
|
//
|
|
// Probably we are under attack, The notification RPC functions should not fail if a wrong (read: malicious)
|
|
// notification context arrives.
|
|
// Instead, it should report success but not process notifications from that AsyncInfo object.
|
|
//
|
|
// This will make it very hard for an attacker to scan the 4G context range and detect the
|
|
// right context for bogus notifications.
|
|
//
|
|
|
|
DebugPrintEx(DEBUG_ERR, TEXT("Invalid AssyncInfo signature"));
|
|
|
|
//
|
|
// Don't report the error to the malicious user!
|
|
//
|
|
ec = ERROR_SUCCESS;
|
|
goto exit;
|
|
}
|
|
|
|
if ( AsyncInfo->bLocalNotificationsOnly)
|
|
{
|
|
//
|
|
// Client asked for local events only
|
|
//
|
|
BOOL bIsLocal = FALSE;
|
|
|
|
ec = IsLocalRPCConnectionIpTcp(AsyncInfo->hBinding,&bIsLocal);
|
|
if (ERROR_SUCCESS != ec)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("IsLocalRPCConnectionIpTcp failed. (ec: %lu)"),
|
|
ec);
|
|
goto exit;
|
|
}
|
|
else
|
|
{
|
|
if (FALSE == bIsLocal)
|
|
{
|
|
//
|
|
// Client asked for local events only but the call is from remote location. We are under attack!!!!
|
|
//
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Client asked for local events only. We are under attack!!!!"));
|
|
|
|
//
|
|
// Don't report the error to the malicious user!
|
|
//
|
|
ec = ERROR_SUCCESS;
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (AsyncInfo->CompletionPort != NULL)
|
|
{
|
|
//
|
|
// Use completion port
|
|
//
|
|
PFAX_EVENT FaxEventPost = NULL;
|
|
|
|
FaxEventPost = (PFAX_EVENT) LocalAlloc( LMEM_FIXED, sizeof(FAX_EVENT) );
|
|
if (!FaxEventPost)
|
|
{
|
|
ec = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto exit;
|
|
}
|
|
CopyMemory( FaxEventPost, &FaxEvent, sizeof(FAX_EVENT) );
|
|
|
|
if (!PostQueuedCompletionStatus(
|
|
AsyncInfo->CompletionPort,
|
|
sizeof(FAX_EVENT),
|
|
AsyncInfo->CompletionKey,
|
|
(LPOVERLAPPED) FaxEventPost))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrint(( TEXT("PostQueuedCompletionStatus failed, ec = %d\n"), ec ));
|
|
LocalFree (FaxEventPost);
|
|
goto exit;
|
|
}
|
|
goto exit;
|
|
}
|
|
|
|
Assert (AsyncInfo->hWindow != NULL)
|
|
//
|
|
// Use window messages
|
|
//
|
|
if (! PostMessage( AsyncInfo->hWindow,
|
|
AsyncInfo->MessageStart + FaxEvent.EventId,
|
|
(WPARAM)FaxEvent.DeviceId,
|
|
(LPARAM)FaxEvent.JobId ))
|
|
{
|
|
ec = GetLastError();
|
|
DebugPrint(( TEXT("PostMessage failed, ec = %d\n"), ec ));
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
return ec;
|
|
}
|
|
|
|
DWORD
|
|
DispatchEvent (
|
|
const ASYNC_EVENT_INFO* pAsyncInfo,
|
|
const FAX_EVENT_EX* pEvent,
|
|
DWORD dwEventSize
|
|
)
|
|
{
|
|
DWORD dwRes = ERROR_SUCCESS;
|
|
DEBUG_FUNCTION_NAME(TEXT("DispatchEvent"));
|
|
|
|
Assert (pAsyncInfo && pEvent && dwEventSize);
|
|
|
|
if (pAsyncInfo->CompletionPort != NULL)
|
|
{
|
|
//
|
|
// Use completion port
|
|
//
|
|
if (!PostQueuedCompletionStatus( pAsyncInfo->CompletionPort,
|
|
dwEventSize,
|
|
pAsyncInfo->CompletionKey,
|
|
(LPOVERLAPPED) pEvent))
|
|
{
|
|
dwRes = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("PostQueuedCompletionStatus failed (ec: %ld)"),
|
|
dwRes);
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Assert (pAsyncInfo->hWindow != NULL)
|
|
//
|
|
// Use window messages
|
|
//
|
|
if (! PostMessage( pAsyncInfo->hWindow,
|
|
pAsyncInfo->MessageStart,
|
|
(WPARAM)NULL,
|
|
(LPARAM)pEvent ))
|
|
{
|
|
dwRes = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("PostMessage failed (ec: %ld)"),
|
|
dwRes);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
Assert (ERROR_SUCCESS == dwRes);
|
|
exit:
|
|
return dwRes;
|
|
} // DispatchEvent
|
|
|
|
|
|
|
|
void
|
|
PostRundownEventEx (
|
|
PASYNC_EVENT_INFO pAsyncInfo
|
|
)
|
|
{
|
|
PFAX_EVENT_EX pEvent = NULL;
|
|
DWORD dwRes = ERROR_SUCCESS;
|
|
DWORD dwEventSize = sizeof(FAX_EVENT_EX);
|
|
DEBUG_FUNCTION_NAME(TEXT("PostRundownEventEx"));
|
|
|
|
Assert (pAsyncInfo);
|
|
|
|
pEvent = (PFAX_EVENT_EX)MemAlloc (dwEventSize);
|
|
if (NULL == pEvent)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("PostRundownEventEx failed , Error allocatin FAX_EVENT_EX"));
|
|
return;
|
|
}
|
|
|
|
ZeroMemory(pEvent, dwEventSize);
|
|
pEvent->dwSizeOfStruct = sizeof(FAX_EVENT_EX);
|
|
GetSystemTimeAsFileTime( &(pEvent->TimeStamp) );
|
|
pEvent->EventType = FAX_EVENT_TYPE_FXSSVC_ENDED;
|
|
|
|
dwRes = DispatchEvent (pAsyncInfo, pEvent, dwEventSize);
|
|
if (ERROR_SUCCESS != dwRes)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, _T("DispatchEvent failed , ec = %ld"), dwRes);
|
|
MemFree (pEvent);
|
|
}
|
|
} // PostRundownEventEx
|
|
|
|
|
|
VOID
|
|
RPC_FAX_HANDLE_rundown(
|
|
IN HANDLE FaxHandle
|
|
)
|
|
{
|
|
PASYNC_EVENT_INFO pAsyncInfo = (PASYNC_EVENT_INFO) FaxHandle;
|
|
DWORD dwRes = ERROR_SUCCESS;
|
|
|
|
DEBUG_FUNCTION_NAME(TEXT("RPC_FAX_HANDLE_rundown"));
|
|
|
|
EnterCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
if (!ValidAsyncInfoSignature(pAsyncInfo))
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, TEXT("Invalid AssyncInfo signature"));
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
return;
|
|
}
|
|
|
|
Assert (pAsyncInfo->CompletionPort || pAsyncInfo->hWindow);
|
|
|
|
if (pAsyncInfo->bEventEx == TRUE)
|
|
{
|
|
PostRundownEventEx(pAsyncInfo);
|
|
}
|
|
else
|
|
{
|
|
// legacy event - FAX_EVENT
|
|
if (pAsyncInfo->CompletionPort != NULL)
|
|
{
|
|
PFAX_EVENT pFaxEvent;
|
|
|
|
pFaxEvent = (PFAX_EVENT) LocalAlloc( LMEM_FIXED, sizeof(FAX_EVENT) );
|
|
if (!pFaxEvent)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
pFaxEvent->SizeOfStruct = sizeof(ASYNC_EVENT_INFO);
|
|
GetSystemTimeAsFileTime( &pFaxEvent->TimeStamp );
|
|
pFaxEvent->DeviceId = 0;
|
|
pFaxEvent->EventId = FEI_FAXSVC_ENDED;
|
|
pFaxEvent->JobId = 0;
|
|
|
|
|
|
if( !PostQueuedCompletionStatus (pAsyncInfo->CompletionPort,
|
|
sizeof(FAX_EVENT),
|
|
pAsyncInfo->CompletionKey,
|
|
(LPOVERLAPPED) pFaxEvent
|
|
) )
|
|
|
|
{
|
|
dwRes = GetLastError();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("PostQueuedCompletionStatus failed (ec: %ld)"),
|
|
dwRes);
|
|
LocalFree (pFaxEvent);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if (pAsyncInfo->hWindow != NULL)
|
|
{
|
|
PostMessage (pAsyncInfo->hWindow,
|
|
pAsyncInfo->MessageStart + FEI_FAXSVC_ENDED,
|
|
0,
|
|
0);
|
|
}
|
|
}
|
|
|
|
exit:
|
|
ZeroMemory(pAsyncInfo, sizeof(ASYNC_EVENT_INFO));
|
|
MemFree (pAsyncInfo);
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
return;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ValidateAndFixupEventStringPtr (
|
|
PFAX_EVENT_EXW pEventEx,
|
|
LPCWSTR *lpptstrString,
|
|
DWORD dwDataSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function validates that the string offest in a FAX_EVENT_EXW structure
|
|
is completely contained within the event structure data range.
|
|
Once this is validated, the function converts the offest to a valid string pointer.
|
|
|
|
Arguments:
|
|
|
|
pEventEx [in] - Pointer to the fax event structure.
|
|
lpptstrString [in / out] - Pointer to string offset, later converted to the string itself.
|
|
dwDataSize [in] - Size of the event blob (bytes)
|
|
|
|
Return Value:
|
|
|
|
Win32 error code.
|
|
|
|
--*/
|
|
{
|
|
LPCWSTR lpcwstrString = *lpptstrString;
|
|
if (!lpcwstrString)
|
|
{
|
|
return TRUE;
|
|
}
|
|
//
|
|
// Make sure the offest falls within the structure size
|
|
//
|
|
if ((ULONG_PTR)lpcwstrString >= dwDataSize)
|
|
{
|
|
return FALSE;
|
|
}
|
|
//
|
|
// Convert offset to string
|
|
//
|
|
*lpptstrString = (LPCWSTR)((LPBYTE)pEventEx + (ULONG_PTR)lpcwstrString);
|
|
lpcwstrString = *lpptstrString;
|
|
if ((ULONG_PTR)lpcwstrString < (ULONG_PTR)pEventEx)
|
|
{
|
|
return FALSE;
|
|
}
|
|
//
|
|
// Make sure string ends within the event structure bounds
|
|
//
|
|
while (*lpcwstrString != TEXT('\0'))
|
|
{
|
|
lpcwstrString++;
|
|
if (lpcwstrString >= (LPCWSTR)((LPBYTE)pEventEx + dwDataSize))
|
|
{
|
|
//
|
|
// Going to exceed structure - corrupted offset
|
|
//
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
} // ValidateAndFixupEventStringPtr
|
|
|
|
|
|
error_status_t
|
|
FAX_ClientEventQueueEx(
|
|
IN RPC_FAX_HANDLE hClientContext,
|
|
IN const LPBYTE lpbData,
|
|
IN DWORD dwDataSize
|
|
)
|
|
{
|
|
PASYNC_EVENT_INFO pAsyncInfo = (PASYNC_EVENT_INFO) hClientContext;
|
|
PFAX_EVENT_EXW pEvent = NULL;
|
|
PFAX_EVENT_EXA pEventA = NULL;
|
|
DWORD dwRes = ERROR_SUCCESS;
|
|
DEBUG_FUNCTION_NAME(TEXT("FAX_ClientEventQueueEx"));
|
|
|
|
Assert (pAsyncInfo && lpbData && dwDataSize);
|
|
|
|
EnterCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
if (!ValidAsyncInfoSignature(pAsyncInfo))
|
|
{
|
|
//
|
|
// Probably we are under attack, The notification RPC functions should not fail if a wrong (read: malicious)
|
|
// notification context arrives.
|
|
// Instead, it should report success but not process notifications from that AsyncInfo object.
|
|
//
|
|
// This will make it very hard for an attacker to scan the 4G context range and detect the
|
|
// right context for bogus notifications.
|
|
//
|
|
|
|
DebugPrintEx(DEBUG_ERR, TEXT("Invalid AssyncInfo signature"));
|
|
|
|
//
|
|
// Don't report the error to the malicious user!
|
|
//
|
|
dwRes = ERROR_SUCCESS;
|
|
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
goto exit;
|
|
}
|
|
|
|
if ( pAsyncInfo->bLocalNotificationsOnly )
|
|
{
|
|
//
|
|
// Client asked for local events only
|
|
//
|
|
BOOL bIsLocal = FALSE;
|
|
|
|
dwRes = IsLocalRPCConnectionIpTcp(pAsyncInfo->hBinding,&bIsLocal);
|
|
if (ERROR_SUCCESS != dwRes)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("IsLocalRPCConnectionIpTcp failed. (ec: %lu)"),
|
|
dwRes);
|
|
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
goto exit;
|
|
}
|
|
else
|
|
{
|
|
if (FALSE == bIsLocal)
|
|
{
|
|
//
|
|
// Client asked for local events only but the call is from remote location. We are under attack!!!!
|
|
//
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Client asked for local events only. We are under attack!!!!"));
|
|
|
|
//
|
|
// Don't report the error to the malicious user!
|
|
//
|
|
dwRes = ERROR_SUCCESS;
|
|
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
|
|
|
|
//
|
|
// IMPORTANT - Do not use pAsyncInfo before validating it again with ValidAsyncInfoSignature().
|
|
//
|
|
|
|
pEvent = (PFAX_EVENT_EXW)MemAlloc (dwDataSize);
|
|
if (NULL == pEvent)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("Error allocatin FAX_EVENT_EX"));
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
CopyMemory (pEvent, lpbData, dwDataSize);
|
|
|
|
if(pEvent->EventType == FAX_EVENT_TYPE_NEW_CALL)
|
|
{
|
|
if (!ValidateAndFixupEventStringPtr (pEvent,
|
|
(LPCWSTR *)&(pEvent->EventInfo).NewCall.lptstrCallerId,
|
|
dwDataSize))
|
|
{
|
|
dwRes = ERROR_INVALID_DATA;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if ( (pEvent->EventType == FAX_EVENT_TYPE_IN_QUEUE ||
|
|
pEvent->EventType == FAX_EVENT_TYPE_OUT_QUEUE) &&
|
|
((pEvent->EventInfo).JobInfo.Type == FAX_JOB_EVENT_TYPE_STATUS) )
|
|
{
|
|
//
|
|
// Unpack FAX_EVENT_EX
|
|
//
|
|
Assert ((pEvent->EventInfo).JobInfo.pJobData);
|
|
|
|
(pEvent->EventInfo).JobInfo.pJobData = (PFAX_JOB_STATUSW)
|
|
((LPBYTE)pEvent +
|
|
(ULONG_PTR)((pEvent->EventInfo).JobInfo.pJobData));
|
|
|
|
if (!ValidateAndFixupEventStringPtr (pEvent,
|
|
&((pEvent->EventInfo).JobInfo.pJobData->lpctstrExtendedStatus),
|
|
dwDataSize) ||
|
|
!ValidateAndFixupEventStringPtr (pEvent,
|
|
&((pEvent->EventInfo).JobInfo.pJobData->lpctstrTsid),
|
|
dwDataSize) ||
|
|
!ValidateAndFixupEventStringPtr (pEvent,
|
|
&((pEvent->EventInfo).JobInfo.pJobData->lpctstrCsid),
|
|
dwDataSize) ||
|
|
!ValidateAndFixupEventStringPtr (pEvent,
|
|
&((pEvent->EventInfo).JobInfo.pJobData->lpctstrDeviceName),
|
|
dwDataSize) ||
|
|
!ValidateAndFixupEventStringPtr (pEvent,
|
|
&((pEvent->EventInfo).JobInfo.pJobData->lpctstrCallerID),
|
|
dwDataSize) ||
|
|
!ValidateAndFixupEventStringPtr (pEvent,
|
|
&((pEvent->EventInfo).JobInfo.pJobData->lpctstrRoutingInfo),
|
|
dwDataSize))
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("ValidateAndFixupEventStringPtr failed"));
|
|
dwRes = ERROR_INVALID_DATA;
|
|
goto exit;
|
|
}
|
|
#ifndef UNICODE
|
|
(pEvent->EventInfo).JobInfo.pJobData->dwSizeOfStruct = sizeof(FAX_JOB_STATUSA);
|
|
if (!ConvertUnicodeStringInPlace( (LPWSTR) (pEvent->EventInfo).JobInfo.pJobData->lpctstrExtendedStatus ) ||
|
|
!ConvertUnicodeStringInPlace( (LPWSTR) (pEvent->EventInfo).JobInfo.pJobData->lpctstrTsid ) ||
|
|
!ConvertUnicodeStringInPlace( (LPWSTR) (pEvent->EventInfo).JobInfo.pJobData->lpctstrCsid ) ||
|
|
!ConvertUnicodeStringInPlace( (LPWSTR) (pEvent->EventInfo).JobInfo.pJobData->lpctstrDeviceName ) ||
|
|
!ConvertUnicodeStringInPlace( (LPWSTR) (pEvent->EventInfo).JobInfo.pJobData->lpctstrCallerID ) ||
|
|
!ConvertUnicodeStringInPlace( (LPWSTR) (pEvent->EventInfo).JobInfo.pJobData->lpctstrRoutingInfo ))
|
|
{
|
|
dwRes = GetLastError ();
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("ConvertUnicodeStringInPlace failed with %ld"),
|
|
dwRes);
|
|
goto exit;
|
|
}
|
|
#endif // ifndef UNICODE
|
|
}
|
|
|
|
EnterCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
if (!ValidAsyncInfoSignature(pAsyncInfo))
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, TEXT("Invalid AssyncInfo signature"));
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
//
|
|
// if we got here and pAsyncInfo is invalid, it must be that
|
|
// Fax_CloseConnection or rundown was called and the pAsyncInfo
|
|
// become invalid.
|
|
//
|
|
dwRes = ERROR_INVALID_DATA;
|
|
goto exit;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
dwRes = DispatchEvent (pAsyncInfo, pEvent, dwDataSize);
|
|
#else
|
|
pEvent->dwSizeOfStruct = sizeof(FAX_EVENT_EXA);
|
|
pEventA = (PFAX_EVENT_EXA)pEvent;
|
|
dwRes = DispatchEvent (pAsyncInfo, pEventA, dwDataSize);
|
|
#endif
|
|
|
|
LeaveCriticalSection(&g_CsFaxAssyncInfo); // Protect AsyncInfo
|
|
|
|
if (ERROR_SUCCESS != dwRes)
|
|
{
|
|
DebugPrintEx(
|
|
DEBUG_ERR,
|
|
TEXT("DispatchEvent failed , errro %ld"),
|
|
dwRes);
|
|
goto exit;
|
|
}
|
|
|
|
Assert (ERROR_SUCCESS == dwRes);
|
|
|
|
exit:
|
|
if (ERROR_SUCCESS != dwRes)
|
|
{
|
|
MemFree (pEvent);
|
|
}
|
|
return dwRes;
|
|
} // FAX_ClientEventQueueEx
|