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
;
283 { NULL
, L
"C:\\", TRUE
, STATUS_SUCCESS
, TRUE
},
284 { NULL
, L
"C:\\\\", TRUE
, STATUS_SUCCESS
, TRUE
},
285 { NULL
, L
"C:\\\\\\", TRUE
, STATUS_OBJECT_NAME_INVALID
, TRUE
},
286 { NULL
, L
"C:\\ReactOS", TRUE
, STATUS_SUCCESS
},
287 { NULL
, L
"C:\\ReactOS\\", TRUE
, STATUS_SUCCESS
},
288 { NULL
, L
"C:\\ReactOS\\\\", TRUE
, STATUS_SUCCESS
},
289 { NULL
, L
"C:\\ReactOS\\\\\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
290 { NULL
, L
"C:\\\\ReactOS", TRUE
, STATUS_SUCCESS
},
291 { NULL
, L
"C:\\\\ReactOS\\", TRUE
, STATUS_SUCCESS
},
292 { NULL
, L
"C:\\ReactOS\\explorer.exe", FALSE
, STATUS_SUCCESS
},
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 { NULL
, L
"C:\\ReactOS\\explorer.exe\\file", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
296 { NULL
, L
"C:\\ReactOS\\explorer.exe\\\\", FALSE
, STATUS_OBJECT_NAME_INVALID
},
297 /* This will never return STATUS_NOT_A_DIRECTORY. IsDirectory=TRUE is a little hacky but achieves that without special handling */
298 { NULL
, L
"C:\\ReactOS\\explorer.exe\\\\\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
299 { L
"C:\\", L
"", TRUE
, STATUS_SUCCESS
},
300 { L
"C:\\", L
"\\", 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:\\", L
"ReactOS\\", TRUE
, STATUS_SUCCESS
},
304 { L
"C:\\", L
"\\ReactOS\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
305 { L
"C:\\ReactOS", L
"", TRUE
, STATUS_SUCCESS
},
306 { L
"C:\\ReactOS", L
"explorer.exe", FALSE
, STATUS_SUCCESS
},
307 { L
"C:\\ReactOS\\explorer.exe", L
"", FALSE
, STATUS_SUCCESS
},
308 { L
"C:\\ReactOS\\explorer.exe", L
"file", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
309 /* Let's try some nonexistent things */
310 { NULL
, L
"C:\\ReactOS\\IDoNotExist", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
311 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
312 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file?", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
313 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file\\\\",TRUE
,STATUS_OBJECT_PATH_NOT_FOUND
},
314 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file\\\\\\",TRUE
,STATUS_OBJECT_PATH_NOT_FOUND
},
315 { NULL
, L
"C:\\ReactOS\\AmIInvalid?", FALSE
, STATUS_OBJECT_NAME_INVALID
},
316 { NULL
, L
"C:\\ReactOS\\.", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
317 { NULL
, L
"C:\\ReactOS\\..", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
318 { NULL
, L
"C:\\ReactOS\\...", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
319 { NULL
, L
"C:\\ReactOS\\.\\system32", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
320 { NULL
, L
"C:\\ReactOS\\..\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
321 { L
"C:\\", L
".", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
322 { L
"C:\\", L
"..", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
323 { L
"C:\\", L
"...", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
324 { L
"C:\\", L
".\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
325 { L
"C:\\", L
"..\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
326 { L
"C:\\ReactOS", L
".", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
327 { L
"C:\\ReactOS", L
"..", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
328 { L
"C:\\ReactOS", L
"...", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
329 { L
"C:\\ReactOS", L
".\\system32", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
330 { L
"C:\\ReactOS", L
"..\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
332 { NULL
, L
"C:", FALSE
, STATUS_SUCCESS
, TRUE
},
333 { L
"C:", L
"", FALSE
, STATUS_SUCCESS
, TRUE
},
334 { L
"C:", L
"\\", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
335 { L
"C:", L
"file", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
338 OBJECT_ATTRIBUTES ObjectAttributes
;
339 IO_STATUS_BLOCK IoStatus
;
340 UNICODE_STRING ParentPath
;
341 UNICODE_STRING RelativePath
;
344 UNICODE_STRING SystemRoot
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
345 HANDLE SymbolicLinkHandle
= NULL
;
346 WCHAR LinkNameBuffer
[128];
347 UNICODE_STRING SymbolicLinkName
;
348 PWSTR SystemDriveName
;
349 PWSTR SystemRootName
;
350 PWCHAR Buffer
= NULL
;
351 BOOLEAN TrailingBackslash
;
352 LARGE_INTEGER AllocationSize
;
353 FILE_DISPOSITION_INFORMATION DispositionInfo
;
355 /* Query \SystemRoot */
356 InitializeObjectAttributes(&ObjectAttributes
,
358 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
361 Status
= ZwOpenSymbolicLinkObject(&SymbolicLinkHandle
,
364 if (skip(NT_SUCCESS(Status
), "Failed to open SystemRoot, %lx\n", Status
))
367 RtlInitEmptyUnicodeString(&SymbolicLinkName
,
369 sizeof(LinkNameBuffer
));
370 Status
= ZwQuerySymbolicLinkObject(SymbolicLinkHandle
,
373 ObCloseHandle(SymbolicLinkHandle
, KernelMode
);
374 if (skip(NT_SUCCESS(Status
), "Failed to query SystemRoot, %lx\n", Status
))
377 /* Split SymbolicLinkName into drive and path */
378 SystemDriveName
= SymbolicLinkName
.Buffer
;
379 SystemRootName
= SymbolicLinkName
.Buffer
+ SymbolicLinkName
.Length
/ sizeof(WCHAR
);
380 *SystemRootName
-- = UNICODE_NULL
;
381 while (*SystemRootName
!= L
'\\')
383 ASSERT(SystemRootName
> SymbolicLinkName
.Buffer
);
386 *SystemRootName
++ = UNICODE_NULL
;
387 trace("System Drive: '%ls'\n", SystemDriveName
);
388 trace("System Root: '%ls'\n", SystemRootName
);
390 /* Allocate path buffer */
391 Buffer
= ExAllocatePoolWithTag(PagedPool
, MAXUSHORT
, 'sFmK');
392 if (skip(Buffer
!= NULL
, "No buffer\n"))
395 /* Finally run some tests! */
396 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
398 /* Open parent directory first */
400 if (Tests
[i
].ParentPathTemplate
)
404 Tests
[i
].ParentPathTemplate
,
407 RtlInitUnicodeString(&ParentPath
, Buffer
);
408 InitializeObjectAttributes(&ObjectAttributes
,
410 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
413 Status
= ZwOpenFile(&ParentHandle
,
417 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
419 ok(Status
== STATUS_SUCCESS
,
420 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i
, Status
);
421 if (skip(NT_SUCCESS(Status
), "No parent handle %lu\n", i
))
425 /* Now open the relative file: */
428 Tests
[i
].RelativePathTemplate
,
431 RtlInitUnicodeString(&RelativePath
, Buffer
);
432 InitializeObjectAttributes(&ObjectAttributes
,
434 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
437 TrailingBackslash
= FALSE
;
438 if (wcslen(Buffer
) && Buffer
[wcslen(Buffer
) - 1] == L
'\\')
439 TrailingBackslash
= TRUE
;
442 Status
= ZwOpenFile(&FileHandle
,
446 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
448 ok(Status
== Tests
[i
].Status
,
449 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
450 if (NT_SUCCESS(Status
))
451 ObCloseHandle(FileHandle
, KernelMode
);
453 /* (2) Directory File */
454 Status
= ZwOpenFile(&FileHandle
,
458 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
459 FILE_DIRECTORY_FILE
);
460 if (Tests
[i
].IsDirectory
|| (!TrailingBackslash
&& !NT_SUCCESS(Tests
[i
].Status
)))
461 ok(Status
== Tests
[i
].Status
,
462 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
464 ok(Status
== STATUS_NOT_A_DIRECTORY
,
465 "[%lu] Status = %lx, expected STATUS_NOT_A_DIRECTORY\n", i
, Status
);
466 if (NT_SUCCESS(Status
))
467 ObCloseHandle(FileHandle
, KernelMode
);
469 /* (3) Non-Directory File */
470 Status
= ZwOpenFile(&FileHandle
,
474 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
475 FILE_NON_DIRECTORY_FILE
);
476 if (Tests
[i
].IsDirectory
&& NT_SUCCESS(Tests
[i
].Status
))
477 ok(Status
== STATUS_FILE_IS_A_DIRECTORY
,
478 "[%lu] Status = %lx, expected STATUS_FILE_IS_A_DIRECTORY\n", i
, Status
);
480 ok(Status
== Tests
[i
].Status
,
481 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
482 if (NT_SUCCESS(Status
))
483 ObCloseHandle(FileHandle
, KernelMode
);
485 /* (4) Directory + Non-Directory */
486 Status
= ZwOpenFile(&FileHandle
,
490 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
491 FILE_DIRECTORY_FILE
| FILE_NON_DIRECTORY_FILE
);
492 if (Tests
[i
].Status
== STATUS_OBJECT_NAME_INVALID
&& Tests
[i
].IsDrive
)
493 ok(Status
== STATUS_OBJECT_NAME_INVALID
,
494 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_INVALID\n", i
, Status
);
496 ok(Status
== STATUS_INVALID_PARAMETER
,
497 "[%lu] Status = %lx, expected STATUS_INVALID_PARAMETER\n", i
, Status
);
498 if (NT_SUCCESS(Status
))
499 ObCloseHandle(FileHandle
, KernelMode
);
501 /* (5) Try to create it */
502 AllocationSize
.QuadPart
= 0;
503 Status
= ZwCreateFile(&FileHandle
,
504 GENERIC_READ
| DELETE
,
508 FILE_ATTRIBUTE_NORMAL
,
509 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
514 if (Tests
[i
].Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
515 ok(Status
== STATUS_SUCCESS
,
516 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i
, Status
);
517 else if (Tests
[i
].Status
== STATUS_OBJECT_NAME_INVALID
&& Tests
[i
].IsDrive
)
518 ok(Status
== STATUS_OBJECT_NAME_INVALID
,
519 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_INVALID\n", i
, Status
);
520 else if (Tests
[i
].IsDrive
)
521 ok(Status
== STATUS_ACCESS_DENIED
,
522 "[%lu] Status = %lx, expected STATUS_ACCESS_DENIED\n", i
, Status
);
523 else if (Tests
[i
].Status
== STATUS_SUCCESS
)
524 ok(Status
== STATUS_OBJECT_NAME_COLLISION
,
525 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_COLLISION\n", i
, Status
);
527 ok(Status
== Tests
[i
].Status
,
528 "[%lu] Status = %lx, expected %lx; %ls -- %ls\n", i
, Status
, Tests
[i
].Status
, Tests
[i
].ParentPathTemplate
, Tests
[i
].RelativePathTemplate
);
529 if (NT_SUCCESS(Status
))
531 if (IoStatus
.Information
== FILE_CREATED
)
533 DispositionInfo
.DeleteFile
= TRUE
;
534 Status
= ZwSetInformationFile(FileHandle
,
537 sizeof(DispositionInfo
),
538 FileDispositionInformation
);
539 ok(Status
== STATUS_SUCCESS
,
540 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i
, Status
);
542 ObCloseHandle(FileHandle
, KernelMode
);
546 ObCloseHandle(ParentHandle
, KernelMode
);
549 ExFreePoolWithTag(Buffer
, 'sFmK');
554 TestSharedCacheMap(VOID
)
563 { 0, L
"\\SystemRoot\\system32\\drivers\\etc\\hosts" },
564 { L
"\\SystemRoot", L
"system32\\drivers\\etc\\hosts" },
565 { L
"\\SystemRoot\\system32", L
"drivers\\etc\\hosts" },
566 { L
"\\SystemRoot\\system32\\drivers", L
"etc\\hosts" },
567 { L
"\\SystemRoot\\system32\\drivers\\etc", L
"hosts" },
569 OBJECT_ATTRIBUTES ObjectAttributes
;
570 IO_STATUS_BLOCK IoStatus
;
571 UNICODE_STRING ParentPath
;
572 UNICODE_STRING RelativePath
;
573 HANDLE ParentHandle
[RTL_NUMBER_OF(Tests
)] = { NULL
};
574 HANDLE FileHandle
[RTL_NUMBER_OF(Tests
)] = { NULL
};
575 PFILE_OBJECT FileObject
[RTL_NUMBER_OF(Tests
)] = { NULL
};
576 PFILE_OBJECT SystemRootObject
= NULL
;
579 LARGE_INTEGER FileOffset
;
582 /* We need an event for ZwReadFile */
583 InitializeObjectAttributes(&ObjectAttributes
,
588 Status
= ZwCreateEvent(&EventHandle
,
593 if (skip(NT_SUCCESS(Status
), "No event\n"))
596 /* Open all test files and get their FILE_OBJECT pointers */
597 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
599 if (Tests
[i
].ParentPath
)
601 RtlInitUnicodeString(&ParentPath
, Tests
[i
].ParentPath
);
602 InitializeObjectAttributes(&ObjectAttributes
,
604 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
607 Status
= ZwOpenFile(&ParentHandle
[i
],
611 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
613 ok_eq_hex(Status
, STATUS_SUCCESS
);
614 if (skip(NT_SUCCESS(Status
), "No parent handle %lu\n", i
))
618 RtlInitUnicodeString(&RelativePath
, Tests
[i
].RelativePath
);
619 InitializeObjectAttributes(&ObjectAttributes
,
621 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
624 Status
= ZwOpenFile(&FileHandle
[i
],
628 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
630 ok_eq_hex(Status
, STATUS_SUCCESS
);
631 if (skip(NT_SUCCESS(Status
), "No file handle %lu\n", i
))
634 Status
= ObReferenceObjectByHandle(FileHandle
[i
],
638 (PVOID
*)&FileObject
[i
],
640 ok_eq_hex(Status
, STATUS_SUCCESS
);
641 if (skip(NT_SUCCESS(Status
), "No file object %lu\n", i
))
645 /* Also get a file object for the SystemRoot directory */
646 Status
= ObReferenceObjectByHandle(ParentHandle
[1],
650 (PVOID
*)&SystemRootObject
,
652 ok_eq_hex(Status
, STATUS_SUCCESS
);
653 if (skip(NT_SUCCESS(Status
), "No SystemRoot object\n"))
656 /* Before read, caching is not initialized */
657 ok_eq_pointer(SystemRootObject
->SectionObjectPointer
, NULL
);
658 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
660 ok(FileObject
[i
]->SectionObjectPointer
!= NULL
, "FileObject[%lu]->SectionObjectPointer = NULL\n", i
);
661 ok(FileObject
[i
]->SectionObjectPointer
== FileObject
[0]->SectionObjectPointer
,
662 "FileObject[%lu]->SectionObjectPointer = %p, expected %p\n",
663 i
, FileObject
[i
]->SectionObjectPointer
, FileObject
[0]->SectionObjectPointer
);
665 if (!skip(FileObject
[0]->SectionObjectPointer
!= NULL
, "No section object pointers\n"))
666 ok_eq_pointer(FileObject
[0]->SectionObjectPointer
->SharedCacheMap
, NULL
);
668 /* Perform a read on one handle to initialize caching */
669 FileOffset
.QuadPart
= 0;
670 Status
= ZwReadFile(FileHandle
[0],
679 if (Status
== STATUS_PENDING
)
681 Status
= ZwWaitForSingleObject(EventHandle
, FALSE
, NULL
);
682 ok_eq_hex(Status
, STATUS_SUCCESS
);
683 Status
= IoStatus
.Status
;
685 ok_eq_hex(Status
, STATUS_SUCCESS
);
687 /* Now we see a SharedCacheMap for the file */
688 ok_eq_pointer(SystemRootObject
->SectionObjectPointer
, NULL
);
689 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
691 ok(FileObject
[i
]->SectionObjectPointer
!= NULL
, "FileObject[%lu]->SectionObjectPointer = NULL\n", i
);
692 ok(FileObject
[i
]->SectionObjectPointer
== FileObject
[0]->SectionObjectPointer
,
693 "FileObject[%lu]->SectionObjectPointer = %p, expected %p\n",
694 i
, FileObject
[i
]->SectionObjectPointer
, FileObject
[0]->SectionObjectPointer
);
696 if (!skip(FileObject
[0]->SectionObjectPointer
!= NULL
, "No section object pointers\n"))
697 ok(FileObject
[0]->SectionObjectPointer
->SharedCacheMap
!= NULL
, "SharedCacheMap is NULL\n");
700 if (SystemRootObject
)
701 ObDereferenceObject(SystemRootObject
);
703 ObCloseHandle(EventHandle
, KernelMode
);
704 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
707 ObDereferenceObject(FileObject
[i
]);
709 ObCloseHandle(FileHandle
[i
], KernelMode
);
711 ObCloseHandle(ParentHandle
[i
], KernelMode
);
715 START_TEST(IoFilesystem
)
717 TestAllInformation();
719 TestSharedCacheMap();