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 HANDLE ParentHandle
, SystemRootHandle
, TargetHandle
;
27 PFILE_OBJECT ParentFileObject
, TargetFileObject
, SystemRootFileObject
;
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
,
60 #ifdef _PROPER_NT_EXPORTS
66 (PVOID
*)&TargetFileObject
,
68 ok_eq_hex(Status
, STATUS_SUCCESS
);
71 ok(TargetFileObject
!= NULL
, "Not target to continue!\n");
72 if (TargetFileObject
== NULL
)
74 if (TargetHandle
!= INVALID_HANDLE_VALUE
)
76 ObCloseHandle(TargetHandle
, KernelMode
);
81 /* Open target directory of \SystemRoot\Regedit.exe
82 * This must lead to \SystemRoot opening
84 IoStatusBlock
.Status
= 0xFFFFFFFF;
85 IoStatusBlock
.Information
= 0xFFFFFFFF;
86 InitializeObjectAttributes(&ObjectAttributes
,
88 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
90 Status
= IoCreateFile(&ParentHandle
,
91 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
96 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
98 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
103 IO_OPEN_TARGET_DIRECTORY
);
104 ok_eq_hex(Status
, STATUS_SUCCESS
);
105 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
106 if (Status
== STATUS_SUCCESS
)
108 Status
= ObReferenceObjectByHandle(ParentHandle
,
110 #ifdef _PROPER_NT_EXPORTS
116 (PVOID
*)&ParentFileObject
,
118 ok_eq_hex(Status
, STATUS_SUCCESS
);
119 if (Status
== STATUS_SUCCESS
)
121 /* At that point, file object must point to \SystemRoot
122 * But must not be the same FO than target (diverted file object)
123 * This means FCB & FileName are equal
124 * But CCB & FO are different
125 * CCB must be != NULL, otherwise it means open failed
127 ok(ParentFileObject
!= TargetFileObject
, "Diverted file object must be different\n");
128 ok_eq_pointer(ParentFileObject
->RelatedFileObject
, NULL
);
129 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
130 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
131 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
132 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
133 ObDereferenceObject(ParentFileObject
);
135 /* Because target exists FSD must signal it */
136 ok_eq_long(IoStatusBlock
.Information
, FILE_EXISTS
);
137 ObCloseHandle(ParentHandle
, KernelMode
);
140 /* Do the same with relative open */
141 IoStatusBlock
.Status
= 0xFFFFFFFF;
142 IoStatusBlock
.Information
= 0xFFFFFFFF;
143 InitializeObjectAttributes(&ObjectAttributes
,
145 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
147 Status
= ZwOpenFile(&SystemRootHandle
,
148 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
151 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
152 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
153 ok_eq_hex(Status
, STATUS_SUCCESS
);
154 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
155 if (Status
== STATUS_SUCCESS
)
157 IoStatusBlock
.Status
= 0xFFFFFFFF;
158 IoStatusBlock
.Information
= 0xFFFFFFFF;
159 InitializeObjectAttributes(&ObjectAttributes
,
161 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
164 Status
= IoCreateFile(&ParentHandle
,
165 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
170 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
172 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
177 IO_OPEN_TARGET_DIRECTORY
);
178 ok_eq_hex(Status
, STATUS_SUCCESS
);
179 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
180 if (Status
== STATUS_SUCCESS
)
182 Status
= ObReferenceObjectByHandle(ParentHandle
,
184 #ifdef _PROPER_NT_EXPORTS
190 (PVOID
*)&ParentFileObject
,
192 ok_eq_hex(Status
, STATUS_SUCCESS
);
193 if (Status
== STATUS_SUCCESS
)
195 ok(ParentFileObject
!= TargetFileObject
, "Diverted file object must be different\n");
196 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
197 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
198 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
199 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
200 Status
= ObReferenceObjectByHandle(SystemRootHandle
,
202 #ifdef _PROPER_NT_EXPORTS
208 (PVOID
*)&SystemRootFileObject
,
210 ok_eq_hex(Status
, STATUS_SUCCESS
);
211 if (Status
== STATUS_SUCCESS
)
213 ok_eq_pointer(ParentFileObject
->RelatedFileObject
, SystemRootFileObject
);
214 ok(ParentFileObject
->RelatedFileObject
!= TargetFileObject
, "File objects must be different\n");
215 ok(SystemRootFileObject
!= TargetFileObject
, "File objects must be different\n");
216 ObDereferenceObject(SystemRootFileObject
);
218 ObDereferenceObject(ParentFileObject
);
220 ok_eq_long(IoStatusBlock
.Information
, FILE_EXISTS
);
221 ObCloseHandle(ParentHandle
, KernelMode
);
223 ObCloseHandle(SystemRootHandle
, KernelMode
);
228 /* Now redo the same scheme, but using a target that doesn't exist
229 * The difference will be in IoStatusBlock.Information, the FSD will
230 * inform that the target doesn't exist.
231 * Clear for rename :-)
233 IoStatusBlock
.Status
= 0xFFFFFFFF;
234 IoStatusBlock
.Information
= 0xFFFFFFFF;
235 InitializeObjectAttributes(&ObjectAttributes
,
237 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
239 Status
= IoCreateFile(&ParentHandle
,
240 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
245 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
247 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
252 IO_OPEN_TARGET_DIRECTORY
);
253 ok_eq_hex(Status
, STATUS_SUCCESS
);
254 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
255 if (Status
== STATUS_SUCCESS
)
257 Status
= ObReferenceObjectByHandle(ParentHandle
,
259 #ifdef _PROPER_NT_EXPORTS
266 (PVOID
*)&ParentFileObject
,
268 ok_eq_hex(Status
, STATUS_SUCCESS
);
269 if (Status
== STATUS_SUCCESS
)
271 ok(ParentFileObject
!= TargetFileObject
, "Diverted file object must be different\n");
272 ok_eq_pointer(ParentFileObject
->RelatedFileObject
, NULL
);
273 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
274 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
275 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
276 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
277 ObDereferenceObject(ParentFileObject
);
279 ok_eq_long(IoStatusBlock
.Information
, FILE_DOES_NOT_EXIST
);
280 ObCloseHandle(ParentHandle
, KernelMode
);
283 IoStatusBlock
.Status
= 0xFFFFFFFF;
284 IoStatusBlock
.Information
= 0xFFFFFFFF;
285 InitializeObjectAttributes(&ObjectAttributes
,
287 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
289 Status
= ZwOpenFile(&SystemRootHandle
,
290 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
293 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
294 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
295 ok_eq_hex(Status
, STATUS_SUCCESS
);
296 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
297 if (Status
== STATUS_SUCCESS
)
299 IoStatusBlock
.Status
= 0xFFFFFFFF;
300 IoStatusBlock
.Information
= 0xFFFFFFFF;
301 InitializeObjectAttributes(&ObjectAttributes
,
303 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
306 Status
= IoCreateFile(&ParentHandle
,
307 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
312 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
314 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
319 IO_OPEN_TARGET_DIRECTORY
);
320 ok_eq_hex(Status
, STATUS_SUCCESS
);
321 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
322 if (Status
== STATUS_SUCCESS
)
324 Status
= ObReferenceObjectByHandle(ParentHandle
,
326 #ifdef _PROPER_NT_EXPORTS
333 (PVOID
*)&ParentFileObject
,
335 ok_eq_hex(Status
, STATUS_SUCCESS
);
336 if (Status
== STATUS_SUCCESS
)
338 ok(ParentFileObject
!= TargetFileObject
, "Diverted file object must be different\n");
339 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
340 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
341 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
342 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
343 Status
= ObReferenceObjectByHandle(SystemRootHandle
,
345 #ifdef _PROPER_NT_EXPORTS
352 (PVOID
*)&SystemRootFileObject
,
354 ok_eq_hex(Status
, STATUS_SUCCESS
);
355 if (Status
== STATUS_SUCCESS
)
357 ok_eq_pointer(ParentFileObject
->RelatedFileObject
, SystemRootFileObject
);
358 ok(ParentFileObject
->RelatedFileObject
!= TargetFileObject
, "File objects must be different\n");
359 ok(SystemRootFileObject
!= TargetFileObject
, "File objects must be different\n");
360 ObDereferenceObject(SystemRootFileObject
);
362 ObDereferenceObject(ParentFileObject
);
364 ok_eq_long(IoStatusBlock
.Information
, FILE_DOES_NOT_EXIST
);
365 ObCloseHandle(ParentHandle
, KernelMode
);
367 ObCloseHandle(SystemRootHandle
, KernelMode
);
370 ObDereferenceObject(TargetFileObject
);
371 ObCloseHandle(TargetHandle
, KernelMode
);
375 /* Direct target open of something that doesn't exist */
376 IoStatusBlock
.Status
= 0xFFFFFFFF;
377 IoStatusBlock
.Information
= 0xFFFFFFFF;
378 InitializeObjectAttributes(&ObjectAttributes
,
379 &SystemRootFoobarFoobar
,
380 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
382 Status
= IoCreateFile(&ParentHandle
,
383 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
388 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
390 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
395 IO_OPEN_TARGET_DIRECTORY
);
396 ok_eq_hex(Status
, STATUS_OBJECT_PATH_NOT_FOUND
);
397 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
398 if (Status
== STATUS_SUCCESS
)
400 ObCloseHandle(ParentHandle
, KernelMode
);
403 /* Relative target open of something that doesn't exist */
404 IoStatusBlock
.Status
= 0xFFFFFFFF;
405 IoStatusBlock
.Information
= 0xFFFFFFFF;
406 InitializeObjectAttributes(&ObjectAttributes
,
408 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
410 Status
= ZwOpenFile(&SystemRootHandle
,
411 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
414 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
415 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
416 ok_eq_hex(Status
, STATUS_SUCCESS
);
417 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
418 if (Status
== STATUS_SUCCESS
)
420 IoStatusBlock
.Status
= 0xFFFFFFFF;
421 IoStatusBlock
.Information
= 0xFFFFFFFF;
422 InitializeObjectAttributes(&ObjectAttributes
,
424 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
427 Status
= IoCreateFile(&ParentHandle
,
428 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
433 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
435 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
440 IO_OPEN_TARGET_DIRECTORY
);
441 ok_eq_hex(Status
, STATUS_OBJECT_PATH_NOT_FOUND
);
442 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
443 if (Status
== STATUS_SUCCESS
)
445 ObCloseHandle(ParentHandle
, KernelMode
);
447 ObCloseHandle(SystemRootHandle
, KernelMode
);
457 IO_STATUS_BLOCK IoStatusBlock
;
458 OBJECT_ATTRIBUTES ObjectAttributes
;
459 HANDLE ParentHandle
, SystemRootHandle
;
461 ok(ExGetPreviousMode() == UserMode
, "KernelMode returned!\n");
463 /* Attempt direct target open */
464 IoStatusBlock
.Status
= 0xFFFFFFFF;
465 IoStatusBlock
.Information
= 0xFFFFFFFF;
466 InitializeObjectAttributes(&ObjectAttributes
,
468 OBJ_CASE_INSENSITIVE
,
470 Status
= IoCreateFile(&ParentHandle
,
471 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
476 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
478 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
483 IO_OPEN_TARGET_DIRECTORY
);
484 ok_eq_hex(Status
, STATUS_ACCESS_VIOLATION
);
485 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
486 if (Status
== STATUS_SUCCESS
)
488 ObCloseHandle(ParentHandle
, KernelMode
);
491 /* Attempt relative target open */
492 IoStatusBlock
.Status
= 0xFFFFFFFF;
493 IoStatusBlock
.Information
= 0xFFFFFFFF;
494 InitializeObjectAttributes(&ObjectAttributes
,
496 OBJ_CASE_INSENSITIVE
,
498 Status
= ZwOpenFile(&SystemRootHandle
,
499 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
502 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
503 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
504 ok_eq_hex(Status
, STATUS_SUCCESS
);
505 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
506 if (Status
== STATUS_SUCCESS
)
508 IoStatusBlock
.Status
= 0xFFFFFFFF;
509 IoStatusBlock
.Information
= 0xFFFFFFFF;
510 InitializeObjectAttributes(&ObjectAttributes
,
512 OBJ_CASE_INSENSITIVE
,
515 Status
= IoCreateFile(&ParentHandle
,
516 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
521 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
523 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
528 IO_OPEN_TARGET_DIRECTORY
);
529 ok_eq_hex(Status
, STATUS_ACCESS_VIOLATION
);
530 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
531 if (Status
== STATUS_SUCCESS
)
533 ObCloseHandle(ParentHandle
, KernelMode
);
535 ObCloseHandle(SystemRootHandle
, KernelMode
);
539 START_TEST(IoCreateFile
)
542 OBJECT_ATTRIBUTES ObjectAttributes
;
544 PVOID ThreadObject
= NULL
;
546 /* Justify the next comment/statement */
549 /* We've to be in kernel mode, so spawn a thread */
550 InitializeObjectAttributes(&ObjectAttributes
,
555 Status
= PsCreateSystemThread(&ThreadHandle
,
562 ok_eq_hex(Status
, STATUS_SUCCESS
);
563 if (Status
== STATUS_SUCCESS
)
565 /* Then, just wait on our thread to finish */
566 Status
= ObReferenceObjectByHandle(ThreadHandle
,
568 #ifdef _PROPER_NT_EXPORTS
576 ObCloseHandle(ThreadHandle
, KernelMode
);
578 Status
= KeWaitForSingleObject(ThreadObject
,
583 ok_eq_hex(Status
, STATUS_SUCCESS
);
584 ObDereferenceObject(ThreadObject
);