From e0371a4c142ae69d5420c3eed6118db4f6c35734 Mon Sep 17 00:00:00 2001
From: Ivo Hinkelmann <ihi@openoffice.org>
Date: Thu, 2 Apr 2009 13:31:45 +0000
Subject: CWS-TOOLING: integrate CWS dv10 2009-03-10 11:09:48 +0100 dv  r269257
 : #158915# Check msi version before checking patches, better logging
 2009-02-27 14:48:58 +0100 dv  r268594 : #i99154# Added missing string,
 removed wrong svn flags 2009-02-26 16:07:25 +0100 dv  r268531 : Removed
 superfluous file 2009-02-26 13:49:01 +0100 dv  r268514 : CWS-TOOLING: rebase
 CWS dv10 to trunk@268395 (milestone: DEV300:m42) 2009-02-26 08:13:32 +0100 dv
  r268479 : #i86963# Listen to dispose events for xPackages 2009-02-12
 15:40:06 +0100 dv  r267668 : #i99154# Added missing string 2009-02-03
 11:47:11 +0100 dv  r267308 : #i73966# Ask for confirmation when removing an
 extension 2009-01-30 09:27:52 +0100 dv  r267175 : #158915# Check for already
 installed patches to allow launching the setup in maintainance mode

---
 desktop/source/deployment/gui/dp_gui.hrc         |   2 +-
 desktop/source/deployment/gui/dp_gui_dialog.src  |  10 +-
 desktop/source/deployment/gui/dp_gui_dialog2.cxx | 175 ++++++++++-------------
 desktop/source/deployment/gui/dp_gui_dialog2.hxx |   2 +-
 desktop/win32/source/setup/makefile.mk           |   2 +-
 desktop/win32/source/setup/setup.cpp             | 106 ++++++++++++--
 desktop/win32/source/setup/setup.hxx             |   4 +-
 desktop/win32/source/setup/setup_main.cxx        |   6 +-
 8 files changed, 186 insertions(+), 121 deletions(-)

(limited to 'desktop')

diff --git a/desktop/source/deployment/gui/dp_gui.hrc b/desktop/source/deployment/gui/dp_gui.hrc
index a85b764da3e9..ada1b58b8de3 100644
--- a/desktop/source/deployment/gui/dp_gui.hrc
+++ b/desktop/source/deployment/gui/dp_gui.hrc
@@ -204,7 +204,7 @@
 
 #define RID_STR_UNSUPPORTED_PLATFORM            (RID_DEPLOYMENT_GUI_START+101)
 #define RID_WARNINGBOX_UPDATE_SHARED_EXTENSION  (RID_DEPLOYMENT_GUI_START+102)
-#define RID_WARNINGBOX_ADD_SHARED_EXTENSION     (RID_DEPLOYMENT_GUI_START+103)
+#define RID_WARNINGBOX_REMOVE_EXTENSION         (RID_DEPLOYMENT_GUI_START+103)
 #define RID_WARNINGBOX_REMOVE_SHARED_EXTENSION  (RID_DEPLOYMENT_GUI_START+104)
 #define RID_WARNINGBOX_ENABLE_SHARED_EXTENSION  (RID_DEPLOYMENT_GUI_START+105)
 #define RID_WARNINGBOX_DISABLE_SHARED_EXTENSION (RID_DEPLOYMENT_GUI_START+106)
diff --git a/desktop/source/deployment/gui/dp_gui_dialog.src b/desktop/source/deployment/gui/dp_gui_dialog.src
index 96f49555190d..d3730a12536e 100644
--- a/desktop/source/deployment/gui/dp_gui_dialog.src
+++ b/desktop/source/deployment/gui/dp_gui_dialog.src
@@ -486,14 +486,12 @@ WarningBox RID_WARNINGBOX_INSTALL_EXTENSION {
     "Click \'Cancel\' to stop the installation.";
 };
 
-WARNINGBOX RID_WARNINGBOX_ADD_SHARED_EXTENSION
-{
+WarningBox RID_WARNINGBOX_REMOVE_EXTENSION {
     Buttons = WB_OK_CANCEL;
     DefButton = WB_DEF_CANCEL;
-    Message[en-US] = "Make sure that no further users are working with the same "
-    "%PRODUCTNAME, when changing shared extensions in a multi user environment.\n"
-    "Click \'OK\' to install the extension.\n"
-    "Click \'Cancel\' to stop the installation.";
+    Message[en-US] = "You are about to remove the extension \'%NAME\'.\n"
+    "Click \'OK\' to remove the extension.\n"
+    "Click \'Cancel\' to stop removing the extension.";
 };
 
 WARNINGBOX RID_WARNINGBOX_REMOVE_SHARED_EXTENSION
diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.cxx b/desktop/source/deployment/gui/dp_gui_dialog2.cxx
index 63c6bcc32388..47bcd507cd90 100644
--- a/desktop/source/deployment/gui/dp_gui_dialog2.cxx
+++ b/desktop/source/deployment/gui/dp_gui_dialog2.cxx
@@ -55,6 +55,7 @@
 
 #include "comphelper/anytostring.hxx"
 #include "cppuhelper/exc_hlp.hxx"
+#include "cppuhelper/implbase1.hxx"
 
 #include "comphelper/processfactory.hxx"
 #include "ucbhelper/content.hxx"
@@ -229,7 +230,8 @@ enum MENU_COMMAND
     CMD_UPDATE
 };
 
-class ExtensionBox_Impl : public ::svt::IExtensionListBox
+class ExtensionBox_Impl : public ::svt::IExtensionListBox,
+                          public ::cppu::WeakImplHelper1< ::com::sun::star::lang::XEventListener >
 {
     bool            m_bHasScrollBar;
     bool            m_bHasActive;
@@ -317,7 +319,6 @@ public:
     void            enableButtons( bool bEnable );
 
     void            updateEntry( const uno::Reference< deployment::XPackage > &xPackage );
-    void            removeEntry( const uno::Reference< deployment::XPackage > &xPackage );
 
     void            prepareChecking( const uno::Reference< deployment::XPackageManager > &xPackageMgr );
     void            checkEntries();
@@ -373,7 +374,11 @@ public:
             2. one extension can be installed as user and shared extension.
     */
     virtual void select( const OUString & sName );
+
     //===================================================================================
+    // XEventListener
+    virtual void SAL_CALL disposing( ::com::sun::star::lang::EventObject const & evt )
+        throw (::com::sun::star::uno::RuntimeException);
 };
 
 //------------------------------------------------------------------------------
@@ -461,6 +466,13 @@ ExtensionBox_Impl::ExtensionBox_Impl( ExtMgrDialog* pParent, TheExtensionManager
 //------------------------------------------------------------------------------
 ExtensionBox_Impl::~ExtensionBox_Impl()
 {
+    typedef std::vector< TEntry_Impl >::iterator ITER;
+
+//    for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex )
+//        (*iIndex)->m_xPackage->removeEventListener( this );
+
+    m_vEntries.clear();
+
     delete m_pOptionsBtn;
     delete m_pEnableBtn;
     delete m_pRemoveBtn;
@@ -1249,41 +1261,6 @@ bool ExtensionBox_Impl::FindEntryPos( const TEntry_Impl pEntry, const long nStar
     }
 }
 
-//------------------------------------------------------------------------------
-void ExtensionBox_Impl::removeEntry( const uno::Reference< deployment::XPackage > &xPackage )
-{
-    ::osl::ClearableMutexGuard aGuard( m_entriesMutex );
-    typedef std::vector< TEntry_Impl >::iterator ITER;
-
-    for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex )
-    {
-        if ( (*iIndex)->m_xPackage == xPackage )
-        {
-            long nPos = iIndex - m_vEntries.begin();
-
-            m_vEntries.erase( iIndex );
-
-            if ( IsReallyVisible() )
-                Invalidate();
-
-            if ( m_bHasActive )
-            {
-                if ( nPos < m_nActive )
-                    m_nActive -= 1;
-                else if ( ( nPos == m_nActive ) &&
-                          ( nPos == (long) m_vEntries.size() ) )
-                    m_nActive -= 1;
-
-                m_bHasActive = false;
-                //clear before calling out of this method
-                aGuard.clear();
-                selectEntry( m_nActive );
-            }
-            break;
-        }
-    }
-}
-
 //------------------------------------------------------------------------------
 long ExtensionBox_Impl::addEntry( const uno::Reference< deployment::XPackage > &xPackage,
                                   const uno::Reference< deployment::XPackageManager > &xPackageManager )
@@ -1292,6 +1269,7 @@ long ExtensionBox_Impl::addEntry( const uno::Reference< deployment::XPackage > &
     PackageState eState = m_pManager->getPackageState( xPackage );
 
     TEntry_Impl pEntry( new Entry_Impl( xPackage, xPackageManager, eState ) );
+    xPackage->addEventListener( this );
 
     ::osl::ClearableMutexGuard guard(m_entriesMutex);
     if ( m_vEntries.empty() )
@@ -1377,14 +1355,12 @@ void ExtensionBox_Impl::checkEntries()
     long nNewPos = -1;
     long nPos = 0;
     bool bNeedsUpdate = false;
-    bool bReselectActive = false;
 
     ::osl::ClearableMutexGuard guard(m_entriesMutex);
     typedef std::vector< TEntry_Impl >::iterator ITER;
     ITER iIndex = m_vEntries.begin();
     while ( iIndex < m_vEntries.end() )
     {
-        BOOL bNext = true;
         if ( (*iIndex)->m_bChecked == false )
         {
             bNeedsUpdate = true;
@@ -1396,26 +1372,8 @@ void ExtensionBox_Impl::checkEntries()
                 if ( nPos <= m_nActive )
                     m_nActive += 1;
             }
-            else
-            {
-                //We reach this point when we updated an extension.
-                iIndex = m_vEntries.erase( iIndex );
-                bNext = false;
-
-                if ( m_bHasActive )
-                {
-                    if ( nPos < m_nActive )
-                        m_nActive -= 1;
-                    else if ( nPos == m_nActive )
-                    {
-                        m_bHasActive = false;
-                        bReselectActive = true;
-                    }
-                }
-            }
         }
-        if ( bNext )
-            iIndex++;
+        iIndex++;
     }
     guard.clear();
 
@@ -1423,15 +1381,6 @@ void ExtensionBox_Impl::checkEntries()
 
     if ( nNewPos != - 1)
         selectEntry( nNewPos );
-    else if ( bReselectActive )
-    {
-        {
-            ::osl::MutexGuard guard2(m_entriesMutex);
-            if ( m_nActive >= (long) m_vEntries.size() )
-                m_nActive = (long) m_vEntries.size() - 1;
-        }
-        selectEntry( m_nActive );
-    }
 
     if ( bNeedsUpdate )
     {
@@ -1446,30 +1395,6 @@ bool ExtensionBox_Impl::isHCMode()
     return (bool)GetDisplayBackground().GetColor().IsDark();
 }
 
-//------------------------------------------------------------------------------
-/*void ExtensionBox_Impl::DataChanged( DataChangedEvent const & evt )
-{
-    SvTreeListBox::DataChanged( evt );
-    if (evt.GetType() == DATACHANGED_SETTINGS &&
-        (evt.GetFlags() & SETTINGS_STYLE) != 0 &&
-        m_hiContrastMode != (bool)GetDisplayBackground().GetColor().IsDark())
-    {
-        m_hiContrastMode = ! m_hiContrastMode;
-
-        // Update all images as we changed from/to high contrast mode:
-        for ( SvLBoxEntry * entry = First(); entry != 0; entry = Next(entry) )
-        {
-            NodeImpl * node = NodeImpl::get(entry);
-            Image img( node->getIcon() );
-            SetExpandedEntryBmp( entry, img );
-            SetCollapsedEntryBmp( entry, img );
-        }
-
-        // force redraw:
-        Invalidate();
-    }
-}
-*/
 //------------------------------------------------------------------------------
 void ExtensionBox_Impl::enableButtons( bool bEnable )
 {
@@ -1488,6 +1413,48 @@ void ExtensionBox_Impl::enableButtons( bool bEnable )
     }
 }
 
+//------------------------------------------------------------------------------
+// XEventListener
+void ExtensionBox_Impl::disposing( lang::EventObject const & rEvt )
+    throw ( uno::RuntimeException )
+{
+    uno::Reference< deployment::XPackage > xPackage( rEvt.Source, uno::UNO_QUERY );
+
+    if ( xPackage.is() )
+    {
+        ::osl::ClearableMutexGuard aGuard( m_entriesMutex );
+        typedef std::vector< TEntry_Impl >::iterator ITER;
+
+        for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex )
+        {
+            if ( (*iIndex)->m_xPackage == xPackage )
+            {
+                long nPos = iIndex - m_vEntries.begin();
+
+                m_vEntries.erase( iIndex );
+
+                if ( IsReallyVisible() )
+                    Invalidate();
+
+                if ( m_bHasActive )
+                {
+                    if ( nPos < m_nActive )
+                        m_nActive -= 1;
+                    else if ( ( nPos == m_nActive ) &&
+                              ( nPos == (long) m_vEntries.size() ) )
+                        m_nActive -= 1;
+
+                    m_bHasActive = false;
+                    //clear before calling out of this method
+                    aGuard.clear();
+                    selectEntry( m_nActive );
+                }
+                break;
+            }
+        }
+    }
+}
+
 // -----------------------------------------------------------------------
 IMPL_LINK( ExtensionBox_Impl, ScrollHdl, ScrollBar*, pScrBar )
 {
@@ -1793,6 +1760,19 @@ bool ExtMgrDialog::installExtensionWarn( const OUString &rExtensionName ) const
     return ( RET_OK == aInfo.Execute() );
 }
 
+//------------------------------------------------------------------------------
+bool ExtMgrDialog::removeExtensionWarn( const OUString &rExtensionName ) const
+{
+    const ::vos::OGuard guard( Application::GetSolarMutex() );
+    WarningBox aInfo( const_cast< ExtMgrDialog* >(this), getResId( RID_WARNINGBOX_REMOVE_EXTENSION ) );
+
+    String sText( aInfo.GetMessText() );
+    sText.SearchAndReplaceAllAscii( "%NAME", rExtensionName );
+    aInfo.SetMessText( sText );
+
+    return ( RET_OK == aInfo.Execute() );
+}
+
 //------------------------------------------------------------------------------
 bool ExtMgrDialog::enablePackage( const uno::Reference< deployment::XPackageManager > &xPackageManager,
                                   const uno::Reference< deployment::XPackage > &xPackage,
@@ -1824,6 +1804,12 @@ bool ExtMgrDialog::removePackage( const uno::Reference< deployment::XPackageMana
     if ( !xPackageManager.is() || !xPackage.is() )
         return false;
 
+    if ( !IsSharedPkgMgr( xPackageManager ) || m_bDeleteWarning )
+    {
+        if ( ! removeExtensionWarn( xPackage->getDisplayName() ) )
+            return false;
+    }
+
     if ( ! continueOnSharedExtension( xPackageManager, RID_WARNINGBOX_REMOVE_SHARED_EXTENSION, m_bDeleteWarning ) )
         return false;
 
@@ -2014,13 +2000,6 @@ void ExtMgrDialog::updatePackageInfo( const uno::Reference< deployment::XPackage
     m_pExtensionBox->updateEntry( xPackage );
 }
 
-//------------------------------------------------------------------------------
-void ExtMgrDialog::removeEntry( const uno::Reference< deployment::XPackage > &xPackage )
-{
-    const vos::OGuard aGuard( Application::GetSolarMutex() );
-    m_pExtensionBox->removeEntry( xPackage );
-}
-
 // -----------------------------------------------------------------------
 IMPL_LINK( ExtMgrDialog, HandleAddBtn, void*, EMPTYARG )
 {
diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.hxx b/desktop/source/deployment/gui/dp_gui_dialog2.hxx
index 2deaad268ec3..bab8d52828a9 100644
--- a/desktop/source/deployment/gui/dp_gui_dialog2.hxx
+++ b/desktop/source/deployment/gui/dp_gui_dialog2.hxx
@@ -91,6 +91,7 @@ class ExtMgrDialog : public ModelessDialog
     bool continueOnSharedExtension( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackageManager > &,
                                     const USHORT nResID,
                                     bool &bHadWarning ) const;
+    bool removeExtensionWarn( const ::rtl::OUString &rExtensionTitle ) const;
 
     DECL_DLLPRIVATE_LINK( HandleAddBtn, void * );
     DECL_DLLPRIVATE_LINK( HandleUpdateBtn, void * );
@@ -126,7 +127,6 @@ public:
                                     const ::com::sun::star::uno::Reference< ::com::sun::star::task::XAbortChannel > &xAbortChannel);
     void            updateProgress( const long nProgress );
     void            updatePackageInfo( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage );
-    void            removeEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage );
 
     void            prepareChecking( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackageManager > &xPackageManager );
     void            checkEntries();
diff --git a/desktop/win32/source/setup/makefile.mk b/desktop/win32/source/setup/makefile.mk
index 5c8f471f0938..1453e896679f 100644
--- a/desktop/win32/source/setup/makefile.mk
+++ b/desktop/win32/source/setup/makefile.mk
@@ -75,7 +75,7 @@ LIBSALCPPRT=	$(0)
 APP1NOSAL=		TRUE
 APP1TARGET=		loader2
 
-APP1STDLIBS=	$(GDI32LIB) $(ADVAPI32LIB) $(SHELL32LIB)
+APP1STDLIBS=	$(GDI32LIB) $(ADVAPI32LIB) $(SHELL32LIB) $(MSILIB)
 .IF "$(COM)"!="GCC"
 APP1STDLIBS+=	libcmt.lib
 .ENDIF
diff --git a/desktop/win32/source/setup/setup.cpp b/desktop/win32/source/setup/setup.cpp
index 2782a8de3025..d0619ab11963 100644
--- a/desktop/win32/source/setup/setup.cpp
+++ b/desktop/win32/source/setup/setup.cpp
@@ -44,7 +44,8 @@
 #include <time.h>
 #include <mbctype.h>
 #include <locale.h>
-
+#include <Msiquery.h>
+#include <MsiDefs.h>
 #include "strsafe.h"
 
 #include "setup.hxx"
@@ -147,6 +148,7 @@ SetupAppX::SetupAppX()
     m_bRegNoMsoTypes  = false;
     m_bRegAllMsoTypes = false;
     m_bIsMinorUpgrade = false;
+    m_bSupportsPatch  = false;
 
     m_bIgnoreAlreadyRunning = false;
 }
@@ -446,6 +448,21 @@ boolean SetupAppX::ReadProfile()
     return bRet;
 }
 
+//--------------------------------------------------------------------------
+void SetupAppX::AddFileToPatchList( TCHAR* pPath, TCHAR* pFile )
+{
+    if ( m_pPatchFiles == NULL )
+    {
+        m_pPatchFiles = new TCHAR[ MAX_STR_LENGTH ];
+        StringCchCopy( m_pPatchFiles, MAX_STR_LENGTH, TEXT("\"") );
+    }
+    else
+        StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, TEXT(";") );
+
+    StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, pPath );
+    StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, pFile );
+}
+
 //--------------------------------------------------------------------------
 boolean SetupAppX::GetPatches()
 {
@@ -475,19 +492,18 @@ boolean SetupAppX::GetPatches()
 
         if ( hFindPatches != INVALID_HANDLE_VALUE )
         {
-            bool fNextFile = false;
-            m_pPatchFiles = new TCHAR[ MAX_STR_LENGTH ];
-            StringCchCopy( m_pPatchFiles, MAX_STR_LENGTH, TEXT("\"") );
-            StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, pBaseDir );
-            StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, aFindFileData.cFileName );
+            if ( ! IsPatchInstalled( pBaseDir, aFindFileData.cFileName ) )
+                AddFileToPatchList( pBaseDir, aFindFileData.cFileName );
 
             while ( FindNextFile( hFindPatches, &aFindFileData ) )
             {
-                StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, TEXT(";") );
-                StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, pBaseDir );
-                StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, aFindFileData.cFileName );
+                if ( ! IsPatchInstalled( pBaseDir, aFindFileData.cFileName ) )
+                    AddFileToPatchList( pBaseDir, aFindFileData.cFileName );
             }
-            StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, TEXT("\"") );
+
+            if ( m_pPatchFiles != NULL )
+                StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, TEXT("\"") );
+
             FindClose( hFindPatches );
         }
     }
@@ -1175,6 +1191,10 @@ boolean SetupAppX::CheckVersion()
                     Log( TEXT( " Found MSI version <%s>, no update needed\r\n" ), pMsiVersion );
                     bNeedUpdate = false;
                 }
+                if ( aInfo.dwMajorVersion >= 3 )
+                    m_bSupportsPatch = true;
+                else
+                    Log( TEXT("Warning: Patching not supported! MSI-Version <%s>\r\n"), pMsiVersion );
             }
         }
 
@@ -1492,9 +1512,15 @@ void SetupAppX::Log( LPCTSTR pMessage, LPCTSTR pText ) const
                                    _tsetlocale( LC_ALL, NULL ), _getmbcp() );
         }
         if ( pText )
+        {
             _ftprintf( m_pLogFile, pMessage, pText );
+            OutputDebugStringFormat( pMessage, pText );
+        }
         else
+        {
             _ftprintf( m_pLogFile, pMessage );
+            OutputDebugStringFormat( pMessage );
+        }
 
         fflush( m_pLogFile );
     }
@@ -1924,6 +1950,66 @@ LPTSTR SetupAppX::SetProdToAppTitle( LPCTSTR pProdName )
     return m_pAppTitle;
 }
 
+
+//--------------------------------------------------------------------------
+boolean SetupAppX::IsPatchInstalled( TCHAR* pBaseDir, TCHAR* pFileName )
+{
+    if ( !m_bSupportsPatch )
+        return false;
+
+    PMSIHANDLE hSummaryInfo;
+    int nLen = lstrlen( pBaseDir ) + lstrlen( pFileName ) + 1;
+    TCHAR *szDatabasePath = new TCHAR [ nLen ];
+    TCHAR sBuf[80];
+
+    StringCchCopy( szDatabasePath, nLen, pBaseDir );
+    StringCchCat( szDatabasePath, nLen, pFileName );
+
+    UINT nRet = MsiGetSummaryInformation( NULL, szDatabasePath, 0, &hSummaryInfo );
+
+    if ( nRet != ERROR_SUCCESS )
+    {
+        StringCchPrintf( sBuf, 80, TEXT("ERROR: IsPatchInstalled: MsiGetSummaryInformation returned %u.\r\n"), nRet );
+        Log( sBuf );
+        return false;
+    }
+
+    UINT    uiDataType;
+    LPTSTR  szPatchID = new TCHAR[ 64 ];
+    DWORD   cchValueBuf = 64;
+    nRet = MsiSummaryInfoGetProperty( hSummaryInfo, PID_REVNUMBER, &uiDataType, NULL, NULL, szPatchID, &cchValueBuf );
+
+    if ( nRet != ERROR_SUCCESS )
+    {
+        StringCchPrintf( sBuf, 80, TEXT("ERROR: IsPatchInstalled: MsiSummaryInfoGetProperty returned %u.\r\n"), nRet );
+        Log( sBuf );
+        return false;
+    }
+
+    nRet = MsiGetPatchInfo( szPatchID, INSTALLPROPERTY_LOCALPACKAGE, NULL, NULL );
+
+    StringCchPrintf( sBuf, 80, TEXT("  GetPatchInfo for (%s) returned (%u)\r\n"), szPatchID, nRet );
+    Log( sBuf );
+
+    delete []szPatchID;
+
+    if ( nRet == ERROR_BAD_CONFIGURATION )
+        return false;
+    else if ( nRet == ERROR_INVALID_PARAMETER )
+        return false;
+    else if ( nRet == ERROR_MORE_DATA )
+        return true;
+    else if ( nRet == ERROR_SUCCESS )
+        return true;
+    else if ( nRet == ERROR_UNKNOWN_PRODUCT )
+        return false;
+    else if ( nRet == ERROR_UNKNOWN_PROPERTY )
+        return false;
+    else return false;
+
+    return false;
+}
+
 //--------------------------------------------------------------------------
 //--------------------------------------------------------------------------
 LanguageDataX::LanguageDataX( LPTSTR pData )
diff --git a/desktop/win32/source/setup/setup.hxx b/desktop/win32/source/setup/setup.hxx
index 7e651df5dec7..d74947fa47f2 100644
--- a/desktop/win32/source/setup/setup.hxx
+++ b/desktop/win32/source/setup/setup.hxx
@@ -93,6 +93,7 @@ class SetupAppX : public SetupApp
     boolean     m_bRegNoMsoTypes :1;
     boolean     m_bRegAllMsoTypes :1;
     boolean     m_bIsMinorUpgrade :1;
+    boolean     m_bSupportsPatch :1;
 
     FILE       *m_pLogFile;
 
@@ -125,7 +126,8 @@ private:
     boolean     InstallMsi( LPCTSTR pInstaller );
 
     boolean     IsTerminalServerInstalled() const;
-
+    void        AddFileToPatchList( TCHAR* pPath, TCHAR* pFile );
+    boolean     IsPatchInstalled( TCHAR* pBaseDir, TCHAR* pFileName );
 public:
                     SetupAppX();
                    ~SetupAppX();
diff --git a/desktop/win32/source/setup/setup_main.cxx b/desktop/win32/source/setup/setup_main.cxx
index 24b542a17e8b..b8b54c8f7550 100644
--- a/desktop/win32/source/setup/setup_main.cxx
+++ b/desktop/win32/source/setup/setup_main.cxx
@@ -111,13 +111,13 @@ extern "C" int __stdcall WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int )
         if ( ! pSetup->ReadProfile() )
             throw pSetup->GetError();
 
+        if ( ! pSetup->CheckVersion() )
+            throw pSetup->GetError();
+
         if ( ! pSetup->IsAdminInstall() )
             if ( ! pSetup->GetPatches() )
                 throw pSetup->GetError();
 
-        if ( ! pSetup->CheckVersion() )
-            throw pSetup->GetError();
-
         // CheckForUpgrade() has to be called after calling GetPatches()!
         if ( ! pSetup->CheckForUpgrade() )
             throw pSetup->GetError();
-- 
cgit