msi: Implement the RemoveRegistryValues standard action.

This commit is contained in:
Hans Leidekker 2010-02-25 15:17:11 +01:00 committed by Alexandre Julliard
parent ccdafdb9c3
commit 342f866044
2 changed files with 254 additions and 56 deletions

View file

@ -2218,21 +2218,51 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
return data;
}
static const WCHAR *get_root_key( MSIPACKAGE *package, INT root, HKEY *root_key )
{
const WCHAR *ret;
switch (root)
{
case -1:
if (msi_get_property_int( package, szAllUsers, 0 ))
{
*root_key = HKEY_LOCAL_MACHINE;
ret = szHLM;
}
else
{
*root_key = HKEY_CURRENT_USER;
ret = szHCU;
}
break;
case 0:
*root_key = HKEY_CLASSES_ROOT;
ret = szHCR;
break;
case 1:
*root_key = HKEY_CURRENT_USER;
ret = szHCU;
break;
case 2:
*root_key = HKEY_LOCAL_MACHINE;
ret = szHLM;
break;
case 3:
*root_key = HKEY_USERS;
ret = szHU;
break;
default:
ERR("Unknown root %i\n", root);
return NULL;
}
return ret;
}
static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
{
MSIPACKAGE *package = param;
static const WCHAR szHCR[] =
{'H','K','E','Y','_','C','L','A','S','S','E','S','_',
'R','O','O','T','\\',0};
static const WCHAR szHCU[] =
{'H','K','E','Y','_','C','U','R','R','E','N','T','_',
'U','S','E','R','\\',0};
static const WCHAR szHLM[] =
{'H','K','E','Y','_','L','O','C','A','L','_',
'M','A','C','H','I','N','E','\\',0};
static const WCHAR szHU[] =
{'H','K','E','Y','_','U','S','E','R','S','\\',0};
LPSTR value_data = NULL;
HKEY root_key, hkey;
DWORD type,size;
@ -2280,44 +2310,8 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
root = MSI_RecordGetInteger(row,2);
key = MSI_RecordGetString(row, 3);
/* get the root key */
switch (root)
{
case -1:
{
LPWSTR all_users = msi_dup_property( package, szAllUsers );
if (all_users && all_users[0] == '1')
{
root_key = HKEY_LOCAL_MACHINE;
szRoot = szHLM;
}
else
{
root_key = HKEY_CURRENT_USER;
szRoot = szHCU;
}
msi_free(all_users);
}
break;
case 0: root_key = HKEY_CLASSES_ROOT;
szRoot = szHCR;
break;
case 1: root_key = HKEY_CURRENT_USER;
szRoot = szHCU;
break;
case 2: root_key = HKEY_LOCAL_MACHINE;
szRoot = szHLM;
break;
case 3: root_key = HKEY_USERS;
szRoot = szHU;
break;
default:
ERR("Unknown root %i\n",root);
root_key=NULL;
szRoot = NULL;
break;
}
if (!root_key)
szRoot = get_root_key( package, root, &root_key );
if (!szRoot)
return ERROR_SUCCESS;
deformat_string(package, key , &deformated);
@ -2412,6 +2406,212 @@ static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package)
return rc;
}
static void delete_reg_key_or_value( HKEY hkey_root, LPCWSTR key, LPCWSTR value, BOOL delete_key )
{
LONG res;
HKEY hkey;
DWORD num_subkeys, num_values;
if (delete_key)
{
if ((res = RegDeleteTreeW( hkey_root, key )))
{
WARN("Failed to delete key %s (%d)\n", debugstr_w(key), res);
}
return;
}
if (!(res = RegOpenKeyW( hkey_root, key, &hkey )))
{
if ((res = RegDeleteValueW( hkey, value )))
{
WARN("Failed to delete value %s (%d)\n", debugstr_w(value), res);
}
res = RegQueryInfoKeyW( hkey, NULL, NULL, NULL, &num_subkeys, NULL, NULL, &num_values,
NULL, NULL, NULL, NULL );
RegCloseKey( hkey );
if (!res && !num_subkeys && !num_values)
{
TRACE("Removing empty key %s\n", debugstr_w(key));
RegDeleteKeyW( hkey_root, key );
}
return;
}
WARN("Failed to open key %s (%d)\n", debugstr_w(key), res);
}
static UINT ITERATE_RemoveRegistryValuesOnUninstall( MSIRECORD *row, LPVOID param )
{
MSIPACKAGE *package = param;
LPCWSTR component, name, key_str, root_key_str;
LPWSTR deformated_key, deformated_name, ui_key_str;
MSICOMPONENT *comp;
MSIRECORD *uirow;
BOOL delete_key = FALSE;
HKEY hkey_root;
UINT size;
INT root;
ui_progress( package, 2, 0, 0, 0 );
component = MSI_RecordGetString( row, 6 );
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( row, 4 );
if (MSI_RecordIsNull( row, 5 ) && name )
{
if (name[0] == '+' && !name[1])
return ERROR_SUCCESS;
else if ((name[0] == '-' && !name[1]) || (name[0] == '*' && !name[1]))
{
delete_key = TRUE;
name = NULL;
}
}
root = MSI_RecordGetInteger( row, 2 );
key_str = MSI_RecordGetString( row, 3 );
root_key_str = get_root_key( package, root, &hkey_root );
if (!root_key_str)
return ERROR_SUCCESS;
deformat_string( package, key_str, &deformated_key );
size = strlenW( deformated_key ) + strlenW( root_key_str ) + 1;
ui_key_str = msi_alloc( size * sizeof(WCHAR) );
strcpyW( ui_key_str, root_key_str );
strcatW( ui_key_str, deformated_key );
deformat_string( package, name, &deformated_name );
delete_reg_key_or_value( hkey_root, deformated_key, deformated_name, delete_key );
msi_free( deformated_key );
uirow = MSI_CreateRecord( 2 );
MSI_RecordSetStringW( uirow, 1, ui_key_str );
MSI_RecordSetStringW( uirow, 2, deformated_name );
ui_actiondata( package, szRemoveRegistryValues, uirow );
msiobj_release( &uirow->hdr );
msi_free( ui_key_str );
msi_free( deformated_name );
return ERROR_SUCCESS;
}
static UINT ITERATE_RemoveRegistryValuesOnInstall( MSIRECORD *row, LPVOID param )
{
MSIPACKAGE *package = param;
LPCWSTR component, name, key_str, root_key_str;
LPWSTR deformated_key, deformated_name, ui_key_str;
MSICOMPONENT *comp;
MSIRECORD *uirow;
BOOL delete_key = FALSE;
HKEY hkey_root;
UINT size;
INT root;
ui_progress( package, 2, 0, 0, 0 );
component = MSI_RecordGetString( row, 5 );
comp = get_loaded_component( package, component );
if (!comp)
return ERROR_SUCCESS;
if (comp->ActionRequest != INSTALLSTATE_LOCAL)
{
TRACE("Component not scheduled for installation: %s\n", debugstr_w(component));
comp->Action = comp->Installed;
return ERROR_SUCCESS;
}
comp->Action = INSTALLSTATE_LOCAL;
if ((name = MSI_RecordGetString( row, 4 )))
{
if (name[0] == '-' && !name[1])
{
delete_key = TRUE;
name = NULL;
}
}
root = MSI_RecordGetInteger( row, 2 );
key_str = MSI_RecordGetString( row, 3 );
root_key_str = get_root_key( package, root, &hkey_root );
if (!root_key_str)
return ERROR_SUCCESS;
deformat_string( package, key_str, &deformated_key );
size = strlenW( deformated_key ) + strlenW( root_key_str ) + 1;
ui_key_str = msi_alloc( size * sizeof(WCHAR) );
strcpyW( ui_key_str, root_key_str );
strcatW( ui_key_str, deformated_key );
deformat_string( package, name, &deformated_name );
delete_reg_key_or_value( hkey_root, deformated_key, deformated_name, delete_key );
msi_free( deformated_key );
uirow = MSI_CreateRecord( 2 );
MSI_RecordSetStringW( uirow, 1, ui_key_str );
MSI_RecordSetStringW( uirow, 2, deformated_name );
ui_actiondata( package, szRemoveRegistryValues, uirow );
msiobj_release( &uirow->hdr );
msi_free( ui_key_str );
msi_free( deformated_name );
return ERROR_SUCCESS;
}
static UINT ACTION_RemoveRegistryValues( MSIPACKAGE *package )
{
UINT rc;
MSIQUERY *view;
static const WCHAR registry_query[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','R','e','g','i','s','t','r','y','`',0 };
static const WCHAR remove_registry_query[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','R','e','m','o','v','e','R','e','g','i','s','t','r','y','`',0 };
/* increment progress bar each time action data is sent */
ui_progress( package, 1, REG_PROGRESS_VALUE, 1, 0 );
rc = MSI_DatabaseOpenViewW( package->db, registry_query, &view );
if (rc == ERROR_SUCCESS)
{
rc = MSI_IterateRecords( view, NULL, ITERATE_RemoveRegistryValuesOnUninstall, package );
msiobj_release( &view->hdr );
if (rc != ERROR_SUCCESS)
return rc;
}
rc = MSI_DatabaseOpenViewW( package->db, remove_registry_query, &view );
if (rc == ERROR_SUCCESS)
{
rc = MSI_IterateRecords( view, NULL, ITERATE_RemoveRegistryValuesOnInstall, package );
msiobj_release( &view->hdr );
if (rc != ERROR_SUCCESS)
return rc;
}
return ERROR_SUCCESS;
}
static UINT ACTION_InstallInitialize(MSIPACKAGE *package)
{
package->script->CurrentlyScripting = TRUE;
@ -6604,12 +6804,6 @@ static UINT ACTION_RemoveExistingProducts( MSIPACKAGE *package )
return msi_unimplemented_action_stub( package, "RemoveExistingProducts", table );
}
static UINT ACTION_RemoveRegistryValues( MSIPACKAGE *package )
{
static const WCHAR table[] = { 'R','e','m','o','v','e','R','e','g','i','s','t','r','y',0 };
return msi_unimplemented_action_stub( package, "RemoveRegistryValues", table );
}
static UINT ACTION_SetODBCFolders( MSIPACKAGE *package )
{
static const WCHAR table[] = { 'D','i','r','e','c','t','o','r','y',0 };

View file

@ -1076,6 +1076,10 @@ static const WCHAR szPIDTemplate[] = {'P','I','D','T','e','m','p','l','a','t','e
static const WCHAR szPIDKEY[] = {'P','I','D','K','E','Y',0};
static const WCHAR szTYPELIB[] = {'T','Y','P','E','L','I','B',0};
static const WCHAR szSumInfo[] = {5 ,'S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0};
static const WCHAR szHCR[] = {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T','\\',0};
static const WCHAR szHCU[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\',0};
static const WCHAR szHLM[] = {'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E','\\',0};
static const WCHAR szHU[] = {'H','K','E','Y','_','U','S','E','R','S','\\',0};
/* memory allocation macro functions */
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);