From: Vibhav Pant vibhavp@gmail.com
--- dlls/ntoskrnl.exe/pnp.c | 57 +++++++++++++++++++++++++--- dlls/ntoskrnl.exe/tests/driver_pnp.c | 2 +- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 8 ++-- 3 files changed, 56 insertions(+), 11 deletions(-)
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index bb10c27fbee..2ab3ec3ba33 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( DWORD code, const WCHAR *path, void *data, unsigned int size ) { __TRY { - plugplay_send_event( code, data, size ); + plugplay_send_event( code, path, 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( enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, NULL, broadcast, len ); heap_free( broadcast ); } return ret; @@ -1001,10 +1001,55 @@ NTSTATUS WINAPI IoRegisterDeviceInterface(DEVICE_OBJECT *device, const GUID *cla return status; }
-NTSTATUS WINAPI IoReportTargetDeviceChange( DEVICE_OBJECT *pdo, void *notification ) +/*********************************************************************** + * IoReportTargetDeviceChange (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI IoReportTargetDeviceChange( DEVICE_OBJECT *pdo, VOID *n ) { - FIXME( "(%p, %p) stub!\n", pdo, notification ); - return STATUS_NOT_SUPPORTED; + OBJECT_NAME_INFORMATION *name_info; + DEV_BROADCAST_HANDLE *event_handle; + DWORD 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; + + data_size = notification->Size - offsetof(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer); + if (notification->NameBufferOffset != -1 && notification->CustomDataBuffer[data_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, + notification->Size - + offsetof( TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer[1] ) ); + send_devicechange( DBT_CUSTOMEVENT, name_info->Name.Buffer, (BYTE *)event_handle, event_handle->dbch_size ); + heap_free( event_handle ); + heap_free( name_info ); + + return STATUS_SUCCESS; }
/*********************************************************************** diff --git a/dlls/ntoskrnl.exe/tests/driver_pnp.c b/dlls/ntoskrnl.exe/tests/driver_pnp.c index e79edae7125..210da969bfc 100644 --- a/dlls/ntoskrnl.exe/tests/driver_pnp.c +++ b/dlls/ntoskrnl.exe/tests/driver_pnp.c @@ -722,7 +722,7 @@ static void test_devicechange( DEVICE_OBJECT *obj ) notif->NameBufferOffset = -1;
status = IoReportTargetDeviceChange( obj, notif ); - todo_wine ok( status == STATUS_SUCCESS, "IoReportTargetDeviceChange failed, status %#lx size %d,\n", status, notif->Size ); + ok( status == STATUS_SUCCESS, "IoReportTargetDeviceChange failed, status %#lx size %d,\n", status, notif->Size ); ExFreePool( notif ); winetest_pop_context(); } diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index dae214aec4d..8910a5eb9f8 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1587,15 +1587,15 @@ static void test_pnp_devices(void)
filter_handle.dbch_handle = bus; notify_handle_custom = RegisterDeviceNotificationA(window, &filter_handle, 0); - todo_wine ok(!!notify_handle_custom, "failed to register for device notifications, error %lu\n", GetLastError()); + 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(); - todo_wine ok(got_custom_event == ARRAY_SIZE(custom_events), - "got %u custom event messages, expected %d\n", got_custom_event, - (int)ARRAY_SIZE(custom_events)); + ok(got_custom_event == ARRAY_SIZE(custom_events), + "got %u custom event messages, expected %d\n", got_custom_event, + (int)ARRAY_SIZE(custom_events));
/* Test IoRegisterDeviceInterface() and IoSetDeviceInterfaceState(). */