[INPORT] Add driver for bus mouse devices (#3173)

It adds basic input support for:
- Standard Bus Mouse
- Standard InPort Mouse
- Logitech Bus Mouse
- Microsoft Bus Mouse
- Microsoft InPort Mouse
- NEC PC-98 Bus Mouse

Untested on PC/AT, but should work.
This commit is contained in:
Dmitry Borisov 2020-09-13 17:42:48 +06:00 committed by Stanislav Motylkov
parent c464b02c90
commit 310a24da6e
No known key found for this signature in database
GPG key ID: AFE513258CBA9E92
11 changed files with 1563 additions and 0 deletions

View file

@ -1,5 +1,6 @@
add_subdirectory(i8042prt)
add_subdirectory(inport)
add_subdirectory(kbdclass)
add_subdirectory(mouclass)
add_subdirectory(sermouse)

View file

@ -0,0 +1,15 @@
list(APPEND SOURCE
hardware.c
inport.c
inport.h
ioctl.c
pnp.c
wmi.c)
add_library(inport MODULE ${SOURCE} inport.rc)
set_module_type(inport kernelmodedriver)
add_pch(inport inport.h SOURCE)
add_importlibs(inport ntoskrnl hal wmilib)
add_cd_file(TARGET inport DESTINATION reactos/system32/drivers FOR all)

View file

@ -0,0 +1,433 @@
/*
* PROJECT: ReactOS InPort (Bus) Mouse Driver
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Hardware support code
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* Note: Some code was taken from Linux */
/* INCLUDES *******************************************************************/
#include "inport.h"
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, InPortInitializeMouse)
#endif
#define READ_MOUSE(DeviceExtension, Port) \
READ_PORT_UCHAR((DeviceExtension)->IoBase + (Port))
#define WRITE_MOUSE(DeviceExtension, Port, Data) \
WRITE_PORT_UCHAR((DeviceExtension)->IoBase + (Port), (Data))
/*
* NEC
*/
#define NEC_BM_DATA 0x00
#define NEC_BM_CONTROL 0x04
#define NEC_INT_ENABLE 0x00
#define NEC_INT_DISABLE 0x10
#define NEC_READ_X_LOW 0x00
#define NEC_READ_X_HIGH 0x20
#define NEC_READ_Y_LOW 0x40
#define NEC_READ_Y_HIGH 0x60
#define NEC_INPUT_CAPTURE 0x00
#define NEC_INPUT_HOLD 0x80
#define NEC_BM_CONFIG 0x06
#define NEC_PPI_INT_ENABLE 0x08
#define NEC_PPI_INT_DISABLE 0x09
#define NEC_PPI_HC_NO_CLEAR 0x0E
#define NEC_PPI_HC_CLEAR 0x0F
#define NEC_PPI_DEFAULT_MODE 0x93
#define NEC_BM_INT_RATE 0x4002
#define NEC_RATE_120_HZ 0x00
#define NEC_RATE_60_HZ 0x01
#define NEC_RATE_30_HZ 0x02
#define NEC_RATE_15_HZ 0x03
#define NEC_BM_HIRESO_BASE (PUCHAR)0x61
#define NEC_BUTTON_RIGHT 0x20
#define NEC_BUTTON_LEFT 0x80
/*
* Microsoft InPort
*/
#define MS_INPORT_CONTROL 0x00
#define INPORT_REG_BTNS 0x00
#define INPORT_REG_X 0x01
#define INPORT_REG_Y 0x02
#define INPORT_REG_MODE 0x07
#define INPORT_RESET 0x80
#define MS_INPORT_DATA 0x01
#define INPORT_MODE_IRQ 0x01
#define INPORT_MODE_BASE 0x10
#define INPORT_MODE_HOLD 0x20
#define MS_INPORT_SIGNATURE 0x02
#define MS_BUTTON_MIDDLE 0x01
#define MS_BUTTON_LEFT 0x02
#define MS_BUTTON_RIGHT 0x04
/*
* Logitech
*/
#define LOG_BM_DATA 0x00
#define LOG_BM_SIGNATURE 0x01
#define LOG_SIGNATURE_BYTE 0xA5
#define LOG_BM_CONTROL 0x02
#define LOG_ENABLE_IRQ 0x00
#define LOG_DISABLE_IRQ 0x10
#define LOG_READ_X_LOW 0x80
#define LOG_READ_X_HIGH 0xA0
#define LOG_READ_Y_LOW 0xC0
#define LOG_READ_Y_HIGH 0xE0
#define LOG_BM_CONFIG 0x03
#define LOG_DEFAULT_MODE 0x90
#define LOG_CONFIG_BYTE 0x91
#define LOG_BUTTON_RIGHT 0x20
#define LOG_BUTTON_MIDDLE 0x40
#define LOG_BUTTON_LEFT 0x80
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
InPortDpcForIsr(
_In_ PKDPC Dpc,
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp,
_In_opt_ PVOID Context)
{
PINPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
KIRQL OldIrql;
ULONG DummyInputDataConsumed;
INPORT_RAW_DATA RawData;
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(Context);
/* Copy raw data */
OldIrql = KeAcquireInterruptSpinLock(DeviceExtension->InterruptObject);
RawData = DeviceExtension->RawData;
KeReleaseInterruptSpinLock(DeviceExtension->InterruptObject, OldIrql);
/* Fill out fields */
DeviceExtension->MouseInputData.LastX = RawData.DeltaX;
DeviceExtension->MouseInputData.LastY = RawData.DeltaY;
DeviceExtension->MouseInputData.ButtonFlags = 0;
if (RawData.ButtonDiff != 0)
{
switch (DeviceExtension->MouseType)
{
case NecBusMouse:
{
if (RawData.ButtonDiff & NEC_BUTTON_LEFT)
{
if (RawData.Buttons & NEC_BUTTON_LEFT)
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
else
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
}
if (RawData.ButtonDiff & NEC_BUTTON_RIGHT)
{
if (RawData.Buttons & NEC_BUTTON_RIGHT)
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
else
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
}
break;
}
case MsInPortMouse:
{
/* Button flags have to be inverted */
if (RawData.ButtonDiff & MS_BUTTON_LEFT)
{
if (RawData.Buttons & MS_BUTTON_LEFT)
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
else
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
}
if (RawData.ButtonDiff & MS_BUTTON_RIGHT)
{
if (RawData.Buttons & MS_BUTTON_RIGHT)
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
else
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
}
if (RawData.ButtonDiff & MS_BUTTON_MIDDLE)
{
if (RawData.Buttons & MS_BUTTON_MIDDLE)
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;
else
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;
}
break;
}
case LogitechBusMouse:
{
if (RawData.ButtonDiff & LOG_BUTTON_LEFT)
{
if (RawData.Buttons & LOG_BUTTON_LEFT)
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
else
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
}
if (RawData.ButtonDiff & LOG_BUTTON_RIGHT)
{
if (RawData.Buttons & LOG_BUTTON_RIGHT)
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
else
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
}
if (RawData.ButtonDiff & LOG_BUTTON_MIDDLE)
{
if (RawData.Buttons & LOG_BUTTON_MIDDLE)
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;
else
DeviceExtension->MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;
}
break;
}
}
}
/* Send mouse packet */
(*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassService)(
DeviceExtension->ClassDeviceObject,
&DeviceExtension->MouseInputData,
&DeviceExtension->MouseInputData + 1,
&DummyInputDataConsumed);
}
BOOLEAN
NTAPI
InPortIsr(
_In_ PKINTERRUPT Interrupt,
_In_ PVOID Context)
{
UCHAR Buttons;
ULONG ButtonDiff;
CHAR DeltaX, DeltaY;
PINPORT_DEVICE_EXTENSION DeviceExtension = Context;
UNREFERENCED_PARAMETER(Interrupt);
switch (DeviceExtension->MouseType)
{
case NecBusMouse:
{
WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
NEC_INPUT_CAPTURE | NEC_INT_DISABLE);
WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
NEC_INPUT_HOLD | NEC_INT_DISABLE | NEC_READ_X_LOW);
DeltaX = READ_MOUSE(DeviceExtension, NEC_BM_DATA) & 0x0F;
WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
NEC_INPUT_HOLD | NEC_INT_DISABLE | NEC_READ_X_HIGH);
DeltaX |= READ_MOUSE(DeviceExtension, NEC_BM_DATA) << 4;
WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
NEC_INPUT_HOLD | NEC_INT_DISABLE | NEC_READ_Y_LOW);
DeltaY = READ_MOUSE(DeviceExtension, NEC_BM_DATA) & 0x0F;
WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
NEC_INPUT_HOLD | NEC_INT_DISABLE | NEC_READ_Y_HIGH);
Buttons = READ_MOUSE(DeviceExtension, NEC_BM_DATA);
DeltaY |= Buttons << 4;
Buttons &= (NEC_BUTTON_LEFT | NEC_BUTTON_RIGHT);
WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
NEC_INPUT_HOLD | NEC_INT_ENABLE);
break;
}
case MsInPortMouse:
{
WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_REG_MODE);
WRITE_MOUSE(DeviceExtension, MS_INPORT_DATA,
INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE);
WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_REG_X);
DeltaX = READ_MOUSE(DeviceExtension, MS_INPORT_DATA);
WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_REG_Y);
DeltaY = READ_MOUSE(DeviceExtension, MS_INPORT_DATA);
WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_REG_BTNS);
Buttons = READ_MOUSE(DeviceExtension, MS_INPORT_DATA);
Buttons &= (MS_BUTTON_MIDDLE | MS_BUTTON_LEFT | MS_BUTTON_RIGHT);
WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_REG_MODE);
WRITE_MOUSE(DeviceExtension, MS_INPORT_DATA,
INPORT_MODE_IRQ | INPORT_MODE_BASE);
break;
}
case LogitechBusMouse:
{
WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_READ_X_LOW);
DeltaX = READ_MOUSE(DeviceExtension, LOG_BM_DATA) & 0x0F;
WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_READ_X_HIGH);
DeltaX |= READ_MOUSE(DeviceExtension, LOG_BM_DATA) << 4;
WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_READ_Y_LOW);
DeltaY = READ_MOUSE(DeviceExtension, LOG_BM_DATA) & 0x0F;
WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_READ_Y_HIGH);
Buttons = READ_MOUSE(DeviceExtension, LOG_BM_DATA);
DeltaY |= Buttons << 4;
Buttons &= (LOG_BUTTON_RIGHT | LOG_BUTTON_MIDDLE | LOG_BUTTON_LEFT);
WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_ENABLE_IRQ);
break;
}
}
ButtonDiff = DeviceExtension->MouseButtonState ^ Buttons;
DeviceExtension->MouseButtonState = Buttons;
/*
* Bus mouse devices don't have a status register to check
* whether this interrupt is indeed for us.
*/
if ((DeltaX == 0) && (DeltaY == 0) && (ButtonDiff == 0))
{
/* We just pretend that the interrupt is not ours */
return FALSE;
}
else
{
DeviceExtension->RawData.DeltaX = DeltaX;
DeviceExtension->RawData.DeltaY = DeltaY;
DeviceExtension->RawData.Buttons = Buttons;
DeviceExtension->RawData.ButtonDiff = ButtonDiff;
IoRequestDpc(DeviceExtension->Self, NULL, NULL);
return TRUE;
}
}
VOID
NTAPI
InPortInitializeMouse(
_In_ PINPORT_DEVICE_EXTENSION DeviceExtension)
{
PAGED_CODE();
/* Initialize mouse and disable interrupts */
switch (DeviceExtension->MouseType)
{
case NecBusMouse:
WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_DEFAULT_MODE);
/* Setup interrupt rate (unavailable on hireso machines) */
if (DeviceExtension->IoBase != NEC_BM_HIRESO_BASE)
WRITE_MOUSE(DeviceExtension, NEC_BM_INT_RATE, NEC_RATE_60_HZ);
WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_INT_DISABLE);
WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_HC_NO_CLEAR);
WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_HC_CLEAR);
break;
case MsInPortMouse:
WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_RESET);
WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_REG_MODE);
WRITE_MOUSE(DeviceExtension, MS_INPORT_DATA, INPORT_MODE_BASE);
break;
case LogitechBusMouse:
WRITE_MOUSE(DeviceExtension, LOG_BM_CONFIG, LOG_DEFAULT_MODE);
WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_DISABLE_IRQ);
break;
}
}
BOOLEAN
NTAPI
InPortStartMouse(
_In_ PVOID SynchronizeContext)
{
PINPORT_DEVICE_EXTENSION DeviceExtension = SynchronizeContext;
/* Enable interrupts */
switch (DeviceExtension->MouseType)
{
case NecBusMouse:
WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_INT_ENABLE);
WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_HC_NO_CLEAR);
WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_HC_CLEAR);
break;
case MsInPortMouse:
WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_REG_MODE);
WRITE_MOUSE(DeviceExtension, MS_INPORT_DATA,
INPORT_MODE_IRQ | INPORT_MODE_BASE);
break;
case LogitechBusMouse:
WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_ENABLE_IRQ);
break;
}
return TRUE;
}
BOOLEAN
NTAPI
InPortStopMouse(
_In_ PVOID SynchronizeContext)
{
PINPORT_DEVICE_EXTENSION DeviceExtension = SynchronizeContext;
/* Disable interrupts */
switch (DeviceExtension->MouseType)
{
case NecBusMouse:
WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_INT_DISABLE);
WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_HC_NO_CLEAR);
WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_HC_CLEAR);
break;
case MsInPortMouse:
WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_REG_MODE);
WRITE_MOUSE(DeviceExtension, MS_INPORT_DATA, INPORT_MODE_BASE);
break;
case LogitechBusMouse:
WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_DISABLE_IRQ);
break;
}
return TRUE;
}

View file

@ -0,0 +1,238 @@
/*
* PROJECT: ReactOS InPort (Bus) Mouse Driver
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Driver entrypoint
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES *******************************************************************/
#include "inport.h"
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, InPortCreateClose)
#pragma alloc_text(PAGE, InPortAddDevice)
#pragma alloc_text(PAGE, InPortUnload)
#endif
UNICODE_STRING DriverRegistryPath;
/* FUNCTIONS ******************************************************************/
NTSTATUS
NTAPI
InPortCreateClose(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp)
{
PAGED_CODE();
DPRINT("%s(%p, %p) %X\n", __FUNCTION__, DeviceObject,
Irp, IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
InPortAddDevice(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PDEVICE_OBJECT PhysicalDeviceObject)
{
NTSTATUS Status;
PDEVICE_OBJECT Fdo;
PINPORT_DEVICE_EXTENSION FdoExtension = NULL;
WCHAR HardwareIdBuffer[32];
UNICODE_STRING HardwareId;
ULONG DummyResultLength;
UNICODE_STRING HardwareId1 = RTL_CONSTANT_STRING(L"*nEC1F00");
UNICODE_STRING HardwareId2 = RTL_CONSTANT_STRING(L"*PNP0F00");
UNICODE_STRING HardwareId3 = RTL_CONSTANT_STRING(L"*PNP0F02");
UNICODE_STRING HardwareId4 = RTL_CONSTANT_STRING(L"*PNP0F0D");
UNICODE_STRING HardwareId5 = RTL_CONSTANT_STRING(L"*PNP0F11");
UNICODE_STRING HardwareId6 = RTL_CONSTANT_STRING(L"*PNP0F15");
PAGED_CODE();
DPRINT("%s(%p, %p)\n", __FUNCTION__, DriverObject, PhysicalDeviceObject);
Status = IoCreateDevice(DriverObject,
sizeof(INPORT_DEVICE_EXTENSION),
NULL,
FILE_DEVICE_INPORT_PORT,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&Fdo);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create FDO 0x%X\n", Status);
goto Failure;
}
FdoExtension = Fdo->DeviceExtension;
RtlZeroMemory(FdoExtension, sizeof(INPORT_DEVICE_EXTENSION));
FdoExtension->State = dsStopped;
FdoExtension->Self = Fdo;
FdoExtension->Pdo = PhysicalDeviceObject;
FdoExtension->Ldo = IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject);
if (!FdoExtension->Ldo)
{
DPRINT1("Failed to attach FDO\n");
Status = STATUS_NO_SUCH_DEVICE;
goto Failure;
}
IoInitializeRemoveLock(&FdoExtension->RemoveLock, INPORT_TAG, 0, 0);
IoInitializeDpcRequest(Fdo, InPortDpcForIsr);
Status = IoGetDeviceProperty(PhysicalDeviceObject,
DevicePropertyHardwareID,
sizeof(HardwareIdBuffer),
HardwareIdBuffer,
&DummyResultLength);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to query the hardware ID string 0x%X\n", Status);
goto Failure;
}
RtlInitUnicodeString(&HardwareId, HardwareIdBuffer);
if (RtlEqualUnicodeString(&HardwareId, &HardwareId1, FALSE))
{
FdoExtension->MouseType = NecBusMouse;
FdoExtension->MouseAttributes.SampleRate = 60;
FdoExtension->MouseAttributes.NumberOfButtons = 2;
}
else if (RtlEqualUnicodeString(&HardwareId, &HardwareId3, FALSE) ||
RtlEqualUnicodeString(&HardwareId, &HardwareId4, FALSE))
{
FdoExtension->MouseType = MsInPortMouse;
FdoExtension->MouseAttributes.SampleRate = 100;
FdoExtension->MouseAttributes.NumberOfButtons = 3;
}
else if (RtlEqualUnicodeString(&HardwareId, &HardwareId2, FALSE) ||
RtlEqualUnicodeString(&HardwareId, &HardwareId5, FALSE) ||
RtlEqualUnicodeString(&HardwareId, &HardwareId6, FALSE))
{
FdoExtension->MouseType = LogitechBusMouse;
FdoExtension->MouseAttributes.SampleRate = 100;
FdoExtension->MouseAttributes.NumberOfButtons = 3;
}
else
{
DPRINT1("Unrecognized hardware '%wZ'\n", &HardwareId);
Status = STATUS_DEVICE_REMOVED;
goto Failure;
}
FdoExtension->MouseAttributes.MouseIdentifier = MOUSE_INPORT_HARDWARE;
/* 1 packet */
FdoExtension->MouseAttributes.InputDataQueueLength = sizeof(MOUSE_INPUT_DATA);
Fdo->Flags |= DO_BUFFERED_IO;
if (FdoExtension->Ldo->Flags & DO_POWER_PAGABLE)
Fdo->Flags |= DO_POWER_PAGABLE;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
Failure:
if (FdoExtension)
{
if (FdoExtension->Ldo)
IoDetachDevice(FdoExtension->Ldo);
}
if (Fdo)
{
IoDeleteDevice(Fdo);
}
return Status;
}
VOID
NTAPI
InPortUnload(
_In_ PDRIVER_OBJECT DriverObject)
{
PAGED_CODE();
DPRINT("%s(%p)\n", __FUNCTION__, DriverObject);
RtlFreeUnicodeString(&DriverRegistryPath);
}
NTSTATUS
NTAPI
InPortPower(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp)
{
NTSTATUS Status;
PINPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
DPRINT("%s(%p, %p) %X\n", __FUNCTION__, DeviceObject, Irp,
IoGetCurrentIrpStackLocation(Irp)->MinorFunction);
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Status = Status;
PoStartNextPowerIrp(Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
Status = PoCallDriver(DeviceExtension->Ldo, Irp);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
return Status;
}
NTSTATUS
NTAPI
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath)
{
DPRINT("%s(%p, %wZ)\n", __FUNCTION__, DriverObject, RegistryPath);
DriverRegistryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool,
RegistryPath->Length +
sizeof(UNICODE_NULL),
INPORT_TAG);
if (!DriverRegistryPath.Buffer)
{
DPRINT1("Failed to allocate the registry string buffer\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
DriverRegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
DriverRegistryPath.Buffer[RegistryPath->Length / sizeof(WCHAR)] = UNICODE_NULL;
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] = InPortCreateClose;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = InPortInternalDeviceControl;
DriverObject->MajorFunction[IRP_MJ_POWER] = InPortPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = InPortWmi;
DriverObject->MajorFunction[IRP_MJ_PNP] = InPortPnp;
DriverObject->DriverExtension->AddDevice = InPortAddDevice;
DriverObject->DriverUnload = InPortUnload;
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,158 @@
/*
* PROJECT: ReactOS InPort (Bus) Mouse Driver
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Main header file
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
#ifndef _INPORT_H_
#define _INPORT_H_
#include <wdm.h>
#include <wmilib.h>
#include <wmistr.h>
#include <kbdmou.h>
#define INPORT_TAG 'tPnI'
typedef enum
{
dsStopped,
dsStarted,
dsRemoved
} INPORT_DEVICE_STATE;
typedef enum
{
NecBusMouse,
MsInPortMouse,
LogitechBusMouse
} INPORT_MOUSE_TYPE;
typedef struct _INPORT_RAW_DATA
{
CHAR DeltaX;
CHAR DeltaY;
UCHAR Buttons;
ULONG ButtonDiff;
} INPORT_RAW_DATA, *PINPORT_RAW_DATA;
typedef struct _INPORT_DEVICE_EXTENSION
{
PDEVICE_OBJECT Self;
PDEVICE_OBJECT Pdo;
PDEVICE_OBJECT Ldo;
INPORT_DEVICE_STATE State;
IO_REMOVE_LOCK RemoveLock;
WMILIB_CONTEXT WmiLibInfo;
PUCHAR IoBase;
INPORT_MOUSE_TYPE MouseType;
/* Interrupt */
PKINTERRUPT InterruptObject;
ULONG InterruptVector;
KIRQL InterruptLevel;
KINTERRUPT_MODE InterruptMode;
BOOLEAN InterruptShared;
KAFFINITY InterruptAffinity;
/* Movement data and state of the mouse buttons */
INPORT_RAW_DATA RawData;
/* Mouclass */
CONNECT_DATA ConnectData;
PDEVICE_OBJECT ClassDeviceObject;
PVOID ClassService;
/* Mouse packet */
MOUSE_INPUT_DATA MouseInputData;
/* Previous state */
ULONG MouseButtonState;
/* Mouse device attributes */
MOUSE_ATTRIBUTES MouseAttributes;
} INPORT_DEVICE_EXTENSION, *PINPORT_DEVICE_EXTENSION;
DRIVER_INITIALIZE DriverEntry;
DRIVER_UNLOAD InPortUnload;
DRIVER_ADD_DEVICE InPortAddDevice;
_Dispatch_type_(IRP_MJ_CREATE)
_Dispatch_type_(IRP_MJ_CLOSE)
DRIVER_DISPATCH_PAGED InPortCreateClose;
_Dispatch_type_(IRP_MJ_INTERNAL_DEVICE_CONTROL)
DRIVER_DISPATCH_RAISED InPortInternalDeviceControl;
_Dispatch_type_(IRP_MJ_POWER)
DRIVER_DISPATCH_RAISED InPortPower;
_Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
DRIVER_DISPATCH_PAGED InPortWmi;
_Dispatch_type_(IRP_MJ_PNP)
DRIVER_DISPATCH_PAGED InPortPnp;
KSERVICE_ROUTINE InPortIsr;
IO_DPC_ROUTINE InPortDpcForIsr;
KSYNCHRONIZE_ROUTINE InPortStartMouse;
KSYNCHRONIZE_ROUTINE InPortStopMouse;
NTSTATUS
NTAPI
InPortStartDevice(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp);
NTSTATUS
NTAPI
InPortRemoveDevice(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp);
VOID
NTAPI
InPortInitializeMouse(
_In_ PINPORT_DEVICE_EXTENSION DeviceExtension);
NTSTATUS
NTAPI
InPortWmiRegistration(
_Inout_ PINPORT_DEVICE_EXTENSION DeviceExtension);
NTSTATUS
NTAPI
InPortWmiDeRegistration(
_Inout_ PINPORT_DEVICE_EXTENSION DeviceExtension);
NTSTATUS
NTAPI
InPortQueryWmiRegInfo(
_Inout_ PDEVICE_OBJECT DeviceObject,
_Inout_ PULONG RegFlags,
_Inout_ PUNICODE_STRING InstanceName,
_Out_opt_ PUNICODE_STRING *RegistryPath,
_Inout_ PUNICODE_STRING MofResourceName,
_Out_opt_ PDEVICE_OBJECT *Pdo);
NTSTATUS
NTAPI
InPortQueryWmiDataBlock(
_Inout_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp,
_In_ ULONG GuidIndex,
_In_ ULONG InstanceIndex,
_In_ ULONG InstanceCount,
_Out_opt_ PULONG InstanceLengthArray,
_In_ ULONG BufferAvail,
_Out_opt_ PUCHAR Buffer);
extern UNICODE_STRING DriverRegistryPath;
#endif /* _INPORT_H_ */

View file

@ -0,0 +1,5 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "InPort (Bus) Mouse Device Driver"
#define REACTOS_STR_INTERNAL_NAME "inport"
#define REACTOS_STR_ORIGINAL_FILENAME "inport.sys"
#include <reactos/version.rc>

View file

@ -0,0 +1,83 @@
/*
* PROJECT: ReactOS InPort (Bus) Mouse Driver
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: I/O control handling
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES *******************************************************************/
#include "inport.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ******************************************************************/
NTSTATUS
NTAPI
InPortInternalDeviceControl(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp)
{
NTSTATUS Status;
PCONNECT_DATA ConnectData;
PINPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
DPRINT("%s(%p, %p) 0x%X\n", __FUNCTION__, DeviceObject, Irp,
IrpSp->Parameters.DeviceIoControl.IoControlCode);
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_INTERNAL_MOUSE_CONNECT:
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
{
Status = STATUS_INVALID_PARAMETER;
break;
}
/* Already connected */
if (DeviceExtension->ClassService)
{
Status = STATUS_SHARING_VIOLATION;
break;
}
ConnectData = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
DeviceExtension->ClassDeviceObject = ConnectData->ClassDeviceObject;
DeviceExtension->ClassService = ConnectData->ClassService;
Status = STATUS_SUCCESS;
break;
case IOCTL_INTERNAL_MOUSE_DISCONNECT:
DeviceExtension->ClassService = NULL;
Status = STATUS_SUCCESS;
break;
case IOCTL_MOUSE_QUERY_ATTRIBUTES:
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
*(PMOUSE_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer = DeviceExtension->MouseAttributes;
Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
Status = STATUS_SUCCESS;
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}

283
drivers/input/inport/pnp.c Normal file
View file

@ -0,0 +1,283 @@
/*
* PROJECT: ReactOS InPort (Bus) Mouse Driver
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Plug and Play requests handling
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES *******************************************************************/
#include "inport.h"
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, InPortPnp)
#pragma alloc_text(PAGE, InPortStartDevice)
#pragma alloc_text(PAGE, InPortRemoveDevice)
#endif
/* FUNCTIONS ******************************************************************/
NTSTATUS
NTAPI
InPortStartDevice(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp)
{
NTSTATUS Status;
PCM_RESOURCE_LIST AllocatedResources, AllocatedResourcesTranslated;
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, DescriptorTranslated;
ULONG i;
ULONG RawVector;
BOOLEAN FoundBasePort = FALSE, FoundIrq = FALSE;
PINPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PAGED_CODE();
ASSERT(DeviceExtension->State == dsStopped);
if (!IoForwardIrpSynchronously(DeviceExtension->Ldo, Irp))
{
Status = STATUS_UNSUCCESSFUL;
goto Complete;
}
Status = Irp->IoStatus.Status;
if (!NT_SUCCESS(Status))
{
DPRINT1("LDO failed to start 0x%X\n", Status);
goto Complete;
}
AllocatedResources = IrpSp->Parameters.StartDevice.AllocatedResources;
AllocatedResourcesTranslated = IrpSp->Parameters.StartDevice.AllocatedResourcesTranslated;
if (!AllocatedResources || !AllocatedResourcesTranslated)
{
DPRINT1("No allocated resources\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Complete;
}
if (AllocatedResources->Count != 1)
DPRINT1("Expected FullList count is 1, got %d\n", AllocatedResources->Count);
for (i = 0; i < AllocatedResources->List[0].PartialResourceList.Count; i++)
{
Descriptor = &AllocatedResources->List[0].PartialResourceList.PartialDescriptors[i];
DescriptorTranslated = &AllocatedResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[i];
switch (Descriptor->Type)
{
case CmResourceTypePort:
{
DPRINT("[%p:%X:%X] I/O ports at [%p-%p]\n",
Descriptor,
Descriptor->ShareDisposition,
Descriptor->Flags,
Descriptor->u.Port.Start.LowPart,
Descriptor->u.Port.Start.LowPart + (Descriptor->u.Port.Length - 1));
if (!FoundBasePort)
{
DeviceExtension->IoBase = ULongToPtr(Descriptor->u.Port.Start.u.LowPart);
FoundBasePort = TRUE;
}
break;
}
case CmResourceTypeInterrupt:
{
DPRINT("[%p:%X:%X] INT Vec %d Lev %d Aff %IX\n",
Descriptor,
Descriptor->ShareDisposition,
Descriptor->Flags,
Descriptor->u.Interrupt.Vector,
Descriptor->u.Interrupt.Level,
Descriptor->u.Interrupt.Affinity);
if (!FoundIrq)
{
DeviceExtension->InterruptVector = DescriptorTranslated->u.Interrupt.Vector;
DeviceExtension->InterruptLevel = (KIRQL)DescriptorTranslated->u.Interrupt.Level;
if (DescriptorTranslated->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
DeviceExtension->InterruptMode = Latched;
else
DeviceExtension->InterruptMode = LevelSensitive;
DeviceExtension->InterruptShared = (DescriptorTranslated->ShareDisposition == CmResourceShareShared);
DeviceExtension->InterruptAffinity = DescriptorTranslated->u.Interrupt.Affinity;
RawVector = Descriptor->u.Interrupt.Vector;
FoundIrq = TRUE;
}
break;
}
default:
DPRINT("[%p:%X:%X] Unrecognized resource type %X\n",
Descriptor,
Descriptor->ShareDisposition,
Descriptor->Flags,
Descriptor->Type);
break;
}
}
if (!FoundBasePort || !FoundIrq)
{
DPRINT1("The device resources were not found\n");
Status = STATUS_DEVICE_CONFIGURATION_ERROR;
goto Complete;
}
DPRINT("I/O base at %p\n", DeviceExtension->IoBase);
DPRINT("IRQ %d\n", RawVector);
Status = InPortWmiRegistration(DeviceExtension);
if (!NT_SUCCESS(Status))
{
DPRINT1("WMI registration failed 0x%X\n", Status);
goto Complete;
}
InPortInitializeMouse(DeviceExtension);
Status = IoConnectInterrupt(&DeviceExtension->InterruptObject,
InPortIsr,
DeviceExtension,
NULL,
DeviceExtension->InterruptVector,
DeviceExtension->InterruptLevel,
DeviceExtension->InterruptLevel,
DeviceExtension->InterruptMode,
DeviceExtension->InterruptShared,
DeviceExtension->InterruptAffinity,
FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not connect to interrupt %d\n", DeviceExtension->InterruptVector);
goto Complete;
}
KeSynchronizeExecution(DeviceExtension->InterruptObject,
InPortStartMouse,
DeviceExtension);
DeviceExtension->State = dsStarted;
Complete:
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
NTAPI
InPortRemoveDevice(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp)
{
NTSTATUS Status;
BOOLEAN IsStarted;
PINPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PAGED_CODE();
InPortWmiDeRegistration(DeviceExtension);
IsStarted = (DeviceExtension->State == dsStarted);
DeviceExtension->State = dsRemoved;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(DeviceExtension->Ldo, Irp);
IoReleaseRemoveLockAndWait(&DeviceExtension->RemoveLock, Irp);
/* Device is active */
if (IsStarted)
{
KeSynchronizeExecution(DeviceExtension->InterruptObject,
InPortStopMouse,
DeviceExtension);
IoDisconnectInterrupt(DeviceExtension->InterruptObject);
/* Flush DPC for ISR */
KeFlushQueuedDpcs();
}
IoDetachDevice(DeviceExtension->Ldo);
IoDeleteDevice(DeviceObject);
return Status;
}
NTSTATUS
NTAPI
InPortPnp(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp)
{
NTSTATUS Status;
PINPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PAGED_CODE();
DPRINT("%s(%p, %p) %X\n",
__FUNCTION__, DeviceObject, Irp, IrpSp->MinorFunction);
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
switch (IrpSp->MinorFunction)
{
case IRP_MN_START_DEVICE:
Status = InPortStartDevice(DeviceObject, Irp);
break;
case IRP_MN_REMOVE_DEVICE:
return InPortRemoveDevice(DeviceObject, Irp);
case IRP_MN_QUERY_STOP_DEVICE:
/* Device cannot work with other resources */
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_STOP_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
case IRP_MN_SURPRISE_REMOVAL:
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(DeviceExtension->Ldo, Irp);
break;
default:
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(DeviceExtension->Ldo, Irp);
break;
}
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
return Status;
}

202
drivers/input/inport/wmi.c Normal file
View file

@ -0,0 +1,202 @@
/*
* PROJECT: ReactOS InPort (Bus) Mouse Driver
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: WMI support
* COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES *******************************************************************/
#include "inport.h"
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, InPortWmi)
#pragma alloc_text(PAGE, InPortWmiRegistration)
#pragma alloc_text(PAGE, InPortWmiDeRegistration)
#pragma alloc_text(PAGE, InPortQueryWmiRegInfo)
#pragma alloc_text(PAGE, InPortQueryWmiDataBlock)
#endif
GUID GuidWmiPortData = POINTER_PORT_WMI_STD_DATA_GUID;
WMIGUIDREGINFO InPortWmiGuidList[] =
{
{&GuidWmiPortData, 1, 0}
};
/* FUNCTIONS ******************************************************************/
NTSTATUS
NTAPI
InPortQueryWmiRegInfo(
_Inout_ PDEVICE_OBJECT DeviceObject,
_Inout_ PULONG RegFlags,
_Inout_ PUNICODE_STRING InstanceName,
_Out_opt_ PUNICODE_STRING *RegistryPath,
_Inout_ PUNICODE_STRING MofResourceName,
_Out_opt_ PDEVICE_OBJECT *Pdo)
{
PINPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
UNREFERENCED_PARAMETER(InstanceName);
UNREFERENCED_PARAMETER(MofResourceName);
PAGED_CODE();
DPRINT("%s()\n", __FUNCTION__);
*RegFlags = WMIREG_FLAG_INSTANCE_PDO;
*RegistryPath = &DriverRegistryPath;
*Pdo = DeviceExtension->Pdo;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
InPortQueryWmiDataBlock(
_Inout_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp,
_In_ ULONG GuidIndex,
_In_ ULONG InstanceIndex,
_In_ ULONG InstanceCount,
_Out_opt_ PULONG InstanceLengthArray,
_In_ ULONG BufferAvail,
_Out_opt_ PUCHAR Buffer)
{
NTSTATUS Status;
PPOINTER_PORT_WMI_STD_DATA InPortData;
PINPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PAGED_CODE();
DPRINT("%s()\n", __FUNCTION__);
if (GuidIndex > RTL_NUMBER_OF(InPortWmiGuidList))
{
Status = STATUS_WMI_GUID_NOT_FOUND;
goto Complete;
}
/* Only register 1 instance per GUID */
if (InstanceIndex != 0 || InstanceCount != 1)
{
Status = STATUS_WMI_INSTANCE_NOT_FOUND;
goto Complete;
}
if (!InstanceLengthArray || BufferAvail < sizeof(POINTER_PORT_WMI_STD_DATA))
{
Status = STATUS_BUFFER_TOO_SMALL;
goto Complete;
}
InPortData = (PPOINTER_PORT_WMI_STD_DATA)Buffer;
/* Bus mouse connector isn't defined in the DDK, so set type to something generic */
InPortData->ConnectorType = POINTER_PORT_WMI_STD_I8042;
/* 1 packet */
InPortData->DataQueueSize = 1;
/* Not supported by device */
InPortData->ErrorCount = 0;
InPortData->Buttons = DeviceExtension->MouseAttributes.NumberOfButtons;
InPortData->HardwareType = POINTER_PORT_WMI_STD_MOUSE;
*InstanceLengthArray = sizeof(POINTER_PORT_WMI_STD_DATA);
Status = STATUS_SUCCESS;
Complete:
return WmiCompleteRequest(DeviceObject,
Irp,
Status,
sizeof(POINTER_PORT_WMI_STD_DATA),
IO_NO_INCREMENT);
}
NTSTATUS
NTAPI
InPortWmiRegistration(
_Inout_ PINPORT_DEVICE_EXTENSION DeviceExtension)
{
PAGED_CODE();
DeviceExtension->WmiLibInfo.GuidCount = RTL_NUMBER_OF(InPortWmiGuidList);
DeviceExtension->WmiLibInfo.GuidList = InPortWmiGuidList;
DeviceExtension->WmiLibInfo.QueryWmiRegInfo = InPortQueryWmiRegInfo;
DeviceExtension->WmiLibInfo.QueryWmiDataBlock = InPortQueryWmiDataBlock;
DeviceExtension->WmiLibInfo.SetWmiDataBlock = NULL;
DeviceExtension->WmiLibInfo.SetWmiDataItem = NULL;
DeviceExtension->WmiLibInfo.ExecuteWmiMethod = NULL;
DeviceExtension->WmiLibInfo.WmiFunctionControl = NULL;
return IoWMIRegistrationControl(DeviceExtension->Self,
WMIREG_ACTION_REGISTER);
}
NTSTATUS
NTAPI
InPortWmiDeRegistration(
_Inout_ PINPORT_DEVICE_EXTENSION DeviceExtension)
{
PAGED_CODE();
return IoWMIRegistrationControl(DeviceExtension->Self,
WMIREG_ACTION_DEREGISTER);
}
NTSTATUS
NTAPI
InPortWmi(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp)
{
NTSTATUS Status;
SYSCTL_IRP_DISPOSITION Disposition;
PINPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PAGED_CODE();
DPRINT("%s(%p, %p) %X\n", __FUNCTION__, DeviceObject, Irp,
IoGetCurrentIrpStackLocation(Irp)->MinorFunction);
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
Status = WmiSystemControl(&DeviceExtension->WmiLibInfo,
DeviceObject,
Irp,
&Disposition);
switch (Disposition)
{
case IrpProcessed:
break;
case IrpNotCompleted:
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IrpForward:
case IrpNotWmi:
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(DeviceExtension->Ldo, Irp);
break;
}
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
return Status;
}