From: Elizabeth Figura zfigura@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(); }
From: Elizabeth Figura zfigura@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; }
From: Elizabeth Figura zfigura@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]);
From: Elizabeth Figura zfigura@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());