diff --git a/dll/win32/setupapi/diskspace.c b/dll/win32/setupapi/diskspace.c index b900f8a84ee..962764cf279 100644 --- a/dll/win32/setupapi/diskspace.c +++ b/dll/win32/setupapi/diskspace.c @@ -36,7 +36,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.@) @@ -267,18 +281,6 @@ BOOL WINAPI SetupDestroyDiskSpaceList(HDSKSPC diskspace) return TRUE; } -/*********************************************************************** -* SetupAddToDiskSpaceListA (SETUPAPI.@) -*/ -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; -} - /*********************************************************************** * SetupAddToDiskSpaceListW (SETUPAPI.@) */ @@ -286,7 +288,122 @@ 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, %s, %u, %p, %u)\n", diskspace, debugstr_w(targetfile), + wine_dbgstr_longlong(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 (!lstrcmpiW(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 = wcsdup(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; +} + +/*********************************************************************** +* SetupAddToDiskSpaceListA (SETUPAPI.@) +*/ +BOOL WINAPI SetupAddToDiskSpaceListA(HDSKSPC diskspace, PCSTR targetfile, + LONGLONG filesize, UINT operation, + PVOID reserved1, UINT reserved2) +{ + 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/modules/rostests/winetests/setupapi/diskspace.c b/modules/rostests/winetests/setupapi/diskspace.c index 577b1f84a2a..3cd83c8471f 100644 --- a/modules/rostests/winetests/setupapi/diskspace.c +++ b/modules/rostests/winetests/setupapi/diskspace.c @@ -19,6 +19,7 @@ */ #include +#include #include "windef.h" #include "winbase.h" @@ -29,6 +30,16 @@ #include "wine/test.h" +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; @@ -293,11 +304,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; SetLastError(0xdeadbeef); ret = SetupQuerySpaceRequiredOnDriveA(NULL, NULL, NULL, NULL, 0); @@ -357,7 +388,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 %lu\n", + "Expected GetLastError() to return ERROR_INVALID_DRIVE, got %lu\n", GetLastError()); SetLastError(0xdeadbeef); @@ -369,6 +400,97 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %lu\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"); } @@ -460,6 +582,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 %lu\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 %lu\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) { test_SetupCreateDiskSpaceListA(); @@ -468,4 +624,5 @@ START_TEST(diskspace) test_SetupDuplicateDiskSpaceListW(); test_SetupQuerySpaceRequiredOnDriveA(); test_SetupQuerySpaceRequiredOnDriveW(); + test_SetupAddToDiskSpaceListA(); } diff --git a/sdk/tools/winesync/setupapi_staging/0002-setupapi__Implement_SetupAddToDiskSpaceList.diff b/sdk/tools/winesync/setupapi_staging/0002-setupapi__Implement_SetupAddToDiskSpaceList.diff new file mode 100644 index 00000000000..64f494fbdf2 --- /dev/null +++ b/sdk/tools/winesync/setupapi_staging/0002-setupapi__Implement_SetupAddToDiskSpaceList.diff @@ -0,0 +1,380 @@ +diff --git a/dll/win32/setupapi/diskspace.c b/dll/win32/setupapi/diskspace.c +index b900f8a84ee..962764cf279 100644 +--- a/dll/win32/setupapi/diskspace.c ++++ b/dll/win32/setupapi/diskspace.c +@@ -36,7 +36,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.@) +@@ -268,25 +282,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, %s, %u, %p, %u)\n", diskspace, debugstr_w(targetfile), ++ wine_dbgstr_longlong(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 (!lstrcmpiW(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 = wcsdup(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/modules/rostests/winetests/setupapi/diskspace.c b/modules/rostests/winetests/setupapi/diskspace.c +index 577b1f84a2a..3cd83c8471f 100644 +--- a/modules/rostests/winetests/setupapi/diskspace.c ++++ b/modules/rostests/winetests/setupapi/diskspace.c +@@ -19,6 +19,7 @@ + */ + + #include ++#include + + #include "windef.h" + #include "winbase.h" +@@ -29,6 +30,16 @@ + + #include "wine/test.h" + ++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; +@@ -293,11 +304,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; + + SetLastError(0xdeadbeef); + ret = SetupQuerySpaceRequiredOnDriveA(NULL, NULL, NULL, NULL, 0); +@@ -357,7 +388,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 %lu\n", ++ "Expected GetLastError() to return ERROR_INVALID_DRIVE, got %lu\n", + GetLastError()); + + SetLastError(0xdeadbeef); +@@ -369,6 +400,97 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void) + "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %lu\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"); + } +@@ -460,6 +582,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 %lu\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 %lu\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) + { + test_SetupCreateDiskSpaceListA(); +@@ -468,4 +624,5 @@ START_TEST(diskspace) + test_SetupDuplicateDiskSpaceListW(); + test_SetupQuerySpaceRequiredOnDriveA(); + test_SetupQuerySpaceRequiredOnDriveW(); ++ test_SetupAddToDiskSpaceListA(); + }