Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

827 lines
23 KiB

/*++
Copyright (c) 1996-1998 Microsoft Corporation
Module Name:
IOCTL.C
Abstract:
This source file contains the dispatch routine which handles:
IRP_MJ_DEVICE_CONTROL
Environment:
kernel mode
Revision History:
06-01-98 : started rewrite
--*/
//*****************************************************************************
// I N C L U D E S
//*****************************************************************************
#include <wdm.h>
#include <usbdi.h>
#include <usbdlib.h>
#include "i82930.h"
#include "ioctl.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, I82930_DeviceControl)
#pragma alloc_text(PAGE, I82930_IoctlGetDeviceDescriptor)
#pragma alloc_text(PAGE, I82930_IoctlGetConfigDescriptor)
#pragma alloc_text(PAGE, I82930_IoctlSetConfigDescriptor)
#pragma alloc_text(PAGE, I82930_ValidateConfigurationDescriptor)
#pragma alloc_text(PAGE, I82930_IoctlGetPipeInformation)
#pragma alloc_text(PAGE, I82930_IoctlResetPipe)
#endif
//******************************************************************************
//
// I82930_DeviceControl()
//
// Dispatch routine which handles IRP_MJ_DEVICE_CONTROL
//
//******************************************************************************
NTSTATUS
I82930_DeviceControl (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
ULONG ioControlCode;
NTSTATUS ntStatus;
DBGPRINT(2, ("enter: I82930_DeviceControl\n"));
LOGENTRY('IOCT', DeviceObject, Irp, 0);
DBGFBRK(DBGF_BRK_IOCTL);
deviceExtension = DeviceObject->DeviceExtension;
if (deviceExtension->AcceptingRequests)
{
irpStack = IoGetCurrentIrpStackLocation(Irp);
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
case IOCTL_I82930_GET_DEVICE_DESCRIPTOR:
ntStatus = I82930_IoctlGetDeviceDescriptor(DeviceObject,
Irp);
break;
case IOCTL_I82930_GET_CONFIG_DESCRIPTOR:
ntStatus = I82930_IoctlGetConfigDescriptor(DeviceObject,
Irp);
break;
case IOCTL_I82930_SET_CONFIG_DESCRIPTOR:
ntStatus = I82930_IoctlSetConfigDescriptor(DeviceObject,
Irp);
break;
case IOCTL_I82930_GET_PIPE_INFORMATION:
ntStatus = I82930_IoctlGetPipeInformation(DeviceObject,
Irp);
break;
case IOCTL_I82930_RESET_PIPE:
ntStatus = I82930_IoctlResetPipe(DeviceObject,
Irp);
break;
case IOCTL_I82930_STALL_PIPE:
ntStatus = I82930_IoctlStallPipe(DeviceObject,
Irp);
break;
case IOCTL_I82930_ABORT_PIPE:
ntStatus = I82930_IoctlAbortPipe(DeviceObject,
Irp);
break;
case IOCTL_I82930_RESET_DEVICE:
ntStatus = I82930_IoctlResetDevice(DeviceObject,
Irp);
break;
case IOCTL_I82930_SELECT_ALTERNATE_INTERFACE:
ntStatus = I82930_IoctlSelectAlternateInterface(DeviceObject,
Irp);
break;
default:
ntStatus = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
}
}
else
{
ntStatus = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
DBGPRINT(2, ("exit: I82930_DeviceControl %08X\n", ntStatus));
LOGENTRY('ioct', ntStatus, 0, 0);
return ntStatus;
}
//******************************************************************************
//
// I82930_IoctlGetDeviceDescriptor()
//
// This routine handles IRP_MJ_DEVICE_CONTROL,
// IOCTL_I82930_GET_DEVICE_DESCRIPTOR
//
//******************************************************************************
NTSTATUS
I82930_IoctlGetDeviceDescriptor (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PVOID dest;
ULONG destLength;
PVOID src;
ULONG srcLength;
ULONG copyLength;
NTSTATUS ntStatus;
DBGPRINT(2, ("enter: I82930_IoctlGetDeviceDescriptor\n"));
deviceExtension = DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
dest = Irp->AssociatedIrp.SystemBuffer;
destLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
src = deviceExtension->DeviceDescriptor;
srcLength = sizeof(USB_DEVICE_DESCRIPTOR);
copyLength = (destLength < srcLength) ? destLength : srcLength;
RtlCopyMemory(dest, src, copyLength);
ntStatus = STATUS_SUCCESS;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = copyLength;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DBGPRINT(2, ("exit: I82930_IoctlGetDeviceDescriptor %08X\n", ntStatus));
return ntStatus;
}
//******************************************************************************
//
// I82930_IoctlGetConfigDescriptor()
//
// This routine handles IRP_MJ_DEVICE_CONTROL,
// IOCTL_I82930_GET_CONFIG_DESCRIPTOR
//
//******************************************************************************
NTSTATUS
I82930_IoctlGetConfigDescriptor (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PVOID dest;
ULONG destLength;
PVOID src;
ULONG srcLength;
ULONG copyLength;
NTSTATUS ntStatus;
DBGPRINT(2, ("enter: I82930_IoctlGetConfigDescriptor\n"));
deviceExtension = DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
dest = Irp->AssociatedIrp.SystemBuffer;
destLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
src = deviceExtension->ConfigurationDescriptor;
srcLength = deviceExtension->ConfigurationDescriptor->wTotalLength;
copyLength = (destLength < srcLength) ? destLength : srcLength;
RtlCopyMemory(dest, src, copyLength);
ntStatus = STATUS_SUCCESS;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = copyLength;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DBGPRINT(2, ("exit: I82930_IoctlGetConfigDescriptor %08X\n", ntStatus));
return ntStatus;
}
//******************************************************************************
//
// I82930_IoctlSetConfigDescriptor()
//
// This routine handles IRP_MJ_DEVICE_CONTROL,
// IOCTL_I82930_SET_CONFIG_DESCRIPTOR
//
//******************************************************************************
NTSTATUS
I82930_IoctlSetConfigDescriptor (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PUSB_CONFIGURATION_DESCRIPTOR configDesc;
PUSB_CONFIGURATION_DESCRIPTOR configDescCopy;
ULONG length;
NTSTATUS ntStatus;
DBGPRINT(2, ("enter: I82930_IoctlSetConfigDescriptor\n"));
ntStatus = STATUS_SUCCESS;
deviceExtension = DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
length = irpStack->Parameters.DeviceIoControl.InputBufferLength;
if (!I82930_ValidateConfigurationDescriptor(configDesc, length))
{
ntStatus = STATUS_INVALID_PARAMETER;
}
if (NT_SUCCESS(ntStatus))
{
configDescCopy = ExAllocatePool(NonPagedPool, length);
if (configDescCopy != NULL)
{
RtlCopyMemory(configDescCopy, configDesc, length);
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
if (NT_SUCCESS(ntStatus))
{
ntStatus = I82930_UnConfigure(DeviceObject);
}
if (NT_SUCCESS(ntStatus))
{
ASSERT(deviceExtension->ConfigurationDescriptor != NULL);
ExFreePool(deviceExtension->ConfigurationDescriptor);
deviceExtension->ConfigurationDescriptor = configDescCopy;
ntStatus = I82930_SelectConfiguration(DeviceObject);
}
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DBGPRINT(2, ("exit: I82930_IoctlSetConfigDescriptor %08X\n", ntStatus));
return ntStatus;
}
//******************************************************************************
//
// I82930_ValidateConfigurationDescriptor()
//
// This routine verifies that a Configuration Descriptor is valid.
//
//******************************************************************************
BOOLEAN
I82930_ValidateConfigurationDescriptor (
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc,
IN ULONG Length
)
{
PUCHAR descEnd;
PUSB_COMMON_DESCRIPTOR commonDesc;
PUSB_INTERFACE_DESCRIPTOR interfaceDesc;
UCHAR numInterfaces;
UCHAR numEndpoints;
PAGED_CODE();
//
// Validate the Configuration Descriptor header
//
if (Length < sizeof(USB_CONFIGURATION_DESCRIPTOR))
{
DBGPRINT(0, ("I82930_ValidateConfigurationDescriptor: Bad Length\n"));
return FALSE;
}
if (ConfigDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR))
{
DBGPRINT(0, ("I82930_ValidateConfigurationDescriptor: Bad bLength\n"));
return FALSE;
}
if (ConfigDesc->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE)
{
DBGPRINT(0, ("I82930_ValidateConfigurationDescriptor: Bad bDescriptorType\n"));
return FALSE;
}
if (ConfigDesc->wTotalLength != Length)
{
DBGPRINT(0, ("I82930_ValidateConfigurationDescriptor: wTotalLength != Length\n"));
return FALSE;
}
//
// End of descriptor pointer, one byte past the last valid byte.
//
descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength;
//
// Start at first descriptor past the Configuration Descriptor header
//
commonDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)ConfigDesc +
sizeof(USB_CONFIGURATION_DESCRIPTOR));
interfaceDesc = NULL;
numInterfaces = 0;
while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd &&
(PUCHAR)commonDesc + commonDesc->bLength <= descEnd)
{
// Is this an Interface Descriptor?
//
if ((commonDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) &&
(commonDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR)))
{
if ((interfaceDesc == NULL) ||
(interfaceDesc->bInterfaceNumber !=
((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceNumber))
{
// One more Interface Descriptor for this Configuration Descriptor
//
numInterfaces++;
}
// If there was a previous Interface Descriptor, verify that there
// were the correct number of Endpoint Descriptors
//
if ((interfaceDesc != NULL) &&
(numEndpoints != interfaceDesc->bNumEndpoints))
{
DBGPRINT(0, ("I82930_ValidateConfigurationDescriptor: Bad bNumEndpoints\n"));
return FALSE;
}
// Remember the current Interface Descriptor
//
interfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)commonDesc;
// Reset the Endpoint Descriptor count for this Interface Descriptor
//
numEndpoints = 0;
}
// Is this an Endpoint Descriptor?
//
else if ((commonDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) &&
(commonDesc->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)))
{
// One more Endpoint Descriptor for this Interface Descriptor
//
numEndpoints++;
}
else
{
DBGPRINT(0, ("I82930_ValidateConfigurationDescriptor: Bad bDescriptorType and/or bLength\n"));
return FALSE;
}
// Advance past this descriptor
//
(PUCHAR)commonDesc += commonDesc->bLength;
}
if ((PUCHAR)commonDesc != descEnd)
{
DBGPRINT(0, ("I82930_ValidateConfigurationDescriptor: Bad final descriptor\n"));
return FALSE;
}
if (numInterfaces != ConfigDesc->bNumInterfaces)
{
DBGPRINT(0, ("I82930_ValidateConfigurationDescriptor: Bad bNumInterfaces and/or bLength\n"));
}
// If there was a previous Interface Descriptor, verify that there
// were the correct number of Endpoint Descriptors
//
if ((interfaceDesc != NULL) &&
(numEndpoints != interfaceDesc->bNumEndpoints))
{
DBGPRINT(0, ("I82930_ValidateConfigurationDescriptor: Bad bNumEndpoints\n"));
return FALSE;
}
return TRUE;
}
//******************************************************************************
//
// I82930_IoctlGetPipeInformation()
//
// This routine handles IRP_MJ_DEVICE_CONTROL,
// IOCTL_I82930_GET_PIPE_INFORMATION
//
//******************************************************************************
NTSTATUS
I82930_IoctlGetPipeInformation (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PVOID dest;
ULONG destLength;
PVOID src;
ULONG srcLength;
ULONG copyLength;
NTSTATUS ntStatus;
DBGPRINT(2, ("enter: I82930_IoctlGetPipeInformation\n"));
deviceExtension = DeviceObject->DeviceExtension;
if (deviceExtension->InterfaceInfo != NULL)
{
irpStack = IoGetCurrentIrpStackLocation(Irp);
dest = Irp->AssociatedIrp.SystemBuffer;
destLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
src = deviceExtension->InterfaceInfo;
srcLength = deviceExtension->InterfaceInfo->Length;
copyLength = (destLength < srcLength) ? destLength : srcLength;
RtlCopyMemory(dest, src, copyLength);
ntStatus = STATUS_SUCCESS;
}
else
{
copyLength = 0;
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = copyLength;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DBGPRINT(2, ("exit: I82930_IoctlGetPipeInformation %08X\n", ntStatus));
return ntStatus;
}
//******************************************************************************
//
// I82930_IoctlResetPipe()
//
// This routine handles IRP_MJ_DEVICE_CONTROL,
// IOCTL_I82930_RESET_PIPE
//
//******************************************************************************
NTSTATUS
I82930_IoctlResetPipe (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PFILE_OBJECT fileObject;
PI82930_PIPE pipe;
NTSTATUS ntStatus;
DBGPRINT(2, ("enter: I82930_IoctlResetPipe\n"));
deviceExtension = DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
pipe = fileObject->FsContext;
if (pipe != NULL)
{
DBGPRINT(2, ("Reset pipe %2d %08X\n",
pipe->PipeIndex, pipe));
ntStatus = I82930_ResetPipe(DeviceObject,
pipe,
TRUE);
}
else
{
ntStatus = STATUS_INVALID_PARAMETER;
}
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DBGPRINT(2, ("exit: I82930_IoctlResetPipe %08X\n", ntStatus));
return ntStatus;
}
//******************************************************************************
//
// I82930_IoctlStallPipe()
//
// This routine handles IRP_MJ_DEVICE_CONTROL,
// IOCTL_I82930_STALL_PIPE
//
//******************************************************************************
NTSTATUS
I82930_IoctlStallPipe (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PFILE_OBJECT fileObject;
PI82930_PIPE pipe;
PURB urb;
NTSTATUS ntStatus;
DBGPRINT(2, ("enter: I82930_IoctlStallPipe\n"));
deviceExtension = DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
pipe = fileObject->FsContext;
if (pipe != NULL)
{
DBGPRINT(2, ("Stall pipe %2d %08X\n",
pipe->PipeIndex, pipe));
// Allocate URB for CONTROL_FEATURE request
//
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_FEATURE_REQUEST));
if (urb != NULL)
{
// Initialize CONTROL_FEATURE request URB
//
urb->UrbHeader.Length = sizeof (struct _URB_CONTROL_FEATURE_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_SET_FEATURE_TO_ENDPOINT;
urb->UrbControlFeatureRequest.UrbLink = NULL;
urb->UrbControlFeatureRequest.FeatureSelector = USB_FEATURE_ENDPOINT_STALL;
urb->UrbControlFeatureRequest.Index = pipe->PipeInfo->EndpointAddress;
// Submit CONTROL_FEATURE request URB
//
ntStatus = I82930_SyncSendUsbRequest(DeviceObject, urb);
// Done with URB for CONTROL_FEATURE request, free it
//
ExFreePool(urb);
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
else
{
ntStatus = STATUS_INVALID_PARAMETER;
}
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DBGPRINT(2, ("exit: I82930_IoctlStallPipe %08X\n", ntStatus));
return ntStatus;
}
//******************************************************************************
//
// I82930_IoctlAbortPipe()
//
// This routine handles IRP_MJ_DEVICE_CONTROL,
// IOCTL_I82930_ABORT_PIPE
//
//******************************************************************************
NTSTATUS
I82930_IoctlAbortPipe (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
PFILE_OBJECT fileObject;
PI82930_PIPE pipe;
NTSTATUS ntStatus;
DBGPRINT(2, ("enter: I82930_IoctlAbortPipe\n"));
deviceExtension = DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
pipe = fileObject->FsContext;
if (pipe != NULL)
{
DBGPRINT(2, ("Abort pipe %2d %08X\n",
pipe->PipeIndex, pipe));
ntStatus = I82930_AbortPipe(DeviceObject,
pipe);
}
else
{
ntStatus = STATUS_INVALID_PARAMETER;
}
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DBGPRINT(2, ("exit: I82930_IoctlAbortPipe %08X\n", ntStatus));
return ntStatus;
}
//******************************************************************************
//
// I82930_IoctlResetDevice()
//
// This routine handles IRP_MJ_DEVICE_CONTROL,
// IOCTL_I82930_RESET_DEVICE
//
//******************************************************************************
NTSTATUS
I82930_IoctlResetDevice (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION nextStack;
NTSTATUS ntStatus;
DBGPRINT(2, ("enter: I82930_IoctlResetDevice\n"));
deviceExtension = DeviceObject->DeviceExtension;
// Set the Irp parameters
//
nextStack = IoGetNextIrpStackLocation(Irp);
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_RESET_PORT;
ntStatus = I82930_SyncPassDownIrp(DeviceObject,
Irp,
FALSE);
// Must complete request since completion routine returned
// STATUS_MORE_PROCESSING_REQUIRED
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DBGPRINT(2, ("exit: I82930_IoctlResetDevice %08X\n", ntStatus));
return ntStatus;
}
//******************************************************************************
//
// I82930_IoctlSelectAlternateInterface()
//
// This routine handles IRP_MJ_DEVICE_CONTROL,
// IOCTL_I82930_SELECT_ALTERNATE_INTERFACE
//
//******************************************************************************
NTSTATUS
I82930_IoctlSelectAlternateInterface (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
UCHAR alternateSetting;
NTSTATUS ntStatus;
DBGPRINT(2, ("enter: I82930_IoctlSelectAlternateInterface\n"));
deviceExtension = DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
if (irpStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(UCHAR))
{
alternateSetting = *(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
DBGPRINT(2, ("Select AlternateInterface %d\n",
alternateSetting));
ntStatus = I82930_SelectAlternateInterface(DeviceObject,
alternateSetting);
}
else
{
ntStatus = STATUS_INVALID_PARAMETER;
}
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DBGPRINT(2, ("exit: I82930_IoctlSelectAlternateInterface %08X\n", ntStatus));
return ntStatus;
}