1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir #define WIN // scope W32 API 29*cdf0e10cSrcweir 30*cdf0e10cSrcweir #if defined _MSC_VER 31*cdf0e10cSrcweir #pragma warning(push, 1) 32*cdf0e10cSrcweir #endif 33*cdf0e10cSrcweir #include <windows.h> 34*cdf0e10cSrcweir #if defined _MSC_VER 35*cdf0e10cSrcweir #pragma warning(pop) 36*cdf0e10cSrcweir #endif 37*cdf0e10cSrcweir #include <tchar.h> 38*cdf0e10cSrcweir #include <assert.h> 39*cdf0e10cSrcweir #include <shlwapi.h> 40*cdf0e10cSrcweir #include <new> 41*cdf0e10cSrcweir #include <time.h> 42*cdf0e10cSrcweir #include <mbctype.h> 43*cdf0e10cSrcweir #include <locale.h> 44*cdf0e10cSrcweir #include <Msiquery.h> 45*cdf0e10cSrcweir #include <MsiDefs.h> 46*cdf0e10cSrcweir #include "strsafe.h" 47*cdf0e10cSrcweir 48*cdf0e10cSrcweir #include "setup.hxx" 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir #include "resource.h" 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir //-------------------------------------------------------------------------- 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir #define MAX_STR_LENGTH 32000 55*cdf0e10cSrcweir #define MAX_TEXT_LENGTH 1024 56*cdf0e10cSrcweir #define MAX_LANGUAGE_LEN 80 57*cdf0e10cSrcweir #define MAX_STR_CAPTION 256 58*cdf0e10cSrcweir #define VERSION_SIZE 80 59*cdf0e10cSrcweir #define SECTION_SETUP TEXT( "Setup" ) 60*cdf0e10cSrcweir #define SECTION_LANGUAGE TEXT( "Languages" ) 61*cdf0e10cSrcweir #define PRODUCT_NAME_VAR TEXT( "%PRODUCTNAME" ) 62*cdf0e10cSrcweir #define PRODUCT_VERSION TEXT( "ProductVersion" ) 63*cdf0e10cSrcweir #define ERROR_SHOW_USAGE -2 64*cdf0e10cSrcweir #define ERROR_SETUP_TO_OLD -3 65*cdf0e10cSrcweir #define ERROR_SETUP_NOT_FOUND -4 66*cdf0e10cSrcweir 67*cdf0e10cSrcweir #define PARAM_SETUP_USED TEXT( " SETUP_USED=1 " ) 68*cdf0e10cSrcweir #define PARAM_PACKAGE TEXT( "/I " ) 69*cdf0e10cSrcweir #define PARAM_MINOR_UPGRADE TEXT( "/FVOMUS " ) 70*cdf0e10cSrcweir #define PARAM_ADMIN TEXT( "/A " ) 71*cdf0e10cSrcweir #define PARAM_TRANSFORM TEXT( " TRANSFORMS=" ) 72*cdf0e10cSrcweir #define PARAM_REBOOT TEXT( " REBOOT=Force" ) 73*cdf0e10cSrcweir #define PARAM_PATCH TEXT( " /update " ) 74*cdf0e10cSrcweir #define PARAM_REG_ALL_MSO_TYPES TEXT( "REGISTER_ALL_MSO_TYPES=1 " ) 75*cdf0e10cSrcweir #define PARAM_REG_NO_MSO_TYPES TEXT( "REGISTER_NO_MSO_TYPES=1 " ) 76*cdf0e10cSrcweir #define PARAM_SILENTINSTALL TEXT( " /QB" ) 77*cdf0e10cSrcweir 78*cdf0e10cSrcweir #define PARAM_RUNNING TEXT( "ignore_running" ) 79*cdf0e10cSrcweir #define CMDLN_REG_ALL_MSO_TYPES TEXT( "msoreg=1" ) 80*cdf0e10cSrcweir #define CMDLN_REG_NO_MSO_TYPES TEXT( "msoreg=0" ) 81*cdf0e10cSrcweir 82*cdf0e10cSrcweir #define MSI_DLL TEXT( "msi.dll" ) 83*cdf0e10cSrcweir #define ADVAPI32_DLL TEXT( "advapi32.dll" ) 84*cdf0e10cSrcweir #define PROFILE_NAME TEXT( "setup.ini" ) 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir #define RUNTIME_X64_NAME TEXT( "redist\\vcredist_x64.exe" ) 87*cdf0e10cSrcweir #define RUNTIME_X86_NAME TEXT( "redist\\vcredist_x86.exe" ) 88*cdf0e10cSrcweir #define PRODUCTCODE_X86 TEXT( "{E503B4BF-F7BB-3D5F-8BC8-F694B1CFF942}" ) 89*cdf0e10cSrcweir #define PRODUCTCODE_X64 TEXT( "{350AA351-21FA-3270-8B7A-835434E766AD}" ) 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir #define MSIAPI_DllGetVersion "DllGetVersion" 92*cdf0e10cSrcweir #define ADVAPI32API_CheckTokenMembership "CheckTokenMembership" 93*cdf0e10cSrcweir 94*cdf0e10cSrcweir typedef HRESULT (CALLBACK* PFnDllGetVersion)( DLLVERSIONINFO *pdvi); 95*cdf0e10cSrcweir typedef BOOL (WINAPI* PFnCheckTokenMembership)(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember); 96*cdf0e10cSrcweir 97*cdf0e10cSrcweir #ifdef DEBUG 98*cdf0e10cSrcweir inline void OutputDebugStringFormat( LPCTSTR pFormat, ... ) 99*cdf0e10cSrcweir { 100*cdf0e10cSrcweir TCHAR buffer[1024]; 101*cdf0e10cSrcweir va_list args; 102*cdf0e10cSrcweir 103*cdf0e10cSrcweir va_start( args, pFormat ); 104*cdf0e10cSrcweir StringCchVPrintf( buffer, sizeof(buffer), pFormat, args ); 105*cdf0e10cSrcweir OutputDebugString( buffer ); 106*cdf0e10cSrcweir } 107*cdf0e10cSrcweir #else 108*cdf0e10cSrcweir static inline void OutputDebugStringFormat( LPCTSTR, ... ) 109*cdf0e10cSrcweir { 110*cdf0e10cSrcweir } 111*cdf0e10cSrcweir #endif 112*cdf0e10cSrcweir 113*cdf0e10cSrcweir //-------------------------------------------------------------------------- 114*cdf0e10cSrcweir 115*cdf0e10cSrcweir const TCHAR sInstKey[] = TEXT( "Software\\Microsoft\\Windows\\CurrentVersion\\Installer" ); 116*cdf0e10cSrcweir const TCHAR sInstLocValue[] = TEXT( "InstallerLocation" ); 117*cdf0e10cSrcweir const TCHAR sMsiDll[] = TEXT( "\\msi.dll" ); 118*cdf0e10cSrcweir const TCHAR sMsiExe[] = TEXT( "\\msiexec.exe" ); 119*cdf0e10cSrcweir const TCHAR sDelayReboot[] = TEXT( " /c:\"msiinst /delayreboot\"" ); 120*cdf0e10cSrcweir const TCHAR sMsiQuiet[] = TEXT( " /q" ); 121*cdf0e10cSrcweir const TCHAR sMemMapName[] = TEXT( "Global\\MsiErrorObject" ); 122*cdf0e10cSrcweir 123*cdf0e10cSrcweir //-------------------------------------------------------------------------- 124*cdf0e10cSrcweir SetupAppX::SetupAppX() 125*cdf0e10cSrcweir { 126*cdf0e10cSrcweir m_hInst = NULL; 127*cdf0e10cSrcweir m_hMapFile = NULL; 128*cdf0e10cSrcweir m_pAppTitle = NULL; 129*cdf0e10cSrcweir m_pCmdLine = NULL; 130*cdf0e10cSrcweir 131*cdf0e10cSrcweir m_pDatabase = NULL; 132*cdf0e10cSrcweir m_pReqVersion = NULL; 133*cdf0e10cSrcweir m_pProductName = NULL; 134*cdf0e10cSrcweir m_pAdvertise = NULL; 135*cdf0e10cSrcweir m_pTmpName = NULL; 136*cdf0e10cSrcweir m_pLogFile = NULL; 137*cdf0e10cSrcweir m_pModuleFile = NULL; 138*cdf0e10cSrcweir m_pPatchFiles = NULL; 139*cdf0e10cSrcweir m_pMSIErrorCode = NULL; 140*cdf0e10cSrcweir m_pUpgradeKey = NULL; 141*cdf0e10cSrcweir m_pProductVersion = NULL; 142*cdf0e10cSrcweir 143*cdf0e10cSrcweir m_pErrorText = new TCHAR[ MAX_TEXT_LENGTH ]; 144*cdf0e10cSrcweir m_pErrorText[0] = '\0'; 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir m_nLanguageID = 0; 147*cdf0e10cSrcweir m_nLanguageCount = 0; 148*cdf0e10cSrcweir m_ppLanguageList = NULL; 149*cdf0e10cSrcweir 150*cdf0e10cSrcweir m_bQuiet = false; 151*cdf0e10cSrcweir m_bRegNoMsoTypes = false; 152*cdf0e10cSrcweir m_bRegAllMsoTypes = false; 153*cdf0e10cSrcweir m_bIsMinorUpgrade = false; 154*cdf0e10cSrcweir m_bSupportsPatch = false; 155*cdf0e10cSrcweir 156*cdf0e10cSrcweir m_bIgnoreAlreadyRunning = false; 157*cdf0e10cSrcweir } 158*cdf0e10cSrcweir 159*cdf0e10cSrcweir //-------------------------------------------------------------------------- 160*cdf0e10cSrcweir SetupAppX::~SetupAppX() 161*cdf0e10cSrcweir { 162*cdf0e10cSrcweir if ( m_ppLanguageList ) 163*cdf0e10cSrcweir { 164*cdf0e10cSrcweir for ( int i = 0; i < m_nLanguageCount; i++ ) 165*cdf0e10cSrcweir if ( m_ppLanguageList[i] ) 166*cdf0e10cSrcweir delete m_ppLanguageList[ i ]; 167*cdf0e10cSrcweir delete [] m_ppLanguageList; 168*cdf0e10cSrcweir } 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir time_t aTime; 171*cdf0e10cSrcweir time( &aTime ); 172*cdf0e10cSrcweir tm *pTime = localtime( &aTime ); // Convert time to struct tm form 173*cdf0e10cSrcweir 174*cdf0e10cSrcweir Log( TEXT( "End: %s\n\r\n\r\n" ), _tasctime( pTime ) ); 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir if ( m_pLogFile ) fclose( m_pLogFile ); 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir if ( m_pTmpName ) 179*cdf0e10cSrcweir { 180*cdf0e10cSrcweir _tremove( m_pTmpName ); 181*cdf0e10cSrcweir free( m_pTmpName ); 182*cdf0e10cSrcweir } 183*cdf0e10cSrcweir 184*cdf0e10cSrcweir if ( m_pMSIErrorCode ) UnmapViewOfFile( m_pMSIErrorCode ); 185*cdf0e10cSrcweir if ( m_hMapFile ) CloseHandle( m_hMapFile ); 186*cdf0e10cSrcweir 187*cdf0e10cSrcweir if ( m_pAppTitle ) delete [] m_pAppTitle; 188*cdf0e10cSrcweir if ( m_pDatabase ) delete [] m_pDatabase; 189*cdf0e10cSrcweir if ( m_pReqVersion ) delete [] m_pReqVersion; 190*cdf0e10cSrcweir if ( m_pProductName ) delete [] m_pProductName; 191*cdf0e10cSrcweir if ( m_pAdvertise ) delete [] m_pAdvertise; 192*cdf0e10cSrcweir if ( m_pLogFile ) delete [] m_pLogFile; 193*cdf0e10cSrcweir if ( m_pErrorText ) delete [] m_pErrorText; 194*cdf0e10cSrcweir if ( m_pModuleFile ) delete [] m_pModuleFile; 195*cdf0e10cSrcweir if ( m_pPatchFiles ) delete [] m_pPatchFiles; 196*cdf0e10cSrcweir if ( m_pUpgradeKey ) delete [] m_pUpgradeKey; 197*cdf0e10cSrcweir if ( m_pProductVersion ) delete [] m_pProductVersion; 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir 200*cdf0e10cSrcweir //-------------------------------------------------------------------------- 201*cdf0e10cSrcweir boolean SetupAppX::Initialize( HINSTANCE hInst ) 202*cdf0e10cSrcweir { 203*cdf0e10cSrcweir m_pCmdLine = WIN::GetCommandLine(); 204*cdf0e10cSrcweir m_hInst = hInst; 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir // Load our AppTitle (caption) 207*cdf0e10cSrcweir m_pAppTitle = new TCHAR[ MAX_STR_CAPTION ]; 208*cdf0e10cSrcweir m_pAppTitle[0] = '\0'; 209*cdf0e10cSrcweir WIN::LoadString( hInst, IDS_APP_TITLE, m_pAppTitle, MAX_STR_CAPTION ); 210*cdf0e10cSrcweir 211*cdf0e10cSrcweir // Obtain path we are running from 212*cdf0e10cSrcweir m_pModuleFile = new TCHAR[ MAX_PATH ]; 213*cdf0e10cSrcweir m_pModuleFile[ 0 ] = '\0'; 214*cdf0e10cSrcweir 215*cdf0e10cSrcweir if ( 0 == WIN::GetModuleFileName( hInst, m_pModuleFile, MAX_PATH ) ) 216*cdf0e10cSrcweir { 217*cdf0e10cSrcweir SetError( WIN::GetLastError() ); 218*cdf0e10cSrcweir return false; 219*cdf0e10cSrcweir } 220*cdf0e10cSrcweir 221*cdf0e10cSrcweir if ( ! GetCmdLineParameters( &m_pCmdLine ) ) 222*cdf0e10cSrcweir return false; 223*cdf0e10cSrcweir 224*cdf0e10cSrcweir m_hMapFile = CreateFileMapping( 225*cdf0e10cSrcweir INVALID_HANDLE_VALUE, // use paging file 226*cdf0e10cSrcweir NULL, // default security 227*cdf0e10cSrcweir PAGE_READWRITE, // read/write access 228*cdf0e10cSrcweir 0, // max. object size 229*cdf0e10cSrcweir sizeof( int ), // buffer size 230*cdf0e10cSrcweir sMemMapName ); 231*cdf0e10cSrcweir if ( m_hMapFile ) 232*cdf0e10cSrcweir { 233*cdf0e10cSrcweir m_pMSIErrorCode = (int*) MapViewOfFile( m_hMapFile, // handle to map object 234*cdf0e10cSrcweir FILE_MAP_ALL_ACCESS, // read/write permission 235*cdf0e10cSrcweir 0, 236*cdf0e10cSrcweir 0, 237*cdf0e10cSrcweir sizeof( int ) ); 238*cdf0e10cSrcweir if ( m_pMSIErrorCode ) 239*cdf0e10cSrcweir *m_pMSIErrorCode = 0; 240*cdf0e10cSrcweir else 241*cdf0e10cSrcweir OutputDebugStringFormat( TEXT("Could not map view of file (%d).\n"), GetLastError() ); 242*cdf0e10cSrcweir } 243*cdf0e10cSrcweir else 244*cdf0e10cSrcweir OutputDebugStringFormat( TEXT("Could not create file mapping object (%d).\n"), GetLastError() ); 245*cdf0e10cSrcweir 246*cdf0e10cSrcweir Log( TEXT("Starting: %s\r\n"), m_pModuleFile ); 247*cdf0e10cSrcweir Log( TEXT(" CommandLine=<%s>\r\n"), m_pCmdLine ); 248*cdf0e10cSrcweir 249*cdf0e10cSrcweir if ( m_bQuiet ) 250*cdf0e10cSrcweir Log( TEXT(" Using quiet install mode\r\n") ); 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir time_t aTime; 253*cdf0e10cSrcweir time( &aTime ); 254*cdf0e10cSrcweir tm* pTime = localtime( &aTime ); 255*cdf0e10cSrcweir Log( TEXT(" Begin: %s\n"), _tasctime( pTime ) ); 256*cdf0e10cSrcweir 257*cdf0e10cSrcweir return true; 258*cdf0e10cSrcweir } 259*cdf0e10cSrcweir 260*cdf0e10cSrcweir //-------------------------------------------------------------------------- 261*cdf0e10cSrcweir boolean SetupAppX::GetProfileSection( LPCTSTR pFileName, LPCTSTR pSection, 262*cdf0e10cSrcweir DWORD& rSize, LPTSTR *pRetBuf ) 263*cdf0e10cSrcweir { 264*cdf0e10cSrcweir if ( !rSize || !*pRetBuf ) 265*cdf0e10cSrcweir { 266*cdf0e10cSrcweir rSize = 512; 267*cdf0e10cSrcweir *pRetBuf = new TCHAR[ rSize ]; 268*cdf0e10cSrcweir } 269*cdf0e10cSrcweir 270*cdf0e10cSrcweir DWORD nRet = GetPrivateProfileSection( pSection, *pRetBuf, rSize, pFileName ); 271*cdf0e10cSrcweir 272*cdf0e10cSrcweir if ( nRet && ( nRet + 2 > rSize ) ) // buffer was too small, retry with bigger one 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir if ( nRet < 32767 - 2 ) 275*cdf0e10cSrcweir { 276*cdf0e10cSrcweir delete [] (*pRetBuf); 277*cdf0e10cSrcweir rSize = nRet + 2; 278*cdf0e10cSrcweir *pRetBuf = new TCHAR[ rSize ]; 279*cdf0e10cSrcweir 280*cdf0e10cSrcweir nRet = GetPrivateProfileSection( pSection, *pRetBuf, rSize, pFileName ); 281*cdf0e10cSrcweir } 282*cdf0e10cSrcweir } 283*cdf0e10cSrcweir 284*cdf0e10cSrcweir if ( !nRet ) 285*cdf0e10cSrcweir { 286*cdf0e10cSrcweir SetError( WIN::GetLastError() ); 287*cdf0e10cSrcweir 288*cdf0e10cSrcweir TCHAR sBuf[80]; 289*cdf0e10cSrcweir StringCchPrintf( sBuf, 80, TEXT("ERROR: GetPrivateProfileSection(): GetLastError returned %u\r\n"), GetError() ); 290*cdf0e10cSrcweir Log( sBuf ); 291*cdf0e10cSrcweir return false; 292*cdf0e10cSrcweir } 293*cdf0e10cSrcweir else if ( nRet + 2 > rSize ) 294*cdf0e10cSrcweir { 295*cdf0e10cSrcweir SetError( ERROR_OUTOFMEMORY ); 296*cdf0e10cSrcweir Log( TEXT( "ERROR: GetPrivateProfileSection() out of memory\r\n" ) ); 297*cdf0e10cSrcweir return false; 298*cdf0e10cSrcweir } 299*cdf0e10cSrcweir 300*cdf0e10cSrcweir Log( TEXT( " GetProfileSection read %s\r\n" ), pSection ); 301*cdf0e10cSrcweir 302*cdf0e10cSrcweir return true; 303*cdf0e10cSrcweir } 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir //-------------------------------------------------------------------------- 306*cdf0e10cSrcweir boolean SetupAppX::ReadProfile() 307*cdf0e10cSrcweir { 308*cdf0e10cSrcweir boolean bRet = false; 309*cdf0e10cSrcweir TCHAR *sProfilePath = 0; 310*cdf0e10cSrcweir 311*cdf0e10cSrcweir if ( GetPathToFile( PROFILE_NAME, &sProfilePath ) ) 312*cdf0e10cSrcweir { 313*cdf0e10cSrcweir DWORD nSize = 0; 314*cdf0e10cSrcweir LPTSTR pRetBuf = NULL; 315*cdf0e10cSrcweir 316*cdf0e10cSrcweir Log( TEXT( " Open ini file: <%s>\r\n" ), sProfilePath ); 317*cdf0e10cSrcweir 318*cdf0e10cSrcweir bRet = GetProfileSection( sProfilePath, SECTION_SETUP, nSize, &pRetBuf ); 319*cdf0e10cSrcweir 320*cdf0e10cSrcweir if ( !bRet ) 321*cdf0e10cSrcweir { 322*cdf0e10cSrcweir LPTSTR pTmpFile = CopyIniFile( sProfilePath ); 323*cdf0e10cSrcweir delete [] sProfilePath; 324*cdf0e10cSrcweir sProfilePath = pTmpFile; 325*cdf0e10cSrcweir 326*cdf0e10cSrcweir if ( sProfilePath ) 327*cdf0e10cSrcweir { 328*cdf0e10cSrcweir SetError( ERROR_SUCCESS ); 329*cdf0e10cSrcweir 330*cdf0e10cSrcweir Log( TEXT( " Could not open inifile, copied ini file to: <%s>\r\n" ), sProfilePath ); 331*cdf0e10cSrcweir bRet = GetProfileSection( sProfilePath, SECTION_SETUP, nSize, &pRetBuf ); 332*cdf0e10cSrcweir } 333*cdf0e10cSrcweir } 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir if ( bRet ) 336*cdf0e10cSrcweir { 337*cdf0e10cSrcweir LPTSTR pCurLine = pRetBuf; 338*cdf0e10cSrcweir while ( *pCurLine ) 339*cdf0e10cSrcweir { 340*cdf0e10cSrcweir LPTSTR pName = 0; 341*cdf0e10cSrcweir LPTSTR pValue = 0; 342*cdf0e10cSrcweir 343*cdf0e10cSrcweir pCurLine += GetNameValue( pCurLine, &pName, &pValue ); 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir if ( lstrcmpi( TEXT( "database" ), pName ) == 0 ) 346*cdf0e10cSrcweir { 347*cdf0e10cSrcweir m_pDatabase = pValue; 348*cdf0e10cSrcweir Log( TEXT( " Database = %s\r\n" ), pValue ); 349*cdf0e10cSrcweir } 350*cdf0e10cSrcweir else if ( lstrcmpi( TEXT( "msiversion" ), pName ) == 0 ) 351*cdf0e10cSrcweir { 352*cdf0e10cSrcweir m_pReqVersion = pValue; 353*cdf0e10cSrcweir Log( TEXT( " msiversion = %s\r\n" ), pValue ); 354*cdf0e10cSrcweir } 355*cdf0e10cSrcweir else if ( lstrcmpi( TEXT( "productname" ), pName ) == 0 ) 356*cdf0e10cSrcweir { 357*cdf0e10cSrcweir m_pProductName = pValue; 358*cdf0e10cSrcweir Log( TEXT( " productname = %s\r\n" ), pValue ); 359*cdf0e10cSrcweir m_pAppTitle = SetProdToAppTitle( m_pProductName ); 360*cdf0e10cSrcweir } 361*cdf0e10cSrcweir else if ( lstrcmpi( TEXT( "upgradekey" ), pName ) == 0 ) 362*cdf0e10cSrcweir { 363*cdf0e10cSrcweir m_pUpgradeKey = pValue; 364*cdf0e10cSrcweir Log( TEXT( " upgradekey = %s\r\n" ), pValue ); 365*cdf0e10cSrcweir } 366*cdf0e10cSrcweir else if ( lstrcmpi( TEXT( "productversion" ), pName ) == 0 ) 367*cdf0e10cSrcweir { 368*cdf0e10cSrcweir m_pProductVersion = pValue; 369*cdf0e10cSrcweir Log( TEXT( " productversion = %s\r\n" ), pValue ); 370*cdf0e10cSrcweir } 371*cdf0e10cSrcweir else if ( lstrcmpi( TEXT( "productcode" ), pName ) == 0 ) 372*cdf0e10cSrcweir { 373*cdf0e10cSrcweir delete [] pValue; 374*cdf0e10cSrcweir } 375*cdf0e10cSrcweir else 376*cdf0e10cSrcweir { 377*cdf0e10cSrcweir Log( TEXT( "Warning: unknown entry in profile <%s>\r\n" ), pName ); 378*cdf0e10cSrcweir delete [] pValue; 379*cdf0e10cSrcweir } 380*cdf0e10cSrcweir } 381*cdf0e10cSrcweir } 382*cdf0e10cSrcweir 383*cdf0e10cSrcweir if ( bRet && ( !m_pDatabase || !m_pReqVersion || !m_pProductName ) ) 384*cdf0e10cSrcweir { 385*cdf0e10cSrcweir Log( TEXT( "ERROR: incomplete 'Setup' section in profile\r\n" ) ); 386*cdf0e10cSrcweir SetError( ERROR_INVALID_DATA ); 387*cdf0e10cSrcweir bRet = false; 388*cdf0e10cSrcweir } 389*cdf0e10cSrcweir 390*cdf0e10cSrcweir if ( bRet ) 391*cdf0e10cSrcweir bRet = GetProfileSection( sProfilePath, SECTION_LANGUAGE, nSize, &pRetBuf ); 392*cdf0e10cSrcweir 393*cdf0e10cSrcweir if ( bRet ) 394*cdf0e10cSrcweir { 395*cdf0e10cSrcweir LPTSTR pName = 0; 396*cdf0e10cSrcweir LPTSTR pValue = 0; 397*cdf0e10cSrcweir LPTSTR pCurLine = pRetBuf; 398*cdf0e10cSrcweir LPTSTR pLastChar; 399*cdf0e10cSrcweir int nNext = 0; 400*cdf0e10cSrcweir 401*cdf0e10cSrcweir // first line in this section should be the language count 402*cdf0e10cSrcweir nNext = GetNameValue( pCurLine, &pName, &pValue ); 403*cdf0e10cSrcweir if ( lstrcmpi( TEXT( "count" ), pName ) == 0 ) 404*cdf0e10cSrcweir { 405*cdf0e10cSrcweir Log( TEXT( " Languages = %s\r\n" ), pValue ); 406*cdf0e10cSrcweir m_nLanguageCount = _tcstol( pValue, &pLastChar, 10 ); 407*cdf0e10cSrcweir pCurLine += nNext; 408*cdf0e10cSrcweir delete [] pValue; 409*cdf0e10cSrcweir } 410*cdf0e10cSrcweir 411*cdf0e10cSrcweir m_ppLanguageList = new LanguageDataX*[ m_nLanguageCount ]; 412*cdf0e10cSrcweir 413*cdf0e10cSrcweir for ( int i=0; i < m_nLanguageCount; i++ ) 414*cdf0e10cSrcweir { 415*cdf0e10cSrcweir if ( !*pCurLine ) 416*cdf0e10cSrcweir { 417*cdf0e10cSrcweir m_nLanguageCount = i; 418*cdf0e10cSrcweir break; 419*cdf0e10cSrcweir } 420*cdf0e10cSrcweir 421*cdf0e10cSrcweir pCurLine += GetNameValue( pCurLine, &pName, &pValue ); 422*cdf0e10cSrcweir m_ppLanguageList[ i ] = new LanguageDataX( pValue ); 423*cdf0e10cSrcweir Log( TEXT( " Language = %s\r\n" ), pValue ); 424*cdf0e10cSrcweir 425*cdf0e10cSrcweir if ( m_ppLanguageList[ i ]->m_pTransform ) 426*cdf0e10cSrcweir Log( TEXT( " Transform = %s\r\n" ), m_ppLanguageList[ i ]->m_pTransform ); 427*cdf0e10cSrcweir 428*cdf0e10cSrcweir delete [] pValue; 429*cdf0e10cSrcweir } 430*cdf0e10cSrcweir } 431*cdf0e10cSrcweir 432*cdf0e10cSrcweir if ( pRetBuf ) 433*cdf0e10cSrcweir delete [] pRetBuf; 434*cdf0e10cSrcweir } 435*cdf0e10cSrcweir 436*cdf0e10cSrcweir if ( sProfilePath && ! m_pTmpName ) 437*cdf0e10cSrcweir delete [] sProfilePath; 438*cdf0e10cSrcweir 439*cdf0e10cSrcweir return bRet; 440*cdf0e10cSrcweir } 441*cdf0e10cSrcweir 442*cdf0e10cSrcweir //-------------------------------------------------------------------------- 443*cdf0e10cSrcweir void SetupAppX::AddFileToPatchList( TCHAR* pPath, TCHAR* pFile ) 444*cdf0e10cSrcweir { 445*cdf0e10cSrcweir if ( m_pPatchFiles == NULL ) 446*cdf0e10cSrcweir { 447*cdf0e10cSrcweir m_pPatchFiles = new TCHAR[ MAX_STR_LENGTH ]; 448*cdf0e10cSrcweir StringCchCopy( m_pPatchFiles, MAX_STR_LENGTH, TEXT("\"") ); 449*cdf0e10cSrcweir } 450*cdf0e10cSrcweir else 451*cdf0e10cSrcweir StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, TEXT(";") ); 452*cdf0e10cSrcweir 453*cdf0e10cSrcweir StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, pPath ); 454*cdf0e10cSrcweir StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, pFile ); 455*cdf0e10cSrcweir } 456*cdf0e10cSrcweir 457*cdf0e10cSrcweir //-------------------------------------------------------------------------- 458*cdf0e10cSrcweir boolean SetupAppX::GetPatches() 459*cdf0e10cSrcweir { 460*cdf0e10cSrcweir boolean bRet = true; 461*cdf0e10cSrcweir 462*cdf0e10cSrcweir int nPatternLen = lstrlen( m_pModuleFile ) + 7; // 1 for null terminator, 1 for back slash, 5 for extensions 463*cdf0e10cSrcweir TCHAR* pPattern = new TCHAR[ nPatternLen ]; 464*cdf0e10cSrcweir TCHAR* pBaseDir = new TCHAR[ nPatternLen ]; 465*cdf0e10cSrcweir 466*cdf0e10cSrcweir // find 'setup.exe' in the path so we can remove it 467*cdf0e10cSrcweir TCHAR *pFilePart = 0; 468*cdf0e10cSrcweir if ( 0 == GetFullPathName( m_pModuleFile, nPatternLen, pPattern, &pFilePart ) ) 469*cdf0e10cSrcweir { 470*cdf0e10cSrcweir SetError( WIN::GetLastError() ); 471*cdf0e10cSrcweir bRet = false; 472*cdf0e10cSrcweir } 473*cdf0e10cSrcweir else 474*cdf0e10cSrcweir { 475*cdf0e10cSrcweir if ( pFilePart ) 476*cdf0e10cSrcweir *pFilePart = '\0'; 477*cdf0e10cSrcweir StringCchCopy( pBaseDir, nPatternLen, pPattern ); 478*cdf0e10cSrcweir StringCchCat( pPattern, nPatternLen, TEXT("*.msp") ); 479*cdf0e10cSrcweir 480*cdf0e10cSrcweir WIN32_FIND_DATA aFindFileData; 481*cdf0e10cSrcweir 482*cdf0e10cSrcweir HANDLE hFindPatches = FindFirstFile( pPattern, &aFindFileData ); 483*cdf0e10cSrcweir 484*cdf0e10cSrcweir if ( hFindPatches != INVALID_HANDLE_VALUE ) 485*cdf0e10cSrcweir { 486*cdf0e10cSrcweir if ( ! IsPatchInstalled( pBaseDir, aFindFileData.cFileName ) ) 487*cdf0e10cSrcweir AddFileToPatchList( pBaseDir, aFindFileData.cFileName ); 488*cdf0e10cSrcweir 489*cdf0e10cSrcweir while ( FindNextFile( hFindPatches, &aFindFileData ) ) 490*cdf0e10cSrcweir { 491*cdf0e10cSrcweir if ( ! IsPatchInstalled( pBaseDir, aFindFileData.cFileName ) ) 492*cdf0e10cSrcweir AddFileToPatchList( pBaseDir, aFindFileData.cFileName ); 493*cdf0e10cSrcweir } 494*cdf0e10cSrcweir 495*cdf0e10cSrcweir if ( m_pPatchFiles != NULL ) 496*cdf0e10cSrcweir StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, TEXT("\"") ); 497*cdf0e10cSrcweir 498*cdf0e10cSrcweir FindClose( hFindPatches ); 499*cdf0e10cSrcweir } 500*cdf0e10cSrcweir } 501*cdf0e10cSrcweir 502*cdf0e10cSrcweir delete [] pPattern; 503*cdf0e10cSrcweir delete [] pBaseDir; 504*cdf0e10cSrcweir 505*cdf0e10cSrcweir return bRet; 506*cdf0e10cSrcweir } 507*cdf0e10cSrcweir 508*cdf0e10cSrcweir //-------------------------------------------------------------------------- 509*cdf0e10cSrcweir boolean SetupAppX::GetPathToFile( TCHAR* pFileName, TCHAR** pPath ) 510*cdf0e10cSrcweir { 511*cdf0e10cSrcweir // generate the path to the file = szModuleFile + FileName 512*cdf0e10cSrcweir // note: FileName is a relative path 513*cdf0e10cSrcweir 514*cdf0e10cSrcweir boolean bRet = true; 515*cdf0e10cSrcweir 516*cdf0e10cSrcweir int nTempPath = lstrlen( m_pModuleFile ) + lstrlen( pFileName ) + 2; // 1 for null terminator, 1 for back slash 517*cdf0e10cSrcweir TCHAR* pTempPath = new TCHAR[ nTempPath ]; 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir // find 'setup.exe' in the path so we can remove it 520*cdf0e10cSrcweir TCHAR *pFilePart = 0; 521*cdf0e10cSrcweir if ( 0 == GetFullPathName( m_pModuleFile, nTempPath, pTempPath, &pFilePart ) ) 522*cdf0e10cSrcweir { 523*cdf0e10cSrcweir SetError( WIN::GetLastError() ); 524*cdf0e10cSrcweir bRet = false; 525*cdf0e10cSrcweir } 526*cdf0e10cSrcweir else 527*cdf0e10cSrcweir { 528*cdf0e10cSrcweir if ( pFilePart ) 529*cdf0e10cSrcweir *pFilePart = '\0'; 530*cdf0e10cSrcweir 531*cdf0e10cSrcweir StringCchCat( pTempPath, nTempPath, pFileName ); 532*cdf0e10cSrcweir 533*cdf0e10cSrcweir int nPath = 2 * nTempPath; 534*cdf0e10cSrcweir *pPath = new TCHAR[ nPath ]; 535*cdf0e10cSrcweir 536*cdf0e10cSrcweir // normalize the path 537*cdf0e10cSrcweir int nReturn = GetFullPathName( pTempPath, nPath, *pPath, &pFilePart ); 538*cdf0e10cSrcweir 539*cdf0e10cSrcweir if ( nReturn > nPath ) 540*cdf0e10cSrcweir { 541*cdf0e10cSrcweir // try again, with larger buffer 542*cdf0e10cSrcweir delete [] (*pPath); 543*cdf0e10cSrcweir nPath = nReturn; 544*cdf0e10cSrcweir *pPath = new TCHAR[ nPath ]; 545*cdf0e10cSrcweir 546*cdf0e10cSrcweir nReturn = GetFullPathName( pTempPath, nPath, *pPath, &pFilePart ); 547*cdf0e10cSrcweir } 548*cdf0e10cSrcweir 549*cdf0e10cSrcweir if ( 0 == nReturn ) 550*cdf0e10cSrcweir { 551*cdf0e10cSrcweir // error -- invalid path 552*cdf0e10cSrcweir SetError( WIN::GetLastError() ); 553*cdf0e10cSrcweir bRet = false; 554*cdf0e10cSrcweir } 555*cdf0e10cSrcweir } 556*cdf0e10cSrcweir 557*cdf0e10cSrcweir if ( bRet ) // check for the file's existence 558*cdf0e10cSrcweir { 559*cdf0e10cSrcweir DWORD dwFileAttrib = GetFileAttributes( *pPath ); 560*cdf0e10cSrcweir 561*cdf0e10cSrcweir if (0xFFFFFFFF == dwFileAttrib) 562*cdf0e10cSrcweir { 563*cdf0e10cSrcweir StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pFileName ); 564*cdf0e10cSrcweir SetError( ERROR_FILE_NOT_FOUND ); 565*cdf0e10cSrcweir bRet = false; 566*cdf0e10cSrcweir } 567*cdf0e10cSrcweir } 568*cdf0e10cSrcweir 569*cdf0e10cSrcweir delete [] pTempPath; 570*cdf0e10cSrcweir return bRet; 571*cdf0e10cSrcweir } 572*cdf0e10cSrcweir 573*cdf0e10cSrcweir //-------------------------------------------------------------------------- 574*cdf0e10cSrcweir int SetupAppX::GetNameValue( TCHAR* pLine, TCHAR** pName, TCHAR** pValue ) 575*cdf0e10cSrcweir { 576*cdf0e10cSrcweir int nRet = lstrlen( pLine ) + 1; 577*cdf0e10cSrcweir *pValue = 0; 578*cdf0e10cSrcweir 579*cdf0e10cSrcweir if ( nRet == 1 ) 580*cdf0e10cSrcweir return nRet; 581*cdf0e10cSrcweir 582*cdf0e10cSrcweir LPTSTR pChar = pLine; 583*cdf0e10cSrcweir LPTSTR pLast = NULL; 584*cdf0e10cSrcweir 585*cdf0e10cSrcweir // Skip leading spaces. 586*cdf0e10cSrcweir while (' ' == *pChar || '\t' == *pChar) 587*cdf0e10cSrcweir pChar = CharNext( pChar ); 588*cdf0e10cSrcweir 589*cdf0e10cSrcweir *pName = pChar; 590*cdf0e10cSrcweir 591*cdf0e10cSrcweir // look for the end of the name 592*cdf0e10cSrcweir while( *pChar && (' ' != *pChar) && 593*cdf0e10cSrcweir ( '\t' != *pChar ) && ( '=' != *pChar ) ) 594*cdf0e10cSrcweir pChar = CharNext( pChar ); 595*cdf0e10cSrcweir 596*cdf0e10cSrcweir if ( ! *pChar ) 597*cdf0e10cSrcweir return nRet; 598*cdf0e10cSrcweir 599*cdf0e10cSrcweir pLast = pChar; 600*cdf0e10cSrcweir pChar = CharNext( pChar ); 601*cdf0e10cSrcweir *pLast = '\0'; 602*cdf0e10cSrcweir 603*cdf0e10cSrcweir // look for the start of the value 604*cdf0e10cSrcweir while( ( ' ' == *pChar ) || ( '\t' == *pChar ) || 605*cdf0e10cSrcweir ( '=' == *pChar ) ) 606*cdf0e10cSrcweir pChar = CharNext( pChar ); 607*cdf0e10cSrcweir 608*cdf0e10cSrcweir int nValueLen = lstrlen( pChar ) + 1; 609*cdf0e10cSrcweir *pValue = new TCHAR[ nValueLen ]; 610*cdf0e10cSrcweir 611*cdf0e10cSrcweir if ( *pValue ) 612*cdf0e10cSrcweir StringCchCopy( *pValue, nValueLen, pChar ); 613*cdf0e10cSrcweir 614*cdf0e10cSrcweir return nRet; 615*cdf0e10cSrcweir } 616*cdf0e10cSrcweir 617*cdf0e10cSrcweir //-------------------------------------------------------------------------- 618*cdf0e10cSrcweir boolean SetupAppX::ChooseLanguage( long& rLanguage ) 619*cdf0e10cSrcweir { 620*cdf0e10cSrcweir rLanguage = 0; 621*cdf0e10cSrcweir 622*cdf0e10cSrcweir if ( m_bQuiet ) 623*cdf0e10cSrcweir return true; 624*cdf0e10cSrcweir 625*cdf0e10cSrcweir // When there are none or only one language, there is nothing 626*cdf0e10cSrcweir // to do here 627*cdf0e10cSrcweir if ( m_nLanguageCount > 1 ) 628*cdf0e10cSrcweir { 629*cdf0e10cSrcweir TCHAR *sString = new TCHAR[ MAX_LANGUAGE_LEN ]; 630*cdf0e10cSrcweir 631*cdf0e10cSrcweir LANGID nUserDefLang = GetUserDefaultLangID(); 632*cdf0e10cSrcweir LANGID nSysDefLang = GetSystemDefaultLangID(); 633*cdf0e10cSrcweir 634*cdf0e10cSrcweir int nUserPrimary = PRIMARYLANGID( nUserDefLang ); 635*cdf0e10cSrcweir int nSysPrimary = PRIMARYLANGID( nSysDefLang ); 636*cdf0e10cSrcweir 637*cdf0e10cSrcweir long nUserIndex = -1; 638*cdf0e10cSrcweir long nUserPrimIndex = -1; 639*cdf0e10cSrcweir long nSystemIndex = -1; 640*cdf0e10cSrcweir long nSystemPrimIndex = -1; 641*cdf0e10cSrcweir long nParamIndex = -1; 642*cdf0e10cSrcweir 643*cdf0e10cSrcweir for ( long i=0; i<GetLanguageCount(); i++ ) 644*cdf0e10cSrcweir { 645*cdf0e10cSrcweir long nLanguage = GetLanguageID( i ); 646*cdf0e10cSrcweir int nPrimary = PRIMARYLANGID( nLanguage ); 647*cdf0e10cSrcweir GetLanguageName( nLanguage, sString ); 648*cdf0e10cSrcweir Log( TEXT( " Info: found Language: %s\r\n" ), sString ); 649*cdf0e10cSrcweir 650*cdf0e10cSrcweir if ( nLanguage == nUserDefLang ) 651*cdf0e10cSrcweir nUserIndex = i; 652*cdf0e10cSrcweir if ( nPrimary == nUserPrimary ) 653*cdf0e10cSrcweir nUserPrimIndex = i; 654*cdf0e10cSrcweir if ( nLanguage == nSysDefLang ) 655*cdf0e10cSrcweir nSystemIndex = i; 656*cdf0e10cSrcweir if ( nPrimary == nSysPrimary ) 657*cdf0e10cSrcweir nSystemPrimIndex = i; 658*cdf0e10cSrcweir if ( m_nLanguageID && ( nLanguage == m_nLanguageID ) ) 659*cdf0e10cSrcweir nParamIndex = i; 660*cdf0e10cSrcweir } 661*cdf0e10cSrcweir 662*cdf0e10cSrcweir if ( m_nLanguageID && ( nParamIndex == -1 ) ) 663*cdf0e10cSrcweir { 664*cdf0e10cSrcweir Log( TEXT( "Warning: Language chosen with parameter -lang not found.\r\n" ) ); 665*cdf0e10cSrcweir } 666*cdf0e10cSrcweir 667*cdf0e10cSrcweir if ( nParamIndex != -1 ) 668*cdf0e10cSrcweir { 669*cdf0e10cSrcweir Log( TEXT( "Info: Found language chosen with parameter -lang.\r\n" ) ); 670*cdf0e10cSrcweir rLanguage = GetLanguageID( nParamIndex ); 671*cdf0e10cSrcweir } 672*cdf0e10cSrcweir else if ( nUserIndex != -1 ) 673*cdf0e10cSrcweir { 674*cdf0e10cSrcweir Log( TEXT( "Info: Found user default language.\r\n" ) ); 675*cdf0e10cSrcweir rLanguage = GetLanguageID( nUserIndex ); 676*cdf0e10cSrcweir } 677*cdf0e10cSrcweir else if ( nUserPrimIndex != -1 ) 678*cdf0e10cSrcweir { 679*cdf0e10cSrcweir Log( TEXT( "Info: Found user default primary language.\r\n" ) ); 680*cdf0e10cSrcweir rLanguage = GetLanguageID( nUserPrimIndex ); 681*cdf0e10cSrcweir } 682*cdf0e10cSrcweir else if ( nSystemIndex != -1 ) 683*cdf0e10cSrcweir { 684*cdf0e10cSrcweir Log( TEXT( "Info: Found system default language.\r\n" ) ); 685*cdf0e10cSrcweir rLanguage = GetLanguageID( nSystemIndex ); 686*cdf0e10cSrcweir } 687*cdf0e10cSrcweir else if ( nSystemPrimIndex != -1 ) 688*cdf0e10cSrcweir { 689*cdf0e10cSrcweir Log( TEXT( "Info: Found system default primary language.\r\n" ) ); 690*cdf0e10cSrcweir rLanguage = GetLanguageID( nSystemPrimIndex ); 691*cdf0e10cSrcweir } 692*cdf0e10cSrcweir else 693*cdf0e10cSrcweir { 694*cdf0e10cSrcweir Log( TEXT( "Info: Use default language from ini file.\r\n" ) ); 695*cdf0e10cSrcweir rLanguage = GetLanguageID( 0 ); 696*cdf0e10cSrcweir } 697*cdf0e10cSrcweir delete [] sString; 698*cdf0e10cSrcweir } 699*cdf0e10cSrcweir 700*cdf0e10cSrcweir return true; 701*cdf0e10cSrcweir } 702*cdf0e10cSrcweir 703*cdf0e10cSrcweir //-------------------------------------------------------------------------- 704*cdf0e10cSrcweir HMODULE SetupAppX::LoadMsiLibrary() 705*cdf0e10cSrcweir { 706*cdf0e10cSrcweir HMODULE hMsi = NULL; 707*cdf0e10cSrcweir HKEY hInstKey = NULL; 708*cdf0e10cSrcweir 709*cdf0e10cSrcweir // find registered location of Msi.dll 710*cdf0e10cSrcweir if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sInstKey, 0, KEY_READ, &hInstKey ) ) 711*cdf0e10cSrcweir { 712*cdf0e10cSrcweir long nRet = ERROR_SUCCESS; 713*cdf0e10cSrcweir TCHAR *sMsiFolder = new TCHAR[ MAX_PATH + 1 ]; 714*cdf0e10cSrcweir DWORD dwMsiFolderSize = MAX_PATH + 1; 715*cdf0e10cSrcweir DWORD dwType = 0; 716*cdf0e10cSrcweir 717*cdf0e10cSrcweir if ( ERROR_MORE_DATA == ( nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, 718*cdf0e10cSrcweir &dwType, (BYTE*)sMsiFolder, &dwMsiFolderSize ) ) ) 719*cdf0e10cSrcweir { 720*cdf0e10cSrcweir // try again with larger buffer 721*cdf0e10cSrcweir delete [] sMsiFolder; 722*cdf0e10cSrcweir sMsiFolder = new TCHAR[ dwMsiFolderSize ]; 723*cdf0e10cSrcweir 724*cdf0e10cSrcweir nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, &dwType, 725*cdf0e10cSrcweir (BYTE*)sMsiFolder, &dwMsiFolderSize ); 726*cdf0e10cSrcweir } 727*cdf0e10cSrcweir 728*cdf0e10cSrcweir if ( ERROR_SUCCESS == nRet && dwType == REG_SZ && dwMsiFolderSize > 0 ) 729*cdf0e10cSrcweir { 730*cdf0e10cSrcweir // load Msi.dll from registered location 731*cdf0e10cSrcweir int nLength = lstrlen( sMsiDll ) + dwMsiFolderSize + 1; // use StringCchLength ? 732*cdf0e10cSrcweir TCHAR *pMsiLocation = new TCHAR[ nLength ]; 733*cdf0e10cSrcweir 734*cdf0e10cSrcweir if ( SUCCEEDED( StringCchCopy( pMsiLocation, nLength, sMsiFolder ) ) && 735*cdf0e10cSrcweir SUCCEEDED( StringCchCat( pMsiLocation, nLength, sMsiDll ) ) ) 736*cdf0e10cSrcweir { 737*cdf0e10cSrcweir hMsi = LoadLibrary( pMsiLocation ); 738*cdf0e10cSrcweir } 739*cdf0e10cSrcweir } 740*cdf0e10cSrcweir } 741*cdf0e10cSrcweir 742*cdf0e10cSrcweir if ( !hMsi ) // use the default location 743*cdf0e10cSrcweir { 744*cdf0e10cSrcweir hMsi = LoadLibrary( sMsiDll ); 745*cdf0e10cSrcweir } 746*cdf0e10cSrcweir 747*cdf0e10cSrcweir return hMsi; 748*cdf0e10cSrcweir } 749*cdf0e10cSrcweir 750*cdf0e10cSrcweir //-------------------------------------------------------------------------- 751*cdf0e10cSrcweir LPCTSTR SetupAppX::GetPathToMSI() 752*cdf0e10cSrcweir { 753*cdf0e10cSrcweir LPTSTR sMsiPath = NULL; 754*cdf0e10cSrcweir HKEY hInstKey = NULL; 755*cdf0e10cSrcweir TCHAR *sMsiFolder = new TCHAR[ MAX_PATH + 1 ]; 756*cdf0e10cSrcweir DWORD nMsiFolderSize = MAX_PATH + 1; 757*cdf0e10cSrcweir 758*cdf0e10cSrcweir sMsiFolder[0] = '\0'; 759*cdf0e10cSrcweir 760*cdf0e10cSrcweir // find registered location of Msi.dll 761*cdf0e10cSrcweir if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sInstKey, 0, KEY_READ, &hInstKey ) ) 762*cdf0e10cSrcweir { 763*cdf0e10cSrcweir LONG nRet = ERROR_SUCCESS; 764*cdf0e10cSrcweir DWORD dwType = 0; 765*cdf0e10cSrcweir 766*cdf0e10cSrcweir if ( ERROR_MORE_DATA == ( nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, 767*cdf0e10cSrcweir &dwType, (BYTE*)sMsiFolder, &nMsiFolderSize ) ) ) 768*cdf0e10cSrcweir { 769*cdf0e10cSrcweir // try again with larger buffer 770*cdf0e10cSrcweir delete [] sMsiFolder; 771*cdf0e10cSrcweir sMsiFolder = new TCHAR[ nMsiFolderSize ]; 772*cdf0e10cSrcweir 773*cdf0e10cSrcweir nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, &dwType, 774*cdf0e10cSrcweir (BYTE*)sMsiFolder, &nMsiFolderSize ); 775*cdf0e10cSrcweir } 776*cdf0e10cSrcweir 777*cdf0e10cSrcweir if ( ERROR_SUCCESS != nRet || dwType != REG_SZ || nMsiFolderSize == 0 ) 778*cdf0e10cSrcweir sMsiFolder[0] = '\0'; 779*cdf0e10cSrcweir } 780*cdf0e10cSrcweir 781*cdf0e10cSrcweir if ( sMsiFolder[0] == '\0' ) // use the default location 782*cdf0e10cSrcweir { 783*cdf0e10cSrcweir Log( TEXT( " Could not find path to msiexec.exe in registry" ) ); 784*cdf0e10cSrcweir 785*cdf0e10cSrcweir DWORD nRet = WIN::GetSystemDirectory( sMsiFolder, nMsiFolderSize ); 786*cdf0e10cSrcweir if ( nRet > nMsiFolderSize ) 787*cdf0e10cSrcweir { 788*cdf0e10cSrcweir delete [] sMsiFolder; 789*cdf0e10cSrcweir sMsiFolder = new TCHAR[ nRet ]; 790*cdf0e10cSrcweir nMsiFolderSize = nRet; 791*cdf0e10cSrcweir 792*cdf0e10cSrcweir nRet = WIN::GetSystemDirectory( sMsiFolder, nMsiFolderSize ); 793*cdf0e10cSrcweir } 794*cdf0e10cSrcweir if ( 0 == nRet ) 795*cdf0e10cSrcweir { 796*cdf0e10cSrcweir sMsiFolder[0] = '\0'; 797*cdf0e10cSrcweir SetError( WIN::GetLastError() ); 798*cdf0e10cSrcweir } 799*cdf0e10cSrcweir nMsiFolderSize = nRet; 800*cdf0e10cSrcweir } 801*cdf0e10cSrcweir 802*cdf0e10cSrcweir if ( sMsiFolder[0] != '\0' ) 803*cdf0e10cSrcweir { 804*cdf0e10cSrcweir int nLength = lstrlen( sMsiExe ) + lstrlen( sMsiFolder ) + 1; 805*cdf0e10cSrcweir sMsiPath = new TCHAR[ nLength ]; 806*cdf0e10cSrcweir 807*cdf0e10cSrcweir if ( FAILED( StringCchCopy( sMsiPath, nLength, sMsiFolder ) ) || 808*cdf0e10cSrcweir FAILED( StringCchCat( sMsiPath, nLength, sMsiExe ) ) ) 809*cdf0e10cSrcweir { 810*cdf0e10cSrcweir delete [] sMsiPath; 811*cdf0e10cSrcweir sMsiPath = NULL; 812*cdf0e10cSrcweir } 813*cdf0e10cSrcweir } 814*cdf0e10cSrcweir 815*cdf0e10cSrcweir if ( ! sMsiPath ) 816*cdf0e10cSrcweir Log( TEXT( "ERROR: Can't build path to msiexec.exe!" ) ); 817*cdf0e10cSrcweir 818*cdf0e10cSrcweir return sMsiPath; 819*cdf0e10cSrcweir } 820*cdf0e10cSrcweir 821*cdf0e10cSrcweir //-------------------------------------------------------------------------- 822*cdf0e10cSrcweir boolean SetupAppX::LaunchInstaller( LPCTSTR pParam ) 823*cdf0e10cSrcweir { 824*cdf0e10cSrcweir LPCTSTR sMsiPath = GetPathToMSI(); 825*cdf0e10cSrcweir 826*cdf0e10cSrcweir if ( !sMsiPath ) 827*cdf0e10cSrcweir { 828*cdf0e10cSrcweir Log( TEXT( "ERROR: msiexec not found!" ) ); 829*cdf0e10cSrcweir SetError( ERROR_FILE_NOT_FOUND ); 830*cdf0e10cSrcweir return false; 831*cdf0e10cSrcweir } 832*cdf0e10cSrcweir 833*cdf0e10cSrcweir STARTUPINFO aSUI; 834*cdf0e10cSrcweir PROCESS_INFORMATION aPI; 835*cdf0e10cSrcweir 836*cdf0e10cSrcweir Log( TEXT( " Will install using <%s>\r\n" ), sMsiPath ); 837*cdf0e10cSrcweir Log( TEXT( " Prameters are: %s\r\n" ), pParam ); 838*cdf0e10cSrcweir 839*cdf0e10cSrcweir OutputDebugStringFormat( TEXT( " Will install using <%s>\r\n" ), sMsiPath ); 840*cdf0e10cSrcweir OutputDebugStringFormat( TEXT( " Prameters are: %s\r\n" ), pParam ); 841*cdf0e10cSrcweir 842*cdf0e10cSrcweir ZeroMemory( (void*)&aPI, sizeof( PROCESS_INFORMATION ) ); 843*cdf0e10cSrcweir ZeroMemory( (void*)&aSUI, sizeof( STARTUPINFO ) ); 844*cdf0e10cSrcweir 845*cdf0e10cSrcweir aSUI.cb = sizeof(STARTUPINFO); 846*cdf0e10cSrcweir aSUI.dwFlags = STARTF_USESHOWWINDOW; 847*cdf0e10cSrcweir aSUI.wShowWindow = SW_SHOW; 848*cdf0e10cSrcweir 849*cdf0e10cSrcweir DWORD nCmdLineLength = lstrlen( sMsiPath ) + lstrlen( pParam ) + 2; 850*cdf0e10cSrcweir TCHAR *sCmdLine = new TCHAR[ nCmdLineLength ]; 851*cdf0e10cSrcweir 852*cdf0e10cSrcweir if ( FAILED( StringCchCopy( sCmdLine, nCmdLineLength, sMsiPath ) ) || 853*cdf0e10cSrcweir FAILED( StringCchCat( sCmdLine, nCmdLineLength, TEXT( " " ) ) ) || 854*cdf0e10cSrcweir FAILED( StringCchCat( sCmdLine, nCmdLineLength, pParam ) ) ) 855*cdf0e10cSrcweir { 856*cdf0e10cSrcweir delete [] sCmdLine; 857*cdf0e10cSrcweir SetError( ERROR_INSTALL_FAILURE ); 858*cdf0e10cSrcweir return false; 859*cdf0e10cSrcweir } 860*cdf0e10cSrcweir 861*cdf0e10cSrcweir if ( !WIN::CreateProcess( NULL, sCmdLine, NULL, NULL, FALSE, 862*cdf0e10cSrcweir CREATE_DEFAULT_ERROR_MODE, NULL, NULL, 863*cdf0e10cSrcweir &aSUI, &aPI ) ) 864*cdf0e10cSrcweir { 865*cdf0e10cSrcweir Log( TEXT( "ERROR: Could not create process %s.\r\n" ), sCmdLine ); 866*cdf0e10cSrcweir SetError( WIN::GetLastError() ); 867*cdf0e10cSrcweir delete [] sCmdLine; 868*cdf0e10cSrcweir return false; 869*cdf0e10cSrcweir } 870*cdf0e10cSrcweir 871*cdf0e10cSrcweir DWORD nResult = WaitForProcess( aPI.hProcess ); 872*cdf0e10cSrcweir bool bRet = true; 873*cdf0e10cSrcweir 874*cdf0e10cSrcweir if( ERROR_SUCCESS != nResult ) 875*cdf0e10cSrcweir { 876*cdf0e10cSrcweir Log( TEXT( "ERROR: While waiting for %s.\r\n" ), sCmdLine ); 877*cdf0e10cSrcweir SetError( nResult ); 878*cdf0e10cSrcweir bRet = false; 879*cdf0e10cSrcweir } 880*cdf0e10cSrcweir else 881*cdf0e10cSrcweir { 882*cdf0e10cSrcweir GetExitCodeProcess( aPI.hProcess, &nResult ); 883*cdf0e10cSrcweir SetError( nResult ); 884*cdf0e10cSrcweir 885*cdf0e10cSrcweir if ( nResult != ERROR_SUCCESS ) 886*cdf0e10cSrcweir { 887*cdf0e10cSrcweir TCHAR sBuf[80]; 888*cdf0e10cSrcweir StringCchPrintf( sBuf, 80, TEXT("Warning: msiexec returned %u.\r\n"), nResult ); 889*cdf0e10cSrcweir Log( sBuf ); 890*cdf0e10cSrcweir } 891*cdf0e10cSrcweir else 892*cdf0e10cSrcweir Log( TEXT( " Installation completed successfully.\r\n" ) ); 893*cdf0e10cSrcweir } 894*cdf0e10cSrcweir 895*cdf0e10cSrcweir CloseHandle( aPI.hProcess ); 896*cdf0e10cSrcweir 897*cdf0e10cSrcweir delete [] sCmdLine; 898*cdf0e10cSrcweir 899*cdf0e10cSrcweir return bRet; 900*cdf0e10cSrcweir } 901*cdf0e10cSrcweir 902*cdf0e10cSrcweir //-------------------------------------------------------------------------- 903*cdf0e10cSrcweir boolean SetupAppX::Install( long nLanguage ) 904*cdf0e10cSrcweir { 905*cdf0e10cSrcweir LPTSTR pTransform = NULL; 906*cdf0e10cSrcweir 907*cdf0e10cSrcweir if ( nLanguage ) // look for transformation 908*cdf0e10cSrcweir { 909*cdf0e10cSrcweir for ( int i = 0; i < m_nLanguageCount; i++ ) 910*cdf0e10cSrcweir { 911*cdf0e10cSrcweir if ( m_ppLanguageList[i]->m_nLanguageID == nLanguage ) 912*cdf0e10cSrcweir { 913*cdf0e10cSrcweir if ( m_ppLanguageList[i]->m_pTransform ) 914*cdf0e10cSrcweir { 915*cdf0e10cSrcweir if ( !GetPathToFile( m_ppLanguageList[i]->m_pTransform, 916*cdf0e10cSrcweir &pTransform ) ) 917*cdf0e10cSrcweir { 918*cdf0e10cSrcweir Log( TEXT( "ERROR: Could not find transform <%s\r\n" ), m_ppLanguageList[i]->m_pTransform ); 919*cdf0e10cSrcweir return false; 920*cdf0e10cSrcweir } 921*cdf0e10cSrcweir } 922*cdf0e10cSrcweir break; 923*cdf0e10cSrcweir } 924*cdf0e10cSrcweir } 925*cdf0e10cSrcweir } 926*cdf0e10cSrcweir 927*cdf0e10cSrcweir TCHAR *pDataBasePath = NULL; 928*cdf0e10cSrcweir 929*cdf0e10cSrcweir if ( ! GetPathToFile( m_pDatabase, &pDataBasePath ) ) 930*cdf0e10cSrcweir { 931*cdf0e10cSrcweir Log( TEXT( "ERROR: Could not find database <%s\r\n" ), m_pDatabase ); 932*cdf0e10cSrcweir SetError( ERROR_INSTALL_SOURCE_ABSENT ); 933*cdf0e10cSrcweir return false; 934*cdf0e10cSrcweir } 935*cdf0e10cSrcweir 936*cdf0e10cSrcweir // we will always use the parameter setup used 937*cdf0e10cSrcweir int nParLen = lstrlen( PARAM_SETUP_USED ); 938*cdf0e10cSrcweir 939*cdf0e10cSrcweir if ( m_bRegNoMsoTypes ) 940*cdf0e10cSrcweir nParLen += lstrlen( PARAM_REG_NO_MSO_TYPES ); 941*cdf0e10cSrcweir else if ( m_bRegAllMsoTypes ) 942*cdf0e10cSrcweir nParLen += lstrlen( PARAM_REG_ALL_MSO_TYPES ); 943*cdf0e10cSrcweir 944*cdf0e10cSrcweir if ( m_pAdvertise ) 945*cdf0e10cSrcweir nParLen += lstrlen( m_pAdvertise ) + 1; // one for the space 946*cdf0e10cSrcweir else if ( m_bIsMinorUpgrade ) 947*cdf0e10cSrcweir nParLen += lstrlen( PARAM_MINOR_UPGRADE ); 948*cdf0e10cSrcweir else 949*cdf0e10cSrcweir nParLen += lstrlen( PARAM_PACKAGE ); 950*cdf0e10cSrcweir 951*cdf0e10cSrcweir nParLen += lstrlen( pDataBasePath ) + 3; // two quotes, one null 952*cdf0e10cSrcweir 953*cdf0e10cSrcweir if ( NeedReboot() ) 954*cdf0e10cSrcweir nParLen += lstrlen( PARAM_REBOOT ); 955*cdf0e10cSrcweir 956*cdf0e10cSrcweir if ( m_pPatchFiles ) 957*cdf0e10cSrcweir { 958*cdf0e10cSrcweir nParLen += lstrlen( PARAM_PATCH ); 959*cdf0e10cSrcweir nParLen += lstrlen( m_pPatchFiles ); 960*cdf0e10cSrcweir } 961*cdf0e10cSrcweir 962*cdf0e10cSrcweir if ( pTransform ) 963*cdf0e10cSrcweir { 964*cdf0e10cSrcweir nParLen += lstrlen( PARAM_TRANSFORM ); 965*cdf0e10cSrcweir nParLen += lstrlen( pTransform ) + 2; // two quotes 966*cdf0e10cSrcweir } 967*cdf0e10cSrcweir 968*cdf0e10cSrcweir if ( m_pCmdLine ) 969*cdf0e10cSrcweir nParLen += lstrlen( m_pCmdLine ) + 1; // one for the space; 970*cdf0e10cSrcweir 971*cdf0e10cSrcweir TCHAR *pParams = new TCHAR[ nParLen ]; 972*cdf0e10cSrcweir 973*cdf0e10cSrcweir StringCchCopy( pParams, nParLen, PARAM_SETUP_USED ); 974*cdf0e10cSrcweir 975*cdf0e10cSrcweir if ( m_bRegNoMsoTypes ) 976*cdf0e10cSrcweir StringCchCat( pParams, nParLen, PARAM_REG_NO_MSO_TYPES ); 977*cdf0e10cSrcweir else if ( m_bRegAllMsoTypes ) 978*cdf0e10cSrcweir StringCchCat( pParams, nParLen, PARAM_REG_ALL_MSO_TYPES ); 979*cdf0e10cSrcweir 980*cdf0e10cSrcweir if ( m_pAdvertise ) 981*cdf0e10cSrcweir StringCchCat( pParams, nParLen, m_pAdvertise ); 982*cdf0e10cSrcweir else if ( IsAdminInstall() ) 983*cdf0e10cSrcweir StringCchCat( pParams, nParLen, PARAM_ADMIN ); 984*cdf0e10cSrcweir else if ( m_bIsMinorUpgrade ) 985*cdf0e10cSrcweir StringCchCat( pParams, nParLen, PARAM_MINOR_UPGRADE ); 986*cdf0e10cSrcweir else 987*cdf0e10cSrcweir StringCchCat( pParams, nParLen, PARAM_PACKAGE ); 988*cdf0e10cSrcweir 989*cdf0e10cSrcweir StringCchCat( pParams, nParLen, TEXT( "\"" ) ); 990*cdf0e10cSrcweir StringCchCat( pParams, nParLen, pDataBasePath ); 991*cdf0e10cSrcweir StringCchCat( pParams, nParLen, TEXT( "\"" ) ); 992*cdf0e10cSrcweir 993*cdf0e10cSrcweir if ( NeedReboot() ) 994*cdf0e10cSrcweir StringCchCat( pParams, nParLen, PARAM_REBOOT ); 995*cdf0e10cSrcweir 996*cdf0e10cSrcweir if ( m_pPatchFiles ) 997*cdf0e10cSrcweir { 998*cdf0e10cSrcweir StringCchCat( pParams, nParLen, PARAM_PATCH ); 999*cdf0e10cSrcweir StringCchCat( pParams, nParLen, m_pPatchFiles ); 1000*cdf0e10cSrcweir } 1001*cdf0e10cSrcweir 1002*cdf0e10cSrcweir if ( pTransform ) 1003*cdf0e10cSrcweir { 1004*cdf0e10cSrcweir StringCchCat( pParams, nParLen, PARAM_TRANSFORM ); 1005*cdf0e10cSrcweir StringCchCat( pParams, nParLen, TEXT( "\"" ) ); 1006*cdf0e10cSrcweir StringCchCat( pParams, nParLen, pTransform ); 1007*cdf0e10cSrcweir StringCchCat( pParams, nParLen, TEXT( "\"" ) ); 1008*cdf0e10cSrcweir } 1009*cdf0e10cSrcweir 1010*cdf0e10cSrcweir if ( m_pCmdLine ) 1011*cdf0e10cSrcweir { 1012*cdf0e10cSrcweir StringCchCat( pParams, nParLen, TEXT( " " ) ); 1013*cdf0e10cSrcweir StringCchCat( pParams, nParLen, m_pCmdLine ); 1014*cdf0e10cSrcweir } 1015*cdf0e10cSrcweir 1016*cdf0e10cSrcweir return LaunchInstaller( pParams ); 1017*cdf0e10cSrcweir } 1018*cdf0e10cSrcweir 1019*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1020*cdf0e10cSrcweir UINT SetupAppX::GetError() const 1021*cdf0e10cSrcweir { 1022*cdf0e10cSrcweir UINT nErr = 0; 1023*cdf0e10cSrcweir 1024*cdf0e10cSrcweir if ( m_pMSIErrorCode ) 1025*cdf0e10cSrcweir nErr = (UINT) *m_pMSIErrorCode; 1026*cdf0e10cSrcweir 1027*cdf0e10cSrcweir if ( nErr == 0 ) 1028*cdf0e10cSrcweir nErr = m_uiRet; 1029*cdf0e10cSrcweir 1030*cdf0e10cSrcweir if ( nErr != 0 ) 1031*cdf0e10cSrcweir OutputDebugStringFormat( TEXT("Setup will return error (%d).\n"), nErr ); 1032*cdf0e10cSrcweir return nErr; 1033*cdf0e10cSrcweir } 1034*cdf0e10cSrcweir 1035*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1036*cdf0e10cSrcweir void SetupAppX::DisplayError( UINT nErr ) const 1037*cdf0e10cSrcweir { 1038*cdf0e10cSrcweir TCHAR sError[ MAX_TEXT_LENGTH ] = {0}; 1039*cdf0e10cSrcweir TCHAR sTmp[ MAX_TEXT_LENGTH ] = {0}; 1040*cdf0e10cSrcweir 1041*cdf0e10cSrcweir UINT nMsgType = MB_OK | MB_ICONERROR; 1042*cdf0e10cSrcweir 1043*cdf0e10cSrcweir switch ( nErr ) 1044*cdf0e10cSrcweir { 1045*cdf0e10cSrcweir case ERROR_SUCCESS: break; // 0 1046*cdf0e10cSrcweir 1047*cdf0e10cSrcweir case ERROR_FILE_NOT_FOUND: // 2 1048*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_FILE_NOT_FOUND, sTmp, MAX_TEXT_LENGTH ); 1049*cdf0e10cSrcweir StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pErrorText ); 1050*cdf0e10cSrcweir break; 1051*cdf0e10cSrcweir case ERROR_INVALID_DATA: // 13 1052*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_INVALID_PROFILE, sError, MAX_TEXT_LENGTH ); 1053*cdf0e10cSrcweir break; 1054*cdf0e10cSrcweir case ERROR_OUTOFMEMORY: WIN::LoadString( m_hInst, IDS_OUTOFMEM, sError, MAX_TEXT_LENGTH ); 1055*cdf0e10cSrcweir break; 1056*cdf0e10cSrcweir case ERROR_INSTALL_USEREXIT: 1057*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_USER_CANCELLED, sError, MAX_TEXT_LENGTH ); 1058*cdf0e10cSrcweir break; 1059*cdf0e10cSrcweir case ERROR_INSTALL_ALREADY_RUNNING: // 1618 1060*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_ALREADY_RUNNING, sError, MAX_TEXT_LENGTH ); 1061*cdf0e10cSrcweir break; 1062*cdf0e10cSrcweir case ERROR_INSTALL_SOURCE_ABSENT: 1063*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_NOMSI, sError, MAX_TEXT_LENGTH ); 1064*cdf0e10cSrcweir break; 1065*cdf0e10cSrcweir case ERROR_DS_INSUFF_ACCESS_RIGHTS: // 8344 1066*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_REQUIRES_ADMIN_PRIV, sError, MAX_TEXT_LENGTH ); 1067*cdf0e10cSrcweir break; 1068*cdf0e10cSrcweir case E_ABORT: WIN::LoadString( m_hInst, IDS_UNKNOWN_ERROR, sError, MAX_TEXT_LENGTH ); 1069*cdf0e10cSrcweir break; 1070*cdf0e10cSrcweir case ERROR_INVALID_PARAMETER: // 87 1071*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_INVALID_PARAM, sTmp, MAX_TEXT_LENGTH ); 1072*cdf0e10cSrcweir StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pErrorText ); 1073*cdf0e10cSrcweir break; 1074*cdf0e10cSrcweir 1075*cdf0e10cSrcweir case ERROR_SETUP_TO_OLD: // - 3 1076*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_SETUP_TO_OLD, sTmp, MAX_TEXT_LENGTH ); 1077*cdf0e10cSrcweir StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pReqVersion, m_pErrorText ); 1078*cdf0e10cSrcweir break; 1079*cdf0e10cSrcweir case ERROR_SETUP_NOT_FOUND: // - 4 1080*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_SETUP_NOT_FOUND, sTmp, MAX_TEXT_LENGTH ); 1081*cdf0e10cSrcweir StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pReqVersion ); 1082*cdf0e10cSrcweir break; 1083*cdf0e10cSrcweir case ERROR_SHOW_USAGE: // - 2 1084*cdf0e10cSrcweir nMsgType = MB_OK | MB_ICONINFORMATION; 1085*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_USAGE, sError, MAX_TEXT_LENGTH ); 1086*cdf0e10cSrcweir break; 1087*cdf0e10cSrcweir 1088*cdf0e10cSrcweir default: WIN::LoadString( m_hInst, IDS_UNKNOWN_ERROR, sError, MAX_TEXT_LENGTH ); 1089*cdf0e10cSrcweir break; 1090*cdf0e10cSrcweir } 1091*cdf0e10cSrcweir 1092*cdf0e10cSrcweir if ( sError[0] ) 1093*cdf0e10cSrcweir { 1094*cdf0e10cSrcweir if ( !m_bQuiet ) 1095*cdf0e10cSrcweir { 1096*cdf0e10cSrcweir ConvertNewline( sError ); 1097*cdf0e10cSrcweir WIN::MessageBox( NULL, sError, m_pAppTitle, nMsgType ); 1098*cdf0e10cSrcweir } 1099*cdf0e10cSrcweir 1100*cdf0e10cSrcweir Log( TEXT( "ERROR: %s\r\n" ), sError ); 1101*cdf0e10cSrcweir } 1102*cdf0e10cSrcweir } 1103*cdf0e10cSrcweir 1104*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1105*cdf0e10cSrcweir long SetupAppX::GetLanguageID( long nIndex ) const 1106*cdf0e10cSrcweir { 1107*cdf0e10cSrcweir if ( nIndex >=0 && nIndex < m_nLanguageCount ) 1108*cdf0e10cSrcweir return m_ppLanguageList[ nIndex ]->m_nLanguageID; 1109*cdf0e10cSrcweir else 1110*cdf0e10cSrcweir return 0; 1111*cdf0e10cSrcweir } 1112*cdf0e10cSrcweir 1113*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1114*cdf0e10cSrcweir void SetupAppX::GetLanguageName( long nLanguage, LPTSTR sName ) const 1115*cdf0e10cSrcweir { 1116*cdf0e10cSrcweir switch ( nLanguage ) 1117*cdf0e10cSrcweir { 1118*cdf0e10cSrcweir case 1028: WIN::LoadString( m_hInst, IDS_LANGUAGE_ZH_TW, sName, MAX_LANGUAGE_LEN ); break; 1119*cdf0e10cSrcweir case 1029: WIN::LoadString( m_hInst, IDS_LANGUAGE_CS, sName, MAX_LANGUAGE_LEN ); break; 1120*cdf0e10cSrcweir case 1030: WIN::LoadString( m_hInst, IDS_LANGUAGE_DA, sName, MAX_LANGUAGE_LEN ); break; 1121*cdf0e10cSrcweir case 1031: WIN::LoadString( m_hInst, IDS_LANGUAGE_DE_DE, sName, MAX_LANGUAGE_LEN ); break; 1122*cdf0e10cSrcweir case 1032: WIN::LoadString( m_hInst, IDS_LANGUAGE_EL, sName, MAX_LANGUAGE_LEN ); break; 1123*cdf0e10cSrcweir case 1033: WIN::LoadString( m_hInst, IDS_LANGUAGE_EN_US, sName, MAX_LANGUAGE_LEN ); break; 1124*cdf0e10cSrcweir case 1034: WIN::LoadString( m_hInst, IDS_LANGUAGE_ES, sName, MAX_LANGUAGE_LEN ); break; 1125*cdf0e10cSrcweir case 1035: WIN::LoadString( m_hInst, IDS_LANGUAGE_FI, sName, MAX_LANGUAGE_LEN ); break; 1126*cdf0e10cSrcweir case 1036: WIN::LoadString( m_hInst, IDS_LANGUAGE_FR_FR, sName, MAX_LANGUAGE_LEN ); break; 1127*cdf0e10cSrcweir case 1037: WIN::LoadString( m_hInst, IDS_LANGUAGE_HE, sName, MAX_LANGUAGE_LEN ); break; 1128*cdf0e10cSrcweir case 1038: WIN::LoadString( m_hInst, IDS_LANGUAGE_HU, sName, MAX_LANGUAGE_LEN ); break; 1129*cdf0e10cSrcweir case 1040: WIN::LoadString( m_hInst, IDS_LANGUAGE_IT_IT, sName, MAX_LANGUAGE_LEN ); break; 1130*cdf0e10cSrcweir case 1041: WIN::LoadString( m_hInst, IDS_LANGUAGE_JA, sName, MAX_LANGUAGE_LEN ); break; 1131*cdf0e10cSrcweir case 1042: WIN::LoadString( m_hInst, IDS_LANGUAGE_KO, sName, MAX_LANGUAGE_LEN ); break; 1132*cdf0e10cSrcweir case 1043: WIN::LoadString( m_hInst, IDS_LANGUAGE_NL_NL, sName, MAX_LANGUAGE_LEN ); break; 1133*cdf0e10cSrcweir case 1044: WIN::LoadString( m_hInst, IDS_LANGUAGE_NO_NO, sName, MAX_LANGUAGE_LEN ); break; 1134*cdf0e10cSrcweir case 1045: WIN::LoadString( m_hInst, IDS_LANGUAGE_PL, sName, MAX_LANGUAGE_LEN ); break; 1135*cdf0e10cSrcweir case 1046: WIN::LoadString( m_hInst, IDS_LANGUAGE_PT_BR, sName, MAX_LANGUAGE_LEN ); break; 1136*cdf0e10cSrcweir case 1049: WIN::LoadString( m_hInst, IDS_LANGUAGE_RU, sName, MAX_LANGUAGE_LEN ); break; 1137*cdf0e10cSrcweir case 1051: WIN::LoadString( m_hInst, IDS_LANGUAGE_SK, sName, MAX_LANGUAGE_LEN ); break; 1138*cdf0e10cSrcweir case 1053: WIN::LoadString( m_hInst, IDS_LANGUAGE_SV_SE, sName, MAX_LANGUAGE_LEN ); break; 1139*cdf0e10cSrcweir case 1054: WIN::LoadString( m_hInst, IDS_LANGUAGE_TH, sName, MAX_LANGUAGE_LEN ); break; 1140*cdf0e10cSrcweir case 1055: WIN::LoadString( m_hInst, IDS_LANGUAGE_TR, sName, MAX_LANGUAGE_LEN ); break; 1141*cdf0e10cSrcweir case 1061: WIN::LoadString( m_hInst, IDS_LANGUAGE_ET, sName, MAX_LANGUAGE_LEN ); break; 1142*cdf0e10cSrcweir case 2052: WIN::LoadString( m_hInst, IDS_LANGUAGE_ZH_CN, sName, MAX_LANGUAGE_LEN ); break; 1143*cdf0e10cSrcweir case 2070: WIN::LoadString( m_hInst, IDS_LANGUAGE_PT_PT, sName, MAX_LANGUAGE_LEN ); break; 1144*cdf0e10cSrcweir 1145*cdf0e10cSrcweir default: 1146*cdf0e10cSrcweir { 1147*cdf0e10cSrcweir TCHAR sTmp[ MAX_LANGUAGE_LEN ] = {0}; 1148*cdf0e10cSrcweir 1149*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_UNKNOWN_LANG, sTmp, MAX_LANGUAGE_LEN ); 1150*cdf0e10cSrcweir StringCchPrintf( sName, MAX_LANGUAGE_LEN, sTmp, nLanguage ); 1151*cdf0e10cSrcweir } 1152*cdf0e10cSrcweir } 1153*cdf0e10cSrcweir } 1154*cdf0e10cSrcweir 1155*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1156*cdf0e10cSrcweir boolean SetupAppX::CheckVersion() 1157*cdf0e10cSrcweir { 1158*cdf0e10cSrcweir boolean bRet = false; 1159*cdf0e10cSrcweir HMODULE hMsi = LoadMsiLibrary(); 1160*cdf0e10cSrcweir 1161*cdf0e10cSrcweir Log( TEXT( " Looking for installed MSI with version >= %s\r\n" ), m_pReqVersion ); 1162*cdf0e10cSrcweir 1163*cdf0e10cSrcweir if ( !hMsi ) 1164*cdf0e10cSrcweir { 1165*cdf0e10cSrcweir Log( TEXT( "Error: No MSI found!\r\n" ) ); 1166*cdf0e10cSrcweir SetError( (UINT) ERROR_SETUP_NOT_FOUND ); 1167*cdf0e10cSrcweir } 1168*cdf0e10cSrcweir else 1169*cdf0e10cSrcweir { 1170*cdf0e10cSrcweir PFnDllGetVersion pDllGetVersion = (PFnDllGetVersion) GetProcAddress( hMsi, MSIAPI_DllGetVersion ); 1171*cdf0e10cSrcweir 1172*cdf0e10cSrcweir if ( pDllGetVersion ) 1173*cdf0e10cSrcweir { 1174*cdf0e10cSrcweir DLLVERSIONINFO aInfo; 1175*cdf0e10cSrcweir 1176*cdf0e10cSrcweir aInfo.cbSize = sizeof( DLLVERSIONINFO ); 1177*cdf0e10cSrcweir if ( NOERROR == pDllGetVersion( &aInfo ) ) 1178*cdf0e10cSrcweir { 1179*cdf0e10cSrcweir TCHAR pMsiVersion[ VERSION_SIZE ]; 1180*cdf0e10cSrcweir StringCchPrintf( pMsiVersion, VERSION_SIZE, TEXT("%d.%d.%4d"), 1181*cdf0e10cSrcweir aInfo.dwMajorVersion, 1182*cdf0e10cSrcweir aInfo.dwMinorVersion, 1183*cdf0e10cSrcweir aInfo.dwBuildNumber ); 1184*cdf0e10cSrcweir if ( _tcsncmp( pMsiVersion, m_pReqVersion, _tcslen( pMsiVersion ) ) < 0 ) 1185*cdf0e10cSrcweir { 1186*cdf0e10cSrcweir StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pMsiVersion ); 1187*cdf0e10cSrcweir SetError( (UINT) ERROR_SETUP_TO_OLD ); 1188*cdf0e10cSrcweir Log( TEXT( "Warning: Old MSI version found <%s>, update needed!\r\n" ), pMsiVersion ); 1189*cdf0e10cSrcweir } 1190*cdf0e10cSrcweir else 1191*cdf0e10cSrcweir { 1192*cdf0e10cSrcweir Log( TEXT( " Found MSI version <%s>, no update needed\r\n" ), pMsiVersion ); 1193*cdf0e10cSrcweir bRet = true; 1194*cdf0e10cSrcweir } 1195*cdf0e10cSrcweir if ( aInfo.dwMajorVersion >= 3 ) 1196*cdf0e10cSrcweir m_bSupportsPatch = true; 1197*cdf0e10cSrcweir else 1198*cdf0e10cSrcweir Log( TEXT("Warning: Patching not supported! MSI-Version <%s>\r\n"), pMsiVersion ); 1199*cdf0e10cSrcweir } 1200*cdf0e10cSrcweir } 1201*cdf0e10cSrcweir 1202*cdf0e10cSrcweir FreeLibrary( hMsi ); 1203*cdf0e10cSrcweir } 1204*cdf0e10cSrcweir 1205*cdf0e10cSrcweir return bRet; 1206*cdf0e10cSrcweir } 1207*cdf0e10cSrcweir 1208*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1209*cdf0e10cSrcweir boolean SetupAppX::CheckForUpgrade() 1210*cdf0e10cSrcweir { 1211*cdf0e10cSrcweir // When we have patch files we will never try an Minor upgrade 1212*cdf0e10cSrcweir if ( m_pPatchFiles ) return true; 1213*cdf0e10cSrcweir 1214*cdf0e10cSrcweir if ( !m_pUpgradeKey || ( _tcslen( m_pUpgradeKey ) == 0 ) ) 1215*cdf0e10cSrcweir { 1216*cdf0e10cSrcweir Log( TEXT( " No Upgrade Key Found -> continue with standard installation!\r\n" ) ); 1217*cdf0e10cSrcweir return true; 1218*cdf0e10cSrcweir } 1219*cdf0e10cSrcweir 1220*cdf0e10cSrcweir HKEY hInstKey = NULL; 1221*cdf0e10cSrcweir 1222*cdf0e10cSrcweir if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, m_pUpgradeKey, 0, KEY_READ, &hInstKey ) ) 1223*cdf0e10cSrcweir { 1224*cdf0e10cSrcweir Log( TEXT( " Found Upgrade Key in Registry (HKLM) -> will try minor upgrade!\r\n" ) ); 1225*cdf0e10cSrcweir m_bIsMinorUpgrade = true; 1226*cdf0e10cSrcweir } 1227*cdf0e10cSrcweir else if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_CURRENT_USER, m_pUpgradeKey, 0, KEY_READ, &hInstKey ) ) 1228*cdf0e10cSrcweir { 1229*cdf0e10cSrcweir Log( TEXT( " Found Upgrade Key in Registry (HKCU) -> will try minor upgrade!\r\n" ) ); 1230*cdf0e10cSrcweir m_bIsMinorUpgrade = true; 1231*cdf0e10cSrcweir } 1232*cdf0e10cSrcweir else 1233*cdf0e10cSrcweir { 1234*cdf0e10cSrcweir Log( TEXT( " Didn't Find Upgrade Key in Registry -> continue with standard installation!\r\n" ) ); 1235*cdf0e10cSrcweir return true; 1236*cdf0e10cSrcweir } 1237*cdf0e10cSrcweir 1238*cdf0e10cSrcweir if ( m_pProductVersion && ( _tcslen( m_pProductVersion ) > 0 ) ) 1239*cdf0e10cSrcweir { 1240*cdf0e10cSrcweir TCHAR *sProductVersion = new TCHAR[ MAX_PATH + 1 ]; 1241*cdf0e10cSrcweir DWORD nSize = MAX_PATH + 1; 1242*cdf0e10cSrcweir 1243*cdf0e10cSrcweir sProductVersion[0] = '\0'; 1244*cdf0e10cSrcweir 1245*cdf0e10cSrcweir // get product version 1246*cdf0e10cSrcweir if ( ERROR_SUCCESS == RegQueryValueEx( hInstKey, PRODUCT_VERSION, NULL, NULL, (LPBYTE)sProductVersion, &nSize ) ) 1247*cdf0e10cSrcweir { 1248*cdf0e10cSrcweir if ( lstrcmpi( sProductVersion, m_pProductVersion ) == 0 ) 1249*cdf0e10cSrcweir { 1250*cdf0e10cSrcweir Log( TEXT( " Same Product Version already installed, no minor upgrade!\r\n" ) ); 1251*cdf0e10cSrcweir m_bIsMinorUpgrade = false; 1252*cdf0e10cSrcweir } 1253*cdf0e10cSrcweir } 1254*cdf0e10cSrcweir 1255*cdf0e10cSrcweir delete [] sProductVersion; 1256*cdf0e10cSrcweir } 1257*cdf0e10cSrcweir 1258*cdf0e10cSrcweir return true; 1259*cdf0e10cSrcweir } 1260*cdf0e10cSrcweir 1261*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1262*cdf0e10cSrcweir boolean SetupAppX::IsTerminalServerInstalled() const 1263*cdf0e10cSrcweir { 1264*cdf0e10cSrcweir boolean bIsTerminalServer = false; 1265*cdf0e10cSrcweir 1266*cdf0e10cSrcweir const TCHAR sSearchStr[] = TEXT("Terminal Server"); 1267*cdf0e10cSrcweir const TCHAR sKey[] = TEXT("System\\CurrentControlSet\\Control\\ProductOptions"); 1268*cdf0e10cSrcweir const TCHAR sValue[] = TEXT("ProductSuite"); 1269*cdf0e10cSrcweir 1270*cdf0e10cSrcweir DWORD dwSize = 0; 1271*cdf0e10cSrcweir HKEY hKey = 0; 1272*cdf0e10cSrcweir DWORD dwType = 0; 1273*cdf0e10cSrcweir 1274*cdf0e10cSrcweir if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sKey, 0, KEY_READ, &hKey ) && 1275*cdf0e10cSrcweir ERROR_SUCCESS == RegQueryValueEx( hKey, sValue, NULL, &dwType, NULL, &dwSize ) && 1276*cdf0e10cSrcweir dwSize > 0 && 1277*cdf0e10cSrcweir REG_MULTI_SZ == dwType ) 1278*cdf0e10cSrcweir { 1279*cdf0e10cSrcweir TCHAR* sSuiteList = new TCHAR[ (dwSize*sizeof(byte)/sizeof(TCHAR)) + 1 ]; 1280*cdf0e10cSrcweir 1281*cdf0e10cSrcweir ZeroMemory(sSuiteList, dwSize); 1282*cdf0e10cSrcweir 1283*cdf0e10cSrcweir if ( ERROR_SUCCESS == RegQueryValueEx( hKey, sValue, NULL, &dwType, (LPBYTE)sSuiteList, &dwSize) ) 1284*cdf0e10cSrcweir { 1285*cdf0e10cSrcweir DWORD nMulti = 0; 1286*cdf0e10cSrcweir DWORD nSrch = lstrlen( sSearchStr ); 1287*cdf0e10cSrcweir const TCHAR *sSubString = sSuiteList; 1288*cdf0e10cSrcweir 1289*cdf0e10cSrcweir while (*sSubString) 1290*cdf0e10cSrcweir { 1291*cdf0e10cSrcweir nMulti = lstrlen( sSubString ); 1292*cdf0e10cSrcweir if ( nMulti == nSrch && 0 == lstrcmp( sSearchStr, sSubString ) ) 1293*cdf0e10cSrcweir { 1294*cdf0e10cSrcweir bIsTerminalServer = true; 1295*cdf0e10cSrcweir break; 1296*cdf0e10cSrcweir } 1297*cdf0e10cSrcweir 1298*cdf0e10cSrcweir sSubString += (nMulti + 1); 1299*cdf0e10cSrcweir } 1300*cdf0e10cSrcweir } 1301*cdf0e10cSrcweir delete [] sSuiteList; 1302*cdf0e10cSrcweir } 1303*cdf0e10cSrcweir 1304*cdf0e10cSrcweir if ( hKey ) 1305*cdf0e10cSrcweir RegCloseKey( hKey ); 1306*cdf0e10cSrcweir 1307*cdf0e10cSrcweir return bIsTerminalServer; 1308*cdf0e10cSrcweir } 1309*cdf0e10cSrcweir 1310*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1311*cdf0e10cSrcweir boolean SetupAppX::AlreadyRunning() const 1312*cdf0e10cSrcweir { 1313*cdf0e10cSrcweir if ( m_bIgnoreAlreadyRunning ) 1314*cdf0e10cSrcweir { 1315*cdf0e10cSrcweir Log( TEXT("Ignoring already running MSI instance!\r\n") ); 1316*cdf0e10cSrcweir return false; 1317*cdf0e10cSrcweir } 1318*cdf0e10cSrcweir 1319*cdf0e10cSrcweir const TCHAR *sMutexName = NULL; 1320*cdf0e10cSrcweir const TCHAR sGUniqueName[] = TEXT( "Global\\_MSISETUP_{EA8130C1-8D3D-4338-9309-1A52D530D846}" ); 1321*cdf0e10cSrcweir const TCHAR sUniqueName[] = TEXT( "_MSISETUP_{EA8130C1-8D3D-4338-9309-1A52D530D846}" ); 1322*cdf0e10cSrcweir 1323*cdf0e10cSrcweir if ( IsWin9x() ) 1324*cdf0e10cSrcweir sMutexName = sUniqueName; 1325*cdf0e10cSrcweir else if ( ( GetOSVersion() < 5 ) && ! IsTerminalServerInstalled() ) 1326*cdf0e10cSrcweir sMutexName = sUniqueName; 1327*cdf0e10cSrcweir else 1328*cdf0e10cSrcweir sMutexName = sGUniqueName; 1329*cdf0e10cSrcweir 1330*cdf0e10cSrcweir HANDLE hMutex = 0; 1331*cdf0e10cSrcweir 1332*cdf0e10cSrcweir hMutex = WIN::CreateMutex( NULL, FALSE, sMutexName ); 1333*cdf0e10cSrcweir 1334*cdf0e10cSrcweir if ( !hMutex || ERROR_ALREADY_EXISTS == WIN::GetLastError() ) 1335*cdf0e10cSrcweir { 1336*cdf0e10cSrcweir if ( !hMutex ) 1337*cdf0e10cSrcweir Log( TEXT( "ERROR: AlreadyRunning() could not create mutex!\r\n" ) ); 1338*cdf0e10cSrcweir else 1339*cdf0e10cSrcweir Log( TEXT( "ERROR: There's already a setup running!\r\n" ) ); 1340*cdf0e10cSrcweir 1341*cdf0e10cSrcweir return true; 1342*cdf0e10cSrcweir } 1343*cdf0e10cSrcweir Log( TEXT( " No running Setup found\r\n" ) ); 1344*cdf0e10cSrcweir 1345*cdf0e10cSrcweir return false; 1346*cdf0e10cSrcweir } 1347*cdf0e10cSrcweir 1348*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1349*cdf0e10cSrcweir DWORD SetupAppX::WaitForProcess( HANDLE hHandle ) 1350*cdf0e10cSrcweir { 1351*cdf0e10cSrcweir DWORD nResult = NOERROR; 1352*cdf0e10cSrcweir boolean bLoop = true; 1353*cdf0e10cSrcweir 1354*cdf0e10cSrcweir MSG aMsg; 1355*cdf0e10cSrcweir ZeroMemory( (void*) &aMsg, sizeof(MSG) ); 1356*cdf0e10cSrcweir 1357*cdf0e10cSrcweir while ( bLoop ) 1358*cdf0e10cSrcweir { 1359*cdf0e10cSrcweir switch ( WIN::MsgWaitForMultipleObjects( 1, &hHandle, false, 1360*cdf0e10cSrcweir INFINITE, QS_ALLINPUT ) ) 1361*cdf0e10cSrcweir { 1362*cdf0e10cSrcweir case WAIT_OBJECT_0: bLoop = false; 1363*cdf0e10cSrcweir break; 1364*cdf0e10cSrcweir 1365*cdf0e10cSrcweir case (WAIT_OBJECT_0 + 1): 1366*cdf0e10cSrcweir { 1367*cdf0e10cSrcweir if ( WIN::PeekMessage( &aMsg, NULL, NULL, NULL, PM_REMOVE ) ) 1368*cdf0e10cSrcweir { 1369*cdf0e10cSrcweir WIN::TranslateMessage( &aMsg ); 1370*cdf0e10cSrcweir WIN::DispatchMessage( &aMsg ); 1371*cdf0e10cSrcweir } 1372*cdf0e10cSrcweir break; 1373*cdf0e10cSrcweir } 1374*cdf0e10cSrcweir 1375*cdf0e10cSrcweir default: 1376*cdf0e10cSrcweir { 1377*cdf0e10cSrcweir nResult = WIN::GetLastError(); 1378*cdf0e10cSrcweir bLoop = false; 1379*cdf0e10cSrcweir } 1380*cdf0e10cSrcweir } 1381*cdf0e10cSrcweir } 1382*cdf0e10cSrcweir 1383*cdf0e10cSrcweir return nResult; 1384*cdf0e10cSrcweir } 1385*cdf0e10cSrcweir 1386*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1387*cdf0e10cSrcweir void SetupAppX::Log( LPCTSTR pMessage, LPCTSTR pText ) const 1388*cdf0e10cSrcweir { 1389*cdf0e10cSrcweir if ( m_pLogFile ) 1390*cdf0e10cSrcweir { 1391*cdf0e10cSrcweir static boolean bInit = false; 1392*cdf0e10cSrcweir 1393*cdf0e10cSrcweir if ( !bInit ) 1394*cdf0e10cSrcweir { 1395*cdf0e10cSrcweir bInit = true; 1396*cdf0e10cSrcweir if ( ! IsWin9x() ) 1397*cdf0e10cSrcweir _ftprintf( m_pLogFile, TEXT("%c"), 0xfeff ); 1398*cdf0e10cSrcweir 1399*cdf0e10cSrcweir _tsetlocale( LC_ALL, TEXT("") ); 1400*cdf0e10cSrcweir _ftprintf( m_pLogFile, TEXT("\nCodepage=%s\nMultiByte Codepage=[%d]\n"), 1401*cdf0e10cSrcweir _tsetlocale( LC_ALL, NULL ), _getmbcp() ); 1402*cdf0e10cSrcweir } 1403*cdf0e10cSrcweir if ( pText ) 1404*cdf0e10cSrcweir { 1405*cdf0e10cSrcweir _ftprintf( m_pLogFile, pMessage, pText ); 1406*cdf0e10cSrcweir OutputDebugStringFormat( pMessage, pText ); 1407*cdf0e10cSrcweir } 1408*cdf0e10cSrcweir else 1409*cdf0e10cSrcweir { 1410*cdf0e10cSrcweir _ftprintf( m_pLogFile, pMessage ); 1411*cdf0e10cSrcweir OutputDebugStringFormat( pMessage ); 1412*cdf0e10cSrcweir } 1413*cdf0e10cSrcweir 1414*cdf0e10cSrcweir fflush( m_pLogFile ); 1415*cdf0e10cSrcweir } 1416*cdf0e10cSrcweir } 1417*cdf0e10cSrcweir 1418*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1419*cdf0e10cSrcweir DWORD SetupAppX::GetNextArgument( LPCTSTR pStr, LPTSTR *pArg, LPTSTR *pNext, 1420*cdf0e10cSrcweir boolean bStripQuotes ) 1421*cdf0e10cSrcweir { 1422*cdf0e10cSrcweir boolean bInQuotes = false; 1423*cdf0e10cSrcweir boolean bFoundArgEnd = false; 1424*cdf0e10cSrcweir LPCTSTR pChar = pStr; 1425*cdf0e10cSrcweir LPCTSTR pFirst = NULL; 1426*cdf0e10cSrcweir 1427*cdf0e10cSrcweir if ( NULL == pChar ) 1428*cdf0e10cSrcweir return ERROR_NO_MORE_ITEMS; 1429*cdf0e10cSrcweir 1430*cdf0e10cSrcweir while ( ' ' == (*pChar) || '\t' == (*pChar) ) 1431*cdf0e10cSrcweir pChar = CharNext( pChar ); 1432*cdf0e10cSrcweir 1433*cdf0e10cSrcweir if ( '\0' == (*pChar) ) 1434*cdf0e10cSrcweir return ERROR_NO_MORE_ITEMS; 1435*cdf0e10cSrcweir 1436*cdf0e10cSrcweir int nCount = 1; 1437*cdf0e10cSrcweir pFirst = pChar; 1438*cdf0e10cSrcweir 1439*cdf0e10cSrcweir while ( ! bFoundArgEnd ) 1440*cdf0e10cSrcweir { 1441*cdf0e10cSrcweir if ( '\0' == (*pChar) ) 1442*cdf0e10cSrcweir bFoundArgEnd = true; 1443*cdf0e10cSrcweir else if ( !bInQuotes && ' ' == (*pChar) ) 1444*cdf0e10cSrcweir bFoundArgEnd = true; 1445*cdf0e10cSrcweir else if ( !bInQuotes && '\t' == (*pChar) ) 1446*cdf0e10cSrcweir bFoundArgEnd = true; 1447*cdf0e10cSrcweir else 1448*cdf0e10cSrcweir { 1449*cdf0e10cSrcweir if ( '\"' == (*pChar) ) 1450*cdf0e10cSrcweir { 1451*cdf0e10cSrcweir bInQuotes = !bInQuotes; 1452*cdf0e10cSrcweir if ( bStripQuotes ) 1453*cdf0e10cSrcweir { 1454*cdf0e10cSrcweir if ( pChar == pFirst ) 1455*cdf0e10cSrcweir pFirst = CharNext( pFirst ); 1456*cdf0e10cSrcweir nCount -= 1; 1457*cdf0e10cSrcweir } 1458*cdf0e10cSrcweir } 1459*cdf0e10cSrcweir 1460*cdf0e10cSrcweir pChar = CharNext( pChar ); 1461*cdf0e10cSrcweir nCount += 1; 1462*cdf0e10cSrcweir } 1463*cdf0e10cSrcweir } 1464*cdf0e10cSrcweir 1465*cdf0e10cSrcweir if ( pArg ) 1466*cdf0e10cSrcweir { 1467*cdf0e10cSrcweir *pArg = new TCHAR[ nCount ]; 1468*cdf0e10cSrcweir StringCchCopyN ( *pArg, nCount, pFirst, nCount-1 ); 1469*cdf0e10cSrcweir } 1470*cdf0e10cSrcweir 1471*cdf0e10cSrcweir if ( pNext ) 1472*cdf0e10cSrcweir *pNext = CharNext( pChar ); 1473*cdf0e10cSrcweir 1474*cdf0e10cSrcweir return ERROR_SUCCESS; 1475*cdf0e10cSrcweir } 1476*cdf0e10cSrcweir 1477*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1478*cdf0e10cSrcweir boolean SetupAppX::GetCmdLineParameters( LPTSTR *pCmdLine ) 1479*cdf0e10cSrcweir { 1480*cdf0e10cSrcweir int nRet = ERROR_SUCCESS; 1481*cdf0e10cSrcweir LPTSTR pStart = NULL; 1482*cdf0e10cSrcweir LPTSTR pNext = NULL; 1483*cdf0e10cSrcweir 1484*cdf0e10cSrcweir if ( GetNextArgument( *pCmdLine, NULL, &pNext ) != ERROR_SUCCESS ) 1485*cdf0e10cSrcweir { 1486*cdf0e10cSrcweir SetError( ERROR_NO_MORE_ITEMS ); 1487*cdf0e10cSrcweir return false; 1488*cdf0e10cSrcweir } 1489*cdf0e10cSrcweir 1490*cdf0e10cSrcweir int nSize = lstrlen( *pCmdLine ) + 2; 1491*cdf0e10cSrcweir TCHAR *pNewCmdLine = new TCHAR[ nSize ]; 1492*cdf0e10cSrcweir pNewCmdLine[0] = '\0'; 1493*cdf0e10cSrcweir 1494*cdf0e10cSrcweir while ( GetNextArgument( pNext, &pStart, &pNext ) == ERROR_SUCCESS ) 1495*cdf0e10cSrcweir { 1496*cdf0e10cSrcweir boolean bDeleteStart = true; 1497*cdf0e10cSrcweir 1498*cdf0e10cSrcweir if ( (*pStart) == '/' || (*pStart) == '-' ) 1499*cdf0e10cSrcweir { 1500*cdf0e10cSrcweir LPTSTR pSub = CharNext( pStart ); 1501*cdf0e10cSrcweir if ( (*pSub) == 'l' || (*pSub) == 'L' ) 1502*cdf0e10cSrcweir { 1503*cdf0e10cSrcweir pSub = CharNext( pSub ); 1504*cdf0e10cSrcweir if ( (*pSub) == 'a' || (*pSub) == 'A' ) 1505*cdf0e10cSrcweir { // --- handle the lang parameter --- 1506*cdf0e10cSrcweir LPTSTR pLanguage = NULL; 1507*cdf0e10cSrcweir LPTSTR pLastChar; 1508*cdf0e10cSrcweir if ( GetNextArgument( pNext, &pLanguage, &pNext, true ) != ERROR_SUCCESS ) 1509*cdf0e10cSrcweir { 1510*cdf0e10cSrcweir StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); 1511*cdf0e10cSrcweir nRet = ERROR_INVALID_PARAMETER; 1512*cdf0e10cSrcweir break; 1513*cdf0e10cSrcweir } 1514*cdf0e10cSrcweir 1515*cdf0e10cSrcweir m_nLanguageID = _tcstol( pLanguage, &pLastChar, 10 ); 1516*cdf0e10cSrcweir delete [] pLanguage; 1517*cdf0e10cSrcweir } 1518*cdf0e10cSrcweir else 1519*cdf0e10cSrcweir { // --- handle the l(og) parameter --- 1520*cdf0e10cSrcweir boolean bAppend = false; 1521*cdf0e10cSrcweir LPTSTR pFileName = NULL; 1522*cdf0e10cSrcweir 1523*cdf0e10cSrcweir while ( *pSub ) 1524*cdf0e10cSrcweir { 1525*cdf0e10cSrcweir if ( *pSub == '+' ) 1526*cdf0e10cSrcweir { 1527*cdf0e10cSrcweir bAppend = true; 1528*cdf0e10cSrcweir break; 1529*cdf0e10cSrcweir } 1530*cdf0e10cSrcweir pSub = CharNext( pSub ); 1531*cdf0e10cSrcweir } 1532*cdf0e10cSrcweir 1533*cdf0e10cSrcweir if ( GetNextArgument( pNext, &pFileName, &pNext, true ) != ERROR_SUCCESS ) 1534*cdf0e10cSrcweir { 1535*cdf0e10cSrcweir StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); 1536*cdf0e10cSrcweir nRet = ERROR_INVALID_PARAMETER; 1537*cdf0e10cSrcweir break; 1538*cdf0e10cSrcweir } 1539*cdf0e10cSrcweir 1540*cdf0e10cSrcweir if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) ) 1541*cdf0e10cSrcweir { 1542*cdf0e10cSrcweir nRet = ERROR_OUTOFMEMORY; 1543*cdf0e10cSrcweir break; 1544*cdf0e10cSrcweir } 1545*cdf0e10cSrcweir // we need to append a '+' otherwise msiexec would overwrite our log file 1546*cdf0e10cSrcweir if ( !bAppend && FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( "+" ) ) ) ) 1547*cdf0e10cSrcweir { 1548*cdf0e10cSrcweir nRet = ERROR_OUTOFMEMORY; 1549*cdf0e10cSrcweir break; 1550*cdf0e10cSrcweir } 1551*cdf0e10cSrcweir if ( FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " \"" ) ) ) || 1552*cdf0e10cSrcweir FAILED( StringCchCat( pNewCmdLine, nSize, pFileName ) ) || 1553*cdf0e10cSrcweir FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( "\" " ) ) ) ) 1554*cdf0e10cSrcweir { 1555*cdf0e10cSrcweir nRet = ERROR_OUTOFMEMORY; 1556*cdf0e10cSrcweir break; 1557*cdf0e10cSrcweir } 1558*cdf0e10cSrcweir 1559*cdf0e10cSrcweir if ( bAppend ) 1560*cdf0e10cSrcweir m_pLogFile = _tfopen( pFileName, TEXT( "ab" ) ); 1561*cdf0e10cSrcweir else 1562*cdf0e10cSrcweir m_pLogFile = _tfopen( pFileName, TEXT( "wb" ) ); 1563*cdf0e10cSrcweir 1564*cdf0e10cSrcweir delete [] pFileName; 1565*cdf0e10cSrcweir } 1566*cdf0e10cSrcweir } 1567*cdf0e10cSrcweir else if ( (*pSub) == 'q' || (*pSub) == 'Q' ) 1568*cdf0e10cSrcweir { // --- Handle quiet file parameter --- 1569*cdf0e10cSrcweir pSub = CharNext( pSub ); 1570*cdf0e10cSrcweir if ( ! (*pSub) || (*pSub) == 'n' || (*pSub) == 'N' ) 1571*cdf0e10cSrcweir m_bQuiet = true; 1572*cdf0e10cSrcweir 1573*cdf0e10cSrcweir if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || 1574*cdf0e10cSrcweir FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) 1575*cdf0e10cSrcweir { 1576*cdf0e10cSrcweir nRet = ERROR_OUTOFMEMORY; 1577*cdf0e10cSrcweir break; 1578*cdf0e10cSrcweir } 1579*cdf0e10cSrcweir } 1580*cdf0e10cSrcweir else if ( _tcsnicmp( pSub, PARAM_RUNNING, _tcslen( PARAM_RUNNING ) ) == 0 ) 1581*cdf0e10cSrcweir { 1582*cdf0e10cSrcweir m_bIgnoreAlreadyRunning = true; 1583*cdf0e10cSrcweir } 1584*cdf0e10cSrcweir else if ( _tcsnicmp( pSub, CMDLN_REG_ALL_MSO_TYPES, _tcslen( CMDLN_REG_ALL_MSO_TYPES ) ) == 0 ) 1585*cdf0e10cSrcweir { 1586*cdf0e10cSrcweir m_bRegAllMsoTypes = true; 1587*cdf0e10cSrcweir } 1588*cdf0e10cSrcweir else if ( _tcsnicmp( pSub, CMDLN_REG_NO_MSO_TYPES, _tcslen( CMDLN_REG_NO_MSO_TYPES ) ) == 0 ) 1589*cdf0e10cSrcweir { 1590*cdf0e10cSrcweir m_bRegNoMsoTypes = true; 1591*cdf0e10cSrcweir } 1592*cdf0e10cSrcweir else if ( (*pSub) == 'i' || (*pSub) == 'I' || (*pSub) == 'f' || (*pSub) == 'F' || 1593*cdf0e10cSrcweir (*pSub) == 'p' || (*pSub) == 'P' || (*pSub) == 'x' || (*pSub) == 'X' || 1594*cdf0e10cSrcweir (*pSub) == 'y' || (*pSub) == 'Y' || (*pSub) == 'z' || (*pSub) == 'Z' ) 1595*cdf0e10cSrcweir { 1596*cdf0e10cSrcweir StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); 1597*cdf0e10cSrcweir nRet = ERROR_INVALID_PARAMETER; 1598*cdf0e10cSrcweir break; 1599*cdf0e10cSrcweir } 1600*cdf0e10cSrcweir else if ( (*pSub) == 'a' || (*pSub) == 'A' ) 1601*cdf0e10cSrcweir { // --- Handle Adminstrative Installation --- 1602*cdf0e10cSrcweir SetAdminInstall( true ); 1603*cdf0e10cSrcweir } 1604*cdf0e10cSrcweir else if ( (*pSub) == 'j' || (*pSub) == 'J' ) 1605*cdf0e10cSrcweir { // --- Handle Adminstrative Installation --- 1606*cdf0e10cSrcweir m_pAdvertise = pStart; 1607*cdf0e10cSrcweir m_bQuiet = true; 1608*cdf0e10cSrcweir bDeleteStart = false; 1609*cdf0e10cSrcweir } 1610*cdf0e10cSrcweir else if ( (*pSub) == '?' || (*pSub) == 'h' || (*pSub) == 'H' ) 1611*cdf0e10cSrcweir { // --- Handle Show Usage --- 1612*cdf0e10cSrcweir nRet = ERROR_SHOW_USAGE; 1613*cdf0e10cSrcweir break; 1614*cdf0e10cSrcweir } 1615*cdf0e10cSrcweir else 1616*cdf0e10cSrcweir { 1617*cdf0e10cSrcweir if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || 1618*cdf0e10cSrcweir FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) 1619*cdf0e10cSrcweir { 1620*cdf0e10cSrcweir nRet = ERROR_OUTOFMEMORY; 1621*cdf0e10cSrcweir break; 1622*cdf0e10cSrcweir } 1623*cdf0e10cSrcweir } 1624*cdf0e10cSrcweir } 1625*cdf0e10cSrcweir else 1626*cdf0e10cSrcweir { 1627*cdf0e10cSrcweir if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || 1628*cdf0e10cSrcweir FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) 1629*cdf0e10cSrcweir { 1630*cdf0e10cSrcweir nRet = ERROR_OUTOFMEMORY; 1631*cdf0e10cSrcweir break; 1632*cdf0e10cSrcweir } 1633*cdf0e10cSrcweir } 1634*cdf0e10cSrcweir 1635*cdf0e10cSrcweir if ( bDeleteStart ) delete [] pStart; 1636*cdf0e10cSrcweir pStart = NULL; 1637*cdf0e10cSrcweir } 1638*cdf0e10cSrcweir 1639*cdf0e10cSrcweir if ( pStart ) delete [] pStart; 1640*cdf0e10cSrcweir 1641*cdf0e10cSrcweir *pCmdLine = pNewCmdLine; 1642*cdf0e10cSrcweir 1643*cdf0e10cSrcweir if ( nRet != ERROR_SUCCESS ) 1644*cdf0e10cSrcweir { 1645*cdf0e10cSrcweir SetError( nRet ); 1646*cdf0e10cSrcweir return false; 1647*cdf0e10cSrcweir } 1648*cdf0e10cSrcweir else 1649*cdf0e10cSrcweir return true;; 1650*cdf0e10cSrcweir } 1651*cdf0e10cSrcweir 1652*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1653*cdf0e10cSrcweir boolean SetupAppX::IsAdmin() 1654*cdf0e10cSrcweir { 1655*cdf0e10cSrcweir if ( IsWin9x() ) 1656*cdf0e10cSrcweir return true; 1657*cdf0e10cSrcweir 1658*cdf0e10cSrcweir PSID aPsidAdmin; 1659*cdf0e10cSrcweir SID_IDENTIFIER_AUTHORITY aAuthority = SECURITY_NT_AUTHORITY; 1660*cdf0e10cSrcweir 1661*cdf0e10cSrcweir if ( !AllocateAndInitializeSid( &aAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, 1662*cdf0e10cSrcweir DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, 1663*cdf0e10cSrcweir &aPsidAdmin ) ) 1664*cdf0e10cSrcweir return false; 1665*cdf0e10cSrcweir 1666*cdf0e10cSrcweir BOOL bIsAdmin = FALSE; 1667*cdf0e10cSrcweir 1668*cdf0e10cSrcweir if ( GetOSVersion() >= 5 ) 1669*cdf0e10cSrcweir { 1670*cdf0e10cSrcweir HMODULE hAdvapi32 = LoadLibrary( ADVAPI32_DLL ); 1671*cdf0e10cSrcweir 1672*cdf0e10cSrcweir if ( !hAdvapi32 ) 1673*cdf0e10cSrcweir bIsAdmin = FALSE; 1674*cdf0e10cSrcweir else 1675*cdf0e10cSrcweir { 1676*cdf0e10cSrcweir PFnCheckTokenMembership pfnCheckTokenMembership = (PFnCheckTokenMembership) GetProcAddress( hAdvapi32, ADVAPI32API_CheckTokenMembership); 1677*cdf0e10cSrcweir if ( !pfnCheckTokenMembership || !pfnCheckTokenMembership( NULL, aPsidAdmin, &bIsAdmin ) ) 1678*cdf0e10cSrcweir bIsAdmin = FALSE; 1679*cdf0e10cSrcweir } 1680*cdf0e10cSrcweir FreeLibrary( hAdvapi32 ); 1681*cdf0e10cSrcweir } 1682*cdf0e10cSrcweir else 1683*cdf0e10cSrcweir { 1684*cdf0e10cSrcweir // NT4, check groups of user 1685*cdf0e10cSrcweir HANDLE hAccessToken = 0; 1686*cdf0e10cSrcweir UCHAR *szInfoBuffer = new UCHAR[ 1024 ]; // may need to resize if TokenInfo too big 1687*cdf0e10cSrcweir DWORD dwInfoBufferSize = 1024; 1688*cdf0e10cSrcweir DWORD dwRetInfoBufferSize = 0; 1689*cdf0e10cSrcweir UINT i=0; 1690*cdf0e10cSrcweir 1691*cdf0e10cSrcweir if ( WIN::OpenProcessToken( WIN::GetCurrentProcess(), TOKEN_READ, &hAccessToken ) ) 1692*cdf0e10cSrcweir { 1693*cdf0e10cSrcweir bool bSuccess = false; 1694*cdf0e10cSrcweir bSuccess = WIN::GetTokenInformation( hAccessToken, TokenGroups, 1695*cdf0e10cSrcweir szInfoBuffer, dwInfoBufferSize, 1696*cdf0e10cSrcweir &dwRetInfoBufferSize ) == TRUE; 1697*cdf0e10cSrcweir 1698*cdf0e10cSrcweir if( dwRetInfoBufferSize > dwInfoBufferSize ) 1699*cdf0e10cSrcweir { 1700*cdf0e10cSrcweir delete [] szInfoBuffer; 1701*cdf0e10cSrcweir szInfoBuffer = new UCHAR[ dwRetInfoBufferSize ]; 1702*cdf0e10cSrcweir dwInfoBufferSize = dwRetInfoBufferSize; 1703*cdf0e10cSrcweir bSuccess = WIN::GetTokenInformation( hAccessToken, TokenGroups, 1704*cdf0e10cSrcweir szInfoBuffer, dwInfoBufferSize, 1705*cdf0e10cSrcweir &dwRetInfoBufferSize ) == TRUE; 1706*cdf0e10cSrcweir } 1707*cdf0e10cSrcweir 1708*cdf0e10cSrcweir WIN::CloseHandle( hAccessToken ); 1709*cdf0e10cSrcweir 1710*cdf0e10cSrcweir if ( bSuccess ) 1711*cdf0e10cSrcweir { 1712*cdf0e10cSrcweir PTOKEN_GROUPS pGroups = (PTOKEN_GROUPS)(UCHAR*) szInfoBuffer; 1713*cdf0e10cSrcweir for( i=0; i<pGroups->GroupCount; i++ ) 1714*cdf0e10cSrcweir { 1715*cdf0e10cSrcweir if( WIN::EqualSid( aPsidAdmin, pGroups->Groups[i].Sid ) ) 1716*cdf0e10cSrcweir { 1717*cdf0e10cSrcweir bIsAdmin = TRUE; 1718*cdf0e10cSrcweir break; 1719*cdf0e10cSrcweir } 1720*cdf0e10cSrcweir } 1721*cdf0e10cSrcweir } 1722*cdf0e10cSrcweir 1723*cdf0e10cSrcweir delete [] szInfoBuffer; 1724*cdf0e10cSrcweir } 1725*cdf0e10cSrcweir } 1726*cdf0e10cSrcweir 1727*cdf0e10cSrcweir WIN::FreeSid( aPsidAdmin ); 1728*cdf0e10cSrcweir 1729*cdf0e10cSrcweir return bIsAdmin ? true : false; 1730*cdf0e10cSrcweir } 1731*cdf0e10cSrcweir 1732*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1733*cdf0e10cSrcweir LPTSTR SetupAppX::CopyIniFile( LPCTSTR pIniFile ) 1734*cdf0e10cSrcweir { 1735*cdf0e10cSrcweir m_pTmpName = _ttempnam( TEXT( "C:\\" ), TEXT( "Setup" ) ); 1736*cdf0e10cSrcweir 1737*cdf0e10cSrcweir if ( !m_pTmpName ) 1738*cdf0e10cSrcweir { 1739*cdf0e10cSrcweir Log( TEXT( "ERROR: Could not create temp file\n" ) ); 1740*cdf0e10cSrcweir return NULL; 1741*cdf0e10cSrcweir } 1742*cdf0e10cSrcweir 1743*cdf0e10cSrcweir FILE *pOut = _tfopen( m_pTmpName, TEXT( "wb" ) ); 1744*cdf0e10cSrcweir FILE *pIn = _tfopen( pIniFile, TEXT( "rb" ) ); 1745*cdf0e10cSrcweir 1746*cdf0e10cSrcweir if ( pOut && pIn ) 1747*cdf0e10cSrcweir { 1748*cdf0e10cSrcweir size_t nRead, nWritten; 1749*cdf0e10cSrcweir BYTE pBuf[1024]; 1750*cdf0e10cSrcweir 1751*cdf0e10cSrcweir nRead = fread( pBuf, sizeof( BYTE ), 1024, pIn ); 1752*cdf0e10cSrcweir while ( nRead && !ferror( pIn ) ) 1753*cdf0e10cSrcweir { 1754*cdf0e10cSrcweir nWritten = fwrite( pBuf, sizeof( BYTE ), nRead, pOut ); 1755*cdf0e10cSrcweir if ( nWritten != nRead ) 1756*cdf0e10cSrcweir { 1757*cdf0e10cSrcweir Log( TEXT( "ERROR: Could not write all bytes to temp file\n" ) ); 1758*cdf0e10cSrcweir break; 1759*cdf0e10cSrcweir } 1760*cdf0e10cSrcweir nRead = fread( pBuf, sizeof( BYTE ), 1024, pIn ); 1761*cdf0e10cSrcweir } 1762*cdf0e10cSrcweir } 1763*cdf0e10cSrcweir 1764*cdf0e10cSrcweir if ( pOut ) fclose( pOut ); 1765*cdf0e10cSrcweir if ( pIn ) fclose( pIn ); 1766*cdf0e10cSrcweir 1767*cdf0e10cSrcweir return m_pTmpName; 1768*cdf0e10cSrcweir } 1769*cdf0e10cSrcweir 1770*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1771*cdf0e10cSrcweir void SetupAppX::ConvertNewline( LPTSTR pText ) const 1772*cdf0e10cSrcweir { 1773*cdf0e10cSrcweir int i=0; 1774*cdf0e10cSrcweir 1775*cdf0e10cSrcweir while ( pText[i] != 0 ) 1776*cdf0e10cSrcweir { 1777*cdf0e10cSrcweir if ( ( pText[i] == '\\' ) && ( pText[i+1] == 'n' ) ) 1778*cdf0e10cSrcweir { 1779*cdf0e10cSrcweir pText[i] = 0x0d; 1780*cdf0e10cSrcweir pText[i+1] = 0x0a; 1781*cdf0e10cSrcweir i+=2; 1782*cdf0e10cSrcweir } 1783*cdf0e10cSrcweir else 1784*cdf0e10cSrcweir i+=1; 1785*cdf0e10cSrcweir } 1786*cdf0e10cSrcweir } 1787*cdf0e10cSrcweir 1788*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1789*cdf0e10cSrcweir LPTSTR SetupAppX::SetProdToAppTitle( LPCTSTR pProdName ) 1790*cdf0e10cSrcweir { 1791*cdf0e10cSrcweir if ( !pProdName ) return m_pAppTitle; 1792*cdf0e10cSrcweir 1793*cdf0e10cSrcweir LPTSTR pAppProdTitle = new TCHAR[ MAX_STR_CAPTION ]; 1794*cdf0e10cSrcweir pAppProdTitle[0] = '\0'; 1795*cdf0e10cSrcweir 1796*cdf0e10cSrcweir WIN::LoadString( m_hInst, IDS_APP_PROD_TITLE, pAppProdTitle, MAX_STR_CAPTION ); 1797*cdf0e10cSrcweir 1798*cdf0e10cSrcweir int nAppLen = lstrlen( pAppProdTitle ); 1799*cdf0e10cSrcweir int nProdLen = lstrlen( pProdName ); 1800*cdf0e10cSrcweir 1801*cdf0e10cSrcweir if ( ( nAppLen == 0 ) || ( nProdLen == 0 ) ) 1802*cdf0e10cSrcweir { 1803*cdf0e10cSrcweir delete [] pAppProdTitle; 1804*cdf0e10cSrcweir return m_pAppTitle; 1805*cdf0e10cSrcweir } 1806*cdf0e10cSrcweir 1807*cdf0e10cSrcweir int nLen = nAppLen + nProdLen + 3; 1808*cdf0e10cSrcweir 1809*cdf0e10cSrcweir if ( nLen > STRSAFE_MAX_CCH ) return m_pAppTitle; 1810*cdf0e10cSrcweir 1811*cdf0e10cSrcweir LPTSTR pIndex = _tcsstr( pAppProdTitle, PRODUCT_NAME_VAR ); 1812*cdf0e10cSrcweir 1813*cdf0e10cSrcweir if ( pIndex ) 1814*cdf0e10cSrcweir { 1815*cdf0e10cSrcweir int nOffset = pIndex - pAppProdTitle; 1816*cdf0e10cSrcweir int nVarLen = lstrlen( PRODUCT_NAME_VAR ); 1817*cdf0e10cSrcweir 1818*cdf0e10cSrcweir LPTSTR pNewTitle = new TCHAR[ nLen ]; 1819*cdf0e10cSrcweir pNewTitle[0] = '\0'; 1820*cdf0e10cSrcweir 1821*cdf0e10cSrcweir if ( nOffset > 0 ) 1822*cdf0e10cSrcweir { 1823*cdf0e10cSrcweir StringCchCopyN( pNewTitle, nLen, pAppProdTitle, nOffset ); 1824*cdf0e10cSrcweir } 1825*cdf0e10cSrcweir 1826*cdf0e10cSrcweir StringCchCat( pNewTitle, nLen, pProdName ); 1827*cdf0e10cSrcweir 1828*cdf0e10cSrcweir if ( nOffset + nVarLen < nAppLen ) 1829*cdf0e10cSrcweir { 1830*cdf0e10cSrcweir StringCchCat( pNewTitle, nLen, pIndex + nVarLen ); 1831*cdf0e10cSrcweir } 1832*cdf0e10cSrcweir 1833*cdf0e10cSrcweir delete [] m_pAppTitle; 1834*cdf0e10cSrcweir m_pAppTitle = pNewTitle; 1835*cdf0e10cSrcweir } 1836*cdf0e10cSrcweir 1837*cdf0e10cSrcweir delete [] pAppProdTitle; 1838*cdf0e10cSrcweir 1839*cdf0e10cSrcweir return m_pAppTitle; 1840*cdf0e10cSrcweir } 1841*cdf0e10cSrcweir 1842*cdf0e10cSrcweir 1843*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1844*cdf0e10cSrcweir boolean SetupAppX::IsPatchInstalled( TCHAR* pBaseDir, TCHAR* pFileName ) 1845*cdf0e10cSrcweir { 1846*cdf0e10cSrcweir if ( !m_bSupportsPatch ) 1847*cdf0e10cSrcweir return false; 1848*cdf0e10cSrcweir 1849*cdf0e10cSrcweir PMSIHANDLE hSummaryInfo; 1850*cdf0e10cSrcweir int nLen = lstrlen( pBaseDir ) + lstrlen( pFileName ) + 1; 1851*cdf0e10cSrcweir TCHAR *szDatabasePath = new TCHAR [ nLen ]; 1852*cdf0e10cSrcweir TCHAR sBuf[80]; 1853*cdf0e10cSrcweir 1854*cdf0e10cSrcweir StringCchCopy( szDatabasePath, nLen, pBaseDir ); 1855*cdf0e10cSrcweir StringCchCat( szDatabasePath, nLen, pFileName ); 1856*cdf0e10cSrcweir 1857*cdf0e10cSrcweir UINT nRet = MsiGetSummaryInformation( NULL, szDatabasePath, 0, &hSummaryInfo ); 1858*cdf0e10cSrcweir 1859*cdf0e10cSrcweir if ( nRet != ERROR_SUCCESS ) 1860*cdf0e10cSrcweir { 1861*cdf0e10cSrcweir StringCchPrintf( sBuf, 80, TEXT("ERROR: IsPatchInstalled: MsiGetSummaryInformation returned %u.\r\n"), nRet ); 1862*cdf0e10cSrcweir Log( sBuf ); 1863*cdf0e10cSrcweir return false; 1864*cdf0e10cSrcweir } 1865*cdf0e10cSrcweir 1866*cdf0e10cSrcweir UINT uiDataType; 1867*cdf0e10cSrcweir LPTSTR szPatchID = new TCHAR[ 64 ]; 1868*cdf0e10cSrcweir DWORD cchValueBuf = 64; 1869*cdf0e10cSrcweir nRet = MsiSummaryInfoGetProperty( hSummaryInfo, PID_REVNUMBER, &uiDataType, NULL, NULL, szPatchID, &cchValueBuf ); 1870*cdf0e10cSrcweir 1871*cdf0e10cSrcweir if ( nRet != ERROR_SUCCESS ) 1872*cdf0e10cSrcweir { 1873*cdf0e10cSrcweir StringCchPrintf( sBuf, 80, TEXT("ERROR: IsPatchInstalled: MsiSummaryInfoGetProperty returned %u.\r\n"), nRet ); 1874*cdf0e10cSrcweir Log( sBuf ); 1875*cdf0e10cSrcweir return false; 1876*cdf0e10cSrcweir } 1877*cdf0e10cSrcweir 1878*cdf0e10cSrcweir nRet = MsiGetPatchInfo( szPatchID, INSTALLPROPERTY_LOCALPACKAGE, NULL, NULL ); 1879*cdf0e10cSrcweir 1880*cdf0e10cSrcweir StringCchPrintf( sBuf, 80, TEXT(" GetPatchInfo for (%s) returned (%u)\r\n"), szPatchID, nRet ); 1881*cdf0e10cSrcweir Log( sBuf ); 1882*cdf0e10cSrcweir 1883*cdf0e10cSrcweir delete []szPatchID; 1884*cdf0e10cSrcweir 1885*cdf0e10cSrcweir if ( nRet == ERROR_BAD_CONFIGURATION ) 1886*cdf0e10cSrcweir return false; 1887*cdf0e10cSrcweir else if ( nRet == ERROR_INVALID_PARAMETER ) 1888*cdf0e10cSrcweir return false; 1889*cdf0e10cSrcweir else if ( nRet == ERROR_MORE_DATA ) 1890*cdf0e10cSrcweir return true; 1891*cdf0e10cSrcweir else if ( nRet == ERROR_SUCCESS ) 1892*cdf0e10cSrcweir return true; 1893*cdf0e10cSrcweir else if ( nRet == ERROR_UNKNOWN_PRODUCT ) 1894*cdf0e10cSrcweir return false; 1895*cdf0e10cSrcweir else if ( nRet == ERROR_UNKNOWN_PROPERTY ) 1896*cdf0e10cSrcweir return false; 1897*cdf0e10cSrcweir else return false; 1898*cdf0e10cSrcweir 1899*cdf0e10cSrcweir return false; 1900*cdf0e10cSrcweir } 1901*cdf0e10cSrcweir 1902*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1903*cdf0e10cSrcweir boolean SetupAppX::InstallRuntimes( TCHAR *sProductCode, TCHAR *sRuntimePath ) 1904*cdf0e10cSrcweir { 1905*cdf0e10cSrcweir INSTALLSTATE nRet = MsiQueryProductState( sProductCode ); 1906*cdf0e10cSrcweir OutputDebugStringFormat( TEXT( "MsiQueryProductState returned <%d>\r\n" ), nRet ); 1907*cdf0e10cSrcweir if ( nRet == INSTALLSTATE_DEFAULT ) 1908*cdf0e10cSrcweir return true; 1909*cdf0e10cSrcweir 1910*cdf0e10cSrcweir Log( TEXT( " Will install runtime <%s>\r\n" ), sRuntimePath ); 1911*cdf0e10cSrcweir OutputDebugStringFormat( TEXT( " Will install runtime <%s>\r\n" ), sRuntimePath ); 1912*cdf0e10cSrcweir 1913*cdf0e10cSrcweir STARTUPINFO aSUI; 1914*cdf0e10cSrcweir PROCESS_INFORMATION aPI; 1915*cdf0e10cSrcweir 1916*cdf0e10cSrcweir ZeroMemory( (void*)&aPI, sizeof( PROCESS_INFORMATION ) ); 1917*cdf0e10cSrcweir ZeroMemory( (void*)&aSUI, sizeof( STARTUPINFO ) ); 1918*cdf0e10cSrcweir 1919*cdf0e10cSrcweir aSUI.cb = sizeof(STARTUPINFO); 1920*cdf0e10cSrcweir aSUI.dwFlags = STARTF_USESHOWWINDOW; 1921*cdf0e10cSrcweir aSUI.wShowWindow = SW_SHOW; 1922*cdf0e10cSrcweir 1923*cdf0e10cSrcweir DWORD nCmdLineLength = lstrlen( sRuntimePath ) + lstrlen( PARAM_SILENTINSTALL ) + 2; 1924*cdf0e10cSrcweir TCHAR *sCmdLine = new TCHAR[ nCmdLineLength ]; 1925*cdf0e10cSrcweir 1926*cdf0e10cSrcweir if ( FAILED( StringCchCopy( sCmdLine, nCmdLineLength, sRuntimePath ) ) || 1927*cdf0e10cSrcweir FAILED( StringCchCat( sCmdLine, nCmdLineLength, PARAM_SILENTINSTALL ) ) ) 1928*cdf0e10cSrcweir { 1929*cdf0e10cSrcweir delete [] sCmdLine; 1930*cdf0e10cSrcweir SetError( ERROR_INSTALL_FAILURE ); 1931*cdf0e10cSrcweir return false; 1932*cdf0e10cSrcweir } 1933*cdf0e10cSrcweir 1934*cdf0e10cSrcweir if ( !WIN::CreateProcess( NULL, sCmdLine, NULL, NULL, FALSE, 1935*cdf0e10cSrcweir CREATE_DEFAULT_ERROR_MODE, NULL, NULL, 1936*cdf0e10cSrcweir &aSUI, &aPI ) ) 1937*cdf0e10cSrcweir { 1938*cdf0e10cSrcweir Log( TEXT( "ERROR: Could not create process %s.\r\n" ), sCmdLine ); 1939*cdf0e10cSrcweir SetError( WIN::GetLastError() ); 1940*cdf0e10cSrcweir delete [] sCmdLine; 1941*cdf0e10cSrcweir return false; 1942*cdf0e10cSrcweir } 1943*cdf0e10cSrcweir 1944*cdf0e10cSrcweir DWORD nResult = WaitForProcess( aPI.hProcess ); 1945*cdf0e10cSrcweir bool bRet = true; 1946*cdf0e10cSrcweir 1947*cdf0e10cSrcweir if( ERROR_SUCCESS != nResult ) 1948*cdf0e10cSrcweir { 1949*cdf0e10cSrcweir Log( TEXT( "ERROR: While waiting for %s.\r\n" ), sCmdLine ); 1950*cdf0e10cSrcweir SetError( nResult ); 1951*cdf0e10cSrcweir bRet = false; 1952*cdf0e10cSrcweir } 1953*cdf0e10cSrcweir else 1954*cdf0e10cSrcweir { 1955*cdf0e10cSrcweir GetExitCodeProcess( aPI.hProcess, &nResult ); 1956*cdf0e10cSrcweir SetError( nResult ); 1957*cdf0e10cSrcweir 1958*cdf0e10cSrcweir if ( nResult != ERROR_SUCCESS ) 1959*cdf0e10cSrcweir { 1960*cdf0e10cSrcweir TCHAR sBuf[80]; 1961*cdf0e10cSrcweir StringCchPrintf( sBuf, 80, TEXT("Warning: install runtime returned %u.\r\n"), nResult ); 1962*cdf0e10cSrcweir Log( sBuf ); 1963*cdf0e10cSrcweir } 1964*cdf0e10cSrcweir else 1965*cdf0e10cSrcweir Log( TEXT( " Installation of runtime completed successfully.\r\n" ) ); 1966*cdf0e10cSrcweir } 1967*cdf0e10cSrcweir 1968*cdf0e10cSrcweir CloseHandle( aPI.hProcess ); 1969*cdf0e10cSrcweir 1970*cdf0e10cSrcweir delete [] sCmdLine; 1971*cdf0e10cSrcweir 1972*cdf0e10cSrcweir return bRet; 1973*cdf0e10cSrcweir } 1974*cdf0e10cSrcweir 1975*cdf0e10cSrcweir //-------------------------------------------------------------------------- 1976*cdf0e10cSrcweir boolean SetupAppX::InstallRuntimes() 1977*cdf0e10cSrcweir { 1978*cdf0e10cSrcweir TCHAR *sRuntimePath = 0; 1979*cdf0e10cSrcweir SYSTEM_INFO siSysInfo; 1980*cdf0e10cSrcweir 1981*cdf0e10cSrcweir HMODULE hKernel32 = ::LoadLibrary(_T("Kernel32.dll")); 1982*cdf0e10cSrcweir if ( hKernel32 != NULL ) 1983*cdf0e10cSrcweir { 1984*cdf0e10cSrcweir typedef void (CALLBACK* pfnGetNativeSystemInfo_t)(LPSYSTEM_INFO); 1985*cdf0e10cSrcweir pfnGetNativeSystemInfo_t pfnGetNativeSystemInfo; 1986*cdf0e10cSrcweir pfnGetNativeSystemInfo = (pfnGetNativeSystemInfo_t)::GetProcAddress(hKernel32, "GetNativeSystemInfo"); 1987*cdf0e10cSrcweir if ( pfnGetNativeSystemInfo != NULL ) 1988*cdf0e10cSrcweir { 1989*cdf0e10cSrcweir pfnGetNativeSystemInfo(&siSysInfo); 1990*cdf0e10cSrcweir } 1991*cdf0e10cSrcweir else 1992*cdf0e10cSrcweir { 1993*cdf0e10cSrcweir // GetNativeSystemInfo does not exist. Maybe the code is running under Windows 2000. 1994*cdf0e10cSrcweir // Use GetSystemInfo instead. 1995*cdf0e10cSrcweir GetSystemInfo(&siSysInfo); 1996*cdf0e10cSrcweir } 1997*cdf0e10cSrcweir FreeLibrary(hKernel32); 1998*cdf0e10cSrcweir } 1999*cdf0e10cSrcweir else 2000*cdf0e10cSrcweir { 2001*cdf0e10cSrcweir // Failed to check Kernel32.dll. There may be something wrong. 2002*cdf0e10cSrcweir // Use GetSystemInfo instead anyway. 2003*cdf0e10cSrcweir GetSystemInfo(&siSysInfo); 2004*cdf0e10cSrcweir } 2005*cdf0e10cSrcweir 2006*cdf0e10cSrcweir OutputDebugStringFormat( TEXT( "found architecture<%d>\r\n" ), siSysInfo.wProcessorArchitecture ); 2007*cdf0e10cSrcweir 2008*cdf0e10cSrcweir if ( siSysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ) 2009*cdf0e10cSrcweir { 2010*cdf0e10cSrcweir if ( GetPathToFile( RUNTIME_X64_NAME, &sRuntimePath ) ) 2011*cdf0e10cSrcweir InstallRuntimes( PRODUCTCODE_X64, sRuntimePath ); 2012*cdf0e10cSrcweir else 2013*cdf0e10cSrcweir Log( TEXT( "ERROR: no installer for x64 runtime libraries found!" ) ); 2014*cdf0e10cSrcweir 2015*cdf0e10cSrcweir if ( sRuntimePath ) 2016*cdf0e10cSrcweir { 2017*cdf0e10cSrcweir delete [] sRuntimePath; 2018*cdf0e10cSrcweir sRuntimePath = 0; 2019*cdf0e10cSrcweir } 2020*cdf0e10cSrcweir } 2021*cdf0e10cSrcweir 2022*cdf0e10cSrcweir if ( GetPathToFile( RUNTIME_X86_NAME, &sRuntimePath ) ) 2023*cdf0e10cSrcweir InstallRuntimes( PRODUCTCODE_X86, sRuntimePath ); 2024*cdf0e10cSrcweir else 2025*cdf0e10cSrcweir Log( TEXT( "ERROR: no installer for x86 runtime libraries found!" ) ); 2026*cdf0e10cSrcweir 2027*cdf0e10cSrcweir if ( sRuntimePath ) 2028*cdf0e10cSrcweir delete [] sRuntimePath; 2029*cdf0e10cSrcweir 2030*cdf0e10cSrcweir return true; 2031*cdf0e10cSrcweir } 2032*cdf0e10cSrcweir 2033*cdf0e10cSrcweir //-------------------------------------------------------------------------- 2034*cdf0e10cSrcweir //-------------------------------------------------------------------------- 2035*cdf0e10cSrcweir LanguageDataX::LanguageDataX( LPTSTR pData ) 2036*cdf0e10cSrcweir { 2037*cdf0e10cSrcweir m_nLanguageID = 0; 2038*cdf0e10cSrcweir m_pTransform = NULL; 2039*cdf0e10cSrcweir 2040*cdf0e10cSrcweir LPTSTR pLastChar; 2041*cdf0e10cSrcweir 2042*cdf0e10cSrcweir m_nLanguageID = _tcstol( pData, &pLastChar, 10 ); 2043*cdf0e10cSrcweir 2044*cdf0e10cSrcweir if ( *pLastChar == ',' ) 2045*cdf0e10cSrcweir { 2046*cdf0e10cSrcweir pLastChar += 1; 2047*cdf0e10cSrcweir int nLen = lstrlen( pLastChar ) + 1; 2048*cdf0e10cSrcweir m_pTransform = new TCHAR [ nLen ]; 2049*cdf0e10cSrcweir StringCchCopy( m_pTransform, nLen, pLastChar ); 2050*cdf0e10cSrcweir } 2051*cdf0e10cSrcweir } 2052*cdf0e10cSrcweir 2053*cdf0e10cSrcweir //-------------------------------------------------------------------------- 2054*cdf0e10cSrcweir LanguageDataX::~LanguageDataX() 2055*cdf0e10cSrcweir { 2056*cdf0e10cSrcweir if ( m_pTransform ) delete [] m_pTransform; 2057*cdf0e10cSrcweir } 2058*cdf0e10cSrcweir 2059*cdf0e10cSrcweir //-------------------------------------------------------------------------- 2060*cdf0e10cSrcweir //-------------------------------------------------------------------------- 2061*cdf0e10cSrcweir SetupApp* Create_SetupAppX() 2062*cdf0e10cSrcweir { 2063*cdf0e10cSrcweir return new SetupAppX; 2064*cdf0e10cSrcweir } 2065*cdf0e10cSrcweir 2066*cdf0e10cSrcweir //-------------------------------------------------------------------------- 2067