Index: dll/win32/setupapi/parser.c =================================================================== --- dll/win32/setupapi/parser.c (revision 56642) +++ dll/win32/setupapi/parser.c (working copy) @@ -2284,6 +2284,12 @@ TRACE("%s %p %p %ld %p\n", debugstr_w(InfName), ClassGuid, ClassName, ClassNameSize, RequiredSize); + if (!InfName) + { + SetLastError(ERROR_INVALID_PARAMETER); + goto cleanup; + } + /* Open .inf file */ hInf = SetupOpenInfFileW(InfName, NULL, INF_STYLE_WIN4, NULL); if (hInf == INVALID_HANDLE_VALUE) Index: include/psdk/setupapi.h =================================================================== --- include/psdk/setupapi.h (revision 56642) +++ include/psdk/setupapi.h (working copy) @@ -279,7 +279,6 @@ #define ERROR_SECTION_NAME_TOO_LONG (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|2) #define ERROR_GENERAL_SYNTAX (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|3) #define ERROR_WRONG_INF_STYLE (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x100) -#define ERROR_NOT_INSTALLED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x1000) #define ERROR_SECTION_NOT_FOUND (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x101) #define ERROR_LINE_NOT_FOUND (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x102) #define ERROR_NO_BACKUP (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x103) @@ -334,11 +333,38 @@ #define ERROR_DEVINSTALL_QUEUE_NONNATIVE (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x230) #define ERROR_NOT_DISABLEABLE (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x231) #define ERROR_CANT_REMOVE_DEVINST (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x232) +#define ERROR_INVALID_TARGET (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x233) +#define ERROR_DRIVER_NONNATIVE (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x234) +#define ERROR_IN_WOW64 (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x235) +#define ERROR_SET_SYSTEM_RESTORE_POINT (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x236) +#define ERROR_SCE_DISABLED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x238) +#define ERROR_UNKNOWN_EXCEPTION (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x239) +#define ERROR_PNP_REGISTRY_ERROR (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x23A) +#define ERROR_REMOTE_REQUEST_UNSUPPORTED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x23B) +#define ERROR_NOT_AN_INSTALLED_OEM_INF (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x23C) +#define ERROR_INF_IN_USE_BY_DEVICES (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x23D) +#define ERROR_DI_FUNCTION_OBSOLETE (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x23E) +#define ERROR_NO_AUTHENTICODE_CATALOG (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x23F) +#define ERROR_AUTHENTICODE_DISALLOWED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x240) +#define ERROR_AUTHENTICODE_TRUSTED_PUBLISHER (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x241) +#define ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x242) +#define ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x243) +#define ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x244) +#define ERROR_ONLY_VALIDATE_VIA_AUTHENTICODE (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x245) +#define ERROR_DEVICE_INSTALLER_NOT_READY (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x246) +#define ERROR_DRIVER_STORE_ADD_FAILED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x247) +#define ERROR_DEVICE_INSTALL_BLOCKED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x248) +#define ERROR_DRIVER_INSTALL_BLOCKED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x249) +#define ERROR_WRONG_INF_TYPE (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x24A) +#define ERROR_FILE_HASH_NOT_IN_CATALOG (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x24B) +#define ERROR_DRIVER_STORE_DELETE_FAILED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x24C) + +#define ERROR_NOT_INSTALLED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x1000) + #define ERROR_INTERFACE_DEVICE_ACTIVE ERROR_DEVICE_INTERFACE_ACTIVE #define ERROR_INTERFACE_DEVICE_REMOVED ERROR_DEVICE_INTERFACE_REMOVED #define ERROR_NO_DEFAULT_INTERFACE_DEVICE ERROR_NO_DEFAULT_DEVICE_INTERFACE #define ERROR_NO_SUCH_INTERFACE_DEVICE ERROR_NO_SUCH_DEVICE_INTERFACE -#define ERROR_WRONG_INF_TYPE (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x24A) #define FILEOP_COPY 0 #define FILEOP_ABORT 0 Index: modules/rostests/winetests/setupapi/devinst.c =================================================================== --- modules/rostests/winetests/setupapi/devinst.c (revision 56642) +++ modules/rostests/winetests/setupapi/devinst.c (working copy) @@ -18,9 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include #include #include + #include "windef.h" #include "winbase.h" #include "wingdi.h" @@ -31,8 +31,9 @@ #include "wine/test.h" +static BOOL is_wow64; + /* function pointers */ -static HMODULE hSetupAPI; static HDEVINFO (WINAPI *pSetupDiCreateDeviceInfoList)(GUID*,HWND); static HDEVINFO (WINAPI *pSetupDiCreateDeviceInfoListExW)(GUID*,HWND,PCWSTR,PVOID); static BOOL (WINAPI *pSetupDiCreateDeviceInterfaceA)(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, PCSTR, DWORD, PSP_DEVICE_INTERFACE_DATA); @@ -40,6 +41,7 @@ static BOOL (WINAPI *pSetupDiDestroyDeviceInfoList)(HDEVINFO); static BOOL (WINAPI *pSetupDiEnumDeviceInfo)(HDEVINFO, DWORD, PSP_DEVINFO_DATA); static BOOL (WINAPI *pSetupDiEnumDeviceInterfaces)(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, DWORD, PSP_DEVICE_INTERFACE_DATA); +static BOOL (WINAPI *pSetupDiGetINFClassA)(PCSTR, LPGUID, PSTR, DWORD, PDWORD); static BOOL (WINAPI *pSetupDiInstallClassA)(HWND, PCSTR, DWORD, HSPFILEQ); static HKEY (WINAPI *pSetupDiOpenClassRegKeyExA)(GUID*,REGSAM,DWORD,PCSTR,PVOID); static HKEY (WINAPI *pSetupDiOpenDevRegKey)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM); @@ -56,13 +58,15 @@ static BOOL (WINAPI *pSetupDiSetDeviceRegistryPropertyW)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, const BYTE *, DWORD); static BOOL (WINAPI *pSetupDiGetDeviceRegistryPropertyA)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD); static BOOL (WINAPI *pSetupDiGetDeviceRegistryPropertyW)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD); +static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); /* This is a unique guid for testing purposes */ static GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}}; static void init_function_pointers(void) { - hSetupAPI = GetModuleHandleA("setupapi.dll"); + HMODULE hSetupAPI = GetModuleHandleA("setupapi.dll"); + HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA"); pSetupDiCreateDeviceInfoW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoW"); @@ -83,10 +87,12 @@ pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo"); pSetupDiGetClassDevsA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsA"); pSetupDiGetClassDevsW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsW"); + pSetupDiGetINFClassA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetINFClassA"); pSetupDiSetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyA"); pSetupDiSetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyW"); pSetupDiGetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyA"); pSetupDiGetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyW"); + pIsWow64Process = (void *)GetProcAddress(hKernel32, "IsWow64Process"); } static void change_reg_permissions(const WCHAR *regkey) @@ -126,7 +132,7 @@ { HDEVINFO set; SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } }; - BOOL ret; + BOOL ret, retval = FALSE; SetLastError(0xdeadbeef); set = pSetupDiGetClassDevsA(&guid, NULL, 0, 0); @@ -134,19 +140,26 @@ GetLastError()); SetLastError(0xdeadbeef); - ok(pSetupDiEnumDeviceInfo(set, 0, &devInfo), - "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError()); + ret = pSetupDiEnumDeviceInfo(set, 0, &devInfo); + ok(ret, "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError()); - SetLastError(0xdeadbeef); - ret = pSetupDiCallClassInstaller(DIF_REMOVE, set, &devInfo); - todo_wine - ok(ret, "SetupDiCallClassInstaller(DIF_REMOVE...) failed: %08x\n", GetLastError()); + if (ret) /* ReactOS */ + { + SetLastError(0xdeadbeef); + retval = pSetupDiCallClassInstaller(DIF_REMOVE, set, &devInfo); + if(is_wow64) + todo_wine ok(!retval && GetLastError() == ERROR_IN_WOW64, + "SetupDiCallClassInstaller(DIF_REMOVE...) succeeded: %08x\n", GetLastError()); + else + todo_wine ok(retval, + "SetupDiCallClassInstaller(DIF_REMOVE...) failed: %08x\n", GetLastError()); + } SetLastError(0xdeadbeef); - ok(pSetupDiDestroyDeviceInfoList(set), - "SetupDiDestroyDeviceInfoList failed: %08x\n", GetLastError()); + ret = pSetupDiDestroyDeviceInfoList(set); + ok(ret, "SetupDiDestroyDeviceInfoList failed: %08x\n", GetLastError()); - return ret; + return retval; } /* RegDeleteTreeW from dlls/advapi32/registry.c */ @@ -251,6 +264,7 @@ DWORD error; static CHAR notnull[] = "NotNull"; static const WCHAR machine[] = { 'd','u','m','m','y',0 }; + static const WCHAR empty[] = { 0 }; SetLastError(0xdeadbeef); /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */ @@ -280,6 +294,14 @@ /* destroy DeviceInfoList */ ret = pSetupDiDestroyDeviceInfoList(devlist); ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error); + + /* create empty DeviceInfoList with empty machine name */ + devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, empty, NULL); + ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE); + + /* destroy DeviceInfoList */ + ret = pSetupDiDestroyDeviceInfoList(devlist); + ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error); } static void test_SetupDiOpenClassRegKeyExA(void) @@ -955,7 +977,6 @@ key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DRV, 0); /* The software key isn't created by default */ - todo_wine ok(key == INVALID_HANDLE_VALUE && GetLastError() == ERROR_KEY_DOES_NOT_EXIST, "Expected ERROR_KEY_DOES_NOT_EXIST, got %08x\n", GetLastError()); @@ -1005,8 +1026,8 @@ /* Cleanup */ ret = remove_device(); - todo_wine - ok(ret, "Expected the device to be removed: %08x\n", GetLastError()); + if(!is_wow64) + todo_wine ok(ret, "Expected the device to be removed: %08x\n", GetLastError()); /* FIXME: Only do the RegDeleteKey, once Wine is fixed */ if (!ret) @@ -1089,8 +1110,10 @@ { static const char path[] = "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}"; + static const char path_wow64[] = + "\\\\?\\root#legacy_bogus#0001#{6a55b5a4-3f65-11db-b704-0011955c2bdb}"; static const char path_w2k[] = - "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\"; + "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\"; PSP_DEVICE_INTERFACE_DETAIL_DATA_A detail = NULL; detail = HeapAlloc(GetProcessHeap(), 0, dwSize); @@ -1104,10 +1127,13 @@ /* FIXME: This one only worked because old data wasn't removed properly. As soon * as all the tests are cleaned up correctly this has to be (or should be) fixed */ - todo_wine - ok(!lstrcmpiA(path, detail->DevicePath) || - !lstrcmpiA(path_w2k, detail->DevicePath), "Unexpected path %s\n", - detail->DevicePath); + if(is_wow64) + ok(!lstrcmpiA(path_wow64, detail->DevicePath), + "Unexpected path %s\n", detail->DevicePath); + else + todo_wine ok(!lstrcmpiA(path, detail->DevicePath) || + !lstrcmpiA(path_w2k, detail->DevicePath), + "Unexpected path %s\n", detail->DevicePath); HeapFree(GetProcessHeap(), 0, detail); } } @@ -1116,8 +1142,8 @@ /* Cleanup */ ret = remove_device(); - todo_wine - ok(ret, "Expected the device to be removed: %08x\n", GetLastError()); + if(!is_wow64) + todo_wine ok(ret, "Expected the device to be removed: %08x\n", GetLastError()); /* FIXME: Only do the RegDeleteKey, once Wine is fixed */ if (!ret) @@ -1226,8 +1252,8 @@ pSetupDiDestroyDeviceInfoList(set); res = RegOpenKeyA(HKEY_LOCAL_MACHINE, bogus, &key); - todo_wine - ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n"); + if(!is_wow64) + todo_wine ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n"); /* FIXME: Remove when Wine is fixed */ if (res == ERROR_SUCCESS) { @@ -1332,8 +1358,8 @@ pSetupDiDestroyDeviceInfoList(set); res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key); - todo_wine - ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n"); + if(!is_wow64) + todo_wine ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n"); /* FIXME: Remove when Wine is fixed */ if (res == ERROR_SUCCESS) { @@ -1343,24 +1369,183 @@ } } -START_TEST(devinst) +static void testSetupDiGetINFClassA(void) { - HDEVINFO set; + static const char inffile[] = "winetest.inf"; + static const char content[] = "[Version]\r\n\r\n"; - init_function_pointers(); + char cn[MAX_PATH]; + char filename[MAX_PATH]; + DWORD count; + BOOL retval; + GUID guid; + HANDLE h; - /* Win9x/WinMe does things totally different so we skip all the tests - * - * We don't want to exclude NT4 so hence this check. - */ + if(!pSetupDiGetINFClassA) + { + win_skip("SetupDiGetINFClassA not present\n"); + return; + } + + count = GetTempPathA(MAX_PATH, filename); + if(!count) + { + win_skip("GetTempPathA failed\n"); + return; + } + + strcat(filename, inffile); + DeleteFileA(filename); + + /* not existing file */ SetLastError(0xdeadbeef); - set = pSetupDiGetClassDevsW(NULL, NULL, 0, 0); - if (set == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + if (ERROR_CALL_NOT_IMPLEMENTED == GetLastError()) { - win_skip("Win9x/WinMe has totally different behavior\n"); + skip("SetupDiGetINFClassA is not implemented\n"); return; } + ok(ERROR_FILE_NOT_FOUND == GetLastError(), + "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); + /* missing file wins against other invalid parameter */ + SetLastError(0xdeadbeef); + retval = SetupDiGetINFClassA(filename, NULL, cn, MAX_PATH, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + ok(ERROR_FILE_NOT_FOUND == GetLastError(), + "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + retval = SetupDiGetINFClassA(filename, &guid, NULL, MAX_PATH, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + ok(ERROR_FILE_NOT_FOUND == GetLastError(), + "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + retval = SetupDiGetINFClassA(filename, &guid, cn, 0, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + ok(ERROR_FILE_NOT_FOUND == GetLastError(), + "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, NULL); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + ok(ERROR_FILE_NOT_FOUND == GetLastError(), + "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); + + /* test file content */ + h = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + if(h == INVALID_HANDLE_VALUE) + { + win_skip("failed to create file %s (error %u)\n", filename, GetLastError()); + return; + } + CloseHandle( h); + + retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + + h = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + if(h == INVALID_HANDLE_VALUE) + { + win_skip("failed to create file %s (error %u)\n", filename, GetLastError()); + return; + } + WriteFile( h, content, sizeof(content), &count, NULL); + CloseHandle( h); + + retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + + WritePrivateProfileStringA("Version", "Signature", "\"$CHICAGO$\"", filename); + + retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + + WritePrivateProfileStringA("Version", "Class", "WINE", filename); + + count = 0xdeadbeef; + retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); + ok(retval, "expected SetupDiGetINFClassA to succeed! error %u\n", GetLastError()); + ok(count == 5, "expected count==5, got %u\n", count); + + count = 0xdeadbeef; + retval = SetupDiGetINFClassA(filename, &guid, cn, 5, &count); + ok(retval, "expected SetupDiGetINFClassA to succeed! error %u\n", GetLastError()); + ok(count == 5, "expected count==5, got %u\n", count); + + count = 0xdeadbeef; + SetLastError(0xdeadbeef); + retval = SetupDiGetINFClassA(filename, &guid, cn, 4, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), + "expected error ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); + ok(count == 5, "expected count==5, got %u\n", count); + + /* invalid parameter */ + SetLastError(0xdeadbeef); + retval = SetupDiGetINFClassA(NULL, &guid, cn, MAX_PATH, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + ok(ERROR_INVALID_PARAMETER == GetLastError(), + "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + retval = SetupDiGetINFClassA(filename, NULL, cn, MAX_PATH, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + ok(ERROR_INVALID_PARAMETER == GetLastError(), + "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + retval = SetupDiGetINFClassA(filename, &guid, NULL, MAX_PATH, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + ok(ERROR_INVALID_PARAMETER == GetLastError(), + "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + retval = SetupDiGetINFClassA(filename, &guid, cn, 0, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + ok(ERROR_INSUFFICIENT_BUFFER == GetLastError() || + ERROR_INVALID_PARAMETER == GetLastError(), + "expected error ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER, " + "got %u\n", GetLastError()); + + DeleteFileA(filename); + + WritePrivateProfileStringA("Version", "Signature", "\"$CHICAGO$\"", filename); + WritePrivateProfileStringA("Version", "ClassGUID", "WINE", filename); + + SetLastError(0xdeadbeef); + retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); + ok(!retval, "expected SetupDiGetINFClassA to fail!\n"); + ok(RPC_S_INVALID_STRING_UUID == GetLastError() || + ERROR_INVALID_PARAMETER == GetLastError(), + "expected error RPC_S_INVALID_STRING_UUID or ERROR_INVALID_PARAMETER, " + "got %u\n", GetLastError()); + + /* network adapter guid */ + WritePrivateProfileStringA("Version", "ClassGUID", + "{4d36e972-e325-11ce-bfc1-08002be10318}", filename); + + /* this test succeeds only if the guid is known to the system */ + count = 0xdeadbeef; + retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count); + ok(retval, "expected SetupDiGetINFClassA to succeed! error %u\n", GetLastError()); + todo_wine + ok(count == 4, "expected count==4, got %u(%s)\n", count, cn); + + DeleteFileA(filename); +} + +START_TEST(devinst) +{ + init_function_pointers(); + + if (pIsWow64Process) + pIsWow64Process(GetCurrentProcess(), &is_wow64); + if (pSetupDiCreateDeviceInfoListExW) test_SetupDiCreateDeviceInfoListEx(); else @@ -1381,4 +1566,5 @@ testRegisterAndGetDetail(); testDeviceRegistryPropertyA(); testDeviceRegistryPropertyW(); + testSetupDiGetINFClassA(); }