windows-nt/Source/XPSP1/NT/printscan/fax/service/client/clirpc.c
2020-09-26 16:20:57 +08:00

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;
}