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.
 
 
 
 
 
 

507 lines
21 KiB

//**************************************************************************
//
// MSGAME.C -- Xena Gaming Project
//
// Version 3.XX
//
// Copyright (c) 1997 Microsoft Corporation. All rights reserved.
//
// @doc
// @module MSGAME.C | Human Input Device (HID) gameport driver
//**************************************************************************
#include "msgame.h"
//---------------------------------------------------------------------------
// Alloc_text pragma to specify routines that can be paged out.
//---------------------------------------------------------------------------
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (INIT, MSGAME_ReadRegistry)
#pragma alloc_text (PAGE, MSGAME_CreateClose)
#pragma alloc_text (PAGE, MSGAME_SystemControl)
#pragma alloc_text (PAGE, MSGAME_AddDevice)
#endif
//---------------------------------------------------------------------------
// Private Data
//---------------------------------------------------------------------------
static UNICODE_STRING RegistryPath;
//---------------------------------------------------------------------------
// @func Main driver entry point
// @parm PDRIVER_OBJECT | DriverObject | Pointer to driver object
// @parm PUNICODE_STRING | registryPath | Registry path for this device
// @rdesc Returns NT status code
// @comm Public function
//---------------------------------------------------------------------------
NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING registryPath)
{
NTSTATUS ntStatus;
RTL_QUERY_REGISTRY_TABLE Parameters[2];
HID_MINIDRIVER_REGISTRATION HidMinidriverRegistration;
MsGamePrint ((DBG_CRITICAL, "%s: Built %s at %s\n", MSGAME_NAME, __DATE__, __TIME__));
MsGamePrint ((DBG_INFORM, "%s: DriverEntry Enter\n", MSGAME_NAME));
//
// Fill in driver dispatch table
//
DriverObject->MajorFunction[IRP_MJ_CREATE] = MSGAME_CreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MSGAME_CreateClose;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = MSGAME_Internal_Ioctl;
DriverObject->MajorFunction[IRP_MJ_PNP] = MSGAME_PnP;
DriverObject->MajorFunction[IRP_MJ_POWER] = MSGAME_Power;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = MSGAME_SystemControl;
DriverObject->DriverUnload = MSGAME_Unload;
DriverObject->DriverExtension->AddDevice = MSGAME_AddDevice;
//
// Register driver with Hid.Sys
//
HidMinidriverRegistration.Revision = HID_REVISION;
HidMinidriverRegistration.DriverObject = DriverObject;
HidMinidriverRegistration.RegistryPath = registryPath;
HidMinidriverRegistration.DeviceExtensionSize = sizeof (DEVICE_EXTENSION);
HidMinidriverRegistration.DevicesArePolled = TRUE;
MsGamePrint ((DBG_CONTROL, "%s: Registering with HID.SYS\n", MSGAME_NAME));
ntStatus = HidRegisterMinidriver (&HidMinidriverRegistration);
//
// Need to ensure that the registry path is null-terminated.
// Allocate pool to hold a null-terminated copy of the path.
//
if (NT_SUCCESS(ntStatus))
{
RtlInitUnicodeString (&RegistryPath, NULL);
RegistryPath.Length = registryPath->Length + sizeof(UNICODE_NULL);
RegistryPath.MaximumLength = RegistryPath.Length;
RegistryPath.Buffer = ExAllocatePool (PagedPool, RegistryPath.Length);
RtlZeroMemory (RegistryPath.Buffer, RegistryPath.Length);
RtlMoveMemory (RegistryPath.Buffer, registryPath->Buffer, registryPath->Length);
}
//
// Read any driver specific registry values
//
if (NT_SUCCESS(ntStatus))
{
RtlZeroMemory (Parameters, sizeof(Parameters));
Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[0].Name = L"PollingInterval";
Parameters[0].EntryContext = &PollingInterval;
Parameters[0].DefaultType = REG_DWORD;
Parameters[0].DefaultData = &PollingInterval;
Parameters[0].DefaultLength = sizeof(ULONG);
if (!NT_SUCCESS(RtlQueryRegistryValues (RTL_REGISTRY_ABSOLUTE, RegistryPath.Buffer, Parameters, NULL, NULL)))
{
MsGamePrint((DBG_INFORM,"%s: %s_DriverEntry RtlQueryRegistryValues failed\n", MSGAME_NAME, MSGAME_NAME));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, RegistryPath.Buffer, L"PollingInterval", REG_DWORD, &PollingInterval, sizeof (ULONG));
}
MsGamePrint((DBG_CONTROL,"%s: Polling interval will be %lu milliseconds\n", MSGAME_NAME, PollingInterval));
}
//
// Initialize portio layer on entry
//
if (NT_SUCCESS(ntStatus))
ntStatus = PORTIO_DriverEntry ();
//
// Initialize device layer on entry
//
if (NT_SUCCESS(ntStatus))
ntStatus = DEVICE_DriverEntry ();
//
// Return driver status
//
MsGamePrint ((DBG_INFORM, "%s: DriverEntry Exit = %x\n", MSGAME_NAME, ntStatus));
return (ntStatus);
}
//---------------------------------------------------------------------------
// @func Process the Create and Close IRPs
// @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_CreateClose (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION IrpStack;
NTSTATUS ntStatus = STATUS_SUCCESS;
PAGED_CODE ();
MsGamePrint ((DBG_INFORM, "%s: %s_CreateClose Enter\n", MSGAME_NAME, MSGAME_NAME));
//
// Get pointer to current location in Irp
//
IrpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Process Create or Close function call
//
switch (IrpStack->MajorFunction)
{
case IRP_MJ_CREATE:
MsGamePrint ((DBG_VERBOSE, "%s: IRP_MJ_CREATE\n", MSGAME_NAME));
Irp->IoStatus.Information = 0;
break;
case IRP_MJ_CLOSE:
MsGamePrint ((DBG_VERBOSE, "%s: IRP_MJ_CLOSE\n", MSGAME_NAME));
Irp->IoStatus.Information = 0;
break;
default:
MsGamePrint ((DBG_SEVERE, "%s: Invalid CreateClose Parameter\n", MSGAME_NAME));
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
//
// Save Status for return and complete Irp
//
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
MsGamePrint ((DBG_INFORM, "%s: %s_CreateClose Exit = %x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
return (ntStatus);
}
//---------------------------------------------------------------------------
// @func Process the WMI system control IRPs
// @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_SystemControl (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PAGED_CODE ();
MsGamePrint ((DBG_INFORM, "%s: %s_SystemControl Enter\n", MSGAME_NAME, MSGAME_NAME));
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver (GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
MsGamePrint ((DBG_INFORM, "%s: %s_SystemControl Exit = %x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
return (ntStatus);
}
//---------------------------------------------------------------------------
// @func Processes the Pnp Add Device call
// @parm PDRIVER_OBJECT | DriverObject | Pointer to driver object
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
// @rdesc Returns NT status code
// @comm Public function
//---------------------------------------------------------------------------
NTSTATUS MSGAME_AddDevice (IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION pDevExt;
PAGED_CODE ();
MsGamePrint ((DBG_INFORM, "%s: %s_AddDevice Entry\n", MSGAME_NAME, MSGAME_NAME));
//
// Initialize the device extension
//
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
memset(pDevExt, 0, sizeof(DEVICE_EXTENSION));
pDevExt->Driver = DriverObject;
pDevExt->Self = DeviceObject;
pDevExt->IrpCount = 1;
pDevExt->Started = FALSE;
pDevExt->Removed = FALSE;
pDevExt->Surprised = FALSE;
pDevExt->Removing = FALSE;
pDevExt->TopOfStack = NULL;
KeInitializeEvent (&pDevExt->StartEvent, NotificationEvent, FALSE);
KeInitializeEvent (&pDevExt->RemoveEvent, SynchronizationEvent, FALSE);
//
// Clear device initialization flags
//
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
//
// Attach our functional driver to the device stack. The return value of
// IoAttachDeviceToDeviceStack is the top of the attachment chain. This
// is where all the IRPs should be routed.
//
pDevExt->TopOfStack = GET_NEXT_DEVICE_OBJECT(DeviceObject);
//
// If this attachment fails then top of stack will be null. Failure
// for attachment is an indication of a broken plug play system.
//
ASSERT (pDevExt->TopOfStack);
//
// Return status
//
MsGamePrint ((DBG_INFORM, "%s: %s_AddDevice Exit = %x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
return (ntStatus);
}
//---------------------------------------------------------------------------
// @func Processes the driver unload call
// @parm PDRIVER_OBJECT | DriverObject | Pointer to driver object
// @rdesc Returns NT status code
// @comm Public function
//---------------------------------------------------------------------------
VOID MSGAME_Unload (IN PDRIVER_OBJECT DriverObject)
{
PAGED_CODE();
MsGamePrint ((DBG_INFORM, "%s: %s_Unload Enter\n", MSGAME_NAME, MSGAME_NAME));
//
// All the device objects should be gone
//
ASSERT (!DriverObject->DeviceObject);
//
// Free the unicode strings.
//
ExFreePool (RegistryPath.Buffer);
MsGamePrint ((DBG_CONTROL, "%s: %s_Unload Exit\n", MSGAME_NAME, MSGAME_NAME));
}
//---------------------------------------------------------------------------
// @func Reads registry data for a named device
// @parm PCHAR | DeviceName | Device name string
// @parm PDEVICE_VALUES | DeviceValues | Device values structure to fill
// @rdesc Returns nothing
// @comm Public function
//---------------------------------------------------------------------------
VOID MSGAME_ReadRegistry (PCHAR DeviceName, PDEVICE_VALUES DeviceValues)
{
#define PARAMS_PLUS_ONE 13
NTSTATUS ntStatus;
ANSI_STRING AnsiName;
UNICODE_STRING UnicodeName;
UNICODE_STRING ParametersPath;
PRTL_QUERY_REGISTRY_TABLE Parameters;
MsGamePrint((DBG_INFORM,"%s: %s_ReadRegistry Enter\n", MSGAME_NAME, MSGAME_NAME));
//
// Initialize local variables
//
RtlInitAnsiString (&AnsiName, DeviceName);
RtlInitUnicodeString (&UnicodeName, NULL);
RtlInitUnicodeString (&ParametersPath, NULL);
Parameters = ExAllocatePool (PagedPool, sizeof(RTL_QUERY_REGISTRY_TABLE) * PARAMS_PLUS_ONE);
if (!Parameters)
{
MsGamePrint((DBG_CRITICAL, "%s: %s_ReadRegistry couldn't allocate Rtl query table for %ws\n", MSGAME_NAME, MSGAME_NAME, RegistryPath.Buffer));
goto ReadRegistryExit;
}
RtlZeroMemory (Parameters, sizeof(RTL_QUERY_REGISTRY_TABLE) * PARAMS_PLUS_ONE);
//
// Form a path to this driver's Parameters subkey.
//
ParametersPath.MaximumLength = RegistryPath.Length + MAX_DEVICE_NAME;
ParametersPath.Buffer = ExAllocatePool (PagedPool, ParametersPath.MaximumLength);
if (!ParametersPath.Buffer)
{
MsGamePrint((DBG_CRITICAL, "%s: %s_ReadRegistry couldn't allocate path string for %ws\n", MSGAME_NAME, MSGAME_NAME, RegistryPath.Buffer));
goto ReadRegistryExit;
}
//
// Form the Parameters path.
//
RtlZeroMemory (ParametersPath.Buffer, ParametersPath.MaximumLength);
RtlAppendUnicodeToString (&ParametersPath, RegistryPath.Buffer);
RtlAppendUnicodeToString (&ParametersPath, L"\\");
RtlAnsiStringToUnicodeString (&UnicodeName, &AnsiName, TRUE);
RtlAppendUnicodeStringToString (&ParametersPath, &UnicodeName);
RtlFreeUnicodeString (&UnicodeName);
MsGamePrint((DBG_VERBOSE, "%s: %s_ReadRegistry path is %ws\n", MSGAME_NAME, MSGAME_NAME, ParametersPath.Buffer));
//
// Gather all device information from the registry.
//
Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[0].Name = L"PacketStartTimeout";
Parameters[0].EntryContext = &DeviceValues->PacketStartTimeout;
Parameters[0].DefaultType = REG_DWORD;
Parameters[0].DefaultData = &DeviceValues->PacketStartTimeout;
Parameters[0].DefaultLength = sizeof(ULONG);
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[1].Name = L"PacketLowHighTimeout";
Parameters[1].EntryContext = &DeviceValues->PacketLowHighTimeout;
Parameters[1].DefaultType = REG_DWORD;
Parameters[1].DefaultData = &DeviceValues->PacketLowHighTimeout;
Parameters[1].DefaultLength = sizeof(ULONG);
Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[2].Name = L"PacketHighLowTimeout";
Parameters[2].EntryContext = &DeviceValues->PacketHighLowTimeout;
Parameters[2].DefaultType = REG_DWORD;
Parameters[2].DefaultData = &DeviceValues->PacketHighLowTimeout;
Parameters[2].DefaultLength = sizeof(ULONG);
Parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[3].Name = L"IdStartTimeout";
Parameters[3].EntryContext = &DeviceValues->IdStartTimeout;
Parameters[3].DefaultType = REG_DWORD;
Parameters[3].DefaultData = &DeviceValues->IdStartTimeout;
Parameters[3].DefaultLength = sizeof(ULONG);
Parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[4].Name = L"IdLowHighTimeout";
Parameters[4].EntryContext = &DeviceValues->IdLowHighTimeout;
Parameters[4].DefaultType = REG_DWORD;
Parameters[4].DefaultData = &DeviceValues->IdLowHighTimeout;
Parameters[4].DefaultLength = sizeof(ULONG);
Parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[5].Name = L"IdHighLowTimeout";
Parameters[5].EntryContext = &DeviceValues->IdHighLowTimeout;
Parameters[5].DefaultType = REG_DWORD;
Parameters[5].DefaultData = &DeviceValues->IdHighLowTimeout;
Parameters[5].DefaultLength = sizeof(ULONG);
Parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[6].Name = L"InterruptDelay";
Parameters[6].EntryContext = &DeviceValues->InterruptDelay;
Parameters[6].DefaultType = REG_DWORD;
Parameters[6].DefaultData = &DeviceValues->InterruptDelay;
Parameters[6].DefaultLength = sizeof(ULONG);
Parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[7].Name = L"MaxClockDutyCycle";
Parameters[7].EntryContext = &DeviceValues->MaxClockDutyCycle;
Parameters[7].DefaultType = REG_DWORD;
Parameters[7].DefaultData = &DeviceValues->MaxClockDutyCycle;
Parameters[7].DefaultLength = sizeof(ULONG);
Parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[8].Name = L"StatusStartTimeout";
Parameters[8].EntryContext = &DeviceValues->StatusStartTimeout;
Parameters[8].DefaultType = REG_DWORD;
Parameters[8].DefaultData = &DeviceValues->StatusStartTimeout;
Parameters[8].DefaultLength = sizeof(ULONG);
Parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[9].Name = L"StatusLowHighTimeout";
Parameters[9].EntryContext = &DeviceValues->StatusLowHighTimeout;
Parameters[9].DefaultType = REG_DWORD;
Parameters[9].DefaultData = &DeviceValues->StatusLowHighTimeout;
Parameters[9].DefaultLength = sizeof(ULONG);
Parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[10].Name = L"StatusHighLowTimeout";
Parameters[10].EntryContext = &DeviceValues->StatusHighLowTimeout;
Parameters[10].DefaultType = REG_DWORD;
Parameters[10].DefaultData = &DeviceValues->StatusHighLowTimeout;
Parameters[10].DefaultLength = sizeof(ULONG);
Parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT;
Parameters[11].Name = L"StatusGateTimeout";
Parameters[11].EntryContext = &DeviceValues->StatusGateTimeout;
Parameters[11].DefaultType = REG_DWORD;
Parameters[11].DefaultData = &DeviceValues->StatusGateTimeout;
Parameters[11].DefaultLength = sizeof(ULONG);
ntStatus = RtlQueryRegistryValues (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, Parameters, NULL, NULL);
if (!NT_SUCCESS(ntStatus))
{
MsGamePrint((DBG_INFORM,"%s: %s_ReadRegistry RtlQueryRegistryValues failed with 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
//
// Create registry entries as needed
//
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"PacketStartTimeout", REG_DWORD, &DeviceValues->PacketStartTimeout, sizeof (ULONG));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"PacketLowHighTimeout", REG_DWORD, &DeviceValues->PacketLowHighTimeout, sizeof (ULONG));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"PacketHighLowTimeout", REG_DWORD, &DeviceValues->PacketHighLowTimeout, sizeof (ULONG));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"IdStartTimeout", REG_DWORD, &DeviceValues->IdStartTimeout, sizeof (ULONG));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"IdLowHighTimeout", REG_DWORD, &DeviceValues->IdLowHighTimeout, sizeof (ULONG));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"IdHighLowTimeout", REG_DWORD, &DeviceValues->IdHighLowTimeout, sizeof (ULONG));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"InterruptDelay", REG_DWORD, &DeviceValues->InterruptDelay, sizeof (ULONG));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"MaxClockDutyCycle", REG_DWORD, &DeviceValues->MaxClockDutyCycle, sizeof (ULONG));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"StatusStartTimeout", REG_DWORD, &DeviceValues->StatusStartTimeout, sizeof (ULONG));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"StatusLowHighTimeout", REG_DWORD, &DeviceValues->StatusLowHighTimeout, sizeof (ULONG));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"StatusHighLowTimeout", REG_DWORD, &DeviceValues->StatusHighLowTimeout, sizeof (ULONG));
RtlWriteRegistryValue (RTL_REGISTRY_ABSOLUTE, ParametersPath.Buffer, L"StatusGateTimeout", REG_DWORD, &DeviceValues->StatusGateTimeout, sizeof (ULONG));
}
// -----------------
ReadRegistryExit:
// -----------------
if (ParametersPath.Buffer)
ExFreePool(ParametersPath.Buffer);
if (Parameters)
ExFreePool(Parameters);
#undef PARAMS_PLUS_ONE
}
//---------------------------------------------------------------------------
// @func Posts a transaction to hooking driver
// @parm PPACKETINFO | PacketInfo | Device packet info struct
// @rdesc None
// @comm Public function
//---------------------------------------------------------------------------
VOID MSGAME_PostTransaction (PPACKETINFO PacketInfo)
{
//
// Not Implemented
//
}