2005-10-31 16:46:46 +00:00
|
|
|
|
/*
|
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
|
* PROJECT: ReactOS Keyboard class driver
|
|
|
|
|
* FILE: drivers/kbdclass/kbdclass.c
|
|
|
|
|
* PURPOSE: Keyboard class driver
|
|
|
|
|
*
|
|
|
|
|
* PROGRAMMERS: Herv<EFBFBD> Poussineau (hpoussin@reactos.org)
|
2005-05-01 20:38:29 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
#define INITGUID
|
2005-05-01 20:38:29 +00:00
|
|
|
|
#include "kbdclass.h"
|
|
|
|
|
|
2005-11-09 11:15:42 +00:00
|
|
|
|
static NTSTATUS
|
|
|
|
|
SearchForLegacyDrivers(
|
|
|
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
|
|
|
IN PCLASS_DRIVER_EXTENSION DriverExtension);
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
static VOID NTAPI
|
|
|
|
|
DriverUnload(IN PDRIVER_OBJECT DriverObject)
|
|
|
|
|
{
|
|
|
|
|
// nothing to do here yet
|
|
|
|
|
}
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
static NTSTATUS NTAPI
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ClassCreate(
|
2005-10-31 16:46:46 +00:00
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN PIRP Irp)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("IRP_MJ_CREATE\n");
|
2005-10-06 21:39:18 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
|
|
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
/* FIXME: open all associated Port devices */
|
2006-04-25 22:22:22 +00:00
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
}
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
static NTSTATUS NTAPI
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ClassClose(
|
2005-10-31 16:46:46 +00:00
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN PIRP Irp)
|
2005-05-01 20:38:29 +00:00
|
|
|
|
{
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DPRINT("IRP_MJ_CLOSE\n");
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
|
|
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
|
|
|
|
|
|
/* FIXME: close all associated Port devices */
|
2006-04-25 22:22:22 +00:00
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
return STATUS_SUCCESS;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-11-01 23:39:12 +00:00
|
|
|
|
static NTSTATUS NTAPI
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ClassCleanup(
|
2005-11-01 23:39:12 +00:00
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN PIRP Irp)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("IRP_MJ_CLEANUP\n");
|
|
|
|
|
|
|
|
|
|
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
|
|
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
/* FIXME: cleanup all associated Port devices */
|
2006-04-25 22:22:22 +00:00
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
2005-11-01 23:39:12 +00:00
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
static NTSTATUS NTAPI
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ClassRead(
|
2005-10-31 16:46:46 +00:00
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN PIRP Irp)
|
2005-05-01 20:38:29 +00:00
|
|
|
|
{
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DPRINT("IRP_MJ_READ\n");
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
|
|
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length < sizeof(KEYBOARD_INPUT_DATA))
|
|
|
|
|
{
|
|
|
|
|
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
return STATUS_BUFFER_TOO_SMALL;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
IoMarkIrpPending(Irp);
|
|
|
|
|
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
|
|
|
|
return STATUS_PENDING;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
static NTSTATUS NTAPI
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ClassDeviceControl(
|
2005-10-31 16:46:46 +00:00
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN PIRP Irp)
|
2005-05-01 20:38:29 +00:00
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
PCLASS_DEVICE_EXTENSION DeviceExtension;
|
2006-02-24 13:38:14 +00:00
|
|
|
|
NTSTATUS Status = Irp->IoStatus.Status;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DPRINT("IRP_MJ_DEVICE_CONTROL\n");
|
2005-11-01 23:39:12 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
|
|
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DeviceExtension = (PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
switch (IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode)
|
|
|
|
|
{
|
|
|
|
|
case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
|
|
|
|
|
case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
|
|
|
|
|
case IOCTL_KEYBOARD_QUERY_INDICATORS:
|
|
|
|
|
case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
|
2006-02-24 13:38:14 +00:00
|
|
|
|
{
|
|
|
|
|
/* FIXME: We hope that all devices will return the same result.
|
|
|
|
|
* Ask only the first one */
|
|
|
|
|
PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
|
|
|
|
|
if (Head->Flink != Head)
|
|
|
|
|
{
|
2006-07-17 22:13:40 +00:00
|
|
|
|
/* We have at least one device */
|
2006-02-24 13:38:14 +00:00
|
|
|
|
PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Head->Flink, PORT_DEVICE_EXTENSION, ListEntry);
|
|
|
|
|
IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
|
return IoCallDriver(DevExt->DeviceObject, Irp);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2005-10-31 16:46:46 +00:00
|
|
|
|
case IOCTL_KEYBOARD_SET_INDICATORS:
|
|
|
|
|
case IOCTL_KEYBOARD_SET_TYPEMATIC: /* not in MSDN, would seem logical */
|
2006-02-24 13:38:14 +00:00
|
|
|
|
{
|
|
|
|
|
/* Send it to all associated Port devices */
|
|
|
|
|
PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
|
|
|
|
|
PLIST_ENTRY Entry = Head->Flink;
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
while (Entry != Head)
|
|
|
|
|
{
|
|
|
|
|
PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Entry, PORT_DEVICE_EXTENSION, ListEntry);
|
|
|
|
|
NTSTATUS IntermediateStatus;
|
|
|
|
|
|
|
|
|
|
IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
|
|
|
|
IntermediateStatus = ForwardIrpAndWait(DevExt->DeviceObject, Irp);
|
|
|
|
|
if (!NT_SUCCESS(IntermediateStatus))
|
|
|
|
|
Status = IntermediateStatus;
|
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
|
}
|
2005-10-31 16:46:46 +00:00
|
|
|
|
break;
|
2006-02-24 13:38:14 +00:00
|
|
|
|
}
|
2005-10-31 16:46:46 +00:00
|
|
|
|
default:
|
|
|
|
|
DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
|
|
|
|
|
IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode);
|
2006-04-16 07:17:34 +00:00
|
|
|
|
ASSERT(FALSE);
|
2006-02-24 13:38:14 +00:00
|
|
|
|
break;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
}
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NTSTATUS NTAPI
|
|
|
|
|
IrpStub(
|
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN PIRP Irp)
|
2005-05-01 20:38:29 +00:00
|
|
|
|
{
|
2005-10-31 16:46:46 +00:00
|
|
|
|
NTSTATUS Status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
|
|
|
|
|
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
|
|
|
|
{
|
|
|
|
|
/* Forward some IRPs to lower device */
|
|
|
|
|
switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction)
|
|
|
|
|
{
|
2006-02-24 13:38:14 +00:00
|
|
|
|
case IRP_MJ_PNP:
|
2005-10-31 16:46:46 +00:00
|
|
|
|
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
|
|
|
|
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Port DO stub for major function 0x%lx\n",
|
|
|
|
|
IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
|
|
|
|
|
ASSERT(FALSE);
|
|
|
|
|
Status = Irp->IoStatus.Status;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Class DO stub for major function 0x%lx\n",
|
|
|
|
|
IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
|
|
|
|
|
ASSERT(FALSE);
|
|
|
|
|
Status = Irp->IoStatus.Status;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
}
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
return Status;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
static NTSTATUS
|
|
|
|
|
ReadRegistryEntries(
|
|
|
|
|
IN PUNICODE_STRING RegistryPath,
|
2005-11-05 08:21:59 +00:00
|
|
|
|
IN PCLASS_DRIVER_EXTENSION DriverExtension)
|
2005-05-01 20:38:29 +00:00
|
|
|
|
{
|
2005-11-01 23:39:12 +00:00
|
|
|
|
UNICODE_STRING ParametersRegistryKey;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
RTL_QUERY_REGISTRY_TABLE Parameters[4];
|
|
|
|
|
NTSTATUS Status;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ULONG DefaultConnectMultiplePorts = 0;
|
|
|
|
|
ULONG DefaultDataQueueSize = 0x64;
|
|
|
|
|
UNICODE_STRING DefaultDeviceBaseName = RTL_CONSTANT_STRING(L"KeyboardClass");
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
2005-11-01 23:39:12 +00:00
|
|
|
|
ParametersRegistryKey.Length = 0;
|
|
|
|
|
ParametersRegistryKey.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(UNICODE_NULL);
|
|
|
|
|
ParametersRegistryKey.Buffer = ExAllocatePool(PagedPool, ParametersRegistryKey.MaximumLength);
|
|
|
|
|
if (!ParametersRegistryKey.Buffer)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("ExAllocatePool() failed\n");
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyUnicodeString(&ParametersRegistryKey, RegistryPath);
|
|
|
|
|
RtlAppendUnicodeToString(&ParametersRegistryKey, L"\\Parameters");
|
|
|
|
|
ParametersRegistryKey.Buffer[ParametersRegistryKey.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
RtlZeroMemory(Parameters, sizeof(Parameters));
|
|
|
|
|
|
|
|
|
|
Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
|
|
|
|
Parameters[0].Name = L"ConnectMultiplePorts";
|
|
|
|
|
Parameters[0].EntryContext = &DriverExtension->ConnectMultiplePorts;
|
|
|
|
|
Parameters[0].DefaultType = REG_DWORD;
|
|
|
|
|
Parameters[0].DefaultData = &DefaultConnectMultiplePorts;
|
|
|
|
|
Parameters[0].DefaultLength = sizeof(ULONG);
|
2005-11-01 23:39:12 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
|
|
|
|
Parameters[1].Name = L"KeyboardDataQueueSize";
|
2005-11-05 08:21:59 +00:00
|
|
|
|
Parameters[1].EntryContext = &DriverExtension->DataQueueSize;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
Parameters[1].DefaultType = REG_DWORD;
|
2005-11-05 08:21:59 +00:00
|
|
|
|
Parameters[1].DefaultData = &DefaultDataQueueSize;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
Parameters[1].DefaultLength = sizeof(ULONG);
|
2005-11-01 23:39:12 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
|
|
|
|
|
Parameters[2].Name = L"KeyboardDeviceBaseName";
|
2005-11-05 08:21:59 +00:00
|
|
|
|
Parameters[2].EntryContext = &DriverExtension->DeviceBaseName;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
Parameters[2].DefaultType = REG_SZ;
|
2005-11-05 08:21:59 +00:00
|
|
|
|
Parameters[2].DefaultData = &DefaultDeviceBaseName;
|
2005-11-09 11:15:42 +00:00
|
|
|
|
Parameters[2].DefaultLength = 0;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
|
|
|
|
Status = RtlQueryRegistryValues(
|
|
|
|
|
RTL_REGISTRY_ABSOLUTE,
|
2005-11-01 23:39:12 +00:00
|
|
|
|
ParametersRegistryKey.Buffer,
|
2005-10-31 16:46:46 +00:00
|
|
|
|
Parameters,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
/* Check values */
|
|
|
|
|
if (DriverExtension->ConnectMultiplePorts != 0
|
|
|
|
|
&& DriverExtension->ConnectMultiplePorts != 1)
|
|
|
|
|
{
|
|
|
|
|
DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts;
|
|
|
|
|
}
|
2005-11-05 08:21:59 +00:00
|
|
|
|
if (DriverExtension->DataQueueSize == 0)
|
2005-10-31 16:46:46 +00:00
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DriverExtension->DataQueueSize = DefaultDataQueueSize;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2005-11-01 23:39:12 +00:00
|
|
|
|
else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
|
|
|
|
{
|
|
|
|
|
/* Registry path doesn't exist. Set defaults */
|
|
|
|
|
DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts;
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DriverExtension->DataQueueSize = DefaultDataQueueSize;
|
2005-11-01 23:39:12 +00:00
|
|
|
|
Status = RtlDuplicateUnicodeString(
|
|
|
|
|
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
|
2005-11-05 08:21:59 +00:00
|
|
|
|
&DefaultDeviceBaseName,
|
|
|
|
|
&DriverExtension->DeviceBaseName);
|
2005-11-01 23:39:12 +00:00
|
|
|
|
}
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
return Status;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
static NTSTATUS
|
2005-11-05 08:21:59 +00:00
|
|
|
|
CreateClassDeviceObject(
|
2005-10-31 16:46:46 +00:00
|
|
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
|
|
|
OUT PDEVICE_OBJECT *ClassDO OPTIONAL)
|
2005-05-01 20:38:29 +00:00
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
PCLASS_DRIVER_EXTENSION DriverExtension;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
ULONG DeviceId = 0;
|
|
|
|
|
ULONG PrefixLength;
|
|
|
|
|
UNICODE_STRING DeviceNameU;
|
|
|
|
|
PWSTR DeviceIdW = NULL; /* Pointer into DeviceNameU.Buffer */
|
|
|
|
|
PDEVICE_OBJECT Fdo;
|
2005-11-05 08:21:59 +00:00
|
|
|
|
PCLASS_DEVICE_EXTENSION DeviceExtension;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DPRINT("CreateClassDeviceObject(0x%p)\n", DriverObject);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
|
|
|
|
/* Create new device object */
|
|
|
|
|
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
|
|
|
|
DeviceNameU.Length = 0;
|
|
|
|
|
DeviceNameU.MaximumLength =
|
2005-11-05 08:21:59 +00:00
|
|
|
|
wcslen(L"\\Device\\") * sizeof(WCHAR) /* "\Device\" */
|
|
|
|
|
+ DriverExtension->DeviceBaseName.Length /* "KeyboardClass" */
|
|
|
|
|
+ 4 * sizeof(WCHAR) /* Id between 0 and 9999 */
|
|
|
|
|
+ sizeof(UNICODE_NULL); /* Final NULL char */
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DeviceNameU.Buffer = ExAllocatePool(PagedPool, DeviceNameU.MaximumLength);
|
|
|
|
|
if (!DeviceNameU.Buffer)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("ExAllocatePool() failed\n");
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
Status = RtlAppendUnicodeToString(&DeviceNameU, L"\\Device\\");
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
2005-11-05 08:21:59 +00:00
|
|
|
|
Status = RtlAppendUnicodeStringToString(&DeviceNameU, &DriverExtension->DeviceBaseName);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
PrefixLength = DeviceNameU.MaximumLength - 4 * sizeof(WCHAR) - sizeof(UNICODE_NULL);
|
|
|
|
|
DeviceIdW = &DeviceNameU.Buffer[PrefixLength / sizeof(WCHAR)];
|
|
|
|
|
while (DeviceId < 9999)
|
|
|
|
|
{
|
|
|
|
|
DeviceNameU.Length = PrefixLength + swprintf(DeviceIdW, L"%lu", DeviceId) * sizeof(WCHAR);
|
|
|
|
|
Status = IoCreateDevice(
|
|
|
|
|
DriverObject,
|
2005-11-05 08:21:59 +00:00
|
|
|
|
sizeof(CLASS_DEVICE_EXTENSION),
|
2005-10-31 16:46:46 +00:00
|
|
|
|
&DeviceNameU,
|
|
|
|
|
FILE_DEVICE_KEYBOARD,
|
|
|
|
|
FILE_DEVICE_SECURE_OPEN,
|
2005-11-01 23:39:12 +00:00
|
|
|
|
TRUE,
|
2005-10-31 16:46:46 +00:00
|
|
|
|
&Fdo);
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
|
goto cleanup;
|
|
|
|
|
else if (Status != STATUS_OBJECT_NAME_COLLISION)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
|
|
|
|
|
goto cleanup;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
}
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DeviceId++;
|
|
|
|
|
}
|
2006-01-02 11:32:03 +00:00
|
|
|
|
DPRINT("Too many devices starting with '\\Device\\%wZ'\n", &DriverExtension->DeviceBaseName);
|
|
|
|
|
Status = STATUS_TOO_MANY_NAMES;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
cleanup:
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
2005-11-01 23:39:12 +00:00
|
|
|
|
{
|
|
|
|
|
ExFreePool(DeviceNameU.Buffer);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
return Status;
|
2005-11-01 23:39:12 +00:00
|
|
|
|
}
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DeviceExtension = (PCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
|
|
|
|
|
RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DeviceExtension->Common.IsClassDO = TRUE;
|
|
|
|
|
DeviceExtension->DriverExtension = DriverExtension;
|
2006-02-24 13:38:14 +00:00
|
|
|
|
InitializeListHead(&DeviceExtension->ListHead);
|
|
|
|
|
KeInitializeSpinLock(&DeviceExtension->ListSpinLock);
|
|
|
|
|
KeInitializeSpinLock(&DeviceExtension->SpinLock);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DeviceExtension->ReadIsPending = FALSE;
|
|
|
|
|
DeviceExtension->InputCount = 0;
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(KEYBOARD_INPUT_DATA));
|
2006-07-11 13:38:59 +00:00
|
|
|
|
if (!DeviceExtension->PortData)
|
|
|
|
|
{
|
|
|
|
|
ExFreePool(DeviceNameU.Buffer);
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
2006-07-17 22:13:40 +00:00
|
|
|
|
DeviceExtension->DeviceName = DeviceNameU.Buffer;
|
2006-04-25 22:22:22 +00:00
|
|
|
|
Fdo->Flags |= DO_POWER_PAGABLE;
|
|
|
|
|
Fdo->Flags |= DO_BUFFERED_IO; /* FIXME: Why is it needed for 1st stage setup? */
|
2005-10-31 16:46:46 +00:00
|
|
|
|
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
|
|
2005-11-09 11:15:42 +00:00
|
|
|
|
/* Add entry entry to HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
|
|
|
|
|
RtlWriteRegistryValue(
|
|
|
|
|
RTL_REGISTRY_DEVICEMAP,
|
|
|
|
|
DriverExtension->DeviceBaseName.Buffer,
|
2006-07-17 22:13:40 +00:00
|
|
|
|
DeviceExtension->DeviceName,
|
2005-11-09 11:15:42 +00:00
|
|
|
|
REG_SZ,
|
|
|
|
|
DriverExtension->RegistryPath.Buffer,
|
|
|
|
|
DriverExtension->RegistryPath.MaximumLength);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
|
|
|
|
if (ClassDO)
|
|
|
|
|
*ClassDO = Fdo;
|
|
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-25 22:22:22 +00:00
|
|
|
|
static NTSTATUS
|
2006-07-17 22:13:40 +00:00
|
|
|
|
FillEntries(
|
2006-04-25 22:22:22 +00:00
|
|
|
|
IN PDEVICE_OBJECT ClassDeviceObject,
|
|
|
|
|
IN PIRP Irp,
|
2006-07-17 22:13:40 +00:00
|
|
|
|
IN PKEYBOARD_INPUT_DATA DataStart,
|
|
|
|
|
IN SIZE_T NumberOfEntries)
|
2006-04-25 22:22:22 +00:00
|
|
|
|
{
|
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
if (ClassDeviceObject->Flags & DO_BUFFERED_IO)
|
|
|
|
|
{
|
|
|
|
|
RtlCopyMemory(
|
|
|
|
|
Irp->AssociatedIrp.SystemBuffer,
|
|
|
|
|
DataStart,
|
2006-07-17 22:13:40 +00:00
|
|
|
|
NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA));
|
2006-04-25 22:22:22 +00:00
|
|
|
|
}
|
|
|
|
|
else if (ClassDeviceObject->Flags & DO_DIRECT_IO)
|
|
|
|
|
{
|
|
|
|
|
PVOID DestAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
|
|
|
|
|
if (DestAddress)
|
|
|
|
|
{
|
|
|
|
|
RtlCopyMemory(
|
|
|
|
|
DestAddress,
|
|
|
|
|
DataStart,
|
2006-07-17 22:13:40 +00:00
|
|
|
|
NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA));
|
2006-04-25 22:22:22 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_SEH_TRY
|
|
|
|
|
{
|
|
|
|
|
RtlCopyMemory(
|
|
|
|
|
Irp->UserBuffer,
|
|
|
|
|
DataStart,
|
2006-07-17 22:13:40 +00:00
|
|
|
|
NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA));
|
2006-04-25 22:22:22 +00:00
|
|
|
|
}
|
|
|
|
|
_SEH_HANDLE
|
|
|
|
|
{
|
|
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
|
}
|
|
|
|
|
_SEH_END;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
static BOOLEAN
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ClassCallback(
|
2005-10-31 16:46:46 +00:00
|
|
|
|
IN PDEVICE_OBJECT ClassDeviceObject,
|
2005-11-05 08:21:59 +00:00
|
|
|
|
IN OUT PKEYBOARD_INPUT_DATA DataStart,
|
|
|
|
|
IN PKEYBOARD_INPUT_DATA DataEnd,
|
2005-10-31 16:46:46 +00:00
|
|
|
|
IN OUT PULONG ConsumedCount)
|
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
PCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
PIRP Irp = NULL;
|
|
|
|
|
KIRQL OldIrql;
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ULONG InputCount = DataEnd - DataStart;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
ULONG ReadSize;
|
|
|
|
|
|
|
|
|
|
ASSERT(ClassDeviceExtension->Common.IsClassDO);
|
|
|
|
|
|
2005-11-18 10:53:32 +00:00
|
|
|
|
KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
|
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DPRINT("ClassCallback()\n");
|
2005-10-31 16:46:46 +00:00
|
|
|
|
/* A filter driver might have consumed all the data already; I'm
|
|
|
|
|
* not sure if they are supposed to move the packets when they
|
|
|
|
|
* consume them though.
|
|
|
|
|
*/
|
|
|
|
|
if (ClassDeviceExtension->ReadIsPending == TRUE && InputCount)
|
|
|
|
|
{
|
2006-07-17 22:13:40 +00:00
|
|
|
|
/* A read request is waiting for input, so go straight to it */
|
2006-04-25 22:22:22 +00:00
|
|
|
|
NTSTATUS Status;
|
2006-07-17 22:13:40 +00:00
|
|
|
|
SIZE_T NumberOfEntries;
|
2006-04-25 22:22:22 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
Irp = ClassDeviceObject->CurrentIrp;
|
|
|
|
|
ClassDeviceObject->CurrentIrp = NULL;
|
|
|
|
|
|
2006-07-17 22:13:40 +00:00
|
|
|
|
NumberOfEntries = MIN(
|
|
|
|
|
InputCount,
|
|
|
|
|
IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(KEYBOARD_INPUT_DATA));
|
|
|
|
|
|
|
|
|
|
Status = FillEntries(
|
2006-04-25 22:22:22 +00:00
|
|
|
|
ClassDeviceObject,
|
|
|
|
|
Irp,
|
2006-07-17 22:13:40 +00:00
|
|
|
|
DataStart,
|
|
|
|
|
NumberOfEntries);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
2006-04-25 22:22:22 +00:00
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
/* Go to next packet and complete this request with STATUS_SUCCESS */
|
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
2006-07-17 22:13:40 +00:00
|
|
|
|
Irp->IoStatus.Information = NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
2006-04-25 22:22:22 +00:00
|
|
|
|
ClassDeviceExtension->ReadIsPending = FALSE;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
2006-04-25 22:22:22 +00:00
|
|
|
|
/* Skip the packet we just sent away */
|
2006-07-17 22:13:40 +00:00
|
|
|
|
DataStart += NumberOfEntries;
|
|
|
|
|
(*ConsumedCount) += NumberOfEntries;
|
|
|
|
|
InputCount -= NumberOfEntries;
|
2006-04-25 22:22:22 +00:00
|
|
|
|
}
|
2005-05-01 20:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
/* If we have data from the port driver and a higher service to send the data to */
|
|
|
|
|
if (InputCount != 0)
|
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
if (ClassDeviceExtension->InputCount + InputCount > ClassDeviceExtension->DriverExtension->DataQueueSize)
|
2006-05-03 14:42:28 +00:00
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* We're exceeding the buffer, and data will be thrown away...
|
|
|
|
|
* FIXME: What could we do, as we are at DISPATCH_LEVEL?
|
|
|
|
|
*/
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ReadSize = ClassDeviceExtension->DriverExtension->DataQueueSize - ClassDeviceExtension->InputCount;
|
2006-05-03 14:42:28 +00:00
|
|
|
|
}
|
2005-10-31 16:46:46 +00:00
|
|
|
|
else
|
|
|
|
|
ReadSize = InputCount;
|
|
|
|
|
|
|
|
|
|
/*
|
2005-11-05 08:21:59 +00:00
|
|
|
|
* Move the input data from the port data queue to our class data
|
2005-10-31 16:46:46 +00:00
|
|
|
|
* queue.
|
|
|
|
|
*/
|
2006-07-11 13:38:59 +00:00
|
|
|
|
RtlCopyMemory(
|
|
|
|
|
&ClassDeviceExtension->PortData[ClassDeviceExtension->InputCount],
|
2005-11-05 08:21:59 +00:00
|
|
|
|
(PCHAR)DataStart,
|
2005-10-31 16:46:46 +00:00
|
|
|
|
sizeof(KEYBOARD_INPUT_DATA) * ReadSize);
|
|
|
|
|
|
2006-07-11 13:38:59 +00:00
|
|
|
|
/* Move the counter up */
|
2005-10-31 16:46:46 +00:00
|
|
|
|
ClassDeviceExtension->InputCount += ReadSize;
|
|
|
|
|
|
|
|
|
|
(*ConsumedCount) += ReadSize;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2006-06-27 11:09:23 +00:00
|
|
|
|
DPRINT("ClassCallback(): no more data to process\n");
|
2005-10-31 16:46:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-11-18 10:53:32 +00:00
|
|
|
|
KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
if (Irp != NULL)
|
|
|
|
|
{
|
|
|
|
|
IoStartNextPacket(ClassDeviceObject, FALSE);
|
|
|
|
|
IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
|
|
|
|
|
}
|
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DPRINT("Leaving ClassCallback()\n");
|
2005-10-31 16:46:46 +00:00
|
|
|
|
return TRUE;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
/* Send IOCTL_INTERNAL_*_CONNECT to port */
|
2005-10-31 16:46:46 +00:00
|
|
|
|
static NTSTATUS
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ConnectPortDriver(
|
|
|
|
|
IN PDEVICE_OBJECT PortDO,
|
|
|
|
|
IN PDEVICE_OBJECT ClassDO)
|
2005-05-01 20:38:29 +00:00
|
|
|
|
{
|
|
|
|
|
KEVENT Event;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
PIRP Irp;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
IO_STATUS_BLOCK IoStatus;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
CONNECT_DATA ConnectData;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
2006-07-13 22:20:54 +00:00
|
|
|
|
DPRINT("Connecting PortDO %p [%wZ] to ClassDO %p\n",
|
|
|
|
|
PortDO, &PortDO->DriverObject->DriverName, ClassDO);
|
|
|
|
|
|
2005-05-01 20:38:29 +00:00
|
|
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ConnectData.ClassDeviceObject = ClassDO;
|
|
|
|
|
ConnectData.ClassService = ClassCallback;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
2006-07-17 22:13:40 +00:00
|
|
|
|
Irp = IoBuildDeviceIoControlRequest(
|
|
|
|
|
IOCTL_INTERNAL_KEYBOARD_CONNECT,
|
2005-11-05 08:21:59 +00:00
|
|
|
|
PortDO,
|
2005-10-31 16:46:46 +00:00
|
|
|
|
&ConnectData, sizeof(CONNECT_DATA),
|
|
|
|
|
NULL, 0,
|
|
|
|
|
TRUE, &Event, &IoStatus);
|
2006-07-17 22:13:40 +00:00
|
|
|
|
if (!Irp)
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
Status = IoCallDriver(PortDO, Irp);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
|
|
|
|
if (Status == STATUS_PENDING)
|
|
|
|
|
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
|
|
|
|
else
|
|
|
|
|
IoStatus.Status = Status;
|
|
|
|
|
|
2005-11-09 11:15:42 +00:00
|
|
|
|
if (NT_SUCCESS(IoStatus.Status))
|
2006-02-24 13:38:14 +00:00
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ObReferenceObject(PortDO);
|
2006-02-24 13:38:14 +00:00
|
|
|
|
ExInterlockedInsertTailList(
|
|
|
|
|
&((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListHead,
|
|
|
|
|
&((PPORT_DEVICE_EXTENSION)PortDO->DeviceExtension)->ListEntry,
|
|
|
|
|
&((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListSpinLock);
|
|
|
|
|
if (ClassDO->StackSize <= PortDO->StackSize)
|
|
|
|
|
{
|
|
|
|
|
/* Increase the stack size, in case we have to
|
|
|
|
|
* forward some IRPs to the port device object
|
|
|
|
|
*/
|
|
|
|
|
ClassDO->StackSize = PortDO->StackSize + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-11-01 23:39:12 +00:00
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
return IoStatus.Status;
|
|
|
|
|
}
|
|
|
|
|
|
2006-07-17 22:13:40 +00:00
|
|
|
|
/* Send IOCTL_INTERNAL_*_DISCONNECT to port + destroy the Port DO */
|
|
|
|
|
static VOID
|
|
|
|
|
DestroyPortDriver(
|
2006-07-13 22:20:54 +00:00
|
|
|
|
IN PDEVICE_OBJECT PortDO)
|
|
|
|
|
{
|
2006-07-17 22:13:40 +00:00
|
|
|
|
PPORT_DEVICE_EXTENSION DeviceExtension;
|
|
|
|
|
PCLASS_DEVICE_EXTENSION ClassDeviceExtension;
|
|
|
|
|
PCLASS_DRIVER_EXTENSION DriverExtension;
|
|
|
|
|
KEVENT Event;
|
|
|
|
|
PIRP Irp;
|
|
|
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
|
KIRQL OldIrql;
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
|
|
DPRINT("Destroying PortDO %p [%wZ]\n",
|
2006-07-13 22:20:54 +00:00
|
|
|
|
PortDO, &PortDO->DriverObject->DriverName);
|
|
|
|
|
|
2006-07-17 22:13:40 +00:00
|
|
|
|
DeviceExtension = (PPORT_DEVICE_EXTENSION)PortDO->DeviceExtension;
|
|
|
|
|
ClassDeviceExtension = DeviceExtension->ClassDO->DeviceExtension;
|
|
|
|
|
DriverExtension = IoGetDriverObjectExtension(PortDO->DriverObject, PortDO->DriverObject);
|
|
|
|
|
|
|
|
|
|
/* Send IOCTL_INTERNAL_*_DISCONNECT */
|
|
|
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
|
|
|
Irp = IoBuildDeviceIoControlRequest(
|
|
|
|
|
IOCTL_INTERNAL_KEYBOARD_DISCONNECT,
|
|
|
|
|
PortDO,
|
|
|
|
|
NULL, 0,
|
|
|
|
|
NULL, 0,
|
|
|
|
|
TRUE, &Event, &IoStatus);
|
|
|
|
|
if (Irp)
|
|
|
|
|
{
|
|
|
|
|
Status = IoCallDriver(PortDO, Irp);
|
|
|
|
|
if (Status == STATUS_PENDING)
|
|
|
|
|
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Remove from ClassDeviceExtension->ListHead list */
|
|
|
|
|
KeAcquireSpinLock(&ClassDeviceExtension->ListSpinLock, &OldIrql);
|
|
|
|
|
RemoveHeadList(DeviceExtension->ListEntry.Blink);
|
|
|
|
|
KeReleaseSpinLock(&ClassDeviceExtension->ListSpinLock, OldIrql);
|
|
|
|
|
|
|
|
|
|
/* Remove entry from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
|
|
|
|
|
RtlDeleteRegistryValue(
|
|
|
|
|
RTL_REGISTRY_DEVICEMAP,
|
|
|
|
|
DriverExtension->DeviceBaseName.Buffer,
|
|
|
|
|
ClassDeviceExtension->DeviceName);
|
|
|
|
|
|
|
|
|
|
if (DeviceExtension->LowerDevice)
|
|
|
|
|
IoDetachDevice(DeviceExtension->LowerDevice);
|
|
|
|
|
ObDereferenceObject(PortDO);
|
|
|
|
|
|
|
|
|
|
if (!DriverExtension->ConnectMultiplePorts && DeviceExtension->ClassDO)
|
|
|
|
|
{
|
|
|
|
|
ExFreePool(ClassDeviceExtension->PortData);
|
|
|
|
|
ExFreePool((PVOID)ClassDeviceExtension->DeviceName);
|
|
|
|
|
IoDeleteDevice(DeviceExtension->ClassDO);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IoDeleteDevice(PortDO);
|
2006-07-13 22:20:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
static NTSTATUS NTAPI
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ClassAddDevice(
|
2005-10-31 16:46:46 +00:00
|
|
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
|
|
|
IN PDEVICE_OBJECT Pdo)
|
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
PCLASS_DRIVER_EXTENSION DriverExtension;
|
2006-04-16 07:17:34 +00:00
|
|
|
|
PDEVICE_OBJECT Fdo = NULL;
|
|
|
|
|
PPORT_DEVICE_EXTENSION DeviceExtension = NULL;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DPRINT("ClassAddDevice called. Pdo = 0x%p\n", Pdo);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
|
|
|
|
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
|
|
|
|
|
2005-11-09 11:15:42 +00:00
|
|
|
|
if (Pdo == NULL)
|
|
|
|
|
/* We're getting a NULL Pdo at the first call as we're a legacy driver.
|
|
|
|
|
* Use it to search for legacy port drivers. */
|
|
|
|
|
return SearchForLegacyDrivers(DriverObject, DriverExtension);
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
/* Create new device object */
|
|
|
|
|
Status = IoCreateDevice(
|
|
|
|
|
DriverObject,
|
2005-11-05 08:21:59 +00:00
|
|
|
|
sizeof(PORT_DEVICE_EXTENSION),
|
2005-10-31 16:46:46 +00:00
|
|
|
|
NULL,
|
|
|
|
|
Pdo->DeviceType,
|
2006-04-25 22:22:22 +00:00
|
|
|
|
Pdo->Characteristics & FILE_DEVICE_SECURE_OPEN ? FILE_DEVICE_SECURE_OPEN : 0,
|
2005-11-01 23:39:12 +00:00
|
|
|
|
TRUE,
|
2005-10-31 16:46:46 +00:00
|
|
|
|
&Fdo);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
|
2006-04-16 07:17:34 +00:00
|
|
|
|
goto cleanup;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension;
|
|
|
|
|
RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DeviceExtension->Common.IsClassDO = FALSE;
|
2006-02-24 13:38:14 +00:00
|
|
|
|
DeviceExtension->DeviceObject = Fdo;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DeviceExtension->PnpState = dsStopped;
|
|
|
|
|
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
|
2006-04-16 07:17:34 +00:00
|
|
|
|
goto cleanup;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
}
|
2005-11-18 17:28:19 +00:00
|
|
|
|
if (DeviceExtension->LowerDevice->Flags & DO_POWER_PAGABLE)
|
|
|
|
|
Fdo->Flags |= DO_POWER_PAGABLE;
|
|
|
|
|
if (DeviceExtension->LowerDevice->Flags & DO_BUFFERED_IO)
|
|
|
|
|
Fdo->Flags |= DO_BUFFERED_IO;
|
2006-04-25 22:22:22 +00:00
|
|
|
|
if (DeviceExtension->LowerDevice->Flags & DO_DIRECT_IO)
|
|
|
|
|
Fdo->Flags |= DO_DIRECT_IO;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
|
|
|
|
if (DriverExtension->ConnectMultiplePorts)
|
2006-04-16 07:17:34 +00:00
|
|
|
|
DeviceExtension->ClassDO = DriverExtension->MainClassDeviceObject;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
else
|
2006-04-16 07:17:34 +00:00
|
|
|
|
{
|
|
|
|
|
/* We need a new class device object for this Fdo */
|
|
|
|
|
Status = CreateClassDeviceObject(
|
|
|
|
|
DriverObject,
|
|
|
|
|
&DeviceExtension->ClassDO);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT("CreateClassDeviceObject() failed with status 0x%08lx\n", Status);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Status = ConnectPortDriver(Fdo, DeviceExtension->ClassDO);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
|
2006-04-16 07:17:34 +00:00
|
|
|
|
goto cleanup;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
}
|
2005-11-01 23:39:12 +00:00
|
|
|
|
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
2006-07-17 22:13:40 +00:00
|
|
|
|
/* Register interface ; ignore the error (if any) as having
|
|
|
|
|
* a registred interface is not so important... */
|
2005-10-31 16:46:46 +00:00
|
|
|
|
Status = IoRegisterDeviceInterface(
|
|
|
|
|
Pdo,
|
|
|
|
|
&GUID_DEVINTERFACE_KEYBOARD,
|
|
|
|
|
NULL,
|
2005-11-05 08:21:59 +00:00
|
|
|
|
&DeviceExtension->InterfaceName);
|
2006-07-17 22:13:40 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
DeviceExtension->InterfaceName.Length = 0;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
2006-04-16 07:17:34 +00:00
|
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
if (Fdo)
|
2006-07-17 22:13:40 +00:00
|
|
|
|
DestroyPortDriver(Fdo);
|
2006-04-16 07:17:34 +00:00
|
|
|
|
return Status;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static VOID NTAPI
|
2005-11-05 08:21:59 +00:00
|
|
|
|
ClassStartIo(
|
2005-10-31 16:46:46 +00:00
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN PIRP Irp)
|
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
|
|
|
|
ASSERT(DeviceExtension->Common.IsClassDO);
|
|
|
|
|
|
|
|
|
|
if (DeviceExtension->InputCount > 0)
|
|
|
|
|
{
|
|
|
|
|
KIRQL oldIrql;
|
2006-04-25 22:22:22 +00:00
|
|
|
|
NTSTATUS Status;
|
2006-07-17 22:13:40 +00:00
|
|
|
|
SIZE_T NumberOfEntries;
|
|
|
|
|
|
|
|
|
|
NumberOfEntries = MIN(
|
|
|
|
|
DeviceExtension->InputCount,
|
|
|
|
|
IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(KEYBOARD_INPUT_DATA));
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
|
|
|
|
KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
|
|
|
|
|
|
2006-07-17 22:13:40 +00:00
|
|
|
|
Status = FillEntries(
|
2006-04-25 22:22:22 +00:00
|
|
|
|
DeviceObject,
|
|
|
|
|
Irp,
|
2006-07-17 22:13:40 +00:00
|
|
|
|
DeviceExtension->PortData,
|
|
|
|
|
NumberOfEntries);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
2006-04-25 22:22:22 +00:00
|
|
|
|
if (NT_SUCCESS(Status))
|
2005-10-31 16:46:46 +00:00
|
|
|
|
{
|
2006-07-17 22:13:40 +00:00
|
|
|
|
if (DeviceExtension->InputCount > NumberOfEntries)
|
2006-04-25 22:22:22 +00:00
|
|
|
|
{
|
|
|
|
|
RtlMoveMemory(
|
2006-07-11 13:38:59 +00:00
|
|
|
|
&DeviceExtension->PortData[0],
|
2006-07-17 22:13:40 +00:00
|
|
|
|
&DeviceExtension->PortData[NumberOfEntries],
|
|
|
|
|
(DeviceExtension->InputCount - NumberOfEntries) * sizeof(KEYBOARD_INPUT_DATA));
|
2006-04-25 22:22:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-07-17 22:13:40 +00:00
|
|
|
|
DeviceExtension->InputCount -= NumberOfEntries;
|
2006-04-25 22:22:22 +00:00
|
|
|
|
DeviceExtension->ReadIsPending = FALSE;
|
|
|
|
|
|
2006-07-17 22:13:40 +00:00
|
|
|
|
Irp->IoStatus.Information = NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
}
|
2006-04-25 22:22:22 +00:00
|
|
|
|
|
|
|
|
|
/* Go to next packet and complete this request */
|
|
|
|
|
Irp->IoStatus.Status = Status;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
|
|
|
|
|
|
|
|
|
|
IoStartNextPacket(DeviceObject, FALSE);
|
|
|
|
|
KeReleaseSpinLock(&DeviceExtension->SpinLock, oldIrql);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DeviceExtension->ReadIsPending = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
|
SearchForLegacyDrivers(
|
|
|
|
|
IN PDRIVER_OBJECT DriverObject,
|
2005-11-05 08:21:59 +00:00
|
|
|
|
IN PCLASS_DRIVER_EXTENSION DriverExtension)
|
2005-10-31 16:46:46 +00:00
|
|
|
|
{
|
|
|
|
|
UNICODE_STRING DeviceMapKeyU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
|
|
|
|
|
UNICODE_STRING PortBaseName = {0, };
|
|
|
|
|
PKEY_VALUE_BASIC_INFORMATION KeyValueInformation = NULL;
|
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
|
HANDLE hDeviceMapKey = (HANDLE)-1;
|
|
|
|
|
HANDLE hPortKey = (HANDLE)-1;
|
|
|
|
|
ULONG Index = 0;
|
|
|
|
|
ULONG Size, ResultLength;
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
|
|
/* Create port base name, by replacing Class by Port at the end of the class base name */
|
|
|
|
|
Status = RtlDuplicateUnicodeString(
|
|
|
|
|
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
|
2005-11-05 08:21:59 +00:00
|
|
|
|
&DriverExtension->DeviceBaseName,
|
2005-10-31 16:46:46 +00:00
|
|
|
|
&PortBaseName);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
PortBaseName.Length -= (sizeof(L"Class") - sizeof(UNICODE_NULL));
|
|
|
|
|
RtlAppendUnicodeToString(&PortBaseName, L"Port");
|
|
|
|
|
|
|
|
|
|
/* Allocate memory */
|
|
|
|
|
Size = sizeof(KEY_VALUE_BASIC_INFORMATION) + MAX_PATH;
|
|
|
|
|
KeyValueInformation = ExAllocatePool(PagedPool, Size);
|
|
|
|
|
if (!KeyValueInformation)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("ExAllocatePool() failed\n");
|
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Open HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
|
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes, &DeviceMapKeyU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
|
|
|
Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes);
|
2005-11-05 08:21:59 +00:00
|
|
|
|
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("HKLM\\HARDWARE\\DEVICEMAP is non-existent\n");
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
else if (!NT_SUCCESS(Status))
|
2005-10-31 16:46:46 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Open sub key */
|
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes, &PortBaseName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDeviceMapKey, NULL);
|
|
|
|
|
Status = ZwOpenKey(&hPortKey, KEY_QUERY_VALUE, &ObjectAttributes);
|
2005-11-05 08:21:59 +00:00
|
|
|
|
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("HKLM\\HARDWARE\\DEVICEMAP\\%wZ is non-existent\n", &PortBaseName);
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
else if (!NT_SUCCESS(Status))
|
2005-10-31 16:46:46 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Read each value name */
|
|
|
|
|
while (ZwEnumerateValueKey(hPortKey, Index++, KeyValueBasicInformation, KeyValueInformation, Size, &ResultLength) == STATUS_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
UNICODE_STRING PortName;
|
|
|
|
|
PDEVICE_OBJECT PortDeviceObject = NULL;
|
|
|
|
|
PFILE_OBJECT FileObject = NULL;
|
|
|
|
|
|
|
|
|
|
PortName.Length = PortName.MaximumLength = KeyValueInformation->NameLength;
|
|
|
|
|
PortName.Buffer = KeyValueInformation->Name;
|
|
|
|
|
|
|
|
|
|
/* Open the device object pointer */
|
|
|
|
|
Status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status);
|
2006-02-24 13:38:14 +00:00
|
|
|
|
continue;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
}
|
2006-04-16 07:17:34 +00:00
|
|
|
|
DPRINT("Legacy driver found: %wZ\n", &PortDeviceObject->DriverObject->DriverName);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
2006-04-16 07:17:34 +00:00
|
|
|
|
Status = ClassAddDevice(DriverObject, PortDeviceObject);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
2005-10-31 16:46:46 +00:00
|
|
|
|
{
|
2006-04-16 07:17:34 +00:00
|
|
|
|
/* FIXME: Log the error */
|
|
|
|
|
DPRINT("ClassAddDevice() failed with status 0x%08lx\n", Status);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (Status == STATUS_NO_MORE_ENTRIES)
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
if (KeyValueInformation != NULL)
|
|
|
|
|
ExFreePool(KeyValueInformation);
|
|
|
|
|
if (hDeviceMapKey != (HANDLE)-1)
|
|
|
|
|
ZwClose(hDeviceMapKey);
|
|
|
|
|
if (hPortKey != (HANDLE)-1)
|
|
|
|
|
ZwClose(hPortKey);
|
|
|
|
|
return Status;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2005-10-31 16:46:46 +00:00
|
|
|
|
* Standard DriverEntry method.
|
2005-05-01 20:38:29 +00:00
|
|
|
|
*/
|
2005-10-31 16:46:46 +00:00
|
|
|
|
NTSTATUS NTAPI
|
|
|
|
|
DriverEntry(
|
|
|
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
|
|
|
IN PUNICODE_STRING RegistryPath)
|
2005-05-01 20:38:29 +00:00
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
PCLASS_DRIVER_EXTENSION DriverExtension;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
ULONG i;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
NTSTATUS Status;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
|
|
|
|
|
Status = IoAllocateDriverObjectExtension(
|
|
|
|
|
DriverObject,
|
|
|
|
|
DriverObject,
|
2005-11-05 08:21:59 +00:00
|
|
|
|
sizeof(CLASS_DRIVER_EXTENSION),
|
2005-10-31 16:46:46 +00:00
|
|
|
|
(PVOID*)&DriverExtension);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status);
|
2005-05-01 20:38:29 +00:00
|
|
|
|
return Status;
|
|
|
|
|
}
|
2005-11-05 08:21:59 +00:00
|
|
|
|
RtlZeroMemory(DriverExtension, sizeof(CLASS_DRIVER_EXTENSION));
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-11-09 11:15:42 +00:00
|
|
|
|
Status = RtlDuplicateUnicodeString(
|
|
|
|
|
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
|
|
|
|
|
RegistryPath,
|
|
|
|
|
&DriverExtension->RegistryPath);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status);
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-31 16:46:46 +00:00
|
|
|
|
Status = ReadRegistryEntries(RegistryPath, DriverExtension);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status);
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DriverExtension->ConnectMultiplePorts == 1)
|
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
Status = CreateClassDeviceObject(
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DriverObject,
|
2005-11-05 08:21:59 +00:00
|
|
|
|
&DriverExtension->MainClassDeviceObject);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DPRINT("CreateClassDeviceObject() failed with status 0x%08lx\n", Status);
|
2005-10-31 16:46:46 +00:00
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DriverObject->DriverExtension->AddDevice = ClassAddDevice;
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DriverObject->DriverUnload = DriverUnload;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-12-18 20:50:26 +00:00
|
|
|
|
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
2005-10-31 16:46:46 +00:00
|
|
|
|
DriverObject->MajorFunction[i] = IrpStub;
|
2005-05-08 02:16:32 +00:00
|
|
|
|
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = ClassCreate;
|
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ClassClose;
|
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ClassCleanup;
|
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_READ] = ClassRead;
|
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl;
|
2006-02-24 13:38:14 +00:00
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ForwardIrpAndForget;
|
2005-11-05 08:21:59 +00:00
|
|
|
|
DriverObject->DriverStartIo = ClassStartIo;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
|
2005-11-09 11:15:42 +00:00
|
|
|
|
return STATUS_SUCCESS;
|
2005-05-01 20:38:29 +00:00
|
|
|
|
}
|