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\\\\", FALSE
, STATUS_OBJECT_NAME_INVALID
},
296 /* This will never return STATUS_NOT_A_DIRECTORY. IsDirectory=TRUE is a little hacky but achieves that without special handling */
297 { NULL
, L
"C:\\ReactOS\\explorer.exe\\\\\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
298 { L
"C:\\", L
"", TRUE
, STATUS_SUCCESS
},
299 { L
"C:\\", L
"\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
300 { L
"C:\\", L
"ReactOS", TRUE
, STATUS_SUCCESS
},
301 { L
"C:\\", L
"\\ReactOS", TRUE
, STATUS_OBJECT_NAME_INVALID
},
302 { L
"C:\\", L
"ReactOS\\", TRUE
, STATUS_SUCCESS
},
303 { L
"C:\\", L
"\\ReactOS\\", TRUE
, STATUS_OBJECT_NAME_INVALID
},
304 { L
"C:\\ReactOS", L
"", TRUE
, STATUS_SUCCESS
},
305 { L
"C:\\ReactOS", L
"explorer.exe", FALSE
, STATUS_SUCCESS
},
306 { L
"C:\\ReactOS\\explorer.exe", L
"", FALSE
, STATUS_SUCCESS
},
307 { L
"C:\\ReactOS\\explorer.exe", L
"file", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
308 /* Let's try some nonexistent things */
309 { NULL
, L
"C:\\ReactOS\\IDoNotExist", FALSE
, STATUS_OBJECT_NAME_NOT_FOUND
},
310 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
311 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file?", FALSE
, STATUS_OBJECT_PATH_NOT_FOUND
},
312 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file\\\\",TRUE
,STATUS_OBJECT_PATH_NOT_FOUND
},
313 { NULL
, L
"C:\\ReactOS\\IDoNotExist\\file\\\\\\",TRUE
,STATUS_OBJECT_PATH_NOT_FOUND
},
314 { NULL
, L
"C:\\ReactOS\\AmIInvalid?", FALSE
, STATUS_OBJECT_NAME_INVALID
},
315 { NULL
, L
"C:\\ReactOS\\.", TRUE
, STATUS_OBJECT_NAME_NOT_FOUND
},
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\\.\\system32", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
319 { NULL
, L
"C:\\ReactOS\\..\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
320 { L
"C:\\", L
".", TRUE
, STATUS_OBJECT_NAME_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
".\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
324 { L
"C:\\", L
"..\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
325 { L
"C:\\ReactOS", L
".", TRUE
, STATUS_OBJECT_NAME_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
".\\system32", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
329 { L
"C:\\ReactOS", L
"..\\ReactOS", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
331 { NULL
, L
"C:", FALSE
, STATUS_SUCCESS
, TRUE
},
332 { L
"C:", L
"", FALSE
, STATUS_SUCCESS
, TRUE
},
333 { L
"C:", L
"\\", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
334 { L
"C:", L
"file", TRUE
, STATUS_OBJECT_PATH_NOT_FOUND
},
337 OBJECT_ATTRIBUTES ObjectAttributes
;
338 IO_STATUS_BLOCK IoStatus
;
339 UNICODE_STRING ParentPath
;
340 UNICODE_STRING RelativePath
;
343 UNICODE_STRING SystemRoot
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
344 HANDLE SymbolicLinkHandle
= NULL
;
345 WCHAR LinkNameBuffer
[128];
346 UNICODE_STRING SymbolicLinkName
;
347 PWSTR SystemDriveName
;
348 PWSTR SystemRootName
;
349 PWCHAR Buffer
= NULL
;
350 BOOLEAN TrailingBackslash
;
351 LARGE_INTEGER AllocationSize
;
352 FILE_DISPOSITION_INFORMATION DispositionInfo
;
354 /* Query \SystemRoot */
355 InitializeObjectAttributes(&ObjectAttributes
,
357 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
360 Status
= ZwOpenSymbolicLinkObject(&SymbolicLinkHandle
,
363 if (skip(NT_SUCCESS(Status
), "Failed to open SystemRoot, %lx\n", Status
))
366 RtlInitEmptyUnicodeString(&SymbolicLinkName
,
368 sizeof(LinkNameBuffer
));
369 Status
= ZwQuerySymbolicLinkObject(SymbolicLinkHandle
,
372 ObCloseHandle(SymbolicLinkHandle
, KernelMode
);
373 if (skip(NT_SUCCESS(Status
), "Failed to query SystemRoot, %lx\n", Status
))
376 /* Split SymbolicLinkName into drive and path */
377 SystemDriveName
= SymbolicLinkName
.Buffer
;
378 SystemRootName
= SymbolicLinkName
.Buffer
+ SymbolicLinkName
.Length
/ sizeof(WCHAR
);
379 *SystemRootName
-- = UNICODE_NULL
;
380 while (*SystemRootName
!= L
'\\')
382 ASSERT(SystemRootName
> SymbolicLinkName
.Buffer
);
385 *SystemRootName
++ = UNICODE_NULL
;
386 trace("System Drive: '%ls'\n", SystemDriveName
);
387 trace("System Root: '%ls'\n", SystemRootName
);
389 /* Allocate path buffer */
390 Buffer
= ExAllocatePoolWithTag(PagedPool
, MAXUSHORT
, 'sFmK');
391 if (skip(Buffer
!= NULL
, "No buffer\n"))
394 /* Finally run some tests! */
395 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
397 /* Open parent directory first */
399 if (Tests
[i
].ParentPathTemplate
)
403 Tests
[i
].ParentPathTemplate
,
406 RtlInitUnicodeString(&ParentPath
, Buffer
);
407 InitializeObjectAttributes(&ObjectAttributes
,
409 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
412 Status
= ZwOpenFile(&ParentHandle
,
416 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
418 ok(Status
== STATUS_SUCCESS
,
419 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i
, Status
);
420 if (skip(NT_SUCCESS(Status
), "No parent handle %lu\n", i
))
424 /* Now open the relative file: */
427 Tests
[i
].RelativePathTemplate
,
430 RtlInitUnicodeString(&RelativePath
, Buffer
);
431 InitializeObjectAttributes(&ObjectAttributes
,
433 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
436 TrailingBackslash
= FALSE
;
437 if (wcslen(Buffer
) && Buffer
[wcslen(Buffer
) - 1] == L
'\\')
438 TrailingBackslash
= TRUE
;
441 Status
= ZwOpenFile(&FileHandle
,
445 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
447 ok(Status
== Tests
[i
].Status
,
448 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
449 if (NT_SUCCESS(Status
))
450 ObCloseHandle(FileHandle
, KernelMode
);
452 /* (2) Directory File */
453 Status
= ZwOpenFile(&FileHandle
,
457 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
458 FILE_DIRECTORY_FILE
);
459 if (Tests
[i
].IsDirectory
|| (!TrailingBackslash
&& !NT_SUCCESS(Tests
[i
].Status
)))
460 ok(Status
== Tests
[i
].Status
,
461 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
463 ok(Status
== STATUS_NOT_A_DIRECTORY
,
464 "[%lu] Status = %lx, expected STATUS_NOT_A_DIRECTORY\n", i
, Status
);
465 if (NT_SUCCESS(Status
))
466 ObCloseHandle(FileHandle
, KernelMode
);
468 /* (3) Non-Directory File */
469 Status
= ZwOpenFile(&FileHandle
,
473 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
474 FILE_NON_DIRECTORY_FILE
);
475 if (Tests
[i
].IsDirectory
&& NT_SUCCESS(Tests
[i
].Status
))
476 ok(Status
== STATUS_FILE_IS_A_DIRECTORY
,
477 "[%lu] Status = %lx, expected STATUS_FILE_IS_A_DIRECTORY\n", i
, Status
);
479 ok(Status
== Tests
[i
].Status
,
480 "[%lu] Status = %lx, expected %lx\n", i
, Status
, Tests
[i
].Status
);
481 if (NT_SUCCESS(Status
))
482 ObCloseHandle(FileHandle
, KernelMode
);
484 /* (4) Directory + Non-Directory */
485 Status
= ZwOpenFile(&FileHandle
,
489 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
490 FILE_DIRECTORY_FILE
| FILE_NON_DIRECTORY_FILE
);
491 if (Tests
[i
].Status
== STATUS_OBJECT_NAME_INVALID
&& Tests
[i
].IsDrive
)
492 ok(Status
== STATUS_OBJECT_NAME_INVALID
,
493 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_INVALID\n", i
, Status
);
495 ok(Status
== STATUS_INVALID_PARAMETER
,
496 "[%lu] Status = %lx, expected STATUS_INVALID_PARAMETER\n", i
, Status
);
497 if (NT_SUCCESS(Status
))
498 ObCloseHandle(FileHandle
, KernelMode
);
500 /* (5) Try to create it */
501 AllocationSize
.QuadPart
= 0;
502 Status
= ZwCreateFile(&FileHandle
,
503 GENERIC_READ
| DELETE
,
507 FILE_ATTRIBUTE_NORMAL
,
508 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
513 if (Tests
[i
].Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
514 ok(Status
== STATUS_SUCCESS
,
515 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i
, Status
);
516 else if (Tests
[i
].Status
== STATUS_OBJECT_NAME_INVALID
&& Tests
[i
].IsDrive
)
517 ok(Status
== STATUS_OBJECT_NAME_INVALID
,
518 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_INVALID\n", i
, Status
);else if (Tests
[i
].IsDrive
)
519 ok(Status
== STATUS_ACCESS_DENIED
,
520 "[%lu] Status = %lx, expected STATUS_ACCESS_DENIED\n", i
, Status
);
521 else if (Tests
[i
].Status
== STATUS_SUCCESS
)
522 ok(Status
== STATUS_OBJECT_NAME_COLLISION
,
523 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_COLLISION\n", i
, Status
);
525 ok(Status
== Tests
[i
].Status
,
526 "[%lu] Status = %lx, expected %lx; %ls -- %ls\n", i
, Status
, Tests
[i
].Status
, Tests
[i
].ParentPathTemplate
, Tests
[i
].RelativePathTemplate
);
527 if (NT_SUCCESS(Status
))
529 if (IoStatus
.Information
== FILE_CREATED
)
531 DispositionInfo
.DeleteFile
= TRUE
;
532 Status
= ZwSetInformationFile(FileHandle
,
535 sizeof(DispositionInfo
),
536 FileDispositionInformation
);
537 ok(Status
== STATUS_SUCCESS
,
538 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i
, Status
);
540 ObCloseHandle(FileHandle
, KernelMode
);
544 ObCloseHandle(ParentHandle
, KernelMode
);
547 ExFreePoolWithTag(Buffer
, 'sFmK');
552 TestSharedCacheMap(VOID
)
561 { 0, L
"\\SystemRoot\\system32\\drivers\\etc\\hosts" },
562 { L
"\\SystemRoot", L
"system32\\drivers\\etc\\hosts" },
563 { L
"\\SystemRoot\\system32", L
"drivers\\etc\\hosts" },
564 { L
"\\SystemRoot\\system32\\drivers", L
"etc\\hosts" },
565 { L
"\\SystemRoot\\system32\\drivers\\etc", L
"hosts" },
567 OBJECT_ATTRIBUTES ObjectAttributes
;
568 IO_STATUS_BLOCK IoStatus
;
569 UNICODE_STRING ParentPath
;
570 UNICODE_STRING RelativePath
;
571 HANDLE ParentHandle
[RTL_NUMBER_OF(Tests
)] = { NULL
};
572 HANDLE FileHandle
[RTL_NUMBER_OF(Tests
)] = { NULL
};
573 PFILE_OBJECT FileObject
[RTL_NUMBER_OF(Tests
)] = { NULL
};
574 PFILE_OBJECT SystemRootObject
= NULL
;
577 LARGE_INTEGER FileOffset
;
580 /* We need an event for ZwReadFile */
581 InitializeObjectAttributes(&ObjectAttributes
,
586 Status
= ZwCreateEvent(&EventHandle
,
591 if (skip(NT_SUCCESS(Status
), "No event\n"))
594 /* Open all test files and get their FILE_OBJECT pointers */
595 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
597 if (Tests
[i
].ParentPath
)
599 RtlInitUnicodeString(&ParentPath
, Tests
[i
].ParentPath
);
600 InitializeObjectAttributes(&ObjectAttributes
,
602 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
605 Status
= ZwOpenFile(&ParentHandle
[i
],
609 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
611 ok_eq_hex(Status
, STATUS_SUCCESS
);
612 if (skip(NT_SUCCESS(Status
), "No parent handle %lu\n", i
))
616 RtlInitUnicodeString(&RelativePath
, Tests
[i
].RelativePath
);
617 InitializeObjectAttributes(&ObjectAttributes
,
619 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
622 Status
= ZwOpenFile(&FileHandle
[i
],
626 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
628 ok_eq_hex(Status
, STATUS_SUCCESS
);
629 if (skip(NT_SUCCESS(Status
), "No file handle %lu\n", i
))
632 Status
= ObReferenceObjectByHandle(FileHandle
[i
],
636 (PVOID
*)&FileObject
[i
],
638 ok_eq_hex(Status
, STATUS_SUCCESS
);
639 if (skip(NT_SUCCESS(Status
), "No file object %lu\n", i
))
643 /* Also get a file object for the SystemRoot directory */
644 Status
= ObReferenceObjectByHandle(ParentHandle
[1],
648 (PVOID
*)&SystemRootObject
,
650 ok_eq_hex(Status
, STATUS_SUCCESS
);
651 if (skip(NT_SUCCESS(Status
), "No SystemRoot object\n"))
654 /* Before read, caching is not initialized */
655 ok_eq_pointer(SystemRootObject
->SectionObjectPointer
, NULL
);
656 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
658 ok(FileObject
[i
]->SectionObjectPointer
!= NULL
, "FileObject[%lu]->SectionObjectPointer = NULL\n", i
);
659 ok(FileObject
[i
]->SectionObjectPointer
== FileObject
[0]->SectionObjectPointer
,
660 "FileObject[%lu]->SectionObjectPointer = %p, expected %p\n",
661 i
, FileObject
[i
]->SectionObjectPointer
, FileObject
[0]->SectionObjectPointer
);
663 if (!skip(FileObject
[0]->SectionObjectPointer
!= NULL
, "No section object pointers\n"))
664 ok_eq_pointer(FileObject
[0]->SectionObjectPointer
->SharedCacheMap
, NULL
);
666 /* Perform a read on one handle to initialize caching */
667 FileOffset
.QuadPart
= 0;
668 Status
= ZwReadFile(FileHandle
[0],
677 if (Status
== STATUS_PENDING
)
679 Status
= ZwWaitForSingleObject(EventHandle
, FALSE
, NULL
);
680 ok_eq_hex(Status
, STATUS_SUCCESS
);
681 Status
= IoStatus
.Status
;
683 ok_eq_hex(Status
, STATUS_SUCCESS
);
685 /* Now we see a SharedCacheMap for the file */
686 ok_eq_pointer(SystemRootObject
->SectionObjectPointer
, NULL
);
687 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
689 ok(FileObject
[i
]->SectionObjectPointer
!= NULL
, "FileObject[%lu]->SectionObjectPointer = NULL\n", i
);
690 ok(FileObject
[i
]->SectionObjectPointer
== FileObject
[0]->SectionObjectPointer
,
691 "FileObject[%lu]->SectionObjectPointer = %p, expected %p\n",
692 i
, FileObject
[i
]->SectionObjectPointer
, FileObject
[0]->SectionObjectPointer
);
694 if (!skip(FileObject
[0]->SectionObjectPointer
!= NULL
, "No section object pointers\n"))
695 ok(FileObject
[0]->SectionObjectPointer
->SharedCacheMap
!= NULL
, "SharedCacheMap is NULL\n");
698 if (SystemRootObject
)
699 ObDereferenceObject(SystemRootObject
);
701 ObCloseHandle(EventHandle
, KernelMode
);
702 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
705 ObDereferenceObject(FileObject
[i
]);
707 ObCloseHandle(FileHandle
[i
], KernelMode
);
709 ObCloseHandle(ParentHandle
[i
], KernelMode
);
713 START_TEST(IoFilesystem
)
715 TestAllInformation();
717 TestSharedCacheMap();