Commit f6221119 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Implement the RemoveEnvironmentStrings standard action.

parent 7b685854
...@@ -5810,7 +5810,7 @@ static UINT ACTION_RemoveODBC( MSIPACKAGE *package ) ...@@ -5810,7 +5810,7 @@ static UINT ACTION_RemoveODBC( MSIPACKAGE *package )
#define check_flag_combo(x, y) ((x) & ~(y)) == (y) #define check_flag_combo(x, y) ((x) & ~(y)) == (y)
static LONG env_set_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags ) static UINT env_parse_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags )
{ {
LPCWSTR cptr = *name; LPCWSTR cptr = *name;
...@@ -5891,18 +5891,8 @@ static LONG env_set_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags ) ...@@ -5891,18 +5891,8 @@ static LONG env_set_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) static UINT open_env_key( DWORD flags, HKEY *key )
{ {
MSIPACKAGE *package = param;
LPCWSTR name, value, component;
LPWSTR data = NULL, newval = NULL;
LPWSTR deformatted = NULL, ptr;
DWORD flags, type, size;
LONG res;
HKEY env = NULL, root;
LPCWSTR environment;
MSICOMPONENT *comp;
static const WCHAR user_env[] = static const WCHAR user_env[] =
{'E','n','v','i','r','o','n','m','e','n','t',0}; {'E','n','v','i','r','o','n','m','e','n','t',0};
static const WCHAR machine_env[] = static const WCHAR machine_env[] =
...@@ -5911,6 +5901,42 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -5911,6 +5901,42 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
'C','o','n','t','r','o','l','\\', 'C','o','n','t','r','o','l','\\',
'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r','\\', 'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r','\\',
'E','n','v','i','r','o','n','m','e','n','t',0}; 'E','n','v','i','r','o','n','m','e','n','t',0};
const WCHAR *env;
HKEY root;
LONG res;
if (flags & ENV_MOD_MACHINE)
{
env = machine_env;
root = HKEY_LOCAL_MACHINE;
}
else
{
env = user_env;
root = HKEY_CURRENT_USER;
}
res = RegOpenKeyExW( root, env, 0, KEY_ALL_ACCESS, key );
if (res != ERROR_SUCCESS)
{
WARN("Failed to open key %s (%d)\n", debugstr_w(env), res);
return ERROR_FUNCTION_FAILED;
}
return ERROR_SUCCESS;
}
static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
{
MSIPACKAGE *package = param;
LPCWSTR name, value, component;
LPWSTR data = NULL, newval = NULL, deformatted = NULL, ptr;
DWORD flags, type, size;
UINT res;
HKEY env;
MSICOMPONENT *comp;
MSIRECORD *uirow;
int action = 0;
component = MSI_RecordGetString(rec, 4); component = MSI_RecordGetString(rec, 4);
comp = get_loaded_component(package, component); comp = get_loaded_component(package, component);
...@@ -5930,7 +5956,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -5930,7 +5956,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_parse_flags(&name, &value, &flags);
if (res != ERROR_SUCCESS || !value) if (res != ERROR_SUCCESS || !value)
goto done; goto done;
...@@ -5942,24 +5968,12 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -5942,24 +5968,12 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
value = deformatted; value = deformatted;
if (flags & ENV_MOD_MACHINE) res = open_env_key( flags, &env );
{
environment = machine_env;
root = HKEY_LOCAL_MACHINE;
}
else
{
environment = user_env;
root = HKEY_CURRENT_USER;
}
res = RegCreateKeyExW(root, environment, 0, NULL, 0,
KEY_ALL_ACCESS, NULL, &env, NULL);
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
goto done; goto done;
if (flags & ENV_ACT_REMOVE) if (flags & ENV_MOD_MACHINE)
FIXME("Not removing environment variable on uninstall!\n"); action |= 0x20000000;
size = 0; size = 0;
type = REG_SZ; type = REG_SZ;
...@@ -5970,6 +5984,8 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -5970,6 +5984,8 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
if ((res == ERROR_FILE_NOT_FOUND || !(flags & ENV_MOD_MASK))) if ((res == ERROR_FILE_NOT_FOUND || !(flags & ENV_MOD_MASK)))
{ {
action = 0x2;
/* Nothing to do. */ /* Nothing to do. */
if (!value) if (!value)
{ {
...@@ -5990,6 +6006,8 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -5990,6 +6006,8 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
} }
else else
{ {
action = 0x1;
/* Contrary to MSDN, +-variable to [~];path works */ /* Contrary to MSDN, +-variable to [~];path works */
if (flags & ENV_ACT_SETABSENT && !(flags & ENV_MOD_MASK)) if (flags & ENV_ACT_SETABSENT && !(flags & ENV_MOD_MASK))
{ {
...@@ -6010,7 +6028,10 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -6010,7 +6028,10 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
if (flags & ENV_ACT_REMOVEMATCH && (!value || !lstrcmpW(data, value))) if (flags & ENV_ACT_REMOVEMATCH && (!value || !lstrcmpW(data, value)))
{ {
res = RegDeleteKeyW(env, name); action = 0x4;
res = RegDeleteValueW(env, name);
if (res != ERROR_SUCCESS)
WARN("Failed to remove value %s (%d)\n", debugstr_w(name), res);
goto done; goto done;
} }
...@@ -6037,6 +6058,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -6037,6 +6058,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
{ {
lstrcpyW(newval, value); lstrcpyW(newval, value);
ptr = newval + lstrlenW(value); ptr = newval + lstrlenW(value);
action |= 0x80000000;
} }
lstrcpyW(ptr, data); lstrcpyW(ptr, data);
...@@ -6044,12 +6066,24 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) ...@@ -6044,12 +6066,24 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
if (flags & ENV_MOD_APPEND) if (flags & ENV_MOD_APPEND)
{ {
lstrcatW(newval, value); lstrcatW(newval, value);
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, (LPVOID)newval, size);
if (res)
{
WARN("Failed to set %s to %s (%d)\n", debugstr_w(name), debugstr_w(newval), res);
}
done: done:
uirow = MSI_CreateRecord( 3 );
MSI_RecordSetStringW( uirow, 1, name );
MSI_RecordSetStringW( uirow, 2, newval );
MSI_RecordSetInteger( uirow, 3, action );
ui_actiondata( package, szWriteEnvironmentStrings, uirow );
msiobj_release( &uirow->hdr );
if (env) RegCloseKey(env); if (env) RegCloseKey(env);
msi_free(deformatted); msi_free(deformatted);
msi_free(data); msi_free(data);
...@@ -6074,6 +6108,102 @@ static UINT ACTION_WriteEnvironmentStrings( MSIPACKAGE *package ) ...@@ -6074,6 +6108,102 @@ static UINT ACTION_WriteEnvironmentStrings( MSIPACKAGE *package )
return rc; return rc;
} }
static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param )
{
MSIPACKAGE *package = param;
LPCWSTR name, value, component;
LPWSTR deformatted = NULL;
DWORD flags;
HKEY env;
MSICOMPONENT *comp;
MSIRECORD *uirow;
int action = 0;
LONG res;
UINT r;
component = MSI_RecordGetString( rec, 4 );
comp = get_loaded_component( package, component );
if (!comp)
return ERROR_SUCCESS;
if (comp->ActionRequest != INSTALLSTATE_ABSENT)
{
TRACE("Component not scheduled for removal: %s\n", debugstr_w(component));
comp->Action = comp->Installed;
return ERROR_SUCCESS;
}
comp->Action = INSTALLSTATE_ABSENT;
name = MSI_RecordGetString( rec, 2 );
value = MSI_RecordGetString( rec, 3 );
TRACE("name %s value %s\n", debugstr_w(name), debugstr_w(value));
r = env_parse_flags( &name, &value, &flags );
if (r != ERROR_SUCCESS)
return r;
if (!(flags & ENV_ACT_REMOVE))
{
TRACE("Environment variable %s not marked for removal\n", debugstr_w(name));
return ERROR_SUCCESS;
}
if (value && !deformat_string( package, value, &deformatted ))
return ERROR_OUTOFMEMORY;
value = deformatted;
r = open_env_key( flags, &env );
if (r != ERROR_SUCCESS)
{
r = ERROR_SUCCESS;
goto done;
}
if (flags & ENV_MOD_MACHINE)
action |= 0x20000000;
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);
r = ERROR_SUCCESS;
}
done:
uirow = MSI_CreateRecord( 3 );
MSI_RecordSetStringW( uirow, 1, name );
MSI_RecordSetStringW( uirow, 2, value );
MSI_RecordSetInteger( uirow, 3, action );
ui_actiondata( package, szRemoveEnvironmentStrings, uirow );
msiobj_release( &uirow->hdr );
if (env) RegCloseKey( env );
msi_free( deformatted );
return r;
}
static UINT ACTION_RemoveEnvironmentStrings( MSIPACKAGE *package )
{
UINT rc;
MSIQUERY *view;
static const WCHAR query[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','E','n','v','i','r','o','n','m','e','n','t','`',0};
rc = MSI_DatabaseOpenViewW( package->db, query, &view );
if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS;
rc = MSI_IterateRecords( view, NULL, ITERATE_RemoveEnvironmentString, package );
msiobj_release( &view->hdr );
return rc;
}
#define is_dot_dir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0)))) #define is_dot_dir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
typedef struct typedef struct
...@@ -6972,13 +7102,6 @@ static UINT ACTION_MigrateFeatureStates( MSIPACKAGE *package ) ...@@ -6972,13 +7102,6 @@ static UINT ACTION_MigrateFeatureStates( MSIPACKAGE *package )
return msi_unimplemented_action_stub( package, "MigrateFeatureStates", table ); return msi_unimplemented_action_stub( package, "MigrateFeatureStates", table );
} }
static UINT ACTION_RemoveEnvironmentStrings( MSIPACKAGE *package )
{
static const WCHAR table[] = {
'E','n','v','i','r','o','n','m','e','n','t',0 };
return msi_unimplemented_action_stub( package, "RemoveEnvironmentStrings", table );
}
static UINT ACTION_MsiUnpublishAssemblies( MSIPACKAGE *package ) static UINT ACTION_MsiUnpublishAssemblies( MSIPACKAGE *package )
{ {
static const WCHAR table[] = { static const WCHAR table[] = {
......
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