1 /*
2  * PROJECT:     ReactOS API Tests
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Test for IOCTL_MOUNTMGR_QUERY_POINTS
5  * COPYRIGHT:   Copyright 2019 Pierre Schweitzer <pierre@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 VOID
TraceMountPoint(_In_ const MOUNTMGR_MOUNT_POINTS * MountPoints,_In_ const MOUNTMGR_MOUNT_POINT * MountPoint)11 TraceMountPoint(
12     _In_ const MOUNTMGR_MOUNT_POINTS* MountPoints,
13     _In_ const MOUNTMGR_MOUNT_POINT* MountPoint)
14 {
15     trace("MountPoint: %p\n", MountPoint);
16     trace("\tSymbolicOffset: %ld\n", MountPoint->SymbolicLinkNameOffset);
17     trace("\tSymbolicLinkName: %.*S\n",
18           MountPoint->SymbolicLinkNameLength / sizeof(WCHAR),
19           (PWCHAR)((ULONG_PTR)MountPoints + MountPoint->SymbolicLinkNameOffset));
20     trace("\tDeviceOffset: %ld\n", MountPoint->DeviceNameOffset);
21     trace("\tDeviceName: %.*S\n",
22           MountPoint->DeviceNameLength / sizeof(WCHAR),
23           (PWCHAR)((ULONG_PTR)MountPoints + MountPoint->DeviceNameOffset));
24 }
25 
START_TEST(QueryPoints)26 START_TEST(QueryPoints)
27 {
28     BOOL Ret;
29     HANDLE MountMgrHandle;
30     DWORD LastError, BytesReturned, Drives, i;
31     struct
32     {
33         MOUNTMGR_MOUNT_POINT;
34         WCHAR Buffer[sizeof("\\DosDevice\\A:")];
35     } SinglePoint;
36     MOUNTMGR_MOUNT_POINTS MountPoints;
37     PMOUNTMGR_MOUNT_POINTS AllocatedPoints;
38 
39     MountMgrHandle = GetMountMgrHandle(FILE_READ_ATTRIBUTES);
40     if (!MountMgrHandle)
41     {
42         win_skip("MountMgr unavailable: %lu\n", GetLastError());
43         return;
44     }
45 
46     ZeroMemory(&SinglePoint, sizeof(SinglePoint));
47 
48     /* Retrieve the size needed to enumerate all the existing mount points */
49     Ret = DeviceIoControl(MountMgrHandle, IOCTL_MOUNTMGR_QUERY_POINTS,
50                           &SinglePoint, sizeof(MOUNTMGR_MOUNT_POINT), // Size without the string.
51                           &MountPoints, sizeof(MountPoints),
52                           &BytesReturned, NULL);
53     LastError = GetLastError();
54     ok(Ret == FALSE, "IOCTL unexpectedly succeeded\n");
55     ok(LastError == ERROR_MORE_DATA, "Unexpected failure: %lu\n", LastError);
56 
57     /* Allocate a suitably-sized buffer for the mount points */
58     AllocatedPoints = RtlAllocateHeap(RtlGetProcessHeap(), 0, MountPoints.Size);
59     if (AllocatedPoints == NULL)
60     {
61         skip("Insufficient memory\n");
62     }
63     else
64     {
65         AllocatedPoints->NumberOfMountPoints = 0;
66 
67         /* Retrieve the list of all the existing mount points */
68         Ret = DeviceIoControl(MountMgrHandle, IOCTL_MOUNTMGR_QUERY_POINTS,
69                               &SinglePoint, sizeof(MOUNTMGR_MOUNT_POINT), // Size without the string.
70                               AllocatedPoints, MountPoints.Size,
71                               &BytesReturned, NULL);
72         ok(Ret == TRUE, "IOCTL unexpectedly failed: %lu\n", GetLastError());
73 
74         for (i = 0; i < AllocatedPoints->NumberOfMountPoints; ++i)
75         {
76             TraceMountPoint(AllocatedPoints, &AllocatedPoints->MountPoints[i]);
77         }
78 
79         RtlFreeHeap(RtlGetProcessHeap(), 0, AllocatedPoints);
80     }
81 
82     /* Now, find the first unused drive letter */
83     Drives = GetLogicalDrives();
84     if (Drives == 0)
85     {
86         skip("Drives map unavailable: %lu\n", GetLastError());
87         goto Done;
88     }
89     for (i = 0; i <= 'Z'-'A'; ++i)
90     {
91         if (!(Drives & (1 << i)))
92             break;
93     }
94     if (i > 'Z'-'A')
95     {
96         skip("All the drive letters are in use, skipping\n");
97         goto Done;
98     }
99 
100     /* Check that this drive letter is not an existing mount point */
101     SinglePoint.SymbolicLinkNameOffset = ((ULONG_PTR)&SinglePoint.Buffer - (ULONG_PTR)&SinglePoint);
102     SinglePoint.SymbolicLinkNameLength = sizeof(SinglePoint.Buffer) - sizeof(UNICODE_NULL);
103     StringCbPrintfW(SinglePoint.Buffer, sizeof(SinglePoint.Buffer),
104                     L"\\DosDevice\\%C:", L'A' + i);
105 
106     Ret = DeviceIoControl(MountMgrHandle, IOCTL_MOUNTMGR_QUERY_POINTS,
107                           &SinglePoint, sizeof(SinglePoint),
108                           &MountPoints, sizeof(MountPoints),
109                           &BytesReturned, NULL);
110     LastError = GetLastError();
111     ok(Ret == FALSE, "IOCTL unexpectedly succeeded\n");
112     ok(LastError == ERROR_FILE_NOT_FOUND, "Unexpected failure: %lu\n", LastError);
113 
114 Done:
115     CloseHandle(MountMgrHandle);
116 }
117