1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_desktop.hxx"
29 #define UNICODE
30 #define _UNICODE
31 
32 #define WIN32_LEAN_AND_MEAN
33 #if defined _MSC_VER
34 #pragma warning(push, 1)
35 #endif
36 #include <windows.h>
37 #include <shellapi.h>
38 #include <imagehlp.h>
39 #include <wchar.h>
40 #if defined _MSC_VER
41 #pragma warning(pop)
42 #endif
43 
44 #include <time.h>
45 #include "sal/config.h"
46 #include "tools/pathutils.hxx"
47 
48 #define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1)
49 #define MY_STRING(s) (s), MY_LENGTH(s)
50 
51 const int   FORMAT_MESSAGE_SIZE = 4096;
52 const DWORD PE_Signature        = 0x00004550;
53 const DWORD BASEVIRTUALADDRESS	= 0x10000000;
54 
55 namespace
56 {
57 
58 bool IsValidHandle( HANDLE handle )
59 {
60 	return ((NULL != handle) && (INVALID_HANDLE_VALUE != handle));
61 }
62 
63 void fail()
64 {
65     LPWSTR buf = NULL;
66     FormatMessageW(
67         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
68         GetLastError(), 0, reinterpret_cast< LPWSTR >(&buf), 0, NULL);
69     MessageBoxW(NULL, buf, NULL, MB_OK | MB_ICONERROR);
70     LocalFree(buf);
71     TerminateProcess(GetCurrentProcess(), 255);
72 }
73 
74 bool rebaseImage( wchar_t* pszFilePath, ULONG nNewImageBase)
75 {
76 	ULONG ulOldImageSize;
77 	ULONG_PTR lpOldImageBase;
78 	ULONG ulNewImageSize;
79 	ULONG_PTR lpNewImageBase  = nNewImageBase;
80 	ULONG	  ulDateTimeStamp = 0;
81 	bool      bResult(false);
82 
83 	char cszFilePath[_MAX_PATH+1] = {0};
84 	int nResult = WideCharToMultiByte(CP_ACP, 0, pszFilePath, -1, cszFilePath, _MAX_PATH, NULL, NULL);
85 
86 	if (nResult != 0)
87 	{
88 		BOOL bResult = ReBaseImage(
89 			cszFilePath,
90 			"",
91 			TRUE,
92 			FALSE,
93 			FALSE,
94 			0,
95 			&ulOldImageSize,
96 			&lpOldImageBase,
97 			&ulNewImageSize,
98 			&lpNewImageBase,
99 			ulDateTimeStamp );
100 	}
101 
102 	return bResult;
103 }
104 
105 wchar_t* getBrandPath(wchar_t * path)
106 {
107     DWORD n = GetModuleFileNameW(NULL, path, MAX_PATH);
108     if (n == 0 || n >= MAX_PATH) {
109         exit(EXIT_FAILURE);
110     }
111     return tools::filename(path);
112 }
113 
114 void rebaseImagesInFolder( wchar_t* pszFolder, DWORD nNewImageBase )
115 {
116 	wchar_t szPattern[MAX_PATH];
117 	wchar_t	*lpLastSlash = wcsrchr( pszFolder, '\\' );
118 	if ( lpLastSlash )
119 	{
120 		size_t len = lpLastSlash - pszFolder + 1;
121 		wcsncpy( szPattern, pszFolder, len );
122 		wcsncpy( szPattern + len, TEXT("*.dll"), sizeof(szPattern)/sizeof(szPattern[0]) - len );
123 	}
124 
125 	WIN32_FIND_DATA	aFindFileData;
126 	HANDLE	hFind = FindFirstFile( szPattern, &aFindFileData );
127 
128 	if ( IsValidHandle(hFind) )
129 	{
130 		BOOL fSuccess = false;
131 
132 		do
133 		{
134 			wchar_t szLibFilePath[MAX_PATH];
135 			wchar_t	*lpLastSlash = wcsrchr( pszFolder, '\\' );
136 			if ( lpLastSlash )
137 			{
138 				size_t len = lpLastSlash - pszFolder + 1;
139 				wcsncpy( szLibFilePath, pszFolder, len );
140 				wcsncpy( szLibFilePath + len, aFindFileData.cFileName, sizeof(szLibFilePath)/sizeof(szLibFilePath[0]) - len );
141 			}
142 
143 			rebaseImage( szLibFilePath, nNewImageBase );
144 			fSuccess = FindNextFile( hFind, &aFindFileData );
145 		}
146 		while ( fSuccess );
147 
148 		FindClose( hFind );
149 	}
150 }
151 
152 }
153 
154 extern "C" int APIENTRY WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
155 {
156 	wchar_t path[MAX_PATH];
157 
158 	wchar_t * pathEnd = getBrandPath(path);
159 
160 	if (tools::buildPath(path, path, pathEnd, MY_STRING(L"")) == NULL)
161 		fail();
162 	rebaseImagesInFolder(path, BASEVIRTUALADDRESS);
163 
164 	if (tools::buildPath(path, path, pathEnd, MY_STRING(L"..\\basis-link")) == NULL)
165 		fail();
166 	pathEnd = tools::resolveLink(path);
167 
168 	if ( pathEnd == NULL )
169 		return 0;
170 
171 	if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\program\\")) == NULL)
172 		fail();
173 	rebaseImagesInFolder(path, BASEVIRTUALADDRESS);
174 
175 	if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")) == NULL)
176 		fail();
177 	pathEnd = tools::resolveLink(path);
178 
179 	if ( pathEnd == NULL )
180 		return 0;
181 
182 	if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\bin\\")) == NULL)
183 		fail();
184 	rebaseImagesInFolder(path, BASEVIRTUALADDRESS);
185 
186 	return 0;
187 }
188