[KMTESTS:FSRTL]
[reactos.git] / rostests / kmtests / ntos_ob / ObHandle.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Object Handle 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, Attrib, Access) 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_hex(ObjectInfo.Attributes, Attrib); \
19 ok_eq_hex(ObjectInfo.GrantedAccess, Access); \
20 ok_eq_ulong(ObjectInfo.PointerCount, Pointers); \
21 ok_eq_ulong(ObjectInfo.HandleCount, Handles); \
22 } while (0)
23
24 #define KERNEL_HANDLE_FLAG ((ULONG_PTR)0xFFFFFFFF80000000)
25 #define IsUserHandle(h) (((ULONG_PTR)(h) & KERNEL_HANDLE_FLAG) == 0)
26 #define IsKernelHandle(h) (((ULONG_PTR)(h) & KERNEL_HANDLE_FLAG) == KERNEL_HANDLE_FLAG)
27
28 static HANDLE SystemProcessHandle;
29
30 static
31 VOID
32 TestDuplicate(
33 _In_ HANDLE Handle)
34 {
35 NTSTATUS Status;
36 HANDLE NewHandle;
37 struct
38 {
39 ACCESS_MASK DesiredAccess;
40 ULONG RequestedAttributes;
41 ULONG Options;
42 ACCESS_MASK GrantedAccess;
43 ULONG ExpectedAttributes;
44 } Tests[] =
45 {
46 { DIRECTORY_ALL_ACCESS, 0, 0,
47 DIRECTORY_ALL_ACCESS, 0 },
48 { DIRECTORY_ALL_ACCESS, OBJ_KERNEL_HANDLE, 0,
49 DIRECTORY_ALL_ACCESS, 0 },
50 { DIRECTORY_QUERY, 0, 0,
51 DIRECTORY_QUERY, 0 },
52 { DIRECTORY_QUERY, OBJ_INHERIT, 0,
53 DIRECTORY_QUERY, OBJ_INHERIT },
54 { DIRECTORY_QUERY, OBJ_INHERIT, DUPLICATE_SAME_ACCESS,
55 DIRECTORY_ALL_ACCESS, OBJ_INHERIT },
56 /* 5 */
57 { DIRECTORY_QUERY, OBJ_INHERIT, DUPLICATE_SAME_ATTRIBUTES,
58 DIRECTORY_QUERY, 0 },
59 { DIRECTORY_QUERY, OBJ_INHERIT, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES,
60 DIRECTORY_ALL_ACCESS, 0 },
61 };
62 ULONG i;
63
64 for (i = 0; i < RTL_NUMBER_OF(Tests); i++)
65 {
66 trace("Test %lu\n", i);
67 Status = ZwDuplicateObject(ZwCurrentProcess(),
68 Handle,
69 ZwCurrentProcess(),
70 &NewHandle,
71 Tests[i].DesiredAccess,
72 Tests[i].RequestedAttributes,
73 Tests[i].Options);
74 ok_eq_hex(Status, STATUS_SUCCESS);
75 if (!skip(NT_SUCCESS(Status), "DuplicateHandle failed\n"))
76 {
77 ok(IsUserHandle(NewHandle), "New handle = %p\n", NewHandle);
78 CheckObject(NewHandle, 3UL, 2UL, Tests[i].ExpectedAttributes, Tests[i].GrantedAccess);
79 CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS);
80
81 Status = ObCloseHandle(NewHandle, UserMode);
82 ok_eq_hex(Status, STATUS_SUCCESS);
83 CheckObject(Handle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS);
84 }
85 }
86
87 /* If TargetProcess is the System process, we do get a kernel handle */
88 Status = ZwDuplicateObject(ZwCurrentProcess(),
89 Handle,
90 SystemProcessHandle,
91 &NewHandle,
92 DIRECTORY_ALL_ACCESS,
93 OBJ_KERNEL_HANDLE,
94 0);
95 ok_eq_hex(Status, STATUS_SUCCESS);
96 if (!skip(NT_SUCCESS(Status), "DuplicateHandle failed\n"))
97 {
98 ok(IsKernelHandle(NewHandle), "New handle = %p\n", NewHandle);
99 CheckObject(NewHandle, 3UL, 2UL, 0, DIRECTORY_ALL_ACCESS);
100 CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS);
101
102 Status = ObCloseHandle(NewHandle, UserMode);
103 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
104 CheckObject(NewHandle, 3UL, 2UL, 0, DIRECTORY_ALL_ACCESS);
105 CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS);
106
107 if (IsKernelHandle(NewHandle))
108 {
109 Status = ObCloseHandle(NewHandle, KernelMode);
110 ok_eq_hex(Status, STATUS_SUCCESS);
111 CheckObject(Handle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS);
112 }
113 }
114 }
115
116 START_TEST(ObHandle)
117 {
118 NTSTATUS Status;
119 OBJECT_ATTRIBUTES ObjectAttributes;
120 HANDLE KernelDirectoryHandle;
121 HANDLE UserDirectoryHandle;
122
123 Status = ObOpenObjectByPointer(PsInitialSystemProcess,
124 OBJ_KERNEL_HANDLE,
125 NULL,
126 PROCESS_ALL_ACCESS,
127 *PsProcessType,
128 KernelMode,
129 &SystemProcessHandle);
130 ok_eq_hex(Status, STATUS_SUCCESS);
131 if (skip(NT_SUCCESS(Status), "No handle for system process\n"))
132 {
133 SystemProcessHandle = NULL;
134 }
135
136 InitializeObjectAttributes(&ObjectAttributes,
137 NULL,
138 0,
139 NULL,
140 NULL);
141 Status = ZwCreateDirectoryObject(&UserDirectoryHandle,
142 DIRECTORY_ALL_ACCESS,
143 &ObjectAttributes);
144 ok_eq_hex(Status, STATUS_SUCCESS);
145 if (!skip(NT_SUCCESS(Status), "No directory handle\n"))
146 {
147 ok(IsUserHandle(UserDirectoryHandle), "User handle = %p\n", UserDirectoryHandle);
148 CheckObject(UserDirectoryHandle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS);
149
150 TestDuplicate(UserDirectoryHandle);
151
152 Status = ObCloseHandle(UserDirectoryHandle, UserMode);
153 ok_eq_hex(Status, STATUS_SUCCESS);
154 }
155
156 InitializeObjectAttributes(&ObjectAttributes,
157 NULL,
158 OBJ_KERNEL_HANDLE,
159 NULL,
160 NULL);
161 Status = ZwCreateDirectoryObject(&KernelDirectoryHandle,
162 DIRECTORY_ALL_ACCESS,
163 &ObjectAttributes);
164 ok_eq_hex(Status, STATUS_SUCCESS);
165 if (!skip(NT_SUCCESS(Status), "No directory handle\n"))
166 {
167 ok(IsKernelHandle(KernelDirectoryHandle), "Kernel handle = %p\n", KernelDirectoryHandle);
168 CheckObject(KernelDirectoryHandle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS);
169
170 TestDuplicate(KernelDirectoryHandle);
171
172 Status = ObCloseHandle(KernelDirectoryHandle, UserMode);
173 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
174 CheckObject(KernelDirectoryHandle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS);
175
176 Status = ObCloseHandle(KernelDirectoryHandle, KernelMode);
177 ok_eq_hex(Status, STATUS_SUCCESS);
178 }
179
180 /* Tests for closing handles */
181 KmtStartSeh()
182 /* NtClose must accept everything */
183 DPRINT("Closing null handle (NtClose)\n");
184 Status = NtClose(NULL);
185 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
186 DPRINT("Closing null kernel handle (NtClose)\n");
187 Status = NtClose((HANDLE)0x80000000);
188 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
189 DPRINT("Closing -1 handle (NtClose)\n");
190 Status = NtClose((HANDLE)0x7FFFFFFF);
191 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
192 DPRINT("Closing -1 kernel handle (NtClose)\n");
193 Status = NtClose((HANDLE)0xFFFFFFFF);
194 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
195 DPRINT("Closing 123 handle (NtClose)\n");
196 Status = NtClose((HANDLE)123);
197 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
198 DPRINT("Closing 123 kernel handle (NtClose)\n");
199 Status = NtClose((HANDLE)(123 | 0x80000000));
200 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
201
202 /* ObCloseHandle with UserMode accepts everything */
203 DPRINT("Closing null handle (ObCloseHandle, UserMode)\n");
204 Status = ObCloseHandle(NULL, UserMode);
205 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
206 DPRINT("Closing null kernel handle (ObCloseHandle, UserMode)\n");
207 Status = ObCloseHandle((HANDLE)0x80000000, UserMode);
208 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
209 DPRINT("Closing -1 handle (ObCloseHandle, UserMode)\n");
210 Status = ObCloseHandle((HANDLE)0x7FFFFFFF, UserMode);
211 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
212 DPRINT("Closing -1 kernel handle (ObCloseHandle, UserMode)\n");
213 Status = ObCloseHandle((HANDLE)0xFFFFFFFF, UserMode);
214 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
215 DPRINT("Closing 123 handle (ObCloseHandle, UserMode)\n");
216 Status = ObCloseHandle((HANDLE)123, UserMode);
217 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
218 DPRINT("Closing 123 kernel handle (ObCloseHandle, UserMode)\n");
219 Status = ObCloseHandle((HANDLE)(123 | 0x80000000), UserMode);
220 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
221
222 /* ZwClose only accepts 0 and -1 */
223 DPRINT("Closing null handle (ZwClose)\n");
224 Status = ZwClose(NULL);
225 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
226 DPRINT("Closing null kernel handle (ZwClose)\n");
227 Status = ZwClose((HANDLE)0x80000000);
228 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
229 /* INVALID_KERNEL_HANDLE, 0x7FFFFFFF
230 Status = ZwClose((HANDLE)0x7FFFFFFF);*/
231 DPRINT("Closing -1 kernel handle (ZwClose)\n");
232 Status = ZwClose((HANDLE)0xFFFFFFFF);
233 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
234 /* INVALID_KERNEL_HANDLE, 0x7B, 1, 0, 0
235 Status = ZwClose((HANDLE)123);
236 Status = ZwClose((HANDLE)(123 | 0x80000000));*/
237
238 /* ObCloseHandle with KernelMode accepts only 0 and -1 */
239 DPRINT("Closing null handle (ObCloseHandle, KernelMode)\n");
240 Status = ObCloseHandle(NULL, KernelMode);
241 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
242 DPRINT("Closing null kernel handle (ObCloseHandle, KernelMode)\n");
243 Status = ObCloseHandle((HANDLE)0x80000000, KernelMode);
244 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
245 /* INVALID_KERNEL_HANDLE, 0x7FFFFFFF, 1, 0, 0
246 Status = ObCloseHandle((HANDLE)0x7FFFFFFF, KernelMode);*/
247 DPRINT("Closing -1 kernel handle (ObCloseHandle, KernelMode)\n");
248 Status = ObCloseHandle((HANDLE)0xFFFFFFFF, KernelMode);
249 ok_eq_hex(Status, STATUS_INVALID_HANDLE);
250 /* INVALID_KERNEL_HANDLE, 0x7B, 1, 0, 0
251 Status = ObCloseHandle((HANDLE)123, KernelMode);
252 Status = ObCloseHandle((HANDLE)(123 | 0x80000000), KernelMode);*/
253 KmtEndSeh(STATUS_SUCCESS);
254
255 if (SystemProcessHandle)
256 {
257 ObCloseHandle(SystemProcessHandle, KernelMode);
258 }
259 }