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
);
425 HANDLE ReparseHandle
;
427 IO_STATUS_BLOCK IoStatusBlock
;
428 OBJECT_ATTRIBUTES ObjectAttributes
;
429 PREPARSE_DATA_BUFFER Reparse
;
430 FILE_DISPOSITION_INFORMATION ToDelete
;
431 PFILE_OBJECT FileObject
;
432 UNICODE_STRING SysDir
, Foobar
, Regedit
;
435 /* Get Windows/ReactOS directory */
436 InitializeObjectAttributes(&ObjectAttributes
,
438 OBJ_CASE_INSENSITIVE
,
441 Status
= ZwOpenFile(&ReparseHandle
,
445 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
446 FILE_DIRECTORY_FILE
);
447 if (skip(NT_SUCCESS(Status
), "Opening \\SystemRoot failed: %lx\n", Status
))
452 Status
= ObReferenceObjectByHandle(ReparseHandle
,
456 (PVOID
*)&FileObject
,
458 if (skip(NT_SUCCESS(Status
), "Querying name failed: %lx\n", Status
))
460 ZwClose(ReparseHandle
);
464 SysDir
.Buffer
= ExAllocatePool(NonPagedPool
, FileObject
->FileName
.Length
+ sizeof(L
"\\??\\C:"));
465 if (skip(SysDir
.Buffer
!= NULL
, "Allocating memory failed\n"))
467 ObDereferenceObject(FileObject
);
468 ZwClose(ReparseHandle
);
472 SysDir
.Length
= sizeof(L
"\\??\\C:") - sizeof(UNICODE_NULL
);
473 SysDir
.MaximumLength
= FileObject
->FileName
.Length
+ sizeof(L
"\\??\\C:");
474 RtlCopyMemory(SysDir
.Buffer
, L
"\\??\\C:", sizeof(L
"\\??\\C:") - sizeof(UNICODE_NULL
));
475 RtlAppendUnicodeStringToString(&SysDir
, &FileObject
->FileName
);
477 Foobar
.Buffer
= ExAllocatePool(NonPagedPool
, FileObject
->FileName
.Length
+ sizeof(L
"\\foobar.exe"));
478 if (skip(Foobar
.Buffer
!= NULL
, "Allocating memory failed\n"))
480 ExFreePool(SysDir
.Buffer
);
481 ObDereferenceObject(FileObject
);
482 ZwClose(ReparseHandle
);
487 Foobar
.MaximumLength
= FileObject
->FileName
.Length
+ sizeof(L
"\\foobar.exe");
488 RtlCopyUnicodeString(&Foobar
, &FileObject
->FileName
);
489 RtlCopyMemory(&Foobar
.Buffer
[Foobar
.Length
/ sizeof(WCHAR
)], L
"\\foobar.exe", sizeof(L
"\\foobar.exe") - sizeof(UNICODE_NULL
));
490 Foobar
.Length
+= (sizeof(L
"\\foobar.exe") - sizeof(UNICODE_NULL
));
492 Regedit
.Buffer
= ExAllocatePool(NonPagedPool
, FileObject
->FileName
.Length
+ sizeof(L
"\\regedit.exe"));
493 if (skip(Regedit
.Buffer
!= NULL
, "Allocating memory failed\n"))
495 ExFreePool(Foobar
.Buffer
);
496 ExFreePool(SysDir
.Buffer
);
497 ObDereferenceObject(FileObject
);
498 ZwClose(ReparseHandle
);
503 Regedit
.MaximumLength
= FileObject
->FileName
.Length
+ sizeof(L
"\\regedit.exe");
504 RtlCopyUnicodeString(&Regedit
, &FileObject
->FileName
);
505 RtlCopyMemory(&Regedit
.Buffer
[Regedit
.Length
/ sizeof(WCHAR
)], L
"\\regedit.exe", sizeof(L
"\\regedit.exe") - sizeof(UNICODE_NULL
));
506 Regedit
.Length
+= (sizeof(L
"\\regedit.exe") - sizeof(UNICODE_NULL
));
508 ObDereferenceObject(FileObject
);
509 ZwClose(ReparseHandle
);
511 ToDelete
.DeleteFile
= TRUE
;
512 Size
= FIELD_OFFSET(REPARSE_DATA_BUFFER
, SymbolicLinkReparseBuffer
.PathBuffer
) + SysDir
.Length
* 2 + sizeof(L
"\\regedit.exe") * 2 - sizeof(L
"\\??\\") - sizeof(UNICODE_NULL
);
514 InitializeObjectAttributes(&ObjectAttributes
,
516 OBJ_CASE_INSENSITIVE
,
519 Status
= ZwCreateFile(&ReparseHandle
,
520 GENERIC_READ
| GENERIC_WRITE
| DELETE
,
524 FILE_ATTRIBUTE_NORMAL
,
525 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
527 FILE_NON_DIRECTORY_FILE
,
530 ok_eq_hex(Status
, STATUS_SUCCESS
);
531 if (skip(NT_SUCCESS(Status
), "Creating file failed: %lx\n", Status
))
533 ExFreePool(Regedit
.Buffer
);
534 ExFreePool(Foobar
.Buffer
);
535 ExFreePool(SysDir
.Buffer
);
539 Reparse
= ExAllocatePool(NonPagedPool
, Size
);
540 RtlZeroMemory(Reparse
, Size
);
541 Reparse
->ReparseTag
= IO_REPARSE_TAG_SYMLINK
;
542 Reparse
->ReparseDataLength
= 12 + SysDir
.Length
* 2 + sizeof(L
"\\regedit.exe") * 2 - sizeof(L
"\\??\\") - sizeof(UNICODE_NULL
);
543 Reparse
->SymbolicLinkReparseBuffer
.SubstituteNameLength
= SysDir
.Length
+ sizeof(L
"\\regedit.exe") - sizeof(UNICODE_NULL
);
544 Reparse
->SymbolicLinkReparseBuffer
.PrintNameLength
= SysDir
.Length
+ sizeof(L
"\\regedit.exe") - sizeof(L
"\\??\\");
545 Reparse
->SymbolicLinkReparseBuffer
.SubstituteNameOffset
= Reparse
->SymbolicLinkReparseBuffer
.PrintNameLength
;
546 RtlCopyMemory(Reparse
->SymbolicLinkReparseBuffer
.PathBuffer
,
547 (WCHAR
*)((ULONG_PTR
)SysDir
.Buffer
+ sizeof(L
"\\??\\") - sizeof(UNICODE_NULL
)),
548 SysDir
.Length
- sizeof(L
"\\??\\") + sizeof(UNICODE_NULL
));
549 RtlCopyMemory((WCHAR
*)((ULONG_PTR
)Reparse
->SymbolicLinkReparseBuffer
.PathBuffer
+ SysDir
.Length
- sizeof(L
"\\??\\") + sizeof(UNICODE_NULL
)),
550 L
"\\regedit.exe", sizeof(L
"\\regedit.exe") - sizeof(UNICODE_NULL
));
551 RtlCopyMemory((WCHAR
*)((ULONG_PTR
)Reparse
->SymbolicLinkReparseBuffer
.PathBuffer
+ Reparse
->SymbolicLinkReparseBuffer
.SubstituteNameOffset
),
552 SysDir
.Buffer
, SysDir
.Length
);
553 RtlCopyMemory((WCHAR
*)((ULONG_PTR
)Reparse
->SymbolicLinkReparseBuffer
.PathBuffer
+ Reparse
->SymbolicLinkReparseBuffer
.SubstituteNameOffset
+ SysDir
.Length
),
554 L
"\\regedit.exe", sizeof(L
"\\regedit.exe") - sizeof(UNICODE_NULL
));
556 Status
= ZwFsControlFile(ReparseHandle
,
561 FSCTL_SET_REPARSE_POINT
,
566 ok_eq_hex(Status
, STATUS_SUCCESS
);
567 if (!NT_SUCCESS(Status
))
569 ZwClose(ReparseHandle
);
571 Status
= ZwCreateFile(&ReparseHandle
,
572 FILE_WRITE_ATTRIBUTES
| DELETE
| SYNCHRONIZE
,
576 FILE_ATTRIBUTE_NORMAL
,
579 FILE_NON_DIRECTORY_FILE
| FILE_OPEN_REPARSE_POINT
| FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
,
582 if (skip(NT_SUCCESS(Status
), "Creating symlink failed: %lx\n", Status
))
584 Status
= ZwOpenFile(&ReparseHandle
,
589 FILE_NON_DIRECTORY_FILE
| FILE_DELETE_ON_CLOSE
);
590 ok_eq_hex(Status
, STATUS_SUCCESS
);
591 ZwClose(ReparseHandle
);
592 ExFreePool(Regedit
.Buffer
);
593 ExFreePool(Foobar
.Buffer
);
594 ExFreePool(SysDir
.Buffer
);
599 Status
= ZwFsControlFile(ReparseHandle
,
604 FSCTL_SET_REPARSE_POINT
,
611 if (skip(NT_SUCCESS(Status
), "Creating symlink failed: %lx\n", Status
))
613 ZwSetInformationFile(ReparseHandle
,
617 FileDispositionInformation
);
618 ZwClose(ReparseHandle
);
619 ExFreePool(Regedit
.Buffer
);
620 ExFreePool(Foobar
.Buffer
);
621 ExFreePool(SysDir
.Buffer
);
626 ZwClose(ReparseHandle
);
628 Status
= ZwCreateFile(&ReparseHandle
,
633 FILE_ATTRIBUTE_NORMAL
,
634 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
636 FILE_NON_DIRECTORY_FILE
,
639 ok(Status
== STATUS_SUCCESS
|| /* Windows Vista+ */
640 Status
== STATUS_IO_REPARSE_TAG_NOT_HANDLED
, /* Windows 2003 (SP1, SP2) */
641 "ZwCreateFile returned unexpected status: %lx\n", Status
);
642 if (NT_SUCCESS(Status
))
644 Status
= ObReferenceObjectByHandle(ReparseHandle
,
648 (PVOID
*)&FileObject
,
650 ok_eq_hex(Status
, STATUS_SUCCESS
);
651 if (NT_SUCCESS(Status
))
653 ok(RtlCompareUnicodeString(&Regedit
, &FileObject
->FileName
, TRUE
) == 0,
654 "Expected: %wZ. Opened: %wZ\n", &Regedit
, &FileObject
->FileName
);
655 ObDereferenceObject(FileObject
);
658 ZwClose(ReparseHandle
);
661 ExFreePool(Regedit
.Buffer
);
663 Status
= IoCreateFile(&ReparseHandle
,
668 FILE_ATTRIBUTE_NORMAL
,
669 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
671 FILE_NON_DIRECTORY_FILE
,
676 IO_NO_PARAMETER_CHECKING
| IO_STOP_ON_SYMLINK
);
677 ok(Status
== STATUS_STOPPED_ON_SYMLINK
|| /* Windows Vista+ */
678 Status
== STATUS_IO_REPARSE_TAG_NOT_HANDLED
, /* Windows 2003 (SP1, SP2) */
679 "ZwCreateFile returned unexpected status: %lx\n", Status
);
680 if (NT_SUCCESS(Status
))
682 ZwClose(ReparseHandle
);
685 Status
= ZwCreateFile(&ReparseHandle
,
686 GENERIC_READ
| GENERIC_WRITE
| DELETE
,
690 FILE_ATTRIBUTE_NORMAL
,
691 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
693 FILE_NON_DIRECTORY_FILE
| FILE_OPEN_REPARSE_POINT
| FILE_OPEN_FOR_BACKUP_INTENT
,
696 if (skip(NT_SUCCESS(Status
), "Creating opening reparse point: %lx\n", Status
))
698 Status
= ZwOpenFile(&ReparseHandle
,
703 FILE_NON_DIRECTORY_FILE
| FILE_DELETE_ON_CLOSE
);
704 ok_eq_hex(Status
, STATUS_SUCCESS
);
705 ZwClose(ReparseHandle
);
706 ExFreePool(Foobar
.Buffer
);
707 ExFreePool(SysDir
.Buffer
);
712 Status
= ObReferenceObjectByHandle(ReparseHandle
,
716 (PVOID
*)&FileObject
,
718 ok_eq_hex(Status
, STATUS_SUCCESS
);
719 if (NT_SUCCESS(Status
))
721 ok(RtlCompareUnicodeString(&Foobar
, &FileObject
->FileName
, TRUE
) == 0,
722 "Expected: %wZ. Opened: %wZ\n", &Foobar
, &FileObject
->FileName
);
723 ObDereferenceObject(FileObject
);
726 ExFreePool(Foobar
.Buffer
);
728 RtlZeroMemory(Reparse
, Size
);
729 Status
= ZwFsControlFile(ReparseHandle
,
734 FSCTL_GET_REPARSE_POINT
,
739 ok_eq_hex(Status
, STATUS_SUCCESS
);
740 ok_eq_hex(IoStatusBlock
.Information
, Size
);
741 if (NT_SUCCESS(Status
))
744 UNICODE_STRING ReparsePath
, FullPath
;
746 ok_eq_hex(Reparse
->ReparseTag
, IO_REPARSE_TAG_SYMLINK
);
747 ok_eq_hex(Reparse
->ReparseDataLength
, 12 + SysDir
.Length
* 2 + sizeof(L
"\\regedit.exe") * 2 - sizeof(L
"\\??\\") - sizeof(UNICODE_NULL
));
748 ok_eq_hex(Reparse
->SymbolicLinkReparseBuffer
.Flags
, 0);
751 FullPath
.MaximumLength
= SysDir
.Length
+ sizeof(L
"\\regedit.exe") - sizeof(UNICODE_NULL
);
752 Buffer
= FullPath
.Buffer
= ExAllocatePool(NonPagedPool
, FullPath
.MaximumLength
);
753 if (!skip(Buffer
!= NULL
, "Memory allocation failed!\n"))
755 RtlCopyUnicodeString(&FullPath
, &SysDir
);
756 RtlCopyMemory(&FullPath
.Buffer
[FullPath
.Length
/ sizeof(WCHAR
)], L
"\\regedit.exe", sizeof(L
"\\regedit.exe") - sizeof(UNICODE_NULL
));
757 FullPath
.Length
+= (sizeof(L
"\\regedit.exe") - sizeof(UNICODE_NULL
));
758 ReparsePath
.Buffer
= (PWSTR
)((ULONG_PTR
)Reparse
->SymbolicLinkReparseBuffer
.PathBuffer
+ Reparse
->SymbolicLinkReparseBuffer
.SubstituteNameOffset
);
759 ReparsePath
.Length
= ReparsePath
.MaximumLength
= Reparse
->SymbolicLinkReparseBuffer
.SubstituteNameLength
;
760 ok(RtlCompareUnicodeString(&ReparsePath
, &FullPath
, TRUE
) == 0, "Expected: %wZ. Got: %wZ\n", &ReparsePath
, &FullPath
);
762 FullPath
.Length
-= (sizeof(L
"\\??\\") - sizeof(UNICODE_NULL
));
763 FullPath
.MaximumLength
-= (sizeof(L
"\\??\\") - sizeof(UNICODE_NULL
));
764 FullPath
.Buffer
= (PWSTR
)((ULONG_PTR
)Buffer
+ sizeof(L
"\\??\\") - sizeof(UNICODE_NULL
));
765 ReparsePath
.Buffer
= (PWSTR
)((ULONG_PTR
)Reparse
->SymbolicLinkReparseBuffer
.PathBuffer
+ Reparse
->SymbolicLinkReparseBuffer
.PrintNameOffset
);
766 ReparsePath
.Length
= ReparsePath
.MaximumLength
= Reparse
->SymbolicLinkReparseBuffer
.PrintNameLength
;
767 ok(RtlCompareUnicodeString(&ReparsePath
, &FullPath
, TRUE
) == 0, "Expected: %wZ. Got: %wZ\n", &ReparsePath
, &FullPath
);
773 ExFreePool(SysDir
.Buffer
);
776 ZwSetInformationFile(ReparseHandle
,
780 FileDispositionInformation
);
781 ZwClose(ReparseHandle
);
790 IO_STATUS_BLOCK IoStatusBlock
;
791 OBJECT_ATTRIBUTES ObjectAttributes
;
792 HANDLE ParentHandle
, SystemRootHandle
;
794 ok(ExGetPreviousMode() == UserMode
, "KernelMode returned!\n");
796 /* Attempt direct target open */
797 IoStatusBlock
.Status
= 0xFFFFFFFF;
798 IoStatusBlock
.Information
= 0xFFFFFFFF;
799 InitializeObjectAttributes(&ObjectAttributes
,
801 OBJ_CASE_INSENSITIVE
,
803 Status
= IoCreateFile(&ParentHandle
,
804 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
809 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
811 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
816 IO_OPEN_TARGET_DIRECTORY
);
817 ok_eq_hex(Status
, STATUS_ACCESS_VIOLATION
);
818 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
819 if (Status
== STATUS_SUCCESS
)
821 ObCloseHandle(ParentHandle
, UserMode
);
824 /* Attempt relative target open */
825 IoStatusBlock
.Status
= 0xFFFFFFFF;
826 IoStatusBlock
.Information
= 0xFFFFFFFF;
827 InitializeObjectAttributes(&ObjectAttributes
,
829 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
831 Status
= ZwOpenFile(&SystemRootHandle
,
832 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
835 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
836 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
837 ok_eq_hex(Status
, STATUS_SUCCESS
);
838 ok_eq_hex(IoStatusBlock
.Status
, STATUS_SUCCESS
);
839 if (Status
== STATUS_SUCCESS
)
841 IoStatusBlock
.Status
= 0xFFFFFFFF;
842 IoStatusBlock
.Information
= 0xFFFFFFFF;
843 InitializeObjectAttributes(&ObjectAttributes
,
845 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
848 Status
= IoCreateFile(&ParentHandle
,
849 GENERIC_WRITE
| GENERIC_READ
| SYNCHRONIZE
,
854 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
856 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
861 IO_OPEN_TARGET_DIRECTORY
);
862 ok_eq_hex(Status
, STATUS_ACCESS_VIOLATION
);
863 ok_eq_hex(IoStatusBlock
.Status
, 0xFFFFFFFF);
864 if (Status
== STATUS_SUCCESS
)
866 ObCloseHandle(ParentHandle
, KernelMode
);
868 ObCloseHandle(SystemRootHandle
, KernelMode
);
872 START_TEST(IoCreateFile
)
874 PKTHREAD ThreadHandle
;
878 /* Justify the next comment/statement */
881 /* We've to be in kernel mode, so spawn a thread */
882 ThreadHandle
= KmtStartThread(KernelModeTest
, NULL
);
883 KmtFinishThread(ThreadHandle
, NULL
);