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
,
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
->RelatedFileObject
, NULL
);
121 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
122 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
123 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
124 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
125 ObDereferenceObject(ParentFileObject
);
127 /* Because target exists FSD must signal it */
128 ok_eq_long(IoStatusBlock
.Information
, FILE_EXISTS
);
129 ObCloseHandle(ParentHandle
, KernelMode
);
132 /* Do the same with relative open */
133 IoStatusBlock
.Status
= 0xFFFFFFFF;
134 IoStatusBlock
.Information
= 0xFFFFFFFF;
135 InitializeObjectAttributes(&ObjectAttributes
,
137 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
139 Status
= ZwOpenFile(&SystemRootHandle
,
140 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
143 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
144 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
145 ok_eq_hex(Status
, STATUS_SUCCESS
);
146 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
147 if (Status
== STATUS_SUCCESS
)
149 IoStatusBlock
.Status
= 0xFFFFFFFF;
150 IoStatusBlock
.Information
= 0xFFFFFFFF;
151 InitializeObjectAttributes(&ObjectAttributes
,
153 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
156 Status
= IoCreateFile(&ParentHandle
,
157 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
162 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
164 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
169 IO_OPEN_TARGET_DIRECTORY
);
170 ok_eq_hex(Status
, STATUS_SUCCESS
);
171 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
172 if (Status
== STATUS_SUCCESS
)
174 Status
= ObReferenceObjectByHandle(ParentHandle
,
178 (PVOID
*)&ParentFileObject
,
180 ok_eq_hex(Status
, STATUS_SUCCESS
);
181 if (Status
== STATUS_SUCCESS
)
183 ok(ParentFileObject
!= TargetFileObject
, "Diverted file object must be different\n");
184 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
185 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
186 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
187 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
188 Status
= ObReferenceObjectByHandle(SystemRootHandle
,
192 (PVOID
*)&SystemRootFileObject
,
194 ok_eq_hex(Status
, STATUS_SUCCESS
);
195 if (Status
== STATUS_SUCCESS
)
197 ok_eq_pointer(ParentFileObject
->RelatedFileObject
, SystemRootFileObject
);
198 ok(ParentFileObject
->RelatedFileObject
!= TargetFileObject
, "File objects must be different\n");
199 ok(SystemRootFileObject
!= TargetFileObject
, "File objects must be different\n");
200 ObDereferenceObject(SystemRootFileObject
);
202 ObDereferenceObject(ParentFileObject
);
204 ok_eq_long(IoStatusBlock
.Information
, FILE_EXISTS
);
205 ObCloseHandle(ParentHandle
, KernelMode
);
207 ObCloseHandle(SystemRootHandle
, KernelMode
);
212 /* Now redo the same scheme, but using a target that doesn't exist
213 * The difference will be in IoStatusBlock.Information, the FSD will
214 * inform that the target doesn't exist.
215 * Clear for rename :-)
217 IoStatusBlock
.Status
= 0xFFFFFFFF;
218 IoStatusBlock
.Information
= 0xFFFFFFFF;
219 InitializeObjectAttributes(&ObjectAttributes
,
221 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
223 Status
= IoCreateFile(&ParentHandle
,
224 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
229 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
231 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
236 IO_OPEN_TARGET_DIRECTORY
);
237 ok_eq_hex(Status
, STATUS_SUCCESS
);
238 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
239 if (Status
== STATUS_SUCCESS
)
241 Status
= ObReferenceObjectByHandle(ParentHandle
,
245 (PVOID
*)&ParentFileObject
,
247 ok_eq_hex(Status
, STATUS_SUCCESS
);
248 if (Status
== STATUS_SUCCESS
)
250 ok(ParentFileObject
!= TargetFileObject
, "Diverted file object must be different\n");
251 ok_eq_pointer(ParentFileObject
->RelatedFileObject
, NULL
);
252 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
253 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
254 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
255 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
256 ObDereferenceObject(ParentFileObject
);
258 ok_eq_long(IoStatusBlock
.Information
, FILE_DOES_NOT_EXIST
);
259 ObCloseHandle(ParentHandle
, KernelMode
);
262 IoStatusBlock
.Status
= 0xFFFFFFFF;
263 IoStatusBlock
.Information
= 0xFFFFFFFF;
264 InitializeObjectAttributes(&ObjectAttributes
,
266 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
268 Status
= ZwOpenFile(&SystemRootHandle
,
269 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
272 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
273 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
274 ok_eq_hex(Status
, STATUS_SUCCESS
);
275 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
276 if (Status
== STATUS_SUCCESS
)
278 IoStatusBlock
.Status
= 0xFFFFFFFF;
279 IoStatusBlock
.Information
= 0xFFFFFFFF;
280 InitializeObjectAttributes(&ObjectAttributes
,
282 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
285 Status
= IoCreateFile(&ParentHandle
,
286 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
291 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
293 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
298 IO_OPEN_TARGET_DIRECTORY
);
299 ok_eq_hex(Status
, STATUS_SUCCESS
);
300 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
301 if (Status
== STATUS_SUCCESS
)
303 Status
= ObReferenceObjectByHandle(ParentHandle
,
307 (PVOID
*)&ParentFileObject
,
309 ok_eq_hex(Status
, STATUS_SUCCESS
);
310 if (Status
== STATUS_SUCCESS
)
312 ok(ParentFileObject
!= TargetFileObject
, "Diverted file object must be different\n");
313 ok_eq_pointer(ParentFileObject
->FsContext
, TargetFileObject
->FsContext
);
314 ok(ParentFileObject
->FsContext2
!= 0x0, "Parent must be open!\n");
315 ok(ParentFileObject
->FsContext2
!= TargetFileObject
->FsContext2
, "Parent open must have its own context!\n");
316 ok_eq_long(RtlCompareUnicodeString(&ParentFileObject
->FileName
, &TargetFileObject
->FileName
, FALSE
), 0);
317 Status
= ObReferenceObjectByHandle(SystemRootHandle
,
321 (PVOID
*)&SystemRootFileObject
,
323 ok_eq_hex(Status
, STATUS_SUCCESS
);
324 if (Status
== STATUS_SUCCESS
)
326 ok_eq_pointer(ParentFileObject
->RelatedFileObject
, SystemRootFileObject
);
327 ok(ParentFileObject
->RelatedFileObject
!= TargetFileObject
, "File objects must be different\n");
328 ok(SystemRootFileObject
!= TargetFileObject
, "File objects must be different\n");
329 ObDereferenceObject(SystemRootFileObject
);
331 ObDereferenceObject(ParentFileObject
);
333 ok_eq_long(IoStatusBlock
.Information
, FILE_DOES_NOT_EXIST
);
334 ObCloseHandle(ParentHandle
, KernelMode
);
336 ObCloseHandle(SystemRootHandle
, KernelMode
);
339 ObDereferenceObject(TargetFileObject
);
340 ObCloseHandle(TargetHandle
, KernelMode
);
344 /* Direct target open of something that doesn't exist */
345 IoStatusBlock
.Status
= 0xFFFFFFFF;
346 IoStatusBlock
.Information
= 0xFFFFFFFF;
347 InitializeObjectAttributes(&ObjectAttributes
,
348 &SystemRootFoobarFoobar
,
349 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
351 Status
= IoCreateFile(&ParentHandle
,
352 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
357 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
359 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
364 IO_OPEN_TARGET_DIRECTORY
);
365 ok_eq_hex(Status
, STATUS_OBJECT_PATH_NOT_FOUND
);
366 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
367 if (Status
== STATUS_SUCCESS
)
369 ObCloseHandle(ParentHandle
, KernelMode
);
372 /* Relative target open of something that doesn't exist */
373 IoStatusBlock
.Status
= 0xFFFFFFFF;
374 IoStatusBlock
.Information
= 0xFFFFFFFF;
375 InitializeObjectAttributes(&ObjectAttributes
,
377 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
379 Status
= ZwOpenFile(&SystemRootHandle
,
380 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
383 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
384 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
385 ok_eq_hex(Status
, STATUS_SUCCESS
);
386 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
387 if (Status
== STATUS_SUCCESS
)
389 IoStatusBlock
.Status
= 0xFFFFFFFF;
390 IoStatusBlock
.Information
= 0xFFFFFFFF;
391 InitializeObjectAttributes(&ObjectAttributes
,
393 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
396 Status
= IoCreateFile(&ParentHandle
,
397 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
402 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
404 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
409 IO_OPEN_TARGET_DIRECTORY
);
410 ok_eq_hex(Status
, STATUS_OBJECT_PATH_NOT_FOUND
);
411 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
412 if (Status
== STATUS_SUCCESS
)
414 ObCloseHandle(ParentHandle
, KernelMode
);
416 ObCloseHandle(SystemRootHandle
, KernelMode
);
426 IO_STATUS_BLOCK IoStatusBlock
;
427 OBJECT_ATTRIBUTES ObjectAttributes
;
428 HANDLE ParentHandle
, SystemRootHandle
;
430 ok(ExGetPreviousMode() == UserMode
, "KernelMode returned!\n");
432 /* Attempt direct target open */
433 IoStatusBlock
.Status
= 0xFFFFFFFF;
434 IoStatusBlock
.Information
= 0xFFFFFFFF;
435 InitializeObjectAttributes(&ObjectAttributes
,
437 OBJ_CASE_INSENSITIVE
,
439 Status
= IoCreateFile(&ParentHandle
,
440 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
445 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
447 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
452 IO_OPEN_TARGET_DIRECTORY
);
453 ok_eq_hex(Status
, STATUS_ACCESS_VIOLATION
);
454 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
455 if (Status
== STATUS_SUCCESS
)
457 ObCloseHandle(ParentHandle
, KernelMode
);
460 /* Attempt relative target open */
461 IoStatusBlock
.Status
= 0xFFFFFFFF;
462 IoStatusBlock
.Information
= 0xFFFFFFFF;
463 InitializeObjectAttributes(&ObjectAttributes
,
465 OBJ_CASE_INSENSITIVE
,
467 Status
= ZwOpenFile(&SystemRootHandle
,
468 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
471 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
472 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
473 ok_eq_hex(Status
, STATUS_SUCCESS
);
474 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
475 if (Status
== STATUS_SUCCESS
)
477 IoStatusBlock
.Status
= 0xFFFFFFFF;
478 IoStatusBlock
.Information
= 0xFFFFFFFF;
479 InitializeObjectAttributes(&ObjectAttributes
,
481 OBJ_CASE_INSENSITIVE
,
484 Status
= IoCreateFile(&ParentHandle
,
485 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
490 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
492 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
497 IO_OPEN_TARGET_DIRECTORY
);
498 ok_eq_hex(Status
, STATUS_ACCESS_VIOLATION
);
499 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
500 if (Status
== STATUS_SUCCESS
)
502 ObCloseHandle(ParentHandle
, KernelMode
);
504 ObCloseHandle(SystemRootHandle
, KernelMode
);
508 START_TEST(IoCreateFile
)
511 OBJECT_ATTRIBUTES ObjectAttributes
;
513 PVOID ThreadObject
= NULL
;
515 /* Justify the next comment/statement */
518 /* We've to be in kernel mode, so spawn a thread */
519 InitializeObjectAttributes(&ObjectAttributes
,
524 Status
= PsCreateSystemThread(&ThreadHandle
,
531 ok_eq_hex(Status
, STATUS_SUCCESS
);
532 if (Status
== STATUS_SUCCESS
)
534 /* Then, just wait on our thread to finish */
535 Status
= ObReferenceObjectByHandle(ThreadHandle
,
541 ObCloseHandle(ThreadHandle
, KernelMode
);
543 Status
= KeWaitForSingleObject(ThreadObject
,
548 ok_eq_hex(Status
, STATUS_SUCCESS
);
549 ObDereferenceObject(ThreadObject
);