source: trunk/src/win16ldr/odindll.c@ 22012

Last change on this file since 22012 was 21308, checked in by ydario, 16 years ago

Minor updates, backout imm changes.

File size: 10.6 KB
Line 
1#include <windows.h>
2#include <string.h>
3#include <stdlib.h>
4#include <stdio.h>
5#include "peexe.h"
6
7DWORD FAR PASCAL MyGetVersion();
8UINT FAR _loadds PASCAL MyWinExec(LPCSTR lpszCmdLine, UINT fuShowCmd);
9
10BOOL FAR _loadds PASCAL MyPostMessage(HWND, UINT, WPARAM, LPARAM);
11LRESULT FAR _loadds PASCAL MySendMessage(HWND, UINT, WPARAM, LPARAM);
12
13BOOL GetPEFileHeader (LPVOID lpFile, PIMAGE_FILE_HEADER pHeader);
14BOOL GetPEOptionalHeader (LPVOID lpFile, PIMAGE_OPTIONAL_HEADER pHeader);
15
16typedef DWORD (FAR * PASCAL FUNC_GetVersion)(void);
17typedef UINT (FAR * PASCAL FUNC_WinExec)(LPCSTR, UINT);
18#ifdef PATCH_POSTSENDMSG
19typedef BOOL (FAR * PASCAL FUNC_PostMessage)(HWND, UINT, WPARAM, LPARAM);
20typedef LRESULT (FAR * PASCAL FUNC_SendMessage)(HWND, UINT, WPARAM, LPARAM);
21#endif
22
23BYTE oldcodeEXEC;
24DWORD olddataEXEC;
25UINT selEXEC;
26BYTE FAR *jumpEXEC;
27
28BYTE oldcodeVER;
29DWORD olddataVER;
30UINT selVER;
31BYTE FAR *jumpVER;
32
33#ifdef PATCH_POSTSENDMSG
34BYTE oldcodeSEND;
35DWORD olddataSEND;
36UINT selSEND;
37BYTE FAR *jumpSEND;
38
39BYTE oldcodePOST;
40DWORD olddataPOST;
41UINT selPOST;
42BYTE FAR *jumpPOST;
43#endif
44
45BOOL fUnloaded = FALSE;
46BOOL fInit = FALSE;
47
48char szPEPath[256] = {0};
49
50FUNC_GetVersion orggetver = NULL;
51FUNC_WinExec orgwinexec = NULL;
52#ifdef PATCH_POSTSENDMSG
53FUNC_SendMessage orgsendmsg = NULL;
54FUNC_PostMessage orgpostmsg = NULL;
55#endif
56
57//*****************************************************************************************
58//*****************************************************************************************
59int FAR _loadds CALLBACK LibMain(HINSTANCE hinst, WORD wDataSeg, WORD cbHeap, LPSTR lpszCmdLine)
60{
61 DWORD FAR *addr;
62
63 if(fInit == FALSE)
64 {
65 fInit = TRUE;
66
67 GetProfileString("PELDR", "LdrPath", "PE.EXE", szPEPath, sizeof(szPEPath));
68
69 orggetver = (FUNC_GetVersion)GetVersion;
70 selVER = AllocSelector(0);
71 PrestoChangoSelector(SELECTOROF(orggetver), selVER);
72
73 jumpVER = MAKELP(selVER, OFFSETOF(orggetver));
74 addr = (DWORD FAR *)(jumpVER+1);
75 oldcodeVER = *jumpVER;
76 olddataVER = *addr;
77 *jumpVER = 0xEA; //jmp
78 *addr = (DWORD)MyGetVersion;
79
80 orgwinexec = (FUNC_WinExec)WinExec;
81 selEXEC = AllocSelector(0);
82 PrestoChangoSelector(SELECTOROF(orgwinexec), selEXEC);
83
84 jumpEXEC = MAKELP(selEXEC, OFFSETOF(orgwinexec));
85 addr = (DWORD FAR *)(jumpEXEC+1);
86 oldcodeEXEC = *jumpEXEC;
87 olddataEXEC = *addr;
88 *jumpEXEC = 0xEA; //jmp
89 *addr = (DWORD)MyWinExec;
90
91#ifdef PATCH_POSTSENDMSG
92 orgsendmsg = (FUNC_SendMessage)SendMessage;
93 selSEND = AllocSelector(0);
94 PrestoChangoSelector(SELECTOROF(orgsendmsg), selSEND);
95
96 jumpSEND = MAKELP(selSEND, OFFSETOF(orgsendmsg));
97 addr = (DWORD FAR *)(jumpSEND+1);
98 oldcodeSEND = *jumpSEND;
99 olddataSEND = *addr;
100 *jumpSEND = 0xEA; //jmp
101 *addr = (DWORD)MySendMessage;
102
103 orgpostmsg = (FUNC_PostMessage)PostMessage;
104 selPOST = AllocSelector(0);
105 PrestoChangoSelector(SELECTOROF(orgpostmsg), selPOST);
106
107 jumpPOST = MAKELP(selPOST, OFFSETOF(orgpostmsg));
108 addr = (DWORD FAR *)(jumpPOST+1);
109 oldcodePOST = *jumpPOST;
110 olddataPOST = *addr;
111 *jumpPOST = 0xEA; //jmp
112 *addr = (DWORD)MyPostMessage;
113#endif
114 }
115 return 1;
116}
117//*****************************************************************************************
118//*****************************************************************************************
119int FAR _loadds PASCAL WEP(int entry)
120{
121 DWORD FAR *addr;
122
123 /* Your WEP functionality goes here */
124 if(!fUnloaded) {
125 fUnloaded = TRUE;
126
127 //restore entrypoints
128 addr = (DWORD FAR *)(jumpVER + 1);
129 *jumpVER = oldcodeVER;
130 *addr = olddataVER;
131
132 addr = (DWORD FAR *)(jumpEXEC + 1);
133 *jumpEXEC = oldcodeEXEC;
134 *addr = olddataEXEC;
135
136#ifdef PATCH_POSTSENDMSG
137 addr = (DWORD FAR *)(jumpSEND + 1);
138 *jumpSEND = oldcodeSEND;
139 *addr = olddataSEND;
140
141 addr = (DWORD FAR *)(jumpPOST + 1);
142 *jumpPOST = oldcodePOST;
143 *addr = olddataPOST;
144#endif
145 }
146 return 1;
147}
148//*****************************************************************************************
149//*****************************************************************************************
150DWORD FAR PASCAL MyGetVersion()
151{
152 return 0x00005F0C;
153}
154#ifdef PATCH_POSTSENDMSG
155//*****************************************************************************************
156//*****************************************************************************************
157BOOL FAR _loadds PASCAL MyPostMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
158{
159 DWORD FAR *addr;
160 BOOL ret;
161 char buffer[64];
162
163 addr = (DWORD FAR *)(jumpPOST + 1);
164 *jumpPOST = oldcodePOST;
165 *addr = olddataPOST;
166
167#ifdef DEBUG
168 if(hwnd == HWND_BROADCAST) {
169 sprintf(buffer, "Broadcast %x %lx %lx", Msg, wParam, lParam);
170 MessageBox(0, "PostMessage", buffer, MB_OK);
171 }
172#endif
173 ret = PostMessage(hwnd, Msg, wParam, lParam);
174
175 *jumpPOST = 0xEA; //jmp
176 *addr = (DWORD)&MyPostMessage;
177
178 return ret;
179}
180//*****************************************************************************************
181//*****************************************************************************************
182LRESULT FAR _loadds PASCAL MySendMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
183{
184 DWORD FAR *addr;
185 BOOL ret;
186 char buffer[64];
187
188 addr = (DWORD FAR *)(jumpSEND + 1);
189 *jumpSEND = oldcodeSEND;
190 *addr = olddataSEND;
191
192#ifdef DEBUG
193 if(hwnd == HWND_BROADCAST) {
194 sprintf(buffer, "Broadcast %x %lx %lx", Msg, wParam, lParam);
195 MessageBox(0, "SendMessage", buffer, MB_OK);
196 }
197#endif
198 ret = SendMessage(hwnd, Msg, wParam, lParam);
199
200 *jumpSEND = 0xEA; //jmp
201 *addr = (DWORD)&MySendMessage;
202
203 return ret;
204}
205#endif
206//*****************************************************************************************
207//*****************************************************************************************
208void FAR _loadds PASCAL SetPELdr(LPCSTR lpszPELdr)
209{
210 strcpy(szPEPath, lpszPELdr);
211}
212//*****************************************************************************************
213//*****************************************************************************************
214UINT FAR _loadds PASCAL MyWinExec(LPCSTR lpszCmdLine, UINT fuShowCmd)
215{
216 LPSTR cmdline, tmp;
217 UINT ret;
218 OFSTRUCT of = {0};
219 HFILE hFile = 0;
220 int hdrsize;
221 IMAGE_DOS_HEADER doshdr;
222 IMAGE_FILE_HEADER fh;
223 IMAGE_OPTIONAL_HEADER oh;
224 DWORD FAR *addr;
225 UINT bytesRead;
226 char FAR *header;
227 HGLOBAL hMem1 = 0, hMem2 = 0, hMem3 = 0, hMem4 = 0;
228 BOOL fFail = TRUE;
229
230 if(szPEPath[0] == 0) goto calloldfunc;
231
232 of.cBytes = sizeof(OFSTRUCT);
233
234 hMem1 = GlobalAlloc(GPTR, strlen(lpszCmdLine)+1);
235 cmdline = GlobalLock(hMem1);
236 if(cmdline == NULL) goto calloldfunc;
237
238 strcpy(cmdline, lpszCmdLine);
239
240 //isolate path of executable
241 while(*cmdline == ' ') cmdline++;
242 tmp = cmdline;
243 while(*tmp != ' ' && *tmp != 0) tmp++;
244 *tmp = 0;
245
246 //open it to check the executable type; we only care about PE (win32) executables
247 //we'll let the original WinExec function handle everything else
248 hFile = OpenFile(cmdline, &of, OF_READ);
249 bytesRead = _lread(hFile, &doshdr, sizeof(doshdr));
250 if(bytesRead != sizeof(doshdr)) goto calloldfunc;
251 if(doshdr.e_magic != IMAGE_DOS_SIGNATURE) goto calloldfunc;
252 hdrsize = doshdr.e_lfanew + SIZE_OF_NT_SIGNATURE + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER);
253
254 _llseek(hFile, 0, 0);
255 hMem3 = GlobalAlloc(GPTR, hdrsize);
256 header = GlobalLock(hMem3);
257 if(header == NULL) goto calloldfunc;
258
259 bytesRead = _lread(hFile, header, hdrsize);
260 if(bytesRead != hdrsize) {
261 goto calloldfunc;
262 }
263 if(GetPEFileHeader (header, &fh) == FALSE) {
264 goto calloldfunc;
265 }
266 if(GetPEOptionalHeader (header, &oh) == FALSE) {
267 goto calloldfunc;
268 }
269
270 if(!(fh.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {//not valid
271 goto calloldfunc;
272 }
273 if(fh.Machine != IMAGE_FILE_MACHINE_I386) {
274 goto calloldfunc;
275 }
276 //IMAGE_FILE_SYSTEM == only drivers (device/file system/video etc)?
277 if(fh.Characteristics & IMAGE_FILE_SYSTEM) {
278 goto calloldfunc;
279 }
280
281 //Ok, it's a PE executable. Use the PE loader to launch it
282 tmp = cmdline;
283 hMem4 = hMem1;
284
285 hMem1 = GlobalAlloc(GPTR, strlen(tmp)+16+strlen(szPEPath));
286 cmdline = GlobalLock(hMem1);
287 if(cmdline == NULL) {
288 goto calloldfunc;
289 }
290
291 strcpy(cmdline, szPEPath);
292 strcat(cmdline, " ");
293 strcat(cmdline, tmp);
294
295 fFail = FALSE;
296
297calloldfunc:
298 if(hMem4) {
299 GlobalUnlock(hMem4);
300 GlobalFree(hMem4);
301 }
302 if(hMem3) {
303 GlobalUnlock(hMem3);
304 GlobalFree(hMem3);
305 }
306 if(hMem2) {
307 GlobalUnlock(hMem2);
308 GlobalFree(hMem2);
309 }
310 if(hFile)
311 _lclose(hFile);
312
313 //restore original WinExec entrypoint
314 addr = (DWORD FAR *)(jumpEXEC + 1);
315 *jumpEXEC = oldcodeEXEC;
316 *addr = olddataEXEC;
317
318 //and call it
319 if(fFail) {
320 //non-PE executable
321 ret = WinExec(lpszCmdLine, fuShowCmd);
322 }
323 else {
324 //PE executable
325 ret = WinExec(cmdline, fuShowCmd);
326 if(ret >= 32) {
327 DWORD tickcount1, tickcount2;
328
329 //give PE a chance to load the exe file
330 tickcount1 = GetTickCount();
331 do {
332 Yield();
333 tickcount2 = GetTickCount();
334 }
335 while(tickcount2 - tickcount1 < 2000UL);
336 }
337 }
338
339 //put back our WinExec override
340 *jumpEXEC = 0xEA; //jmp
341 *addr = (DWORD)&MyWinExec;
342
343 if(hMem1) {
344 GlobalUnlock(hMem1);
345 GlobalFree(hMem1);
346 }
347 return ret;
348}
349//******************************************************************************
350//******************************************************************************
351BOOL GetPEFileHeader (LPVOID lpFile, PIMAGE_FILE_HEADER pHeader)
352{
353 if(*(WORD *)lpFile == IMAGE_DOS_SIGNATURE &&
354 *(DWORD *)PE_HEADER (lpFile) == IMAGE_NT_SIGNATURE)
355 {
356 memcpy ((LPVOID)pHeader, PEHEADEROFF (lpFile), sizeof (IMAGE_FILE_HEADER));
357 return TRUE;
358 }
359 else return FALSE;
360}
361//******************************************************************************
362//******************************************************************************
363BOOL GetPEOptionalHeader (LPVOID lpFile, PIMAGE_OPTIONAL_HEADER pHeader)
364{
365 if(*(WORD *)lpFile == IMAGE_DOS_SIGNATURE &&
366 *(DWORD *)PE_HEADER (lpFile) == IMAGE_NT_SIGNATURE)
367 {
368 memcpy ((LPVOID)pHeader, OPTHEADEROFF (lpFile), sizeof (IMAGE_OPTIONAL_HEADER));
369 return TRUE;
370 }
371 else return FALSE;
372}
373//*****************************************************************************************
374//*****************************************************************************************
Note: See TracBrowser for help on using the repository browser.