183 lines
5.8 KiB
C
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 );
|
|
}
|
|
|
|
|