cls->Feature = msi_get_loaded_feature(package, buffer);
cls->Attributes = MSI_RecordGetInteger(row,13);
-
+ cls->action = INSTALLSTATE_UNKNOWN;
return cls;
}
buffer = MSI_RecordGetString(row,5);
ext->Feature = msi_get_loaded_feature( package, buffer );
-
+ ext->action = INSTALLSTATE_UNKNOWN;
return ext;
}
return load_all_mimes( package );
}
-static void mark_progid_for_install( MSIPACKAGE* package, MSIPROGID *progid )
-{
- MSIPROGID *child;
-
- if (!progid)
- return;
-
- if (progid->InstallMe)
- return;
-
- progid->InstallMe = TRUE;
-
- /* all children if this is a parent also install */
- LIST_FOR_EACH_ENTRY( child, &package->progids, MSIPROGID, entry )
- {
- if (child->Parent == progid)
- mark_progid_for_install( package, child );
- }
-}
-
-static void mark_progid_for_uninstall( MSIPACKAGE *package, MSIPROGID *progid )
-{
- MSIPROGID *child;
-
- if (!progid)
- return;
-
- if (!progid->InstallMe)
- return;
-
- progid->InstallMe = FALSE;
-
- LIST_FOR_EACH_ENTRY( child, &package->progids, MSIPROGID, entry )
- {
- if (child->Parent == progid)
- mark_progid_for_uninstall( package, child );
- }
-}
-
-static void mark_mime_for_install( MSIMIME *mime )
-{
- if (!mime)
- return;
- mime->InstallMe = TRUE;
-}
-
-static void mark_mime_for_uninstall( MSIMIME *mime )
-{
- if (!mime)
- return;
- mime->InstallMe = FALSE;
-}
-
static UINT register_appid(const MSIAPPID *appid, LPCWSTR app )
{
static const WCHAR szRemoteServerName[] =
}
TRACE("Registering class %s (%p)\n", debugstr_w(cls->clsid), cls);
- cls->Installed = TRUE;
- mark_progid_for_install( package, cls->ProgID );
+ cls->action = INSTALLSTATE_LOCAL;
RegCreateKeyW( hkey, cls->clsid, &hkey2 );
}
TRACE("Unregistering class %s (%p)\n", debugstr_w(cls->clsid), cls);
- cls->Installed = FALSE;
- mark_progid_for_uninstall( package, cls->ProgID );
+ cls->action = INSTALLSTATE_ABSENT;
res = RegDeleteTreeW( hkey, cls->clsid );
if (res != ERROR_SUCCESS)
return rc;
}
+static const MSICLASS *get_progid_class( const MSIPROGID *progid )
+{
+ while (progid)
+ {
+ if (progid->Parent) progid = progid->Parent;
+ if (progid->Class) return progid->Class;
+ if (!progid->Parent || progid->Parent == progid) break;
+ }
+ return NULL;
+}
+
+static BOOL has_class_installed( const MSIPROGID *progid )
+{
+ const MSICLASS *class = get_progid_class( progid );
+ if (!class || !class->ProgID) return FALSE;
+ return (class->action == INSTALLSTATE_LOCAL);
+}
+
+static BOOL has_one_extension_installed( const MSIPACKAGE *package, const MSIPROGID *progid )
+{
+ const MSIEXTENSION *extension;
+ LIST_FOR_EACH_ENTRY( extension, &package->extensions, MSIEXTENSION, entry )
+ {
+ if (extension->ProgID == progid && !list_empty( &extension->verbs ) &&
+ extension->action == INSTALLSTATE_LOCAL) return TRUE;
+ }
+ return FALSE;
+}
+
UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
{
MSIPROGID *progid;
LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
{
- /* check if this progid is to be installed */
- if (progid->Class && progid->Class->Installed)
- progid->InstallMe = TRUE;
-
- if (!progid->InstallMe)
+ if (!has_class_installed( progid ) && !has_one_extension_installed( package, progid ))
{
- TRACE("progid %s not scheduled to be installed\n",
- debugstr_w(progid->ProgID));
+ TRACE("progid %s not scheduled to be installed\n", debugstr_w(progid->ProgID));
continue;
}
-
TRACE("Registering progid %s\n", debugstr_w(progid->ProgID));
register_progid( progid );
return ERROR_SUCCESS;
}
+static BOOL has_class_removed( const MSIPROGID *progid )
+{
+ const MSICLASS *class = get_progid_class( progid );
+ if (!class || !class->ProgID) return FALSE;
+ return (class->action == INSTALLSTATE_ABSENT);
+}
+
+static BOOL has_extensions( const MSIPACKAGE *package, const MSIPROGID *progid )
+{
+ const MSIEXTENSION *extension;
+ LIST_FOR_EACH_ENTRY( extension, &package->extensions, MSIEXTENSION, entry )
+ {
+ if (extension->ProgID == progid && !list_empty( &extension->verbs )) return TRUE;
+ }
+ return FALSE;
+}
+
+static BOOL has_all_extensions_removed( const MSIPACKAGE *package, const MSIPROGID *progid )
+{
+ BOOL ret = FALSE;
+ const MSIEXTENSION *extension;
+ LIST_FOR_EACH_ENTRY( extension, &package->extensions, MSIEXTENSION, entry )
+ {
+ if (extension->ProgID == progid && !list_empty( &extension->verbs ) &&
+ extension->action == INSTALLSTATE_ABSENT) ret = TRUE;
+ else ret = FALSE;
+ }
+ return ret;
+}
+
UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package )
{
MSIPROGID *progid;
LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
{
- /* check if this progid is to be removed */
- if (progid->Class && !progid->Class->Installed)
- progid->InstallMe = FALSE;
-
- if (progid->InstallMe)
+ if (!has_class_removed( progid ) ||
+ (has_extensions( package, progid ) && !has_all_extensions_removed( package, progid )))
{
TRACE("progid %s not scheduled to be removed\n", debugstr_w(progid->ProgID));
continue;
}
-
TRACE("Unregistering progid %s\n", debugstr_w(progid->ProgID));
res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid->ProgID );
}
TRACE("Registering extension %s (%p)\n", debugstr_w(ext->Extension), ext);
- ext->Installed = TRUE;
-
- /* this is only registered if the extension has at least 1 verb
- * according to MSDN
- */
- if (ext->ProgID && !list_empty( &ext->verbs ) )
- mark_progid_for_install( package, ext->ProgID );
-
- mark_mime_for_install(ext->Mime);
+ ext->action = INSTALLSTATE_LOCAL;
extension = msi_alloc( (strlenW( ext->Extension ) + 2) * sizeof(WCHAR) );
if (extension)
}
TRACE("Unregistering extension %s\n", debugstr_w(ext->Extension));
- ext->Installed = FALSE;
-
- if (ext->ProgID && !list_empty( &ext->verbs ))
- mark_progid_for_uninstall( package, ext->ProgID );
-
- mark_mime_for_uninstall( ext->Mime );
+ ext->action = INSTALLSTATE_ABSENT;
extension = msi_alloc( (strlenW( ext->Extension ) + 2) * sizeof(WCHAR) );
if (extension)
* check if the MIME is to be installed. Either as requested by an
* extension or Class
*/
- mt->InstallMe = (mt->InstallMe ||
- (mt->Class && mt->Class->Installed) ||
- (mt->Extension && mt->Extension->Installed));
-
- if (!mt->InstallMe)
+ if ((!mt->Class || mt->Class->action != INSTALLSTATE_LOCAL) &&
+ mt->Extension->action != INSTALLSTATE_LOCAL)
{
TRACE("MIME %s not scheduled to be installed\n", debugstr_w(mt->ContentType));
continue;
LONG res;
LPWSTR mime_key;
- mime->InstallMe = (mime->InstallMe ||
- (mime->Class && mime->Class->Installed) ||
- (mime->Extension && mime->Extension->Installed));
-
- if (mime->InstallMe)
+ if ((!mime->Class || mime->Class->action != INSTALLSTATE_ABSENT) &&
+ mime->Extension->action != INSTALLSTATE_ABSENT)
{
TRACE("MIME %s not scheduled to be removed\n", debugstr_w(mime->ContentType));
continue;