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]);