msi: Don't add the same environment string more than once.

This commit is contained in:
Hans Leidekker 2015-08-26 08:45:31 +02:00 committed by Alexandre Julliard
parent 58bf3ca17f
commit ddaba7a369
2 changed files with 53 additions and 28 deletions

View File

@ -6922,13 +6922,13 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
{ {
MSIPACKAGE *package = param; MSIPACKAGE *package = param;
LPCWSTR name, value, component; LPCWSTR name, value, component;
LPWSTR data = NULL, newval = NULL, deformatted = NULL, ptr; WCHAR *data = NULL, *newval = NULL, *deformatted = NULL, *p, *q;
DWORD flags, type, size; DWORD flags, type, size, len, len_value = 0;
UINT res; UINT res;
HKEY env = NULL; HKEY env = NULL;
MSICOMPONENT *comp; MSICOMPONENT *comp;
MSIRECORD *uirow; MSIRECORD *uirow;
int action = 0; int action = 0, found = 0;
component = MSI_RecordGetString(rec, 4); component = MSI_RecordGetString(rec, 4);
comp = msi_get_loaded_component(package, component); comp = msi_get_loaded_component(package, component);
@ -6956,7 +6956,20 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
goto done; goto done;
} }
value = deformatted; if ((value = deformatted))
{
if (flags & ENV_MOD_PREFIX)
{
p = strrchrW( value, ';' );
len_value = p - value;
}
else if (flags & ENV_MOD_APPEND)
{
value = strchrW( value, ';' ) + 1;
len_value = strlenW( value );
}
else len_value = strlenW( value );
}
res = open_env_key( flags, &env ); res = open_env_key( flags, &env );
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
@ -6982,10 +6995,6 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
res = ERROR_SUCCESS; res = ERROR_SUCCESS;
goto done; goto done;
} }
/* If we are appending but the string was empty, strip ; */
if ((flags & ENV_MOD_APPEND) && (value[0] == szSemiColon[0])) value++;
size = (lstrlenW(value) + 1) * sizeof(WCHAR); size = (lstrlenW(value) + 1) * sizeof(WCHAR);
newval = strdupW(value); newval = strdupW(value);
if (!newval) if (!newval)
@ -7005,15 +7014,14 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
goto done; goto done;
} }
data = msi_alloc(size); if (!(p = q = data = msi_alloc( size )))
if (!data)
{ {
msi_free(deformatted); msi_free(deformatted);
RegCloseKey(env); RegCloseKey(env);
return ERROR_OUTOFMEMORY; return ERROR_OUTOFMEMORY;
} }
res = RegQueryValueExW(env, name, NULL, &type, (LPVOID)data, &size); res = RegQueryValueExW( env, name, NULL, &type, (BYTE *)data, &size );
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
goto done; goto done;
@ -7026,20 +7034,28 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
goto done; goto done;
} }
size = (lstrlenW(data) + 1) * sizeof(WCHAR); for (;;)
if (flags & ENV_MOD_MASK)
{ {
DWORD mod_size; while (*q && *q != ';') q++;
int multiplier = 0; len = q - p;
if (flags & ENV_MOD_APPEND) multiplier++; if (value && len == len_value && !memcmp( value, p, len * sizeof(WCHAR) ) &&
if (flags & ENV_MOD_PREFIX) multiplier++; (!p[len] || p[len] == ';'))
mod_size = lstrlenW(value) * multiplier; {
size += mod_size * sizeof(WCHAR); found = 1;
break;
}
if (!*q) break;
p = ++q;
} }
newval = msi_alloc(size); if (found)
ptr = newval; {
if (!newval) TRACE("string already set\n");
goto done;
}
size = (len_value + 1 + strlenW( data ) + 1) * sizeof(WCHAR);
if (!(p = newval = msi_alloc( size )))
{ {
res = ERROR_OUTOFMEMORY; res = ERROR_OUTOFMEMORY;
goto done; goto done;
@ -7047,21 +7063,24 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
if (flags & ENV_MOD_PREFIX) if (flags & ENV_MOD_PREFIX)
{ {
lstrcpyW(newval, value); memcpy( newval, value, len_value * sizeof(WCHAR) );
ptr = newval + lstrlenW(value); newval[len_value] = ';';
p = newval + len_value + 1;
action |= 0x80000000; action |= 0x80000000;
} }
lstrcpyW(ptr, data); strcpyW( p, data );
if (flags & ENV_MOD_APPEND) if (flags & ENV_MOD_APPEND)
{ {
lstrcatW(newval, value); p += strlenW( data );
*p++ = ';';
memcpy( p, value, (len_value + 1) * sizeof(WCHAR) );
action |= 0x40000000; action |= 0x40000000;
} }
} }
TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval)); TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size); res = RegSetValueExW( env, name, 0, type, (BYTE *)newval, size );
if (res) if (res)
{ {
WARN("Failed to set %s to %s (%d)\n", debugstr_w(name), debugstr_w(newval), res); WARN("Failed to set %s to %s (%d)\n", debugstr_w(name), debugstr_w(newval), res);

View File

@ -218,7 +218,8 @@ static const char environment_dat[] =
"Var23\t+-MSITESTVAR19\t1\tOne\n" "Var23\t+-MSITESTVAR19\t1\tOne\n"
"Var24\t+-MSITESTVAR19\t[~]2\tOne\n" "Var24\t+-MSITESTVAR19\t[~]2\tOne\n"
"Var25\t+-MSITESTVAR20\t1\tOne\n" "Var25\t+-MSITESTVAR20\t1\tOne\n"
"Var26\t+-MSITESTVAR20\t2[~]\tOne\n"; "Var26\t+-MSITESTVAR20\t2[~]\tOne\n"
"Var27\t+-MSITESTVAR21\t[~];1\tOne\n";
static const char service_install_dat[] = static const char service_install_dat[] =
"ServiceInstall\tName\tDisplayName\tServiceType\tStartType\tErrorControl\t" "ServiceInstall\tName\tDisplayName\tServiceType\tStartType\tErrorControl\t"
@ -5145,6 +5146,7 @@ static void test_envvar(void)
"1;;2;;", /* MSITESTVAR18 */ "1;;2;;", /* MSITESTVAR18 */
"1", /* MSITESTVAR19 */ "1", /* MSITESTVAR19 */
"1", /* MSITESTVAR20 */ "1", /* MSITESTVAR20 */
"1", /* MSITESTVAR21 */
NULL NULL
}; };
UINT r; UINT r;
@ -5172,6 +5174,9 @@ static void test_envvar(void)
res = RegSetValueExA(env, "MSITESTVAR2", 0, REG_SZ, (const BYTE *)"0", 2); res = RegSetValueExA(env, "MSITESTVAR2", 0, REG_SZ, (const BYTE *)"0", 2);
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
res = RegSetValueExA(env, "MSITESTVAR21", 0, REG_SZ, (const BYTE *)"1", 2);
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
r = MsiInstallProductA(msifile, NULL); r = MsiInstallProductA(msifile, NULL);
@ -5264,6 +5269,7 @@ static void test_envvar(void)
error: error:
RegDeleteValueA(env, "MSITESTVAR1"); RegDeleteValueA(env, "MSITESTVAR1");
RegDeleteValueA(env, "MSITESTVAR2"); RegDeleteValueA(env, "MSITESTVAR2");
RegDeleteValueA(env, "MSITESTVAR21");
RegCloseKey(env); RegCloseKey(env);
delete_test_files(); delete_test_files();