1*32b1fd08SAndrew Rist /**************************************************************
2*32b1fd08SAndrew Rist *
3*32b1fd08SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*32b1fd08SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*32b1fd08SAndrew Rist * distributed with this work for additional information
6*32b1fd08SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*32b1fd08SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*32b1fd08SAndrew Rist * "License"); you may not use this file except in compliance
9*32b1fd08SAndrew Rist * with the License. You may obtain a copy of the License at
10*32b1fd08SAndrew Rist *
11*32b1fd08SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*32b1fd08SAndrew Rist *
13*32b1fd08SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*32b1fd08SAndrew Rist * software distributed under the License is distributed on an
15*32b1fd08SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*32b1fd08SAndrew Rist * KIND, either express or implied. See the License for the
17*32b1fd08SAndrew Rist * specific language governing permissions and limitations
18*32b1fd08SAndrew Rist * under the License.
19*32b1fd08SAndrew Rist *
20*32b1fd08SAndrew Rist *************************************************************/
21*32b1fd08SAndrew Rist
22cdf0e10cSrcweir #undef UNICODE
23cdf0e10cSrcweir #undef _UNICODE
24cdf0e10cSrcweir
25cdf0e10cSrcweir #pragma once
26cdf0e10cSrcweir
27cdf0e10cSrcweir #ifdef _MSC_VER
28cdf0e10cSrcweir #pragma warning(push, 1) /* disable warnings within system headers */
29cdf0e10cSrcweir #endif
30cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN
31cdf0e10cSrcweir #include <windows.h>
32cdf0e10cSrcweir #include <msiquery.h>
33cdf0e10cSrcweir #include <imagehlp.h>
34cdf0e10cSrcweir #include <tchar.h>
35cdf0e10cSrcweir #include <strsafe.h>
36cdf0e10cSrcweir #ifdef _MSC_VER
37cdf0e10cSrcweir #pragma warning(pop)
38cdf0e10cSrcweir #endif
39cdf0e10cSrcweir
40cdf0e10cSrcweir #include <malloc.h>
41cdf0e10cSrcweir #include <time.h>
42cdf0e10cSrcweir #include <string>
43cdf0e10cSrcweir #include <hash_map>
44cdf0e10cSrcweir
45cdf0e10cSrcweir const DWORD PE_Signature = 0x00004550;
46cdf0e10cSrcweir typedef std::pair< std::string, bool > StringPair;
47cdf0e10cSrcweir typedef std::hash_map< std::string, bool > ExcludeLibsMap;
48cdf0e10cSrcweir
49cdf0e10cSrcweir #ifdef DEBUG
OutputDebugStringFormat(LPCSTR pFormat,...)50cdf0e10cSrcweir static void OutputDebugStringFormat( LPCSTR pFormat, ... )
51cdf0e10cSrcweir {
52cdf0e10cSrcweir CHAR buffer[1024];
53cdf0e10cSrcweir va_list args;
54cdf0e10cSrcweir
55cdf0e10cSrcweir va_start( args, pFormat );
56cdf0e10cSrcweir StringCchVPrintfA( buffer, sizeof(buffer), pFormat, args );
57cdf0e10cSrcweir OutputDebugStringA( buffer );
58cdf0e10cSrcweir }
59cdf0e10cSrcweir #else
OutputDebugStringFormat(LPCSTR,...)60cdf0e10cSrcweir static void OutputDebugStringFormat( LPCSTR, ... )
61cdf0e10cSrcweir {
62cdf0e10cSrcweir }
63cdf0e10cSrcweir #endif
64cdf0e10cSrcweir
IsValidHandle(HANDLE handle)65cdf0e10cSrcweir static bool IsValidHandle( HANDLE handle )
66cdf0e10cSrcweir {
67cdf0e10cSrcweir return NULL != handle && INVALID_HANDLE_VALUE != handle;
68cdf0e10cSrcweir }
69cdf0e10cSrcweir
GetMsiProperty(MSIHANDLE handle,const std::string & sProperty)70cdf0e10cSrcweir static std::string GetMsiProperty(MSIHANDLE handle, const std::string& sProperty)
71cdf0e10cSrcweir {
72cdf0e10cSrcweir std::string result;
73cdf0e10cSrcweir TCHAR szDummy[1] = TEXT("");
74cdf0e10cSrcweir DWORD nChars = 0;
75cdf0e10cSrcweir
76cdf0e10cSrcweir if (MsiGetProperty(handle, sProperty.c_str(), szDummy, &nChars) == ERROR_MORE_DATA)
77cdf0e10cSrcweir {
78cdf0e10cSrcweir DWORD nBytes = ++nChars * sizeof(TCHAR);
79cdf0e10cSrcweir LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes));
80cdf0e10cSrcweir ZeroMemory( buffer, nBytes );
81cdf0e10cSrcweir MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars);
82cdf0e10cSrcweir result = buffer;
83cdf0e10cSrcweir }
84cdf0e10cSrcweir return result;
85cdf0e10cSrcweir }
86cdf0e10cSrcweir
rebaseImage(const std::string & filePath,LPVOID address)87cdf0e10cSrcweir static BOOL rebaseImage( const std::string& filePath, LPVOID address )
88cdf0e10cSrcweir {
89cdf0e10cSrcweir ULONG ulOldImageSize;
90cdf0e10cSrcweir ULONG_PTR lpOldImageBase;
91cdf0e10cSrcweir ULONG ulNewImageSize;
92cdf0e10cSrcweir ULONG_PTR lpNewImageBase = reinterpret_cast<ULONG_PTR>(address);
93cdf0e10cSrcweir
94cdf0e10cSrcweir BOOL bResult = ReBaseImage(
95cdf0e10cSrcweir filePath.c_str(),
96cdf0e10cSrcweir "",
97cdf0e10cSrcweir TRUE,
98cdf0e10cSrcweir FALSE,
99cdf0e10cSrcweir FALSE,
100cdf0e10cSrcweir 0,
101cdf0e10cSrcweir &ulOldImageSize,
102cdf0e10cSrcweir &lpOldImageBase,
103cdf0e10cSrcweir &ulNewImageSize,
104cdf0e10cSrcweir &lpNewImageBase,
105cdf0e10cSrcweir (ULONG)time(NULL) );
106cdf0e10cSrcweir
107cdf0e10cSrcweir return bResult;
108cdf0e10cSrcweir }
109cdf0e10cSrcweir
rebaseImage(MSIHANDLE,const std::string & sFilePath,LPVOID address)110cdf0e10cSrcweir static BOOL rebaseImage( MSIHANDLE /*handle*/, const std::string& sFilePath, LPVOID address )
111cdf0e10cSrcweir {
112cdf0e10cSrcweir std::string mystr;
113cdf0e10cSrcweir mystr = "Full file: " + sFilePath;
114cdf0e10cSrcweir
115cdf0e10cSrcweir BOOL bResult = rebaseImage( sFilePath, address );
116cdf0e10cSrcweir
117cdf0e10cSrcweir if ( !bResult )
118cdf0e10cSrcweir {
119cdf0e10cSrcweir OutputDebugStringFormat( "Rebasing library %s failed", mystr.c_str() );
120cdf0e10cSrcweir }
121cdf0e10cSrcweir
122cdf0e10cSrcweir return bResult;
123cdf0e10cSrcweir }
124cdf0e10cSrcweir
rebaseImagesInFolder(MSIHANDLE handle,const std::string & sPath,LPVOID address,ExcludeLibsMap & rExcludeMap)125cdf0e10cSrcweir static BOOL rebaseImagesInFolder( MSIHANDLE handle, const std::string& sPath, LPVOID address, ExcludeLibsMap& rExcludeMap )
126cdf0e10cSrcweir {
127cdf0e10cSrcweir std::string sDir = sPath;
128cdf0e10cSrcweir std::string sPattern = sPath + TEXT("*.dll");
129cdf0e10cSrcweir WIN32_FIND_DATA aFindFileData;
130cdf0e10cSrcweir
131cdf0e10cSrcweir HANDLE hFind = FindFirstFile( sPattern.c_str(), &aFindFileData );
132cdf0e10cSrcweir if ( IsValidHandle(hFind) )
133cdf0e10cSrcweir {
134cdf0e10cSrcweir BOOL fSuccess = false;
135cdf0e10cSrcweir
136cdf0e10cSrcweir do
137cdf0e10cSrcweir {
138cdf0e10cSrcweir std::string sFileName = aFindFileData.cFileName;
139cdf0e10cSrcweir if ( rExcludeMap.find( sFileName ) == rExcludeMap.end() )
140cdf0e10cSrcweir {
141cdf0e10cSrcweir OutputDebugStringFormat( "Rebase library: %s", sFileName.c_str() );
142cdf0e10cSrcweir std::string sLibFile = sDir + sFileName;
143cdf0e10cSrcweir rebaseImage( handle, sLibFile, address );
144cdf0e10cSrcweir }
145cdf0e10cSrcweir else
146cdf0e10cSrcweir {
147cdf0e10cSrcweir OutputDebugStringFormat( "Exclude library %s from rebase", sFileName.c_str() );
148cdf0e10cSrcweir }
149cdf0e10cSrcweir
150cdf0e10cSrcweir fSuccess = FindNextFile( hFind, &aFindFileData );
151cdf0e10cSrcweir }
152cdf0e10cSrcweir while ( fSuccess );
153cdf0e10cSrcweir
154cdf0e10cSrcweir FindClose( hFind );
155cdf0e10cSrcweir }
156cdf0e10cSrcweir
157cdf0e10cSrcweir return ERROR_SUCCESS;
158cdf0e10cSrcweir }
159cdf0e10cSrcweir
rebaseImages(MSIHANDLE handle,LPVOID pAddress,ExcludeLibsMap & rMap)160cdf0e10cSrcweir static BOOL rebaseImages( MSIHANDLE handle, LPVOID pAddress, ExcludeLibsMap& rMap )
161cdf0e10cSrcweir {
162cdf0e10cSrcweir std::string sInstallPath = GetMsiProperty(handle, TEXT("INSTALLLOCATION"));
163cdf0e10cSrcweir
164cdf0e10cSrcweir std::string sBasisDir = sInstallPath + TEXT("Basis\\program\\");
165cdf0e10cSrcweir std::string sOfficeDir = sInstallPath + TEXT("program\\");
166cdf0e10cSrcweir std::string sUreDir = sInstallPath + TEXT("URE\\bin\\");
167cdf0e10cSrcweir
168cdf0e10cSrcweir BOOL bResult = rebaseImagesInFolder( handle, sBasisDir, pAddress, rMap );
169cdf0e10cSrcweir bResult &= rebaseImagesInFolder( handle, sOfficeDir, pAddress, rMap );
170cdf0e10cSrcweir bResult &= rebaseImagesInFolder( handle, sUreDir, pAddress, rMap );
171cdf0e10cSrcweir
172cdf0e10cSrcweir return bResult;
173cdf0e10cSrcweir }
174cdf0e10cSrcweir
IsServerSystem(MSIHANDLE)175cdf0e10cSrcweir static BOOL IsServerSystem( MSIHANDLE /*handle*/ )
176cdf0e10cSrcweir {
177cdf0e10cSrcweir OSVERSIONINFOEX osVersionInfoEx;
178cdf0e10cSrcweir osVersionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
179cdf0e10cSrcweir GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(&osVersionInfoEx));
180cdf0e10cSrcweir
181cdf0e10cSrcweir if ( osVersionInfoEx.wProductType != VER_NT_WORKSTATION )
182cdf0e10cSrcweir {
183cdf0e10cSrcweir OutputDebugStringFormat( "Server system detected. No rebase necessary!" );
184cdf0e10cSrcweir return TRUE;
185cdf0e10cSrcweir }
186cdf0e10cSrcweir else
187cdf0e10cSrcweir {
188cdf0e10cSrcweir OutputDebugStringFormat( "Client system detected. Rebase necessary!" );
189cdf0e10cSrcweir return FALSE;
190cdf0e10cSrcweir }
191cdf0e10cSrcweir }
192cdf0e10cSrcweir
InitExcludeFromRebaseList(MSIHANDLE handle,ExcludeLibsMap & rMap)193cdf0e10cSrcweir static void InitExcludeFromRebaseList( MSIHANDLE handle, ExcludeLibsMap& rMap )
194cdf0e10cSrcweir {
195cdf0e10cSrcweir size_t nPos( 0 );
196cdf0e10cSrcweir const TCHAR cDelim = ',';
197cdf0e10cSrcweir std::string sLibsExcluded = GetMsiProperty(handle, TEXT("EXCLUDE_FROM_REBASE"));
198cdf0e10cSrcweir
199cdf0e10cSrcweir while ( nPos < sLibsExcluded.size() )
200cdf0e10cSrcweir {
201cdf0e10cSrcweir size_t nDelPos = sLibsExcluded.find_first_of( cDelim, nPos );
202cdf0e10cSrcweir
203cdf0e10cSrcweir std::string sExcludedLibName;
204cdf0e10cSrcweir if ( nDelPos != std::string::npos )
205cdf0e10cSrcweir {
206cdf0e10cSrcweir sExcludedLibName = sLibsExcluded.substr( nPos, nDelPos - nPos );
207cdf0e10cSrcweir nPos = nDelPos+1;
208cdf0e10cSrcweir }
209cdf0e10cSrcweir else
210cdf0e10cSrcweir {
211cdf0e10cSrcweir sExcludedLibName = sLibsExcluded.substr( nPos );
212cdf0e10cSrcweir nPos = sLibsExcluded.size();
213cdf0e10cSrcweir }
214cdf0e10cSrcweir
215cdf0e10cSrcweir if ( sExcludedLibName.size() > 0 )
216cdf0e10cSrcweir {
217cdf0e10cSrcweir OutputDebugStringFormat( "Insert library %s into exclude from rebase list", sExcludedLibName.c_str() );
218cdf0e10cSrcweir rMap.insert( StringPair( sExcludedLibName, true ));
219cdf0e10cSrcweir }
220cdf0e10cSrcweir }
221cdf0e10cSrcweir }
222cdf0e10cSrcweir
RebaseLibrariesOnProperties(MSIHANDLE handle)223cdf0e10cSrcweir extern "C" BOOL __stdcall RebaseLibrariesOnProperties( MSIHANDLE handle )
224cdf0e10cSrcweir {
225cdf0e10cSrcweir static LPVOID pDefault = reinterpret_cast<LPVOID>(0x10000000);
226cdf0e10cSrcweir
227cdf0e10cSrcweir OutputDebugStringFormat( "RebaseLibrariesOnProperties has been called" );
228cdf0e10cSrcweir std::string sDontOptimizeLibs = GetMsiProperty(handle, TEXT("DONTOPTIMIZELIBS"));
229cdf0e10cSrcweir if ( sDontOptimizeLibs.length() > 0 && sDontOptimizeLibs == "1" )
230cdf0e10cSrcweir {
231cdf0e10cSrcweir OutputDebugStringFormat( "Don't optimize libraries set. No rebase necessary!" );
232cdf0e10cSrcweir return TRUE;
233cdf0e10cSrcweir }
234cdf0e10cSrcweir
235cdf0e10cSrcweir if ( !IsServerSystem( handle ))
236cdf0e10cSrcweir {
237cdf0e10cSrcweir ExcludeLibsMap aExcludeLibsMap;
238cdf0e10cSrcweir InitExcludeFromRebaseList( handle, aExcludeLibsMap );
239cdf0e10cSrcweir
240cdf0e10cSrcweir return rebaseImages( handle, pDefault, aExcludeLibsMap );
241cdf0e10cSrcweir }
242cdf0e10cSrcweir
243cdf0e10cSrcweir return TRUE;
244cdf0e10cSrcweir }
245