ReactOS 0.4.16-dev-1946-g52006dd
IoFilesystem.c
Go to the documentation of this file.
1/*
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>
6 */
7
8#include <kmt_test.h>
9
10typedef enum
11{
16
18
19static
26{
30
31 *Info = NULL;
32 if (*Length)
33 {
35 if (skip(Buffer != NULL, "Failed to allocate %Iu bytes\n", *Length))
37
39 }
40 else
41 {
42 Buffer = NULL;
43 }
44 RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
46 {
47 Status = ZwQueryInformationFile(FileHandle,
48 &IoStatus,
49 Buffer,
50 *Length,
52 }
54 {
56 ok(0, "Exception %lx querying class %d with length %Iu\n",
58 }
61 {
62 Status = ZwWaitForSingleObject(FileHandle, FALSE, NULL);
64 Status = IoStatus.Status;
65 }
66
67 *Length = IoStatus.Information;
68 if (NT_SUCCESS(Status))
69 {
70 *Info = Buffer;
71 }
72 else if (Buffer)
73 {
75 }
76 return Status;
77}
78
79static
80VOID
82{
84 UNICODE_STRING FileName = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntoskrnl.exe");
85 UNICODE_STRING Ntoskrnl = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
89 PFILE_ALL_INFORMATION FileAllInfo;
91 ULONG NameLength;
93 UNICODE_STRING NamePart;
94 FILE_FS_ATTRIBUTE_INFORMATION* FsAttributeInfo;
95 ULONG FSAttributeBufferSize = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 256;
96
98 &FileName,
100 NULL,
101 NULL);
105 &IoStatus,
108 if (Status == STATUS_PENDING)
109 {
110 Status = ZwWaitForSingleObject(FileHandle, FALSE, NULL);
112 Status = IoStatus.Status;
113 }
115 if (skip(NT_SUCCESS(Status), "No file handle, %lx\n", Status))
116 return;
117
118 /* Find filesystem for the system */
119 FsAttributeInfo = ExAllocatePoolWithTag(PagedPool, FSAttributeBufferSize, 'sySF');
120 if (FsAttributeInfo == NULL)
121 {
122 ok(FALSE, "Failed to allocate memory to query the filesystem!\n");
124 return;
125 }
126
128 &IoStatus,
129 FsAttributeInfo,
130 FSAttributeBufferSize,
132 if (NT_SUCCESS(Status))
133 {
134 if (FsAttributeInfo->FileSystemNameLength >= 8 &&
135 RtlCompareMemory(FsAttributeInfo->FileSystemName, L"NTFS", 8) == 8)
136 {
138 trace("Filesystem: NTFS\n");
139 }
140 else if (FsAttributeInfo->FileSystemNameLength >= 10 &&
141 RtlCompareMemory(FsAttributeInfo->FileSystemName, L"FAT32", 10) == 10)
142 {
144 trace("Filesystem: FAT32\n");
145 }
146 else
147 {
148 UNICODE_STRING FsName;
149 FsName.Length = FsAttributeInfo->FileSystemNameLength;
150 FsName.MaximumLength = FsAttributeInfo->FileSystemNameLength;
151 FsName.Buffer = FsAttributeInfo->FileSystemName;
153 trace("Unknown filesystem: %wZ\n", &FsName);
154 }
155 }
156 else
157 {
158 ok(FALSE, "Failed to query filesystem: %lx\n", Status);
159 }
160
161 ExFreePoolWithTag(FsAttributeInfo, 'sySF');
162
163 /* NtQueryInformationFile doesn't do length checks for kernel callers in a free build */
165 {
166 /* Zero length */
167 Length = 0;
170 ok_eq_size(Length, (ULONG_PTR)0x5555555555555555);
171 if (FileAllInfo)
172 KmtFreeGuarded(FileAllInfo);
173
174 /* One less than the minimum */
175 Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) - 1;
178 ok_eq_size(Length, (ULONG_PTR)0x5555555555555555);
179 if (FileAllInfo)
180 KmtFreeGuarded(FileAllInfo);
181
182 /* No space for the name -- fastfat handles this gracefully, ntfs doesn't.
183 * But the Io manager makes it fail on checked builds, so it's
184 * technically illegal
185 */
186 Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName);
189 ok_eq_size(Length, (ULONG_PTR)0x5555555555555555);
190 if (FileAllInfo)
191 KmtFreeGuarded(FileAllInfo);
192 }
193
194 /* The minimum allowed */
199 if (FileAllInfo)
200 KmtFreeGuarded(FileAllInfo);
201
202 /* Plenty of space -- determine NameLength and copy the name */
203 Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + MAX_PATH * sizeof(WCHAR);
206 if (skip(NT_SUCCESS(Status) && FileAllInfo != NULL, "No info\n"))
207 {
208 goto NoInfo;
209 }
210
211 NameLength = FileAllInfo->NameInformation.FileNameLength;
212 ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength);
213 Name = ExAllocatePoolWithTag(PagedPool, NameLength + sizeof(UNICODE_NULL), 'sFmK');
214 if (!skip(Name != NULL, "Could not allocate %lu bytes\n", NameLength + (ULONG)sizeof(UNICODE_NULL)))
215 {
217 FileAllInfo->NameInformation.FileName,
218 NameLength);
219 Name[NameLength / sizeof(WCHAR)] = UNICODE_NULL;
220 ok(Name[0] == L'\\', "Name is %ls, expected first char to be \\\n", Name);
221 ok(NameLength >= Ntoskrnl.Length + sizeof(WCHAR), "NameLength %lu too short\n", NameLength);
222 if (NameLength >= Ntoskrnl.Length)
223 {
224 NamePart.Buffer = Name + (NameLength - Ntoskrnl.Length) / sizeof(WCHAR);
225 NamePart.Length = Ntoskrnl.Length;
226 NamePart.MaximumLength = NamePart.Length;
227 ok(RtlEqualUnicodeString(&NamePart, &Ntoskrnl, TRUE),
228 "Name ends in '%wZ', expected %wZ\n", &NamePart, &Ntoskrnl);
229 }
230 ExFreePoolWithTag(Name, 'sFmK');
231 }
232 ok(FileAllInfo->NameInformation.FileName[NameLength / sizeof(WCHAR)] == 0xdddd,
233 "Char past FileName is %x\n",
234 FileAllInfo->NameInformation.FileName[NameLength / sizeof(WCHAR)]);
235 if (FileAllInfo)
236 KmtFreeGuarded(FileAllInfo);
237
238 /* One char less than needed */
239 Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - sizeof(WCHAR);
242 ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - sizeof(WCHAR));
243 if (FileAllInfo)
244 KmtFreeGuarded(FileAllInfo);
245
246 /* One byte less than needed */
247 Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - 1;
250 if (g_Filesystem == FAT32)
251 ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - 1);
252 else if (g_Filesystem == NTFS)
253 ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - 2);
254 if (FileAllInfo)
255 KmtFreeGuarded(FileAllInfo);
256
257 /* Exactly the required size */
258 Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength;
261 ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength);
262 if (FileAllInfo)
263 KmtFreeGuarded(FileAllInfo);
264
265 /* One byte more than needed */
266 Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength + 1;
269 ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength);
270 if (FileAllInfo)
271 KmtFreeGuarded(FileAllInfo);
272
273 /* One char more than needed */
274 Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength + sizeof(WCHAR);
277 ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength);
278 if (FileAllInfo)
279 KmtFreeGuarded(FileAllInfo);
280
282 Length = sizeof(*FileEofInfo);
284 // Checked build: STATUS_INVALID_INFO_CLASS, Free build: STATUS_INVALID_PARAMETER
285 ok(Status == STATUS_INVALID_PARAMETER || Status == STATUS_INVALID_INFO_CLASS, "Wrong Status = %lx\n", Status);
286 ok(Length == 0 || // Win10
287 Length == (SIZE_T)0x5555555555555555ULL, // Win2k3-Win8.1
288 "Invalid length (0x%X)\n", Length);
289 if (FileEofInfo)
290 KmtFreeGuarded(FileEofInfo);
291
292NoInfo:
295}
296
297static
298VOID
302 _In_ PCWSTR Template,
303 _In_ PCWSTR SystemDriveName,
304 _In_ PCWSTR SystemRootName)
305{
306 UNICODE_STRING SystemDriveTemplate = RTL_CONSTANT_STRING(L"C:");
307 UNICODE_STRING SystemRootTemplate = RTL_CONSTANT_STRING(L"ReactOS");
308 ULONG SystemDriveLength;
309 ULONG SystemRootLength;
310 PWCHAR Dest = Buffer;
312
313 SystemDriveLength = (ULONG)wcslen(SystemDriveName) * sizeof(WCHAR);
314 SystemRootLength = (ULONG)wcslen(SystemRootName) * sizeof(WCHAR);
315
316 RtlInitUnicodeString(&String, Template);
317 ASSERT(String.Length % sizeof(WCHAR) == 0);
318 while (String.Length)
319 {
320 if (RtlPrefixUnicodeString(&SystemDriveTemplate, &String, TRUE))
321 {
322 ASSERT((Dest - Buffer) * sizeof(WCHAR) + SystemDriveLength < BufferSize);
323 RtlCopyMemory(Dest,
324 SystemDriveName,
325 SystemDriveLength);
326 Dest += SystemDriveLength / sizeof(WCHAR);
327
328 String.Buffer += SystemDriveTemplate.Length / sizeof(WCHAR);
329 String.Length -= SystemDriveTemplate.Length;
330 String.MaximumLength -= SystemDriveTemplate.Length;
331 continue;
332 }
333
334 if (RtlPrefixUnicodeString(&SystemRootTemplate, &String, TRUE))
335 {
336 ASSERT((Dest - Buffer) * sizeof(WCHAR) + SystemRootLength < BufferSize);
337 RtlCopyMemory(Dest,
338 SystemRootName,
339 SystemRootLength);
340 Dest += SystemRootLength / sizeof(WCHAR);
341
342 String.Buffer += SystemRootTemplate.Length / sizeof(WCHAR);
343 String.Length -= SystemRootTemplate.Length;
344 String.MaximumLength -= SystemRootTemplate.Length;
345 continue;
346 }
347
348 ASSERT(Dest - Buffer < BufferSize / sizeof(WCHAR));
349 *Dest++ = String.Buffer[0];
350
351 String.Buffer++;
352 String.Length -= sizeof(WCHAR);
353 String.MaximumLength -= sizeof(WCHAR);
354 }
355 ASSERT(Dest - Buffer < BufferSize / sizeof(WCHAR));
356 *Dest = UNICODE_NULL;
357}
358
359static
360VOID
362{
364 typedef struct
365 {
366 PCWSTR ParentPathTemplate;
367 PCWSTR RelativePathTemplate;
368 BOOLEAN IsDirectory_FAT32;
369 NTSTATUS Status_FAT32;
370 BOOLEAN IsDirectory_NTFS;
371 NTSTATUS Status_NTFS;
372 BOOLEAN IsDrive;
373 } RelativeNameTest;
374
375 RelativeNameTest Tests[] =
376 {
378 { NULL, L"C:\\\\", TRUE, STATUS_SUCCESS, TRUE, STATUS_SUCCESS, TRUE },
380 { NULL, L"C:\\ReactOS", TRUE, STATUS_SUCCESS, TRUE, STATUS_SUCCESS},
381 { NULL, L"C:\\ReactOS\\", TRUE, STATUS_SUCCESS, TRUE, STATUS_SUCCESS, },
382 { NULL, L"C:\\ReactOS\\\\", TRUE, STATUS_SUCCESS, TRUE, STATUS_OBJECT_NAME_INVALID},
384 { NULL, L"C:\\\\ReactOS", TRUE, STATUS_SUCCESS, TRUE, STATUS_SUCCESS},
385 { NULL, L"C:\\\\ReactOS\\", TRUE, STATUS_SUCCESS, TRUE, STATUS_SUCCESS },
386 { NULL, L"C:\\ReactOS\\explorer.exe", FALSE, STATUS_SUCCESS, FALSE, STATUS_SUCCESS},
387 { NULL, L"C:\\ReactOS\\\\explorer.exe", FALSE, STATUS_OBJECT_NAME_INVALID, FALSE, STATUS_OBJECT_NAME_INVALID },
388 { NULL, L"C:\\ReactOS\\explorer.exe\\", FALSE, STATUS_OBJECT_NAME_INVALID, FALSE, STATUS_OBJECT_NAME_INVALID },
389 { NULL, L"C:\\ReactOS\\explorer.exe\\file", FALSE, STATUS_OBJECT_PATH_NOT_FOUND, FALSE, STATUS_OBJECT_PATH_NOT_FOUND },
390 { NULL, L"C:\\ReactOS\\explorer.exe\\\\", FALSE, STATUS_OBJECT_NAME_INVALID, TRUE, STATUS_OBJECT_NAME_INVALID },
391 /* This will never return STATUS_NOT_A_DIRECTORY. IsDirectory=TRUE is a little hacky but achieves that without special handling */
392 { NULL, L"C:\\ReactOS\\explorer.exe\\\\\\", TRUE, STATUS_OBJECT_NAME_INVALID, TRUE, STATUS_OBJECT_NAME_INVALID },
393 { L"C:\\", L"", TRUE, STATUS_SUCCESS, TRUE, STATUS_SUCCESS },
395 { L"C:\\", L"ReactOS", TRUE, STATUS_SUCCESS, TRUE, STATUS_SUCCESS },
397 { L"C:\\", L"ReactOS\\", TRUE, STATUS_SUCCESS, TRUE, STATUS_SUCCESS },
399 { L"C:\\ReactOS", L"", TRUE, STATUS_SUCCESS, TRUE, STATUS_SUCCESS },
400 { L"C:\\ReactOS", L"explorer.exe", FALSE, STATUS_SUCCESS, FALSE, STATUS_SUCCESS },
401 { L"C:\\ReactOS\\explorer.exe", L"", FALSE, STATUS_SUCCESS, FALSE, STATUS_SUCCESS },
402 { L"C:\\ReactOS\\explorer.exe", L"file", FALSE, STATUS_OBJECT_PATH_NOT_FOUND, FALSE, STATUS_OBJECT_PATH_NOT_FOUND },
403 /* Let's try some nonexistent things */
405 { NULL, L"C:\\ReactOS\\IDoNotExist\\file", FALSE, STATUS_OBJECT_PATH_NOT_FOUND, FALSE, STATUS_OBJECT_PATH_NOT_FOUND },
406 { NULL, L"C:\\ReactOS\\IDoNotExist\\file?", FALSE, STATUS_OBJECT_PATH_NOT_FOUND, FALSE, STATUS_OBJECT_PATH_NOT_FOUND },
407 { NULL, L"C:\\ReactOS\\IDoNotExist\\file\\\\",TRUE, STATUS_OBJECT_PATH_NOT_FOUND, TRUE, STATUS_OBJECT_NAME_INVALID },
408 { NULL, L"C:\\ReactOS\\IDoNotExist\\file\\\\\\",TRUE,STATUS_OBJECT_PATH_NOT_FOUND, TRUE, STATUS_OBJECT_NAME_INVALID },
409 { NULL, L"C:\\ReactOS\\AmIInvalid?", FALSE, STATUS_OBJECT_NAME_INVALID, FALSE, STATUS_OBJECT_NAME_INVALID },
413 { NULL, L"C:\\ReactOS\\.\\system32", TRUE, STATUS_OBJECT_PATH_NOT_FOUND, TRUE, STATUS_OBJECT_PATH_NOT_FOUND },
414 { NULL, L"C:\\ReactOS\\..\\ReactOS", TRUE, STATUS_OBJECT_PATH_NOT_FOUND, TRUE, STATUS_OBJECT_NAME_INVALID },
423 { L"C:\\ReactOS", L".\\system32", TRUE, STATUS_OBJECT_PATH_NOT_FOUND, TRUE, STATUS_OBJECT_PATH_NOT_FOUND },
424 { L"C:\\ReactOS", L"..\\ReactOS", TRUE, STATUS_OBJECT_PATH_NOT_FOUND, TRUE, STATUS_OBJECT_NAME_INVALID },
425 /* Volume open */
430 };
431
432 ULONG i;
435 UNICODE_STRING ParentPath;
436 UNICODE_STRING RelativePath;
437 HANDLE ParentHandle;
440 HANDLE SymbolicLinkHandle = NULL;
441 WCHAR LinkNameBuffer[128];
443 PWSTR SystemDriveName;
444 PWSTR SystemRootName;
446 BOOLEAN TrailingBackslash;
448 FILE_DISPOSITION_INFORMATION DispositionInfo;
449
450 /* Query \SystemRoot */
452 &SystemRoot,
454 NULL,
455 NULL);
456 Status = ZwOpenSymbolicLinkObject(&SymbolicLinkHandle,
459 if (skip(NT_SUCCESS(Status), "Failed to open SystemRoot, %lx\n", Status))
460 return;
461
462 RtlInitEmptyUnicodeString(&SymbolicLinkName,
463 LinkNameBuffer,
464 sizeof(LinkNameBuffer));
465 Status = ZwQuerySymbolicLinkObject(SymbolicLinkHandle,
467 NULL);
468 ObCloseHandle(SymbolicLinkHandle, KernelMode);
469 if (skip(NT_SUCCESS(Status), "Failed to query SystemRoot, %lx\n", Status))
470 return;
471
472 /* Split SymbolicLinkName into drive and path */
473 SystemDriveName = SymbolicLinkName.Buffer;
474 SystemRootName = SymbolicLinkName.Buffer + SymbolicLinkName.Length / sizeof(WCHAR);
475 *SystemRootName-- = UNICODE_NULL;
476 while (*SystemRootName != L'\\')
477 {
478 ASSERT(SystemRootName > SymbolicLinkName.Buffer);
479 SystemRootName--;
480 }
481 *SystemRootName++ = UNICODE_NULL;
482 trace("System Drive: '%ls'\n", SystemDriveName);
483 trace("System Root: '%ls'\n", SystemRootName);
484
485 /* Allocate path buffer */
487 if (skip(Buffer != NULL, "No buffer\n"))
488 return;
489
490 if (g_Filesystem == Unknown)
491 {
492 trace("Unknown filesystem, running NTFS tests!\n");
493 }
494
495 /* Finally run some tests! */
496 for (i = 0; i < RTL_NUMBER_OF(Tests); i++)
497 {
498 BOOLEAN isDirectory;
499 NTSTATUS expectedStatus;
500
501 if (g_Filesystem == FAT32)
502 {
503 isDirectory = Tests[i].IsDirectory_FAT32;
504 expectedStatus = Tests[i].Status_FAT32;
505 }
506 else /* Default to NTFS */
507 {
508 isDirectory = Tests[i].IsDirectory_NTFS;
509 expectedStatus = Tests[i].Status_NTFS;
510 }
511
512 /* Open parent directory first */
513 ParentHandle = NULL;
514 if (Tests[i].ParentPathTemplate)
515 {
517 MAXUSHORT,
518 Tests[i].ParentPathTemplate,
519 SystemDriveName,
520 SystemRootName);
521 RtlInitUnicodeString(&ParentPath, Buffer);
523 &ParentPath,
525 NULL,
526 NULL);
527 Status = ZwOpenFile(&ParentHandle,
530 &IoStatus,
532 0);
534 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i, Status);
535 if (skip(NT_SUCCESS(Status), "No parent handle %lu\n", i))
536 continue;
537 }
538
539 /* Now open the relative file: */
541 MAXUSHORT,
542 Tests[i].RelativePathTemplate,
543 SystemDriveName,
544 SystemRootName);
545 RtlInitUnicodeString(&RelativePath, Buffer);
547 &RelativePath,
549 ParentHandle,
550 NULL);
551 TrailingBackslash = FALSE;
552 if (wcslen(Buffer) && Buffer[wcslen(Buffer) - 1] == L'\\')
553 TrailingBackslash = TRUE;
554
555 /* (1) No flags */
559 &IoStatus,
561 0);
562 ok(Status == expectedStatus,
563 "[%lu] Status = %lx, expected %lx\n", i, Status, expectedStatus);
564 if (NT_SUCCESS(Status))
566
567 /* (2) Directory File */
571 &IoStatus,
574 if (isDirectory || (!TrailingBackslash && !NT_SUCCESS(expectedStatus)))
575 {
576 ok(Status == expectedStatus,
577 "[%lu] Status = %lx, expected %lx\n", i, Status, expectedStatus);
578 }
579 else
580 {
581 if (g_Filesystem == FAT32)
583 "[%lu] Status = %lx, expected STATUS_NOT_A_DIRECTORY\n", i, Status);
584 else if (g_Filesystem == NTFS)
586 "[%lu] Status = %lx, expected STATUS_NOT_A_DIRECTORY or STATUS_INVALID_PARAMETER\n", i, Status);
587 }
588 if (NT_SUCCESS(Status))
590
591 /* (3) Non-Directory File */
595 &IoStatus,
598 if (isDirectory && NT_SUCCESS(expectedStatus))
600 "[%lu] Status = %lx, expected STATUS_FILE_IS_A_DIRECTORY\n", i, Status);
601 else
602 ok(Status == expectedStatus,
603 "[%lu] Status = %lx, expected %lx\n", i, Status, expectedStatus);
604 if (NT_SUCCESS(Status))
606
607 /* (4) Directory + Non-Directory */
611 &IoStatus,
614 if (expectedStatus == STATUS_OBJECT_NAME_INVALID && Tests[i].IsDrive)
615 {
616 if (g_Filesystem == FAT32)
618 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_INVALID\n", i, Status);
619 else if (g_Filesystem == NTFS)
621 "[%lu] Status = %lx, expected STATUS_INVALID_PARAMETER\n", i, Status);
622 }
623 else
624 {
626 "[%lu] Status = %lx, expected STATUS_INVALID_PARAMETER\n", i, Status);
627 }
628 if (NT_SUCCESS(Status))
630
631 /* (5) Try to create it */
632 AllocationSize.QuadPart = 0;
633 Status = ZwCreateFile(&FileHandle,
636 &IoStatus,
641 0,
642 NULL,
643 0);
644 if (expectedStatus == STATUS_OBJECT_NAME_NOT_FOUND)
646 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i, Status);
647 else if (expectedStatus == STATUS_OBJECT_NAME_INVALID && Tests[i].IsDrive)
649 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_INVALID\n", i, Status);
650 else if (Tests[i].IsDrive)
652 "[%lu] Status = %lx, expected STATUS_ACCESS_DENIED\n", i, Status);
653 else if (expectedStatus == STATUS_SUCCESS)
655 "[%lu] Status = %lx, expected STATUS_OBJECT_NAME_COLLISION or STATUS_ACCESS_DENIED\n", i, Status);
656 else
657 ok(Status == expectedStatus,
658 "[%lu] Status = %lx, expected %lx; %ls -- %ls\n", i, Status, expectedStatus, Tests[i].ParentPathTemplate, Tests[i].RelativePathTemplate);
659 if (NT_SUCCESS(Status))
660 {
661 if (IoStatus.Information == FILE_CREATED)
662 {
663 DispositionInfo.DeleteFile = TRUE;
664 Status = ZwSetInformationFile(FileHandle,
665 &IoStatus,
666 &DispositionInfo,
667 sizeof(DispositionInfo),
670 "[%lu] Status = %lx, expected STATUS_SUCCESS\n", i, Status);
671 }
673 }
674
675 /* And close */
676 ObCloseHandle(ParentHandle, KernelMode);
677 }
678
679 ExFreePoolWithTag(Buffer, 'sFmK');
680}
681
682static
683VOID
685{
687 struct
688 {
689 PCWSTR ParentPath;
690 PCWSTR RelativePath;
691 } Tests[] =
692 {
693 { 0, L"\\SystemRoot\\system32\\drivers\\etc\\hosts" },
694 { L"\\SystemRoot", L"system32\\drivers\\etc\\hosts" },
695 { L"\\SystemRoot\\system32", L"drivers\\etc\\hosts" },
696 { L"\\SystemRoot\\system32\\drivers", L"etc\\hosts" },
697 { L"\\SystemRoot\\system32\\drivers\\etc", L"hosts" },
698 };
701 UNICODE_STRING ParentPath;
702 UNICODE_STRING RelativePath;
703 HANDLE ParentHandle[RTL_NUMBER_OF(Tests)] = { NULL };
706 PFILE_OBJECT SystemRootObject = NULL;
707 UCHAR Buffer[32];
710 ULONG i;
711
712 /* We need an event for ZwReadFile */
714 NULL,
716 NULL,
717 NULL);
718 Status = ZwCreateEvent(&EventHandle,
722 FALSE);
723 if (skip(NT_SUCCESS(Status), "No event\n"))
724 goto Cleanup;
725
726 /* Open all test files and get their FILE_OBJECT pointers */
727 for (i = 0; i < RTL_NUMBER_OF(Tests); i++)
728 {
729 if (Tests[i].ParentPath)
730 {
731 RtlInitUnicodeString(&ParentPath, Tests[i].ParentPath);
733 &ParentPath,
735 NULL,
736 NULL);
737 Status = ZwOpenFile(&ParentHandle[i],
740 &IoStatus,
742 0);
744 if (skip(NT_SUCCESS(Status), "No parent handle %lu\n", i))
745 goto Cleanup;
746 }
747
748 RtlInitUnicodeString(&RelativePath, Tests[i].RelativePath);
750 &RelativePath,
752 ParentHandle[i],
753 NULL);
757 &IoStatus,
759 0);
761 if (skip(NT_SUCCESS(Status), "No file handle %lu\n", i))
762 goto Cleanup;
763
768 (PVOID*)&FileObject[i],
769 NULL);
771 if (skip(NT_SUCCESS(Status), "No file object %lu\n", i))
772 goto Cleanup;
773 }
774
775 /* Also get a file object for the SystemRoot directory */
776 Status = ObReferenceObjectByHandle(ParentHandle[1],
780 (PVOID*)&SystemRootObject,
781 NULL);
783 if (skip(NT_SUCCESS(Status), "No SystemRoot object\n"))
784 goto Cleanup;
785
786 /* Before read, caching is not initialized */
787 ok_eq_pointer(SystemRootObject->SectionObjectPointer, NULL);
788 for (i = 0; i < RTL_NUMBER_OF(Tests); i++)
789 {
790 ok(FileObject[i]->SectionObjectPointer != NULL, "FileObject[%lu]->SectionObjectPointer = NULL\n", i);
792 "FileObject[%lu]->SectionObjectPointer = %p, expected %p\n",
794 }
795 if (!skip(FileObject[0]->SectionObjectPointer != NULL, "No section object pointers\n"))
797
798 /* Perform a read on one handle to initialize caching */
799 FileOffset.QuadPart = 0;
800 Status = ZwReadFile(FileHandle[0],
802 NULL,
803 NULL,
804 &IoStatus,
805 Buffer,
806 sizeof(Buffer),
807 &FileOffset,
808 NULL);
809 if (Status == STATUS_PENDING)
810 {
811 Status = ZwWaitForSingleObject(EventHandle, FALSE, NULL);
813 Status = IoStatus.Status;
814 }
816
817 /* Now we see a SharedCacheMap for the file */
818 ok_eq_pointer(SystemRootObject->SectionObjectPointer, NULL);
819 for (i = 0; i < RTL_NUMBER_OF(Tests); i++)
820 {
821 ok(FileObject[i]->SectionObjectPointer != NULL, "FileObject[%lu]->SectionObjectPointer = NULL\n", i);
823 "FileObject[%lu]->SectionObjectPointer = %p, expected %p\n",
825 }
826 if (!skip(FileObject[0]->SectionObjectPointer != NULL, "No section object pointers\n"))
827 ok(FileObject[0]->SectionObjectPointer->SharedCacheMap != NULL, "SharedCacheMap is NULL\n");
828
829Cleanup:
830 if (SystemRootObject)
831 ObDereferenceObject(SystemRootObject);
832 if (EventHandle)
834 for (i = 0; i < RTL_NUMBER_OF(Tests); i++)
835 {
836 if (FileObject[i])
838 if (FileHandle[i])
840 if (ParentHandle[i])
841 ObCloseHandle(ParentHandle[i], KernelMode);
842 }
843}
844
845START_TEST(IoFilesystem)
846{
847 /* TestAllInformation() has to be first since we detect the filesystem there */
851}
static NTSTATUS QueryFileInfo(_In_ HANDLE FileHandle, _Out_ PVOID *Info, _Inout_ PSIZE_T Length, _In_ FILE_INFORMATION_CLASS FileInformationClass)
Definition: IoFilesystem.c:21
static VOID Substitute(_Out_writes_bytes_(BufferSize) PWCHAR Buffer, _In_ ULONG BufferSize, _In_ PCWSTR Template, _In_ PCWSTR SystemDriveName, _In_ PCWSTR SystemRootName)
Definition: IoFilesystem.c:299
static VOID TestAllInformation(VOID)
Definition: IoFilesystem.c:81
static VOID TestRelativeNames(VOID)
Definition: IoFilesystem.c:361
FSType
Definition: IoFilesystem.c:11
@ NTFS
Definition: IoFilesystem.c:12
@ Unknown
Definition: IoFilesystem.c:14
@ FAT32
Definition: IoFilesystem.c:13
static FSType g_Filesystem
Definition: IoFilesystem.c:17
static VOID TestSharedCacheMap(VOID)
Definition: IoFilesystem.c:684
unsigned char BOOLEAN
struct test_data Tests[]
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define ok_eq_pointer(value, expected)
Definition: apitest.h:116
#define ok_eq_hex(value, expected)
Definition: apitest.h:134
#define ok_eq_size(value, expected)
Definition: apitest.h:126
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
LPWSTR Name
Definition: desk.c:124
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
static const WCHAR SystemRoot[]
Definition: reg.c:38
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
static const WCHAR Cleanup[]
Definition: register.c:80
#define L(x)
Definition: resources.c:13
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define PagedPool
Definition: env_spec_w32.h:308
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:323
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
@ FileEndOfFileInformation
Definition: from_kernel.h:81
@ FileAllInformation
Definition: from_kernel.h:79
@ FileDispositionInformation
Definition: from_kernel.h:74
#define FILE_CREATE
Definition: from_kernel.h:55
enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS
Definition: directory.c:44
struct _FILE_FS_ATTRIBUTE_INFORMATION FILE_FS_ATTRIBUTE_INFORMATION
@ FileFsAttributeInformation
Definition: from_kernel.h:223
_Must_inspect_result_ _In_ PDEVICE_OBJECT _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer
Definition: fsrtlfuncs.h:1369
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:603
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
struct _FILE_ALL_INFORMATION FILE_ALL_INFORMATION
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
VOID KmtFreeGuarded(PVOID Pointer)
BOOLEAN BOOLEAN VOID VOID BOOLEAN BOOLEAN PVOID KmtAllocateGuarded(SIZE_T SizeRequested)
BOOLEAN KmtIsCheckedBuild
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define KernelMode
Definition: asm.h:38
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
NTSYSAPI NTSTATUS NTAPI ZwOpenSymbolicLinkObject(_Out_ PHANDLE SymbolicLinkHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _Out_writes_bytes_(s)
Definition: no_sal2.h:178
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define FILE_CREATED
Definition: nt_native.h:770
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define DELETE
Definition: nt_native.h:57
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define FILE_ALL_ACCESS
Definition: nt_native.h:651
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
static OUT PIO_STATUS_BLOCK OUT PVOID IN ULONG IN FILE_INFORMATION_CLASS FileInformationClass
Definition: pipe.c:75
NTSYSAPI NTSTATUS NTAPI ZwQueryVolumeInformationFile(IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FsInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FsInformationClass)
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:333
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:181
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
FILE_NAME_INFORMATION NameInformation
Definition: winternl.h:1798
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define STATUS_PENDING
Definition: telnetd.h:14
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define MAXUSHORT
Definition: typedefs.h:83
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_FILE_IS_A_DIRECTORY
Definition: udferr_usr.h:164
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING SymbolicLinkName
Definition: wdfdevice.h:3745
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2439
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_Out_ PHANDLE EventHandle
Definition: iofuncs.h:857
* PFILE_OBJECT
Definition: iotypes.h:1998
#define ObDereferenceObject
Definition: obfuncs.h:203
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180