ReactOS 0.4.16-dev-747-gbc52d5f
IoDeviceInterface.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Test for Device Interface functions
5 * COPYRIGHT: Copyright 2011 Filip Navara <xnavara@volny.cz>
6 * Copyright 2011-2015 Thomas Faber <thomas.faber@reactos.org>
7 * Copyright 2021 Mark Jansen <mark.jansen@reactos.org>
8 * Copyright 2021-2024 Oleg Dubinskiy <oleg.dubinskiy@reactos.org>
9 */
10
11/* TODO: Add IoRegisterDeviceInterface testcase */
12
13#include <kmt_test.h>
14#include <poclass.h>
15
16#define NDEBUG
17#include <debug.h>
18
19/* Predefined GUIDs are required for IoGetDeviceInterfaceAlias and IoOpenDeviceInterfaceRegistryKey.
20 * Only they can provide the aliases and the needed subkeys, unlike manually declared test GUIDs.
21 * Since IoRegisterDeviceInterface testcase is missing, it is not possible to register the new device interface
22 * and get an alias/key handle of it using this test. */
23/* Invalid GUID */
24static const GUID GUID_NULL = {0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
25/* From our ks.h */
26static const GUID KSCATEGORY_BRIDGE = {0x085AFF00L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
27static const GUID KSCATEGORY_CAPTURE = {0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
28static const GUID KSCATEGORY_COMMUNICATIONSTRANSFORM = {0xCF1DDA2CL, 0x9743, 0x11D0, {0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
29static const GUID KSCATEGORY_DATACOMPRESSOR = {0x1E84C900L, 0x7E70, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
30static const GUID KSCATEGORY_DATADECOMPRESSOR = {0x2721AE20L, 0x7E70, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
31static const GUID KSCATEGORY_DATATRANSFORM = {0x2EB07EA0L, 0x7E70, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
32static const GUID KSCATEGORY_FILESYSTEM = {0x760FED5EL, 0x9357, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
33static const GUID KSCATEGORY_INTERFACETRANSFORM = {0xCF1DDA2DL, 0x9743, 0x11D0, {0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
34static const GUID KSCATEGORY_MEDIUMTRANSFORM = {0xCF1DDA2EL, 0x9743, 0x11D0, {0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
35static const GUID KSCATEGORY_MIXER = {0xAD809C00L, 0x7B88, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
36static const GUID KSCATEGORY_RENDER = {0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
37static const GUID KSCATEGORY_SPLITTER = {0x0A4252A0L, 0x7E70, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
38
39static const GUID* Types[] =
40{
41 &GUID_NULL,
54};
55
56static
57VOID
60{
64 size_t n;
65
67 RtlInitUnicodeString(&KeyName, L"ReactOS_kmtest");
68
69 /* It's okay to call this from a user process's thread */
71
72 if (skip(NT_SUCCESS(Status), "IoOpenDeviceInterfaceRegistryKey() failed: 0x%lx\n", Status))
73 return;
74
75 trace("IoOpenDeviceInterfaceRegistryKey() success: 0x%p\n", DeviceInterfaceKey);
76
77 for (n = 0; n < RTL_NUMBER_OF(Types); ++n)
78 {
79 HANDLE DeviceInterfaceSubKey;
81
82 /* Try to create the non-volatile subkey to check whether the parent key is volatile */
84 &KeyName,
87 NULL);
88 Status = ZwCreateKey(&DeviceInterfaceSubKey,
91 0,
92 NULL,
94 NULL);
95
96 if (skip(NT_SUCCESS(Status), "ZwCreateKey() failed to create a subkey: %d 0x%lx\n", n, Status))
97 continue;
98
99 trace("ZwCreateKey(): successfully created subkey: %d 0x%p\n", n, DeviceInterfaceSubKey);
100
101 ZwDeleteKey(DeviceInterfaceSubKey);
102 ZwClose(DeviceInterfaceSubKey);
103 }
104
106}
107
108static
109VOID
112{
114 size_t n;
115
117
118 for (n = 0; n < RTL_NUMBER_OF(Types); ++n)
119 {
120 UNICODE_STRING AliasSymbolicLinkName;
121 NTSTATUS Status = IoGetDeviceInterfaceAlias(&SymbolicLinkName, Types[n], &AliasSymbolicLinkName);
122
123 if (skip(NT_SUCCESS(Status), "IoGetDeviceInterfaceAlias(): fail: %d 0x%x\n", n, Status))
124 continue;
125
126 trace("IoGetDeviceInterfaceAlias(): success: %d %wZ\n", n, &AliasSymbolicLinkName);
127
128 /* Test IoOpenDeviceInterfaceRegistryKey with alias symbolic link too */
129 Test_IoOpenDeviceInterfaceRegistryKey(AliasSymbolicLinkName.Buffer);
130
131 RtlFreeUnicodeString(&AliasSymbolicLinkName);
132 }
133}
134
135static
136VOID
139{
141 size_t n;
142
144
145 for (n = 0; n < RTL_NUMBER_OF(Types); ++n)
146 {
148
149 if (skip(NT_SUCCESS(Status), "IoSetDeviceInterfaceState(): failed to enable interface: %d 0x%x\n", n, Status))
150 continue;
151
152 trace("IoSetDeviceInterfaceState(): successfully enabled interface: %d %wZ\n", n, &SymbolicLinkName);
153 }
154}
155
156static
157VOID
159 _In_ const GUID* Guid)
160{
165
167
169 if (skip(NT_SUCCESS(Status), "IoGetDeviceInterfaces failed with status 0x%x for '%wZ'\n", Status, &GuidString))
170 {
172 return;
173 }
174
175 trace("IoGetDeviceInterfaces '%wZ' results:\n", &GuidString);
177
181 {
182 trace("Symbolic Link: %S\n", SymbolicLink);
186 }
187
189}
190
192
193static DRIVER_NOTIFICATION_CALLBACK_ROUTINE NotificationCallback;
194static
196NTAPI
200{
205
206 ok_irql(PASSIVE_LEVEL);
208 ok_eq_uint(Notification->Version, 1);
209 ok_eq_uint(Notification->Size, sizeof(*Notification));
210
211 /* symbolic link must exist */
212 trace("Interface change: %wZ\n", Notification->SymbolicLinkName);
214 Notification->SymbolicLinkName,
216 NULL,
217 NULL);
220 if (!skip(NT_SUCCESS(Status), "No symbolic link\n"))
221 {
224 }
225 return STATUS_SUCCESS;
226}
227
228static
229VOID
231{
234
237 (PVOID)&GUID_DEVICE_SYS_BUTTON,
238 KmtDriverObject,
243 if (!skip(NT_SUCCESS(Status), "PlugPlayNotification not registered\n"))
244 {
247 }
248}
249
250START_TEST(IoDeviceInterface)
251{
252 size_t n;
253 for (n = 0; n < RTL_NUMBER_OF(Types); ++n)
254 {
256 }
257 /* Test the invalid case behaviour */
262}
static const GUID GUID_NULL
static const GUID KSCATEGORY_DATADECOMPRESSOR
static const GUID KSCATEGORY_INTERFACETRANSFORM
static VOID Test_IoOpenDeviceInterfaceRegistryKey(_In_opt_ PCWSTR SymbolicLink)
static const GUID KSCATEGORY_RENDER
static VOID Test_IoGetDeviceInterfaces(_In_ const GUID *Guid)
static const GUID KSCATEGORY_SPLITTER
static const GUID KSCATEGORY_FILESYSTEM
static VOID Test_IoSetDeviceInterfaceState(_In_opt_ PCWSTR SymbolicLink)
static VOID Test_IoGetDeviceInterfaceAlias(_In_opt_ PCWSTR SymbolicLink)
static const GUID KSCATEGORY_DATACOMPRESSOR
static const GUID KSCATEGORY_MIXER
static DRIVER_NOTIFICATION_CALLBACK_ROUTINE NotificationCallback
static const GUID KSCATEGORY_MEDIUMTRANSFORM
static VOID Test_IoRegisterPlugPlayNotification(VOID)
static const GUID KSCATEGORY_CAPTURE
static const GUID KSCATEGORY_COMMUNICATIONSTRANSFORM
static const GUID KSCATEGORY_DATATRANSFORM
static const GUID * Types[]
static const GUID KSCATEGORY_BRIDGE
static UCHAR NotificationContext
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define ok_eq_pointer(value, expected)
Definition: apitest.h:40
#define ok_eq_hex(value, expected)
Definition: apitest.h:58
#define ok_eq_uint(value, expected)
Definition: apitest.h:42
#define trace
Definition: atltest.h:70
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define GENERIC_READ
Definition: compat.h:135
static const WCHAR SymbolicLink[]
Definition: interface.c:31
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLdouble n
Definition: glext.h:7729
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlStringFromGUID(REFGUID, PUNICODE_STRING)
static PWSTR GuidString
Definition: apphelp.c:93
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define KernelMode
Definition: asm.h:38
NTSYSAPI NTSTATUS NTAPI ZwOpenSymbolicLinkObject(_Out_ PHANDLE SymbolicLinkHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define _Inout_opt_
Definition: no_sal2.h:216
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define KEY_WRITE
Definition: nt_native.h:1031
#define UNICODE_NULL
_NullNull_terminated_ WCHAR * PZZWSTR
Definition: ntbasedef.h:428
NTSTATUS NTAPI IoOpenDeviceInterfaceRegistryKey(IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DeviceInterfaceKey)
Definition: deviface.c:595
NTSTATUS NTAPI IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid, IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, IN ULONG Flags, OUT PWSTR *SymbolicLinkList)
Definition: deviface.c:936
NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
Definition: deviface.c:1793
NTSTATUS NTAPI IoGetDeviceInterfaceAlias(_In_ PUNICODE_STRING SymbolicLinkName, _In_ CONST GUID *AliasInterfaceClassGuid, _Out_ PUNICODE_STRING AliasSymbolicLinkName)
Returns the alias device interface of the specified device interface instance, if the alias exists.
Definition: deviface.c:758
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
NTSTATUS NTAPI IoRegisterPlugPlayNotification(_In_ IO_NOTIFICATION_EVENT_CATEGORY EventCategory, _In_ ULONG EventCategoryFlags, _In_opt_ PVOID EventCategoryData, _In_ PDRIVER_OBJECT DriverObject, _In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, _Inout_opt_ PVOID Context, _Out_ PVOID *NotificationEntry)
Definition: pnpnotify.c:346
NTSTATUS NTAPI IoUnregisterPlugPlayNotification(_In_ PVOID NotificationEntry)
Definition: pnpnotify.c:480
#define STATUS_SUCCESS
Definition: shellext.h:65
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define NTAPI
Definition: typedefs.h:36
_In_ PWDFDEVICE_INIT _In_ PFN_WDF_DEVICE_SHUTDOWN_NOTIFICATION Notification
Definition: wdfcontrol.h:115
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING SymbolicLinkName
Definition: wdfdevice.h:3739
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_ WDFOBJECT _In_ CONST GUID * Guid
Definition: wdfobject.h:762
_In_opt_ PDEVICE_OBJECT _In_ ULONG _Outptr_result_nullonfailure_ _At_ * SymbolicLinkList(return==0, __drv_allocatesMem(Mem))) PZZWSTR *SymbolicLinkList
_In_ ACCESS_MASK _Out_ PHANDLE DeviceInterfaceKey
Definition: iofuncs.h:1116
_In_ ULONG _In_opt_ PVOID _In_ PDRIVER_OBJECT _In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE _Inout_opt_ __drv_aliasesMem PVOID _Outptr_result_nullonfailure_ _At_ * NotificationEntry(return==0, __drv_allocatesMem(Mem))) PVOID *NotificationEntry
#define DEVICE_INTERFACE_INCLUDE_NONACTIVE
Definition: iofuncs.h:2856
_In_ PVOID NotificationStructure
Definition: iofuncs.h:1206
@ EventCategoryDeviceInterfaceChange
Definition: iotypes.h:1226
#define PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES
Definition: iotypes.h:1239
unsigned char UCHAR
Definition: xmlstorage.h:181