Commit 06c45a8d authored by Jason Edmeades's avatar Jason Edmeades Committed by Alexandre Julliard

msi: Correct the setting of environment variables.

Contrary to the MSDN, you can 'create only' whilst using a previous value (ie +-variable and [~];value). This breaks the install of an application I was debugging who uses that throughout for all their variables. In addition whilst adding some tests I've also cleaned up invalid prefix syntax handling and semicolon removal if the original string is empty.
parent bfe9e6d7
...@@ -4924,16 +4924,30 @@ static LONG env_set_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags ) ...@@ -4924,16 +4924,30 @@ static LONG env_set_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags )
LPCWSTR ptr = *value; LPCWSTR ptr = *value;
if (!strncmpW(ptr, prefix, prefix_len)) if (!strncmpW(ptr, prefix, prefix_len))
{ {
*flags |= ENV_MOD_APPEND; if (ptr[prefix_len] == szSemiColon[0])
*value += lstrlenW(prefix); {
*flags |= ENV_MOD_APPEND;
*value += lstrlenW(prefix);
}
else
{
*value = NULL;
}
} }
else if (lstrlenW(*value) >= prefix_len) else if (lstrlenW(*value) >= prefix_len)
{ {
ptr += lstrlenW(ptr) - prefix_len; ptr += lstrlenW(ptr) - prefix_len;
if (!lstrcmpW(ptr, prefix)) if (!lstrcmpW(ptr, prefix))
{ {
*flags |= ENV_MOD_PREFIX; if ((ptr-1) > *value && *(ptr-1) == szSemiColon[0])
/* the "[~]" will be removed by deformat_string */; {
*flags |= ENV_MOD_PREFIX;
/* the "[~]" will be removed by deformat_string */;
}
else
{
*value = NULL;
}
} }
} }
} }
...@@ -4979,7 +4993,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -4979,7 +4993,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
TRACE("name %s value %s\n", debugstr_w(name), debugstr_w(value)); TRACE("name %s value %s\n", debugstr_w(name), debugstr_w(value));
res = env_set_flags(&name, &value, &flags); res = env_set_flags(&name, &value, &flags);
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS || !value)
goto done; goto done;
if (value && !deformat_string(package, value, &deformatted)) if (value && !deformat_string(package, value, &deformatted))
...@@ -5025,6 +5039,9 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -5025,6 +5039,9 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
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)
...@@ -5035,7 +5052,8 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -5035,7 +5052,8 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
} }
else else
{ {
if (flags & ENV_ACT_SETABSENT) /* Contrary to MSDN, +-variable to [~];path works */
if (flags & ENV_ACT_SETABSENT && !(flags & ENV_MOD_MASK))
{ {
res = ERROR_SUCCESS; res = ERROR_SUCCESS;
goto done; goto done;
...@@ -5065,7 +5083,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -5065,7 +5083,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
int multiplier = 0; int multiplier = 0;
if (flags & ENV_MOD_APPEND) multiplier++; if (flags & ENV_MOD_APPEND) multiplier++;
if (flags & ENV_MOD_PREFIX) multiplier++; if (flags & ENV_MOD_PREFIX) multiplier++;
mod_size = (lstrlenW(value) + 1) * multiplier; mod_size = lstrlenW(value) * multiplier;
size += mod_size * sizeof(WCHAR); size += mod_size * sizeof(WCHAR);
} }
...@@ -5080,15 +5098,13 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -5080,15 +5098,13 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
if (flags & ENV_MOD_PREFIX) if (flags & ENV_MOD_PREFIX)
{ {
lstrcpyW(newval, value); lstrcpyW(newval, value);
lstrcatW(newval, szSemiColon); ptr = newval + lstrlenW(value);
ptr = newval + lstrlenW(value) + 1;
} }
lstrcpyW(ptr, data); lstrcpyW(ptr, data);
if (flags & ENV_MOD_APPEND) if (flags & ENV_MOD_APPEND)
{ {
lstrcatW(newval, szSemiColon);
lstrcatW(newval, value); lstrcatW(newval, value);
} }
} }
......
...@@ -226,7 +226,36 @@ static const CHAR environment_dat[] = "Environment\tName\tValue\tComponent_\n" ...@@ -226,7 +226,36 @@ static const CHAR environment_dat[] = "Environment\tName\tValue\tComponent_\n"
"Var7\t!-MSITESTVAR7\t\tOne\n" "Var7\t!-MSITESTVAR7\t\tOne\n"
"Var8\t!-*MSITESTVAR8\t\tOne\n" "Var8\t!-*MSITESTVAR8\t\tOne\n"
"Var9\t=-MSITESTVAR9\t\tOne\n" "Var9\t=-MSITESTVAR9\t\tOne\n"
"Var10\t=MSITESTVAR10\t\tOne\n"; "Var10\t=MSITESTVAR10\t\tOne\n"
"Var11\t+-MSITESTVAR11\t[~];1\tOne\n"
"Var12\t+-MSITESTVAR11\t[~];2\tOne\n"
"Var13\t+-MSITESTVAR12\t[~];1\tOne\n"
"Var14\t=MSITESTVAR13\t[~];1\tOne\n"
"Var15\t=MSITESTVAR13\t[~];2\tOne\n"
"Var16\t=MSITESTVAR14\t;1;\tOne\n"
"Var17\t=MSITESTVAR15\t;;1;;\tOne\n"
"Var18\t=MSITESTVAR16\t 1 \tOne\n"
"Var19\t+-MSITESTVAR17\t1\tOne\n"
"Var20\t+-MSITESTVAR17\t;;2;;[~]\tOne\n"
"Var21\t+-MSITESTVAR18\t1\tOne\n"
"Var22\t+-MSITESTVAR18\t[~];;2;;\tOne\n"
"Var23\t+-MSITESTVAR19\t1\tOne\n"
"Var24\t+-MSITESTVAR19\t[~]2\tOne\n"
"Var25\t+-MSITESTVAR20\t1\tOne\n"
"Var26\t+-MSITESTVAR20\t2[~]\tOne\n";
/* Expected results, starting from MSITESTVAR11 onwards */
static const CHAR *environment_dat_results[] = {"1;2", /*MSITESTVAR11*/
"1", /*MSITESTVAR12*/
"1;2", /*MSITESTVAR13*/
";1;", /*MSITESTVAR14*/
";;1;;", /*MSITESTVAR15*/
" 1 ", /*MSITESTVAR16*/
";;2;;1", /*MSITESTVAR17*/
"1;;2;;", /*MSITESTVAR18*/
"1", /*MSITESTVAR19*/
"1", /*MSITESTVAR20*/
NULL};
static const CHAR condition_dat[] = "Feature_\tLevel\tCondition\n" static const CHAR condition_dat[] = "Feature_\tLevel\tCondition\n"
"s38\ti2\tS255\n" "s38\ti2\tS255\n"
...@@ -6732,6 +6761,7 @@ static void test_envvar(void) ...@@ -6732,6 +6761,7 @@ static void test_envvar(void)
LONG res; LONG res;
DWORD type, size; DWORD type, size;
char buffer[16]; char buffer[16];
UINT i;
if (on_win9x) if (on_win9x)
{ {
...@@ -6800,8 +6830,27 @@ static void test_envvar(void) ...@@ -6800,8 +6830,27 @@ static void test_envvar(void)
res = RegDeleteValueA(env, "MSITESTVAR10"); res = RegDeleteValueA(env, "MSITESTVAR10");
ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
RegCloseKey(env); i = 11;
while (environment_dat_results[(i-11)]) {
char name[20];
sprintf(name, "MSITESTVAR%d", i);
type = REG_NONE;
size = sizeof(buffer);
buffer[0] = 0;
res = RegQueryValueExA(env, name, NULL, &type, (LPBYTE)buffer, &size);
ok(res == ERROR_SUCCESS, "%d: Expected ERROR_SUCCESS, got %d\n", i, res);
ok(type == REG_SZ, "%d: Expected REG_SZ, got %u\n", i, type);
ok(!lstrcmp(buffer, environment_dat_results[(i-11)]), "%d: Expected %s, got %s\n",
i, environment_dat_results[(i-11)], buffer);
res = RegDeleteValueA(env, name);
ok(res == ERROR_SUCCESS, "%d: Expected ERROR_SUCCESS, got %d\n", i, res);
i++;
}
RegCloseKey(env);
delete_pf("msitest\\cabout\\new\\five.txt", TRUE); delete_pf("msitest\\cabout\\new\\five.txt", TRUE);
delete_pf("msitest\\cabout\\new", FALSE); delete_pf("msitest\\cabout\\new", FALSE);
delete_pf("msitest\\cabout\\four.txt", TRUE); delete_pf("msitest\\cabout\\four.txt", TRUE);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment