diff options
Diffstat (limited to 'desktop/win32/source/setup')
-rw-r--r-- | desktop/win32/source/setup/Resource.h | 79 | ||||
-rw-r--r-- | desktop/win32/source/setup/makefile.mk | 95 | ||||
-rw-r--r-- | desktop/win32/source/setup/rcfooter.txt | 2 | ||||
-rw-r--r-- | desktop/win32/source/setup/rcheader.txt | 43 | ||||
-rw-r--r-- | desktop/win32/source/setup/rctmpl.txt | 49 | ||||
-rw-r--r-- | desktop/win32/source/setup/setup.cpp | 1932 | ||||
-rw-r--r-- | desktop/win32/source/setup/setup.hxx | 155 | ||||
-rw-r--r-- | desktop/win32/source/setup/setup.ico | bin | 0 -> 4710 bytes | |||
-rw-r--r-- | desktop/win32/source/setup/setup.ulf | 162 | ||||
-rw-r--r-- | desktop/win32/source/setup/setup_a.cxx | 34 | ||||
-rw-r--r-- | desktop/win32/source/setup/setup_help.hxx | 50 | ||||
-rw-r--r-- | desktop/win32/source/setup/setup_main.cxx | 144 | ||||
-rw-r--r-- | desktop/win32/source/setup/setup_main.hxx | 76 | ||||
-rw-r--r-- | desktop/win32/source/setup/setup_w.cxx | 38 |
14 files changed, 2859 insertions, 0 deletions
diff --git a/desktop/win32/source/setup/Resource.h b/desktop/win32/source/setup/Resource.h new file mode 100644 index 000000000000..99ef720451f3 --- /dev/null +++ b/desktop/win32/source/setup/Resource.h @@ -0,0 +1,79 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _RESOURCE_H +#define _RESOURCE_H + +#define IDS_APP_TITLE 10 +#define IDS_APP_PROD_TITLE 11 +#define IDS_OUTOFMEM 12 +#define IDS_NOMSI 13 +#define IDS_USER_CANCELLED 14 +#define IDS_REQUIRES_ADMIN_PRIV 15 +#define IDS_FILE_NOT_FOUND 16 +#define IDS_INVALID_PARAM 17 +#define IDS_ALLOW_MSI_UPDATE 18 +#define IDS_USAGE 19 +#define IDS_ALREADY_RUNNING 20 +#define IDS_UNKNOWN_ERROR 21 +#define IDS_INVALID_PROFILE 22 +#define IDS_UNKNOWN_LANG 23 +#define IDS_SETUP_TO_OLD 24 +#define IDS_SETUP_NOT_FOUND 25 +#define IDS_LANGUAGE_ENGLISH 50 +#define IDS_LANGUAGE_SPAIN 51 +#define IDS_LANGUAGE_GERMAN 52 +#define IDS_LANGUAGE_ZH_TW 53 +#define IDS_LANGUAGE_CS 54 +#define IDS_LANGUAGE_DA 55 +#define IDS_LANGUAGE_DE_DE 56 +#define IDS_LANGUAGE_EL 57 +#define IDS_LANGUAGE_EN_US 58 +#define IDS_LANGUAGE_ES 59 +#define IDS_LANGUAGE_FI 60 +#define IDS_LANGUAGE_FR_FR 61 +#define IDS_LANGUAGE_HE 62 +#define IDS_LANGUAGE_HU 63 +#define IDS_LANGUAGE_IT_IT 64 +#define IDS_LANGUAGE_JA 65 +#define IDS_LANGUAGE_KO 66 +#define IDS_LANGUAGE_NL_NL 67 +#define IDS_LANGUAGE_NO_NO 68 +#define IDS_LANGUAGE_PL 69 +#define IDS_LANGUAGE_PT_BR 70 +#define IDS_LANGUAGE_RU 71 +#define IDS_LANGUAGE_SK 72 +#define IDS_LANGUAGE_SV_SE 73 +#define IDS_LANGUAGE_TH 74 +#define IDS_LANGUAGE_TR 75 +#define IDS_LANGUAGE_ET 76 +#define IDS_LANGUAGE_ZH_CN 77 +#define IDS_LANGUAGE_PT_PT 78 + +#define IDI_INSTALLER 99 + +#endif diff --git a/desktop/win32/source/setup/makefile.mk b/desktop/win32/source/setup/makefile.mk new file mode 100644 index 000000000000..d26c9c953861 --- /dev/null +++ b/desktop/win32/source/setup/makefile.mk @@ -0,0 +1,95 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.12 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME = desktop +TARGET = loader2 +LIBTARGET = NO +DYNAMIC_CRT = +TARGETTYPE = GUI + +ENABLE_EXCEPTIONS = TRUE + +# --- Settings ------------------------------------------------------------ + +.INCLUDE : settings.mk + +# --- Allgemein ----------------------------------------------------------- + +INCPRE+=$(MFC_INCLUDE) + +.IF "$(USE_STLP_DEBUG)"!="" +CDEFS+=-D_DEBUG +.ENDIF # "$(USE_STLP_DEBUG)"!="" + +RCFILES= $(RES)$/$(TARGET).rc + +ULFFILES= setup.ulf + +.IF "$(WITH_LANG)"!="" +ULFDIR:=$(COMMONMISC)$/$(TARGET) +.ELSE # "$(WITH_LANG)"!="" +ULFDIR:=. +.ENDIF # "$(WITH_LANG)"!="" + +OBJFILES= $(OBJ)$/setup_main.obj \ + $(OBJ)$/setup_a.obj \ + $(OBJ)$/setup_w.obj + +# --- Targets ------------------------------------------------------ +# Generate the native Windows resource file +# using lngconvex.exe + +UWINAPILIB= $(0) +LIBSALCPPRT= $(0) + +APP1NOSAL= TRUE +APP1TARGET= loader2 + +APP1STDLIBS= $(GDI32LIB) $(ADVAPI32LIB) $(SHELL32LIB) $(MSILIB) +.IF "$(COM)"!="GCC" +APP1STDLIBS+= libcmt.lib +.ENDIF +APP1OBJS= $(OBJFILES) + +APP1DEF= $(MISC)$/$(TARGET).def + +APP1RES= $(RES)$/$(TARGET).res +APP1NOSVRES= $(RES)$/$(TARGET).res + +# --- setup -------------------------------------------------------------- + +.INCLUDE : target.mk + +$(RCFILES) : $(ULFDIR)$/setup.ulf makefile.mk rcfooter.txt rcheader.txt rctmpl.txt + $(LNGCONVEX) -ulf $(ULFDIR)$/setup.ulf -rc $(RCFILES) -rct rctmpl.txt -rch rcheader.txt -rcf rcfooter.txt + diff --git a/desktop/win32/source/setup/rcfooter.txt b/desktop/win32/source/setup/rcfooter.txt new file mode 100644 index 000000000000..3237729437f5 --- /dev/null +++ b/desktop/win32/source/setup/rcfooter.txt @@ -0,0 +1,2 @@ + +// The end diff --git a/desktop/win32/source/setup/rcheader.txt b/desktop/win32/source/setup/rcheader.txt new file mode 100644 index 000000000000..9a59ad7f6477 --- /dev/null +++ b/desktop/win32/source/setup/rcheader.txt @@ -0,0 +1,43 @@ +#if defined(_MSC_VER) && (_MSC_VER < 1500) +#include <winres.h> +#else +#define WINVER 0x0500 +#include <winresrc.h> +#define LB_ADDSTRING (WM_USER+1) +#define CB_ADDSTRING (WM_USER+3) +#define IDC_STATIC (-1) +#endif +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,1,1,0 + PRODUCTVERSION 1,1,1,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x9L +#else + FILEFLAGS 0x8L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +IDI_INSTALLER ICON "setup.ico" + diff --git a/desktop/win32/source/setup/rctmpl.txt b/desktop/win32/source/setup/rctmpl.txt new file mode 100644 index 000000000000..59f454f70c16 --- /dev/null +++ b/desktop/win32/source/setup/rctmpl.txt @@ -0,0 +1,49 @@ +// String Table + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APP_TITLE %APP_TITLE% + IDS_APP_PROD_TITLE %APP_PROD_TITLE% + IDS_OUTOFMEM %OUTOFMEM% + IDS_NOMSI %NOMSI% + IDS_USER_CANCELLED %USER_CANCELLED% + IDS_REQUIRES_ADMIN_PRIV %REQUIRES_ADMIN_PRIV% + IDS_FILE_NOT_FOUND %FILE_NOT_FOUND% + IDS_INVALID_PARAM %INVALID_PARAM% + IDS_SETUP_TO_OLD %SETUP_TO_OLD% + IDS_SETUP_NOT_FOUND %SETUP_NOT_FOUND% + IDS_USAGE %USAGE% + IDS_ALREADY_RUNNING %ALREADY_RUNNING% + IDS_UNKNOWN_ERROR %UNKNOWN_ERROR% + IDS_INVALID_PROFILE %INVALID_PROFILE% + IDS_UNKNOWN_LANG %UNKNOWN_LANG% + IDS_LANGUAGE_ENGLISH %LANGUAGE_ENGLISH% + IDS_LANGUAGE_SPAIN %LANGUAGE_SPAIN% + IDS_LANGUAGE_GERMAN %LANGUAGE_GERMAN% + IDS_LANGUAGE_ZH_TW %LANGUAGE_ZH_TW% + IDS_LANGUAGE_CS %LANGUAGE_CS% + IDS_LANGUAGE_DA %LANGUAGE_DA% + IDS_LANGUAGE_DE_DE %LANGUAGE_DE_DE% + IDS_LANGUAGE_EL %LANGUAGE_EL% + IDS_LANGUAGE_EN_US %LANGUAGE_EN_US% + IDS_LANGUAGE_ES %LANGUAGE_ES% + IDS_LANGUAGE_FI %LANGUAGE_FI% + IDS_LANGUAGE_FR_FR %LANGUAGE_FR_FR% + IDS_LANGUAGE_HE %LANGUAGE_HE% + IDS_LANGUAGE_HU %LANGUAGE_HU% + IDS_LANGUAGE_IT_IT %LANGUAGE_IT_IT% + IDS_LANGUAGE_JA %LANGUAGE_JA% + IDS_LANGUAGE_KO %LANGUAGE_KO% + IDS_LANGUAGE_NL_NL %LANGUAGE_NL_NL% + IDS_LANGUAGE_NO_NO %LANGUAGE_NO_NO% + IDS_LANGUAGE_PL %LANGUAGE_PL% + IDS_LANGUAGE_PT_BR %LANGUAGE_PT_BR% + IDS_LANGUAGE_RU %LANGUAGE_RU% + IDS_LANGUAGE_SK %LANGUAGE_SK% + IDS_LANGUAGE_SV_SE %LANGUAGE_SV_SE% + IDS_LANGUAGE_TH %LANGUAGE_TH% + IDS_LANGUAGE_TR %LANGUAGE_TR% + IDS_LANGUAGE_ET %LANGUAGE_ET% + IDS_LANGUAGE_ZH_CN %LANGUAGE_ZH_CN% + IDS_LANGUAGE_PT_PT %LANGUAGE_PT_PT% +END diff --git a/desktop/win32/source/setup/setup.cpp b/desktop/win32/source/setup/setup.cpp new file mode 100644 index 000000000000..fb29c13d3a1c --- /dev/null +++ b/desktop/win32/source/setup/setup.cpp @@ -0,0 +1,1932 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: setup.cpp,v $ + * $Revision: 1.16 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#define WIN // scope W32 API + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <tchar.h> +#include <assert.h> +#include <shlwapi.h> +#include <new> +#include <time.h> +#include <mbctype.h> +#include <locale.h> +#include <Msiquery.h> +#include <MsiDefs.h> +#include "strsafe.h" + +#include "setup.hxx" + +#include "resource.h" + +//-------------------------------------------------------------------------- + +#define MAX_STR_LENGTH 32000 +#define MAX_TEXT_LENGTH 1024 +#define MAX_LANGUAGE_LEN 80 +#define MAX_STR_CAPTION 256 +#define VERSION_SIZE 80 +#define SECTION_SETUP TEXT( "Setup" ) +#define SECTION_LANGUAGE TEXT( "Languages" ) +#define PRODUCT_NAME_VAR TEXT( "%PRODUCTNAME" ) +#define PRODUCT_VERSION TEXT( "ProductVersion" ) +#define ERROR_SHOW_USAGE -2 +#define ERROR_SETUP_TO_OLD -3 +#define ERROR_SETUP_NOT_FOUND -4 + +#define PARAM_SETUP_USED TEXT( " SETUP_USED=1 " ) +#define PARAM_PACKAGE TEXT( "/I " ) +#define PARAM_MINOR_UPGRADE TEXT( "/FVOMUS " ) +#define PARAM_ADMIN TEXT( "/A " ) +#define PARAM_TRANSFORM TEXT( " TRANSFORMS=" ) +#define PARAM_REBOOT TEXT( " REBOOT=Force" ) +#define PARAM_PATCH TEXT( " /update " ) +#define PARAM_REG_ALL_MSO_TYPES TEXT( "REGISTER_ALL_MSO_TYPES=1 " ) +#define PARAM_REG_NO_MSO_TYPES TEXT( "REGISTER_NO_MSO_TYPES=1 " ) + +#define PARAM_RUNNING TEXT( "ignore_running" ) +#define CMDLN_REG_ALL_MSO_TYPES TEXT( "msoreg=1" ) +#define CMDLN_REG_NO_MSO_TYPES TEXT( "msoreg=0" ) + +#define MSI_DLL TEXT( "msi.dll" ) +#define ADVAPI32_DLL TEXT( "advapi32.dll" ) +#define PROFILE_NAME TEXT( "setup.ini" ) + +#define MSIAPI_DllGetVersion "DllGetVersion" +#define ADVAPI32API_CheckTokenMembership "CheckTokenMembership" + +typedef HRESULT (CALLBACK* PFnDllGetVersion)( DLLVERSIONINFO *pdvi); +typedef BOOL (WINAPI* PFnCheckTokenMembership)(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember); + +#ifdef DEBUG +inline void OutputDebugStringFormat( LPCTSTR pFormat, ... ) +{ + TCHAR buffer[1024]; + va_list args; + + va_start( args, pFormat ); + StringCchVPrintf( buffer, sizeof(buffer), pFormat, args ); + OutputDebugString( buffer ); +} +#else +static inline void OutputDebugStringFormat( LPCTSTR, ... ) +{ +} +#endif + +//-------------------------------------------------------------------------- + +const TCHAR sInstKey[] = TEXT( "Software\\Microsoft\\Windows\\CurrentVersion\\Installer" ); +const TCHAR sInstLocValue[] = TEXT( "InstallerLocation" ); +const TCHAR sMsiDll[] = TEXT( "\\msi.dll" ); +const TCHAR sMsiExe[] = TEXT( "\\msiexec.exe" ); +const TCHAR sDelayReboot[] = TEXT( " /c:\"msiinst /delayreboot\"" ); +const TCHAR sMsiQuiet[] = TEXT( " /q" ); +const TCHAR sMemMapName[] = TEXT( "Global\\MsiErrorObject" ); + +//-------------------------------------------------------------------------- +SetupAppX::SetupAppX() +{ + m_hInst = NULL; + m_hMapFile = NULL; + m_pAppTitle = NULL; + m_pCmdLine = NULL; + + m_pDatabase = NULL; + m_pReqVersion = NULL; + m_pProductName = NULL; + m_pAdvertise = NULL; + m_pTmpName = NULL; + m_pLogFile = NULL; + m_pModuleFile = NULL; + m_pPatchFiles = NULL; + m_pMSIErrorCode = NULL; + m_pUpgradeKey = NULL; + m_pProductVersion = NULL; + + m_pErrorText = new TCHAR[ MAX_TEXT_LENGTH ]; + m_pErrorText[0] = '\0'; + + m_nLanguageID = 0; + m_nLanguageCount = 0; + m_ppLanguageList = NULL; + + m_bQuiet = false; + m_bRegNoMsoTypes = false; + m_bRegAllMsoTypes = false; + m_bIsMinorUpgrade = false; + m_bSupportsPatch = false; + + m_bIgnoreAlreadyRunning = false; +} + +//-------------------------------------------------------------------------- +SetupAppX::~SetupAppX() +{ + if ( m_ppLanguageList ) + { + for ( int i = 0; i < m_nLanguageCount; i++ ) + if ( m_ppLanguageList[i] ) + delete m_ppLanguageList[ i ]; + delete [] m_ppLanguageList; + } + + time_t aTime; + time( &aTime ); + tm *pTime = localtime( &aTime ); // Convert time to struct tm form + + Log( TEXT( "End: %s\n\r\n\r\n" ), _tasctime( pTime ) ); + + if ( m_pLogFile ) fclose( m_pLogFile ); + + if ( m_pTmpName ) + { + _tremove( m_pTmpName ); + free( m_pTmpName ); + } + + if ( m_pMSIErrorCode ) UnmapViewOfFile( m_pMSIErrorCode ); + if ( m_hMapFile ) CloseHandle( m_hMapFile ); + + if ( m_pAppTitle ) delete [] m_pAppTitle; + if ( m_pDatabase ) delete [] m_pDatabase; + if ( m_pReqVersion ) delete [] m_pReqVersion; + if ( m_pProductName ) delete [] m_pProductName; + if ( m_pAdvertise ) delete [] m_pAdvertise; + if ( m_pLogFile ) delete [] m_pLogFile; + if ( m_pErrorText ) delete [] m_pErrorText; + if ( m_pModuleFile ) delete [] m_pModuleFile; + if ( m_pPatchFiles ) delete [] m_pPatchFiles; + if ( m_pUpgradeKey ) delete [] m_pUpgradeKey; + if ( m_pProductVersion ) delete [] m_pProductVersion; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::Initialize( HINSTANCE hInst ) +{ + m_pCmdLine = WIN::GetCommandLine(); + m_hInst = hInst; + + // Load our AppTitle (caption) + m_pAppTitle = new TCHAR[ MAX_STR_CAPTION ]; + m_pAppTitle[0] = '\0'; + WIN::LoadString( hInst, IDS_APP_TITLE, m_pAppTitle, MAX_STR_CAPTION ); + + // Obtain path we are running from + m_pModuleFile = new TCHAR[ MAX_PATH ]; + m_pModuleFile[ 0 ] = '\0'; + + if ( 0 == WIN::GetModuleFileName( hInst, m_pModuleFile, MAX_PATH ) ) + { + SetError( WIN::GetLastError() ); + return false; + } + + if ( ! GetCmdLineParameters( &m_pCmdLine ) ) + return false; + + m_hMapFile = CreateFileMapping( + INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // max. object size + sizeof( int ), // buffer size + sMemMapName ); + if ( m_hMapFile ) + { + m_pMSIErrorCode = (int*) MapViewOfFile( m_hMapFile, // handle to map object + FILE_MAP_ALL_ACCESS, // read/write permission + 0, + 0, + sizeof( int ) ); + if ( m_pMSIErrorCode ) + *m_pMSIErrorCode = 0; + else + OutputDebugStringFormat( TEXT("Could not map view of file (%d).\n"), GetLastError() ); + } + else + OutputDebugStringFormat( TEXT("Could not create file mapping object (%d).\n"), GetLastError() ); + + Log( TEXT("Starting: %s\r\n"), m_pModuleFile ); + Log( TEXT(" CommandLine=<%s>\r\n"), m_pCmdLine ); + + if ( m_bQuiet ) + Log( TEXT(" Using quiet install mode\r\n") ); + + time_t aTime; + time( &aTime ); + tm* pTime = localtime( &aTime ); + Log( TEXT(" Begin: %s\n"), _tasctime( pTime ) ); + + return true; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::GetProfileSection( LPCTSTR pFileName, LPCTSTR pSection, + DWORD& rSize, LPTSTR *pRetBuf ) +{ + if ( !rSize || !*pRetBuf ) + { + rSize = 512; + *pRetBuf = new TCHAR[ rSize ]; + } + + DWORD nRet = GetPrivateProfileSection( pSection, *pRetBuf, rSize, pFileName ); + + if ( nRet && ( nRet + 2 > rSize ) ) // buffer was too small, retry with bigger one + { + if ( nRet < 32767 - 2 ) + { + delete [] (*pRetBuf); + rSize = nRet + 2; + *pRetBuf = new TCHAR[ rSize ]; + + nRet = GetPrivateProfileSection( pSection, *pRetBuf, rSize, pFileName ); + } + } + + if ( !nRet ) + { + SetError( WIN::GetLastError() ); + + TCHAR sBuf[80]; + StringCchPrintf( sBuf, 80, TEXT("ERROR: GetPrivateProfileSection(): GetLastError returned %u\r\n"), GetError() ); + Log( sBuf ); + return false; + } + else if ( nRet + 2 > rSize ) + { + SetError( ERROR_OUTOFMEMORY ); + Log( TEXT( "ERROR: GetPrivateProfileSection() out of memory\r\n" ) ); + return false; + } + + Log( TEXT( " GetProfileSection read %s\r\n" ), pSection ); + + return true; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::ReadProfile() +{ + boolean bRet = false; + TCHAR *sProfilePath = 0; + + if ( GetPathToFile( PROFILE_NAME, &sProfilePath ) ) + { + DWORD nSize = 0; + LPTSTR pRetBuf = NULL; + + Log( TEXT( " Open ini file: <%s>\r\n" ), sProfilePath ); + + bRet = GetProfileSection( sProfilePath, SECTION_SETUP, nSize, &pRetBuf ); + + if ( !bRet ) + { + LPTSTR pTmpFile = CopyIniFile( sProfilePath ); + delete [] sProfilePath; + sProfilePath = pTmpFile; + + if ( sProfilePath ) + { + SetError( ERROR_SUCCESS ); + + Log( TEXT( " Could not open inifile, copied ini file to: <%s>\r\n" ), sProfilePath ); + bRet = GetProfileSection( sProfilePath, SECTION_SETUP, nSize, &pRetBuf ); + } + } + + if ( bRet ) + { + LPTSTR pCurLine = pRetBuf; + while ( *pCurLine ) + { + LPTSTR pName = 0; + LPTSTR pValue = 0; + + pCurLine += GetNameValue( pCurLine, &pName, &pValue ); + + if ( lstrcmpi( TEXT( "database" ), pName ) == 0 ) + { + m_pDatabase = pValue; + Log( TEXT( " Database = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "msiversion" ), pName ) == 0 ) + { + m_pReqVersion = pValue; + Log( TEXT( " msiversion = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "productname" ), pName ) == 0 ) + { + m_pProductName = pValue; + Log( TEXT( " productname = %s\r\n" ), pValue ); + m_pAppTitle = SetProdToAppTitle( m_pProductName ); + } + else if ( lstrcmpi( TEXT( "upgradekey" ), pName ) == 0 ) + { + m_pUpgradeKey = pValue; + Log( TEXT( " upgradekey = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "productversion" ), pName ) == 0 ) + { + m_pProductVersion = pValue; + Log( TEXT( " productversion = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "productcode" ), pName ) == 0 ) + { + delete [] pValue; + } + else + { + Log( TEXT( "Warning: unknown entry in profile <%s>\r\n" ), pName ); + delete [] pValue; + } + } + } + + if ( bRet && ( !m_pDatabase || !m_pReqVersion || !m_pProductName ) ) + { + Log( TEXT( "ERROR: incomplete 'Setup' section in profile\r\n" ) ); + SetError( ERROR_INVALID_DATA ); + bRet = false; + } + + if ( bRet ) + bRet = GetProfileSection( sProfilePath, SECTION_LANGUAGE, nSize, &pRetBuf ); + + if ( bRet ) + { + LPTSTR pName = 0; + LPTSTR pValue = 0; + LPTSTR pCurLine = pRetBuf; + LPTSTR pLastChar; + int nNext = 0; + + // first line in this section should be the language count + nNext = GetNameValue( pCurLine, &pName, &pValue ); + if ( lstrcmpi( TEXT( "count" ), pName ) == 0 ) + { + Log( TEXT( " Languages = %s\r\n" ), pValue ); + m_nLanguageCount = _tcstol( pValue, &pLastChar, 10 ); + pCurLine += nNext; + delete [] pValue; + } + + m_ppLanguageList = new LanguageDataX*[ m_nLanguageCount ]; + + for ( int i=0; i < m_nLanguageCount; i++ ) + { + if ( !*pCurLine ) + { + m_nLanguageCount = i; + break; + } + + pCurLine += GetNameValue( pCurLine, &pName, &pValue ); + m_ppLanguageList[ i ] = new LanguageDataX( pValue ); + Log( TEXT( " Language = %s\r\n" ), pValue ); + + if ( m_ppLanguageList[ i ]->m_pTransform ) + Log( TEXT( " Transform = %s\r\n" ), m_ppLanguageList[ i ]->m_pTransform ); + + delete [] pValue; + } + } + + if ( pRetBuf ) + delete [] pRetBuf; + } + + if ( sProfilePath && ! m_pTmpName ) + delete [] sProfilePath; + + 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() +{ + boolean bRet = true; + + int nPatternLen = lstrlen( m_pModuleFile ) + 7; // 1 for null terminator, 1 for back slash, 5 for extensions + TCHAR* pPattern = new TCHAR[ nPatternLen ]; + TCHAR* pBaseDir = new TCHAR[ nPatternLen ]; + + // find 'setup.exe' in the path so we can remove it + TCHAR *pFilePart = 0; + if ( 0 == GetFullPathName( m_pModuleFile, nPatternLen, pPattern, &pFilePart ) ) + { + SetError( WIN::GetLastError() ); + bRet = false; + } + else + { + if ( pFilePart ) + *pFilePart = '\0'; + StringCchCopy( pBaseDir, nPatternLen, pPattern ); + StringCchCat( pPattern, nPatternLen, TEXT("*.msp") ); + + WIN32_FIND_DATA aFindFileData; + + HANDLE hFindPatches = FindFirstFile( pPattern, &aFindFileData ); + + if ( hFindPatches != INVALID_HANDLE_VALUE ) + { + if ( ! IsPatchInstalled( pBaseDir, aFindFileData.cFileName ) ) + AddFileToPatchList( pBaseDir, aFindFileData.cFileName ); + + while ( FindNextFile( hFindPatches, &aFindFileData ) ) + { + if ( ! IsPatchInstalled( pBaseDir, aFindFileData.cFileName ) ) + AddFileToPatchList( pBaseDir, aFindFileData.cFileName ); + } + + if ( m_pPatchFiles != NULL ) + StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, TEXT("\"") ); + + FindClose( hFindPatches ); + } + } + + delete [] pPattern; + delete [] pBaseDir; + + return bRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::GetPathToFile( TCHAR* pFileName, TCHAR** pPath ) +{ + // generate the path to the file = szModuleFile + FileName + // note: FileName is a relative path + + boolean bRet = true; + + int nTempPath = lstrlen( m_pModuleFile ) + lstrlen( pFileName ) + 2; // 1 for null terminator, 1 for back slash + TCHAR* pTempPath = new TCHAR[ nTempPath ]; + + // find 'setup.exe' in the path so we can remove it + TCHAR *pFilePart = 0; + if ( 0 == GetFullPathName( m_pModuleFile, nTempPath, pTempPath, &pFilePart ) ) + { + SetError( WIN::GetLastError() ); + bRet = false; + } + else + { + if ( pFilePart ) + *pFilePart = '\0'; + + StringCchCat( pTempPath, nTempPath, pFileName ); + + int nPath = 2 * nTempPath; + *pPath = new TCHAR[ nPath ]; + + // normalize the path + int nReturn = GetFullPathName( pTempPath, nPath, *pPath, &pFilePart ); + + if ( nReturn > nPath ) + { + // try again, with larger buffer + delete [] (*pPath); + nPath = nReturn; + *pPath = new TCHAR[ nPath ]; + + nReturn = GetFullPathName( pTempPath, nPath, *pPath, &pFilePart ); + } + + if ( 0 == nReturn ) + { + // error -- invalid path + SetError( WIN::GetLastError() ); + bRet = false; + } + } + + if ( bRet ) // check for the file's existence + { + DWORD dwFileAttrib = GetFileAttributes( *pPath ); + + if (0xFFFFFFFF == dwFileAttrib) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pFileName ); + SetError( ERROR_FILE_NOT_FOUND ); + bRet = false; + } + } + + delete [] pTempPath; + return bRet; +} + +//-------------------------------------------------------------------------- +int SetupAppX::GetNameValue( TCHAR* pLine, TCHAR** pName, TCHAR** pValue ) +{ + int nRet = lstrlen( pLine ) + 1; + *pValue = 0; + + if ( nRet == 1 ) + return nRet; + + LPTSTR pChar = pLine; + LPTSTR pLast = NULL; + + // Skip leading spaces. + while (' ' == *pChar || '\t' == *pChar) + pChar = CharNext( pChar ); + + *pName = pChar; + + // look for the end of the name + while( *pChar && (' ' != *pChar) && + ( '\t' != *pChar ) && ( '=' != *pChar ) ) + pChar = CharNext( pChar ); + + if ( ! *pChar ) + return nRet; + + pLast = pChar; + pChar = CharNext( pChar ); + *pLast = '\0'; + + // look for the start of the value + while( ( ' ' == *pChar ) || ( '\t' == *pChar ) || + ( '=' == *pChar ) ) + pChar = CharNext( pChar ); + + int nValueLen = lstrlen( pChar ) + 1; + *pValue = new TCHAR[ nValueLen ]; + + if ( *pValue ) + StringCchCopy( *pValue, nValueLen, pChar ); + + return nRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::ChooseLanguage( long& rLanguage ) +{ + rLanguage = 0; + + if ( m_bQuiet ) + return true; + + // When there are none or only one language, there is nothing + // to do here + if ( m_nLanguageCount > 1 ) + { + TCHAR *sString = new TCHAR[ MAX_LANGUAGE_LEN ]; + + LANGID nUserDefLang = GetUserDefaultLangID(); + LANGID nSysDefLang = GetSystemDefaultLangID(); + + int nUserPrimary = PRIMARYLANGID( nUserDefLang ); + int nSysPrimary = PRIMARYLANGID( nSysDefLang ); + + long nUserIndex = -1; + long nUserPrimIndex = -1; + long nSystemIndex = -1; + long nSystemPrimIndex = -1; + long nParamIndex = -1; + + for ( long i=0; i<GetLanguageCount(); i++ ) + { + long nLanguage = GetLanguageID( i ); + int nPrimary = PRIMARYLANGID( nLanguage ); + GetLanguageName( nLanguage, sString ); + Log( TEXT( " Info: found Language: %s\r\n" ), sString ); + + if ( nLanguage == nUserDefLang ) + nUserIndex = i; + if ( nPrimary == nUserPrimary ) + nUserPrimIndex = i; + if ( nLanguage == nSysDefLang ) + nSystemIndex = i; + if ( nPrimary == nSysPrimary ) + nSystemPrimIndex = i; + if ( m_nLanguageID && ( nLanguage == m_nLanguageID ) ) + nParamIndex = i; + } + + if ( m_nLanguageID && ( nParamIndex == -1 ) ) + { + Log( TEXT( "Warning: Language chosen with parameter -lang not found.\r\n" ) ); + } + + if ( nParamIndex != -1 ) + { + Log( TEXT( "Info: Found language chosen with parameter -lang.\r\n" ) ); + rLanguage = GetLanguageID( nParamIndex ); + } + else if ( nUserIndex != -1 ) + { + Log( TEXT( "Info: Found user default language.\r\n" ) ); + rLanguage = GetLanguageID( nUserIndex ); + } + else if ( nUserPrimIndex != -1 ) + { + Log( TEXT( "Info: Found user default primary language.\r\n" ) ); + rLanguage = GetLanguageID( nUserPrimIndex ); + } + else if ( nSystemIndex != -1 ) + { + Log( TEXT( "Info: Found system default language.\r\n" ) ); + rLanguage = GetLanguageID( nSystemIndex ); + } + else if ( nSystemPrimIndex != -1 ) + { + Log( TEXT( "Info: Found system default primary language.\r\n" ) ); + rLanguage = GetLanguageID( nSystemPrimIndex ); + } + else + { + Log( TEXT( "Info: Use default language from ini file.\r\n" ) ); + rLanguage = GetLanguageID( 0 ); + } + delete [] sString; + } + + return true; +} + +//-------------------------------------------------------------------------- +HMODULE SetupAppX::LoadMsiLibrary() +{ + HMODULE hMsi = NULL; + HKEY hInstKey = NULL; + + // find registered location of Msi.dll + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sInstKey, 0, KEY_READ, &hInstKey ) ) + { + long nRet = ERROR_SUCCESS; + TCHAR *sMsiFolder = new TCHAR[ MAX_PATH + 1 ]; + DWORD dwMsiFolderSize = MAX_PATH + 1; + DWORD dwType = 0; + + if ( ERROR_MORE_DATA == ( nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, + &dwType, (BYTE*)sMsiFolder, &dwMsiFolderSize ) ) ) + { + // try again with larger buffer + delete [] sMsiFolder; + sMsiFolder = new TCHAR[ dwMsiFolderSize ]; + + nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, &dwType, + (BYTE*)sMsiFolder, &dwMsiFolderSize ); + } + + if ( ERROR_SUCCESS == nRet && dwType == REG_SZ && dwMsiFolderSize > 0 ) + { + // load Msi.dll from registered location + int nLength = lstrlen( sMsiDll ) + dwMsiFolderSize + 1; // use StringCchLength ? + TCHAR *pMsiLocation = new TCHAR[ nLength ]; + + if ( SUCCEEDED( StringCchCopy( pMsiLocation, nLength, sMsiFolder ) ) && + SUCCEEDED( StringCchCat( pMsiLocation, nLength, sMsiDll ) ) ) + { + hMsi = LoadLibrary( pMsiLocation ); + } + } + } + + if ( !hMsi ) // use the default location + { + hMsi = LoadLibrary( sMsiDll ); + } + + return hMsi; +} + +//-------------------------------------------------------------------------- +LPCTSTR SetupAppX::GetPathToMSI() +{ + LPTSTR sMsiPath = NULL; + HKEY hInstKey = NULL; + TCHAR *sMsiFolder = new TCHAR[ MAX_PATH + 1 ]; + DWORD nMsiFolderSize = MAX_PATH + 1; + + sMsiFolder[0] = '\0'; + + // find registered location of Msi.dll + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sInstKey, 0, KEY_READ, &hInstKey ) ) + { + LONG nRet = ERROR_SUCCESS; + DWORD dwType = 0; + + if ( ERROR_MORE_DATA == ( nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, + &dwType, (BYTE*)sMsiFolder, &nMsiFolderSize ) ) ) + { + // try again with larger buffer + delete [] sMsiFolder; + sMsiFolder = new TCHAR[ nMsiFolderSize ]; + + nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, &dwType, + (BYTE*)sMsiFolder, &nMsiFolderSize ); + } + + if ( ERROR_SUCCESS != nRet || dwType != REG_SZ || nMsiFolderSize == 0 ) + sMsiFolder[0] = '\0'; + } + + if ( sMsiFolder[0] == '\0' ) // use the default location + { + Log( TEXT( " Could not find path to msiexec.exe in registry" ) ); + + DWORD nRet = WIN::GetSystemDirectory( sMsiFolder, nMsiFolderSize ); + if ( nRet > nMsiFolderSize ) + { + delete [] sMsiFolder; + sMsiFolder = new TCHAR[ nRet ]; + nMsiFolderSize = nRet; + + nRet = WIN::GetSystemDirectory( sMsiFolder, nMsiFolderSize ); + } + if ( 0 == nRet ) + { + sMsiFolder[0] = '\0'; + SetError( WIN::GetLastError() ); + } + nMsiFolderSize = nRet; + } + + if ( sMsiFolder[0] != '\0' ) + { + int nLength = lstrlen( sMsiExe ) + lstrlen( sMsiFolder ) + 1; + sMsiPath = new TCHAR[ nLength ]; + + if ( FAILED( StringCchCopy( sMsiPath, nLength, sMsiFolder ) ) || + FAILED( StringCchCat( sMsiPath, nLength, sMsiExe ) ) ) + { + delete [] sMsiPath; + sMsiPath = NULL; + } + } + + if ( ! sMsiPath ) + Log( TEXT( "ERROR: Can't build path to msiexec.exe!" ) ); + + return sMsiPath; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::LaunchInstaller( LPCTSTR pParam ) +{ + LPCTSTR sMsiPath = GetPathToMSI(); + + if ( !sMsiPath ) + { + Log( TEXT( "ERROR: msiexec not found!" ) ); + SetError( ERROR_FILE_NOT_FOUND ); + return false; + } + + STARTUPINFO aSUI; + PROCESS_INFORMATION aPI; + + Log( TEXT( " Will install using <%s>\r\n" ), sMsiPath ); + Log( TEXT( " Prameters are: %s\r\n" ), pParam ); + + OutputDebugStringFormat( TEXT( " Will install using <%s>\r\n" ), sMsiPath ); + OutputDebugStringFormat( TEXT( " Prameters are: %s\r\n" ), pParam ); + + ZeroMemory( (void*)&aPI, sizeof( PROCESS_INFORMATION ) ); + ZeroMemory( (void*)&aSUI, sizeof( STARTUPINFO ) ); + + aSUI.cb = sizeof(STARTUPINFO); + aSUI.dwFlags = STARTF_USESHOWWINDOW; + aSUI.wShowWindow = SW_SHOW; + + DWORD nCmdLineLength = lstrlen( sMsiPath ) + lstrlen( pParam ) + 2; + TCHAR *sCmdLine = new TCHAR[ nCmdLineLength ]; + + if ( FAILED( StringCchCopy( sCmdLine, nCmdLineLength, sMsiPath ) ) || + FAILED( StringCchCat( sCmdLine, nCmdLineLength, TEXT( " " ) ) ) || + FAILED( StringCchCat( sCmdLine, nCmdLineLength, pParam ) ) ) + { + delete [] sCmdLine; + SetError( ERROR_INSTALL_FAILURE ); + return false; + } + + if ( !WIN::CreateProcess( NULL, sCmdLine, NULL, NULL, FALSE, + CREATE_DEFAULT_ERROR_MODE, NULL, NULL, + &aSUI, &aPI ) ) + { + Log( TEXT( "ERROR: Could not create process %s.\r\n" ), sCmdLine ); + SetError( WIN::GetLastError() ); + delete [] sCmdLine; + return false; + } + + DWORD nResult = WaitForProcess( aPI.hProcess ); + bool bRet = true; + + if( ERROR_SUCCESS != nResult ) + { + Log( TEXT( "ERROR: While waiting for %s.\r\n" ), sCmdLine ); + SetError( nResult ); + bRet = false; + } + else + { + GetExitCodeProcess( aPI.hProcess, &nResult ); + SetError( nResult ); + + if ( nResult != ERROR_SUCCESS ) + { + TCHAR sBuf[80]; + StringCchPrintf( sBuf, 80, TEXT("Warning: msiexec returned %u.\r\n"), nResult ); + Log( sBuf ); + } + else + Log( TEXT( " Installation completed successfully.\r\n" ) ); + } + + CloseHandle( aPI.hProcess ); + + delete [] sCmdLine; + + return bRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::Install( long nLanguage ) +{ + LPTSTR pTransform = NULL; + + if ( nLanguage ) // look for transformation + { + for ( int i = 0; i < m_nLanguageCount; i++ ) + { + if ( m_ppLanguageList[i]->m_nLanguageID == nLanguage ) + { + if ( m_ppLanguageList[i]->m_pTransform ) + { + if ( !GetPathToFile( m_ppLanguageList[i]->m_pTransform, + &pTransform ) ) + { + Log( TEXT( "ERROR: Could not find transform <%s\r\n" ), m_ppLanguageList[i]->m_pTransform ); + return false; + } + } + break; + } + } + } + + TCHAR *pDataBasePath = NULL; + + if ( ! GetPathToFile( m_pDatabase, &pDataBasePath ) ) + { + Log( TEXT( "ERROR: Could not find database <%s\r\n" ), m_pDatabase ); + SetError( ERROR_INSTALL_SOURCE_ABSENT ); + return false; + } + + // we will always use the parameter setup used + int nParLen = lstrlen( PARAM_SETUP_USED ); + + if ( m_bRegNoMsoTypes ) + nParLen += lstrlen( PARAM_REG_NO_MSO_TYPES ); + else if ( m_bRegAllMsoTypes ) + nParLen += lstrlen( PARAM_REG_ALL_MSO_TYPES ); + + if ( m_pAdvertise ) + nParLen += lstrlen( m_pAdvertise ) + 1; // one for the space + else if ( m_bIsMinorUpgrade ) + nParLen += lstrlen( PARAM_MINOR_UPGRADE ); + else + nParLen += lstrlen( PARAM_PACKAGE ); + + nParLen += lstrlen( pDataBasePath ) + 3; // two quotes, one null + + if ( NeedReboot() ) + nParLen += lstrlen( PARAM_REBOOT ); + + if ( m_pPatchFiles ) + { + nParLen += lstrlen( PARAM_PATCH ); + nParLen += lstrlen( m_pPatchFiles ); + } + + if ( pTransform ) + { + nParLen += lstrlen( PARAM_TRANSFORM ); + nParLen += lstrlen( pTransform ) + 2; // two quotes + } + + if ( m_pCmdLine ) + nParLen += lstrlen( m_pCmdLine ) + 1; // one for the space; + + TCHAR *pParams = new TCHAR[ nParLen ]; + + StringCchCopy( pParams, nParLen, PARAM_SETUP_USED ); + + if ( m_bRegNoMsoTypes ) + StringCchCat( pParams, nParLen, PARAM_REG_NO_MSO_TYPES ); + else if ( m_bRegAllMsoTypes ) + StringCchCat( pParams, nParLen, PARAM_REG_ALL_MSO_TYPES ); + + if ( m_pAdvertise ) + StringCchCat( pParams, nParLen, m_pAdvertise ); + else if ( IsAdminInstall() ) + StringCchCat( pParams, nParLen, PARAM_ADMIN ); + else if ( m_bIsMinorUpgrade ) + StringCchCat( pParams, nParLen, PARAM_MINOR_UPGRADE ); + else + StringCchCat( pParams, nParLen, PARAM_PACKAGE ); + + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + StringCchCat( pParams, nParLen, pDataBasePath ); + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + + if ( NeedReboot() ) + StringCchCat( pParams, nParLen, PARAM_REBOOT ); + + if ( m_pPatchFiles ) + { + StringCchCat( pParams, nParLen, PARAM_PATCH ); + StringCchCat( pParams, nParLen, m_pPatchFiles ); + } + + if ( pTransform ) + { + StringCchCat( pParams, nParLen, PARAM_TRANSFORM ); + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + StringCchCat( pParams, nParLen, pTransform ); + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + } + + if ( m_pCmdLine ) + { + StringCchCat( pParams, nParLen, TEXT( " " ) ); + StringCchCat( pParams, nParLen, m_pCmdLine ); + } + + return LaunchInstaller( pParams ); +} + +//-------------------------------------------------------------------------- +UINT SetupAppX::GetError() const +{ + UINT nErr = 0; + + if ( m_pMSIErrorCode ) + nErr = (UINT) *m_pMSIErrorCode; + + if ( nErr == 0 ) + nErr = m_uiRet; + + if ( nErr != 0 ) + OutputDebugStringFormat( TEXT("Setup will return error (%d).\n"), nErr ); + return nErr; +} + +//-------------------------------------------------------------------------- +void SetupAppX::DisplayError( UINT nErr ) const +{ + TCHAR sError[ MAX_TEXT_LENGTH ] = {0}; + TCHAR sTmp[ MAX_TEXT_LENGTH ] = {0}; + + UINT nMsgType = MB_OK | MB_ICONERROR; + + switch ( nErr ) + { + case ERROR_SUCCESS: break; // 0 + + case ERROR_FILE_NOT_FOUND: // 2 + WIN::LoadString( m_hInst, IDS_FILE_NOT_FOUND, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pErrorText ); + break; + case ERROR_INVALID_DATA: // 13 + WIN::LoadString( m_hInst, IDS_INVALID_PROFILE, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_OUTOFMEMORY: WIN::LoadString( m_hInst, IDS_OUTOFMEM, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INSTALL_USEREXIT: + WIN::LoadString( m_hInst, IDS_USER_CANCELLED, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INSTALL_ALREADY_RUNNING: // 1618 + WIN::LoadString( m_hInst, IDS_ALREADY_RUNNING, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INSTALL_SOURCE_ABSENT: + WIN::LoadString( m_hInst, IDS_NOMSI, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_DS_INSUFF_ACCESS_RIGHTS: // 8344 + WIN::LoadString( m_hInst, IDS_REQUIRES_ADMIN_PRIV, sError, MAX_TEXT_LENGTH ); + break; + case E_ABORT: WIN::LoadString( m_hInst, IDS_UNKNOWN_ERROR, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INVALID_PARAMETER: // 87 + WIN::LoadString( m_hInst, IDS_INVALID_PARAM, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pErrorText ); + break; + + case ERROR_SETUP_TO_OLD: // - 3 + WIN::LoadString( m_hInst, IDS_SETUP_TO_OLD, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pReqVersion, m_pErrorText ); + break; + case ERROR_SETUP_NOT_FOUND: // - 4 + WIN::LoadString( m_hInst, IDS_SETUP_NOT_FOUND, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pReqVersion ); + break; + case ERROR_SHOW_USAGE: // - 2 + nMsgType = MB_OK | MB_ICONINFORMATION; + WIN::LoadString( m_hInst, IDS_USAGE, sError, MAX_TEXT_LENGTH ); + break; + + default: WIN::LoadString( m_hInst, IDS_UNKNOWN_ERROR, sError, MAX_TEXT_LENGTH ); + break; + } + + if ( sError[0] ) + { + if ( !m_bQuiet ) + { + ConvertNewline( sError ); + WIN::MessageBox( NULL, sError, m_pAppTitle, nMsgType ); + } + + Log( TEXT( "ERROR: %s\r\n" ), sError ); + } +} + +//-------------------------------------------------------------------------- +long SetupAppX::GetLanguageID( long nIndex ) const +{ + if ( nIndex >=0 && nIndex < m_nLanguageCount ) + return m_ppLanguageList[ nIndex ]->m_nLanguageID; + else + return 0; +} + +//-------------------------------------------------------------------------- +void SetupAppX::GetLanguageName( long nLanguage, LPTSTR sName ) const +{ + switch ( nLanguage ) + { + case 1028: WIN::LoadString( m_hInst, IDS_LANGUAGE_ZH_TW, sName, MAX_LANGUAGE_LEN ); break; + case 1029: WIN::LoadString( m_hInst, IDS_LANGUAGE_CS, sName, MAX_LANGUAGE_LEN ); break; + case 1030: WIN::LoadString( m_hInst, IDS_LANGUAGE_DA, sName, MAX_LANGUAGE_LEN ); break; + case 1031: WIN::LoadString( m_hInst, IDS_LANGUAGE_DE_DE, sName, MAX_LANGUAGE_LEN ); break; + case 1032: WIN::LoadString( m_hInst, IDS_LANGUAGE_EL, sName, MAX_LANGUAGE_LEN ); break; + case 1033: WIN::LoadString( m_hInst, IDS_LANGUAGE_EN_US, sName, MAX_LANGUAGE_LEN ); break; + case 1034: WIN::LoadString( m_hInst, IDS_LANGUAGE_ES, sName, MAX_LANGUAGE_LEN ); break; + case 1035: WIN::LoadString( m_hInst, IDS_LANGUAGE_FI, sName, MAX_LANGUAGE_LEN ); break; + case 1036: WIN::LoadString( m_hInst, IDS_LANGUAGE_FR_FR, sName, MAX_LANGUAGE_LEN ); break; + case 1037: WIN::LoadString( m_hInst, IDS_LANGUAGE_HE, sName, MAX_LANGUAGE_LEN ); break; + case 1038: WIN::LoadString( m_hInst, IDS_LANGUAGE_HU, sName, MAX_LANGUAGE_LEN ); break; + case 1040: WIN::LoadString( m_hInst, IDS_LANGUAGE_IT_IT, sName, MAX_LANGUAGE_LEN ); break; + case 1041: WIN::LoadString( m_hInst, IDS_LANGUAGE_JA, sName, MAX_LANGUAGE_LEN ); break; + case 1042: WIN::LoadString( m_hInst, IDS_LANGUAGE_KO, sName, MAX_LANGUAGE_LEN ); break; + case 1043: WIN::LoadString( m_hInst, IDS_LANGUAGE_NL_NL, sName, MAX_LANGUAGE_LEN ); break; + case 1044: WIN::LoadString( m_hInst, IDS_LANGUAGE_NO_NO, sName, MAX_LANGUAGE_LEN ); break; + case 1045: WIN::LoadString( m_hInst, IDS_LANGUAGE_PL, sName, MAX_LANGUAGE_LEN ); break; + case 1046: WIN::LoadString( m_hInst, IDS_LANGUAGE_PT_BR, sName, MAX_LANGUAGE_LEN ); break; + case 1049: WIN::LoadString( m_hInst, IDS_LANGUAGE_RU, sName, MAX_LANGUAGE_LEN ); break; + case 1051: WIN::LoadString( m_hInst, IDS_LANGUAGE_SK, sName, MAX_LANGUAGE_LEN ); break; + case 1053: WIN::LoadString( m_hInst, IDS_LANGUAGE_SV_SE, sName, MAX_LANGUAGE_LEN ); break; + case 1054: WIN::LoadString( m_hInst, IDS_LANGUAGE_TH, sName, MAX_LANGUAGE_LEN ); break; + case 1055: WIN::LoadString( m_hInst, IDS_LANGUAGE_TR, sName, MAX_LANGUAGE_LEN ); break; + case 1061: WIN::LoadString( m_hInst, IDS_LANGUAGE_ET, sName, MAX_LANGUAGE_LEN ); break; + case 2052: WIN::LoadString( m_hInst, IDS_LANGUAGE_ZH_CN, sName, MAX_LANGUAGE_LEN ); break; + case 2070: WIN::LoadString( m_hInst, IDS_LANGUAGE_PT_PT, sName, MAX_LANGUAGE_LEN ); break; + + default: + { + TCHAR sTmp[ MAX_LANGUAGE_LEN ] = {0}; + + WIN::LoadString( m_hInst, IDS_UNKNOWN_LANG, sTmp, MAX_LANGUAGE_LEN ); + StringCchPrintf( sName, MAX_LANGUAGE_LEN, sTmp, nLanguage ); + } + } +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::CheckVersion() +{ + boolean bRet = false; + HMODULE hMsi = LoadMsiLibrary(); + + Log( TEXT( " Looking for installed MSI with version >= %s\r\n" ), m_pReqVersion ); + + if ( !hMsi ) + { + Log( TEXT( "Error: No MSI found!\r\n" ) ); + SetError( (UINT) ERROR_SETUP_NOT_FOUND ); + } + else + { + PFnDllGetVersion pDllGetVersion = (PFnDllGetVersion) GetProcAddress( hMsi, MSIAPI_DllGetVersion ); + + if ( pDllGetVersion ) + { + DLLVERSIONINFO aInfo; + + aInfo.cbSize = sizeof( DLLVERSIONINFO ); + if ( NOERROR == pDllGetVersion( &aInfo ) ) + { + TCHAR pMsiVersion[ VERSION_SIZE ]; + StringCchPrintf( pMsiVersion, VERSION_SIZE, TEXT("%d.%d.%4d"), + aInfo.dwMajorVersion, + aInfo.dwMinorVersion, + aInfo.dwBuildNumber ); + if ( _tcsncmp( pMsiVersion, m_pReqVersion, _tcslen( pMsiVersion ) ) < 0 ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pMsiVersion ); + SetError( (UINT) ERROR_SETUP_TO_OLD ); + Log( TEXT( "Warning: Old MSI version found <%s>, update needed!\r\n" ), pMsiVersion ); + } + else + { + Log( TEXT( " Found MSI version <%s>, no update needed\r\n" ), pMsiVersion ); + bRet = true; + } + if ( aInfo.dwMajorVersion >= 3 ) + m_bSupportsPatch = true; + else + Log( TEXT("Warning: Patching not supported! MSI-Version <%s>\r\n"), pMsiVersion ); + } + } + + FreeLibrary( hMsi ); + } + + return bRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::CheckForUpgrade() +{ + // When we have patch files we will never try an Minor upgrade + if ( m_pPatchFiles ) return true; + + if ( !m_pUpgradeKey || ( _tcslen( m_pUpgradeKey ) == 0 ) ) + { + Log( TEXT( " No Upgrade Key Found -> continue with standard installation!\r\n" ) ); + return true; + } + + HKEY hInstKey = NULL; + + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, m_pUpgradeKey, 0, KEY_READ, &hInstKey ) ) + { + Log( TEXT( " Found Upgrade Key in Registry (HKLM) -> will try minor upgrade!\r\n" ) ); + m_bIsMinorUpgrade = true; + } + else if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_CURRENT_USER, m_pUpgradeKey, 0, KEY_READ, &hInstKey ) ) + { + Log( TEXT( " Found Upgrade Key in Registry (HKCU) -> will try minor upgrade!\r\n" ) ); + m_bIsMinorUpgrade = true; + } + else + { + Log( TEXT( " Didn't Find Upgrade Key in Registry -> continue with standard installation!\r\n" ) ); + return true; + } + + if ( m_pProductVersion && ( _tcslen( m_pProductVersion ) > 0 ) ) + { + TCHAR *sProductVersion = new TCHAR[ MAX_PATH + 1 ]; + DWORD nSize = MAX_PATH + 1; + + sProductVersion[0] = '\0'; + + // get product version + if ( ERROR_SUCCESS == RegQueryValueEx( hInstKey, PRODUCT_VERSION, NULL, NULL, (LPBYTE)sProductVersion, &nSize ) ) + { + if ( lstrcmpi( sProductVersion, m_pProductVersion ) == 0 ) + { + Log( TEXT( " Same Product Version already installed, no minor upgrade!\r\n" ) ); + m_bIsMinorUpgrade = false; + } + } + + delete [] sProductVersion; + } + + return true; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::IsTerminalServerInstalled() const +{ + boolean bIsTerminalServer = false; + + const TCHAR sSearchStr[] = TEXT("Terminal Server"); + const TCHAR sKey[] = TEXT("System\\CurrentControlSet\\Control\\ProductOptions"); + const TCHAR sValue[] = TEXT("ProductSuite"); + + DWORD dwSize = 0; + HKEY hKey = 0; + DWORD dwType = 0; + + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sKey, 0, KEY_READ, &hKey ) && + ERROR_SUCCESS == RegQueryValueEx( hKey, sValue, NULL, &dwType, NULL, &dwSize ) && + dwSize > 0 && + REG_MULTI_SZ == dwType ) + { + TCHAR* sSuiteList = new TCHAR[ (dwSize*sizeof(byte)/sizeof(TCHAR)) + 1 ]; + + ZeroMemory(sSuiteList, dwSize); + + if ( ERROR_SUCCESS == RegQueryValueEx( hKey, sValue, NULL, &dwType, (LPBYTE)sSuiteList, &dwSize) ) + { + DWORD nMulti = 0; + DWORD nSrch = lstrlen( sSearchStr ); + const TCHAR *sSubString = sSuiteList; + + while (*sSubString) + { + nMulti = lstrlen( sSubString ); + if ( nMulti == nSrch && 0 == lstrcmp( sSearchStr, sSubString ) ) + { + bIsTerminalServer = true; + break; + } + + sSubString += (nMulti + 1); + } + } + delete [] sSuiteList; + } + + if ( hKey ) + RegCloseKey( hKey ); + + return bIsTerminalServer; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::AlreadyRunning() const +{ + if ( m_bIgnoreAlreadyRunning ) + { + Log( TEXT("Ignoring already running MSI instance!\r\n") ); + return false; + } + + const TCHAR *sMutexName = NULL; + const TCHAR sGUniqueName[] = TEXT( "Global\\_MSISETUP_{EA8130C1-8D3D-4338-9309-1A52D530D846}" ); + const TCHAR sUniqueName[] = TEXT( "_MSISETUP_{EA8130C1-8D3D-4338-9309-1A52D530D846}" ); + + if ( IsWin9x() ) + sMutexName = sUniqueName; + else if ( ( GetOSVersion() < 5 ) && ! IsTerminalServerInstalled() ) + sMutexName = sUniqueName; + else + sMutexName = sGUniqueName; + + HANDLE hMutex = 0; + + hMutex = WIN::CreateMutex( NULL, FALSE, sMutexName ); + + if ( !hMutex || ERROR_ALREADY_EXISTS == WIN::GetLastError() ) + { + if ( !hMutex ) + Log( TEXT( "ERROR: AlreadyRunning() could not create mutex!\r\n" ) ); + else + Log( TEXT( "ERROR: There's already a setup running!\r\n" ) ); + + return true; + } + Log( TEXT( " No running Setup found\r\n" ) ); + + return false; +} + +//-------------------------------------------------------------------------- +DWORD SetupAppX::WaitForProcess( HANDLE hHandle ) +{ + DWORD nResult = NOERROR; + boolean bLoop = true; + + MSG aMsg; + ZeroMemory( (void*) &aMsg, sizeof(MSG) ); + + while ( bLoop ) + { + switch ( WIN::MsgWaitForMultipleObjects( 1, &hHandle, false, + INFINITE, QS_ALLINPUT ) ) + { + case WAIT_OBJECT_0: bLoop = false; + break; + + case (WAIT_OBJECT_0 + 1): + { + if ( WIN::PeekMessage( &aMsg, NULL, NULL, NULL, PM_REMOVE ) ) + { + WIN::TranslateMessage( &aMsg ); + WIN::DispatchMessage( &aMsg ); + } + break; + } + + default: + { + nResult = WIN::GetLastError(); + bLoop = false; + } + } + } + + return nResult; +} + +//-------------------------------------------------------------------------- +void SetupAppX::Log( LPCTSTR pMessage, LPCTSTR pText ) const +{ + if ( m_pLogFile ) + { + static boolean bInit = false; + + if ( !bInit ) + { + bInit = true; + if ( ! IsWin9x() ) + _ftprintf( m_pLogFile, TEXT("%c"), 0xfeff ); + + _tsetlocale( LC_ALL, TEXT("") ); + _ftprintf( m_pLogFile, TEXT("\nCodepage=%s\nMultiByte Codepage=[%d]\n"), + _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 ); + } +} + +//-------------------------------------------------------------------------- +DWORD SetupAppX::GetNextArgument( LPCTSTR pStr, LPTSTR *pArg, LPTSTR *pNext, + boolean bStripQuotes ) +{ + boolean bInQuotes = false; + boolean bFoundArgEnd = false; + LPCTSTR pChar = pStr; + LPCTSTR pFirst = NULL; + + if ( NULL == pChar ) + return ERROR_NO_MORE_ITEMS; + + while ( ' ' == (*pChar) || '\t' == (*pChar) ) + pChar = CharNext( pChar ); + + if ( '\0' == (*pChar) ) + return ERROR_NO_MORE_ITEMS; + + int nCount = 1; + pFirst = pChar; + + while ( ! bFoundArgEnd ) + { + if ( '\0' == (*pChar) ) + bFoundArgEnd = true; + else if ( !bInQuotes && ' ' == (*pChar) ) + bFoundArgEnd = true; + else if ( !bInQuotes && '\t' == (*pChar) ) + bFoundArgEnd = true; + else + { + if ( '\"' == (*pChar) ) + { + bInQuotes = !bInQuotes; + if ( bStripQuotes ) + { + if ( pChar == pFirst ) + pFirst = CharNext( pFirst ); + nCount -= 1; + } + } + + pChar = CharNext( pChar ); + nCount += 1; + } + } + + if ( pArg ) + { + *pArg = new TCHAR[ nCount ]; + StringCchCopyN ( *pArg, nCount, pFirst, nCount-1 ); + } + + if ( pNext ) + *pNext = CharNext( pChar ); + + return ERROR_SUCCESS; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::GetCmdLineParameters( LPTSTR *pCmdLine ) +{ + int nRet = ERROR_SUCCESS; + LPTSTR pStart = NULL; + LPTSTR pNext = NULL; + + if ( GetNextArgument( *pCmdLine, NULL, &pNext ) != ERROR_SUCCESS ) + { + SetError( ERROR_NO_MORE_ITEMS ); + return false; + } + + int nSize = lstrlen( *pCmdLine ) + 2; + TCHAR *pNewCmdLine = new TCHAR[ nSize ]; + pNewCmdLine[0] = '\0'; + + while ( GetNextArgument( pNext, &pStart, &pNext ) == ERROR_SUCCESS ) + { + boolean bDeleteStart = true; + + if ( (*pStart) == '/' || (*pStart) == '-' ) + { + LPTSTR pSub = CharNext( pStart ); + if ( (*pSub) == 'l' || (*pSub) == 'L' ) + { + pSub = CharNext( pSub ); + if ( (*pSub) == 'a' || (*pSub) == 'A' ) + { // --- handle the lang parameter --- + LPTSTR pLanguage = NULL; + LPTSTR pLastChar; + if ( GetNextArgument( pNext, &pLanguage, &pNext, true ) != ERROR_SUCCESS ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); + nRet = ERROR_INVALID_PARAMETER; + break; + } + + m_nLanguageID = _tcstol( pLanguage, &pLastChar, 10 ); + delete [] pLanguage; + } + else + { // --- handle the l(og) parameter --- + boolean bAppend = false; + LPTSTR pFileName = NULL; + + while ( *pSub ) + { + if ( *pSub == '+' ) + { + bAppend = true; + break; + } + pSub = CharNext( pSub ); + } + + if ( GetNextArgument( pNext, &pFileName, &pNext, true ) != ERROR_SUCCESS ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); + nRet = ERROR_INVALID_PARAMETER; + break; + } + + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + // we need to append a '+' otherwise msiexec would overwrite our log file + if ( !bAppend && FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( "+" ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + if ( FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " \"" ) ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, pFileName ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( "\" " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + + if ( bAppend ) + m_pLogFile = _tfopen( pFileName, TEXT( "ab" ) ); + else + m_pLogFile = _tfopen( pFileName, TEXT( "wb" ) ); + + delete [] pFileName; + } + } + else if ( (*pSub) == 'q' || (*pSub) == 'Q' ) + { // --- Handle quiet file parameter --- + pSub = CharNext( pSub ); + if ( ! (*pSub) || (*pSub) == 'n' || (*pSub) == 'N' ) + m_bQuiet = true; + + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + } + else if ( _tcsnicmp( pSub, PARAM_RUNNING, _tcslen( PARAM_RUNNING ) ) == 0 ) + { + m_bIgnoreAlreadyRunning = true; + } + else if ( _tcsnicmp( pSub, CMDLN_REG_ALL_MSO_TYPES, _tcslen( CMDLN_REG_ALL_MSO_TYPES ) ) == 0 ) + { + m_bRegAllMsoTypes = true; + } + else if ( _tcsnicmp( pSub, CMDLN_REG_NO_MSO_TYPES, _tcslen( CMDLN_REG_NO_MSO_TYPES ) ) == 0 ) + { + m_bRegNoMsoTypes = true; + } + else if ( (*pSub) == 'i' || (*pSub) == 'I' || (*pSub) == 'f' || (*pSub) == 'F' || + (*pSub) == 'p' || (*pSub) == 'P' || (*pSub) == 'x' || (*pSub) == 'X' || + (*pSub) == 'y' || (*pSub) == 'Y' || (*pSub) == 'z' || (*pSub) == 'Z' ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); + nRet = ERROR_INVALID_PARAMETER; + break; + } + else if ( (*pSub) == 'a' || (*pSub) == 'A' ) + { // --- Handle Adminstrative Installation --- + SetAdminInstall( true ); + } + else if ( (*pSub) == 'j' || (*pSub) == 'J' ) + { // --- Handle Adminstrative Installation --- + m_pAdvertise = pStart; + m_bQuiet = true; + bDeleteStart = false; + } + else if ( (*pSub) == '?' || (*pSub) == 'h' || (*pSub) == 'H' ) + { // --- Handle Show Usage --- + nRet = ERROR_SHOW_USAGE; + break; + } + else + { + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + } + } + else + { + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + } + + if ( bDeleteStart ) delete [] pStart; + pStart = NULL; + } + + if ( pStart ) delete [] pStart; + + *pCmdLine = pNewCmdLine; + + if ( nRet != ERROR_SUCCESS ) + { + SetError( nRet ); + return false; + } + else + return true;; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::IsAdmin() +{ + if ( IsWin9x() ) + return true; + + PSID aPsidAdmin; + SID_IDENTIFIER_AUTHORITY aAuthority = SECURITY_NT_AUTHORITY; + + if ( !AllocateAndInitializeSid( &aAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, + &aPsidAdmin ) ) + return false; + + BOOL bIsAdmin = FALSE; + + if ( GetOSVersion() >= 5 ) + { + HMODULE hAdvapi32 = LoadLibrary( ADVAPI32_DLL ); + + if ( !hAdvapi32 ) + bIsAdmin = FALSE; + else + { + PFnCheckTokenMembership pfnCheckTokenMembership = (PFnCheckTokenMembership) GetProcAddress( hAdvapi32, ADVAPI32API_CheckTokenMembership); + if ( !pfnCheckTokenMembership || !pfnCheckTokenMembership( NULL, aPsidAdmin, &bIsAdmin ) ) + bIsAdmin = FALSE; + } + FreeLibrary( hAdvapi32 ); + } + else + { + // NT4, check groups of user + HANDLE hAccessToken = 0; + UCHAR *szInfoBuffer = new UCHAR[ 1024 ]; // may need to resize if TokenInfo too big + DWORD dwInfoBufferSize = 1024; + DWORD dwRetInfoBufferSize = 0; + UINT i=0; + + if ( WIN::OpenProcessToken( WIN::GetCurrentProcess(), TOKEN_READ, &hAccessToken ) ) + { + bool bSuccess = false; + bSuccess = WIN::GetTokenInformation( hAccessToken, TokenGroups, + szInfoBuffer, dwInfoBufferSize, + &dwRetInfoBufferSize ) == TRUE; + + if( dwRetInfoBufferSize > dwInfoBufferSize ) + { + delete [] szInfoBuffer; + szInfoBuffer = new UCHAR[ dwRetInfoBufferSize ]; + dwInfoBufferSize = dwRetInfoBufferSize; + bSuccess = WIN::GetTokenInformation( hAccessToken, TokenGroups, + szInfoBuffer, dwInfoBufferSize, + &dwRetInfoBufferSize ) == TRUE; + } + + WIN::CloseHandle( hAccessToken ); + + if ( bSuccess ) + { + PTOKEN_GROUPS pGroups = (PTOKEN_GROUPS)(UCHAR*) szInfoBuffer; + for( i=0; i<pGroups->GroupCount; i++ ) + { + if( WIN::EqualSid( aPsidAdmin, pGroups->Groups[i].Sid ) ) + { + bIsAdmin = TRUE; + break; + } + } + } + + delete [] szInfoBuffer; + } + } + + WIN::FreeSid( aPsidAdmin ); + + return bIsAdmin ? true : false; +} + +//-------------------------------------------------------------------------- +LPTSTR SetupAppX::CopyIniFile( LPCTSTR pIniFile ) +{ + m_pTmpName = _ttempnam( TEXT( "C:\\" ), TEXT( "Setup" ) ); + + if ( !m_pTmpName ) + { + Log( TEXT( "ERROR: Could not create temp file\n" ) ); + return NULL; + } + + FILE *pOut = _tfopen( m_pTmpName, TEXT( "wb" ) ); + FILE *pIn = _tfopen( pIniFile, TEXT( "rb" ) ); + + if ( pOut && pIn ) + { + size_t nRead, nWritten; + BYTE pBuf[1024]; + + nRead = fread( pBuf, sizeof( BYTE ), 1024, pIn ); + while ( nRead && !ferror( pIn ) ) + { + nWritten = fwrite( pBuf, sizeof( BYTE ), nRead, pOut ); + if ( nWritten != nRead ) + { + Log( TEXT( "ERROR: Could not write all bytes to temp file\n" ) ); + break; + } + nRead = fread( pBuf, sizeof( BYTE ), 1024, pIn ); + } + } + + if ( pOut ) fclose( pOut ); + if ( pIn ) fclose( pIn ); + + return m_pTmpName; +} + +//-------------------------------------------------------------------------- +void SetupAppX::ConvertNewline( LPTSTR pText ) const +{ + int i=0; + + while ( pText[i] != 0 ) + { + if ( ( pText[i] == '\\' ) && ( pText[i+1] == 'n' ) ) + { + pText[i] = 0x0d; + pText[i+1] = 0x0a; + i+=2; + } + else + i+=1; + } +} + +//-------------------------------------------------------------------------- +LPTSTR SetupAppX::SetProdToAppTitle( LPCTSTR pProdName ) +{ + if ( !pProdName ) return m_pAppTitle; + + LPTSTR pAppProdTitle = new TCHAR[ MAX_STR_CAPTION ]; + pAppProdTitle[0] = '\0'; + + WIN::LoadString( m_hInst, IDS_APP_PROD_TITLE, pAppProdTitle, MAX_STR_CAPTION ); + + int nAppLen = lstrlen( pAppProdTitle ); + int nProdLen = lstrlen( pProdName ); + + if ( ( nAppLen == 0 ) || ( nProdLen == 0 ) ) + { + delete [] pAppProdTitle; + return m_pAppTitle; + } + + int nLen = nAppLen + nProdLen + 3; + + if ( nLen > STRSAFE_MAX_CCH ) return m_pAppTitle; + + LPTSTR pIndex = _tcsstr( pAppProdTitle, PRODUCT_NAME_VAR ); + + if ( pIndex ) + { + int nOffset = pIndex - pAppProdTitle; + int nVarLen = lstrlen( PRODUCT_NAME_VAR ); + + LPTSTR pNewTitle = new TCHAR[ nLen ]; + pNewTitle[0] = '\0'; + + if ( nOffset > 0 ) + { + StringCchCopyN( pNewTitle, nLen, pAppProdTitle, nOffset ); + } + + StringCchCat( pNewTitle, nLen, pProdName ); + + if ( nOffset + nVarLen < nAppLen ) + { + StringCchCat( pNewTitle, nLen, pIndex + nVarLen ); + } + + delete [] m_pAppTitle; + m_pAppTitle = pNewTitle; + } + + delete [] pAppProdTitle; + + 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 ) +{ + m_nLanguageID = 0; + m_pTransform = NULL; + + LPTSTR pLastChar; + + m_nLanguageID = _tcstol( pData, &pLastChar, 10 ); + + if ( *pLastChar == ',' ) + { + pLastChar += 1; + int nLen = lstrlen( pLastChar ) + 1; + m_pTransform = new TCHAR [ nLen ]; + StringCchCopy( m_pTransform, nLen, pLastChar ); + } +} + +//-------------------------------------------------------------------------- +LanguageDataX::~LanguageDataX() +{ + if ( m_pTransform ) delete [] m_pTransform; +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +SetupApp* Create_SetupAppX() +{ + return new SetupAppX; +} + +//-------------------------------------------------------------------------- diff --git a/desktop/win32/source/setup/setup.hxx b/desktop/win32/source/setup/setup.hxx new file mode 100644 index 000000000000..72785cc75b31 --- /dev/null +++ b/desktop/win32/source/setup/setup.hxx @@ -0,0 +1,155 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: setup.hxx,v $ + * $Revision: 1.12 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "setup_main.hxx" + +//-------------------------------------------------------------------------- + +#ifdef SetupAppX + #undef SetupAppX +#endif + +#ifdef Create_SetupAppX + #undef Create_SetupAppX +#endif + +#ifdef LanguageDataX + #undef LanguageDataX +#endif + + +#ifdef UNICODE + #define SetupAppX SetupAppW + #define Create_SetupAppX Create_SetupAppW + #define LanguageDataX LanguageDataW +#else + #define SetupAppX SetupAppA + #define Create_SetupAppX Create_SetupAppA + #define LanguageDataX LanguageDataA +#endif + +//-------------------------------------------------------------------------- + +struct LanguageDataX +{ + long m_nLanguageID; + LPTSTR m_pTransform; + + LanguageDataX( LPTSTR pData ); + ~LanguageDataX(); +}; + +//-------------------------------------------------------------------------- + +class SetupAppX : public SetupApp +{ + HINSTANCE m_hInst; + HANDLE m_hMapFile; + LPTSTR m_pAppTitle; + LPTSTR m_pCmdLine; + LPTSTR m_pDatabase; + LPTSTR m_pReqVersion; + LPTSTR m_pProductName; + LPTSTR m_pAdvertise; + LPTSTR m_pTmpName; + LPTSTR m_pErrorText; + LPTSTR m_pModuleFile; + LPTSTR m_pPatchFiles; + LPCTSTR m_pUpgradeKey; + LPCTSTR m_pProductVersion; + int *m_pMSIErrorCode; + + boolean m_bQuiet : 1; + boolean m_bIgnoreAlreadyRunning : 1; + boolean m_bRegNoMsoTypes :1; + boolean m_bRegAllMsoTypes :1; + boolean m_bIsMinorUpgrade :1; + boolean m_bSupportsPatch :1; + + FILE *m_pLogFile; + + long m_nLanguageID; + long m_nLanguageCount; + LanguageDataX** m_ppLanguageList; + +private: + + boolean GetPathToFile( TCHAR* pFileName, TCHAR **pPath ); + LPCTSTR GetPathToMSI(); + + int GetNameValue( TCHAR* pLine, TCHAR **pName, TCHAR **pValue ); + boolean GetProfileSection( LPCTSTR pFileName, LPCTSTR pSection, + DWORD& rSize, LPTSTR *pRetBuf ); + LPTSTR CopyIniFile( LPCTSTR pIniFile ); + void ConvertNewline( LPTSTR pText ) const; + + boolean LaunchInstaller( LPCTSTR pParam ); + HMODULE LoadMsiLibrary(); + DWORD WaitForProcess( HANDLE hHandle ); + + boolean GetCmdLineParameters( LPTSTR *pCmdLine ); + DWORD GetNextArgument( LPCTSTR pStr, LPTSTR *pArg, + LPTSTR *pNext, boolean bStripQuotes = false ); + boolean IsAdmin(); + + + boolean GetCommandLine(); + + boolean IsTerminalServerInstalled() const; + void AddFileToPatchList( TCHAR* pPath, TCHAR* pFile ); + boolean IsPatchInstalled( TCHAR* pBaseDir, TCHAR* pFileName ); +public: + SetupAppX(); + ~SetupAppX(); + + virtual boolean Initialize( HINSTANCE hInst ); + virtual boolean AlreadyRunning() const; + virtual boolean ReadProfile(); + virtual boolean GetPatches(); + virtual boolean ChooseLanguage( long& rLanguage ); + virtual boolean CheckVersion(); + virtual boolean CheckForUpgrade(); + virtual boolean Install( long nLanguage ); + + virtual UINT GetError() const; + virtual void DisplayError( UINT nErr ) const; + + void Log( LPCTSTR pMessage, LPCTSTR pText = NULL ) const; + + long GetLanguageCount() const { return m_nLanguageCount; } + long GetLanguageID( long nIndex ) const; + void GetLanguageName( long nLanguage, LPTSTR sName ) const; + + LPCTSTR GetAppTitle() const { return m_pAppTitle; } + LPTSTR SetProdToAppTitle( LPCTSTR pProdName ); + HINSTANCE GetHInst() const { return m_hInst; } +}; + +//-------------------------------------------------------------------------- diff --git a/desktop/win32/source/setup/setup.ico b/desktop/win32/source/setup/setup.ico Binary files differnew file mode 100644 index 000000000000..2a7ebda53a25 --- /dev/null +++ b/desktop/win32/source/setup/setup.ico diff --git a/desktop/win32/source/setup/setup.ulf b/desktop/win32/source/setup/setup.ulf new file mode 100644 index 000000000000..d0e867d49f3f --- /dev/null +++ b/desktop/win32/source/setup/setup.ulf @@ -0,0 +1,162 @@ +[%APP_TITLE%] +en-US = "Setup" + + +[%APP_PROD_TITLE%] +en-US = "The %PRODUCTNAME Setup" + + +[%OUTOFMEM%] +en-US = "Out of Memory" + + +[%NOMSI%] +en-US = "Setup was unable to find the msi package." + + +[%USER_CANCELLED%] +en-US = "Setup was cancelled" + + +[%REQUIRES_ADMIN_PRIV%] +en-US = "Administrator privileges are required for upgrading the Windows Installer." + + +[%FILE_NOT_FOUND%] +en-US = "Setup was unable to find the file '%s'." + + +[%INVALID_PARAM%] +en-US = "Invalid command line option '%s'. Please use '/?' for help." + + +[%SETUP_TO_OLD%] +en-US = "This package requires at least the version '%s' of the Windows Installer. \nYou have Windows Installer '%s' on your system!" + +[%SETUP_NOT_FOUND%] +en-US = "This package requires the Windows Installer. \nYou need at least Windows Installer '%s' on your system!" + + +[%USAGE%] +en-US = "Usage:\n /? : Shows this dialog.\n /a : Performs an administrative installation.\n /j[u|m] : Performs an advertising installation.\n /q[n] : Do not show any user interface (silent mode).\n" + + +[%ALREADY_RUNNING%] +en-US = "There is already a setup process running." + + +[%UNKNOWN_ERROR%] +en-US = "An Unknown Error occured!" + + +[%INVALID_PROFILE%] +en-US = "Invalid or incomplete profile." + + +[%UNKNOWN_LANG%] +en-US = "Unknown Language: %d" + + +[%LANGUAGE_ZH_TW%] +en-US = "Chinese (traditional)" + + +[%LANGUAGE_CS%] +en-US = "Czech" + + +[%LANGUAGE_DA%] +en-US = "Danish" + + +[%LANGUAGE_DE_DE%] +en-US = "German (Germany)" + + +[%LANGUAGE_EL%] +en-US = "Greek" + + +[%LANGUAGE_EN_US%] +en-US = "English (USA)" + + +[%LANGUAGE_ES%] +en-US = "Spanish (Spain)" + + +[%LANGUAGE_FI%] +en-US = "Finnish" + + +[%LANGUAGE_FR_FR%] +en-US = "French (France)" + + +[%LANGUAGE_HE%] +en-US = "Hebrew" + + +[%LANGUAGE_HU%] +en-US = "Hungarian" + + +[%LANGUAGE_IT_IT%] +en-US = "Italian (Italy)" + + +[%LANGUAGE_JA%] +en-US = "Japanese" + + +[%LANGUAGE_KO%] +en-US = "Korean" + + +[%LANGUAGE_NL_NL%] +en-US = "Dutch (Netherlands)" + + +[%LANGUAGE_NO_NO%] +en-US = "Norwegian (Bokmål)" + + +[%LANGUAGE_PL%] +en-US = "Polish" + + +[%LANGUAGE_PT_BR%] +en-US = "Portuguese (Brazil)" + + +[%LANGUAGE_RU%] +en-US = "Russian" + + +[%LANGUAGE_SK%] +en-US = "Slovakian" + + +[%LANGUAGE_SV_SE%] +en-US = "Swedish (Sweden)" + + +[%LANGUAGE_TH%] +en-US = "Thai" + + +[%LANGUAGE_TR%] +en-US = "Turkish" + + +[%LANGUAGE_ET%] +en-US = "Estonian" + + +[%LANGUAGE_ZH_CN%] +en-US = "Chinese (Simplified)" + + +[%LANGUAGE_PT_PT%] +en-US = "Portuguese (Portugal)" + diff --git a/desktop/win32/source/setup/setup_a.cxx b/desktop/win32/source/setup/setup_a.cxx new file mode 100644 index 000000000000..91f4fdc9a141 --- /dev/null +++ b/desktop/win32/source/setup/setup_a.cxx @@ -0,0 +1,34 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: setup_a.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "setup.cpp" diff --git a/desktop/win32/source/setup/setup_help.hxx b/desktop/win32/source/setup/setup_help.hxx new file mode 100644 index 000000000000..c3ccdaf53cbc --- /dev/null +++ b/desktop/win32/source/setup/setup_help.hxx @@ -0,0 +1,50 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: setup_help.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SETUP_HELP_HXX +#define SETUP_HELP_HXX + +//-------------------------------------------------------------------------- + + +#ifdef UNICODE +#else + #define LanguageDataX LanguageDataA +#endif + +//-------------------------------------------------------------------------- + +class SetupHelperX +{ +}; + +//-------------------------------------------------------------------------- + +#endif
\ No newline at end of file diff --git a/desktop/win32/source/setup/setup_main.cxx b/desktop/win32/source/setup/setup_main.cxx new file mode 100644 index 000000000000..515363749c55 --- /dev/null +++ b/desktop/win32/source/setup/setup_main.cxx @@ -0,0 +1,144 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <new> + +#include "setup_main.hxx" + +//-------------------------------------------------------------------------- + +void __cdecl newhandler() +{ + throw std::bad_alloc(); + return; +} + +//-------------------------------------------------------------------------- + +SetupApp::SetupApp() +{ + m_uiRet = ERROR_SUCCESS; + + // Get OS version + OSVERSIONINFO sInfoOS; + + ZeroMemory( &sInfoOS, sizeof(OSVERSIONINFO) ); + sInfoOS.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); + + GetVersionEx( &sInfoOS ); + + m_nOSVersion = sInfoOS.dwMajorVersion; + m_nMinorVersion = sInfoOS.dwMinorVersion; + m_bIsWin9x = ( VER_PLATFORM_WIN32_NT != sInfoOS.dwPlatformId ); + m_bNeedReboot = false; + m_bAdministrative = false; +} + +//-------------------------------------------------------------------------- + +SetupApp::~SetupApp() +{ +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +extern "C" int __stdcall WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int ) +{ + // Get OS version + OSVERSIONINFO sInfoOS; + + ZeroMemory( &sInfoOS, sizeof(OSVERSIONINFO) ); + sInfoOS.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); + + GetVersionEx( &sInfoOS ); + + boolean bIsWin9x = ( VER_PLATFORM_WIN32_NT != sInfoOS.dwPlatformId ); + + SetupApp *pSetup; + + if ( bIsWin9x ) + pSetup = Create_SetupAppA(); + else + pSetup = Create_SetupAppW(); + + try + { + if ( ! pSetup->Initialize( hInst ) ) + throw pSetup->GetError(); + + if ( pSetup->AlreadyRunning() ) + throw (UINT) ERROR_INSTALL_ALREADY_RUNNING; + + if ( ! pSetup->ReadProfile() ) + throw pSetup->GetError(); + + if ( ! pSetup->CheckVersion() ) + throw pSetup->GetError(); + + if ( ! pSetup->IsAdminInstall() ) + if ( ! pSetup->GetPatches() ) + throw pSetup->GetError(); + + // CheckForUpgrade() has to be called after calling GetPatches()! + if ( ! pSetup->CheckForUpgrade() ) + throw pSetup->GetError(); + + long nLanguage; + + if ( ! pSetup->ChooseLanguage( nLanguage ) ) + throw pSetup->GetError(); + + if ( ! pSetup->Install( nLanguage ) ) + throw pSetup->GetError(); + } + catch ( std::bad_alloc ) + { + pSetup->DisplayError( ERROR_OUTOFMEMORY ); + } + catch ( UINT nErr ) + { + pSetup->DisplayError( nErr ); + } + + int nRet = pSetup->GetError(); + + delete pSetup; + + return nRet; +} diff --git a/desktop/win32/source/setup/setup_main.hxx b/desktop/win32/source/setup/setup_main.hxx new file mode 100644 index 000000000000..67b54adc0d2a --- /dev/null +++ b/desktop/win32/source/setup/setup_main.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: setup_main.hxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef SETUP_MAIN_HXX +#define SETUP_MAIN_HXX + +class SetupApp +{ + DWORD m_nOSVersion; + DWORD m_nMinorVersion; + boolean m_bIsWin9x : 1; + boolean m_bNeedReboot : 1; + boolean m_bAdministrative : 1; + +public: + UINT m_uiRet; + + SetupApp(); + virtual ~SetupApp(); + + virtual boolean Initialize( HINSTANCE hInst ) = 0; + virtual boolean AlreadyRunning() const = 0; + virtual boolean ReadProfile() = 0; + virtual boolean GetPatches() = 0; + virtual boolean ChooseLanguage( long& rLanguage ) = 0; + virtual boolean CheckVersion() = 0; + virtual boolean CheckForUpgrade() = 0; + virtual boolean Install( long nLanguage ) = 0; + + virtual UINT GetError() const = 0; + virtual void DisplayError( UINT nErr ) const = 0; + + void SetError( UINT nErr ) { m_uiRet = nErr; } + boolean IsWin9x() const { return m_bIsWin9x; } + DWORD GetOSVersion() const { return m_nOSVersion; } + DWORD GetMinorVersion() const { return m_nMinorVersion; } + + boolean IsAdminInstall() { return m_bAdministrative; } + void SetAdminInstall( boolean bValue ) { m_bAdministrative = bValue; } + + void SetRebootNeeded( boolean bNeedReboot ) { m_bNeedReboot = bNeedReboot; } + boolean NeedReboot() const { return m_bNeedReboot; } +}; + +SetupApp* Create_SetupAppA(); +SetupApp* Create_SetupAppW(); + +#endif diff --git a/desktop/win32/source/setup/setup_w.cxx b/desktop/win32/source/setup/setup_w.cxx new file mode 100644 index 000000000000..67270cae7c0b --- /dev/null +++ b/desktop/win32/source/setup/setup_w.cxx @@ -0,0 +1,38 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: setup_w.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#define UNICODE 1 +#define _UNICODE 1 + +#include "setup.cpp" + |