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