Partial merge of condrv_restructure branch r65657.
[reactos.git] / rostests / kmtests / ntos_ob / ObReference.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Object Referencing test
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <kmt_test.h>
9 #define NDEBUG
10 #include <debug.h>
11
12 #define CheckObject(Handle, Pointers, Handles) do \
13 { \
14 PUBLIC_OBJECT_BASIC_INFORMATION ObjectInfo; \
15 Status = ZwQueryObject(Handle, ObjectBasicInformation, \
16 &ObjectInfo, sizeof ObjectInfo, NULL); \
17 ok_eq_hex(Status, STATUS_SUCCESS); \
18 ok_eq_ulong(ObjectInfo.PointerCount, Pointers); \
19 ok_eq_ulong(ObjectInfo.HandleCount, Handles); \
20 } while (0)
21
22 static POBJECT_TYPE ObDirectoryObjectType;
23
24 static
25 VOID
26 TestReference(
27 IN HANDLE Handle,
28 IN PUNICODE_STRING Name OPTIONAL,
29 IN PUNICODE_STRING NameUpper OPTIONAL,
30 IN BOOLEAN CaseSensitive,
31 IN ULONG AdditionalReferences,
32 IN BOOLEAN Permanent)
33 {
34 NTSTATUS Status;
35 LONG_PTR Ret;
36 PVOID Object = NULL;
37 PVOID Object2 = NULL;
38 PVOID Object3 = NULL;
39 PVOID Object4 = NULL;
40
41 CheckObject(Handle, 2LU + AdditionalReferences, 1LU);
42
43 Status = ObReferenceObjectByHandle(Handle, DIRECTORY_ALL_ACCESS, NULL, KernelMode, &Object, NULL);
44 ok_eq_hex(Status, STATUS_SUCCESS);
45 ok(Object != NULL, "ObReferenceObjectByHandle returned NULL object\n");
46 CheckObject(Handle, 3LU + AdditionalReferences, 1LU);
47
48 Status = ObReferenceObjectByHandle(Handle, DIRECTORY_ALL_ACCESS, NULL, KernelMode, &Object2, NULL);
49 ok_eq_hex(Status, STATUS_SUCCESS);
50 ok(Object != NULL, "ObReferenceObjectByHandle returned NULL object\n");
51 ok_eq_pointer(Object, Object2);
52 CheckObject(Handle, 4LU + AdditionalReferences, 1LU);
53
54 if (!skip(Object != NULL, "No object to reference!\n"))
55 {
56 Ret = ObReferenceObject(Object);
57 ok_eq_longptr(Ret, (LONG_PTR)4 + AdditionalReferences);
58 CheckObject(Handle, 5LU + AdditionalReferences, 1LU);
59
60 Ret = ObReferenceObject(Object);
61 ok_eq_longptr(Ret, (LONG_PTR)5 + AdditionalReferences);
62 CheckObject(Handle, 6LU + AdditionalReferences, 1LU);
63
64 Status = ObReferenceObjectByPointer(Object, DIRECTORY_ALL_ACCESS, NULL, KernelMode);
65 ok_eq_hex(Status, STATUS_SUCCESS);
66 CheckObject(Handle, 7LU + AdditionalReferences, 1LU);
67
68 Status = ObReferenceObjectByPointer(Object, DIRECTORY_ALL_ACCESS, NULL, KernelMode);
69 ok_eq_hex(Status, STATUS_SUCCESS);
70 CheckObject(Handle, 8LU + AdditionalReferences, 1LU);
71
72 Ret = ObDereferenceObject(Object);
73 ok_eq_longptr(Ret, (LONG_PTR)6 + AdditionalReferences);
74 CheckObject(Handle, 7LU + AdditionalReferences, 1LU);
75
76 Ret = ObDereferenceObject(Object);
77 ok_eq_longptr(Ret, (LONG_PTR)5 + AdditionalReferences);
78 CheckObject(Handle, 6LU + AdditionalReferences, 1LU);
79
80 Ret = ObDereferenceObject(Object);
81 ok_eq_longptr(Ret, (LONG_PTR)4 + AdditionalReferences);
82 CheckObject(Handle, 5LU + AdditionalReferences, 1LU);
83
84 Ret = ObDereferenceObject(Object);
85 ok_eq_longptr(Ret, (LONG_PTR)3 + AdditionalReferences);
86 CheckObject(Handle, 4LU + AdditionalReferences, 1LU);
87 }
88
89 if (Name && !skip(ObDirectoryObjectType != NULL, "No directory object type\n"))
90 {
91 Status = ObReferenceObjectByName(Name, 0, NULL, DIRECTORY_ALL_ACCESS, ObDirectoryObjectType, KernelMode, NULL, &Object3);
92 ok_eq_hex(Status, STATUS_SUCCESS);
93 CheckObject(Handle, 5LU + AdditionalReferences, 1LU);
94 }
95
96 if (NameUpper && !skip(ObDirectoryObjectType != NULL, "No directory object type\n"))
97 {
98 Status = ObReferenceObjectByName(NameUpper, 0, NULL, DIRECTORY_ALL_ACCESS, ObDirectoryObjectType, KernelMode, NULL, &Object4);
99 ok_eq_hex(Status, CaseSensitive ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS);
100 CheckObject(Handle, 5LU + AdditionalReferences + !CaseSensitive, 1LU);
101 }
102
103 if (NameUpper && !skip(Object4 != NULL, "No object to dereference\n"))
104 {
105 Ret = ObDereferenceObject(Object4);
106 ok_eq_longptr(Ret, (LONG_PTR)4 + AdditionalReferences);
107 CheckObject(Handle, 5LU + AdditionalReferences, 1LU);
108 }
109 if (Name && !skip(Object3 != NULL, "No object to dereference\n"))
110 {
111 Ret = ObDereferenceObject(Object3);
112 ok_eq_longptr(Ret, (LONG_PTR)3 + AdditionalReferences);
113 CheckObject(Handle, 4LU + AdditionalReferences, 1LU);
114 }
115 if (!skip(Object2 != NULL, "No object to dereference\n"))
116 {
117 Ret = ObDereferenceObject(Object2);
118 ok_eq_longptr(Ret, (LONG_PTR)2 + AdditionalReferences);
119 CheckObject(Handle, 3LU + AdditionalReferences, 1LU);
120 }
121 if (!skip(Object != NULL, "No object to dereference\n"))
122 {
123 Ret = ObDereferenceObject(Object);
124 ok_eq_longptr(Ret, (LONG_PTR)1 + AdditionalReferences);
125 CheckObject(Handle, 2LU + AdditionalReferences, 1LU);
126 }
127
128 CheckObject(Handle, 2LU + AdditionalReferences, 1LU);
129
130 if (Permanent)
131 {
132 Status = ZwMakeTemporaryObject(Handle);
133 ok_eq_hex(Status, STATUS_SUCCESS);
134 CheckObject(Handle, 2LU + AdditionalReferences, 1LU);
135
136 Status = ZwMakeTemporaryObject(Handle);
137 ok_eq_hex(Status, STATUS_SUCCESS);
138 CheckObject(Handle, 2LU + AdditionalReferences, 1LU);
139 }
140 }
141
142 START_TEST(ObReference)
143 {
144 NTSTATUS Status;
145 HANDLE DirectoryHandle = NULL;
146 OBJECT_ATTRIBUTES ObjectAttributes;
147 UNICODE_STRING Name, *pName;
148 UNICODE_STRING NameUpper, *pNameUpper;
149 ULONG i;
150 struct
151 {
152 PWSTR Name;
153 ULONG Flags;
154 ULONG AdditionalReferences;
155 } Tests[] =
156 {
157 { NULL, 0, 0 },
158 { NULL, OBJ_CASE_INSENSITIVE, 0 },
159 { NULL, OBJ_KERNEL_HANDLE, 0 },
160 { NULL, OBJ_PERMANENT, 0 },
161 { NULL, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 0 },
162 { NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0 },
163 { NULL, OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 0 },
164 { NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 0 },
165 { L"\\YayDirectory0", 0, 1 },
166 { L"\\YayDirectory1", OBJ_CASE_INSENSITIVE, 1 },
167 { L"\\YayDirectory2", OBJ_KERNEL_HANDLE, 1 },
168 { L"\\YayDirectory3", OBJ_PERMANENT, 1 },
169 { L"\\YayDirectory4", OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 1 },
170 { L"\\YayDirectory5", OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1 },
171 { L"\\YayDirectory6", OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 1 },
172 { L"\\YayDirectory7", OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 1 },
173 };
174 HANDLE ObjectTypeHandle;
175
176 /* ObReferenceObjectByName needs the object type... so get it... */
177 RtlInitUnicodeString(&Name, L"\\ObjectTypes\\Directory");
178 InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_KERNEL_HANDLE, NULL, NULL);
179 Status = ObOpenObjectByName(&ObjectAttributes, NULL, KernelMode, NULL, 0, NULL, &ObjectTypeHandle);
180 ok_eq_hex(Status, STATUS_SUCCESS);
181 ok(ObjectTypeHandle != NULL, "ObjectTypeHandle = NULL\n");
182 if (!skip(Status == STATUS_SUCCESS && ObjectTypeHandle, "No handle\n"))
183 {
184 Status = ObReferenceObjectByHandle(ObjectTypeHandle, 0, NULL, KernelMode, (PVOID)&ObDirectoryObjectType, NULL);
185 ok_eq_hex(Status, STATUS_SUCCESS);
186 ok(ObDirectoryObjectType != NULL, "ObDirectoryObjectType = NULL\n");
187 Status = ZwClose(ObjectTypeHandle);
188 ok_eq_hex(Status, STATUS_SUCCESS);
189 }
190
191 for (i = 0; i < sizeof Tests / sizeof Tests[0]; ++i)
192 {
193 DPRINT("Run %d\n", i);
194 if (Tests[i].Name)
195 {
196 RtlInitUnicodeString(&Name, Tests[i].Name);
197 pName = &Name;
198 Status = RtlUpcaseUnicodeString(&NameUpper, &Name, TRUE);
199 ok_eq_hex(Status, STATUS_SUCCESS);
200 if (skip(Status == STATUS_SUCCESS, "No upper case name\n"))
201 pNameUpper = NULL;
202 else
203 pNameUpper = &NameUpper;
204 }
205 else
206 {
207 pName = NULL;
208 pNameUpper = NULL;
209 }
210 InitializeObjectAttributes(&ObjectAttributes, pName, Tests[i].Flags, NULL, NULL);
211 Status = ZwCreateDirectoryObject(&DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes);
212 ok_eq_hex(Status, STATUS_SUCCESS);
213 ok(DirectoryHandle != NULL, "DirectoryHandle = NULL\n");
214
215 if (!skip(Status == STATUS_SUCCESS && DirectoryHandle, "Cannot proceed without an object"))
216 {
217 TestReference(DirectoryHandle, pName, pNameUpper, FALSE, Tests[i].AdditionalReferences, (Tests[i].Flags & OBJ_PERMANENT) != 0);
218 /* try again for good measure */
219 TestReference(DirectoryHandle, pName, pNameUpper, FALSE, Tests[i].AdditionalReferences, FALSE);
220
221 Status = ZwClose(DirectoryHandle);
222 ok_eq_hex(Status, STATUS_SUCCESS);
223 DirectoryHandle = NULL;
224 }
225
226 if (pNameUpper)
227 RtlFreeUnicodeString(pNameUpper);
228 }
229
230 if (DirectoryHandle)
231 {
232 Status = ZwClose(DirectoryHandle);
233 ok_eq_hex(Status, STATUS_SUCCESS);
234 }
235
236 /* parameter tests */
237 /* bugcheck at APC_LEVEL
238 Status = ObReferenceObject(NULL);
239 Status = ObReferenceObjectByPointer(NULL, 0, NULL, UserMode);
240 Status = ObReferenceObjectByPointer(NULL, 0, NULL, KernelMode);*/
241
242 KmtStartSeh()
243 /* TODO: this belongs in an ObHandle test if we ever have one */
244 /* NtClose must accept everything */
245 DPRINT("Closing null handle (NtClose)\n");
246 Status = NtClose(NULL);
247 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
248 DPRINT("Closing null kernel handle (NtClose)\n");
249 Status = NtClose((HANDLE)0x80000000);
250 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
251 DPRINT("Closing -1 handle (NtClose)\n");
252 Status = NtClose((HANDLE)0x7FFFFFFF);
253 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
254 DPRINT("Closing -1 kernel handle (NtClose)\n");
255 Status = NtClose((HANDLE)0xFFFFFFFF);
256 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
257 DPRINT("Closing 123 handle (NtClose)\n");
258 Status = NtClose((HANDLE)123);
259 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
260 DPRINT("Closing 123 kernel handle (NtClose)\n");
261 Status = NtClose((HANDLE)(123 | 0x80000000));
262 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
263
264 /* ObCloseHandle with UserMode accepts everything */
265 DPRINT("Closing null handle (ObCloseHandle, UserMode)\n");
266 Status = ObCloseHandle(NULL, UserMode);
267 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
268 DPRINT("Closing null kernel handle (ObCloseHandle, UserMode)\n");
269 Status = ObCloseHandle((HANDLE)0x80000000, UserMode);
270 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
271 DPRINT("Closing -1 handle (ObCloseHandle, UserMode)\n");
272 Status = ObCloseHandle((HANDLE)0x7FFFFFFF, UserMode);
273 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
274 DPRINT("Closing -1 kernel handle (ObCloseHandle, UserMode)\n");
275 Status = ObCloseHandle((HANDLE)0xFFFFFFFF, UserMode);
276 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
277 DPRINT("Closing 123 handle (ObCloseHandle, UserMode)\n");
278 Status = ObCloseHandle((HANDLE)123, UserMode);
279 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
280 DPRINT("Closing 123 kernel handle (ObCloseHandle, UserMode)\n");
281 Status = ObCloseHandle((HANDLE)(123 | 0x80000000), UserMode);
282 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
283
284 /* ZwClose only accepts 0 and -1 */
285 DPRINT("Closing null handle (ZwClose)\n");
286 Status = ZwClose(NULL);
287 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
288 DPRINT("Closing null kernel handle (ZwClose)\n");
289 Status = ZwClose((HANDLE)0x80000000);
290 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
291 /* INVALID_KERNEL_HANDLE, 0x7FFFFFFF
292 Status = ZwClose((HANDLE)0x7FFFFFFF);*/
293 DPRINT("Closing -1 kernel handle (ZwClose)\n");
294 Status = ZwClose((HANDLE)0xFFFFFFFF);
295 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
296 /* INVALID_KERNEL_HANDLE, 0x7B, 1, 0, 0
297 Status = ZwClose((HANDLE)123);
298 Status = ZwClose((HANDLE)(123 | 0x80000000));*/
299
300 /* ObCloseHandle with KernelMode accepts only 0 and -1 */
301 DPRINT("Closing null handle (ObCloseHandle, KernelMode)\n");
302 Status = ObCloseHandle(NULL, KernelMode);
303 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
304 DPRINT("Closing null kernel handle (ObCloseHandle, KernelMode)\n");
305 Status = ObCloseHandle((HANDLE)0x80000000, KernelMode);
306 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
307 /* INVALID_KERNEL_HANDLE, 0x7FFFFFFF, 1, 0, 0
308 Status = ObCloseHandle((HANDLE)0x7FFFFFFF, KernelMode);*/
309 DPRINT("Closing -1 kernel handle (ObCloseHandle, KernelMode)\n");
310 Status = ObCloseHandle((HANDLE)0xFFFFFFFF, KernelMode);
311 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
312 /* INVALID_KERNEL_HANDLE, 0x7B, 1, 0, 0
313 Status = ObCloseHandle((HANDLE)123, KernelMode);
314 Status = ObCloseHandle((HANDLE)(123 | 0x80000000), KernelMode);*/
315 KmtEndSeh(STATUS_SUCCESS);
316
317 if (ObDirectoryObjectType)
318 {
319 ObDereferenceObject(ObDirectoryObjectType);
320 ObDirectoryObjectType = NULL;
321 }
322 }