diff --git a/sdk/tools/winesync/setupapi.cfg b/sdk/tools/winesync/setupapi.cfg new file mode 100644 index 00000000000..a061b8ecfec --- /dev/null +++ b/sdk/tools/winesync/setupapi.cfg @@ -0,0 +1,8 @@ +directories: null +files: + dlls/setupapi/devinst.c: dll/win32/setupapi/devinst.c + dlls/setupapi/install.c: dll/win32/setupapi/install.c + dlls/setupapi/misc.c: dll/win32/setupapi/misc.c + dlls/setupapi/stubs.c: dll/win32/setupapi/stubs.c +tags: + wine: wine-0.9.13 diff --git a/sdk/tools/winesync/setupapi_staging/0001-wine-staging-4.0-setupapi-dll.patch b/sdk/tools/winesync/setupapi_staging/0001-wine-staging-4.0-setupapi-dll.patch new file mode 100644 index 00000000000..7e049966632 --- /dev/null +++ b/sdk/tools/winesync/setupapi_staging/0001-wine-staging-4.0-setupapi-dll.patch @@ -0,0 +1,57 @@ +From e53b61c73dfb02450206ace1f7c9e90734344991 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= + +Date: Wed, 6 Sep 2023 21:59:48 +0200 +Subject: [PATCH 1/3] wine-staging 4.0 setupapi dll +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Hermès Bélusca-Maïto +--- + dll/win32/setupapi/dialog.c | 29 ++ + 1 files changed, 29 insertions(+) + +diff --git a/dll/win32/setupapi/dialog.c b/dll/win32/setupapi/dialog.c +index fc74cfc1727..4c4f8c6a840 100644 +--- a/dll/win32/setupapi/dialog.c ++++ b/dll/win32/setupapi/dialog.c +@@ -243,6 +243,35 @@ UINT WINAPI SetupPromptForDiskW(HWND hwndParent, PCWSTR DialogTitle, PCWSTR Disk + SetLastError(ERROR_INVALID_PARAMETER); + return DPROMPT_CANCEL; + } ++ ++ if (PathToSource && (DiskPromptStyle & IDF_CHECKFIRST)) ++ { ++ static const WCHAR format[] = {'%', 's', '\\', '%', 's', '\0'}; ++ WCHAR filepath[MAX_PATH]; ++ ++ if (strlenW(PathToSource) + 1 + strlenW(FileSought) < sizeof(filepath)) ++ { ++ snprintfW(filepath, MAX_PATH, format, PathToSource, FileSought); ++ ++ if (GetFileAttributesW(filepath) != INVALID_FILE_ATTRIBUTES) ++ { ++ if (PathRequiredSize) ++ *PathRequiredSize = strlenW(PathToSource) + 1; ++ ++ if (!PathBuffer) ++ return DPROMPT_SUCCESS; ++ ++ if (PathBufferSize >= strlenW(PathToSource) + 1) ++ { ++ strcpyW(PathBuffer, PathToSource); ++ return DPROMPT_SUCCESS; ++ } ++ else ++ return DPROMPT_BUFFERTOOSMALL; ++ } ++ } ++ } ++ + params.DialogTitle = DialogTitle; + params.DiskName = DiskName; + params.PathToSource = PathToSource; +-- +2.36.1.windows.1 + diff --git a/sdk/tools/winesync/setupapi_staging/0002-wine-staging-4.0-setupapi_winetest.patch b/sdk/tools/winesync/setupapi_staging/0002-wine-staging-4.0-setupapi_winetest.patch new file mode 100644 index 00000000000..425e03a8da1 --- /dev/null +++ b/sdk/tools/winesync/setupapi_staging/0002-wine-staging-4.0-setupapi_winetest.patch @@ -0,0 +1,1120 @@ +From 343133aa46610b470f891c84d98cedb0a61acbb6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= + +Date: Wed, 6 Sep 2023 22:00:13 +0200 +Subject: [PATCH 2/3] wine-staging 4.0 setupapi_winetest +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Hermès Bélusca-Maïto +--- + modules/rostests/winetests/setupapi/CMakeLists.txt | 1 + + modules/rostests/winetests/setupapi/devinst.c | 23 ++ + modules/rostests/winetests/setupapi/dialog.c | 111 ++++++ + modules/rostests/winetests/setupapi/diskspace.c | 650 +++++++++++++++++++++++++++++++- + modules/rostests/winetests/setupapi/setupcab.c | 113 +++++- + 5 files changed, 883 insertions(+), 15 deletions(-) + create mode 100644 modules/rostests/winetests/setupapi/dialog.c + +diff --git a/modules/rostests/winetests/setupapi/CMakeLists.txt b/modules/rostests/winetests/setupapi/CMakeLists.txt +index 0e9a1586671e..c314cffaabff 100644 +--- a/modules/rostests/winetests/setupapi/CMakeLists.txt ++++ b/modules/rostests/winetests/setupapi/CMakeLists.txt +@@ -1,6 +1,7 @@ + + list(APPEND SOURCE + devinst.c ++ dialog.c + diskspace.c + install.c + misc.c +diff --git a/modules/rostests/winetests/setupapi/devinst.c b/modules/rostests/winetests/setupapi/devinst.c +index 4abc188ea41..d871be34179 100644 +--- a/modules/rostests/winetests/setupapi/devinst.c ++++ b/modules/rostests/winetests/setupapi/devinst.c +@@ -1351,6 +1351,28 @@ static void test_device_interface_key(void) + SetupDiDestroyDeviceInfoList(set); + } + ++static void testSetupDiGetClassDevsA(void) ++{ ++ static GUID displayguid = {0x4d36e968, 0xe325, 0x11ce, {0xbf,0xc1,0x08,0x00,0x2b,0xe1,0x03,0x18}}; ++ SP_DEVINFO_DATA devinfo; ++ DISPLAY_DEVICEA disp; ++ HDEVINFO set; ++ BOOL ret; ++ ++ disp.cb = sizeof(disp); ++ ok(EnumDisplayDevicesA(NULL, 0, &disp, 0), "EnumDisplayDevices failed: %08x\n", GetLastError()); ++ ++ SetLastError(0xdeadbeef); ++ set = SetupDiGetClassDevsA(&displayguid, disp.DeviceID, 0, 0); ++ ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n", GetLastError()); ++ ++ devinfo.cbSize = sizeof(devinfo); ++ ret = SetupDiEnumDeviceInfo(set, 0, &devinfo); ++ ok(ret, "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError()); ++ ++ SetupDiDestroyDeviceInfoList(set); ++} ++ + START_TEST(devinst) + { + HKEY hkey; +@@ -1375,6 +1397,7 @@ START_TEST(devinst) + test_registry_property_a(); + test_registry_property_w(); + test_get_inf_class(); ++ testSetupDiGetClassDevsA(); + test_devnode(); + test_device_interface_key(); + } +diff --git a/modules/rostests/winetests/setupapi/dialog.c b/modules/rostests/winetests/setupapi/dialog.c +new file mode 100644 +index 00000000000..8b47350542d +--- /dev/null ++++ b/modules/rostests/winetests/setupapi/dialog.c +@@ -0,0 +1,111 @@ ++/* ++ * Unit tests for SetupPromptForDisk ++ * ++ * Copyright 2014 Michael Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#include ++ ++#include "windef.h" ++#include "winbase.h" ++#include "wingdi.h" ++#include "winuser.h" ++#include "winreg.h" ++#include "guiddef.h" ++#include "setupapi.h" ++ ++#include "wine/test.h" ++ ++static void test_SetupPromptForDiskA(void) ++{ ++ char file[] = "kernel32.dll"; ++ char path[MAX_PATH]; ++ char buffer[MAX_PATH]; ++ UINT ret; ++ DWORD length; ++ ++ GetSystemDirectoryA(path, MAX_PATH); ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = SetupPromptForDiskA(0, "Test", "Testdisk", path, file, 0, IDF_CHECKFIRST, buffer, sizeof(buffer) - 1, &length); ++ ok(ret == DPROMPT_SUCCESS, "Expected DPROMPT_SUCCESS, got %u\n", ret); ++ ok(length == strlen(path)+1, "Expect length %u, got %u\n", (DWORD)strlen(path) + 1, length); ++ ok(strcmp(path, buffer) == 0, "Expected path %s, got %s\n", path, buffer); ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = SetupPromptForDiskA(0, "Test", "Testdisk", path, file, 0, IDF_CHECKFIRST, 0, 0, &length); ++ ok(ret == DPROMPT_SUCCESS, "Expected DPROMPT_SUCCESS, got %d\n", ret); ++ ok(length == strlen(path)+1, "Expect length %u, got %u\n", (DWORD)strlen(path) + 1, length); ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = SetupPromptForDiskA(0, "Test", "Testdisk", path, file, 0, IDF_CHECKFIRST, buffer, 1, &length); ++ ok(ret == DPROMPT_BUFFERTOOSMALL, "Expected DPROMPT_BUFFERTOOSMALL, got %u\n", ret); ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = SetupPromptForDiskA(0, "Test", "Testdisk", path, file, 0, IDF_CHECKFIRST, buffer, strlen(path), &length); ++ ok(ret == DPROMPT_BUFFERTOOSMALL, "Expected DPROMPT_BUFFERTOOSMALL, got %u\n", ret); ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = SetupPromptForDiskA(0, "Test", "Testdisk", path, file, 0, IDF_CHECKFIRST, buffer, strlen(path)+1, &length); ++ ok(ret == DPROMPT_SUCCESS, "Expected DPROMPT_SUCCESS, got %u\n", ret); ++ ok(length == strlen(path)+1, "Expect length %u, got %u\n", (DWORD)strlen(path) + 1, length); ++ ok(strcmp(path, buffer) == 0, "Expected path %s, got %s\n", path, buffer); ++} ++ ++static void test_SetupPromptForDiskW(void) ++{ ++ WCHAR file[] = {'k','e','r','n','e','l','3','2','.','d','l','l','\0'}; ++ WCHAR title[] = {'T','e','s','t','\0'}; ++ WCHAR disk[] = {'T','e','s','t','d','i','s','k','\0'}; ++ WCHAR path[MAX_PATH]; ++ WCHAR buffer[MAX_PATH]; ++ UINT ret; ++ DWORD length; ++ ++ GetSystemDirectoryW(path, MAX_PATH); ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = SetupPromptForDiskW(0, title, disk, path, file, 0, IDF_CHECKFIRST, buffer, MAX_PATH-1, &length); ++ ok(ret == DPROMPT_SUCCESS, "Expected DPROMPT_SUCCESS, got %u\n", ret); ++ ok(length == lstrlenW(path)+1, "Expect length %u, got %u\n", lstrlenW(path)+1, length); ++ ok(lstrcmpW(path, buffer) == 0, "Expected path %s, got %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer)); ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = SetupPromptForDiskW(0, title, disk, path, file, 0, IDF_CHECKFIRST, 0, 0, &length); ++ ok(ret == DPROMPT_SUCCESS, "Expected DPROMPT_SUCCESS, got %d\n", ret); ++ ok(length == lstrlenW(path)+1, "Expect length %u, got %u\n", lstrlenW(path)+1, length); ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = SetupPromptForDiskW(0, title, disk, path, file, 0, IDF_CHECKFIRST, buffer, 1, &length); ++ ok(ret == DPROMPT_BUFFERTOOSMALL, "Expected DPROMPT_BUFFERTOOSMALL, got %u\n", ret); ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = SetupPromptForDiskW(0, title, disk, path, file, 0, IDF_CHECKFIRST, buffer, lstrlenW(path), &length); ++ ok(ret == DPROMPT_BUFFERTOOSMALL, "Expected DPROMPT_BUFFERTOOSMALL, got %u\n", ret); ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = SetupPromptForDiskW(0, title, disk, path, file, 0, IDF_CHECKFIRST, buffer, lstrlenW(path)+1, &length); ++ ok(ret == DPROMPT_SUCCESS, "Expected DPROMPT_SUCCESS, got %u\n", ret); ++ ok(length == lstrlenW(path)+1, "Expect length %u, got %u\n", lstrlenW(path)+1, length); ++ ok(lstrcmpW(path, buffer) == 0, "Expected path %s, got %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer)); ++} ++ ++START_TEST(dialog) ++{ ++ test_SetupPromptForDiskA(); ++ test_SetupPromptForDiskW(); ++} +\ No newline at end of file +diff --git a/modules/rostests/winetests/setupapi/diskspace.c b/modules/rostests/winetests/setupapi/diskspace.c +index 4e87ea905e0..c2c714eecd9 100644 +--- a/modules/rostests/winetests/setupapi/diskspace.c ++++ b/modules/rostests/winetests/setupapi/diskspace.c +@@ -19,6 +19,7 @@ + */ + + #include ++#include + + #include "windef.h" + #include "winbase.h" +@@ -31,6 +32,30 @@ + + static BOOL is_win9x; + ++#define STD_HEADER "[Version]\r\nSignature=\"$CHICAGO$\"\r\n" ++ ++static inline const char* debugstr_longlong(ULONGLONG ll) ++{ ++ static char string[17]; ++ if (sizeof(ll) > sizeof(unsigned long) && ll >> 32) ++ sprintf(string, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll); ++ else ++ sprintf(string, "%lx", (unsigned long)ll); ++ return string; ++} ++ ++/* create a new file with specified contents and open it */ ++static HINF inf_open_file_content(const char * tmpfilename, const char *data, UINT *err_line) ++{ ++ DWORD res; ++ HANDLE handle = CreateFileA(tmpfilename, GENERIC_READ|GENERIC_WRITE, ++ FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0); ++ if (handle == INVALID_HANDLE_VALUE) return 0; ++ if (!WriteFile( handle, data, strlen(data), &res, NULL )) trace( "write error\n" ); ++ CloseHandle( handle ); ++ return SetupOpenInfFileA( tmpfilename, 0, INF_STYLE_WIN4, err_line ); ++} ++ + static void test_SetupCreateDiskSpaceListA(void) + { + HDSKSPC ret; +@@ -300,11 +325,31 @@ static void test_SetupDuplicateDiskSpaceListW(void) + ok(SetupDestroyDiskSpaceList(handle), "Expected SetupDestroyDiskSpaceList to succeed\n"); + } + ++static LONGLONG get_file_size(char *path) ++{ ++ HANDLE file; ++ LARGE_INTEGER size; ++ ++ file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, ++ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ++ if (file == INVALID_HANDLE_VALUE) return 0; ++ ++ if (!GetFileSizeEx(file, &size)) ++ size.QuadPart = 0; ++ ++ CloseHandle(file); ++ return size.QuadPart; ++} ++ + static void test_SetupQuerySpaceRequiredOnDriveA(void) + { + BOOL ret; + HDSKSPC handle; + LONGLONG space; ++ char windir[MAX_PATH]; ++ char drive[3]; ++ char tmp[MAX_PATH]; ++ LONGLONG size; + + if (is_win9x) + win_skip("SetupQuerySpaceRequiredOnDriveA crashes with NULL disk space handle on Win9x\n"); +@@ -369,7 +414,7 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) + ret = SetupQuerySpaceRequiredOnDriveA(handle, "", NULL, NULL, 0); + ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveA to return FALSE, got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_DRIVE, +- "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", ++ "Expected GetLastError() to return ERROR_INVALID_DRIVE, got %u\n", + GetLastError()); + + SetLastError(0xdeadbeef); +@@ -381,6 +426,155 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) + "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", + GetLastError()); + ++ GetWindowsDirectoryA(windir, MAX_PATH); ++ drive[0] = windir[0]; drive[1] = windir[1]; drive[2] = 0; ++ ++ snprintf(tmp, MAX_PATH, "%c:\\wine-test-should-not-exist.txt", drive[0]); ++ ret = SetupAddToDiskSpaceListA(handle, tmp, 0x100000, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ space = 0; ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space == 0x100000, "Expected 0x100000 as required space, got %s\n", debugstr_longlong(space)); ++ ++ /* adding the same file again doesn't sum up the size */ ++ ret = SetupAddToDiskSpaceListA(handle, tmp, 0x200000, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ space = 0; ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space == 0x200000, "Expected 0x200000 as required space, got %s\n", debugstr_longlong(space)); ++ ++ /* the device doesn't need to exist */ ++ snprintf(tmp, MAX_PATH, "F:\\wine-test-should-not-exist.txt"); ++ ret = SetupAddToDiskSpaceListA(handle, tmp, 0x200000, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, "F:", &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space == 0x200000, "Expected 0x200000 as required space, got %s\n", debugstr_longlong(space)); ++ ++ snprintf(tmp, MAX_PATH, "F:\\wine-test-should-not-exist.txt"); ++ ret = SetupAddToDiskSpaceListA(handle, tmp, 0x200000, FILEOP_DELETE, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, "F:", &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space == 0x200000, "Expected 0x200000 as required space, got %s\n", debugstr_longlong(space)); ++ ++ ok(SetupDestroyDiskSpaceList(handle), ++ "Expected SetupDestroyDiskSpaceList to succeed\n"); ++ ++ handle = SetupCreateDiskSpaceListA(NULL, 0, 0); ++ ok(handle != NULL, ++ "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n"); ++ ++ /* the real size is subtracted unless SPDSL_IGNORE_DISK is specified */ ++ snprintf(tmp, MAX_PATH, "%s\\regedit.exe", windir); ++ ++ size = get_file_size(tmp); ++ ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ space = 0; ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space == 0 || broken(space == -0x5000) || broken(space == -0x7000), ++ "Expected 0x0 as required space, got %s\n", debugstr_longlong(space)); ++ ++ ret = SetupAddToDiskSpaceListA(handle, tmp, size + 0x100000, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space == 0x100000 || broken(space == 0xf9000) || broken(space == 0xfb000), ++ "Expected 0x100000 as required space, got %s\n", debugstr_longlong(space)); ++ ++ ret = SetupAddToDiskSpaceListA(handle, tmp, size - 0x1000, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space == -0x1000 || broken(space == -0x6000) || broken(space == -0x8000), ++ "Expected -0x1000 as required space, got %s\n", debugstr_longlong(space)); ++ ++ ok(SetupDestroyDiskSpaceList(handle), ++ "Expected SetupDestroyDiskSpaceList to succeed\n"); ++ ++ /* test FILEOP_DELETE, then FILEOP_COPY */ ++ handle = SetupCreateDiskSpaceListA(NULL, 0, 0); ++ ok(handle != NULL, ++ "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n"); ++ ++ ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_DELETE, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ space = 0; ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space == 0 || broken(space == -0x5000) || broken(space == -0x7000), ++ "Expected 0x0 as required space, got %s\n", debugstr_longlong(space)); ++ ++ ok(SetupDestroyDiskSpaceList(handle), ++ "Expected SetupDestroyDiskSpaceList to succeed\n"); ++ ++ /* test FILEOP_COPY, then FILEOP_DELETE */ ++ handle = SetupCreateDiskSpaceListA(NULL, 0, 0); ++ ok(handle != NULL, ++ "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n"); ++ ++ ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_DELETE, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ space = 0; ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space == 0 || broken(space == -0x5000) || broken(space == -0x7000), ++ "Expected 0x0 as required space, got %s\n", debugstr_longlong(space)); ++ ++ ok(SetupDestroyDiskSpaceList(handle), ++ "Expected SetupDestroyDiskSpaceList to succeed\n"); ++ ++ /* test FILEOP_DELETE without SPDSL_IGNORE_DISK */ ++ handle = SetupCreateDiskSpaceListA(NULL, 0, 0); ++ ok(handle != NULL, ++ "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n"); ++ ++ ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_DELETE, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ space = 0; ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space <= -size, "Expected space <= -size, got %s\n", debugstr_longlong(space)); ++ ++ ok(SetupDestroyDiskSpaceList(handle), ++ "Expected SetupDestroyDiskSpaceList to succeed\n"); ++ ++ /* test FILEOP_COPY and FILEOP_DELETE with SPDSL_IGNORE_DISK */ ++ handle = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK); ++ ok(handle != NULL, ++ "Expected SetupCreateDiskSpaceListA to return a valid handle, got NULL\n"); ++ ++ ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_DELETE, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ space = 0; ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space == 0, "Expected size = 0, got %s\n", debugstr_longlong(space)); ++ ++ ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ret = SetupAddToDiskSpaceListA(handle, tmp, size, FILEOP_DELETE, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ space = 0; ++ ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ++ ok(ret, "Expected SetupQuerySpaceRequiredOnDriveA to succeed\n"); ++ ok(space >= size, "Expected size >= %s\n", debugstr_longlong(space)); ++ + ok(SetupDestroyDiskSpaceList(handle), + "Expected SetupDestroyDiskSpaceList to succeed\n"); + } +@@ -472,6 +666,456 @@ static void test_SetupQuerySpaceRequiredOnDriveW(void) + "Expected SetupDestroyDiskSpaceList to succeed\n"); + } + ++static void test_SetupAddToDiskSpaceListA(void) ++{ ++ HDSKSPC handle; ++ BOOL ret; ++ ++ ret = SetupAddToDiskSpaceListA(NULL, "C:\\some-file.dat", 0, FILEOP_COPY, 0, 0); ++ ok(!ret, "Expected SetupAddToDiskSpaceListA to return FALSE, got %d\n", ret); ++ ok(GetLastError() == ERROR_INVALID_HANDLE, ++ "Expected GetLastError() to return ERROR_INVALID_HANDLE, got %u\n", GetLastError()); ++ ++ handle = SetupCreateDiskSpaceListA(NULL, 0, 0); ++ ok(handle != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n"); ++ ++ ret = SetupAddToDiskSpaceListA(handle, NULL, 0, FILEOP_COPY, 0, 0); ++ ok(ret || broken(!ret) /* >= Vista */, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ ret = SetupAddToDiskSpaceListA(handle, "C:\\some-file.dat", -20, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ ret = SetupAddToDiskSpaceListA(handle, "C:\\some-file.dat", 0, FILEOP_RENAME, 0, 0); ++ ok(!ret, "Expected SetupAddToDiskSpaceListA to return FALSE\n"); ++ ok(GetLastError() == ERROR_INVALID_PARAMETER, ++ "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); ++ ++ ret = SetupAddToDiskSpaceListA(handle, NULL, 0, FILEOP_RENAME, 0, 0); ++ ok(ret || broken(!ret) /* >= Vista */, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ ret = SetupAddToDiskSpaceListA(NULL, NULL, 0, FILEOP_RENAME, 0, 0); ++ ok(ret || broken(!ret) /* >= Vista */, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ ok(SetupDestroyDiskSpaceList(handle), ++ "Expected SetupDestroyDiskSpaceList to succeed\n"); ++} ++ ++static void test_SetupQueryDrivesInDiskSpaceListA(void) ++{ ++ char buffer[MAX_PATH]; ++ HDSKSPC handle; ++ DWORD size; ++ BOOL ret; ++ ++ handle = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK); ++ ok(handle != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n"); ++ ++ ret = SetupQueryDrivesInDiskSpaceListA(handle, NULL, 0, NULL); ++ ok(ret, "Expected SetupQueryDrivesInDiskSpaceListA to succeed\n"); ++ ++ size = 0; ++ ret = SetupQueryDrivesInDiskSpaceListA(handle, NULL, 0, &size); ++ ok(ret, "Expected SetupQueryDrivesInDiskSpaceListA to succeed\n"); ++ ok(size == 1, "Expected size 1, got %u\n", size); ++ ++ ret = SetupAddToDiskSpaceListA(handle, "F:\\random-file.dat", 0, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ ret = SetupAddToDiskSpaceListA(handle, "G:\\random-file.dat", 0, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ ret = SetupAddToDiskSpaceListA(handle, "G:\\random-file2.dat", 0, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ ret = SetupAddToDiskSpaceListA(handle, "X:\\random-file.dat", 0, FILEOP_COPY, 0, 0); ++ ok(ret, "Expected SetupAddToDiskSpaceListA to succeed\n"); ++ ++ size = 0; ++ ret = SetupQueryDrivesInDiskSpaceListA(handle, NULL, 0, &size); ++ ok(ret, "Expected SetupQueryDrivesInDiskSpaceListA to succeed\n"); ++ ok(size == 10, "Expected size 10, got %u\n", size); ++ ++ size = 0; ++ ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, 0, &size); ++ ok(!ret, "Expected SetupQueryDrivesInDiskSpaceListA to fail\n"); ++ ok(size == 4, "Expected size 4, got %u\n", size); ++ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, ++ "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); ++ ++ size = 0; ++ ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, 4, &size); ++ ok(!ret, "Expected SetupQueryDrivesInDiskSpaceListA to fail\n"); ++ ok(size == 7, "Expected size 7, got %u\n", size); ++ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, ++ "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); ++ ++ size = 0; ++ ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, 7, &size); ++ ok(!ret, "Expected SetupQueryDrivesInDiskSpaceListA to fail\n"); ++ ok(size == 10, "Expected size 10, got %u\n", size); ++ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, ++ "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); ++ ++ size = 0; ++ memset(buffer, 0xff, sizeof(buffer)); ++ ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, sizeof(buffer), &size); ++ ok(ret, "Expected SetupQueryDrivesInDiskSpaceListA to succeed\n"); ++ ok(size == 10, "Expected size 10, got %u\n", size); ++ ok(!memcmp("f:\0g:\0x:\0\0", buffer, 10), "Device list does not match\n"); ++ ++ memset(buffer, 0xff, sizeof(buffer)); ++ ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, sizeof(buffer), NULL); ++ ok(ret, "Expected SetupQueryDrivesInDiskSpaceListA to succeed\n"); ++ ok(!memcmp("f:\0g:\0x:\0\0", buffer, 10), "Device list does not match\n"); ++ ++ ok(SetupDestroyDiskSpaceList(handle), ++ "Expected SetupDestroyDiskSpaceList to succeed\n"); ++} ++ ++struct device_usage ++{ ++ const char *dev; ++ LONGLONG usage; ++}; ++ ++struct section ++{ ++ const char *name; ++ UINT fileop; ++ BOOL result; ++ DWORD error_code; ++}; ++ ++static const struct ++{ ++ const char *data; ++ struct section sections[2]; ++ const char *devices; ++ int device_length; ++ struct device_usage usage[2]; ++} ++section_test[] = ++{ ++ /* 0 */ ++ {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", ++ {{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}}, ++ "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}}, ++ /* 1 */ ++ {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", ++ {{"a", FILEOP_DELETE, TRUE, 0}, {NULL, 0, TRUE, 0}}, ++ "c:\00", sizeof("c:\00"), {{"c:", 0}, {NULL, 0}}}, ++ /* 2 */ ++ {STD_HEADER "[a]\ntest,,,\n\r\n", ++ {{"a", FILEOP_COPY, FALSE, ERROR_LINE_NOT_FOUND}, {NULL, 0, TRUE, 0}}, ++ "", sizeof(""), {{NULL, 0}, {NULL, 0}}}, ++ /* 3 */ ++ {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\n[DestinationDirs]\nDefaultDestDir=-1,F:\\test\r\n", ++ {{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}}, ++ "f:\00", sizeof("f:\00"), {{"f:", 4096}, {NULL, 0}}}, ++ /* 4 */ ++ {STD_HEADER "[a]\ntest,test2,,\n[SourceDisksFiles]\ntest2=1,,4096\r\n", ++ {{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}}, ++ "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}}, ++ /* 5 */ ++ {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", ++ {{"b", FILEOP_COPY, FALSE, ERROR_SECTION_NOT_FOUND}, {NULL, 0, TRUE, 0}}, ++ "", sizeof(""), {{NULL, 0}, {NULL, 0}}}, ++ /* 6 */ ++ {STD_HEADER "[a]\ntest,,,\n[b]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", ++ {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}}, ++ "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}}, ++ /* 7 */ ++ {STD_HEADER "[a]\ntest,,,\n[b]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\n[DestinationDirs]\nb=-1,F:\\test\r\n", ++ {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}}, ++ "c:\00f:\00", sizeof("c:\00f:\00"), {{"c:", 4096}, {"f:", 4096}}}, ++ /* 8 */ ++ {STD_HEADER "[a]\ntest,test1,,\n[b]\ntest,test2,,\n[SourceDisksFiles]\ntest1=1,,4096\ntest2=1,,8192\r\n", ++ {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}}, ++ "c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}}, ++ /* 9 */ ++ {STD_HEADER "[a]\ntest1,test,,\n[b]\ntest2,test,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", ++ {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}}, ++ "c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}}, ++}; ++ ++static void test_SetupAddSectionToDiskSpaceListA(void) ++{ ++ char tmp[MAX_PATH]; ++ char tmpfilename[MAX_PATH]; ++ char buffer[MAX_PATH]; ++ HDSKSPC diskspace; ++ UINT err_line; ++ LONGLONG space; ++ BOOL ret; ++ int i, j; ++ HINF inf; ++ ++ if (!GetTempPathA(MAX_PATH, tmp)) ++ { ++ win_skip("GetTempPath failed with error %d\n", GetLastError()); ++ return; ++ } ++ ++ if (!GetTempFileNameA(tmp, "inftest", 0, tmpfilename)) ++ { ++ win_skip("GetTempFileNameA failed with error %d\n", GetLastError()); ++ return; ++ } ++ ++ inf = inf_open_file_content(tmpfilename, STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", &err_line); ++ ok(!!inf, "Failed to open inf file (%d, line %d)\n", GetLastError(), err_line); ++ ++ diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK); ++ ok(diskspace != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n"); ++ ++ ret = SetupAddSectionToDiskSpaceListA(diskspace, NULL, NULL, "a", FILEOP_COPY, 0, 0); ++ ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n"); ++ ok(GetLastError() == ERROR_SECTION_NOT_FOUND, "Expected ERROR_SECTION_NOT_FOUND as error, got %u\n", ++ GetLastError()); ++ ++ ret = SetupAddSectionToDiskSpaceListA(NULL, inf, NULL, "a", FILEOP_COPY, 0, 0); ++ ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n"); ++ ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE as error, got %u\n", ++ GetLastError()); ++ ++ ret = SetupAddSectionToDiskSpaceListA(NULL, inf, NULL, "b", FILEOP_COPY, 0, 0); ++ ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n"); ++ ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE as error, got %u\n", ++ GetLastError()); ++ ++ ret = SetupAddSectionToDiskSpaceListA(diskspace, inf, NULL, "a", 0, 0, 0); ++ ok(ret, "Expected SetupAddSectionToDiskSpaceListA to succeed (%u)\n", GetLastError()); ++ ++ ok(SetupDestroyDiskSpaceList(diskspace), ++ "Expected SetupDestroyDiskSpaceList to succeed\n"); ++ ++ for (i = 0; i < sizeof(section_test) / sizeof(section_test[0]); i++) ++ { ++ err_line = 0; ++ ++ inf = inf_open_file_content(tmpfilename, section_test[i].data, &err_line); ++ ok(!!inf, "test %d: Failed to open inf file (%d, line %d)\n", i, GetLastError(), err_line); ++ if (!inf) continue; ++ ++ diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK); ++ ok(diskspace != NULL, "Expected SetupCreateDiskSpaceListA to return a valid handle\n"); ++ ++ for (j = 0; j < 2; j++) ++ { ++ const struct section *section = §ion_test[i].sections[j]; ++ if (!section->name) ++ continue; ++ ++ SetLastError(0xdeadbeef); ++ ret = SetupAddSectionToDiskSpaceListA(diskspace, inf, NULL, section->name, section->fileop, 0, 0); ++ if (section->result) ++ ok(ret, "test %d: Expected adding section %d to succeed (%u)\n", i, j, GetLastError()); ++ else ++ { ++ ok(!ret, "test %d: Expected adding section %d to fail\n", i, j); ++ ok(GetLastError() == section->error_code, "test %d: Expected %u as error, got %u\n", ++ i, section->error_code, GetLastError()); ++ } ++ } ++ ++ memset(buffer, 0x0, sizeof(buffer)); ++ ret = SetupQueryDrivesInDiskSpaceListA(diskspace, buffer, sizeof(buffer), NULL); ++ ok(ret, "test %d: Expected SetupQueryDrivesInDiskSpaceListA to succeed (%u)\n", i, GetLastError()); ++ ok(!memcmp(section_test[i].devices, buffer, section_test[i].device_length), ++ "test %d: Device list (%s) does not match\n", i, buffer); ++ ++ for (j = 0; j < 2; j++) ++ { ++ const struct device_usage *usage = §ion_test[i].usage[j]; ++ if (!usage->dev) ++ continue; ++ ++ space = 0; ++ ret = SetupQuerySpaceRequiredOnDriveA(diskspace, usage->dev, &space, NULL, 0); ++ ok(ret, "test %d: Expected SetupQuerySpaceRequiredOnDriveA to succeed for device %s (%u)\n", ++ i, usage->dev, GetLastError()); ++ ok(space == usage->usage, "test %d: Expected size %u for device %s, got %u\n", ++ i, (DWORD)usage->usage, usage->dev, (DWORD)space); ++ } ++ ++ ok(SetupDestroyDiskSpaceList(diskspace), ++ "Expected SetupDestroyDiskSpaceList to succeed\n"); ++ ++ SetupCloseInfFile(inf); ++ } ++ ++ DeleteFileA(tmpfilename); ++} ++ ++struct section_i ++{ ++ const char *name; ++ BOOL result; ++ DWORD error_code; ++}; ++ ++static const struct ++{ ++ const char *data; ++ struct section_i sections[2]; ++ const char *devices; ++ int device_length; ++ struct device_usage usage[2]; ++} ++section_test_i[] = ++{ ++ /* 0 */ ++ {STD_HEADER "[a.Install]\nCopyFiles=a.CopyFiles\n" ++ "[a.CopyFiles]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", ++ {{"a.Install", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}}, ++ /* 1 */ ++ {STD_HEADER "[a]\nCopyFiles=a.CopyFiles\n" ++ "[a.CopyFiles]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", ++ {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}}, ++ /* 2 */ ++ {STD_HEADER "[a]\nCopyFiles=a.CopyFiles\nCopyFiles=a.CopyFiles2\n" ++ "[a.CopyFiles]\ntest,,,\n[a.CopyFiles2]\ntest2,,,\n" ++ "[SourceDisksFiles]\ntest=1,,4096\ntest2=1,,4096\r\n", ++ {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}}, ++ /* 3 */ ++ {STD_HEADER "[a]\nCopyFiles=a.CopyFiles,a.CopyFiles2\n" ++ "[a.CopyFiles]\ntest,,,\n[a.CopyFiles2]\ntest2,,,\n" ++ "[SourceDisksFiles]\ntest=1,,4096\ntest2=1,,4096\r\n", ++ {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}}, ++ /* 4 */ ++ {STD_HEADER "[a]\r\n", ++ {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "", sizeof(""), {{NULL, 0}, {NULL, 0}}}, ++ /* 5 */ ++ {STD_HEADER "[a]\nDelFiles=a.DelFiles\n" ++ "[a.nDelFiles]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", ++ {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "", sizeof(""), {{NULL, 0}, {NULL, 0}}}, ++ /* 6 */ ++ {STD_HEADER "[a]\nCopyFiles=a.CopyFiles\nDelFiles=a.DelFiles\n" ++ "[a.CopyFiles]\ntest,,,\n[a.DelFiles]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", ++ {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}}, ++ /* 7 */ ++ {STD_HEADER "[a]\nCopyFiles=a.CopyFiles\n[b]\nDelFiles=b.DelFiles\n" ++ "[a.CopyFiles]\ntest,,,\n[b.DelFiles]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", ++ {{"a", TRUE, 0}, {"b", TRUE, 0}}, "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}}, ++ /* 7 */ ++ {STD_HEADER "[a]\nCopyFiles=\r\n", ++ {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "", sizeof(""), {{NULL, 0}, {NULL, 0}}}, ++ /* 8 */ ++ {STD_HEADER "[a]\nCopyFiles=something\r\n", ++ {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "", sizeof(""), {{NULL, 0}, {NULL, 0}}}, ++ /* 9 */ ++ {STD_HEADER "[a]\nCopyFiles=a.CopyFiles,b.CopyFiles\n[a.CopyFiles]\ntest,,,\n[b.CopyFiles]\ntest,,,\n" ++ "[SourceDisksFiles]\ntest=1,,4096\n[DestinationDirs]\nb.CopyFiles=-1,F:\\test\r\n", ++ {{"a", TRUE, 0}, {NULL, TRUE, 0}}, "c:\00f:\00", sizeof("c:\00f:\00"), {{"c:", 4096}, {"f:", 4096}}}, ++}; ++ ++static void test_SetupAddInstallSectionToDiskSpaceListA(void) ++{ ++ char tmp[MAX_PATH]; ++ char tmpfilename[MAX_PATH]; ++ char buffer[MAX_PATH]; ++ HDSKSPC diskspace; ++ LONGLONG space; ++ UINT err_line; ++ BOOL ret; ++ int i, j; ++ HINF inf; ++ ++ if (!GetTempPathA(MAX_PATH, tmp)) ++ { ++ win_skip("GetTempPath failed with error %d\n", GetLastError()); ++ return; ++ } ++ ++ if (!GetTempFileNameA(tmp, "inftest", 0, tmpfilename)) ++ { ++ win_skip("GetTempFileNameA failed with error %d\n", GetLastError()); ++ return; ++ } ++ ++ inf = inf_open_file_content(tmpfilename, STD_HEADER "[a]\nCopyFiles=b\n[b]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", &err_line); ++ ok(!!inf, "Failed to open inf file (%d, line %d)\n", GetLastError(), err_line); ++ ++ diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK); ++ ok(diskspace != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n"); ++ ++ ret = SetupAddInstallSectionToDiskSpaceListA(diskspace, NULL, NULL, "a", 0, 0); ++ ok(ret, "Expected SetupAddInstallSectionToDiskSpaceListA to succeed\n"); ++ ++ ret = SetupAddInstallSectionToDiskSpaceListA(NULL, inf, NULL, "a", 0, 0); ++ ok(!ret, "Expected SetupAddInstallSectionToDiskSpaceListA to fail\n"); ++ ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE as error, got %u\n", ++ GetLastError()); ++ ++ ret = SetupAddInstallSectionToDiskSpaceListA(diskspace, inf, NULL, NULL, 0, 0); ++ ok(!ret || broken(ret), "Expected SetupAddSectionToDiskSpaceListA to fail\n"); ++ ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(ret), ++ "Expected ERROR_INVALID_PARAMETER as error, got %u\n", GetLastError()); ++ ++ ret = SetupAddInstallSectionToDiskSpaceListA(diskspace, inf, NULL, "", 0, 0); ++ ok(ret, "Expected SetupAddInstallSectionToDiskSpaceListA to succeed (%u)\n", GetLastError()); ++ ++ ok(SetupDestroyDiskSpaceList(diskspace), ++ "Expected SetupDestroyDiskSpaceList to succeed\n"); ++ ++ for (i = 0; i < sizeof(section_test_i) / sizeof(section_test_i[0]); i++) ++ { ++ err_line = 0; ++ ++ inf = inf_open_file_content(tmpfilename, section_test_i[i].data, &err_line); ++ ok(!!inf, "test %d: Failed to open inf file (%d, line %d)\n", i, GetLastError(), err_line); ++ if (!inf) continue; ++ ++ diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK); ++ ok(diskspace != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n"); ++ ++ for (j = 0; j < 2; j++) ++ { ++ const struct section_i *section = §ion_test_i[i].sections[j]; ++ if (!section->name) ++ continue; ++ ++ SetLastError(0xdeadbeef); ++ ret = SetupAddInstallSectionToDiskSpaceListA(diskspace, inf, NULL, section->name, 0, 0); ++ if (section->result) ++ ok(ret, "test %d: Expected adding section %d to succeed (%u)\n", i, j, GetLastError()); ++ else ++ { ++ ok(!ret, "test %d: Expected adding section %d to fail\n", i, j); ++ ok(GetLastError() == section->error_code, "test %d: Expected %u as error, got %u\n", ++ i, section->error_code, GetLastError()); ++ } ++ } ++ ++ memset(buffer, 0x0, sizeof(buffer)); ++ ret = SetupQueryDrivesInDiskSpaceListA(diskspace, buffer, sizeof(buffer), NULL); ++ ok(ret, "test %d: Expected SetupQueryDrivesInDiskSpaceListA to succeed (%u)\n", i, GetLastError()); ++ ok(!memcmp(section_test_i[i].devices, buffer, section_test_i[i].device_length), ++ "test %d: Device list (%s) does not match\n", i, buffer); ++ ++ for (j = 0; j < 2; j++) ++ { ++ const struct device_usage *usage = §ion_test_i[i].usage[j]; ++ if (!usage->dev) ++ continue; ++ ++ space = 0; ++ ret = SetupQuerySpaceRequiredOnDriveA(diskspace, usage->dev, &space, NULL, 0); ++ ok(ret, "test %d: Expected SetupQuerySpaceRequiredOnDriveA to succeed for device %s (%u)\n", ++ i, usage->dev, GetLastError()); ++ ok(space == usage->usage, "test %d: Expected size %u for device %s, got %u\n", ++ i, (DWORD)usage->usage, usage->dev, (DWORD)space); ++ } ++ ++ ok(SetupDestroyDiskSpaceList(diskspace), ++ "Expected SetupDestroyDiskSpaceList to succeed\n"); ++ ++ SetupCloseInfFile(inf); ++ } ++ ++ DeleteFileA(tmpfilename); ++} ++ + START_TEST(diskspace) + { + is_win9x = !SetupCreateDiskSpaceListW((void *)0xdeadbeef, 0xdeadbeef, 0) && +@@ -482,4 +1126,8 @@ START_TEST(diskspace) + test_SetupDuplicateDiskSpaceListW(); + test_SetupQuerySpaceRequiredOnDriveA(); + test_SetupQuerySpaceRequiredOnDriveW(); ++ test_SetupAddToDiskSpaceListA(); ++ test_SetupQueryDrivesInDiskSpaceListA(); ++ test_SetupAddSectionToDiskSpaceListA(); ++ test_SetupAddInstallSectionToDiskSpaceListA(); + } +diff --git a/modules/rostests/winetests/setupapi/setupcab.c b/modules/rostests/winetests/setupapi/setupcab.c +index bb9add035db..2e776e66879 100644 +--- a/modules/rostests/winetests/setupapi/setupcab.c ++++ b/modules/rostests/winetests/setupapi/setupcab.c +@@ -299,30 +299,49 @@ static void test_invalid_callbackW(void) + + static const char *expected_files[] = {"tristram", "wine", "shandy"}; + ++struct contextA ++{ ++ int count; ++ const char *cabinet; ++ const char *target; ++}; ++ + static UINT CALLBACK simple_callbackA(PVOID Context, UINT Notification, + UINT_PTR Param1, UINT_PTR Param2) + { + static int index; +- int *file_count = Context; ++ struct contextA *ctx = Context; + + switch (Notification) + { + case SPFILENOTIFY_CABINETINFO: ++ { ++ CABINET_INFO_A *info = (CABINET_INFO_A *)Param1; ++ ++ ok(!strcmp(info->CabinetFile, ""), ++ "Expected empty CabinetFile, got \"%s\"\n", info->CabinetFile); ++ + index = 0; + return NO_ERROR; ++ } + case SPFILENOTIFY_FILEINCABINET: + { + FILE_IN_CABINET_INFO_A *info = (FILE_IN_CABINET_INFO_A *)Param1; ++ const char *cabinet_file = (const char *)Param2; + +- (*file_count)++; ++ ctx->count++; + + if (index < ARRAY_SIZE(expected_files)) + { + ok(!strcmp(expected_files[index], info->NameInCabinet), + "[%d] Expected file \"%s\", got \"%s\"\n", + index, expected_files[index], info->NameInCabinet); +- index++; +- return FILEOP_SKIP; ++ ok(!strcmp(ctx->cabinet, cabinet_file), ++ "[%d] Expected cabinet \"%s\", got \"%s\"\n", ++ index, ctx->cabinet, cabinet_file); ++ ++ strcpy(info->FullTargetName, ctx->target); ++ return FILEOP_DOIT; + } + else + { +@@ -330,6 +349,23 @@ static UINT CALLBACK simple_callbackA(PVOID Context, UINT Notification, + return FILEOP_ABORT; + } + } ++ case SPFILENOTIFY_FILEEXTRACTED: ++ { ++ FILEPATHS_A *info = (FILEPATHS_A *)Param1; ++ ++ ok(!strcmp(ctx->cabinet, info->Source), ++ "[%d] Expected cabinet \"%s\", got \"%s\"\n", ++ index, ctx->cabinet, info->Source); ++ ok(!strcmp(ctx->target, info->Target), ++ "[%d] Expected target \"%s\", got \"%s\"\n", ++ index, ctx->target, info->Target); ++ ok(info->Win32Error == 0, ++ "[%d] Expected Win32Error 0, got %u\n", ++ index, info->Win32Error); ++ ++ index++; ++ return NO_ERROR; ++ } + default: + return NO_ERROR; + } +@@ -339,18 +375,24 @@ static void test_simple_enumerationA(void) + { + BOOL ret; + char source[MAX_PATH], temp[MAX_PATH]; +- int enum_count = 0; ++ char target[MAX_PATH]; ++ struct contextA ctx; + + GetTempPathA(sizeof(temp), temp); + GetTempFileNameA(temp, "doc", 0, source); ++ GetTempFileNameA(temp, "doc", 0, target); + + create_source_fileA(source, comp_cab_zip_multi, sizeof(comp_cab_zip_multi)); + +- ret = SetupIterateCabinetA(source, 0, simple_callbackA, &enum_count); ++ ctx.count = 0; ++ ctx.cabinet = source; ++ ctx.target = target; ++ ret = SetupIterateCabinetA(source, 0, simple_callbackA, &ctx); + ok(ret == 1, "Expected SetupIterateCabinetA to return 1, got %d\n", ret); +- ok(enum_count == ARRAY_SIZE(expected_files), "Unexpectedly enumerated %d files\n", enum_count); ++ ok(ctx.count == ARRAY_SIZE(expected_files), "Unexpectedly enumerated %d files\n", ctx.count); + + DeleteFileA(source); ++ DeleteFileA(target); + } + + static const WCHAR tristramW[] = {'t','r','i','s','t','r','a','m',0}; +@@ -358,30 +400,50 @@ static const WCHAR wineW[] = {'w','i','n','e',0}; + static const WCHAR shandyW[] = {'s','h','a','n','d','y',0}; + static const WCHAR *expected_filesW[] = {tristramW, wineW, shandyW}; + ++struct contextW ++{ ++ int count; ++ const WCHAR *cabinet; ++ const WCHAR *target; ++}; ++ + static UINT CALLBACK simple_callbackW(PVOID Context, UINT Notification, + UINT_PTR Param1, UINT_PTR Param2) + { ++ static const WCHAR emptyW[] = {0}; + static int index; +- int *file_count = Context; ++ struct contextW *ctx = Context; + + switch (Notification) + { + case SPFILENOTIFY_CABINETINFO: ++ { ++ CABINET_INFO_W *info = (CABINET_INFO_W *)Param1; ++ ++ ok(!lstrcmpW(info->CabinetFile, emptyW), ++ "Expected empty CabinetFile, got %s\n", wine_dbgstr_w(info->CabinetFile)); ++ + index = 0; + return NO_ERROR; ++ } + case SPFILENOTIFY_FILEINCABINET: + { + FILE_IN_CABINET_INFO_W *info = (FILE_IN_CABINET_INFO_W *)Param1; ++ const WCHAR *cabinet_file = (const WCHAR *)Param2; + +- (*file_count)++; ++ ctx->count++; + + if (index < ARRAY_SIZE(expected_filesW)) + { + ok(!lstrcmpW(expected_filesW[index], info->NameInCabinet), + "[%d] Expected file %s, got %s\n", + index, wine_dbgstr_w(expected_filesW[index]), wine_dbgstr_w(info->NameInCabinet)); +- index++; +- return FILEOP_SKIP; ++ ok(!lstrcmpW(ctx->cabinet, cabinet_file), ++ "[%d] Expected cabinet %s, got %s\n", ++ index, wine_dbgstr_w(ctx->cabinet), wine_dbgstr_w(cabinet_file)); ++ ++ lstrcpyW(info->FullTargetName, ctx->target); ++ return FILEOP_DOIT; + } + else + { +@@ -389,6 +451,23 @@ static UINT CALLBACK simple_callbackW(PVOID Context, UINT Notification, + return FILEOP_ABORT; + } + } ++ case SPFILENOTIFY_FILEEXTRACTED: ++ { ++ FILEPATHS_W *info = (FILEPATHS_W *)Param1; ++ ++ ok(!lstrcmpW(ctx->cabinet, info->Source), ++ "[%d] Expected cabinet %s, got %s\n", ++ index, wine_dbgstr_w(ctx->cabinet), wine_dbgstr_w(info->Source)); ++ ok(!lstrcmpW(ctx->target, info->Target), ++ "[%d] Expected target %s, got %s\n", ++ index, wine_dbgstr_w(ctx->target), wine_dbgstr_w(info->Target)); ++ ok(info->Win32Error == 0, ++ "[%d] Expected Win32Error 0, got %u\n", ++ index, info->Win32Error); ++ ++ index++; ++ return NO_ERROR; ++ } + default: + return NO_ERROR; + } +@@ -398,7 +477,8 @@ static void test_simple_enumerationW(void) + { + BOOL ret; + WCHAR source[MAX_PATH], temp[MAX_PATH]; +- int enum_count = 0; ++ WCHAR target[MAX_PATH]; ++ struct contextW ctx; + + ret = SetupIterateCabinetW(NULL, 0, NULL, NULL); + if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) +@@ -409,14 +489,19 @@ static void test_simple_enumerationW(void) + + GetTempPathW(ARRAY_SIZE(temp), temp); + GetTempFileNameW(temp, docW, 0, source); ++ GetTempFileNameW(temp, docW, 0, target); + + create_source_fileW(source, comp_cab_zip_multi, sizeof(comp_cab_zip_multi)); + +- ret = SetupIterateCabinetW(source, 0, simple_callbackW, &enum_count); ++ ctx.count = 0; ++ ctx.cabinet = source; ++ ctx.target = target; ++ ret = SetupIterateCabinetW(source, 0, simple_callbackW, &ctx); + ok(ret == 1, "Expected SetupIterateCabinetW to return 1, got %d\n", ret); +- ok(enum_count == ARRAY_SIZE(expected_files), "Unexpectedly enumerated %d files\n", enum_count); ++ ok(ctx.count == ARRAY_SIZE(expected_files), "Unexpectedly enumerated %d files\n", ctx.count); + + DeleteFileW(source); ++ DeleteFileW(target); + } + + START_TEST(setupcab) +-- +2.36.1.windows.1 +