|
|
/*************************************************************************
* 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" )); }
|