1 /* 2 * Devinst tests 3 * 4 * Copyright 2006 Christian Gmeiner 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 #include <stdio.h> 23 24 #include "windef.h" 25 #include "winbase.h" 26 #include "wingdi.h" 27 #include "winuser.h" 28 #include "winreg.h" 29 #include "guiddef.h" 30 #include "setupapi.h" 31 32 #include "wine/test.h" 33 34 static BOOL is_wow64; 35 36 /* function pointers */ 37 static HDEVINFO (WINAPI *pSetupDiCreateDeviceInfoList)(GUID*,HWND); 38 static HDEVINFO (WINAPI *pSetupDiCreateDeviceInfoListExW)(GUID*,HWND,PCWSTR,PVOID); 39 static BOOL (WINAPI *pSetupDiCreateDeviceInterfaceA)(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, PCSTR, DWORD, PSP_DEVICE_INTERFACE_DATA); 40 static BOOL (WINAPI *pSetupDiCallClassInstaller)(DI_FUNCTION, HDEVINFO, PSP_DEVINFO_DATA); 41 static BOOL (WINAPI *pSetupDiDestroyDeviceInfoList)(HDEVINFO); 42 static BOOL (WINAPI *pSetupDiEnumDeviceInfo)(HDEVINFO, DWORD, PSP_DEVINFO_DATA); 43 static BOOL (WINAPI *pSetupDiEnumDeviceInterfaces)(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, DWORD, PSP_DEVICE_INTERFACE_DATA); 44 static BOOL (WINAPI *pSetupDiGetINFClassA)(PCSTR, LPGUID, PSTR, DWORD, PDWORD); 45 static BOOL (WINAPI *pSetupDiInstallClassA)(HWND, PCSTR, DWORD, HSPFILEQ); 46 static HKEY (WINAPI *pSetupDiOpenClassRegKeyExA)(GUID*,REGSAM,DWORD,PCSTR,PVOID); 47 static HKEY (WINAPI *pSetupDiOpenDevRegKey)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM); 48 static HKEY (WINAPI *pSetupDiCreateDevRegKeyW)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, HINF, PCWSTR); 49 static BOOL (WINAPI *pSetupDiCreateDeviceInfoA)(HDEVINFO, PCSTR, GUID *, PCSTR, HWND, DWORD, PSP_DEVINFO_DATA); 50 static BOOL (WINAPI *pSetupDiCreateDeviceInfoW)(HDEVINFO, PCWSTR, GUID *, PCWSTR, HWND, DWORD, PSP_DEVINFO_DATA); 51 static BOOL (WINAPI *pSetupDiGetDeviceInstanceIdA)(HDEVINFO, PSP_DEVINFO_DATA, PSTR, DWORD, PDWORD); 52 static BOOL (WINAPI *pSetupDiGetDeviceInterfaceDetailA)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA); 53 static BOOL (WINAPI *pSetupDiGetDeviceInterfaceDetailW)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_W, DWORD, PDWORD, PSP_DEVINFO_DATA); 54 static BOOL (WINAPI *pSetupDiRegisterDeviceInfo)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PSP_DETSIG_CMPPROC, PVOID, PSP_DEVINFO_DATA); 55 static HDEVINFO (WINAPI *pSetupDiGetClassDevsA)(const GUID *, LPCSTR, HWND, DWORD); 56 static HDEVINFO (WINAPI *pSetupDiGetClassDevsW)(const GUID *, LPCWSTR, HWND, DWORD); 57 static BOOL (WINAPI *pSetupDiSetDeviceRegistryPropertyA)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, const BYTE *, DWORD); 58 static BOOL (WINAPI *pSetupDiSetDeviceRegistryPropertyW)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, const BYTE *, DWORD); 59 static BOOL (WINAPI *pSetupDiGetDeviceRegistryPropertyA)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD); 60 static BOOL (WINAPI *pSetupDiGetDeviceRegistryPropertyW)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD); 61 static BOOL (WINAPI *pSetupDiRemoveDevice)(HDEVINFO, PSP_DEVINFO_DATA); 62 static BOOL (WINAPI *pSetupDiRemoveDeviceInterface)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA); 63 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); 64 65 /* This is a unique guid for testing purposes */ 66 static GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}}; 67 68 static void init_function_pointers(void) 69 { 70 HMODULE hSetupAPI = GetModuleHandleA("setupapi.dll"); 71 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); 72 73 pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA"); 74 pSetupDiCreateDeviceInfoW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoW"); 75 pSetupDiCreateDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoList"); 76 pSetupDiCreateDeviceInfoListExW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoListExW"); 77 pSetupDiCreateDeviceInterfaceA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInterfaceA"); 78 pSetupDiDestroyDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList"); 79 pSetupDiCallClassInstaller = (void *)GetProcAddress(hSetupAPI, "SetupDiCallClassInstaller"); 80 pSetupDiEnumDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo"); 81 pSetupDiEnumDeviceInterfaces = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInterfaces"); 82 pSetupDiGetDeviceInstanceIdA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInstanceIdA"); 83 pSetupDiGetDeviceInterfaceDetailA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailA"); 84 pSetupDiGetDeviceInterfaceDetailW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailW"); 85 pSetupDiInstallClassA = (void *)GetProcAddress(hSetupAPI, "SetupDiInstallClassA"); 86 pSetupDiOpenClassRegKeyExA = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenClassRegKeyExA"); 87 pSetupDiOpenDevRegKey = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenDevRegKey"); 88 pSetupDiCreateDevRegKeyW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDevRegKeyW"); 89 pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo"); 90 pSetupDiGetClassDevsA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsA"); 91 pSetupDiGetClassDevsW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsW"); 92 pSetupDiGetINFClassA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetINFClassA"); 93 pSetupDiSetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyA"); 94 pSetupDiSetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyW"); 95 pSetupDiGetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyA"); 96 pSetupDiGetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyW"); 97 pSetupDiRemoveDeviceInterface = (void *)GetProcAddress(hSetupAPI, "SetupDiRemoveDeviceInterface"); 98 pSetupDiRemoveDevice = (void *)GetProcAddress(hSetupAPI, "SetupDiRemoveDevice"); 99 pIsWow64Process = (void *)GetProcAddress(hKernel32, "IsWow64Process"); 100 } 101 102 static LSTATUS devinst_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey) 103 { 104 LONG ret; 105 DWORD dwMaxSubkeyLen, dwMaxValueLen; 106 DWORD dwMaxLen, dwSize; 107 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf; 108 HKEY hSubKey = hKey; 109 110 if(lpszSubKey) 111 { 112 ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey); 113 if (ret) return ret; 114 } 115 116 /* Get highest length for keys, values */ 117 ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL, 118 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL); 119 if (ret) goto cleanup; 120 121 dwMaxSubkeyLen++; 122 dwMaxValueLen++; 123 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen); 124 if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR)) 125 { 126 /* Name too big: alloc a buffer for it */ 127 if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR)))) 128 { 129 ret = ERROR_NOT_ENOUGH_MEMORY; 130 goto cleanup; 131 } 132 } 133 134 135 /* Recursively delete all the subkeys */ 136 while (TRUE) 137 { 138 dwSize = dwMaxLen; 139 if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL, 140 NULL, NULL, NULL)) break; 141 142 ret = devinst_RegDeleteTreeW(hSubKey, lpszName); 143 if (ret) goto cleanup; 144 } 145 146 if (lpszSubKey) 147 ret = RegDeleteKeyW(hKey, lpszSubKey); 148 else 149 while (TRUE) 150 { 151 dwSize = dwMaxLen; 152 if (RegEnumValueW(hKey, 0, lpszName, &dwSize, 153 NULL, NULL, NULL, NULL)) break; 154 155 ret = RegDeleteValueW(hKey, lpszName); 156 if (ret) goto cleanup; 157 } 158 159 cleanup: 160 /* Free buffer if allocated */ 161 if (lpszName != szNameBuf) 162 HeapFree( GetProcessHeap(), 0, lpszName); 163 if(lpszSubKey) 164 RegCloseKey(hSubKey); 165 return ret; 166 } 167 168 static void test_SetupDiCreateDeviceInfoListEx(void) 169 { 170 HDEVINFO devlist; 171 BOOL ret; 172 DWORD error; 173 static CHAR notnull[] = "NotNull"; 174 static const WCHAR machine[] = { 'd','u','m','m','y',0 }; 175 static const WCHAR empty[] = { 0 }; 176 177 SetLastError(0xdeadbeef); 178 /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */ 179 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull); 180 181 error = GetLastError(); 182 if (error == ERROR_CALL_NOT_IMPLEMENTED) 183 { 184 win_skip("SetupDiCreateDeviceInfoListExW is not implemented\n"); 185 return; 186 } 187 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE); 188 ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_PARAMETER); 189 190 SetLastError(0xdeadbeef); 191 /* create empty DeviceInfoList, but set MachineName to something */ 192 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL); 193 194 error = GetLastError(); 195 if (error == ERROR_CALL_NOT_IMPLEMENTED) 196 { 197 /* win10 reports ERROR_CALL_NOT_IMPLEMENTED at first here */ 198 win_skip("SetupDiCreateDeviceInfoListExW is not implemented\n"); 199 return; 200 } 201 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE); 202 ok(error == ERROR_INVALID_MACHINENAME || error == ERROR_MACHINE_UNAVAILABLE, "GetLastError returned wrong value : %d, (expected %d or %d)\n", error, ERROR_INVALID_MACHINENAME, ERROR_MACHINE_UNAVAILABLE); 203 204 /* create empty DeviceInfoList */ 205 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); 206 ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE); 207 208 /* destroy DeviceInfoList */ 209 ret = pSetupDiDestroyDeviceInfoList(devlist); 210 ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error); 211 212 /* create empty DeviceInfoList with empty machine name */ 213 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, empty, NULL); 214 ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE); 215 216 /* destroy DeviceInfoList */ 217 ret = pSetupDiDestroyDeviceInfoList(devlist); 218 ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error); 219 } 220 221 static void test_SetupDiOpenClassRegKeyExA(void) 222 { 223 static const CHAR guidString[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}"; 224 HKEY hkey; 225 226 /* Check return value for nonexistent key */ 227 hkey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS, 228 DIOCR_INSTALLER, NULL, NULL); 229 ok(hkey == INVALID_HANDLE_VALUE, 230 "returned %p (expected INVALID_HANDLE_VALUE)\n", hkey); 231 232 /* Test it for a key that exists */ 233 hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS); 234 if (hkey != INVALID_HANDLE_VALUE) 235 { 236 HKEY classKey; 237 if (RegCreateKeyA(hkey, guidString, &classKey) == ERROR_SUCCESS) 238 { 239 RegCloseKey(classKey); 240 SetLastError(0xdeadbeef); 241 classKey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS, 242 DIOCR_INSTALLER, NULL, NULL); 243 ok(classKey != INVALID_HANDLE_VALUE, 244 "opening class registry key failed with error %d\n", 245 GetLastError()); 246 if (classKey != INVALID_HANDLE_VALUE) 247 RegCloseKey(classKey); 248 RegDeleteKeyA(hkey, guidString); 249 } 250 else 251 trace("failed to create registry key for test\n"); 252 253 RegCloseKey(hkey); 254 } 255 else 256 trace("failed to open classes key %u\n", GetLastError()); 257 } 258 259 static void create_inf_file(LPCSTR filename) 260 { 261 DWORD dwNumberOfBytesWritten; 262 HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL, 263 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 264 265 static const char data[] = 266 "[Version]\n" 267 "Signature=\"$Chicago$\"\n" 268 "Class=Bogus\n" 269 "ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n" 270 "[ClassInstall32]\n" 271 "AddReg=BogusClass.NT.AddReg\n" 272 "[BogusClass.NT.AddReg]\n" 273 "HKR,,,,\"Wine test devices\"\n"; 274 275 WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL); 276 CloseHandle(hf); 277 } 278 279 static void get_temp_filename(LPSTR path) 280 { 281 static char curr[MAX_PATH] = { 0 }; 282 char temp[MAX_PATH]; 283 LPSTR ptr; 284 285 if (!*curr) 286 GetCurrentDirectoryA(MAX_PATH, curr); 287 GetTempFileNameA(curr, "set", 0, temp); 288 ptr = strrchr(temp, '\\'); 289 290 lstrcpyA(path, ptr + 1); 291 } 292 293 static void testInstallClass(void) 294 { 295 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\', 296 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 297 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\', 298 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-', 299 '1','1','d','b','-','b','7','0','4','-', 300 '0','0','1','1','9','5','5','c','2','b','d','b','}',0}; 301 char tmpfile[MAX_PATH]; 302 BOOL ret; 303 304 tmpfile[0] = '.'; 305 tmpfile[1] = '\\'; 306 get_temp_filename(tmpfile + 2); 307 create_inf_file(tmpfile + 2); 308 309 ret = pSetupDiInstallClassA(NULL, NULL, 0, NULL); 310 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 311 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 312 ret = pSetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL); 313 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 314 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 315 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL); 316 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 317 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 318 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL); 319 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 320 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 321 /* The next call will succeed. Information is put into the registry but the 322 * location(s) is/are depending on the Windows version. 323 */ 324 ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL); 325 ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError()); 326 327 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey), 328 "Couldn't delete classkey\n"); 329 330 DeleteFileA(tmpfile); 331 } 332 333 static void testCreateDeviceInfo(void) 334 { 335 BOOL ret; 336 HDEVINFO set; 337 338 SetLastError(0xdeadbeef); 339 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL); 340 ok(!ret, "Expected failure\n"); 341 ok(GetLastError() == ERROR_INVALID_DEVINST_NAME || 342 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 343 "Unexpected last error, got %08x\n", GetLastError()); 344 345 SetLastError(0xdeadbeef); 346 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL, 347 NULL, NULL, 0, NULL); 348 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, 349 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError()); 350 set = pSetupDiCreateDeviceInfoList(&guid, NULL); 351 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n", 352 GetLastError()); 353 if (set) 354 { 355 SP_DEVINFO_DATA devInfo = { 0 }; 356 DWORD i; 357 static GUID deadbeef = 358 {0xdeadbeef, 0xdead, 0xbeef, {0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}}; 359 360 /* No GUID given */ 361 SetLastError(0xdeadbeef); 362 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL, 363 NULL, NULL, 0, NULL); 364 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 365 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 366 367 /* We can't add device information to the set with a different GUID */ 368 SetLastError(0xdeadbeef); 369 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", 370 &deadbeef, NULL, NULL, 0, NULL); 371 ok(!ret && GetLastError() == ERROR_CLASS_MISMATCH, 372 "Expected ERROR_CLASS_MISMATCH, got %08x\n", GetLastError()); 373 374 /* Finally, with all three required parameters, this succeeds: */ 375 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, 376 NULL, NULL, 0, NULL); 377 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); 378 /* This fails because the device ID already exists.. */ 379 SetLastError(0xdeadbeef); 380 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, 381 NULL, NULL, 0, &devInfo); 382 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS, 383 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError()); 384 /* whereas this "fails" because cbSize is wrong.. */ 385 SetLastError(0xdeadbeef); 386 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL, 387 DICD_GENERATE_ID, &devInfo); 388 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, 389 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); 390 /* and this finally succeeds. */ 391 devInfo.cbSize = sizeof(devInfo); 392 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL, 393 DICD_GENERATE_ID, &devInfo); 394 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); 395 /* There were three devices added, however - the second failure just 396 * resulted in the SP_DEVINFO_DATA not getting copied. 397 */ 398 SetLastError(0xdeadbeef); 399 i = 0; 400 while (pSetupDiEnumDeviceInfo(set, i, &devInfo)) 401 i++; 402 ok(i == 3, "Expected 3 devices, got %d\n", i); 403 ok(GetLastError() == ERROR_NO_MORE_ITEMS, 404 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError()); 405 406 ret = pSetupDiRemoveDevice(set, &devInfo); 407 todo_wine ok(ret, "got %u\n", GetLastError()); 408 pSetupDiDestroyDeviceInfoList(set); 409 } 410 } 411 412 static void testGetDeviceInstanceId(void) 413 { 414 BOOL ret; 415 HDEVINFO set; 416 SP_DEVINFO_DATA devInfo = { 0 }; 417 418 SetLastError(0xdeadbeef); 419 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL); 420 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, 421 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError()); 422 SetLastError(0xdeadbeef); 423 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL); 424 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, 425 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError()); 426 set = pSetupDiCreateDeviceInfoList(&guid, NULL); 427 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n", 428 GetLastError()); 429 if (set) 430 { 431 char instanceID[MAX_PATH]; 432 DWORD size; 433 434 SetLastError(0xdeadbeef); 435 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL); 436 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 437 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 438 SetLastError(0xdeadbeef); 439 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL); 440 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 441 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 442 SetLastError(0xdeadbeef); 443 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size); 444 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 445 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 446 devInfo.cbSize = sizeof(devInfo); 447 SetLastError(0xdeadbeef); 448 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size); 449 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 450 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 451 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, 452 NULL, NULL, 0, &devInfo); 453 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); 454 SetLastError(0xdeadbeef); 455 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size); 456 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, 457 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError()); 458 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID, 459 sizeof(instanceID), NULL); 460 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError()); 461 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"), 462 "Unexpected instance ID %s\n", instanceID); 463 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, 464 NULL, NULL, DICD_GENERATE_ID, &devInfo); 465 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); 466 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID, 467 sizeof(instanceID), NULL); 468 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError()); 469 /* NT4 returns 'Root' and W2K and above 'ROOT' */ 470 ok(!lstrcmpiA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"), 471 "Unexpected instance ID %s\n", instanceID); 472 473 ret = pSetupDiRemoveDevice(set, &devInfo); 474 todo_wine ok(ret, "got %u\n", GetLastError()); 475 pSetupDiDestroyDeviceInfoList(set); 476 } 477 } 478 479 static void testRegisterDeviceInfo(void) 480 { 481 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\', 482 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 483 'E','n','u','m','\\','U','S','B','\\','B','O','G','U','S',0}; 484 BOOL ret; 485 HDEVINFO set; 486 487 SetLastError(0xdeadbeef); 488 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL); 489 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, 490 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 491 set = pSetupDiCreateDeviceInfoList(&guid, NULL); 492 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError()); 493 if (set) 494 { 495 SP_DEVINFO_DATA devInfo = { 0 }; 496 497 SetLastError(0xdeadbeef); 498 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL); 499 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 500 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 501 SetLastError(0xdeadbeef); 502 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL); 503 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 504 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 505 devInfo.cbSize = sizeof(devInfo); 506 SetLastError(0xdeadbeef); 507 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL); 508 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 509 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 510 511 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid, 512 NULL, NULL, 0, &devInfo); 513 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); 514 515 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL); 516 ok(ret, "SetupDiRegisterDeviceInfo failed: %d\n", GetLastError()); 517 518 ret = pSetupDiRemoveDevice(set, &devInfo); 519 todo_wine ok(ret, "got %u\n", GetLastError()); 520 pSetupDiDestroyDeviceInfoList(set); 521 522 /* remove once Wine is fixed */ 523 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus); 524 } 525 } 526 527 static void testCreateDeviceInterface(void) 528 { 529 BOOL ret; 530 HDEVINFO set; 531 532 if (!pSetupDiCreateDeviceInterfaceA || !pSetupDiEnumDeviceInterfaces) 533 { 534 win_skip("SetupDiCreateDeviceInterfaceA and/or SetupDiEnumDeviceInterfaces are not available\n"); 535 return; 536 } 537 SetLastError(0xdeadbeef); 538 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL); 539 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, 540 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 541 SetLastError(0xdeadbeef); 542 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL); 543 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, 544 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 545 set = pSetupDiCreateDeviceInfoList(&guid, NULL); 546 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError()); 547 if (set) 548 { 549 SP_DEVINFO_DATA devInfo = { 0 }; 550 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), 551 { 0 } }; 552 DWORD i; 553 554 SetLastError(0xdeadbeef); 555 ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL); 556 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 557 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 558 SetLastError(0xdeadbeef); 559 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0, 560 NULL); 561 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 562 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 563 devInfo.cbSize = sizeof(devInfo); 564 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid, 565 NULL, NULL, 0, &devInfo); 566 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); 567 SetLastError(0xdeadbeef); 568 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0, 569 NULL); 570 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, 571 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); 572 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, 573 NULL); 574 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); 575 /* Creating the same interface a second time succeeds */ 576 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, 577 NULL); 578 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); 579 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0, 580 NULL); 581 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); 582 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0, 583 &interfaceData); 584 ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError()); 585 i = 0; 586 while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i, 587 &interfaceData)) 588 i++; 589 ok(i == 2, "expected 2 interfaces, got %d\n", i); 590 ok(GetLastError() == ERROR_NO_MORE_ITEMS, 591 "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError()); 592 593 for (i = 0; i < 2; i++) 594 { 595 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i, &interfaceData); 596 ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError()); 597 598 ret = pSetupDiRemoveDeviceInterface(set, &interfaceData); 599 todo_wine ok(ret, "SetupDiRemoveDeviceInterface failed: %08x\n", GetLastError()); 600 } 601 602 ret = pSetupDiRemoveDevice(set, &devInfo); 603 todo_wine ok(ret, "got %u\n", GetLastError()); 604 605 ret = pSetupDiDestroyDeviceInfoList(set); 606 ok(ret, "SetupDiDestroyDeviceInfoList failed: %08x\n", GetLastError()); 607 } 608 } 609 610 static void testGetDeviceInterfaceDetail(void) 611 { 612 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\', 613 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 614 'E','n','u','m','\\','R','o','o','t','\\', 615 'L','E','G','A','C','Y','_','B','O','G','U','S',0}; 616 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\', 617 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 618 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\', 619 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-', 620 '1','1','d','b','-','b','7','0','4','-', 621 '0','0','1','1','9','5','5','c','2','b','d','b','}',0}; 622 BOOL ret; 623 HDEVINFO set; 624 625 if (!pSetupDiCreateDeviceInterfaceA || !pSetupDiGetDeviceInterfaceDetailA) 626 { 627 win_skip("SetupDiCreateDeviceInterfaceA and/or SetupDiGetDeviceInterfaceDetailA are not available\n"); 628 return; 629 } 630 SetLastError(0xdeadbeef); 631 ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL); 632 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, 633 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 634 set = pSetupDiCreateDeviceInfoList(&guid, NULL); 635 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError()); 636 if (set) 637 { 638 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } }; 639 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), 640 { 0 } }; 641 DWORD size = 0; 642 643 SetLastError(0xdeadbeef); 644 ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL, 645 NULL); 646 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 647 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 648 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid, 649 NULL, NULL, 0, &devInfo); 650 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); 651 SetLastError(0xdeadbeef); 652 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, 653 &interfaceData); 654 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); 655 SetLastError(0xdeadbeef); 656 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, 657 0, NULL, NULL); 658 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, 659 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 660 SetLastError(0xdeadbeef); 661 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, 662 100, NULL, NULL); 663 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, 664 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); 665 SetLastError(0xdeadbeef); 666 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, 667 0, &size, NULL); 668 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, 669 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 670 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 671 { 672 static const char path[] = 673 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}"; 674 static const char path_w2k[] = 675 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\"; 676 SP_DEVINFO_DATA devinfo; 677 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size); 678 SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail = 679 (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf; 680 DWORD expectedsize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)*(1 + strlen(path)); 681 682 detail->cbSize = 0; 683 SetLastError(0xdeadbeef); 684 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail, 685 size, &size, NULL); 686 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, 687 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); 688 detail->cbSize = size; 689 SetLastError(0xdeadbeef); 690 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail, 691 size, &size, NULL); 692 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, 693 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); 694 detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); 695 SetLastError(0xdeadbeef); 696 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail, 697 size, &size, NULL); 698 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n", 699 GetLastError()); 700 ok(!lstrcmpiA(path, detail->DevicePath) || 701 !lstrcmpiA(path_w2k, detail->DevicePath), "Unexpected path %s\n", 702 detail->DevicePath); 703 /* Check SetupDiGetDeviceInterfaceDetailW */ 704 memset(&devinfo, 0, sizeof(devinfo)); 705 devinfo.cbSize = sizeof(devinfo); 706 ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, &devinfo); 707 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, 708 "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError()); 709 ok(devinfo.DevInst, "Expected DevInst to be set\n"); 710 ok(expectedsize == size || 711 (expectedsize + sizeof(WCHAR)) == size /* W2K adds a backslash */, 712 "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize, got %d\n", 713 size); 714 715 HeapFree(GetProcessHeap(), 0, buf); 716 } 717 718 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0, &interfaceData); 719 ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError()); 720 721 ret = pSetupDiRemoveDeviceInterface(set, &interfaceData); 722 todo_wine ok(ret, "SetupDiRemoveDeviceInterface failed: %08x\n", GetLastError()); 723 724 ret = pSetupDiRemoveDevice(set, &devInfo); 725 todo_wine ok(ret, "got %u\n", GetLastError()); 726 pSetupDiDestroyDeviceInfoList(set); 727 728 /* remove once Wine is fixed */ 729 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus); 730 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass); 731 } 732 } 733 734 static void testDevRegKey(void) 735 { 736 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\', 737 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 738 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\', 739 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-', 740 '1','1','d','b','-','b','7','0','4','-', 741 '0','0','1','1','9','5','5','c','2','b','d','b','}',0}; 742 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\', 743 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 744 'E','n','u','m','\\','R','o','o','t','\\', 745 'L','E','G','A','C','Y','_','B','O','G','U','S',0}; 746 BOOL ret; 747 HDEVINFO set; 748 HKEY key = NULL; 749 750 SetLastError(0xdeadbeef); 751 key = pSetupDiCreateDevRegKeyW(NULL, NULL, 0, 0, 0, NULL, NULL); 752 ok(key == INVALID_HANDLE_VALUE, 753 "Expected INVALID_HANDLE_VALUE, got %p\n", key); 754 ok(GetLastError() == ERROR_INVALID_HANDLE, 755 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError()); 756 757 set = pSetupDiCreateDeviceInfoList(&guid, NULL); 758 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError()); 759 if (set) 760 { 761 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } }; 762 LONG res; 763 764 /* The device info key shouldn't be there */ 765 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key); 766 ok(res != ERROR_SUCCESS, "Expected key to not exist\n"); 767 RegCloseKey(key); 768 /* Create the device information */ 769 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid, 770 NULL, NULL, 0, &devInfo); 771 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); 772 /* The device info key should have been created */ 773 ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key), 774 "Expected registry key to exist\n"); 775 RegCloseKey(key); 776 SetLastError(0xdeadbeef); 777 key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0); 778 ok(!key || key == INVALID_HANDLE_VALUE, 779 "Expected INVALID_HANDLE_VALUE or a NULL key (NT4)\n"); 780 ok(GetLastError() == ERROR_INVALID_HANDLE, 781 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 782 SetLastError(0xdeadbeef); 783 key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0); 784 ok(key == INVALID_HANDLE_VALUE && 785 GetLastError() == ERROR_INVALID_PARAMETER, 786 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 787 SetLastError(0xdeadbeef); 788 key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 0, 0, 0); 789 ok(key == INVALID_HANDLE_VALUE && 790 GetLastError() == ERROR_INVALID_FLAGS, 791 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError()); 792 SetLastError(0xdeadbeef); 793 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 0, 0); 794 ok(key == INVALID_HANDLE_VALUE && 795 GetLastError() == ERROR_INVALID_FLAGS, 796 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError()); 797 SetLastError(0xdeadbeef); 798 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 799 DIREG_BOTH, 0); 800 ok(key == INVALID_HANDLE_VALUE && 801 GetLastError() == ERROR_INVALID_FLAGS, 802 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError()); 803 SetLastError(0xdeadbeef); 804 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 805 DIREG_DRV, 0); 806 ok(key == INVALID_HANDLE_VALUE && 807 GetLastError() == ERROR_DEVINFO_NOT_REGISTERED, 808 "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError()); 809 SetLastError(0xdeadbeef); 810 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL); 811 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError()); 812 SetLastError(0xdeadbeef); 813 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 814 DIREG_DRV, 0); 815 /* The software key isn't created by default */ 816 ok(key == INVALID_HANDLE_VALUE && 817 GetLastError() == ERROR_KEY_DOES_NOT_EXIST, 818 "Expected ERROR_KEY_DOES_NOT_EXIST, got %08x\n", GetLastError()); 819 SetLastError(0xdeadbeef); 820 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 821 DIREG_DEV, 0); 822 todo_wine 823 ok(key == INVALID_HANDLE_VALUE && 824 GetLastError() == ERROR_KEY_DOES_NOT_EXIST, 825 "Expected ERROR_KEY_DOES_NOT_EXIST, got %08x\n", GetLastError()); 826 SetLastError(0xdeadbeef); 827 /* The class key shouldn't be there */ 828 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key); 829 todo_wine 830 ok(res != ERROR_SUCCESS, "Expected key to not exist\n"); 831 RegCloseKey(key); 832 /* Create the device reg key */ 833 key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0, 834 DIREG_DRV, NULL, NULL); 835 /* Vista and higher don't actually create the key */ 836 ok(key != INVALID_HANDLE_VALUE || GetLastError() == ERROR_KEY_DOES_NOT_EXIST, 837 "SetupDiCreateDevRegKey failed: %08x\n", GetLastError()); 838 if (key != INVALID_HANDLE_VALUE) 839 { 840 RegCloseKey(key); 841 /* The class key should have been created */ 842 ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key), 843 "Expected registry key to exist\n"); 844 RegCloseKey(key); 845 SetLastError(0xdeadbeef); 846 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 847 DIREG_DRV, 0); 848 todo_wine 849 ok(key == INVALID_HANDLE_VALUE && 850 (GetLastError() == ERROR_INVALID_DATA || 851 GetLastError() == ERROR_ACCESS_DENIED), /* win2k3 */ 852 "Expected ERROR_INVALID_DATA or ERROR_ACCESS_DENIED, got %08x\n", GetLastError()); 853 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 854 DIREG_DRV, KEY_READ); 855 ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n", 856 GetLastError()); 857 RegCloseKey(key); 858 } 859 860 ret = pSetupDiRemoveDevice(set, &devInfo); 861 todo_wine ok(ret, "got %u\n", GetLastError()); 862 pSetupDiDestroyDeviceInfoList(set); 863 864 /* remove once Wine is fixed */ 865 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus); 866 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey); 867 } 868 } 869 870 static void testRegisterAndGetDetail(void) 871 { 872 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\', 873 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 874 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\', 875 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-', 876 '1','1','d','b','-','b','7','0','4','-', 877 '0','0','1','1','9','5','5','c','2','b','d','b','}',0}; 878 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\', 879 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 880 'E','n','u','m','\\','R','o','o','t','\\', 881 'L','E','G','A','C','Y','_','B','O','G','U','S',0}; 882 HDEVINFO set, set2; 883 BOOL ret; 884 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } }; 885 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), { 0 } }; 886 SP_DEVICE_INTERFACE_DATA interfaceData2 = { sizeof(interfaceData2), { 0 } }; 887 DWORD dwSize = 0; 888 HKEY key; 889 LONG res; 890 891 if (!pSetupDiCreateDeviceInterfaceA || !pSetupDiEnumDeviceInterfaces || 892 !pSetupDiGetDeviceInterfaceDetailA) 893 { 894 win_skip("Needed functions are not available\n"); 895 return; 896 } 897 898 SetLastError(0xdeadbeef); 899 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_ALLCLASSES); 900 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n", 901 GetLastError()); 902 903 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key); 904 ok(res != ERROR_SUCCESS, "Expected key to not exist\n"); 905 RegCloseKey(key); 906 907 SetLastError(0xdeadbeef); 908 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, 0, 909 DICD_GENERATE_ID, &devInfo); 910 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); 911 SetLastError(0xdeadbeef); 912 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, &interfaceData); 913 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); 914 SetLastError(0xdeadbeef); 915 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL); 916 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError()); 917 918 SetLastError(0xdeadbeef); 919 set2 = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE); 920 ok(set2 != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n", 921 GetLastError()); 922 923 SetLastError(0xdeadbeef); 924 ret = pSetupDiEnumDeviceInterfaces(set2, NULL, &guid, 0, &interfaceData2); 925 ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError()); 926 SetLastError(0xdeadbeef); 927 ret = pSetupDiGetDeviceInterfaceDetailA(set2, &interfaceData2, NULL, 0, &dwSize, NULL); 928 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, 929 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError()); 930 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 931 { 932 static const char path[] = 933 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}"; 934 static const char path_w10[] = 935 "\\\\?\\root#legacy_bogus#0001#{6a55b5a4-3f65-11db-b704-0011955c2bdb}"; 936 static const char path_w2k[] = 937 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\"; 938 PSP_DEVICE_INTERFACE_DETAIL_DATA_A detail = NULL; 939 940 detail = HeapAlloc(GetProcessHeap(), 0, dwSize); 941 if (detail) 942 { 943 detail->cbSize = sizeof(*detail); 944 SetLastError(0xdeadbeef); 945 ret = pSetupDiGetDeviceInterfaceDetailA(set2, &interfaceData2, 946 detail, dwSize, &dwSize, NULL); 947 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %08x\n", GetLastError()); 948 ok(!lstrcmpiA(path, detail->DevicePath) || 949 !lstrcmpiA(path_w10, detail->DevicePath) || 950 !lstrcmpiA(path_w2k, detail->DevicePath), 951 "Unexpected path %s\n", detail->DevicePath); 952 HeapFree(GetProcessHeap(), 0, detail); 953 } 954 } 955 956 ret = pSetupDiRemoveDeviceInterface(set, &interfaceData); 957 todo_wine ok(ret, "SetupDiRemoveDeviceInterface failed: %08x\n", GetLastError()); 958 959 ret = pSetupDiRemoveDevice(set, &devInfo); 960 todo_wine ok(ret, "got %u\n", GetLastError()); 961 962 pSetupDiDestroyDeviceInfoList(set); 963 pSetupDiDestroyDeviceInfoList(set2); 964 965 /* remove once Wine is fixed */ 966 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus); 967 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey); 968 } 969 970 static void testDeviceRegistryPropertyA(void) 971 { 972 HDEVINFO set; 973 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } }; 974 CHAR devName[] = "LEGACY_BOGUS"; 975 CHAR friendlyName[] = "Bogus"; 976 CHAR buf[6] = ""; 977 DWORD buflen = 6; 978 DWORD size; 979 DWORD regType; 980 BOOL ret; 981 LONG res; 982 HKEY key; 983 static const CHAR bogus[] = 984 "System\\CurrentControlSet\\Enum\\Root\\LEGACY_BOGUS"; 985 986 SetLastError(0xdeadbeef); 987 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE); 988 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n", 989 GetLastError()); 990 SetLastError(0xdeadbeef); 991 ret = pSetupDiCreateDeviceInfoA(set, devName, &guid, NULL, NULL, 992 DICD_GENERATE_ID, &devInfo); 993 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); 994 SetLastError(0xdeadbeef); 995 ret = pSetupDiSetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, 0); 996 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, 997 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError()); 998 SetLastError(0xdeadbeef); 999 ret = pSetupDiSetDeviceRegistryPropertyA(set, NULL, -1, NULL, 0); 1000 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 1001 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 1002 SetLastError(0xdeadbeef); 1003 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, 0); 1004 todo_wine 1005 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY, 1006 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError()); 1007 /* GetLastError() returns nonsense in win2k3 */ 1008 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME, 1009 NULL, 0); 1010 todo_wine 1011 ok(!ret, "Expected failure, got %d\n", ret); 1012 SetLastError(0xdeadbeef); 1013 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME, 1014 (PBYTE)friendlyName, buflen); 1015 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError()); 1016 SetLastError(0xdeadbeef); 1017 ret = pSetupDiGetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, NULL, 0, NULL); 1018 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, 1019 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError()); 1020 SetLastError(0xdeadbeef); 1021 ret = pSetupDiGetDeviceRegistryPropertyA(set, NULL, -1, NULL, NULL, 0, NULL); 1022 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 1023 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 1024 SetLastError(0xdeadbeef); 1025 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, NULL, 0, NULL); 1026 todo_wine 1027 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY, 1028 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError()); 1029 /* GetLastError() returns nonsense in win2k3 */ 1030 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME, 1031 NULL, NULL, buflen, NULL); 1032 ok(!ret, "Expected failure, got %d\n", ret); 1033 SetLastError(0xdeadbeef); 1034 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME, 1035 NULL, NULL, 0, &size); 1036 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, 1037 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError()); 1038 ok(buflen == size, "Unexpected size: %d\n", size); 1039 SetLastError(0xdeadbeef); 1040 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME, 1041 NULL, (PBYTE)buf, buflen, NULL); 1042 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError()); 1043 ok(!lstrcmpiA(friendlyName, buf), "Unexpected property\n"); 1044 SetLastError(0xdeadbeef); 1045 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME, 1046 ®Type, (PBYTE)buf, buflen, NULL); 1047 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError()); 1048 ok(!lstrcmpiA(friendlyName, buf), "Unexpected value of property\n"); 1049 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType); 1050 SetLastError(0xdeadbeef); 1051 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME, 1052 NULL, 0); 1053 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError()); 1054 SetLastError(0xdeadbeef); 1055 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME, 1056 NULL, (PBYTE)buf, buflen, &size); 1057 todo_wine 1058 ok(!ret && GetLastError() == ERROR_INVALID_DATA, 1059 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError()); 1060 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_HARDWAREID, 1061 NULL, NULL, 0, &size); 1062 ok(!ret && GetLastError() == ERROR_INVALID_DATA, 1063 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError()); 1064 pSetupDiDestroyDeviceInfoList(set); 1065 1066 res = RegOpenKeyA(HKEY_LOCAL_MACHINE, bogus, &key); 1067 if(!is_wow64) 1068 todo_wine ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n"); 1069 /* FIXME: Remove when Wine is fixed */ 1070 if (res == ERROR_SUCCESS) 1071 { 1072 /* Wine doesn't delete the information currently */ 1073 RegDeleteKeyA(HKEY_LOCAL_MACHINE, bogus); 1074 } 1075 } 1076 1077 static void testDeviceRegistryPropertyW(void) 1078 { 1079 HDEVINFO set; 1080 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } }; 1081 WCHAR devName[] = {'L','E','G','A','C','Y','_','B','O','G','U','S',0}; 1082 WCHAR friendlyName[] = {'B','o','g','u','s',0}; 1083 WCHAR buf[6] = {0}; 1084 DWORD buflen = 6 * sizeof(WCHAR); 1085 DWORD size; 1086 DWORD regType; 1087 BOOL ret; 1088 LONG res; 1089 HKEY key; 1090 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\', 1091 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 1092 'E','n','u','m','\\','R','o','o','t','\\', 1093 'L','E','G','A','C','Y','_','B','O','G','U','S',0}; 1094 1095 SetLastError(0xdeadbeef); 1096 set = pSetupDiGetClassDevsW(&guid, NULL, 0, DIGCF_DEVICEINTERFACE); 1097 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsW failed: %08x\n", 1098 GetLastError()); 1099 SetLastError(0xdeadbeef); 1100 ret = pSetupDiCreateDeviceInfoW(set, devName, &guid, NULL, NULL, 1101 DICD_GENERATE_ID, &devInfo); 1102 ok(ret, "SetupDiCreateDeviceInfoW failed: %08x\n", GetLastError()); 1103 SetLastError(0xdeadbeef); 1104 ret = pSetupDiSetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, 0); 1105 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, 1106 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError()); 1107 SetLastError(0xdeadbeef); 1108 ret = pSetupDiSetDeviceRegistryPropertyW(set, NULL, -1, NULL, 0); 1109 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 1110 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 1111 SetLastError(0xdeadbeef); 1112 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, 0); 1113 todo_wine 1114 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY, 1115 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError()); 1116 /* GetLastError() returns nonsense in win2k3 */ 1117 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME, 1118 NULL, 0); 1119 todo_wine 1120 ok(!ret, "Expected failure, got %d\n", ret); 1121 SetLastError(0xdeadbeef); 1122 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME, 1123 (PBYTE)friendlyName, buflen); 1124 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError()); 1125 SetLastError(0xdeadbeef); 1126 ret = pSetupDiGetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, NULL, 0, NULL); 1127 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, 1128 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError()); 1129 SetLastError(0xdeadbeef); 1130 ret = pSetupDiGetDeviceRegistryPropertyW(set, NULL, -1, NULL, NULL, 0, NULL); 1131 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 1132 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 1133 SetLastError(0xdeadbeef); 1134 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, NULL, 0, NULL); 1135 todo_wine 1136 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY, 1137 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError()); 1138 /* GetLastError() returns nonsense in win2k3 */ 1139 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME, 1140 NULL, NULL, buflen, NULL); 1141 ok(!ret, "Expected failure, got %d\n", ret); 1142 SetLastError(0xdeadbeef); 1143 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME, 1144 NULL, NULL, 0, &size); 1145 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, 1146 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError()); 1147 ok(buflen == size, "Unexpected size: %d\n", size); 1148 SetLastError(0xdeadbeef); 1149 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME, 1150 NULL, (PBYTE)buf, buflen, NULL); 1151 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError()); 1152 ok(!lstrcmpiW(friendlyName, buf), "Unexpected property\n"); 1153 SetLastError(0xdeadbeef); 1154 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME, 1155 ®Type, (PBYTE)buf, buflen, NULL); 1156 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError()); 1157 ok(!lstrcmpiW(friendlyName, buf), "Unexpected value of property\n"); 1158 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType); 1159 SetLastError(0xdeadbeef); 1160 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME, 1161 NULL, 0); 1162 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError()); 1163 SetLastError(0xdeadbeef); 1164 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME, 1165 NULL, (PBYTE)buf, buflen, &size); 1166 todo_wine 1167 ok(!ret && GetLastError() == ERROR_INVALID_DATA, 1168 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError()); 1169 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_HARDWAREID, 1170 NULL, NULL, 0, &size); 1171 ok(!ret && GetLastError() == ERROR_INVALID_DATA, 1172 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError()); 1173 pSetupDiDestroyDeviceInfoList(set); 1174 1175 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key); 1176 if(!is_wow64) 1177 todo_wine ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n"); 1178 /* FIXME: Remove when Wine is fixed */ 1179 if (res == ERROR_SUCCESS) 1180 { 1181 /* Wine doesn't delete the information currently */ 1182 RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus); 1183 } 1184 } 1185 1186 static void testSetupDiGetINFClassA(void) 1187 { 1188 static const char inffile[] = "winetest.inf"; 1189 static const char content[] = "[Version]\r\n\r\n"; 1190 static const char* signatures[] = {"\"$CHICAGO$\"", "\"$Windows NT$\""}; 1191 1192 char cn[MAX_PATH]; 1193 char filename[MAX_PATH]; 1194 DWORD count; 1195 BOOL retval; 1196 GUID guid; 1197 HANDLE h; 1198 int i; 1199 1200 if(!pSetupDiGetINFClassA) 1201 { 1202 win_skip("SetupDiGetINFClassA not present\n"); 1203 return; 1204 } 1205 1206 count = GetTempPathA(MAX_PATH, filename); 1207 if(!count) 1208 { 1209 win_skip("GetTempPathA failed\n"); 1210 return; 1211 } 1212 1213 strcat(filename, inffile); 1214 DeleteFileA(filename); 1215 1216 /* not existing file */ 1217 SetLastError(0xdeadbeef); 1218 retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); 1219 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1220 if (ERROR_CALL_NOT_IMPLEMENTED == GetLastError()) 1221 { 1222 skip("SetupDiGetINFClassA is not implemented\n"); 1223 return; 1224 } 1225 ok(ERROR_FILE_NOT_FOUND == GetLastError(), 1226 "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); 1227 1228 /* missing file wins against other invalid parameter */ 1229 SetLastError(0xdeadbeef); 1230 retval = SetupDiGetINFClassA(filename, NULL, cn, MAX_PATH, &count); 1231 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1232 ok(ERROR_FILE_NOT_FOUND == GetLastError(), 1233 "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); 1234 1235 SetLastError(0xdeadbeef); 1236 retval = SetupDiGetINFClassA(filename, &guid, NULL, MAX_PATH, &count); 1237 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1238 ok(ERROR_FILE_NOT_FOUND == GetLastError(), 1239 "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); 1240 1241 SetLastError(0xdeadbeef); 1242 retval = SetupDiGetINFClassA(filename, &guid, cn, 0, &count); 1243 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1244 ok(ERROR_FILE_NOT_FOUND == GetLastError(), 1245 "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); 1246 1247 SetLastError(0xdeadbeef); 1248 retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, NULL); 1249 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1250 ok(ERROR_FILE_NOT_FOUND == GetLastError(), 1251 "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); 1252 1253 /* test file content */ 1254 h = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 1255 FILE_ATTRIBUTE_NORMAL, NULL); 1256 if(h == INVALID_HANDLE_VALUE) 1257 { 1258 win_skip("failed to create file %s (error %u)\n", filename, GetLastError()); 1259 return; 1260 } 1261 CloseHandle( h); 1262 1263 retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); 1264 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1265 1266 for(i=0; i < sizeof(signatures)/sizeof(char*); i++) 1267 { 1268 trace("testing signature %s\n", signatures[i]); 1269 h = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 1270 FILE_ATTRIBUTE_NORMAL, NULL); 1271 if(h == INVALID_HANDLE_VALUE) 1272 { 1273 win_skip("failed to create file %s (error %u)\n", filename, GetLastError()); 1274 return; 1275 } 1276 WriteFile( h, content, sizeof(content), &count, NULL); 1277 CloseHandle( h); 1278 1279 retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); 1280 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1281 1282 WritePrivateProfileStringA("Version", "Signature", signatures[i], filename); 1283 1284 retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); 1285 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1286 1287 WritePrivateProfileStringA("Version", "Class", "WINE", filename); 1288 1289 count = 0xdeadbeef; 1290 retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); 1291 ok(retval, "expected SetupDiGetINFClassA to succeed! error %u\n", GetLastError()); 1292 ok(count == 5, "expected count==5, got %u\n", count); 1293 1294 count = 0xdeadbeef; 1295 retval = SetupDiGetINFClassA(filename, &guid, cn, 5, &count); 1296 ok(retval, "expected SetupDiGetINFClassA to succeed! error %u\n", GetLastError()); 1297 ok(count == 5, "expected count==5, got %u\n", count); 1298 1299 count = 0xdeadbeef; 1300 SetLastError(0xdeadbeef); 1301 retval = SetupDiGetINFClassA(filename, &guid, cn, 4, &count); 1302 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1303 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), 1304 "expected error ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); 1305 ok(count == 5, "expected count==5, got %u\n", count); 1306 1307 /* invalid parameter */ 1308 SetLastError(0xdeadbeef); 1309 retval = SetupDiGetINFClassA(NULL, &guid, cn, MAX_PATH, &count); 1310 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1311 ok(ERROR_INVALID_PARAMETER == GetLastError(), 1312 "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); 1313 1314 SetLastError(0xdeadbeef); 1315 retval = SetupDiGetINFClassA(filename, NULL, cn, MAX_PATH, &count); 1316 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1317 ok(ERROR_INVALID_PARAMETER == GetLastError(), 1318 "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); 1319 1320 SetLastError(0xdeadbeef); 1321 retval = SetupDiGetINFClassA(filename, &guid, NULL, MAX_PATH, &count); 1322 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1323 ok(ERROR_INVALID_PARAMETER == GetLastError(), 1324 "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); 1325 1326 SetLastError(0xdeadbeef); 1327 retval = SetupDiGetINFClassA(filename, &guid, cn, 0, &count); 1328 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1329 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError() || 1330 ERROR_INVALID_PARAMETER == GetLastError(), 1331 "expected error ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER, " 1332 "got %u\n", GetLastError()); 1333 1334 DeleteFileA(filename); 1335 1336 WritePrivateProfileStringA("Version", "Signature", signatures[i], filename); 1337 WritePrivateProfileStringA("Version", "ClassGUID", "WINE", filename); 1338 1339 SetLastError(0xdeadbeef); 1340 retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); 1341 ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); 1342 ok(RPC_S_INVALID_STRING_UUID == GetLastError() || 1343 ERROR_INVALID_PARAMETER == GetLastError(), 1344 "expected error RPC_S_INVALID_STRING_UUID or ERROR_INVALID_PARAMETER, " 1345 "got %u\n", GetLastError()); 1346 1347 /* network adapter guid */ 1348 WritePrivateProfileStringA("Version", "ClassGUID", 1349 "{4d36e972-e325-11ce-bfc1-08002be10318}", filename); 1350 1351 /* this test succeeds only if the guid is known to the system */ 1352 count = 0xdeadbeef; 1353 retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); 1354 ok(retval, "expected SetupDiGetINFClassA to succeed! error %u\n", GetLastError()); 1355 todo_wine 1356 ok(count == 4, "expected count==4, got %u(%s)\n", count, cn); 1357 1358 DeleteFileA(filename); 1359 } 1360 } 1361 1362 static void testSetupDiGetClassDevsA(void) 1363 { 1364 static GUID displayguid = {0x4d36e968, 0xe325, 0x11ce, {0xbf,0xc1,0x08,0x00,0x2b,0xe1,0x03,0x18}}; 1365 SP_DEVINFO_DATA devinfo; 1366 DISPLAY_DEVICEA disp; 1367 HDEVINFO set; 1368 BOOL ret; 1369 1370 disp.cb = sizeof(disp); 1371 ok(EnumDisplayDevicesA(NULL, 0, &disp, 0), "EnumDisplayDevices failed: %08x\n", GetLastError()); 1372 1373 SetLastError(0xdeadbeef); 1374 set = pSetupDiGetClassDevsA(&displayguid, disp.DeviceID, 0, 0); 1375 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n", GetLastError()); 1376 1377 devinfo.cbSize = sizeof(devinfo); 1378 ret = SetupDiEnumDeviceInfo(set, 0, &devinfo); 1379 ok(ret, "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError()); 1380 1381 pSetupDiDestroyDeviceInfoList(set); 1382 } 1383 1384 START_TEST(devinst) 1385 { 1386 HKEY hkey; 1387 1388 init_function_pointers(); 1389 1390 if ((hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS)) == INVALID_HANDLE_VALUE) 1391 { 1392 skip("needs admin rights\n"); 1393 return; 1394 } 1395 RegCloseKey(hkey); 1396 1397 if (pIsWow64Process) 1398 pIsWow64Process(GetCurrentProcess(), &is_wow64); 1399 1400 if (pSetupDiCreateDeviceInfoListExW) 1401 test_SetupDiCreateDeviceInfoListEx(); 1402 else 1403 win_skip("SetupDiCreateDeviceInfoListExW is not available\n"); 1404 1405 if (pSetupDiOpenClassRegKeyExA) 1406 test_SetupDiOpenClassRegKeyExA(); 1407 else 1408 win_skip("SetupDiOpenClassRegKeyExA is not available\n"); 1409 1410 testInstallClass(); 1411 testCreateDeviceInfo(); 1412 testGetDeviceInstanceId(); 1413 testRegisterDeviceInfo(); 1414 testCreateDeviceInterface(); 1415 testGetDeviceInterfaceDetail(); 1416 testDevRegKey(); 1417 testRegisterAndGetDetail(); 1418 testDeviceRegistryPropertyA(); 1419 testDeviceRegistryPropertyW(); 1420 if (!winetest_interactive) 1421 { 1422 win_skip("testSetupDiGetINFClassA(), ROSTESTS-66.\n"); 1423 } 1424 else 1425 { 1426 testSetupDiGetINFClassA(); 1427 } 1428 testSetupDiGetClassDevsA(); 1429 } 1430