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
);
119 /* No space for the name -- fastfat handles this gracefully, ntfs doesn't.
120 * But the Io manager makes it fail on checked builds, so it's
121 * technically illegal
123 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
);
124 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
125 ok_eq_hex(Status
, STATUS_INFO_LENGTH_MISMATCH
);
126 ok_eq_size(Length
, (ULONG_PTR
)0x5555555555555555);
128 KmtFreeGuarded(FileAllInfo
);
131 /* The minimum allowed */
132 Length
= sizeof(FILE_ALL_INFORMATION
);
133 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
134 ok_eq_hex(Status
, STATUS_BUFFER_OVERFLOW
);
135 ok_eq_size(Length
, sizeof(FILE_ALL_INFORMATION
));
137 KmtFreeGuarded(FileAllInfo
);
139 /* Plenty of space -- determine NameLength and copy the name */
140 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + MAX_PATH
* sizeof(WCHAR
);
141 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
142 ok_eq_hex(Status
, STATUS_SUCCESS
);
143 if (!skip(NT_SUCCESS(Status
) && FileAllInfo
!= NULL
, "No info\n"))
145 NameLength
= FileAllInfo
->NameInformation
.FileNameLength
;
146 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
);
147 Name
= ExAllocatePoolWithTag(PagedPool
, NameLength
+ sizeof(UNICODE_NULL
), 'sFmK');
148 if (!skip(Name
!= NULL
, "Could not allocate %lu bytes\n", NameLength
+ (ULONG
)sizeof(UNICODE_NULL
)))
151 FileAllInfo
->NameInformation
.FileName
,
153 Name
[NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
154 ok(Name
[0] == L
'\\', "Name is %ls, expected first char to be \\\n", Name
);
155 ok(NameLength
>= Ntoskrnl
.Length
+ sizeof(WCHAR
), "NameLength %lu too short\n", NameLength
);
156 if (NameLength
>= Ntoskrnl
.Length
)
158 NamePart
.Buffer
= Name
+ (NameLength
- Ntoskrnl
.Length
) / sizeof(WCHAR
);
159 NamePart
.Length
= Ntoskrnl
.Length
;
160 NamePart
.MaximumLength
= NamePart
.Length
;
161 ok(RtlEqualUnicodeString(&NamePart
, &Ntoskrnl
, TRUE
),
162 "Name ends in '%wZ', expected %wZ\n", &NamePart
, &Ntoskrnl
);
165 ok(FileAllInfo
->NameInformation
.FileName
[NameLength
/ sizeof(WCHAR
)] == 0xdddd,
166 "Char past FileName is %x\n",
167 FileAllInfo
->NameInformation
.FileName
[NameLength
/ sizeof(WCHAR
)]);
170 KmtFreeGuarded(FileAllInfo
);
172 /* One char less than needed */
173 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
- sizeof(WCHAR
);
174 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
175 ok_eq_hex(Status
, STATUS_BUFFER_OVERFLOW
);
176 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
- sizeof(WCHAR
));
178 KmtFreeGuarded(FileAllInfo
);
180 /* One byte less than needed */
181 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
- 1;
182 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
183 ok_eq_hex(Status
, STATUS_BUFFER_OVERFLOW
);
184 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
- 1);
186 KmtFreeGuarded(FileAllInfo
);
188 /* Exactly the required size */
189 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
;
190 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
191 ok_eq_hex(Status
, STATUS_SUCCESS
);
192 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
);
194 KmtFreeGuarded(FileAllInfo
);
196 /* One byte more than needed */
197 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
+ 1;
198 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
199 ok_eq_hex(Status
, STATUS_SUCCESS
);
200 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
);
202 KmtFreeGuarded(FileAllInfo
);
204 /* One char more than needed */
205 Length
= FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
+ sizeof(WCHAR
);
206 Status
= QueryFileInfo(FileHandle
, (PVOID
*)&FileAllInfo
, &Length
, FileAllInformation
);
207 ok_eq_hex(Status
, STATUS_SUCCESS
);
208 ok_eq_size(Length
, FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
) + NameLength
);
210 KmtFreeGuarded(FileAllInfo
);
212 ExFreePoolWithTag(Name
, 'sFmK');
214 Status
= ObCloseHandle(FileHandle
, KernelMode
);
215 ok_eq_hex(Status
, STATUS_SUCCESS
);
221 _Out_writes_bytes_(BufferSize
) PWCHAR Buffer
,
222 _In_ ULONG BufferSize
,
223 _In_ PCWSTR Template
,
224 _In_ PCWSTR SystemDriveName
,
225 _In_ PCWSTR SystemRootName
)
227 UNICODE_STRING SystemDriveTemplate
= RTL_CONSTANT_STRING(L
"C:");
228 UNICODE_STRING SystemRootTemplate
= RTL_CONSTANT_STRING(L
"ReactOS");
229 ULONG SystemDriveLength
;
230 ULONG SystemRootLength
;
231 PWCHAR Dest
= Buffer
;
232 UNICODE_STRING String
;
234 SystemDriveLength
= wcslen(SystemDriveName
) * sizeof(WCHAR
);
235 SystemRootLength
= wcslen(SystemRootName
) * sizeof(WCHAR
);
237 RtlInitUnicodeString(&String
, Template
);
238 ASSERT(String
.Length
% sizeof(WCHAR
) == 0);
239 while (String
.Length
)
241 if (RtlPrefixUnicodeString(&SystemDriveTemplate
, &String
, TRUE
))
243 ASSERT((Dest
- Buffer
) * sizeof(WCHAR
) + SystemDriveLength
< BufferSize
);
247 Dest
+= SystemDriveLength
/ sizeof(WCHAR
);
249 String
.Buffer
+= SystemDriveTemplate
.Length
/ sizeof(WCHAR
);
250 String
.Length
-= SystemDriveTemplate
.Length
;
251 String
.MaximumLength
-= SystemDriveTemplate
.Length
;
255 if (RtlPrefixUnicodeString(&SystemRootTemplate
, &String
, TRUE
))
257 ASSERT((Dest
- Buffer
) * sizeof(WCHAR
) + SystemRootLength
< BufferSize
);
261 Dest
+= SystemRootLength
/ sizeof(WCHAR
);
263 String
.Buffer
+= SystemRootTemplate
.Length
/ sizeof(WCHAR
);
264 String
.Length
-= SystemRootTemplate
.Length
;
265 String
.MaximumLength
-= SystemRootTemplate
.Length
;
269 ASSERT(Dest
- Buffer
< BufferSize
/ sizeof(WCHAR
));
270 *Dest
++ = String
.Buffer
[0];
273 String
.Length
-= sizeof(WCHAR
);
274 String
.MaximumLength
-= sizeof(WCHAR
);
276 ASSERT(Dest
- Buffer
< BufferSize
/ sizeof(WCHAR
));
277 *Dest
= UNICODE_NULL
;
282 TestRelativeNames(VOID
)
287 PCWSTR ParentPathTemplate
;
288 PCWSTR RelativePathTemplate
;
294 { NULL
, L
"C:\\", TRUE
, STATUS_SUCCESS
, TRUE
},
295 { NULL
, L
"C:\\\\", TRUE
, STATUS_SUCCESS
, TRUE
},
296 { NULL
, L
"C:\\\\\\", TRUE
, STATUS_OBJECT_NAME_INVALID
, TRUE
},
297 { NULL
, L
"C:\\ReactOS", TRUE
, STATUS_SUCCESS
},
298 { NULL
, L
"C:\\ReactOS\\", TRUE
, STATUS_SUCCESS
},
299 { NULL
, L
"C:\\ReactOS\\\\", TRUE
, STATUS_SUCCESS
},
300 { NULL
, L
"C:\\ReactOS\\\\\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
301 { NULL
, L
"C:\\\\ReactOS", TRUE
, STATUS_SUCCESS
},
302 { NULL
, L
"C:\\\\ReactOS\\", TRUE
, STATUS_SUCCESS
},
303 { NULL
, L
"C:\\ReactOS\\explorer.exe", FALSE
, STATUS_SUCCESS
},
304 { NULL
, L
"C:\\ReactOS\\\\explorer.exe", FALSE
, STATUS_OBJECT_NAME_INVALID
},
305 { NULL
, L
"C:\\ReactOS\\explorer.exe\\", FALSE
, STATUS_OBJECT_NAME_INVALID
},
306 { NULL
, L
"C:\\ReactOS\\explorer.exe\\file", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
307 { NULL
, L
"C:\\ReactOS\\explorer.exe\\\\", FALSE
, STATUS_OBJECT_NAME_INVALID
},
308 /* This will never return STATUS_NOT_A_DIRECTORY. IsDirectory=TRUE is a little hacky but achieves that without special handling */
309 { NULL
, L
"C:\\ReactOS\\explorer.exe\\\\\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
310 { L
"C:\\", L
"", TRUE
, STATUS_SUCCESS
},
311 { L
"C:\\", L
"\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
312 { L
"C:\\", L
"ReactOS", TRUE
, STATUS_SUCCESS
},
313 { L
"C:\\", L
"\\ReactOS", TRUE
, STATUS_OBJECT_NAME_INVALID
},
314 { L
"C:\\", L
"ReactOS\\", TRUE
, STATUS_SUCCESS
},
315 { L
"C:\\", L
"\\ReactOS\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
316 { L
"C:\\ReactOS", L
"", TRUE
, STATUS_SUCCESS
},
317 { L
"C:\\ReactOS", L
"explorer.exe", FALSE
, STATUS_SUCCESS
},
318 { L
"C:\\ReactOS\\explorer.exe", L
"", FALSE
, STATUS_SUCCESS
},
319 { L
"C:\\ReactOS\\explorer.exe", L
"file", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
320 /* Let's try some nonexistent things */
321 { NULL
, L
"C:\\ReactOS\\IDoNotExist", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
322 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
323 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file?", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
324 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file\\\\",TRUE
,STATUS_OBJECT_PATH_NOT_FOUND
},
325 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file\\\\\\",TRUE
,STATUS_OBJECT_PATH_NOT_FOUND
},
326 { NULL
, L
"C:\\ReactOS\\AmIInvalid?", FALSE
, STATUS_OBJECT_NAME_INVALID
},
327 { NULL
, L
"C:\\ReactOS\\.", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
328 { NULL
, L
"C:\\ReactOS\\..", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
329 { NULL
, L
"C:\\ReactOS\\...", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
330 { NULL
, L
"C:\\ReactOS\\.\\system32", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
331 { NULL
, L
"C:\\ReactOS\\..\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
332 { L
"C:\\", L
".", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
333 { L
"C:\\", L
"..", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
334 { L
"C:\\", L
"...", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
335 { L
"C:\\", L
".\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
336 { L
"C:\\", L
"..\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
337 { L
"C:\\ReactOS", L
".", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
338 { L
"C:\\ReactOS", L
"..", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
339 { L
"C:\\ReactOS", L
"...", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
340 { L
"C:\\ReactOS", L
".\\system32", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
341 { L
"C:\\ReactOS", L
"..\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
343 { NULL
, L
"C:", FALSE
, STATUS_SUCCESS
, TRUE
},
344 { L
"C:", L
"", FALSE
, STATUS_SUCCESS
, TRUE
},
345 { L
"C:", L
"\\", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
346 { L
"C:", L
"file", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
349 OBJECT_ATTRIBUTES ObjectAttributes
;
350 IO_STATUS_BLOCK IoStatus
;
351 UNICODE_STRING ParentPath
;
352 UNICODE_STRING RelativePath
;
355 UNICODE_STRING SystemRoot
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
356 HANDLE SymbolicLinkHandle
= NULL
;
357 WCHAR LinkNameBuffer
[128];
358 UNICODE_STRING SymbolicLinkName
;
359 PWSTR SystemDriveName
;
360 PWSTR SystemRootName
;
361 PWCHAR Buffer
= NULL
;
362 BOOLEAN TrailingBackslash
;
363 LARGE_INTEGER AllocationSize
;
364 FILE_DISPOSITION_INFORMATION DispositionInfo
;
366 /* Query \SystemRoot */
367 InitializeObjectAttributes(&ObjectAttributes
,
369 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
372 Status
= ZwOpenSymbolicLinkObject(&SymbolicLinkHandle
,
375 if (skip(NT_SUCCESS(Status
), "Failed to open SystemRoot, %lx\n", Status
))
378 RtlInitEmptyUnicodeString(&SymbolicLinkName
,
380 sizeof(LinkNameBuffer
));
381 Status
= ZwQuerySymbolicLinkObject(SymbolicLinkHandle
,
384 ObCloseHandle(SymbolicLinkHandle
, KernelMode
);
385 if (skip(NT_SUCCESS(Status
), "Failed to query SystemRoot, %lx\n", Status
))
388 /* Split SymbolicLinkName into drive and path */
389 SystemDriveName
= SymbolicLinkName
.Buffer
;
390 SystemRootName
= SymbolicLinkName
.Buffer
+ SymbolicLinkName
.Length
/ sizeof(WCHAR
);
391 *SystemRootName
-- = UNICODE_NULL
;
392 while (*SystemRootName
!= L
'\\')
394 ASSERT(SystemRootName
> SymbolicLinkName
.Buffer
);
397 *SystemRootName
++ = UNICODE_NULL
;
398 trace("System Drive: '%ls'\n", SystemDriveName
);
399 trace("System Root: '%ls'\n", SystemRootName
);
401 /* Allocate path buffer */
402 Buffer
= ExAllocatePoolWithTag(PagedPool
, MAXUSHORT
, 'sFmK');
403 if (skip(Buffer
!= NULL
, "No buffer\n"))
406 /* Finally run some tests! */
407 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
409 /* Open parent directory first */
411 if (Tests
[i
].ParentPathTemplate
)
415 Tests
[i
].ParentPathTemplate
,
418 RtlInitUnicodeString(&ParentPath
, Buffer
);
419 InitializeObjectAttributes(&ObjectAttributes
,
421 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
424 Status
= ZwOpenFile(&ParentHandle
,
428 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
430 ok(Status
== STATUS_SUCCESS
,
431 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i
, Status
);
432 if (skip(NT_SUCCESS(Status
), "No parent handle %lu\n", i
))
436 /* Now open the relative file: */
439 Tests
[i
].RelativePathTemplate
,
442 RtlInitUnicodeString(&RelativePath
, Buffer
);
443 InitializeObjectAttributes(&ObjectAttributes
,
445 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
448 TrailingBackslash
= FALSE
;
449 if (wcslen(Buffer
) && Buffer
[wcslen(Buffer
) - 1] == L
'\\')
450 TrailingBackslash
= TRUE
;
453 Status
= ZwOpenFile(&FileHandle
,
457 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
459 ok(Status
== Tests
[i
].Status
,
460 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
461 if (NT_SUCCESS(Status
))
462 ObCloseHandle(FileHandle
, KernelMode
);
464 /* (2) Directory File */
465 Status
= ZwOpenFile(&FileHandle
,
469 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
470 FILE_DIRECTORY_FILE
);
471 if (Tests
[i
].IsDirectory
|| (!TrailingBackslash
&& !NT_SUCCESS(Tests
[i
].Status
)))
472 ok(Status
== Tests
[i
].Status
,
473 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
475 ok(Status
== STATUS_NOT_A_DIRECTORY
,
476 "[%lu] Status = %lx, expected STATUS_NOT_A_DIRECTORY\n", i
, Status
);
477 if (NT_SUCCESS(Status
))
478 ObCloseHandle(FileHandle
, KernelMode
);
480 /* (3) Non-Directory File */
481 Status
= ZwOpenFile(&FileHandle
,
485 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
486 FILE_NON_DIRECTORY_FILE
);
487 if (Tests
[i
].IsDirectory
&& NT_SUCCESS(Tests
[i
].Status
))
488 ok(Status
== STATUS_FILE_IS_A_DIRECTORY
,
489 "[%lu] Status = %lx, expected STATUS_FILE_IS_A_DIRECTORY\n", i
, Status
);
491 ok(Status
== Tests
[i
].Status
,
492 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
493 if (NT_SUCCESS(Status
))
494 ObCloseHandle(FileHandle
, KernelMode
);
496 /* (4) Directory + Non-Directory */
497 Status
= ZwOpenFile(&FileHandle
,
501 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
502 FILE_DIRECTORY_FILE
| FILE_NON_DIRECTORY_FILE
);
503 if (Tests
[i
].Status
== STATUS_OBJECT_NAME_INVALID
&& Tests
[i
].IsDrive
)
504 ok(Status
== STATUS_OBJECT_NAME_INVALID
,
505 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_INVALID\n", i
, Status
);
507 ok(Status
== STATUS_INVALID_PARAMETER
,
508 "[%lu] Status = %lx, expected STATUS_INVALID_PARAMETER\n", i
, Status
);
509 if (NT_SUCCESS(Status
))
510 ObCloseHandle(FileHandle
, KernelMode
);
512 /* (5) Try to create it */
513 AllocationSize
.QuadPart
= 0;
514 Status
= ZwCreateFile(&FileHandle
,
515 GENERIC_READ
| DELETE
,
519 FILE_ATTRIBUTE_NORMAL
,
520 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
525 if (Tests
[i
].Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
526 ok(Status
== STATUS_SUCCESS
,
527 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i
, Status
);
528 else if (Tests
[i
].Status
== STATUS_OBJECT_NAME_INVALID
&& Tests
[i
].IsDrive
)
529 ok(Status
== STATUS_OBJECT_NAME_INVALID
,
530 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_INVALID\n", i
, Status
);
531 else if (Tests
[i
].IsDrive
)
532 ok(Status
== STATUS_ACCESS_DENIED
,
533 "[%lu] Status = %lx, expected STATUS_ACCESS_DENIED\n", i
, Status
);
534 else if (Tests
[i
].Status
== STATUS_SUCCESS
)
535 ok(Status
== STATUS_OBJECT_NAME_COLLISION
,
536 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_COLLISION\n", i
, Status
);
538 ok(Status
== Tests
[i
].Status
,
539 "[%lu] Status = %lx, expected %lx; %ls -- %ls\n", i
, Status
, Tests
[i
].Status
, Tests
[i
].ParentPathTemplate
, Tests
[i
].RelativePathTemplate
);
540 if (NT_SUCCESS(Status
))
542 if (IoStatus
.Information
== FILE_CREATED
)
544 DispositionInfo
.DeleteFile
= TRUE
;
545 Status
= ZwSetInformationFile(FileHandle
,
548 sizeof(DispositionInfo
),
549 FileDispositionInformation
);
550 ok(Status
== STATUS_SUCCESS
,
551 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i
, Status
);
553 ObCloseHandle(FileHandle
, KernelMode
);
557 ObCloseHandle(ParentHandle
, KernelMode
);
560 ExFreePoolWithTag(Buffer
, 'sFmK');
565 TestSharedCacheMap(VOID
)
574 { 0, L
"\\SystemRoot\\system32\\drivers\\etc\\hosts" },
575 { L
"\\SystemRoot", L
"system32\\drivers\\etc\\hosts" },
576 { L
"\\SystemRoot\\system32", L
"drivers\\etc\\hosts" },
577 { L
"\\SystemRoot\\system32\\drivers", L
"etc\\hosts" },
578 { L
"\\SystemRoot\\system32\\drivers\\etc", L
"hosts" },
580 OBJECT_ATTRIBUTES ObjectAttributes
;
581 IO_STATUS_BLOCK IoStatus
;
582 UNICODE_STRING ParentPath
;
583 UNICODE_STRING RelativePath
;
584 HANDLE ParentHandle
[RTL_NUMBER_OF(Tests
)] = { NULL
};
585 HANDLE FileHandle
[RTL_NUMBER_OF(Tests
)] = { NULL
};
586 PFILE_OBJECT FileObject
[RTL_NUMBER_OF(Tests
)] = { NULL
};
587 PFILE_OBJECT SystemRootObject
= NULL
;
590 LARGE_INTEGER FileOffset
;
593 /* We need an event for ZwReadFile */
594 InitializeObjectAttributes(&ObjectAttributes
,
599 Status
= ZwCreateEvent(&EventHandle
,
604 if (skip(NT_SUCCESS(Status
), "No event\n"))
607 /* Open all test files and get their FILE_OBJECT pointers */
608 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
610 if (Tests
[i
].ParentPath
)
612 RtlInitUnicodeString(&ParentPath
, Tests
[i
].ParentPath
);
613 InitializeObjectAttributes(&ObjectAttributes
,
615 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
618 Status
= ZwOpenFile(&ParentHandle
[i
],
622 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
624 ok_eq_hex(Status
, STATUS_SUCCESS
);
625 if (skip(NT_SUCCESS(Status
), "No parent handle %lu\n", i
))
629 RtlInitUnicodeString(&RelativePath
, Tests
[i
].RelativePath
);
630 InitializeObjectAttributes(&ObjectAttributes
,
632 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
635 Status
= ZwOpenFile(&FileHandle
[i
],
639 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
641 ok_eq_hex(Status
, STATUS_SUCCESS
);
642 if (skip(NT_SUCCESS(Status
), "No file handle %lu\n", i
))
645 Status
= ObReferenceObjectByHandle(FileHandle
[i
],
649 (PVOID
*)&FileObject
[i
],
651 ok_eq_hex(Status
, STATUS_SUCCESS
);
652 if (skip(NT_SUCCESS(Status
), "No file object %lu\n", i
))
656 /* Also get a file object for the SystemRoot directory */
657 Status
= ObReferenceObjectByHandle(ParentHandle
[1],
661 (PVOID
*)&SystemRootObject
,
663 ok_eq_hex(Status
, STATUS_SUCCESS
);
664 if (skip(NT_SUCCESS(Status
), "No SystemRoot object\n"))
667 /* Before read, caching is not initialized */
668 ok_eq_pointer(SystemRootObject
->SectionObjectPointer
, NULL
);
669 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
671 ok(FileObject
[i
]->SectionObjectPointer
!= NULL
, "FileObject[%lu]->SectionObjectPointer = NULL\n", i
);
672 ok(FileObject
[i
]->SectionObjectPointer
== FileObject
[0]->SectionObjectPointer
,
673 "FileObject[%lu]->SectionObjectPointer = %p, expected %p\n",
674 i
, FileObject
[i
]->SectionObjectPointer
, FileObject
[0]->SectionObjectPointer
);
676 if (!skip(FileObject
[0]->SectionObjectPointer
!= NULL
, "No section object pointers\n"))
677 ok_eq_pointer(FileObject
[0]->SectionObjectPointer
->SharedCacheMap
, NULL
);
679 /* Perform a read on one handle to initialize caching */
680 FileOffset
.QuadPart
= 0;
681 Status
= ZwReadFile(FileHandle
[0],
690 if (Status
== STATUS_PENDING
)
692 Status
= ZwWaitForSingleObject(EventHandle
, FALSE
, NULL
);
693 ok_eq_hex(Status
, STATUS_SUCCESS
);
694 Status
= IoStatus
.Status
;
696 ok_eq_hex(Status
, STATUS_SUCCESS
);
698 /* Now we see a SharedCacheMap for the file */
699 ok_eq_pointer(SystemRootObject
->SectionObjectPointer
, NULL
);
700 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
702 ok(FileObject
[i
]->SectionObjectPointer
!= NULL
, "FileObject[%lu]->SectionObjectPointer = NULL\n", i
);
703 ok(FileObject
[i
]->SectionObjectPointer
== FileObject
[0]->SectionObjectPointer
,
704 "FileObject[%lu]->SectionObjectPointer = %p, expected %p\n",
705 i
, FileObject
[i
]->SectionObjectPointer
, FileObject
[0]->SectionObjectPointer
);
707 if (!skip(FileObject
[0]->SectionObjectPointer
!= NULL
, "No section object pointers\n"))
708 ok(FileObject
[0]->SectionObjectPointer
->SharedCacheMap
!= NULL
, "SharedCacheMap is NULL\n");
711 if (SystemRootObject
)
712 ObDereferenceObject(SystemRootObject
);
714 ObCloseHandle(EventHandle
, KernelMode
);
715 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
718 ObDereferenceObject(FileObject
[i
]);
720 ObCloseHandle(FileHandle
[i
], KernelMode
);
722 ObCloseHandle(ParentHandle
[i
], KernelMode
);
726 START_TEST(IoFilesystem
)
728 TestAllInformation();
730 TestSharedCacheMap();