windows-nt/Source/XPSP1/NT/drivers/wdm/usb/driver/usbdiag/ioctl.c
2020-09-26 16:20:57 +08:00

313 lines
8.6 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
ioctl.c
Abstract:
USB device driver for Intel/Microsoft diagnostic apps
Environment:
kernel mode only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
Revision History:
5-4-96 : created
7-21-97 : Added Chapter 11 IOCTL's (t-toddca)
--*/
#define DRIVER
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
// Enable 1-byte alignment in structs
#pragma pack (push,1)
#include "usb100.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "usbioctl.h"
#pragma pack (pop) //disable 1-byte alignment
#include "opaque.h"
// Enable 1-byte alignment in structs
#pragma pack (push,1)
#include "ioctl.h"
#include "chap9drv.h"
#include "USBDIAG.h"
#pragma pack (pop) //disable 1-byte alignment
extern USBD_VERSION_INFORMATION gVersionInformation;
NTSTATUS
USBDIAG_ProcessIOCTL(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - pointer to the device object for this instance of the 82930
devcice.
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
PDEVICE_EXTENSION deviceExtension;
ULONG ioControlCode;
NTSTATUS ntStatus = STATUS_SUCCESS;
USBDIAG_KdPrint(("USBDIAG.SYS: IRP_MJ_DEVICE_CONTROL\n"));
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//
// Get a pointer to the device extension
//
deviceExtension = DeviceObject->DeviceExtension;
//USBDIAG_KdPrint(("USBDIAG.SYS: DeviceObj: %X | DeviceExt: %X\n",DeviceObject, DeviceObject->DeviceExtension));
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
USBDIAG_KdPrint(("USBDIAG.SYS: IOControlCode: %X\n", ioControlCode));
//
// Handle Ioctls from User mode
//
switch (ioControlCode) {
case IOCTL_USBDIAG_GET_USBDI_VERSION:
{
PULONG pulUSBDIVersion = (PULONG)ioBuffer;
*pulUSBDIVersion = gVersionInformation.USBDI_Version;
Irp->IoStatus.Status = ntStatus = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(ULONG);
}
break;
case IOCTL_USBDIAG_CHAP9_GET_DEVHANDLE:
{
//
// inputs - ptr to _REQ_DEVICE_HANDLES structure
// with devicehandle set to the last handle
// returned or NULL.
// outputs -
//
struct _REQ_DEVICE_HANDLES *reqDeviceHandles;
PDEVICE_LIST_ENTRY device;
PDEVICE_EXTENSION localDeviceExtension;
PDEVICE_OBJECT deviceObject;
//USBDIAG_KdPrint(("USBDIAG.SYS: IOCTL_USBDIAG_CHAP9_GET_DEVHANDLE\n"));
// walk our list of PDOs and find the current one
// if cuurent is NULL return the first PDO in our list
// if current can not be found then return NULL for next_device
reqDeviceHandles = ioBuffer;
//
// Check that the buffer length is of the appropriate size
//
if (inputBufferLength < sizeof(struct _REQ_DEVICE_HANDLES) ||
outputBufferLength < sizeof(struct _REQ_DEVICE_HANDLES)) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
device = deviceExtension->DeviceList;
// should always have at least one
if (device != NULL)
{
if (reqDeviceHandles->DeviceHandle != NULL)
{
//
// Searching for the next device in the list
//
while (device != NULL && device != reqDeviceHandles->DeviceHandle)
{
device = device->Next;
}
//
// Make device point to the next possible device in our list,
// if we haven't reached the end of the list
//
if (NULL != device)
{
device = device -> Next;
}
}
//
// At this point, device is either NULL or points to a usbdiag
// device. However, the diag device may not yet be started and
// if so, should not be reported in this query so we must skip
// over it. We will skip over all such devices in our list.
// Do that here.
//
while (device != NULL)
{
deviceObject = FDO_FROM_DEVICE_HANDLE(device);
localDeviceExtension = deviceObject -> DeviceExtension;
if (!(localDeviceExtension -> Stopped))
{
//
// Found a legit started device, break out of this loop
//
break;
}
//
// Oops, we've got a device but it hasn't been started yet,
// don't return it in the query. Try the next one in the list.
//
device = device -> Next;
}
//
// At this point, device is either NULL or points to a device that
// can be legitimately returned to the calling app. If a legit
// device, then create a device string for it.
//
if (NULL != device)
{
sprintf(reqDeviceHandles->DeviceString,
"%2.2d Vid (0x%4.4x) Pid (0x%4.4x)",
device->DeviceNumber,
localDeviceExtension->pDeviceDescriptor->idVendor,
localDeviceExtension->pDeviceDescriptor->idProduct);
}
}
reqDeviceHandles -> NextDeviceHandle = device;
Irp->IoStatus.Information = sizeof(struct _REQ_DEVICE_HANDLES);
Irp->IoStatus.Status = STATUS_SUCCESS;
}
break;
case IOCTL_USBDIAG_CHAP9_CONTROL:
//
// inputs -
// outputs -
//
//USBDIAG_KdPrint(("USBDIAG.SYS: IOCTL_USBDIAG_CHAP9_CONTROL\n"));
ntStatus = USBDIAG_Chap9Control(DeviceObject, Irp);
//USBDIAG_KdPrint(("USBDIAG.SYS: Done w/ IOCTL_USBDIAG_CHAP9_CONTROL\n"));
goto USBDIAG_ProcessIOCTL_Done;
break;
case IOCTL_USBDIAG_HIDP_GETCOLLECTION:
/*
// calls thru to the HID Parser
// NOTE: The function called will complete the IRP since it will
// free the buffers created by the HID parser immediately
// thereafter, and since BUFFERED method is used, the IOS
// needs the buffers to be present while it's copying it
// back to the user space. So, we jump to the end to avoid this.
*/
//USBDIAG_KdPrint(("USBDIAG.SYS: IOCTL_USBDIAG_HIDP_GETCOLLECTION\n"));
ntStatus = USBDIAG_HIDP_GetCollection (DeviceObject, Irp);
break;
case IOCTL_USBDIAG_CONFIGURE_DEVICE:
/*
// Configures a given device in the given configuration
// Input: IOCTL block indicating what configuration to put
// device into
// Output: Success/error code
//
*/
//USBDIAG_KdPrint(("USBDIAG.SYS: IOCTL_USBDIAG_CONFIGURE_DEVICE\n"));
ntStatus = USBDIAG_Configure_Device (DeviceObject, Irp);
break;
default:
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
//USBDIAG_KdPrint(("USBDIAG.SYS: Chap9Ctrl Compltng Irp w/ IoStatus.Status=%X | .Inf = %X | ntSt=%X\n",
//Irp->IoStatus.Status, Irp->IoStatus.Information, ntStatus));
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
USBDIAG_ProcessIOCTL_Done:
return ntStatus;
}