Signed-off-by: Zebediah Figura z.figura12@gmail.com --- loader/Makefile.in | 1 + loader/wine.inf.in | 1 + loader/winebus.inf.in | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 loader/winebus.inf.in
diff --git a/loader/Makefile.in b/loader/Makefile.in index 3ada656408b..11a476103c1 100644 --- a/loader/Makefile.in +++ b/loader/Makefile.in @@ -10,6 +10,7 @@ SOURCES = \ wine.man.in \ wine.pl.UTF-8.man.in \ wine_info.plist.in \ + winebus.inf.in \ winehid.inf.in
PROGRAMS = $(WINELOADER_PROGRAMS) diff --git a/loader/wine.inf.in b/loader/wine.inf.in index 6356081d82a..ae48ca7ca86 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -3861,4 +3861,5 @@ inf_section = 17 l_intl.nls
[inf_section] +winebus.inf winehid.inf diff --git a/loader/winebus.inf.in b/loader/winebus.inf.in new file mode 100644 index 00000000000..3950c3dfc4e --- /dev/null +++ b/loader/winebus.inf.in @@ -0,0 +1,22 @@ +[Version] +Signature="$CHICAGO$" +ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} +Class=System + +[Manufacturer] +Wine=mfg_section + +[mfg_section] +Wine HID bus driver=device_section,root\winebus + +[device_section.Services] +AddService = winebus,0x2,svc_section + +[svc_section] +Description="Wine HID bus driver" +DisplayName="Wine HID bus" +ServiceBinary="%12%\winebus.sys" +LoadOrderGroup="WinePlugPlay" +ServiceType=1 +StartType=3 +ErrorControl=1
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winebus.sys/main.c | 65 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 98ed890af89..bffd9b8f5f8 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -88,6 +88,9 @@ static DRIVER_OBJECT *driver_obj;
static DEVICE_OBJECT *mouse_obj;
+/* The root-enumerated device stack. */ +static DEVICE_OBJECT *bus_pdo, *bus_fdo; + HANDLE driver_key;
struct pnp_device @@ -490,7 +493,33 @@ static NTSTATUS handle_IRP_MN_QUERY_ID(DEVICE_OBJECT *device, IRP *irp) return status; }
-static NTSTATUS WINAPI common_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) +static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); + NTSTATUS ret; + + switch (irpsp->MinorFunction) + { + case IRP_MN_START_DEVICE: + case IRP_MN_SURPRISE_REMOVAL: + irp->IoStatus.u.Status = STATUS_SUCCESS; + break; + case IRP_MN_REMOVE_DEVICE: + irp->IoStatus.u.Status = STATUS_SUCCESS; + IoSkipCurrentIrpStackLocation(irp); + ret = IoCallDriver(bus_pdo, irp); + IoDetachDevice(bus_pdo); + IoDeleteDevice(device); + return ret; + default: + FIXME("Unhandled minor function %#x.\n", irpsp->MinorFunction); + } + + IoSkipCurrentIrpStackLocation(irp); + return IoCallDriver(bus_pdo, irp); +} + +static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) { NTSTATUS status = irp->IoStatus.u.Status; IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); @@ -519,6 +548,13 @@ static NTSTATUS WINAPI common_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) return status; }
+static NTSTATUS WINAPI common_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) +{ + if (device == bus_fdo) + return fdo_pnp_dispatch(device, irp); + return pdo_pnp_dispatch(device, irp); +} + static NTSTATUS deliver_last_report(struct device_extension *ext, DWORD buffer_length, BYTE* buffer, ULONG_PTR *out_length) { if (buffer_length < ext->last_report_size) @@ -592,6 +628,12 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp)
TRACE("(%p, %p)\n", device, irp);
+ if (device == bus_fdo) + { + IoSkipCurrentIrpStackLocation(irp); + return IoCallDriver(bus_pdo, irp); + } + switch (irpsp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_HID_GET_DEVICE_ATTRIBUTES: @@ -836,6 +878,26 @@ BOOL is_xbox_gamepad(WORD vid, WORD pid) return FALSE; }
+static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *pdo) +{ + NTSTATUS ret; + + TRACE("driver %p, pdo %p.\n", driver, pdo); + + if ((ret = IoCreateDevice(driver, 0, NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &bus_fdo))) + { + ERR("Failed to create FDO, status %#x.\n", ret); + return ret; + } + + IoAttachDeviceToDeviceStack(bus_fdo, pdo); + bus_pdo = pdo; + + bus_fdo->Flags &= ~DO_DEVICE_INITIALIZING; + + return STATUS_SUCCESS; +} + static void WINAPI driver_unload(DRIVER_OBJECT *driver) { udev_driver_unload(); @@ -933,6 +995,7 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
driver->MajorFunction[IRP_MJ_PNP] = common_pnp_dispatch; driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = hid_internal_dispatch; + driver->DriverExtension->AddDevice = driver_add_device; driver->DriverUnload = driver_unload;
mouse_device_create();
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- Windows drivers install root-enumerated devices by using user-mode code similar to this.
programs/wineboot/Makefile.in | 2 +- programs/wineboot/wineboot.c | 55 +++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/programs/wineboot/Makefile.in b/programs/wineboot/Makefile.in index eaea154057f..3921fa96444 100644 --- a/programs/wineboot/Makefile.in +++ b/programs/wineboot/Makefile.in @@ -1,7 +1,7 @@ MODULE = wineboot.exe APPMODE = -mconsole IMPORTS = uuid advapi32 -DELAYIMPORTS = shell32 shlwapi version user32 +DELAYIMPORTS = shell32 shlwapi version user32 setupapi newdev
EXTRADLLFLAGS = -mno-cygwin
diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c index 4dfbca5e2cd..cd5c9505b3f 100644 --- a/programs/wineboot/wineboot.c +++ b/programs/wineboot/wineboot.c @@ -69,6 +69,8 @@ #include <shobjidl.h> #include <shlwapi.h> #include <shellapi.h> +#include <setupapi.h> +#include <newdev.h> #include "resource.h"
WINE_DEFAULT_DEBUG_CHANNEL(wineboot); @@ -1121,6 +1123,57 @@ static HANDLE start_rundll32( const WCHAR *inf_path, BOOL wow64 ) return pi.hProcess; }
+static void install_root_pnp_devices(void) +{ + static const struct + { + const char *name; + const char *hardware_id; + const char *infpath; + } + root_devices[] = + { + {"root\wine\winebus", "root\winebus\0", "C:\windows\inf\winebus.inf"}, + }; + SP_DEVINFO_DATA device = {sizeof(device)}; + unsigned int i; + HDEVINFO set; + + if ((set = SetupDiCreateDeviceInfoList( NULL, NULL )) == INVALID_HANDLE_VALUE) + { + WINE_ERR("Failed to create device info list, error %#x.\n", GetLastError()); + return; + } + + for (i = 0; i < ARRAY_SIZE(root_devices); ++i) + { + if (!SetupDiCreateDeviceInfoA( set, root_devices[i].name, &GUID_NULL, NULL, NULL, 0, &device)) + { + if (GetLastError() != ERROR_DEVINST_ALREADY_EXISTS) + WINE_ERR("Failed to create device %s, error %#x.\n", debugstr_a(root_devices[i].name), GetLastError()); + continue; + } + + if (!SetupDiSetDeviceRegistryPropertyA(set, &device, SPDRP_HARDWAREID, + (const BYTE *)root_devices[i].hardware_id, (strlen(root_devices[i].hardware_id) + 2) * sizeof(WCHAR))) + { + WINE_ERR("Failed to set hardware id for %s, error %#x.\n", debugstr_a(root_devices[i].name), GetLastError()); + continue; + } + + if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, set, &device)) + { + WINE_ERR("Failed to register device %s, error %#x.\n", debugstr_a(root_devices[i].name), GetLastError()); + continue; + } + + if (!UpdateDriverForPlugAndPlayDevicesA(NULL, root_devices[i].hardware_id, root_devices[i].infpath, 0, NULL)) + WINE_ERR("Failed to install drivers for %s, error %#x.\n", debugstr_a(root_devices[i].name), GetLastError()); + } + + SetupDiDestroyDeviceInfoList(set); +} + /* execute rundll32 on the wine.inf file if necessary */ static void update_wineprefix( BOOL force ) { @@ -1164,6 +1217,8 @@ static void update_wineprefix( BOOL force ) } DestroyWindow( hwnd ); } + install_root_pnp_devices(); + WINE_MESSAGE( "wine: configuration in '%s' has been updated.\n", prettyprint_configdir() ); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- loader/wine.inf.in | 12 ------------ 1 file changed, 12 deletions(-)
diff --git a/loader/wine.inf.in b/loader/wine.inf.in index ae48ca7ca86..351f2d48ec7 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -165,7 +165,6 @@ AddService=FontCache3.0.0.0,0,WPFFontCacheService AddService=LanmanServer,0,LanmanServerService AddService=FontCache,0,FontCacheService AddService=Schedule,0,TaskSchedulerService -AddService=WineBus,0,WineBusService AddService=Winmgmt,0,WinmgmtService AddService=wuauserv,0,wuauService
@@ -183,7 +182,6 @@ AddService=FontCache3.0.0.0,0,WPFFontCacheService AddService=LanmanServer,0,LanmanServerService AddService=FontCache,0,FontCacheService AddService=Schedule,0,TaskSchedulerService -AddService=WineBus,0,WineBusService AddService=Winmgmt,0,WinmgmtService AddService=wuauserv,0,wuauService
@@ -201,7 +199,6 @@ AddService=FontCache3.0.0.0,0,WPFFontCacheService AddService=LanmanServer,0,LanmanServerService AddService=FontCache,0,FontCacheService AddService=Schedule,0,TaskSchedulerService -AddService=WineBus,0,WineBusService AddService=Winmgmt,0,WinmgmtService AddService=wuauserv,0,wuauService
@@ -3611,15 +3608,6 @@ ServiceType=32 StartType=3 ErrorControl=1
-[WineBusService] -Description="Wine Platform Bus Kernel" -DisplayName="Platform Bus Kernel" -ServiceBinary="%12%\winebus.sys" -LoadOrderGroup="WinePlugPlay" -ServiceType=1 -StartType=2 -ErrorControl=1 - [SpoolerService] AddReg=SpoolerServiceKeys Description="Loads files to memory for later printing"
As of the next patch this will be necessary.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winebus.sys/main.c | 172 ++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 85 deletions(-)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index bffd9b8f5f8..ec8e0f7f480 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -493,18 +493,105 @@ static NTSTATUS handle_IRP_MN_QUERY_ID(DEVICE_OBJECT *device, IRP *irp) return status; }
+static NTSTATUS mouse_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *ret_length) +{ + TRACE("buffer %p, length %u.\n", buffer, length); + + *ret_length = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL); + if (length < sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL)) + return STATUS_BUFFER_TOO_SMALL; + + memcpy(buffer, REPORT_HEADER, sizeof(REPORT_HEADER)); + memcpy(buffer + sizeof(REPORT_HEADER), REPORT_TAIL, sizeof(REPORT_TAIL)); + buffer[IDX_HEADER_PAGE] = HID_USAGE_PAGE_GENERIC; + buffer[IDX_HEADER_USAGE] = HID_USAGE_GENERIC_MOUSE; + + return STATUS_SUCCESS; +} + +static NTSTATUS mouse_get_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length) +{ + static const WCHAR nameW[] = {'W','i','n','e',' ','H','I','D',' ','m','o','u','s','e',0}; + if (index != HID_STRING_ID_IPRODUCT) + return STATUS_NOT_IMPLEMENTED; + if (length < ARRAY_SIZE(nameW)) + return STATUS_BUFFER_TOO_SMALL; + strcpyW(buffer, nameW); + return STATUS_SUCCESS; +} + +static NTSTATUS mouse_begin_report_processing(DEVICE_OBJECT *device) +{ + return STATUS_SUCCESS; +} + +static NTSTATUS mouse_set_output_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *ret_length) +{ + FIXME("id %u, stub!\n", id); + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS mouse_get_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *ret_length) +{ + FIXME("id %u, stub!\n", id); + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS mouse_set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *ret_length) +{ + FIXME("id %u, stub!\n", id); + return STATUS_NOT_IMPLEMENTED; +} + +static const platform_vtbl mouse_vtbl = +{ + .get_reportdescriptor = mouse_get_reportdescriptor, + .get_string = mouse_get_string, + .begin_report_processing = mouse_begin_report_processing, + .set_output_report = mouse_set_output_report, + .get_feature_report = mouse_get_feature_report, + .set_feature_report = mouse_set_feature_report, +}; + +static void mouse_device_create(void) +{ + static const GUID wine_mouse_class = {0xdfe2580e,0x52fd,0x453d,{0xa2,0xc1,0x33,0x81,0xf2,0x32,0x68,0x4c}}; + static const WCHAR busidW[] = {'W','I','N','E','M','O','U','S','E',0}; + + mouse_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, + &wine_mouse_class, &mouse_vtbl, 0); + IoInvalidateDeviceRelations(mouse_obj, BusRelations); +} + static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) { + static const WCHAR SDL_enabledW[] = {'E','n','a','b','l','e',' ','S','D','L',0}; + static const UNICODE_STRING SDL_enabled = {sizeof(SDL_enabledW) - sizeof(WCHAR), sizeof(SDL_enabledW), (WCHAR*)SDL_enabledW}; IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); NTSTATUS ret;
switch (irpsp->MinorFunction) { case IRP_MN_START_DEVICE: + mouse_device_create(); + + if (check_bus_option(&SDL_enabled, 1)) + { + if (sdl_driver_init() == STATUS_SUCCESS) + return STATUS_SUCCESS; + } + udev_driver_init(); + iohid_driver_init(); + irp->IoStatus.u.Status = STATUS_SUCCESS; + break; case IRP_MN_SURPRISE_REMOVAL: irp->IoStatus.u.Status = STATUS_SUCCESS; break; case IRP_MN_REMOVE_DEVICE: + udev_driver_unload(); + iohid_driver_unload(); + sdl_driver_unload(); + irp->IoStatus.u.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(irp); ret = IoCallDriver(bus_pdo, irp); @@ -900,86 +987,11 @@ static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *p
static void WINAPI driver_unload(DRIVER_OBJECT *driver) { - udev_driver_unload(); - iohid_driver_unload(); - sdl_driver_unload(); NtClose(driver_key); }
-static NTSTATUS mouse_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *ret_length) -{ - TRACE("buffer %p, length %u.\n", buffer, length); - - *ret_length = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL); - if (length < sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL)) - return STATUS_BUFFER_TOO_SMALL; - - memcpy(buffer, REPORT_HEADER, sizeof(REPORT_HEADER)); - memcpy(buffer + sizeof(REPORT_HEADER), REPORT_TAIL, sizeof(REPORT_TAIL)); - buffer[IDX_HEADER_PAGE] = HID_USAGE_PAGE_GENERIC; - buffer[IDX_HEADER_USAGE] = HID_USAGE_GENERIC_MOUSE; - - return STATUS_SUCCESS; -} - -static NTSTATUS mouse_get_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length) -{ - static const WCHAR nameW[] = {'W','i','n','e',' ','H','I','D',' ','m','o','u','s','e',0}; - if (index != HID_STRING_ID_IPRODUCT) - return STATUS_NOT_IMPLEMENTED; - if (length < ARRAY_SIZE(nameW)) - return STATUS_BUFFER_TOO_SMALL; - strcpyW(buffer, nameW); - return STATUS_SUCCESS; -} - -static NTSTATUS mouse_begin_report_processing(DEVICE_OBJECT *device) -{ - return STATUS_SUCCESS; -} - -static NTSTATUS mouse_set_output_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *ret_length) -{ - FIXME("id %u, stub!\n", id); - return STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS mouse_get_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *ret_length) -{ - FIXME("id %u, stub!\n", id); - return STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS mouse_set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *ret_length) -{ - FIXME("id %u, stub!\n", id); - return STATUS_NOT_IMPLEMENTED; -} - -static const platform_vtbl mouse_vtbl = -{ - .get_reportdescriptor = mouse_get_reportdescriptor, - .get_string = mouse_get_string, - .begin_report_processing = mouse_begin_report_processing, - .set_output_report = mouse_set_output_report, - .get_feature_report = mouse_get_feature_report, - .set_feature_report = mouse_set_feature_report, -}; - -static void mouse_device_create(void) -{ - static const GUID wine_mouse_class = {0xdfe2580e,0x52fd,0x453d,{0xa2,0xc1,0x33,0x81,0xf2,0x32,0x68,0x4c}}; - static const WCHAR busidW[] = {'W','I','N','E','M','O','U','S','E',0}; - - mouse_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, - &wine_mouse_class, &mouse_vtbl, 0); - IoInvalidateDeviceRelations(mouse_obj, BusRelations); -} - NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) { - static const WCHAR SDL_enabledW[] = {'E','n','a','b','l','e',' ','S','D','L',0}; - static const UNICODE_STRING SDL_enabled = {sizeof(SDL_enabledW) - sizeof(WCHAR), sizeof(SDL_enabledW), (WCHAR*)SDL_enabledW}; OBJECT_ATTRIBUTES attr = {0}; NTSTATUS ret;
@@ -998,15 +1010,5 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) driver->DriverExtension->AddDevice = driver_add_device; driver->DriverUnload = driver_unload;
- mouse_device_create(); - - if (check_bus_option(&SDL_enabled, 1)) - { - if (sdl_driver_init() == STATUS_SUCCESS) - return STATUS_SUCCESS; - } - udev_driver_init(); - iohid_driver_init(); - return STATUS_SUCCESS; }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 8 ++- dlls/ntoskrnl.exe/ntoskrnl_private.h | 6 ++ dlls/ntoskrnl.exe/pnp.c | 84 ++++++++++++++++++++++++---- dlls/winebus.sys/bus.h | 1 + dlls/winebus.sys/bus_iohid.c | 2 +- dlls/winebus.sys/bus_sdl.c | 2 +- dlls/winebus.sys/bus_udev.c | 2 +- dlls/winebus.sys/main.c | 13 ++--- 8 files changed, 96 insertions(+), 22 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 1c9c75d8ddf..fcfc0b0314f 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -1472,6 +1472,7 @@ NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size, { static const WCHAR auto_format[] = {'\','D','e','v','i','c','e','\','%','0','8','x',0}; NTSTATUS status; + struct wine_device *wine_device; DEVICE_OBJECT *device; HANDLE manager = get_device_manager(); static unsigned int auto_idx = 0; @@ -1480,11 +1481,12 @@ NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size, TRACE( "(%p, %u, %s, %u, %x, %u, %p)\n", driver, ext_size, debugstr_us(name), type, characteristics, exclusive, ret_device );
- if (!(device = alloc_kernel_object( IoDeviceObjectType, NULL, sizeof(DEVICE_OBJECT) + ext_size, 1 ))) + if (!(wine_device = alloc_kernel_object( IoDeviceObjectType, NULL, sizeof(struct wine_device) + ext_size, 1 ))) return STATUS_NO_MEMORY; + device = &wine_device->device_obj;
device->DriverObject = driver; - device->DeviceExtension = device + 1; + device->DeviceExtension = wine_device + 1; device->DeviceType = type; device->StackSize = 1;
@@ -1550,9 +1552,11 @@ void WINAPI IoDeleteDevice( DEVICE_OBJECT *device )
if (status == STATUS_SUCCESS) { + struct wine_device *wine_device = CONTAINING_RECORD(device, struct wine_device, device_obj); DEVICE_OBJECT **prev = &device->DriverObject->DeviceObject; while (*prev && *prev != device) prev = &(*prev)->NextDevice; if (*prev) *prev = (*prev)->NextDevice; + ExFreePool( wine_device->children ); ObDereferenceObject( device ); } } diff --git a/dlls/ntoskrnl.exe/ntoskrnl_private.h b/dlls/ntoskrnl.exe/ntoskrnl_private.h index b5244ef1641..256e945e6f3 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl_private.h +++ b/dlls/ntoskrnl.exe/ntoskrnl_private.h @@ -86,4 +86,10 @@ static const WCHAR servicesW[] = {'\','R','e','g','i','s','t','r','y', '\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t', '\','S','e','r','v','i','c','e','s', '\',0}; + +struct wine_device +{ + DEVICE_OBJECT device_obj; + DEVICE_RELATIONS *children; +}; #endif diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index a3dbe772ae9..62a32a4afc4 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -318,25 +318,18 @@ static void start_device( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVINFO_DATA * } }
-static void handle_bus_relations( DEVICE_OBJECT *device ) +static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set ) { static const WCHAR infpathW[] = {'I','n','f','P','a','t','h',0};
SP_DEVINFO_DATA sp_device = {sizeof(sp_device)}; WCHAR device_instance_id[MAX_DEVICE_ID_LEN]; BOOL need_driver = TRUE; - HDEVINFO set; HKEY key;
- /* We could (should?) do a full IRP_MN_QUERY_DEVICE_RELATIONS query, - * but we don't have to, we have the DEVICE_OBJECT of the new device - * so we can simply handle the process here */ - if (get_device_instance_id( device, device_instance_id )) return;
- set = SetupDiCreateDeviceInfoList( NULL, NULL ); - if (!SetupDiCreateDeviceInfoW( set, device_instance_id, &GUID_NULL, NULL, NULL, 0, &sp_device ) && !SetupDiOpenDeviceInfoW( set, device_instance_id, NULL, 0, &sp_device )) { @@ -364,19 +357,90 @@ static void handle_bus_relations( DEVICE_OBJECT *device ) }
start_device( device, set, &sp_device ); - - SetupDiDestroyDeviceInfoList( set ); }
static void remove_device( DEVICE_OBJECT *device ) { + struct wine_device *wine_device = CONTAINING_RECORD(device, struct wine_device, device_obj); + TRACE("Removing device %p.\n", device);
+ if (wine_device->children) + { + ULONG i; + for (i = 0; i < wine_device->children->Count; ++i) + remove_device( wine_device->children->Objects[i] ); + } + send_power_irp( device, PowerDeviceD3 ); send_pnp_irp( device, IRP_MN_SURPRISE_REMOVAL ); send_pnp_irp( device, IRP_MN_REMOVE_DEVICE ); }
+static BOOL device_in_list( const DEVICE_RELATIONS *list, const DEVICE_OBJECT *device ) +{ + ULONG i; + for (i = 0; i < list->Count; ++i) + { + if (list->Objects[i] == device) + return TRUE; + } + return FALSE; +} + +static void handle_bus_relations( DEVICE_OBJECT *parent ) +{ + struct wine_device *wine_parent = CONTAINING_RECORD(parent, struct wine_device, device_obj); + SP_DEVINFO_DATA sp_device = {sizeof(sp_device)}; + DEVICE_RELATIONS *relations; + IO_STATUS_BLOCK irp_status; + IO_STACK_LOCATION *irpsp; + NTSTATUS status; + HDEVINFO set; + IRP *irp; + ULONG i; + + TRACE( "(%p)\n", parent ); + + set = SetupDiCreateDeviceInfoList( NULL, NULL ); + + parent = IoGetAttachedDevice( parent ); + + if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, parent, NULL, 0, NULL, NULL, &irp_status ))) + { + SetupDiDestroyDeviceInfoList( set ); + return; + } + + irpsp = IoGetNextIrpStackLocation( irp ); + irpsp->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS; + irpsp->Parameters.QueryDeviceRelations.Type = BusRelations; + if ((status = send_device_irp( parent, irp, (ULONG_PTR *)&relations ))) + { + ERR("Failed to enumerate child devices, status %#x.\n", status); + SetupDiDestroyDeviceInfoList( set ); + return; + } + + TRACE("Got %u devices.\n", relations->Count); + + for (i = 0; i < relations->Count; ++i) + { + DEVICE_OBJECT *child = relations->Objects[i]; + + if (!wine_parent->children || !device_in_list( wine_parent->children, child )) + { + TRACE("Adding new device %p.\n", child); + enumerate_new_device( child, set ); + } + } + + ExFreePool( wine_parent->children ); + wine_parent->children = relations; + + SetupDiDestroyDeviceInfoList( set ); +} + /*********************************************************************** * IoInvalidateDeviceRelations (NTOSKRNL.EXE.@) */ diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h index de8ddf7ad9d..a2508784899 100644 --- a/dlls/winebus.sys/bus.h +++ b/dlls/winebus.sys/bus.h @@ -54,3 +54,4 @@ DWORD check_bus_option(const UNICODE_STRING *option, DWORD default_value) DECLSP BOOL is_xbox_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN;
HANDLE driver_key DECLSPEC_HIDDEN; +DEVICE_OBJECT *bus_pdo DECLSPEC_HIDDEN; diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index f0f10ca98e0..ad542b5dfbf 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -357,7 +357,7 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void * struct platform_private *private = impl_from_DEVICE_OBJECT(device); private->device = IOHIDDevice; private->buffer = NULL; - IoInvalidateDeviceRelations(device, BusRelations); + IoInvalidateDeviceRelations(bus_pdo, BusRelations); } }
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 64c5a8a1d2c..5f07ee24354 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -996,7 +996,7 @@ static void try_add_device(unsigned int index) HeapFree(GetProcessHeap(), 0, serial); return; } - IoInvalidateDeviceRelations(device, BusRelations); + IoInvalidateDeviceRelations(bus_pdo, BusRelations); } else { diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 6fa6efb7dce..b2cf62dedb0 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -1268,7 +1268,7 @@ static void try_add_device(struct udev_device *dev) return; } #endif - IoInvalidateDeviceRelations(device, BusRelations); + IoInvalidateDeviceRelations(bus_pdo, BusRelations); } else { diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index ec8e0f7f480..24ddb21c4ae 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -89,7 +89,8 @@ static DRIVER_OBJECT *driver_obj; static DEVICE_OBJECT *mouse_obj;
/* The root-enumerated device stack. */ -static DEVICE_OBJECT *bus_pdo, *bus_fdo; +DEVICE_OBJECT *bus_pdo; +static DEVICE_OBJECT *bus_fdo;
HANDLE driver_key;
@@ -560,7 +561,7 @@ static void mouse_device_create(void)
mouse_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, &wine_mouse_class, &mouse_vtbl, 0); - IoInvalidateDeviceRelations(mouse_obj, BusRelations); + IoInvalidateDeviceRelations(bus_pdo, BusRelations); }
static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) @@ -572,6 +573,9 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
switch (irpsp->MinorFunction) { + case IRP_MN_QUERY_DEVICE_RELATIONS: + irp->IoStatus.u.Status = handle_IRP_MN_QUERY_DEVICE_RELATIONS(irp); + break; case IRP_MN_START_DEVICE: mouse_device_create();
@@ -613,11 +617,6 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
switch (irpsp->MinorFunction) { - case IRP_MN_QUERY_DEVICE_RELATIONS: - TRACE("IRP_MN_QUERY_DEVICE_RELATIONS\n"); - status = handle_IRP_MN_QUERY_DEVICE_RELATIONS(irp); - irp->IoStatus.u.Status = status; - break; case IRP_MN_QUERY_ID: TRACE("IRP_MN_QUERY_ID\n"); status = handle_IRP_MN_QUERY_ID(device, irp);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/pnp.c | 18 +++++++++++++++--- dlls/winebus.sys/bus_iohid.c | 2 +- dlls/winebus.sys/bus_sdl.c | 2 +- dlls/winebus.sys/bus_udev.c | 2 +- 4 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index 62a32a4afc4..863eee390f1 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -435,6 +435,21 @@ static void handle_bus_relations( DEVICE_OBJECT *parent ) } }
+ if (wine_parent->children) + { + for (i = 0; i < wine_parent->children->Count; ++i) + { + DEVICE_OBJECT *child = wine_parent->children->Objects[i]; + + if (!device_in_list( relations, child )) + { + TRACE("Removing device %p.\n", child); + remove_device( child ); + } + ObDereferenceObject( child ); + } + } + ExFreePool( wine_parent->children ); wine_parent->children = relations;
@@ -453,9 +468,6 @@ void WINAPI IoInvalidateDeviceRelations( DEVICE_OBJECT *device_object, DEVICE_RE case BusRelations: handle_bus_relations( device_object ); break; - case RemovalRelations: - remove_device( device_object ); - break; default: FIXME("Unhandled relation %#x.\n", type); break; diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index ad542b5dfbf..c6aa003ffcf 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -371,7 +371,7 @@ static void handle_RemovalCallback(void *context, IOReturn result, void *sender, device = bus_find_hid_device(&iohid_vtbl, IOHIDDevice); if (device) { - IoInvalidateDeviceRelations(device, RemovalRelations); + IoInvalidateDeviceRelations(bus_pdo, BusRelations); bus_remove_hid_device(device); } } diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 5f07ee24354..322e09be793 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -902,7 +902,7 @@ static void try_remove_device(SDL_JoystickID id) sdl_controller = private->sdl_controller; sdl_haptic = private->sdl_haptic;
- IoInvalidateDeviceRelations(device, RemovalRelations); + IoInvalidateDeviceRelations(bus_pdo, BusRelations);
bus_remove_hid_device(device);
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index b2cf62dedb0..5e0b5c51519 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -1297,7 +1297,7 @@ static void try_remove_device(struct udev_device *dev) #endif if (!device) return;
- IoInvalidateDeviceRelations(device, RemovalRelations); + IoInvalidateDeviceRelations(bus_pdo, BusRelations);
private = impl_from_DEVICE_OBJECT(device);
ntoskrnl.exe handles this now.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winebus.sys/Makefile.in | 2 +- dlls/winebus.sys/bus.h | 2 +- dlls/winebus.sys/bus_iohid.c | 5 +--- dlls/winebus.sys/bus_sdl.c | 8 ++---- dlls/winebus.sys/bus_udev.c | 8 ++---- dlls/winebus.sys/main.c | 56 +++--------------------------------- 6 files changed, 11 insertions(+), 70 deletions(-)
diff --git a/dlls/winebus.sys/Makefile.in b/dlls/winebus.sys/Makefile.in index 78e3da1b9c6..3bdc1a5d58a 100644 --- a/dlls/winebus.sys/Makefile.in +++ b/dlls/winebus.sys/Makefile.in @@ -1,5 +1,5 @@ MODULE = winebus.sys -IMPORTS = ntoskrnl setupapi advapi32 +IMPORTS = ntoskrnl advapi32 EXTRALIBS = $(IOKIT_LIBS) $(UDEV_LIBS) EXTRAINCL = $(UDEV_CFLAGS) $(SDL2_CFLAGS) EXTRADLLFLAGS = -Wl,--subsystem,native diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h index a2508784899..09666dc151f 100644 --- a/dlls/winebus.sys/bus.h +++ b/dlls/winebus.sys/bus.h @@ -43,7 +43,7 @@ void *get_platform_private(DEVICE_OBJECT *device) DECLSPEC_HIDDEN; /* HID Plug and Play Bus */ DEVICE_OBJECT *bus_create_hid_device(const WCHAR *busidW, WORD vid, WORD pid, WORD input, DWORD version, DWORD uid, const WCHAR *serialW, BOOL is_gamepad, - const GUID *class, const platform_vtbl *vtbl, DWORD platform_data_size) DECLSPEC_HIDDEN; + const platform_vtbl *vtbl, DWORD platform_data_size) DECLSPEC_HIDDEN; DEVICE_OBJECT *bus_find_hid_device(const platform_vtbl *vtbl, void *platform_dev) DECLSPEC_HIDDEN; void bus_remove_hid_device(DEVICE_OBJECT *device) DECLSPEC_HIDDEN; void process_hid_report(DEVICE_OBJECT *device, BYTE *report, DWORD length) DECLSPEC_HIDDEN; diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index c6aa003ffcf..ed91b51fc8c 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -102,9 +102,6 @@ static HANDLE run_loop_handle;
static const WCHAR busidW[] = {'I','O','H','I','D',0};
-#include "initguid.h" -DEFINE_GUID(GUID_DEVCLASS_IOHID, 0x989D309D,0x0470,0x4E1A,0x89,0x38,0x50,0x1F,0x42,0xBD,0x9A,0xCD); - struct platform_private { IOHIDDeviceRef device; @@ -348,7 +345,7 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void * input = 0;
device = bus_create_hid_device(busidW, vid, pid, input, - version, uid, str?serial_string:NULL, is_gamepad, &GUID_DEVCLASS_IOHID, + version, uid, str ? serial_string : NULL, is_gamepad, &iohid_vtbl, sizeof(struct platform_private)); if (!device) ERR("Failed to create device\n"); diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 322e09be793..61651c92f60 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -66,9 +66,6 @@ static const WCHAR sdl_busidW[] = {'S','D','L','J','O','Y',0};
static DWORD map_controllers = 0;
-#include "initguid.h" -DEFINE_GUID(GUID_DEVCLASS_SDL, 0x463d60b5,0x802b,0x4bb2,0x8f,0xdb,0x7d,0xa9,0xb9,0x96,0x04,0xd8); - static void *sdl_handle = NULL; static HANDLE deviceloop_handle; static UINT quit_event = -1; @@ -974,9 +971,8 @@ static void try_add_device(unsigned int index) if (is_xbox_gamepad) input = 0;
- device = bus_create_hid_device(sdl_busidW, vid, pid, - input, version, index, serial, is_xbox_gamepad, &GUID_DEVCLASS_SDL, - &sdl_vtbl, sizeof(struct platform_private)); + device = bus_create_hid_device(sdl_busidW, vid, pid, input, version, index, + serial, is_xbox_gamepad, &sdl_vtbl, sizeof(struct platform_private));
if (device) { diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 5e0b5c51519..239051723ce 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -98,10 +98,6 @@ static int deviceloop_control[2]; static const WCHAR hidraw_busidW[] = {'H','I','D','R','A','W',0}; static const WCHAR lnxev_busidW[] = {'L','N','X','E','V',0};
-#include "initguid.h" -DEFINE_GUID(GUID_DEVCLASS_HIDRAW, 0x3def44ad,0x242e,0x46e5,0x82,0x6d,0x70,0x72,0x13,0xf3,0xaa,0x81); -DEFINE_GUID(GUID_DEVCLASS_LINUXEVENT, 0x1b932c0d,0xfea7,0x42cd,0x8e,0xaa,0x0e,0x48,0x79,0xb6,0x9e,0xaa); - struct platform_private { struct udev_device *udev_device; @@ -1241,13 +1237,13 @@ static void try_add_device(struct udev_device *dev) if (strcmp(subsystem, "hidraw") == 0) { device = bus_create_hid_device(hidraw_busidW, vid, pid, input, version, 0, serial, is_gamepad, - &GUID_DEVCLASS_HIDRAW, &hidraw_vtbl, sizeof(struct platform_private)); + &hidraw_vtbl, sizeof(struct platform_private)); } #ifdef HAS_PROPER_INPUT_HEADER else if (strcmp(subsystem, "input") == 0) { device = bus_create_hid_device(lnxev_busidW, vid, pid, input, version, 0, serial, is_gamepad, - &GUID_DEVCLASS_LINUXEVENT, &lnxev_vtbl, sizeof(struct wine_input_private)); + &lnxev_vtbl, sizeof(struct wine_input_private)); } #endif
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 24ddb21c4ae..b4599b68894 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -25,13 +25,7 @@
#include "ntstatus.h" #define WIN32_NO_STATUS -#include "windef.h" -#include "winbase.h" -#include "winuser.h" #include "winternl.h" -#include "winreg.h" -#include "setupapi.h" -#include "cfgmgr32.h" #include "winioctl.h" #include "hidusage.h" #include "ddk/wdm.h" @@ -47,8 +41,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(plugplay); WINE_DECLARE_DEBUG_CHANNEL(hid_report);
-static const WCHAR backslashW[] = {'\',0}; - struct product_desc { WORD vid; @@ -223,23 +215,20 @@ static WCHAR *get_compatible_ids(DEVICE_OBJECT *device)
DEVICE_OBJECT *bus_create_hid_device(const WCHAR *busidW, WORD vid, WORD pid, WORD input, DWORD version, DWORD uid, const WCHAR *serialW, BOOL is_gamepad, - const GUID *class, const platform_vtbl *vtbl, DWORD platform_data_size) + const platform_vtbl *vtbl, DWORD platform_data_size) { static const WCHAR device_name_fmtW[] = {'\','D','e','v','i','c','e','\','%','s','#','%','p',0}; - WCHAR *id, instance[MAX_DEVICE_ID_LEN]; struct device_extension *ext; struct pnp_device *pnp_dev; DEVICE_OBJECT *device; UNICODE_STRING nameW; WCHAR dev_name[256]; - HDEVINFO devinfo; - SP_DEVINFO_DATA data = {sizeof(data)}; NTSTATUS status; DWORD length;
- TRACE("(%s, %04x, %04x, %04x, %u, %u, %s, %u, %s, %p, %u)\n", + TRACE("(%s, %04x, %04x, %04x, %u, %u, %s, %u, %p, %u)\n", debugstr_w(busidW), vid, pid, input, version, uid, debugstr_w(serialW), - is_gamepad, debugstr_guid(class), vtbl, platform_data_size); + is_gamepad, vtbl, platform_data_size);
if (!(pnp_dev = HeapAlloc(GetProcessHeap(), 0, sizeof(*pnp_dev)))) return NULL; @@ -286,41 +275,6 @@ DEVICE_OBJECT *bus_create_hid_device(const WCHAR *busidW, WORD vid, WORD pid, list_add_tail(&pnp_devset, &pnp_dev->entry);
LeaveCriticalSection(&device_list_cs); - - devinfo = SetupDiCreateDeviceInfoList(class, NULL); - if (devinfo == INVALID_HANDLE_VALUE) - { - ERR("failed to create device info list, error %#x\n", GetLastError()); - goto error; - } - - if (!(id = get_device_id(device))) - { - ERR("failed to generate instance id\n"); - goto error; - } - strcpyW(instance, id); - ExFreePool(id); - - if (!(id = get_instance_id(device))) - { - ERR("failed to generate instance id\n"); - goto error; - } - strcatW(instance, backslashW); - strcatW(instance, id); - ExFreePool(id); - - if (SetupDiCreateDeviceInfoW(devinfo, instance, class, NULL, NULL, DICD_INHERIT_CLASSDRVS, &data)) - { - if (!SetupDiRegisterDeviceInfo(devinfo, &data, 0, NULL, NULL, NULL)) - ERR("failed to register device info, error %#x\n", GetLastError()); - } - else if (GetLastError() != ERROR_DEVINST_ALREADY_EXISTS) - ERR("failed to create device info, error %#x\n", GetLastError()); - -error: - SetupDiDestroyDeviceInfoList(devinfo); return device; }
@@ -556,11 +510,9 @@ static const platform_vtbl mouse_vtbl =
static void mouse_device_create(void) { - static const GUID wine_mouse_class = {0xdfe2580e,0x52fd,0x453d,{0xa2,0xc1,0x33,0x81,0xf2,0x32,0x68,0x4c}}; static const WCHAR busidW[] = {'W','I','N','E','M','O','U','S','E',0};
- mouse_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, - &wine_mouse_class, &mouse_vtbl, 0); + mouse_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, &mouse_vtbl, 0); IoInvalidateDeviceRelations(bus_pdo, BusRelations); }