diff options
-rwxr-xr-x | crashrep/source/win32/soreport.cpp | 54 | ||||
-rw-r--r-- | setup_native/prj/build.lst | 1 | ||||
-rw-r--r-- | setup_native/source/win32/customactions/rebase/makefile.mk | 94 | ||||
-rw-r--r-- | setup_native/source/win32/customactions/rebase/rebase.cxx | 168 | ||||
-rw-r--r-- | setup_native/source/win32/customactions/rebase/rebase.dxp | 1 |
5 files changed, 318 insertions, 0 deletions
diff --git a/crashrep/source/win32/soreport.cpp b/crashrep/source/win32/soreport.cpp index 4c897f76e0b5..043ad62b0051 100755 --- a/crashrep/source/win32/soreport.cpp +++ b/crashrep/source/win32/soreport.cpp @@ -1564,8 +1564,60 @@ static void repatch_soffice_exe( void *pBuffer, size_t nBufSize ) } while ( !bPatched && nBufSize ); } +// Normalize executable/library images to prevent different MD5 checksums due +// to a different PE header date/checksum (this doesn't affect the code/data +// sections of a executable/library. Please see tools/source/bootstrp/md5.cxx +// where the same method is also used. The tool so_checksum creates the MD5 +// checksums during build time. You have to make sure that both methods use the +// same algorithm otherwise there could be problems with stack reports. +static void normalize_pe_image(sal_uInt8* buffer, size_t nBufferSize) +{ + const int OFFSET_PE_OFFSET = 0x3c; + const int OFFSET_COFF_TIMEDATESTAMP = 4; + const int PE_SIGNATURE_SIZE = 4; + const int COFFHEADER_SIZE = 20; + const int OFFSET_PE_OPTIONALHEADER_CHECKSUM = 64; + + // Check the header part of the file buffer + if (buffer[0] == 'M' && buffer[1] == 'Z') + { + unsigned long PEHeaderOffset = (long)buffer[OFFSET_PE_OFFSET]; + if (PEHeaderOffset < nBufferSize-4) + { + if ( buffer[PEHeaderOffset] == 'P' && + buffer[PEHeaderOffset+1] == 'E' && + buffer[PEHeaderOffset+2] == 0 && + buffer[PEHeaderOffset+3] == 0 ) + { + PEHeaderOffset += PE_SIGNATURE_SIZE; + if (PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP < nBufferSize-4) + { + // Set timedatestamp and checksum fields to a normalized + // value to enforce the same MD5 checksum for identical + // Windows executables/libraries. + buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP] = 0; + buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+1] = 0; + buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+2] = 0; + buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+3] = 0; + } + + if (PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM < nBufferSize-4) + { + // Set checksum to a normalized value + buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM] = 0; + buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+1] = 0; + buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+2] = 0; + buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+3] = 0; + } + } + } + } +} + static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen ) { + const int MINIMAL_FILESIZE = 512; + sal_uInt32 nBytesProcessed = 0; FILE *fp = fopen( filename, "rb" ); @@ -1585,6 +1637,8 @@ static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum { if ( 0 == stricmp( GetFileName(filename).c_str(), "soffice.bin" ) ) repatch_soffice_exe( pBuffer, nBytesRead ); + else if ( nFileSize > MINIMAL_FILESIZE ) + normalize_pe_image( pBuffer, nBytesRead ); rtlDigestError error = rtl_digest_MD5 ( pBuffer, nBytesRead, diff --git a/setup_native/prj/build.lst b/setup_native/prj/build.lst index 7966d21533fc..fcb276075a09 100644 --- a/setup_native/prj/build.lst +++ b/setup_native/prj/build.lst @@ -4,6 +4,7 @@ pk setup_native\scripts\source nmake - u sn_sour pk setup_native\scripts nmake - u sn_scripts sn_source.u NULL pk setup_native\source\win32\customactions\tools nmake - w sn_tools NULL pk setup_native\source\win32\customactions\relnotes nmake - w sn_relnotes NULL +pk setup_native\source\win32\customactions\rebase nmake - w sn_rebase NULL pk setup_native\source\win32\customactions\regactivex nmake - w sn_regactivex NULL pk setup_native\source\win32\customactions\regpatchactivex nmake - w sn_regpatchactivex NULL pk setup_native\source\win32\customactions\reg4allmsdoc nmake - w sn_reg4allmsdoc NULL diff --git a/setup_native/source/win32/customactions/rebase/makefile.mk b/setup_native/source/win32/customactions/rebase/makefile.mk new file mode 100644 index 000000000000..6694c8cde6cc --- /dev/null +++ b/setup_native/source/win32/customactions/rebase/makefile.mk @@ -0,0 +1,94 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.7 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/..$/.. +PRJNAME=setup_native +TARGET=rebase + +# --- Settings ----------------------------------------------------- + +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +NO_DEFAULT_STL=TRUE +DYNAMIC_CRT= +USE_DEFFILE=TRUE +MINGW_NODLL=YES + +.INCLUDE : settings.mk + +.IF "$(USE_SYSTEM_STL)" != "YES" +CFLAGS+=-D_STLP_USE_STATIC_LIB +.ENDIF + +UWINAPILIB= + +# --- Files -------------------------------------------------------- + +.IF "$(GUI)"=="WNT" + +STDSHL += \ + $(ADVAPI32LIB)\ + $(SHELL32LIB)\ + $(MSILIB) + +.IF "$(USE_SYSTEM_STL)" != "YES" +STDSHL += $(LIBSTLPORTST) +.ENDIF + +.IF "$(COM)"=="GCC" +STDSHL+= \ + $(KERNEL32LIB)\ + -lmsvcrt \ + $(PSDK_HOME)$/lib$/imagehlp.lib +.ELSE +STDSHL+= \ + Imagehlp.lib +.ENDIF + +SHL1OBJS = \ + $(SLO)$/rebase.obj + +SHL1TARGET = $(TARGET) +SHL1IMPLIB = i$(TARGET) + +SHL1DEF = $(MISC)$/$(SHL1TARGET).def +SHL1BASE = 0x1c000000 +DEF1NAME=$(SHL1TARGET) +SHL1DEPN=$(SHL1OBJS) +DEF1EXPORTFILE=$(TARGET).dxp + +.ENDIF + +# --- Targets -------------------------------------------------------------- + +.INCLUDE : target.mk + +# ------------------------------------------------------------------------- diff --git a/setup_native/source/win32/customactions/rebase/rebase.cxx b/setup_native/source/win32/customactions/rebase/rebase.cxx new file mode 100644 index 000000000000..4d031bee908a --- /dev/null +++ b/setup_native/source/win32/customactions/rebase/rebase.cxx @@ -0,0 +1,168 @@ +#undef UNICODE +#undef _UNICODE + +#pragma once + +#ifdef _MSC_VER +#pragma warning(push, 1) /* disable warnings within system headers */ +#endif +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <msiquery.h> +#include <imagehlp.h> +#include <tchar.h> +#include <strsafe.h> +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include <malloc.h> +#include <time.h> +#include <string> + +const DWORD PE_Signature = 0x00004550; + +#ifdef DEBUG +inline void OutputDebugStringFormat( LPCSTR pFormat, ... ) +{ + CHAR buffer[1024]; + va_list args; + + va_start( args, pFormat ); + StringCchVPrintfA( buffer, sizeof(buffer), pFormat, args ); + OutputDebugStringA( buffer ); +} +#else +static inline void OutputDebugStringFormat( LPCSTR, ... ) +{ +} +#endif + +static bool IsValidHandle( HANDLE handle ) +{ + return NULL != handle && INVALID_HANDLE_VALUE != handle; +} + +static std::string GetMsiProperty(MSIHANDLE handle, const std::string& sProperty) +{ + std::string result; + TCHAR szDummy[1] = TEXT(""); + DWORD nChars = 0; + + if (MsiGetProperty(handle, sProperty.c_str(), szDummy, &nChars) == ERROR_MORE_DATA) + { + DWORD nBytes = ++nChars * sizeof(TCHAR); + LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes)); + ZeroMemory( buffer, nBytes ); + MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars); + result = buffer; + } + return result; +} + +static BOOL rebaseImage( const std::string& filePath, LPVOID address ) +{ + ULONG ulOldImageSize; + ULONG_PTR lpOldImageBase; + ULONG ulNewImageSize; + ULONG_PTR lpNewImageBase = reinterpret_cast<ULONG_PTR>(address); + + BOOL bResult = ReBaseImage( + filePath.c_str(), + "", + TRUE, + FALSE, + FALSE, + 0, + &ulOldImageSize, + &lpOldImageBase, + &ulNewImageSize, + &lpNewImageBase, + (ULONG)time(NULL) ); + + return bResult; +} + +static BOOL rebaseImage( MSIHANDLE /*handle*/, const std::string& sFilePath, LPVOID address ) +{ + std::string mystr; + mystr = "Full file: " + sFilePath; + + BOOL bResult = rebaseImage( sFilePath, address ); + + if ( !bResult ) + { + OutputDebugStringFormat( "Rebasing library %s failed", mystr.c_str() ); + } + + return bResult; +} + +static BOOL rebaseImagesInFolder( MSIHANDLE handle, const std::string& sPath, LPVOID address ) +{ + std::string sDir = sPath; + std::string sPattern = sPath + TEXT("*.dll"); + + WIN32_FIND_DATA aFindFileData; + HANDLE hFind = FindFirstFile( sPattern.c_str(), &aFindFileData ); + + if ( IsValidHandle(hFind) ) + { + BOOL fSuccess = false; + + do + { + std::string sLibFile = sDir + aFindFileData.cFileName; + rebaseImage( handle, sLibFile, address ); + fSuccess = FindNextFile( hFind, &aFindFileData ); + } + while ( fSuccess ); + + FindClose( hFind ); + } + + return ERROR_SUCCESS; +} + +static BOOL rebaseImages( MSIHANDLE handle, LPVOID pAddress ) +{ + std::string sOfficeInstallPath = GetMsiProperty(handle, TEXT("OFFICEINSTALLLOCATION")); + std::string sBasisInstallPath = GetMsiProperty(handle, TEXT("BASISINSTALLLOCATION")); + std::string sUreInstallPath = GetMsiProperty(handle, TEXT("UREINSTALLLOCATION")); + + std::string sBasisDir = sBasisInstallPath + TEXT("program\\"); + std::string sOfficeDir = sOfficeInstallPath + TEXT("program\\"); + std::string sUreDir = sUreInstallPath + TEXT("bin\\"); + + BOOL bResult = rebaseImagesInFolder( handle, sBasisDir, pAddress ); + bResult &= rebaseImagesInFolder( handle, sOfficeDir, pAddress ); + bResult &= rebaseImagesInFolder( handle, sUreDir, pAddress ); + + return bResult; +} + +static BOOL IsServerSystem( MSIHANDLE /*handle*/ ) +{ + OSVERSIONINFOEX osVersionInfoEx; + osVersionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(&osVersionInfoEx)); + + if ( osVersionInfoEx.wProductType != VER_NT_WORKSTATION ) + return TRUE; + else + return FALSE; +} + +extern "C" BOOL __stdcall RebaseLibrariesOnProperties( MSIHANDLE handle ) +{ + static LPVOID pDefault = reinterpret_cast<LPVOID>(0x10000000); + + std::string sDontOptimizeLibs = GetMsiProperty(handle, TEXT("DONTOPTIMIZELIBS")); + if ( sDontOptimizeLibs.length() > 0 && sDontOptimizeLibs == "1" ) + return TRUE; + + if ( !IsServerSystem( handle )) + return rebaseImages( handle, pDefault ); + + return TRUE; +} diff --git a/setup_native/source/win32/customactions/rebase/rebase.dxp b/setup_native/source/win32/customactions/rebase/rebase.dxp new file mode 100644 index 000000000000..47ea23951f04 --- /dev/null +++ b/setup_native/source/win32/customactions/rebase/rebase.dxp @@ -0,0 +1 @@ +RebaseLibrariesOnProperties
|