962 lines
26 KiB
C
962 lines
26 KiB
C
|
|
||
|
/*************************************************************************
|
||
|
*
|
||
|
* stack.c
|
||
|
*
|
||
|
* ICA STACK IOCTLS
|
||
|
*
|
||
|
* Copyright Microsoft, 1998
|
||
|
*
|
||
|
*
|
||
|
*************************************************************************/
|
||
|
|
||
|
/*
|
||
|
* Includes
|
||
|
*/
|
||
|
#include <ntddk.h>
|
||
|
#include <ntddvdeo.h>
|
||
|
#include <ntddkbd.h>
|
||
|
#include <ntddmou.h>
|
||
|
#include <ntddbeep.h>
|
||
|
|
||
|
#include <winstaw.h>
|
||
|
#include <icadd.h>
|
||
|
#include <sdapi.h>
|
||
|
#include <td.h>
|
||
|
|
||
|
|
||
|
|
||
|
/*=============================================================================
|
||
|
== External procedures defined
|
||
|
=============================================================================*/
|
||
|
|
||
|
NTSTATUS StackCreateEndpoint( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackCdCreateEndpoint( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackCallbackInitiate( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackCallbackComplete( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackOpenEndpoint( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackCloseEndpoint( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackConnectionWait( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackConnectionSend( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackConnectionRequest( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackQueryParams( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackSetParams( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackQueryLastError( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackWaitForStatus( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackCancelIo( PTD, PSD_IOCTL );
|
||
|
NTSTATUS StackQueryRemoteAddress( PTD, PSD_IOCTL );
|
||
|
|
||
|
|
||
|
/*=============================================================================
|
||
|
== Internal procedures defined
|
||
|
=============================================================================*/
|
||
|
|
||
|
NTSTATUS _TdCreateInputThread( PTD );
|
||
|
|
||
|
|
||
|
/*=============================================================================
|
||
|
== Procedures used
|
||
|
=============================================================================*/
|
||
|
|
||
|
NTSTATUS DeviceCreateEndpoint( PTD, PICA_STACK_ADDRESS, PICA_STACK_ADDRESS );
|
||
|
NTSTATUS DeviceOpenEndpoint( PTD, PVOID, ULONG );
|
||
|
NTSTATUS DeviceCloseEndpoint( PTD );
|
||
|
NTSTATUS DeviceConnectionWait( PTD, PVOID, ULONG, PULONG );
|
||
|
NTSTATUS DeviceConnectionSend( PTD );
|
||
|
NTSTATUS DeviceConnectionRequest( PTD, PICA_STACK_ADDRESS, PVOID, ULONG, PULONG );
|
||
|
NTSTATUS DeviceGetLastError( PTD, PICA_STACK_LAST_ERROR );
|
||
|
NTSTATUS DeviceWaitForStatus( PTD );
|
||
|
NTSTATUS DeviceCancelIo( PTD );
|
||
|
NTSTATUS DeviceSetParams( PTD );
|
||
|
NTSTATUS DeviceIoctl( PTD, PSD_IOCTL );
|
||
|
NTSTATUS DeviceQueryRemoteAddress( PTD, PVOID, ULONG, PVOID, ULONG, PULONG );
|
||
|
|
||
|
NTSTATUS TdInputThread( PTD );
|
||
|
NTSTATUS TdSyncWrite( PTD, PSD_SYNCWRITE );
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackCreateEndpoint IOCTL_ICA_STACK_CREATE_ENDPOINT
|
||
|
*
|
||
|
* Create new transport endpoint
|
||
|
*
|
||
|
* The endpoint structure contains everything necessary to preserve
|
||
|
* a client connection across a transport driver unload and reload.
|
||
|
*
|
||
|
* This routine creates a new endpoint, using the optional local address.
|
||
|
* In the case of a network connection, the actual endpoint cannot be
|
||
|
* created until the client connection is established. What this routine
|
||
|
* creates is an endpoint to listen on.
|
||
|
*
|
||
|
* DeviceConnectionWait and DeviceConnectionRequest return the endpoint.
|
||
|
*
|
||
|
* NOTE: The endpoint structure is an opaque, variable length data
|
||
|
* structure whose length and contents are determined by the
|
||
|
* transport driver.
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - ICA_STACK_ADDRESS (or NULL)
|
||
|
* output - nothing
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackCreateEndpoint( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
PICA_STACK_ADDRESS pAddressIn;
|
||
|
PICA_STACK_ADDRESS pAddressOut;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
if ( pSdIoctl->InputBufferLength < sizeof(ICA_STACK_ADDRESS) ) {
|
||
|
|
||
|
/*
|
||
|
* No address specified
|
||
|
*/
|
||
|
pAddressIn = NULL;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
* Get local address to use, if any
|
||
|
*/
|
||
|
pAddressIn = pSdIoctl->InputBuffer;
|
||
|
}
|
||
|
|
||
|
if ( pSdIoctl->OutputBufferLength < sizeof(ICA_STACK_ADDRESS) ) {
|
||
|
|
||
|
/*
|
||
|
* No address specified
|
||
|
*/
|
||
|
pAddressOut = NULL;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
* Get local address to use, if any
|
||
|
*/
|
||
|
pAddressOut = pSdIoctl->OutputBuffer;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Initialize transport driver endpoint
|
||
|
*/
|
||
|
Status = DeviceCreateEndpoint( pTd, pAddressIn, pAddressOut );
|
||
|
if ( !NT_SUCCESS(Status) )
|
||
|
goto badcreate;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackCreateEndpoint: %x, success\n", pAddressIn ));
|
||
|
return( STATUS_SUCCESS );
|
||
|
|
||
|
/*=============================================================================
|
||
|
== Error returns
|
||
|
=============================================================================*/
|
||
|
|
||
|
/*
|
||
|
* endpoint create failed
|
||
|
*/
|
||
|
badcreate:
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackCreateEndpoint: %x, Status=0x%x\n", pAddressIn, Status ));
|
||
|
return( Status );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackCdCreateEndpoint IOCTL_ICA_STACK_CD_CREATE_ENDPOINT
|
||
|
*
|
||
|
* Create an endpoint based on a data provided by a connection driver.
|
||
|
*
|
||
|
* NOTE: The endpoint structure is an opaque, variable length data
|
||
|
* structure whose length and contents are determined by the
|
||
|
* transport driver.
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - <endpoint data)
|
||
|
* output - <endpoint data>
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackCdCreateEndpoint( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1,
|
||
|
"TD: StackCdCreateEndpoint: entry\n" ));
|
||
|
|
||
|
pTd->fClosing = FALSE;
|
||
|
|
||
|
/*
|
||
|
* Initialize transport driver endpoint
|
||
|
*/
|
||
|
Status = DeviceIoctl( pTd, pSdIoctl );
|
||
|
if ( !NT_SUCCESS(Status) )
|
||
|
goto badopen;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1,
|
||
|
"TD: StackCdCreateEndpoint: success\n" ));
|
||
|
|
||
|
return( STATUS_SUCCESS );
|
||
|
|
||
|
/*=============================================================================
|
||
|
== Error returns
|
||
|
=============================================================================*/
|
||
|
|
||
|
/*
|
||
|
* endpoint open failed
|
||
|
*/
|
||
|
badopen:
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_ERROR,
|
||
|
"TD: StackCdCreateEndpoint: Status=0x%x\n",
|
||
|
Status ));
|
||
|
return( Status );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackCallbackInitiate IOCTL_ICA_STACK_CALLBACK_INITIATE
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - ICA_STACK_CALLBACK
|
||
|
* output - nothing
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackCallbackInitiate( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1,
|
||
|
"TD: StackCallbackInitiate: entry\n" ));
|
||
|
|
||
|
pTd->fCallbackInProgress = TRUE;
|
||
|
|
||
|
return( STATUS_SUCCESS );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackCallbackComplete IOCTL_ICA_STACK_CALLBACK_COMPLETE
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - nothing
|
||
|
* output - nothing
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackCallbackComplete( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1,
|
||
|
"TD: StackCallbackComplete: entry\n" ));
|
||
|
|
||
|
pTd->fCallbackInProgress = FALSE;
|
||
|
|
||
|
/*
|
||
|
* Create the input thread if one is not running.
|
||
|
*/
|
||
|
if ( pTd->pInputThread ) {
|
||
|
Status = IcaWaitForSingleObject( pTd->pContext,
|
||
|
pTd->pInputThread, 0 );
|
||
|
if ( Status != STATUS_TIMEOUT) { // if input thread not running
|
||
|
/*
|
||
|
* The old input thread has gone away, but hasn't
|
||
|
* been cleaned up. Clean it up now.
|
||
|
*/
|
||
|
ObDereferenceObject( pTd->pInputThread );
|
||
|
pTd->pInputThread = NULL;
|
||
|
}
|
||
|
}
|
||
|
if ( !pTd->pInputThread ) {
|
||
|
Status = _TdCreateInputThread( pTd );
|
||
|
if ( !NT_SUCCESS(Status) )
|
||
|
goto badthreadcreate;
|
||
|
}
|
||
|
return( STATUS_SUCCESS );
|
||
|
|
||
|
badthreadcreate:
|
||
|
return( Status );
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackOpenEndpoint IOCTL_ICA_STACK_OPEN_ENDPOINT
|
||
|
*
|
||
|
* Open an existing transport endpoint
|
||
|
*
|
||
|
* The endpoint structure contains everything necessary to preserve
|
||
|
* a client connection across a transport driver unload and reload.
|
||
|
*
|
||
|
* This routine will bind to an existing endpoint which is passed as
|
||
|
* the input parameter.
|
||
|
*
|
||
|
* NOTE: The endpoint structure is an opaque, variable length data
|
||
|
* structure whose length and contents are determined by the
|
||
|
* transport driver.
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - <endpoint data>
|
||
|
* output - nothing
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackOpenEndpoint( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
/*
|
||
|
* Initialize transport driver endpoint
|
||
|
*/
|
||
|
Status = DeviceOpenEndpoint( pTd,
|
||
|
pSdIoctl->InputBuffer,
|
||
|
pSdIoctl->InputBufferLength );
|
||
|
if ( !NT_SUCCESS(Status) )
|
||
|
goto badopen;
|
||
|
|
||
|
/*
|
||
|
* Create the input thread now.
|
||
|
*/
|
||
|
Status = _TdCreateInputThread( pTd );
|
||
|
if ( !NT_SUCCESS(Status) )
|
||
|
goto badthreadcreate;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackOpenEndpoint, success\n" ));
|
||
|
return( STATUS_SUCCESS );
|
||
|
|
||
|
/*=============================================================================
|
||
|
== Error returns
|
||
|
=============================================================================*/
|
||
|
|
||
|
/*
|
||
|
* thread create failed - we used to close the endpoint, however TermSrv
|
||
|
* does not expect this and would do a double free. Now we just rely on
|
||
|
* TermSrv to turn around and close the endpoint.
|
||
|
*/
|
||
|
badthreadcreate:
|
||
|
// (void) DeviceCloseEndpoint( pTd );
|
||
|
|
||
|
/*
|
||
|
* endpoint open failed
|
||
|
*/
|
||
|
badopen:
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackOpenEndpoint, Status=0x%x\n", Status ));
|
||
|
return( Status );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackCloseEndpoint IOCTL_ICA_STACK_CLOSE_ENDPOINT
|
||
|
*
|
||
|
* Close transport endpoint
|
||
|
*
|
||
|
* This will terminate any client connection
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - nothing
|
||
|
* output - nothing
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackCloseEndpoint( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
/*
|
||
|
* Close transport driver endpoint
|
||
|
*/
|
||
|
Status = DeviceCloseEndpoint( pTd );
|
||
|
if ( !NT_SUCCESS(Status) )
|
||
|
goto badclose;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackCloseEndpoint: success\n" ));
|
||
|
return( STATUS_SUCCESS );
|
||
|
|
||
|
/*=============================================================================
|
||
|
== Error returns
|
||
|
=============================================================================*/
|
||
|
|
||
|
/*
|
||
|
* endpoint close failed
|
||
|
*/
|
||
|
badclose:
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackCloseEndpoint: 0x%x\n", Status ));
|
||
|
return( Status );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackConnectionWait IOCTL_ICA_STACK_CONNECTION_WAIT
|
||
|
*
|
||
|
* Waits for a new client connection
|
||
|
*
|
||
|
* After the transport driver is loaded and StackCreateEndpoint is called
|
||
|
* this routine is called to wait for a new client connection.
|
||
|
*
|
||
|
* If an endpoint does not yet exist, DeviceConnectionWait will create one
|
||
|
* when the client connects.
|
||
|
*
|
||
|
* Changed 02/18/97 JohnR:
|
||
|
*
|
||
|
* This routine returns an opaque 32 bit handle to a data structure that
|
||
|
* is maintained by ICADD.SYS. This data structure allows the transport
|
||
|
* driver to maintain specific state information in a secure manner.
|
||
|
*
|
||
|
* This state information is only known to the transport driver.
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - nothing
|
||
|
* output - <endpoint data>
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackConnectionWait( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackConnectionWait: enter\n" ));
|
||
|
|
||
|
/*
|
||
|
* Initialize return byte count
|
||
|
* - size of returned endpoint structure
|
||
|
*/
|
||
|
pSdIoctl->BytesReturned = 0;
|
||
|
|
||
|
/*
|
||
|
* Wait for physical connection
|
||
|
*
|
||
|
* - DeviceConnectionWait should check OutputBufferLength to make
|
||
|
* sure it's long enough to return an endpoint structure before
|
||
|
* blocking.
|
||
|
*/
|
||
|
Status = DeviceConnectionWait( pTd,
|
||
|
pSdIoctl->OutputBuffer,
|
||
|
pSdIoctl->OutputBufferLength,
|
||
|
&pSdIoctl->BytesReturned );
|
||
|
if ( !NT_SUCCESS(Status) )
|
||
|
goto badwait;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackConnectionWait: success\n" ));
|
||
|
return( STATUS_SUCCESS );
|
||
|
|
||
|
/*=============================================================================
|
||
|
== Error returns
|
||
|
=============================================================================*/
|
||
|
|
||
|
/*
|
||
|
* thread create failed
|
||
|
* Wait failed
|
||
|
*/
|
||
|
badwait:
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackConnectionWait: Status=0x%x\n", Status ));
|
||
|
return( Status );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackConnectionSend IOCTL_ICA_STACK_CONNECTION_SEND
|
||
|
*
|
||
|
* Initialize transport driver module data to send to the client
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - nothing
|
||
|
* output - nothing
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackConnectionSend( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
return( DeviceConnectionSend( pTd ) );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackConnectionRequest IOCTL_ICA_STACK_CONNECTION_REQUEST
|
||
|
*
|
||
|
* Initiate a connection to the specified remote address
|
||
|
*
|
||
|
* - this routine is only used by shadow
|
||
|
*
|
||
|
* DeviceConnectionRequest will create a new endpoint after establishing
|
||
|
* a connection.
|
||
|
*
|
||
|
* This routine returns the endpoint data structure. The endpoint structure
|
||
|
* contains everything necessary to preserve a connection across a transport
|
||
|
* driver unload and reload.
|
||
|
*
|
||
|
* NOTE: The endpoint structure is an opaque, variable length data
|
||
|
* structure whose length and contents are determined by the
|
||
|
* transport driver.
|
||
|
*
|
||
|
*
|
||
|
* typedef struct _ICA_STACK_ADDRESS {
|
||
|
* BYTE Address[MAX_BR_ADDRESS]; // bytes 0,1 family, 2-n address
|
||
|
* } ICA_STACK_ADDRESS, *PICA_STACK_ADDRESS;
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - ICA_STACK_ADDRESS (remote address)
|
||
|
* output - <endpoint data>
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackConnectionRequest( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
if ( pSdIoctl->InputBufferLength < sizeof(ICA_STACK_ADDRESS) ) {
|
||
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||
|
goto badbuffer;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Establish physical connection
|
||
|
*
|
||
|
* - DeviceConnectionRequest should check OutputBufferLength to make
|
||
|
* sure it is long enough to return an endpoint structure before
|
||
|
* making a connection.
|
||
|
*/
|
||
|
Status = DeviceConnectionRequest( pTd,
|
||
|
pSdIoctl->InputBuffer,
|
||
|
pSdIoctl->OutputBuffer,
|
||
|
pSdIoctl->OutputBufferLength,
|
||
|
&pSdIoctl->BytesReturned );
|
||
|
if ( !NT_SUCCESS(Status) )
|
||
|
goto badrequest;
|
||
|
|
||
|
/*
|
||
|
* Create input thread
|
||
|
*/
|
||
|
Status = _TdCreateInputThread( pTd );
|
||
|
if ( !NT_SUCCESS(Status) )
|
||
|
goto badthreadcreate;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackConnectionRequest: success\n" ));
|
||
|
return( STATUS_SUCCESS );
|
||
|
|
||
|
/*=============================================================================
|
||
|
== Error returns
|
||
|
=============================================================================*/
|
||
|
|
||
|
/*
|
||
|
* thread create failed
|
||
|
* connection request failed
|
||
|
* buffer too small
|
||
|
*/
|
||
|
badthreadcreate:
|
||
|
badrequest:
|
||
|
badbuffer:
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackConnectionRequest: Status=0x%x\n", Status ));
|
||
|
return( Status );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackQueryParams IOCTL_ICA_STACK_QUERY_PARAMS
|
||
|
*
|
||
|
* query transport driver parameters
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - SDCLASS
|
||
|
* output - PDPARAMS
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackQueryParams( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
PPDPARAMS pParams;
|
||
|
|
||
|
if ( pSdIoctl->InputBufferLength < sizeof(SDCLASS) ||
|
||
|
pSdIoctl->OutputBufferLength < sizeof(PDPARAMS) ) {
|
||
|
return( STATUS_BUFFER_TOO_SMALL );
|
||
|
}
|
||
|
|
||
|
pParams = pSdIoctl->OutputBuffer;
|
||
|
|
||
|
*pParams = pTd->Params;
|
||
|
pSdIoctl->BytesReturned = sizeof(PDPARAMS);
|
||
|
|
||
|
return( STATUS_SUCCESS );
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackQueryRemoteAddress IOCTL_TS_STACK_QUERY_REMOTEADDRESS
|
||
|
*
|
||
|
* query for the remote address
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - endpoint data
|
||
|
* output - sockaddr
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
NTSTATUS
|
||
|
StackQueryRemoteAddress( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
Status = DeviceQueryRemoteAddress( pTd,
|
||
|
pSdIoctl->InputBuffer,
|
||
|
pSdIoctl->InputBufferLength,
|
||
|
pSdIoctl->OutputBuffer,
|
||
|
pSdIoctl->OutputBufferLength,
|
||
|
&pSdIoctl->BytesReturned );
|
||
|
|
||
|
if ( !NT_SUCCESS(Status) )
|
||
|
{
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackQueryRemoteAddress: 0x%\n", Status ));
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackSetParams IOCTL_ICA_STACK_SET_PARAMS
|
||
|
*
|
||
|
* set transport driver parameters
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - PDPARAMS
|
||
|
* output - nothing
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackSetParams( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
PPDPARAMS pParams;
|
||
|
|
||
|
if ( pSdIoctl->InputBufferLength < sizeof(PDPARAMS) ) {
|
||
|
return( STATUS_BUFFER_TOO_SMALL );
|
||
|
}
|
||
|
|
||
|
pParams = pSdIoctl->InputBuffer;
|
||
|
|
||
|
pTd->Params = *pParams;
|
||
|
|
||
|
return( DeviceSetParams( pTd ) );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackQueryLastError IOCTL_ICA_STACK_QUERY_LAST_ERROR
|
||
|
*
|
||
|
* Query transport driver error code and message
|
||
|
*
|
||
|
* typedef struct _ICA_STACK_LAST_ERROR {
|
||
|
* ULONG Error;
|
||
|
* CHAR Message[ MAX_ERRORMESSAGE ];
|
||
|
* } ICA_STACK_LAST_ERROR, *PICA_STACK_LAST_ERROR;
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - nothing
|
||
|
* output - ICA_STACK_LAST_ERROR
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackQueryLastError( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
if ( pSdIoctl->OutputBufferLength < sizeof(ICA_STACK_LAST_ERROR) ) {
|
||
|
return( STATUS_BUFFER_TOO_SMALL );
|
||
|
}
|
||
|
|
||
|
pSdIoctl->BytesReturned = sizeof(ICA_STACK_LAST_ERROR);
|
||
|
|
||
|
return( DeviceGetLastError( pTd, pSdIoctl->OutputBuffer ) );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackWaitForStatus IOCTL_ICA_STACK_WAIT_FOR_STATUS
|
||
|
*
|
||
|
* Wait for transport driver status to change
|
||
|
* - only supported by async transport driver to wait for rs232 signal change
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - nothing
|
||
|
* output - nothing
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackWaitForStatus( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
/*
|
||
|
* Check if driver is being closed
|
||
|
*/
|
||
|
if ( pTd->fClosing )
|
||
|
return( STATUS_CTX_CLOSE_PENDING );
|
||
|
|
||
|
return( DeviceWaitForStatus( pTd ) );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackCancelIo IOCTL_ICA_STACK_CANCEL_IO
|
||
|
*
|
||
|
* cancel all current and future transport driver i/o
|
||
|
*
|
||
|
* NOTE: no more i/o can be done after StackCancelIo is called.
|
||
|
* The transport driver must be unloaded and reloaded to
|
||
|
* re-enable i/o.
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - nothing
|
||
|
* output - nothing
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
StackCancelIo( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
PLIST_ENTRY Head, Next;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackCancelIo (enter)\n" ));
|
||
|
|
||
|
/*
|
||
|
* Set stack closing flag
|
||
|
*/
|
||
|
pTd->fClosing = TRUE;
|
||
|
|
||
|
/*
|
||
|
* Clear error thresholds now
|
||
|
*/
|
||
|
pTd->ReadErrorThreshold = 0;
|
||
|
pTd->WriteErrorThreshold = 0;
|
||
|
|
||
|
/*
|
||
|
* Call device specific cancel I/O routine
|
||
|
*/
|
||
|
Status = DeviceCancelIo( pTd );
|
||
|
ASSERT( Status == STATUS_SUCCESS );
|
||
|
|
||
|
/*
|
||
|
* Wait for all writes to complete
|
||
|
*/
|
||
|
Status = TdSyncWrite( pTd, NULL );
|
||
|
ASSERT( Status == STATUS_SUCCESS );
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackCancelIo, %u (exit)\n", Status ));
|
||
|
|
||
|
return( Status );
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* StackSetBrokenReason IOCTL_ICA_STACK_SET_BROKENREASON
|
||
|
*
|
||
|
* Store a broken reason for later use (when reporting back up the stack)
|
||
|
*
|
||
|
* NOTE: Does not break the connection
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
* pSdIoctl (input/output)
|
||
|
* input - ICA_STACK_BROKENREASON
|
||
|
* output - nothing
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
NTSTATUS
|
||
|
StackSetBrokenReason( PTD pTd, PSD_IOCTL pSdIoctl )
|
||
|
{
|
||
|
PICA_STACK_BROKENREASON pBrkReason;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1,
|
||
|
"TD: StackSetBrokenReason (enter)\n" ));
|
||
|
|
||
|
if ( pSdIoctl->InputBufferLength < sizeof(ICA_STACK_BROKENREASON) ) {
|
||
|
return( STATUS_BUFFER_TOO_SMALL );
|
||
|
}
|
||
|
|
||
|
pBrkReason = pSdIoctl->InputBuffer;
|
||
|
pTd->UserBrokenReason = pBrkReason->BrokenReason;
|
||
|
|
||
|
TRACE(( pTd->pContext, TC_TD, TT_API1,
|
||
|
"TD: StackSetBrokenReason, %u (exit)\n", STATUS_SUCCESS ));
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* _TdCreateInputThread
|
||
|
*
|
||
|
* Start the input thread running.
|
||
|
*
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pTd (input)
|
||
|
* Pointer to td data structure
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
NTSTATUS
|
||
|
_TdCreateInputThread( PTD pTd )
|
||
|
{
|
||
|
HANDLE hInputThread;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
/*
|
||
|
* Create input thread
|
||
|
*/
|
||
|
Status = IcaCreateThread( pTd->pContext,
|
||
|
TdInputThread,
|
||
|
pTd,
|
||
|
ICALOCK_DRIVER,
|
||
|
&hInputThread );
|
||
|
if ( !NT_SUCCESS(Status) )
|
||
|
return( Status );
|
||
|
|
||
|
/*
|
||
|
* Convert thread handle to pointer reference
|
||
|
*/
|
||
|
Status = ObReferenceObjectByHandle( hInputThread,
|
||
|
THREAD_ALL_ACCESS,
|
||
|
NULL,
|
||
|
KernelMode,
|
||
|
&pTd->pInputThread,
|
||
|
NULL );
|
||
|
(VOID) ZwClose( hInputThread );
|
||
|
if ( !NT_SUCCESS( Status ) ) {
|
||
|
(VOID) StackCancelIo( pTd, NULL );
|
||
|
}
|
||
|
|
||
|
return( Status );
|
||
|
}
|
||
|
|
||
|
|