[KMTESTS]
[reactos.git] / rostests / kmtests / ntos_io / IoDeviceInterface.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Device Interface functions test
5 * PROGRAMMER: Filip Navara <xnavara@volny.cz>
6 */
7
8 /* TODO: what's with the prototypes at the top, what's with the if-ed out part? Doesn't process most results */
9
10 #include <kmt_test.h>
11 #include <poclass.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 #if 0
17 NTSTATUS
18 (NTAPI *IoGetDeviceInterfaces_Func)(
19 IN CONST GUID *InterfaceClassGuid,
20 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
21 IN ULONG Flags,
22 OUT PWSTR *SymbolicLinkList);
23
24 NTSTATUS NTAPI
25 ReactOS_IoGetDeviceInterfaces(
26 IN CONST GUID *InterfaceClassGuid,
27 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
28 IN ULONG Flags,
29 OUT PWSTR *SymbolicLinkList);
30 #endif /* 0 */
31
32 static VOID DeviceInterfaceTest_Func()
33 {
34 NTSTATUS Status;
35 PWSTR SymbolicLinkList;
36 PWSTR SymbolicLinkListPtr;
37 GUID Guid = {0x378de44c, 0x56ef, 0x11d1, {0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd}};
38
39 Status = IoGetDeviceInterfaces(
40 &Guid,
41 NULL,
42 0,
43 &SymbolicLinkList);
44
45 ok(NT_SUCCESS(Status),
46 "IoGetDeviceInterfaces failed with status 0x%X\n",
47 (unsigned int)Status);
48 if (!NT_SUCCESS(Status))
49 {
50 return;
51 }
52
53 DPRINT("IoGetDeviceInterfaces results:\n");
54 for (SymbolicLinkListPtr = SymbolicLinkList;
55 SymbolicLinkListPtr[0] != 0 && SymbolicLinkListPtr[1] != 0;
56 SymbolicLinkListPtr += wcslen(SymbolicLinkListPtr) + 1)
57 {
58 DPRINT1("Symbolic Link: %S\n", SymbolicLinkListPtr);
59 }
60
61 #if 0
62 DPRINT("[PnP Test] Trying to get aliases\n");
63
64 for (SymbolicLinkListPtr = SymbolicLinkList;
65 SymbolicLinkListPtr[0] != 0 && SymbolicLinkListPtr[1] != 0;
66 SymbolicLinkListPtr += wcslen(SymbolicLinkListPtr) + 1)
67 {
68 UNICODE_STRING SymbolicLink;
69 UNICODE_STRING AliasSymbolicLink;
70
71 SymbolicLink.Buffer = SymbolicLinkListPtr;
72 SymbolicLink.Length = SymbolicLink.MaximumLength = wcslen(SymbolicLinkListPtr);
73 RtlInitUnicodeString(&AliasSymbolicLink, NULL);
74 IoGetDeviceInterfaceAlias(
75 &SymbolicLink,
76 &AliasGuid,
77 &AliasSymbolicLink);
78 if (AliasSymbolicLink.Buffer != NULL)
79 {
80 DPRINT("[PnP Test] Original: %S\n", SymbolicLinkListPtr);
81 DPRINT("[PnP Test] Alias: %S\n", AliasSymbolicLink.Buffer);
82 }
83 }
84 #endif
85
86 ExFreePool(SymbolicLinkList);
87 }
88
89 static
90 VOID
91 Test_IoRegisterDeviceInterface(VOID)
92 {
93 GUID Guid = {0x378de44c, 0x56ef, 0x11d1, {0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd}};
94 DEVICE_OBJECT DeviceObject;
95 EXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
96 DEVICE_NODE DeviceNode;
97 UNICODE_STRING SymbolicLinkName;
98 NTSTATUS Status;
99
100 RtlInitUnicodeString(&SymbolicLinkName, L"");
101
102 // Prepare our surrogate of a Device Object
103 DeviceObject.DeviceObjectExtension = (PDEVOBJ_EXTENSION)&DeviceObjectExtension;
104
105 // 1. DeviceNode = NULL
106 DeviceObjectExtension.DeviceNode = NULL;
107 Status = IoRegisterDeviceInterface(&DeviceObject, &Guid, NULL,
108 &SymbolicLinkName);
109
110 ok(Status == STATUS_INVALID_DEVICE_REQUEST,
111 "IoRegisterDeviceInterface returned 0x%08lX\n", Status);
112
113 // 2. DeviceNode->InstancePath is of a null length
114 DeviceObjectExtension.DeviceNode = &DeviceNode;
115 DeviceNode.InstancePath.Length = 0;
116 Status = IoRegisterDeviceInterface(&DeviceObject, &Guid, NULL,
117 &SymbolicLinkName);
118
119 ok(Status == STATUS_INVALID_DEVICE_REQUEST,
120 "IoRegisterDeviceInterface returned 0x%08lX\n", Status);
121
122 DeviceInterfaceTest_Func();
123 }
124
125 static UCHAR NotificationContext;
126
127 static DRIVER_NOTIFICATION_CALLBACK_ROUTINE NotificationCallback;
128 static
129 NTSTATUS
130 NTAPI
131 NotificationCallback(
132 _In_ PVOID NotificationStructure,
133 _Inout_opt_ PVOID Context)
134 {
135 PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification = NotificationStructure;
136 NTSTATUS Status;
137 OBJECT_ATTRIBUTES ObjectAttributes;
138 HANDLE Handle;
139
140 ok_irql(PASSIVE_LEVEL);
141 ok_eq_pointer(Context, &NotificationContext);
142 ok_eq_uint(Notification->Version, 1);
143 ok_eq_uint(Notification->Size, sizeof(*Notification));
144
145 /* symbolic link must exist */
146 trace("Interface change: %wZ\n", Notification->SymbolicLinkName);
147 InitializeObjectAttributes(&ObjectAttributes,
148 Notification->SymbolicLinkName,
149 OBJ_KERNEL_HANDLE,
150 NULL,
151 NULL);
152 Status = ZwOpenSymbolicLinkObject(&Handle, GENERIC_READ, &ObjectAttributes);
153 ok_eq_hex(Status, STATUS_SUCCESS);
154 if (!skip(NT_SUCCESS(Status), "No symbolic link\n"))
155 {
156 Status = ObCloseHandle(Handle, KernelMode);
157 ok_eq_hex(Status, STATUS_SUCCESS);
158 }
159 return STATUS_SUCCESS;
160 }
161
162 static
163 VOID
164 Test_IoRegisterPlugPlayNotification(VOID)
165 {
166 NTSTATUS Status;
167 PVOID NotificationEntry;
168
169 Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
170 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
171 (PVOID)&GUID_DEVICE_SYS_BUTTON,
172 KmtDriverObject,
173 NotificationCallback,
174 &NotificationContext,
175 &NotificationEntry);
176 ok_eq_hex(Status, STATUS_SUCCESS);
177 if (!skip(NT_SUCCESS(Status), "PlugPlayNotification not registered\n"))
178 {
179 Status = IoUnregisterPlugPlayNotification(NotificationEntry);
180 ok_eq_hex(Status, STATUS_SUCCESS);
181 }
182 }
183
184 START_TEST(IoDeviceInterface)
185 {
186 // FIXME: This test crashes in Windows
187 (void)Test_IoRegisterDeviceInterface;
188 Test_IoRegisterPlugPlayNotification();
189 }