From 91247236a6662c433d892dec25cd7e4b1ba0239c Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Thu, 3 Mar 2016 06:56:21 +0100 Subject: [PATCH] Added patches to implement multiple setupapi DiskSpaceList functions. --- patches/patchinstall.sh | 20 + ...rite-DiskSpaceList-logic-using-lists.patch | 295 +++++++++++++ ...pi-Implement-SetupAddToDiskSpaceList.patch | 393 ++++++++++++++++++ ...ment-SetupQueryDrivesInDiskSpaceList.patch | 222 ++++++++++ patches/setupapi-DiskSpaceList/definition | 2 + 5 files changed, 932 insertions(+) create mode 100644 patches/setupapi-DiskSpaceList/0001-setupapi-Rewrite-DiskSpaceList-logic-using-lists.patch create mode 100644 patches/setupapi-DiskSpaceList/0002-setupapi-Implement-SetupAddToDiskSpaceList.patch create mode 100644 patches/setupapi-DiskSpaceList/0003-setupapi-Implement-SetupQueryDrivesInDiskSpaceList.patch create mode 100644 patches/setupapi-DiskSpaceList/definition diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 55119fd6..6734e64c 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -283,6 +283,7 @@ patch_enable_all () enable_server_Stored_ACLs="$1" enable_server_Timestamp_Compat="$1" enable_setupapi_DelReg="$1" + enable_setupapi_DiskSpaceList="$1" enable_setupapi_Display_Device="$1" enable_setupapi_Fix_Parser="$1" enable_setupapi_HSPFILEQ_Check_Type="$1" @@ -1007,6 +1008,9 @@ patch_enable () setupapi-DelReg) enable_setupapi_DelReg="$2" ;; + setupapi-DiskSpaceList) + enable_setupapi_DiskSpaceList="$2" + ;; setupapi-Display_Device) enable_setupapi_Display_Device="$2" ;; @@ -5900,6 +5904,22 @@ if test "$enable_setupapi_DelReg" -eq 1; then ) >> "$patchlist" fi +# Patchset setupapi-DiskSpaceList +# | +# | Modified files: +# | * dlls/setupapi/diskspace.c, dlls/setupapi/stubs.c, dlls/setupapi/tests/diskspace.c +# | +if test "$enable_setupapi_DiskSpaceList" -eq 1; then + patch_apply setupapi-DiskSpaceList/0001-setupapi-Rewrite-DiskSpaceList-logic-using-lists.patch + patch_apply setupapi-DiskSpaceList/0002-setupapi-Implement-SetupAddToDiskSpaceList.patch + patch_apply setupapi-DiskSpaceList/0003-setupapi-Implement-SetupQueryDrivesInDiskSpaceList.patch + ( + echo '+ { "Michael Müller", "setupapi: Rewrite DiskSpaceList logic using lists.", 1 },'; + echo '+ { "Michael Müller", "setupapi: Implement SetupAddToDiskSpaceList.", 1 },'; + echo '+ { "Michael Müller", "setupapi: Implement SetupQueryDrivesInDiskSpaceList.", 1 },'; + ) >> "$patchlist" +fi + # Patchset setupapi-Display_Device # | # | This patchset fixes the following Wine bugs: diff --git a/patches/setupapi-DiskSpaceList/0001-setupapi-Rewrite-DiskSpaceList-logic-using-lists.patch b/patches/setupapi-DiskSpaceList/0001-setupapi-Rewrite-DiskSpaceList-logic-using-lists.patch new file mode 100644 index 00000000..1e7ea2e1 --- /dev/null +++ b/patches/setupapi-DiskSpaceList/0001-setupapi-Rewrite-DiskSpaceList-logic-using-lists.patch @@ -0,0 +1,295 @@ +From b83937f062380afb686fe503fe72c0d96a9843f4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 3 Mar 2016 04:52:35 +0100 +Subject: setupapi: Rewrite DiskSpaceList logic using lists. + +--- + dlls/setupapi/diskspace.c | 184 +++++++++++++++++++++++++--------------------- + 1 file changed, 102 insertions(+), 82 deletions(-) + +diff --git a/dlls/setupapi/diskspace.c b/dlls/setupapi/diskspace.c +index 1ca45f9..7c33542 100644 +--- a/dlls/setupapi/diskspace.c ++++ b/dlls/setupapi/diskspace.c +@@ -1,6 +1,7 @@ + /* + * SetupAPI DiskSpace functions + * ++ * Copyright 2016 Michael Müller + * Copyright 2004 CodeWeavers (Aric Stewart) + * + * This library is free software; you can redistribute it and/or +@@ -27,69 +28,51 @@ + #include "winnls.h" + #include "winreg.h" + #include "setupapi.h" ++#include "wine/unicode.h" ++#include "wine/list.h" + #include "wine/debug.h" ++#include "setupapi_private.h" + + WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +-typedef struct { +- WCHAR lpzName[20]; +- LONGLONG dwFreeSpace; +- LONGLONG dwWantedSpace; +-} DRIVE_ENTRY, *LPDRIVE_ENTRY; ++struct file_entry ++{ ++ struct list entry; ++ WCHAR *path; ++ UINT operation; ++ LONGLONG size; ++}; ++ ++struct space_list ++{ ++ struct list files; ++ UINT flags; ++}; + +-typedef struct { +- DWORD dwDriveCount; +- DRIVE_ENTRY Drives[26]; +-} DISKSPACELIST, *LPDISKSPACELIST; + + + /*********************************************************************** + * SetupCreateDiskSpaceListW (SETUPAPI.@) + */ +-HDSKSPC WINAPI SetupCreateDiskSpaceListW(PVOID Reserved1, DWORD Reserved2, UINT Flags) ++HDSKSPC WINAPI SetupCreateDiskSpaceListW(PVOID reserved1, DWORD reserved2, UINT flags) + { +- WCHAR drives[255]; +- DWORD rc; +- WCHAR *ptr; +- LPDISKSPACELIST list=NULL; ++ struct space_list *list; + +- TRACE("(%p, %u, 0x%08x)\n", Reserved1, Reserved2, Flags); ++ TRACE("(%p, %u, 0x%08x)\n", reserved1, reserved2, flags); + +- if (Reserved1 || Reserved2 || Flags & ~SPDSL_IGNORE_DISK) ++ if (reserved1 || reserved2 || flags & ~SPDSL_IGNORE_DISK) + { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + +- rc = GetLogicalDriveStringsW(255,drives); +- +- if (rc == 0) +- return NULL; +- +- list = HeapAlloc(GetProcessHeap(),0,sizeof(DISKSPACELIST)); +- +- list->dwDriveCount = 0; +- +- ptr = drives; +- +- while (*ptr) ++ list = HeapAlloc(GetProcessHeap(), 0, sizeof(*list)); ++ if (list) + { +- 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; ++ list->flags = flags; ++ list_init(&list->files); + } ++ + return list; + } + +@@ -105,32 +88,58 @@ 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 diskspace, PVOID reserved1, DWORD reserved2, UINT flags) + { +- DISKSPACELIST *list_copy, *list_original = DiskSpace; ++ struct space_list *list_copy, *list = diskspace; ++ struct file_entry *file, *file_copy; ++ ++ TRACE("(%p, %p, %u, %u)\n", diskspace, reserved1, reserved2, flags); + +- if (Reserved1 || Reserved2 || Flags) ++ if (reserved1 || reserved2 || flags) + { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + +- if (!DiskSpace) ++ if (!diskspace) + { + SetLastError(ERROR_INVALID_HANDLE); + return NULL; + } + +- list_copy = HeapAlloc(GetProcessHeap(), 0, sizeof(DISKSPACELIST)); ++ list_copy = HeapAlloc(GetProcessHeap(), 0, sizeof(*list_copy)); + if (!list_copy) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + +- *list_copy = *list_original; ++ list_copy->flags = list->flags; ++ list_init(&list_copy->files); ++ ++ LIST_FOR_EACH_ENTRY(file, &list->files, struct file_entry, entry) ++ { ++ file_copy = HeapAlloc(GetProcessHeap(), 0, sizeof(*file_copy)); ++ if (!file_copy) goto error; ++ ++ file_copy->path = strdupW(file->path); ++ if (!file_copy->path) ++ { ++ HeapFree(GetProcessHeap(), 0, file_copy); ++ goto error; ++ } ++ ++ file_copy->operation = file->operation; ++ file_copy->size = file->size; ++ list_add_head(&list_copy->files, &file->entry); ++ } + + return list_copy; ++ ++error: ++ SetLastError(ERROR_NOT_ENOUGH_MEMORY); ++ SetupDestroyDiskSpaceList(list_copy); ++ return NULL; + } + + /*********************************************************************** +@@ -155,55 +164,51 @@ BOOL WINAPI SetupAddInstallSectionToDiskSpaceListA(HDSKSPC DiskSpace, + /*********************************************************************** + * SetupQuerySpaceRequiredOnDriveW (SETUPAPI.@) + */ +-BOOL WINAPI SetupQuerySpaceRequiredOnDriveW(HDSKSPC DiskSpace, +- LPCWSTR DriveSpec, LONGLONG *SpaceRequired, +- PVOID Reserved1, UINT Reserved2) ++BOOL WINAPI SetupQuerySpaceRequiredOnDriveW(HDSKSPC diskspace, ++ LPCWSTR drivespec, LONGLONG *required, ++ PVOID reserved1, UINT reserved2) + { +- WCHAR *driveW; +- unsigned int i; +- LPDISKSPACELIST list = DiskSpace; +- BOOL rc = FALSE; +- static const WCHAR bkslsh[]= {'\\',0}; ++ struct space_list *list = diskspace; ++ struct file_entry *file; ++ LONGLONG sum = 0; + +- if (!DiskSpace) ++ TRACE("(%p, %s, %p, %p, %u)\n", diskspace, debugstr_w(drivespec), required, reserved1, reserved2); ++ ++ if (!diskspace) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + +- if (!DriveSpec) ++ if (!drivespec || !drivespec[0]) + { +- SetLastError(ERROR_INVALID_PARAMETER); ++ SetLastError(drivespec ? ERROR_INVALID_DRIVE : ERROR_INVALID_DRIVE); + return FALSE; + } + +- driveW = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(DriveSpec) + 2) * sizeof(WCHAR)); +- if (!driveW) ++ if (!required) + { +- SetLastError(ERROR_NOT_ENOUGH_MEMORY); ++ SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + +- lstrcpyW(driveW,DriveSpec); +- lstrcatW(driveW,bkslsh); +- +- TRACE("Looking for drive %s\n",debugstr_w(driveW)); +- +- for (i = 0; i < list->dwDriveCount; i++) ++ if (tolowerW(drivespec[0]) < 'a' || tolowerW(drivespec[0]) > 'z' || ++ drivespec[1] != ':' || drivespec[2] != 0) + { +- TRACE("checking drive %s\n",debugstr_w(list->Drives[i].lpzName)); +- if (lstrcmpW(driveW,list->Drives[i].lpzName)==0) +- { +- rc = TRUE; +- *SpaceRequired = list->Drives[i].dwWantedSpace; +- break; +- } ++ FIXME("UNC paths not yet supported (%s)\n", debugstr_w(drivespec)); ++ SetLastError((GetVersion() & 0x80000000) ? ERROR_INVALID_DRIVE : ERROR_INVALID_PARAMETER); ++ return FALSE; + } + +- HeapFree(GetProcessHeap(), 0, driveW); ++ LIST_FOR_EACH_ENTRY(file, &list->files, struct file_entry, entry) ++ { ++ if (tolowerW(file->path[0]) == tolowerW(drivespec[0]) && ++ file->path[1] == ':' && file->path[2] == '\\') ++ sum += file->size; ++ } + +- if (!rc) SetLastError(ERROR_INVALID_DRIVE); +- return rc; ++ *required = sum; ++ return TRUE; + } + + /*********************************************************************** +@@ -253,10 +258,25 @@ BOOL WINAPI SetupQuerySpaceRequiredOnDriveA(HDSKSPC DiskSpace, + /*********************************************************************** + * SetupDestroyDiskSpaceList (SETUPAPI.@) + */ +-BOOL WINAPI SetupDestroyDiskSpaceList(HDSKSPC DiskSpace) ++BOOL WINAPI SetupDestroyDiskSpaceList(HDSKSPC diskspace) + { +- LPDISKSPACELIST list = DiskSpace; +- HeapFree(GetProcessHeap(),0,list); ++ struct space_list *list = diskspace; ++ struct file_entry *file, *file2; ++ ++ if (!diskspace) ++ { ++ SetLastError(ERROR_INVALID_PARAMETER); ++ return FALSE; ++ } ++ ++ LIST_FOR_EACH_ENTRY_SAFE(file, file2, &list->files, struct file_entry, entry) ++ { ++ HeapFree(GetProcessHeap(), 0, file->path); ++ list_remove(&file->entry); ++ HeapFree(GetProcessHeap(), 0, file); ++ } ++ ++ HeapFree(GetProcessHeap(), 0, list); + return TRUE; + } + +-- +2.7.1 + diff --git a/patches/setupapi-DiskSpaceList/0002-setupapi-Implement-SetupAddToDiskSpaceList.patch b/patches/setupapi-DiskSpaceList/0002-setupapi-Implement-SetupAddToDiskSpaceList.patch new file mode 100644 index 00000000..41f84d29 --- /dev/null +++ b/patches/setupapi-DiskSpaceList/0002-setupapi-Implement-SetupAddToDiskSpaceList.patch @@ -0,0 +1,393 @@ +From 675e85075039dca812bdfeb5e353d45d9da6cac3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 3 Mar 2016 05:02:21 +0100 +Subject: setupapi: Implement SetupAddToDiskSpaceList. + +--- + dlls/setupapi/diskspace.c | 137 +++++++++++++++++++++++++++++++--- + dlls/setupapi/tests/diskspace.c | 159 +++++++++++++++++++++++++++++++++++++++- + 2 files changed, 285 insertions(+), 11 deletions(-) + +diff --git a/dlls/setupapi/diskspace.c b/dlls/setupapi/diskspace.c +index 7c33542..0e589fa 100644 +--- a/dlls/setupapi/diskspace.c ++++ b/dlls/setupapi/diskspace.c +@@ -49,7 +49,21 @@ struct space_list + UINT flags; + }; + ++static LONGLONG get_file_size(WCHAR *path) ++{ ++ HANDLE file; ++ LARGE_INTEGER size; ++ ++ file = CreateFileW(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; ++} + + /*********************************************************************** + * SetupCreateDiskSpaceListW (SETUPAPI.@) +@@ -281,25 +295,128 @@ BOOL WINAPI SetupDestroyDiskSpaceList(HDSKSPC diskspace) + } + + /*********************************************************************** +-* SetupAddToDiskSpaceListA (SETUPAPI.@) ++* SetupAddToDiskSpaceListW (SETUPAPI.@) + */ +-BOOL WINAPI SetupAddToDiskSpaceListA(HDSKSPC diskspace, PCSTR targetfile, ++BOOL WINAPI SetupAddToDiskSpaceListW(HDSKSPC diskspace, PCWSTR targetfile, + LONGLONG filesize, UINT operation, + PVOID reserved1, UINT reserved2) + { +- FIXME(": stub\n"); +- SetLastError(ERROR_CALL_NOT_IMPLEMENTED); +- return FALSE; ++ struct space_list *list = diskspace; ++ struct file_entry *file; ++ WCHAR *fullpathW; ++ BOOL ret = FALSE; ++ DWORD size; ++ ++ TRACE("(%p, %s, %llu, %u, %p, %u)\n", diskspace, debugstr_w(targetfile), filesize, ++ operation, reserved1, reserved2); ++ ++ if (!targetfile) ++ return TRUE; ++ ++ if (!diskspace) ++ { ++ SetLastError(ERROR_INVALID_HANDLE); ++ return FALSE; ++ } ++ ++ if (operation != FILEOP_COPY && operation != FILEOP_DELETE) ++ { ++ SetLastError(ERROR_INVALID_PARAMETER); ++ return FALSE; ++ } ++ ++ size = GetFullPathNameW(targetfile, 0, NULL, NULL); ++ if (!size) ++ { ++ SetLastError(ERROR_INVALID_PARAMETER); ++ return FALSE; ++ } ++ ++ size = (size+1) * sizeof(WCHAR); ++ fullpathW = HeapAlloc(GetProcessHeap(), 0, size); ++ ++ if (!GetFullPathNameW(targetfile, size, fullpathW, NULL)) ++ { ++ SetLastError(ERROR_INVALID_PARAMETER); ++ goto done; ++ } ++ ++ if (fullpathW[1] != ':' && fullpathW[2] != '\\') ++ { ++ FIXME("UNC paths not yet supported\n"); ++ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); ++ goto done; ++ } ++ ++ LIST_FOR_EACH_ENTRY(file, &list->files, struct file_entry, entry) ++ { ++ if (!strcmpiW(file->path, fullpathW)) ++ break; ++ } ++ ++ if (&file->entry == &list->files) ++ { ++ file = HeapAlloc(GetProcessHeap(), 0, sizeof(*file)); ++ if (!file) ++ { ++ SetLastError(ERROR_NOT_ENOUGH_MEMORY); ++ goto done; ++ } ++ ++ file->path = strdupW(fullpathW); ++ if (!file->path) ++ { ++ SetLastError(ERROR_NOT_ENOUGH_MEMORY); ++ HeapFree(GetProcessHeap(), 0, file); ++ goto done; ++ } ++ ++ list_add_tail(&list->files, &file->entry); ++ } ++ ++ file->operation = operation; ++ if (operation == FILEOP_COPY) ++ file->size = filesize; ++ else ++ file->size = 0; ++ ++ if (!(list->flags & SPDSL_IGNORE_DISK)) ++ file->size -= get_file_size(fullpathW); ++ ++ ret = TRUE; ++ ++done: ++ HeapFree(GetProcessHeap(), 0, fullpathW); ++ return ret; + } + + /*********************************************************************** +-* SetupAddToDiskSpaceListW (SETUPAPI.@) ++* SetupAddToDiskSpaceListA (SETUPAPI.@) + */ +-BOOL WINAPI SetupAddToDiskSpaceListW(HDSKSPC diskspace, PCWSTR targetfile, ++BOOL WINAPI SetupAddToDiskSpaceListA(HDSKSPC diskspace, PCSTR targetfile, + LONGLONG filesize, UINT operation, + PVOID reserved1, UINT reserved2) + { +- FIXME(": stub\n"); +- SetLastError(ERROR_CALL_NOT_IMPLEMENTED); +- return FALSE; ++ LPWSTR targetfileW = NULL; ++ DWORD len; ++ BOOL ret; ++ ++ if (targetfile) ++ { ++ len = MultiByteToWideChar(CP_ACP, 0, targetfile, -1, NULL, 0); ++ ++ targetfileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); ++ if (!targetfileW) ++ { ++ SetLastError(ERROR_NOT_ENOUGH_MEMORY); ++ return FALSE; ++ } ++ ++ MultiByteToWideChar(CP_ACP, 0, targetfile, -1, targetfileW, len); ++ } ++ ++ ret = SetupAddToDiskSpaceListW(diskspace, targetfileW, filesize, ++ operation, reserved1, reserved2); ++ if (targetfileW) HeapFree(GetProcessHeap(), 0, targetfileW); ++ return ret; + } +diff --git a/dlls/setupapi/tests/diskspace.c b/dlls/setupapi/tests/diskspace.c +index 4e87ea9..bb8c7b7 100644 +--- a/dlls/setupapi/tests/diskspace.c ++++ b/dlls/setupapi/tests/diskspace.c +@@ -19,6 +19,7 @@ + */ + + #include ++#include + + #include "windef.h" + #include "winbase.h" +@@ -31,6 +32,16 @@ + + static BOOL is_win9x; + ++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; ++} ++ + static void test_SetupCreateDiskSpaceListA(void) + { + HDSKSPC ret; +@@ -300,11 +311,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 +400,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 +412,97 @@ 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 0x100000 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"); ++ ++ 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"); ++ ++ 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)); ++ + ok(SetupDestroyDiskSpaceList(handle), + "Expected SetupDestroyDiskSpaceList to succeed\n"); + } +@@ -472,6 +594,40 @@ 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"); ++} ++ + START_TEST(diskspace) + { + is_win9x = !SetupCreateDiskSpaceListW((void *)0xdeadbeef, 0xdeadbeef, 0) && +@@ -482,4 +638,5 @@ START_TEST(diskspace) + test_SetupDuplicateDiskSpaceListW(); + test_SetupQuerySpaceRequiredOnDriveA(); + test_SetupQuerySpaceRequiredOnDriveW(); ++ test_SetupAddToDiskSpaceListA(); + } +-- +2.7.1 + diff --git a/patches/setupapi-DiskSpaceList/0003-setupapi-Implement-SetupQueryDrivesInDiskSpaceList.patch b/patches/setupapi-DiskSpaceList/0003-setupapi-Implement-SetupQueryDrivesInDiskSpaceList.patch new file mode 100644 index 00000000..ef28bcd4 --- /dev/null +++ b/patches/setupapi-DiskSpaceList/0003-setupapi-Implement-SetupQueryDrivesInDiskSpaceList.patch @@ -0,0 +1,222 @@ +From 16118fd1abc95a103ff097409062abf5c3ebb592 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 3 Mar 2016 05:03:11 +0100 +Subject: setupapi: Implement SetupQueryDrivesInDiskSpaceList. + +--- + dlls/setupapi/diskspace.c | 85 +++++++++++++++++++++++++++++++++++++++++ + dlls/setupapi/stubs.c | 18 --------- + dlls/setupapi/tests/diskspace.c | 70 +++++++++++++++++++++++++++++++++ + 3 files changed, 155 insertions(+), 18 deletions(-) + +diff --git a/dlls/setupapi/diskspace.c b/dlls/setupapi/diskspace.c +index 0e589fa..378aa59d 100644 +--- a/dlls/setupapi/diskspace.c ++++ b/dlls/setupapi/diskspace.c +@@ -420,3 +420,88 @@ BOOL WINAPI SetupAddToDiskSpaceListA(HDSKSPC diskspace, PCSTR targetfile, + if (targetfileW) HeapFree(GetProcessHeap(), 0, targetfileW); + return ret; + } ++ ++/*********************************************************************** ++ * SetupQueryDrivesInDiskSpaceListW (SETUPAPI.@) ++ */ ++BOOL WINAPI SetupQueryDrivesInDiskSpaceListW(HDSKSPC diskspace, PWSTR buffer, DWORD size, PDWORD required_size) ++{ ++ struct space_list *list = diskspace; ++ struct file_entry *file; ++ DWORD cur_size = 1; ++ BOOL used[26]; ++ ++ TRACE("(%p, %p, %d, %p)\n", diskspace, buffer, size, required_size); ++ ++ if (!diskspace) ++ { ++ SetLastError(ERROR_INVALID_PARAMETER); ++ return FALSE; ++ } ++ ++ memset(&used, 0, sizeof(used)); ++ LIST_FOR_EACH_ENTRY(file, &list->files, struct file_entry, entry) ++ { ++ int device; ++ ++ /* UNC paths are not yet supported by this function */ ++ if (tolowerW(file->path[0]) < 'a' || tolowerW(file->path[0]) > 'z' || file->path[1] != ':') ++ continue; ++ ++ device = tolowerW(file->path[0]) - 'a'; ++ if (used[device]) continue; ++ ++ cur_size += 3; ++ ++ if (buffer) ++ { ++ if (cur_size > size) ++ { ++ if (required_size) *required_size = cur_size; ++ SetLastError(ERROR_INSUFFICIENT_BUFFER); ++ return FALSE; ++ } ++ *buffer++ = tolowerW(file->path[0]); ++ *buffer++ = ':'; ++ *buffer++ = 0; ++ } ++ ++ used[device] = TRUE; ++ } ++ ++ if (buffer && size) *buffer = 0; ++ if (required_size) *required_size = cur_size; ++ return TRUE; ++} ++ ++/*********************************************************************** ++ * SetupQueryDrivesInDiskSpaceListA (SETUPAPI.@) ++ */ ++BOOL WINAPI SetupQueryDrivesInDiskSpaceListA(HDSKSPC diskspace, PSTR buffer, DWORD size, PDWORD required_size) ++{ ++ WCHAR *bufferW = NULL; ++ BOOL ret; ++ int i; ++ ++ if (buffer && size) ++ { ++ bufferW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); ++ if (!bufferW) ++ { ++ SetLastError(ERROR_NOT_ENOUGH_MEMORY); ++ return FALSE; ++ } ++ } ++ ++ ret = SetupQueryDrivesInDiskSpaceListW(diskspace, bufferW ? bufferW : (WCHAR *)buffer, ++ size, required_size); ++ ++ if (bufferW) ++ { ++ for (i = 0; i < size; i++) ++ buffer[i] = bufferW[i]; ++ HeapFree(GetProcessHeap(), 0, bufferW); ++ } ++ ++ return ret; ++} +diff --git a/dlls/setupapi/stubs.c b/dlls/setupapi/stubs.c +index ffc766b..94e98af1 100644 +--- a/dlls/setupapi/stubs.c ++++ b/dlls/setupapi/stubs.c +@@ -198,24 +198,6 @@ INT WINAPI SetupPromptReboot( HSPFILEQ file_queue, HWND owner, BOOL scan_only ) + } + + /*********************************************************************** +- * SetupQueryDrivesInDiskSpaceListA (SETUPAPI.@) +- */ +-BOOL WINAPI SetupQueryDrivesInDiskSpaceListA(HDSKSPC disk_space, PSTR return_buffer, DWORD return_buffer_size, PDWORD required_size) +-{ +- FIXME("%p, %p, %d, %p: stub\n", disk_space, return_buffer, return_buffer_size, required_size); +- return FALSE; +-} +- +-/*********************************************************************** +- * SetupQueryDrivesInDiskSpaceListW (SETUPAPI.@) +- */ +-BOOL WINAPI SetupQueryDrivesInDiskSpaceListW(HDSKSPC disk_space, PWSTR return_buffer, DWORD return_buffer_size, PDWORD required_size) +-{ +- FIXME("%p, %p, %d, %p: stub\n", disk_space, return_buffer, return_buffer_size, required_size); +- return FALSE; +-} +- +-/*********************************************************************** + * SetupAddToSourceListA (SETUPAPI.@) + */ + BOOL WINAPI SetupAddToSourceListA(DWORD flags, PCSTR source) +diff --git a/dlls/setupapi/tests/diskspace.c b/dlls/setupapi/tests/diskspace.c +index bb8c7b7..60087d1 100644 +--- a/dlls/setupapi/tests/diskspace.c ++++ b/dlls/setupapi/tests/diskspace.c +@@ -628,6 +628,75 @@ static void test_SetupAddToDiskSpaceListA(void) + "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"); ++} ++ + START_TEST(diskspace) + { + is_win9x = !SetupCreateDiskSpaceListW((void *)0xdeadbeef, 0xdeadbeef, 0) && +@@ -639,4 +708,5 @@ START_TEST(diskspace) + test_SetupQuerySpaceRequiredOnDriveA(); + test_SetupQuerySpaceRequiredOnDriveW(); + test_SetupAddToDiskSpaceListA(); ++ test_SetupQueryDrivesInDiskSpaceListA(); + } +-- +2.7.1 + diff --git a/patches/setupapi-DiskSpaceList/definition b/patches/setupapi-DiskSpaceList/definition new file mode 100644 index 00000000..9aa5dbd7 --- /dev/null +++ b/patches/setupapi-DiskSpaceList/definition @@ -0,0 +1,2 @@ +Fixes: Add implementation for setupapi.SetupAddToDiskSpaceListA/W +Fixes: Add implementation for setupapi.SetupQueryDrivesInDiskSpaceListA/W