1 /*
2  * PROJECT:     ReactOS kernel-mode tests
3  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:     Kernel-Mode Test Suite Volume Device test
5  * COPYRIGHT:   Copyright 2019 Thomas Faber (thomas.faber@reactos.org)
6  */
7 
8 #include <kmt_test.h>
9 
10 static
11 NTSTATUS
12 GetNextVolumeDevice(
13     _Inout_ PUNICODE_STRING VolumeDeviceName,
14     _Inout_ PULONG VolumeNumber,
15     _In_ NTSTATUS PreviousStatus)
16 {
17     NTSTATUS Status;
18 
19 #ifndef __REACTOS__
20     *VolumeNumber++;
21     Status = RtlStringCbPrintfW(VolumeDeviceName->Buffer,
22                                 VolumeDeviceName->MaximumLength,
23                                 L"\\Device\\HarddiskVolume%lu",
24                                 *VolumeNumber);
25 #else
26     /* ROS's storage stack is old an broken, we don't have HarddiskVolumeN */
27     ULONG DiskNumber, PartitionNumber;
28     DiskNumber = *VolumeNumber >> 16;
29     PartitionNumber = *VolumeNumber & 0xffff;
30     if (!NT_SUCCESS(PreviousStatus))
31     {
32         if (PartitionNumber == 1)
33         {
34             /* Looks like this disk doesn't exist (or has no partitions),
35              * so we're done */
36             return STATUS_NO_MORE_ENTRIES;
37         }
38         DiskNumber++;
39         PartitionNumber = 0;
40     }
41     PartitionNumber++;
42     Status = RtlStringCbPrintfW(VolumeDeviceName->Buffer,
43                                 VolumeDeviceName->MaximumLength,
44                                 L"\\Device\\Harddisk%lu\\Partition%lu",
45                                 DiskNumber,
46                                 PartitionNumber);
47     *VolumeNumber = DiskNumber << 16 | PartitionNumber;
48 #endif
49     return Status;
50 }
51 
52 static
53 void
54 TestIoVolumeDeviceToDosName(void)
55 {
56     NTSTATUS Status;
57     ULONG VolumeNumber;
58     WCHAR VolumeDeviceNameBuffer[32];
59     UNICODE_STRING VolumeDeviceName;
60     PFILE_OBJECT FileObject;
61     PDEVICE_OBJECT DeviceObject;
62     UNICODE_STRING DosName;
63     UNICODE_STRING DosVolumePrefix = RTL_CONSTANT_STRING(L"\\\\?\\Volume");
64 
65     RtlInitEmptyUnicodeString(&VolumeDeviceName,
66                               VolumeDeviceNameBuffer,
67                               sizeof(VolumeDeviceNameBuffer));
68     VolumeNumber = 0;
69     Status = STATUS_SUCCESS;
70     while (1)
71     {
72         Status = GetNextVolumeDevice(&VolumeDeviceName,
73                                      &VolumeNumber,
74                                      Status);
75         if (!NT_SUCCESS(Status))
76         {
77             trace("GetNextVolumeDevice(0x%lx) failed with %lx\n",
78                   VolumeNumber, Status);
79             break;
80         }
81 
82         RtlInitUnicodeString(&VolumeDeviceName, VolumeDeviceNameBuffer);
83         Status = IoGetDeviceObjectPointer(&VolumeDeviceName,
84                                           READ_CONTROL,
85                                           &FileObject,
86                                           &DeviceObject);
87         if (!NT_SUCCESS(Status))
88         {
89             trace("IoGetDeviceObjectPointer(%wZ) failed with %lx\n",
90                   &VolumeDeviceName, Status);
91             continue;
92         }
93 
94         Status = IoVolumeDeviceToDosName(DeviceObject, &DosName);
95         ok_eq_hex(Status, STATUS_SUCCESS);
96         if (!skip(NT_SUCCESS(Status), "No DOS name\n"))
97         {
98             trace("DOS name for %wZ is %wZ\n", &VolumeDeviceName, &DosName);
99             if (DosName.Length == 2 * sizeof(WCHAR))
100             {
101                 ok(DosName.Buffer[0] >= L'A' &&
102                    DosName.Buffer[0] <= L'Z' &&
103                    DosName.Buffer[1] == L':',
104                    "Unexpected drive letter: %wZ\n", &DosName);
105             }
106             else
107             {
108                 ok(RtlPrefixUnicodeString(&DosVolumePrefix, &DosName, FALSE),
109                    "Unexpected volume path: %wZ\n", &DosName);
110             }
111             RtlFreeUnicodeString(&DosName);
112         }
113         ObDereferenceObject(FileObject);
114         Status = STATUS_SUCCESS;
115     }
116     ok(VolumeNumber > 1, "No volumes found\n");
117 }
118 
119 START_TEST(IoVolume)
120 {
121     TestIoVolumeDeviceToDosName();
122 }
123