ReactOS  0.4.14-dev-49-gfb4591c
DeviceIoControl.c
Go to the documentation of this file.
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 "precomp.h"
9 
10 #include <winioctl.h>
11 #include <mountdev.h>
12 
16 
17 #define ok_type(condition, format, ...) ok(condition, "(%d): " format, DriveType, ##__VA_ARGS__)
18 #define skip_type(format, ...) skip("(%d): " format, DriveType, ##__VA_ARGS__)
19 
20 static
21 BOOL
23 {
24  UINT Ret;
26  DWORD Size, Error;
27  DISK_GEOMETRY_EX DGE;
28 
29  Size = 0;
30  Ret = DeviceIoControl(Device, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DG, sizeof(DG) - 1, &Size, NULL);
31  ok_type(Ret == 0, "DeviceIoControl succeed\n");
32  Error = GetLastError();
33  ok_type(Error == ERROR_INSUFFICIENT_BUFFER, "Expecting ERROR_INSUFFICIENT_BUFFER, got %ld\n", Error);
34  ok_type(Size == 0, "Invalid output size: %ld\n", Size);
35 
36  Size = 0;
38  /* Specific for CDROM, no disk present */
39  if (Ret == 0 && GetLastError() == ERROR_NOT_READY)
40  {
41  skip_type("No CDROM present\n");
42  return FALSE;
43  }
44  ok_type(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
45  ok_type(Size == sizeof(DG), "Invalid output size: %ld\n", Size);
46 
47  Size = 0;
49  ok_type(Ret == 0, "DeviceIoControl succeed\n");
50  Error = GetLastError();
51  ok_type(Error == ERROR_INSUFFICIENT_BUFFER, "Expecting ERROR_INSUFFICIENT_BUFFER, got %ld\n", Error);
52  ok_type(Size == 0, "Invalid output size: %ld\n", Size);
53 
54  Size = 0;
56  ok_type(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
57  ok_type(Size == FIELD_OFFSET(DISK_GEOMETRY_EX, Data), "Invalid output size: %ld\n", Size);
58 
59  Size = 0;
60  Ret = DeviceIoControl(Device, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &DGE, sizeof(DGE), &Size, NULL);
61  ok_type(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
62  if (DriveType == DRIVE_FIXED)
63  {
64  ok_type(Size == sizeof(DGE), "Invalid output size: %ld\n", Size);
65  }
66  else
67  {
68  ok_type(Size == FIELD_OFFSET(DISK_GEOMETRY_EX, Data), "Invalid output size: %ld\n", Size);
69  }
70 
71  return TRUE;
72 }
73 
74 static
75 VOID
77 {
78  UINT Ret;
79  BOOL IsValid;
80  DWORD Size, Error;
81  MOUNTDEV_NAME MDN, *AllocatedMDN;
82 
83  Size = 0;
84  Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &MDN, sizeof(MDN) - 1, &Size, NULL);
85  ok_type(Ret == 0, "DeviceIoControl succeed\n");
86  Error = GetLastError();
87  if (DriveType == DRIVE_FIXED)
88  {
89  ok_type(Error == ERROR_INVALID_PARAMETER, "Expecting ERROR_INVALID_PARAMETER, got %ld\n", Error);
90  }
91  else
92  {
93  ok_type(Error == ERROR_INSUFFICIENT_BUFFER, "Expecting ERROR_INSUFFICIENT_BUFFER, got %ld\n", Error);
94  }
95  ok_type(Size == 0, "Invalid output size: %ld\n", Size);
96 
97  Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &MDN, sizeof(MDN), &Size, NULL);
98  ok_type(Ret == 0, "DeviceIoControl succeed\n");
99  Error = GetLastError();
100  ok_type(Error == ERROR_MORE_DATA, "Expecting ERROR_MORE_DATA, got %ld\n", Error);
101  ok_type(Size == sizeof(MOUNTDEV_NAME), "Invalid output size: %ld\n", Size);
102 
103  AllocatedMDN = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MOUNTDEV_NAME, Name) + MDN.NameLength + sizeof(UNICODE_NULL));
104  if (AllocatedMDN == NULL)
105  {
106  skip_type("Memory allocation failure\n");
107  return;
108  }
109 
110  Size = 0;
112  ok_type(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
113  ok_type(Size == FIELD_OFFSET(MOUNTDEV_NAME, Name) + MDN.NameLength, "Invalid output size: %ld\n", Size);
114  ok_type(AllocatedMDN->NameLength == MDN.NameLength, "Mismatching sizes: %d %d\n", AllocatedMDN->NameLength, MDN.NameLength);
115 
116  if (Ret != 0)
117  {
118  IsValid = FALSE;
119  AllocatedMDN->Name[AllocatedMDN->NameLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
120 
121  if ((DriveType == DRIVE_FIXED && wcsstr(AllocatedMDN->Name, L"\\Device\\HarddiskVolume") != NULL) ||
122  (DriveType == DRIVE_CDROM && wcsstr(AllocatedMDN->Name, L"\\Device\\CdRom") != NULL))
123  {
124  IsValid = TRUE;
125  }
126  else if (wcsstr(AllocatedMDN->Name, L"\\DosDevices\\") != NULL)
127  {
128  IsValid = (AllocatedMDN->Name[12] == Letter && AllocatedMDN->Name[13] == L':');
129  }
130 
131  ok_type(IsValid, "Invalid name: %.*S\n", AllocatedMDN->NameLength, AllocatedMDN->Name);
132  }
133  else
134  {
135  skip_type("Failed to query device name\n");
136  }
137 
138  HeapFree(GetProcessHeap(), 0, AllocatedMDN);
139 }
140 
141 static
142 VOID
144 {
145  UINT Ret;
146  DWORD Size, Error;
147  MOUNTDEV_UNIQUE_ID MUI, *AllocatedMUI;
148 
149  Size = 0;
150  Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, NULL, 0, &MUI, sizeof(MUI) - 1, &Size, NULL);
151  ok_type(Ret == 0, "DeviceIoControl succeed\n");
152  Error = GetLastError();
153  if (DriveType == DRIVE_FIXED)
154  {
155  ok_type(Error == ERROR_INVALID_PARAMETER, "Expecting ERROR_INVALID_PARAMETER, got %ld\n", Error);
156  }
157  else
158  {
159  ok_type(Error == ERROR_INSUFFICIENT_BUFFER, "Expecting ERROR_INSUFFICIENT_BUFFER, got %ld\n", Error);
160  }
161  ok_type(Size == 0, "Invalid output size: %ld\n", Size);
162 
163  Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, NULL, 0, &MUI, sizeof(MUI), &Size, NULL);
164  ok_type(Ret == 0, "DeviceIoControl succeed\n");
165  Error = GetLastError();
166  ok_type(Error == ERROR_MORE_DATA, "Expecting ERROR_MORE_DATA, got %ld\n", Error);
167  ok_type(Size == sizeof(MOUNTDEV_UNIQUE_ID), "Invalid output size: %ld\n", Size);
168 
169  AllocatedMUI = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + MUI.UniqueIdLength + sizeof(UNICODE_NULL));
170  if (AllocatedMUI == NULL)
171  {
172  skip_type("Memory allocation failure\n");
173  return;
174  }
175 
176  Size = 0;
178  ok_type(Ret != 0, "DeviceIoControl failed: %ld\n", GetLastError());
179  ok_type(Size == FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + MUI.UniqueIdLength, "Invalid output size: %ld\n", Size);
180  ok_type(AllocatedMUI->UniqueIdLength == MUI.UniqueIdLength, "Mismatching sizes: %d %d\n", AllocatedMUI->UniqueIdLength, MUI.UniqueIdLength);
181 
182  HeapFree(GetProcessHeap(), 0, AllocatedMUI);
183 }
184 
185 static
186 VOID
188 {
189  UINT Ret;
190  DWORD Size, Error;
192 
193  Size = 0;
194  Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME, NULL, 0, &MSLN, sizeof(MSLN) - 1, &Size, NULL);
195  ok_type(Ret == 0, "DeviceIoControl succeed\n");
196  Error = GetLastError();
197  if (DriveType == DRIVE_FIXED)
198  {
199  ok_type(Error == ERROR_INVALID_PARAMETER, "Expecting ERROR_INVALID_PARAMETER, got %ld\n", Error);
200  }
201  else
202  {
203  ok_type(Error == ERROR_INSUFFICIENT_BUFFER, "Expecting ERROR_INSUFFICIENT_BUFFER, got %ld\n", Error);
204  }
205  ok_type(Size == 0, "Invalid output size: %ld\n", Size);
206 
207  Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME, NULL, 0, &MSLN, sizeof(MSLN), &Size, NULL);
208  ok_type(Ret == 0, "DeviceIoControl succeed\n");
209  Error = GetLastError();
210  if (DriveType == DRIVE_FIXED)
211  {
212  ok_type(Error == ERROR_NOT_FOUND, "Expecting ERROR_NOT_FOUND, got %ld\n", Error);
213  }
214  else
215  {
216  ok_type(Error == ERROR_FILE_NOT_FOUND, "Expecting ERROR_FILE_NOT_FOUND, got %ld\n", Error);
217  }
218  ok_type(Size == 0, "Invalid output size: %ld\n", Size);
219 }
220 
222 {
223  UINT Ret;
225  DWORD DriveMap, Current;
226  BOOL DiskDone, CdRomDone;
227 
228  DiskDone = FALSE;
229  CdRomDone = FALSE;
230  DriveMap = GetLogicalDrives();
231  for (Current = 0; Current < 26; ++Current)
232  {
233  if (DriveMap & (1 << Current))
234  {
235  Ret = StringCchPrintfW(Path, MAX_PATH, L"%c:\\", Current + L'A');
236  ok(Ret == S_OK, "StringCchPrintfW failed: %d\n", Ret);
237 
239  if ((DriveType == DRIVE_FIXED && !DiskDone) ||
240  (DriveType == DRIVE_CDROM && !CdRomDone))
241  {
242  Ret = StringCchPrintfW(Path, MAX_PATH, L"\\\\?\\%c:", Current + L'A');
243  ok(Ret == S_OK, "StringCchPrintfW failed: %d\n", Ret);
244 
247  {
248  skip_type("CreateFileW for %S failed: %ld\n", Path, GetLastError());
249  continue;
250  }
251 
252  DiskDone = (DiskDone || (DriveType == DRIVE_FIXED));
253  CdRomDone = (CdRomDone || (DriveType == DRIVE_CDROM));
254 
255  if (GetDiskGeometry())
256  {
257  QueryDeviceName();
258  QueryUniqueId();
260  }
261 
263  }
264 
265  if (CdRomDone && DiskDone)
266  {
267  break;
268  }
269  }
270  }
271 
272  if (!DiskDone)
273  {
274  skip("No disk drive found\n");
275  }
276 
277  if (!CdRomDone)
278  {
279  skip("No CDROM drive found\n");
280  }
281 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
Definition: ntddk_ex.h:208
START_TEST(DeviceIoControl)
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
#define ok_type(condition, format,...)
static VOID QuerySuggestedLinkName(VOID)
USHORT UniqueIdLength
Definition: imports.h:138
#define skip_type(format,...)
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
UINT DriveType
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_SHARE_READ
Definition: compat.h:125
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
HANDLE Device
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:80
#define UNICODE_NULL
unsigned int BOOL
Definition: ntddk_ex.h:94
smooth NULL
Definition: ftsmooth.c:416
#define ERROR_NOT_READY
Definition: winerror.h:124
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define OPEN_EXISTING
Definition: compat.h:426
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR Name[1]
Definition: imports.h:144
static VOID QueryDeviceName(VOID)
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL Error
Definition: chkdsk.c:66
static VOID QueryUniqueId(VOID)
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
static const WCHAR L[]
Definition: oid.c:1250
WCHAR Letter
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
#define ERROR_MORE_DATA
Definition: dderror.h:13
TW_UINT32 DG
Definition: twain.h:1827
#define DRIVE_FIXED
Definition: winbase.h:249
DWORD WINAPI GetLogicalDrives(VOID)
Definition: disk.c:110
#define S_OK
Definition: intsafe.h:59
PRTL_UNICODE_STRING_BUFFER Path
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:99
static BOOL GetDiskGeometry(VOID)
#define ok(value,...)
Definition: atltest.h:57
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
#define DRIVE_CDROM
Definition: winbase.h:251
unsigned int UINT
Definition: ndis.h:50
USHORT NameLength
Definition: imports.h:143
#define ERROR_NOT_FOUND
Definition: winerror.h:690
#define CreateFileW
Definition: compat.h:400
#define skip(...)
Definition: atltest.h:64
#define HeapFree(x, y, z)
Definition: compat.h:394
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10