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 #include <mountmgr.h>
10 
11 static
12 void
TestIoVolumeDeviceToDosName(void)13 TestIoVolumeDeviceToDosName(void)
14 {
15     NTSTATUS Status;
16     ULONG VolumeNumber;
17     WCHAR VolumeDeviceNameBuffer[32];
18     UNICODE_STRING VolumeDeviceName;
19     PFILE_OBJECT FileObject;
20     PDEVICE_OBJECT DeviceObject;
21     UNICODE_STRING DosName;
22     UNICODE_STRING DosVolumePrefix = RTL_CONSTANT_STRING(L"\\\\?\\Volume");
23 
24     RtlInitEmptyUnicodeString(&VolumeDeviceName,
25                               VolumeDeviceNameBuffer,
26                               sizeof(VolumeDeviceNameBuffer));
27     // TODO: Query the partition/volume manager for the list of volumes.
28     for (VolumeNumber = 0; VolumeNumber < 32; ++VolumeNumber)
29     {
30         Status = RtlStringCbPrintfW(VolumeDeviceName.Buffer,
31                                     VolumeDeviceName.MaximumLength,
32                                     L"\\Device\\HarddiskVolume%lu",
33                                     VolumeNumber);
34         if (!NT_SUCCESS(Status))
35         {
36             trace("RtlStringCbPrintfW(%lu) failed with 0x%lx\n",
37                   VolumeNumber, Status);
38             break;
39         }
40 
41         RtlInitUnicodeString(&VolumeDeviceName, VolumeDeviceNameBuffer);
42         Status = IoGetDeviceObjectPointer(&VolumeDeviceName,
43                                           READ_CONTROL,
44                                           &FileObject,
45                                           &DeviceObject);
46         if (!NT_SUCCESS(Status))
47         {
48             trace("IoGetDeviceObjectPointer(%wZ) failed with 0x%lx\n",
49                   &VolumeDeviceName, Status);
50             continue;
51         }
52 
53         Status = IoVolumeDeviceToDosName(DeviceObject, &DosName);
54         ok_eq_hex(Status, STATUS_SUCCESS);
55         if (!skip(NT_SUCCESS(Status), "No DOS name\n"))
56         {
57             trace("DOS name for %wZ is %wZ\n", &VolumeDeviceName, &DosName);
58 
59             /* The DosName should contain one NUL-terminated string (always there?),
60              * plus one final NUL-terminator */
61             ok(DosName.MaximumLength == DosName.Length + sizeof(UNICODE_NULL),
62                "Unexpected DOS name maximum length %hu, expected %hu\n",
63                DosName.MaximumLength, DosName.Length + sizeof(UNICODE_NULL));
64             ok(DosName.Length >= sizeof(UNICODE_NULL),
65                "DOS name too short (length: %lu)\n",
66                DosName.Length / sizeof(WCHAR));
67             ok(DosName.Buffer[DosName.Length / sizeof(WCHAR)] == UNICODE_NULL,
68                "Missing NUL-terminator (1)\n");
69             ok(DosName.Buffer[DosName.MaximumLength / sizeof(WCHAR) - 1] == UNICODE_NULL,
70                "Missing NUL-terminator (2)\n");
71 
72             /* The DOS name is either a drive letter, or a
73              * volume GUID name (if the volume is not mounted) */
74             if (DosName.Length == 2 * sizeof(WCHAR))
75             {
76                 ok(DosName.Buffer[0] >= L'A' &&
77                    DosName.Buffer[0] <= L'Z' &&
78                    DosName.Buffer[1] == L':',
79                    "Unexpected drive letter: %wZ\n", &DosName);
80             }
81             else
82             {
83                 ok(RtlPrefixUnicodeString(&DosVolumePrefix, &DosName, FALSE),
84                    "Unexpected volume path: %wZ\n", &DosName);
85                 ok(MOUNTMGR_IS_DOS_VOLUME_NAME(&DosName),
86                    "Invalid DOS volume path returned: %wZ\n", &DosName);
87             }
88             RtlFreeUnicodeString(&DosName);
89         }
90         ObDereferenceObject(FileObject);
91     }
92     ok(VolumeNumber > 1, "No volumes found\n");
93 }
94 
START_TEST(IoVolume)95 START_TEST(IoVolume)
96 {
97     TestIoVolumeDeviceToDosName();
98 }
99