From: Vibhav Pant vibhavp@gmail.com
Instead of using the user-passed DEV_BROADCAST_* value to filter incoming notifications, simplify device_notification_details to precisely reflect filtering semantics, additionally making it a public definition in wine/dbt.h. --- dlls/sechost/service.c | 73 +++++++++++++++++++++++++++--------------- dlls/user32/input.c | 32 ++++++------------ include/Makefile.in | 1 + include/wine/dbt.h | 47 +++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 48 deletions(-) create mode 100644 include/wine/dbt.h
diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index 915b0b4ebe0..201b4947d4d 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -36,6 +36,8 @@ #include "svcctl.h" #include "plugplay.h"
+#include "wine/dbt.h" + WINE_DEFAULT_DEBUG_CHANNEL(service);
struct notify_data @@ -1973,17 +1975,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH StartServiceCtrlDispatcherW( const SERVICE_TABLE_E return service_run_main_thread(); }
-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; -}; - static HANDLE device_notify_thread; static struct list device_notify_list = LIST_INIT(device_notify_list);
@@ -1993,23 +1984,33 @@ struct device_notify_registration struct device_notification_details details; };
-static BOOL notification_filter_matches( DEV_BROADCAST_HDR *filter, DEV_BROADCAST_HDR *event ) +static BOOL notification_filter_matches( const struct device_notification_details *filter, const DEV_BROADCAST_HDR *event ) { - if (!filter->dbch_devicetype) return TRUE; - if (filter->dbch_devicetype != event->dbch_devicetype) return FALSE; + if (!filter->devicetype) return TRUE; + if (filter->devicetype != event->dbch_devicetype) return FALSE;
- if (filter->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + switch (filter->devicetype) { - DEV_BROADCAST_DEVICEINTERFACE_W *filter_iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)filter; - DEV_BROADCAST_DEVICEINTERFACE_W *event_iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)event; - if (filter_iface->dbcc_size == offsetof(DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_classguid)) return TRUE; - return IsEqualGUID( &filter_iface->dbcc_classguid, &event_iface->dbcc_classguid ); + case DBT_DEVTYP_DEVICEINTERFACE: + { + DEV_BROADCAST_DEVICEINTERFACE_W *event_iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)event; + if (filter->filter.deviceinterface.all_classes) return TRUE; + return IsEqualGUID( &filter->filter.deviceinterface.class, + &event_iface->dbcc_classguid ); + } + default: + FIXME( "Filter devicetype %lu not implemented \n", filter->devicetype ); }
- FIXME( "Filter dbch_devicetype %lu not implemented\n", filter->dbch_devicetype ); return TRUE; }
+struct device_notification_details_with_hdevnotify +{ + HDEVNOTIFY notify_handle; + struct device_notification_details details; +}; + static DWORD WINAPI device_notify_proc( void *arg ) { WCHAR endpoint[] = L"\pipe\wine_plugplay"; @@ -2017,7 +2018,7 @@ static DWORD WINAPI device_notify_proc( void *arg ) RPC_WSTR binding_str; DWORD err = ERROR_SUCCESS; struct device_notify_registration *registration; - struct device_notification_details *details_copy; + struct device_notification_details_with_hdevnotify *details_copy; unsigned int details_copy_nelems, details_copy_size; plugplay_rpc_handle handle = NULL; DWORD code = 0; @@ -2084,7 +2085,8 @@ static DWORD WINAPI device_notify_proc( void *arg ) EnterCriticalSection( &service_cs ); LIST_FOR_EACH_ENTRY(registration, &device_notify_list, struct device_notify_registration, entry) { - details_copy[i++] = registration->details; + details_copy[i].details = registration->details; + details_copy[i++].notify_handle = registration; details_copy_nelems++; if (i == details_copy_size) { @@ -2096,8 +2098,10 @@ 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 ); + const struct device_notification_details *details = &details_copy[i].details; + + if (!notification_filter_matches( details, (DEV_BROADCAST_HDR *)buf )) continue; + details->cb( details->handle, code, (DEV_BROADCAST_HDR *)buf ); } MIDL_user_free(buf); } @@ -2116,6 +2120,24 @@ static DWORD WINAPI device_notify_proc( void *arg ) return 0; }
+static inline const char * +debugstr_device_notification_details( const struct device_notification_details *details ) +{ + if (!details) return "(null)"; + switch (details->devicetype) + { + case DBT_DEVTYP_DEVICEINTERFACE: + if (details->filter.deviceinterface.all_classes) + return wine_dbg_sprintf( "{%p %p DBT_DEVTYP_DEVICEINTERFACE {all_classes=1}}", + details->cb, details->handle ); + return wine_dbg_sprintf( "{%p %p DBT_DEVTYP_DEVICEINTERFACE {%s}}", details->cb, + details->handle, + debugstr_guid( &details->filter.deviceinterface.class ) ); + default: + return wine_dbg_sprintf( "{%p %p (unknown %#lx)}", details->cb, details->handle, details->devicetype); + } +} + /****************************************************************************** * I_ScRegisterDeviceNotification (sechost.@) */ @@ -2124,7 +2146,8 @@ HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( struct device_notification_det { struct device_notify_registration *registration;
- TRACE("callback %p, handle %p, filter %p, flags %#lx\n", details->cb, details->handle, filter, flags); + TRACE( "details %s, filter %p, flags %#lx\n", debugstr_device_notification_details( details ), + filter, flags );
if (!(registration = malloc( sizeof(struct device_notify_registration) ))) { diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 108592f018f..f0d33cf7540 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -24,11 +24,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "ntstatus.h" +#define WIN32_NO_STATUS #include "user_private.h" #include "dbt.h" #include "wine/server.h" #include "wine/debug.h"
+#include "wine/dbt.h" + WINE_DEFAULT_DEBUG_CHANNEL(win); WINE_DECLARE_DEBUG_CHANNEL(keyboard);
@@ -530,10 +534,8 @@ static DWORD CALLBACK devnotify_window_callbackA(HANDLE handle, DWORD flags, DEV free( ifaceA ); return 0; } - default: FIXME( "unimplemented W to A mapping for %#lx\n", header->dbch_devicetype ); - /* fall through */ case DBT_DEVTYP_HANDLE: case DBT_DEVTYP_OEM: break; @@ -550,21 +552,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,7 +567,7 @@ HDEVNOTIFY WINAPI RegisterDeviceNotificationA( HANDLE handle, void *filter, DWOR */ HDEVNOTIFY WINAPI RegisterDeviceNotificationW( HANDLE handle, void *filter, DWORD flags ) { - struct device_notification_details details; + struct device_notification_details details = {0}; DEV_BROADCAST_HDR *header = filter;
TRACE("handle %p, filter %p, flags %#lx\n", handle, filter, flags); @@ -597,21 +584,20 @@ HDEVNOTIFY WINAPI RegisterDeviceNotificationW( HANDLE handle, void *filter, DWOR return NULL; }
- if (!header) details.filter.header.dbch_devicetype = 0; + if (!header) details.devicetype = 0; else if (header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { DEV_BROADCAST_DEVICEINTERFACE_W *iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)header; - details.filter.iface = *iface;
+ details.devicetype = DBT_DEVTYP_DEVICEINTERFACE; if (flags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES) - details.filter.iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_classguid ); + details.filter.deviceinterface.all_classes = TRUE; else - details.filter.iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_name ); + details.filter.deviceinterface.class = iface->dbcc_classguid; } else if (header->dbch_devicetype == DBT_DEVTYP_HANDLE) { FIXME( "DBT_DEVTYP_HANDLE filter type not implemented\n" ); - details.filter.header.dbch_devicetype = 0; } else { diff --git a/include/Makefile.in b/include/Makefile.in index 000214484ed..cc35c12827c 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -901,6 +901,7 @@ SOURCES = \ wine/asm.h \ wine/atsvc.idl \ wine/condrv.h \ + wine/dbt.h \ wine/dcetypes.idl \ wine/debug.h \ wine/dplaysp.h \ diff --git a/include/wine/dbt.h b/include/wine/dbt.h new file mode 100644 index 00000000000..702fda17126 --- /dev/null +++ b/include/wine/dbt.h @@ -0,0 +1,47 @@ +/* + * Definitions for registering device notifications + * + * Copyright 2024 Vibhav Pant + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_WINE_DBT_H_ +#define __WINE_WINE_DBT_H_ + +#include <wine/debug.h> + +struct device_notification_details +{ + DWORD (CALLBACK *cb)(HANDLE handle, DWORD flags, DEV_BROADCAST_HDR *header); + HANDLE handle; + DWORD devicetype; + union + { + struct + { + /* Used to implement DEVICE_NOTIFY_ALL_INTERFACE_CLASSES. If true, the class field below + * should be ignored. */ + BOOL all_classes; + GUID class; + } deviceinterface; + } filter; +}; + +extern HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( struct device_notification_details *details, + void *filter, DWORD flags ); +extern BOOL WINAPI I_ScUnregisterDeviceNotification( HDEVNOTIFY handle ); + +#endif /* __WINE_WINE_DBT_H_ */
From: Vibhav Pant vibhavp@gmail.com
DBT_DEVTYP_HANDLE notifications are registered by providing the file path for the user-provided handle in device_notification_details. The device path is sent with dbch_reserved set to an offset in dbch_data pointing to the path for the device the notification originates from. --- dlls/sechost/service.c | 21 ++++++++++- dlls/user32/input.c | 75 ++++++++++++++++++++++++++++++++++++++-- include/wine/dbt.h | 8 +++++ programs/plugplay/main.c | 8 +++-- 4 files changed, 106 insertions(+), 6 deletions(-)
diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index 201b4947d4d..c5901d7e3e5 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -31,6 +31,7 @@
#include "wine/debug.h" #include "wine/exception.h" +#include "wine/heap.h" #include "wine/list.h"
#include "svcctl.h" @@ -1998,6 +1999,13 @@ static BOOL notification_filter_matches( const struct device_notification_detail return IsEqualGUID( &filter->filter.deviceinterface.class, &event_iface->dbcc_classguid ); } + case DBT_DEVTYP_HANDLE: + { + DEV_BROADCAST_HANDLE *event_handle = (DEV_BROADCAST_HANDLE *)event; + const WCHAR *device_path = (const WCHAR *)&event_handle->dbch_data[event_handle->dbch_reserved]; + + return !wcsicmp( device_path, filter->filter.device.name_info->Name.Buffer ); + } default: FIXME( "Filter devicetype %lu not implemented \n", filter->devicetype ); } @@ -2098,9 +2106,15 @@ static DWORD WINAPI device_notify_proc( void *arg )
for (i = 0; i < details_copy_nelems; i++) { - const struct device_notification_details *details = &details_copy[i].details; + struct device_notification_details *details = &details_copy[i].details;
if (!notification_filter_matches( details, (DEV_BROADCAST_HDR *)buf )) continue; + if (details->devicetype == DBT_DEVTYP_HANDLE) + { + DEV_BROADCAST_HANDLE *handle = (DEV_BROADCAST_HANDLE *)buf; + handle->dbch_handle = details->filter.device.device; + handle->dbch_hdevnotify = details_copy[i].notify_handle; + } details->cb( details->handle, code, (DEV_BROADCAST_HDR *)buf ); } MIDL_user_free(buf); @@ -2133,6 +2147,9 @@ debugstr_device_notification_details( const struct device_notification_details * return wine_dbg_sprintf( "{%p %p DBT_DEVTYP_DEVICEINTERFACE {%s}}", details->cb, details->handle, debugstr_guid( &details->filter.deviceinterface.class ) ); + case DBT_DEVTYP_HANDLE: + return wine_dbg_sprintf( "{%p %p DBT_DEVTYP_HANDLE {%p %p}}", details->cb, details->handle, + details->filter.device.name_info, details->filter.device.device ); default: return wine_dbg_sprintf( "{%p %p (unknown %#lx)}", details->cb, details->handle, details->devicetype); } @@ -2183,6 +2200,8 @@ BOOL WINAPI I_ScUnregisterDeviceNotification( HDEVNOTIFY handle ) EnterCriticalSection( &service_cs ); list_remove( ®istration->entry ); LeaveCriticalSection(&service_cs); + if (registration->details.devicetype == DBT_DEVTYP_HANDLE) + heap_free( registration->details.filter.device.name_info ); free( registration ); return TRUE; } diff --git a/dlls/user32/input.c b/dlls/user32/input.c index f0d33cf7540..3625219a079 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -30,6 +30,7 @@ #include "dbt.h" #include "wine/server.h" #include "wine/debug.h" +#include "wine/heap.h"
#include "wine/dbt.h"
@@ -534,11 +535,51 @@ static DWORD CALLBACK devnotify_window_callbackA(HANDLE handle, DWORD flags, DEV free( ifaceA ); return 0; } - default: - FIXME( "unimplemented W to A mapping for %#lx\n", header->dbch_devicetype ); + case DBT_DEVTYP_HANDLE: + { + const DEV_BROADCAST_HANDLE *handleW = (const DEV_BROADCAST_HANDLE *)header; + DEV_BROADCAST_HANDLE *handleA; + size_t lenA = 0; + size_t name_lenW = handleW->dbch_nameoffset == -1 + ? 0 + : wcslen( (WCHAR *)&handleW->dbch_data[handleW->dbch_nameoffset] ); + size_t data_size = handleW->dbch_nameoffset == -1 + ? handleW->dbch_reserved + : handleW->dbch_nameoffset + ( name_lenW * 3 + 1 ); + + handleA = malloc( offsetof( DEV_BROADCAST_HANDLE, dbch_data[data_size] )); + if (!handleA) + return 0; + + handleA->dbch_devicetype = DBT_DEVTYP_HANDLE; + if (handleW->dbch_nameoffset != -1) + { + lenA = WideCharToMultiByte( + CP_ACP, 0, (WCHAR *)&handleW->dbch_data[handleW->dbch_nameoffset], name_lenW + 1, + (CHAR *)&handleA->dbch_data[handleW->dbch_nameoffset], name_lenW * 3 + 1, NULL, + NULL ); + handleA->dbch_size = offsetof( DEV_BROADCAST_HANDLE, dbch_data[handleW->dbch_nameoffset + lenA + 1] ); + } + else + handleA->dbch_size = offsetof(DEV_BROADCAST_HANDLE, dbch_data[handleW->dbch_reserved]); + + handleA->dbch_reserved = 0; + handleA->dbch_handle = handleW->dbch_handle; + handleA->dbch_hdevnotify = handleW->dbch_hdevnotify; + handleA->dbch_eventguid = handleW->dbch_eventguid; + handleA->dbch_nameoffset = handleW->dbch_nameoffset; + memcpy( &handleA->dbch_data, &handleW->dbch_data, + handleW->dbch_nameoffset == -1 ? data_size : handleW->dbch_nameoffset ); + 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 ); } }
@@ -597,7 +638,35 @@ HDEVNOTIFY WINAPI RegisterDeviceNotificationW( HANDLE handle, void *filter, DWOR } else if (header->dbch_devicetype == DBT_DEVTYP_HANDLE) { - FIXME( "DBT_DEVTYP_HANDLE filter type not implemented\n" ); + OBJECT_NAME_INFORMATION *name_info; + DEV_BROADCAST_HANDLE *handle = (DEV_BROADCAST_HANDLE *)header; + HANDLE device = handle->dbch_handle; + NTSTATUS status; + DWORD size; + + details.devicetype = DBT_DEVTYP_HANDLE; + status = NtQueryObject( device, ObjectNameInformation, NULL, 0, &size ); + if (status != STATUS_INFO_LENGTH_MISMATCH) + { + SetLastError( RtlNtStatusToDosError( status ) ); + return NULL; + } + name_info = heap_alloc( size ); + if (!name_info) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return NULL; + } + + status = NtQueryObject( device, ObjectNameInformation, name_info, size, 0 ); + if (status != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError( status )); + heap_free( name_info ); + return NULL; + } + details.filter.device.name_info = name_info; + details.filter.device.device = handle->dbch_handle; } else { diff --git a/include/wine/dbt.h b/include/wine/dbt.h index 702fda17126..b8a82a87b08 100644 --- a/include/wine/dbt.h +++ b/include/wine/dbt.h @@ -37,6 +37,14 @@ struct device_notification_details BOOL all_classes; GUID class; } deviceinterface; + struct + { + /* The path for the device file the notification is originating from. */ + OBJECT_NAME_INFORMATION *name_info; + /* HANDLE to the device the event originates from. Is passed to the callback as-is, even + * if the user has closed this handle. */ + HANDLE device; + } device; } filter; };
diff --git a/programs/plugplay/main.c b/programs/plugplay/main.c index 8426f2204a3..1242b01ba2a 100644 --- a/programs/plugplay/main.c +++ b/programs/plugplay/main.c @@ -141,9 +141,13 @@ void __cdecl plugplay_send_event( DWORD code, const BYTE *data, unsigned int siz { 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/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- dlls/ntoskrnl.exe/pnp.c | 60 +++++++++++++++++++++++++++++ include/ddk/wdm.h | 10 +++++ 3 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index e9ad2aa7e74..690b4e166c3 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -465,7 +465,7 @@ @ stub IoReportHalResourceUsage @ stdcall IoReportResourceForDetection(ptr ptr long ptr ptr long ptr) @ stdcall IoReportResourceUsage(ptr ptr ptr long ptr ptr long long ptr) -@ stub IoReportTargetDeviceChange +@ stdcall IoReportTargetDeviceChange(ptr ptr) @ stub IoReportTargetDeviceChangeAsynchronous @ stub IoRequestDeviceEject @ stdcall IoReuseIrp(ptr long) diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index cbd5cf6ff2a..16837c9cd57 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -1001,6 +1001,66 @@ NTSTATUS WINAPI IoRegisterDeviceInterface(DEVICE_OBJECT *device, const GUID *cla return status; }
+/*********************************************************************** + * IoReportTargetDeviceChange (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI IoReportTargetDeviceChange( DEVICE_OBJECT *pdo, VOID *n ) +{ + OBJECT_NAME_INFORMATION *name_info; + DEV_BROADCAST_HANDLE *event_handle; + DWORD custom_buf_size, data_size; + TARGET_DEVICE_CUSTOM_NOTIFICATION *notification = n; + ULONG size; + NTSTATUS ret; + + TRACE( "(%p, %p)\n", pdo, n ); + + if (notification->Version != 1) + return STATUS_INVALID_PARAMETER; + + ret = ObQueryNameString( pdo, NULL, 0, &size ); + if (ret != STATUS_INFO_LENGTH_MISMATCH) + return ret; + + name_info = heap_alloc( size ); + if (!name_info) + return STATUS_NO_MEMORY; + + ret = ObQueryNameString( pdo, name_info, size, &size ); + if ( ret != STATUS_SUCCESS ) return ret; + + custom_buf_size = notification->Size - offsetof(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer) + 1; + data_size = custom_buf_size + name_info->Name.Length * sizeof( WCHAR ) + 1; + if (notification->NameBufferOffset != -1 && notification->CustomDataBuffer[custom_buf_size - 1] != '\0') + data_size++; + + event_handle = heap_alloc_zero( offsetof( DEV_BROADCAST_HANDLE, dbch_data[data_size] ) ); + if (!event_handle) + { + heap_free( name_info ); + return STATUS_NO_MEMORY; + } + event_handle->dbch_size = offsetof( DEV_BROADCAST_HANDLE, dbch_data[data_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, custom_buf_size ); + if (notification->NameBufferOffset != -1 && notification->CustomDataBuffer[custom_buf_size - 1] != '\0') + notification->CustomDataBuffer[custom_buf_size++] = '\0'; + + memcpy( &event_handle->dbch_data[custom_buf_size], name_info->Name.Buffer, + name_info->Name.Length * sizeof( WCHAR ) + 1); + event_handle->dbch_reserved = custom_buf_size; + heap_free( name_info ); + + /* TODO: Note that this is not really synchronous. This will merely queue up an event in the + * plugplay service, which will be asynchronously broadcast to all listeners. */ + send_devicechange( DBT_CUSTOMEVENT, (BYTE *)event_handle, event_handle->dbch_size ); + heap_free( event_handle ); + + return STATUS_SUCCESS; +} + /*********************************************************************** * IoOpenDeviceRegistryKey (NTOSKRNL.EXE.@) */ diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index e0c21d0ccfd..23ac13018e7 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1613,6 +1613,15 @@ 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 +1790,7 @@ 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 *); void WINAPI IoReuseIrp(IRP*,NTSTATUS); NTSTATUS WINAPI IoSetDeviceInterfaceState(UNICODE_STRING*,BOOLEAN); NTSTATUS WINAPI IoSetDevicePropertyData(DEVICE_OBJECT*,const DEVPROPKEY*,LCID,ULONG,DEVPROPTYPE,ULONG,void*);
From: Vibhav Pant vibhavp@gmail.com
--- dlls/ntoskrnl.exe/tests/driver.h | 38 ++++++++++++ dlls/ntoskrnl.exe/tests/driver_pnp.c | 43 ++++++++++++++ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 86 ++++++++++++++++++++++++++-- 3 files changed, 162 insertions(+), 5 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h index 9c51af0a4c6..a3a3c622097 100644 --- a/dlls/ntoskrnl.exe/tests/driver.h +++ b/dlls/ntoskrnl.exe/tests/driver.h @@ -78,6 +78,44 @@ struct return_status_params
static const GUID control_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc0}};
+static const struct +{ + GUID eventguid; + BYTE *data; + SIZE_T data_size; + const WCHAR *str; + const CHAR *strA; +} custom_events[] = { + { + {0xdeadbeef, 0xdead, 0xbeef, { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0x01}}, + NULL, + 0, + NULL, + NULL, + }, + { + {0xdeadbeef, 0xdead, 0xbeef, { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0x02}}, + (BYTE *)(&custom_events[1].eventguid), + sizeof(GUID), + NULL, + NULL, + }, + { + {0xdeadbeef, 0xdead, 0xbeef, { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0x03}}, + (BYTE *)(&custom_events[2].eventguid), + sizeof(GUID), + L"Wine is not an emulator", + "Wine is not an emulator" + }, + { + {0xdeadbeef, 0xdead, 0xbeef, { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0x04}}, + NULL, + 0, + L"Wine is not an emulator", + "Wine is not an emulator" + } +}; + #define SERVER_LISTEN_PORT 9374 #define CLIENT_LISTEN_PORT 9375
diff --git a/dlls/ntoskrnl.exe/tests/driver_pnp.c b/dlls/ntoskrnl.exe/tests/driver_pnp.c index 70678b1a45c..b3e80c9f6b6 100644 --- a/dlls/ntoskrnl.exe/tests/driver_pnp.c +++ b/dlls/ntoskrnl.exe/tests/driver_pnp.c @@ -686,6 +686,48 @@ static void test_device_properties( DEVICE_OBJECT *device ) return; }
+static void test_devicechange( DEVICE_OBJECT *obj ) +{ + INT i; + + for (i = 0; i < ARRAY_SIZE( custom_events ); i++) + { + TARGET_DEVICE_CUSTOM_NOTIFICATION *notif = NULL; + SIZE_T size = offsetof(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer) + 1; + NTSTATUS status; + + winetest_push_context( "custom_events %d", i + 1 ); + if (custom_events[i].data) + size += custom_events[i].data_size - 1; + + if (custom_events[i].str) + size += wcslen(custom_events[i].str) * sizeof(WCHAR) + (custom_events[i].data ? 1 : 0); + + notif = ExAllocatePool( PagedPool, size ); + ok( notif != NULL, "Failed to allocate memory for notification.\n" ); + notif->Version = 1; + notif->Size = size; + notif->Event = custom_events[i].eventguid; + notif->FileObject = NULL; + + if (custom_events[i].data) + memcpy(notif->CustomDataBuffer, custom_events[i].data, custom_events[i].data_size); + + if (custom_events[i].str) + { + notif->NameBufferOffset = custom_events[i].data_size; + wcscpy( (WCHAR *)¬if->CustomDataBuffer[notif->NameBufferOffset], custom_events[i].str ); + } + else + notif->NameBufferOffset = -1; + + status = IoReportTargetDeviceChange( obj, notif ); + ok( status == STATUS_SUCCESS, "IoReportTargetDeviceChange failed, status %#lx size %d,\n", status, notif->Size ); + ExFreePool( notif ); + winetest_pop_context(); + } +} + static NTSTATUS fdo_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG code) { switch (code) @@ -693,6 +735,7 @@ static NTSTATUS fdo_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG code) case IOCTL_WINETEST_BUS_MAIN: test_bus_query(); test_device_properties( bus_pdo ); + test_devicechange( bus_pdo ); return STATUS_SUCCESS;
case IOCTL_WINETEST_BUS_REGISTER_IFACE: diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 48deda7c455..fd7ee193a95 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1356,7 +1356,10 @@ static void add_file_to_catalog(HANDLE catalog, const WCHAR *file) static const GUID bus_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc1}}; static const GUID child_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc2}};
-static unsigned int got_bus_arrival, got_bus_removal, got_child_arrival, got_child_removal; +static unsigned int got_bus_arrival, got_bus_removal, got_child_arrival, got_child_removal, got_custom_event; + +static HDEVNOTIFY notify_handle_custom; +static HANDLE bus;
static LRESULT WINAPI device_notify_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) { @@ -1427,6 +1430,63 @@ static LRESULT WINAPI device_notify_proc(HWND window, UINT message, WPARAM wpara } break; } + + case DBT_CUSTOMEVENT: + { + const DEV_BROADCAST_HANDLE *handle = (const DEV_BROADCAST_HANDLE *)lparam; + INT i; + + if (handle->dbch_devicetype != DBT_DEVTYP_HANDLE) + break; + + if (winetest_debug > 1) trace("custom device event\n"); + + ok( handle->dbch_handle == bus, "Expected dbch_handle %p, got %p.\n", bus, handle->dbch_handle ); + + for (i = 0; i < ARRAY_SIZE( custom_events ); i++) + { + const GUID *guid = &custom_events[i].eventguid; + DWORD expect_size; + DWORD size = 0; + + if (!IsEqualGUID( &handle->dbch_eventguid, guid )) + continue; + + winetest_push_context( "custom_events %d", i + 1 ); + got_custom_event++; + + if (custom_events[i].data) size = custom_events[i].data_size; + if (custom_events[i].strA) size += strlen( custom_events[i].strA ); + + expect_size = offsetof( DEV_BROADCAST_HANDLE, dbch_data[size] ); + ok( handle->dbch_size >= expect_size, + "Unexpected dbch_size=%lu, expected atleast %lu.\n", handle->dbch_size, + expect_size ); + ok( handle->dbch_handle == bus, "Expected dbch_handle=%p, got %p.\n", bus, + handle->dbch_handle ); + ok( handle->dbch_hdevnotify == notify_handle_custom, + "Expected dbch_hdevnotify=%p, got %p.\n", notify_handle_custom, + handle->dbch_hdevnotify ); + + if (handle->dbch_size < expect_size) continue; + + if (custom_events[i].data) + ok( !memcmp( handle->dbch_data, custom_events[i].data, custom_events[i].data_size ), + "Unexpected dbch_data contents.\n"); + + if (custom_events[i].strA) + { + const CHAR *strA = (CHAR *)&handle->dbch_data[handle->dbch_nameoffset]; + + ok( handle->dbch_nameoffset != -1, "Expected dbch_nameoffset = %lu, got -1.\n", + handle->dbch_nameoffset ); + ok( !strcmp( strA, custom_events[i].strA ), "Expected %s, got %s\n", + debugstr_a( custom_events[i].strA ), debugstr_a( strA ) ); + } + winetest_pop_context(); + } + break; + } } return DefWindowProcA(window, message, wparam, lparam); } @@ -1456,11 +1516,16 @@ static void test_pnp_devices(void) SP_DEVICE_INTERFACE_DETAIL_DATA_A *iface_detail = (void *)buffer; SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; SP_DEVINFO_DATA device = {sizeof(device)}; - DEV_BROADCAST_DEVICEINTERFACE_A filter = + DEV_BROADCAST_DEVICEINTERFACE_A filter_iface = { - .dbcc_size = sizeof(filter), + .dbcc_size = sizeof(filter_iface), .dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE, }; + DEV_BROADCAST_HANDLE filter_handle = + { + .dbch_size = sizeof(filter_handle), + .dbch_devicetype = DBT_DEVTYP_HANDLE, + }; static const WNDCLASSA class = { .lpszClassName = "ntoskrnl_test_wc", @@ -1468,7 +1533,7 @@ static void test_pnp_devices(void) }; HDEVNOTIFY notify_handle; DWORD size, type, dword; - HANDLE bus, child, tmp; + HANDLE child, tmp; OBJECT_ATTRIBUTES attr; UNICODE_STRING string; OVERLAPPED ovl = {0}; @@ -1477,12 +1542,13 @@ static void test_pnp_devices(void) HWND window; BOOL ret; int id; + INT i;
ret = RegisterClassA(&class); ok(ret, "failed to register class\n"); window = CreateWindowA("ntoskrnl_test_wc", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); ok(!!window, "failed to create window\n"); - notify_handle = RegisterDeviceNotificationA(window, &filter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); + notify_handle = RegisterDeviceNotificationA(window, &filter_iface, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); ok(!!notify_handle, "failed to register window, error %lu\n", GetLastError());
set = SetupDiGetClassDevsA(&control_class, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); @@ -1513,8 +1579,17 @@ static void test_pnp_devices(void) bus = CreateFileA(iface_detail->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, NULL); ok(bus != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError());
+ filter_handle.dbch_handle = bus; + notify_handle_custom = RegisterDeviceNotificationA(window, &filter_handle, 0); + ok(!!notify_handle_custom, "failed to register for device notifications, error %lu\n", GetLastError()); + ret = DeviceIoControl(bus, IOCTL_WINETEST_BUS_MAIN, NULL, 0, NULL, 0, &size, NULL); ok(ret, "got error %lu\n", GetLastError()); + for (i = 0; i < ARRAY_SIZE(custom_events); i++) + pump_messages(); + ok(got_custom_event == ARRAY_SIZE(custom_events), + "got %u custom event messages, expected %lu\n", got_custom_event, + ARRAY_SIZE(custom_events));
/* Test IoRegisterDeviceInterface() and IoSetDeviceInterfaceState(). */
@@ -1734,6 +1809,7 @@ static void test_pnp_devices(void) CloseHandle(bus);
UnregisterDeviceNotification(notify_handle); + UnregisterDeviceNotification(notify_handle_custom); DestroyWindow(window); UnregisterClassA("ntoskrnl_test_wc", GetModuleHandleA(NULL)); }
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 tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=148169
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w7u_adm (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w7u_el (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w8 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w8adm (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w864 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w1064v1507 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w1064v1809 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w1064_tsign (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w10pro64 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w10pro64_en_AE_u8 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w11pro64 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w7pro64 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w864 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w1064v1507 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w1064v1809 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w1064_2qxl (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w1064_adm (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w1064_tsign (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w10pro64 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w10pro64_ar (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w10pro64_ja (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w10pro64_zh_CN (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w11pro64_amd (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver' does not exist.
=== w7u_2qxl (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w7u_adm (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w7u_el (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w8 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w8adm (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w864 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w1064v1507 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w1064v1809 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w1064_tsign (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w10pro64 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w10pro64_en_AE_u8 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w11pro64 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w7pro64 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w864 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w1064v1507 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w1064v1809 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w1064_2qxl (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w1064_adm (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w1064_tsign (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w10pro64 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w10pro64_ar (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w10pro64_ja (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w10pro64_zh_CN (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w11pro64_amd (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver2' does not exist.
=== w7u_2qxl (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w7u_adm (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w7u_el (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w8 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w8adm (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w864 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w1064v1507 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w1064v1809 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w1064_tsign (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w10pro64 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w10pro64_en_AE_u8 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w11pro64 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w7pro64 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w864 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w1064v1507 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w1064v1809 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w1064_2qxl (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w1064_adm (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w1064_tsign (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w10pro64 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w10pro64_ar (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w10pro64_ja (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w10pro64_zh_CN (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w11pro64_amd (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver3' does not exist.
=== w7u_2qxl (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w7u_adm (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w7u_el (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w8 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w8adm (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w864 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w1064v1507 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w1064v1809 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w1064_tsign (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w10pro64 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w10pro64_en_AE_u8 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w11pro64 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w7pro64 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w864 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w1064v1507 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w1064v1809 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w1064_2qxl (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w1064_adm (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w1064_tsign (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w10pro64 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w10pro64_ar (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w10pro64_ja (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w10pro64_zh_CN (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w11pro64_amd (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_netio' does not exist.
=== w7u_2qxl (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w7u_adm (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w7u_el (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w8 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w8adm (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w864 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w1064v1507 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w1064v1809 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w1064_tsign (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w10pro64 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w10pro64_en_AE_u8 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w11pro64 (32 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w7pro64 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w864 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w1064v1507 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w1064v1809 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w1064_2qxl (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w1064_adm (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w1064_tsign (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w10pro64 (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w10pro64_ar (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w10pro64_ja (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w10pro64_zh_CN (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w11pro64_amd (64 bit report) ===
ntoskrnl.exe: Fatal: test 'driver_pnp' does not exist.
=== w7u_2qxl (32 bit report) ===
ntoskrnl.exe: ntoskrnl.c:1584: Test failed: failed to register for device notifications, error 1066 ntoskrnl.c:1590: Test failed: got 0 custom event messages, expected 4 ntoskrnl.c:1719: Test failed: got size 488 ntoskrnl.c:1720: Test failed: got hardware IDs "\x05\x00\x00\x00\\x00w\x00\x04\x00\x00\x00e\x00t\x00e\x00s\x00\x04\x00\x00\x00\xbc\xed$\x00\x00\x00\x00\x00R\x00O\x00O\x00T\x00\\x00W\x00I\x00N\x00E\x00T\x00E\x00S\x00T\x00\\x000\x00\x00\x00i\x00n\x00e\x00t\x00e\x00s\x00t\x00.\x00i\x00n\x00f\x00\x00\x00\x00\x00\x00\x00\xcaj\xcft-\xee\xc8"... ntoskrnl.c:1727: Test failed: got size 488 ntoskrnl.c:1728: Test failed: got container ID L"" ntoskrnl.c:1734: Test failed: got size 488 ntoskrnl.c:1735: Test failed: got compatible IDs "\x05\x00\x00\x00\\x00w\x00\x04\x00\x00\x00e\x00t\x00e\x00s\x00\x04\x00\x00\x00\xbc\xed$\x00\x00\x00\x00\x00R\x00O\x00O\x00T\x00\\x00W\x00I\x00N\x00E\x00T\x00E\x00S\x00T\x00\\x000\x00\x00\x00i\x00n\x00e\x00t\x00e\x00s\x00t\x00.\x00i\x00n\x00f\x00\x00\x00\x00\x00\x00\x00\xcaj\xcft-\xee\xc8"... ntoskrnl.c:1769: Test failed: got size 488 ntoskrnl.c:1779: Test failed: got size 488 ntoskrnl.c:1798: Test failed: got size 488
=== w7u_el (32 bit report) ===
ntoskrnl.exe: ntoskrnl.c:1584: Test failed: failed to register for device notifications, error 1066 ntoskrnl.c:1590: Test failed: got 0 custom event messages, expected 4 ntoskrnl.c:1719: Test failed: got size 488 ntoskrnl.c:1720: Test failed: got hardware IDs "\x05\x00\x00\x00\\x00w\x00\x04\x00\x00\x00e\x00t\x00e\x00s\x00\x04\x00\x00\x00\xa4\xedU\x00\x00\x00\x00\x00R\x00O\x00O\x00T\x00\\x00W\x00I\x00N\x00E\x00T\x00E\x00S\x00T\x00\\x000\x00\x00\x00i\x00n\x00e\x00t\x00e\x00s\x00t\x00.\x00i\x00n\x00f\x00\x00\x00\x00\x00\x00\x00\xcaj\x0euN\x88\x96"... ntoskrnl.c:1727: Test failed: got size 488 ntoskrnl.c:1728: Test failed: got container ID L"" ntoskrnl.c:1734: Test failed: got size 488 ntoskrnl.c:1735: Test failed: got compatible IDs "\x05\x00\x00\x00\\x00w\x00\x04\x00\x00\x00e\x00t\x00e\x00s\x00\x04\x00\x00\x00\xa4\xedU\x00\x00\x00\x00\x00R\x00O\x00O\x00T\x00\\x00W\x00I\x00N\x00E\x00T\x00E\x00S\x00T\x00\\x000\x00\x00\x00i\x00n\x00e\x00t\x00e\x00s\x00t\x00.\x00i\x00n\x00f\x00\x00\x00\x00\x00\x00\x00\xcaj\x0euN\x88\x96"... ntoskrnl.c:1769: Test failed: got size 488 ntoskrnl.c:1779: Test failed: got size 488 ntoskrnl.c:1798: Test failed: got size 488
=== w8 (testbot log) ===
WineRunTask.pl:error: An error occurred while waiting for the test to complete: the 2916 process does not exist or is not a child process WineRunTask.pl:error: The test VM has crashed, rebooted or lost connectivity (or the TestAgent server died)
=== w1064_tsign (testbot log) ===
WineRunTask.pl:error: An error occurred while waiting for the test to complete: the 5804 process does not exist or is not a child process WineRunTask.pl:error: The test VM has crashed, rebooted or lost connectivity (or the TestAgent server died)
=== debian11 (32 bit report) ===
user32: msg.c:6935: Test failed: SetFocus(hwnd) on a button: 3: the winevent_hook 0x8005 was expected, but got hook 0x0005 instead msg.c:6935: Test failed: SetFocus(hwnd) on a button: 3: the winevent_hook 0x8005 was expected, but got winevent_hook 0x0003 instead msg.c:6935: Test failed: SetFocus(hwnd) on a button: 3: the winevent_hook 0x8005 was expected, but got msg 0x030f instead msg.c:6935: Test failed: SetFocus(hwnd) on a button: 3: the winevent_hook 0x8005 was expected, but got msg 0x001c instead msg.c:6935: Test failed: SetFocus(hwnd) on a button: 3: the winevent_hook 0x8005 was expected, but got msg 0x0086 instead msg.c:6935: Test failed: SetFocus(hwnd) on a button: 3: the winevent_hook 0x8005 was expected, but got msg 0x0006 instead msg.c:6935: Test failed: SetFocus(hwnd) on a button: 3: the winevent_hook 0x8005 was expected, but got hook 0x0009 instead
=== debian11b (64 bit WoW report) ===
ddraw: ddraw2.c:3814: Test failed: Expected (0,0)-(640,480), got (0,0)-(1024,768). ddraw2.c:3839: Test failed: Expected (0,0)-(640,480), got (0,0)-(1024,768).