[KMTESTS/OB]
[reactos.git] / 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 <thfabba@gmx.de>
6 */
7
8 #include <kmt_test.h>
9
10 #define CheckObject(Handle, Pointers, Handles) do \
11 { \
12 PUBLIC_OBJECT_BASIC_INFORMATION ObjectInfo; \
13 Status = ZwQueryObject(Handle, ObjectBasicInformation, \
14 &ObjectInfo, sizeof ObjectInfo, NULL); \
15 ok_eq_hex(Status, STATUS_SUCCESS); \
16 ok_eq_ulong(ObjectInfo.PointerCount, Pointers); \
17 ok_eq_ulong(ObjectInfo.HandleCount, Handles); \
18 } while (0)
19
20 static POBJECT_TYPE ObDirectoryObjectType;
21
22 static
23 VOID
24 TestReference(
25 IN HANDLE Handle,
26 IN PUNICODE_STRING Name OPTIONAL,
27 IN PUNICODE_STRING NameUpper OPTIONAL,
28 IN BOOLEAN CaseSensitive,
29 IN ULONG AdditionalReferences,
30 IN BOOLEAN Permanent)
31 {
32 NTSTATUS Status;
33 LONG_PTR Ret;
34 PVOID Object = NULL;
35 PVOID Object2 = NULL;
36 PVOID Object3 = NULL;
37 PVOID Object4 = NULL;
38
39 CheckObject(Handle, 2LU + AdditionalReferences, 1LU);
40
41 Status = ObReferenceObjectByHandle(Handle, DIRECTORY_ALL_ACCESS, NULL, KernelMode, &Object, NULL);
42 ok_eq_hex(Status, STATUS_SUCCESS);
43 ok(Object != NULL, "ObReferenceObjectByHandle returned NULL object\n");
44 CheckObject(Handle, 3LU + AdditionalReferences, 1LU);
45
46 Status = ObReferenceObjectByHandle(Handle, DIRECTORY_ALL_ACCESS, NULL, KernelMode, &Object2, NULL);
47 ok_eq_hex(Status, STATUS_SUCCESS);
48 ok(Object != NULL, "ObReferenceObjectByHandle returned NULL object\n");
49 ok_eq_pointer(Object, Object2);
50 CheckObject(Handle, 4LU + AdditionalReferences, 1LU);
51
52 if (!skip(Object != NULL, "No object to reference!\n"))
53 {
54 Ret = ObReferenceObject(Object);
55 ok_eq_longptr(Ret, (LONG_PTR)4 + AdditionalReferences);
56 CheckObject(Handle, 5LU + AdditionalReferences, 1LU);
57
58 Ret = ObReferenceObject(Object);
59 ok_eq_longptr(Ret, (LONG_PTR)5 + AdditionalReferences);
60 CheckObject(Handle, 6LU + AdditionalReferences, 1LU);
61
62 Status = ObReferenceObjectByPointer(Object, DIRECTORY_ALL_ACCESS, NULL, KernelMode);
63 ok_eq_hex(Status, STATUS_SUCCESS);
64 CheckObject(Handle, 7LU + AdditionalReferences, 1LU);
65
66 Status = ObReferenceObjectByPointer(Object, DIRECTORY_ALL_ACCESS, NULL, KernelMode);
67 ok_eq_hex(Status, STATUS_SUCCESS);
68 CheckObject(Handle, 8LU + AdditionalReferences, 1LU);
69
70 Ret = ObDereferenceObject(Object);
71 ok_eq_longptr(Ret, (LONG_PTR)6 + AdditionalReferences);
72 CheckObject(Handle, 7LU + AdditionalReferences, 1LU);
73
74 Ret = ObDereferenceObject(Object);
75 ok_eq_longptr(Ret, (LONG_PTR)5 + AdditionalReferences);
76 CheckObject(Handle, 6LU + AdditionalReferences, 1LU);
77
78 Ret = ObDereferenceObject(Object);
79 ok_eq_longptr(Ret, (LONG_PTR)4 + AdditionalReferences);
80 CheckObject(Handle, 5LU + AdditionalReferences, 1LU);
81
82 Ret = ObDereferenceObject(Object);
83 ok_eq_longptr(Ret, (LONG_PTR)3 + AdditionalReferences);
84 CheckObject(Handle, 4LU + AdditionalReferences, 1LU);
85 }
86
87 if (Name && !skip(ObDirectoryObjectType != NULL, "No directory object type\n"))
88 {
89 Status = ObReferenceObjectByName(Name, 0, NULL, DIRECTORY_ALL_ACCESS, ObDirectoryObjectType, KernelMode, NULL, &Object3);
90 ok_eq_hex(Status, STATUS_SUCCESS);
91 CheckObject(Handle, 5LU + AdditionalReferences, 1LU);
92 }
93
94 if (NameUpper && !skip(ObDirectoryObjectType != NULL, "No directory object type\n"))
95 {
96 Status = ObReferenceObjectByName(NameUpper, 0, NULL, DIRECTORY_ALL_ACCESS, ObDirectoryObjectType, KernelMode, NULL, &Object4);
97 ok_eq_hex(Status, CaseSensitive ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_SUCCESS);
98 CheckObject(Handle, 5LU + AdditionalReferences + !CaseSensitive, 1LU);
99 }
100
101 if (NameUpper && !skip(Object4 != NULL, "No object to dereference\n"))
102 {
103 Ret = ObDereferenceObject(Object4);
104 ok_eq_longptr(Ret, (LONG_PTR)4 + AdditionalReferences);
105 CheckObject(Handle, 5LU + AdditionalReferences, 1LU);
106 }
107 if (Name && !skip(Object3 != NULL, "No object to dereference\n"))
108 {
109 Ret = ObDereferenceObject(Object3);
110 ok_eq_longptr(Ret, (LONG_PTR)3 + AdditionalReferences);
111 CheckObject(Handle, 4LU + AdditionalReferences, 1LU);
112 }
113 if (!skip(Object2 != NULL, "No object to dereference\n"))
114 {
115 Ret = ObDereferenceObject(Object2);
116 ok_eq_longptr(Ret, (LONG_PTR)2 + AdditionalReferences);
117 CheckObject(Handle, 3LU + AdditionalReferences, 1LU);
118 }
119 if (!skip(Object != NULL, "No object to dereference\n"))
120 {
121 Ret = ObDereferenceObject(Object);
122 ok_eq_longptr(Ret, (LONG_PTR)1 + AdditionalReferences);
123 CheckObject(Handle, 2LU + AdditionalReferences, 1LU);
124 }
125
126 CheckObject(Handle, 2LU + AdditionalReferences, 1LU);
127
128 if (Permanent)
129 {
130 Status = ZwMakeTemporaryObject(Handle);
131 ok_eq_hex(Status, STATUS_SUCCESS);
132 CheckObject(Handle, 2LU + AdditionalReferences, 1LU);
133
134 Status = ZwMakeTemporaryObject(Handle);
135 ok_eq_hex(Status, STATUS_SUCCESS);
136 CheckObject(Handle, 2LU + AdditionalReferences, 1LU);
137 }
138 }
139
140 START_TEST(ObReference)
141 {
142 NTSTATUS Status;
143 NTSTATUS ExceptionStatus;
144 HANDLE DirectoryHandle = NULL;
145 OBJECT_ATTRIBUTES ObjectAttributes;
146 UNICODE_STRING Name, *pName;
147 UNICODE_STRING NameUpper, *pNameUpper;
148 ULONG i;
149 struct
150 {
151 PWSTR Name;
152 ULONG Flags;
153 ULONG AdditionalReferences;
154 } Tests[] =
155 {
156 { NULL, 0, 0 },
157 { NULL, OBJ_CASE_INSENSITIVE, 0 },
158 { NULL, OBJ_KERNEL_HANDLE, 0 },
159 { NULL, OBJ_PERMANENT, 0 },
160 { NULL, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 0 },
161 { NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0 },
162 { NULL, OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 0 },
163 { NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 0 },
164 { L"\\YayDirectory0", 0, 1 },
165 { L"\\YayDirectory1", OBJ_CASE_INSENSITIVE, 1 },
166 { L"\\YayDirectory2", OBJ_KERNEL_HANDLE, 1 },
167 { L"\\YayDirectory3", OBJ_PERMANENT, 1 },
168 { L"\\YayDirectory4", OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 1 },
169 { L"\\YayDirectory5", OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1 },
170 { L"\\YayDirectory6", OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 1 },
171 { L"\\YayDirectory7", OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 1 },
172 };
173 HANDLE ObjectTypeHandle;
174
175 /* ObReferenceObjectByName needs the object type... so get it... */
176 RtlInitUnicodeString(&Name, L"\\ObjectTypes\\Directory");
177 InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_KERNEL_HANDLE, NULL, NULL);
178 Status = ObOpenObjectByName(&ObjectAttributes, NULL, KernelMode, NULL, 0, NULL, &ObjectTypeHandle);
179 ok_eq_hex(Status, STATUS_SUCCESS);
180 ok(ObjectTypeHandle != NULL, "ObjectTypeHandle = NULL\n");
181 if (!skip(Status == STATUS_SUCCESS && ObjectTypeHandle, "No handle\n"))
182 {
183 Status = ObReferenceObjectByHandle(ObjectTypeHandle, 0, NULL, KernelMode, (PVOID)&ObDirectoryObjectType, NULL);
184 ok_eq_hex(Status, STATUS_SUCCESS);
185 ok(ObDirectoryObjectType != NULL, "ObDirectoryObjectType = NULL\n");
186 Status = ZwClose(ObjectTypeHandle);
187 ok_eq_hex(Status, STATUS_SUCCESS);
188 }
189
190 for (i = 0; i < sizeof Tests / sizeof Tests[0]; ++i)
191 {
192 if (Tests[i].Name)
193 {
194 RtlInitUnicodeString(&Name, Tests[i].Name);
195 pName = &Name;
196 Status = RtlUpcaseUnicodeString(&NameUpper, &Name, TRUE);
197 ok_eq_hex(Status, STATUS_SUCCESS);
198 if (skip(Status == STATUS_SUCCESS, "No upper case name\n"))
199 pNameUpper = NULL;
200 else
201 pNameUpper = &NameUpper;
202 }
203 else
204 {
205 pName = NULL;
206 pNameUpper = NULL;
207 }
208 InitializeObjectAttributes(&ObjectAttributes, pName, Tests[i].Flags, NULL, NULL);
209 Status = ZwCreateDirectoryObject(&DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes);
210 ok_eq_hex(Status, STATUS_SUCCESS);
211 ok(DirectoryHandle != NULL, "DirectoryHandle = NULL\n");
212
213 if (!skip(Status == STATUS_SUCCESS && DirectoryHandle, "Cannot proceed without an object"))
214 {
215 TestReference(DirectoryHandle, pName, pNameUpper, FALSE, Tests[i].AdditionalReferences, (Tests[i].Flags & OBJ_PERMANENT) != 0);
216 /* try again for good measure */
217 TestReference(DirectoryHandle, pName, pNameUpper, FALSE, Tests[i].AdditionalReferences, FALSE);
218
219 Status = ZwClose(DirectoryHandle);
220 ok_eq_hex(Status, STATUS_SUCCESS);
221 DirectoryHandle = NULL;
222 }
223
224 if (pNameUpper)
225 RtlFreeUnicodeString(pNameUpper);
226 }
227
228 if (DirectoryHandle)
229 {
230 Status = ZwClose(DirectoryHandle);
231 ok_eq_hex(Status, STATUS_SUCCESS);
232 }
233
234 /* parameter tests */
235 /* bugcheck at APC_LEVEL
236 Status = ObReferenceObject(NULL);
237 Status = ObReferenceObjectByPointer(NULL, 0, NULL, UserMode);
238 Status = ObReferenceObjectByPointer(NULL, 0, NULL, KernelMode);*/
239
240 ExceptionStatus = STATUS_SUCCESS;
241 _SEH2_TRY {
242 Status = ZwClose(NULL);
243 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
244 Status = ZwClose((HANDLE)-1);
245 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
246 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
247 ExceptionStatus = _SEH2_GetExceptionCode();
248 } _SEH2_END;
249 ok_eq_hex(ExceptionStatus, STATUS_SUCCESS);
250
251 if (ObDirectoryObjectType)
252 {
253 ObDereferenceObject(ObDirectoryObjectType);
254 ObDirectoryObjectType = NULL;
255 }
256 }