Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / setup_native / source / win32 / customactions / rebase / rebase.cxx
blob641e397fb9d224344b19dbf8502f1124dcbf970e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 #undef UNICODE
3 #undef _UNICODE
5 #pragma once
7 #ifdef _MSC_VER
8 #pragma warning(push, 1) /* disable warnings within system headers */
9 #endif
10 #define WIN32_LEAN_AND_MEAN
11 #include <windows.h>
12 #include <msiquery.h>
13 #include <imagehlp.h>
14 #include <tchar.h>
15 #define STRSAFE_NO_DEPRECATE
16 #include <strsafe.h>
17 #ifdef _MSC_VER
18 #pragma warning(pop)
19 #endif
21 #include <malloc.h>
22 #include <time.h>
23 #include <string>
24 #include <boost/unordered_map.hpp>
26 const DWORD PE_Signature = 0x00004550;
27 typedef std::pair< std::string, bool > StringPair;
28 typedef boost::unordered_map< std::string, bool > ExcludeLibsMap;
30 #ifdef DEBUG
31 static void OutputDebugStringFormat( LPCSTR pFormat, ... )
33 CHAR buffer[1024];
34 va_list args;
36 va_start( args, pFormat );
37 StringCchVPrintfA( buffer, sizeof(buffer), pFormat, args );
38 OutputDebugStringA( buffer );
40 #else
41 static void OutputDebugStringFormat( LPCSTR, ... )
44 #endif
46 static bool IsValidHandle( HANDLE handle )
48 return NULL != handle && INVALID_HANDLE_VALUE != handle;
51 static std::string GetMsiProperty(MSIHANDLE handle, const std::string& sProperty)
53 std::string result;
54 TCHAR szDummy[1] = TEXT("");
55 DWORD nChars = 0;
57 if (MsiGetProperty(handle, sProperty.c_str(), szDummy, &nChars) == ERROR_MORE_DATA)
59 DWORD nBytes = ++nChars * sizeof(TCHAR);
60 LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes));
61 ZeroMemory( buffer, nBytes );
62 MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars);
63 result = buffer;
65 return result;
68 static BOOL rebaseImage( const std::string& filePath, LPVOID address )
70 ULONG ulOldImageSize;
71 ULONG_PTR lpOldImageBase;
72 ULONG ulNewImageSize;
73 ULONG_PTR lpNewImageBase = reinterpret_cast<ULONG_PTR>(address);
75 BOOL bResult = ReBaseImage(
76 (PSTR)filePath.c_str(),
77 (PSTR)"",
78 TRUE,
79 FALSE,
80 FALSE,
82 &ulOldImageSize,
83 &lpOldImageBase,
84 &ulNewImageSize,
85 &lpNewImageBase,
86 (ULONG)time(NULL) );
88 return bResult;
91 static BOOL rebaseImage( MSIHANDLE /*handle*/, const std::string& sFilePath, LPVOID address )
93 std::string mystr;
94 mystr = "Full file: " + sFilePath;
96 BOOL bResult = rebaseImage( sFilePath, address );
98 if ( !bResult )
100 OutputDebugStringFormat( "Rebasing library %s failed", mystr.c_str() );
103 return bResult;
106 static BOOL rebaseImagesInFolder( MSIHANDLE handle, const std::string& sPath, LPVOID address, ExcludeLibsMap& rExcludeMap )
108 std::string sDir = sPath;
109 std::string sPattern = sPath + TEXT("*.dll");
110 WIN32_FIND_DATA aFindFileData;
112 HANDLE hFind = FindFirstFile( sPattern.c_str(), &aFindFileData );
113 if ( IsValidHandle(hFind) )
115 BOOL fSuccess = false;
119 std::string sFileName = aFindFileData.cFileName;
120 if ( rExcludeMap.find( sFileName ) == rExcludeMap.end() )
122 OutputDebugStringFormat( "Rebase library: %s", sFileName.c_str() );
123 std::string sLibFile = sDir + sFileName;
124 rebaseImage( handle, sLibFile, address );
126 else
128 OutputDebugStringFormat( "Exclude library %s from rebase", sFileName.c_str() );
131 fSuccess = FindNextFile( hFind, &aFindFileData );
133 while ( fSuccess );
135 FindClose( hFind );
138 return ERROR_SUCCESS;
141 static BOOL rebaseImages( MSIHANDLE handle, LPVOID pAddress, ExcludeLibsMap& rMap )
143 std::string sInstallPath = GetMsiProperty(handle, TEXT("INSTALLLOCATION"));
145 std::string sBasisDir = sInstallPath + TEXT("Basis\\program\\");
146 std::string sOfficeDir = sInstallPath + TEXT("program\\");
147 std::string sUreDir = sInstallPath + TEXT("URE\\bin\\");
149 BOOL bResult = rebaseImagesInFolder( handle, sBasisDir, pAddress, rMap );
150 bResult &= rebaseImagesInFolder( handle, sOfficeDir, pAddress, rMap );
151 bResult &= rebaseImagesInFolder( handle, sUreDir, pAddress, rMap );
153 return bResult;
156 static BOOL IsServerSystem( MSIHANDLE /*handle*/ )
158 OSVERSIONINFOEX osVersionInfoEx;
159 osVersionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
160 GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(&osVersionInfoEx));
162 if ( osVersionInfoEx.wProductType != VER_NT_WORKSTATION )
164 OutputDebugStringFormat( "Server system detected. No rebase necessary!" );
165 return TRUE;
167 else
169 OutputDebugStringFormat( "Client system detected. Rebase necessary!" );
170 return FALSE;
174 static void InitExcludeFromRebaseList( MSIHANDLE handle, ExcludeLibsMap& rMap )
176 size_t nPos( 0 );
177 const TCHAR cDelim = ',';
178 std::string sLibsExcluded = GetMsiProperty(handle, TEXT("EXCLUDE_FROM_REBASE"));
180 while ( nPos < sLibsExcluded.size() )
182 size_t nDelPos = sLibsExcluded.find_first_of( cDelim, nPos );
184 std::string sExcludedLibName;
185 if ( nDelPos != std::string::npos )
187 sExcludedLibName = sLibsExcluded.substr( nPos, nDelPos - nPos );
188 nPos = nDelPos+1;
190 else
192 sExcludedLibName = sLibsExcluded.substr( nPos );
193 nPos = sLibsExcluded.size();
196 if ( sExcludedLibName.size() > 0 )
198 OutputDebugStringFormat( "Insert library %s into exclude from rebase list", sExcludedLibName.c_str() );
199 rMap.insert( StringPair( sExcludedLibName, true ));
204 extern "C" BOOL __stdcall RebaseLibrariesOnProperties( MSIHANDLE handle )
206 static LPVOID pDefault = reinterpret_cast<LPVOID>(0x10000000);
208 OutputDebugStringFormat( "RebaseLibrariesOnProperties has been called" );
209 std::string sDontOptimizeLibs = GetMsiProperty(handle, TEXT("DONTOPTIMIZELIBS"));
210 if ( sDontOptimizeLibs.length() > 0 && sDontOptimizeLibs == "1" )
212 OutputDebugStringFormat( "Don't optimize libraries set. No rebase necessary!" );
213 return TRUE;
216 if ( !IsServerSystem( handle ))
218 ExcludeLibsMap aExcludeLibsMap;
219 InitExcludeFromRebaseList( handle, aExcludeLibsMap );
221 return rebaseImages( handle, pDefault, aExcludeLibsMap );
224 return TRUE;
227 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */