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 13 WCHAR Letter; 14 HANDLE Device; 15 UINT DriveType; 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 22 GetDiskGeometry(VOID) 23 { 24 UINT Ret; 25 DISK_GEOMETRY DG; 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; 37 Ret = DeviceIoControl(Device, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DG, sizeof(DG), &Size, NULL); 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; 48 Ret = DeviceIoControl(Device, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &DGE, FIELD_OFFSET(DISK_GEOMETRY_EX, Data) - 1, &Size, NULL); 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; 55 Ret = DeviceIoControl(Device, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &DGE, FIELD_OFFSET(DISK_GEOMETRY_EX, Data), &Size, NULL); 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 76 QueryDeviceName(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; 111 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, AllocatedMDN, FIELD_OFFSET(MOUNTDEV_NAME, Name) + MDN.NameLength, &Size, NULL); 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 143 QueryUniqueId(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; 177 Ret = DeviceIoControl(Device, IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, NULL, 0, AllocatedMUI, FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + MUI.UniqueIdLength, &Size, NULL); 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 187 QuerySuggestedLinkName(VOID) 188 { 189 UINT Ret; 190 DWORD Size, Error; 191 MOUNTDEV_SUGGESTED_LINK_NAME MSLN; 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 221 START_TEST(DeviceIoControl) 222 { 223 UINT Ret; 224 WCHAR Path[MAX_PATH]; 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 238 DriveType = GetDriveTypeW(Path); 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 245 Device = CreateFileW(Path, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 246 if (Device == INVALID_HANDLE_VALUE) 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(); 259 QuerySuggestedLinkName(); 260 } 261 262 CloseHandle(Device); 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 } 282