ed1c6f7fa3a4dae0955c35d37a4479daaf1a36aa
[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 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &MDN, sizeof(MDN) - 1, &Size, NULL);
66 ok(Ret == 0, "DeviceIoControl succeed\n");
67 Error = GetLastError();
68 ok(Error == ERROR_INVALID_PARAMETER, "Expecting ERROR_INVALID_PARAMETER, got %ld\n", Error);
69 ok(Size == 40 /* ?! */, "Invalid output size: %ld\n", Size);
70
71 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &MDN, sizeof(MDN), &Size, NULL);
72 ok(Ret == 0, "DeviceIoControl succeed\n");
73 Error = GetLastError();
74 ok(Error == ERROR_MORE_DATA, "Expecting ERROR_MORE_DATA, got %ld\n", Error);
75 ok(Size == sizeof(MOUNTDEV_NAME), "Invalid output size: %ld\n", Size);
76
77 AllocatedMDN = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MOUNTDEV_NAME, Name) + MDN.NameLength + sizeof(UNICODE_NULL));
78 if (AllocatedMDN == NULL)
79 {
80 skip("Memory allocation failure\n");
81 return;
82 }
83
84 Size = 0;
85 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, AllocatedMDN, FIELD_OFFSET(MOUNTDEV_NAME, Name) + MDN.NameLength, &Size, NULL);
86 ok(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
87 ok(Size == FIELD_OFFSET(MOUNTDEV_NAME, Name) + MDN.NameLength, "Invalid output size: %ld\n", Size);
88 ok(AllocatedMDN->NameLength == MDN.NameLength, "Mismatching sizes: %d %d\n", AllocatedMDN->NameLength, MDN.NameLength);
89
90 if (Ret != 0)
91 {
92 IsValid = FALSE;
93 AllocatedMDN->Name[AllocatedMDN->NameLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
94
95 if (wcsstr(AllocatedMDN->Name, L"\\Device\\HarddiskVolume") != NULL)
96 {
97 IsValid = TRUE;
98 }
99 else if (wcsstr(AllocatedMDN->Name, L"\\DosDevices\\") != NULL)
100 {
101 IsValid = (AllocatedMDN->Name[12] == Letter && AllocatedMDN->Name[13] == L':');
102 }
103
104 ok(IsValid, "Invalid name: %.*S", AllocatedMDN->NameLength, AllocatedMDN->Name);
105 }
106 else
107 {
108 skip("Failed to query device name\n");
109 }
110
111 HeapFree(GetProcessHeap(), 0, AllocatedMDN);
112 }
113
114 static
115 VOID
116 QueryUniqueId(VOID)
117 {
118 UINT Ret;
119 DWORD Size, Error;
120 MOUNTDEV_UNIQUE_ID MUI, *AllocatedMUI;
121
122 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, NULL, 0, &MUI, sizeof(MUI) - 1, &Size, NULL);
123 ok(Ret == 0, "DeviceIoControl succeed\n");
124 Error = GetLastError();
125 ok(Error == ERROR_INVALID_PARAMETER, "Expecting ERROR_INVALID_PARAMETER, got %ld\n", Error);
126 ok(Size == 48 /* ?! */, "Invalid output size: %ld\n", Size);
127
128 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, NULL, 0, &MUI, sizeof(MUI), &Size, NULL);
129 ok(Ret == 0, "DeviceIoControl succeed\n");
130 Error = GetLastError();
131 ok(Error == ERROR_MORE_DATA, "Expecting ERROR_MORE_DATA, got %ld\n", Error);
132 ok(Size == sizeof(MOUNTDEV_UNIQUE_ID), "Invalid output size: %ld\n", Size);
133
134 AllocatedMUI = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + MUI.UniqueIdLength + sizeof(UNICODE_NULL));
135 if (AllocatedMUI == NULL)
136 {
137 skip("Memory allocation failure\n");
138 return;
139 }
140
141 Size = 0;
142 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, NULL, 0, AllocatedMUI, FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + MUI.UniqueIdLength, &Size, NULL);
143 ok(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
144 ok(Size == FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + MUI.UniqueIdLength, "Invalid output size: %ld\n", Size);
145 ok(AllocatedMUI->UniqueIdLength == MUI.UniqueIdLength, "Mismatching sizes: %d %d\n", AllocatedMUI->UniqueIdLength, MUI.UniqueIdLength);
146
147 HeapFree(GetProcessHeap(), 0, AllocatedMUI);
148 }
149
150 START_TEST(DeviceIoControl)
151 {
152 UINT Ret;
153 WCHAR Path[MAX_PATH];
154
155 Path[0] = 'C';
156 Path[1] = ':';
157 Path[2] = '\\';
158 Ret = GetSystemDirectoryW(Path, MAX_PATH);
159 ok(Ret > 0, "GetSystemDirectory failed\n");
160
161 Letter = towupper(Path[0]);
162 ok(Path[1] == ':', "Not a drive letter: %c\n", Path[1]);
163 ok(Path[2] == '\\', "Not a drive letter: %c\n", Path[2]);
164
165 Ret = StringCchPrintfW(Path, MAX_PATH, L"\\\\?\\%c:", Letter);
166 ok(Ret == S_OK, "StringCchPrintfW failed: %d\n", Ret);
167
168 Device = CreateFileW(Path, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
169 if (Device == INVALID_HANDLE_VALUE)
170 {
171 skip("CreateFileW for %S failed: %ld\n", Path, GetLastError());
172 return;
173 }
174
175 GetDiskGeometry();
176 QueryDeviceName();
177 QueryUniqueId();
178
179 CloseHandle(Device);
180 }