389 lines
8.5 KiB
C
389 lines
8.5 KiB
C
/*++
|
|
|
|
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"
|
|
#pragma hdrstop
|
|
|
|
BOOL RpcServerStarted;
|
|
|
|
|
|
|
|
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 );
|
|
}
|
|
|
|
|
|
DWORD
|
|
FaxServerThread(
|
|
LPVOID UnUsed
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Thread to process RPC messages from the various fax servers.
|
|
|
|
Arguments:
|
|
|
|
AsyncInfo - Packet of data necessary for processing this thread
|
|
|
|
Return Value:
|
|
|
|
Always zero.
|
|
|
|
--*/
|
|
|
|
{
|
|
error_status_t ec;
|
|
|
|
ec = RpcMgmtWaitServerListen();
|
|
if (ec != 0) {
|
|
return ec;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FaxInitializeEventQueue(
|
|
IN HANDLE FaxHandle,
|
|
IN HANDLE CompletionPort,
|
|
IN ULONG_PTR CompletionKey,
|
|
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.
|
|
CompletionKey - A value that will be returned through the lpCompletionKey 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.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD ThreadId;
|
|
HANDLE hThread;
|
|
PASYNC_EVENT_INFO AsyncInfo;
|
|
DWORD Size;
|
|
error_status_t ec;
|
|
TCHAR ComputerName[64];
|
|
TCHAR ClientName[64];
|
|
DWORD FaxSvcProcessId;
|
|
|
|
if (CompletionPort && hWnd) {
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
|
|
if (!ValidateFaxHandle(FaxHandle, FHT_SERVICE)) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
if (hWnd && !IsLocalFaxConnection(FaxHandle)) {
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
|
|
if (hWnd) {
|
|
if (MessageStart < WM_USER) {
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
if (CompletionKey == (ULONG_PTR)-1) {
|
|
//
|
|
// this means that we want the fax service to close it's token so we can logoff
|
|
//
|
|
ec = FAX_RegisterEventWindow( FH_FAX_HANDLE(FaxHandle), (ULONG64)hWnd, 0, NULL , NULL , &FaxSvcProcessId );
|
|
} else {
|
|
//
|
|
// normal registration of event window
|
|
//
|
|
HWINSTA hWinStation;
|
|
HDESK hDesktop;
|
|
WCHAR StationName[100];
|
|
WCHAR DesktopName[100];
|
|
DWORD dwNeeded;
|
|
|
|
if (!IsWindow(hWnd)) {
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
|
|
hWinStation = GetProcessWindowStation();
|
|
if (!GetUserObjectInformation(hWinStation,
|
|
UOI_NAME,
|
|
StationName,
|
|
sizeof(StationName),
|
|
&dwNeeded) ) {
|
|
return FALSE;
|
|
}
|
|
hDesktop = GetThreadDesktop( GetCurrentThreadId() );
|
|
if (! GetUserObjectInformation(hDesktop,
|
|
UOI_NAME,
|
|
DesktopName,
|
|
sizeof(DesktopName),
|
|
&dwNeeded) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
ec = FAX_RegisterEventWindow( FH_FAX_HANDLE(FaxHandle),
|
|
(ULONG64)hWnd,
|
|
MessageStart,
|
|
StationName,
|
|
DesktopName,
|
|
&FaxSvcProcessId );
|
|
}
|
|
if (ec) {
|
|
SetLastError( ec );
|
|
return FALSE;
|
|
}
|
|
return FaxSvcProcessId;
|
|
} else if (!CompletionPort) {
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
AsyncInfo = (PASYNC_EVENT_INFO) MemAlloc( sizeof(ASYNC_EVENT_INFO) );
|
|
if (!AsyncInfo) {
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return FALSE;
|
|
}
|
|
|
|
AsyncInfo->FaxData = FH_DATA(FaxHandle);
|
|
AsyncInfo->CompletionPort = CompletionPort;
|
|
AsyncInfo->CompletionKey = CompletionKey;
|
|
|
|
|
|
Size = sizeof(ComputerName) / sizeof(TCHAR);
|
|
if (!GetComputerName( ComputerName, &Size )) {
|
|
goto error_exit;
|
|
}
|
|
|
|
_stprintf( ClientName, TEXT("FaxClient$%d"), GetCurrentProcessId() );
|
|
|
|
//
|
|
// timing: get the server thread up and running before
|
|
// registering with the fax service (our client)
|
|
//
|
|
ec = RpcpStartRpcServer( ClientName, faxclient_ServerIfHandle );
|
|
if (ec != 0) {
|
|
SetLastError( ec );
|
|
goto error_exit;
|
|
}
|
|
|
|
FH_DATA(FaxHandle)->EventInit = TRUE;
|
|
|
|
if (!RpcServerStarted) {
|
|
hThread = CreateThread(
|
|
NULL,
|
|
1024*100,
|
|
FaxServerThread,
|
|
NULL,
|
|
0,
|
|
&ThreadId
|
|
);
|
|
|
|
if (!hThread) {
|
|
goto error_exit;
|
|
} else {
|
|
RpcServerStarted = TRUE;
|
|
CloseHandle(hThread);
|
|
}
|
|
}
|
|
|
|
ec = FAX_StartClientServer( FH_FAX_HANDLE(FaxHandle), ComputerName, ClientName, (ULONG64) AsyncInfo );
|
|
if (ec) {
|
|
SetLastError( ec );
|
|
goto error_exit;
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
error_exit:
|
|
if (AsyncInfo) {
|
|
MemFree(AsyncInfo);
|
|
}
|
|
|
|
if (RpcServerStarted) {
|
|
FH_DATA(FaxHandle)->EventInit = FALSE;
|
|
// this should also terminate FaxServerThread
|
|
RpcpStopRpcServer( faxclient_ServerIfHandle );
|
|
RpcServerStarted = FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
error_status_t
|
|
FAX_OpenConnection(
|
|
IN handle_t hBinding,
|
|
IN ULONG64 Context,
|
|
OUT LPHANDLE FaxHandle
|
|
)
|
|
{
|
|
*FaxHandle = (HANDLE) Context;
|
|
return 0;
|
|
}
|
|
|
|
|
|
error_status_t
|
|
FAX_CloseConnection(
|
|
OUT LPHANDLE FaxHandle
|
|
)
|
|
{
|
|
*FaxHandle = NULL;
|
|
return 0;
|
|
}
|
|
|
|
|
|
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:
|
|
|
|
TRUE - Success
|
|
FALSE - Failure, call GetLastError() for more error information.
|
|
|
|
--*/
|
|
|
|
{
|
|
PASYNC_EVENT_INFO AsyncInfo = (PASYNC_EVENT_INFO) FaxHandle;
|
|
PFAX_EVENT FaxEventPost = NULL;
|
|
|
|
|
|
FaxEventPost = (PFAX_EVENT) LocalAlloc( LMEM_FIXED, sizeof(FAX_EVENT) );
|
|
if (!FaxEventPost) {
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
CopyMemory( FaxEventPost, &FaxEvent, sizeof(FAX_EVENT) );
|
|
|
|
PostQueuedCompletionStatus(
|
|
AsyncInfo->CompletionPort,
|
|
sizeof(FAX_EVENT),
|
|
AsyncInfo->CompletionKey,
|
|
(LPOVERLAPPED) FaxEventPost
|
|
);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
VOID
|
|
RPC_FAX_HANDLE_rundown(
|
|
IN HANDLE FaxHandle
|
|
)
|
|
{
|
|
PASYNC_EVENT_INFO AsyncInfo = (PASYNC_EVENT_INFO) FaxHandle;
|
|
PFAX_EVENT FaxEvent;
|
|
|
|
|
|
FaxEvent = (PFAX_EVENT) LocalAlloc( LMEM_FIXED, sizeof(FAX_EVENT) );
|
|
if (!FaxEvent) {
|
|
goto exit;
|
|
}
|
|
|
|
FaxEvent->SizeOfStruct = sizeof(ASYNC_EVENT_INFO);
|
|
GetSystemTimeAsFileTime( &FaxEvent->TimeStamp );
|
|
FaxEvent->DeviceId = 0;
|
|
FaxEvent->EventId = FEI_FAXSVC_ENDED;
|
|
FaxEvent->JobId = 0;
|
|
|
|
PostQueuedCompletionStatus(
|
|
AsyncInfo->CompletionPort,
|
|
sizeof(FAX_EVENT),
|
|
AsyncInfo->CompletionKey,
|
|
(LPOVERLAPPED) FaxEvent
|
|
);
|
|
|
|
exit:
|
|
RpcpStopRpcServer( faxclient_ServerIfHandle );
|
|
|
|
return;
|
|
}
|