2f993eb25e21d0ee4a5e57320a6477946cd9b99d
[reactos.git] / modules / rostests / apitests / kernel32 / DeviceIoControl.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for DeviceIoControl
5 * PROGRAMMER: Pierre Schweitzer <pierre@reactos.org>
6 */
7
8 #include <apitest.h>
9 #include <strsafe.h>
10 #include <winioctl.h>
11 #include <mountmgr.h>
12 #include <mountdev.h>
13
14 WCHAR Letter;
15 HANDLE Device;
16
17 static
18 VOID
19 GetDiskGeometry(VOID)
20 {
21 UINT Ret;
22 DISK_GEOMETRY DG;
23 DWORD Size, Error;
24 DISK_GEOMETRY_EX DGE;
25
26 Size = 0;
27 Ret = DeviceIoControl(Device, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DG, sizeof(DG) - 1, &Size, NULL);
28 ok(Ret == 0, "DeviceIoControl succeed\n");
29 Error = GetLastError();
30 ok(Error == ERROR_INSUFFICIENT_BUFFER, "Expecting ERROR_INSUFFICIENT_BUFFER, got %ld\n", Error);
31 ok(Size == 0, "Invalid output size: %ld\n", Size);
32
33 Size = 0;
34 Ret = DeviceIoControl(Device, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DG, sizeof(DG), &Size, NULL);
35 ok(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
36 ok(Size == sizeof(DG), "Invalid output size: %ld\n", Size);
37
38 Size = 0;
39 Ret = DeviceIoControl(Device, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &DGE, FIELD_OFFSET(DISK_GEOMETRY_EX, Data) - 1, &Size, NULL);
40 ok(Ret == 0, "DeviceIoControl succeed\n");
41 Error = GetLastError();
42 ok(Error == ERROR_INSUFFICIENT_BUFFER, "Expecting ERROR_INSUFFICIENT_BUFFER, got %ld\n", Error);
43 ok(Size == 0, "Invalid output size: %ld\n", Size);
44
45 Size = 0;
46 Ret = DeviceIoControl(Device, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &DGE, FIELD_OFFSET(DISK_GEOMETRY_EX, Data), &Size, NULL);
47 ok(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
48 ok(Size == FIELD_OFFSET(DISK_GEOMETRY_EX, Data), "Invalid output size: %ld\n", Size);
49
50 Size = 0;
51 Ret = DeviceIoControl(Device, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &DGE, sizeof(DGE), &Size, NULL);
52 ok(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
53 ok(Size == sizeof(DGE), "Invalid output size: %ld\n", Size);
54 }
55
56 static
57 VOID
58 QueryDeviceName(VOID)
59 {
60 UINT Ret;
61 BOOL IsValid;
62 DWORD Size, Error;
63 MOUNTDEV_NAME MDN, *AllocatedMDN;
64
65 Size = 0;
66 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &MDN, sizeof(MDN) - 1, &Size, NULL);
67 ok(Ret == 0, "DeviceIoControl succeed\n");
68 Error = GetLastError();
69 ok(Error == ERROR_INVALID_PARAMETER, "Expecting ERROR_INVALID_PARAMETER, got %ld\n", Error);
70 ok(Size == 0, "Invalid output size: %ld\n", Size);
71
72 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &MDN, sizeof(MDN), &Size, NULL);
73 ok(Ret == 0, "DeviceIoControl succeed\n");
74 Error = GetLastError();
75 ok(Error == ERROR_MORE_DATA, "Expecting ERROR_MORE_DATA, got %ld\n", Error);
76 ok(Size == sizeof(MOUNTDEV_NAME), "Invalid output size: %ld\n", Size);
77
78 AllocatedMDN = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MOUNTDEV_NAME, Name) + MDN.NameLength + sizeof(UNICODE_NULL));
79 if (AllocatedMDN == NULL)
80 {
81 skip("Memory allocation failure\n");
82 return;
83 }
84
85 Size = 0;
86 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, AllocatedMDN, FIELD_OFFSET(MOUNTDEV_NAME, Name) + MDN.NameLength, &Size, NULL);
87 ok(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
88 ok(Size == FIELD_OFFSET(MOUNTDEV_NAME, Name) + MDN.NameLength, "Invalid output size: %ld\n", Size);
89 ok(AllocatedMDN->NameLength == MDN.NameLength, "Mismatching sizes: %d %d\n", AllocatedMDN->NameLength, MDN.NameLength);
90
91 if (Ret != 0)
92 {
93 IsValid = FALSE;
94 AllocatedMDN->Name[AllocatedMDN->NameLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
95
96 if (wcsstr(AllocatedMDN->Name, L"\\Device\\HarddiskVolume") != NULL)
97 {
98 IsValid = TRUE;
99 }
100 else if (wcsstr(AllocatedMDN->Name, L"\\DosDevices\\") != NULL)
101 {
102 IsValid = (AllocatedMDN->Name[12] == Letter && AllocatedMDN->Name[13] == L':');
103 }
104
105 ok(IsValid, "Invalid name: %.*S", AllocatedMDN->NameLength, AllocatedMDN->Name);
106 }
107 else
108 {
109 skip("Failed to query device name\n");
110 }
111
112 HeapFree(GetProcessHeap(), 0, AllocatedMDN);
113 }
114
115 static
116 VOID
117 QueryUniqueId(VOID)
118 {
119 UINT Ret;
120 DWORD Size, Error;
121 MOUNTDEV_UNIQUE_ID MUI, *AllocatedMUI;
122
123 Size = 0;
124 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, NULL, 0, &MUI, sizeof(MUI) - 1, &Size, NULL);
125 ok(Ret == 0, "DeviceIoControl succeed\n");
126 Error = GetLastError();
127 ok(Error == ERROR_INVALID_PARAMETER, "Expecting ERROR_INVALID_PARAMETER, got %ld\n", Error);
128 ok(Size == 0, "Invalid output size: %ld\n", Size);
129
130 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, NULL, 0, &MUI, sizeof(MUI), &Size, NULL);
131 ok(Ret == 0, "DeviceIoControl succeed\n");
132 Error = GetLastError();
133 ok(Error == ERROR_MORE_DATA, "Expecting ERROR_MORE_DATA, got %ld\n", Error);
134 ok(Size == sizeof(MOUNTDEV_UNIQUE_ID), "Invalid output size: %ld\n", Size);
135
136 AllocatedMUI = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + MUI.UniqueIdLength + sizeof(UNICODE_NULL));
137 if (AllocatedMUI == NULL)
138 {
139 skip("Memory allocation failure\n");
140 return;
141 }
142
143 Size = 0;
144 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, NULL, 0, AllocatedMUI, FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + MUI.UniqueIdLength, &Size, NULL);
145 ok(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
146 ok(Size == FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + MUI.UniqueIdLength, "Invalid output size: %ld\n", Size);
147 ok(AllocatedMUI->UniqueIdLength == MUI.UniqueIdLength, "Mismatching sizes: %d %d\n", AllocatedMUI->UniqueIdLength, MUI.UniqueIdLength);
148
149 HeapFree(GetProcessHeap(), 0, AllocatedMUI);
150 }
151
152 START_TEST(DeviceIoControl)
153 {
154 UINT Ret;
155 WCHAR Path[MAX_PATH];
156
157 Path[0] = 'C';
158 Path[1] = ':';
159 Path[2] = '\\';
160 Ret = GetSystemDirectoryW(Path, MAX_PATH);
161 ok(Ret > 0, "GetSystemDirectory failed\n");
162
163 Letter = towupper(Path[0]);
164 ok(Path[1] == ':', "Not a drive letter: %c\n", Path[1]);
165 ok(Path[2] == '\\', "Not a drive letter: %c\n", Path[2]);
166
167 Ret = StringCchPrintfW(Path, MAX_PATH, L"\\\\?\\%c:", Letter);
168 ok(Ret == S_OK, "StringCchPrintfW failed: %d\n", Ret);
169
170 Device = CreateFileW(Path, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
171 if (Device == INVALID_HANDLE_VALUE)
172 {
173 skip("CreateFileW for %S failed: %ld\n", Path, GetLastError());
174 return;
175 }
176
177 GetDiskGeometry();
178 QueryDeviceName();
179 QueryUniqueId();
180
181 CloseHandle(Device);
182 }