/*++ 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; }