Module: wine Branch: master Commit: 99dfc15e72cc456e565b3139b32e6f9b908f6609 URL: http://source.winehq.org/git/wine.git/?a=commit;h=99dfc15e72cc456e565b3139b3...
Author: Hans Leidekker hans@codeweavers.com Date: Tue Aug 18 10:21:29 2015 +0200
msi: Only remove environment strings that were added on install.
---
dlls/msi/action.c | 63 ++++++++++++++++++++++++++++++++++++++----- dlls/msi/tests/action.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 126 insertions(+), 8 deletions(-)
diff --git a/dlls/msi/action.c b/dlls/msi/action.c index c0ab23d..0fe7d38 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -7103,8 +7103,8 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param ) { MSIPACKAGE *package = param; LPCWSTR name, value, component; - LPWSTR deformatted = NULL; - DWORD flags; + WCHAR *p, *q, *deformatted = NULL, *new_value = NULL; + DWORD flags, type, size, len, len_value = 0, len_new_value; HKEY env; MSICOMPONENT *comp; MSIRECORD *uirow; @@ -7141,7 +7141,20 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param ) if (value && !deformat_string( package, value, &deformatted )) return ERROR_OUTOFMEMORY;
- value = deformatted; + if ((value = deformatted)) + { + if (flags & ENV_MOD_PREFIX) + { + p = strchrW( value, ';' ); + len_value = p - value; + } + else if (flags & ENV_MOD_APPEND) + { + value = strchrW( value, ';' ) + 1; + len_value = strlenW( value ); + } + else len_value = strlenW( value ); + }
r = open_env_key( flags, &env ); if (r != ERROR_SUCCESS) @@ -7153,13 +7166,48 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param ) if (flags & ENV_MOD_MACHINE) action |= 0x20000000;
- TRACE("Removing %s\n", debugstr_w(name)); + size = 0; + type = REG_SZ; + res = RegQueryValueExW( env, name, NULL, &type, NULL, &size ); + if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ)) + goto done; + + if (!(new_value = msi_alloc( size ))) goto done;
- res = RegDeleteValueW( env, name ); + res = RegQueryValueExW( env, name, NULL, &type, (BYTE *)new_value, &size ); if (res != ERROR_SUCCESS) + goto done; + + len_new_value = size / sizeof(WCHAR) - 1; + p = q = new_value; + for (;;) { - WARN("Failed to delete value %s (%d)\n", debugstr_w(name), res); - r = ERROR_SUCCESS; + while (*q && *q != ';') q++; + len = q - p; + if (value && len == len_value && !memcmp( value, p, len * sizeof(WCHAR) )) + { + if (*q == ';') q++; + memmove( p, q, (len_new_value - (q - new_value) + 1) * sizeof(WCHAR) ); + break; + } + if (!*q) break; + p = ++q; + } + + if (!new_value[0] || !value) + { + TRACE("removing %s\n", debugstr_w(name)); + res = RegDeleteValueW( env, name ); + if (res != ERROR_SUCCESS) + WARN("failed to delete value %s (%d)\n", debugstr_w(name), res); + } + else + { + TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(new_value)); + size = (strlenW( new_value ) + 1) * sizeof(WCHAR); + res = RegSetValueExW( env, name, 0, type, (BYTE *)new_value, size ); + if (res != ERROR_SUCCESS) + WARN("failed to set %s to %s (%d)\n", debugstr_w(name), debugstr_w(new_value), res); }
done: @@ -7172,6 +7220,7 @@ done:
if (env) RegCloseKey( env ); msi_free( deformatted ); + msi_free( new_value ); return r; }
diff --git a/dlls/msi/tests/action.c b/dlls/msi/tests/action.c index 60562f1..9512410 100644 --- a/dlls/msi/tests/action.c +++ b/dlls/msi/tests/action.c @@ -1205,7 +1205,13 @@ static const char res_environment_dat[] = "var2\t=+-MSITESTVAR2\t1\tenvvar\n" "var3\t=MSITESTVAR3\t1\tenvvar\n" "var4\t=-MSITESTVAR4\t\tenvvar\n" - "var5\t=MSITESTVAR5\t\tenvvar\n"; + "var5\t=MSITESTVAR5\t\tenvvar\n" + "Var6\t-MSITESTVAR6\t1;[~]\tenvvar\n" + "Var7\t-MSITESTVAR7\t[~];1\tenvvar\n" + "Var8\t-MSITESTVAR8\t1;[~]\tenvvar\n" + "Var9\t-MSITESTVAR9\t[~];1\tenvvar\n" + "Var10\t-MSITESTVAR10\t1\tenvvar\n" + "Var11\t-MSITESTVAR11\t2\tenvvar\n";
static const char res_install_exec_seq_dat[] = "Action\tCondition\tSequence\n" @@ -6192,6 +6198,12 @@ static void test_remove_env_strings(void) RegSetValueExA(key, "MSITESTVAR3", 0, REG_SZ, (const BYTE *)"1", 2); RegSetValueExA(key, "MSITESTVAR4", 0, REG_SZ, (const BYTE *)"1", 2); RegSetValueExA(key, "MSITESTVAR5", 0, REG_SZ, (const BYTE *)"1", 2); + RegSetValueExA(key, "MSITESTVAR6", 0, REG_SZ, (const BYTE *)"1;2", 4); + RegSetValueExA(key, "MSITESTVAR7", 0, REG_SZ, (const BYTE *)"1;2", 4); + RegSetValueExA(key, "MSITESTVAR8", 0, REG_SZ, (const BYTE *)"2;1;0", 6); + RegSetValueExA(key, "MSITESTVAR9", 0, REG_SZ, (const BYTE *)"0;1;2", 6); + RegSetValueExA(key, "MSITESTVAR10", 0, REG_SZ, (const BYTE *)"1", 2); + RegSetValueExA(key, "MSITESTVAR11", 0, REG_SZ, (const BYTE *)"1", 2);
RegCloseKey(key);
@@ -6281,6 +6293,57 @@ static void test_remove_env_strings(void) ok(!lstrcmpA(buffer, "1"), "expected "1", got "%s"\n", buffer); RegDeleteValueA(key, "MSITESTVAR5");
+ type = REG_NONE; + buffer[0] = 0; + size = sizeof(buffer); + res = RegQueryValueExA(key, "MSITESTVAR6", NULL, &type, (LPBYTE)buffer, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + ok(type == REG_SZ, "expected REG_SZ, got %u\n", type); + ok(!lstrcmpA(buffer, "2"), "expected "2", got "%s"\n", buffer); + RegDeleteValueA(key, "MSITESTVAR6"); + + type = REG_NONE; + buffer[0] = 0; + size = sizeof(buffer); + res = RegQueryValueExA(key, "MSITESTVAR7", NULL, &type, (LPBYTE)buffer, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + ok(type == REG_SZ, "expected REG_SZ, got %u\n", type); + ok(!lstrcmpA(buffer, "2"), "expected "2", got "%s"\n", buffer); + RegDeleteValueA(key, "MSITESTVAR7"); + + type = REG_NONE; + buffer[0] = 0; + size = sizeof(buffer); + res = RegQueryValueExA(key, "MSITESTVAR8", NULL, &type, (LPBYTE)buffer, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + ok(type == REG_SZ, "expected REG_SZ, got %u\n", type); + ok(!lstrcmpA(buffer, "2;0"), "expected "2;0", got "%s"\n", buffer); + RegDeleteValueA(key, "MSITESTVAR8"); + + type = REG_NONE; + buffer[0] = 0; + size = sizeof(buffer); + res = RegQueryValueExA(key, "MSITESTVAR9", NULL, &type, (LPBYTE)buffer, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + ok(type == REG_SZ, "expected REG_SZ, got %u\n", type); + ok(!lstrcmpA(buffer, "0;2"), "expected "0;2", got "%s"\n", buffer); + RegDeleteValueA(key, "MSITESTVAR9"); + + type = REG_NONE; + buffer[0] = 0; + size = sizeof(buffer); + res = RegQueryValueExA(key, "MSITESTVAR10", NULL, &type, (LPBYTE)buffer, &size); + ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); + + type = REG_NONE; + buffer[0] = 0; + size = sizeof(buffer); + res = RegQueryValueExA(key, "MSITESTVAR11", NULL, &type, (LPBYTE)buffer, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + ok(type == REG_SZ, "expected REG_SZ, got %u\n", type); + ok(!lstrcmpA(buffer, "1"), "expected "1", got "%s"\n", buffer); + RegDeleteValueA(key, "MSITESTVAR11"); + ok(!delete_pf("msitest\envvar.txt", TRUE), "file not removed\n"); ok(!delete_pf("msitest", FALSE), "directory not removed\n");
@@ -6290,6 +6353,12 @@ error: RegDeleteValueA(key, "MSITESTVAR3"); RegDeleteValueA(key, "MSITESTVAR4"); RegDeleteValueA(key, "MSITESTVAR5"); + RegDeleteValueA(key, "MSITESTVAR6"); + RegDeleteValueA(key, "MSITESTVAR7"); + RegDeleteValueA(key, "MSITESTVAR8"); + RegDeleteValueA(key, "MSITESTVAR9"); + RegDeleteValueA(key, "MSITESTVAR10"); + RegDeleteValueA(key, "MSITESTVAR11"); RegCloseKey(key);
DeleteFileA("msitest\envvar.txt");