2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite File System test
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
10 /* FIXME: Test this stuff on non-FAT volumes */
15 _In_ HANDLE FileHandle
,
17 _Inout_ PSIZE_T Length
,
18 _In_ FILE_INFORMATION_CLASS FileInformationClass
)
21 IO_STATUS_BLOCK IoStatus
;
27 Buffer
= KmtAllocateGuarded(*Length
);
28 if (skip(Buffer
!= NULL
, "Failed to allocate %Iu bytes\n", *Length
))
29 return STATUS_INSUFFICIENT_RESOURCES
;
35 RtlFillMemory(Buffer
, *Length
, 0xDD);
36 RtlFillMemory(&IoStatus
, sizeof(IoStatus
), 0x55);
39 Status
= ZwQueryInformationFile(FileHandle
,
43 FileInformationClass
);
45 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
47 Status
= _SEH2_GetExceptionCode();
48 ok(0, "Exception %lx querying class %d with length %Iu\n",
49 Status
, FileInformationClass
, *Length
);
52 if (Status
== STATUS_PENDING
)
54 Status
= ZwWaitForSingleObject(FileHandle
, FALSE
, NULL
);
55 ok_eq_hex(Status
, STATUS_SUCCESS
);
56 Status
= IoStatus
.Status
;
58 *Length
= IoStatus
.Information
;
65 TestAllInformation(VOID
)
68 UNICODE_STRING FileName
= RTL_CONSTANT_STRING(L
"\\SystemRoot\\system32\\ntoskrnl.exe");
69 UNICODE_STRING Ntoskrnl
= RTL_CONSTANT_STRING(L
"ntoskrnl.exe");
70 OBJECT_ATTRIBUTES ObjectAttributes
;
72 IO_STATUS_BLOCK IoStatus
;
73 PFILE_ALL_INFORMATION FileAllInfo
;
77 UNICODE_STRING NamePart
;
79 InitializeObjectAttributes(&ObjectAttributes
,
81 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
84 Status
= ZwOpenFile(&FileHandle
,
85 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
88 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
89 FILE_NON_DIRECTORY_FILE
);
90 if (Status
== STATUS_PENDING
)
92 Status
= ZwWaitForSingleObject(FileHandle
, FALSE
, NULL
);
93 ok_eq_hex(Status
, STATUS_SUCCESS
);
94 Status
= IoStatus
.Status
;
96 ok_eq_hex(Status
, STATUS_SUCCESS
);
97 if (skip(NT_SUCCESS(Status
), "No file handle, %lx\n", Status
))
100 /* NtQueryInformationFile doesn't do length checks for kernel callers in a free build */
101 if (KmtIsCheckedBuild
)
105 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
106 ok_eq_hex(Status
, STATUS_INFO_LENGTH_MISMATCH
);
107 ok_eq_size(Length
, (ULONG_PTR
)0x5555555555555555);
109 KmtFreeGuarded(FileAllInfo
);
111 /* One less than the minimum */
112 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) - 1;
113 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
114 ok_eq_hex(Status
, STATUS_INFO_LENGTH_MISMATCH
);
115 ok_eq_size(Length
, (ULONG_PTR
)0x5555555555555555);
117 KmtFreeGuarded(FileAllInfo
);
120 /* The minimum allowed */
121 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
);
122 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
123 ok_eq_hex(Status
, STATUS_BUFFER_OVERFLOW
);
124 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
));
126 KmtFreeGuarded(FileAllInfo
);
128 /* Plenty of space -- determine NameLength and copy the name */
129 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + MAX_PATH
* sizeof(WCHAR
);
130 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
131 ok_eq_hex(Status
, STATUS_SUCCESS
);
132 if (!skip(NT_SUCCESS(Status
) && FileAllInfo
!= NULL
, "No info\n"))
134 NameLength
= FileAllInfo
->NameInformation
.FileNameLength
;
135 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
);
136 Name
= ExAllocatePoolWithTag(PagedPool
, NameLength
+ sizeof(UNICODE_NULL
), 'sFmK');
137 if (!skip(Name
!= NULL
, "Could not allocate %lu bytes\n", NameLength
+ (ULONG
)sizeof(UNICODE_NULL
)))
140 FileAllInfo
->NameInformation
.FileName
,
142 Name
[NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
143 ok(Name
[0] == L
'\\', "Name is %ls, expected first char to be \\\n", Name
);
144 ok(NameLength
>= Ntoskrnl
.Length
+ sizeof(WCHAR
), "NameLength %lu too short\n", NameLength
);
145 if (NameLength
>= Ntoskrnl
.Length
)
147 NamePart
.Buffer
= Name
+ (NameLength
- Ntoskrnl
.Length
) / sizeof(WCHAR
);
148 NamePart
.Length
= Ntoskrnl
.Length
;
149 NamePart
.MaximumLength
= NamePart
.Length
;
150 ok(RtlEqualUnicodeString(&NamePart
, &Ntoskrnl
, TRUE
),
151 "Name ends in '%wZ', expected %wZ\n", &NamePart
, &Ntoskrnl
);
154 ok(FileAllInfo
->NameInformation
.FileName
[NameLength
/ sizeof(WCHAR
)] == 0xdddd,
155 "Char past FileName is %x\n",
156 FileAllInfo
->NameInformation
.FileName
[NameLength
/ sizeof(WCHAR
)]);
159 KmtFreeGuarded(FileAllInfo
);
161 /* One char less than needed */
162 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
- sizeof(WCHAR
);
163 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
164 ok_eq_hex(Status
, STATUS_BUFFER_OVERFLOW
);
165 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
- sizeof(WCHAR
));
167 KmtFreeGuarded(FileAllInfo
);
169 /* One byte less than needed */
170 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
- 1;
171 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
172 ok_eq_hex(Status
, STATUS_BUFFER_OVERFLOW
);
173 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
- 1);
175 KmtFreeGuarded(FileAllInfo
);
177 /* Exactly the required size */
178 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
;
179 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
180 ok_eq_hex(Status
, STATUS_SUCCESS
);
181 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
);
183 KmtFreeGuarded(FileAllInfo
);
185 /* One byte more than needed */
186 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
+ 1;
187 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
188 ok_eq_hex(Status
, STATUS_SUCCESS
);
189 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
);
191 KmtFreeGuarded(FileAllInfo
);
193 /* One char more than needed */
194 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
+ sizeof(WCHAR
);
195 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
196 ok_eq_hex(Status
, STATUS_SUCCESS
);
197 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
);
199 KmtFreeGuarded(FileAllInfo
);
201 ExFreePoolWithTag(Name
, 'sFmK');
203 Status
= ObCloseHandle(FileHandle
, KernelMode
);
204 ok_eq_hex(Status
, STATUS_SUCCESS
);
210 _Out_writes_bytes_(BufferSize
) PWCHAR Buffer
,
211 _In_ ULONG BufferSize
,
212 _In_ PCWSTR Template
,
213 _In_ PCWSTR SystemDriveName
,
214 _In_ PCWSTR SystemRootName
)
216 UNICODE_STRING SystemDriveTemplate
= RTL_CONSTANT_STRING(L
"C:");
217 UNICODE_STRING SystemRootTemplate
= RTL_CONSTANT_STRING(L
"ReactOS");
218 ULONG SystemDriveLength
;
219 ULONG SystemRootLength
;
220 PWCHAR Dest
= Buffer
;
221 UNICODE_STRING String
;
223 SystemDriveLength
= wcslen(SystemDriveName
) * sizeof(WCHAR
);
224 SystemRootLength
= wcslen(SystemRootName
) * sizeof(WCHAR
);
226 RtlInitUnicodeString(&String
, Template
);
227 ASSERT(String
.Length
% sizeof(WCHAR
) == 0);
228 while (String
.Length
)
230 if (RtlPrefixUnicodeString(&SystemDriveTemplate
, &String
, TRUE
))
232 ASSERT((Dest
- Buffer
) * sizeof(WCHAR
) + SystemDriveLength
< BufferSize
);
236 Dest
+= SystemDriveLength
/ sizeof(WCHAR
);
238 String
.Buffer
+= SystemDriveTemplate
.Length
/ sizeof(WCHAR
);
239 String
.Length
-= SystemDriveTemplate
.Length
;
240 String
.MaximumLength
-= SystemDriveTemplate
.Length
;
244 if (RtlPrefixUnicodeString(&SystemRootTemplate
, &String
, TRUE
))
246 ASSERT((Dest
- Buffer
) * sizeof(WCHAR
) + SystemRootLength
< BufferSize
);
250 Dest
+= SystemRootLength
/ sizeof(WCHAR
);
252 String
.Buffer
+= SystemRootTemplate
.Length
/ sizeof(WCHAR
);
253 String
.Length
-= SystemRootTemplate
.Length
;
254 String
.MaximumLength
-= SystemRootTemplate
.Length
;
258 ASSERT(Dest
- Buffer
< BufferSize
/ sizeof(WCHAR
));
259 *Dest
++ = String
.Buffer
[0];
262 String
.Length
-= sizeof(WCHAR
);
263 String
.MaximumLength
-= sizeof(WCHAR
);
265 ASSERT(Dest
- Buffer
< BufferSize
/ sizeof(WCHAR
));
266 *Dest
= UNICODE_NULL
;
271 TestRelativeNames(VOID
)
276 PCWSTR ParentPathTemplate
;
277 PCWSTR RelativePathTemplate
;
282 { NULL
, L
"C:\\", TRUE
, STATUS_SUCCESS
},
283 { NULL
, L
"C:\\\\", TRUE
, STATUS_SUCCESS
},
284 { NULL
, L
"C:\\\\\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
285 { NULL
, L
"C:\\ReactOS", TRUE
, STATUS_SUCCESS
},
286 { NULL
, L
"C:\\ReactOS\\", TRUE
, STATUS_SUCCESS
},
287 { NULL
, L
"C:\\ReactOS\\\\", TRUE
, STATUS_SUCCESS
},
288 { NULL
, L
"C:\\ReactOS\\\\\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
289 { NULL
, L
"C:\\\\ReactOS", TRUE
, STATUS_SUCCESS
},
290 { NULL
, L
"C:\\\\ReactOS\\", TRUE
, STATUS_SUCCESS
},
291 { NULL
, L
"C:\\ReactOS\\explorer.exe", FALSE
, STATUS_SUCCESS
},
292 { NULL
, L
"C:\\ReactOS\\\\explorer.exe", FALSE
, STATUS_OBJECT_NAME_INVALID
},
293 { NULL
, L
"C:\\ReactOS\\explorer.exe\\", FALSE
, STATUS_OBJECT_NAME_INVALID
},
294 { NULL
, L
"C:\\ReactOS\\explorer.exe\\\\", FALSE
, STATUS_OBJECT_NAME_INVALID
},
295 /* This will never return STATUS_NOT_A_DIRECTORY. IsDirectory=TRUE is a little hacky but achieves that without special handling */
296 { NULL
, L
"C:\\ReactOS\\explorer.exe\\\\\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
297 { L
"C:\\", L
"", TRUE
, STATUS_SUCCESS
},
298 { L
"C:\\", L
"\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
299 { L
"C:\\", L
"ReactOS", TRUE
, STATUS_SUCCESS
},
300 { L
"C:\\", L
"\\ReactOS", TRUE
, STATUS_OBJECT_NAME_INVALID
},
301 { L
"C:\\", L
"ReactOS\\", TRUE
, STATUS_SUCCESS
},
302 { L
"C:\\", L
"\\ReactOS\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
303 { L
"C:\\ReactOS", L
"", TRUE
, STATUS_SUCCESS
},
304 { L
"C:\\ReactOS", L
"explorer.exe", FALSE
, STATUS_SUCCESS
},
305 { L
"C:\\ReactOS\\explorer.exe", L
"", FALSE
, STATUS_SUCCESS
},
306 /* Let's try some nonexistent things */
307 { NULL
, L
"C:\\ReactOS\\IDoNotExist", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
308 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
309 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file?", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
310 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file\\\\",TRUE
,STATUS_OBJECT_PATH_NOT_FOUND
},
311 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file\\\\\\",TRUE
,STATUS_OBJECT_PATH_NOT_FOUND
},
312 { NULL
, L
"C:\\ReactOS\\AmIInvalid?", FALSE
, STATUS_OBJECT_NAME_INVALID
},
313 { NULL
, L
"C:\\ReactOS\\.", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
314 { NULL
, L
"C:\\ReactOS\\..", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
315 { NULL
, L
"C:\\ReactOS\\...", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
316 { L
"C:\\", L
".", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
317 { L
"C:\\", L
"..", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
318 { L
"C:\\", L
"...", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
319 { L
"C:\\ReactOS", L
".", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
320 { L
"C:\\ReactOS", L
"..", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
321 { L
"C:\\ReactOS", L
"...", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
324 OBJECT_ATTRIBUTES ObjectAttributes
;
325 IO_STATUS_BLOCK IoStatus
;
326 UNICODE_STRING ParentPath
;
327 UNICODE_STRING RelativePath
;
330 UNICODE_STRING SystemRoot
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
331 HANDLE SymbolicLinkHandle
= NULL
;
332 WCHAR LinkNameBuffer
[128];
333 UNICODE_STRING SymbolicLinkName
;
334 PWSTR SystemDriveName
;
335 PWSTR SystemRootName
;
336 PWCHAR Buffer
= NULL
;
337 BOOLEAN TrailingBackslash
;
339 /* Query \SystemRoot */
340 InitializeObjectAttributes(&ObjectAttributes
,
342 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
345 Status
= ZwOpenSymbolicLinkObject(&SymbolicLinkHandle
,
348 if (skip(NT_SUCCESS(Status
), "Failed to open SystemRoot, %lx\n", Status
))
351 RtlInitEmptyUnicodeString(&SymbolicLinkName
,
353 sizeof(LinkNameBuffer
));
354 Status
= ZwQuerySymbolicLinkObject(SymbolicLinkHandle
,
357 ObCloseHandle(SymbolicLinkHandle
, KernelMode
);
358 if (skip(NT_SUCCESS(Status
), "Failed to query SystemRoot, %lx\n", Status
))
361 /* Split SymbolicLinkName into drive and path */
362 SystemDriveName
= SymbolicLinkName
.Buffer
;
363 SystemRootName
= SymbolicLinkName
.Buffer
+ SymbolicLinkName
.Length
/ sizeof(WCHAR
);
364 *SystemRootName
-- = UNICODE_NULL
;
365 while (*SystemRootName
!= L
'\\')
367 ASSERT(SystemRootName
> SymbolicLinkName
.Buffer
);
370 *SystemRootName
++ = UNICODE_NULL
;
371 trace("System Drive: '%ls'\n", SystemDriveName
);
372 trace("System Root: '%ls'\n", SystemRootName
);
374 /* Allocate path buffer */
375 Buffer
= ExAllocatePoolWithTag(PagedPool
, MAXUSHORT
, 'sFmK');
376 if (skip(Buffer
!= NULL
, "No buffer\n"))
379 /* Finally run some tests! */
380 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
382 /* Open parent directory first */
384 if (Tests
[i
].ParentPathTemplate
)
388 Tests
[i
].ParentPathTemplate
,
391 RtlInitUnicodeString(&ParentPath
, Buffer
);
392 InitializeObjectAttributes(&ObjectAttributes
,
394 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
397 Status
= ZwOpenFile(&ParentHandle
,
401 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
403 ok(Status
== STATUS_SUCCESS
,
404 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i
, Status
);
405 if (skip(NT_SUCCESS(Status
), "No parent handle %lu\n", i
))
409 /* Now open the relative file: */
412 Tests
[i
].RelativePathTemplate
,
415 RtlInitUnicodeString(&RelativePath
, Buffer
);
416 InitializeObjectAttributes(&ObjectAttributes
,
418 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
421 TrailingBackslash
= FALSE
;
422 if (wcslen(Buffer
) && Buffer
[wcslen(Buffer
) - 1] == L
'\\')
423 TrailingBackslash
= TRUE
;
426 Status
= ZwOpenFile(&FileHandle
,
430 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
432 ok(Status
== Tests
[i
].Status
,
433 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
434 if (NT_SUCCESS(Status
))
435 ObCloseHandle(FileHandle
, KernelMode
);
437 /* (2) Directory File */
438 Status
= ZwOpenFile(&FileHandle
,
442 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
443 FILE_DIRECTORY_FILE
);
444 if (Tests
[i
].IsDirectory
|| (!TrailingBackslash
&& !NT_SUCCESS(Tests
[i
].Status
)))
445 ok(Status
== Tests
[i
].Status
,
446 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
448 ok(Status
== STATUS_NOT_A_DIRECTORY
,
449 "[%lu] Status = %lx, expected STATUS_NOT_A_DIRECTORY\n", i
, Status
);
450 if (NT_SUCCESS(Status
))
451 ObCloseHandle(FileHandle
, KernelMode
);
453 /* (3) Non-Directory File */
454 Status
= ZwOpenFile(&FileHandle
,
458 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
459 FILE_NON_DIRECTORY_FILE
);
460 if (Tests
[i
].IsDirectory
&& NT_SUCCESS(Tests
[i
].Status
))
461 ok(Status
== STATUS_FILE_IS_A_DIRECTORY
,
462 "[%lu] Status = %lx, expected STATUS_FILE_IS_A_DIRECTORY\n", i
, Status
);
464 ok(Status
== Tests
[i
].Status
,
465 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
466 if (NT_SUCCESS(Status
))
467 ObCloseHandle(FileHandle
, KernelMode
);
470 ObCloseHandle(ParentHandle
, KernelMode
);
473 ExFreePoolWithTag(Buffer
, 'sFmK');
478 TestSharedCacheMap(VOID
)
487 { 0, L
"\\SystemRoot\\system32\\drivers\\etc\\hosts" },
488 { L
"\\SystemRoot", L
"system32\\drivers\\etc\\hosts" },
489 { L
"\\SystemRoot\\system32", L
"drivers\\etc\\hosts" },
490 { L
"\\SystemRoot\\system32\\drivers", L
"etc\\hosts" },
491 { L
"\\SystemRoot\\system32\\drivers\\etc", L
"hosts" },
493 OBJECT_ATTRIBUTES ObjectAttributes
;
494 IO_STATUS_BLOCK IoStatus
;
495 UNICODE_STRING ParentPath
;
496 UNICODE_STRING RelativePath
;
497 HANDLE ParentHandle
[RTL_NUMBER_OF(Tests
)] = { NULL
};
498 HANDLE FileHandle
[RTL_NUMBER_OF(Tests
)] = { NULL
};
499 PFILE_OBJECT FileObject
[RTL_NUMBER_OF(Tests
)] = { NULL
};
500 PFILE_OBJECT SystemRootObject
= NULL
;
503 LARGE_INTEGER FileOffset
;
506 /* We need an event for ZwReadFile */
507 InitializeObjectAttributes(&ObjectAttributes
,
512 Status
= ZwCreateEvent(&EventHandle
,
517 if (skip(NT_SUCCESS(Status
), "No event\n"))
520 /* Open all test files and get their FILE_OBJECT pointers */
521 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
523 if (Tests
[i
].ParentPath
)
525 RtlInitUnicodeString(&ParentPath
, Tests
[i
].ParentPath
);
526 InitializeObjectAttributes(&ObjectAttributes
,
528 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
531 Status
= ZwOpenFile(&ParentHandle
[i
],
535 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
537 ok_eq_hex(Status
, STATUS_SUCCESS
);
538 if (skip(NT_SUCCESS(Status
), "No parent handle %lu\n", i
))
542 RtlInitUnicodeString(&RelativePath
, Tests
[i
].RelativePath
);
543 InitializeObjectAttributes(&ObjectAttributes
,
545 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
548 Status
= ZwOpenFile(&FileHandle
[i
],
552 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
554 ok_eq_hex(Status
, STATUS_SUCCESS
);
555 if (skip(NT_SUCCESS(Status
), "No file handle %lu\n", i
))
558 Status
= ObReferenceObjectByHandle(FileHandle
[i
],
562 (PVOID
*)&FileObject
[i
],
564 ok_eq_hex(Status
, STATUS_SUCCESS
);
565 if (skip(NT_SUCCESS(Status
), "No file object %lu\n", i
))
569 /* Also get a file object for the SystemRoot directory */
570 Status
= ObReferenceObjectByHandle(ParentHandle
[1],
574 (PVOID
*)&SystemRootObject
,
576 ok_eq_hex(Status
, STATUS_SUCCESS
);
577 if (skip(NT_SUCCESS(Status
), "No SystemRoot object\n"))
580 /* Before read, caching is not initialized */
581 ok_eq_pointer(SystemRootObject
->SectionObjectPointer
, NULL
);
582 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
584 ok(FileObject
[i
]->SectionObjectPointer
!= NULL
, "FileObject[%lu]->SectionObjectPointer = NULL\n", i
);
585 ok(FileObject
[i
]->SectionObjectPointer
== FileObject
[0]->SectionObjectPointer
,
586 "FileObject[%lu]->SectionObjectPointer = %p, expected %p\n",
587 i
, FileObject
[i
]->SectionObjectPointer
, FileObject
[0]->SectionObjectPointer
);
589 if (!skip(FileObject
[0]->SectionObjectPointer
!= NULL
, "No section object pointers\n"))
590 ok_eq_pointer(FileObject
[0]->SectionObjectPointer
->SharedCacheMap
, NULL
);
592 /* Perform a read on one handle to initialize caching */
593 FileOffset
.QuadPart
= 0;
594 Status
= ZwReadFile(FileHandle
[0],
603 if (Status
== STATUS_PENDING
)
605 Status
= ZwWaitForSingleObject(EventHandle
, FALSE
, NULL
);
606 ok_eq_hex(Status
, STATUS_SUCCESS
);
607 Status
= IoStatus
.Status
;
609 ok_eq_hex(Status
, STATUS_SUCCESS
);
611 /* Now we see a SharedCacheMap for the file */
612 ok_eq_pointer(SystemRootObject
->SectionObjectPointer
, NULL
);
613 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
615 ok(FileObject
[i
]->SectionObjectPointer
!= NULL
, "FileObject[%lu]->SectionObjectPointer = NULL\n", i
);
616 ok(FileObject
[i
]->SectionObjectPointer
== FileObject
[0]->SectionObjectPointer
,
617 "FileObject[%lu]->SectionObjectPointer = %p, expected %p\n",
618 i
, FileObject
[i
]->SectionObjectPointer
, FileObject
[0]->SectionObjectPointer
);
620 if (!skip(FileObject
[0]->SectionObjectPointer
!= NULL
, "No section object pointers\n"))
621 ok(FileObject
[0]->SectionObjectPointer
->SharedCacheMap
!= NULL
, "SharedCacheMap is NULL\n");
624 if (SystemRootObject
)
625 ObDereferenceObject(SystemRootObject
);
627 ObCloseHandle(EventHandle
, KernelMode
);
628 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
631 ObDereferenceObject(FileObject
[i
]);
633 ObCloseHandle(FileHandle
[i
], KernelMode
);
635 ObCloseHandle(ParentHandle
[i
], KernelMode
);
639 START_TEST(IoFilesystem
)
641 TestAllInformation();
643 TestSharedCacheMap();