diff --git a/modules/rostests/winetests/setupapi/CMakeLists.txt b/modules/rostests/winetests/setupapi/CMakeLists.txt index 82227b7499d..cf2ce4b449c 100644 --- a/modules/rostests/winetests/setupapi/CMakeLists.txt +++ b/modules/rostests/winetests/setupapi/CMakeLists.txt @@ -2,6 +2,7 @@ add_definitions( -D__WINESRC__ -Dstrcasecmp=_stricmp + -Dstrncasecmp=_strnicmp ) remove_definitions(-D_CRT_NON_CONFORMING_SWPRINTFS) diff --git a/modules/rostests/winetests/setupapi/coinst.c b/modules/rostests/winetests/setupapi/coinst.c index dd64b15cca8..5e8d890cfa5 100644 --- a/modules/rostests/winetests/setupapi/coinst.c +++ b/modules/rostests/winetests/setupapi/coinst.c @@ -49,3 +49,23 @@ DWORD WINAPI class_error(DI_FUNCTION function, HDEVINFO set, SP_DEVINFO_DATA *de { return 0xdeadbeef; } + +DWORD WINAPI co_success(DI_FUNCTION function, HDEVINFO set, SP_DEVINFO_DATA *device, + COINSTALLER_CONTEXT_DATA *context) +{ + callback_count++; + last_message = function; + return ERROR_SUCCESS; +} + +DWORD WINAPI CoDeviceInstall(DI_FUNCTION function, HDEVINFO set, SP_DEVINFO_DATA *device, + COINSTALLER_CONTEXT_DATA *context) +{ + return co_success(function, set, device, context); +} + +DWORD WINAPI co_error(DI_FUNCTION function, HDEVINFO set, SP_DEVINFO_DATA *device, + COINSTALLER_CONTEXT_DATA *context) +{ + return 0xdeadbeef; +} diff --git a/modules/rostests/winetests/setupapi/coinst.spec b/modules/rostests/winetests/setupapi/coinst.spec index 34a5fdde6d3..bbfd316b4b5 100644 --- a/modules/rostests/winetests/setupapi/coinst.spec +++ b/modules/rostests/winetests/setupapi/coinst.spec @@ -2,5 +2,8 @@ @ stdcall ClassInstall(long ptr ptr) @ stdcall class_default(long ptr ptr) @ stdcall class_error(long ptr ptr) +@ stdcall co_success(long ptr ptr ptr) +@ stdcall CoDeviceInstall(long ptr ptr ptr) +@ stdcall co_error(long ptr ptr ptr) @ extern callback_count @ extern last_message diff --git a/modules/rostests/winetests/setupapi/devinst.c b/modules/rostests/winetests/setupapi/devinst.c index ba52eaf37b8..81ee1cf2a14 100644 --- a/modules/rostests/winetests/setupapi/devinst.c +++ b/modules/rostests/winetests/setupapi/devinst.c @@ -41,6 +41,8 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); /* This is a unique guid for testing purposes */ static GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}}; static GUID guid2 = {0x6a55b5a5, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}}; +static GUID iface_guid = {0xdeadbeef, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}}; +static GUID iface_guid2 = {0xdeadf00d, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}}; BOOL (WINAPI *pSetupDiSetDevicePropertyW)(HDEVINFO, PSP_DEVINFO_DATA, const DEVPROPKEY *, DEVPROPTYPE, const BYTE *, DWORD, DWORD); BOOL (WINAPI *pSetupDiGetDevicePropertyW)(HDEVINFO, PSP_DEVINFO_DATA, const DEVPROPKEY *, DEVPROPTYPE *, BYTE *, DWORD, DWORD *, DWORD); @@ -202,7 +204,8 @@ static void test_install_class(void) ret = SetupDiInstallClassA(NULL, tmpfile, 0, NULL); ok(ret, "Failed to install class, error %#x.\n", GetLastError()); - ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey), "Failed to delete class key, error %u.\n", GetLastError()); + ret = RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey); + ok(!ret, "Failed to delete class key, error %u.\n", GetLastError()); DeleteFileA(tmpfile); } @@ -1059,8 +1062,8 @@ static void test_device_iface(void) { char buffer[200]; SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buffer; + SP_DEVINFO_DATA device = {0}, device2 = {sizeof(device2)}; SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; - SP_DEVINFO_DATA device = {0}; BOOL ret; HDEVINFO set; @@ -1158,6 +1161,16 @@ static void test_device_iface(void) check_device_iface(set, &device, &guid, 1, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\test"); check_device_iface(set, &device, &guid, 2, 0, NULL); + ret = SetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0001", &guid, NULL, NULL, 0, &device2); + ok(ret, "Failed to create device, error %#x.\n", GetLastError()); + ret = SetupDiCreateDeviceInterfaceA(set, &device2, &guid, NULL, 0, NULL); + ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); + + check_device_iface(set, NULL, &guid, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\Oogah"); + check_device_iface(set, NULL, &guid, 1, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\test"); + check_device_iface(set, NULL, &guid, 2, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0001#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}"); + check_device_iface(set, NULL, &guid, 3, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); } @@ -2424,8 +2437,8 @@ static void test_class_installer(void) SetupDiDestroyDeviceInfoList(set); - todo_wine ok(*coinst_callback_count == 1, "Got %d callbacks.\n", *coinst_callback_count); - todo_wine ok(*coinst_last_message == DIF_DESTROYPRIVATEDATA, "Got unexpected message %#x.\n", *coinst_last_message); + ok(*coinst_callback_count == 1, "Got %d callbacks.\n", *coinst_callback_count); + ok(*coinst_last_message == DIF_DESTROYPRIVATEDATA, "Got unexpected message %#x.\n", *coinst_last_message); *coinst_callback_count = 0; /* Test returning an error. */ @@ -2502,8 +2515,8 @@ static void test_class_installer(void) SetupDiDestroyDeviceInfoList(set); - todo_wine ok(*coinst_callback_count == 1, "Got %d callbacks.\n", *coinst_callback_count); - todo_wine ok(*coinst_last_message == DIF_DESTROYPRIVATEDATA, "Got unexpected message %#x.\n", *coinst_last_message); + ok(*coinst_callback_count == 1, "Got %d callbacks.\n", *coinst_callback_count); + ok(*coinst_last_message == DIF_DESTROYPRIVATEDATA, "Got unexpected message %#x.\n", *coinst_last_message); *coinst_callback_count = 0; res = RegDeleteKeyA(class_key, ""); @@ -2511,6 +2524,126 @@ static void test_class_installer(void) RegCloseKey(class_key); } +static void test_class_coinstaller(void) +{ + SP_DEVINFO_DATA device = {sizeof(device)}; + char regdata[200]; + HKEY coinst_key; + HDEVINFO set; + BOOL ret; + LONG res; + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\CoDeviceInstallers", &coinst_key); + ok(!res, "Failed to open CoDeviceInstallers key, error %u.\n", res); + strcpy(regdata, "winetest_coinst.dll,co_success"); + regdata[strlen(regdata) + 1] = 0; + res = RegSetValueExA(coinst_key, "{6a55b5a4-3f65-11db-b704-0011955c2bdb}", 0, + REG_MULTI_SZ, (BYTE *)regdata, strlen(regdata) + 2); + ok(!res, "Failed to set registry value, error %u.\n", res); + + /* We must recreate the device list, or Windows will not recognize that the + * class co-installer exists. */ + set = SetupDiCreateDeviceInfoList(&guid, NULL); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device); + ok(ret, "Failed to create device, error %#x.\n", GetLastError()); + + ret = SetupDiCallClassInstaller(DIF_ALLOW_INSTALL, set, &device); + ok(!ret, "Expected failure.\n"); + ok(GetLastError() == ERROR_DI_DO_DEFAULT, "Got unexpected error %#x.\n", GetLastError()); + + ok(*coinst_callback_count == 1, "Got %d callbacks.\n", *coinst_callback_count); + ok(*coinst_last_message == DIF_ALLOW_INSTALL, "Got unexpected message %#x.\n", *coinst_last_message); + *coinst_callback_count = 0; + + ret = SetupDiCallClassInstaller(0xdeadbeef, set, &device); + ok(!ret, "Expected failure.\n"); + ok(GetLastError() == ERROR_DI_DO_DEFAULT, "Got unexpected error %#x.\n", GetLastError()); + + ok(*coinst_callback_count == 1, "Got %d callbacks.\n", *coinst_callback_count); + ok(*coinst_last_message == 0xdeadbeef, "Got unexpected message %#x.\n", *coinst_last_message); + *coinst_callback_count = 0; + + ok(!device_is_registered(set, &device), "Expected device not to be registered.\n"); + ret = SetupDiCallClassInstaller(DIF_REGISTERDEVICE, set, &device); + ok(ret, "Failed to call class installer, error %#x.\n", GetLastError()); + ok(device_is_registered(set, &device), "Expected device to be registered.\n"); + + ok(*coinst_callback_count == 1, "Got %d callbacks.\n", *coinst_callback_count); + ok(*coinst_last_message == DIF_REGISTERDEVICE, "Got unexpected message %#x.\n", *coinst_last_message); + *coinst_callback_count = 0; + + ret = SetupDiCallClassInstaller(DIF_REMOVE, set, &device); + ok(ret, "Failed to call class installer, error %#x.\n", GetLastError()); + ok(!device_is_registered(set, &device), "Expected device not to be registered.\n"); + + ok(*coinst_callback_count == 1, "Got %d callbacks.\n", *coinst_callback_count); + ok(*coinst_last_message == DIF_REMOVE, "Got unexpected message %#x.\n", *coinst_last_message); + *coinst_callback_count = 0; + + SetupDiDestroyDeviceInfoList(set); + + todo_wine ok(*coinst_callback_count == 1, "Got %d callbacks.\n", *coinst_callback_count); + todo_wine ok(*coinst_last_message == DIF_DESTROYPRIVATEDATA, "Got unexpected message %#x.\n", *coinst_last_message); + *coinst_callback_count = 0; + + /* Test returning an error from the co-installer. */ + + strcpy(regdata, "winetest_coinst.dll,co_error"); + regdata[strlen(regdata) + 1] = 0; + res = RegSetValueExA(coinst_key, "{6a55b5a4-3f65-11db-b704-0011955c2bdb}", 0, + REG_MULTI_SZ, (BYTE *)regdata, strlen(regdata) + 2); + ok(!res, "Failed to set registry value, error %u.\n", res); + + set = SetupDiCreateDeviceInfoList(&guid, NULL); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device); + ok(ret, "Failed to create device, error %#x.\n", GetLastError()); + + ret = SetupDiCallClassInstaller(DIF_ALLOW_INSTALL, set, &device); + ok(!ret, "Expected failure.\n"); + ok(GetLastError() == 0xdeadbeef, "Got unexpected error %#x.\n", GetLastError()); + + ok(!device_is_registered(set, &device), "Expected device not to be registered.\n"); + ret = SetupDiCallClassInstaller(DIF_REGISTERDEVICE, set, &device); + ok(!ret, "Expected failure.\n"); + ok(GetLastError() == 0xdeadbeef, "Got unexpected error %#x.\n", GetLastError()); + ok(!device_is_registered(set, &device), "Expected device not to be registered.\n"); + + SetupDiDestroyDeviceInfoList(set); + + /* The default entry point is CoDeviceInstall(). */ + + strcpy(regdata, "winetest_coinst.dll"); + regdata[strlen(regdata) + 1] = 0; + res = RegSetValueExA(coinst_key, "{6a55b5a4-3f65-11db-b704-0011955c2bdb}", 0, + REG_MULTI_SZ, (BYTE *)regdata, strlen(regdata) + 2); + ok(!res, "Failed to set registry value, error %u.\n", res); + + set = SetupDiCreateDeviceInfoList(&guid, NULL); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device); + ok(ret, "Failed to create device, error %#x.\n", GetLastError()); + + ret = SetupDiCallClassInstaller(DIF_ALLOW_INSTALL, set, &device); + ok(!ret, "Expected failure.\n"); + ok(GetLastError() == ERROR_DI_DO_DEFAULT, "Got unexpected error %#x.\n", GetLastError()); + + ok(*coinst_callback_count == 1, "Got %d callbacks.\n", *coinst_callback_count); + ok(*coinst_last_message == DIF_ALLOW_INSTALL, "Got unexpected message %#x.\n", *coinst_last_message); + *coinst_callback_count = 0; + + SetupDiDestroyDeviceInfoList(set); + + ok(*coinst_callback_count == 1, "Got %d callbacks.\n", *coinst_callback_count); + ok(*coinst_last_message == DIF_DESTROYPRIVATEDATA, "Got unexpected message %#x.\n", *coinst_last_message); + *coinst_callback_count = 0; + + res = RegDeleteValueA(coinst_key, "{6a55b5a4-3f65-11db-b704-0011955c2bdb}"); + ok(!res, "Failed to delete value, error %u.\n", res); + RegCloseKey(coinst_key); +} + static void test_call_class_installer(void) { SP_DEVINFO_DATA device = {sizeof(device)}; @@ -2557,6 +2690,7 @@ static void test_call_class_installer(void) coinst_last_message = (void *)GetProcAddress(coinst, "last_message"); test_class_installer(); + test_class_coinstaller(); FreeLibrary(coinst); @@ -2564,6 +2698,312 @@ static void test_call_class_installer(void) ok(ret, "Failed to delete file, error %u.\n", GetLastError()); } +static void check_all_devices_enumerated_(int line, HDEVINFO set, BOOL expect_dev3) +{ + SP_DEVINFO_DATA device = {sizeof(device)}; + BOOL ret, found_dev1 = 0, found_dev2 = 0, found_dev3 = 0; + char id[50]; + DWORD i; + + for (i = 0; SetupDiEnumDeviceInfo(set, i, &device); ++i) + { + ret = SetupDiGetDeviceInstanceIdA(set, &device, id, sizeof(id), NULL); + if (!ret) continue; + + if (!strcasecmp(id, "Root\\LEGACY_BOGUS\\foo")) + { + found_dev1 = 1; + ok_(__FILE__, line)(IsEqualGUID(&device.ClassGuid, &guid), + "Got unexpected class %s.\n", wine_dbgstr_guid(&device.ClassGuid)); + } + else if (!strcasecmp(id, "Root\\LEGACY_BOGUS\\qux")) + { + found_dev2 = 1; + ok_(__FILE__, line)(IsEqualGUID(&device.ClassGuid, &guid), + "Got unexpected class %s.\n", wine_dbgstr_guid(&device.ClassGuid)); + } + else if (!strcasecmp(id, "Root\\LEGACY_BOGUS\\bar")) + { + found_dev3 = 1; + ok_(__FILE__, line)(IsEqualGUID(&device.ClassGuid, &guid2), + "Got unexpected class %s.\n", wine_dbgstr_guid(&device.ClassGuid)); + } + } + ok_(__FILE__, line)(found_dev1, "Expected device 1 to be enumerated.\n"); + ok_(__FILE__, line)(found_dev2, "Expected device 2 to be enumerated.\n"); + ok_(__FILE__, line)(found_dev3 == expect_dev3, "Expected device 2 %sto be enumerated.\n", + expect_dev3 ? "" : "not "); +} +#define check_all_devices_enumerated(a,b) check_all_devices_enumerated_(__LINE__,a,b) + +static void check_device_list_(int line, HDEVINFO set, const GUID *expect) +{ + SP_DEVINFO_LIST_DETAIL_DATA_A detail = {sizeof(detail)}; + BOOL ret = SetupDiGetDeviceInfoListDetailA(set, &detail); + ok_(__FILE__, line)(ret, "Failed to get list detail, error %#x.\n", GetLastError()); + ok_(__FILE__, line)(IsEqualGUID(&detail.ClassGuid, expect), "Expected class %s, got %s\n", + wine_dbgstr_guid(expect), wine_dbgstr_guid(&detail.ClassGuid)); +} +#define check_device_list(a,b) check_device_list_(__LINE__,a,b) + +static void test_get_class_devs(void) +{ + SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; + SP_DEVINFO_DATA device = {sizeof(device)}; + HDEVINFO set; + BOOL ret; + + set = SetupDiCreateDeviceInfoList(NULL, NULL); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + + ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\foo", &guid, NULL, NULL, 0, &device); + ok(ret, "Failed to create device, error %#x.\n", GetLastError()); + ret = SetupDiCreateDeviceInterfaceA(set, &device, &iface_guid, NULL, 0, &iface); + ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); + ret = SetupDiCreateDeviceInterfaceA(set, &device, &iface_guid2, NULL, 0, &iface); + ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); + ret = SetupDiRegisterDeviceInfo(set, &device, 0, NULL, NULL, NULL); + ok(ret, "Failed to register device, error %#x.\n", GetLastError()); + + ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\qux", &guid, NULL, NULL, 0, &device); + ok(ret, "Failed to create device, error %#x.\n", GetLastError()); + ret = SetupDiCreateDeviceInterfaceA(set, &device, &iface_guid, NULL, 0, &iface); + ok(ret, "Failed to create interface, error %#x.\n", GetLastError()); + ret = SetupDiRegisterDeviceInfo(set, &device, 0, NULL, NULL, NULL); + ok(ret, "Failed to register device, error %#x.\n", GetLastError()); + + ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\bar", &guid2, NULL, NULL, 0, &device); + ok(ret, "Failed to create device, error %#x.\n", GetLastError()); + ret = SetupDiRegisterDeviceInfo(set, &device, 0, NULL, NULL, NULL); + ok(ret, "Failed to register device, error %#x.\n", GetLastError()); + + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + SetLastError(0xdeadbeef); + set = SetupDiGetClassDevsA(NULL, NULL, NULL, 0); + ok(set == INVALID_HANDLE_VALUE, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(NULL, NULL, NULL, DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); + check_all_devices_enumerated(set, TRUE); + check_device_iface(set, NULL, &iface_guid, 0, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(&guid, NULL, NULL, 0); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &guid); + check_device_info(set, 0, &guid, "ROOT\\LEGACY_BOGUS\\FOO"); + check_device_info(set, 1, &guid, "ROOT\\LEGACY_BOGUS\\QUX"); + check_device_info(set, 2, NULL, NULL); + check_device_iface(set, NULL, &iface_guid, 0, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(&guid, NULL, NULL, DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); + check_all_devices_enumerated(set, TRUE); + check_device_iface(set, NULL, &iface_guid, 0, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + SetLastError(0xdeadbeef); + set = SetupDiGetClassDevsA(NULL, "ROOT", NULL, 0); + ok(set == INVALID_HANDLE_VALUE, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(NULL, "ROOT", NULL, DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); + check_all_devices_enumerated(set, TRUE); + check_device_iface(set, NULL, &iface_guid, 0, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(NULL, "ROOT\\LEGACY_BOGUS", NULL, DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); +todo_wine { + check_device_info(set, 0, &guid2, "ROOT\\LEGACY_BOGUS\\BAR"); + check_device_info(set, 1, &guid, "ROOT\\LEGACY_BOGUS\\FOO"); + check_device_info(set, 2, &guid, "ROOT\\LEGACY_BOGUS\\QUX"); +} + check_device_info(set, 3, NULL, NULL); + check_device_iface(set, NULL, &iface_guid, 0, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(&guid, "ROOT\\LEGACY_BOGUS", NULL, 0); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &guid); +todo_wine { + check_device_info(set, 0, &guid, "ROOT\\LEGACY_BOGUS\\FOO"); + check_device_info(set, 1, &guid, "ROOT\\LEGACY_BOGUS\\QUX"); +} + check_device_info(set, 2, NULL, NULL); + check_device_iface(set, NULL, &iface_guid, 0, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(&guid, "ROOT\\LEGACY_BOGUS", NULL, DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); +todo_wine { + check_device_info(set, 0, &guid2, "ROOT\\LEGACY_BOGUS\\BAR"); + check_device_info(set, 1, &guid, "ROOT\\LEGACY_BOGUS\\FOO"); + check_device_info(set, 2, &guid, "ROOT\\LEGACY_BOGUS\\QUX"); +} + check_device_info(set, 3, NULL, NULL); + check_device_iface(set, NULL, &iface_guid, 0, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + /* test DIGCF_DEVICE_INTERFACE */ + + SetLastError(0xdeadbeef); + set = SetupDiGetClassDevsA(NULL, NULL, NULL, DIGCF_DEVICEINTERFACE); + ok(set == INVALID_HANDLE_VALUE, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(NULL, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); + check_all_devices_enumerated(set, FALSE); + check_device_iface(set, NULL, &iface_guid, 0, 0, "\\\\?\\root#legacy_bogus#foo#{deadbeef-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid, 1, 0, "\\\\?\\root#legacy_bogus#qux#{deadbeef-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid, 2, 0, NULL); + check_device_iface(set, NULL, &iface_guid2, 0, 0, "\\\\?\\root#legacy_bogus#foo#{deadf00d-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid2, 1, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); + check_device_info(set, 0, NULL, NULL); + check_device_iface(set, NULL, &iface_guid, 0, 0, NULL); + check_device_iface(set, NULL, &iface_guid2, 0, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(&iface_guid, NULL, NULL, DIGCF_DEVICEINTERFACE); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); + check_device_info(set, 0, &guid, "ROOT\\LEGACY_BOGUS\\FOO"); + check_device_info(set, 1, &guid, "ROOT\\LEGACY_BOGUS\\QUX"); + check_device_info(set, 2, &guid, NULL); + check_device_iface(set, NULL, &iface_guid, 0, 0, "\\\\?\\root#legacy_bogus#foo#{deadbeef-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid, 1, 0, "\\\\?\\root#legacy_bogus#qux#{deadbeef-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid, 2, 0, NULL); + check_device_iface(set, NULL, &iface_guid2, 0, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(&iface_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); + check_all_devices_enumerated(set, FALSE); + check_device_iface(set, NULL, &iface_guid, 0, 0, "\\\\?\\root#legacy_bogus#foo#{deadbeef-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid, 1, 0, "\\\\?\\root#legacy_bogus#qux#{deadbeef-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid, 2, 0, NULL); + check_device_iface(set, NULL, &iface_guid2, 0, 0, "\\\\?\\root#legacy_bogus#foo#{deadf00d-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid2, 1, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + SetLastError(0xdeadbeef); + set = SetupDiGetClassDevsA(NULL, "ROOT", NULL, DIGCF_DEVICEINTERFACE); + ok(set == INVALID_HANDLE_VALUE, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError()); + + SetLastError(0xdeadbeef); + set = SetupDiGetClassDevsA(NULL, "ROOT", NULL, DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES); +todo_wine { + ok(set == INVALID_HANDLE_VALUE, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "Got unexpected error %#x.\n", GetLastError()); +} + + SetLastError(0xdeadbeef); + set = SetupDiGetClassDevsA(NULL, "ROOT\\LEGACY_BOGUS", NULL, DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES); +todo_wine { + ok(set == INVALID_HANDLE_VALUE, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "Got unexpected error %#x.\n", GetLastError()); +} + + set = SetupDiGetClassDevsA(NULL, "ROOT\\LEGACY_BOGUS\\foo", NULL, DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); + check_device_info(set, 0, &guid, "ROOT\\LEGACY_BOGUS\\FOO"); + check_device_info(set, 1, NULL, NULL); + check_device_iface(set, NULL, &iface_guid, 0, 0, "\\\\?\\root#legacy_bogus#foo#{deadbeef-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid, 1, 0, NULL); + check_device_iface(set, NULL, &iface_guid2, 0, 0, "\\\\?\\root#legacy_bogus#foo#{deadf00d-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid2, 1, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(NULL, "ROOT\\LEGACY_BOGUS\\bar", NULL, DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); + check_device_info(set, 0, NULL, NULL); + check_device_iface(set, NULL, &iface_guid, 0, 0, NULL); + check_device_iface(set, NULL, &iface_guid2, 0, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + SetLastError(0xdeadbeef); + set = SetupDiGetClassDevsA(&iface_guid, "ROOT\\LEGACY_BOGUS", NULL, DIGCF_DEVICEINTERFACE); +todo_wine { + ok(set == INVALID_HANDLE_VALUE, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "Got unexpected error %#x.\n", GetLastError()); +} + + SetLastError(0xdeadbeef); + set = SetupDiGetClassDevsA(&iface_guid, "ROOT\\LEGACY_BOGUS", NULL, DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES); +todo_wine { + ok(set == INVALID_HANDLE_VALUE, "Expected failure.\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "Got unexpected error %#x.\n", GetLastError()); +} + + set = SetupDiGetClassDevsA(&iface_guid, "ROOT\\LEGACY_BOGUS\\foo", NULL, DIGCF_DEVICEINTERFACE); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); + check_device_info(set, 0, &guid, "ROOT\\LEGACY_BOGUS\\FOO"); + check_device_info(set, 1, NULL, NULL); + check_device_iface(set, NULL, &iface_guid, 0, 0, "\\\\?\\root#legacy_bogus#foo#{deadbeef-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid, 1, 0, NULL); + check_device_iface(set, NULL, &iface_guid2, 0, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(&iface_guid, "ROOT\\LEGACY_BOGUS\\foo", NULL, DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError()); + check_device_list(set, &GUID_NULL); + check_device_info(set, 0, &guid, "ROOT\\LEGACY_BOGUS\\FOO"); + check_device_info(set, 1, NULL, NULL); + check_device_iface(set, NULL, &iface_guid, 0, 0, "\\\\?\\root#legacy_bogus#foo#{deadbeef-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid, 1, 0, NULL); + check_device_iface(set, NULL, &iface_guid2, 0, 0, "\\\\?\\root#legacy_bogus#foo#{deadf00d-3f65-11db-b704-0011955c2bdb}"); + check_device_iface(set, NULL, &iface_guid2, 1, 0, NULL); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError()); + + set = SetupDiGetClassDevsA(&guid, NULL, NULL, 0); + SetupDiEnumDeviceInfo(set, 0, &device); + SetupDiRemoveDevice(set, &device); + SetupDiEnumDeviceInfo(set, 1, &device); + SetupDiRemoveDevice(set, &device); + SetupDiDestroyDeviceInfoList(set); + set = SetupDiGetClassDevsA(&guid2, NULL, NULL, 0); + SetupDiEnumDeviceInfo(set, 0, &device); + SetupDiRemoveDevice(set, &device); + SetupDiDestroyDeviceInfoList(set); +} + START_TEST(devinst) { static BOOL (WINAPI *pIsWow64Process)(HANDLE, BOOL *); @@ -2601,4 +3041,5 @@ START_TEST(devinst) test_device_install_params(); test_driver_list(); test_call_class_installer(); + test_get_class_devs(); } diff --git a/modules/rostests/winetests/setupapi/install.c b/modules/rostests/winetests/setupapi/install.c index a0a45969a42..f9e55929f2e 100644 --- a/modules/rostests/winetests/setupapi/install.c +++ b/modules/rostests/winetests/setupapi/install.c @@ -574,6 +574,20 @@ static void test_install_svc_from(void) SetupCloseInfFile(infhandle); DeleteFileA(inffile); + strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n"); + strcat(inf, "[Winetest.Services]\n"); + strcat(inf, "AddService=,2\n"); + create_inf_file(inffile, inf); + sprintf(path, "%s\\%s", CURR_DIR, inffile); + infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL); + + SetLastError(0xdeadbeef); + ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0); + ok(ret, "Expected success\n"); + ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %08x\n", GetLastError()); + SetupCloseInfFile(infhandle); + DeleteFileA(inffile); + /* TODO: Test the Flags */ } diff --git a/modules/rostests/winetests/setupapi/misc.c b/modules/rostests/winetests/setupapi/misc.c index 9143cd4bd33..ce72a5d0b8a 100644 --- a/modules/rostests/winetests/setupapi/misc.c +++ b/modules/rostests/winetests/setupapi/misc.c @@ -45,27 +45,19 @@ static CHAR CURR_DIR[MAX_PATH]; */ static BOOL (WINAPI *pSetupGetFileCompressionInfoExA)(PCSTR, PSTR, DWORD, PDWORD, PDWORD, PDWORD, PUINT); -static BOOL (WINAPI *pSetupCopyOEMInfA)(PCSTR, PCSTR, DWORD, DWORD, PSTR, DWORD, PDWORD, PSTR *); static BOOL (WINAPI *pSetupQueryInfOriginalFileInformationA)(PSP_INF_INFORMATION, UINT, PSP_ALTPLATFORM_INFO, PSP_ORIGINAL_FILE_INFO_A); -static BOOL (WINAPI *pSetupUninstallOEMInfA)(PCSTR, DWORD, PVOID); -static void create_inf_file(LPCSTR filename) +static void create_file(const char *name, const char *data) { - DWORD dwNumberOfBytesWritten; - HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + HANDLE file; + DWORD size; + BOOL ret; - static const char data[] = - "[Version]\n" - "Signature=\"$Chicago$\"\n" - "AdvancedINF=2.5\n" - "[DefaultInstall]\n" - "RegisterOCXs=RegisterOCXsSection\n" - "[RegisterOCXsSection]\n" - "%%11%%\\ole32.dll\n"; - - WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL); - CloseHandle(hf); + file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + ok(file != INVALID_HANDLE_VALUE, "Failed to create %s, error %u.\n", name, GetLastError()); + ret = WriteFile(file, data, strlen(data), &size, NULL); + ok(ret && size == strlen(data), "Failed to write %s, error %u.\n", name, GetLastError()); + CloseHandle(file); } static void get_temp_filename(LPSTR path) @@ -84,19 +76,13 @@ static BOOL file_exists(LPSTR path) return GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES; } -static BOOL check_format(LPSTR path, LPSTR inf) +static BOOL is_in_inf_dir(const char *path) { - CHAR check[MAX_PATH]; - BOOL res; + char expect[MAX_PATH]; - static const CHAR format[] = "\\INF\\oem"; - - GetWindowsDirectoryA(check, MAX_PATH); - strcat(check, format); - res = CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, check, -1, path, strlen(check)) == CSTR_EQUAL && - path[strlen(check)] != '\\'; - - return (!inf) ? res : res && (inf == path + strlen(check) - 3); + GetWindowsDirectoryA(expect, sizeof(expect)); + strcat(expect, "\\inf\\"); + return !strncasecmp(path, expect, strrchr(path, '\\') - path); } static void test_original_file_name(LPCSTR original, LPCSTR dest) @@ -133,7 +119,6 @@ static void test_original_file_name(LPCSTR original, LPCSTR dest) res = pSetupQueryInfOriginalFileInformationA(pspii, 0, NULL, &spofi); ok(res, "SetupQueryInfOriginalFileInformationA failed with error %d\n", GetLastError()); ok(!spofi.OriginalCatalogName[0], "spofi.OriginalCatalogName should have been \"\" instead of \"%s\"\n", spofi.OriginalCatalogName); - todo_wine ok(!strcmp(original, spofi.OriginalInfName), "spofi.OriginalInfName of %s didn't match real original name %s\n", spofi.OriginalInfName, original); HeapFree(GetProcessHeap(), 0, pspii); @@ -143,32 +128,39 @@ static void test_original_file_name(LPCSTR original, LPCSTR dest) static void test_SetupCopyOEMInf(void) { - CHAR toolong[MAX_PATH * 2]; - CHAR path[MAX_PATH], dest[MAX_PATH]; - CHAR tmpfile[MAX_PATH], dest_save[MAX_PATH]; - LPSTR inf = NULL; + char path[MAX_PATH * 2], dest[MAX_PATH], tmpfile[MAX_PATH], orig_dest[MAX_PATH]; + char *filepart, pnf[MAX_PATH]; DWORD size; BOOL res; + static const char inf_data1[] = + "[Version]\n" + "Signature=\"$Chicago$\"\n" + "; This is a WINE test INF file\n"; + + static const char inf_data2[] = + "[Version]\n" + "Signature=\"$Chicago$\"\n" + "; This is another WINE test INF file\n"; + /* try NULL SourceInfFileName */ SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(NULL, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); + res = SetupCopyOEMInfA(NULL, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); ok(res == FALSE, "Expected FALSE, got %d\n", res); ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); /* try empty SourceInfFileName */ SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA("", NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); + res = SetupCopyOEMInfA("", NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); ok(res == FALSE, "Expected FALSE, got %d\n", res); ok(GetLastError() == ERROR_FILE_NOT_FOUND || - GetLastError() == ERROR_BAD_PATHNAME || /* Win98 */ GetLastError() == ERROR_INVALID_PARAMETER, /* Vista, W2K8 */ "Unexpected error : %d\n", GetLastError()); /* try a relative nonexistent SourceInfFileName */ SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA("nonexistent", NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); + res = SetupCopyOEMInfA("nonexistent", NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); ok(res == FALSE, "Expected FALSE, got %d\n", res); ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); @@ -177,30 +169,18 @@ static void test_SetupCopyOEMInf(void) strcpy(path, CURR_DIR); strcat(path, "\\nonexistent"); SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(path, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); + res = SetupCopyOEMInfA(path, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); ok(res == FALSE, "Expected FALSE, got %d\n", res); ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); - /* try a long SourceInfFileName */ - memset(toolong, 'a', MAX_PATH * 2); - toolong[MAX_PATH * 2 - 1] = '\0'; - SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(toolong, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); - ok(res == FALSE, "Expected FALSE, got %d\n", res); - ok(GetLastError() == ERROR_FILE_NOT_FOUND || - GetLastError() == ERROR_FILENAME_EXCED_RANGE, /* Win98 */ - "Expected ERROR_FILE_NOT_FOUND or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError()); - get_temp_filename(tmpfile); - create_inf_file(tmpfile); + create_file(tmpfile, inf_data1); /* try a relative SourceInfFileName */ SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(tmpfile, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); - ok(res == FALSE || - broken(res == TRUE), /* Win98 */ - "Expected FALSE, got %d\n", res); + res = SetupCopyOEMInfA(tmpfile, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); + ok(res == FALSE, "Expected FALSE, got %d\n", res); if (GetLastError() == ERROR_WRONG_INF_TYPE || GetLastError() == ERROR_UNSUPPORTED_TYPE /* Win7 */) { /* FIXME: @@ -212,152 +192,161 @@ static void test_SetupCopyOEMInf(void) return; } - ok(GetLastError() == ERROR_FILE_NOT_FOUND || - broken(GetLastError() == ERROR_SUCCESS), /* Win98 */ - "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); ok(file_exists(tmpfile), "Expected tmpfile to exist\n"); /* try SP_COPY_REPLACEONLY, dest does not exist */ SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_REPLACEONLY, NULL, 0, NULL, NULL); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_REPLACEONLY, NULL, 0, NULL, NULL); ok(res == FALSE, "Expected FALSE, got %d\n", res); ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); ok(file_exists(tmpfile), "Expected source inf to exist\n"); - /* try an absolute SourceInfFileName, without DestinationInfFileName */ + /* Test a successful call. */ strcpy(path, CURR_DIR); strcat(path, "\\"); strcat(path, tmpfile); SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, NULL, 0, NULL, NULL); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, sizeof(dest), NULL, NULL); if (!res && GetLastError() == ERROR_ACCESS_DENIED) { skip("SetupCopyOEMInfA() failed on insufficient permissions\n"); + DeleteFileA(tmpfile); return; } ok(res == TRUE, "Expected TRUE, got %d\n", res); ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError()); - ok(file_exists(path), "Expected source inf to exist\n"); + ok(file_exists(path), "Expected source inf to exist.\n"); + ok(file_exists(dest), "Expected dest file to exist.\n"); + ok(is_in_inf_dir(dest), "Got unexpected path '%s'.\n", dest); + strcpy(orig_dest, dest); + + /* Existing INF files are checked for a match. */ + SetLastError(0xdeadbeef); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, sizeof(dest), NULL, NULL); + ok(res == TRUE, "Expected TRUE, got %d\n", res); + ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError()); + ok(file_exists(path), "Expected source inf to exist.\n"); + ok(file_exists(dest), "Expected dest file to exist.\n"); + ok(!strcmp(orig_dest, dest), "Expected '%s', got '%s'.\n", orig_dest, dest); /* try SP_COPY_REPLACEONLY, dest exists */ SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_REPLACEONLY, NULL, 0, NULL, NULL); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_REPLACEONLY, dest, sizeof(dest), NULL, NULL); ok(res == TRUE, "Expected TRUE, got %d\n", res); ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError()); - ok(file_exists(path), "Expected source inf to exist\n"); + ok(file_exists(path), "Expected source inf to exist.\n"); + ok(file_exists(dest), "Expected dest file to exist.\n"); + ok(!strcmp(orig_dest, dest), "Expected '%s', got '%s'.\n", orig_dest, dest); - /* try SP_COPY_NOOVERWRITE */ + strcpy(dest, "aaa"); SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_NOOVERWRITE, dest, sizeof(dest), NULL, NULL); ok(res == FALSE, "Expected FALSE, got %d\n", res); ok(GetLastError() == ERROR_FILE_EXISTS, "Expected ERROR_FILE_EXISTS, got %d\n", GetLastError()); + ok(!strcmp(orig_dest, dest), "Expected '%s', got '%s'.\n", orig_dest, dest); - /* get the DestinationInfFileName */ SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, NULL, NULL); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, NULL, 0, NULL, NULL); ok(res == TRUE, "Expected TRUE, got %d\n", res); ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError()); - ok(strlen(dest) != 0, "Expected a non-zero length string\n"); - ok(file_exists(dest), "Expected destination inf to exist\n"); - ok(check_format(dest, NULL), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest); - ok(file_exists(path), "Expected source inf to exist\n"); + ok(file_exists(path), "Expected source inf to exist.\n"); + ok(file_exists(orig_dest), "Expected dest file to exist.\n"); - strcpy(dest_save, dest); - DeleteFileA(dest_save); - - /* get the DestinationInfFileName, DestinationInfFileNameSize is too small - * - inf is still copied - */ strcpy(dest, "aaa"); size = 0; SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, 5, &size, NULL); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, 5, &size, NULL); ok(res == FALSE, "Expected FALSE, got %d\n", res); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(file_exists(path), "Expected source inf to exist\n"); - ok(file_exists(dest_save), "Expected dest inf to exist\n"); + ok(file_exists(orig_dest), "Expected dest inf to exist\n"); ok(!strcmp(dest, "aaa"), "Expected dest to be unchanged\n"); - ok(size == strlen(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n"); + ok(size == strlen(orig_dest) + 1, "Got %d.\n", size); - /* get the DestinationInfFileName and DestinationInfFileNameSize */ SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, &size, NULL); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, sizeof(dest), &size, NULL); ok(res == TRUE, "Expected TRUE, got %d\n", res); ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError()); - ok(lstrlenA(dest) + 1 == size, "Expected sizes to match, got (%d, %d)\n", lstrlenA(dest), size); - ok(file_exists(dest), "Expected destination inf to exist\n"); - ok(check_format(dest, NULL), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest); - ok(file_exists(path), "Expected source inf to exist\n"); - ok(size == lstrlenA(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n"); + ok(!strcmp(orig_dest, dest), "Expected '%s', got '%s'.\n", orig_dest, dest); + ok(size == strlen(dest) + 1, "Got %d.\n", size); test_original_file_name(strrchr(path, '\\') + 1, dest); - /* get the DestinationInfFileName, DestinationInfFileNameSize, and DestinationInfFileNameComponent */ SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, MAX_PATH, &size, &inf); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, sizeof(dest), NULL, &filepart); ok(res == TRUE, "Expected TRUE, got %d\n", res); ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError()); - ok(lstrlenA(dest) + 1 == size, "Expected sizes to match, got (%d, %d)\n", lstrlenA(dest), size); - ok(file_exists(dest), "Expected destination inf to exist\n"); - ok((inf && inf[0] != 0) || - broken(!inf), /* Win98 */ - "Expected inf to point to the filename\n"); - ok(check_format(dest, inf), "Expected %%windir%%\\inf\\OEMx.inf, got %s\n", dest); - ok(file_exists(path), "Expected source inf to exist\n"); - ok(size == lstrlenA(dest_save) + 1, "Expected size to be lstrlen(dest_save) + 1\n"); + ok(!strcmp(orig_dest, dest), "Expected '%s', got '%s'.\n", orig_dest, dest); + ok(filepart == strrchr(dest, '\\') + 1, "Got unexpected file part %s.\n", filepart); - /* try SP_COPY_DELETESOURCE */ SetLastError(0xdeadbeef); - res = pSetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_DELETESOURCE, NULL, 0, NULL, NULL); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, SP_COPY_DELETESOURCE, NULL, 0, NULL, NULL); ok(res == TRUE, "Expected TRUE, got %d\n", res); ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError()); ok(!file_exists(path), "Expected source inf to not exist\n"); - if (pSetupUninstallOEMInfA) - { - char pnf[MAX_PATH]; - char *pnffile; - char *destfile = strrchr(dest, '\\') + 1; + strcpy(pnf, dest); + *(strrchr(pnf, '.') + 1) = 'p'; - strcpy(pnf, dest); - *(strrchr(pnf, '.') + 1) = 'p'; - pnffile = strrchr(pnf, '\\') + 1; + res = SetupUninstallOEMInfA(strrchr(dest, '\\') + 1, 0, NULL); + ok(res, "Failed to uninstall '%s', error %u.\n", dest, GetLastError()); + todo_wine ok(!file_exists(dest), "Expected inf '%s' to not exist\n", dest); + DeleteFileA(dest); + ok(!file_exists(pnf), "Expected pnf '%s' to not exist\n", pnf); - SetLastError(0xdeadbeef); - res = pSetupUninstallOEMInfA(destfile, 0, NULL); - if(!res) - res = pSetupUninstallOEMInfA(pnffile, 0, NULL); - ok(res, "Failed to uninstall '%s'/'%s' : %d\n", destfile, - pnffile, GetLastError()); - todo_wine ok(!file_exists(dest), "Expected inf '%s' to not exist\n", dest); - if(file_exists(dest)) - { - SetLastError(0xdeadbeef); - res = DeleteFileA(dest); - ok(res, "Failed to delete file '%s' : %d\n", dest, GetLastError()); - } - ok(!file_exists(pnf), "Expected pnf '%s' to not exist\n", pnf); - if(file_exists(pnf)) - { - SetLastError(0xdeadbeef); - res = DeleteFileA(pnf); - ok(res, "Failed to delete file '%s' : %d\n", pnf, GetLastError()); - } - } - else - { - /* Win9x/WinMe */ - SetLastError(0xdeadbeef); - res = DeleteFileA(dest); - ok(res, "Failed to delete file '%s' : %d\n", dest, GetLastError()); + create_file(tmpfile, inf_data1); + SetLastError(0xdeadbeef); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, sizeof(dest), NULL, NULL); + ok(res == TRUE, "Expected TRUE, got %d\n", res); + ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError()); + ok(is_in_inf_dir(dest), "Got unexpected path '%s'.\n", dest); + strcpy(orig_dest, dest); - /* On WinMe we also need to remove the .pnf file */ - *(strrchr(dest, '.') + 1) = 'p'; - DeleteFileA(dest); - } + create_file(tmpfile, inf_data2); + SetLastError(0xdeadbeef); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, sizeof(dest), NULL, NULL); + ok(res == TRUE, "Expected TRUE, got %d\n", res); + ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError()); + ok(is_in_inf_dir(dest), "Got unexpected path '%s'.\n", dest); + ok(strcmp(dest, orig_dest), "Expected INF files to be copied to differnet paths.\n"); + + res = SetupUninstallOEMInfA(strrchr(dest, '\\') + 1, 0, NULL); + ok(res, "Failed to uninstall '%s', error %u.\n", dest, GetLastError()); + todo_wine ok(!file_exists(dest), "Expected inf '%s' to not exist\n", dest); + DeleteFileA(dest); + strcpy(pnf, dest); + *(strrchr(pnf, '.') + 1) = 'p'; + ok(!file_exists(pnf), "Expected pnf '%s' to not exist\n", pnf); + + res = SetupUninstallOEMInfA(strrchr(orig_dest, '\\') + 1, 0, NULL); + ok(res, "Failed to uninstall '%s', error %u.\n", orig_dest, GetLastError()); + todo_wine ok(!file_exists(orig_dest), "Expected inf '%s' to not exist\n", dest); + DeleteFileA(orig_dest); + strcpy(pnf, dest); + *(strrchr(pnf, '.') + 1) = 'p'; + ok(!file_exists(pnf), "Expected pnf '%s' to not exist\n", pnf); + + GetWindowsDirectoryA(orig_dest, sizeof(orig_dest)); + strcat(orig_dest, "\\inf\\"); + strcat(orig_dest, tmpfile); + res = CopyFileA(tmpfile, orig_dest, TRUE); + ok(res, "Failed to copy file, error %u.\n", GetLastError()); + SetLastError(0xdeadbeef); + res = SetupCopyOEMInfA(path, NULL, SPOST_NONE, 0, dest, sizeof(dest), NULL, NULL); + ok(res == TRUE, "Expected TRUE, got %d\n", res); + ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError()); + ok(!strcasecmp(dest, orig_dest), "Expected '%s', got '%s'.\n", orig_dest, dest); + + /* Since it wasn't actually installed, SetupUninstallOEMInf would fail here. */ + res = DeleteFileA(dest); + ok(res, "Failed to delete '%s', error %u.\n", tmpfile, GetLastError()); + + res = DeleteFileA(tmpfile); + ok(res, "Failed to delete '%s', error %u.\n", tmpfile, GetLastError()); } static void create_source_file(LPSTR filename, const BYTE *data, DWORD size) @@ -716,12 +705,12 @@ static void test_SetupUninstallOEMInf(void) BOOL ret; SetLastError(0xdeadbeef); - ret = pSetupUninstallOEMInfA(NULL, 0, NULL); + ret = SetupUninstallOEMInfA(NULL, 0, NULL); ok(!ret, "Expected failure\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); SetLastError(0xdeadbeef); - ret = pSetupUninstallOEMInfA("", 0, NULL); + ret = SetupUninstallOEMInfA("", 0, NULL); todo_wine { ok(!ret, "Expected failure\n"); @@ -729,7 +718,7 @@ static void test_SetupUninstallOEMInf(void) } SetLastError(0xdeadbeef); - ret = pSetupUninstallOEMInfA("nonexistent.inf", 0, NULL); + ret = SetupUninstallOEMInfA("nonexistent.inf", 0, NULL); todo_wine { ok(!ret, "Expected failure\n"); @@ -835,17 +824,11 @@ START_TEST(misc) HMODULE hsetupapi = GetModuleHandleA("setupapi.dll"); pSetupGetFileCompressionInfoExA = (void*)GetProcAddress(hsetupapi, "SetupGetFileCompressionInfoExA"); - pSetupCopyOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupCopyOEMInfA"); pSetupQueryInfOriginalFileInformationA = (void*)GetProcAddress(hsetupapi, "SetupQueryInfOriginalFileInformationA"); - pSetupUninstallOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupUninstallOEMInfA"); GetCurrentDirectoryA(MAX_PATH, CURR_DIR); - if (pSetupCopyOEMInfA) - test_SetupCopyOEMInf(); - else - win_skip("SetupCopyOEMInfA is not available\n"); - + test_SetupCopyOEMInf(); test_SetupGetFileCompressionInfo(); if (pSetupGetFileCompressionInfoExA) @@ -854,14 +837,8 @@ START_TEST(misc) win_skip("SetupGetFileCompressionInfoExA is not available\n"); test_SetupDecompressOrCopyFile(); - - if (pSetupUninstallOEMInfA) - test_SetupUninstallOEMInf(); - else - win_skip("SetupUninstallOEMInfA is not available\n"); - + test_SetupUninstallOEMInf(); test_defaultcallback(); - test_SetupLogError(); test_CM_Get_Version(); } diff --git a/sdk/tools/winesync/setupapi.cfg b/sdk/tools/winesync/setupapi.cfg index ce4232f3e89..8f8f7502b4a 100644 --- a/sdk/tools/winesync/setupapi.cfg +++ b/sdk/tools/winesync/setupapi.cfg @@ -10,4 +10,4 @@ files: dlls/setupapi/setupcab.c: dll/win32/setupapi/setupcab.c dlls/setupapi/stringtable.c: dll/win32/setupapi/stringtable_wine.c tags: - wine: fce26e60cc2400f3f3da27c221dce95593dd400e + wine: dae160ceda33598632597527cb56090acf58f60d