[PATCH 0/4] MR7408: setupapi: Implement basic disk space list functions.
From: Elizabeth Figura <zfigura(a)codeweavers.com> --- dlls/setupapi/tests/diskspace.c | 300 ++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) diff --git a/dlls/setupapi/tests/diskspace.c b/dlls/setupapi/tests/diskspace.c index 577b1f84a2a..34ed717dfc0 100644 --- a/dlls/setupapi/tests/diskspace.c +++ b/dlls/setupapi/tests/diskspace.c @@ -295,9 +295,11 @@ static void test_SetupDuplicateDiskSpaceListW(void) static void test_SetupQuerySpaceRequiredOnDriveA(void) { + char temp_path[MAX_PATH], drive[3]; BOOL ret; HDSKSPC handle; LONGLONG space; + HANDLE file; SetLastError(0xdeadbeef); ret = SetupQuerySpaceRequiredOnDriveA(NULL, NULL, NULL, NULL, 0); @@ -369,8 +371,149 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %lu\n", GetLastError()); + SetLastError(0xdeadbeef); + space = 0xdeadbeef; + ret = SetupQuerySpaceRequiredOnDriveA(handle, "c:", &space, NULL, 0); + ok(!ret, "got %d\n", ret); + ok(space == 0xdeadbeef, "got space %I64d\n", space); + ok(GetLastError() == ERROR_INVALID_DRIVE, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, "C:/file1", 10000, FILEOP_COPY, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, "C:/file2", 13, FILEOP_COPY, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, "C:\\file1", 5000, FILEOP_COPY, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, "C:/file1", 4000, FILEOP_DELETE, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, "D:/file1", 4000, FILEOP_COPY, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = SetupQuerySpaceRequiredOnDriveA(handle, "c", &space, NULL, 0); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_DRIVE, "got error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = SetupQuerySpaceRequiredOnDriveA(handle, "c:\\", &space, NULL, 0); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_DRIVE, "got error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + space = 0xdeadbeef; + ret = SetupQuerySpaceRequiredOnDriveA(handle, "c:", &space, NULL, 0); + todo_wine ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + todo_wine ok(space == (4096 * 3), "got space %I64d\n", space); + ok(SetupDestroyDiskSpaceList(handle), "Expected SetupDestroyDiskSpaceList to succeed\n"); + + /* Test treatment of a file that exists. */ + + GetTempPathA(ARRAY_SIZE(temp_path), temp_path); + strcat(temp_path, "\\winetest_diskspace"); + + handle = SetupCreateDiskSpaceListW(NULL, 0, 0); + ok(!!handle, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, temp_path, 10000, FILEOP_DELETE, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + drive[0] = temp_path[0]; + drive[1] = ':'; + drive[2] = 0; + + file = CreateFileA(temp_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + ok(file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError()); + SetFilePointer(file, 1025, NULL, FILE_BEGIN); + ret = SetEndOfFile(file); + ok(ret == TRUE, "got error %d\n", errno); + + SetLastError(0xdeadbeef); + space = 0xdeadbeef; + ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); + ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + ok(!space, "got space %I64d\n", space); + + ret = SetupAddToDiskSpaceListA(handle, temp_path, 10000, FILEOP_DELETE, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + space = 0xdeadbeef; + ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); + ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + todo_wine ok(space == -4096, "got space %I64d\n", space); + + ret = SetupAddToDiskSpaceListA(handle, temp_path, 4097, FILEOP_COPY, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + space = 0xdeadbeef; + ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); + ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + todo_wine ok(space == 4096, "got space %I64d\n", space); + + /* Delete after copy does not replace, and seems to be ignored. */ + ret = SetupAddToDiskSpaceListA(handle, temp_path, 10000, FILEOP_DELETE, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + space = 0xdeadbeef; + ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); + ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + todo_wine ok(space == 4096, "got space %I64d\n", space); + + ret = SetupDestroyDiskSpaceList(handle); + ok(ret, "got error %lu\n", GetLastError()); + + /* Test copy without delete. */ + + handle = SetupCreateDiskSpaceListW(NULL, 0, 0); + ok(!!handle, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, temp_path, 4097, FILEOP_COPY, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + space = 0xdeadbeef; + ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); + ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + todo_wine ok(space == 4096, "got space %I64d\n", space); + + ret = SetupDestroyDiskSpaceList(handle); + ok(ret, "got error %lu\n", GetLastError()); + + /* With SPDSL_IGNORE_DISK. */ + + handle = SetupCreateDiskSpaceListW(NULL, 0, SPDSL_IGNORE_DISK); + ok(!!handle, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, temp_path, 4097, FILEOP_COPY, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + space = 0xdeadbeef; + ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); + ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + todo_wine ok(space == (4096 * 2), "got space %I64d\n", space); + + ret = SetupDestroyDiskSpaceList(handle); + ok(ret, "got error %lu\n", GetLastError()); + + CloseHandle(file); + ret = DeleteFileA(temp_path); + ok(ret, "got error %lu\n", GetLastError()); } static void test_SetupQuerySpaceRequiredOnDriveW(void) @@ -460,12 +603,169 @@ static void test_SetupQuerySpaceRequiredOnDriveW(void) "Expected SetupDestroyDiskSpaceList to succeed\n"); } +static void test_add_files(void) +{ + HDSKSPC handle; + BOOL ret; + + static const struct + { + const char *path; + unsigned int op; + DWORD error; + } + tests[] = + { + {"W:/file1", FILEOP_RENAME, ERROR_INVALID_PARAMETER}, + {"W:/file1", FILEOP_BACKUP, ERROR_INVALID_PARAMETER}, + {"W:/file1", FILEOP_DELETE}, + {"W:/file1", FILEOP_DELETE}, /* add the same file twice */ + {"w:file1", FILEOP_COPY}, + {"w:file1", FILEOP_COPY}, /* add the same file twice */ + {"W:/dir/", FILEOP_DELETE, ERROR_INVALID_PARAMETER}, + {"W:/dir/", FILEOP_COPY, ERROR_INVALID_PARAMETER}, + {"C:/windows", FILEOP_COPY}, + {"../file1", FILEOP_COPY}, + {"\\\\unc\\file1", FILEOP_COPY, ERROR_INVALID_PARAMETER}, + {"\\\\.\\file1", FILEOP_COPY, ERROR_INVALID_PARAMETER}, + {"\\\\?\\file1", FILEOP_COPY, ERROR_INVALID_PARAMETER}, + {"", FILEOP_COPY, ERROR_INVALID_NAME}, + }; + + handle = SetupCreateDiskSpaceListW(NULL, 0, 0); + ok(!!handle, "got error %lu\n", GetLastError()); + + for (unsigned int i = 0; i < ARRAY_SIZE(tests); ++i) + { + SetLastError(0xdeadbeef); + ret = SetupAddToDiskSpaceListA(handle, tests[i].path, 0, tests[i].op, 0, 0); + ok(ret == !GetLastError(), "got %d\n", ret); + todo_wine ok(GetLastError() == tests[i].error, "got error %lu for path %s, op %u\n", + GetLastError(), tests[i].path, tests[i].op); + } + + ret = SetupDestroyDiskSpaceList(handle); + ok(ret, "got error %lu\n", GetLastError()); +} + +static void test_query_drives(void) +{ + char buffer[20], cwd[MAX_PATH]; + WCHAR bufferW[20]; + HDSKSPC handle; + DWORD len; + BOOL ret; + + handle = SetupCreateDiskSpaceListW(NULL, 0, 0); + ok(!!handle, "got error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = SetupQueryDrivesInDiskSpaceListA(handle, NULL, 0, NULL); + todo_wine ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = SetupQueryDrivesInDiskSpaceListA(handle, NULL, 0, &len); + todo_wine ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + todo_wine ok(len == 1, "got len %lu\n", len); + + SetLastError(0xdeadbeef); + len = 0xdeadbeef; + ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, 0, &len); + ok(!ret, "got %d\n", ret); + todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError()); + todo_wine ok(len == 1, "got len %lu\n", len); + + SetLastError(0xdeadbeef); + len = 0xdeadbeef; + memset(buffer, 0xcc, sizeof(buffer)); + ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, 1, &len); + todo_wine ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + todo_wine ok(len == 1, "got len %lu\n", len); + todo_wine ok(!buffer[0], "got %s\n", debugstr_an(buffer, len)); + + ret = SetupAddToDiskSpaceListA(handle, "P:/file1", 123, FILEOP_DELETE, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, "P:/file2", 123, FILEOP_DELETE, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, "H:file3", 123, FILEOP_DELETE, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, "R:/file4", 123, FILEOP_DELETE, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + len = 0xdeadbeef; + memset(buffer, 0xcc, sizeof(buffer)); + ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, 4, &len); + ok(!ret, "got %d\n", ret); + todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError()); + todo_wine ok(len == 7, "got len %lu\n", len); + todo_wine ok(!memcmp(buffer, "h:\0\xcc", 4), "got %s\n", debugstr_an(buffer, len)); + + SetLastError(0xdeadbeef); + len = 0xdeadbeef; + memset(bufferW, 0xcc, sizeof(bufferW)); + ret = SetupQueryDrivesInDiskSpaceListW(handle, bufferW, 4, &len); + ok(!ret, "got %d\n", ret); + todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError()); + todo_wine ok(len == 7, "got len %lu\n", len); + todo_wine ok(!memcmp(bufferW, L"h:\0\xcccc", 4 * sizeof(WCHAR)), "got %s\n", debugstr_wn(bufferW, len)); + + SetLastError(0xdeadbeef); + len = 0xdeadbeef; + memset(buffer, 0xcc, sizeof(buffer)); + ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, 8, &len); + ok(!ret, "got %d\n", ret); + todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError()); + todo_wine ok(len == 10, "got len %lu\n", len); + todo_wine ok(!memcmp(buffer, "h:\0p:\0\xcc\xcc", 8), "got %s\n", debugstr_an(buffer, len)); + + SetLastError(0xdeadbeef); + len = 0xdeadbeef; + memset(buffer, 0xcc, sizeof(buffer)); + ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, sizeof(buffer), &len); + todo_wine ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + todo_wine ok(len == 10, "got len %lu\n", len); + todo_wine ok(!memcmp(buffer, "h:\0p:\0r:\0", 10), "got %s\n", debugstr_an(buffer, len)); + + ret = SetupDestroyDiskSpaceList(handle); + ok(ret, "got error %lu\n", GetLastError()); + + handle = SetupCreateDiskSpaceListW(NULL, 0, 0); + ok(!!handle, "got error %lu\n", GetLastError()); + + ret = SetupAddToDiskSpaceListA(handle, "file5", 123, FILEOP_DELETE, 0, 0); + todo_wine ok(ret, "got error %lu\n", GetLastError()); + + GetCurrentDirectoryA(sizeof(cwd), cwd); + cwd[0] = tolower(cwd[0]); + cwd[2] = cwd[3] = 0; + + SetLastError(0xdeadbeef); + memset(buffer, 0xcc, sizeof(buffer)); + ret = SetupQueryDrivesInDiskSpaceListA(handle, buffer, sizeof(buffer), NULL); + todo_wine ok(ret == TRUE, "got %d\n", ret); + todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + todo_wine ok(!memcmp(buffer, cwd, 4), "expected %s, got %s\n", debugstr_an(cwd, 4), debugstr_an(buffer, len)); + + ret = SetupDestroyDiskSpaceList(handle); + ok(ret, "got error %lu\n", GetLastError()); +} + START_TEST(diskspace) { test_SetupCreateDiskSpaceListA(); test_SetupCreateDiskSpaceListW(); test_SetupDuplicateDiskSpaceListA(); test_SetupDuplicateDiskSpaceListW(); + test_add_files(); test_SetupQuerySpaceRequiredOnDriveA(); test_SetupQuerySpaceRequiredOnDriveW(); + test_query_drives(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7408
From: Elizabeth Figura <zfigura(a)codeweavers.com> --- dlls/setupapi/diskspace.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/dlls/setupapi/diskspace.c b/dlls/setupapi/diskspace.c index 425ec80b7e8..f542bc14c0c 100644 --- a/dlls/setupapi/diskspace.c +++ b/dlls/setupapi/diskspace.c @@ -37,10 +37,11 @@ typedef struct { LONGLONG dwWantedSpace; } DRIVE_ENTRY, *LPDRIVE_ENTRY; -typedef struct { +struct disk_space_list +{ DWORD dwDriveCount; DRIVE_ENTRY Drives[26]; -} DISKSPACELIST, *LPDISKSPACELIST; +}; /*********************************************************************** @@ -48,10 +49,10 @@ typedef struct { */ HDSKSPC WINAPI SetupCreateDiskSpaceListW(PVOID Reserved1, DWORD Reserved2, UINT Flags) { + struct disk_space_list *list; WCHAR drives[255]; DWORD rc; WCHAR *ptr; - LPDISKSPACELIST list=NULL; TRACE("(%p, %lu, 0x%08x)\n", Reserved1, Reserved2, Flags); @@ -66,7 +67,7 @@ HDSKSPC WINAPI SetupCreateDiskSpaceListW(PVOID Reserved1, DWORD Reserved2, UINT if (rc == 0) return NULL; - list = malloc(sizeof(DISKSPACELIST)); + list = malloc(sizeof(*list)); list->dwDriveCount = 0; @@ -105,9 +106,9 @@ HDSKSPC WINAPI SetupCreateDiskSpaceListA(PVOID Reserved1, DWORD Reserved2, UINT /*********************************************************************** * SetupDuplicateDiskSpaceListW (SETUPAPI.@) */ -HDSKSPC WINAPI SetupDuplicateDiskSpaceListW(HDSKSPC DiskSpace, PVOID Reserved1, DWORD Reserved2, UINT Flags) +HDSKSPC WINAPI SetupDuplicateDiskSpaceListW(HDSKSPC handle, PVOID Reserved1, DWORD Reserved2, UINT Flags) { - DISKSPACELIST *list_copy, *list_original = DiskSpace; + struct disk_space_list *copy, *list = handle; if (Reserved1 || Reserved2 || Flags) { @@ -115,22 +116,21 @@ HDSKSPC WINAPI SetupDuplicateDiskSpaceListW(HDSKSPC DiskSpace, PVOID Reserved1, return NULL; } - if (!DiskSpace) + if (!handle) { SetLastError(ERROR_INVALID_HANDLE); return NULL; } - list_copy = malloc(sizeof(DISKSPACELIST)); - if (!list_copy) + if (!(copy = malloc(sizeof(*copy)))) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } - *list_copy = *list_original; + *copy = *list; - return list_copy; + return copy; } /*********************************************************************** @@ -155,16 +155,16 @@ BOOL WINAPI SetupAddInstallSectionToDiskSpaceListA(HDSKSPC DiskSpace, /*********************************************************************** * SetupQuerySpaceRequiredOnDriveW (SETUPAPI.@) */ -BOOL WINAPI SetupQuerySpaceRequiredOnDriveW(HDSKSPC DiskSpace, +BOOL WINAPI SetupQuerySpaceRequiredOnDriveW(HDSKSPC handle, LPCWSTR DriveSpec, LONGLONG *SpaceRequired, PVOID Reserved1, UINT Reserved2) { + struct disk_space_list *list = handle; WCHAR *driveW; unsigned int i; - LPDISKSPACELIST list = DiskSpace; BOOL rc = FALSE; - if (!DiskSpace) + if (!handle) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; @@ -252,9 +252,9 @@ BOOL WINAPI SetupQuerySpaceRequiredOnDriveA(HDSKSPC DiskSpace, /*********************************************************************** * SetupDestroyDiskSpaceList (SETUPAPI.@) */ -BOOL WINAPI SetupDestroyDiskSpaceList(HDSKSPC DiskSpace) +BOOL WINAPI SetupDestroyDiskSpaceList(HDSKSPC handle) { - LPDISKSPACELIST list = DiskSpace; + struct disk_space_list *list = handle; free(list); return TRUE; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7408
From: Elizabeth Figura <zfigura(a)codeweavers.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50337 --- dlls/setupapi/devinst.c | 2 +- dlls/setupapi/diskspace.c | 120 +++++++++++++++++++++++++++---- dlls/setupapi/setupapi_private.h | 3 + dlls/setupapi/tests/diskspace.c | 34 ++++----- 4 files changed, 126 insertions(+), 33 deletions(-) diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 1977b117961..9a02692350f 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -118,7 +118,7 @@ struct device_iface struct list entry; }; -static bool array_reserve(void **elements, size_t *capacity, size_t count, size_t size) +bool array_reserve(void **elements, size_t *capacity, size_t count, size_t size) { unsigned int new_capacity, max_capacity; void *new_elements; diff --git a/dlls/setupapi/diskspace.c b/dlls/setupapi/diskspace.c index f542bc14c0c..cb2d193d3a0 100644 --- a/dlls/setupapi/diskspace.c +++ b/dlls/setupapi/diskspace.c @@ -29,6 +29,8 @@ #include "setupapi.h" #include "wine/debug.h" +#include "setupapi_private.h" + WINE_DEFAULT_DEBUG_CHANNEL(setupapi); typedef struct { @@ -37,12 +39,26 @@ typedef struct { LONGLONG dwWantedSpace; } DRIVE_ENTRY, *LPDRIVE_ENTRY; +struct file +{ + WCHAR *path; + LONGLONG size; + UINT op; +}; + struct disk_space_list { + unsigned int flags; + struct file *files; + size_t count, capacity; DWORD dwDriveCount; DRIVE_ENTRY Drives[26]; }; +static bool ascii_isalpha(char c) +{ + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); +} /*********************************************************************** * SetupCreateDiskSpaceListW (SETUPAPI.@) @@ -67,10 +83,9 @@ HDSKSPC WINAPI SetupCreateDiskSpaceListW(PVOID Reserved1, DWORD Reserved2, UINT if (rc == 0) return NULL; - list = malloc(sizeof(*list)); + list = calloc(1, sizeof(*list)); + list->flags = Flags; - list->dwDriveCount = 0; - ptr = drives; while (*ptr) @@ -130,6 +145,15 @@ HDSKSPC WINAPI SetupDuplicateDiskSpaceListW(HDSKSPC handle, PVOID Reserved1, DWO *copy = *list; + copy->capacity = 0; + array_reserve((void **)©->files, ©->capacity, copy->count, sizeof(*copy->files)); + for (size_t i = 0; i < list->count; ++i) + { + copy->files[i].path = wcsdup(list->files[i].path); + copy->files[i].op = list->files[i].op; + copy->files[i].size = list->files[i].size; + } + return copy; } @@ -255,30 +279,96 @@ BOOL WINAPI SetupQuerySpaceRequiredOnDriveA(HDSKSPC DiskSpace, BOOL WINAPI SetupDestroyDiskSpaceList(HDSKSPC handle) { struct disk_space_list *list = handle; + + for (size_t i = 0; i < list->count; ++i) + free(list->files[i].path); + free(list->files); free(list); return TRUE; } +static LONGLONG get_aligned_size(LONGLONG size) +{ + return (size + 4095) & ~4095; +} + /*********************************************************************** * SetupAddToDiskSpaceListA (SETUPAPI.@) */ -BOOL WINAPI SetupAddToDiskSpaceListA(HDSKSPC diskspace, PCSTR targetfile, - LONGLONG filesize, UINT operation, - PVOID reserved1, UINT reserved2) +BOOL WINAPI SetupAddToDiskSpaceListA(HDSKSPC handle, const char *file, + LONGLONG size, UINT op, void *reserved1, UINT reserved2) { - FIXME(": stub\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + WCHAR *fileW = strdupAtoW(file); + BOOL ret = SetupAddToDiskSpaceListW(handle, fileW, size, op, reserved1, reserved2); + free(fileW); + return ret; } /*********************************************************************** * SetupAddToDiskSpaceListW (SETUPAPI.@) */ -BOOL WINAPI SetupAddToDiskSpaceListW(HDSKSPC diskspace, PCWSTR targetfile, - LONGLONG filesize, UINT operation, - PVOID reserved1, UINT reserved2) +BOOL WINAPI SetupAddToDiskSpaceListW(HDSKSPC handle, const WCHAR *file, + LONGLONG size, UINT op, void *reserved1, UINT reserved2) { - FIXME(": stub\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + struct disk_space_list *list = handle; + WIN32_FILE_ATTRIBUTE_DATA attr; + WCHAR *full_path; + DWORD len; + + TRACE("handle %p, file %s, size %I64d, op %#x, reserved1 %p, reserved2 %#x.\n", + handle, debugstr_w(file), size, op, reserved1, reserved2); + + size = get_aligned_size(size); + + if (op != FILEOP_COPY && op != FILEOP_DELETE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (op == FILEOP_DELETE) + size = 0; + + if (!(len = GetFullPathNameW(file, 0, NULL, NULL))) + { + SetLastError(ERROR_INVALID_NAME); + return FALSE; + } + full_path = malloc(len * sizeof(WCHAR)); + GetFullPathNameW(file, len, full_path, NULL); + + if (full_path[len - 2] == '\\' || !ascii_isalpha(full_path[0]) || full_path[1] != ':') + { + free(full_path); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!(list->flags & SPDSL_IGNORE_DISK) + && GetFileAttributesExW(full_path, GetFileExInfoStandard, &attr) + && !(attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + size -= get_aligned_size(((LONGLONG)attr.nFileSizeHigh << 32) | attr.nFileSizeLow); + + for (size_t i = 0; i < list->count; ++i) + { + if (!wcscmp(full_path, list->files[i].path)) + { + if (!(op == FILEOP_DELETE && list->files[i].op == FILEOP_COPY)) + { + list->files[i].op = op; + list->files[i].size = size; + } + free(full_path); + SetLastError(ERROR_SUCCESS); + return TRUE; + } + } + + array_reserve((void **)&list->files, &list->capacity, list->count + 1, sizeof(*list->files)); + list->files[list->count].path = full_path; + list->files[list->count].op = op; + list->files[list->count].size = size; + ++list->count; + SetLastError(ERROR_SUCCESS); + return TRUE; } diff --git a/dlls/setupapi/setupapi_private.h b/dlls/setupapi/setupapi_private.h index 9d3d19c84c0..d9022729907 100644 --- a/dlls/setupapi/setupapi_private.h +++ b/dlls/setupapi/setupapi_private.h @@ -19,6 +19,7 @@ #ifndef __SETUPAPI_PRIVATE_H #define __SETUPAPI_PRIVATE_H +#include <stdbool.h> #include <windef.h> #include <winuser.h> @@ -71,6 +72,8 @@ static inline WCHAR *strdupAtoW( const char *str ) return ret; } +bool array_reserve(void **elements, size_t *capacity, size_t count, size_t size); + /* exported functions not in public headers */ void WINAPI MyFree( void *mem ); diff --git a/dlls/setupapi/tests/diskspace.c b/dlls/setupapi/tests/diskspace.c index 34ed717dfc0..c914489f866 100644 --- a/dlls/setupapi/tests/diskspace.c +++ b/dlls/setupapi/tests/diskspace.c @@ -379,19 +379,19 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) ok(GetLastError() == ERROR_INVALID_DRIVE, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, "C:/file1", 10000, FILEOP_COPY, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, "C:/file2", 13, FILEOP_COPY, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, "C:\\file1", 5000, FILEOP_COPY, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, "C:/file1", 4000, FILEOP_DELETE, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, "D:/file1", 4000, FILEOP_COPY, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); SetLastError(0xdeadbeef); ret = SetupQuerySpaceRequiredOnDriveA(handle, "c", &space, NULL, 0); @@ -422,7 +422,7 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) ok(!!handle, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, temp_path, 10000, FILEOP_DELETE, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); drive[0] = temp_path[0]; drive[1] = ':'; @@ -442,7 +442,7 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) ok(!space, "got space %I64d\n", space); ret = SetupAddToDiskSpaceListA(handle, temp_path, 10000, FILEOP_DELETE, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); SetLastError(0xdeadbeef); space = 0xdeadbeef; @@ -452,7 +452,7 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) todo_wine ok(space == -4096, "got space %I64d\n", space); ret = SetupAddToDiskSpaceListA(handle, temp_path, 4097, FILEOP_COPY, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); SetLastError(0xdeadbeef); space = 0xdeadbeef; @@ -463,7 +463,7 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) /* Delete after copy does not replace, and seems to be ignored. */ ret = SetupAddToDiskSpaceListA(handle, temp_path, 10000, FILEOP_DELETE, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); SetLastError(0xdeadbeef); space = 0xdeadbeef; @@ -481,7 +481,7 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) ok(!!handle, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, temp_path, 4097, FILEOP_COPY, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); SetLastError(0xdeadbeef); space = 0xdeadbeef; @@ -499,7 +499,7 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) ok(!!handle, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, temp_path, 4097, FILEOP_COPY, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); SetLastError(0xdeadbeef); space = 0xdeadbeef; @@ -640,7 +640,7 @@ static void test_add_files(void) SetLastError(0xdeadbeef); ret = SetupAddToDiskSpaceListA(handle, tests[i].path, 0, tests[i].op, 0, 0); ok(ret == !GetLastError(), "got %d\n", ret); - todo_wine ok(GetLastError() == tests[i].error, "got error %lu for path %s, op %u\n", + ok(GetLastError() == tests[i].error, "got error %lu for path %s, op %u\n", GetLastError(), tests[i].path, tests[i].op); } @@ -687,16 +687,16 @@ static void test_query_drives(void) todo_wine ok(!buffer[0], "got %s\n", debugstr_an(buffer, len)); ret = SetupAddToDiskSpaceListA(handle, "P:/file1", 123, FILEOP_DELETE, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, "P:/file2", 123, FILEOP_DELETE, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, "H:file3", 123, FILEOP_DELETE, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, "R:/file4", 123, FILEOP_DELETE, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); SetLastError(0xdeadbeef); len = 0xdeadbeef; @@ -741,7 +741,7 @@ static void test_query_drives(void) ok(!!handle, "got error %lu\n", GetLastError()); ret = SetupAddToDiskSpaceListA(handle, "file5", 123, FILEOP_DELETE, 0, 0); - todo_wine ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "got error %lu\n", GetLastError()); GetCurrentDirectoryA(sizeof(cwd), cwd); cwd[0] = tolower(cwd[0]); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7408
From: Elizabeth Figura <zfigura(a)codeweavers.com> --- dlls/setupapi/diskspace.c | 85 +++++++++------------------------ dlls/setupapi/tests/diskspace.c | 28 +++++------ 2 files changed, 37 insertions(+), 76 deletions(-) diff --git a/dlls/setupapi/diskspace.c b/dlls/setupapi/diskspace.c index cb2d193d3a0..60022b2e48c 100644 --- a/dlls/setupapi/diskspace.c +++ b/dlls/setupapi/diskspace.c @@ -33,12 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(setupapi); -typedef struct { - WCHAR lpzName[20]; - LONGLONG dwFreeSpace; - LONGLONG dwWantedSpace; -} DRIVE_ENTRY, *LPDRIVE_ENTRY; - struct file { WCHAR *path; @@ -51,8 +45,6 @@ struct disk_space_list unsigned int flags; struct file *files; size_t count, capacity; - DWORD dwDriveCount; - DRIVE_ENTRY Drives[26]; }; static bool ascii_isalpha(char c) @@ -66,9 +58,6 @@ static bool ascii_isalpha(char c) HDSKSPC WINAPI SetupCreateDiskSpaceListW(PVOID Reserved1, DWORD Reserved2, UINT Flags) { struct disk_space_list *list; - WCHAR drives[255]; - DWORD rc; - WCHAR *ptr; TRACE("(%p, %lu, 0x%08x)\n", Reserved1, Reserved2, Flags); @@ -78,34 +67,8 @@ HDSKSPC WINAPI SetupCreateDiskSpaceListW(PVOID Reserved1, DWORD Reserved2, UINT return NULL; } - rc = GetLogicalDriveStringsW(255,drives); - - if (rc == 0) - return NULL; - list = calloc(1, sizeof(*list)); list->flags = Flags; - - ptr = drives; - - while (*ptr) - { - DWORD type = GetDriveTypeW(ptr); - if (type == DRIVE_FIXED) - { - DWORD clusters; - DWORD sectors; - DWORD bytes; - DWORD total; - lstrcpyW(list->Drives[list->dwDriveCount].lpzName,ptr); - GetDiskFreeSpaceW(ptr,§ors,&bytes,&clusters,&total); - list->Drives[list->dwDriveCount].dwFreeSpace = clusters * sectors * - bytes; - list->Drives[list->dwDriveCount].dwWantedSpace = 0; - list->dwDriveCount++; - } - ptr += lstrlenW(ptr) + 1; - } return list; } @@ -143,8 +106,8 @@ HDSKSPC WINAPI SetupDuplicateDiskSpaceListW(HDSKSPC handle, PVOID Reserved1, DWO return NULL; } - *copy = *list; - + copy->flags = list->flags; + copy->count = list->count; copy->capacity = 0; array_reserve((void **)©->files, ©->capacity, copy->count, sizeof(*copy->files)); for (size_t i = 0; i < list->count; ++i) @@ -180,13 +143,14 @@ BOOL WINAPI SetupAddInstallSectionToDiskSpaceListA(HDSKSPC DiskSpace, * SetupQuerySpaceRequiredOnDriveW (SETUPAPI.@) */ BOOL WINAPI SetupQuerySpaceRequiredOnDriveW(HDSKSPC handle, - LPCWSTR DriveSpec, LONGLONG *SpaceRequired, - PVOID Reserved1, UINT Reserved2) + const WCHAR *drive, LONGLONG *ret_size, void *reserved1, UINT reserved2) { struct disk_space_list *list = handle; - WCHAR *driveW; - unsigned int i; - BOOL rc = FALSE; + bool has_files = false; + LONGLONG size = 0; + + TRACE("handle %p, drive %s, ret_size %p, reserved1 %p, reserved2 %#x.\n", + handle, debugstr_w(drive), ret_size, reserved1, reserved2); if (!handle) { @@ -194,39 +158,36 @@ BOOL WINAPI SetupQuerySpaceRequiredOnDriveW(HDSKSPC handle, return FALSE; } - if (!DriveSpec) + if (!drive) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - driveW = malloc((wcslen(DriveSpec) + 2) * sizeof(WCHAR)); - if (!driveW) + if (!ascii_isalpha(drive[0]) || drive[1] != ':' || drive[2]) { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); + SetLastError(ERROR_INVALID_DRIVE); return FALSE; } - lstrcpyW(driveW,DriveSpec); - lstrcatW(driveW,L"\\"); - - TRACE("Looking for drive %s\n",debugstr_w(driveW)); - - for (i = 0; i < list->dwDriveCount; i++) + for (size_t i = 0; i < list->count; ++i) { - TRACE("checking drive %s\n",debugstr_w(list->Drives[i].lpzName)); - if (wcscmp(driveW,list->Drives[i].lpzName)==0) + if (tolower(drive[0]) == tolower(list->files[i].path[0])) { - rc = TRUE; - *SpaceRequired = list->Drives[i].dwWantedSpace; - break; + has_files = true; + size += list->files[i].size; } } - free(driveW); + if (!has_files) + { + SetLastError(ERROR_INVALID_DRIVE); + return FALSE; + } - if (!rc) SetLastError(ERROR_INVALID_DRIVE); - return rc; + *ret_size = size; + SetLastError(ERROR_SUCCESS); + return TRUE; } /*********************************************************************** diff --git a/dlls/setupapi/tests/diskspace.c b/dlls/setupapi/tests/diskspace.c index c914489f866..9f2afc1e53d 100644 --- a/dlls/setupapi/tests/diskspace.c +++ b/dlls/setupapi/tests/diskspace.c @@ -406,9 +406,9 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) SetLastError(0xdeadbeef); space = 0xdeadbeef; ret = SetupQuerySpaceRequiredOnDriveA(handle, "c:", &space, NULL, 0); - todo_wine ok(ret == TRUE, "got %d\n", ret); - todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); - todo_wine ok(space == (4096 * 3), "got space %I64d\n", space); + ok(ret == TRUE, "got %d\n", ret); + ok(!GetLastError(), "got error %lu\n", GetLastError()); + ok(space == (4096 * 3), "got space %I64d\n", space); ok(SetupDestroyDiskSpaceList(handle), "Expected SetupDestroyDiskSpaceList to succeed\n"); @@ -438,7 +438,7 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) space = 0xdeadbeef; ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ok(ret == TRUE, "got %d\n", ret); - todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); + ok(!GetLastError(), "got error %lu\n", GetLastError()); ok(!space, "got space %I64d\n", space); ret = SetupAddToDiskSpaceListA(handle, temp_path, 10000, FILEOP_DELETE, 0, 0); @@ -448,8 +448,8 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) space = 0xdeadbeef; ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ok(ret == TRUE, "got %d\n", ret); - todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); - todo_wine ok(space == -4096, "got space %I64d\n", space); + ok(!GetLastError(), "got error %lu\n", GetLastError()); + ok(space == -4096, "got space %I64d\n", space); ret = SetupAddToDiskSpaceListA(handle, temp_path, 4097, FILEOP_COPY, 0, 0); ok(ret, "got error %lu\n", GetLastError()); @@ -458,8 +458,8 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) space = 0xdeadbeef; ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ok(ret == TRUE, "got %d\n", ret); - todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); - todo_wine ok(space == 4096, "got space %I64d\n", space); + ok(!GetLastError(), "got error %lu\n", GetLastError()); + ok(space == 4096, "got space %I64d\n", space); /* Delete after copy does not replace, and seems to be ignored. */ ret = SetupAddToDiskSpaceListA(handle, temp_path, 10000, FILEOP_DELETE, 0, 0); @@ -469,8 +469,8 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) space = 0xdeadbeef; ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ok(ret == TRUE, "got %d\n", ret); - todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); - todo_wine ok(space == 4096, "got space %I64d\n", space); + ok(!GetLastError(), "got error %lu\n", GetLastError()); + ok(space == 4096, "got space %I64d\n", space); ret = SetupDestroyDiskSpaceList(handle); ok(ret, "got error %lu\n", GetLastError()); @@ -487,8 +487,8 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) space = 0xdeadbeef; ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ok(ret == TRUE, "got %d\n", ret); - todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); - todo_wine ok(space == 4096, "got space %I64d\n", space); + ok(!GetLastError(), "got error %lu\n", GetLastError()); + ok(space == 4096, "got space %I64d\n", space); ret = SetupDestroyDiskSpaceList(handle); ok(ret, "got error %lu\n", GetLastError()); @@ -505,8 +505,8 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) space = 0xdeadbeef; ret = SetupQuerySpaceRequiredOnDriveA(handle, drive, &space, NULL, 0); ok(ret == TRUE, "got %d\n", ret); - todo_wine ok(!GetLastError(), "got error %lu\n", GetLastError()); - todo_wine ok(space == (4096 * 2), "got space %I64d\n", space); + ok(!GetLastError(), "got error %lu\n", GetLastError()); + ok(space == (4096 * 2), "got space %I64d\n", space); ret = SetupDestroyDiskSpaceList(handle); ok(ret, "got error %lu\n", GetLastError()); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7408
participants (2)
-
Elizabeth Figura -
Elizabeth Figura (@zfigura)