source: trunk/src/peldr/pe.cpp@ 4231

Last change on this file since 4231 was 4231, checked in by sandervl, 25 years ago

cmd line parse fix

File size: 10.7 KB
Line 
1/* $Id: pe.cpp,v 1.21 2000-09-10 21:54:44 sandervl Exp $ */
2
3/*
4 * PELDR main exe loader code
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#define INCL_DOSFILEMGR /* File Manager values */
13#define INCL_DOSERRORS /* DOS Error values */
14#define INCL_DOSPROCESS /* DOS Process values */
15#define INCL_DOSMISC /* DOS Miscellanous values */
16#define INCL_DOSMODULEMGR
17#define INCL_WIN
18#include <os2.h>
19#include <bseord.h>
20#include <stdio.h>
21#include <string.h>
22#include <stdlib.h>
23#include <string.h>
24#include <assert.h>
25#include <win32type.h>
26#include <misc.h>
27#include <wprocess.h>
28#include <win\peexe.h>
29#include "pe.h"
30
31char INFO_BANNER[] = "Usage: PE winexe commandline";
32char szErrorTitle[] = "Odin";
33char szLoadErrorMsg[] = "Can't load executable";
34char szFileErrorMsg[] = "File IO error";
35char szPEErrorMsg[] = "Not a valid win32 exe. (perhaps 16 bits windows)";
36char szCPUErrorMsg[] = "Executable doesn't run on x86 machines";
37char szExeErrorMsg[] = "File isn't an executable";
38char szInteralErrorMsg[]= "Internal Error";
39char szNoKernel32Msg[] = "Can't load/find kernel32.dll (rc=%d)";
40char szDosInfoBlocks[] = "DosInfoBlocks failed!";
41
42char fullpath[CCHMAXPATH];
43
44typedef HAB (* APIENTRY WININITIALIZEPROC)(ULONG flOptions);
45typedef BOOL (* APIENTRY WINTERMINATEPROC)(HAB hab);
46typedef HMQ (* APIENTRY WINCREATEMSGQUEUEPROC) (HAB hab, LONG cmsg);
47typedef BOOL (* APIENTRY WINDESTROYMSGQUEUEPROC) (HMQ hmq);
48typedef ULONG (* APIENTRY WINMESSAGEBOXPROC) (HWND hwndParent,
49 HWND hwndOwner,
50 PCSZ pszText,
51 PCSZ pszCaption,
52 ULONG idWindow,
53 ULONG flStyle);
54typedef void (* KRNL32EXCEPTPROC) (void *exceptframe);
55
56WININITIALIZEPROC MyWinInitialize = 0;
57WINTERMINATEPROC MyWinTerminate = 0;
58WINCREATEMSGQUEUEPROC MyWinCreateMsgQueue = 0;
59WINDESTROYMSGQUEUEPROC MyWinDestroyMsgQueue = 0;
60WINMESSAGEBOXPROC MyWinMessageBox = 0;
61KRNL32EXCEPTPROC Krnl32SetExceptionHandler = 0;
62KRNL32EXCEPTPROC Krnl32UnsetExceptionHandler = 0;
63
64//should be the same as in ..\kernel32\winexepeldr.h
65typedef BOOL (* WIN32API WIN32CTOR)(char *, char *, ULONG);
66
67WIN32CTOR CreateWin32Exe = 0;
68
69ULONG reservedMemory = 0;
70
71void AllocateExeMem(char *filename);
72
73//******************************************************************************
74//******************************************************************************
75int main(int argc, char *argv[])
76{
77 HAB hab = 0; /* PM anchor block handle */
78 HMQ hmq = 0; /* Message queue handle */
79 char exeName[CCHMAXPATH];
80 char fullpath[CCHMAXPATH];
81 APIRET rc;
82 HMODULE hmodPMWin = 0, hmodKernel32 = 0;
83 PTIB ptib;
84 PPIB ppib;
85 char *cmdline, *win32cmdline;
86 BOOL fQuote = FALSE;
87 int nrTries = 1;
88
89 if(argc >= 2) {
90 if(DosGetInfoBlocks(&ptib, &ppib) == 0) {
91tryagain:
92 cmdline = ppib->pib_pchcmd;
93 cmdline += strlen(cmdline)+1; //skip pe.exe
94 while(*cmdline == ' ') cmdline++; //skip leading space
95 if(*cmdline == '"') {
96 cmdline++;
97 fQuote = TRUE;
98 }
99 win32cmdline = cmdline;
100
101 strncpy(exeName, cmdline, sizeof(exeName)-1);
102 exeName[sizeof(exeName)-1] = 0;
103 char *p = exeName;
104 if(fQuote) {
105 while(*p != '"' && *p != 0) p++;
106 }
107 else {
108 for(int i=0;i<nrTries;i++) {
109 while(*p != ' ' && *p != 0) p++;
110 if(*p == 0) break;
111 if(i != nrTries-1) {
112 while(*p == ' ' && *p != 0) p++;
113 }
114 }
115 }
116 *p = 0;
117 strupr(exeName);
118 cmdline = strstr(exeName, ".EXE");
119 if(cmdline) {
120 cmdline[4] = 0;
121 win32cmdline += ((ULONG)cmdline - (ULONG)exeName) + 4;
122 }
123 else {
124 win32cmdline += strlen(exeName);
125 if(strstr(exeName, ".") == NULL) {
126 strcat(exeName, ".EXE");
127 }
128 }
129 if(fQuote) win32cmdline++;
130 while(*win32cmdline == ' ') win32cmdline++; //skip spaces
131 if(*win32cmdline == '"') {
132 win32cmdline++;
133 cmdline = win32cmdline + strlen(win32cmdline) - 1;
134 while(*cmdline == ' ') cmdline--;
135 if(*cmdline == '"') {
136 *cmdline = 0;
137 }
138 }
139 cmdline = exeName + strlen(exeName) - 1;
140 while(*cmdline == ' ') cmdline--;
141 cmdline[1] = 0;
142 if(DosQueryPathInfo(exeName, FIL_QUERYFULLNAME, (PVOID)fullpath, sizeof(fullpath)) == 0) {
143 strcpy(exeName, fullpath);
144 }
145 FILESTATUS3 fstat3;
146 if(DosQueryPathInfo(exeName, FIL_STANDARD, (PVOID)&fstat3, sizeof(fstat3)))
147 {
148 nrTries++;
149 if(*win32cmdline != NULL && !fQuote) {
150 goto tryagain;
151 }
152 }
153 }
154 else {//should never happen!
155filenotfound:
156 DebugInt3();
157 rc = DosLoadModule(exeName, sizeof(exeName), "PMWIN.DLL", &hmodPMWin);
158 rc = DosQueryProcAddr(hmodPMWin, ORD_WIN32MESSAGEBOX, NULL, (PFN *)&MyWinMessageBox);
159 MyWinMessageBox(HWND_DESKTOP, NULL, szDosInfoBlocks, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
160 goto fail;
161 }
162 AllocateExeMem(exeName);
163 }
164
165 rc = DosLoadModule(exeName, sizeof(exeName), "PMWIN.DLL", &hmodPMWin);
166 rc = DosQueryProcAddr(hmodPMWin, ORD_WIN32INITIALIZE, NULL, (PFN *)&MyWinInitialize);
167 rc = DosQueryProcAddr(hmodPMWin, ORD_WIN32TERMINATE, NULL, (PFN *)&MyWinTerminate);
168 rc = DosQueryProcAddr(hmodPMWin, ORD_WIN32CREATEMSGQUEUE, NULL, (PFN *)&MyWinCreateMsgQueue);
169 rc = DosQueryProcAddr(hmodPMWin, ORD_WIN32DESTROYMSGQUEUE, NULL, (PFN *)&MyWinDestroyMsgQueue);
170 rc = DosQueryProcAddr(hmodPMWin, ORD_WIN32MESSAGEBOX, NULL, (PFN *)&MyWinMessageBox);
171
172 if ((hab = MyWinInitialize(0)) == 0L) /* Initialize PM */
173 goto fail;
174
175 hmq = MyWinCreateMsgQueue(hab, 0);
176
177 if(argc < 2) {
178 MyWinMessageBox(HWND_DESKTOP, NULL, INFO_BANNER, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
179 goto fail;
180 }
181
182 rc = DosLoadModule(exeName, sizeof(exeName), "KERNEL32.DLL", &hmodKernel32);
183 if(rc) {
184 sprintf(exeName, szNoKernel32Msg, rc);
185 MyWinMessageBox(HWND_DESKTOP, NULL, exeName, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
186 goto fail;
187 }
188 rc = DosQueryProcAddr(hmodKernel32, 0, "_CreateWin32PeLdrExe@12", (PFN *)&CreateWin32Exe);
189
190 if(CreateWin32Exe(exeName, win32cmdline, reservedMemory) == FALSE) {
191 goto fail;
192 }
193
194 if(hmq) MyWinDestroyMsgQueue( hmq ); /* Tidy up... */
195 MyWinTerminate( hab ); /* Terminate the application */
196
197 DosFreeModule(hmodPMWin);
198 DosFreeModule(hmodKernel32);
199 return 0;
200
201fail:
202 if(hmq) MyWinDestroyMsgQueue( hmq ); /* Tidy up... */
203 if(hab) MyWinTerminate( hab ); /* Terminate the application */
204
205 if(hmodPMWin) DosFreeModule(hmodPMWin);
206 if(hmodKernel32) DosFreeModule(hmodKernel32);
207 return(1);
208}
209//******************************************************************************
210//SvL: Reserve memory for win32 exes without fixups
211// This is done before any Odin or PMWIN dll is loaded, so we'll get
212// a very low virtual address. (which is exactly what we want)
213//******************************************************************************
214void AllocateExeMem(char *filename)
215{
216 HFILE dllfile = 0;
217 char szFileName[CCHMAXPATH], *tmp;
218 char szResult[CCHMAXPATH];
219 ULONG action, ulRead, signature;
220 APIRET rc;
221 IMAGE_DOS_HEADER doshdr;
222 IMAGE_OPTIONAL_HEADER oh;
223 IMAGE_FILE_HEADER fh;
224 ULONG address = 0;
225 ULONG *memallocs;
226 ULONG alloccnt = 0;
227 ULONG diff, i, baseAddress;
228 ULONG ulSysinfo, flAllocMem = 0;
229
230 strcpy(szFileName, filename);
231
232 rc = DosOpen(szFileName, &dllfile, &action, 0, FILE_READONLY, OPEN_ACTION_OPEN_IF_EXISTS|OPEN_ACTION_FAIL_IF_NEW, OPEN_SHARE_DENYNONE|OPEN_ACCESS_READONLY, NULL);
233 if(rc != 0) {
234 if(!strstr(szFileName, ".EXE")) {
235 strcat(szFileName,".EXE");
236 }
237 }
238 else DosClose(dllfile);
239
240 rc = DosOpen(szFileName, &dllfile, &action, 0, FILE_READONLY, OPEN_ACTION_OPEN_IF_EXISTS|OPEN_ACTION_FAIL_IF_NEW, OPEN_SHARE_DENYNONE|OPEN_ACCESS_READONLY, NULL);
241 if(rc) {
242 if(DosSearchPath(SEARCH_IGNORENETERRS|SEARCH_ENVIRONMENT, "PATH",
243 szFileName, szResult, sizeof(szResult)) != 0) {
244 goto end; //oops
245 }
246 rc = DosOpen(szResult, &dllfile, &action, 0, FILE_READONLY, OPEN_ACTION_OPEN_IF_EXISTS|OPEN_ACTION_FAIL_IF_NEW, OPEN_SHARE_DENYNONE|OPEN_ACCESS_READONLY, NULL);
247 if(rc) {
248 goto end; //oops
249 }
250 }
251
252 //read dos header
253 if(DosRead(dllfile, (LPVOID)&doshdr, sizeof(doshdr), &ulRead)) {
254 goto end;
255 }
256 if(DosSetFilePtr(dllfile, doshdr.e_lfanew, FILE_BEGIN, &ulRead)) {
257 goto end;
258 }
259 //read signature dword
260 if(DosRead(dllfile, (LPVOID)&signature, sizeof(signature), &ulRead)) {
261 goto end;
262 }
263 //read pe header
264 if(DosRead(dllfile, (LPVOID)&fh, sizeof(fh), &ulRead)) {
265 goto end;
266 }
267 //read optional header
268 if(DosRead(dllfile, (LPVOID)&oh, sizeof(oh), &ulRead)) {
269 goto end;
270 }
271 if(doshdr.e_magic != IMAGE_DOS_SIGNATURE || signature != IMAGE_NT_SIGNATURE) {
272 goto end;
273 }
274// if(!(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)) {
275// goto end; //no need to allocate anything now
276// }
277
278 // check for high memory support
279 rc = DosQuerySysInfo(QSV_VIRTUALADDRESSLIMIT, QSV_VIRTUALADDRESSLIMIT, &ulSysinfo, sizeof(ulSysinfo));
280 if (rc == 0 && ulSysinfo > 512) //VirtualAddresslimit is in MB
281 {
282 flAllocMem = PAG_ANY; // high memory support. Let's use it!
283 }
284
285 //Reserve enough space to store 4096 pointers to 1MB memory chunks
286 memallocs = (ULONG *)alloca(4096*sizeof(ULONG *));
287 if(memallocs == NULL) {
288 goto end; //oops
289 }
290
291 if(oh.ImageBase < 512*1024*1024) {
292 flAllocMem = 0;
293 }
294 else {
295 if(flAllocMem == 0) {
296 goto end; //no support for > 512 MB
297 }
298 }
299 while(TRUE) {
300 rc = DosAllocMem((PPVOID)&address, FALLOC_SIZE, PAG_READ | flAllocMem);
301 if(rc) break;
302
303 if(address + FALLOC_SIZE >= oh.ImageBase) {
304 if(address > oh.ImageBase) {//we've passed it!
305 DosFreeMem((PVOID)address);
306 break;
307 }
308 //found the right address
309 DosFreeMem((PVOID)address);
310
311 diff = oh.ImageBase - address;
312 if(diff) {
313 rc = DosAllocMem((PPVOID)&address, diff, PAG_READ | flAllocMem);
314 if(rc) break;
315 }
316 rc = DosAllocMem((PPVOID)&baseAddress, oh.SizeOfImage, PAG_READ | PAG_WRITE | flAllocMem);
317 if(rc) break;
318
319 if(diff) DosFreeMem((PVOID)address);
320
321 reservedMemory = baseAddress;
322 break;
323 }
324 memallocs[alloccnt++] = address;
325 }
326 for(i=0;i<alloccnt;i++) {
327 DosFreeMem((PVOID)memallocs[i]);
328 }
329end:
330 if(dllfile) DosClose(dllfile);
331 return;
332}
333//******************************************************************************
334//******************************************************************************
Note: See TracBrowser for help on using the repository browser.