486 lines
11 KiB
C
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" ));
|
|
}
|
|
|
|
|