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.
506 lines
14 KiB
506 lines
14 KiB
//**************************************************************************
|
|
//
|
|
// IOCTL.C -- Xena Gaming Project
|
|
//
|
|
// Version 3.XX
|
|
//
|
|
// Copyright (c) 1997 Microsoft Corporation. All rights reserved.
|
|
//
|
|
// @doc
|
|
// @module IOCTL.C | Routines to support internal ioctl queries
|
|
//**************************************************************************
|
|
|
|
#include "msgame.h"
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Alloc_text pragma to specify routines that can be paged out.
|
|
//---------------------------------------------------------------------------
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text (PAGE, MSGAME_GetDeviceDescriptor)
|
|
#pragma alloc_text (PAGE, MSGAME_GetReportDescriptor)
|
|
#pragma alloc_text (PAGE, MSGAME_GetAttributes)
|
|
#endif
|
|
|
|
//---------------------------------------------------------------------------
|
|
// @func Process the Control IRPs sent to this device
|
|
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
|
|
// @parm PIRP | pIrp | Pointer to IO request packet
|
|
// @rdesc Returns NT status code
|
|
// @comm Public function
|
|
//---------------------------------------------------------------------------
|
|
|
|
NTSTATUS MSGAME_Internal_Ioctl (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PDEVICE_EXTENSION pDevExt;
|
|
PIO_STACK_LOCATION pIrpStack;
|
|
|
|
MsGamePrint ((DBG_VERBOSE, "%s: %s_Internal_Ioctl Enter\n", MSGAME_NAME, MSGAME_NAME));
|
|
|
|
//
|
|
// Get pointer to current location in pIrp
|
|
//
|
|
|
|
pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
|
|
|
|
//
|
|
// Get a pointer to the device extension
|
|
//
|
|
|
|
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
|
|
|
|
//
|
|
// Increment IRP count to hold driver removes
|
|
//
|
|
|
|
InterlockedIncrement (&pDevExt->IrpCount);
|
|
|
|
//
|
|
// Check if we've been removed and bounce request
|
|
//
|
|
|
|
if (pDevExt->Removed)
|
|
{
|
|
//
|
|
// Someone sent us another IRP after removed
|
|
//
|
|
|
|
MsGamePrint ((DBG_SEVERE, "%s: internal Irp after device removed\n", MSGAME_NAME));
|
|
ASSERT (FALSE);
|
|
|
|
if (!InterlockedDecrement (&pDevExt->IrpCount))
|
|
KeSetEvent (&pDevExt->RemoveEvent, 0, FALSE);
|
|
|
|
pIrp->IoStatus.Information = 0;
|
|
pIrp->IoStatus.Status = STATUS_DELETE_PENDING;
|
|
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
|
|
return (STATUS_DELETE_PENDING);
|
|
}
|
|
|
|
//
|
|
// Process HID internal IO request
|
|
//
|
|
|
|
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
|
|
MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_DEVICE_DESCRIPTOR\n", MSGAME_NAME));
|
|
ntStatus = MSGAME_GetDeviceDescriptor (DeviceObject, pIrp);
|
|
break;
|
|
|
|
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
|
|
MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_REPORT_DESCRIPTOR\n", MSGAME_NAME));
|
|
ntStatus = MSGAME_GetReportDescriptor (DeviceObject, pIrp);
|
|
break;
|
|
|
|
case IOCTL_HID_READ_REPORT:
|
|
MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_READ_REPORT\n", MSGAME_NAME));
|
|
ntStatus = MSGAME_ReadReport (DeviceObject, pIrp);
|
|
break;
|
|
|
|
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
|
|
MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_DEVICE_ATTRIBUTES\n", MSGAME_NAME));
|
|
ntStatus = MSGAME_GetAttributes (DeviceObject, pIrp);
|
|
break;
|
|
|
|
case IOCTL_HID_ACTIVATE_DEVICE:
|
|
case IOCTL_HID_DEACTIVATE_DEVICE:
|
|
MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_(DE)ACTIVATE_DEVICE\n", MSGAME_NAME));
|
|
ntStatus = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IOCTL_HID_GET_FEATURE:
|
|
MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_FEATURE\n", MSGAME_NAME));
|
|
ntStatus = MSGAME_GetFeature (DeviceObject, pIrp);
|
|
break;
|
|
|
|
case IOCTL_HID_SET_FEATURE:
|
|
MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_SET_FEATURE\n", MSGAME_NAME));
|
|
ntStatus = STATUS_NOT_SUPPORTED;
|
|
break;
|
|
|
|
default:
|
|
MsGamePrint ((DBG_CONTROL, "%s: Unknown or unsupported IOCTL (%x)\n", MSGAME_NAME,
|
|
pIrpStack->Parameters.DeviceIoControl.IoControlCode));
|
|
ntStatus = STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set real return status in pIrp
|
|
//
|
|
|
|
pIrp->IoStatus.Status = ntStatus;
|
|
|
|
//
|
|
// Complete Irp
|
|
//
|
|
|
|
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
|
|
|
|
//
|
|
// Decrement IRP count for device removes
|
|
//
|
|
|
|
if (!InterlockedDecrement (&pDevExt->IrpCount))
|
|
KeSetEvent (&pDevExt->RemoveEvent, 0, FALSE);
|
|
|
|
//
|
|
// Return status
|
|
//
|
|
|
|
MsGamePrint ((DBG_VERBOSE, "%s: %s_Internal_Ioctl Exit = %x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// @func Processes the HID getdevice descriptor IRP
|
|
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
|
|
// @parm PIRP | pIrp | Pointer to IO request packet
|
|
// @rdesc Returns NT status code
|
|
// @comm Public function
|
|
//---------------------------------------------------------------------------
|
|
|
|
NTSTATUS MSGAME_GetDeviceDescriptor (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PDEVICE_EXTENSION pDevExt;
|
|
PIO_STACK_LOCATION pIrpStack;
|
|
|
|
PAGED_CODE ();
|
|
|
|
MsGamePrint ((DBG_INFORM, "%s: %s_GetDeviceDescriptor Enter\n", MSGAME_NAME, MSGAME_NAME));
|
|
|
|
//
|
|
// Get a pointer to the current location in the Irp
|
|
//
|
|
|
|
pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
|
|
|
|
//
|
|
// Get a pointer to the device extension
|
|
//
|
|
|
|
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
|
|
|
|
//
|
|
// Get device descriptor into HIDCLASS buffer
|
|
//
|
|
|
|
ntStatus = DEVICE_GetDeviceDescriptor (
|
|
&pDevExt->PortInfo,
|
|
pIrp->UserBuffer,
|
|
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
|
|
&pIrp->IoStatus.Information);
|
|
|
|
//
|
|
// Return status
|
|
//
|
|
|
|
MsGamePrint ((DBG_INFORM, "%s: %s_GetDeviceDescriptor Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
|
|
return (ntStatus);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// @func Processes the HID get report descriptor IRP
|
|
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
|
|
// @parm PIRP | pIrp | Pointer to IO request packet
|
|
// @rdesc Returns NT status code
|
|
// @comm Public function
|
|
//---------------------------------------------------------------------------
|
|
|
|
NTSTATUS MSGAME_GetReportDescriptor (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
|
|
{
|
|
PDEVICE_EXTENSION pDevExt;
|
|
PIO_STACK_LOCATION pIrpStack;
|
|
NTSTATUS ntStatus;
|
|
|
|
PAGED_CODE ();
|
|
|
|
MsGamePrint ((DBG_INFORM, "%s: %s_GetReportDescriptor Enter\n", MSGAME_NAME, MSGAME_NAME));
|
|
|
|
//
|
|
// Get a pointer to the current location in the Irp
|
|
//
|
|
|
|
pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
|
|
|
|
//
|
|
// Get a pointer to the device extension
|
|
//
|
|
|
|
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
|
|
|
|
//
|
|
// Get report descriptor into HIDCLASS buffer
|
|
//
|
|
|
|
ntStatus = DEVICE_GetReportDescriptor (
|
|
&pDevExt->PortInfo,
|
|
pIrp->UserBuffer,
|
|
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
|
|
&pIrp->IoStatus.Information);
|
|
|
|
//
|
|
// Return status
|
|
//
|
|
|
|
MsGamePrint ((DBG_INFORM, "%s: %s_GetReportDescriptor Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
|
|
return (ntStatus);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// @func Processes the HID get attributes IRP
|
|
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
|
|
// @parm PIRP | pIrp | Pointer to IO request packet
|
|
// @rdesc Returns NT status code
|
|
// @comm Public function
|
|
//---------------------------------------------------------------------------
|
|
|
|
NTSTATUS MSGAME_GetAttributes (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PDEVICE_EXTENSION pDevExt;
|
|
PIO_STACK_LOCATION irpStack;
|
|
PHID_DEVICE_ATTRIBUTES pDevAtt;
|
|
|
|
PAGED_CODE ();
|
|
|
|
MsGamePrint ((DBG_INFORM, "%s: %s_GetAttributes Entry\n", MSGAME_NAME, MSGAME_NAME));
|
|
|
|
//
|
|
// Get a pointer to the current location in the Irp
|
|
//
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
//
|
|
// Get a pointer to the device extension
|
|
//
|
|
|
|
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
|
|
pDevAtt = (PHID_DEVICE_ATTRIBUTES) Irp->UserBuffer;
|
|
|
|
ASSERT(sizeof(HID_DEVICE_ATTRIBUTES) == irpStack->Parameters.DeviceIoControl.OutputBufferLength);
|
|
|
|
//
|
|
// Fill in HID device attributes
|
|
//
|
|
|
|
pDevAtt->Size = sizeof (HID_DEVICE_ATTRIBUTES);
|
|
pDevAtt->VendorID = MSGAME_VENDOR_ID;
|
|
pDevAtt->ProductID = GET_DEVICE_ID(&pDevExt->PortInfo);
|
|
pDevAtt->VersionNumber = MSGAME_VERSION_NUMBER;
|
|
|
|
//
|
|
// Report how many bytes were copied
|
|
//
|
|
|
|
Irp->IoStatus.Information = sizeof (HID_DEVICE_ATTRIBUTES);
|
|
|
|
//
|
|
// Return status
|
|
//
|
|
|
|
MsGamePrint ((DBG_INFORM, "%s: %s_GetAttributes Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
|
|
return (ntStatus);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// @func Processes the HID get device features IRP
|
|
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
|
|
// @parm PIRP | pIrp | Pointer to IO request packet
|
|
// @rdesc Returns NT status code
|
|
// @comm Public function
|
|
//---------------------------------------------------------------------------
|
|
|
|
NTSTATUS MSGAME_GetFeature (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PDEVICE_EXTENSION pDevExt;
|
|
PIO_STACK_LOCATION irpStack;
|
|
PHID_XFER_PACKET Packet;
|
|
PUCHAR Report;
|
|
|
|
MsGamePrint ((DBG_INFORM, "%s: %s_GetFeature Entry\n", MSGAME_NAME, MSGAME_NAME));
|
|
|
|
//
|
|
// Get a pointer to the current location in the Irp
|
|
//
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
//
|
|
// Get a pointer to the device extension
|
|
//
|
|
|
|
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
|
|
|
|
//
|
|
// Get pointer to feature packet
|
|
//
|
|
|
|
Packet = (PHID_XFER_PACKET)Irp->UserBuffer;
|
|
|
|
//
|
|
// Test packet size in case version error
|
|
//
|
|
|
|
ASSERT (irpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(HID_XFER_PACKET));
|
|
|
|
//
|
|
// Setup return values (return HidReportId even on errors)
|
|
//
|
|
|
|
Report = Packet->reportBuffer;
|
|
*(PHID_REPORT_ID)Report++ = (HID_REPORT_ID)Packet->reportId;
|
|
Irp->IoStatus.Information = sizeof (HID_REPORT_ID);
|
|
|
|
//
|
|
// Check if device has been removed
|
|
//
|
|
|
|
if (pDevExt->Removed || pDevExt->Surprised)
|
|
{
|
|
MsGamePrint ((DBG_SEVERE, "%s: %s_GetFeature On Removed Device!\n", MSGAME_NAME, MSGAME_NAME));
|
|
return (STATUS_DELETE_PENDING);
|
|
}
|
|
|
|
//
|
|
// Check if device being removed
|
|
//
|
|
|
|
if (pDevExt->Removing)
|
|
{
|
|
MsGamePrint ((DBG_SEVERE, "%s: %s_GetFeature On Device Pending Removal!\n", MSGAME_NAME, MSGAME_NAME));
|
|
return (STATUS_DELETE_PENDING);
|
|
}
|
|
|
|
//
|
|
// Call mini-driver to process
|
|
//
|
|
|
|
MsGamePrint ((DBG_INFORM, "%s: %s_GetFeature Report Id = %lu\n", MSGAME_NAME, MSGAME_NAME, Packet->reportId));
|
|
ntStatus = DEVICE_GetFeature (&pDevExt->PortInfo,
|
|
Packet->reportId,
|
|
Report,
|
|
Packet->reportBufferLen,
|
|
&Irp->IoStatus.Information);
|
|
|
|
//
|
|
// Return status
|
|
//
|
|
|
|
MsGamePrint ((DBG_INFORM, "%s: %s_GetFeature Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
|
|
return (ntStatus);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// @func Processes the HID read report IRP
|
|
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
|
|
// @parm PIRP | pIrp | Pointer to IO request packet
|
|
// @rdesc Returns NT status code
|
|
// @comm Public function
|
|
//---------------------------------------------------------------------------
|
|
|
|
NTSTATUS MSGAME_ReadReport (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_PENDING;
|
|
PDEVICE_EXTENSION pDevExt;
|
|
PIO_STACK_LOCATION pIrpStack;
|
|
PIO_STACK_LOCATION nextStack;
|
|
KIRQL OldIrql;
|
|
PUCHAR Report;
|
|
|
|
MsGamePrint ((DBG_VERBOSE, "%s: %s_ReadReport Enter\n", MSGAME_NAME, MSGAME_NAME));
|
|
|
|
//
|
|
// Get a pointer to the device extension.
|
|
//
|
|
|
|
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
|
|
|
|
//
|
|
// Get stack location
|
|
//
|
|
|
|
pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
|
|
|
|
//
|
|
// Setup return values (return HidReportId even on errors)
|
|
//
|
|
|
|
Report = pIrp->UserBuffer;
|
|
if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength > sizeof (DEVICE_PACKET))
|
|
{
|
|
*(PHID_REPORT_ID)Report++ = (HID_REPORT_ID)MSGAME_INPUT_JOYINFOEX;
|
|
pIrp->IoStatus.Information = sizeof (HID_REPORT_ID);
|
|
}
|
|
else pIrp->IoStatus.Information = 0;
|
|
|
|
//
|
|
// Check if device has been removed
|
|
//
|
|
|
|
if (pDevExt->Removed || pDevExt->Surprised)
|
|
{
|
|
MsGamePrint ((DBG_SEVERE, "%s: %s_ReadReport On Removed Device!\n", MSGAME_NAME, MSGAME_NAME));
|
|
return (STATUS_DELETE_PENDING);
|
|
}
|
|
|
|
//
|
|
// Check if device being removed
|
|
//
|
|
|
|
if (pDevExt->Removing)
|
|
{
|
|
MsGamePrint ((DBG_SEVERE, "%s: %s_ReadReport On Device Pending Removal!\n", MSGAME_NAME, MSGAME_NAME));
|
|
return (STATUS_DELETE_PENDING);
|
|
}
|
|
|
|
//
|
|
// Poll the device layer
|
|
//
|
|
|
|
ntStatus = DEVICE_ReadReport (
|
|
&pDevExt->PortInfo,
|
|
Report,
|
|
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
|
|
&pIrp->IoStatus.Information);
|
|
|
|
//
|
|
// Check status for device changes
|
|
//
|
|
|
|
switch (ntStatus)
|
|
{
|
|
case STATUS_SIBLING_ADDED:
|
|
//
|
|
// Tell GameEnum to Create a Device
|
|
//
|
|
ntStatus = MSGAME_CreateDevice (DeviceObject);
|
|
break;
|
|
|
|
case STATUS_SIBLING_REMOVED:
|
|
//
|
|
// Tell GameEnum to Remove a Device
|
|
//
|
|
ntStatus = MSGAME_RemoveDevice (DeviceObject);
|
|
break;
|
|
|
|
case STATUS_DEVICE_CHANGED:
|
|
//
|
|
// Tell GameEnum to Create a New Device
|
|
//
|
|
ntStatus = MSGAME_ChangeDevice (DeviceObject);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Return status
|
|
//
|
|
|
|
MsGamePrint ((DBG_VERBOSE, "%s: %s_ReadReport Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
|
|
return (ntStatus);
|
|
}
|