From: Vibhav Pant vibhavp@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*);
From: Rémi Bernon rbernon@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 ); }
From: Rémi Bernon rbernon@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]"),
From: Rémi Bernon rbernon@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);
From: Rémi Bernon rbernon@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; }
From: Rémi Bernon rbernon@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; }
From: Rémi Bernon rbernon@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;
From: Vibhav Pant vibhavp@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 );
From: Vibhav Pant vibhavp@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; }
This merge request was approved by Rémi Bernon.
From: Vibhav Pant vibhavp@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 ); } }
From: Vibhav Pant vibhavp@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; }
/***********************************************************************
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