1 /******************************************************************************
2 *
3 * Copyright (C) 2006-09, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * Author: Alexey Krivonogov
11 *
12 ******************************************************************************/
13
14 #include "windows.h"
15 #include "../../common/types.h"
16 #include "../../genteeapi/gentee.h"
17 //#elif defined(LAUNCHERD)
18 //#include "../../genteeapi/gentee.h"
19 #ifdef MINILAUNCHER
20 #include "../gea/LZGE/lzge.h"
21 #include "../gea/memory.h"
22 #endif
23
24 #define GE_STRING 0x00004547 // String GE
25
26 typedef struct
27 {
28 uint sign1; // 'Gentee Launcher' sign
29 uint sign2; //
30 uint sign3; //
31 uint sign4; //
32 uint exesize; // Размер exe-файла.
33 // Если не 0, то файл является SFX
34 // архивом и далее идут прикрепленныe данные
35 uint minsize; // Если не 0, то выдавать ошибку если размер файла
36 // меньше указанного
37 ubyte console; // 1 если консольное приложение
38 ubyte exeext; // Количество дополнительных блоков
39 ubyte pack; // 1 если байт код и dll упакованы
40 ushort flags; // flags
41 uint dllsize; // Упакованный размер Dll файла.
42 // Если 0, то динамическое подключение gentee.dll
43 uint gesize; // Упакованный размер байт-кода.
44 uint mutex; // ID для mutex, если не 0, то будет проверка
45 uint param; // Зашитый параметр
46 uint offset; // Смещение данной структуры
47 uint extsize[ 16 ]; // Зарезервированно для размеров 8 ext блоков
48 // Каждый размер занимает long
49 } lahead, * plahead;
50
51 #if defined __WATCOMC__
52 #ifdef LAUNCHER
53 const uint gentee_offset = 0x17000; // Смещение gentee секции
54 #elif defined(LAUNCHERD)
55 const uint gentee_offset = 0x5000; // Смещение gentee секции
56 #endif
57 #elif defined __GNUC__
58 #ifdef LAUNCHER
59 const uint gentee_offset = 0x12000; // Смещение gentee секции
60 #elif defined(LAUNCHERD)
61 const uint gentee_offset = 0x6000; // Смещение gentee секции
62 #endif
63 #else
64 #ifdef LAUNCHER
65 #ifdef _ASM
66 const uint gentee_offset = 0xF000; // Смещение gentee секции
67 #else
68 const uint gentee_offset = 0xE000; // Смещение gentee секции
69 #endif
70 #elif defined(LAUNCHERD)
71 const uint gentee_offset = 0x4000; // Смещение gentee секции
72 #elif defined(MINILAUNCHER)
73 const uint gentee_offset = 0x4000; // Mini Launcher
74 #endif
75 #endif
76
77 const lahead head = {
78 0x746E6547,
79 0x4C206565,
80 0x636E7561,
81 0x00726568,
82 0x0, // exesize
83 0, // minsize
84 0, // console
85 0, // exeext
86 0, 0, // pack
87 0, 0, // Размеры dll и байт-кода
88 0, // mutex
89 0, 0, // param offset
90 };
91
92 #ifdef MINILAUNCHER
93
94 gea_call lge_call;
95
96 //--------------------------------------------------------------------------
97
98 uint STDCALL fgeauser( uint param, uint userfunc, uint pgeaparam )
99 {
100 uint result;
101
102 if ( userfunc )
103 {
104 *( puint )pgeaparam = param;
105 lge_call( userfunc, &result, 200, pgeaparam );
106 }
107 return 1;
108 }
109
110 uint STDCALL unpackdll( pubyte input, pubyte out, pubyte temp, pubyte dllname )
111 {
112 uint rw, diskc = 0;
113 HANDLE handle;
114 slzge lzge;
115
116 if ( head.dllsize )
117 {
118 mem_zero( &lzge, sizeof( slzge ));
119 // Looking for the temporary directory
120 GetTempPath( 512, temp );
121 if ( temp[ lstrlen( temp ) - 1 ] == '\\' )
122 temp[ lstrlen( temp ) - 1 ] = 0;
123
124 again:
125 wsprintf( dllname, "%s\\genteert.dll", temp );
126 if ( GetFileAttributes( dllname ) == 0xFFFFFFFF )
127 {
128 handle = CreateFile( dllname, GENERIC_READ | GENERIC_WRITE,
129 0, NULL, CREATE_ALWAYS, 0, NULL );
130 if ( handle == INVALID_HANDLE_VALUE )
131 {
132 if ( !diskc )
133 {
134 lstrcpy( temp, "c:\\temp" );
135 CreateDirectory( temp, NULL );
136 diskc = 1;
137 goto again;
138 }
139 else
140 goto error;
141 }
142 lzge_decode( input + 4, out, *( puint )input, &lzge );
143
144 if ( !WriteFile( handle, out, *( puint )input, &rw, NULL ) ||
145 rw != *( puint )input )
146 goto error;
147
148 CloseHandle( handle );
149 }
150 }
151 if ( head.pack )
152 {
153 // Unpacking the byte-code
154 input += head.dllsize;
155 mem_zero( &lzge, sizeof( slzge ));
156 lzge_decode( input + 4, out, *( puint )input, &lzge );
157 }
158 else
159 mem_copy( out, input, head.gesize );
160
161 return 1;
162 error:
163 lstrcpy( temp, "Cannot create gentee.dll!" );
164 return 0;
165 }
166
167 //--------------------------------------------------------------------------
168 #define LAGET_HEAD 0
169 #define LAGET_ALLOC 1
170 #define LAGET_FREE 2
171 #define LAGET_ZERO 3
172 #define LAGET_COPY 4
173 #define LAGET_GEAUSER 5
174
175 pvoid STDCALL launcher_get( uint id )
176 {
177 switch ( id )
178 {
179 case LAGET_HEAD : return ( pvoid )( &head );
180 case LAGET_ALLOC : return &mem_alloc;
181 case LAGET_FREE : return &mem_free;
182 case LAGET_ZERO : return &mem_zero;
183 case LAGET_COPY : return &mem_copy;
184 case LAGET_GEAUSER : return &fgeauser;
185 }
186 return 0;
187 }
188
189 //--------------------------------------------------------------------------
190
191 PVOID CALLBACK export2gentee( PCHAR str )
192 {
193 if ( !lstrcmp( str, "lzge_decode" ) )
194 return &lzge_decode;
195 if ( !lstrcmp( str, "launcher_get" ) )
196 return &launcher_get;
197 return NULL;
198 }
199 #endif
200
201 //--------------------------------------------------------------------------
202 #if LAUNCHERD
203 int WINAPI WinMainCRTStartup(void)
204 #elif LAUNCHER || MINILAUNCHER
205 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
206 LPSTR lpCmdLine, int nCmdShow )
207 #endif
208 {
209 #ifdef MINILAUNCHER
210 pvoid hdll;
211 FARPROC gentee_init;
212 FARPROC gentee_deinit;
213 FARPROC gentee_load;
214 FARPROC gentee_set;
215 byte dllname[ 512 ];
216 #endif
217
218 uint result = 0;
219 HANDLE hMutex;
220 pvoid handle;
221 ubyte exename[ 512 ];
222 ubyte temp[ 512 ];
223 ubyte tmpname[ 512 ];
224 pubyte gesection, out;
225
226 GetModuleFileName( NULL, exename, 512 );
227
228 // Prohibit to run the second application copy if there is 'mutex' field
229 if ( head.mutex )
230 {
231 wsprintf( temp, "%X", head.mutex );
232 hMutex = CreateMutex( NULL, TRUE, temp );
233 if ( GetLastError() == ERROR_ALREADY_EXISTS )
234 {
235 lstrcpy( temp, __TEXT("The application has already run."));
236 goto error;
237 }
238 }
239 // Checking up the minimum size of EXE file
240 if ( head.minsize )
241 {
242 handle = CreateFile( exename, GENERIC_READ, FILE_SHARE_READ |
243 FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
244 if ( head.minsize > GetFileSize( handle, NULL ))
245 {
246 lstrcpy( temp, __TEXT("The file is corrupted. It was downloaded with errors or otherwise \
247 damaged.\nPlease download it again and make sure that you do not have viruses."));
248 goto error;
249 }
250 CloseHandle( handle );
251 }
252 gesection = ( pubyte )GetModuleHandle( NULL ) + gentee_offset;
253
254 #if MINILAUNCHER
255 out = mem_alloc( max( *( puint )gesection, *(puint)( gesection + head.dllsize )
256 ) + 1024 );
257 if ( !unpackdll( ( pubyte )gesection, out, temp, dllname ))
258 goto error;
259 // Loading gentee.dll
260 hdll = LoadLibrary( dllname );
261
262 if ( !hdll )
263 {
264 wsprintf( temp, __TEXT("Cannot load %s."), dllname );
265 goto error;
266 }
267 gentee_init = ( FARPROC )GetProcAddress( hdll, "gentee_init" );
268 gentee_deinit = ( FARPROC )GetProcAddress( hdll, "gentee_deinit" );
269 gentee_load = ( FARPROC )GetProcAddress( hdll, "gentee_load" );
270 gentee_set = ( FARPROC )GetProcAddress( hdll, "gentee_set" );
271 lge_call = ( gea_call )GetProcAddress( hdll, "gentee_call" );
272 #else
273 out = ( pubyte )gesection;
274 #endif
275
276 #ifdef _ASMRT
277 gentee_init( G_SILENT | head.console | G_ASM | head.flags );
278 #else
279 gentee_init( G_SILENT | head.console | head.flags );
280 #endif
281
282 #if MINILAUNCHER
283 gentee_set( GSET_EXPORT, &export2gentee );
284 #endif
285
286 if ( *( puint )out != GE_STRING )
287 {
288 lstrcpy( temp, "The executable file does not have a bytecode!" );
289 goto error;
290 }
291 result = gentee_load( out, GLOAD_RUN | GLOAD_ARGS );
292
293 #if MINILAUNCHER
294 mem_free( out );
295 #endif
296 gentee_deinit();
297 #if MINILAUNCHER
298 // I don't understand why gentee.dll is free just after
299 // the second FreeLibrary
300 FreeLibrary( hdll );
301 FreeLibrary( hdll );
302 DeleteFile( dllname );
303 #endif
304
305 ExitProcess( result );
306 error:
307 lstrcat( lstrcpy( tmpname, "ERROR: " ), exename );
308 MessageBox( NULL, temp, tmpname, MB_OK | MB_ICONHAND );
309 ExitProcess( 0 );
310 return 0;
311 }