diff options
author | Tor Lillqvist <tml@iki.fi> | 2013-01-08 23:47:02 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@suse.cz> | 2013-01-10 09:32:36 +0000 |
commit | 26c142ca5f2b405b02ab5701dfaeab7bf281a727 (patch) | |
tree | 5f13ab387169c4a17ce6c1304430e23eb49f868d /setup_native/source | |
parent | a5838b19bc774efd261c1d6c78a2b6eb62f1b502 (diff) |
Kill the ancient StarOffice "patch" concept
For Windows, superseded by Windows Installer patching (i.e., creating
.msp files), which is something completely different. (And quite hard
to get working... but still a saner approach, I think.)
For Linux, many distros use delta RPMs or similar, so no home-grown
LO-specific patching mechanism is needed.
Remove the -patch and -patchinc command-line options to
make_installer.pl and all code that was invoked only when using those.
Remove the PATCH and PATCH_ONLY flags in scp2.
Remove the patchmsi.dll Windows Installer custom action.
Change-Id: I09e949e601a969f88eff60067faa2352f4f89537
Reviewed-on: https://gerrit.libreoffice.org/1605
Reviewed-by: Michael Stahl <mstahl@redhat.com>
Tested-by: Miklos Vajna <vmiklos@suse.cz>
Diffstat (limited to 'setup_native/source')
4 files changed, 1 insertions, 832 deletions
diff --git a/setup_native/source/win32/customactions/languagepacks/respintest.cxx b/setup_native/source/win32/customactions/languagepacks/respintest.cxx index 3362a7ad7e82..f757a880f912 100644 --- a/setup_native/source/win32/customactions/languagepacks/respintest.cxx +++ b/setup_native/source/win32/customactions/languagepacks/respintest.cxx @@ -150,38 +150,7 @@ extern "C" UINT __stdcall GetUserInstallMode(MSIHANDLE handle) return ERROR_SUCCESS; } - // 3. Only for patch: Comparing "PRODUCTMINOR from property table and "ProductMinor" from InfoFile - - string isPatch = GetMsiProperty(handle, TEXT("ISPATCH")); - - if (isPatch=="1") - { - string ProductMinor = GetMsiProperty(handle, TEXT("PRODUCTBUILDID")); - int PatchProductMinor = atoi(ProductMinor.c_str()); - - szValue[0] = '\0'; - - GetPrivateProfileString( - TEXT("Bootstrap"), - TEXT("ProductBuildid"), - TEXT("8918"), - szValue, - SAL_N_ELEMENTS(szValue), - sSetupiniPath.c_str() - ); - - int InstalledProductMinor = atoi(szValue); - - if ( InstalledProductMinor >= PatchProductMinor ) - { - SetMsiProperty( handle, TEXT("PATCHISOLDER"), TEXT("YES") ); - // MessageBox(NULL, "PATCHISOLDER set", "DEBUG", MB_OK); - SetMsiErrorCode( MSI_ERROR_PATCHISOLDER ); - return ERROR_SUCCESS; - } - } - - // 4. Setting property ALLUSERS with value from "setup.ini" + // 3. Setting property ALLUSERS with value from "setup.ini" szValue[0] = '\0'; diff --git a/setup_native/source/win32/customactions/patch/exports.dxp b/setup_native/source/win32/customactions/patch/exports.dxp deleted file mode 100644 index bb660772a68b..000000000000 --- a/setup_native/source/win32/customactions/patch/exports.dxp +++ /dev/null @@ -1,8 +0,0 @@ -InstallPatchedFiles -UninstallPatchedFiles -GetUserInstallMode -SetProductInstallMode -ShutDownQuickstarter -SetFeatureState -SetNewFeatureState -ShowOnlineUpdateDialog diff --git a/setup_native/source/win32/customactions/patch/makefile.mk b/setup_native/source/win32/customactions/patch/makefile.mk deleted file mode 100644 index 81ff1c4878f7..000000000000 --- a/setup_native/source/win32/customactions/patch/makefile.mk +++ /dev/null @@ -1,75 +0,0 @@ -# -# This file is part of the LibreOffice project. -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. -# -# This file incorporates work covered by the following license notice: -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed -# with this work for additional information regarding copyright -# ownership. The ASF licenses this file to you under the Apache -# License, Version 2.0 (the "License"); you may not use this file -# except in compliance with the License. You may obtain a copy of -# the License at http://www.apache.org/licenses/LICENSE-2.0 . -# - -PRJ=..$/..$/..$/.. -PRJNAME=setup_native -TARGET=patchmsi - -# --- Settings ----------------------------------------------------- - -ENABLE_EXCEPTIONS=TRUE -NO_DEFAULT_STL=TRUE -DYNAMIC_CRT= -USE_DEFFILE=TRUE - -.INCLUDE : settings.mk - -# --- Files -------------------------------------------------------- - -.IF "$(OS)"=="WNT" && "$(WINDOWS_SDK_HOME)"!="" - -UWINAPILIB= - -SLOFILES = \ - $(SLO)$/swappatchfiles.obj - -STDSHL += \ - $(ADVAPI32LIB)\ - $(MSILIB)\ - $(SHELL32LIB) - -.IF "$(COM)"=="GCC" -STDSHL+= \ - $(KERNEL32LIB)\ - -lmsvcrt -.ENDIF - - -SHL1OBJS = $(SLOFILES) \ - $(SLO)$/respintest.obj \ - $(SLO)$/shutdown_quickstart.obj \ - $(SLO)$/quickstarter.obj \ - $(SLO)$/upgrade.obj \ - $(SLO)$/seterror.obj - -SHL1TARGET = $(TARGET) -SHL1IMPLIB = i$(TARGET) - -SHL1DEF = $(MISC)$/$(SHL1TARGET).def -SHL1DEPN = $(SLB)$/$(TARGET).lib -SHL1BASE = 0x1c000000 -DEF1NAME=$(SHL1TARGET) -DEF1EXPORTFILE=exports.dxp - -.ENDIF - -# --- Targets -------------------------------------------------------------- - -.INCLUDE : target.mk - -# ------------------------------------------------------------------------- diff --git a/setup_native/source/win32/customactions/patch/swappatchfiles.cxx b/setup_native/source/win32/customactions/patch/swappatchfiles.cxx deleted file mode 100644 index f2eb25428b6c..000000000000 --- a/setup_native/source/win32/customactions/patch/swappatchfiles.cxx +++ /dev/null @@ -1,717 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#define _WIN32_WINDOWS 0x0410 - -#ifdef _MSC_VER -#pragma warning(push, 1) /* disable warnings within system headers */ -#endif -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <msiquery.h> -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include <malloc.h> -#include <assert.h> - -#ifdef UNICODE -#define _UNICODE -#define _tstring wstring -#else -#define _tstring string -#endif -#include <tchar.h> -#include <string> -#include <queue> -#include <stdio.h> -#include <sal/macros.h> - -#include <systools/win32/uwinapi.h> -#include <../tools/seterror.hxx> - -#ifdef DEBUG -inline void OutputDebugStringFormat( LPCTSTR pFormat, ... ) -{ - _TCHAR buffer[1024]; - va_list args; - - va_start( args, pFormat ); - _vsntprintf( buffer, SAL_N_ELEMENTS(buffer), pFormat, args ); - OutputDebugString( buffer ); -} -#else -static inline void OutputDebugStringFormat( LPCTSTR, ... ) -{ -} -#endif - -static std::_tstring GetMsiProperty( MSIHANDLE handle, const std::_tstring& sProperty ) -{ - std::_tstring result; - TCHAR szDummy[1] = TEXT(""); - DWORD nChars = 0; - - if ( MsiGetProperty( handle, sProperty.c_str(), szDummy, &nChars ) == ERROR_MORE_DATA ) - { - DWORD nBytes = ++nChars * sizeof(TCHAR); - LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes)); - ZeroMemory( buffer, nBytes ); - MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars); - result = buffer; - } - - return result; -} - -// The provided GUID must be without surounding '{}' -static std::_tstring GetGuidPart(const std::_tstring& guid, int index) -{ - assert((guid.length() == 36) && "No GUID or wrong format!"); - assert(((index > -1) && (index < 5)) && "Out of range!"); - - if (index == 0) return std::_tstring(guid.c_str(), 8); - if (index == 1) return std::_tstring(guid.c_str() + 9, 4); - if (index == 2) return std::_tstring(guid.c_str() + 14, 4); - if (index == 3) return std::_tstring(guid.c_str() + 19, 4); - if (index == 4) return std::_tstring(guid.c_str() + 24, 12); - - return std::_tstring(); -} - -static void Swap(char* p1, char* p2) -{ - char tmp = *p1; - *p1 = *p2; - *p2 = tmp; -} - -static std::_tstring Invert(const std::_tstring& str) -{ - char* buff = reinterpret_cast<char*>(_alloca(str.length())); - strncpy(buff, str.c_str(), str.length()); - - char* front = buff; - char* back = buff + str.length() - 1; - - while (front < back) - Swap(front++, back--); - - return std::_tstring(buff, str.length()); -} - -// Convert the upgrade code (which is a GUID) according -// to the way the windows installer does when writing it -// to the registry -// The first 8 bytes will be inverted, from the the last -// 8 bytes always the nibbles will be inverted for further -// details look in the MSDN under compressed registry keys -static std::_tstring ConvertGuid(const std::_tstring& guid) -{ - std::_tstring convertedGuid; - - std::_tstring part = GetGuidPart(guid, 0); - convertedGuid = Invert(part); - - part = GetGuidPart(guid, 1); - convertedGuid += Invert(part); - - part = GetGuidPart(guid, 2); - convertedGuid += Invert(part); - - part = GetGuidPart(guid, 3); - convertedGuid += Invert(std::_tstring(part.c_str(), 2)); - convertedGuid += Invert(std::_tstring(part.c_str() + 2, 2)); - - part = GetGuidPart(guid, 4); - int pos = 0; - for (int i = 0; i < 6; i++) - { - convertedGuid += Invert(std::_tstring(part.c_str() + pos, 2)); - pos += 2; - } - return convertedGuid; -} - -static inline bool IsSetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty) -{ - std::_tstring value = GetMsiProperty(handle, sProperty); - return (value.length() > 0); -} - -static inline void UnsetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty) -{ - MsiSetProperty(handle, sProperty.c_str(), NULL); -} - -static inline void SetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty) -{ - MsiSetProperty(handle, sProperty.c_str(), TEXT("1")); -} - -static bool SwapFiles( const std::_tstring& sFileName1, const std::_tstring& sFileName2 ) -{ - std::_tstring sTempFileName = sFileName1 + TEXT(".tmp"); - - bool fSuccess = true; - - //Try to move the original file to a temp file - fSuccess = MoveFileExA( sFileName1.c_str(), sTempFileName.c_str(), MOVEFILE_REPLACE_EXISTING); - - if ( fSuccess ) - { - fSuccess = MoveFileExA( sFileName2.c_str(), sFileName1.c_str(), MOVEFILE_REPLACE_EXISTING ); - - if ( fSuccess ) - { - fSuccess = MoveFileExA( sTempFileName.c_str(), sFileName2.c_str(), - MOVEFILE_REPLACE_EXISTING ); - if ( !fSuccess ) - { - MoveFileExA( sFileName1.c_str(), sFileName2.c_str(), MOVEFILE_REPLACE_EXISTING ); - } - } - else - { - MoveFileExA( sTempFileName.c_str(), sFileName1.c_str(), MOVEFILE_REPLACE_EXISTING ); - } - } - else - { - //It could be that there is no original file and therefore copying the original to a temp - // file failed. Examine if there is no original and if so then move file2 to file1 - - WIN32_FIND_DATA data; - HANDLE hdl = FindFirstFile(sFileName1.c_str(), &data); - if (hdl == INVALID_HANDLE_VALUE) - { - fSuccess = MoveFileExA( sFileName2.c_str(), sFileName1.c_str(), MOVEFILE_REPLACE_EXISTING ); - } - else - { - FindClose(hdl); - } - } - - OutputDebugStringFormat( TEXT("%s <-> %s: %s"), sFileName1.c_str(), sFileName2.c_str(), fSuccess ? TEXT("OK") : TEXT("FAILED") ); - - if (!fSuccess ) - { - DWORD dwError = GetLastError(); - LPVOID lpMsgBuf; - if ( FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL )) - { - OutputDebugStringFormat( TEXT("Error Code %d: %s"), dwError, lpMsgBuf ); - LocalFree( lpMsgBuf ); - } - else - OutputDebugStringFormat( TEXT("Error Code %d: Unknown"), dwError ); - SetMsiErrorCode( dwError ); - } - - return fSuccess; -} - -static std::_tstring strip( const std::_tstring& s, _TCHAR c ) -{ - std::_tstring result = s; - - std::_tstring::size_type f; - - do - { - f = result.find( c ); - if ( f != std::_tstring::npos ) - result.erase( f, 1 ); - } while ( f != std::_tstring::npos ); - - return result; -} - -static std::_tstring trim( const std::_tstring& rString ) -{ - std::_tstring temp = rString; - - while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' ) - temp.erase( 0, 1 ); - - std::_tstring::size_type len = temp.length(); - - while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' ) - { - temp.erase( len - 1, 1 ); - len = temp.length(); - } - - return temp; -} - -static bool readLine( FILE *fp, std::_tstring& rLine ) -{ - _TCHAR szBuffer[1024]; - bool bSuccess = false; - bool bEOL = false; - std::_tstring line; - - - while ( !bEOL && _fgetts( szBuffer, sizeof(szBuffer), fp ) ) - { - int len = _tcslen(szBuffer); - - bSuccess = true; - - while ( len && szBuffer[len - 1] == '\n' ) - { - szBuffer[--len] = 0; - bEOL = true; - } - - line.append( szBuffer ); - } - - rLine = line; - return bSuccess; -} - - -static std::_tstring getProfileString( - const std::_tstring& aFileName, - const std::_tstring& aSectionName, - const std::_tstring& aKeyName, - const std::_tstring& aDefault = _T("") ) -{ - FILE *fp = _tfopen( aFileName.c_str(), _T("r") ); - std::_tstring retValue = aDefault.length() ? aDefault : _T(""); - - if ( fp ) - { - std::_tstring line; - std::_tstring section; - - while ( readLine( fp, line ) ) - { - line = trim( line ); - - if ( line.length() && line[0] == '[' ) - { - line.erase( 0, 1 ); - std::_tstring::size_type end = line.find( ']', 0 ); - - if ( std::_tstring::npos != end ) - section = trim( line.substr( 0, end ) ); - } - else - { - - std::_tstring::size_type iEqualSign = line.find( '=', 0 ); - - if ( iEqualSign != std::_tstring::npos ) - { - std::_tstring keyname = line.substr( 0, iEqualSign ); - keyname = trim( keyname ); - - std::_tstring value = line.substr( iEqualSign + 1 /*, std::_tstring::npos */ ); - value = trim( value ); - - if ( - 0 == _tcsicmp( section.c_str(), aSectionName.c_str() ) && - 0 == _tcsicmp( keyname.c_str(), aKeyName.c_str() ) - ) - { - retValue = value; - break; - } - } - } - } - - fclose( fp ); - } - - return retValue; -} - -static std::queue< std::_tstring > getProfileSections( const std::_tstring& aFileName ) -{ - FILE *fp = _tfopen( aFileName.c_str(), _T("r") ); - std::queue< std::_tstring > aResult; - - OutputDebugStringFormat( TEXT("*** Retrieving Section Names ****") ); - - if ( fp ) - { - std::_tstring line; - std::_tstring section; - - while ( readLine( fp, line ) ) - { - line = trim( line ); - - if ( line.length() && line[0] == '[' ) - { - line.erase( 0, 1 ); - std::_tstring::size_type end = line.find( ']', 0 ); - - if ( std::_tstring::npos != end ) - section = trim( line.substr( 0, end ) ); - - aResult.push( section ); - - OutputDebugStringFormat( TEXT("Section: %s"), section.c_str() ); - - } - } - - fclose( fp ); - } - - OutputDebugStringFormat( TEXT("*** Done Section Names ***") ); - - return aResult; -} - -static std::queue< std::_tstring > getProfileKeys( const std::_tstring& aFileName, const std::_tstring& aSectionName ) -{ - FILE *fp = _tfopen( aFileName.c_str(), _T("r") ); - std::queue< std::_tstring > aResult; - - OutputDebugStringFormat( TEXT("*** Retrieving Key Names for [%s] ***"), aSectionName.c_str() ); - - if ( fp ) - { - std::_tstring line; - std::_tstring section; - - while ( readLine( fp, line ) ) - { - line = trim( line ); - - if ( line.length() && line[0] == '[' ) - { - line.erase( 0, 1 ); - std::_tstring::size_type end = line.find( ']', 0 ); - - if ( std::_tstring::npos != end ) - section = trim( line.substr( 0, end ) ); - } - else - { - - std::_tstring::size_type iEqualSign = line.find( '=', 0 ); - - if ( iEqualSign != std::_tstring::npos ) - { - std::_tstring keyname = line.substr( 0, iEqualSign ); - keyname = trim( keyname ); - - if ( 0 == _tcsicmp( section.c_str(), aSectionName.c_str() ) ) - { - aResult.push( keyname ); - - OutputDebugStringFormat( keyname.c_str() ); - - } - } - } - } - - fclose( fp ); - } - - OutputDebugStringFormat( TEXT("*** Done Key Names for [%s] ***"), aSectionName.c_str() ); - - return aResult; -} - -extern "C" UINT __stdcall InstallPatchedFiles( MSIHANDLE handle ) -{ - std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") ); - std::_tstring sProgramDir = sInstDir + TEXT("program\\"); - std::_tstring sPatchFile = sProgramDir + TEXT("patchlist.txt"); - - std::queue< std::_tstring > aSectionNames; - std::queue< std::_tstring > aKeyNames; - - OutputDebugStringA( "Starting Custom Action" ); - - aSectionNames = getProfileSections( sPatchFile ); - while ( !aSectionNames.empty() ) - { - std::_tstring sSectionName = aSectionNames.front(); - if ( std::_tstring(TEXT("_root")) == sSectionName ) { sSectionName = TEXT(""); } - - aKeyNames = getProfileKeys( sPatchFile, sSectionName ); - while ( !aKeyNames.empty() ) - { - std::_tstring sKeyName = aKeyNames.front(); - std::_tstring sValue = getProfileString( sPatchFile, sSectionName, sKeyName ); - - if ( sValue.length() ) - { - std::_tstring sFileName1 = sKeyName; - std::_tstring sExtension = sValue; - std::_tstring sFileName2; - - sFileName1 = strip( sFileName1, '\"' ); - sExtension = strip( sExtension, '\"' ); - - sFileName1 = sInstDir + sSectionName + sFileName1; - sFileName2 = sFileName1 + sExtension; - - SwapFiles( sFileName1, sFileName2 ); - } - - aKeyNames.pop(); - } - - aSectionNames.pop(); - } - - return ERROR_SUCCESS; -} - -extern "C" UINT __stdcall UninstallPatchedFiles( MSIHANDLE handle ) -{ - TCHAR szValue[8192]; - DWORD nValueSize = sizeof(szValue); - HKEY hKey; - - std::_tstring sInstDir; - - std::_tstring sProductKey = GetMsiProperty( handle, TEXT("FINDPRODUCT") ); - - if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, sProductKey.c_str(), &hKey ) ) - { - if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) ) - { - sInstDir = szValue; - } - RegCloseKey( hKey ); - } - else if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, sProductKey.c_str(), &hKey ) ) - { - if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) ) - { - sInstDir = szValue; - } - RegCloseKey( hKey ); - } - else - return ERROR_SUCCESS; - - std::_tstring sProgramDir = sInstDir + TEXT("program\\"); - std::_tstring sPatchFile = sProgramDir + TEXT("patchlist.txt"); - - std::queue< std::_tstring > aSectionNames; - std::queue< std::_tstring > aKeyNames; - - aSectionNames = getProfileSections( sPatchFile ); - while ( !aSectionNames.empty() ) - { - std::_tstring sSectionName = aSectionNames.front(); - if ( std::_tstring(TEXT("_root")) == sSectionName ) { sSectionName = TEXT(""); } - - aKeyNames = getProfileKeys( sPatchFile, sSectionName ); - while( !aKeyNames.empty() ) - { - std::_tstring sKeyName = aKeyNames.front(); - std::_tstring sValue = getProfileString( sPatchFile, sSectionName, sKeyName ); - - if ( sValue.length() ) - { - std::_tstring sFileName1 = sKeyName; - std::_tstring sExtension = sValue; - std::_tstring sFileName2; - - sFileName1 = strip( sFileName1, '\"' ); - sExtension = strip( sExtension, '\"' ); - - sFileName1 = sInstDir + sSectionName + sFileName1; - sFileName2 = sFileName1 + sExtension; - - SwapFiles( sFileName2, sFileName1 ); - } - - aKeyNames.pop(); - } - - aSectionNames.pop(); - } - - return ERROR_SUCCESS; -} - -extern "C" UINT __stdcall SetFeatureState( MSIHANDLE handle ) -{ - - // 1. Reading Product Code from setup.ini of installed Office - - std::_tstring sInstallPath = GetMsiProperty(handle, TEXT("INSTALLLOCATION")); - std::_tstring sSetupiniPath = sInstallPath + TEXT("program\\setup.ini"); - - TCHAR szProductCode[32767]; - - GetPrivateProfileString( - TEXT("Bootstrap"), - TEXT("ProductCode"), - TEXT("NOTFOUND"), - szProductCode, - SAL_N_ELEMENTS(szProductCode), - sSetupiniPath.c_str() - ); - - if ( !_tcsicmp( szProductCode, TEXT("NOTFOUND") ) ) - { - // No setup.ini or no "ProductCode" in setup.ini. This is an invalid directory. - return ERROR_SUCCESS; - } - - // 2. Converting Product code - - std::_tstring productCode = TEXT(szProductCode); - productCode = ConvertGuid(std::_tstring(productCode.c_str() + 1, productCode.length() - 2)); - - // 3. Setting path in the Windows registry to find installed features - - std::_tstring registryKey; - HKEY registryRoot; - - if ( IsSetMsiProperty(handle, TEXT("ALLUSERS")) ) - { - registryRoot = HKEY_LOCAL_MACHINE; - registryKey = TEXT("Software\\Classes\\Installer\\Features\\") + productCode; - } - else - { - registryRoot = HKEY_CURRENT_USER; - registryKey = TEXT("Software\\Microsoft\\Installer\\Features\\") + productCode; - } - - // 4. Collecting all installed features from Windows registry - - HKEY hKey; - if (RegOpenKey(registryRoot, registryKey.c_str(), &hKey) == ERROR_SUCCESS) - { - int counter = 0; - LONG lEnumResult; - - do - { - TCHAR szValueName[8192]; - DWORD nValueNameSize = sizeof(szValueName); - LPDWORD pValueNameSize = &nValueNameSize; - TCHAR szValueData[8192]; - DWORD nValueDataSize = sizeof(szValueData); - - lEnumResult = RegEnumValue( hKey, counter, szValueName, pValueNameSize, NULL, NULL, (LPBYTE)szValueData, &nValueDataSize); - - if ( ERROR_SUCCESS == lEnumResult ) - { - std::_tstring sValueName = szValueName; - - // Does this feature exist in this patch? - if ( IsSetMsiProperty(handle, sValueName) ) - { - // Feature is not installed, if szValueData starts with a "square" (ascii 6) - if ( 6 == szValueData[0] ) - { - MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_ABSENT); // do not install this feature - } - else - { - MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_LOCAL); // do install this feature - } - } - } - - counter = counter + 1; - - } while ( ERROR_SUCCESS == lEnumResult ); - - RegCloseKey( hKey ); - } - - return ERROR_SUCCESS; -} - -extern "C" UINT __stdcall SetNewFeatureState( MSIHANDLE handle ) -{ - std::_tstring sValueName; - - sValueName = TEXT("gm_o_Onlineupdate"); - - if (IsSetMsiProperty(handle, TEXT("SELECT_OU_FEATURE"))) - { - MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_LOCAL); // do install this feature - } - else - { - MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_ABSENT); // do not install this feature - } - - return ERROR_SUCCESS; -} - -extern "C" UINT __stdcall ShowOnlineUpdateDialog( MSIHANDLE handle ) -{ - // Checking existence of file "updchk.uno.dll", which shows, that - // Online Update functionality is always available. Then the dialog - // that offers the Online Update is superfluous. - - std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") ); - std::_tstring sProgramDir = sInstDir + TEXT("program\\"); - std::_tstring sSearchFile = sProgramDir + TEXT("updchk.uno.dll"); - - WIN32_FIND_DATA data; - HANDLE hdl = FindFirstFile(sSearchFile.c_str(), &data); - if (hdl != INVALID_HANDLE_VALUE) // the file exists - { - // And finally setting property SHOW_ONLINEUPDATE_DIALOG - // to hide this dialog - UnsetMsiProperty(handle, TEXT("SHOW_ONLINEUPDATE_DIALOG")); - - // Setting SELECT_OU_FEATURE to 1, which is probably superfluous - // because this is already the default value. But only this - // guarantees, that CustomAction SetNewFeatureState always sets - // the correct FeatureState for "gm_o_Onlineupdate", if it is - // already installed. - SetMsiProperty(handle, TEXT("SELECT_OU_FEATURE")); - } - else - { - // If the file does not exist, the Online Update dialog - // has to be shown. - SetMsiProperty(handle, TEXT("SHOW_ONLINEUPDATE_DIALOG")); - FindClose(hdl); - } - - return ERROR_SUCCESS; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |