Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winebus.sys/main.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 8d3dec4779a..7d3f5064f84 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -112,6 +112,8 @@ struct pnp_device
struct device_extension { + CRITICAL_SECTION cs; + struct pnp_device *pnp_device;
WORD vid, pid, input; @@ -127,7 +129,6 @@ struct device_extension BOOL last_report_read; DWORD buffer_size; LIST_ENTRY irp_queue; - CRITICAL_SECTION report_cs;
BYTE platform_private[1]; }; @@ -285,8 +286,8 @@ DEVICE_OBJECT *bus_create_hid_device(const WCHAR *busidW, WORD vid, WORD pid, memset(ext->platform_private, 0, platform_data_size);
InitializeListHead(&ext->irp_queue); - InitializeCriticalSection(&ext->report_cs); - ext->report_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": report_cs"); + InitializeCriticalSection(&ext->cs); + ext->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs");
/* add to list of pnp devices */ pnp_dev->device = device; @@ -366,7 +367,7 @@ void bus_remove_hid_device(DEVICE_OBJECT *device) TRACE("(%p)\n", device);
/* Cancel pending IRPs */ - EnterCriticalSection(&ext->report_cs); + EnterCriticalSection(&ext->cs); while ((entry = RemoveHeadList(&ext->irp_queue)) != &ext->irp_queue) { irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry); @@ -374,10 +375,10 @@ void bus_remove_hid_device(DEVICE_OBJECT *device) irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); } - LeaveCriticalSection(&ext->report_cs); + LeaveCriticalSection(&ext->cs);
- ext->report_cs.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&ext->report_cs); + ext->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&ext->cs);
HeapFree(GetProcessHeap(), 0, ext->serial); HeapFree(GetProcessHeap(), 0, ext->last_report); @@ -783,12 +784,12 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) { HID_XFER_PACKET *packet = (HID_XFER_PACKET*)(irp->UserBuffer); TRACE_(hid_report)("IOCTL_HID_GET_INPUT_REPORT\n"); - EnterCriticalSection(&ext->report_cs); + EnterCriticalSection(&ext->cs); status = ext->vtbl->begin_report_processing(device); if (status != STATUS_SUCCESS) { irp->IoStatus.u.Status = status; - LeaveCriticalSection(&ext->report_cs); + LeaveCriticalSection(&ext->cs); break; }
@@ -798,18 +799,18 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp)
if (status == STATUS_SUCCESS) packet->reportBufferLen = irp->IoStatus.Information; - LeaveCriticalSection(&ext->report_cs); + LeaveCriticalSection(&ext->cs); break; } case IOCTL_HID_READ_REPORT: { TRACE_(hid_report)("IOCTL_HID_READ_REPORT\n"); - EnterCriticalSection(&ext->report_cs); + EnterCriticalSection(&ext->cs); status = ext->vtbl->begin_report_processing(device); if (status != STATUS_SUCCESS) { irp->IoStatus.u.Status = status; - LeaveCriticalSection(&ext->report_cs); + LeaveCriticalSection(&ext->cs); break; } if (!ext->last_report_read) @@ -824,7 +825,7 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) InsertTailList(&ext->irp_queue, &irp->Tail.Overlay.s.ListEntry); status = STATUS_PENDING; } - LeaveCriticalSection(&ext->report_cs); + LeaveCriticalSection(&ext->cs); break; } case IOCTL_HID_SET_OUTPUT_REPORT: @@ -880,7 +881,7 @@ void process_hid_report(DEVICE_OBJECT *device, BYTE *report, DWORD length) if (!length || !report) return;
- EnterCriticalSection(&ext->report_cs); + EnterCriticalSection(&ext->cs); if (length > ext->buffer_size) { HeapFree(GetProcessHeap(), 0, ext->last_report); @@ -891,7 +892,7 @@ void process_hid_report(DEVICE_OBJECT *device, BYTE *report, DWORD length) ext->buffer_size = 0; ext->last_report_size = 0; ext->last_report_read = TRUE; - LeaveCriticalSection(&ext->report_cs); + LeaveCriticalSection(&ext->cs); return; } else @@ -914,7 +915,7 @@ void process_hid_report(DEVICE_OBJECT *device, BYTE *report, DWORD length) ext->last_report_read = TRUE; IoCompleteRequest(irp, IO_NO_INCREMENT); } - LeaveCriticalSection(&ext->report_cs); + LeaveCriticalSection(&ext->cs); }
DWORD check_bus_option(const UNICODE_STRING *option, DWORD default_value)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winebus.sys/bus.h | 1 + dlls/winebus.sys/bus_iohid.c | 5 ++ dlls/winebus.sys/bus_sdl.c | 27 +++++------ dlls/winebus.sys/bus_udev.c | 88 ++++++++++++++++-------------------- dlls/winebus.sys/main.c | 7 +++ 5 files changed, 65 insertions(+), 63 deletions(-)
diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h index 22a4b46a516..a157f576ef9 100644 --- a/dlls/winebus.sys/bus.h +++ b/dlls/winebus.sys/bus.h @@ -29,6 +29,7 @@ void sdl_driver_unload( void ) DECLSPEC_HIDDEN; /* Native device function table */ typedef struct { + void (*free_device)(DEVICE_OBJECT *device); int (*compare_platform_device)(DEVICE_OBJECT *device, void *platform_dev); NTSTATUS (*get_reportdescriptor)(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *out_length); NTSTATUS (*get_string)(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length); diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index ee6225bf398..c275011b491 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -136,6 +136,10 @@ static void handle_IOHIDDeviceIOHIDReportCallback(void *context, process_hid_report(device, report, report_length); }
+static void free_device(DEVICE_OBJECT *device) +{ +} + static int compare_platform_device(DEVICE_OBJECT *device, void *platform_dev) { struct platform_private *private = impl_from_DEVICE_OBJECT(device); @@ -270,6 +274,7 @@ static NTSTATUS set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report
static const platform_vtbl iohid_vtbl = { + free_device, compare_platform_device, get_reportdescriptor, get_string, diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index bf62f448976..154c0fb19a3 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -605,6 +605,17 @@ static BOOL build_mapped_report_descriptor(struct platform_private *ext) return TRUE; }
+static void free_device(DEVICE_OBJECT *device) +{ + struct platform_private *ext = impl_from_DEVICE_OBJECT(device); + + pSDL_JoystickClose(ext->sdl_joystick); + if (ext->sdl_controller) + pSDL_GameControllerClose(ext->sdl_controller); + if (ext->sdl_haptic) + pSDL_HapticClose(ext->sdl_haptic); +} + static int compare_platform_device(DEVICE_OBJECT *device, void *platform_dev) { SDL_JoystickID id1 = impl_from_DEVICE_OBJECT(device)->id; @@ -722,6 +733,7 @@ static NTSTATUS set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report
static const platform_vtbl sdl_vtbl = { + free_device, compare_platform_device, get_reportdescriptor, get_string, @@ -872,29 +884,14 @@ static BOOL set_mapped_report_from_event(SDL_Event *event) static void try_remove_device(SDL_JoystickID id) { DEVICE_OBJECT *device = NULL; - struct platform_private *private; - SDL_Joystick *sdl_joystick; - SDL_GameController *sdl_controller; - SDL_Haptic *sdl_haptic;
device = bus_enumerate_hid_devices(&sdl_vtbl, compare_joystick_id, ULongToPtr(id)); if (!device) return;
- private = impl_from_DEVICE_OBJECT(device); - sdl_joystick = private->sdl_joystick; - sdl_controller = private->sdl_controller; - sdl_haptic = private->sdl_haptic; - bus_unlink_hid_device(device); IoInvalidateDeviceRelations(bus_pdo, BusRelations);
bus_remove_hid_device(device); - - pSDL_JoystickClose(sdl_joystick); - if (sdl_controller) - pSDL_GameControllerClose(sdl_controller); - if (sdl_haptic) - pSDL_HapticClose(sdl_haptic); }
static void try_add_device(unsigned int index) diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 74cf6a28a1a..c717c13a7db 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -653,6 +653,23 @@ static WCHAR *get_sysattr_string(struct udev_device *dev, const char *sysattr) return strdupAtoW(attr); }
+static void hidraw_free_device(DEVICE_OBJECT *device) +{ + struct platform_private *private = impl_from_DEVICE_OBJECT(device); + + if (private->report_thread) + { + write(private->control_pipe[1], "q", 1); + WaitForSingleObject(private->report_thread, INFINITE); + close(private->control_pipe[0]); + close(private->control_pipe[1]); + CloseHandle(private->report_thread); + } + + close(private->device_fd); + udev_device_unref(private->udev_device); +} + static int compare_platform_device(DEVICE_OBJECT *device, void *platform_dev) { struct udev_device *dev1 = impl_from_DEVICE_OBJECT(device)->udev_device; @@ -921,6 +938,7 @@ static NTSTATUS hidraw_set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE
static const platform_vtbl hidraw_vtbl = { + hidraw_free_device, compare_platform_device, hidraw_get_reportdescriptor, hidraw_get_string, @@ -937,6 +955,27 @@ static inline struct wine_input_private *input_impl_from_DEVICE_OBJECT(DEVICE_OB return (struct wine_input_private*)get_platform_private(device); }
+static void lnxev_free_device(DEVICE_OBJECT *device) +{ + struct wine_input_private *ext = input_impl_from_DEVICE_OBJECT(device); + + if (ext->base.report_thread) + { + write(ext->base.control_pipe[1], "q", 1); + WaitForSingleObject(ext->base.report_thread, INFINITE); + close(ext->base.control_pipe[0]); + close(ext->base.control_pipe[1]); + CloseHandle(ext->base.report_thread); + } + + HeapFree(GetProcessHeap(), 0, ext->current_report_buffer); + HeapFree(GetProcessHeap(), 0, ext->last_report_buffer); + HeapFree(GetProcessHeap(), 0, ext->report_descriptor); + + close(ext->base.device_fd); + udev_device_unref(ext->base.udev_device); +} + static NTSTATUS lnxev_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *out_length) { struct wine_input_private *ext = input_impl_from_DEVICE_OBJECT(device); @@ -1051,6 +1090,7 @@ static NTSTATUS lnxev_set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE * }
static const platform_vtbl lnxev_vtbl = { + lnxev_free_device, compare_platform_device, lnxev_get_reportdescriptor, lnxev_get_string, @@ -1285,54 +1325,17 @@ static void try_add_device(struct udev_device *dev) static void try_remove_device(struct udev_device *dev) { DEVICE_OBJECT *device = NULL; - struct platform_private* private; -#ifdef HAS_PROPER_INPUT_HEADER - BOOL is_input = FALSE; -#endif
device = bus_find_hid_device(&hidraw_vtbl, dev); #ifdef HAS_PROPER_INPUT_HEADER if (device == NULL) - { device = bus_find_hid_device(&lnxev_vtbl, dev); - is_input = TRUE; - } #endif if (!device) return;
bus_unlink_hid_device(device); IoInvalidateDeviceRelations(bus_pdo, BusRelations); - - private = impl_from_DEVICE_OBJECT(device); - - if (private->report_thread) - { - write(private->control_pipe[1], "q", 1); - WaitForSingleObject(private->report_thread, INFINITE); - close(private->control_pipe[0]); - close(private->control_pipe[1]); - CloseHandle(private->report_thread); -#ifdef HAS_PROPER_INPUT_HEADER - if (strcmp(udev_device_get_subsystem(dev), "input") == 0) - { - HeapFree(GetProcessHeap(), 0, ((struct wine_input_private*)private)->current_report_buffer); - HeapFree(GetProcessHeap(), 0, ((struct wine_input_private*)private)->last_report_buffer); - } -#endif - } - -#ifdef HAS_PROPER_INPUT_HEADER - if (is_input) - { - struct wine_input_private *ext = (struct wine_input_private*)private; - HeapFree(GetProcessHeap(), 0, ext->report_descriptor); - } -#endif - - dev = private->udev_device; - close(private->device_fd); bus_remove_hid_device(device); - udev_device_unref(dev); }
static void build_initial_deviceset(void) @@ -1482,12 +1485,6 @@ static DWORD CALLBACK deviceloop_thread(void *args) return 0; }
-static int device_unload(DEVICE_OBJECT *device, void *context) -{ - try_remove_device(impl_from_DEVICE_OBJECT(device)->udev_device); - return 1; -} - void udev_driver_unload( void ) { TRACE("Unload Driver\n"); @@ -1500,11 +1497,6 @@ void udev_driver_unload( void ) close(deviceloop_control[0]); close(deviceloop_control[1]); CloseHandle(deviceloop_handle); - - bus_enumerate_hid_devices(&hidraw_vtbl, device_unload, NULL); -#ifdef HAS_PROPER_INPUT_HEADER - bus_enumerate_hid_devices(&lnxev_vtbl, device_unload, NULL); -#endif }
NTSTATUS udev_driver_init(void) diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 7d3f5064f84..f184945779d 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -377,6 +377,8 @@ void bus_remove_hid_device(DEVICE_OBJECT *device) } LeaveCriticalSection(&ext->cs);
+ ext->vtbl->free_device(device); + ext->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&ext->cs);
@@ -474,6 +476,10 @@ static NTSTATUS handle_IRP_MN_QUERY_ID(DEVICE_OBJECT *device, IRP *irp) return status; }
+static void mouse_free_device(DEVICE_OBJECT *device) +{ +} + static NTSTATUS mouse_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *ret_length) { TRACE("buffer %p, length %u.\n", buffer, length); @@ -526,6 +532,7 @@ static NTSTATUS mouse_set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *
static const platform_vtbl mouse_vtbl = { + .free_device = mouse_free_device, .get_reportdescriptor = mouse_get_reportdescriptor, .get_string = mouse_get_string, .begin_report_processing = mouse_begin_report_processing,
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winebus.sys/main.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index f184945779d..598cd2483fa 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -114,6 +114,8 @@ struct device_extension { CRITICAL_SECTION cs;
+ BOOL removed; + struct pnp_device *pnp_device;
WORD vid, pid, input; @@ -355,6 +357,10 @@ void bus_unlink_hid_device(DEVICE_OBJECT *device) EnterCriticalSection(&device_list_cs); list_remove(&pnp_device->entry); LeaveCriticalSection(&device_list_cs); + + EnterCriticalSection(&ext->cs); + ext->removed = TRUE; + LeaveCriticalSection(&ext->cs); }
void bus_remove_hid_device(DEVICE_OBJECT *device) @@ -709,6 +715,16 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) return IoCallDriver(bus_pdo, irp); }
+ EnterCriticalSection(&ext->cs); + + if (ext->removed) + { + LeaveCriticalSection(&ext->cs); + irp->IoStatus.u.Status = STATUS_DELETE_PENDING; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_DELETE_PENDING; + } + switch (irpsp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_HID_GET_DEVICE_ATTRIBUTES: @@ -791,7 +807,6 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) { HID_XFER_PACKET *packet = (HID_XFER_PACKET*)(irp->UserBuffer); TRACE_(hid_report)("IOCTL_HID_GET_INPUT_REPORT\n"); - EnterCriticalSection(&ext->cs); status = ext->vtbl->begin_report_processing(device); if (status != STATUS_SUCCESS) { @@ -806,13 +821,11 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp)
if (status == STATUS_SUCCESS) packet->reportBufferLen = irp->IoStatus.Information; - LeaveCriticalSection(&ext->cs); break; } case IOCTL_HID_READ_REPORT: { TRACE_(hid_report)("IOCTL_HID_READ_REPORT\n"); - EnterCriticalSection(&ext->cs); status = ext->vtbl->begin_report_processing(device); if (status != STATUS_SUCCESS) { @@ -832,7 +845,6 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) InsertTailList(&ext->irp_queue, &irp->Tail.Overlay.s.ListEntry); status = STATUS_PENDING; } - LeaveCriticalSection(&ext->cs); break; } case IOCTL_HID_SET_OUTPUT_REPORT: @@ -873,6 +885,8 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) } }
+ LeaveCriticalSection(&ext->cs); + if (status != STATUS_PENDING) IoCompleteRequest(irp, IO_NO_INCREMENT);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winebus.sys/bus_iohid.c | 1 - dlls/winebus.sys/bus_sdl.c | 4 +-- dlls/winebus.sys/bus_udev.c | 2 +- dlls/winebus.sys/main.c | 56 +++++++++++++++++++++++++----------- 4 files changed, 42 insertions(+), 21 deletions(-)
diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index c275011b491..0123e73f7ba 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -384,7 +384,6 @@ static void handle_RemovalCallback(void *context, IOReturn result, void *sender, { bus_unlink_hid_device(device); 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 154c0fb19a3..779a1af2736 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -890,8 +890,6 @@ static void try_remove_device(SDL_JoystickID id)
bus_unlink_hid_device(device); IoInvalidateDeviceRelations(bus_pdo, BusRelations); - - bus_remove_hid_device(device); }
static void try_add_device(unsigned int index) @@ -965,6 +963,8 @@ static void try_add_device(unsigned int index) private->sdl_joystick = joystick; private->sdl_controller = controller; private->id = id; + + /* FIXME: We should probably move this to IRP_MN_START_DEVICE. */ if (controller) rc = build_mapped_report_descriptor(private); else diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index c717c13a7db..0c150322006 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -1300,6 +1300,7 @@ static void try_add_device(struct udev_device *dev) private->device_fd = fd; #ifdef HAS_PROPER_INPUT_HEADER if (strcmp(subsystem, "input") == 0) + /* FIXME: We should probably move this to IRP_MN_START_DEVICE. */ if (!build_report_descriptor((struct wine_input_private*)private, dev)) { ERR("Building report descriptor failed, removing device\n"); @@ -1335,7 +1336,6 @@ static void try_remove_device(struct udev_device *dev)
bus_unlink_hid_device(device); IoInvalidateDeviceRelations(bus_pdo, BusRelations); - bus_remove_hid_device(device); }
static void build_initial_deviceset(void) diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 598cd2483fa..01e839f02d8 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -367,24 +367,9 @@ void bus_remove_hid_device(DEVICE_OBJECT *device) { struct device_extension *ext = (struct device_extension *)device->DeviceExtension; struct pnp_device *pnp_device = ext->pnp_device; - LIST_ENTRY *entry; - IRP *irp;
TRACE("(%p)\n", device);
- /* Cancel pending IRPs */ - EnterCriticalSection(&ext->cs); - while ((entry = RemoveHeadList(&ext->irp_queue)) != &ext->irp_queue) - { - irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry); - irp->IoStatus.u.Status = STATUS_DELETE_PENDING; - irp->IoStatus.Information = 0; - IoCompleteRequest(irp, IO_NO_INCREMENT); - } - LeaveCriticalSection(&ext->cs); - - ext->vtbl->free_device(device); - ext->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&ext->cs);
@@ -606,19 +591,56 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) { + struct device_extension *ext = device->DeviceExtension; NTSTATUS status = irp->IoStatus.u.Status; IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
+ TRACE("device %p, irp %p, minor function %#x.\n", device, irp, irpsp->MinorFunction); + switch (irpsp->MinorFunction) { case IRP_MN_QUERY_ID: - TRACE("IRP_MN_QUERY_ID\n"); status = handle_IRP_MN_QUERY_ID(device, irp); break; + case IRP_MN_QUERY_CAPABILITIES: - TRACE("IRP_MN_QUERY_CAPABILITIES\n"); status = STATUS_SUCCESS; break; + + case IRP_MN_REMOVE_DEVICE: + { + struct pnp_device *pnp_device = ext->pnp_device; + LIST_ENTRY *entry; + + EnterCriticalSection(&ext->cs); + while ((entry = RemoveHeadList(&ext->irp_queue)) != &ext->irp_queue) + { + IRP *queued_irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry); + queued_irp->IoStatus.u.Status = STATUS_DELETE_PENDING; + queued_irp->IoStatus.Information = 0; + IoCompleteRequest(queued_irp, IO_NO_INCREMENT); + } + LeaveCriticalSection(&ext->cs); + + ext->vtbl->free_device(device); + + ext->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&ext->cs); + + HeapFree(GetProcessHeap(), 0, ext->serial); + HeapFree(GetProcessHeap(), 0, ext->last_report); + + irp->IoStatus.u.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + + IoDeleteDevice(device); + + /* pnp_device must be released after the device is gone */ + HeapFree(GetProcessHeap(), 0, pnp_device); + + return STATUS_SUCCESS; + } + default: FIXME("Unhandled function %08x\n", irpsp->MinorFunction); break;
Doing otherwise may result in memory corruption. The lower driver should complete its IRPs on device removal anyway.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/hidclass.sys/device.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index fc1dfd07db1..6ca5e39e648 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -288,12 +288,11 @@ static DWORD CALLBACK hid_device_thread(void *args) IO_STATUS_BLOCK irp_status; HID_XFER_PACKET *packet; DWORD rc; - HANDLE events[2]; + HANDLE event; NTSTATUS ntrc;
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - events[0] = CreateEventA(NULL, TRUE, FALSE, NULL); - events[1] = ext->halt_event; + event = CreateEventA(NULL, TRUE, FALSE, NULL);
packet = HeapAlloc(GetProcessHeap(), 0, sizeof(*packet) + ext->preparseData->caps.InputReportByteLength); packet->reportBuffer = (BYTE *)packet + sizeof(*packet); @@ -302,7 +301,7 @@ static DWORD CALLBACK hid_device_thread(void *args) { while(1) { - ResetEvent(events[0]); + ResetEvent(event);
packet->reportBufferLen = ext->preparseData->caps.InputReportByteLength; packet->reportId = 0; @@ -311,11 +310,11 @@ static DWORD CALLBACK hid_device_thread(void *args) device, NULL, 0, packet, sizeof(*packet), TRUE, NULL, &irp_status);
- IoSetCompletionRoutine(irp, read_Completion, events[0], TRUE, TRUE, TRUE); + IoSetCompletionRoutine(irp, read_Completion, event, TRUE, TRUE, TRUE); ntrc = IoCallDriver(device, irp);
if (ntrc == STATUS_PENDING) - WaitForMultipleObjects(2, events, FALSE, INFINITE); + WaitForSingleObject(event, INFINITE);
if (irp->IoStatus.u.Status == STATUS_SUCCESS) { @@ -339,19 +338,19 @@ static DWORD CALLBACK hid_device_thread(void *args)
while(1) { - ResetEvent(events[0]); + ResetEvent(event);
irp = IoBuildDeviceIoControlRequest(IOCTL_HID_READ_REPORT, device, NULL, 0, packet->reportBuffer, ext->preparseData->caps.InputReportByteLength, TRUE, NULL, &irp_status);
- IoSetCompletionRoutine(irp, read_Completion, events[0], TRUE, TRUE, TRUE); + IoSetCompletionRoutine(irp, read_Completion, event, TRUE, TRUE, TRUE); ntrc = IoCallDriver(device, irp);
if (ntrc == STATUS_PENDING) { - WaitForMultipleObjects(2, events, FALSE, INFINITE); + WaitForSingleObject(event, INFINITE); }
rc = WaitForSingleObject(ext->halt_event, 0); @@ -376,8 +375,7 @@ static DWORD CALLBACK hid_device_thread(void *args) } }
- /* FIXME: releasing packet requires IRP cancellation support */ - CloseHandle(events[0]); + CloseHandle(event);
TRACE("Device thread exiting\n"); return 1;