[MSI]
authorChristoph von Wittich <christoph_vw@reactos.org>
Mon, 1 Mar 2010 12:01:30 +0000 (12:01 +0000)
committerChristoph von Wittich <christoph_vw@reactos.org>
Mon, 1 Mar 2010 12:01:30 +0000 (12:01 +0000)
sync msi to wine 1.1.39

svn path=/trunk/; revision=45738

19 files changed:
reactos/dll/win32/msi/action.c
reactos/dll/win32/msi/classes.c
reactos/dll/win32/msi/database.c
reactos/dll/win32/msi/events.c
reactos/dll/win32/msi/files.c
reactos/dll/win32/msi/font.c
reactos/dll/win32/msi/helpers.c
reactos/dll/win32/msi/install.c
reactos/dll/win32/msi/msi.c
reactos/dll/win32/msi/msi.spec
reactos/dll/win32/msi/msi_It.rc
reactos/dll/win32/msi/msipriv.h
reactos/dll/win32/msi/msiserver.idl
reactos/dll/win32/msi/package.c
reactos/dll/win32/msi/streams.c
reactos/dll/win32/msi/suminfo.c
reactos/dll/win32/msi/table.c
reactos/dll/win32/msi/tokenize.c
reactos/include/psdk/msi.h

index d94d842..20929c6 100644 (file)
@@ -886,10 +886,24 @@ static BOOL ACTION_HandleCustomAction( MSIPACKAGE* package, LPCWSTR action,
 static UINT ITERATE_CreateFolders(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE *package = param;
 static UINT ITERATE_CreateFolders(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE *package = param;
-    LPCWSTR dir;
+    LPCWSTR dir, component;
     LPWSTR full_path;
     MSIRECORD *uirow;
     MSIFOLDER *folder;
     LPWSTR full_path;
     MSIRECORD *uirow;
     MSIFOLDER *folder;
+    MSICOMPONENT *comp;
+
+    component = MSI_RecordGetString(row, 2);
+    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;
 
     dir = MSI_RecordGetString(row,1);
     if (!dir)
 
     dir = MSI_RecordGetString(row,1);
     if (!dir)
@@ -951,7 +965,7 @@ UINT msi_create_component_directories( MSIPACKAGE *package )
     /* create all the folders required by the components are going to install */
     LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
     {
     /* create all the folders required by the components are going to install */
     LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
     {
-        if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
+        if (comp->ActionRequest != INSTALLSTATE_LOCAL)
             continue;
         msi_create_directory( package, comp->Directory );
     }
             continue;
         msi_create_directory( package, comp->Directory );
     }
@@ -983,10 +997,24 @@ static UINT ACTION_CreateFolders(MSIPACKAGE *package)
 static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param )
 {
     MSIPACKAGE *package = param;
 static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param )
 {
     MSIPACKAGE *package = param;
-    LPCWSTR dir;
+    LPCWSTR dir, component;
     LPWSTR full_path;
     MSIRECORD *uirow;
     MSIFOLDER *folder;
     LPWSTR full_path;
     MSIRECORD *uirow;
     MSIFOLDER *folder;
+    MSICOMPONENT *comp;
+
+    component = MSI_RecordGetString(row, 2);
+    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;
 
     dir = MSI_RecordGetString( row, 1 );
     if (!dir)
 
     dir = MSI_RecordGetString( row, 1 );
     if (!dir)
@@ -2231,16 +2259,12 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
     if (!comp)
         return ERROR_SUCCESS;
 
     if (!comp)
         return ERROR_SUCCESS;
 
-    if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
+    if (comp->ActionRequest != INSTALLSTATE_LOCAL)
     {
     {
-        TRACE("Skipping write due to disabled component %s\n",
-                        debugstr_w(component));
-
+        TRACE("Component not scheduled for installation: %s\n", debugstr_w(component));
         comp->Action = comp->Installed;
         comp->Action = comp->Installed;
-
         return ERROR_SUCCESS;
     }
         return ERROR_SUCCESS;
     }
-
     comp->Action = INSTALLSTATE_LOCAL;
 
     name = MSI_RecordGetString(row, 4);
     comp->Action = INSTALLSTATE_LOCAL;
 
     name = MSI_RecordGetString(row, 4);
@@ -2623,7 +2647,7 @@ static void ACTION_RefCountComponent( MSIPACKAGE* package, MSICOMPONENT *comp )
     {
         ComponentList *cl;
 
     {
         ComponentList *cl;
 
-        if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL ))
+        if (feature->ActionRequest != INSTALLSTATE_LOCAL)
             continue;
 
         LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
             continue;
 
         LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
@@ -2638,7 +2662,7 @@ static void ACTION_RefCountComponent( MSIPACKAGE* package, MSICOMPONENT *comp )
     {
         ComponentList *cl;
 
     {
         ComponentList *cl;
 
-        if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ABSENT ))
+        if (feature->ActionRequest != INSTALLSTATE_ABSENT)
             continue;
 
         LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
             continue;
 
         LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
@@ -2704,8 +2728,8 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
                             debugstr_w(comp->FullKeypath),
                             comp->RefCount);
 
                             debugstr_w(comp->FullKeypath),
                             comp->RefCount);
 
-        if (ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL) ||
-            ACTION_VerifyComponentForAction( comp, INSTALLSTATE_SOURCE))
+        if (comp->ActionRequest == INSTALLSTATE_LOCAL ||
+            comp->ActionRequest == INSTALLSTATE_SOURCE)
         {
             if (!comp->FullKeypath)
                 continue;
         {
             if (!comp->FullKeypath)
                 continue;
@@ -2771,7 +2795,7 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
             }
             RegCloseKey(hkey);
         }
             }
             RegCloseKey(hkey);
         }
-        else if (ACTION_VerifyComponentForAction(comp, INSTALLSTATE_ABSENT))
+        else if (comp->ActionRequest == INSTALLSTATE_ABSENT)
         {
             if (package->Context == MSIINSTALLCONTEXT_MACHINE)
                 MSIREG_DeleteUserDataComponentKey(comp->ComponentId, szLocalSid);
         {
             if (package->Context == MSIINSTALLCONTEXT_MACHINE)
                 MSIREG_DeleteUserDataComponentKey(comp->ComponentId, szLocalSid);
@@ -2862,28 +2886,25 @@ static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param)
     HMODULE module;
     HRESULT hr;
 
     HMODULE module;
     HRESULT hr;
 
-    static const WCHAR szTYPELIB[] = {'T','Y','P','E','L','I','B',0};
-
     component = MSI_RecordGetString(row,3);
     comp = get_loaded_component(package,component);
     if (!comp)
         return ERROR_SUCCESS;
 
     component = MSI_RecordGetString(row,3);
     comp = get_loaded_component(package,component);
     if (!comp)
         return ERROR_SUCCESS;
 
-    if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
+    if (comp->ActionRequest != INSTALLSTATE_LOCAL)
     {
     {
-        TRACE("Skipping typelib reg due to disabled component\n");
-
+        TRACE("Component not scheduled for installation: %s\n", debugstr_w(component));
         comp->Action = comp->Installed;
         comp->Action = comp->Installed;
-
         return ERROR_SUCCESS;
     }
         return ERROR_SUCCESS;
     }
-
     comp->Action = INSTALLSTATE_LOCAL;
 
     file = get_loaded_file( package, comp->KeyPath ); 
     if (!file)
         return ERROR_SUCCESS;
 
     comp->Action = INSTALLSTATE_LOCAL;
 
     file = get_loaded_file( package, comp->KeyPath ); 
     if (!file)
         return ERROR_SUCCESS;
 
+    ui_actiondata( package, szRegisterTypeLibraries, row );
+
     module = LoadLibraryExW( file->TargetPath, NULL, LOAD_LIBRARY_AS_DATAFILE );
     if (module)
     {
     module = LoadLibraryExW( file->TargetPath, NULL, LOAD_LIBRARY_AS_DATAFILE );
     if (module)
     {
@@ -2913,11 +2934,7 @@ static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param)
                 ERR("Failed to register type library %s\n",
                         debugstr_w(tl_struct.path));
             else
                 ERR("Failed to register type library %s\n",
                         debugstr_w(tl_struct.path));
             else
-            {
-                ui_actiondata(package,szRegisterTypeLibraries,row);
-
                 TRACE("Registered %s\n", debugstr_w(tl_struct.path));
                 TRACE("Registered %s\n", debugstr_w(tl_struct.path));
-            }
 
             ITypeLib_Release(tl_struct.ptLib);
             msi_free(tl_struct.path);
 
             ITypeLib_Release(tl_struct.ptLib);
             msi_free(tl_struct.path);
@@ -2935,7 +2952,7 @@ static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param)
         if (FAILED(hr))
         {
             ERR("Failed to load type library: %08x\n", hr);
         if (FAILED(hr))
         {
             ERR("Failed to load type library: %08x\n", hr);
-            return ERROR_FUNCTION_FAILED;
+            return ERROR_INSTALL_FAILURE;
         }
 
         ITypeLib_Release(tlib);
         }
 
         ITypeLib_Release(tlib);
@@ -2967,31 +2984,119 @@ static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package)
     return rc;
 }
 
     return rc;
 }
 
+static UINT ITERATE_UnregisterTypeLibraries( MSIRECORD *row, LPVOID param )
+{
+    MSIPACKAGE *package = param;
+    LPCWSTR component, guid;
+    MSICOMPONENT *comp;
+    GUID libid;
+    UINT version;
+    LCID language;
+    SYSKIND syskind;
+    HRESULT hr;
+
+    component = MSI_RecordGetString( row, 3 );
+    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;
+
+    ui_actiondata( package, szUnregisterTypeLibraries, row );
+
+    guid = MSI_RecordGetString( row, 1 );
+    CLSIDFromString( (LPWSTR)guid, &libid );
+    version = MSI_RecordGetInteger( row, 4 );
+    language = MSI_RecordGetInteger( row, 2 );
+
+#ifdef _WIN64
+    syskind = SYS_WIN64;
+#else
+    syskind = SYS_WIN32;
+#endif
+
+    hr = UnRegisterTypeLib( &libid, (version >> 8) & 0xffff, version & 0xff, language, syskind );
+    if (FAILED(hr))
+    {
+        WARN("Failed to unregister typelib: %08x\n", hr);
+    }
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ACTION_UnregisterTypeLibraries( MSIPACKAGE *package )
+{
+    UINT rc;
+    MSIQUERY *view;
+    static const WCHAR query[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','T','y','p','e','L','i','b','`',0};
+
+    rc = MSI_DatabaseOpenViewW( package->db, query, &view );
+    if (rc != ERROR_SUCCESS)
+        return ERROR_SUCCESS;
+
+    rc = MSI_IterateRecords( view, NULL, ITERATE_UnregisterTypeLibraries, package );
+    msiobj_release( &view->hdr );
+    return rc;
+}
+
+static WCHAR *get_link_file( MSIPACKAGE *package, MSIRECORD *row )
+{
+    static const WCHAR szlnk[] = {'.','l','n','k',0};
+    LPCWSTR directory, extension;
+    LPWSTR link_folder, link_file, filename;
+
+    directory = MSI_RecordGetString( row, 2 );
+    link_folder = resolve_folder( package, directory, FALSE, FALSE, TRUE, NULL );
+
+    /* may be needed because of a bug somewhere else */
+    create_full_pathW( link_folder );
+
+    filename = msi_dup_record_field( row, 3 );
+    reduce_to_longfilename( filename );
+
+    extension = strchrW( filename, '.' );
+    if (!extension || strcmpiW( extension, szlnk ))
+    {
+        int len = strlenW( filename );
+        filename = msi_realloc( filename, len * sizeof(WCHAR) + sizeof(szlnk) );
+        memcpy( filename + len, szlnk, sizeof(szlnk) );
+    }
+    link_file = build_directory_name( 2, link_folder, filename );
+    msi_free( link_folder );
+    msi_free( filename );
+
+    return link_file;
+}
+
 static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE *package = param;
 static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE *package = param;
-    LPWSTR target_file, target_folder, filename;
-    LPCWSTR buffer, extension;
+    LPWSTR link_file, deformated, path;
+    LPCWSTR component, target;
     MSICOMPONENT *comp;
     MSICOMPONENT *comp;
-    static const WCHAR szlnk[]={'.','l','n','k',0};
     IShellLinkW *sl = NULL;
     IPersistFile *pf = NULL;
     HRESULT res;
 
     IShellLinkW *sl = NULL;
     IPersistFile *pf = NULL;
     HRESULT res;
 
-    buffer = MSI_RecordGetString(row,4);
-    comp = get_loaded_component(package,buffer);
+    component = MSI_RecordGetString(row, 4);
+    comp = get_loaded_component(package, component);
     if (!comp)
         return ERROR_SUCCESS;
 
     if (!comp)
         return ERROR_SUCCESS;
 
-    if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL ))
+    if (comp->ActionRequest != INSTALLSTATE_LOCAL)
     {
     {
-        TRACE("Skipping shortcut creation due to disabled component\n");
-
+        TRACE("Component not scheduled for installation %s\n", debugstr_w(component));
         comp->Action = comp->Installed;
         comp->Action = comp->Installed;
-
         return ERROR_SUCCESS;
     }
         return ERROR_SUCCESS;
     }
-
     comp->Action = INSTALLSTATE_LOCAL;
 
     ui_actiondata(package,szCreateShortcuts,row);
     comp->Action = INSTALLSTATE_LOCAL;
 
     ui_actiondata(package,szCreateShortcuts,row);
@@ -3012,31 +3117,10 @@ static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
         goto err;
     }
 
         goto err;
     }
 
-    buffer = MSI_RecordGetString(row,2);
-    target_folder = resolve_folder(package, buffer,FALSE,FALSE,TRUE,NULL);
-
-    /* may be needed because of a bug somewhere else */
-    create_full_pathW(target_folder);
-
-    filename = msi_dup_record_field( row, 3 );
-    reduce_to_longfilename(filename);
-
-    extension = strchrW(filename,'.');
-    if (!extension || strcmpiW(extension,szlnk))
+    target = MSI_RecordGetString(row, 5);
+    if (strchrW(target, '['))
     {
     {
-        int len = strlenW(filename);
-        filename = msi_realloc(filename, len * sizeof(WCHAR) + sizeof(szlnk));
-        memcpy(filename + len, szlnk, sizeof(szlnk));
-    }
-    target_file = build_directory_name(2, target_folder, filename);
-    msi_free(target_folder);
-    msi_free(filename);
-
-    buffer = MSI_RecordGetString(row,5);
-    if (strchrW(buffer,'['))
-    {
-        LPWSTR deformated;
-        deformat_string(package,buffer,&deformated);
+        deformat_string(package, target, &deformated);
         IShellLinkW_SetPath(sl,deformated);
         msi_free(deformated);
     }
         IShellLinkW_SetPath(sl,deformated);
         msi_free(deformated);
     }
@@ -3048,17 +3132,16 @@ static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
 
     if (!MSI_RecordIsNull(row,6))
     {
 
     if (!MSI_RecordIsNull(row,6))
     {
-        LPWSTR deformated;
-        buffer = MSI_RecordGetString(row,6);
-        deformat_string(package,buffer,&deformated);
+        LPCWSTR arguments = MSI_RecordGetString(row, 6);
+        deformat_string(package, arguments, &deformated);
         IShellLinkW_SetArguments(sl,deformated);
         msi_free(deformated);
     }
 
     if (!MSI_RecordIsNull(row,7))
     {
         IShellLinkW_SetArguments(sl,deformated);
         msi_free(deformated);
     }
 
     if (!MSI_RecordIsNull(row,7))
     {
-        buffer = MSI_RecordGetString(row,7);
-        IShellLinkW_SetDescription(sl,buffer);
+        LPCWSTR description = MSI_RecordGetString(row, 7);
+        IShellLinkW_SetDescription(sl, description);
     }
 
     if (!MSI_RecordIsNull(row,8))
     }
 
     if (!MSI_RecordIsNull(row,8))
@@ -3066,20 +3149,18 @@ static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
 
     if (!MSI_RecordIsNull(row,9))
     {
 
     if (!MSI_RecordIsNull(row,9))
     {
-        LPWSTR Path;
         INT index; 
         INT index; 
+        LPCWSTR icon = MSI_RecordGetString(row, 9);
 
 
-        buffer = MSI_RecordGetString(row,9);
-
-        Path = build_icon_path(package,buffer);
+        path = build_icon_path(package, icon);
         index = MSI_RecordGetInteger(row,10);
 
         /* no value means 0 */
         if (index == MSI_NULL_INTEGER)
             index = 0;
 
         index = MSI_RecordGetInteger(row,10);
 
         /* no value means 0 */
         if (index == MSI_NULL_INTEGER)
             index = 0;
 
-        IShellLinkW_SetIconLocation(sl,Path,index);
-        msi_free(Path);
+        IShellLinkW_SetIconLocation(sl, path, index);
+        msi_free(path);
     }
 
     if (!MSI_RecordIsNull(row,11))
     }
 
     if (!MSI_RecordIsNull(row,11))
@@ -3087,18 +3168,19 @@ static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
 
     if (!MSI_RecordIsNull(row,12))
     {
 
     if (!MSI_RecordIsNull(row,12))
     {
-        LPWSTR Path;
-        buffer = MSI_RecordGetString(row,12);
-        Path = resolve_folder(package, buffer, FALSE, FALSE, TRUE, NULL);
-        if (Path)
-            IShellLinkW_SetWorkingDirectory(sl,Path);
-        msi_free(Path);
+        LPCWSTR wkdir = MSI_RecordGetString(row, 12);
+        path = resolve_folder(package, wkdir, FALSE, FALSE, TRUE, NULL);
+        if (path)
+            IShellLinkW_SetWorkingDirectory(sl, path);
+        msi_free(path);
     }
 
     }
 
-    TRACE("Writing shortcut to %s\n",debugstr_w(target_file));
-    IPersistFile_Save(pf,target_file,FALSE);
+    link_file = get_link_file(package, row);
+
+    TRACE("Writing shortcut to %s\n", debugstr_w(link_file));
+    IPersistFile_Save(pf, link_file, FALSE);
 
 
-    msi_free(target_file);    
+    msi_free(link_file);
 
 err:
     if (pf)
 
 err:
     if (pf)
@@ -3133,6 +3215,58 @@ static UINT ACTION_CreateShortcuts(MSIPACKAGE *package)
     return rc;
 }
 
     return rc;
 }
 
+static UINT ITERATE_RemoveShortcuts( MSIRECORD *row, LPVOID param )
+{
+    MSIPACKAGE *package = param;
+    LPWSTR link_file;
+    LPCWSTR component;
+    MSICOMPONENT *comp;
+
+    component = MSI_RecordGetString( row, 4 );
+    comp = get_loaded_component( package, component );
+    if (!comp)
+        return ERROR_SUCCESS;
+
+    if (comp->ActionRequest != INSTALLSTATE_ABSENT)
+    {
+        TRACE("Component not scheduled for removal %s\n", debugstr_w(component));
+        comp->Action = comp->Installed;
+        return ERROR_SUCCESS;
+    }
+    comp->Action = INSTALLSTATE_ABSENT;
+
+    ui_actiondata( package, szRemoveShortcuts, row );
+
+    link_file = get_link_file( package, row );
+
+    TRACE("Removing shortcut file %s\n", debugstr_w( link_file ));
+    if (!DeleteFileW( link_file ))
+    {
+        WARN("Failed to remove shortcut file %u\n", GetLastError());
+    }
+    msi_free( link_file );
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ACTION_RemoveShortcuts( MSIPACKAGE *package )
+{
+    UINT rc;
+    MSIQUERY *view;
+    static const WCHAR query[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','S','h','o','r','t','c','u','t','`',0};
+
+    rc = MSI_DatabaseOpenViewW( package->db, query, &view );
+    if (rc != ERROR_SUCCESS)
+        return ERROR_SUCCESS;
+
+    rc = MSI_IterateRecords( view, NULL, ITERATE_RemoveShortcuts, package );
+    msiobj_release( &view->hdr );
+
+    return rc;
+}
+
 static UINT ITERATE_PublishIcon(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE* package = param;
 static UINT ITERATE_PublishIcon(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE* package = param;
@@ -3510,17 +3644,15 @@ static UINT ITERATE_WriteIniValues(MSIRECORD *row, LPVOID param)
 
     component = MSI_RecordGetString(row, 8);
     comp = get_loaded_component(package,component);
 
     component = MSI_RecordGetString(row, 8);
     comp = get_loaded_component(package,component);
+    if (!comp)
+        return ERROR_SUCCESS;
 
 
-    if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
+    if (comp->ActionRequest != INSTALLSTATE_LOCAL)
     {
     {
-        TRACE("Skipping ini file due to disabled component %s\n",
-                        debugstr_w(component));
-
+        TRACE("Component not scheduled for installation %s\n", debugstr_w(component));
         comp->Action = comp->Installed;
         comp->Action = comp->Installed;
-
         return ERROR_SUCCESS;
     }
         return ERROR_SUCCESS;
     }
-
     comp->Action = INSTALLSTATE_LOCAL;
 
     identifier = MSI_RecordGetString(row,1); 
     comp->Action = INSTALLSTATE_LOCAL;
 
     identifier = MSI_RecordGetString(row,1); 
@@ -3818,10 +3950,9 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
         BOOL absent = FALSE;
         MSIRECORD *uirow;
 
         BOOL absent = FALSE;
         MSIRECORD *uirow;
 
-        if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL ) &&
-            !ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_SOURCE ) &&
-            !ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ADVERTISED ))
-            absent = TRUE;
+        if (feature->ActionRequest != INSTALLSTATE_LOCAL &&
+            feature->ActionRequest != INSTALLSTATE_SOURCE &&
+            feature->ActionRequest != INSTALLSTATE_ADVERTISED) absent = TRUE;
 
         size = 1;
         LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
 
         size = 1;
         LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
@@ -4359,32 +4490,34 @@ static UINT ACTION_ExecuteAction(MSIPACKAGE *package)
 static UINT ITERATE_PublishComponent(MSIRECORD *rec, LPVOID param)
 {
     MSIPACKAGE *package = param;
 static UINT ITERATE_PublishComponent(MSIRECORD *rec, LPVOID param)
 {
     MSIPACKAGE *package = param;
-    LPCWSTR compgroupid=NULL;
-    LPCWSTR feature=NULL;
-    LPCWSTR text = NULL;
-    LPCWSTR qualifier = NULL;
-    LPCWSTR component = NULL;
-    LPWSTR advertise = NULL;
-    LPWSTR output = NULL;
+    LPCWSTR compgroupid, component, feature, qualifier, text;
+    LPWSTR advertise = NULL, output = NULL;
     HKEY hkey;
     HKEY hkey;
-    UINT rc = ERROR_SUCCESS;
+    UINT rc;
     MSICOMPONENT *comp;
     MSICOMPONENT *comp;
-    DWORD sz = 0;
+    MSIFEATURE *feat;
+    DWORD sz;
     MSIRECORD *uirow;
 
     MSIRECORD *uirow;
 
-    component = MSI_RecordGetString(rec,3);
-    comp = get_loaded_component(package,component);
+    feature = MSI_RecordGetString(rec, 5);
+    feat = get_loaded_feature(package, feature);
+    if (!feat)
+        return ERROR_SUCCESS;
 
 
-    if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL ) && 
-       !ACTION_VerifyComponentForAction( comp, INSTALLSTATE_SOURCE ) &&
-       !ACTION_VerifyComponentForAction( comp, INSTALLSTATE_ADVERTISED ))
+    if (feat->ActionRequest != INSTALLSTATE_LOCAL &&
+        feat->ActionRequest != INSTALLSTATE_SOURCE &&
+        feat->ActionRequest != INSTALLSTATE_ADVERTISED)
     {
     {
-        TRACE("Skipping: Component %s not scheduled for install\n",
-                        debugstr_w(component));
-
+        TRACE("Feature %s not scheduled for installation\n", debugstr_w(feature));
+        feat->Action = feat->Installed;
         return ERROR_SUCCESS;
     }
 
         return ERROR_SUCCESS;
     }
 
+    component = MSI_RecordGetString(rec, 3);
+    comp = get_loaded_component(package, component);
+    if (!comp)
+        return ERROR_SUCCESS;
+
     compgroupid = MSI_RecordGetString(rec,1);
     qualifier = MSI_RecordGetString(rec,2);
 
     compgroupid = MSI_RecordGetString(rec,1);
     qualifier = MSI_RecordGetString(rec,2);
 
@@ -4393,8 +4526,6 @@ static UINT ITERATE_PublishComponent(MSIRECORD *rec, LPVOID param)
         goto end;
     
     text = MSI_RecordGetString(rec,4);
         goto end;
     
     text = MSI_RecordGetString(rec,4);
-    feature = MSI_RecordGetString(rec,5);
-  
     advertise = create_component_advertise_string(package, comp, feature);
 
     sz = strlenW(advertise);
     advertise = create_component_advertise_string(package, comp, feature);
 
     sz = strlenW(advertise);
@@ -4452,6 +4583,80 @@ static UINT ACTION_PublishComponents(MSIPACKAGE *package)
     return rc;
 }
 
     return rc;
 }
 
+static UINT ITERATE_UnpublishComponent( MSIRECORD *rec, LPVOID param )
+{
+    static const WCHAR szInstallerComponents[] = {
+        'S','o','f','t','w','a','r','e','\\',
+        'M','i','c','r','o','s','o','f','t','\\',
+        'I','n','s','t','a','l','l','e','r','\\',
+        'C','o','m','p','o','n','e','n','t','s','\\',0};
+
+    MSIPACKAGE *package = param;
+    LPCWSTR compgroupid, component, feature, qualifier;
+    MSICOMPONENT *comp;
+    MSIFEATURE *feat;
+    MSIRECORD *uirow;
+    WCHAR squashed[GUID_SIZE], keypath[MAX_PATH];
+    LONG res;
+
+    feature = MSI_RecordGetString( rec, 5 );
+    feat = get_loaded_feature( package, feature );
+    if (!feat)
+        return ERROR_SUCCESS;
+
+    if (feat->ActionRequest != INSTALLSTATE_ABSENT)
+    {
+        TRACE("Feature %s not scheduled for removal\n", debugstr_w(feature));
+        feat->Action = feat->Installed;
+        return ERROR_SUCCESS;
+    }
+
+    component = MSI_RecordGetString( rec, 3 );
+    comp = get_loaded_component( package, component );
+    if (!comp)
+        return ERROR_SUCCESS;
+
+    compgroupid = MSI_RecordGetString( rec, 1 );
+    qualifier = MSI_RecordGetString( rec, 2 );
+
+    squash_guid( compgroupid, squashed );
+    strcpyW( keypath, szInstallerComponents );
+    strcatW( keypath, squashed );
+
+    res = RegDeleteKeyW( HKEY_CURRENT_USER, keypath );
+    if (res != ERROR_SUCCESS)
+    {
+        WARN("Unable to delete component key %d\n", res);
+    }
+
+    uirow = MSI_CreateRecord( 2 );
+    MSI_RecordSetStringW( uirow, 1, compgroupid );
+    MSI_RecordSetStringW( uirow, 2, qualifier );
+    ui_actiondata( package, szUnpublishComponents, uirow );
+    msiobj_release( &uirow->hdr );
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ACTION_UnpublishComponents( MSIPACKAGE *package )
+{
+    UINT rc;
+    MSIQUERY *view;
+    static const WCHAR query[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','P','u','b','l','i','s','h',
+         'C','o','m','p','o','n','e','n','t','`',0};
+
+    rc = MSI_DatabaseOpenViewW( package->db, query, &view );
+    if (rc != ERROR_SUCCESS)
+        return ERROR_SUCCESS;
+
+    rc = MSI_IterateRecords( view, NULL, ITERATE_UnpublishComponent, package );
+    msiobj_release( &view->hdr );
+
+    return rc;
+}
+
 static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
 {
     MSIPACKAGE *package = param;
 static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
 {
     MSIPACKAGE *package = param;
@@ -4597,7 +4802,7 @@ static UINT ITERATE_StartService(MSIRECORD *rec, LPVOID param)
 {
     MSIPACKAGE *package = param;
     MSICOMPONENT *comp;
 {
     MSIPACKAGE *package = param;
     MSICOMPONENT *comp;
-    SC_HANDLE scm, service = NULL;
+    SC_HANDLE scm = NULL, service = NULL;
     LPCWSTR *vector = NULL;
     LPWSTR name, args;
     DWORD event, numargs;
     LPCWSTR *vector = NULL;
     LPWSTR name, args;
     DWORD event, numargs;
@@ -4612,7 +4817,10 @@ static UINT ITERATE_StartService(MSIRECORD *rec, LPVOID param)
     event = MSI_RecordGetInteger(rec, 3);
 
     if (!(event & msidbServiceControlEventStart))
     event = MSI_RecordGetInteger(rec, 3);
 
     if (!(event & msidbServiceControlEventStart))
-        return ERROR_SUCCESS;
+    {
+        r = ERROR_SUCCESS;
+        goto done;
+    }
 
     scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
     if (!scm)
 
     scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
     if (!scm)
@@ -4893,15 +5101,17 @@ static UINT ITERATE_InstallODBCDriver( MSIRECORD *rec, LPVOID param )
     driver_file = msi_find_file(package, MSI_RecordGetString(rec, 4));
     setup_file = msi_find_file(package, MSI_RecordGetString(rec, 5));
 
     driver_file = msi_find_file(package, MSI_RecordGetString(rec, 4));
     setup_file = msi_find_file(package, MSI_RecordGetString(rec, 5));
 
-    if (!driver_file || !setup_file)
+    if (!driver_file)
     {
         ERR("ODBC Driver entry not found!\n");
         return ERROR_FUNCTION_FAILED;
     }
 
     {
         ERR("ODBC Driver entry not found!\n");
         return ERROR_FUNCTION_FAILED;
     }
 
-    len = lstrlenW(desc) + lstrlenW(driver_fmt) + lstrlenW(driver_file->FileName) +
-          lstrlenW(setup_fmt) + lstrlenW(setup_file->FileName) +
-          lstrlenW(usage_fmt) + 1;
+    len = lstrlenW(desc) + lstrlenW(driver_fmt) + lstrlenW(driver_file->FileName);
+    if (setup_file)
+        len += lstrlenW(setup_fmt) + lstrlenW(setup_file->FileName);
+    len += lstrlenW(usage_fmt) + 1;
+
     driver = msi_alloc(len * sizeof(WCHAR));
     if (!driver)
         return ERROR_OUTOFMEMORY;
     driver = msi_alloc(len * sizeof(WCHAR));
     if (!driver)
         return ERROR_OUTOFMEMORY;
@@ -4913,8 +5123,11 @@ static UINT ITERATE_InstallODBCDriver( MSIRECORD *rec, LPVOID param )
     sprintfW(ptr, driver_fmt, driver_file->FileName);
     ptr += lstrlenW(ptr) + 1;
 
     sprintfW(ptr, driver_fmt, driver_file->FileName);
     ptr += lstrlenW(ptr) + 1;
 
-    sprintfW(ptr, setup_fmt, setup_file->FileName);
-    ptr += lstrlenW(ptr) + 1;
+    if (setup_file)
+    {
+        sprintfW(ptr, setup_fmt, setup_file->FileName);
+        ptr += lstrlenW(ptr) + 1;
+    }
 
     lstrcpyW(ptr, usage_fmt);
     ptr += lstrlenW(ptr) + 1;
 
     lstrcpyW(ptr, usage_fmt);
     ptr += lstrlenW(ptr) + 1;
@@ -4957,14 +5170,16 @@ static UINT ITERATE_InstallODBCTranslator( MSIRECORD *rec, LPVOID param )
     translator_file = msi_find_file(package, MSI_RecordGetString(rec, 4));
     setup_file = msi_find_file(package, MSI_RecordGetString(rec, 5));
 
     translator_file = msi_find_file(package, MSI_RecordGetString(rec, 4));
     setup_file = msi_find_file(package, MSI_RecordGetString(rec, 5));
 
-    if (!translator_file || !setup_file)
+    if (!translator_file)
     {
         ERR("ODBC Translator entry not found!\n");
         return ERROR_FUNCTION_FAILED;
     }
 
     {
         ERR("ODBC Translator entry not found!\n");
         return ERROR_FUNCTION_FAILED;
     }
 
-    len = lstrlenW(desc) + lstrlenW(translator_fmt) + lstrlenW(translator_file->FileName) +
-          lstrlenW(setup_fmt) + lstrlenW(setup_file->FileName) + 1;
+    len = lstrlenW(desc) + lstrlenW(translator_fmt) + lstrlenW(translator_file->FileName) + 1;
+    if (setup_file)
+        len += lstrlenW(setup_fmt) + lstrlenW(setup_file->FileName);
+
     translator = msi_alloc(len * sizeof(WCHAR));
     if (!translator)
         return ERROR_OUTOFMEMORY;
     translator = msi_alloc(len * sizeof(WCHAR));
     if (!translator)
         return ERROR_OUTOFMEMORY;
@@ -4976,8 +5191,11 @@ static UINT ITERATE_InstallODBCTranslator( MSIRECORD *rec, LPVOID param )
     sprintfW(ptr, translator_fmt, translator_file->FileName);
     ptr += lstrlenW(ptr) + 1;
 
     sprintfW(ptr, translator_fmt, translator_file->FileName);
     ptr += lstrlenW(ptr) + 1;
 
-    sprintfW(ptr, setup_fmt, setup_file->FileName);
-    ptr += lstrlenW(ptr) + 1;
+    if (setup_file)
+    {
+        sprintfW(ptr, setup_fmt, setup_file->FileName);
+        ptr += lstrlenW(ptr) + 1;
+    }
     *ptr = '\0';
 
     translator_path = strdupW(translator_file->TargetPath);
     *ptr = '\0';
 
     translator_path = strdupW(translator_file->TargetPath);
@@ -5021,8 +5239,8 @@ static UINT ITERATE_InstallODBCDataSource( MSIRECORD *rec, LPVOID param )
     if (!attrs)
         return ERROR_OUTOFMEMORY;
 
     if (!attrs)
         return ERROR_OUTOFMEMORY;
 
-    sprintfW(attrs, attrs_fmt, desc);
-    attrs[len - 1] = '\0';
+    len = sprintfW(attrs, attrs_fmt, desc);
+    attrs[len + 1] = 0;
 
     if (!SQLConfigDataSourceW(NULL, request, driver, attrs))
     {
 
     if (!SQLConfigDataSourceW(NULL, request, driver, attrs))
     {
@@ -5076,6 +5294,120 @@ static UINT ACTION_InstallODBC( MSIPACKAGE *package )
     return rc;
 }
 
     return rc;
 }
 
+static UINT ITERATE_RemoveODBCDriver( MSIRECORD *rec, LPVOID param )
+{
+    DWORD usage;
+    LPCWSTR desc;
+
+    desc = MSI_RecordGetString( rec, 3 );
+    if (!SQLRemoveDriverW( desc, FALSE, &usage ))
+    {
+        WARN("Failed to remove ODBC driver\n");
+    }
+    else if (!usage)
+    {
+        FIXME("Usage count reached 0\n");
+    }
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ITERATE_RemoveODBCTranslator( MSIRECORD *rec, LPVOID param )
+{
+    DWORD usage;
+    LPCWSTR desc;
+
+    desc = MSI_RecordGetString( rec, 3 );
+    if (!SQLRemoveTranslatorW( desc, &usage ))
+    {
+        WARN("Failed to remove ODBC translator\n");
+    }
+    else if (!usage)
+    {
+        FIXME("Usage count reached 0\n");
+    }
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ITERATE_RemoveODBCDataSource( MSIRECORD *rec, LPVOID param )
+{
+    LPWSTR attrs;
+    LPCWSTR desc, driver;
+    WORD request = ODBC_REMOVE_SYS_DSN;
+    INT registration;
+    DWORD len;
+
+    static const WCHAR attrs_fmt[] = {
+        'D','S','N','=','%','s',0 };
+
+    desc = MSI_RecordGetString( rec, 3 );
+    driver = MSI_RecordGetString( rec, 4 );
+    registration = MSI_RecordGetInteger( rec, 5 );
+
+    if (registration == msidbODBCDataSourceRegistrationPerMachine) request = ODBC_REMOVE_SYS_DSN;
+    else if (registration == msidbODBCDataSourceRegistrationPerUser) request = ODBC_REMOVE_DSN;
+
+    len = strlenW( attrs_fmt ) + strlenW( desc ) + 1 + 1;
+    attrs = msi_alloc( len * sizeof(WCHAR) );
+    if (!attrs)
+        return ERROR_OUTOFMEMORY;
+
+    FIXME("Use ODBCSourceAttribute table\n");
+
+    len = sprintfW( attrs, attrs_fmt, desc );
+    attrs[len + 1] = 0;
+
+    if (!SQLConfigDataSourceW( NULL, request, driver, attrs ))
+    {
+        WARN("Failed to remove ODBC data source\n");
+    }
+    msi_free( attrs );
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ACTION_RemoveODBC( MSIPACKAGE *package )
+{
+    UINT rc;
+    MSIQUERY *view;
+
+    static const WCHAR driver_query[] = {
+        'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+        'O','D','B','C','D','r','i','v','e','r',0 };
+
+    static const WCHAR translator_query[] = {
+        'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+        'O','D','B','C','T','r','a','n','s','l','a','t','o','r',0 };
+
+    static const WCHAR source_query[] = {
+        'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+        'O','D','B','C','D','a','t','a','S','o','u','r','c','e',0 };
+
+    rc = MSI_DatabaseOpenViewW( package->db, driver_query, &view );
+    if (rc != ERROR_SUCCESS)
+        return ERROR_SUCCESS;
+
+    rc = MSI_IterateRecords( view, NULL, ITERATE_RemoveODBCDriver, package );
+    msiobj_release( &view->hdr );
+
+    rc = MSI_DatabaseOpenViewW( package->db, translator_query, &view );
+    if (rc != ERROR_SUCCESS)
+        return ERROR_SUCCESS;
+
+    rc = MSI_IterateRecords( view, NULL, ITERATE_RemoveODBCTranslator, package );
+    msiobj_release( &view->hdr );
+
+    rc = MSI_DatabaseOpenViewW( package->db, source_query, &view );
+    if (rc != ERROR_SUCCESS)
+        return ERROR_SUCCESS;
+
+    rc = MSI_IterateRecords( view, NULL, ITERATE_RemoveODBCDataSource, package );
+    msiobj_release( &view->hdr );
+
+    return rc;
+}
+
 #define ENV_ACT_SETALWAYS   0x1
 #define ENV_ACT_SETABSENT   0x2
 #define ENV_ACT_REMOVE      0x4
 #define ENV_ACT_SETALWAYS   0x1
 #define ENV_ACT_SETABSENT   0x2
 #define ENV_ACT_REMOVE      0x4
@@ -6125,6 +6457,30 @@ done:
     return r;
 }
 
     return r;
 }
 
+static UINT ACTION_ValidateProductID( MSIPACKAGE *package )
+{
+    LPWSTR key, template, id;
+    UINT r = ERROR_SUCCESS;
+
+    id = msi_dup_property( package, szProductID );
+    if (id)
+    {
+        msi_free( id );
+        return ERROR_SUCCESS;
+    }
+    template = msi_dup_property( package, szPIDTemplate );
+    key = msi_dup_property( package, szPIDKEY );
+
+    if (key && template)
+    {
+        FIXME( "partial stub: template %s key %s\n", debugstr_w(template), debugstr_w(key) );
+        r = MSI_SetPropertyW( package, szProductID, key );
+    }
+    msi_free( template );
+    msi_free( key );
+    return r;
+}
+
 static UINT ACTION_ScheduleReboot( MSIPACKAGE *package )
 {
     TRACE("\n");
 static UINT ACTION_ScheduleReboot( MSIPACKAGE *package )
 {
     TRACE("\n");
@@ -6132,6 +6488,24 @@ static UINT ACTION_ScheduleReboot( MSIPACKAGE *package )
     return ERROR_SUCCESS;
 }
 
     return ERROR_SUCCESS;
 }
 
+static UINT ACTION_AllocateRegistrySpace( MSIPACKAGE *package )
+{
+    TRACE("%p\n", package);
+    return ERROR_SUCCESS;
+}
+
+static UINT ACTION_DisableRollback( MSIPACKAGE *package )
+{
+    FIXME("%p\n", package);
+    return ERROR_SUCCESS;
+}
+
+static UINT ACTION_InstallAdminPackage( MSIPACKAGE *package )
+{
+    FIXME("%p\n", package);
+    return ERROR_SUCCESS;
+}
+
 static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
                                            LPCSTR action, LPCWSTR table )
 {
 static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
                                            LPCSTR action, LPCWSTR table )
 {
@@ -6156,12 +6530,6 @@ static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
     return ERROR_SUCCESS;
 }
 
     return ERROR_SUCCESS;
 }
 
-static UINT ACTION_AllocateRegistrySpace( MSIPACKAGE *package )
-{
-    TRACE("%p\n", package);
-    return ERROR_SUCCESS;
-}
-
 static UINT ACTION_RemoveIniValues( MSIPACKAGE *package )
 {
     static const WCHAR table[] =
 static UINT ACTION_RemoveIniValues( MSIPACKAGE *package )
 {
     static const WCHAR table[] =
@@ -6194,13 +6562,6 @@ static UINT ACTION_MigrateFeatureStates( MSIPACKAGE *package )
     return msi_unimplemented_action_stub( package, "MigrateFeatureStates", table );
 }
 
     return msi_unimplemented_action_stub( package, "MigrateFeatureStates", table );
 }
 
-static UINT ACTION_ValidateProductID( MSIPACKAGE *package )
-{
-       static const WCHAR table[] = {
-               'P','r','o','d','u','c','t','I','D',0 };
-       return msi_unimplemented_action_stub( package, "ValidateProductID", table );
-}
-
 static UINT ACTION_RemoveEnvironmentStrings( MSIPACKAGE *package )
 {
     static const WCHAR table[] = {
 static UINT ACTION_RemoveEnvironmentStrings( MSIPACKAGE *package )
 {
     static const WCHAR table[] = {
@@ -6215,12 +6576,6 @@ static UINT ACTION_MsiUnpublishAssemblies( MSIPACKAGE *package )
     return msi_unimplemented_action_stub( package, "MsiUnpublishAssemblies", table );
 }
 
     return msi_unimplemented_action_stub( package, "MsiUnpublishAssemblies", table );
 }
 
-static UINT ACTION_UnregisterFonts( MSIPACKAGE *package )
-{
-    static const WCHAR table[] = { 'F','o','n','t',0 };
-    return msi_unimplemented_action_stub( package, "UnregisterFonts", table );
-}
-
 static UINT ACTION_RMCCPSearch( MSIPACKAGE *package )
 {
     static const WCHAR table[] = { 'C','C','P','S','e','a','r','c','h',0 };
 static UINT ACTION_RMCCPSearch( MSIPACKAGE *package )
 {
     static const WCHAR table[] = { 'C','C','P','S','e','a','r','c','h',0 };
@@ -6257,36 +6612,18 @@ static UINT ACTION_RemoveExistingProducts( MSIPACKAGE *package )
     return msi_unimplemented_action_stub( package, "RemoveExistingProducts", table );
 }
 
     return msi_unimplemented_action_stub( package, "RemoveExistingProducts", table );
 }
 
-static UINT ACTION_RemoveODBC( MSIPACKAGE *package )
-{
-    static const WCHAR table[] = { 'O','D','B','C','D','r','i','v','e','r',0 };
-    return msi_unimplemented_action_stub( package, "RemoveODBC", 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_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_RemoveShortcuts( MSIPACKAGE *package )
-{
-    static const WCHAR table[] = { 'S','h','o','r','t','c','u','t',0 };
-    return msi_unimplemented_action_stub( package, "RemoveShortcuts", table );
-}
-
 static UINT ACTION_SetODBCFolders( MSIPACKAGE *package )
 {
     static const WCHAR table[] = { 'D','i','r','e','c','t','o','r','y',0 };
     return msi_unimplemented_action_stub( package, "SetODBCFolders", table );
 }
 
 static UINT ACTION_SetODBCFolders( MSIPACKAGE *package )
 {
     static const WCHAR table[] = { 'D','i','r','e','c','t','o','r','y',0 };
     return msi_unimplemented_action_stub( package, "SetODBCFolders", table );
 }
 
-static UINT ACTION_UnpublishComponents( MSIPACKAGE *package )
-{
-    static const WCHAR table[] = { 'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t',0 };
-    return msi_unimplemented_action_stub( package, "UnpublishComponents", table );
-}
-
 static UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
 {
     static const WCHAR table[] = { 'A','p','p','I','d',0 };
 static UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
 {
     static const WCHAR table[] = { 'A','p','p','I','d',0 };
@@ -6311,12 +6648,6 @@ static UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package )
     return msi_unimplemented_action_stub( package, "UnregisterProgIdInfo", table );
 }
 
     return msi_unimplemented_action_stub( package, "UnregisterProgIdInfo", table );
 }
 
-static UINT ACTION_UnregisterTypeLibraries( MSIPACKAGE *package )
-{
-    static const WCHAR table[] = { 'T','y','p','e','L','i','b',0 };
-    return msi_unimplemented_action_stub( package, "UnregisterTypeLibraries", table );
-}
-
 typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*);
 
 static const struct
 typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*);
 
 static const struct
@@ -6335,13 +6666,13 @@ StandardActions[] =
     { szCreateFolders, ACTION_CreateFolders },
     { szCreateShortcuts, ACTION_CreateShortcuts },
     { szDeleteServices, ACTION_DeleteServices },
     { szCreateFolders, ACTION_CreateFolders },
     { szCreateShortcuts, ACTION_CreateShortcuts },
     { szDeleteServices, ACTION_DeleteServices },
-    { szDisableRollback, NULL },
+    { szDisableRollback, ACTION_DisableRollback },
     { szDuplicateFiles, ACTION_DuplicateFiles },
     { szExecuteAction, ACTION_ExecuteAction },
     { szFileCost, ACTION_FileCost },
     { szFindRelatedProducts, ACTION_FindRelatedProducts },
     { szForceReboot, ACTION_ForceReboot },
     { szDuplicateFiles, ACTION_DuplicateFiles },
     { szExecuteAction, ACTION_ExecuteAction },
     { szFileCost, ACTION_FileCost },
     { szFindRelatedProducts, ACTION_FindRelatedProducts },
     { szForceReboot, ACTION_ForceReboot },
-    { szInstallAdminPackage, NULL },
+    { szInstallAdminPackage, ACTION_InstallAdminPackage },
     { szInstallExecute, ACTION_InstallExecute },
     { szInstallExecuteAgain, ACTION_InstallExecute },
     { szInstallFiles, ACTION_InstallFiles},
     { szInstallExecute, ACTION_InstallExecute },
     { szInstallExecuteAgain, ACTION_InstallExecute },
     { szInstallFiles, ACTION_InstallFiles},
index 6ca35b9..acd8429 100644 (file)
@@ -809,16 +809,17 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
             continue;
 
         feature = cls->Feature;
             continue;
 
         feature = cls->Feature;
+        if (!feature)
+            continue;
 
         /*
          * MSDN says that these are based on Feature not on Component.
          */
 
         /*
          * MSDN says that these are based on Feature not on Component.
          */
-        if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL ) &&
-            !ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ADVERTISED ))
+        if (feature->ActionRequest != INSTALLSTATE_LOCAL &&
+            feature->ActionRequest != INSTALLSTATE_ADVERTISED )
         {
         {
-            TRACE("Skipping class %s reg due to disabled feature %s\n",
-                  debugstr_w(cls->clsid), debugstr_w(feature->Feature));
-
+            TRACE("Feature %s not scheduled for installation, skipping regstration of class %s\n",
+                  debugstr_w(feature->Feature), debugstr_w(cls->clsid));
             continue;
         }
 
             continue;
         }
 
@@ -1142,18 +1143,18 @@ UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
             continue;
 
         feature = ext->Feature;
             continue;
 
         feature = ext->Feature;
+        if (!feature)
+            continue;
 
         /* 
          * yes. MSDN says that these are based on _Feature_ not on
          * Component.  So verify the feature is to be installed
          */
 
         /* 
          * yes. MSDN says that these are based on _Feature_ not on
          * Component.  So verify the feature is to be installed
          */
-        if ((!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL )) &&
-             !(install_on_demand &&
-               ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ADVERTISED )))
+        if (feature->ActionRequest != INSTALLSTATE_LOCAL &&
+            !(install_on_demand && feature->ActionRequest == INSTALLSTATE_ADVERTISED))
         {
         {
-            TRACE("Skipping extension %s reg due to disabled feature %s\n",
-                   debugstr_w(ext->Extension), debugstr_w(feature->Feature));
-
+            TRACE("Feature %s not scheduled for installation, skipping registration of extension %s\n",
+                   debugstr_w(feature->Feature), debugstr_w(ext->Extension));
             continue;
         }
 
             continue;
         }
 
index 7855fea..8ec2411 100644 (file)
@@ -125,20 +125,14 @@ static UINT clone_open_stream( MSIDATABASE *db, LPCWSTR name, IStream **stm )
 
 UINT db_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm )
 {
 
 UINT db_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm )
 {
-    LPWSTR encname;
     HRESULT r;
 
     HRESULT r;
 
-    encname = encode_streamname(FALSE, stname);
-
-    TRACE("%s -> %s\n",debugstr_w(stname),debugstr_w(encname));
+    TRACE("%s\n", debugstr_w(stname));
 
 
-    if (clone_open_stream( db, encname, stm ) == ERROR_SUCCESS)
-    {
-        msi_free( encname );
+    if (clone_open_stream( db, stname, stm ) == ERROR_SUCCESS)
         return ERROR_SUCCESS;
         return ERROR_SUCCESS;
-    }
 
 
-    r = IStorage_OpenStream( db->storage, encname, NULL,
+    r = IStorage_OpenStream( db->storage, stname, NULL,
                              STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
     if( FAILED( r ) )
     {
                              STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
     if( FAILED( r ) )
     {
@@ -147,15 +141,13 @@ UINT db_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm )
         LIST_FOR_EACH_ENTRY( transform, &db->transforms, MSITRANSFORM, entry )
         {
             TRACE("looking for %s in transform storage\n", debugstr_w(stname) );
         LIST_FOR_EACH_ENTRY( transform, &db->transforms, MSITRANSFORM, entry )
         {
             TRACE("looking for %s in transform storage\n", debugstr_w(stname) );
-            r = IStorage_OpenStream( transform->stg, encname, NULL,
+            r = IStorage_OpenStream( transform->stg, stname, NULL,
                                      STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
             if (SUCCEEDED(r))
                 break;
         }
     }
 
                                      STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
             if (SUCCEEDED(r))
                 break;
         }
     }
 
-    msi_free( encname );
-
     if( SUCCEEDED(r) )
     {
         MSISTREAM *stream;
     if( SUCCEEDED(r) )
     {
         MSISTREAM *stream;
@@ -181,10 +173,15 @@ UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname,
     ULONG sz, count;
     IStream *stm = NULL;
     STATSTG stat;
     ULONG sz, count;
     IStream *stm = NULL;
     STATSTG stat;
+    LPWSTR encname;
+
+    encname = encode_streamname( FALSE, stname );
+    r = db_get_raw_stream( db, encname, &stm );
+    msi_free( encname );
 
 
-    r = db_get_raw_stream( db, stname, &stm );
     if( r != ERROR_SUCCESS)
         return ret;
     if( r != ERROR_SUCCESS)
         return ret;
+
     r = IStream_Stat(stm, &stat, STATFLAG_NONAME );
     if( FAILED( r ) )
     {
     r = IStream_Stat(stm, &stat, STATFLAG_NONAME );
     if( FAILED( r ) )
     {
@@ -225,16 +222,6 @@ end:
     return ret;
 }
 
     return ret;
 }
 
-void append_storage_to_db( MSIDATABASE *db, IStorage *stg )
-{
-    MSITRANSFORM *t;
-
-    t = msi_alloc( sizeof *t );
-    t->stg = stg;
-    IStorage_AddRef( stg );
-    list_add_tail( &db->transforms, &t->entry );
-}
-
 static void free_transforms( MSIDATABASE *db )
 {
     while( !list_empty( &db->transforms ) )
 static void free_transforms( MSIDATABASE *db )
 {
     while( !list_empty( &db->transforms ) )
@@ -259,6 +246,19 @@ static void free_streams( MSIDATABASE *db )
     }
 }
 
     }
 }
 
+void append_storage_to_db( MSIDATABASE *db, IStorage *stg )
+{
+    MSITRANSFORM *t;
+
+    t = msi_alloc( sizeof *t );
+    t->stg = stg;
+    IStorage_AddRef( stg );
+    list_add_tail( &db->transforms, &t->entry );
+
+    /* the transform may add or replace streams */
+    free_streams( db );
+}
+
 static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
 {
     MSIDATABASE *db = (MSIDATABASE *) arg;
 static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
 {
     MSIDATABASE *db = (MSIDATABASE *) arg;
index f4697dd..e8f2297 100644 (file)
@@ -386,9 +386,6 @@ static UINT ControlEvent_ReinstallMode(MSIPACKAGE *package, LPCWSTR argument,
 static UINT ControlEvent_ValidateProductID(MSIPACKAGE *package, LPCWSTR argument,
                                            msi_dialog *dialog)
 {
 static UINT ControlEvent_ValidateProductID(MSIPACKAGE *package, LPCWSTR argument,
                                            msi_dialog *dialog)
 {
-    static const WCHAR szProductID[] = {'P','r','o','d','u','c','t','I','D',0};
-    static const WCHAR szPIDTemplate[] = {'P','I','D','T','e','m','p','l','a','t','e',0};
-    static const WCHAR szPIDKEY[] = {'P','I','D','K','E','Y',0};
     LPWSTR key, template;
     UINT ret = ERROR_SUCCESS;
 
     LPWSTR key, template;
     UINT ret = ERROR_SUCCESS;
 
index b7af4d3..d641950 100644 (file)
@@ -108,7 +108,7 @@ static void schedule_install_files(MSIPACKAGE *package)
 
     LIST_FOR_EACH_ENTRY(file, &package->files, MSIFILE, entry)
     {
 
     LIST_FOR_EACH_ENTRY(file, &package->files, MSIFILE, entry)
     {
-        if (!ACTION_VerifyComponentForAction(file->Component, INSTALLSTATE_LOCAL))
+        if (file->Component->ActionRequest != INSTALLSTATE_LOCAL)
         {
             TRACE("File %s is not scheduled for install\n", debugstr_w(file->File));
 
         {
             TRACE("File %s is not scheduled for install\n", debugstr_w(file->File));
 
@@ -358,19 +358,15 @@ static UINT ITERATE_DuplicateFiles(MSIRECORD *row, LPVOID param)
 
     component = MSI_RecordGetString(row,2);
     comp = get_loaded_component(package,component);
 
     component = MSI_RecordGetString(row,2);
     comp = get_loaded_component(package,component);
+    if (!comp)
+        return ERROR_SUCCESS;
 
 
-    if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL ))
+    if (comp->ActionRequest != INSTALLSTATE_LOCAL)
     {
     {
-        TRACE("Skipping copy due to disabled component %s\n",
-                        debugstr_w(component));
-
-        /* the action taken was the same as the current install state */        
-        if (comp)
-            comp->Action = comp->Installed;
-
+        TRACE("Component not scheduled for installation %s\n", debugstr_w(component));
+        comp->Action = comp->Installed;
         return ERROR_SUCCESS;
     }
         return ERROR_SUCCESS;
     }
-
     comp->Action = INSTALLSTATE_LOCAL;
 
     file_key = MSI_RecordGetString(row,3);
     comp->Action = INSTALLSTATE_LOCAL;
 
     file_key = MSI_RecordGetString(row,3);
index 085d400..1b2c3c7 100644 (file)
@@ -66,6 +66,21 @@ typedef struct _tagTT_NAME_RECORD {
 
 static const WCHAR szRegisterFonts[] =
     {'R','e','g','i','s','t','e','r','F','o','n','t','s',0};
 
 static const WCHAR szRegisterFonts[] =
     {'R','e','g','i','s','t','e','r','F','o','n','t','s',0};
+static const WCHAR szUnregisterFonts[] =
+    {'U','n','r','e','g','i','s','t','e','r','F','o','n','t','s',0};
+
+static const WCHAR regfont1[] =
+    {'S','o','f','t','w','a','r','e','\\',
+     'M','i','c','r','o','s','o','f','t','\\',
+     'W','i','n','d','o','w','s',' ','N','T','\\',
+     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+     'F','o','n','t','s',0};
+static const WCHAR regfont2[] =
+    {'S','o','f','t','w','a','r','e','\\',
+     'M','i','c','r','o','s','o','f','t','\\',
+     'W','i','n','d','o','w','s','\\',
+     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+     'F','o','n','t','s',0};
 
 /*
  * Code based off of code located here
 
 /*
  * Code based off of code located here
@@ -174,20 +189,7 @@ static UINT ITERATE_RegisterFonts(MSIRECORD *row, LPVOID param)
     LPWSTR name;
     LPCWSTR filename;
     MSIFILE *file;
     LPWSTR name;
     LPCWSTR filename;
     MSIFILE *file;
-    static const WCHAR regfont1[] =
-        {'S','o','f','t','w','a','r','e','\\',
-         'M','i','c','r','o','s','o','f','t','\\',
-         'W','i','n','d','o','w','s',' ','N','T','\\',
-         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
-         'F','o','n','t','s',0};
-    static const WCHAR regfont2[] =
-        {'S','o','f','t','w','a','r','e','\\',
-         'M','i','c','r','o','s','o','f','t','\\',
-         'W','i','n','d','o','w','s','\\',
-         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
-         'F','o','n','t','s',0};
-    HKEY hkey1;
-    HKEY hkey2;
+    HKEY hkey1, hkey2;
     MSIRECORD *uirow;
     LPWSTR uipath, p;
 
     MSIRECORD *uirow;
     LPWSTR uipath, p;
 
@@ -199,10 +201,9 @@ static UINT ITERATE_RegisterFonts(MSIRECORD *row, LPVOID param)
         return ERROR_SUCCESS;
     }
 
         return ERROR_SUCCESS;
     }
 
-    /* check to make sure that component is installed */
-    if (!ACTION_VerifyComponentForAction( file->Component, INSTALLSTATE_LOCAL))
+    if (file->Component->ActionRequest != INSTALLSTATE_LOCAL)
     {
     {
-        TRACE("Skipping: Component not scheduled for install\n");
+        TRACE("Component not scheduled for installation\n");
         return ERROR_SUCCESS;
     }
 
         return ERROR_SUCCESS;
     }
 
@@ -259,3 +260,81 @@ UINT ACTION_RegisterFonts(MSIPACKAGE *package)
 
     return ERROR_SUCCESS;
 }
 
     return ERROR_SUCCESS;
 }
+
+static UINT ITERATE_UnregisterFonts( MSIRECORD *row, LPVOID param )
+{
+    MSIPACKAGE *package = param;
+    LPWSTR name;
+    LPCWSTR filename;
+    MSIFILE *file;
+    HKEY hkey1, hkey2;
+    MSIRECORD *uirow;
+    LPWSTR uipath, p;
+
+    filename = MSI_RecordGetString( row, 1 );
+    file = get_loaded_file( package, filename );
+    if (!file)
+    {
+        ERR("Unable to load file\n");
+        return ERROR_SUCCESS;
+    }
+
+    if (file->Component->ActionRequest != INSTALLSTATE_ABSENT)
+    {
+        TRACE("Component not scheduled for removal\n");
+        return ERROR_SUCCESS;
+    }
+
+    RegCreateKeyW( HKEY_LOCAL_MACHINE, regfont1, &hkey1 );
+    RegCreateKeyW( HKEY_LOCAL_MACHINE, regfont2, &hkey2 );
+
+    if (MSI_RecordIsNull( row, 2 ))
+        name = load_ttfname_from( file->TargetPath );
+    else
+        name = msi_dup_record_field( row, 2 );
+
+    if (name)
+    {
+        RegDeleteValueW( hkey1, name );
+        RegDeleteValueW( hkey2, name );
+    }
+
+    msi_free( name );
+    RegCloseKey( hkey1 );
+    RegCloseKey( hkey2 );
+
+    /* the UI chunk */
+    uirow = MSI_CreateRecord( 1 );
+    uipath = strdupW( file->TargetPath );
+    p = strrchrW( uipath,'\\' );
+    if (p) p++;
+    else p = uipath;
+    MSI_RecordSetStringW( uirow, 1, p );
+    ui_actiondata( package, szUnregisterFonts, uirow );
+    msiobj_release( &uirow->hdr );
+    msi_free( uipath );
+    /* FIXME: call ui_progress? */
+
+    return ERROR_SUCCESS;
+}
+
+UINT ACTION_UnregisterFonts( MSIPACKAGE *package )
+{
+    UINT r;
+    MSIQUERY *view;
+    static const WCHAR query[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','F','o','n','t','`',0};
+
+    r = MSI_DatabaseOpenViewW( package->db, query, &view );
+    if (r != ERROR_SUCCESS)
+    {
+        TRACE("MSI_DatabaseOpenViewW failed: %u\n", r);
+        return ERROR_SUCCESS;
+    }
+
+    MSI_IterateRecords( view, NULL, ITERATE_UnregisterFonts, package );
+    msiobj_release( &view->hdr );
+
+    return ERROR_SUCCESS;
+}
index e3009f7..e763a11 100644 (file)
@@ -604,28 +604,6 @@ void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * record)
     msiobj_release(&row->hdr);
 }
 
     msiobj_release(&row->hdr);
 }
 
-BOOL ACTION_VerifyComponentForAction( const MSICOMPONENT* comp, INSTALLSTATE check )
-{
-    if (!comp)
-        return FALSE;
-
-    if (comp->ActionRequest == check)
-        return TRUE;
-    else
-        return FALSE;
-}
-
-BOOL ACTION_VerifyFeatureForAction( const MSIFEATURE* feature, INSTALLSTATE check )
-{
-    if (!feature)
-        return FALSE;
-
-    if (feature->ActionRequest == check)
-        return TRUE;
-    else
-        return FALSE;
-}
-
 void reduce_to_longfilename(WCHAR* filename)
 {
     LPWSTR p = strchrW(filename,'|');
 void reduce_to_longfilename(WCHAR* filename)
 {
     LPWSTR p = strchrW(filename,'|');
index b1d741a..c23075d 100644 (file)
@@ -661,6 +661,8 @@ BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
     MSIPACKAGE *package;
     BOOL r = FALSE;
 
     MSIPACKAGE *package;
     BOOL r = FALSE;
 
+    TRACE("%d %d\n", hInstall, iRunMode);
+
     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
     {
     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
     {
@@ -706,8 +708,16 @@ BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
         r = package->commit_action_running;
         break;
 
         r = package->commit_action_running;
         break;
 
+    case MSIRUNMODE_MAINTENANCE:
+        r = msi_get_property_int( package, szInstalled, 0 ) != 0;
+        break;
+
+    case MSIRUNMODE_REBOOTATEND:
+        r = package->need_reboot;
+        break;
+
     default:
     default:
-        FIXME("%d %d\n", hInstall, iRunMode);
+        FIXME("unimplemented run mode: %d\n", iRunMode);
         r = TRUE;
     }
 
         r = TRUE;
     }
 
@@ -719,8 +729,52 @@ BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
  */
 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
 {
  */
 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
 {
-    FIXME("%d %d %d\n", hInstall, iRunMode, fState);
-    return ERROR_SUCCESS;
+    MSIPACKAGE *package;
+    UINT r;
+
+    TRACE("%d %d %d\n", hInstall, iRunMode, fState);
+
+    package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
+    if (!package)
+    {
+        HRESULT hr;
+        IWineMsiRemotePackage *remote_package;
+
+        remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
+        if (!remote_package)
+            return FALSE;
+
+        hr = IWineMsiRemotePackage_SetMode( remote_package, iRunMode, fState );
+        IWineMsiRemotePackage_Release( remote_package );
+
+        if (FAILED(hr))
+        {
+            if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
+                return HRESULT_CODE(hr);
+
+            return ERROR_FUNCTION_FAILED;
+        }
+
+        return ERROR_SUCCESS;
+    }
+
+    switch (iRunMode)
+    {
+    case MSIRUNMODE_REBOOTATEND:
+        package->need_reboot = 1;
+        r = ERROR_SUCCESS;
+        break;
+
+    case MSIRUNMODE_REBOOTNOW:
+        FIXME("unimplemented run mode: %d\n", iRunMode);
+        r = ERROR_FUNCTION_FAILED;
+        break;
+
+    default:
+        r = ERROR_ACCESS_DENIED;
+    }
+
+    return r;
 }
 
 /***********************************************************************
 }
 
 /***********************************************************************
index 4d9da4c..0735640 100644 (file)
@@ -1613,6 +1613,93 @@ done:
     return r;
 }
 
     return r;
 }
 
+UINT WINAPI MsiGetPatchInfoA( LPCSTR patch, LPCSTR attr, LPSTR buffer, LPDWORD buflen )
+{
+    UINT r = ERROR_OUTOFMEMORY;
+    DWORD size;
+    LPWSTR patchW = NULL, attrW = NULL, bufferW = NULL;
+
+    TRACE("%s %s %p %p\n", debugstr_a(patch), debugstr_a(attr), buffer, buflen);
+
+    if (!patch || !attr)
+        return ERROR_INVALID_PARAMETER;
+
+    if (!(patchW = strdupAtoW( patch )))
+        goto done;
+
+    if (!(attrW = strdupAtoW( attr )))
+        goto done;
+
+    size = 0;
+    r = MsiGetPatchInfoW( patchW, attrW, NULL, &size );
+    if (r != ERROR_SUCCESS)
+        goto done;
+
+    size++;
+    if (!(bufferW = msi_alloc( size * sizeof(WCHAR) )))
+    {
+        r = ERROR_OUTOFMEMORY;
+        goto done;
+    }
+
+    r = MsiGetPatchInfoW( patchW, attrW, bufferW, &size );
+    if (r == ERROR_SUCCESS)
+    {
+        int len = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
+        if (len > *buflen)
+            r = ERROR_MORE_DATA;
+        else if (buffer)
+            WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, *buflen, NULL, NULL );
+
+        *buflen = len - 1;
+    }
+
+done:
+    msi_free( patchW );
+    msi_free( attrW );
+    msi_free( bufferW );
+    return r;
+}
+
+UINT WINAPI MsiGetPatchInfoW( LPCWSTR patch, LPCWSTR attr, LPWSTR buffer, LPDWORD buflen )
+{
+    UINT r;
+    WCHAR product[GUID_SIZE];
+    DWORD index;
+
+    TRACE("%s %s %p %p\n", debugstr_w(patch), debugstr_w(attr), buffer, buflen);
+
+    if (!patch || !attr)
+        return ERROR_INVALID_PARAMETER;
+
+    if (strcmpW( INSTALLPROPERTY_LOCALPACKAGEW, attr ))
+        return ERROR_UNKNOWN_PROPERTY;
+
+    index = 0;
+    while (1)
+    {
+        r = MsiEnumProductsW( index, product );
+        if (r != ERROR_SUCCESS)
+            break;
+
+        r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERMANAGED, attr, buffer, buflen );
+        if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
+            return r;
+
+        r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, attr, buffer, buflen );
+        if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
+            return r;
+
+        r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_MACHINE, attr, buffer, buflen );
+        if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
+            return r;
+
+        index++;
+    }
+
+    return ERROR_UNKNOWN_PRODUCT;
+}
+
 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
 {
     LPWSTR szwLogFile = NULL;
 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
 {
     LPWSTR szwLogFile = NULL;
index 1475028..30daec9 100644 (file)
 175 stdcall MsiApplyPatchW(wstr wstr long wstr)
 176 stdcall MsiAdvertiseScriptA(str long ptr long)
 177 stdcall MsiAdvertiseScriptW(wstr long ptr long)
 175 stdcall MsiApplyPatchW(wstr wstr long wstr)
 176 stdcall MsiAdvertiseScriptA(str long ptr long)
 177 stdcall MsiAdvertiseScriptW(wstr long ptr long)
-178 stub MsiGetPatchInfoA
-179 stub MsiGetPatchInfoW
+178 stdcall MsiGetPatchInfoA(str str ptr ptr)
+179 stdcall MsiGetPatchInfoW(wstr wstr ptr ptr)
 180 stdcall MsiEnumPatchesA(str long ptr ptr ptr)
 181 stdcall MsiEnumPatchesW(str long ptr ptr ptr)
 182 stdcall -private DllGetVersion(ptr)
 180 stdcall MsiEnumPatchesA(str long ptr ptr ptr)
 181 stdcall MsiEnumPatchesW(str long ptr ptr ptr)
 182 stdcall -private DllGetVersion(ptr)
index 9864806..11525ad 100644 (file)
 
 #include "windef.h"
 
 
 #include "windef.h"
 
+/*UTF-8*/
+#pragma code_page(65001)
+
 LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
 
 STRINGTABLE DISCARDABLE
 {
 LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
 
 STRINGTABLE DISCARDABLE
 {
-       4 "The specified installation package could not be opened.  Please check the file path and try again."
+       4 "Impossibile aprire il pacchetto di installazione specificato.  Per favore controlla l'indirizzo del file e riprova."
        5 "percorso %s non trovato"
        9 "inserire disco %s"
        10 "parametri incorretti"
        11 "immettere il nome della cartella che contiene %s"
        5 "percorso %s non trovato"
        9 "inserire disco %s"
        10 "parametri incorretti"
        11 "immettere il nome della cartella che contiene %s"
-       12 "sorgente di installazione per la funzionalità mancante"
-       13 "periferica di rete per la funzionalità mancante"
-       14 "funzionalità da:"
+       12 "sorgente di installazione per la funzionalità mancante"
+       13 "periferica di rete per la funzionalità mancante"
+       14 "funzionalità da:"
        15 "selezionare la cartella che contiene %s"
 }
        15 "selezionare la cartella che contiene %s"
 }
+#pragma code_page(default)
index 43486e0..2278ff7 100644 (file)
@@ -961,6 +961,7 @@ extern UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package);
 extern UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package);
 extern UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package);
 extern UINT ACTION_RegisterFonts(MSIPACKAGE *package);
 extern UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package);
 extern UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package);
 extern UINT ACTION_RegisterFonts(MSIPACKAGE *package);
+extern UINT ACTION_UnregisterFonts(MSIPACKAGE *package);
 
 /* Helpers */
 extern DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data );
 
 /* Helpers */
 extern DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data );
@@ -981,8 +982,6 @@ extern void msi_free_action_script(MSIPACKAGE *package, UINT script);
 extern LPWSTR build_icon_path(MSIPACKAGE *, LPCWSTR);
 extern LPWSTR build_directory_name(DWORD , ...);
 extern BOOL create_full_pathW(const WCHAR *path);
 extern LPWSTR build_icon_path(MSIPACKAGE *, LPCWSTR);
 extern LPWSTR build_directory_name(DWORD , ...);
 extern BOOL create_full_pathW(const WCHAR *path);
-extern BOOL ACTION_VerifyComponentForAction(const MSICOMPONENT*, INSTALLSTATE);
-extern BOOL ACTION_VerifyFeatureForAction(const MSIFEATURE*, INSTALLSTATE);
 extern void reduce_to_longfilename(WCHAR*);
 extern LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
 extern void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
 extern void reduce_to_longfilename(WCHAR*);
 extern LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
 extern void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
@@ -1071,6 +1070,11 @@ static const WCHAR szFindRelatedProducts[] = {'F','i','n','d','R','e','l','a','t
 static const WCHAR szAllUsers[] = {'A','L','L','U','S','E','R','S',0};
 static const WCHAR szCustomActionData[] = {'C','u','s','t','o','m','A','c','t','i','o','n','D','a','t','a',0};
 static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0};
 static const WCHAR szAllUsers[] = {'A','L','L','U','S','E','R','S',0};
 static const WCHAR szCustomActionData[] = {'C','u','s','t','o','m','A','c','t','i','o','n','D','a','t','a',0};
 static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0};
+static const WCHAR szProductID[] = {'P','r','o','d','u','c','t','I','D',0};
+static const WCHAR szPIDTemplate[] = {'P','I','D','T','e','m','p','l','a','t','e',0};
+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};
 
 /* memory allocation macro functions */
 static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
 
 /* memory allocation macro functions */
 static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
index a814695..aa93436 100644 (file)
@@ -64,6 +64,7 @@ interface IWineMsiRemotePackage : IUnknown
     HRESULT SetTargetPath( [in] BSTR folder, [in] BSTR value );
     HRESULT GetSourcePath( [in] BSTR folder, [out] BSTR *value, [out] DWORD *size );
     HRESULT GetMode( [in] MSIRUNMODE mode, [out] BOOL *ret );
     HRESULT SetTargetPath( [in] BSTR folder, [in] BSTR value );
     HRESULT GetSourcePath( [in] BSTR folder, [out] BSTR *value, [out] DWORD *size );
     HRESULT GetMode( [in] MSIRUNMODE mode, [out] BOOL *ret );
+    HRESULT SetMode( [in] MSIRUNMODE mode, [in] BOOL state );
     HRESULT GetFeatureState( [in] BSTR feature, [out] INSTALLSTATE *installed, [out] INSTALLSTATE *action );
     HRESULT SetFeatureState( [in] BSTR feature, [in] INSTALLSTATE state );
     HRESULT GetComponentState( [in] BSTR component, [out] INSTALLSTATE *installed, [out] INSTALLSTATE *action );
     HRESULT GetFeatureState( [in] BSTR feature, [out] INSTALLSTATE *installed, [out] INSTALLSTATE *action );
     HRESULT SetFeatureState( [in] BSTR feature, [in] INSTALLSTATE state );
     HRESULT GetComponentState( [in] BSTR component, [out] INSTALLSTATE *installed, [out] INSTALLSTATE *action );
index 53804e2..ad6d4c6 100644 (file)
@@ -2104,6 +2104,13 @@ static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode
     return S_OK;
 }
 
     return S_OK;
 }
 
+static HRESULT WINAPI mrp_SetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL state )
+{
+    msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
+    UINT r = MsiSetMode(This->package, mode, state);
+    return HRESULT_FROM_WIN32(r);
+}
+
 static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
                                     INSTALLSTATE *installed, INSTALLSTATE *action )
 {
 static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
                                     INSTALLSTATE *installed, INSTALLSTATE *action )
 {
@@ -2196,6 +2203,7 @@ static const IWineMsiRemotePackageVtbl msi_remote_package_vtbl =
     mrp_SetTargetPath,
     mrp_GetSourcePath,
     mrp_GetMode,
     mrp_SetTargetPath,
     mrp_GetSourcePath,
     mrp_GetMode,
+    mrp_SetMode,
     mrp_GetFeatureState,
     mrp_SetFeatureState,
     mrp_GetComponentState,
     mrp_GetFeatureState,
     mrp_SetFeatureState,
     mrp_GetComponentState,
index 8d2e748..8ec2ad9 100644 (file)
@@ -32,6 +32,7 @@
 #include "query.h"
 
 #include "wine/debug.h"
 #include "query.h"
 
 #include "wine/debug.h"
+#include "wine/unicode.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msidb);
 
 
 WINE_DEFAULT_DEBUG_CHANNEL(msidb);
 
@@ -486,7 +487,8 @@ static INT add_streams_to_table(MSISTREAMSVIEW *sv)
     STATSTG stat;
     STREAM *stream = NULL;
     HRESULT hr;
     STATSTG stat;
     STREAM *stream = NULL;
     HRESULT hr;
-    UINT count = 0, size;
+    UINT r, count = 0, size;
+    LPWSTR encname;
 
     hr = IStorage_EnumElements(sv->db->storage, 0, NULL, 0, &stgenum);
     if (FAILED(hr))
 
     hr = IStorage_EnumElements(sv->db->storage, 0, NULL, 0, &stgenum);
     if (FAILED(hr))
@@ -505,7 +507,10 @@ static INT add_streams_to_table(MSISTREAMSVIEW *sv)
             break;
 
         if (stat.type != STGTY_STREAM)
             break;
 
         if (stat.type != STGTY_STREAM)
+        {
+            CoTaskMemFree(stat.pwcsName);
             continue;
             continue;
+        }
 
         /* table streams are not in the _Streams table */
         if (*stat.pwcsName == 0x4840)
 
         /* table streams are not in the _Streams table */
         if (*stat.pwcsName == 0x4840)
@@ -522,13 +527,22 @@ static INT add_streams_to_table(MSISTREAMSVIEW *sv)
             break;
         }
 
             break;
         }
 
-        hr = IStorage_OpenStream(sv->db->storage, stat.pwcsName, 0,
-                                 STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream);
+        if (!strcmpW(stat.pwcsName, szSumInfo))
+        {
+            /* summary information stream is not encoded */
+            r = db_get_raw_stream(sv->db, stat.pwcsName, &stream->stream);
+        }
+        else
+        {
+            encname = encode_streamname(FALSE, stat.pwcsName);
+            r = db_get_raw_stream(sv->db, encname, &stream->stream);
+            msi_free(encname);
+        }
         CoTaskMemFree(stat.pwcsName);
 
         CoTaskMemFree(stat.pwcsName);
 
-        if (FAILED(hr))
+        if (r != ERROR_SUCCESS)
         {
         {
-            WARN("failed to open stream: %08x\n", hr);
+            WARN("unable to get stream %u\n", r);
             count = -1;
             break;
         }
             count = -1;
             break;
         }
index df35c4d..902a61f 100644 (file)
@@ -86,9 +86,6 @@ static HRESULT (WINAPI *pPropVariantChangeType)
 
 #define SECT_HDR_SIZE (sizeof(PROPERTYSECTIONHEADER))
 
 
 #define SECT_HDR_SIZE (sizeof(PROPERTYSECTIONHEADER))
 
-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 void free_prop( PROPVARIANT *prop )
 {
     if (prop->vt == VT_LPSTR )
 static void free_prop( PROPVARIANT *prop )
 {
     if (prop->vt == VT_LPSTR )
index cc40515..6737ac5 100644 (file)
@@ -1168,7 +1168,7 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
 {
     MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
     UINT r;
 {
     MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
     UINT r;
-    LPWSTR full_name = NULL;
+    LPWSTR encname, full_name = NULL;
 
     if( !view->ops->fetch_int )
         return ERROR_INVALID_PARAMETER;
 
     if( !view->ops->fetch_int )
         return ERROR_INVALID_PARAMETER;
@@ -1180,11 +1180,13 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
         return r;
     }
 
         return r;
     }
 
-    r = db_get_raw_stream( tv->db, full_name, stm );
+    encname = encode_streamname( FALSE, full_name );
+    r = db_get_raw_stream( tv->db, encname, stm );
     if( r )
         ERR("fetching stream %s, error = %d\n",debugstr_w(full_name), r);
     if( r )
         ERR("fetching stream %s, error = %d\n",debugstr_w(full_name), r);
-    msi_free( full_name );
 
 
+    msi_free( full_name );
+    msi_free( encname );
     return r;
 }
 
     return r;
 }
 
index 0482456..e17ded8 100644 (file)
@@ -166,9 +166,9 @@ static int sqliteKeywordCode(const WCHAR *z, int n){
 */
 static const char isIdChar[] = {
 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
 */
 static const char isIdChar[] = {
 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x */
+    0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 1x */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 1x */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,  /* 2x */
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */
     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 4x */
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 5x */
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */
     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 4x */
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 5x */
index 5c2f38c..b331057 100644 (file)
@@ -503,6 +503,10 @@ UINT WINAPI MsiGetPatchInfoExA(LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR
 UINT WINAPI MsiGetPatchInfoExW(LPCWSTR, LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, LPCWSTR, LPWSTR, LPDWORD);
 #define     MsiGetPatchInfoEx WINELIB_NAME_AW(MsiGetPatchInfoEx)
 
 UINT WINAPI MsiGetPatchInfoExW(LPCWSTR, LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, LPCWSTR, LPWSTR, LPDWORD);
 #define     MsiGetPatchInfoEx WINELIB_NAME_AW(MsiGetPatchInfoEx)
 
+UINT WINAPI MsiGetPatchInfoA(LPCSTR, LPCSTR, LPSTR, LPDWORD);
+UINT WINAPI MsiGetPatchInfoW(LPCWSTR, LPCWSTR, LPWSTR, LPDWORD);
+#define     MsiGetPatchInfo WINELIB_NAME_AW(MsiGetPatchInfo)
+
 UINT WINAPI MsiEnableLogA(DWORD, LPCSTR, DWORD);
 UINT WINAPI MsiEnableLogW(DWORD, LPCWSTR, DWORD);
 #define     MsiEnableLog WINELIB_NAME_AW(MsiEnableLog)
 UINT WINAPI MsiEnableLogA(DWORD, LPCSTR, DWORD);
 UINT WINAPI MsiEnableLogW(DWORD, LPCWSTR, DWORD);
 #define     MsiEnableLog WINELIB_NAME_AW(MsiEnableLog)