2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Io Regressions KM-Test (IoCreateFile)
5 * PROGRAMMER: Pierre Schweitzer <pierre@reactos.org>
10 static UNICODE_STRING SystemRoot
= RTL_CONSTANT_STRING(L
"\\SystemRoot\\");
11 static UNICODE_STRING Regedit
= RTL_CONSTANT_STRING(L
"regedit.exe");
12 static UNICODE_STRING Foobar
= RTL_CONSTANT_STRING(L
"foobar.exe");
13 static UNICODE_STRING SystemRootRegedit
= RTL_CONSTANT_STRING(L
"\\SystemRoot\\regedit.exe");
14 static UNICODE_STRING SystemRootFoobar
= RTL_CONSTANT_STRING(L
"\\SystemRoot\\foobar.exe");
15 static UNICODE_STRING SystemRootFoobarFoobar
= RTL_CONSTANT_STRING(L
"\\SystemRoot\\foobar\\foobar.exe");
16 static UNICODE_STRING FoobarFoobar
= RTL_CONSTANT_STRING(L
"foobar\\foobar.exe");
21 KernelModeTest(IN PVOID Context
)
24 IO_STATUS_BLOCK IoStatusBlock
;
25 OBJECT_ATTRIBUTES ObjectAttributes
;
26 PFILE_OBJECT ParentFileObject
, TargetFileObject
;
27 HANDLE ParentHandle
, SystemRootHandle
, TargetHandle
;
29 UNREFERENCED_PARAMETER(Context
);
31 /* Kernelmode mandatory for IoCreateFile */
32 ok(ExGetPreviousMode() == KernelMode
, "UserMode returned!\n");
34 /* First of all, open \\SystemRoot
35 * We're interested in 3 pieces of information about it:
36 * -> Its target (it's a symlink): \Windows or \ReactOS
37 * -> Its associated File Object
38 * -> Its associated FCB
40 TargetFileObject
= NULL
;
41 IoStatusBlock
.Status
= 0xFFFFFFFF;
42 TargetHandle
= INVALID_HANDLE_VALUE
;
43 IoStatusBlock
.Information
= 0xFFFFFFFF;
44 InitializeObjectAttributes(&ObjectAttributes
,
46 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
48 Status
= ZwOpenFile(&TargetHandle
,
49 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
52 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
53 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
54 ok_eq_hex(Status
, STATUS_SUCCESS
);
55 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
56 if (Status
== STATUS_SUCCESS
)
58 Status
= ObReferenceObjectByHandle(TargetHandle
,
62 (PVOID
*)&TargetFileObject
,
64 ok_eq_hex(Status
, STATUS_SUCCESS
);
67 ok(TargetFileObject
!= NULL
, "Not target to continue!\n");
68 if (TargetFileObject
== NULL
)
70 if (TargetHandle
!= INVALID_HANDLE_VALUE
)
72 ObCloseHandle(TargetHandle
, KernelMode
);
77 /* Open target directory of \SystemRoot\Regedit.exe
78 * This must lead to \SystemRoot opening
80 IoStatusBlock
.Status
= 0xFFFFFFFF;
81 IoStatusBlock
.Information
= 0xFFFFFFFF;
82 InitializeObjectAttributes(&ObjectAttributes
,
84 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
86 Status
= IoCreateFile(&ParentHandle
,
87 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
92 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
94 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
99 IO_OPEN_TARGET_DIRECTORY
);
100 ok_eq_hex(Status
, STATUS_SUCCESS
);
101 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
102 if (Status
== STATUS_SUCCESS
)
104 Status
= ObReferenceObjectByHandle(ParentHandle
,
108 (PVOID
*)&ParentFileObject
,
110 ok_eq_hex(Status
, STATUS_SUCCESS
);
111 if (Status
== STATUS_SUCCESS
)
113 /* At that point, file object must point to \SystemRoot
114 * But must not be the same FO than target (diverted file object)
115 * This means FCB & FileName are equal
116 * But CCB & FO are different
117 * CCB must be != NULL, otherwise it means open failed
119 ok(ParentFileObject
!= TargetFileObject
, "Diverted file object must be different\n");
120 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
121 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
122 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
123 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
124 ObDereferenceObject(ParentFileObject
);
126 /* Because target exists FSD must signal it */
127 ok_eq_long(IoStatusBlock
.Information
, FILE_EXISTS
);
128 ObCloseHandle(ParentHandle
, KernelMode
);
131 /* Do the same with relative open */
132 IoStatusBlock
.Status
= 0xFFFFFFFF;
133 IoStatusBlock
.Information
= 0xFFFFFFFF;
134 InitializeObjectAttributes(&ObjectAttributes
,
136 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
138 Status
= ZwOpenFile(&SystemRootHandle
,
139 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
142 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
143 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
144 ok_eq_hex(Status
, STATUS_SUCCESS
);
145 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
146 if (Status
== STATUS_SUCCESS
)
148 IoStatusBlock
.Status
= 0xFFFFFFFF;
149 IoStatusBlock
.Information
= 0xFFFFFFFF;
150 InitializeObjectAttributes(&ObjectAttributes
,
152 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
155 Status
= IoCreateFile(&ParentHandle
,
156 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
161 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
163 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
168 IO_OPEN_TARGET_DIRECTORY
);
169 ok_eq_hex(Status
, STATUS_SUCCESS
);
170 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
171 if (Status
== STATUS_SUCCESS
)
173 Status
= ObReferenceObjectByHandle(ParentHandle
,
177 (PVOID
*)&ParentFileObject
,
179 ok_eq_hex(Status
, STATUS_SUCCESS
);
180 if (Status
== STATUS_SUCCESS
)
182 ok(ParentFileObject
!= TargetFileObject
, "Diverted file object must be different\n");
183 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
184 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
185 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
186 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
187 ObDereferenceObject(ParentFileObject
);
189 ok_eq_long(IoStatusBlock
.Information
, FILE_EXISTS
);
190 ObCloseHandle(ParentHandle
, KernelMode
);
192 ObCloseHandle(SystemRootHandle
, KernelMode
);
197 /* Now redo the same scheme, but using a target that doesn't exist
198 * The difference will be in IoStatusBlock.Information, the FSD will
199 * inform that the target doesn't exist.
200 * Clear for rename :-)
202 IoStatusBlock
.Status
= 0xFFFFFFFF;
203 IoStatusBlock
.Information
= 0xFFFFFFFF;
204 InitializeObjectAttributes(&ObjectAttributes
,
206 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
208 Status
= IoCreateFile(&ParentHandle
,
209 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
214 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
216 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
221 IO_OPEN_TARGET_DIRECTORY
);
222 ok_eq_hex(Status
, STATUS_SUCCESS
);
223 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
224 if (Status
== STATUS_SUCCESS
)
226 Status
= ObReferenceObjectByHandle(ParentHandle
,
230 (PVOID
*)&ParentFileObject
,
232 ok_eq_hex(Status
, STATUS_SUCCESS
);
233 if (Status
== STATUS_SUCCESS
)
235 ok(ParentFileObject
!= TargetFileObject
, "Diverted file object must be different\n");
236 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
237 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
238 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
239 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
240 ObDereferenceObject(ParentFileObject
);
242 ok_eq_long(IoStatusBlock
.Information
, FILE_DOES_NOT_EXIST
);
243 ObCloseHandle(ParentHandle
, KernelMode
);
246 IoStatusBlock
.Status
= 0xFFFFFFFF;
247 IoStatusBlock
.Information
= 0xFFFFFFFF;
248 InitializeObjectAttributes(&ObjectAttributes
,
250 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
252 Status
= ZwOpenFile(&SystemRootHandle
,
253 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
256 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
257 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
258 ok_eq_hex(Status
, STATUS_SUCCESS
);
259 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
260 if (Status
== STATUS_SUCCESS
)
262 IoStatusBlock
.Status
= 0xFFFFFFFF;
263 IoStatusBlock
.Information
= 0xFFFFFFFF;
264 InitializeObjectAttributes(&ObjectAttributes
,
266 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
269 Status
= IoCreateFile(&ParentHandle
,
270 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
275 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
277 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
282 IO_OPEN_TARGET_DIRECTORY
);
283 ok_eq_hex(Status
, STATUS_SUCCESS
);
284 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
285 if (Status
== STATUS_SUCCESS
)
287 Status
= ObReferenceObjectByHandle(ParentHandle
,
291 (PVOID
*)&ParentFileObject
,
293 ok_eq_hex(Status
, STATUS_SUCCESS
);
294 if (Status
== STATUS_SUCCESS
)
296 ok(ParentFileObject
!= TargetFileObject
, "Diverted file object must be different\n");
297 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
298 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
299 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
300 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
301 ObDereferenceObject(ParentFileObject
);
303 ok_eq_long(IoStatusBlock
.Information
, FILE_DOES_NOT_EXIST
);
304 ObCloseHandle(ParentHandle
, KernelMode
);
306 ObCloseHandle(SystemRootHandle
, KernelMode
);
309 ObDereferenceObject(TargetFileObject
);
310 ObCloseHandle(TargetHandle
, KernelMode
);
314 /* Direct target open of something that doesn't exist */
315 IoStatusBlock
.Status
= 0xFFFFFFFF;
316 IoStatusBlock
.Information
= 0xFFFFFFFF;
317 InitializeObjectAttributes(&ObjectAttributes
,
318 &SystemRootFoobarFoobar
,
319 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
321 Status
= IoCreateFile(&ParentHandle
,
322 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
327 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
329 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
334 IO_OPEN_TARGET_DIRECTORY
);
335 ok_eq_hex(Status
, STATUS_OBJECT_PATH_NOT_FOUND
);
336 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
337 if (Status
== STATUS_SUCCESS
)
339 ObCloseHandle(ParentHandle
, KernelMode
);
342 /* Relative target open of something that doesn't exist */
343 IoStatusBlock
.Status
= 0xFFFFFFFF;
344 IoStatusBlock
.Information
= 0xFFFFFFFF;
345 InitializeObjectAttributes(&ObjectAttributes
,
347 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
349 Status
= ZwOpenFile(&SystemRootHandle
,
350 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
353 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
354 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
355 ok_eq_hex(Status
, STATUS_SUCCESS
);
356 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
357 if (Status
== STATUS_SUCCESS
)
359 IoStatusBlock
.Status
= 0xFFFFFFFF;
360 IoStatusBlock
.Information
= 0xFFFFFFFF;
361 InitializeObjectAttributes(&ObjectAttributes
,
363 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
366 Status
= IoCreateFile(&ParentHandle
,
367 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
372 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
374 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
379 IO_OPEN_TARGET_DIRECTORY
);
380 ok_eq_hex(Status
, STATUS_OBJECT_PATH_NOT_FOUND
);
381 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
382 if (Status
== STATUS_SUCCESS
)
384 ObCloseHandle(ParentHandle
, KernelMode
);
386 ObCloseHandle(SystemRootHandle
, KernelMode
);
396 IO_STATUS_BLOCK IoStatusBlock
;
397 OBJECT_ATTRIBUTES ObjectAttributes
;
398 HANDLE ParentHandle
, SystemRootHandle
;
400 ok(ExGetPreviousMode() == UserMode
, "KernelMode returned!\n");
402 /* Attempt direct target open */
403 IoStatusBlock
.Status
= 0xFFFFFFFF;
404 IoStatusBlock
.Information
= 0xFFFFFFFF;
405 InitializeObjectAttributes(&ObjectAttributes
,
407 OBJ_CASE_INSENSITIVE
,
409 Status
= IoCreateFile(&ParentHandle
,
410 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
415 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
417 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
422 IO_OPEN_TARGET_DIRECTORY
);
423 ok_eq_hex(Status
, STATUS_ACCESS_VIOLATION
);
424 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
425 if (Status
== STATUS_SUCCESS
)
427 ObCloseHandle(ParentHandle
, KernelMode
);
430 /* Attempt relative target open */
431 IoStatusBlock
.Status
= 0xFFFFFFFF;
432 IoStatusBlock
.Information
= 0xFFFFFFFF;
433 InitializeObjectAttributes(&ObjectAttributes
,
435 OBJ_CASE_INSENSITIVE
,
437 Status
= ZwOpenFile(&SystemRootHandle
,
438 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
441 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
442 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
443 ok_eq_hex(Status
, STATUS_SUCCESS
);
444 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
445 if (Status
== STATUS_SUCCESS
)
447 IoStatusBlock
.Status
= 0xFFFFFFFF;
448 IoStatusBlock
.Information
= 0xFFFFFFFF;
449 InitializeObjectAttributes(&ObjectAttributes
,
451 OBJ_CASE_INSENSITIVE
,
454 Status
= IoCreateFile(&ParentHandle
,
455 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
460 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
462 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
467 IO_OPEN_TARGET_DIRECTORY
);
468 ok_eq_hex(Status
, STATUS_ACCESS_VIOLATION
);
469 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
470 if (Status
== STATUS_SUCCESS
)
472 ObCloseHandle(ParentHandle
, KernelMode
);
474 ObCloseHandle(SystemRootHandle
, KernelMode
);
478 START_TEST(IoCreateFile
)
481 OBJECT_ATTRIBUTES ObjectAttributes
;
483 PVOID ThreadObject
= NULL
;
485 /* Justify the next comment/statement */
488 /* We've to be in kernel mode, so spawn a thread */
489 InitializeObjectAttributes(&ObjectAttributes
,
494 Status
= PsCreateSystemThread(&ThreadHandle
,
501 ok_eq_hex(Status
, STATUS_SUCCESS
);
502 if (Status
== STATUS_SUCCESS
)
504 /* Then, just wait on our thread to finish */
505 Status
= ObReferenceObjectByHandle(ThreadHandle
,
511 ObCloseHandle(ThreadHandle
, KernelMode
);
513 Status
= KeWaitForSingleObject(ThreadObject
,
518 ok_eq_hex(Status
, STATUS_SUCCESS
);
519 ObDereferenceObject(ThreadObject
);