Hans Leidekker : msi: Only remove environment strings that were added on install.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue Aug 18 09:22:16 CDT 2015
Module: wine
Branch: master
Commit: 99dfc15e72cc456e565b3139b32e6f9b908f6609
URL: http://source.winehq.org/git/wine.git/?a=commit;h=99dfc15e72cc456e565b3139b32e6f9b908f6609
Author: Hans Leidekker <hans at 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");
More information about the wine-cvs
mailing list