mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +00:00
[WINESYNC] setupapi: ImplementSetupAddSectionToDiskSpaceList.
wine-staging patch by Michael Müller <michael@fds-team.de>
This commit is contained in:
parent
b0cecb370b
commit
8c0d311d9f
6 changed files with 745 additions and 3 deletions
|
@ -19,6 +19,7 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "setupapi_private.h"
|
||||
#include "wine/list.h"
|
||||
|
||||
|
@ -52,6 +53,23 @@ static LONGLONG get_file_size(WCHAR *path)
|
|||
return size.QuadPart;
|
||||
}
|
||||
|
||||
static BOOL get_size_from_inf(HINF layoutinf, WCHAR *filename, LONGLONG *size)
|
||||
{
|
||||
static const WCHAR SourceDisksFiles[] = {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
|
||||
INFCONTEXT context;
|
||||
WCHAR buffer[20];
|
||||
|
||||
if (!SetupFindFirstLineW(layoutinf, SourceDisksFiles, filename, &context))
|
||||
return FALSE;
|
||||
|
||||
if (!SetupGetStringFieldW(&context, 3, buffer, sizeof(buffer), NULL))
|
||||
return FALSE;
|
||||
|
||||
/* FIXME: is there a atollW ? */
|
||||
*size = wcstol(buffer, NULL, 10);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupCreateDiskSpaceListW (SETUPAPI.@)
|
||||
*/
|
||||
|
@ -151,6 +169,117 @@ HDSKSPC WINAPI SetupDuplicateDiskSpaceListA(HDSKSPC DiskSpace, PVOID Reserved1,
|
|||
return SetupDuplicateDiskSpaceListW(DiskSpace, Reserved1, Reserved2, Flags);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupAddSectionToDiskSpaceListW (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI SetupAddSectionToDiskSpaceListW(HDSKSPC diskspace, HINF hinf, HINF hlist,
|
||||
PCWSTR section, UINT operation, PVOID reserved1,
|
||||
UINT reserved2)
|
||||
{
|
||||
static const WCHAR sepW[] = {'\\',0};
|
||||
WCHAR dest[MAX_PATH], src[MAX_PATH], *dest_dir, *full_path;
|
||||
INFCONTEXT context;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("(%p, %p, %p, %s, %u, %p, %u)\n", diskspace, hinf, hlist, debugstr_w(section),
|
||||
operation, reserved1, reserved2);
|
||||
|
||||
if (!diskspace)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!section)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!hlist) hlist = hinf;
|
||||
|
||||
if (!SetupFindFirstLineW(hlist, section, NULL, &context))
|
||||
{
|
||||
SetLastError(ERROR_SECTION_NOT_FOUND);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dest_dir = get_destination_dir(hinf, section);
|
||||
if (!dest_dir)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
LONGLONG filesize;
|
||||
int path_size;
|
||||
BOOL tmp_ret;
|
||||
|
||||
if (!SetupGetStringFieldW(&context, 1, dest, sizeof(dest) / sizeof(WCHAR), NULL))
|
||||
goto end;
|
||||
if (!SetupGetStringFieldW(&context, 2, src, sizeof(src) / sizeof(WCHAR), NULL))
|
||||
*src = 0;
|
||||
if (!get_size_from_inf(hinf, src[0] ? src : dest, &filesize))
|
||||
goto end;
|
||||
|
||||
path_size = lstrlenW(dest_dir) + lstrlenW(dest) + 2;
|
||||
full_path = HeapAlloc(GetProcessHeap(), 0, path_size * sizeof(WCHAR));
|
||||
if (!full_path)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
goto end;
|
||||
}
|
||||
|
||||
lstrcpyW(full_path, dest_dir);
|
||||
lstrcatW(full_path, sepW);
|
||||
lstrcatW(full_path, dest);
|
||||
|
||||
tmp_ret = SetupAddToDiskSpaceListW(diskspace, full_path, filesize, operation, 0, 0);
|
||||
HeapFree(GetProcessHeap(), 0, full_path);
|
||||
if (!tmp_ret) goto end;
|
||||
}
|
||||
while (SetupFindNextLine(&context, &context));
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
end:
|
||||
HeapFree(GetProcessHeap(), 0, dest_dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupAddSectionToDiskSpaceListA (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI SetupAddSectionToDiskSpaceListA(HDSKSPC diskspace, HINF hinf, HINF hlist,
|
||||
PCSTR section, UINT operation, PVOID reserved1,
|
||||
UINT reserved2)
|
||||
{
|
||||
LPWSTR sectionW = NULL;
|
||||
DWORD len;
|
||||
BOOL ret;
|
||||
|
||||
if (section)
|
||||
{
|
||||
len = MultiByteToWideChar(CP_ACP, 0, section, -1, NULL, 0);
|
||||
|
||||
sectionW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||
if (!sectionW)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MultiByteToWideChar(CP_ACP, 0, section, -1, sectionW, len);
|
||||
}
|
||||
|
||||
ret = SetupAddSectionToDiskSpaceListW(diskspace, hinf, hlist, sectionW, operation,
|
||||
reserved1, reserved2);
|
||||
if (sectionW) HeapFree(GetProcessHeap(), 0, sectionW);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupAddInstallSectionToDiskSpaceListA (SETUPAPI.@)
|
||||
*/
|
||||
|
|
|
@ -418,7 +418,7 @@ static void get_source_info( HINF hinf, const WCHAR *src_file, SP_FILE_COPY_PARA
|
|||
*
|
||||
* Retrieve the destination dir for a given section.
|
||||
*/
|
||||
static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
|
||||
WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
|
||||
{
|
||||
INFCONTEXT context;
|
||||
WCHAR systemdir[MAX_PATH], *dir;
|
||||
|
|
|
@ -218,8 +218,8 @@
|
|||
@ stdcall MyRealloc(ptr long)
|
||||
@ stdcall SetupAddInstallSectionToDiskSpaceListA(long long long str ptr long)
|
||||
@ stub SetupAddInstallSectionToDiskSpaceListW
|
||||
@ stdcall -stub SetupAddSectionToDiskSpaceListA(long long long str long ptr long)
|
||||
@ stub SetupAddSectionToDiskSpaceListW
|
||||
@ stdcall SetupAddSectionToDiskSpaceListA(ptr ptr ptr str long ptr long)
|
||||
@ stdcall SetupAddSectionToDiskSpaceListW(ptr ptr ptr wstr long ptr long)
|
||||
@ stdcall SetupAddToDiskSpaceListA(long str int64 long ptr long)
|
||||
@ stdcall SetupAddToDiskSpaceListW(long wstr int64 long ptr long)
|
||||
@ stdcall SetupAddToSourceListA(long str)
|
||||
|
|
|
@ -327,6 +327,8 @@ extern const WCHAR *PARSER_get_inf_filename( HINF hinf ) DECLSPEC_HIDDEN;
|
|||
extern WCHAR *PARSER_get_src_root( HINF hinf ) DECLSPEC_HIDDEN;
|
||||
extern WCHAR *PARSER_get_dest_dir( INFCONTEXT *context ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern WCHAR *get_destination_dir( HINF hinf, const WCHAR *section );
|
||||
|
||||
/* support for Ascii queue callback functions */
|
||||
|
||||
struct callback_WtoA_context
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include "wine/test.h"
|
||||
|
||||
#define STD_HEADER "[Version]\r\nSignature=\"$CHICAGO$\"\r\n"
|
||||
|
||||
static inline const char* debugstr_longlong(ULONGLONG ll)
|
||||
{
|
||||
static char string[17];
|
||||
|
@ -40,6 +42,18 @@ static inline const char* debugstr_longlong(ULONGLONG ll)
|
|||
return string;
|
||||
}
|
||||
|
||||
/* create a new file with specified contents and open it */
|
||||
static HINF inf_open_file_content(const char * tmpfilename, const char *data, UINT *err_line)
|
||||
{
|
||||
DWORD res;
|
||||
HANDLE handle = CreateFileA(tmpfilename, GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0);
|
||||
if (handle == INVALID_HANDLE_VALUE) return 0;
|
||||
if (!WriteFile( handle, data, strlen(data), &res, NULL )) trace( "write error\n" );
|
||||
CloseHandle( handle );
|
||||
return SetupOpenInfFileA( tmpfilename, 0, INF_STYLE_WIN4, err_line );
|
||||
}
|
||||
|
||||
static void test_SetupCreateDiskSpaceListA(void)
|
||||
{
|
||||
HDSKSPC ret;
|
||||
|
@ -741,6 +755,184 @@ static void test_SetupQueryDrivesInDiskSpaceListA(void)
|
|||
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");
|
||||
|
||||
ok(SetupDestroyDiskSpaceList(handle),
|
||||
"Expected SetupDestroyDiskSpaceList to succeed\n");
|
||||
}
|
||||
|
||||
struct device_usage
|
||||
{
|
||||
const char *dev;
|
||||
LONGLONG usage;
|
||||
};
|
||||
|
||||
struct section
|
||||
{
|
||||
const char *name;
|
||||
UINT fileop;
|
||||
BOOL result;
|
||||
DWORD error_code;
|
||||
};
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *data;
|
||||
struct section sections[2];
|
||||
const char *devices;
|
||||
int device_length;
|
||||
struct device_usage usage[2];
|
||||
}
|
||||
section_test[] =
|
||||
{
|
||||
/* 0 */
|
||||
{STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
|
||||
{{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}},
|
||||
"c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
|
||||
/* 1 */
|
||||
{STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
|
||||
{{"a", FILEOP_DELETE, TRUE, 0}, {NULL, 0, TRUE, 0}},
|
||||
"c:\00", sizeof("c:\00"), {{"c:", 0}, {NULL, 0}}},
|
||||
/* 2 */
|
||||
{STD_HEADER "[a]\ntest,,,\n\r\n",
|
||||
{{"a", FILEOP_COPY, FALSE, ERROR_LINE_NOT_FOUND}, {NULL, 0, TRUE, 0}},
|
||||
"", sizeof(""), {{NULL, 0}, {NULL, 0}}},
|
||||
/* 3 */
|
||||
{STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\n[DestinationDirs]\nDefaultDestDir=-1,F:\\test\r\n",
|
||||
{{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}},
|
||||
"f:\00", sizeof("f:\00"), {{"f:", 4096}, {NULL, 0}}},
|
||||
/* 4 */
|
||||
{STD_HEADER "[a]\ntest,test2,,\n[SourceDisksFiles]\ntest2=1,,4096\r\n",
|
||||
{{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}},
|
||||
"c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
|
||||
/* 5 */
|
||||
{STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
|
||||
{{"b", FILEOP_COPY, FALSE, ERROR_SECTION_NOT_FOUND}, {NULL, 0, TRUE, 0}},
|
||||
"", sizeof(""), {{NULL, 0}, {NULL, 0}}},
|
||||
/* 6 */
|
||||
{STD_HEADER "[a]\ntest,,,\n[b]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
|
||||
{{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
|
||||
"c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
|
||||
/* 7 */
|
||||
{STD_HEADER "[a]\ntest,,,\n[b]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\n[DestinationDirs]\nb=-1,F:\\test\r\n",
|
||||
{{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
|
||||
"c:\00f:\00", sizeof("c:\00f:\00"), {{"c:", 4096}, {"f:", 4096}}},
|
||||
/* 8 */
|
||||
{STD_HEADER "[a]\ntest,test1,,\n[b]\ntest,test2,,\n[SourceDisksFiles]\ntest1=1,,4096\ntest2=1,,8192\r\n",
|
||||
{{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
|
||||
"c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}},
|
||||
/* 9 */
|
||||
{STD_HEADER "[a]\ntest1,test,,\n[b]\ntest2,test,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
|
||||
{{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
|
||||
"c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}},
|
||||
};
|
||||
|
||||
static void test_SetupAddSectionToDiskSpaceListA(void)
|
||||
{
|
||||
char tmp[MAX_PATH];
|
||||
char tmpfilename[MAX_PATH];
|
||||
char buffer[MAX_PATH];
|
||||
HDSKSPC diskspace;
|
||||
UINT err_line;
|
||||
LONGLONG space;
|
||||
BOOL ret;
|
||||
int i, j;
|
||||
HINF inf;
|
||||
|
||||
if (!GetTempPathA(MAX_PATH, tmp))
|
||||
{
|
||||
win_skip("GetTempPath failed with error %lu\n", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetTempFileNameA(tmp, "inftest", 0, tmpfilename))
|
||||
{
|
||||
win_skip("GetTempFileNameA failed with error %lu\n", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
inf = inf_open_file_content(tmpfilename, STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", &err_line);
|
||||
ok(!!inf, "Failed to open inf file (%lu, line %d)\n", GetLastError(), err_line);
|
||||
|
||||
diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK);
|
||||
ok(diskspace != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n");
|
||||
|
||||
ret = SetupAddSectionToDiskSpaceListA(diskspace, NULL, NULL, "a", FILEOP_COPY, 0, 0);
|
||||
ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n");
|
||||
ok(GetLastError() == ERROR_SECTION_NOT_FOUND, "Expected ERROR_SECTION_NOT_FOUND as error, got %lu\n",
|
||||
GetLastError());
|
||||
|
||||
ret = SetupAddSectionToDiskSpaceListA(NULL, inf, NULL, "a", FILEOP_COPY, 0, 0);
|
||||
ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE as error, got %lu\n",
|
||||
GetLastError());
|
||||
|
||||
ret = SetupAddSectionToDiskSpaceListA(NULL, inf, NULL, "b", FILEOP_COPY, 0, 0);
|
||||
ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE as error, got %lu\n",
|
||||
GetLastError());
|
||||
|
||||
ret = SetupAddSectionToDiskSpaceListA(diskspace, inf, NULL, "a", 0, 0, 0);
|
||||
ok(ret, "Expected SetupAddSectionToDiskSpaceListA to succeed (%lu)\n", GetLastError());
|
||||
|
||||
ok(SetupDestroyDiskSpaceList(diskspace),
|
||||
"Expected SetupDestroyDiskSpaceList to succeed\n");
|
||||
|
||||
for (i = 0; i < sizeof(section_test) / sizeof(section_test[0]); i++)
|
||||
{
|
||||
err_line = 0;
|
||||
|
||||
inf = inf_open_file_content(tmpfilename, section_test[i].data, &err_line);
|
||||
ok(!!inf, "test %d: Failed to open inf file (%lu, line %d)\n", i, GetLastError(), err_line);
|
||||
if (!inf) continue;
|
||||
|
||||
diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK);
|
||||
ok(diskspace != NULL, "Expected SetupCreateDiskSpaceListA to return a valid handle\n");
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
const struct section *section = §ion_test[i].sections[j];
|
||||
if (!section->name)
|
||||
continue;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetupAddSectionToDiskSpaceListA(diskspace, inf, NULL, section->name, section->fileop, 0, 0);
|
||||
if (section->result)
|
||||
ok(ret, "test %d: Expected adding section %d to succeed (%lu)\n", i, j, GetLastError());
|
||||
else
|
||||
{
|
||||
ok(!ret, "test %d: Expected adding section %d to fail\n", i, j);
|
||||
ok(GetLastError() == section->error_code, "test %d: Expected %lu as error, got %lu\n",
|
||||
i, section->error_code, GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
memset(buffer, 0x0, sizeof(buffer));
|
||||
ret = SetupQueryDrivesInDiskSpaceListA(diskspace, buffer, sizeof(buffer), NULL);
|
||||
ok(ret, "test %d: Expected SetupQueryDrivesInDiskSpaceListA to succeed (%lu)\n", i, GetLastError());
|
||||
ok(!memcmp(section_test[i].devices, buffer, section_test[i].device_length),
|
||||
"test %d: Device list (%s) does not match\n", i, buffer);
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
const struct device_usage *usage = §ion_test[i].usage[j];
|
||||
if (!usage->dev)
|
||||
continue;
|
||||
|
||||
space = 0;
|
||||
ret = SetupQuerySpaceRequiredOnDriveA(diskspace, usage->dev, &space, NULL, 0);
|
||||
ok(ret, "test %d: Expected SetupQuerySpaceRequiredOnDriveA to succeed for device %s (%lu)\n",
|
||||
i, usage->dev, GetLastError());
|
||||
ok(space == usage->usage, "test %d: Expected size %lu for device %s, got %lu\n",
|
||||
i, (DWORD)usage->usage, usage->dev, (DWORD)space);
|
||||
}
|
||||
|
||||
ok(SetupDestroyDiskSpaceList(diskspace),
|
||||
"Expected SetupDestroyDiskSpaceList to succeed\n");
|
||||
|
||||
SetupCloseInfFile(inf);
|
||||
}
|
||||
|
||||
DeleteFileA(tmpfilename);
|
||||
}
|
||||
|
||||
START_TEST(diskspace)
|
||||
|
@ -753,4 +945,5 @@ START_TEST(diskspace)
|
|||
test_SetupQuerySpaceRequiredOnDriveW();
|
||||
test_SetupAddToDiskSpaceListA();
|
||||
test_SetupQueryDrivesInDiskSpaceListA();
|
||||
test_SetupAddSectionToDiskSpaceListA();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,418 @@
|
|||
diff --git a/dll/win32/setupapi/diskspace.c b/dll/win32/setupapi/diskspace.c
|
||||
index 474f2b2c48b..c789fcd5958 100644
|
||||
--- a/dll/win32/setupapi/diskspace.c
|
||||
+++ b/dll/win32/setupapi/diskspace.c
|
||||
@@ -19,6 +19,7 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
+#include <stdlib.h>
|
||||
#include "setupapi_private.h"
|
||||
#include "wine/list.h"
|
||||
|
||||
@@ -52,6 +53,23 @@ static LONGLONG get_file_size(WCHAR *path)
|
||||
return size.QuadPart;
|
||||
}
|
||||
|
||||
+static BOOL get_size_from_inf(HINF layoutinf, WCHAR *filename, LONGLONG *size)
|
||||
+{
|
||||
+ static const WCHAR SourceDisksFiles[] = {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
|
||||
+ INFCONTEXT context;
|
||||
+ WCHAR buffer[20];
|
||||
+
|
||||
+ if (!SetupFindFirstLineW(layoutinf, SourceDisksFiles, filename, &context))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (!SetupGetStringFieldW(&context, 3, buffer, sizeof(buffer), NULL))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ /* FIXME: is there a atollW ? */
|
||||
+ *size = wcstol(buffer, NULL, 10);
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
/***********************************************************************
|
||||
* SetupCreateDiskSpaceListW (SETUPAPI.@)
|
||||
*/
|
||||
@@ -151,6 +169,117 @@ HDSKSPC WINAPI SetupDuplicateDiskSpaceListA(HDSKSPC DiskSpace, PVOID Reserved1,
|
||||
return SetupDuplicateDiskSpaceListW(DiskSpace, Reserved1, Reserved2, Flags);
|
||||
}
|
||||
|
||||
+/***********************************************************************
|
||||
+ * SetupAddSectionToDiskSpaceListW (SETUPAPI.@)
|
||||
+ */
|
||||
+BOOL WINAPI SetupAddSectionToDiskSpaceListW(HDSKSPC diskspace, HINF hinf, HINF hlist,
|
||||
+ PCWSTR section, UINT operation, PVOID reserved1,
|
||||
+ UINT reserved2)
|
||||
+{
|
||||
+ static const WCHAR sepW[] = {'\\',0};
|
||||
+ WCHAR dest[MAX_PATH], src[MAX_PATH], *dest_dir, *full_path;
|
||||
+ INFCONTEXT context;
|
||||
+ BOOL ret = FALSE;
|
||||
+
|
||||
+ TRACE("(%p, %p, %p, %s, %u, %p, %u)\n", diskspace, hinf, hlist, debugstr_w(section),
|
||||
+ operation, reserved1, reserved2);
|
||||
+
|
||||
+ if (!diskspace)
|
||||
+ {
|
||||
+ SetLastError(ERROR_INVALID_HANDLE);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ if (!section)
|
||||
+ {
|
||||
+ SetLastError(ERROR_INVALID_PARAMETER);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ if (!hlist) hlist = hinf;
|
||||
+
|
||||
+ if (!SetupFindFirstLineW(hlist, section, NULL, &context))
|
||||
+ {
|
||||
+ SetLastError(ERROR_SECTION_NOT_FOUND);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ dest_dir = get_destination_dir(hinf, section);
|
||||
+ if (!dest_dir)
|
||||
+ {
|
||||
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ do
|
||||
+ {
|
||||
+ LONGLONG filesize;
|
||||
+ int path_size;
|
||||
+ BOOL tmp_ret;
|
||||
+
|
||||
+ if (!SetupGetStringFieldW(&context, 1, dest, sizeof(dest) / sizeof(WCHAR), NULL))
|
||||
+ goto end;
|
||||
+ if (!SetupGetStringFieldW(&context, 2, src, sizeof(src) / sizeof(WCHAR), NULL))
|
||||
+ *src = 0;
|
||||
+ if (!get_size_from_inf(hinf, src[0] ? src : dest, &filesize))
|
||||
+ goto end;
|
||||
+
|
||||
+ path_size = lstrlenW(dest_dir) + lstrlenW(dest) + 2;
|
||||
+ full_path = HeapAlloc(GetProcessHeap(), 0, path_size * sizeof(WCHAR));
|
||||
+ if (!full_path)
|
||||
+ {
|
||||
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
+ goto end;
|
||||
+ }
|
||||
+
|
||||
+ lstrcpyW(full_path, dest_dir);
|
||||
+ lstrcatW(full_path, sepW);
|
||||
+ lstrcatW(full_path, dest);
|
||||
+
|
||||
+ tmp_ret = SetupAddToDiskSpaceListW(diskspace, full_path, filesize, operation, 0, 0);
|
||||
+ HeapFree(GetProcessHeap(), 0, full_path);
|
||||
+ if (!tmp_ret) goto end;
|
||||
+ }
|
||||
+ while (SetupFindNextLine(&context, &context));
|
||||
+
|
||||
+ ret = TRUE;
|
||||
+
|
||||
+end:
|
||||
+ HeapFree(GetProcessHeap(), 0, dest_dir);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * SetupAddSectionToDiskSpaceListA (SETUPAPI.@)
|
||||
+ */
|
||||
+BOOL WINAPI SetupAddSectionToDiskSpaceListA(HDSKSPC diskspace, HINF hinf, HINF hlist,
|
||||
+ PCSTR section, UINT operation, PVOID reserved1,
|
||||
+ UINT reserved2)
|
||||
+{
|
||||
+ LPWSTR sectionW = NULL;
|
||||
+ DWORD len;
|
||||
+ BOOL ret;
|
||||
+
|
||||
+ if (section)
|
||||
+ {
|
||||
+ len = MultiByteToWideChar(CP_ACP, 0, section, -1, NULL, 0);
|
||||
+
|
||||
+ sectionW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||
+ if (!sectionW)
|
||||
+ {
|
||||
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ MultiByteToWideChar(CP_ACP, 0, section, -1, sectionW, len);
|
||||
+ }
|
||||
+
|
||||
+ ret = SetupAddSectionToDiskSpaceListW(diskspace, hinf, hlist, sectionW, operation,
|
||||
+ reserved1, reserved2);
|
||||
+ if (sectionW) HeapFree(GetProcessHeap(), 0, sectionW);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/***********************************************************************
|
||||
* SetupAddInstallSectionToDiskSpaceListA (SETUPAPI.@)
|
||||
*/
|
||||
diff --git a/dll/win32/setupapi/queue.c b/dll/win32/setupapi/queue.c
|
||||
index c9f2d72431c..d908c92a0ef 100644
|
||||
--- a/dll/win32/setupapi/queue.c
|
||||
+++ b/dll/win32/setupapi/queue.c
|
||||
@@ -418,7 +418,7 @@ static void get_source_info( HINF hinf, const WCHAR *src_file, SP_FILE_COPY_PARA
|
||||
*
|
||||
* Retrieve the destination dir for a given section.
|
||||
*/
|
||||
-static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
|
||||
+WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
|
||||
{
|
||||
INFCONTEXT context;
|
||||
WCHAR systemdir[MAX_PATH], *dir;
|
||||
diff --git a/dll/win32/setupapi/setupapi.spec b/dll/win32/setupapi/setupapi.spec
|
||||
index 4a87ac167da..4bc3c552de5 100644
|
||||
--- a/dll/win32/setupapi/setupapi.spec
|
||||
+++ b/dll/win32/setupapi/setupapi.spec
|
||||
@@ -218,8 +218,8 @@
|
||||
@ stdcall MyRealloc(ptr long)
|
||||
@ stdcall SetupAddInstallSectionToDiskSpaceListA(long long long str ptr long)
|
||||
@ stub SetupAddInstallSectionToDiskSpaceListW
|
||||
-@ stdcall -stub SetupAddSectionToDiskSpaceListA(long long long str long ptr long)
|
||||
-@ stub SetupAddSectionToDiskSpaceListW
|
||||
+@ stdcall SetupAddSectionToDiskSpaceListA(ptr ptr ptr str long ptr long)
|
||||
+@ stdcall SetupAddSectionToDiskSpaceListW(ptr ptr ptr wstr long ptr long)
|
||||
@ stdcall SetupAddToDiskSpaceListA(long str int64 long ptr long)
|
||||
@ stdcall SetupAddToDiskSpaceListW(long wstr int64 long ptr long)
|
||||
@ stdcall SetupAddToSourceListA(long str)
|
||||
diff --git a/dll/win32/setupapi/setupapi_private.h b/dll/win32/setupapi/setupapi_private.h
|
||||
index af248ce8e73..970e197b401 100644
|
||||
--- a/dll/win32/setupapi/setupapi_private.h
|
||||
+++ b/dll/win32/setupapi/setupapi_private.h
|
||||
@@ -327,6 +327,8 @@ extern const WCHAR *PARSER_get_inf_filename( HINF hinf ) DECLSPEC_HIDDEN;
|
||||
extern WCHAR *PARSER_get_src_root( HINF hinf ) DECLSPEC_HIDDEN;
|
||||
extern WCHAR *PARSER_get_dest_dir( INFCONTEXT *context ) DECLSPEC_HIDDEN;
|
||||
|
||||
+extern WCHAR *get_destination_dir( HINF hinf, const WCHAR *section );
|
||||
+
|
||||
/* support for Ascii queue callback functions */
|
||||
|
||||
struct callback_WtoA_context
|
||||
diff --git a/modules/rostests/winetests/setupapi/diskspace.c b/modules/rostests/winetests/setupapi/diskspace.c
|
||||
index 0cacf9a75aa..8e2eb88bf93 100644
|
||||
--- a/modules/rostests/winetests/setupapi/diskspace.c
|
||||
+++ b/modules/rostests/winetests/setupapi/diskspace.c
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
+#define STD_HEADER "[Version]\r\nSignature=\"$CHICAGO$\"\r\n"
|
||||
+
|
||||
static inline const char* debugstr_longlong(ULONGLONG ll)
|
||||
{
|
||||
static char string[17];
|
||||
@@ -40,6 +42,18 @@ static inline const char* debugstr_longlong(ULONGLONG ll)
|
||||
return string;
|
||||
}
|
||||
|
||||
+/* create a new file with specified contents and open it */
|
||||
+static HINF inf_open_file_content(const char * tmpfilename, const char *data, UINT *err_line)
|
||||
+{
|
||||
+ DWORD res;
|
||||
+ HANDLE handle = CreateFileA(tmpfilename, GENERIC_READ|GENERIC_WRITE,
|
||||
+ FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0);
|
||||
+ if (handle == INVALID_HANDLE_VALUE) return 0;
|
||||
+ if (!WriteFile( handle, data, strlen(data), &res, NULL )) trace( "write error\n" );
|
||||
+ CloseHandle( handle );
|
||||
+ return SetupOpenInfFileA( tmpfilename, 0, INF_STYLE_WIN4, err_line );
|
||||
+}
|
||||
+
|
||||
static void test_SetupCreateDiskSpaceListA(void)
|
||||
{
|
||||
HDSKSPC ret;
|
||||
@@ -741,6 +755,184 @@ static void test_SetupQueryDrivesInDiskSpaceListA(void)
|
||||
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");
|
||||
+
|
||||
+ ok(SetupDestroyDiskSpaceList(handle),
|
||||
+ "Expected SetupDestroyDiskSpaceList to succeed\n");
|
||||
+}
|
||||
+
|
||||
+struct device_usage
|
||||
+{
|
||||
+ const char *dev;
|
||||
+ LONGLONG usage;
|
||||
+};
|
||||
+
|
||||
+struct section
|
||||
+{
|
||||
+ const char *name;
|
||||
+ UINT fileop;
|
||||
+ BOOL result;
|
||||
+ DWORD error_code;
|
||||
+};
|
||||
+
|
||||
+static const struct
|
||||
+{
|
||||
+ const char *data;
|
||||
+ struct section sections[2];
|
||||
+ const char *devices;
|
||||
+ int device_length;
|
||||
+ struct device_usage usage[2];
|
||||
+}
|
||||
+section_test[] =
|
||||
+{
|
||||
+ /* 0 */
|
||||
+ {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
|
||||
+ {{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}},
|
||||
+ "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
|
||||
+ /* 1 */
|
||||
+ {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
|
||||
+ {{"a", FILEOP_DELETE, TRUE, 0}, {NULL, 0, TRUE, 0}},
|
||||
+ "c:\00", sizeof("c:\00"), {{"c:", 0}, {NULL, 0}}},
|
||||
+ /* 2 */
|
||||
+ {STD_HEADER "[a]\ntest,,,\n\r\n",
|
||||
+ {{"a", FILEOP_COPY, FALSE, ERROR_LINE_NOT_FOUND}, {NULL, 0, TRUE, 0}},
|
||||
+ "", sizeof(""), {{NULL, 0}, {NULL, 0}}},
|
||||
+ /* 3 */
|
||||
+ {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\n[DestinationDirs]\nDefaultDestDir=-1,F:\\test\r\n",
|
||||
+ {{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}},
|
||||
+ "f:\00", sizeof("f:\00"), {{"f:", 4096}, {NULL, 0}}},
|
||||
+ /* 4 */
|
||||
+ {STD_HEADER "[a]\ntest,test2,,\n[SourceDisksFiles]\ntest2=1,,4096\r\n",
|
||||
+ {{"a", FILEOP_COPY, TRUE, 0}, {NULL, 0, TRUE, 0}},
|
||||
+ "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
|
||||
+ /* 5 */
|
||||
+ {STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
|
||||
+ {{"b", FILEOP_COPY, FALSE, ERROR_SECTION_NOT_FOUND}, {NULL, 0, TRUE, 0}},
|
||||
+ "", sizeof(""), {{NULL, 0}, {NULL, 0}}},
|
||||
+ /* 6 */
|
||||
+ {STD_HEADER "[a]\ntest,,,\n[b]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
|
||||
+ {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
|
||||
+ "c:\00", sizeof("c:\00"), {{"c:", 4096}, {NULL, 0}}},
|
||||
+ /* 7 */
|
||||
+ {STD_HEADER "[a]\ntest,,,\n[b]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\n[DestinationDirs]\nb=-1,F:\\test\r\n",
|
||||
+ {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
|
||||
+ "c:\00f:\00", sizeof("c:\00f:\00"), {{"c:", 4096}, {"f:", 4096}}},
|
||||
+ /* 8 */
|
||||
+ {STD_HEADER "[a]\ntest,test1,,\n[b]\ntest,test2,,\n[SourceDisksFiles]\ntest1=1,,4096\ntest2=1,,8192\r\n",
|
||||
+ {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
|
||||
+ "c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}},
|
||||
+ /* 9 */
|
||||
+ {STD_HEADER "[a]\ntest1,test,,\n[b]\ntest2,test,,\n[SourceDisksFiles]\ntest=1,,4096\r\n",
|
||||
+ {{"a", FILEOP_COPY, TRUE, 0}, {"b", FILEOP_COPY, TRUE, 0}},
|
||||
+ "c:\00", sizeof("c:\00"), {{"c:", 8192}, {NULL, 0}}},
|
||||
+};
|
||||
+
|
||||
+static void test_SetupAddSectionToDiskSpaceListA(void)
|
||||
+{
|
||||
+ char tmp[MAX_PATH];
|
||||
+ char tmpfilename[MAX_PATH];
|
||||
+ char buffer[MAX_PATH];
|
||||
+ HDSKSPC diskspace;
|
||||
+ UINT err_line;
|
||||
+ LONGLONG space;
|
||||
+ BOOL ret;
|
||||
+ int i, j;
|
||||
+ HINF inf;
|
||||
+
|
||||
+ if (!GetTempPathA(MAX_PATH, tmp))
|
||||
+ {
|
||||
+ win_skip("GetTempPath failed with error %lu\n", GetLastError());
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!GetTempFileNameA(tmp, "inftest", 0, tmpfilename))
|
||||
+ {
|
||||
+ win_skip("GetTempFileNameA failed with error %lu\n", GetLastError());
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ inf = inf_open_file_content(tmpfilename, STD_HEADER "[a]\ntest,,,\n[SourceDisksFiles]\ntest=1,,4096\r\n", &err_line);
|
||||
+ ok(!!inf, "Failed to open inf file (%lu, line %d)\n", GetLastError(), err_line);
|
||||
+
|
||||
+ diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK);
|
||||
+ ok(diskspace != NULL,"Expected SetupCreateDiskSpaceListA to return a valid handle\n");
|
||||
+
|
||||
+ ret = SetupAddSectionToDiskSpaceListA(diskspace, NULL, NULL, "a", FILEOP_COPY, 0, 0);
|
||||
+ ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n");
|
||||
+ ok(GetLastError() == ERROR_SECTION_NOT_FOUND, "Expected ERROR_SECTION_NOT_FOUND as error, got %lu\n",
|
||||
+ GetLastError());
|
||||
+
|
||||
+ ret = SetupAddSectionToDiskSpaceListA(NULL, inf, NULL, "a", FILEOP_COPY, 0, 0);
|
||||
+ ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n");
|
||||
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE as error, got %lu\n",
|
||||
+ GetLastError());
|
||||
+
|
||||
+ ret = SetupAddSectionToDiskSpaceListA(NULL, inf, NULL, "b", FILEOP_COPY, 0, 0);
|
||||
+ ok(!ret, "Expected SetupAddSectionToDiskSpaceListA to fail\n");
|
||||
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE as error, got %lu\n",
|
||||
+ GetLastError());
|
||||
+
|
||||
+ ret = SetupAddSectionToDiskSpaceListA(diskspace, inf, NULL, "a", 0, 0, 0);
|
||||
+ ok(ret, "Expected SetupAddSectionToDiskSpaceListA to succeed (%lu)\n", GetLastError());
|
||||
+
|
||||
+ ok(SetupDestroyDiskSpaceList(diskspace),
|
||||
+ "Expected SetupDestroyDiskSpaceList to succeed\n");
|
||||
+
|
||||
+ for (i = 0; i < sizeof(section_test) / sizeof(section_test[0]); i++)
|
||||
+ {
|
||||
+ err_line = 0;
|
||||
+
|
||||
+ inf = inf_open_file_content(tmpfilename, section_test[i].data, &err_line);
|
||||
+ ok(!!inf, "test %d: Failed to open inf file (%lu, line %d)\n", i, GetLastError(), err_line);
|
||||
+ if (!inf) continue;
|
||||
+
|
||||
+ diskspace = SetupCreateDiskSpaceListA(NULL, 0, SPDSL_IGNORE_DISK);
|
||||
+ ok(diskspace != NULL, "Expected SetupCreateDiskSpaceListA to return a valid handle\n");
|
||||
+
|
||||
+ for (j = 0; j < 2; j++)
|
||||
+ {
|
||||
+ const struct section *section = §ion_test[i].sections[j];
|
||||
+ if (!section->name)
|
||||
+ continue;
|
||||
+
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ret = SetupAddSectionToDiskSpaceListA(diskspace, inf, NULL, section->name, section->fileop, 0, 0);
|
||||
+ if (section->result)
|
||||
+ ok(ret, "test %d: Expected adding section %d to succeed (%lu)\n", i, j, GetLastError());
|
||||
+ else
|
||||
+ {
|
||||
+ ok(!ret, "test %d: Expected adding section %d to fail\n", i, j);
|
||||
+ ok(GetLastError() == section->error_code, "test %d: Expected %lu as error, got %lu\n",
|
||||
+ i, section->error_code, GetLastError());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ memset(buffer, 0x0, sizeof(buffer));
|
||||
+ ret = SetupQueryDrivesInDiskSpaceListA(diskspace, buffer, sizeof(buffer), NULL);
|
||||
+ ok(ret, "test %d: Expected SetupQueryDrivesInDiskSpaceListA to succeed (%lu)\n", i, GetLastError());
|
||||
+ ok(!memcmp(section_test[i].devices, buffer, section_test[i].device_length),
|
||||
+ "test %d: Device list (%s) does not match\n", i, buffer);
|
||||
+
|
||||
+ for (j = 0; j < 2; j++)
|
||||
+ {
|
||||
+ const struct device_usage *usage = §ion_test[i].usage[j];
|
||||
+ if (!usage->dev)
|
||||
+ continue;
|
||||
+
|
||||
+ space = 0;
|
||||
+ ret = SetupQuerySpaceRequiredOnDriveA(diskspace, usage->dev, &space, NULL, 0);
|
||||
+ ok(ret, "test %d: Expected SetupQuerySpaceRequiredOnDriveA to succeed for device %s (%lu)\n",
|
||||
+ i, usage->dev, GetLastError());
|
||||
+ ok(space == usage->usage, "test %d: Expected size %lu for device %s, got %lu\n",
|
||||
+ i, (DWORD)usage->usage, usage->dev, (DWORD)space);
|
||||
+ }
|
||||
+
|
||||
+ ok(SetupDestroyDiskSpaceList(diskspace),
|
||||
+ "Expected SetupDestroyDiskSpaceList to succeed\n");
|
||||
+
|
||||
+ SetupCloseInfFile(inf);
|
||||
+ }
|
||||
+
|
||||
+ DeleteFileA(tmpfilename);
|
||||
}
|
||||
|
||||
START_TEST(diskspace)
|
||||
@@ -753,4 +945,5 @@ START_TEST(diskspace)
|
||||
test_SetupQuerySpaceRequiredOnDriveW();
|
||||
test_SetupAddToDiskSpaceListA();
|
||||
test_SetupQueryDrivesInDiskSpaceListA();
|
||||
+ test_SetupAddSectionToDiskSpaceListA();
|
||||
}
|
Loading…
Reference in a new issue