msi: Install feature when new component is added.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49350 Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
99e7c801e4
commit
877540b522
|
@ -1374,6 +1374,49 @@ static UINT load_all_patches(MSIPACKAGE *package)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT iterate_patched_component( MSIRECORD *row, LPVOID param )
|
||||||
|
{
|
||||||
|
MSIPACKAGE *package = param;
|
||||||
|
const WCHAR *name;
|
||||||
|
MSICOMPONENT *c;
|
||||||
|
|
||||||
|
name = MSI_RecordGetString( row, 1 );
|
||||||
|
TRACE( "found patched component: %s\n", wine_dbgstr_w(name) );
|
||||||
|
c = msi_get_loaded_component( package, name );
|
||||||
|
if (!c)
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
c->updated = 1;
|
||||||
|
if (!wcscmp( MSI_RecordGetString( row, 2 ), L"INSERT" ))
|
||||||
|
c->added = 1;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mark_patched_components( MSIPACKAGE *package )
|
||||||
|
{
|
||||||
|
static const WCHAR select[] = L"SELECT `Row`, `Column` FROM `_TransformView` WHERE `Table`='Component'";
|
||||||
|
MSIQUERY *q;
|
||||||
|
UINT r;
|
||||||
|
|
||||||
|
r = MSI_OpenQuery( package->db, &q, select );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MSI_IterateRecords( q, NULL, iterate_patched_component, package );
|
||||||
|
msiobj_release( &q->hdr );
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
r = MSI_OpenQuery( package->db, &q, L"ALTER TABLE `_TransformView` FREE" );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
return;
|
||||||
|
r = MSI_ViewExecute( q, NULL );
|
||||||
|
msiobj_release( &q->hdr );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static UINT load_folder_persistence( MSIPACKAGE *package, MSIFOLDER *folder )
|
static UINT load_folder_persistence( MSIPACKAGE *package, MSIFOLDER *folder )
|
||||||
{
|
{
|
||||||
static const WCHAR query[] = {
|
static const WCHAR query[] = {
|
||||||
|
@ -1518,6 +1561,7 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package)
|
||||||
msi_load_all_features( package );
|
msi_load_all_features( package );
|
||||||
load_all_files( package );
|
load_all_files( package );
|
||||||
load_all_patches( package );
|
load_all_patches( package );
|
||||||
|
mark_patched_components( package );
|
||||||
load_all_media( package );
|
load_all_media( package );
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
@ -1802,12 +1846,6 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
|
||||||
{
|
|
||||||
if (feature->Feature_Parent) continue;
|
|
||||||
disable_children( feature, level );
|
|
||||||
follow_parent( feature );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (!msi_get_property_int( package->db, szInstalled, 0 ))
|
else if (!msi_get_property_int( package->db, szInstalled, 0 ))
|
||||||
{
|
{
|
||||||
|
@ -1834,15 +1872,69 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* disable child features of unselected parent or follow parent */
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||||
{
|
{
|
||||||
if (feature->Feature_Parent) continue;
|
ComponentList *cl;
|
||||||
disable_children( feature, level );
|
MSIFEATURE *cur;
|
||||||
follow_parent( feature );
|
|
||||||
|
if (!is_feature_selected( feature, level )) continue;
|
||||||
|
if (feature->ActionRequest != INSTALLSTATE_UNKNOWN) continue;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
|
||||||
|
{
|
||||||
|
if (!cl->component->updated && !cl->component->added)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cur = feature;
|
||||||
|
while (cur)
|
||||||
|
{
|
||||||
|
if (cur->ActionRequest != INSTALLSTATE_UNKNOWN)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (cur->Installed != INSTALLSTATE_ABSENT)
|
||||||
|
{
|
||||||
|
cur->Action = cur->Installed;
|
||||||
|
cur->ActionRequest = cur->Installed;
|
||||||
|
}
|
||||||
|
else if (!cl->component->added)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (cur->Attributes & msidbFeatureAttributesFavorSource)
|
||||||
|
{
|
||||||
|
cur->Action = INSTALLSTATE_SOURCE;
|
||||||
|
cur->ActionRequest = INSTALLSTATE_SOURCE;
|
||||||
|
}
|
||||||
|
else if (cur->Attributes & msidbFeatureAttributesFavorAdvertise)
|
||||||
|
{
|
||||||
|
cur->Action = INSTALLSTATE_ADVERTISED;
|
||||||
|
cur->ActionRequest = INSTALLSTATE_ADVERTISED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur->Action = INSTALLSTATE_LOCAL;
|
||||||
|
cur->ActionRequest = INSTALLSTATE_LOCAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cur->Feature_Parent)
|
||||||
|
break;
|
||||||
|
cur = msi_get_loaded_feature(package, cur->Feature_Parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* disable child features of unselected parent or follow parent */
|
||||||
|
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||||
|
{
|
||||||
|
if (feature->Feature_Parent) continue;
|
||||||
|
disable_children( feature, level );
|
||||||
|
follow_parent( feature );
|
||||||
|
}
|
||||||
|
|
||||||
/* now we want to set component state based based on feature state */
|
/* now we want to set component state based based on feature state */
|
||||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||||
{
|
{
|
||||||
|
|
|
@ -544,6 +544,8 @@ typedef struct tagMSICOMPONENT
|
||||||
unsigned int hasAdvertisedFeature:1;
|
unsigned int hasAdvertisedFeature:1;
|
||||||
unsigned int hasLocalFeature:1;
|
unsigned int hasLocalFeature:1;
|
||||||
unsigned int hasSourceFeature:1;
|
unsigned int hasSourceFeature:1;
|
||||||
|
unsigned int added:1;
|
||||||
|
unsigned int updated:1;
|
||||||
} MSICOMPONENT;
|
} MSICOMPONENT;
|
||||||
|
|
||||||
typedef struct tagComponentList
|
typedef struct tagComponentList
|
||||||
|
|
|
@ -274,9 +274,14 @@ static UINT apply_substorage_transform( MSIPACKAGE *package, MSIDATABASE *patch_
|
||||||
{
|
{
|
||||||
ret = check_transform_applicable( package, stg );
|
ret = check_transform_applicable( package, stg );
|
||||||
if (ret == ERROR_SUCCESS)
|
if (ret == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
msi_table_apply_transform( package->db, stg, MSITRANSFORM_ERROR_VIEWTRANSFORM );
|
||||||
msi_table_apply_transform( package->db, stg, 0 );
|
msi_table_apply_transform( package->db, stg, 0 );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
TRACE("substorage transform %s wasn't applicable\n", debugstr_w(name));
|
TRACE("substorage transform %s wasn't applicable\n", debugstr_w(name));
|
||||||
|
}
|
||||||
IStorage_Release( stg );
|
IStorage_Release( stg );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -844,7 +844,7 @@ static void test_simple_patch( void )
|
||||||
size = get_pf_file_size( "msitest\\patch.txt" );
|
size = get_pf_file_size( "msitest\\patch.txt" );
|
||||||
ok( size == 1002, "expected 1002, got %u\n", size );
|
ok( size == 1002, "expected 1002, got %u\n", size );
|
||||||
size = get_pf_file_size( "msitest\\file.txt" );
|
size = get_pf_file_size( "msitest\\file.txt" );
|
||||||
todo_wine ok( size == 1000, "expected 1000, got %u\n", size );
|
ok( size == 1000, "expected 1000, got %u\n", size );
|
||||||
|
|
||||||
/* show that MsiOpenPackage applies registered patches */
|
/* show that MsiOpenPackage applies registered patches */
|
||||||
r = MsiOpenPackageA( path, &hpackage );
|
r = MsiOpenPackageA( path, &hpackage );
|
||||||
|
|
Loading…
Reference in New Issue