[WINESYNC] setupapi: Avoid debugstr buffer overflow.

Signed-off-by: Józef Kucia <jkucia@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 88e28d971bd119f214e29d4ebfa819af9f18f5b7 by Józef Kucia <jkucia@codeweavers.com>

[WINESYNC] setupapi: Handle an empty string for the source file in SetupQueueCopySection().

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47185
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 86724af01241b257a4b4b39682031c9c7a3aaeaa by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi/tests: Add some basic tests for SetupDi{Get, Set}DeviceInstallParams().

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Aric Stewart <aric@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 45d199023f440209c5753e055db233924664df22 by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi/tests: Add tests for SetupDiGetActualSectionToInstall().

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 6244f05941f13bf330d68208849d74ae54f116a0 by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Return the section name in SetupDiGetActualSectionToInstall() even if it doesn't exist.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 23320d05b628575ab9ccb44e4482a30268e9a93e by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi/tests: Add some tests for SetupInstallFile().

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 2ddc60c8f0276c739b2f512397d32e1b9425e4b0 by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Retrieve the default destination path in SetupInstallFile().

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id d5f6d6419b16ef81ce882f01a318189251320fcb by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Clear the Win32 error if no copy was necessary.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id a748f685a502891bc8fa5f4719f80b6feb39ac9c by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Don't fail a queued copy if no copy was necessary.

This fixes a regression introduced by 3e5c9798a80641e0e39e95e4467c60405b22b062.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47219
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 8bc25b24af0276985ad080c8364c11cfff3a1fe5 by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi/tests: Add tests for building and enumerating driver lists.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 57c3ebec7c803857f39a6cb1033f8a67e3949190 by Zebediah Figura <z.figura12@gmail.com>

[WINESYNC] setupapi: Add a basic implementation of SetupDiCallClassInstaller().

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>

wine commit id 43ee138d4747722cfc7d27e59014a47c3003a898 by Zebediah Figura <z.figura12@gmail.com>
This commit is contained in:
winesync 2023-09-25 17:37:59 +02:00 committed by Hermès Bélusca-Maïto
parent b22b28a68d
commit 2e5c712eb6
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
5 changed files with 655 additions and 32 deletions

View file

@ -2012,12 +2012,8 @@ BOOL WINAPI SetupGetBinaryField( PINFCONTEXT context, DWORD index, BYTE *buffer,
}
buffer[i - index] = value;
}
if (TRACE_ON(setupapi))
{
TRACE( "%p/%p/%d/%d index %d returning:\n",
context->Inf, context->CurrentInf, context->Section, context->Line, index );
for (i = index; i < line->nb_fields; i++) TRACE( " %02x\n", buffer[i - index] );
}
TRACE( "%p/%p/%d/%d index %d\n",
context->Inf, context->CurrentInf, context->Section, context->Line, index );
return TRUE;
}

View file

@ -922,6 +922,7 @@ BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf,
SP_FILE_COPY_PARAMS_W params;
INT flags;
BOOL ret;
DWORD len;
TRACE("queue %p, src_root %s, hinf %p, hlist %p, section %s, style %#x.\n",
queue, debugstr_w(src_root), hinf, hlist, debugstr_w(section), style);
@ -993,7 +994,7 @@ BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf,
if (!SetupGetStringFieldW( &context, 1, dst_file, ARRAY_SIZE( dst_file ), NULL ))
goto end;
if (!SetupGetStringFieldW( &context, 2, src_file, ARRAY_SIZE( src_file ), NULL ))
if (!SetupGetStringFieldW( &context, 2, src_file, ARRAY_SIZE( src_file ), &len ) || len <= sizeof(WCHAR))
strcpyW( src_file, dst_file );
if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */
@ -1396,6 +1397,8 @@ static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
#endif
TRACE("Did copy... rc was %i\n",rc);
}
else
SetLastError(ERROR_SUCCESS);
/* after copy processing */
if (style & SP_COPY_DELETESOURCE)
@ -1467,7 +1470,7 @@ BOOL WINAPI SetupInstallFileExW( HINF hinf, PINFCONTEXT inf_context, PCWSTR sour
static const WCHAR CopyFiles[] = {'C','o','p','y','F','i','l','e','s',0};
BOOL ret, absolute = (root && *root && !(style & SP_COPY_SOURCE_ABSOLUTE));
WCHAR *buffer, *p, *inf_source = NULL;
WCHAR *buffer, *p, *inf_source = NULL, dest_path[MAX_PATH];
unsigned int len;
TRACE("%p %p %s %s %s %x %p %p %p\n", hinf, inf_context, debugstr_w(source), debugstr_w(root),
@ -1475,8 +1478,11 @@ BOOL WINAPI SetupInstallFileExW( HINF hinf, PINFCONTEXT inf_context, PCWSTR sour
if (in_use) FIXME("no file in use support\n");
dest_path[0] = 0;
if (hinf)
{
WCHAR *dest_dir;
INFCONTEXT ctx;
if (!inf_context)
@ -1496,6 +1502,13 @@ BOOL WINAPI SetupInstallFileExW( HINF hinf, PINFCONTEXT inf_context, PCWSTR sour
return FALSE;
}
source = inf_source;
if ((dest_dir = get_destination_dir( hinf, NULL )))
{
strcpyW( dest_path, dest_dir );
strcatW( dest_path, backslashW );
heap_free( dest_dir );
}
}
else if (!source)
{
@ -1522,7 +1535,9 @@ BOOL WINAPI SetupInstallFileExW( HINF hinf, PINFCONTEXT inf_context, PCWSTR sour
while (*source == '\\') source++;
strcpyW( p, source );
ret = do_file_copyW( buffer, dest, style, handler, context );
strcatW( dest_path, dest );
ret = do_file_copyW( buffer, dest_path, style, handler, context );
HeapFree( GetProcessHeap(), 0, inf_source );
HeapFree( GetProcessHeap(), 0, buffer );
@ -1546,7 +1561,7 @@ static BOOL queue_copy_file( const WCHAR *source, const WCHAR *dest,
if (op->dst_path && !create_full_pathW(op->dst_path))
return FALSE;
if (do_file_copyW(source, dest, op->style, handler, context))
if (do_file_copyW(source, dest, op->style, handler, context) || GetLastError() == ERROR_SUCCESS)
return TRUE;
/* try to extract it from the cabinet file */

View file

@ -45,6 +45,21 @@ static GUID guid2 = {0x6a55b5a5, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,
BOOL (WINAPI *pSetupDiSetDevicePropertyW)(HDEVINFO, PSP_DEVINFO_DATA, const DEVPROPKEY *, DEVPROPTYPE, const BYTE *, DWORD, DWORD);
BOOL (WINAPI *pSetupDiGetDevicePropertyW)(HDEVINFO, PSP_DEVINFO_DATA, const DEVPROPKEY *, DEVPROPTYPE *, BYTE *, DWORD, DWORD *, DWORD);
static BOOL wow64;
static void create_file(const char *name, const char *data)
{
HANDLE file;
DWORD size;
BOOL ret;
file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
ok(file != INVALID_HANDLE_VALUE, "Failed to create %s, error %u.\n", name, GetLastError());
ret = WriteFile(file, data, strlen(data), &size, NULL);
ok(ret && size == strlen(data), "Failed to write %s, error %u.\n", name, GetLastError());
CloseHandle(file);
}
static void test_create_device_list_ex(void)
{
static const WCHAR machine[] = { 'd','u','m','m','y',0 };
@ -107,26 +122,6 @@ todo_wine
RegCloseKey(root_key);
}
static void create_inf_file(LPCSTR filename)
{
DWORD dwNumberOfBytesWritten;
HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
static const char data[] =
"[Version]\n"
"Signature=\"$Chicago$\"\n"
"Class=Bogus\n"
"ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n"
"[ClassInstall32]\n"
"AddReg=BogusClass.NT.AddReg\n"
"[BogusClass.NT.AddReg]\n"
"HKR,,,,\"Wine test devices\"\n";
WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
CloseHandle(hf);
}
static void get_temp_filename(LPSTR path)
{
static char curr[MAX_PATH] = { 0 };
@ -152,10 +147,20 @@ static void test_install_class(void)
char tmpfile[MAX_PATH];
BOOL ret;
static const char inf_data[] =
"[Version]\n"
"Signature=\"$Chicago$\"\n"
"Class=Bogus\n"
"ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n"
"[ClassInstall32]\n"
"AddReg=BogusClass.NT.AddReg\n"
"[BogusClass.NT.AddReg]\n"
"HKR,,,,\"Wine test devices\"\n";
tmpfile[0] = '.';
tmpfile[1] = '\\';
get_temp_filename(tmpfile + 2);
create_inf_file(tmpfile + 2);
create_file(tmpfile + 2, inf_data);
ret = SetupDiInstallClassA(NULL, NULL, 0, NULL);
ok(!ret, "Expected failure.\n");
@ -1885,10 +1890,510 @@ static void test_device_interface_key(void)
SetupDiDestroyDeviceInfoList(set);
}
static void test_device_install_params(void)
{
SP_DEVINFO_DATA device = {sizeof(device)};
SP_DEVINSTALL_PARAMS_A params;
HDEVINFO set;
BOOL ret;
set = SetupDiCreateDeviceInfoList(&guid, NULL);
ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device);
ok(ret, "Failed to create device, error %#x.\n", GetLastError());
params.cbSize = sizeof(params) - 1;
SetLastError(0xdeadbeef);
ret = SetupDiGetDeviceInstallParamsA(set, &device, &params);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
params.cbSize = sizeof(params) + 1;
SetLastError(0xdeadbeef);
ret = SetupDiGetDeviceInstallParamsA(set, &device, &params);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
params.cbSize = sizeof(params) - 1;
SetLastError(0xdeadbeef);
ret = SetupDiSetDeviceInstallParamsA(set, &device, &params);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
params.cbSize = sizeof(params) + 1;
SetLastError(0xdeadbeef);
ret = SetupDiSetDeviceInstallParamsA(set, &device, &params);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
memset(&params, 0xcc, sizeof(params));
params.cbSize = sizeof(params);
ret = SetupDiGetDeviceInstallParamsA(set, &device, &params);
ok(ret, "Failed to get device install params, error %#x.\n", GetLastError());
ok(!params.Flags, "Got flags %#x.\n", params.Flags);
ok(!params.FlagsEx, "Got extended flags %#x.\n", params.FlagsEx);
ok(!params.hwndParent, "Got parent %p.\n", params.hwndParent);
ok(!params.InstallMsgHandler, "Got callback %p.\n", params.InstallMsgHandler);
ok(!params.InstallMsgHandlerContext, "Got callback context %p.\n", params.InstallMsgHandlerContext);
ok(!params.FileQueue, "Got queue %p.\n", params.FileQueue);
ok(!params.ClassInstallReserved, "Got class installer data %#lx.\n", params.ClassInstallReserved);
ok(!params.DriverPath[0], "Got driver path %s.\n", params.DriverPath);
params.Flags = DI_INF_IS_SORTED;
params.FlagsEx = DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
strcpy(params.DriverPath, "C:\\windows");
ret = SetupDiSetDeviceInstallParamsA(set, &device, &params);
ok(ret, "Failed to set device install params, error %#x.\n", GetLastError());
memset(&params, 0xcc, sizeof(params));
params.cbSize = sizeof(params);
ret = SetupDiGetDeviceInstallParamsA(set, &device, &params);
ok(ret, "Failed to get device install params, error %#x.\n", GetLastError());
ok(params.Flags == DI_INF_IS_SORTED, "Got flags %#x.\n", params.Flags);
ok(params.FlagsEx == DI_FLAGSEX_ALLOWEXCLUDEDDRVS, "Got extended flags %#x.\n", params.FlagsEx);
ok(!params.hwndParent, "Got parent %p.\n", params.hwndParent);
ok(!params.InstallMsgHandler, "Got callback %p.\n", params.InstallMsgHandler);
ok(!params.InstallMsgHandlerContext, "Got callback context %p.\n", params.InstallMsgHandlerContext);
ok(!params.FileQueue, "Got queue %p.\n", params.FileQueue);
ok(!params.ClassInstallReserved, "Got class installer data %#lx.\n", params.ClassInstallReserved);
ok(!strcasecmp(params.DriverPath, "C:\\windows"), "Got driver path %s.\n", params.DriverPath);
SetupDiDestroyDeviceInfoList(set);
}
#ifdef __i386__
#define MYEXT "x86"
#define WOWEXT "AMD64"
#define WRONGEXT "ARM"
#elif defined(__x86_64__)
#define MYEXT "AMD64"
#define WOWEXT "x86"
#define WRONGEXT "ARM64"
#elif defined(__arm__)
#define MYEXT "ARM"
#define WOWEXT "ARM64"
#define WRONGEXT "x86"
#elif defined(__aarch64__)
#define MYEXT "ARM64"
#define WOWEXT "ARM"
#define WRONGEXT "AMD64"
#else
#define MYEXT
#define WOWEXT
#define WRONGEXT
#endif
static void test_get_actual_section(void)
{
static const char inf_data[] = "[Version]\n"
"Signature=\"$Chicago$\"\n"
"[section1]\n"
"[section2]\n"
"[section2.nt]\n"
"[section3]\n"
"[section3.nt" MYEXT "]\n"
"[section4]\n"
"[section4.nt]\n"
"[section4.nt" MYEXT "]\n"
"[section5.nt]\n"
"[section6.nt" MYEXT "]\n"
"[section7]\n"
"[section7.nt" WRONGEXT "]\n"
"[section8.nt" WRONGEXT "]\n"
"[section9.nt" MYEXT "]\n"
"[section9.nt" WOWEXT "]\n"
"[section10.nt" WOWEXT "]\n";
char inf_path[MAX_PATH], section[LINE_LEN], *extptr;
DWORD size;
HINF hinf;
BOOL ret;
GetTempPathA(sizeof(inf_path), inf_path);
strcat(inf_path, "setupapi_test.inf");
create_file(inf_path, inf_data);
hinf = SetupOpenInfFileA(inf_path, NULL, INF_STYLE_WIN4, NULL);
ok(hinf != INVALID_HANDLE_VALUE, "Failed to open INF file, error %#x.\n", GetLastError());
ret = SetupDiGetActualSectionToInstallA(hinf, "section1", section, ARRAY_SIZE(section), NULL, NULL);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcmp(section, "section1"), "Got unexpected section %s.\n", section);
size = 0xdeadbeef;
ret = SetupDiGetActualSectionToInstallA(hinf, "section1", NULL, 5, &size, NULL);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(size == 9, "Got size %u.\n", size);
SetLastError(0xdeadbeef);
size = 0xdeadbeef;
ret = SetupDiGetActualSectionToInstallA(hinf, "section1", section, 5, &size, NULL);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected error %#x.\n", GetLastError());
ok(size == 9, "Got size %u.\n", size);
SetLastError(0xdeadbeef);
ret = SetupDiGetActualSectionToInstallA(hinf, "section1", section, ARRAY_SIZE(section), &size, NULL);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "section1"), "Got unexpected section %s.\n", section);
ok(size == 9, "Got size %u.\n", size);
extptr = section;
ret = SetupDiGetActualSectionToInstallA(hinf, "section1", section, ARRAY_SIZE(section), NULL, &extptr);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "section1"), "Got unexpected section %s.\n", section);
ok(!extptr || !*extptr /* Windows 10 1809 */, "Got extension %s.\n", extptr);
extptr = section;
ret = SetupDiGetActualSectionToInstallA(hinf, "section2", section, ARRAY_SIZE(section), NULL, &extptr);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "section2.NT"), "Got unexpected section %s.\n", section);
ok(extptr == section + 8, "Got extension %s.\n", extptr);
extptr = section;
ret = SetupDiGetActualSectionToInstallA(hinf, "section3", section, ARRAY_SIZE(section), NULL, &extptr);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "section3.NT" MYEXT), "Got unexpected section %s.\n", section);
ok(extptr == section + 8, "Got extension %s.\n", extptr);
extptr = section;
ret = SetupDiGetActualSectionToInstallA(hinf, "section4", section, ARRAY_SIZE(section), NULL, &extptr);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "section4.NT" MYEXT), "Got unexpected section %s.\n", section);
ok(extptr == section + 8, "Got extension %s.\n", extptr);
extptr = section;
ret = SetupDiGetActualSectionToInstallA(hinf, "section5", section, ARRAY_SIZE(section), NULL, &extptr);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "section5.NT"), "Got unexpected section %s.\n", section);
ok(extptr == section + 8, "Got extension %s.\n", extptr);
extptr = section;
ret = SetupDiGetActualSectionToInstallA(hinf, "section6", section, ARRAY_SIZE(section), NULL, &extptr);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "section6.NT" MYEXT), "Got unexpected section %s.\n", section);
ok(extptr == section + 8, "Got extension %s.\n", extptr);
extptr = section;
ret = SetupDiGetActualSectionToInstallA(hinf, "section7", section, ARRAY_SIZE(section), NULL, &extptr);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "section7"), "Got unexpected section %s.\n", section);
ok(!extptr || !*extptr /* Windows 10 1809 */, "Got extension %s.\n", extptr);
extptr = section;
ret = SetupDiGetActualSectionToInstallA(hinf, "section8", section, ARRAY_SIZE(section), NULL, &extptr);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "section8"), "Got unexpected section %s.\n", section);
ok(!extptr || !*extptr /* Windows 10 1809 */, "Got extension %s.\n", extptr);
extptr = section;
ret = SetupDiGetActualSectionToInstallA(hinf, "nonexistent", section, ARRAY_SIZE(section), NULL, &extptr);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "nonexistent"), "Got unexpected section %s.\n", section);
ok(!extptr || !*extptr /* Windows 10 1809 */, "Got extension %s.\n", extptr);
extptr = section;
ret = SetupDiGetActualSectionToInstallA(hinf, "section9", section, ARRAY_SIZE(section), NULL, &extptr);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "section9.NT" MYEXT), "Got unexpected section %s.\n", section);
ok(extptr == section + 8, "Got extension %s.\n", extptr);
if (0)
{
/* For some reason, this call hangs on Windows 10 1809. */
extptr = section;
ret = SetupDiGetActualSectionToInstallA(hinf, "section10", section, ARRAY_SIZE(section), NULL, &extptr);
ok(ret, "Failed to get section, error %#x.\n", GetLastError());
ok(!strcasecmp(section, "section10"), "Got unexpected section %s.\n", section);
ok(!extptr, "Got extension %s.\n", extptr);
}
SetupCloseInfFile(hinf);
ret = DeleteFileA(inf_path);
ok(ret, "Failed to delete %s, error %u.\n", inf_path, GetLastError());
}
static void test_driver_list(void)
{
char inf_dir[MAX_PATH], inf_path[MAX_PATH], inf_path2[MAX_PATH];
static const char hardware_id[] = "bogus_hardware_id\0";
static const char compat_id[] = "bogus_compat_id\0";
SP_DEVINSTALL_PARAMS_A params = {sizeof(params)};
SP_DRVINFO_DATA_A driver = {sizeof(driver)};
SP_DEVINFO_DATA device = {sizeof(device)};
HDEVINFO set;
BOOL ret;
static const char inf_data[] = "[Version]\n"
"Signature=\"$Chicago$\"\n"
"ClassGuid={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n"
"[Manufacturer]\n"
"mfg1=mfg1_key,NT" MYEXT "\n"
"mfg2=mfg2_key,NT" MYEXT "\n"
"mfg1_wow=mfg1_key,NT" WOWEXT "\n"
"mfg2_wow=mfg2_key,NT" WOWEXT "\n"
"mfg3=mfg3_key,NT" WRONGEXT "\n"
"[mfg1_key.nt" MYEXT "]\n"
"desc1=,bogus_hardware_id\n"
"desc2=,bogus_hardware_id\n"
"desc3=,wrong_hardware_id\n"
"desc4=,wrong_hardware_id,bogus_compat_id\n"
"[mfg1_key.nt" WOWEXT "]\n"
"desc1=,bogus_hardware_id\n"
"desc2=,bogus_hardware_id\n"
"desc3=,wrong_hardware_id\n"
"desc4=,wrong_hardware_id,bogus_compat_id\n"
"[mfg2_key.nt" MYEXT "]\n"
"desc5=,bogus_hardware_id\n"
"[mfg2_key.nt" WOWEXT "]\n"
"desc5=,bogus_hardware_id\n"
"[mfg3_key.nt" WRONGEXT "]\n"
"desc6=,bogus_hardware_id\n";
static const char inf_data_file1[] = "[Version]\n"
"Signature=\"$Chicago$\"\n"
"ClassGuid={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n"
"[Manufacturer]\n"
"mfg1=mfg1_key,NT" MYEXT ",NT" WOWEXT "\n"
"[mfg1_key.nt" MYEXT "]\n"
"desc1=,bogus_hardware_id\n"
"[mfg1_key.nt" WOWEXT "]\n"
"desc1=,bogus_hardware_id\n";
static const char inf_data_file2[] = "[Version]\n"
"Signature=\"$Chicago$\"\n"
"ClassGuid={6a55b5a5-3f65-11db-b704-0011955c2bdb}\n"
"[Manufacturer]\n"
"mfg1=mfg1_key,NT" MYEXT ",NT" WOWEXT "\n"
"[mfg1_key.nt" MYEXT "]\n"
"desc2=,bogus_hardware_id\n"
"[mfg1_key.nt" WOWEXT "]\n"
"desc2=,bogus_hardware_id\n";
GetTempPathA(sizeof(inf_path), inf_path);
strcat(inf_path, "setupapi_test.inf");
create_file(inf_path, inf_data);
set = SetupDiCreateDeviceInfoList(NULL, NULL);
ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
ret = SetupDiCreateDeviceInfoA(set, "Root\\BOGUS\\0000", &GUID_NULL, NULL, NULL, 0, &device);
ok(ret, "Failed to create device, error %#x.\n", GetLastError());
ret = SetupDiSetDeviceRegistryPropertyA(set, &device, SPDRP_HARDWAREID,
(const BYTE *)hardware_id, sizeof(hardware_id));
ok(ret, "Failed to set hardware ID, error %#x.\n", GetLastError());
ret = SetupDiSetDeviceRegistryPropertyA(set, &device, SPDRP_COMPATIBLEIDS,
(const BYTE *)compat_id, sizeof(compat_id));
ok(ret, "Failed to set hardware ID, error %#x.\n", GetLastError());
SetLastError(0xdeadbeef);
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 0, &driver);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_NO_MORE_ITEMS, "Got unexpected error %#x.\n", GetLastError());
ret = SetupDiGetDeviceInstallParamsA(set, &device, &params);
ok(ret, "Failed to get device install params, error %#x.\n", GetLastError());
strcpy(params.DriverPath, inf_path);
params.Flags = DI_ENUMSINGLEINF;
ret = SetupDiSetDeviceInstallParamsA(set, &device, &params);
ok(ret, "Failed to set device install params, error %#x.\n", GetLastError());
ret = SetupDiBuildDriverInfoList(set, &device, SPDIT_COMPATDRIVER);
ok(ret, "Failed to build driver list, error %#x.\n", GetLastError());
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 0, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
ok(!strcmp(driver.Description, "desc1"), "Got wrong description '%s'.\n", driver.Description);
ok(!strcmp(driver.MfgName, wow64 ? "mfg1_wow" : "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 1, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
ok(!strcmp(driver.Description, "desc2"), "Got wrong description '%s'.\n", driver.Description);
ok(!strcmp(driver.MfgName, wow64 ? "mfg1_wow" : "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 2, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
ok(!strcmp(driver.Description, "desc4"), "Got wrong description '%s'.\n", driver.Description);
ok(!strcmp(driver.MfgName, wow64 ? "mfg1_wow" : "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 3, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
ok(!strcmp(driver.Description, "desc5"), "Got wrong description '%s'.\n", driver.Description);
ok(!strcmp(driver.MfgName, wow64 ? "mfg2_wow" : "mfg2"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
SetLastError(0xdeadbeef);
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 4, &driver);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_NO_MORE_ITEMS, "Got unexpected error %#x.\n", GetLastError());
SetupDiDestroyDeviceInfoList(set);
ret = DeleteFileA(inf_path);
ok(ret, "Failed to delete %s, error %u.\n", inf_path, GetLastError());
/* Test building from a path. */
GetTempPathA(sizeof(inf_dir), inf_dir);
strcat(inf_dir, "setupapi_test");
ret = CreateDirectoryA(inf_dir, NULL);
ok(ret, "Failed to create directory, error %u.\n", GetLastError());
sprintf(inf_path, "%s/test1.inf", inf_dir);
create_file(inf_path, inf_data_file1);
sprintf(inf_path2, "%s/test2.inf", inf_dir);
create_file(inf_path2, inf_data_file2);
set = SetupDiCreateDeviceInfoList(NULL, NULL);
ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
ret = SetupDiCreateDeviceInfoA(set, "Root\\BOGUS\\0000", &GUID_NULL, NULL, NULL, 0, &device);
ok(ret, "Failed to create device, error %#x.\n", GetLastError());
ret = SetupDiSetDeviceRegistryPropertyA(set, &device, SPDRP_HARDWAREID,
(const BYTE *)hardware_id, sizeof(hardware_id));
ok(ret, "Failed to set hardware ID, error %#x.\n", GetLastError());
ret = SetupDiGetDeviceInstallParamsA(set, &device, &params);
ok(ret, "Failed to get device install params, error %#x.\n", GetLastError());
strcpy(params.DriverPath, inf_dir);
ret = SetupDiSetDeviceInstallParamsA(set, &device, &params);
ok(ret, "Failed to set device install params, error %#x.\n", GetLastError());
ret = SetupDiBuildDriverInfoList(set, &device, SPDIT_COMPATDRIVER);
ok(ret, "Failed to build driver list, error %#x.\n", GetLastError());
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 0, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
ok(!strcmp(driver.Description, "desc1"), "Got wrong description '%s'.\n", driver.Description);
ok(!strcmp(driver.MfgName, "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 1, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
ok(!strcmp(driver.Description, "desc2"), "Got wrong description '%s'.\n", driver.Description);
ok(!strcmp(driver.MfgName, "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
SetLastError(0xdeadbeef);
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 2, &driver);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_NO_MORE_ITEMS, "Got unexpected error %#x.\n", GetLastError());
SetupDiDestroyDeviceInfoList(set);
ret = DeleteFileA(inf_path);
ok(ret, "Failed to delete %s, error %u.\n", inf_path, GetLastError());
ret = DeleteFileA(inf_path2);
ok(ret, "Failed to delete %s, error %u.\n", inf_path2, GetLastError());
ret = RemoveDirectoryA(inf_dir);
ok(ret, "Failed to delete %s, error %u.\n", inf_dir, GetLastError());
/* Test the default path. */
create_file("C:/windows/inf/wine_test1.inf", inf_data_file1);
create_file("C:/windows/inf/wine_test2.inf", inf_data_file2);
set = SetupDiCreateDeviceInfoList(NULL, NULL);
ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
ret = SetupDiCreateDeviceInfoA(set, "Root\\BOGUS\\0000", &GUID_NULL, NULL, NULL, 0, &device);
ok(ret, "Failed to create device, error %#x.\n", GetLastError());
ret = SetupDiSetDeviceRegistryPropertyA(set, &device, SPDRP_HARDWAREID,
(const BYTE *)hardware_id, sizeof(hardware_id));
ok(ret, "Failed to set hardware ID, error %#x.\n", GetLastError());
ret = SetupDiBuildDriverInfoList(set, &device, SPDIT_COMPATDRIVER);
ok(ret, "Failed to build driver list, error %#x.\n", GetLastError());
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 0, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
ok(!strcmp(driver.Description, "desc1"), "Got wrong description '%s'.\n", driver.Description);
ok(!strcmp(driver.MfgName, "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 1, &driver);
ok(ret, "Failed to enumerate drivers, error %#x.\n", GetLastError());
ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
ok(!strcmp(driver.Description, "desc2"), "Got wrong description '%s'.\n", driver.Description);
ok(!strcmp(driver.MfgName, "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
SetLastError(0xdeadbeef);
ret = SetupDiEnumDriverInfoA(set, &device, SPDIT_COMPATDRIVER, 2, &driver);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_NO_MORE_ITEMS, "Got unexpected error %#x.\n", GetLastError());
SetupDiDestroyDeviceInfoList(set);
ret = DeleteFileA("C:/windows/inf/wine_test1.inf");
ok(ret, "Failed to delete %s, error %u.\n", inf_path, GetLastError());
ret = DeleteFileA("C:/windows/inf/wine_test2.inf");
ok(ret, "Failed to delete %s, error %u.\n", inf_path2, GetLastError());
/* Windows "precompiles" INF files in this dir; try to avoid leaving them behind. */
DeleteFileA("C:/windows/inf/wine_test1.pnf");
DeleteFileA("C:/windows/inf/wine_test2.pnf");
}
static BOOL device_is_registered(HDEVINFO set, SP_DEVINFO_DATA *device)
{
HKEY key = SetupDiOpenDevRegKey(set, device, DICS_FLAG_GLOBAL, 0, DIREG_DRV, 0);
ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
RegCloseKey(key);
return GetLastError() == ERROR_KEY_DOES_NOT_EXIST;
}
static void test_call_class_installer(void)
{
SP_DEVINFO_DATA device = {sizeof(device)};
HDEVINFO set;
BOOL ret;
if (wow64)
{
skip("SetupDiCallClassInstaller() does not work on WoW64.\n");
return;
}
set = SetupDiCreateDeviceInfoList(&guid, NULL);
ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device);
ok(ret, "Failed to create device, error %#x.\n", GetLastError());
ok(!device_is_registered(set, &device), "Expected device not to be registered.\n");
ret = SetupDiCallClassInstaller(DIF_REGISTERDEVICE, set, &device);
ok(ret, "Failed to call class installer, error %#x.\n", GetLastError());
ok(device_is_registered(set, &device), "Expected device to be registered.\n");
/* This is probably not failure per se, but rather an indication that no
* class installer was called and no default handler exists. */
ret = SetupDiCallClassInstaller(DIF_ALLOW_INSTALL, set, &device);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_DI_DO_DEFAULT, "Got unexpected error %#x.\n", GetLastError());
ret = SetupDiCallClassInstaller(0xdeadbeef, set, &device);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_DI_DO_DEFAULT, "Got unexpected error %#x.\n", GetLastError());
ret = SetupDiCallClassInstaller(DIF_REMOVE, set, &device);
ok(ret, "Failed to call class installer, error %#x.\n", GetLastError());
ok(!device_is_registered(set, &device), "Expected device not to be registered.\n");
SetupDiDestroyDeviceInfoList(set);
}
START_TEST(devinst)
{
static BOOL (WINAPI *pIsWow64Process)(HANDLE, BOOL *);
HKEY hkey;
test_get_actual_section();
if ((hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS)) == INVALID_HANDLE_VALUE)
{
skip("needs admin rights\n");
@ -1896,6 +2401,9 @@ START_TEST(devinst)
}
RegCloseKey(hkey);
pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
if (pIsWow64Process) pIsWow64Process(GetCurrentProcess(), &wow64);
test_create_device_list_ex();
test_open_class_key();
test_install_class();
@ -1913,4 +2421,7 @@ START_TEST(devinst)
test_get_inf_class();
test_devnode();
test_device_interface_key();
test_device_install_params();
test_driver_list();
test_call_class_installer();
}

View file

@ -1317,6 +1317,96 @@ static void run_queue_(unsigned int line, HSPFILEQ queue, PSP_FILE_CALLBACK_A cb
ok_(__FILE__,line)(ret, "Failed to close queue, error %#x.\n", GetLastError());
}
static void test_install_file(void)
{
static const char inf_data[] = "[Version]\n"
"Signature=\"$Chicago$\"\n"
"[section1]\n"
"one.txt\n"
"two.txt\n"
"three.txt\n"
"[SourceDisksNames]\n"
"1=heis\n"
"2=duo,,,alpha\n"
"[SourceDisksFiles]\n"
"one.txt=1\n"
"two.txt=1,beta\n"
"three.txt=2\n"
"[DestinationDirs]\n"
"DefaultDestDir=40000,dst\n";
char path[MAX_PATH];
INFCONTEXT infctx;
HINF hinf;
BOOL ret;
create_inf_file(inffile, inf_data);
sprintf(path, "%s\\%s", CURR_DIR, inffile);
hinf = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
ok(hinf != INVALID_HANDLE_VALUE, "Failed to open INF file, error %#x.\n", GetLastError());
ret = CreateDirectoryA("src", NULL);
ok(ret, "Failed to create test directory, error %u.\n", GetLastError());
ret = CreateDirectoryA("src/alpha", NULL);
ok(ret, "Failed to create test directory, error %u.\n", GetLastError());
ret = CreateDirectoryA("src/beta", NULL);
ok(ret, "Failed to create test directory, error %u.\n", GetLastError());
ret = CreateDirectoryA("dst", NULL);
ok(ret, "Failed to create test directory, error %u.\n", GetLastError());
create_file("src/one.txt");
create_file("src/beta/two.txt");
create_file("src/alpha/three.txt");
ret = SetupFindFirstLineA(hinf, "section1", "one.txt", &infctx);
ok(ret, "Failed to find line.\n");
SetLastError(0xdeadbeef);
ret = SetupInstallFileA(hinf, &infctx, "one.txt", "src", "one.txt", 0, NULL, NULL);
ok(ret, "Expected success.\n");
ok(GetLastError() == ERROR_SUCCESS, "Got unexpected error %#x.\n", GetLastError());
ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
SetLastError(0xdeadbeef);
ret = SetupInstallFileA(hinf, &infctx, "one.txt", "src", "one.txt", SP_COPY_REPLACEONLY, NULL, NULL);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_SUCCESS, "Got unexpected error %#x.\n", GetLastError());
ok(!file_exists("dst/one.txt"), "Destination file should not exist.\n");
ret = SetupFindFirstLineA(hinf, "section1", "two.txt", &infctx);
ok(ret, "Failed to find line.\n");
SetLastError(0xdeadbeef);
ret = SetupInstallFileA(hinf, &infctx, "two.txt", "src", "two.txt", 0, NULL, NULL);
todo_wine ok(ret, "Expected success.\n");
todo_wine ok(GetLastError() == ERROR_SUCCESS, "Got unexpected error %#x.\n", GetLastError());
todo_wine ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
ret = SetupFindFirstLineA(hinf, "section1", "three.txt", &infctx);
ok(ret, "Failed to find line.\n");
SetLastError(0xdeadbeef);
ret = SetupInstallFileA(hinf, &infctx, "three.txt", "src", "three.txt", 0, NULL, NULL);
ok(!ret, "Expected failure.\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got unexpected error %#x.\n", GetLastError());
ok(!file_exists("dst/three.txt"), "Destination file should not exist.\n");
ret = SetupFindFirstLineA(hinf, "section1", "three.txt", &infctx);
ok(ret, "Failed to find line.\n");
SetLastError(0xdeadbeef);
ret = SetupInstallFileA(hinf, &infctx, "three.txt", "src/alpha", "three.txt", 0, NULL, NULL);
ok(ret, "Expected success.\n");
ok(GetLastError() == ERROR_SUCCESS, "Got unexpected error %#x.\n", GetLastError());
ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
SetupCloseInfFile(hinf);
delete_file("src/one.txt");
delete_file("src/beta/two.txt");
delete_file("src/beta/");
delete_file("src/alpha/three.txt");
delete_file("src/alpha/");
delete_file("src/");
delete_file("dst/");
ok(delete_file(inffile), "Failed to delete INF file.\n");
}
static void test_need_media(void)
{
static const char inf_data[] = "[Version]\n"
@ -1378,6 +1468,16 @@ static void test_need_media(void)
ok(got_need_media == 1, "Got %u callbacks.\n", got_need_media);
ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
got_need_media = 0;
queue = SetupOpenFileQueue();
ok(queue != INVALID_HANDLE_VALUE, "Failed to open queue, error %#x.\n", GetLastError());
ret = SetupQueueCopyA(queue, "src", NULL, "one.txt", "File One", NULL,
"dst", NULL, SP_COPY_WARNIFSKIP | SP_COPY_REPLACEONLY);
ok(ret, "Failed to queue copy, error %#x.\n", GetLastError());
run_queue(queue, need_media_cb);
ok(got_need_media == 1, "Got %u callbacks.\n", got_need_media);
ok(!file_exists("dst/one.txt"), "Destination file should exist.\n");
/* Test with a subdirectory. */
got_need_media = 0;
@ -1857,6 +1957,7 @@ START_TEST(install)
test_install_files_queue();
test_need_media();
test_close_queue();
test_install_file();
UnhookWindowsHookEx(hhook);

View file

@ -10,4 +10,4 @@ files:
dlls/setupapi/setupcab.c: dll/win32/setupapi/setupcab.c
dlls/setupapi/stringtable.c: dll/win32/setupapi/stringtable_wine.c
tags:
wine: wine-4.8
wine: 43ee138d4747722cfc7d27e59014a47c3003a898