297 lines
7.1 KiB
C
297 lines
7.1 KiB
C
/*++
|
|
|
|
Copyright (c) 1996,1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
hidir.c
|
|
|
|
Abstract: Human Input Device (HID) minidriver that creates an example
|
|
device.
|
|
|
|
--*/
|
|
#include "pch.h"
|
|
|
|
VOID
|
|
HidIrCheckIfMediaCenter();
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,DriverEntry)
|
|
#pragma alloc_text(INIT,HidIrCheckIfMediaCenter)
|
|
#endif
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING registryPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Installable driver initialization entry point.
|
|
This entry point is called directly by the I/O system.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - pointer to the driver object
|
|
|
|
registryPath - pointer to a unicode string representing the path,
|
|
to driver-specific key in the registry.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS if successful,
|
|
STATUS_UNSUCCESSFUL otherwise
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
HID_MINIDRIVER_REGISTRATION HidIrdriverRegistration;
|
|
|
|
HidIrKdPrint((3, "DriverEntry Enter"));
|
|
|
|
HidIrKdPrint((3, "DriverObject (%lx)", DriverObject));
|
|
|
|
//
|
|
// Create dispatch points
|
|
//
|
|
// All of the other dispatch routines are handled by HIDCLASS, except for
|
|
// IRP_MJ_POWER, which isn't implemented yet.
|
|
//
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HidIrIoctl;
|
|
DriverObject->MajorFunction[IRP_MJ_PNP] = HidIrPnP;
|
|
DriverObject->MajorFunction[IRP_MJ_POWER] = HidIrPower;
|
|
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HidIrSystemControl;
|
|
DriverObject->DriverExtension->AddDevice = HidIrAddDevice;
|
|
DriverObject->DriverUnload = HidIrUnload;
|
|
|
|
//
|
|
// Register Sample layer with HIDCLASS.SYS module
|
|
//
|
|
|
|
HidIrdriverRegistration.Revision = HID_REVISION;
|
|
HidIrdriverRegistration.DriverObject = DriverObject;
|
|
HidIrdriverRegistration.RegistryPath = registryPath;
|
|
HidIrdriverRegistration.DeviceExtensionSize = sizeof(HIDIR_EXTENSION);
|
|
|
|
// HIDIR does not need to be polled.
|
|
HidIrdriverRegistration.DevicesArePolled = FALSE;
|
|
|
|
HidIrKdPrint((3, "DeviceExtensionSize = %x", HidIrdriverRegistration.DeviceExtensionSize));
|
|
|
|
HidIrKdPrint((3, "Registering with HIDCLASS.SYS"));
|
|
|
|
HidIrCheckIfMediaCenter();
|
|
|
|
//
|
|
// After registering with HIDCLASS, it takes over control of the device, and sends
|
|
// things our way if they need device specific processing.
|
|
//
|
|
status = HidRegisterMinidriver(&HidIrdriverRegistration);
|
|
|
|
HidIrKdPrint((3, "DriverEntry Exit = %x", status));
|
|
|
|
return status;
|
|
}
|
|
|
|
ULONG RunningMediaCenter;
|
|
|
|
VOID
|
|
HidIrCheckIfMediaCenter()
|
|
{
|
|
OBJECT_ATTRIBUTES attributes;
|
|
HANDLE skuRegKey;
|
|
NTSTATUS status;
|
|
ULONG resultLength;
|
|
UNICODE_STRING regString;
|
|
UCHAR buffer[sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + sizeof( ULONG )];
|
|
|
|
PAGED_CODE();
|
|
|
|
RunningMediaCenter = 0;
|
|
|
|
//
|
|
// Open the MediaCenter SKU registry key
|
|
//
|
|
|
|
RtlInitUnicodeString( ®String, L"\\REGISTRY\\MACHINE\\SYSTEM\\WPA\\MediaCenter" );
|
|
InitializeObjectAttributes( &attributes,
|
|
®String,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL );
|
|
|
|
status = ZwOpenKey( &skuRegKey,
|
|
KEY_READ,
|
|
&attributes );
|
|
|
|
if (!NT_SUCCESS( status )) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Read the Installed value from the registry.
|
|
//
|
|
|
|
RtlInitUnicodeString( ®String, L"Installed" );
|
|
|
|
status = ZwQueryValueKey( skuRegKey,
|
|
®String,
|
|
KeyValuePartialInformation,
|
|
buffer,
|
|
sizeof(buffer),
|
|
&resultLength );
|
|
|
|
|
|
if (NT_SUCCESS( status )) {
|
|
PKEY_VALUE_PARTIAL_INFORMATION info = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
|
|
if (info->DataLength == sizeof(ULONG)) {
|
|
RunningMediaCenter = *((ULONG*) &((info)->Data));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close the registry entry
|
|
//
|
|
|
|
ZwClose(skuRegKey);
|
|
}
|
|
|
|
NTSTATUS
|
|
HidIrAddDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process AddDevice. Provides the opportunity to initialize the DeviceObject or the
|
|
DriverObject.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - pointer to the driver object.
|
|
|
|
DeviceObject - pointer to a device object.
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PHIDIR_EXTENSION deviceExtension;
|
|
LARGE_INTEGER timeout;
|
|
timeout.HighPart = -1;
|
|
timeout.LowPart = -1;
|
|
|
|
HidIrKdPrint((3, "HidIrAddDevice Entry"));
|
|
|
|
deviceExtension = GET_MINIDRIVER_HIDIR_EXTENSION( DeviceObject );
|
|
|
|
deviceExtension->NumPendingRequests = 0;
|
|
KeInitializeEvent( &deviceExtension->AllRequestsCompleteEvent,
|
|
NotificationEvent,
|
|
FALSE);
|
|
|
|
deviceExtension->DeviceState = DEVICE_STATE_NONE;
|
|
deviceExtension->DeviceObject = DeviceObject;
|
|
deviceExtension->VersionNumber = 0x110;
|
|
// deviceExtension->VendorID = 0x045e;
|
|
// deviceExtension->ProductID = 0x006d;
|
|
|
|
// Predispose timer to signalled.
|
|
KeInitializeTimer(&deviceExtension->IgnoreStandbyTimer);
|
|
KeSetTimer(&deviceExtension->IgnoreStandbyTimer, timeout, NULL);
|
|
|
|
HidIrKdPrint((3, "HidIrAddDevice Exit = %x", status));
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
HidIrUnload(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free all the allocated resources, etc. in anticipation of this driver being unloaded.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - pointer to the driver object.
|
|
|
|
Return Value:
|
|
|
|
VOID.
|
|
|
|
--*/
|
|
{
|
|
HidIrKdPrint((3, "HidIrUnload Enter"));
|
|
|
|
HidIrKdPrint((3, "Unloading DriverObject = %x", DriverObject));
|
|
|
|
HidIrKdPrint((3, "Unloading Exit = VOID"));
|
|
}
|
|
|
|
NTSTATUS
|
|
HidIrSynchronousCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER (DeviceObject);
|
|
|
|
KeSetEvent ((PKEVENT) Context, 1, FALSE);
|
|
// No special priority
|
|
// No Wait
|
|
|
|
return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP
|
|
}
|
|
|
|
NTSTATUS
|
|
HidIrCallDriverSynchronous(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
KEVENT event;
|
|
NTSTATUS status;
|
|
|
|
// Set next stack location
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
IoSetCompletionRoutine(Irp,
|
|
HidIrSynchronousCompletion,
|
|
&event, // context
|
|
TRUE,
|
|
TRUE,
|
|
TRUE );
|
|
status = IoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
// wait for it...
|
|
KeWaitForSingleObject(&event,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
status = Irp->IoStatus.Status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|