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

183 lines
5.8 KiB
C

/*************************************************************************
*
* virtual.c
*
* This module contains routines for managing ICA virtual channels.
*
* Copyright 1998, Microsoft.
*
*
*************************************************************************/
/*
* Includes
*/
#include <precomp.h>
#pragma hdrstop
NTSTATUS
_IcaCallStack(
IN PICA_STACK pStack,
IN ULONG ProcIndex,
IN OUT PVOID pParms
);
NTSTATUS
IcaFlushChannel (
IN PICA_CHANNEL pChannel,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp
);
NTSTATUS
IcaDeviceControlVirtual(
IN PICA_CHANNEL pChannel,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp
)
/*++
Routine Description:
This is the device control routine for the ICA Virtual channel.
Arguments:
pChannel -- pointer to ICA_CHANNEL object
Irp - Pointer to I/O request packet
IrpSp - pointer to the stack location to use for this request.
Return Value:
NTSTATUS -- Indicates whether the request was successfully queued.
--*/
{
ULONG code;
SD_IOCTL SdIoctl;
NTSTATUS Status;
PICA_STACK pStack;
/*
* Extract the IOCTL control code and process the request.
*/
code = IrpSp->Parameters.DeviceIoControl.IoControlCode;
TRACECHANNEL(( pChannel, TC_ICADD, TT_API1, "ICADD: IcaDeviceControlVirtual, fc %d, ref %u (enter)\n",
(code & 0x3fff) >> 2, pChannel->RefCount ));
/*
* Process ioctl request
*/
switch ( code ) {
case IOCTL_ICA_VIRTUAL_LOAD_FILTER :
case IOCTL_ICA_VIRTUAL_UNLOAD_FILTER :
case IOCTL_ICA_VIRTUAL_ENABLE_FILTER :
case IOCTL_ICA_VIRTUAL_DISABLE_FILTER :
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
case IOCTL_ICA_VIRTUAL_BOUND :
Status = (pChannel->VirtualClass == UNBOUND_CHANNEL) ?
STATUS_INVALID_DEVICE_REQUEST : STATUS_SUCCESS;
break;
case IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA :
IcaLockConnection( pChannel->pConnect );
if ( IsListEmpty( &pChannel->pConnect->StackHead ) ) {
IcaUnlockConnection( pChannel->pConnect );
return( STATUS_INVALID_DEVICE_REQUEST );
}
pStack = CONTAINING_RECORD( pChannel->pConnect->StackHead.Flink,
ICA_STACK, StackEntry );
if( (pStack->StackClass != Stack_Console) &&
(pStack->StackClass != Stack_Primary) ) {
IcaUnlockConnection( pChannel->pConnect );
return( STATUS_INVALID_DEVICE_REQUEST );
}
IcaReferenceStack( pStack );
IcaUnlockConnection( pChannel->pConnect );
if ( pChannel->VirtualClass == UNBOUND_CHANNEL ) {
IcaDereferenceStack( pStack );
TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, channel not bound\n" ));
return( STATUS_INVALID_DEVICE_REQUEST );
}
TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA begin\n" ));
TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, pStack 0x%x\n", pStack ));
SdIoctl.IoControlCode = code;
SdIoctl.InputBuffer = &pChannel->VirtualClass;
SdIoctl.InputBufferLength = sizeof(pChannel->VirtualClass);
SdIoctl.OutputBuffer = Irp->UserBuffer;
SdIoctl.OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
Status = _IcaCallStack( pStack, SD$IOCTL, &SdIoctl );
Irp->IoStatus.Information = SdIoctl.BytesReturned;
TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, Status 0x%x\n", Status ));
TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA end\n" ));
IcaDereferenceStack( pStack );
break;
case IOCTL_ICA_VIRTUAL_CANCEL_INPUT :
Status = IcaFlushChannel( pChannel, Irp, IrpSp );
if ( !NT_SUCCESS(Status) )
break;
/* fall through */
default :
/*
* Make sure virtual channel is bound to a virtual channel number
*/
if ( pChannel->VirtualClass == UNBOUND_CHANNEL ) {
TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, channel not bound\n" ));
return( STATUS_INVALID_DEVICE_REQUEST );
}
/*
* Save virtual class in first 4 bytes of the input buffer
* - this is used by the wd
*/
if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(VIRTUALCHANNELCLASS) ) {
SdIoctl.InputBuffer = &pChannel->VirtualClass;
SdIoctl.InputBufferLength = sizeof(pChannel->VirtualClass);
} else {
SdIoctl.InputBuffer = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
SdIoctl.InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
RtlCopyMemory( SdIoctl.InputBuffer, &pChannel->VirtualClass, sizeof(pChannel->VirtualClass) );
}
/*
* Send request to WD
*/
SdIoctl.IoControlCode = code;
SdIoctl.OutputBuffer = Irp->UserBuffer;
SdIoctl.OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
Status = IcaCallDriver( pChannel, SD$IOCTL, &SdIoctl );
Irp->IoStatus.Information = SdIoctl.BytesReturned;
break;
}
TRACECHANNEL(( pChannel, TC_ICADD, TT_API1, "ICADD: IcaDeviceControlVirtual, fc %d, ref %u, 0x%x\n",
(code & 0x3fff) >> 2, pChannel->RefCount, Status ));
return( Status );
}