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.
 
 
 
 
 
 

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);
}