From: Rémi Bernon rbernon@codeweavers.com
This only matches with digitizer devices for now, it could later be used for HID mice but for now we use a different path for that. --- MAINTAINERS | 1 + configure.ac | 1 + dlls/mouhid.sys/Makefile.in | 7 ++ dlls/mouhid.sys/main.c | 164 ++++++++++++++++++++++++++++++++ dlls/mouhid.sys/mouhid.inf | 22 +++++ dlls/mouhid.sys/mouhid.rc | 20 ++++ dlls/mouhid.sys/mouhid.sys.spec | 1 + loader/wine.inf.in | 1 + 8 files changed, 217 insertions(+) create mode 100644 dlls/mouhid.sys/Makefile.in create mode 100644 dlls/mouhid.sys/main.c create mode 100644 dlls/mouhid.sys/mouhid.inf create mode 100644 dlls/mouhid.sys/mouhid.rc create mode 100644 dlls/mouhid.sys/mouhid.sys.spec
diff --git a/MAINTAINERS b/MAINTAINERS index 4bab36bfdf9..2e259f12d70 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -169,6 +169,7 @@ P: Aric Stewart aric@codeweavers.com F: dlls/hid/ F: dlls/hidclass.sys/ F: dlls/hidparse.sys/ +F: dlls/mouhid.sys/ F: dlls/winehid.sys/
HTTP server diff --git a/configure.ac b/configure.ac index 57f64ebffc3..533c3b974d1 100644 --- a/configure.ac +++ b/configure.ac @@ -2792,6 +2792,7 @@ WINE_CONFIG_MAKEFILE(dlls/mmdevapi/tests) WINE_CONFIG_MAKEFILE(dlls/mmdevldr.vxd,enable_win16) WINE_CONFIG_MAKEFILE(dlls/mmsystem.dll16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/monodebg.vxd,enable_win16) +WINE_CONFIG_MAKEFILE(dlls/mouhid.sys) WINE_CONFIG_MAKEFILE(dlls/mountmgr.sys) WINE_CONFIG_MAKEFILE(dlls/mouse.drv16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/mp3dmod) diff --git a/dlls/mouhid.sys/Makefile.in b/dlls/mouhid.sys/Makefile.in new file mode 100644 index 00000000000..816d7e58120 --- /dev/null +++ b/dlls/mouhid.sys/Makefile.in @@ -0,0 +1,7 @@ +MODULE = mouhid.sys +IMPORTS = ntoskrnl +EXTRADLLFLAGS = -Wl,--subsystem,native + +SOURCES = \ + main.c \ + mouhid.rc diff --git a/dlls/mouhid.sys/main.c b/dlls/mouhid.sys/main.c new file mode 100644 index 00000000000..af54ffbd70b --- /dev/null +++ b/dlls/mouhid.sys/main.c @@ -0,0 +1,164 @@ +/* + * Copyright 2024 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> +#include <stdlib.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "winioctl.h" +#include "ntuser.h" + +#include "ddk/wdm.h" +#include "ddk/hidport.h" +#include "ddk/hidpddi.h" +#include "ddk/hidtypes.h" + +#include "wine/hid.h" +#include "wine/debug.h" +#include "wine/list.h" + +WINE_DEFAULT_DEBUG_CHANNEL(hid); + +struct device +{ + LONG removed; + DEVICE_OBJECT *bus_device; +}; + +static inline struct device *impl_from_DEVICE_OBJECT( DEVICE_OBJECT *device ) +{ + return (struct device *)device->DeviceExtension; +} + +static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp ) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); + ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; + struct device *impl = impl_from_DEVICE_OBJECT( device ); + + if (InterlockedOr( &impl->removed, FALSE )) + { + irp->IoStatus.Status = STATUS_DELETE_PENDING; + irp->IoStatus.Information = 0; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return STATUS_DELETE_PENDING; + } + + TRACE( "device %p, irp %p, code %#lx, bus_device %p.\n", device, irp, code, impl->bus_device ); + + IoSkipCurrentIrpStackLocation( irp ); + return IoCallDriver( impl->bus_device, irp ); +} + +static NTSTATUS WINAPI set_event_completion( DEVICE_OBJECT *device, IRP *irp, void *context ) +{ + if (irp->PendingReturned) KeSetEvent( (KEVENT *)context, IO_NO_INCREMENT, FALSE ); + return STATUS_MORE_PROCESSING_REQUIRED; +} + +static NTSTATUS WINAPI driver_pnp( DEVICE_OBJECT *device, IRP *irp ) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); + struct device *impl = impl_from_DEVICE_OBJECT( device ); + UCHAR code = stack->MinorFunction; + NTSTATUS status; + KEVENT event; + + TRACE( "device %p, irp %p, code %#x, bus_device %p.\n", device, irp, code, impl->bus_device ); + + switch (stack->MinorFunction) + { + case IRP_MN_START_DEVICE: + KeInitializeEvent( &event, NotificationEvent, FALSE ); + IoCopyCurrentIrpStackLocationToNext( irp ); + IoSetCompletionRoutine( irp, set_event_completion, &event, TRUE, TRUE, TRUE ); + + status = IoCallDriver( impl->bus_device, irp ); + if (status == STATUS_PENDING) + { + KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL ); + status = irp->IoStatus.Status; + } + + if (status) irp->IoStatus.Status = status; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return status; + + case IRP_MN_SURPRISE_REMOVAL: + status = STATUS_SUCCESS; + break; + + case IRP_MN_REMOVE_DEVICE: + IoSkipCurrentIrpStackLocation( irp ); + status = IoCallDriver( impl->bus_device, irp ); + IoDetachDevice( impl->bus_device ); + IoDeleteDevice( device ); + return status; + + default: + IoSkipCurrentIrpStackLocation( irp ); + return IoCallDriver( impl->bus_device, irp ); + } + + return STATUS_SUCCESS; +} + +static NTSTATUS WINAPI add_device( DRIVER_OBJECT *driver, DEVICE_OBJECT *bus_device ) +{ + struct device *impl; + DEVICE_OBJECT *device; + NTSTATUS status; + + TRACE( "driver %p, bus_device %p.\n", driver, bus_device ); + + if ((status = IoCreateDevice( driver, sizeof(struct device), NULL, FILE_DEVICE_BUS_EXTENDER, + 0, FALSE, &device ))) + { + ERR( "failed to create bus FDO, status %#lx.\n", status ); + return status; + } + + impl = device->DeviceExtension; + impl->bus_device = bus_device; + + IoAttachDeviceToDeviceStack( device, bus_device ); + device->Flags &= ~DO_DEVICE_INITIALIZING; + return STATUS_SUCCESS; +} + +static void WINAPI driver_unload( DRIVER_OBJECT *driver ) +{ + TRACE( "driver %p\n", driver ); +} + +NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) +{ + TRACE( "driver %p, path %s.\n", driver, debugstr_w(path->Buffer) ); + + driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = driver_ioctl; + driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_ioctl; + driver->MajorFunction[IRP_MJ_PNP] = driver_pnp; + driver->DriverExtension->AddDevice = add_device; + driver->DriverUnload = driver_unload; + + return STATUS_SUCCESS; +} diff --git a/dlls/mouhid.sys/mouhid.inf b/dlls/mouhid.sys/mouhid.inf new file mode 100644 index 00000000000..efc65794fdc --- /dev/null +++ b/dlls/mouhid.sys/mouhid.inf @@ -0,0 +1,22 @@ +[Version] +Signature="$CHICAGO$" +ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} +Class=System + +[Manufacturer] +Wine=mfg_section + +[mfg_section] +HID touch screen device=device_section,HID_DEVICE_UP:000D_U:0004 + +[device_section.Services] +AddService = mouhid,0x2,svc_section + +[svc_section] +Description="Wine HID mouse device driver" +DisplayName="Wine HID mouse" +ServiceBinary="%12%\mouhid.sys" +LoadOrderGroup="WinePlugPlay" +ServiceType=1 +StartType=3 +ErrorControl=1 diff --git a/dlls/mouhid.sys/mouhid.rc b/dlls/mouhid.sys/mouhid.rc new file mode 100644 index 00000000000..e395b5f5fea --- /dev/null +++ b/dlls/mouhid.sys/mouhid.rc @@ -0,0 +1,20 @@ +/* + * Copyright 2024 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @makedep: mouhid.inf */ +1 WINE_DATA_FILE mouhid.inf diff --git a/dlls/mouhid.sys/mouhid.sys.spec b/dlls/mouhid.sys/mouhid.sys.spec new file mode 100644 index 00000000000..76421d7e35b --- /dev/null +++ b/dlls/mouhid.sys/mouhid.sys.spec @@ -0,0 +1 @@ +# nothing to export diff --git a/loader/wine.inf.in b/loader/wine.inf.in index 06551152f3a..35644cbd285 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -2608,6 +2608,7 @@ services,"@%11%\ws2_32.dll,-4"
[InfFiles] input.inf,"@%12%\hidclass.sys,-1" +mouhid.inf,"@%12%\mouhid.sys,-1" winebus.inf,"@%12%\winebus.sys,-1" winehid.inf,"@%12%\winehid.sys,-1" wineusb.inf,"@%12%\wineusb.sys,-1"