msiobj_release(&row->hdr);
}
-UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine )
+UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine,
+ BOOL preserve_case )
{
LPCWSTR ptr,ptr2;
BOOL quote;
prop = msi_alloc((len+1)*sizeof(WCHAR));
memcpy(prop,ptr,len*sizeof(WCHAR));
prop[len]=0;
+
+ if (!preserve_case)
+ struprW(prop);
+
ptr2++;
len = 0;
static UINT msi_check_transform_applicable( MSIPACKAGE *package, IStorage *patch )
{
- WCHAR szProductCode[] = { 'P','r','o','d','u','c','t','C','o','d','e',0 };
- LPWSTR prod_code, patch_product;
- UINT ret;
+ static const WCHAR szProductCode[] =
+ { 'P','r','o','d','u','c','t','C','o','d','e',0 };
+ static const WCHAR szSystemLanguageID[] =
+ { 'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0 };
+
+ LPWSTR prod_code, patch_product, langid = NULL, template = NULL;
+ UINT ret = ERROR_FUNCTION_FAILED;
prod_code = msi_dup_property( package, szProductCode );
patch_product = msi_get_suminfo_product( patch );
TRACE("db = %s patch = %s\n", debugstr_w(prod_code), debugstr_w(patch_product));
if ( strstrW( patch_product, prod_code ) )
- ret = ERROR_SUCCESS;
- else
- ret = ERROR_FUNCTION_FAILED;
+ {
+ static const WCHAR zero[] = {'0',0};
+ MSISUMMARYINFO *si;
+ const WCHAR *p;
+
+ si = MSI_GetSummaryInformationW( patch, 0 );
+ if (!si)
+ {
+ ERR("no summary information!\n");
+ goto end;
+ }
+
+ template = msi_suminfo_dup_string( si, PID_TEMPLATE );
+ if (!template)
+ {
+ ERR("no template property!\n");
+ msiobj_release( &si->hdr );
+ goto end;
+ }
+
+ if (!template[0])
+ {
+ ret = ERROR_SUCCESS;
+ msiobj_release( &si->hdr );
+ goto end;
+ }
+
+ langid = msi_dup_property( package, szSystemLanguageID );
+ if (!langid)
+ {
+ msiobj_release( &si->hdr );
+ goto end;
+ }
+
+ p = strchrW( template, ';' );
+ if (p && (!strcmpW( p + 1, langid ) || !strcmpW( p + 1, zero )))
+ {
+ TRACE("applicable transform\n");
+ ret = ERROR_SUCCESS;
+ }
+
+ /* FIXME: check platform */
+ msiobj_release( &si->hdr );
+ }
+
+end:
msi_free( patch_product );
msi_free( prod_code );
+ msi_free( template );
+ msi_free( langid );
return ret;
}
return ERROR_SUCCESS;
}
-static UINT msi_check_patch_applicable( MSIPACKAGE *package, MSISUMMARYINFO *si )
+UINT msi_check_patch_applicable( MSIPACKAGE *package, MSISUMMARYINFO *si )
{
static const WCHAR szProdCode[] = { 'P','r','o','d','u','c','t','C','o','d','e',0 };
LPWSTR guid_list, *guids, product_code;
return ret;
}
+static UINT msi_set_media_source_prop(MSIPACKAGE *package)
+{
+ MSIQUERY *view;
+ MSIRECORD *rec = NULL;
+ LPWSTR patch;
+ LPCWSTR prop;
+ UINT r;
+
+ static const WCHAR szPatch[] = {'P','A','T','C','H',0};
+ static const WCHAR query[] = {'S','E','L','E','C','T',' ',
+ '`','S','o','u','r','c','e','`',' ','F','R','O','M',' ',
+ '`','M','e','d','i','a','`',' ','W','H','E','R','E',' ',
+ '`','S','o','u','r','c','e','`',' ','I','S',' ',
+ 'N','O','T',' ','N','U','L','L',0};
+
+ r = MSI_DatabaseOpenViewW(package->db, query, &view);
+ if (r != ERROR_SUCCESS)
+ return r;
+
+ r = MSI_ViewExecute(view, 0);
+ if (r != ERROR_SUCCESS)
+ goto done;
+
+ if (MSI_ViewFetch(view, &rec) == ERROR_SUCCESS)
+ {
+ prop = MSI_RecordGetString(rec, 1);
+ patch = msi_dup_property(package, szPatch);
+ MSI_SetPropertyW(package, prop, patch);
+ msi_free(patch);
+ }
+
+done:
+ if (rec) msiobj_release(&rec->hdr);
+ msiobj_release(&view->hdr);
+
+ return r;
+}
+
static UINT msi_parse_patch_summary( MSIPACKAGE *package, MSIDATABASE *patch_db )
{
MSISUMMARYINFO *si;
if (!si)
return ERROR_FUNCTION_FAILED;
- msi_check_patch_applicable( package, si );
+ if (msi_check_patch_applicable( package, si ) != ERROR_SUCCESS)
+ {
+ TRACE("Patch not applicable\n");
+ return ERROR_SUCCESS;
+ }
+
+ package->patch = msi_alloc(sizeof(MSIPATCHINFO));
+ if (!package->patch)
+ return ERROR_OUTOFMEMORY;
+
+ package->patch->patchcode = msi_suminfo_dup_string(si, PID_REVNUMBER);
+ if (!package->patch->patchcode)
+ return ERROR_OUTOFMEMORY;
/* enumerate the substorage */
str = msi_suminfo_dup_string( si, PID_LASTAUTHOR );
+ package->patch->transforms = str;
+
substorage = msi_split_string( str, ';' );
for ( i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++ )
r = msi_apply_substorage_transform( package, patch_db, substorage[i] );
- msi_free( substorage );
- msi_free( str );
-
- /* FIXME: parse the sources in PID_REVNUMBER and do something with them... */
+ msi_free( substorage );
msiobj_release( &si->hdr );
+ msi_set_media_source_prop(package);
+
return r;
}
return ERROR_SUCCESS;
}
+static UINT msi_set_context(MSIPACKAGE *package)
+{
+ WCHAR val[10];
+ DWORD sz = 10;
+ DWORD num;
+ UINT r;
+
+ static const WCHAR szOne[] = {'1',0};
+ static const WCHAR szAllUsers[] = {'A','L','L','U','S','E','R','S',0};
+
+ package->Context = MSIINSTALLCONTEXT_USERUNMANAGED;
+
+ r = MSI_GetPropertyW(package, szAllUsers, val, &sz);
+ if (r == ERROR_SUCCESS)
+ {
+ num = atolW(val);
+ if (num == 1 || num == 2)
+ package->Context = MSIINSTALLCONTEXT_MACHINE;
+ }
+
+ MSI_SetPropertyW(package, szAllUsers, szOne);
+ return ERROR_SUCCESS;
+}
+
/****************************************************
* TOP level entry points
*****************************************************/
static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0};
static const WCHAR szAction[] = {'A','C','T','I','O','N',0};
static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
+ static const WCHAR szReinstall[] = {'R','E','I','N','S','T','A','L','L',0};
+ static const WCHAR szInstalled[] = {'I','n','s','t','a','l','l','e','d',0};
+ static const WCHAR szAll[] = {'A','L','L',0};
MSI_SetPropertyW(package, szAction, szInstall);
msi_set_sourcedir_props(package, FALSE);
}
- msi_parse_command_line( package, szCommandLine );
+ msi_parse_command_line( package, szCommandLine, FALSE );
msi_apply_transforms( package );
msi_apply_patches( package );
+ if (!szCommandLine && msi_get_property_int( package, szInstalled, 0 ))
+ {
+ TRACE("setting reinstall property\n");
+ MSI_SetPropertyW( package, szReinstall, szAll );
+ }
+
/* properties may have been added by a transform */
msi_clone_properties( package );
+ msi_set_context( package );
if ( (msi_get_property_int(package, szUILevel, 0) & INSTALLUILEVEL_MASK) >= INSTALLUILEVEL_REDUCED )
{
/* finish up running custom actions */
ACTION_FinishCustomActions(package);
+ if (rc == ERROR_SUCCESS && package->need_reboot)
+ return ERROR_SUCCESS_REBOOT_REQUIRED;
+
return rc;
}
static UINT ITERATE_Actions(MSIRECORD *row, LPVOID param)
{
- iterate_action_param *iap= (iterate_action_param*)param;
+ iterate_action_param *iap = param;
UINT rc;
LPCWSTR cond, action;
static UINT ITERATE_CreateFolders(MSIRECORD *row, LPVOID param)
{
- MSIPACKAGE *package = (MSIPACKAGE*)param;
+ MSIPACKAGE *package = param;
LPCWSTR dir;
LPWSTR full_path;
MSIRECORD *uirow;
comp->KeyPath = msi_dup_record_field( row, 6 );
comp->Installed = INSTALLSTATE_UNKNOWN;
- msi_component_set_state( comp, INSTALLSTATE_UNKNOWN );
+ msi_component_set_state(package, comp, INSTALLSTATE_UNKNOWN);
return ERROR_SUCCESS;
}
static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param)
{
- _ilfs* ilfs= (_ilfs*)param;
+ _ilfs* ilfs = param;
LPCWSTR component;
MSICOMPONENT *comp;
static UINT load_feature(MSIRECORD * row, LPVOID param)
{
- MSIPACKAGE* package = (MSIPACKAGE*)param;
+ MSIPACKAGE* package = param;
MSIFEATURE* feature;
static const WCHAR Query1[] =
{'S','E','L','E','C','T',' ',
feature->Attributes = MSI_RecordGetInteger(row,8);
feature->Installed = INSTALLSTATE_UNKNOWN;
- msi_feature_set_state( feature, INSTALLSTATE_UNKNOWN );
+ msi_feature_set_state(package, feature, INSTALLSTATE_UNKNOWN);
list_add_tail( &package->features, &feature->entry );
static UINT find_feature_children(MSIRECORD * row, LPVOID param)
{
- MSIPACKAGE* package = (MSIPACKAGE*)param;
+ MSIPACKAGE* package = param;
MSIFEATURE *parent, *child;
child = find_feature_by_name( package, MSI_RecordGetString( row, 1 ) );
static UINT load_file(MSIRECORD *row, LPVOID param)
{
- MSIPACKAGE* package = (MSIPACKAGE*)param;
+ MSIPACKAGE* package = param;
LPCWSTR component;
MSIFILE *file;
file->Component = get_loaded_component( package, component );
if (!file->Component)
- ERR("Unfound Component %s\n",debugstr_w(component));
+ {
+ WARN("Component not found: %s\n", debugstr_w(component));
+ msi_free(file->File);
+ msi_free(file);
+ return ERROR_SUCCESS;
+ }
file->FileName = msi_dup_record_field( row, 3 );
reduce_to_longfilename( file->FileName );
/* if the compressed bits are not set in the file attributes,
* then read the information from the package word count property
*/
- if (file->Attributes & msidbFileAttributesCompressed)
+ if (package->WordCount & msidbSumInfoSourceTypeAdminImage)
+ {
+ file->IsCompressed = FALSE;
+ }
+ else if (file->Attributes &
+ (msidbFileAttributesCompressed | msidbFileAttributesPatchAdded))
{
file->IsCompressed = TRUE;
}
}
else
{
- file->IsCompressed = package->WordCount & MSIWORDCOUNT_COMPRESSED;
+ file->IsCompressed = package->WordCount & msidbSumInfoSourceTypeCompressed;
}
load_file_hash(package, file);
MSI_SetPropertyW(package, szCosting, szZero);
MSI_SetPropertyW(package, cszRootDrive, c_colon);
+ load_all_folders( package );
load_all_components( package );
load_all_features( package );
load_all_files( package );
- load_all_folders( package );
return ERROR_SUCCESS;
}
static void ACTION_GetComponentInstallStates(MSIPACKAGE *package)
{
MSICOMPONENT *comp;
+ INSTALLSTATE state;
+ UINT r;
- LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
- {
- INSTALLSTATE res;
+ state = MsiQueryProductStateW(package->ProductCode);
+ LIST_FOR_EACH_ENTRY(comp, &package->components, MSICOMPONENT, entry)
+ {
if (!comp->ComponentId)
continue;
- res = MsiGetComponentPathW( package->ProductCode,
- comp->ComponentId, NULL, NULL);
- if (res < 0)
- res = INSTALLSTATE_ABSENT;
- comp->Installed = res;
+ if (state != INSTALLSTATE_LOCAL && state != INSTALLSTATE_DEFAULT)
+ comp->Installed = INSTALLSTATE_ABSENT;
+ else
+ {
+ r = MsiQueryComponentStateW(package->ProductCode, NULL,
+ package->Context, comp->ComponentId,
+ &comp->Installed);
+ if (r != ERROR_SUCCESS)
+ comp->Installed = INSTALLSTATE_ABSENT;
+ }
}
}
-/* scan for and update current install states */
-static void ACTION_UpdateFeatureInstallStates(MSIPACKAGE *package)
+static void ACTION_GetFeatureInstallStates(MSIPACKAGE *package)
{
- MSICOMPONENT *comp;
MSIFEATURE *feature;
+ INSTALLSTATE state;
+
+ state = MsiQueryProductStateW(package->ProductCode);
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
- ComponentList *cl;
- INSTALLSTATE res = INSTALLSTATE_ABSENT;
-
- LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
+ if (state != INSTALLSTATE_LOCAL && state != INSTALLSTATE_DEFAULT)
+ feature->Installed = INSTALLSTATE_ABSENT;
+ else
{
- comp= cl->component;
-
- if (!comp->ComponentId)
- {
- res = INSTALLSTATE_ABSENT;
- break;
- }
-
- if (res == INSTALLSTATE_ABSENT)
- res = comp->Installed;
- else
- {
- if (res == comp->Installed)
- continue;
-
- if (res != INSTALLSTATE_DEFAULT && res != INSTALLSTATE_LOCAL &&
- res != INSTALLSTATE_SOURCE)
- {
- res = INSTALLSTATE_INCOMPLETE;
- }
- }
+ feature->Installed = MsiQueryFeatureStateW(package->ProductCode,
+ feature->Feature);
}
- feature->Installed = res;
}
}
-static BOOL process_state_property (MSIPACKAGE* package, LPCWSTR property,
- INSTALLSTATE state)
+static BOOL process_state_property(MSIPACKAGE* package, int level,
+ LPCWSTR property, INSTALLSTATE state)
{
static const WCHAR all[]={'A','L','L',0};
+ static const WCHAR remove[] = {'R','E','M','O','V','E',0};
+ static const WCHAR reinstall[] = {'R','E','I','N','S','T','A','L','L',0};
LPWSTR override;
MSIFEATURE *feature;
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
+ if (lstrcmpW(property, remove) &&
+ (feature->Level <= 0 || feature->Level > level))
+ continue;
+
+ if (!strcmpW(property, reinstall)) state = feature->Installed;
+
if (strcmpiW(override,all)==0)
- msi_feature_set_state( feature, state );
+ msi_feature_set_state(package, feature, state);
else
{
LPWSTR ptr = override;
if ((ptr2 && strncmpW(ptr,feature->Feature, ptr2-ptr)==0)
|| (!ptr2 && strcmpW(ptr,feature->Feature)==0))
{
- msi_feature_set_state( feature, state );
+ msi_feature_set_state(package, feature, state);
break;
}
if (ptr2)
UINT MSI_SetFeatureStates(MSIPACKAGE *package)
{
- int install_level;
+ int level;
static const WCHAR szlevel[] =
{'I','N','S','T','A','L','L','L','E','V','E','L',0};
static const WCHAR szAddLocal[] =
{'R','E','M','O','V','E',0};
static const WCHAR szReinstall[] =
{'R','E','I','N','S','T','A','L','L',0};
+ static const WCHAR szAdvertise[] =
+ {'A','D','V','E','R','T','I','S','E',0};
BOOL override = FALSE;
MSICOMPONENT* component;
MSIFEATURE *feature;
TRACE("Checking Install Level\n");
- install_level = msi_get_property_int( package, szlevel, 1 );
+ level = msi_get_property_int(package, szlevel, 1);
/* ok here is the _real_ rub
* all these activation/deactivation things happen in order and things
* later on the list override things earlier on the list.
- * 1) INSTALLLEVEL processing
- * 2) ADDLOCAL
- * 3) REMOVE
- * 4) ADDSOURCE
- * 5) ADDDEFAULT
- * 6) REINSTALL
+ * 0) INSTALLLEVEL processing
+ * 1) ADDLOCAL
+ * 2) REMOVE
+ * 3) ADDSOURCE
+ * 4) ADDDEFAULT
+ * 5) REINSTALL
+ * 6) ADVERTISE
* 7) COMPADDLOCAL
* 8) COMPADDSOURCE
* 9) FILEADDLOCAL
* 10) FILEADDSOURCE
* 11) FILEADDDEFAULT
- * I have confirmed that if ADDLOCAL is stated then the INSTALLLEVEL is
- * ignored for all the features. seems strange, especially since it is not
- * documented anywhere, but it is how it works.
*
* I am still ignoring a lot of these. But that is ok for now, ADDLOCAL and
* REMOVE are the big ones, since we don't handle administrative installs
* yet anyway.
*/
- override |= process_state_property(package,szAddLocal,INSTALLSTATE_LOCAL);
- override |= process_state_property(package,szRemove,INSTALLSTATE_ABSENT);
- override |= process_state_property(package,szAddSource,INSTALLSTATE_SOURCE);
- override |= process_state_property(package,szReinstall,INSTALLSTATE_LOCAL);
+ override |= process_state_property(package, level, szAddLocal, INSTALLSTATE_LOCAL);
+ override |= process_state_property(package, level, szRemove, INSTALLSTATE_ABSENT);
+ override |= process_state_property(package, level, szAddSource, INSTALLSTATE_SOURCE);
+ override |= process_state_property(package, level, szReinstall, INSTALLSTATE_UNKNOWN);
+ override |= process_state_property(package, level, szAdvertise, INSTALLSTATE_ADVERTISED);
if (!override)
{
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
BOOL feature_state = ((feature->Level > 0) &&
- (feature->Level <= install_level));
+ (feature->Level <= level));
if ((feature_state) && (feature->Action == INSTALLSTATE_UNKNOWN))
{
if (feature->Attributes & msidbFeatureAttributesFavorSource)
- msi_feature_set_state( feature, INSTALLSTATE_SOURCE );
+ msi_feature_set_state(package, feature, INSTALLSTATE_SOURCE);
else if (feature->Attributes & msidbFeatureAttributesFavorAdvertise)
- msi_feature_set_state( feature, INSTALLSTATE_ADVERTISED );
+ msi_feature_set_state(package, feature, INSTALLSTATE_ADVERTISED);
else
- msi_feature_set_state( feature, INSTALLSTATE_LOCAL );
+ msi_feature_set_state(package, feature, INSTALLSTATE_LOCAL);
}
}
{
FeatureList *fl;
- if (feature->Level > 0 && feature->Level <= install_level)
+ if (feature->Level > 0 && feature->Level <= level)
continue;
LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry )
- msi_feature_set_state( fl->feature, INSTALLSTATE_UNKNOWN );
+ msi_feature_set_state(package, fl->feature, INSTALLSTATE_UNKNOWN);
}
}
else
{
ComponentList *cl;
- TRACE("Examining Feature %s (Installed %i, Action %i)\n",
- debugstr_w(feature->Feature), feature->Installed, feature->Action);
+ TRACE("Examining Feature %s (Level %i, Installed %i, Action %i)\n",
+ debugstr_w(feature->Feature), feature->Level, feature->Installed, feature->Action);
+
+ if (!feature->Level)
+ continue;
/* features with components that have compressed files are made local */
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
cl->component->ForceLocalState &&
feature->Action == INSTALLSTATE_SOURCE)
{
- msi_feature_set_state( feature, INSTALLSTATE_LOCAL );
+ msi_feature_set_state(package, feature, INSTALLSTATE_LOCAL);
break;
}
}
{
if ((component->Attributes & msidbComponentAttributesSourceOnly) &&
!component->ForceLocalState)
- msi_component_set_state( component, INSTALLSTATE_SOURCE );
+ msi_component_set_state(package, component, INSTALLSTATE_SOURCE);
else
- msi_component_set_state( component, INSTALLSTATE_LOCAL );
+ msi_component_set_state(package, component, INSTALLSTATE_LOCAL);
continue;
}
/* if any feature is local, the component must be local too */
if (component->hasLocalFeature)
{
- msi_component_set_state( component, INSTALLSTATE_LOCAL );
+ msi_component_set_state(package, component, INSTALLSTATE_LOCAL);
continue;
}
if (component->hasSourceFeature)
{
- msi_component_set_state( component, INSTALLSTATE_SOURCE );
+ msi_component_set_state(package, component, INSTALLSTATE_SOURCE);
continue;
}
if (component->hasAdvertiseFeature)
{
- msi_component_set_state( component, INSTALLSTATE_ADVERTISED );
+ msi_component_set_state(package, component, INSTALLSTATE_ADVERTISED);
continue;
}
TRACE("nobody wants component %s\n", debugstr_w(component->Component));
if (component->anyAbsent)
- msi_component_set_state(component, INSTALLSTATE_ABSENT);
+ msi_component_set_state(package, component, INSTALLSTATE_ABSENT);
}
LIST_FOR_EACH_ENTRY( component, &package->components, MSICOMPONENT, entry )
if (component->Action == INSTALLSTATE_DEFAULT)
{
TRACE("%s was default, setting to local\n", debugstr_w(component->Component));
- msi_component_set_state( component, INSTALLSTATE_LOCAL );
+ msi_component_set_state(package, component, INSTALLSTATE_LOCAL);
}
TRACE("Result: Component %s (Installed %i, Action %i)\n",
static UINT ITERATE_CostFinalizeDirectories(MSIRECORD *row, LPVOID param)
{
- MSIPACKAGE *package = (MSIPACKAGE*)param;
+ MSIPACKAGE *package = param;
LPCWSTR name;
LPWSTR path;
MSIFOLDER *f;
static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param)
{
- MSIPACKAGE *package = (MSIPACKAGE*)param;
+ MSIPACKAGE *package = param;
LPCWSTR name;
MSIFEATURE *feature;
{
static const WCHAR name_fmt[] =
{'%','u','.','%','u','.','%','u','.','%','u',0};
- static WCHAR name[] = {'\\',0};
+ static const WCHAR name[] = {'\\',0};
VS_FIXEDFILEINFO *lpVer;
WCHAR filever[0x100];
LPVOID version;
{
file->state = msifs_missing;
comp->Cost += file->FileSize;
- comp->Installed = INSTALLSTATE_INCOMPLETE;
continue;
}
{
file->state = msifs_overwrite;
comp->Cost += file->FileSize;
- comp->Installed = INSTALLSTATE_INCOMPLETE;
}
else
file->state = msifs_present;
MSIQUERY * view;
LPWSTR level;
- if ( 1 == msi_get_property_int( package, szCosting, 0 ) )
- return ERROR_SUCCESS;
-
TRACE("Building Directory properties\n");
rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
/* read components states from the registry */
ACTION_GetComponentInstallStates(package);
+ ACTION_GetFeatureInstallStates(package);
TRACE("File calculations\n");
msi_check_file_install_states( package );
TRACE("Disabling component %s\n", debugstr_w(comp->Component));
comp->Enabled = FALSE;
}
+ else
+ comp->Enabled = TRUE;
}
MSI_SetPropertyW(package,szCosting,szOne);
/* FIXME: check volume disk space */
MSI_SetPropertyW(package, szOutOfDiskSpace, szZero);
- ACTION_UpdateFeatureInstallStates(package);
-
return MSI_SetFeatureStates(package);
}
static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
{
- MSIPACKAGE *package = (MSIPACKAGE*)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 UINT ITERATE_LaunchConditions(MSIRECORD *row, LPVOID param)
{
- MSIPACKAGE* package = (MSIPACKAGE*)param;
+ MSIPACKAGE* package = param;
LPCWSTR cond = NULL;
LPCWSTR message = NULL;
UINT r;
ACTION_WriteSharedDLLsCount( comp->FullKeypath, comp->RefCount );
}
-/*
- * Ok further analysis makes me think that this work is
- * actually done in the PublishComponents and PublishFeatures
- * step, and not here. It appears like the keypath and all that is
- * resolved in this step, however actually written in the Publish steps.
- * But we will leave it here for now because it is unclear
- */
static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
{
WCHAR squished_pc[GUID_SIZE];
WCHAR squished_cc[GUID_SIZE];
UINT rc;
MSICOMPONENT *comp;
- HKEY hkey=0,hkey2=0;
+ HKEY hkey;
TRACE("\n");
- /* writes the Component and Features values to the registry */
-
- rc = MSIREG_OpenComponents(&hkey);
- if (rc != ERROR_SUCCESS)
- return rc;
-
squash_guid(package->ProductCode,squished_pc);
ui_progress(package,1,COMPONENT_PROGRESS_VALUE,1,0);
msi_free(comp->FullKeypath);
comp->FullKeypath = resolve_keypath( package, comp );
- /* do the refcounting */
ACTION_RefCountComponent( package, comp );
TRACE("Component %s (%s), Keypath=%s, RefCount=%i\n",
debugstr_w(squished_cc),
debugstr_w(comp->FullKeypath),
comp->RefCount);
- /*
- * Write the keypath out if the component is to be registered
- * and delete the key if the component is to be unregistered
- */
- if (ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
- {
- rc = RegCreateKeyW(hkey,squished_cc,&hkey2);
- if (rc != ERROR_SUCCESS)
- continue;
+ if (ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL) ||
+ ACTION_VerifyComponentForAction( comp, INSTALLSTATE_SOURCE))
+ {
if (!comp->FullKeypath)
continue;
- msi_reg_set_val_str( hkey2, squished_pc, comp->FullKeypath );
+ if (package->Context == MSIINSTALLCONTEXT_MACHINE)
+ rc = MSIREG_OpenUserDataComponentKey(comp->ComponentId, szLocalSid,
+ &hkey, TRUE);
+ else
+ rc = MSIREG_OpenUserDataComponentKey(comp->ComponentId, NULL,
+ &hkey, TRUE);
+
+ if (rc != ERROR_SUCCESS)
+ continue;
if (comp->Attributes & msidbComponentAttributesPermanent)
{
'0','0','0','0','0','0','0','0','0','0','0','0',
'0','0','0','0','0','0','0','0',0 };
- msi_reg_set_val_str( hkey2, szPermKey, comp->FullKeypath );
+ msi_reg_set_val_str(hkey, szPermKey, comp->FullKeypath);
}
- RegCloseKey(hkey2);
-
- rc = MSIREG_OpenUserDataComponentKey(comp->ComponentId, &hkey2, TRUE);
- if (rc != ERROR_SUCCESS)
- continue;
-
- msi_reg_set_val_str(hkey2, squished_pc, comp->FullKeypath);
- RegCloseKey(hkey2);
- }
- else if (ACTION_VerifyComponentForAction( comp, INSTALLSTATE_ABSENT))
- {
- DWORD res;
+ if (comp->Action == INSTALLSTATE_LOCAL)
+ msi_reg_set_val_str(hkey, squished_pc, comp->FullKeypath);
+ else
+ {
+ MSIFILE *file;
+ MSIRECORD *row;
+ LPWSTR ptr, ptr2;
+ WCHAR source[MAX_PATH];
+ WCHAR base[MAX_PATH];
+ LPWSTR sourcepath;
+
+ static const WCHAR fmt[] = {'%','0','2','d','\\',0};
+ static const WCHAR query[] = {
+ 'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
+ '`','M','e','d','i','a','`',' ','W','H','E','R','E',' ',
+ '`','L','a','s','t','S','e','q','u','e','n','c','e','`',' ',
+ '>','=',' ','%','i',' ','O','R','D','E','R',' ','B','Y',' ',
+ '`','D','i','s','k','I','d','`',0};
+
+ file = get_loaded_file(package, comp->KeyPath);
+ if (!file)
+ continue;
- rc = RegOpenKeyW(hkey,squished_cc,&hkey2);
- if (rc != ERROR_SUCCESS)
- continue;
+ row = MSI_QueryGetRecord(package->db, query, file->Sequence);
+ sprintfW(source, fmt, MSI_RecordGetInteger(row, 1));
+ ptr2 = strrchrW(source, '\\') + 1;
+ msiobj_release(&row->hdr);
- RegDeleteValueW(hkey2,squished_pc);
+ lstrcpyW(base, package->PackagePath);
+ ptr = strrchrW(base, '\\');
+ *(ptr + 1) = '\0';
- /* if the key is empty delete it */
- res = RegEnumKeyExW(hkey2,0,NULL,0,0,NULL,0,NULL);
- RegCloseKey(hkey2);
- if (res == ERROR_NO_MORE_ITEMS)
- RegDeleteKeyW(hkey,squished_cc);
+ sourcepath = resolve_file_source(package, file);
+ ptr = sourcepath + lstrlenW(base);
+ lstrcpyW(ptr2, ptr);
+ msi_free(sourcepath);
- MSIREG_DeleteUserDataComponentKey(comp->ComponentId);
+ msi_reg_set_val_str(hkey, squished_pc, source);
+ }
+ RegCloseKey(hkey);
+ }
+ else if (ACTION_VerifyComponentForAction(comp, INSTALLSTATE_ABSENT))
+ {
+ if (package->Context == MSIINSTALLCONTEXT_MACHINE)
+ MSIREG_DeleteUserDataComponentKey(comp->ComponentId, szLocalSid);
+ else
+ MSIREG_DeleteUserDataComponentKey(comp->ComponentId, NULL);
}
/* UI stuff */
ui_actiondata(package,szProcessComponents,uirow);
msiobj_release( &uirow->hdr );
}
- RegCloseKey(hkey);
- return rc;
+
+ return ERROR_SUCCESS;
}
typedef struct {
TRACE("trying %s\n", debugstr_w(tl_struct->path));
res = LoadTypeLib(tl_struct->path,&tl_struct->ptLib);
- if (!SUCCEEDED(res))
+ if (FAILED(res))
{
msi_free(tl_struct->path);
tl_struct->path = NULL;
static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param)
{
- MSIPACKAGE* package = (MSIPACKAGE*)param;
+ MSIPACKAGE* package = param;
LPCWSTR component;
MSICOMPONENT *comp;
MSIFILE *file;
typelib_struct tl_struct;
+ ITypeLib *tlib;
HMODULE module;
+ HRESULT hr;
+
static const WCHAR szTYPELIB[] = {'T','Y','P','E','L','I','B',0};
component = MSI_RecordGetString(row,3);
res = RegisterTypeLib(tl_struct.ptLib,tl_struct.path,help);
msi_free(help);
- if (!SUCCEEDED(res))
+ if (FAILED(res))
ERR("Failed to register type library %s\n",
debugstr_w(tl_struct.path));
else
msi_free(tl_struct.source);
}
else
- ERR("Could not load file! %s\n", debugstr_w(file->TargetPath));
+ {
+ hr = LoadTypeLibEx(file->TargetPath, REGKIND_REGISTER, &tlib);
+ if (FAILED(hr))
+ {
+ ERR("Failed to load type library: %08x\n", hr);
+ return ERROR_FUNCTION_FAILED;
+ }
+
+ ITypeLib_Release(tlib);
+ }
return ERROR_SUCCESS;
}
static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
{
- MSIPACKAGE *package = (MSIPACKAGE*)param;
+ MSIPACKAGE *package = param;
LPWSTR target_file, target_folder, filename;
LPCWSTR buffer, extension;
MSICOMPONENT *comp;
return ERROR_SUCCESS;
res = CoInitialize( NULL );
- if (FAILED (res))
- {
- ERR("CoInitialize failed\n");
- return ERROR_FUNCTION_FAILED;
- }
rc = MSI_IterateRecords(view, NULL, ITERATE_CreateShortcuts, package);
msiobj_release(&view->hdr);
- CoUninitialize();
+ if (SUCCEEDED(res))
+ CoUninitialize();
return rc;
}
-static UINT ITERATE_PublishProduct(MSIRECORD *row, LPVOID param)
+static UINT ITERATE_PublishIcon(MSIRECORD *row, LPVOID param)
{
- MSIPACKAGE* package = (MSIPACKAGE*)param;
+ MSIPACKAGE* package = param;
HANDLE the_file;
LPWSTR FilePath;
LPCWSTR FileName;
return ERROR_SUCCESS;
}
-static BOOL msi_check_publish(MSIPACKAGE *package)
+static UINT msi_publish_icons(MSIPACKAGE *package)
{
- MSIFEATURE *feature;
+ UINT r;
+ MSIQUERY *view;
- LIST_FOR_EACH_ENTRY(feature, &package->features, MSIFEATURE, entry)
+ static const WCHAR query[]= {
+ 'S','E','L','E','C','T',' ','*',' ',
+ 'F','R','O','M',' ','`','I','c','o','n','`',0};
+
+ r = MSI_DatabaseOpenViewW(package->db, query, &view);
+ if (r == ERROR_SUCCESS)
{
- if (feature->ActionRequest == INSTALLSTATE_LOCAL)
- return TRUE;
+ MSI_IterateRecords(view, NULL, ITERATE_PublishIcon, package);
+ msiobj_release(&view->hdr);
}
- return FALSE;
+ return ERROR_SUCCESS;
}
-/*
- * 99% of the work done here is only done for
- * advertised installs. However this is where the
- * Icon table is processed and written out
- * so that is what I am going to do here.
- */
-static UINT ACTION_PublishProduct(MSIPACKAGE *package)
+static UINT msi_publish_sourcelist(MSIPACKAGE *package, HKEY hkey)
{
- UINT rc;
- LPWSTR packname;
- MSIQUERY * view;
- MSISOURCELISTINFO *info;
- MSIMEDIADISK *disk;
- static const WCHAR Query[]=
- {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
- '`','I','c','o','n','`',0};
- /* for registry stuff */
- HKEY hkey=0;
- HKEY hukey=0;
- HKEY hudkey=0, props=0;
+ UINT r;
HKEY source;
- static const WCHAR szProductLanguage[] =
- {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
- static const WCHAR szARPProductIcon[] =
- {'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0};
- static const WCHAR szProductVersion[] =
- {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
- static const WCHAR szSourceList[] =
- {'S','o','u','r','c','e','L','i','s','t',0};
- static const WCHAR szEmpty[] = {0};
- DWORD langid;
LPWSTR buffer;
- DWORD size;
- MSIHANDLE hDb, hSumInfo;
-
- /* FIXME: also need to publish if the product is in advertise mode */
- if (!msi_check_publish(package))
- return ERROR_SUCCESS;
+ MSIMEDIADISK *disk;
+ MSISOURCELISTINFO *info;
- /* write out icon files */
+ static const WCHAR szEmpty[] = {0};
+ static const WCHAR szSourceList[] = {'S','o','u','r','c','e','L','i','s','t',0};
- rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
- if (rc == ERROR_SUCCESS)
- {
- MSI_IterateRecords(view, NULL, ITERATE_PublishProduct, package);
- msiobj_release(&view->hdr);
- }
+ r = RegCreateKeyW(hkey, szSourceList, &source);
+ if (r != ERROR_SUCCESS)
+ return r;
- /* ok there is a lot more done here but i need to figure out what */
+ RegCloseKey(source);
- if (package->Context == MSIINSTALLCONTEXT_MACHINE)
- {
- rc = MSIREG_OpenLocalClassesProductKey(package->ProductCode, &hukey, TRUE);
- if (rc != ERROR_SUCCESS)
- goto end;
+ buffer = strrchrW(package->PackagePath, '\\') + 1;
+ r = MsiSourceListSetInfoW(package->ProductCode, NULL,
+ package->Context, MSICODE_PRODUCT,
+ INSTALLPROPERTY_PACKAGENAMEW, buffer);
+ if (r != ERROR_SUCCESS)
+ return r;
- rc = MSIREG_OpenLocalSystemInstallProps(package->ProductCode, &props, TRUE);
- if (rc != ERROR_SUCCESS)
- goto end;
- }
- else
- {
- rc = MSIREG_OpenProductsKey(package->ProductCode,&hkey,TRUE);
- if (rc != ERROR_SUCCESS)
- goto end;
+ r = MsiSourceListSetInfoW(package->ProductCode, NULL,
+ package->Context, MSICODE_PRODUCT,
+ INSTALLPROPERTY_MEDIAPACKAGEPATHW, szEmpty);
+ if (r != ERROR_SUCCESS)
+ return r;
- rc = MSIREG_OpenUserProductsKey(package->ProductCode,&hukey,TRUE);
- if (rc != ERROR_SUCCESS)
- goto end;
+ r = MsiSourceListSetInfoW(package->ProductCode, NULL,
+ package->Context, MSICODE_PRODUCT,
+ INSTALLPROPERTY_DISKPROMPTW, szEmpty);
+ if (r != ERROR_SUCCESS)
+ return r;
- rc = MSIREG_OpenCurrentUserInstallProps(package->ProductCode, &props, TRUE);
- if (rc != ERROR_SUCCESS)
- goto end;
+ LIST_FOR_EACH_ENTRY(info, &package->sourcelist_info, MSISOURCELISTINFO, entry)
+ {
+ if (!lstrcmpW(info->property, INSTALLPROPERTY_LASTUSEDSOURCEW))
+ msi_set_last_used_source(package->ProductCode, NULL, info->context,
+ info->options, info->value);
+ else
+ MsiSourceListSetInfoW(package->ProductCode, NULL,
+ info->context, info->options,
+ info->property, info->value);
}
- rc = RegCreateKeyW(hukey, szSourceList, &source);
- if (rc != ERROR_SUCCESS)
- goto end;
+ LIST_FOR_EACH_ENTRY(disk, &package->sourcelist_media, MSIMEDIADISK, entry)
+ {
+ MsiSourceListAddMediaDiskW(package->ProductCode, NULL,
+ disk->context, disk->options,
+ disk->disk_id, disk->volume_label, disk->disk_prompt);
+ }
- RegCloseKey(source);
+ return ERROR_SUCCESS;
+}
- rc = MSIREG_OpenUserDataProductKey(package->ProductCode,&hudkey,TRUE);
- if (rc != ERROR_SUCCESS)
- goto end;
+static UINT msi_publish_product_properties(MSIPACKAGE *package, HKEY hkey)
+{
+ MSIHANDLE hdb, suminfo;
+ WCHAR guids[MAX_PATH];
+ WCHAR packcode[SQUISH_GUID_SIZE];
+ LPWSTR buffer;
+ LPWSTR ptr;
+ DWORD langid;
+ DWORD size;
+ UINT r;
- buffer = msi_dup_property( package, INSTALLPROPERTY_PRODUCTNAMEW );
- msi_reg_set_val_str( hukey, INSTALLPROPERTY_PRODUCTNAMEW, buffer );
+ static const WCHAR szProductLanguage[] =
+ {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
+ static const WCHAR szARPProductIcon[] =
+ {'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0};
+ static const WCHAR szProductVersion[] =
+ {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
+ static const WCHAR szAssignment[] =
+ {'A','s','s','i','g','n','m','e','n','t',0};
+ static const WCHAR szAdvertiseFlags[] =
+ {'A','d','v','e','r','t','i','s','e','F','l','a','g','s',0};
+ static const WCHAR szClients[] =
+ {'C','l','i','e','n','t','s',0};
+ static const WCHAR szColon[] = {':',0};
+
+ buffer = msi_dup_property(package, INSTALLPROPERTY_PRODUCTNAMEW);
+ msi_reg_set_val_str(hkey, INSTALLPROPERTY_PRODUCTNAMEW, buffer);
msi_free(buffer);
- langid = msi_get_property_int( package, szProductLanguage, 0 );
- msi_reg_set_val_dword( hukey, INSTALLPROPERTY_LANGUAGEW, langid );
-
- packname = strrchrW( package->PackagePath, '\\' ) + 1;
- msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGENAMEW, packname );
+ langid = msi_get_property_int(package, szProductLanguage, 0);
+ msi_reg_set_val_dword(hkey, INSTALLPROPERTY_LANGUAGEW, langid);
/* FIXME */
- msi_reg_set_val_dword( hukey, INSTALLPROPERTY_AUTHORIZED_LUA_APPW, 0 );
- msi_reg_set_val_dword( props, INSTALLPROPERTY_INSTANCETYPEW, 0 );
+ msi_reg_set_val_dword(hkey, INSTALLPROPERTY_AUTHORIZED_LUA_APPW, 0);
- buffer = msi_dup_property( package, szARPProductIcon );
+ buffer = msi_dup_property(package, szARPProductIcon);
if (buffer)
{
LPWSTR path = build_icon_path(package,buffer);
- msi_reg_set_val_str( hukey, INSTALLPROPERTY_PRODUCTICONW, path );
- msi_free( path );
+ msi_reg_set_val_str(hkey, INSTALLPROPERTY_PRODUCTICONW, path);
+ msi_free(path);
+ msi_free(buffer);
}
- msi_free(buffer);
- buffer = msi_dup_property( package, szProductVersion );
+ buffer = msi_dup_property(package, szProductVersion);
if (buffer)
{
DWORD verdword = msi_version_str_to_dword(buffer);
- msi_reg_set_val_dword( hukey, INSTALLPROPERTY_VERSIONW, verdword );
+ msi_reg_set_val_dword(hkey, INSTALLPROPERTY_VERSIONW, verdword);
+ msi_free(buffer);
}
- msi_free(buffer);
- buffer = strrchrW( package->PackagePath, '\\') + 1;
- rc = MsiSourceListSetInfoW( package->ProductCode, NULL,
- package->Context, MSICODE_PRODUCT,
- INSTALLPROPERTY_PACKAGENAMEW, buffer );
- if (rc != ERROR_SUCCESS)
- goto end;
+ msi_reg_set_val_dword(hkey, szAssignment, 0);
+ msi_reg_set_val_dword(hkey, szAdvertiseFlags, 0x184);
+ msi_reg_set_val_dword(hkey, INSTALLPROPERTY_INSTANCETYPEW, 0);
+ msi_reg_set_val_str(hkey, szClients, szColon);
- rc = MsiSourceListSetInfoW( package->ProductCode, NULL,
- package->Context, MSICODE_PRODUCT,
- INSTALLPROPERTY_MEDIAPACKAGEPATHW, szEmpty );
- if (rc != ERROR_SUCCESS)
- goto end;
+ hdb = alloc_msihandle(&package->db->hdr);
+ if (!hdb)
+ return ERROR_NOT_ENOUGH_MEMORY;
- rc = MsiSourceListSetInfoW( package->ProductCode, NULL,
- package->Context, MSICODE_PRODUCT,
- INSTALLPROPERTY_DISKPROMPTW, szEmpty );
- if (rc != ERROR_SUCCESS)
- goto end;
+ r = MsiGetSummaryInformationW(hdb, NULL, 0, &suminfo);
+ MsiCloseHandle(hdb);
+ if (r != ERROR_SUCCESS)
+ goto done;
- /* FIXME: Need to write more keys to the user registry */
-
- hDb= alloc_msihandle( &package->db->hdr );
- if (!hDb) {
- rc = ERROR_NOT_ENOUGH_MEMORY;
- goto end;
- }
- rc = MsiGetSummaryInformationW(hDb, NULL, 0, &hSumInfo);
- MsiCloseHandle(hDb);
- if (rc == ERROR_SUCCESS)
+ size = MAX_PATH;
+ r = MsiSummaryInfoGetPropertyW(suminfo, PID_REVNUMBER, NULL, NULL,
+ NULL, guids, &size);
+ if (r != ERROR_SUCCESS)
+ goto done;
+
+ ptr = strchrW(guids, ';');
+ if (ptr) *ptr = 0;
+ squash_guid(guids, packcode);
+ msi_reg_set_val_str(hkey, INSTALLPROPERTY_PACKAGECODEW, packcode);
+
+done:
+ MsiCloseHandle(suminfo);
+ return ERROR_SUCCESS;
+}
+
+static UINT msi_publish_upgrade_code(MSIPACKAGE *package)
+{
+ UINT r;
+ HKEY hkey;
+ LPWSTR upgrade;
+ WCHAR squashed_pc[SQUISH_GUID_SIZE];
+
+ static const WCHAR szUpgradeCode[] =
+ {'U','p','g','r','a','d','e','C','o','d','e',0};
+
+ upgrade = msi_dup_property(package, szUpgradeCode);
+ if (!upgrade)
+ return ERROR_SUCCESS;
+
+ if (package->Context == MSIINSTALLCONTEXT_MACHINE)
{
- WCHAR guidbuffer[0x200];
- size = 0x200;
- rc = MsiSummaryInfoGetPropertyW(hSumInfo, 9, NULL, NULL, NULL,
- guidbuffer, &size);
- if (rc == ERROR_SUCCESS)
- {
- /* for now we only care about the first guid */
- LPWSTR ptr = strchrW(guidbuffer,';');
- if (ptr) *ptr = 0;
- msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGECODEW, guidbuffer );
- }
- else
- {
- ERR("Unable to query Revision_Number...\n");
- rc = ERROR_SUCCESS;
- }
- MsiCloseHandle(hSumInfo);
+ r = MSIREG_OpenClassesUpgradeCodesKey(upgrade, &hkey, TRUE);
+ if (r != ERROR_SUCCESS)
+ goto done;
}
else
{
- ERR("Unable to open Summary Information\n");
- rc = ERROR_SUCCESS;
+ r = MSIREG_OpenUserUpgradeCodesKey(upgrade, &hkey, TRUE);
+ if (r != ERROR_SUCCESS)
+ goto done;
}
- /* publish the SourceList info */
- LIST_FOR_EACH_ENTRY(info, &package->sourcelist_info, MSISOURCELISTINFO, entry)
+ squash_guid(package->ProductCode, squashed_pc);
+ msi_reg_set_val_str(hkey, squashed_pc, NULL);
+
+ RegCloseKey(hkey);
+
+done:
+ msi_free(upgrade);
+ return r;
+}
+
+static BOOL msi_check_publish(MSIPACKAGE *package)
+{
+ MSIFEATURE *feature;
+
+ LIST_FOR_EACH_ENTRY(feature, &package->features, MSIFEATURE, entry)
{
- if (!lstrcmpW(info->property, INSTALLPROPERTY_LASTUSEDSOURCEW))
- msi_set_last_used_source(package->ProductCode, NULL, info->context,
- info->options, info->value);
- else
- MsiSourceListSetInfoW(package->ProductCode, NULL,
- info->context, info->options,
- info->property, info->value);
+ if (feature->ActionRequest == INSTALLSTATE_LOCAL)
+ return TRUE;
}
- LIST_FOR_EACH_ENTRY(disk, &package->sourcelist_media, MSIMEDIADISK, entry)
+ return FALSE;
+}
+
+static BOOL msi_check_unpublish(MSIPACKAGE *package)
+{
+ MSIFEATURE *feature;
+
+ LIST_FOR_EACH_ENTRY(feature, &package->features, MSIFEATURE, entry)
{
- MsiSourceListAddMediaDiskW(package->ProductCode, NULL,
- disk->context, disk->options,
- disk->disk_id, disk->volume_label, disk->disk_prompt);
+ if (feature->ActionRequest != INSTALLSTATE_ABSENT)
+ return FALSE;
}
+ return TRUE;
+}
+
+static UINT msi_publish_patch(MSIPACKAGE *package, HKEY prodkey, HKEY hudkey)
+{
+ WCHAR patch_squashed[GUID_SIZE];
+ HKEY patches;
+ LONG res;
+ UINT r = ERROR_FUNCTION_FAILED;
+
+ static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0};
+
+ res = RegCreateKeyExW(prodkey, szPatches, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
+ &patches, NULL);
+ if (res != ERROR_SUCCESS)
+ return ERROR_FUNCTION_FAILED;
+
+ squash_guid(package->patch->patchcode, patch_squashed);
+
+ res = RegSetValueExW(patches, szPatches, 0, REG_MULTI_SZ,
+ (const BYTE *)patch_squashed,
+ (lstrlenW(patch_squashed) + 1) * sizeof(WCHAR));
+ if (res != ERROR_SUCCESS)
+ goto done;
+
+ res = RegSetValueExW(patches, patch_squashed, 0, REG_SZ,
+ (const BYTE *)package->patch->transforms,
+ (lstrlenW(package->patch->transforms) + 1) * sizeof(WCHAR));
+ if (res == ERROR_SUCCESS)
+ r = ERROR_SUCCESS;
+
+done:
+ RegCloseKey(patches);
+ return r;
+}
+
+/*
+ * 99% of the work done here is only done for
+ * advertised installs. However this is where the
+ * Icon table is processed and written out
+ * so that is what I am going to do here.
+ */
+static UINT ACTION_PublishProduct(MSIPACKAGE *package)
+{
+ UINT rc;
+ HKEY hukey=0;
+ HKEY hudkey=0;
+
+ /* FIXME: also need to publish if the product is in advertise mode */
+ if (!msi_check_publish(package))
+ return ERROR_SUCCESS;
+
+ rc = MSIREG_OpenProductKey(package->ProductCode, NULL, package->Context,
+ &hukey, TRUE);
+ if (rc != ERROR_SUCCESS)
+ goto end;
+
+ rc = MSIREG_OpenUserDataProductKey(package->ProductCode, package->Context,
+ NULL, &hudkey, TRUE);
+ if (rc != ERROR_SUCCESS)
+ goto end;
+
+ rc = msi_publish_upgrade_code(package);
+ if (rc != ERROR_SUCCESS)
+ goto end;
+
+ if (package->patch)
+ {
+ rc = msi_publish_patch(package, hukey, hudkey);
+ if (rc != ERROR_SUCCESS)
+ goto end;
+ }
+
+ rc = msi_publish_product_properties(package, hukey);
+ if (rc != ERROR_SUCCESS)
+ goto end;
+
+ rc = msi_publish_sourcelist(package, hukey);
+ if (rc != ERROR_SUCCESS)
+ goto end;
+
+ rc = msi_publish_icons(package);
+
end:
- RegCloseKey(hkey);
RegCloseKey(hukey);
RegCloseKey(hudkey);
- RegCloseKey(props);
return rc;
}
static UINT ITERATE_WriteIniValues(MSIRECORD *row, LPVOID param)
{
- MSIPACKAGE *package = (MSIPACKAGE*)param;
- LPCWSTR component,section,key,value,identifier,filename,dirproperty;
+ MSIPACKAGE *package = param;
+ LPCWSTR component, section, key, value, identifier, dirproperty;
LPWSTR deformated_section, deformated_key, deformated_value;
- LPWSTR folder, fullname = NULL;
+ LPWSTR folder, filename, fullname = NULL;
+ LPCWSTR filenameptr;
MSIRECORD * uirow;
INT action;
MSICOMPONENT *comp;
comp->Action = INSTALLSTATE_LOCAL;
identifier = MSI_RecordGetString(row,1);
- filename = MSI_RecordGetString(row,2);
dirproperty = MSI_RecordGetString(row,3);
section = MSI_RecordGetString(row,4);
key = MSI_RecordGetString(row,5);
deformat_string(package,key,&deformated_key);
deformat_string(package,value,&deformated_value);
+ filename = msi_dup_record_field(row, 2);
+ if (filename && (filenameptr = strchrW(filename, '|')))
+ filenameptr++;
+ else
+ filenameptr = filename;
+
if (dirproperty)
{
folder = resolve_folder(package, dirproperty, FALSE, FALSE, TRUE, NULL);
goto cleanup;
}
- fullname = build_directory_name(2, folder, filename);
+ fullname = build_directory_name(2, folder, filenameptr);
if (action == 0)
{
MSI_RecordSetStringW(uirow,4,deformated_value);
ui_actiondata(package,szWriteIniValues,uirow);
msiobj_release( &uirow->hdr );
+
cleanup:
+ msi_free(filename);
msi_free(fullname);
msi_free(folder);
msi_free(deformated_key);
static UINT ITERATE_SelfRegModules(MSIRECORD *row, LPVOID param)
{
- MSIPACKAGE *package = (MSIPACKAGE*)param;
+ MSIPACKAGE *package = param;
LPCWSTR filename;
LPWSTR FullName;
MSIFILE *file;
&si, &info);
if (brc)
+ {
+ CloseHandle(info.hThread);
msi_dialog_check_messages(info.hProcess);
+ CloseHandle(info.hProcess);
+ }
msi_free(FullName);
{
MSIFEATURE *feature;
UINT rc;
- HKEY hkey=0;
- HKEY hukey=0;
- HKEY userdata=0;
+ HKEY hkey;
+ HKEY userdata = NULL;
if (!msi_check_publish(package))
return ERROR_SUCCESS;
- rc = MSIREG_OpenFeaturesKey(package->ProductCode,&hkey,TRUE);
- if (rc != ERROR_SUCCESS)
- goto end;
-
- rc = MSIREG_OpenUserFeaturesKey(package->ProductCode,&hukey,TRUE);
+ rc = MSIREG_OpenFeaturesKey(package->ProductCode, package->Context,
+ &hkey, TRUE);
if (rc != ERROR_SUCCESS)
goto end;
- rc = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, &userdata, TRUE);
+ rc = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, package->Context,
+ &userdata, TRUE);
if (rc != ERROR_SUCCESS)
goto end;
strcatW(data,feature->Feature_Parent);
}
- msi_reg_set_val_str( hkey, feature->Feature, data );
msi_reg_set_val_str( userdata, feature->Feature, data );
msi_free(data);
{
static const WCHAR emptyW[] = {0};
size += sizeof(WCHAR);
- RegSetValueExW(hukey,feature->Feature,0,REG_SZ,
+ RegSetValueExW(hkey,feature->Feature,0,REG_SZ,
(LPBYTE)(feature->Feature_Parent ? feature->Feature_Parent : emptyW),size);
}
else
data[1] = 0;
if (feature->Feature_Parent)
strcpyW( &data[1], feature->Feature_Parent );
- RegSetValueExW(hukey,feature->Feature,0,REG_SZ,
+ RegSetValueExW(hkey,feature->Feature,0,REG_SZ,
(LPBYTE)data,size);
msi_free(data);
}
end:
RegCloseKey(hkey);
- RegCloseKey(hukey);
+ RegCloseKey(userdata);
return rc;
}
TRACE("unpublishing feature %s\n", debugstr_w(feature->Feature));
- r = MSIREG_OpenUserFeaturesKey(package->ProductCode, &hkey, FALSE);
+ r = MSIREG_OpenFeaturesKey(package->ProductCode, package->Context,
+ &hkey, FALSE);
if (r == ERROR_SUCCESS)
{
RegDeleteValueW(hkey, feature->Feature);
RegCloseKey(hkey);
}
- r = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, &hkey, FALSE);
+ r = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, package->Context,
+ &hkey, FALSE);
if (r == ERROR_SUCCESS)
{
RegDeleteValueW(hkey, feature->Feature);
return ERROR_SUCCESS;
}
-static BOOL msi_check_unpublish(MSIPACKAGE *package)
-{
- MSIFEATURE *feature;
-
- LIST_FOR_EACH_ENTRY(feature, &package->features, MSIFEATURE, entry)
- {
- if (feature->ActionRequest != INSTALLSTATE_ABSENT)
- return FALSE;
- }
-
- return TRUE;
-}
-
static UINT ACTION_UnpublishFeatures(MSIPACKAGE *package)
{
MSIFEATURE *feature;
static UINT msi_make_package_local( MSIPACKAGE *package, HKEY hkey )
{
WCHAR packagefile[MAX_PATH];
- HKEY props;
UINT r;
r = msi_get_local_package_name( packagefile );
msi_reg_set_val_str( hkey, INSTALLPROPERTY_LOCALPACKAGEW, packagefile );
- r = MSIREG_OpenCurrentUserInstallProps(package->ProductCode, &props, TRUE);
- if (r != ERROR_SUCCESS)
- return r;
-
- msi_reg_set_val_str(props, INSTALLPROPERTY_LOCALPACKAGEW, packagefile);
- RegCloseKey(props);
return ERROR_SUCCESS;
}
-static UINT msi_write_uninstall_property_vals( MSIPACKAGE *package, HKEY hkey )
+static UINT msi_publish_install_properties(MSIPACKAGE *package, HKEY hkey)
{
LPWSTR prop, val, key;
+ SYSTEMTIME systime;
+ DWORD size, langid;
+ WCHAR date[9];
+ LPWSTR buffer;
+
+ static const WCHAR date_fmt[] = {'%','i','%','0','2','i','%','0','2','i',0};
+ static const WCHAR szWindowsInstaller[] =
+ {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
+ static const WCHAR modpath_fmt[] =
+ {'M','s','i','E','x','e','c','.','e','x','e',' ',
+ '/','I','[','P','r','o','d','u','c','t','C','o','d','e',']',0};
+ static const WCHAR szModifyPath[] =
+ {'M','o','d','i','f','y','P','a','t','h',0};
+ static const WCHAR szUninstallString[] =
+ {'U','n','i','n','s','t','a','l','l','S','t','r','i','n','g',0};
+ static const WCHAR szEstimatedSize[] =
+ {'E','s','t','i','m','a','t','e','d','S','i','z','e',0};
+ static const WCHAR szProductLanguage[] =
+ {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
+ static const WCHAR szProductVersion[] =
+ {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
+ static const WCHAR szProductName[] =
+ {'P','r','o','d','u','c','t','N','a','m','e',0};
+ static const WCHAR szDisplayName[] =
+ {'D','i','s','p','l','a','y','N','a','m','e',0};
+ static const WCHAR szDisplayVersion[] =
+ {'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
+ static const WCHAR szManufacturer[] =
+ {'M','a','n','u','f','a','c','t','u','r','e','r',0};
+
static const LPCSTR propval[] = {
"ARPAUTHORIZEDCDFPREFIX", "AuthorizedCDFPrefix",
"ARPCONTACT", "Contact",
};
const LPCSTR *p = propval;
- while( *p )
+ while (*p)
{
- prop = strdupAtoW( *p++ );
- key = strdupAtoW( *p++ );
- val = msi_dup_property( package, prop );
- msi_reg_set_val_str( hkey, key, val );
+ prop = strdupAtoW(*p++);
+ key = strdupAtoW(*p++);
+ val = msi_dup_property(package, prop);
+ msi_reg_set_val_str(hkey, key, val);
msi_free(val);
msi_free(key);
msi_free(prop);
}
+
+ msi_reg_set_val_dword(hkey, szWindowsInstaller, 1);
+
+ size = deformat_string(package, modpath_fmt, &buffer);
+ RegSetValueExW(hkey, szModifyPath, 0, REG_EXPAND_SZ, (LPBYTE)buffer, size);
+ RegSetValueExW(hkey, szUninstallString, 0, REG_EXPAND_SZ, (LPBYTE)buffer, size);
+ msi_free(buffer);
+
+ /* FIXME: Write real Estimated Size when we have it */
+ msi_reg_set_val_dword(hkey, szEstimatedSize, 0);
+
+ buffer = msi_dup_property(package, szProductName);
+ msi_reg_set_val_str(hkey, szDisplayName, buffer);
+ msi_free(buffer);
+
+ buffer = msi_dup_property(package, cszSourceDir);
+ msi_reg_set_val_str(hkey, INSTALLPROPERTY_INSTALLSOURCEW, buffer);
+ msi_free(buffer);
+
+ buffer = msi_dup_property(package, szManufacturer);
+ msi_reg_set_val_str(hkey, INSTALLPROPERTY_PUBLISHERW, buffer);
+ msi_free(buffer);
+
+ GetLocalTime(&systime);
+ sprintfW(date, date_fmt, systime.wYear, systime.wMonth, systime.wDay);
+ msi_reg_set_val_str(hkey, INSTALLPROPERTY_INSTALLDATEW, date);
+
+ langid = msi_get_property_int(package, szProductLanguage, 0);
+ msi_reg_set_val_dword(hkey, INSTALLPROPERTY_LANGUAGEW, langid);
+
+ buffer = msi_dup_property(package, szProductVersion);
+ msi_reg_set_val_str(hkey, szDisplayVersion, buffer);
+ if (buffer)
+ {
+ DWORD verdword = msi_version_str_to_dword(buffer);
+
+ msi_reg_set_val_dword(hkey, INSTALLPROPERTY_VERSIONW, verdword);
+ msi_reg_set_val_dword(hkey, INSTALLPROPERTY_VERSIONMAJORW, verdword >> 24);
+ msi_reg_set_val_dword(hkey, INSTALLPROPERTY_VERSIONMINORW, (verdword >> 16) & 0xFF);
+ msi_free(buffer);
+ }
+
return ERROR_SUCCESS;
}
static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
{
- HKEY hkey=0;
- HKEY hudkey=0, props=0;
- LPWSTR buffer = NULL;
+ WCHAR squashed_pc[SQUISH_GUID_SIZE];
+ LPWSTR upgrade_code;
+ HKEY hkey, props;
+ HKEY upgrade;
UINT rc;
- DWORD size, langid;
- static const WCHAR szWindowsInstaller[] =
- {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
- static const WCHAR szUpgradeCode[] =
- {'U','p','g','r','a','d','e','C','o','d','e',0};
- static const WCHAR modpath_fmt[] =
- {'M','s','i','E','x','e','c','.','e','x','e',' ',
- '/','I','[','P','r','o','d','u','c','t','C','o','d','e',']',0};
- static const WCHAR szModifyPath[] =
- {'M','o','d','i','f','y','P','a','t','h',0};
- static const WCHAR szUninstallString[] =
- {'U','n','i','n','s','t','a','l','l','S','t','r','i','n','g',0};
- static const WCHAR szEstimatedSize[] =
- {'E','s','t','i','m','a','t','e','d','S','i','z','e',0};
- static const WCHAR szProductLanguage[] =
- {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
- static const WCHAR szProductVersion[] =
- {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
- static const WCHAR szProductName[] =
- {'P','r','o','d','u','c','t','N','a','m','e',0};
- static const WCHAR szDisplayName[] =
- {'D','i','s','p','l','a','y','N','a','m','e',0};
- static const WCHAR szDisplayVersion[] =
- {'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
- static const WCHAR szManufacturer[] =
- {'M','a','n','u','f','a','c','t','u','r','e','r',0};
- SYSTEMTIME systime;
- static const WCHAR date_fmt[] = {'%','i','%','0','2','i','%','0','2','i',0};
- LPWSTR upgrade_code;
- WCHAR szDate[9];
+ static const WCHAR szUpgradeCode[] = {
+ 'U','p','g','r','a','d','e','C','o','d','e',0};
/* FIXME: also need to publish if the product is in advertise mode */
if (!msi_check_publish(package))
return ERROR_SUCCESS;
- rc = MSIREG_OpenUninstallKey(package->ProductCode,&hkey,TRUE);
+ rc = MSIREG_OpenUninstallKey(package->ProductCode, &hkey, TRUE);
if (rc != ERROR_SUCCESS)
return rc;
- if (package->Context == MSIINSTALLCONTEXT_MACHINE)
- {
- rc = MSIREG_OpenLocalSystemInstallProps(package->ProductCode, &props, TRUE);
- if (rc != ERROR_SUCCESS)
- return rc;
- }
- else
- {
- rc = MSIREG_OpenCurrentUserInstallProps(package->ProductCode, &props, TRUE);
- if (rc != ERROR_SUCCESS)
- return rc;
- }
-
- /* dump all the info i can grab */
- /* FIXME: Flesh out more information */
-
- msi_write_uninstall_property_vals( package, hkey );
-
- msi_reg_set_val_dword( hkey, szWindowsInstaller, 1 );
-
- msi_make_package_local( package, hkey );
-
- /* do ModifyPath and UninstallString */
- size = deformat_string(package,modpath_fmt,&buffer);
- RegSetValueExW(hkey,szModifyPath,0,REG_EXPAND_SZ,(LPBYTE)buffer,size);
- RegSetValueExW(hkey,szUninstallString,0,REG_EXPAND_SZ,(LPBYTE)buffer,size);
- msi_free(buffer);
-
- /* FIXME: Write real Estimated Size when we have it */
- msi_reg_set_val_dword( hkey, szEstimatedSize, 0 );
+ rc = MSIREG_OpenInstallProps(package->ProductCode, package->Context,
+ NULL, &props, TRUE);
+ if (rc != ERROR_SUCCESS)
+ goto done;
- buffer = msi_dup_property( package, szProductName );
- msi_reg_set_val_str( props, szDisplayName, buffer );
- msi_free(buffer);
+ msi_make_package_local(package, props);
- buffer = msi_dup_property( package, cszSourceDir );
- msi_reg_set_val_str( props, INSTALLPROPERTY_INSTALLSOURCEW, buffer);
- msi_free(buffer);
+ rc = msi_publish_install_properties(package, hkey);
+ if (rc != ERROR_SUCCESS)
+ goto done;
- buffer = msi_dup_property( package, szManufacturer );
- msi_reg_set_val_str( props, INSTALLPROPERTY_PUBLISHERW, buffer);
- msi_free(buffer);
-
- GetLocalTime(&systime);
- sprintfW(szDate,date_fmt,systime.wYear,systime.wMonth,systime.wDay);
- msi_reg_set_val_str( hkey, INSTALLPROPERTY_INSTALLDATEW, szDate );
- msi_reg_set_val_str( props, INSTALLPROPERTY_INSTALLDATEW, szDate );
-
- langid = msi_get_property_int( package, szProductLanguage, 0 );
- msi_reg_set_val_dword( hkey, INSTALLPROPERTY_LANGUAGEW, langid );
-
- buffer = msi_dup_property( package, szProductVersion );
- msi_reg_set_val_str( props, szDisplayVersion, buffer );
- if (buffer)
- {
- DWORD verdword = msi_version_str_to_dword(buffer);
+ rc = msi_publish_install_properties(package, props);
+ if (rc != ERROR_SUCCESS)
+ goto done;
- msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONW, verdword );
- msi_reg_set_val_dword( props, INSTALLPROPERTY_VERSIONW, verdword );
- msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMAJORW, verdword>>24 );
- msi_reg_set_val_dword( props, INSTALLPROPERTY_VERSIONMAJORW, verdword>>24 );
- msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMINORW, (verdword>>16)&0x00FF );
- msi_reg_set_val_dword( props, INSTALLPROPERTY_VERSIONMINORW, (verdword>>16)&0x00FF );
- }
- msi_free(buffer);
-
- /* Handle Upgrade Codes */
- upgrade_code = msi_dup_property( package, szUpgradeCode );
+ upgrade_code = msi_dup_property(package, szUpgradeCode);
if (upgrade_code)
{
- HKEY hkey2;
- WCHAR squashed[33];
- MSIREG_OpenUpgradeCodesKey(upgrade_code, &hkey2, TRUE);
- squash_guid(package->ProductCode,squashed);
- msi_reg_set_val_str( hkey2, squashed, NULL );
- RegCloseKey(hkey2);
- MSIREG_OpenUserUpgradeCodesKey(upgrade_code, &hkey2, TRUE);
- squash_guid(package->ProductCode,squashed);
- msi_reg_set_val_str( hkey2, squashed, NULL );
- RegCloseKey(hkey2);
-
+ MSIREG_OpenUpgradeCodesKey(upgrade_code, &upgrade, TRUE);
+ squash_guid(package->ProductCode, squashed_pc);
+ msi_reg_set_val_str(upgrade, squashed_pc, NULL);
+ RegCloseKey(upgrade);
msi_free(upgrade_code);
}
+done:
RegCloseKey(hkey);
- rc = MSIREG_OpenUserDataProductKey(package->ProductCode, &hudkey, TRUE);
- if (rc != ERROR_SUCCESS)
- return rc;
-
- RegCloseKey(hudkey);
-
- msi_reg_set_val_dword( props, szWindowsInstaller, 1 );
- RegCloseKey(props);
-
return ERROR_SUCCESS;
}
static UINT msi_unpublish_product(MSIPACKAGE *package)
{
+ LPWSTR upgrade;
LPWSTR remove = NULL;
LPWSTR *features = NULL;
BOOL full_uninstall = TRUE;
static const WCHAR szRemove[] = {'R','E','M','O','V','E',0};
static const WCHAR szAll[] = {'A','L','L',0};
+ static const WCHAR szUpgradeCode[] =
+ {'U','p','g','r','a','d','e','C','o','d','e',0};
remove = msi_dup_property(package, szRemove);
if (!remove)
goto done;
MSIREG_DeleteProductKey(package->ProductCode);
- MSIREG_DeleteUserProductKey(package->ProductCode);
MSIREG_DeleteUserDataProductKey(package->ProductCode);
- MSIREG_DeleteUserFeaturesKey(package->ProductCode);
MSIREG_DeleteUninstallKey(package->ProductCode);
+ if (package->Context == MSIINSTALLCONTEXT_MACHINE)
+ {
+ MSIREG_DeleteLocalClassesProductKey(package->ProductCode);
+ MSIREG_DeleteLocalClassesFeaturesKey(package->ProductCode);
+ }
+ else
+ {
+ MSIREG_DeleteUserProductKey(package->ProductCode);
+ MSIREG_DeleteUserFeaturesKey(package->ProductCode);
+ }
+
+ upgrade = msi_dup_property(package, szUpgradeCode);
+ if (upgrade)
+ {
+ MSIREG_DeleteUserUpgradeCodesKey(upgrade);
+ msi_free(upgrade);
+ }
+
done:
msi_free(remove);
msi_free(features);
if (!productid)
return ERROR_SUCCESS;
- rc = MSIREG_OpenCurrentUserInstallProps(package->ProductCode, &hkey, TRUE);
+ rc = MSIREG_OpenInstallProps(package->ProductCode, package->Context,
+ NULL, &hkey, TRUE);
if (rc != ERROR_SUCCESS)
goto end;
static UINT ITERATE_PublishComponent(MSIRECORD *rec, LPVOID param)
{
- MSIPACKAGE *package = (MSIPACKAGE*)param;
+ MSIPACKAGE *package = param;
LPCWSTR compgroupid=NULL;
LPCWSTR feature=NULL;
LPCWSTR text = NULL;
static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
{
- MSIPACKAGE *package = (MSIPACKAGE*)param;
+ MSIPACKAGE *package = param;
MSIRECORD *row;
MSIFILE *file;
SC_HANDLE hscm, service = NULL;
static UINT ITERATE_StartService(MSIRECORD *rec, LPVOID param)
{
- MSIPACKAGE *package = (MSIPACKAGE *)param;
+ MSIPACKAGE *package = param;
MSICOMPONENT *comp;
SC_HANDLE scm, service = NULL;
LPCWSTR name, *vector = NULL;
static UINT ITERATE_StopService(MSIRECORD *rec, LPVOID param)
{
- MSIPACKAGE *package = (MSIPACKAGE *)param;
+ MSIPACKAGE *package = param;
MSICOMPONENT *comp;
SERVICE_STATUS status;
SERVICE_STATUS_PROCESS ssp;
static UINT ITERATE_InstallODBCDriver( MSIRECORD *rec, LPVOID param )
{
- MSIPACKAGE *package = (MSIPACKAGE*)param;
+ MSIPACKAGE *package = param;
LPWSTR driver, driver_path, ptr;
WCHAR outpath[MAX_PATH];
MSIFILE *driver_file, *setup_file;
static UINT ITERATE_InstallODBCTranslator( MSIRECORD *rec, LPVOID param )
{
- MSIPACKAGE *package = (MSIPACKAGE*)param;
+ MSIPACKAGE *package = param;
LPWSTR translator, translator_path, ptr;
WCHAR outpath[MAX_PATH];
MSIFILE *translator_file, *setup_file;
}
}
- if (!*flags ||
- check_flag_combo(*flags, ENV_ACT_SETALWAYS | ENV_ACT_SETABSENT) ||
+ if (check_flag_combo(*flags, ENV_ACT_SETALWAYS | ENV_ACT_SETABSENT) ||
check_flag_combo(*flags, ENV_ACT_REMOVEMATCH | ENV_ACT_SETABSENT) ||
check_flag_combo(*flags, ENV_ACT_REMOVEMATCH | ENV_ACT_SETALWAYS) ||
check_flag_combo(*flags, ENV_ACT_SETABSENT | ENV_MOD_MASK))
return ERROR_FUNCTION_FAILED;
}
+ if (!*flags)
+ *flags = ENV_ACT_SETALWAYS | ENV_ACT_REMOVE;
+
return ERROR_SUCCESS;
}
name = MSI_RecordGetString(rec, 2);
value = MSI_RecordGetString(rec, 3);
+ TRACE("name %s value %s\n", debugstr_w(name), debugstr_w(value));
+
res = env_set_flags(&name, &value, &flags);
if (res != ERROR_SUCCESS)
goto done;
{
file = LIST_ENTRY(list_head(&files.entry), FILE_LIST, entry);
- msi_move_file((LPCWSTR)file->source, (LPCWSTR)file->dest, options);
+ msi_move_file(file->source, file->dest, options);
list_remove(&file->entry);
free_file_entry(file);
{
MSIPACKAGE *package = param;
MSICOMPONENT *comp;
- LPCWSTR sourcename, destname;
+ LPCWSTR sourcename;
+ LPWSTR destname = NULL;
LPWSTR sourcedir = NULL, destdir = NULL;
LPWSTR source = NULL, dest = NULL;
int options;
}
sourcename = MSI_RecordGetString(rec, 3);
- destname = MSI_RecordGetString(rec, 4);
options = MSI_RecordGetInteger(rec, 7);
sourcedir = msi_dup_property(package, MSI_RecordGetString(rec, 5));
wildcards = strchrW(source, '*') || strchrW(source, '?');
- if (!destname && !wildcards)
+ if (MSI_RecordIsNull(rec, 4))
{
- destname = strdupW(sourcename);
- if (!destname)
- goto done;
+ if (!wildcards)
+ {
+ destname = strdupW(sourcename);
+ if (!destname)
+ goto done;
+ }
+ }
+ else
+ {
+ destname = strdupW(MSI_RecordGetString(rec, 4));
+ if (destname)
+ reduce_to_longfilename(destname);
}
size = 0;
done:
msi_free(sourcedir);
msi_free(destdir);
+ msi_free(destname);
msi_free(source);
msi_free(dest);
return rc;
}
+typedef struct tagMSIASSEMBLY
+{
+ struct list entry;
+ MSICOMPONENT *component;
+ MSIFEATURE *feature;
+ MSIFILE *file;
+ LPWSTR manifest;
+ LPWSTR application;
+ DWORD attributes;
+ BOOL installed;
+} MSIASSEMBLY;
+
static HRESULT (WINAPI *pCreateAssemblyCache)(IAssemblyCache **ppAsmCache,
DWORD dwReserved);
static HRESULT (WINAPI *pLoadLibraryShim)(LPCWSTR szDllName, LPCWSTR szVersion,
return TRUE;
}
-static UINT install_assembly(LPWSTR path)
+static UINT install_assembly(MSIPACKAGE *package, MSIASSEMBLY *assembly,
+ LPWSTR path)
{
IAssemblyCache *cache;
HRESULT hr;
UINT r = ERROR_FUNCTION_FAILED;
- if (!init_functionpointers() || !pCreateAssemblyCache)
- return ERROR_FUNCTION_FAILED;
+ TRACE("installing assembly: %s\n", debugstr_w(path));
+
+ if (assembly->feature)
+ msi_feature_set_state(package, assembly->feature, INSTALLSTATE_LOCAL);
+
+ if (assembly->manifest)
+ FIXME("Manifest unhandled\n");
+
+ if (assembly->application)
+ {
+ FIXME("Assembly should be privately installed\n");
+ return ERROR_SUCCESS;
+ }
+
+ if (assembly->attributes == msidbAssemblyAttributesWin32)
+ {
+ FIXME("Win32 assemblies not handled\n");
+ return ERROR_SUCCESS;
+ }
hr = pCreateAssemblyCache(&cache, 0);
if (FAILED(hr))
return r;
}
-static UINT ITERATE_PublishAssembly( MSIRECORD *rec, LPVOID param )
+typedef struct tagASSEMBLY_LIST
{
- MSIPACKAGE *package = param;
- MSICOMPONENT *comp;
- MSIFEATURE *feature;
- MSIFILE *file;
- WCHAR path[MAX_PATH];
- LPCWSTR app;
- DWORD attr;
- UINT r;
+ MSIPACKAGE *package;
+ IAssemblyCache *cache;
+ struct list *assemblies;
+} ASSEMBLY_LIST;
+
+typedef struct tagASSEMBLY_NAME
+{
+ LPWSTR name;
+ LPWSTR version;
+ LPWSTR culture;
+ LPWSTR pubkeytoken;
+} ASSEMBLY_NAME;
+
+static UINT parse_assembly_name(MSIRECORD *rec, LPVOID param)
+{
+ ASSEMBLY_NAME *asmname = param;
+ LPCWSTR name = MSI_RecordGetString(rec, 2);
+ LPWSTR val = msi_dup_record_field(rec, 3);
+
+ static const WCHAR Name[] = {'N','a','m','e',0};
+ static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
+ static const WCHAR Culture[] = {'C','u','l','t','u','r','e',0};
+ static const WCHAR PublicKeyToken[] = {
+ 'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
+
+ if (!strcmpiW(name, Name))
+ asmname->name = val;
+ else if (!strcmpiW(name, Version))
+ asmname->version = val;
+ else if (!strcmpiW(name, Culture))
+ asmname->culture = val;
+ else if (!strcmpiW(name, PublicKeyToken))
+ asmname->pubkeytoken = val;
+ else
+ msi_free(val);
- comp = get_loaded_component(package, MSI_RecordGetString(rec, 1));
- if (!comp || !comp->Enabled ||
- !(comp->Action & (INSTALLSTATE_LOCAL | INSTALLSTATE_SOURCE)))
+ return ERROR_SUCCESS;
+}
+
+static void append_str(LPWSTR *str, DWORD *size, LPCWSTR append)
+{
+ if (!*str)
{
- ERR("Component not set for install, not publishing assembly\n");
+ *size = lstrlenW(append) + 1;
+ *str = msi_alloc((*size) * sizeof(WCHAR));
+ lstrcpyW(*str, append);
+ return;
+ }
+
+ (*size) += lstrlenW(append);
+ *str = msi_realloc(*str, (*size) * sizeof(WCHAR));
+ lstrcatW(*str, append);
+}
+
+static BOOL check_assembly_installed(MSIDATABASE *db, IAssemblyCache *cache,
+ MSICOMPONENT *comp)
+{
+ ASSEMBLY_INFO asminfo;
+ ASSEMBLY_NAME name;
+ MSIQUERY *view;
+ LPWSTR disp;
+ DWORD size;
+ BOOL found;
+ UINT r;
+
+ static const WCHAR separator[] = {',',' ',0};
+ static const WCHAR Version[] = {'V','e','r','s','i','o','n','=',0};
+ static const WCHAR Culture[] = {'C','u','l','t','u','r','e','=',0};
+ static const WCHAR PublicKeyToken[] = {
+ 'P','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
+ static const WCHAR query[] = {
+ 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+ '`','M','s','i','A','s','s','e','m','b','l','y','N','a','m','e','`',' ',
+ 'W','H','E','R','E',' ','`','C','o','m','p','o','n','e','n','t','_','`',
+ '=','\'','%','s','\'',0};
+
+ disp = NULL;
+ found = FALSE;
+ ZeroMemory(&name, sizeof(ASSEMBLY_NAME));
+ ZeroMemory(&asminfo, sizeof(ASSEMBLY_INFO));
+
+ r = MSI_OpenQuery(db, &view, query, comp->Component);
+ if (r != ERROR_SUCCESS)
return ERROR_SUCCESS;
+
+ MSI_IterateRecords(view, NULL, parse_assembly_name, &name);
+ msiobj_release(&view->hdr);
+
+ if (!name.name)
+ {
+ ERR("No assembly name specified!\n");
+ goto done;
}
- feature = find_feature_by_name(package, MSI_RecordGetString(rec, 2));
- if (feature)
- msi_feature_set_state(feature, INSTALLSTATE_LOCAL);
+ append_str(&disp, &size, name.name);
- if (MSI_RecordGetString(rec, 3))
- FIXME("Manifest unhandled\n");
+ if (name.version)
+ {
+ append_str(&disp, &size, separator);
+ append_str(&disp, &size, Version);
+ append_str(&disp, &size, name.version);
+ }
- app = MSI_RecordGetString(rec, 4);
- if (app)
+ if (name.culture)
{
- FIXME("Assembly should be privately installed\n");
- return ERROR_SUCCESS;
+ append_str(&disp, &size, separator);
+ append_str(&disp, &size, Culture);
+ append_str(&disp, &size, name.culture);
}
- attr = MSI_RecordGetInteger(rec, 5);
- if (attr == msidbAssemblyAttributesWin32)
+ if (name.pubkeytoken)
{
- FIXME("Win32 assemblies not handled\n");
+ append_str(&disp, &size, separator);
+ append_str(&disp, &size, PublicKeyToken);
+ append_str(&disp, &size, name.pubkeytoken);
+ }
+
+ asminfo.cbAssemblyInfo = sizeof(ASSEMBLY_INFO);
+ IAssemblyCache_QueryAssemblyInfo(cache, QUERYASMINFO_FLAG_VALIDATE,
+ disp, &asminfo);
+ found = (asminfo.dwAssemblyFlags == ASSEMBLYINFO_FLAG_INSTALLED);
+
+done:
+ msi_free(disp);
+ msi_free(name.name);
+ msi_free(name.version);
+ msi_free(name.culture);
+ msi_free(name.pubkeytoken);
+
+ return found;
+}
+
+static UINT load_assembly(MSIRECORD *rec, LPVOID param)
+{
+ ASSEMBLY_LIST *list = param;
+ MSIASSEMBLY *assembly;
+
+ assembly = msi_alloc_zero(sizeof(MSIASSEMBLY));
+ if (!assembly)
+ return ERROR_OUTOFMEMORY;
+
+ assembly->component = get_loaded_component(list->package, MSI_RecordGetString(rec, 1));
+
+ if (!assembly->component || !assembly->component->Enabled ||
+ !(assembly->component->Action & (INSTALLSTATE_LOCAL | INSTALLSTATE_SOURCE)))
+ {
+ TRACE("Component not set for install, not publishing assembly\n");
+ msi_free(assembly);
return ERROR_SUCCESS;
}
- /* FIXME: extract all files belonging to this component */
- file = msi_find_file(package, comp->KeyPath);
+ assembly->feature = find_feature_by_name(list->package, MSI_RecordGetString(rec, 2));
+ assembly->file = msi_find_file(list->package, assembly->component->KeyPath);
+
+ if (!assembly->file)
+ {
+ ERR("File %s not found\n", debugstr_w(assembly->component->KeyPath));
+ return ERROR_FUNCTION_FAILED;
+ }
- GetTempPathW(MAX_PATH, path);
+ assembly->manifest = strdupW(MSI_RecordGetString(rec, 3));
+ assembly->application = strdupW(MSI_RecordGetString(rec, 4));
+ assembly->attributes = MSI_RecordGetInteger(rec, 5);
- if (file->IsCompressed)
+ if (assembly->application)
{
- r = msi_extract_file(package, file, path);
- if (r != ERROR_SUCCESS)
+ WCHAR version[24];
+ DWORD size = sizeof(version)/sizeof(WCHAR);
+
+ /* FIXME: we should probably check the manifest file here */
+
+ if (!MsiGetFileVersionW(assembly->file->TargetPath, version, &size, NULL, NULL) &&
+ (!assembly->file->Version || strcmpW(version, assembly->file->Version) >= 0))
{
- ERR("Failed to extract temporary assembly\n");
- return r;
+ assembly->installed = TRUE;
}
-
- PathAddBackslashW(path);
- lstrcatW(path, file->FileName);
}
else
+ assembly->installed = check_assembly_installed(list->package->db,
+ list->cache,
+ assembly->component);
+
+ list_add_head(list->assemblies, &assembly->entry);
+ return ERROR_SUCCESS;
+}
+
+static UINT load_assemblies(MSIPACKAGE *package, struct list *assemblies)
+{
+ IAssemblyCache *cache = NULL;
+ ASSEMBLY_LIST list;
+ MSIQUERY *view;
+ HRESULT hr;
+ UINT r;
+
+ static const WCHAR query[] =
+ {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+ '`','M','s','i','A','s','s','e','m','b','l','y','`',0};
+
+ r = MSI_DatabaseOpenViewW(package->db, query, &view);
+ if (r != ERROR_SUCCESS)
+ return ERROR_SUCCESS;
+
+ hr = pCreateAssemblyCache(&cache, 0);
+ if (FAILED(hr))
+ return ERROR_FUNCTION_FAILED;
+
+ list.package = package;
+ list.cache = cache;
+ list.assemblies = assemblies;
+
+ r = MSI_IterateRecords(view, NULL, load_assembly, &list);
+ msiobj_release(&view->hdr);
+
+ IAssemblyCache_Release(cache);
+
+ return r;
+}
+
+static void free_assemblies(struct list *assemblies)
+{
+ struct list *item, *cursor;
+
+ LIST_FOR_EACH_SAFE(item, cursor, assemblies)
{
- PathAddBackslashW(path);
- lstrcatW(path, file->FileName);
+ MSIASSEMBLY *assembly = LIST_ENTRY(item, MSIASSEMBLY, entry);
- if (!CopyFileW(file->SourcePath, path, FALSE))
+ list_remove(&assembly->entry);
+ msi_free(assembly->application);
+ msi_free(assembly->manifest);
+ msi_free(assembly);
+ }
+}
+
+static BOOL find_assembly(struct list *assemblies, LPCWSTR file, MSIASSEMBLY **out)
+{
+ MSIASSEMBLY *assembly;
+
+ LIST_FOR_EACH_ENTRY(assembly, assemblies, MSIASSEMBLY, entry)
+ {
+ if (!lstrcmpW(assembly->file->File, file))
{
- ERR("Failed to copy temporary assembly: %d\n", GetLastError());
- return ERROR_FUNCTION_FAILED;
+ *out = assembly;
+ return TRUE;
}
}
- r = install_assembly(path);
- if (r != ERROR_SUCCESS)
- ERR("Failed to install assembly\n");
+ return FALSE;
+}
+
+static BOOL installassembly_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
+ LPWSTR *path, DWORD *attrs, PVOID user)
+{
+ MSIASSEMBLY *assembly;
+ WCHAR temppath[MAX_PATH];
+ struct list *assemblies = user;
+ UINT r;
- /* FIXME: write Installer assembly reg values */
+ if (!find_assembly(assemblies, file, &assembly))
+ return FALSE;
- return r;
+ GetTempPathW(MAX_PATH, temppath);
+ PathAddBackslashW(temppath);
+ lstrcatW(temppath, assembly->file->FileName);
+
+ if (action == MSICABEXTRACT_BEGINEXTRACT)
+ {
+ if (assembly->installed)
+ return FALSE;
+
+ *path = strdupW(temppath);
+ *attrs = assembly->file->Attributes;
+ }
+ else if (action == MSICABEXTRACT_FILEEXTRACTED)
+ {
+ assembly->installed = TRUE;
+
+ r = install_assembly(package, assembly, temppath);
+ if (r != ERROR_SUCCESS)
+ ERR("Failed to install assembly\n");
+ }
+
+ return TRUE;
}
static UINT ACTION_MsiPublishAssemblies( MSIPACKAGE *package )
{
- UINT rc;
- MSIQUERY *view;
+ UINT r;
+ struct list assemblies = LIST_INIT(assemblies);
+ MSIASSEMBLY *assembly;
+ MSIMEDIAINFO *mi;
- static const WCHAR ExecSeqQuery[] =
- {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
- '`','M','s','i','A','s','s','e','m','b','l','y','`',0};
+ if (!init_functionpointers() || !pCreateAssemblyCache)
+ return ERROR_FUNCTION_FAILED;
- rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
- if (rc != ERROR_SUCCESS)
- return ERROR_SUCCESS;
+ r = load_assemblies(package, &assemblies);
+ if (r != ERROR_SUCCESS)
+ goto done;
- rc = MSI_IterateRecords(view, NULL, ITERATE_PublishAssembly, package);
- msiobj_release(&view->hdr);
+ if (list_empty(&assemblies))
+ goto done;
- return rc;
+ mi = msi_alloc_zero(sizeof(MSIMEDIAINFO));
+ if (!mi)
+ {
+ r = ERROR_OUTOFMEMORY;
+ goto done;
+ }
+
+ LIST_FOR_EACH_ENTRY(assembly, &assemblies, MSIASSEMBLY, entry)
+ {
+ if (assembly->installed && !mi->is_continuous)
+ continue;
+
+ if (assembly->file->Sequence > mi->last_sequence || mi->is_continuous ||
+ (assembly->file->IsCompressed && !mi->is_extracted))
+ {
+ MSICABDATA data;
+
+ r = ready_media(package, assembly->file, mi);
+ if (r != ERROR_SUCCESS)
+ {
+ ERR("Failed to ready media\n");
+ break;
+ }
+
+ data.mi = mi;
+ data.package = package;
+ data.cb = installassembly_cb;
+ data.user = &assemblies;
+
+ if (assembly->file->IsCompressed &&
+ !msi_cabextract(package, mi, &data))
+ {
+ ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
+ r = ERROR_FUNCTION_FAILED;
+ break;
+ }
+ }
+
+ if (!assembly->file->IsCompressed)
+ {
+ LPWSTR source = resolve_file_source(package, assembly->file);
+
+ r = install_assembly(package, assembly, source);
+ if (r != ERROR_SUCCESS)
+ ERR("Failed to install assembly\n");
+
+ msi_free(source);
+ }
+
+ /* FIXME: write Installer assembly reg values */
+ }
+
+done:
+ free_assemblies(&assemblies);
+ return r;
}
static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,