[PATCH 0/11] MR6610: ntoskrnl: Implement IoReportTargetDeviceChange.
From: Vibhav Pant <vibhavp(a)gmail.com> --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 4 ++-- dlls/ntoskrnl.exe/pnp.c | 19 +++++++++++++++++++ include/ddk/wdm.h | 13 +++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index e9ad2aa7e74..3b29e0b9e12 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -465,8 +465,8 @@ @ stub IoReportHalResourceUsage @ stdcall IoReportResourceForDetection(ptr ptr long ptr ptr long ptr) @ stdcall IoReportResourceUsage(ptr ptr ptr long ptr ptr long long ptr) -@ stub IoReportTargetDeviceChange -@ stub IoReportTargetDeviceChangeAsynchronous +@ stdcall IoReportTargetDeviceChange(ptr ptr) +@ stdcall IoReportTargetDeviceChangeAsynchronous(ptr ptr ptr ptr) @ stub IoRequestDeviceEject @ stdcall IoReuseIrp(ptr long) @ stub IoSetCompletionRoutineEx diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index cbd5cf6ff2a..9d91160c46d 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -1001,6 +1001,25 @@ NTSTATUS WINAPI IoRegisterDeviceInterface(DEVICE_OBJECT *device, const GUID *cla return status; } +/*********************************************************************** + * IoReportTargetDeviceChange (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI IoReportTargetDeviceChange( DEVICE_OBJECT *device, void *data ) +{ + FIXME( "(%p, %p) stub!\n", device, data ); + return STATUS_NOT_SUPPORTED; +} + +/*********************************************************************** + * IoReportTargetDeviceChangeAsynchronous (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI IoReportTargetDeviceChangeAsynchronous( DEVICE_OBJECT *device, void *data, PDEVICE_CHANGE_COMPLETE_CALLBACK callback, + void *context ) +{ + FIXME( "(%p, %p, %p, %p) stub!\n", device, data, callback, context ); + return STATUS_NOT_SUPPORTED; +} + /*********************************************************************** * IoOpenDeviceRegistryKey (NTOSKRNL.EXE.@) */ diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index e0c21d0ccfd..d33ee248ee8 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -63,6 +63,7 @@ typedef NTSTATUS (WINAPI *PDRIVER_DISPATCH)(struct _DEVICE_OBJECT *, struct _IRP typedef void (WINAPI *PDRIVER_STARTIO)(struct _DEVICE_OBJECT *, struct _IRP *); typedef void (WINAPI *PDRIVER_UNLOAD)(struct _DRIVER_OBJECT *); typedef NTSTATUS (WINAPI *PDRIVER_ADD_DEVICE)(struct _DRIVER_OBJECT *, struct _DEVICE_OBJECT *); +typedef void (WINAPI *PDEVICE_CHANGE_COMPLETE_CALLBACK)(void*); typedef struct _DISPATCHER_HEADER { UCHAR Type; @@ -1613,6 +1614,16 @@ typedef enum _DIRECTORY_NOTIFY_INFORMATION_CLASS { DirectoryNotifyExtendedInformation } DIRECTORY_NOTIFY_INFORMATION_CLASS, *PDIRECTORY_NOTIFY_INFORMATION_CLASS; +typedef struct _TARGET_DEVICE_CUSTOM_NOTIFICATION +{ + USHORT Version; + USHORT Size; + GUID Event; + FILE_OBJECT *FileObject; + LONG NameBufferOffset; + UCHAR CustomDataBuffer[1]; +} TARGET_DEVICE_CUSTOM_NOTIFICATION, *PTARGET_DEVICE_CUSTOM_NOTIFICATION; + typedef enum _WORK_QUEUE_TYPE { CriticalWorkQueue, DelayedWorkQueue, @@ -1781,6 +1792,8 @@ NTSTATUS WINAPI IoRegisterDeviceInterface(PDEVICE_OBJECT,const GUID*,PUNICODE_S void WINAPI IoReleaseCancelSpinLock(KIRQL); void WINAPI IoReleaseRemoveLockAndWaitEx(IO_REMOVE_LOCK*,void*,ULONG); void WINAPI IoReleaseRemoveLockEx(IO_REMOVE_LOCK*,void*,ULONG); +NTSTATUS WINAPI IoReportTargetDeviceChange(DEVICE_OBJECT*,void*); +NTSTATUS WINAPI IoReportTargetDeviceChangeAsynchronous(DEVICE_OBJECT*,void*,PDEVICE_CHANGE_COMPLETE_CALLBACK,void*); void WINAPI IoReuseIrp(IRP*,NTSTATUS); NTSTATUS WINAPI IoSetDeviceInterfaceState(UNICODE_STRING*,BOOLEAN); NTSTATUS WINAPI IoSetDevicePropertyData(DEVICE_OBJECT*,const DEVPROPKEY*,LCID,ULONG,DEVPROPTYPE,ULONG,void*); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
From: Rémi Bernon <rbernon(a)codeweavers.com> Based on a patch from Vibhav Pant. --- dlls/dinput/tests/driver_hid.c | 20 +++++ dlls/dinput/tests/driver_hid.h | 1 + dlls/dinput/tests/hotplug.c | 146 +++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) diff --git a/dlls/dinput/tests/driver_hid.c b/dlls/dinput/tests/driver_hid.c index 6903572b532..7b20af07493 100644 --- a/dlls/dinput/tests/driver_hid.c +++ b/dlls/dinput/tests/driver_hid.c @@ -192,6 +192,26 @@ static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp ) IoSkipCurrentIrpStackLocation( irp ); return IoCallDriver( ext->PhysicalDeviceObject, irp ); + case IOCTL_WINETEST_DEVICE_CHANGE: + { + ULONG in_size = stack->Parameters.DeviceIoControl.InputBufferLength; + TARGET_DEVICE_CUSTOM_NOTIFICATION *notif = irp->AssociatedIrp.SystemBuffer; + NTSTATUS status; + + if (in_size != notif->Size) status = STATUS_INVALID_PARAMETER; + else + { + void *data = ExAllocatePool( PagedPool, notif->Size ); + memcpy( data, notif, notif->Size ); + status = IoReportTargetDeviceChangeAsynchronous( device, data, ExFreePool, data ); + if (status) ExFreePool( data ); + } + + irp->IoStatus.Status = status; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return status; + } + case IOCTL_WINETEST_REMOVE_DEVICE: case IOCTL_WINETEST_CREATE_DEVICE: ok( 0, "unexpected call\n" ); diff --git a/dlls/dinput/tests/driver_hid.h b/dlls/dinput/tests/driver_hid.h index 743be1bb024..8ba01d14b1e 100644 --- a/dlls/dinput/tests/driver_hid.h +++ b/dlls/dinput/tests/driver_hid.h @@ -50,6 +50,7 @@ DEFINE_GUID(control_class,0xdeadbeef,0x29ef,0x4538,0xa5,0xfd,0xb6,0x95,0x73,0xa3 #define IOCTL_WINETEST_CREATE_DEVICE CTL_CODE(FILE_DEVICE_KEYBOARD, 0x804, METHOD_IN_DIRECT, FILE_ANY_ACCESS) #define IOCTL_WINETEST_REMOVE_DEVICE CTL_CODE(FILE_DEVICE_KEYBOARD, 0x805, METHOD_IN_DIRECT, FILE_ANY_ACCESS) #define IOCTL_WINETEST_HID_WAIT_INPUT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x806, METHOD_IN_DIRECT, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_DEVICE_CHANGE CTL_CODE(FILE_DEVICE_KEYBOARD, 0x807, METHOD_IN_DIRECT, FILE_ANY_ACCESS) struct hid_expect { diff --git a/dlls/dinput/tests/hotplug.c b/dlls/dinput/tests/hotplug.c index 5b9455d1819..44fba60d4af 100644 --- a/dlls/dinput/tests/hotplug.c +++ b/dlls/dinput/tests/hotplug.c @@ -229,6 +229,7 @@ done: static int device_change_count; static int device_change_expect; +static int device_change_expect_custom; static HWND device_change_hwnd; static BOOL device_change_all; @@ -244,6 +245,41 @@ static BOOL all_lower( const WCHAR *str, const WCHAR *end ) return TRUE; } +static const union device_change_event +{ + struct + { + USHORT Version; + USHORT Size; + GUID Event; + FILE_OBJECT *FileObject; + LONG NameBufferOffset; + UCHAR CustomDataBuffer[256]; + }; + TARGET_DEVICE_CUSTOM_NOTIFICATION notif; +} device_change_events[] = +{ + {.Version = 1, .Size = sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION), + .Event = {0x00000001,0xdead,0xbeef}, .NameBufferOffset = -1}, + {.Version = 1, .Size = offsetof(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer[sizeof(GUID)]), + .Event = {0x00000002,0xdead,0xbeef}, .NameBufferOffset = -1, + .CustomDataBuffer = {0x00,0x00,0x00,0x03,0xad,0xde,0xef,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {.Version = 1, .Size = offsetof(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer[23 * sizeof(WCHAR)]), + .Event = {0x00000003,0xdead,0xbeef}, .NameBufferOffset = 0, + .CustomDataBuffer = {'W',0,'i',0,'n',0,'e',0,' ',0,'i',0,'s',0,' ',0,'n',0,'o',0,'t',0,' ',0, + 'a',0,'n',0,' ',0,'e',0,'m',0,'u',0,'l',0,'a',0,'t',0,'o',0,'r',0}}, + {.Version = 1, .Size = offsetof(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer[sizeof(GUID) + 23 * sizeof(WCHAR)]), + .Event = {0x00000004,0xdead,0xbeef}, .NameBufferOffset = sizeof(GUID), + .CustomDataBuffer = {0x00,0x00,0x00,0x03,0xad,0xde,0xef,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 'W',0,'i',0,'n',0,'e',0,' ',0,'i',0,'s',0,' ',0,'n',0,'o',0,'t',0,' ',0, + 'a',0,'n',0,' ',0,'e',0,'m',0,'u',0,'l',0,'a',0,'t',0,'o',0,'r',0}}, + /* DBT_DEVICEREMOVECOMPLETE event that is sent when device is removed */ + {.Version = 1, .Size = offsetof(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer[0]), .NameBufferOffset = -1}, +}; +static const union device_change_event *device_change_expect_event; +static HANDLE device_change_expect_handle; +static HDEVNOTIFY handle_devnotify; + static LRESULT CALLBACK devnotify_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { if (msg == WM_DEVICECHANGE) @@ -253,6 +289,42 @@ static LRESULT CALLBACK devnotify_wndproc( HWND hwnd, UINT msg, WPARAM wparam, L const WCHAR *upper_end, *name_end, *expect_prefix; GUID expect_guid; + if (device_change_expect_custom) + { + todo_wine + ok( header->dbch_devicetype == DBT_DEVTYP_HANDLE || + broken( device_change_expect_custom == 1 && header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE ), /* w8 32bit */ + "got type %#lx\n", header->dbch_devicetype); + todo_wine_if( device_change_expect_custom > 1 ) + ok( wparam == (device_change_expect_custom > 1 ? DBT_CUSTOMEVENT : DBT_DEVICEREMOVECOMPLETE), + "got wparam %#Ix\n", wparam ); + } + if (header->dbch_devicetype == DBT_DEVTYP_HANDLE) + { + DEV_BROADCAST_HANDLE *handle = (DEV_BROADCAST_HANDLE *)header; + UINT size = handle->dbch_size - offsetof(DEV_BROADCAST_HANDLE, dbch_data); + + winetest_push_context( "%Id", device_change_expect_event - device_change_events ); + ok( !!device_change_expect_event, "unexpected event\n" ); + ok( device_change_expect_event->Size - offsetof(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer[0]) == + handle->dbch_size - 2 * sizeof(WCHAR) - offsetof(DEV_BROADCAST_HANDLE, dbch_data[0]), + "got dbch_size %#lx\n", handle->dbch_size ); + ok( !handle->dbch_reserved, "got dbch_reserved %lu\n", handle->dbch_reserved ); + ok( handle->dbch_handle == device_change_expect_handle, "got dbch_handle %p\n", handle->dbch_handle ); + ok( handle->dbch_hdevnotify == handle_devnotify, "got dbch_hdevnotify %p\n", handle->dbch_hdevnotify ); + ok( IsEqualGUID( &handle->dbch_eventguid, &device_change_expect_event->Event ), + "got dbch_eventguid %s\n", debugstr_guid(&handle->dbch_eventguid) ); + ok( handle->dbch_nameoffset == device_change_expect_event->NameBufferOffset, + "got dbch_nameoffset %ld\n", handle->dbch_nameoffset ); + ok( !memcmp( handle->dbch_data, device_change_expect_event->CustomDataBuffer, size ), + "got unexpected dbch_data\n" ); + winetest_pop_context(); + + device_change_expect_custom--; + device_change_expect_event++; + return DefWindowProcW( hwnd, msg, wparam, lparam ); + } + if (device_change_all && (device_change_count == 0 || device_change_count == 3)) { expect_guid = control_class; @@ -302,6 +374,11 @@ static void test_RegisterDeviceNotification(void) .dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE, .dbcc_classguid = GUID_DEVINTERFACE_HID, }; + DEV_BROADCAST_HANDLE handle_filter_a = + { + .dbch_size = sizeof(DEV_BROADCAST_HANDLE), + .dbch_devicetype = DBT_DEVTYP_HANDLE, + }; WNDCLASSEXW class = { .cbSize = sizeof(WNDCLASSEXW), @@ -486,6 +563,75 @@ static void test_RegisterDeviceNotification(void) UnregisterDeviceNotification( devnotify ); + devnotify = RegisterDeviceNotificationA( hwnd, &iface_filter_a, DEVICE_NOTIFY_WINDOW_HANDLE ); + ok( !!devnotify, "RegisterDeviceNotificationA failed, error %lu\n", GetLastError() ); + while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE )) DispatchMessageW( &msg ); + + device_change_count = 0; + device_change_expect = 2; + device_change_hwnd = hwnd; + device_change_all = FALSE; + stop_event = CreateEventW( NULL, FALSE, FALSE, NULL ); + ok( !!stop_event, "CreateEventW failed, error %lu\n", GetLastError() ); + thread = CreateThread( NULL, 0, dinput_test_device_thread, stop_event, 0, NULL ); + ok( !!thread, "CreateThread failed, error %lu\n", GetLastError() ); + + while (device_change_count < device_change_expect) + { + ret = MsgWaitForMultipleObjects( 0, NULL, FALSE, 5000, QS_ALLINPUT ); + ok( !ret, "MsgWaitForMultipleObjects returned %#lx\n", ret ); + if (ret) break; + while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE )) + { + TranslateMessage( &msg ); + ok( msg.message != WM_DEVICECHANGE, "got WM_DEVICECHANGE\n" ); + DispatchMessageW( &msg ); + } + if (device_change_count == 1 && !device_change_expect_event) + { + WCHAR device_path[MAX_PATH]; + HANDLE file; + UINT i; + + swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x", LOWORD(EXPECT_VIDPID), HIWORD(EXPECT_VIDPID) ); + ret = find_hid_device_path( device_path ); + ok( ret, "Failed to find HID device matching %s\n", debugstr_w( device_path ) ); + + file = CreateFileW( device_path, FILE_READ_ACCESS | FILE_WRITE_ACCESS, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); + ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() ); + + handle_filter_a.dbch_handle = file; + handle_devnotify = RegisterDeviceNotificationA( hwnd, &handle_filter_a, DEVICE_NOTIFY_WINDOW_HANDLE ); + ok( !!handle_devnotify, "RegisterDeviceNotificationA failed, error %lu\n", GetLastError() ); + + device_change_expect_handle = file; + device_change_expect_event = device_change_events; + for (i = 0; i < ARRAY_SIZE(device_change_events) - 1; i++) + { + ret = sync_ioctl( file, IOCTL_WINETEST_DEVICE_CHANGE, (BYTE *)&device_change_events[i].notif, + device_change_events[i].notif.Size, NULL, 0, 5000 ); + todo_wine ok( ret, "IOCTL_WINETEST_DEVICE_CHANGE failed, last error %lu\n", GetLastError() ); + device_change_expect_custom++; + } + device_change_expect_custom++; /* extra DBT_DEVICEREMOVECOMPLETE event that is sent when device is removed */ + + CloseHandle( file ); + if (!ret) SetEvent( stop_event ); + } + if (device_change_count == 1 && device_change_expect_custom == 1) SetEvent( stop_event ); + } + + ret = WaitForSingleObject( thread, 5000 ); + ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); + CloseHandle( thread ); + CloseHandle( stop_event ); + + if (handle_devnotify) UnregisterDeviceNotification( handle_devnotify ); + UnregisterDeviceNotification( devnotify ); + device_change_expect_event = NULL; + handle_devnotify = 0; + DestroyWindow( hwnd ); UnregisterClassW( class.lpszClassName, class.hInstance ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/sechost/service.c | 13 ++++---- dlls/user32/input.c | 66 +++++++++++++++------------------------ include/wine/plugplay.idl | 13 ++++++++ 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index 788bb61bf48..98dd10cf5ec 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -1978,8 +1978,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH StartServiceCtrlDispatcherW( const SERVICE_TABLE_E struct device_notification_details { - DWORD (CALLBACK *cb)(HANDLE handle, DWORD flags, DEV_BROADCAST_HDR *header); HANDLE handle; + device_notify_callback callback; union { DEV_BROADCAST_HDR header; @@ -2100,7 +2100,7 @@ static DWORD WINAPI device_notify_proc( void *arg ) for (i = 0; i < details_copy_nelems; i++) { if (!notification_filter_matches( &details_copy[i].filter.header, (DEV_BROADCAST_HDR *)buf )) continue; - details_copy[i].cb( details_copy[i].handle, code, (DEV_BROADCAST_HDR *)buf ); + details_copy[i].callback( details_copy[i].handle, code, (DEV_BROADCAST_HDR *)buf ); } MIDL_user_free(buf); } @@ -2122,12 +2122,11 @@ static DWORD WINAPI device_notify_proc( void *arg ) /****************************************************************************** * I_ScRegisterDeviceNotification (sechost.@) */ -HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( struct device_notification_details *details, - void *filter, DWORD flags ) +HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( HANDLE handle, DEV_BROADCAST_HDR *filter, device_notify_callback callback ) { struct device_notify_registration *registration; - TRACE("callback %p, handle %p, filter %p, flags %#lx\n", details->cb, details->handle, filter, flags); + TRACE( "handle %p, filter %p, callback %p\n", handle, filter, callback ); if (!(registration = malloc( sizeof(struct device_notify_registration) ))) { @@ -2135,7 +2134,9 @@ HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( struct device_notification_det return NULL; } - registration->details = *details; + registration->details.handle = handle; + registration->details.callback = callback; + memcpy( ®istration->details.filter, filter, filter->dbch_size ); EnterCriticalSection( &service_cs ); list_add_tail( &device_notify_list, ®istration->entry ); diff --git a/dlls/user32/input.c b/dlls/user32/input.c index b4ee52f3474..4793688749e 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -28,6 +28,7 @@ #include "dbt.h" #include "wine/server.h" #include "wine/debug.h" +#include "wine/plugplay.h" WINE_DEFAULT_DEBUG_CHANNEL(win); WINE_DECLARE_DEBUG_CHANNEL(keyboard); @@ -550,21 +551,6 @@ static DWORD CALLBACK devnotify_service_callback(HANDLE handle, DWORD flags, DEV return 0; } -struct device_notification_details -{ - DWORD (CALLBACK *cb)(HANDLE handle, DWORD flags, DEV_BROADCAST_HDR *header); - HANDLE handle; - union - { - DEV_BROADCAST_HDR header; - DEV_BROADCAST_DEVICEINTERFACE_W iface; - } filter; -}; - -extern HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( struct device_notification_details *details, - void *filter, DWORD flags ); -extern BOOL WINAPI I_ScUnregisterDeviceNotification( HDEVNOTIFY handle ); - /*********************************************************************** * RegisterDeviceNotificationA (USER32.@) * @@ -580,8 +566,8 @@ HDEVNOTIFY WINAPI RegisterDeviceNotificationA( HANDLE handle, void *filter, DWOR */ HDEVNOTIFY WINAPI RegisterDeviceNotificationW( HANDLE handle, void *filter, DWORD flags ) { - struct device_notification_details details; DEV_BROADCAST_HDR *header = filter; + device_notify_callback callback; TRACE("handle %p, filter %p, flags %#lx\n", handle, filter, flags); @@ -597,38 +583,38 @@ HDEVNOTIFY WINAPI RegisterDeviceNotificationW( HANDLE handle, void *filter, DWOR return NULL; } - if (!header) details.filter.header.dbch_devicetype = 0; - else if (header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + if (flags & DEVICE_NOTIFY_SERVICE_HANDLE) + callback = devnotify_service_callback; + else if (IsWindowUnicode( handle )) + callback = devnotify_window_callbackW; + else + callback = devnotify_window_callbackA; + + if (!header) { - DEV_BROADCAST_DEVICEINTERFACE_W *iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)header; - details.filter.iface = *iface; + DEV_BROADCAST_HDR dummy = {0}; + return I_ScRegisterDeviceNotification( handle, &dummy, callback ); + } + if (header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + { + DEV_BROADCAST_DEVICEINTERFACE_W iface = *(DEV_BROADCAST_DEVICEINTERFACE_W *)header; if (flags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES) - details.filter.iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_classguid ); + iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_classguid ); else - details.filter.iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_name ); - } - else if (header->dbch_devicetype == DBT_DEVTYP_HANDLE) - { - FIXME( "DBT_DEVTYP_HANDLE filter type not implemented\n" ); - details.filter.header.dbch_devicetype = 0; + iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_name ); + + return I_ScRegisterDeviceNotification( handle, (DEV_BROADCAST_HDR *)&iface, callback ); } - else + if (header->dbch_devicetype == DBT_DEVTYP_HANDLE) { - SetLastError( ERROR_INVALID_DATA ); - return NULL; + FIXME( "DBT_DEVTYP_HANDLE not implemented\n" ); + return I_ScRegisterDeviceNotification( handle, header, callback ); } - details.handle = handle; - - if (flags & DEVICE_NOTIFY_SERVICE_HANDLE) - details.cb = devnotify_service_callback; - else if (IsWindowUnicode( handle )) - details.cb = devnotify_window_callbackW; - else - details.cb = devnotify_window_callbackA; - - return I_ScRegisterDeviceNotification( &details, filter, 0 ); + FIXME( "type %#lx not implemented\n", header->dbch_devicetype ); + SetLastError( ERROR_INVALID_DATA ); + return NULL; } /*********************************************************************** diff --git a/include/wine/plugplay.idl b/include/wine/plugplay.idl index a3e7b04bf30..32b0799b83c 100644 --- a/include/wine/plugplay.idl +++ b/include/wine/plugplay.idl @@ -16,8 +16,21 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#pragma makedep header + import "wtypes.idl"; +cpp_quote("#if 0") +typedef void *HDEVNOTIFY; +typedef struct _DEV_BROADCAST_HDR DEV_BROADCAST_HDR; +cpp_quote("#else") +cpp_quote("#include \"dbt.h\"") +cpp_quote("#endif") + +typedef DWORD (__stdcall *device_notify_callback)(HANDLE handle, DWORD flags, DEV_BROADCAST_HDR *header); +HDEVNOTIFY __stdcall I_ScRegisterDeviceNotification(HANDLE handle, DEV_BROADCAST_HDR *filter, device_notify_callback callback); +BOOL __stdcall I_ScUnregisterDeviceNotification(HDEVNOTIFY handle); + [ uuid(57c680ac-7bce-4f39-97fd-ffea566754d5), endpoint("ncacn_np:[\\pipe\\wine_plugplay]"), -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/sechost/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index 98dd10cf5ec..d6de0448273 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -2087,6 +2087,7 @@ static DWORD WINAPI device_notify_proc( void *arg ) EnterCriticalSection( &service_cs ); LIST_FOR_EACH_ENTRY(registration, &device_notify_list, struct device_notify_registration, entry) { + if (!notification_filter_matches( ®istration->details.filter.header, (DEV_BROADCAST_HDR *)buf )) continue; details_copy[i++] = registration->details; details_copy_nelems++; if (i == details_copy_size) @@ -2099,7 +2100,6 @@ static DWORD WINAPI device_notify_proc( void *arg ) for (i = 0; i < details_copy_nelems; i++) { - if (!notification_filter_matches( &details_copy[i].filter.header, (DEV_BROADCAST_HDR *)buf )) continue; details_copy[i].callback( details_copy[i].handle, code, (DEV_BROADCAST_HDR *)buf ); } MIDL_user_free(buf); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/sechost/service.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index d6de0448273..41f6d03c7e3 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -1996,6 +1996,16 @@ struct device_notify_registration struct device_notification_details details; }; +static struct device_notify_registration *device_notify_copy( struct device_notify_registration *notify ) +{ + struct device_notify_registration *event; + + if (!(event = calloc( 1, sizeof(*event) ))) return NULL; + event->details = notify->details; + + return event; +} + static BOOL notification_filter_matches( DEV_BROADCAST_HDR *filter, DEV_BROADCAST_HDR *event ) { if (!filter->dbch_devicetype) return TRUE; @@ -2019,12 +2029,11 @@ static DWORD WINAPI device_notify_proc( void *arg ) WCHAR protseq[] = L"ncacn_np"; RPC_WSTR binding_str; DWORD err = ERROR_SUCCESS; - struct device_notify_registration *registration; - struct device_notification_details *details_copy; - unsigned int details_copy_nelems, details_copy_size; + struct device_notify_registration *registration, *event, *next; + struct list events = LIST_INIT(events); plugplay_rpc_handle handle = NULL; DWORD code = 0; - unsigned int i, size; + unsigned int size; BYTE *buf; SetThreadDescription( GetCurrentThread(), L"wine_sechost_device_notify" ); @@ -2058,9 +2067,6 @@ static DWORD WINAPI device_notify_proc( void *arg ) return 1; } - details_copy_size = 8; - details_copy = malloc( details_copy_size * sizeof(*details_copy) ); - for (;;) { buf = NULL; @@ -2082,25 +2088,20 @@ static DWORD WINAPI device_notify_proc( void *arg ) } /* Make a copy to avoid a hang if a callback tries to register or unregister for notifications. */ - i = 0; - details_copy_nelems = 0; EnterCriticalSection( &service_cs ); LIST_FOR_EACH_ENTRY(registration, &device_notify_list, struct device_notify_registration, entry) { if (!notification_filter_matches( ®istration->details.filter.header, (DEV_BROADCAST_HDR *)buf )) continue; - details_copy[i++] = registration->details; - details_copy_nelems++; - if (i == details_copy_size) - { - details_copy_size *= 2; - details_copy = realloc( details_copy, details_copy_size * sizeof(*details_copy) ); - } + if (!(event = device_notify_copy( registration ))) break; + list_add_tail( &events, &event->entry ); } LeaveCriticalSection(&service_cs); - for (i = 0; i < details_copy_nelems; i++) + LIST_FOR_EACH_ENTRY_SAFE( event, next, &events, struct device_notify_registration, entry ) { - details_copy[i].callback( details_copy[i].handle, code, (DEV_BROADCAST_HDR *)buf ); + event->details.callback( event->details.handle, code, (DEV_BROADCAST_HDR *)buf ); + list_remove( &event->entry ); + free( event ); } MIDL_user_free(buf); } @@ -2114,7 +2115,6 @@ static DWORD WINAPI device_notify_proc( void *arg ) } __ENDTRY - free( details_copy ); RpcBindingFree( &plugplay_binding_handle ); return 0; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/sechost/service.c | 62 +++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index 41f6d03c7e3..b376cc312d4 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -1976,32 +1976,27 @@ BOOL WINAPI DECLSPEC_HOTPATCH StartServiceCtrlDispatcherW( const SERVICE_TABLE_E return service_run_main_thread(); } -struct device_notification_details -{ - HANDLE handle; - device_notify_callback callback; - union - { - DEV_BROADCAST_HDR header; - DEV_BROADCAST_DEVICEINTERFACE_W iface; - } filter; -}; - static HANDLE device_notify_thread; static struct list device_notify_list = LIST_INIT(device_notify_list); -struct device_notify_registration +struct device_notify { struct list entry; - struct device_notification_details details; + HANDLE handle; + device_notify_callback callback; + DEV_BROADCAST_HDR header[]; /* variable size */ }; -static struct device_notify_registration *device_notify_copy( struct device_notify_registration *notify ) +C_ASSERT( sizeof(struct device_notify) == offsetof(struct device_notify, header[0]) ); + +static struct device_notify *device_notify_copy( struct device_notify *notify, DEV_BROADCAST_HDR *header ) { - struct device_notify_registration *event; + struct device_notify *event; - if (!(event = calloc( 1, sizeof(*event) ))) return NULL; - event->details = notify->details; + if (!(event = calloc( 1, sizeof(*event) + header->dbch_size ))) return NULL; + event->handle = notify->handle; + event->callback = notify->callback; + memcpy( event->header, header, header->dbch_size ); return event; } @@ -2029,7 +2024,7 @@ static DWORD WINAPI device_notify_proc( void *arg ) WCHAR protseq[] = L"ncacn_np"; RPC_WSTR binding_str; DWORD err = ERROR_SUCCESS; - struct device_notify_registration *registration, *event, *next; + struct device_notify *notify, *event, *next; struct list events = LIST_INIT(events); plugplay_rpc_handle handle = NULL; DWORD code = 0; @@ -2089,17 +2084,17 @@ static DWORD WINAPI device_notify_proc( void *arg ) /* Make a copy to avoid a hang if a callback tries to register or unregister for notifications. */ EnterCriticalSection( &service_cs ); - LIST_FOR_EACH_ENTRY(registration, &device_notify_list, struct device_notify_registration, entry) + LIST_FOR_EACH_ENTRY( notify, &device_notify_list, struct device_notify, entry ) { - if (!notification_filter_matches( ®istration->details.filter.header, (DEV_BROADCAST_HDR *)buf )) continue; - if (!(event = device_notify_copy( registration ))) break; + if (!notification_filter_matches( notify->header, (DEV_BROADCAST_HDR *)buf )) continue; + if (!(event = device_notify_copy( notify, (DEV_BROADCAST_HDR *)buf ))) break; list_add_tail( &events, &event->entry ); } LeaveCriticalSection(&service_cs); - LIST_FOR_EACH_ENTRY_SAFE( event, next, &events, struct device_notify_registration, entry ) + LIST_FOR_EACH_ENTRY_SAFE( event, next, &events, struct device_notify, entry ) { - event->details.callback( event->details.handle, code, (DEV_BROADCAST_HDR *)buf ); + event->callback( event->handle, code, event->header ); list_remove( &event->entry ); free( event ); } @@ -2124,29 +2119,28 @@ static DWORD WINAPI device_notify_proc( void *arg ) */ HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( HANDLE handle, DEV_BROADCAST_HDR *filter, device_notify_callback callback ) { - struct device_notify_registration *registration; + struct device_notify *notify; TRACE( "handle %p, filter %p, callback %p\n", handle, filter, callback ); - if (!(registration = malloc( sizeof(struct device_notify_registration) ))) + if (!(notify = calloc( 1, sizeof(*notify) + filter->dbch_size ))) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } - - registration->details.handle = handle; - registration->details.callback = callback; - memcpy( ®istration->details.filter, filter, filter->dbch_size ); + notify->handle = handle; + notify->callback = callback; + memcpy( notify->header, filter, filter->dbch_size ); EnterCriticalSection( &service_cs ); - list_add_tail( &device_notify_list, ®istration->entry ); + list_add_tail( &device_notify_list, ¬ify->entry ); if (!device_notify_thread) device_notify_thread = CreateThread( NULL, 0, device_notify_proc, NULL, 0, NULL ); LeaveCriticalSection( &service_cs ); - return registration; + return notify; } /****************************************************************************** @@ -2154,7 +2148,7 @@ HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( HANDLE handle, DEV_BROADCAST_H */ BOOL WINAPI I_ScUnregisterDeviceNotification( HDEVNOTIFY handle ) { - struct device_notify_registration *registration = handle; + struct device_notify *notify = handle; TRACE("%p\n", handle); @@ -2162,8 +2156,8 @@ BOOL WINAPI I_ScUnregisterDeviceNotification( HDEVNOTIFY handle ) return FALSE; EnterCriticalSection( &service_cs ); - list_remove( ®istration->entry ); + list_remove( ¬ify->entry ); LeaveCriticalSection(&service_cs); - free( registration ); + free( notify ); return TRUE; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/ntoskrnl.exe/pnp.c | 6 +++--- dlls/sechost/service.c | 6 +++++- include/wine/plugplay.idl | 6 ++++-- programs/plugplay/main.c | 7 +++++-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index 9d91160c46d..de9c319c20f 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -744,11 +744,11 @@ static LONG WINAPI rpc_filter( EXCEPTION_POINTERS *eptr ) return I_RpcExceptionFilter( eptr->ExceptionRecord->ExceptionCode ); } -static void send_devicechange( DWORD code, void *data, unsigned int size ) +static void send_devicechange( const WCHAR *path, DWORD code, void *data, unsigned int size ) { __TRY { - plugplay_send_event( code, data, size ); + plugplay_send_event( path, code, data, size ); } __EXCEPT(rpc_filter) { @@ -864,7 +864,7 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable broadcast->dbcc_classguid = iface->interface_class; lstrcpynW( broadcast->dbcc_name, name->Buffer, namelen + 1 ); if (namelen > 1) broadcast->dbcc_name[1] = '\\'; - send_devicechange( enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, broadcast, len ); + send_devicechange( L"", enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, broadcast, len ); heap_free( broadcast ); } return ret; diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index b376cc312d4..6fc225a3501 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -2029,6 +2029,7 @@ static DWORD WINAPI device_notify_proc( void *arg ) plugplay_rpc_handle handle = NULL; DWORD code = 0; unsigned int size; + WCHAR *path; BYTE *buf; SetThreadDescription( GetCurrentThread(), L"wine_sechost_device_notify" ); @@ -2064,10 +2065,11 @@ static DWORD WINAPI device_notify_proc( void *arg ) for (;;) { + path = NULL; buf = NULL; __TRY { - code = plugplay_get_event( handle, &buf, &size ); + code = plugplay_get_event( handle, &path, &buf, &size ); err = ERROR_SUCCESS; } __EXCEPT(rpc_filter) @@ -2098,7 +2100,9 @@ static DWORD WINAPI device_notify_proc( void *arg ) list_remove( &event->entry ); free( event ); } + MIDL_user_free(buf); + MIDL_user_free(path); } __TRY diff --git a/include/wine/plugplay.idl b/include/wine/plugplay.idl index 32b0799b83c..9df59e9ac05 100644 --- a/include/wine/plugplay.idl +++ b/include/wine/plugplay.idl @@ -41,7 +41,9 @@ interface plugplay typedef [context_handle] void *plugplay_rpc_handle; plugplay_rpc_handle plugplay_register_listener(); - DWORD plugplay_get_event([in] plugplay_rpc_handle handle, [out, size_is(,*size)] BYTE **data, [out] unsigned int *size); + DWORD plugplay_get_event([in] plugplay_rpc_handle handle, [out, string] WCHAR **path, + [out, size_is(,*size)] BYTE **data, [out] unsigned int *size); void plugplay_unregister_listener([in] plugplay_rpc_handle handle); - void plugplay_send_event([in] DWORD event_code, [in, size_is(size)] const BYTE *data, [in] unsigned int size); + void plugplay_send_event([in, string] const WCHAR *path, [in] DWORD event_code, + [in, size_is(size)] const BYTE *data, [in] unsigned int size); } diff --git a/programs/plugplay/main.c b/programs/plugplay/main.c index 8426f2204a3..f3614288f3c 100644 --- a/programs/plugplay/main.c +++ b/programs/plugplay/main.c @@ -65,6 +65,7 @@ struct event struct list entry; DWORD code; BYTE *data; + WCHAR *path; unsigned int size; }; @@ -108,7 +109,7 @@ plugplay_rpc_handle __cdecl plugplay_register_listener(void) return listener; } -DWORD __cdecl plugplay_get_event( plugplay_rpc_handle handle, BYTE **data, unsigned int *size ) +DWORD __cdecl plugplay_get_event( plugplay_rpc_handle handle, WCHAR **path, BYTE **data, unsigned int *size ) { struct listener *listener = handle; struct event *event; @@ -126,6 +127,7 @@ DWORD __cdecl plugplay_get_event( plugplay_rpc_handle handle, BYTE **data, unsig LeaveCriticalSection( &plugplay_cs ); ret = event->code; + *path = event->path; *data = event->data; *size = event->size; free( event ); @@ -137,7 +139,7 @@ void __cdecl plugplay_unregister_listener( plugplay_rpc_handle handle ) destroy_listener( handle ); } -void __cdecl plugplay_send_event( DWORD code, const BYTE *data, unsigned int size ) +void __cdecl plugplay_send_event( const WCHAR *path, DWORD code, const BYTE *data, unsigned int size ) { struct listener *listener; struct event *event; @@ -158,6 +160,7 @@ void __cdecl plugplay_send_event( DWORD code, const BYTE *data, unsigned int siz break; } + event->path = wcsdup( path ); event->code = code; memcpy( event->data, data, size ); event->size = size; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
From: Vibhav Pant <vibhavp(a)gmail.com> --- programs/plugplay/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/programs/plugplay/main.c b/programs/plugplay/main.c index f3614288f3c..d8f4d44f448 100644 --- a/programs/plugplay/main.c +++ b/programs/plugplay/main.c @@ -143,9 +143,13 @@ void __cdecl plugplay_send_event( const WCHAR *path, DWORD code, const BYTE *dat { struct listener *listener; struct event *event; + const DEV_BROADCAST_HDR *header = (const DEV_BROADCAST_HDR *)data; - BroadcastSystemMessageW( 0, NULL, WM_DEVICECHANGE, code, (LPARAM)data ); - BroadcastSystemMessageW( 0, NULL, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0 ); + if (header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + { + BroadcastSystemMessageW( 0, NULL, WM_DEVICECHANGE, code, (LPARAM)data ); + BroadcastSystemMessageW( 0, NULL, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0 ); + } EnterCriticalSection( &plugplay_cs ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
This merge request was approved by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
From: Vibhav Pant <vibhavp(a)gmail.com> --- dlls/sechost/service.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index 6fc225a3501..474d977ac5e 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -1982,6 +1982,7 @@ static struct list device_notify_list = LIST_INIT(device_notify_list); struct device_notify { struct list entry; + WCHAR *path; HANDLE handle; device_notify_callback callback; DEV_BROADCAST_HDR header[]; /* variable size */ @@ -1998,10 +1999,18 @@ static struct device_notify *device_notify_copy( struct device_notify *notify, D event->callback = notify->callback; memcpy( event->header, header, header->dbch_size ); + if (header->dbch_devicetype == DBT_DEVTYP_HANDLE) + { + DEV_BROADCAST_HANDLE *notify_handle = (DEV_BROADCAST_HANDLE *)notify->header; + DEV_BROADCAST_HANDLE *event_handle = (DEV_BROADCAST_HANDLE *)event->header; + event_handle->dbch_handle = notify_handle->dbch_handle; + event_handle->dbch_hdevnotify = notify; + } + return event; } -static BOOL notification_filter_matches( DEV_BROADCAST_HDR *filter, DEV_BROADCAST_HDR *event ) +static BOOL notification_filter_matches( DEV_BROADCAST_HDR *filter, const WCHAR *path, DEV_BROADCAST_HDR *event, const WCHAR *event_path ) { if (!filter->dbch_devicetype) return TRUE; if (filter->dbch_devicetype != event->dbch_devicetype) return FALSE; @@ -2014,6 +2023,8 @@ static BOOL notification_filter_matches( DEV_BROADCAST_HDR *filter, DEV_BROADCAS return IsEqualGUID( &filter_iface->dbcc_classguid, &event_iface->dbcc_classguid ); } + if (filter->dbch_devicetype == DBT_DEVTYP_HANDLE) return !wcscmp(path, event_path); + FIXME( "Filter dbch_devicetype %lu not implemented\n", filter->dbch_devicetype ); return TRUE; } @@ -2088,7 +2099,7 @@ static DWORD WINAPI device_notify_proc( void *arg ) EnterCriticalSection( &service_cs ); LIST_FOR_EACH_ENTRY( notify, &device_notify_list, struct device_notify, entry ) { - if (!notification_filter_matches( notify->header, (DEV_BROADCAST_HDR *)buf )) continue; + if (!notification_filter_matches( notify->header, notify->path, (DEV_BROADCAST_HDR *)buf, path )) continue; if (!(event = device_notify_copy( notify, (DEV_BROADCAST_HDR *)buf ))) break; list_add_tail( &events, &event->entry ); } @@ -2136,6 +2147,25 @@ HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( HANDLE handle, DEV_BROADCAST_H notify->callback = callback; memcpy( notify->header, filter, filter->dbch_size ); + if (filter->dbch_devicetype == DBT_DEVTYP_HANDLE) + { + WCHAR buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH + 1]; + OBJECT_NAME_INFORMATION *info = (OBJECT_NAME_INFORMATION*)&buffer; + DEV_BROADCAST_HANDLE *handle = (DEV_BROADCAST_HANDLE *)filter; + NTSTATUS status; + ULONG dummy; + + status = NtQueryObject( handle->dbch_handle, ObjectNameInformation, &buffer, sizeof(buffer) - sizeof(WCHAR), &dummy ); + if (status || !(notify->path = calloc( 1, info->Name.Length + sizeof(WCHAR) ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + free( notify ); + return NULL; + } + + memcpy( notify->path, info->Name.Buffer, info->Name.Length ); + } + EnterCriticalSection( &service_cs ); list_add_tail( &device_notify_list, ¬ify->entry ); @@ -2162,6 +2192,7 @@ BOOL WINAPI I_ScUnregisterDeviceNotification( HDEVNOTIFY handle ) EnterCriticalSection( &service_cs ); list_remove( ¬ify->entry ); LeaveCriticalSection(&service_cs); + free( notify->path ); free( notify ); return TRUE; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
From: Vibhav Pant <vibhavp(a)gmail.com> --- dlls/user32/input.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 4793688749e..ff1dc6d393f 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -532,12 +532,30 @@ static DWORD CALLBACK devnotify_window_callbackA(HANDLE handle, DWORD flags, DEV return 0; } - default: - FIXME( "unimplemented W to A mapping for %#lx\n", header->dbch_devicetype ); - /* fall through */ case DBT_DEVTYP_HANDLE: + { + const DEV_BROADCAST_HANDLE *handleW = (const DEV_BROADCAST_HANDLE *)header; + UINT sizeW = handleW->dbch_size - offsetof(DEV_BROADCAST_HANDLE, dbch_data[0]), len, offset; + DEV_BROADCAST_HANDLE *handleA; + + if (!(handleA = malloc( offsetof(DEV_BROADCAST_HANDLE, dbch_data[sizeW * 3 + 1]) ))) return 0; + memcpy( handleA, handleW, offsetof(DEV_BROADCAST_HANDLE, dbch_data[0]) ); + offset = min( sizeW, handleW->dbch_nameoffset ); + + memcpy( handleA->dbch_data, handleW->dbch_data, offset ); + len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(handleW->dbch_data + offset), (sizeW - offset) / sizeof(WCHAR), + (char *)handleA->dbch_data + offset, sizeW * 3 + 1 - offset, NULL, NULL ); + handleA->dbch_size = offsetof(DEV_BROADCAST_HANDLE, dbch_data[offset + len + 1]); + + SendMessageTimeoutA( handle, WM_DEVICECHANGE, flags, (LPARAM)handleA, SMTO_ABORTIFHUNG, 2000, NULL ); + free( handleA ); + return 0; + } + case DBT_DEVTYP_OEM: break; + default: + FIXME( "unimplemented W to A mapping for %#lx\n", header->dbch_devicetype ); } } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
From: Vibhav Pant <vibhavp(a)gmail.com> --- dlls/dinput/tests/hotplug.c | 6 ++--- dlls/ntoskrnl.exe/pnp.c | 44 +++++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/dlls/dinput/tests/hotplug.c b/dlls/dinput/tests/hotplug.c index 44fba60d4af..f7199d2b17e 100644 --- a/dlls/dinput/tests/hotplug.c +++ b/dlls/dinput/tests/hotplug.c @@ -291,11 +291,10 @@ static LRESULT CALLBACK devnotify_wndproc( HWND hwnd, UINT msg, WPARAM wparam, L if (device_change_expect_custom) { - todo_wine + todo_wine_if( device_change_expect_custom == 1 ) ok( header->dbch_devicetype == DBT_DEVTYP_HANDLE || broken( device_change_expect_custom == 1 && header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE ), /* w8 32bit */ "got type %#lx\n", header->dbch_devicetype); - todo_wine_if( device_change_expect_custom > 1 ) ok( wparam == (device_change_expect_custom > 1 ? DBT_CUSTOMEVENT : DBT_DEVICEREMOVECOMPLETE), "got wparam %#Ix\n", wparam ); } @@ -611,13 +610,12 @@ static void test_RegisterDeviceNotification(void) { ret = sync_ioctl( file, IOCTL_WINETEST_DEVICE_CHANGE, (BYTE *)&device_change_events[i].notif, device_change_events[i].notif.Size, NULL, 0, 5000 ); - todo_wine ok( ret, "IOCTL_WINETEST_DEVICE_CHANGE failed, last error %lu\n", GetLastError() ); + ok( ret, "IOCTL_WINETEST_DEVICE_CHANGE failed, last error %lu\n", GetLastError() ); device_change_expect_custom++; } device_change_expect_custom++; /* extra DBT_DEVICEREMOVECOMPLETE event that is sent when device is removed */ CloseHandle( file ); - if (!ret) SetEvent( stop_event ); } if (device_change_count == 1 && device_change_expect_custom == 1) SetEvent( stop_event ); } diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index de9c319c20f..db8285824da 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -1006,8 +1006,40 @@ NTSTATUS WINAPI IoRegisterDeviceInterface(DEVICE_OBJECT *device, const GUID *cla */ NTSTATUS WINAPI IoReportTargetDeviceChange( DEVICE_OBJECT *device, void *data ) { - FIXME( "(%p, %p) stub!\n", device, data ); - return STATUS_NOT_SUPPORTED; + TARGET_DEVICE_CUSTOM_NOTIFICATION *notification = data; + OBJECT_NAME_INFORMATION *name_info; + DEV_BROADCAST_HANDLE *event_handle; + DWORD size, data_size; + NTSTATUS ret; + + TRACE( "(%p, %p)\n", device, data ); + + if (notification->Version != 1) return STATUS_INVALID_PARAMETER; + + ret = ObQueryNameString( device, NULL, 0, &size ); + if (ret != STATUS_INFO_LENGTH_MISMATCH) return ret; + if (!(name_info = heap_alloc( size ))) return STATUS_NO_MEMORY; + ret = ObQueryNameString( device, name_info, size, &size ); + if (ret != STATUS_SUCCESS) return ret; + + data_size = notification->Size - offsetof( TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer ); + size = offsetof( DEV_BROADCAST_HANDLE, dbch_data[data_size + 2 * sizeof(WCHAR)] ); + if (!(event_handle = heap_alloc_zero( size ))) + { + heap_free( name_info ); + return STATUS_NO_MEMORY; + } + + event_handle->dbch_size = size; + event_handle->dbch_devicetype = DBT_DEVTYP_HANDLE; + event_handle->dbch_eventguid = notification->Event; + event_handle->dbch_nameoffset = notification->NameBufferOffset; + memcpy( event_handle->dbch_data, notification->CustomDataBuffer, data_size ); + send_devicechange( name_info->Name.Buffer, DBT_CUSTOMEVENT, (BYTE *)event_handle, event_handle->dbch_size ); + heap_free( event_handle ); + heap_free( name_info ); + + return STATUS_SUCCESS; } /*********************************************************************** @@ -1016,8 +1048,12 @@ NTSTATUS WINAPI IoReportTargetDeviceChange( DEVICE_OBJECT *device, void *data ) NTSTATUS WINAPI IoReportTargetDeviceChangeAsynchronous( DEVICE_OBJECT *device, void *data, PDEVICE_CHANGE_COMPLETE_CALLBACK callback, void *context ) { - FIXME( "(%p, %p, %p, %p) stub!\n", device, data, callback, context ); - return STATUS_NOT_SUPPORTED; + NTSTATUS status; + + TRACE( "(%p, %p, %p, %p) semi-stub!\n", device, data, callback, context ); + + if (!(status = IoReportTargetDeviceChange( device, data ))) callback( context ); + return status; } /*********************************************************************** -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6610
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=148835 Your paranoid android. === build (build log) === error: patch failed: dlls/dinput/tests/driver_hid.c:192 error: patch failed: dlls/dinput/tests/driver_hid.h:50 error: patch failed: dlls/dinput/tests/hotplug.c:229 error: patch failed: dlls/sechost/service.c:1978 error: patch failed: dlls/user32/input.c:28 error: patch failed: include/wine/plugplay.idl:16 error: patch failed: dlls/sechost/service.c:2087 error: patch failed: dlls/sechost/service.c:1996 error: patch failed: dlls/sechost/service.c:1976 error: patch failed: dlls/ntoskrnl.exe/pnp.c:744 error: patch failed: dlls/sechost/service.c:2029 error: patch failed: include/wine/plugplay.idl:41 error: patch failed: programs/plugplay/main.c:65 error: patch failed: dlls/sechost/service.c:1982 error: patch failed: dlls/dinput/tests/hotplug.c:291 Task: Patch failed to apply === debian11 (build log) === error: patch failed: dlls/dinput/tests/driver_hid.c:192 error: patch failed: dlls/dinput/tests/driver_hid.h:50 error: patch failed: dlls/dinput/tests/hotplug.c:229 error: patch failed: dlls/sechost/service.c:1978 error: patch failed: dlls/user32/input.c:28 error: patch failed: include/wine/plugplay.idl:16 error: patch failed: dlls/sechost/service.c:2087 error: patch failed: dlls/sechost/service.c:1996 error: patch failed: dlls/sechost/service.c:1976 error: patch failed: dlls/ntoskrnl.exe/pnp.c:744 error: patch failed: dlls/sechost/service.c:2029 error: patch failed: include/wine/plugplay.idl:41 error: patch failed: programs/plugplay/main.c:65 error: patch failed: dlls/sechost/service.c:1982 error: patch failed: dlls/dinput/tests/hotplug.c:291 Task: Patch failed to apply === debian11b (build log) === error: patch failed: dlls/dinput/tests/driver_hid.c:192 error: patch failed: dlls/dinput/tests/driver_hid.h:50 error: patch failed: dlls/dinput/tests/hotplug.c:229 error: patch failed: dlls/sechost/service.c:1978 error: patch failed: dlls/user32/input.c:28 error: patch failed: include/wine/plugplay.idl:16 error: patch failed: dlls/sechost/service.c:2087 error: patch failed: dlls/sechost/service.c:1996 error: patch failed: dlls/sechost/service.c:1976 error: patch failed: dlls/ntoskrnl.exe/pnp.c:744 error: patch failed: dlls/sechost/service.c:2029 error: patch failed: include/wine/plugplay.idl:41 error: patch failed: programs/plugplay/main.c:65 error: patch failed: dlls/sechost/service.c:1982 error: patch failed: dlls/dinput/tests/hotplug.c:291 Task: Patch failed to apply
participants (3)
-
Marvin -
Rémi Bernon -
Vibhav Pant