[PATCH v4 2/6] setupapi: Implement SetupAddToDiskSpaceList.

Vijay Kiran Kamuju infyquest at gmail.com
Tue Oct 22 04:42:50 CDT 2019


From: Michael Müller <michael at fds-team.de>

Signed-off-by: Vijay Kiran Kamuju <infyquest at gmail.com>
---
 dlls/setupapi/diskspace.c       | 123 +++++++++++++++++++++++---
 dlls/setupapi/tests/diskspace.c | 150 +++++++++++++++++++++++++++++++-
 2 files changed, 261 insertions(+), 12 deletions(-)

diff --git a/dlls/setupapi/diskspace.c b/dlls/setupapi/diskspace.c
index 94b68d2e82ba..d500c4c02a33 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.@)
@@ -270,25 +284,114 @@ 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 = heap_alloc(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 = heap_alloc(sizeof(*file));
+        if (!file)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            goto done;
+        }
+
+        file->path = strdupW(fullpathW);
+        if (!file->path)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            heap_free(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:
+    heap_free(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;
+    BOOL ret;
+
+    targetfileW = strdupAtoW(targetfile);
+    ret = SetupAddToDiskSpaceListW(diskspace, targetfileW, filesize,
+                                   operation, reserved1, reserved2);
+    heap_free(targetfileW);
+    return ret;
 }
diff --git a/dlls/setupapi/tests/diskspace.c b/dlls/setupapi/tests/diskspace.c
index 4e87ea905e07..0da1b7fddaf2 100644
--- a/dlls/setupapi/tests/diskspace.c
+++ b/dlls/setupapi/tests/diskspace.c
@@ -300,11 +300,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 +389,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);
@@ -378,9 +398,100 @@ static void test_SetupQuerySpaceRequiredOnDriveA(void)
     ok(!ret, "Expected SetupQuerySpaceRequiredOnDriveA to return FALSE, got %d\n", ret);
     ok(space == 0xdeadbeef, "Expected output space parameter to be untouched\n");
     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());
 
+    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", wine_dbgstr_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", wine_dbgstr_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", wine_dbgstr_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", wine_dbgstr_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", wine_dbgstr_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", wine_dbgstr_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", wine_dbgstr_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", wine_dbgstr_longlong(space));
+
     ok(SetupDestroyDiskSpaceList(handle),
        "Expected SetupDestroyDiskSpaceList to succeed\n");
 }
@@ -472,6 +583,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 +627,5 @@ START_TEST(diskspace)
     test_SetupDuplicateDiskSpaceListW();
     test_SetupQuerySpaceRequiredOnDriveA();
     test_SetupQuerySpaceRequiredOnDriveW();
+    test_SetupAddToDiskSpaceListA();
 }
-- 
2.21.0




More information about the wine-devel mailing list