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

486 lines
11 KiB
C

/*************************************************************************
* CD.C
*
* 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
=============================================================================*/
NTSTATUS IcaCdIoControl( HANDLE pContext, ULONG, PVOID, ULONG, PVOID, ULONG, PULONG );
NTSTATUS IcaCdWaitForSingleObject( HANDLE pContext, HANDLE, LONG );
NTSTATUS IcaCdWaitForMultipleObjects( HANDLE pContext, ULONG, HANDLE *, BOOL, LONG );
HANDLE IcaCdCreateThread( HANDLE pContext, PVOID, PVOID, PULONG );
/*=============================================================================
== Internal procedures defined
=============================================================================*/
NTSTATUS _CdOpen( PSTACK pStack, PWINSTATIONCONFIG2 );
VOID _CdClose( PSTACK pStack );
/*=============================================================================
== Procedures used
=============================================================================*/
void _DecrementStackRef( IN PSTACK pStack );
/****************************************************************************
*
* IcaCdIoControl
*
* Generic interface to an ICA stack (for use by Connection Driver)
*
* ENTRY:
* pContext (input)
* pointer to ICA stack context
* 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
IcaCdIoControl( IN HANDLE pContext,
IN ULONG IoControlCode,
IN PVOID pInBuffer,
IN ULONG InBufferSize,
OUT PVOID pOutBuffer,
IN ULONG OutBufferSize,
OUT PULONG pBytesReturned )
{
NTSTATUS Status;
PSTACK pStack;
pStack = (PSTACK) pContext;
ASSERTLOCK( &pStack->CritSec );
/*
* Unlock critical section
*/
pStack->RefCount++;
UNLOCK( &pStack->CritSec );
/*
* Call ICA Device driver
*/
Status = IcaIoControl( pStack->hStack,
IoControlCode,
pInBuffer,
InBufferSize,
pOutBuffer,
OutBufferSize,
pBytesReturned );
/*
* Re-lock critical section
*/
LOCK( &pStack->CritSec );
_DecrementStackRef( pStack );
if ( pStack->fClosing && (IoControlCode != IOCTL_ICA_STACK_POP) )
Status = STATUS_CTX_CLOSE_PENDING;
return( Status );
}
/****************************************************************************
*
* IcaCdWaitForSingleObject
*
* Wait for handle to be signaled
*
* ENTRY:
* pContext (input)
* pointer to ICA stack context
* hHandle (input)
* handle to wait on
* Timeout (input)
* timeout in milliseconds
*
* EXIT:
* STATUS_SUCCESS - Success
* other - Error return code
*
****************************************************************************/
NTSTATUS
IcaCdWaitForSingleObject( HANDLE pContext,
HANDLE hHandle,
LONG Timeout )
{
NTSTATUS Status;
PSTACK pStack;
pStack = (PSTACK) pContext;
ASSERTLOCK( &pStack->CritSec );
/*
* Unlock critical section
*/
pStack->RefCount++;
UNLOCK( &pStack->CritSec );
/*
* Call ICA Device driver
*/
Status = WaitForSingleObject( hHandle, Timeout );
/*
* Re-lock critical section
*/
LOCK( &pStack->CritSec );
_DecrementStackRef( pStack );
if ( pStack->fClosing )
Status = STATUS_CTX_CLOSE_PENDING;
return( Status );
}
/****************************************************************************
*
* IcaCdWaitForMultipleObjects
*
* Wait for one or more handles to be signaled
*
* ENTRY:
* pContext (input)
* pointer to ICA stack context
* Count (input)
* count of handles
* phHandle (input)
* pointer to array of handles
* bWaitAll (input)
* wait for all flag
* Timeout (input)
* timeout in milliseconds
*
* EXIT:
* STATUS_SUCCESS - Success
* other - Error return code
*
****************************************************************************/
NTSTATUS
IcaCdWaitForMultipleObjects( HANDLE pContext,
ULONG Count,
HANDLE * phHandle,
BOOL bWaitAll,
LONG Timeout )
{
NTSTATUS Status;
PSTACK pStack;
pStack = (PSTACK) pContext;
ASSERTLOCK( &pStack->CritSec );
/*
* Unlock critical section
*/
pStack->RefCount++;
UNLOCK( &pStack->CritSec );
/*
* Call ICA Device driver
*/
Status = WaitForMultipleObjects( Count, phHandle, bWaitAll, Timeout );
/*
* Re-lock critical section
*/
LOCK( &pStack->CritSec );
_DecrementStackRef( pStack );
if ( pStack->fClosing )
Status = STATUS_CTX_CLOSE_PENDING;
return( Status );
}
/****************************************************************************
*
* IcaCdCreateThread
*
* Create a thread
*
* ENTRY:
* pContext (input)
* pointer to ICA stack context
* pProc (input)
* pointer to thread procedure
* pParam (input)
* parameter for thread procedure
* pThreadId (output)
* address to return thread id
*
* EXIT:
* thread handle (null on error)
*
****************************************************************************/
typedef NTSTATUS (*PTHREAD_ROUTINE) ( PVOID );
typedef struct _CDCREATETHREADINFO {
PTHREAD_ROUTINE pProc;
PVOID pParam;
PSTACK pStack;
} CDCREATETHREADINFO, *PCDCREATETHREADINFO;
NTSTATUS _CdThread( IN PCDCREATETHREADINFO pThreadInfo );
HANDLE
IcaCdCreateThread( HANDLE pContext,
PVOID pProc,
PVOID pParam,
PULONG pThreadId )
{
CDCREATETHREADINFO ThreadInfo;
HANDLE Handle;
PSTACK pStack;
pStack = (PSTACK) pContext;
ASSERTLOCK( &pStack->CritSec );
/*
* Initialize thread info
*/
ThreadInfo.pProc = pProc;
ThreadInfo.pParam = pParam;
ThreadInfo.pStack = pStack;
/*
* Increment reference
* - this will be decremented when the thread exits
*/
pStack->RefCount++;
/*
* Create thread
*/
Handle = CreateThread( NULL,
5000,
(LPTHREAD_START_ROUTINE)
_CdThread,
&ThreadInfo,
0,
pThreadId );
return( Handle );
}
NTSTATUS
_CdThread( IN PCDCREATETHREADINFO pThreadInfo )
{
PSTACK pStack = pThreadInfo->pStack;
/*
* Lock critical section
*/
LOCK( &pStack->CritSec );
/*
* Call thread procedure in CD driver
*/
(void) (pThreadInfo->pProc)( pThreadInfo->pParam );
/*
* Decrement reference made in IcaCdCreateThread when thread exits
*/
_DecrementStackRef( pStack );
/*
* Unlock critical section
*/
UNLOCK( &pStack->CritSec );
return( STATUS_SUCCESS );
}
/*******************************************************************************
*
* _CdOpen
*
* Load and open connection driver dll
*
* ENTRY:
* pStack (input)
* pointer to ICA stack structure
* pWinStationConfig (input)
* pointer to winstation config structure
*
* EXIT:
* STATUS_SUCCESS - no error
*
******************************************************************************/
NTSTATUS
_CdOpen( IN PSTACK pStack,
IN PWINSTATIONCONFIG2 pWinStationConfig )
{
PCDCONFIG pCdConfig;
HANDLE Handle;
NTSTATUS Status;
ASSERTLOCK( &pStack->CritSec );
pCdConfig = &pWinStationConfig->Cd;
/*
* Return if there is no connection driver to load
*/
if ( pCdConfig->CdClass == CdNone ) {
TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _CdOpen, no dll\n" ));
return( STATUS_SUCCESS );
}
/*
* load CD DLL
*/
Handle = LoadLibrary( pCdConfig->CdDLL );
if ( Handle == NULL ) {
Status = STATUS_CTX_PD_NOT_FOUND;
goto badload;
}
/*
* get connection driver entry points
*/
pStack->pCdOpen = (PCDOPEN) GetProcAddress( Handle, "CdOpen" );
pStack->pCdClose = (PCDCLOSE) GetProcAddress( Handle, "CdClose" );
pStack->pCdIoControl = (PCDIOCONTROL) GetProcAddress( Handle, "CdIoControl" );
if ( pStack->pCdOpen == NULL ||
pStack->pCdClose == NULL ||
pStack->pCdIoControl == NULL ) {
Status = STATUS_CTX_INVALID_PD;
goto badproc;
}
/*
* Open CD driver
*/
Status = (*pStack->pCdOpen)( pStack,
&pWinStationConfig->Pd[0], // td parameters
&pStack->pCdContext
);
if ( !NT_SUCCESS(Status) )
goto badopen;
/*
* Save CD handle
*/
pStack->hCdDLL = Handle;
TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _CdOpen, %S, success\n",
pCdConfig->CdDLL ));
return( STATUS_SUCCESS );
/*=============================================================================
== Error returns
=============================================================================*/
/*
* Open failed
* get proc address failed
*/
badopen:
badproc:
pStack->pCdOpen = NULL;
pStack->pCdClose = NULL;
pStack->pCdIoControl = NULL;
FreeLibrary( Handle );
/*
* CD DLL load failed
*/
badload:
pStack->pCdContext = NULL;
TRACESTACK(( pStack, TC_ICAAPI, TT_ERROR, "TSAPI: _CdOpen, %S, 0x%x\n", pCdConfig->CdDLL, Status ));
return( Status );
}
/*******************************************************************************
*
* _CdClose
*
* Free local context structure
*
* ENTRY:
* pStack (input)
* pointer to ICA stack structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
_CdClose( IN PSTACK pStack )
{
ASSERTLOCK( &pStack->CritSec );
/*
* Close CD driver
*/
if ( pStack->pCdClose ) {
(void) (*pStack->pCdClose)( pStack->pCdContext );
}
/*
* Clear procedure pointers
*/
pStack->pCdOpen = NULL;
pStack->pCdClose = NULL;
pStack->pCdIoControl = NULL;
/*
* Unload dll
*/
if ( pStack->hCdDLL ) {
FreeLibrary( pStack->hCdDLL );
pStack->hCdDLL = NULL;
}
TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _CdClose\n" ));
}