1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "precompiled_desktop.hxx"
25 #define UNICODE
26 #define _UNICODE
27 
28 #define WIN32_LEAN_AND_MEAN
29 #if defined _MSC_VER
30 #pragma warning(push, 1)
31 #endif
32 #include <windows.h>
33 #include <shellapi.h>
34 #include <imagehlp.h>
35 #include <wchar.h>
36 #if defined _MSC_VER
37 #pragma warning(pop)
38 #endif
39 
40 #include <time.h>
41 #include "sal/config.h"
42 #include "tools/pathutils.hxx"
43 
44 #define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1)
45 #define MY_STRING(s) (s), MY_LENGTH(s)
46 
47 const int   FORMAT_MESSAGE_SIZE = 4096;
48 const DWORD PE_Signature        = 0x00004550;
49 const DWORD BASEVIRTUALADDRESS	= 0x10000000;
50 
51 namespace
52 {
53 
IsValidHandle(HANDLE handle)54 bool IsValidHandle( HANDLE handle )
55 {
56 	return ((NULL != handle) && (INVALID_HANDLE_VALUE != handle));
57 }
58 
fail()59 void fail()
60 {
61     LPWSTR buf = NULL;
62     FormatMessageW(
63         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
64         GetLastError(), 0, reinterpret_cast< LPWSTR >(&buf), 0, NULL);
65     MessageBoxW(NULL, buf, NULL, MB_OK | MB_ICONERROR);
66     LocalFree(buf);
67     TerminateProcess(GetCurrentProcess(), 255);
68 }
69 
rebaseImage(wchar_t * pszFilePath,ULONG nNewImageBase)70 bool rebaseImage( wchar_t* pszFilePath, ULONG nNewImageBase)
71 {
72 	ULONG ulOldImageSize;
73 	ULONG_PTR lpOldImageBase;
74 	ULONG ulNewImageSize;
75 	ULONG_PTR lpNewImageBase  = nNewImageBase;
76 	ULONG	  ulDateTimeStamp = 0;
77 	bool      bResult(false);
78 
79 	char cszFilePath[_MAX_PATH+1] = {0};
80 	int nResult = WideCharToMultiByte(CP_ACP, 0, pszFilePath, -1, cszFilePath, _MAX_PATH, NULL, NULL);
81 
82 	if (nResult != 0)
83 	{
84 		BOOL bResult = ReBaseImage(
85 			cszFilePath,
86 			"",
87 			TRUE,
88 			FALSE,
89 			FALSE,
90 			0,
91 			&ulOldImageSize,
92 			&lpOldImageBase,
93 			&ulNewImageSize,
94 			&lpNewImageBase,
95 			ulDateTimeStamp );
96 	}
97 
98 	return bResult;
99 }
100 
getBrandPath(wchar_t * path)101 wchar_t* getBrandPath(wchar_t * path)
102 {
103     DWORD n = GetModuleFileNameW(NULL, path, MAX_PATH);
104     if (n == 0 || n >= MAX_PATH) {
105         exit(EXIT_FAILURE);
106     }
107     return tools::filename(path);
108 }
109 
rebaseImagesInFolder(wchar_t * pszFolder,DWORD nNewImageBase)110 void rebaseImagesInFolder( wchar_t* pszFolder, DWORD nNewImageBase )
111 {
112 	wchar_t szPattern[MAX_PATH];
113 	wchar_t	*lpLastSlash = wcsrchr( pszFolder, '\\' );
114 	if ( lpLastSlash )
115 	{
116 		size_t len = lpLastSlash - pszFolder + 1;
117 		wcsncpy( szPattern, pszFolder, len );
118 		wcsncpy( szPattern + len, TEXT("*.dll"), sizeof(szPattern)/sizeof(szPattern[0]) - len );
119 	}
120 
121 	WIN32_FIND_DATA	aFindFileData;
122 	HANDLE	hFind = FindFirstFile( szPattern, &aFindFileData );
123 
124 	if ( IsValidHandle(hFind) )
125 	{
126 		BOOL fSuccess = false;
127 
128 		do
129 		{
130 			wchar_t szLibFilePath[MAX_PATH];
131 			wchar_t	*lpLastSlash = wcsrchr( pszFolder, '\\' );
132 			if ( lpLastSlash )
133 			{
134 				size_t len = lpLastSlash - pszFolder + 1;
135 				wcsncpy( szLibFilePath, pszFolder, len );
136 				wcsncpy( szLibFilePath + len, aFindFileData.cFileName, sizeof(szLibFilePath)/sizeof(szLibFilePath[0]) - len );
137 			}
138 
139 			rebaseImage( szLibFilePath, nNewImageBase );
140 			fSuccess = FindNextFile( hFind, &aFindFileData );
141 		}
142 		while ( fSuccess );
143 
144 		FindClose( hFind );
145 	}
146 }
147 
148 }
149 
WinMain(HINSTANCE,HINSTANCE,LPSTR,int)150 extern "C" int APIENTRY WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
151 {
152 	wchar_t path[MAX_PATH];
153 
154 	wchar_t * pathEnd = getBrandPath(path);
155 
156 	if (tools::buildPath(path, path, pathEnd, MY_STRING(L"")) == NULL)
157 		fail();
158 	rebaseImagesInFolder(path, BASEVIRTUALADDRESS);
159 
160 	if (tools::buildPath(path, path, pathEnd, MY_STRING(L"..\\basis-link")) == NULL)
161 		fail();
162 	pathEnd = tools::resolveLink(path);
163 
164 	if ( pathEnd == NULL )
165 		return 0;
166 
167 	if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\program\\")) == NULL)
168 		fail();
169 	rebaseImagesInFolder(path, BASEVIRTUALADDRESS);
170 
171 	if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")) == NULL)
172 		fail();
173 	pathEnd = tools::resolveLink(path);
174 
175 	if ( pathEnd == NULL )
176 		return 0;
177 
178 	if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\bin\\")) == NULL)
179 		fail();
180 	rebaseImagesInFolder(path, BASEVIRTUALADDRESS);
181 
182 	return 0;
183 }
184