windows-nt/Source/XPSP1/NT/termsrv/icaapi/icaapi.c
2020-09-26 16:20:57 +08:00

403 lines
9.9 KiB
C

/*************************************************************************
* ICAAPI.C
*
* ICA DLL Interface for ICA Device Driver
*
* Copyright 1996, Citrix Systems Inc.
* Copyright (C) 1997-1999 Microsoft Corp.
*
* Author: Marc Bloomfield
* Terry Treder
* Brad Pedersen
*************************************************************************/
#include "precomp.h"
#pragma hdrstop
/*=============================================================================
== External procedures defined
=============================================================================*/
#ifdef BUILD_AS_DLL
BOOL WINAPI DllEntryPoint( HINSTANCE, DWORD, LPVOID );
#endif
NTSTATUS IcaOpen( HANDLE * phIca );
NTSTATUS IcaClose( HANDLE hIca );
VOID cdecl IcaSystemTrace( IN HANDLE hIca, ULONG, ULONG, char *, ... );
VOID cdecl IcaTrace( IN HANDLE hIca, ULONG, ULONG, char *, ... );
NTSTATUS IcaIoControl( HANDLE hIca, ULONG, PVOID, ULONG, PVOID, ULONG, PULONG );
/*=============================================================================
== Internal procedures defined
=============================================================================*/
NTSTATUS _IcaOpen( PHANDLE hIca, PVOID, ULONG );
/*=============================================================================
== Procedures used
=============================================================================*/
#ifdef BUILD_AS_DLL
/****************************************************************************
*
* DllEntryPoint
*
* Function is called when the DLL is loaded and unloaded.
*
* ENTRY:
* hinstDLL (input)
* Handle of DLL module
* fdwReason (input)
* Why function was called
* lpvReserved (input)
* Reserved; must be NULL
*
* EXIT:
* TRUE - Success
* FALSE - Error occurred
*
****************************************************************************/
BOOL WINAPI
DllEntryPoint( HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved )
{
switch ( fdwReason ) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
break;
default:
break;
}
return( TRUE );
}
#endif
/****************************************************************************
*
* IcaOpen
*
* Open an instance to the ICA Device Driver
*
* ENTRY:
* phIca (output)
* Pointer to ICA instance handle
*
* EXIT:
* STATUS_SUCCESS - Success
* other - Error return code
*
****************************************************************************/
NTSTATUS
IcaOpen( OUT HANDLE * phIca )
{
NTSTATUS Status;
Status = _IcaOpen( phIca, NULL, 0 );
if ( !NT_SUCCESS(Status) )
goto badopen;
TRACE(( *phIca, TC_ICAAPI, TT_API1, "TSAPI: IcaOpen, success\n" ));
return( STATUS_SUCCESS );
/*=============================================================================
== Error returns
=============================================================================*/
badopen:
*phIca = NULL;
return( Status );
}
/****************************************************************************
*
* IcaClose
*
* Close an instance to the ICA Device Driver
*
* ENTRY:
* hIca (input)
* ICA instance handle
*
* EXIT:
* STATUS_SUCCESS - Success
* other - Error return code
*
****************************************************************************/
NTSTATUS
IcaClose( IN HANDLE hIca )
{
NTSTATUS Status;
TRACE(( hIca, TC_ICAAPI, TT_API1, "TSAPI: IcaClose\n" ));
/*
* Close the ICA device driver instance
*/
Status = NtClose( hIca );
ASSERT( NT_SUCCESS(Status) );
return( Status );
}
/*******************************************************************************
*
* IcaSystemTrace
*
* Write a trace record to the system trace file
*
* ENTRY:
* hIca (input)
* ICA instance handle
* TraceClass (input)
* trace class bit mask
* TraceEnable (input)
* trace type bit mask
* Format (input)
* format string
* ... (input)
* enough arguments to satisfy format string
*
* EXIT:
* nothing
*
******************************************************************************/
VOID cdecl
IcaSystemTrace( IN HANDLE hIca,
IN ULONG TraceClass,
IN ULONG TraceEnable,
IN char * Format,
IN ... )
{
ICA_TRACE_BUFFER Buffer;
va_list arg_marker;
ULONG Length;
va_start( arg_marker, Format );
Length = (ULONG) _vsnprintf( Buffer.Data, sizeof(Buffer.Data), Format, arg_marker );
Buffer.TraceClass = TraceClass;
Buffer.TraceEnable = TraceEnable;
Buffer.DataLength = Length;
(void) IcaIoControl( hIca,
IOCTL_ICA_SYSTEM_TRACE,
&Buffer,
sizeof(Buffer) - sizeof(Buffer.Data) + Length,
NULL,
0,
NULL );
}
/*******************************************************************************
*
* IcaTrace
*
* Write a trace record to the winstation trace file
*
* ENTRY:
* hIca (input)
* ICA instance handle
* TraceClass (input)
* trace class bit mask
* TraceEnable (input)
* trace type bit mask
* Format (input)
* format string
* ... (input)
* enough arguments to satisfy format string
*
* EXIT:
* nothing
*
******************************************************************************/
VOID cdecl
IcaTrace( IN HANDLE hIca,
IN ULONG TraceClass,
IN ULONG TraceEnable,
IN char * Format,
IN ... )
{
ICA_TRACE_BUFFER Buffer;
va_list arg_marker;
ULONG Length;
va_start( arg_marker, Format );
Length = (ULONG) _vsnprintf( Buffer.Data, sizeof(Buffer.Data), Format, arg_marker );
Buffer.TraceClass = TraceClass;
Buffer.TraceEnable = TraceEnable;
Buffer.DataLength = Length;
(void) IcaIoControl( hIca,
IOCTL_ICA_TRACE,
&Buffer,
sizeof(Buffer) - sizeof(Buffer.Data) + Length,
NULL,
0,
NULL );
}
/****************************************************************************
*
* IcaIoControl
*
* Generic interface to the ICA Device Driver
*
* ENTRY:
* hIca (input)
* ICA instance handle
*
* IoControlCode (input)
* I/O control code
*
* pInBuffer (input)
* Pointer to input parameters
*
* InBufferSize (input)
* Size of pInBuffer
*
* pOutBuffer (output)
* Pointer to output buffer
*
* OutBufferSize (input)
* Size of pOutBuffer
*
* pBytesReturned (output)
* Pointer to number of bytes returned
*
* EXIT:
* STATUS_SUCCESS - Success
* other - Error return code
*
****************************************************************************/
NTSTATUS
IcaIoControl( IN HANDLE hIca,
IN ULONG IoControlCode,
IN PVOID pInBuffer,
IN ULONG InBufferSize,
OUT PVOID pOutBuffer,
IN ULONG OutBufferSize,
OUT PULONG pBytesReturned )
{
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
/*
* Issue ioctl
*/
Status = NtDeviceIoControlFile( hIca,
NULL,
NULL,
NULL,
&Iosb,
IoControlCode,
pInBuffer,
InBufferSize,
pOutBuffer,
OutBufferSize );
/*
* Wait for ioctl to complete
*/
if ( Status == STATUS_PENDING ) {
Status = NtWaitForSingleObject( hIca, FALSE, NULL );
if ( NT_SUCCESS(Status))
Status = Iosb.Status;
}
/*
* Convert warning into error
*/
if ( Status == STATUS_BUFFER_OVERFLOW )
Status = STATUS_BUFFER_TOO_SMALL;
/*
* Initialize bytes returned
*/
if ( pBytesReturned )
*pBytesReturned = (ULONG)Iosb.Information;
return( Status );
}
/****************************************************************************
*
* _IcaOpen
*
* Open an instance to the ICA Device Driver or an ICA stack
*
* ENTRY:
* ph (output)
* Pointer to ICA or ICA stack instance handle
*
* pEa (input)
* Pointer to extended attribute buffer
*
* cbEa (input)
* Size of extended attribute buffer
*
* EXIT:
* STATUS_SUCCESS - Success
* other - Error return code
*
****************************************************************************/
NTSTATUS
_IcaOpen( PHANDLE ph,
PVOID pEa,
ULONG cbEa )
{
NTSTATUS Status;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING IcaName;
IO_STATUS_BLOCK ioStatusBlock;
/*
* Initialize the object attributes
*/
RtlInitUnicodeString( &IcaName, ICA_DEVICE_NAME );
InitializeObjectAttributes( &objectAttributes,
&IcaName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
/*
* Open an instance to the ICA device driver
*/
Status = NtCreateFile( ph,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&objectAttributes,
&ioStatusBlock,
NULL, // AllocationSize
0L, // FileAttributes
FILE_SHARE_READ | FILE_SHARE_WRITE, // ShareAccess
FILE_OPEN_IF, // CreateDisposition
0,
pEa,
cbEa );
return( Status );
}