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 | 92 ++++++++++++++++++++++++++-- 3 files changed, 168 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..e79edae7125 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 ); + if (custom_events[i].data) + size += custom_events[i].data_size; + + if (custom_events[i].str) + size += wcslen(custom_events[i].str) * sizeof(WCHAR) + 1; + + 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 ); + todo_wine 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..ea011e9e397 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,69 @@ 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 ); + 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) + { + winetest_pop_context(); + 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 ) ); + } + else + ok( handle->dbch_nameoffset == -1, "%lu != -1\n", handle->dbch_nameoffset); + winetest_pop_context(); + } + break; + } } return DefWindowProcA(window, message, wparam, lparam); } @@ -1456,11 +1522,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 +1539,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 +1548,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 +1585,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); + todo_wine 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));
/* Test IoRegisterDeviceInterface() and IoSetDeviceInterfaceState(). */
@@ -1734,6 +1815,7 @@ static void test_pnp_devices(void) CloseHandle(bus);
UnregisterDeviceNotification(notify_handle); + UnregisterDeviceNotification(notify_handle_custom); DestroyWindow(window); UnregisterClassA("ntoskrnl_test_wc", GetModuleHandleA(NULL)); }