msi: Don't add the same environment string more than once.
This commit is contained in:
parent
58bf3ca17f
commit
ddaba7a369
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue