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

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

also search in path for executable

File size: 8.8 KB
Line 
1/* $Id: pe.cpp,v 1.15 2000-04-13 18:54:41 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)";
40
41char fullpath[CCHMAXPATH];
42
43typedef HAB (* APIENTRY WININITIALIZEPROC)(ULONG flOptions);
44typedef BOOL (* APIENTRY WINTERMINATEPROC)(HAB hab);
45typedef HMQ (* APIENTRY WINCREATEMSGQUEUEPROC) (HAB hab, LONG cmsg);
46typedef BOOL (* APIENTRY WINDESTROYMSGQUEUEPROC) (HMQ hmq);
47typedef ULONG (* APIENTRY WINMESSAGEBOXPROC) (HWND hwndParent,
48 HWND hwndOwner,
49 PCSZ pszText,
50 PCSZ pszCaption,
51 ULONG idWindow,
52 ULONG flStyle);
53typedef void (* KRNL32EXCEPTPROC) (void *exceptframe);
54
55WININITIALIZEPROC MyWinInitialize = 0;
56WINTERMINATEPROC MyWinTerminate = 0;
57WINCREATEMSGQUEUEPROC MyWinCreateMsgQueue = 0;
58WINDESTROYMSGQUEUEPROC MyWinDestroyMsgQueue = 0;
59WINMESSAGEBOXPROC MyWinMessageBox = 0;
60KRNL32EXCEPTPROC Krnl32SetExceptionHandler = 0;
61KRNL32EXCEPTPROC Krnl32UnsetExceptionHandler = 0;
62
63//should be the same as in ..\kernel32\winexepeldr.h
64typedef BOOL (* WIN32API WIN32CTOR)(char *, ULONG);
65
66WIN32CTOR CreateWin32Exe = 0;
67
68ULONG reservedMemory = 0;
69
70void AllocateExeMem(char *filename);
71
72//******************************************************************************
73//******************************************************************************
74int main(int argc, char *argv[])
75{
76 HAB hab = 0; /* PM anchor block handle */
77 HMQ hmq = 0; /* Message queue handle */
78 char exeName[CCHMAXPATH];
79 APIRET rc;
80 HMODULE hmodPMWin = 0, hmodKernel32 = 0;
81
82 if(argc >= 2) {
83 strcpy(exeName, argv[1]);
84 strupr(exeName);
85 AllocateExeMem(exeName);
86 }
87
88 rc = DosLoadModule(exeName, sizeof(exeName), "PMWIN.DLL", &hmodPMWin);
89 rc = DosQueryProcAddr(hmodPMWin, ORD_WIN32INITIALIZE, NULL, (PFN *)&MyWinInitialize);
90 rc = DosQueryProcAddr(hmodPMWin, ORD_WIN32TERMINATE, NULL, (PFN *)&MyWinTerminate);
91 rc = DosQueryProcAddr(hmodPMWin, ORD_WIN32CREATEMSGQUEUE, NULL, (PFN *)&MyWinCreateMsgQueue);
92 rc = DosQueryProcAddr(hmodPMWin, ORD_WIN32DESTROYMSGQUEUE, NULL, (PFN *)&MyWinDestroyMsgQueue);
93 rc = DosQueryProcAddr(hmodPMWin, ORD_WIN32MESSAGEBOX, NULL, (PFN *)&MyWinMessageBox);
94
95 if ((hab = MyWinInitialize(0)) == 0L) /* Initialize PM */
96 goto fail;
97
98 hmq = MyWinCreateMsgQueue(hab, 0);
99
100 if(argc < 2) {
101 MyWinMessageBox(HWND_DESKTOP, NULL, INFO_BANNER, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
102 goto fail;
103 }
104
105 rc = DosLoadModule(exeName, sizeof(exeName), "KERNEL32.DLL", &hmodKernel32);
106 if(rc) {
107 sprintf(exeName, szNoKernel32Msg, rc);
108 MyWinMessageBox(HWND_DESKTOP, NULL, exeName, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
109 goto fail;
110 }
111 rc = DosQueryProcAddr(hmodKernel32, 0, "_CreateWin32PeLdrExe@8", (PFN *)&CreateWin32Exe);
112
113 strcpy(exeName, argv[1]);
114 strupr(exeName);
115 if(CreateWin32Exe(exeName, reservedMemory) == FALSE) {
116 goto fail;
117 }
118
119 if(hmq) MyWinDestroyMsgQueue( hmq ); /* Tidy up... */
120 MyWinTerminate( hab ); /* Terminate the application */
121
122 DosFreeModule(hmodPMWin);
123 DosFreeModule(hmodKernel32);
124 return 0;
125
126fail:
127 if(hmq) MyWinDestroyMsgQueue( hmq ); /* Tidy up... */
128 if(hab) MyWinTerminate( hab ); /* Terminate the application */
129
130 if(hmodPMWin) DosFreeModule(hmodPMWin);
131 if(hmodKernel32) DosFreeModule(hmodKernel32);
132 return(1);
133}
134//******************************************************************************
135//SvL: Reserve memory for win32 exes without fixups
136// This is done before any Odin or PMWIN dll is loaded, so we'll get
137// a very low virtual address. (which is exactly what we want)
138//******************************************************************************
139void AllocateExeMem(char *filename)
140{
141 HFILE dllfile = 0;
142 char szFileName[CCHMAXPATH], *tmp;
143 char szResult[CCHMAXPATH];
144 ULONG action, ulRead, signature;
145 APIRET rc;
146 IMAGE_DOS_HEADER doshdr;
147 IMAGE_OPTIONAL_HEADER oh;
148 IMAGE_FILE_HEADER fh;
149 ULONG address = 0;
150 ULONG *memallocs;
151 ULONG alloccnt = 0;
152 ULONG diff, i, baseAddress;
153 ULONG ulSysinfo, flAllocMem = 0;
154
155 strcpy(szFileName, filename);
156 tmp = szFileName;
157 while(*tmp != ' ' && *tmp != 0)
158 tmp++;
159 *tmp = 0;
160
161 if(!strchr(szFileName, '.')) {
162 strcat(szFileName,".EXE");
163 }
164 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);
165 if(rc != 0) {
166 if(!strstr(szFileName, ".EXE")) {
167 strcat(szFileName,".EXE");
168 }
169 }
170 else DosClose(dllfile);
171
172 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);
173 if(rc) {
174 if(DosSearchPath(SEARCH_IGNORENETERRS|SEARCH_ENVIRONMENT, "PATH",
175 szFileName, szResult, sizeof(szResult)) != 0) {
176 goto end; //oops
177 }
178 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);
179 if(rc) {
180 goto end; //oops
181 }
182 }
183
184 //read dos header
185 if(DosRead(dllfile, (LPVOID)&doshdr, sizeof(doshdr), &ulRead)) {
186 goto end;
187 }
188 if(DosSetFilePtr(dllfile, doshdr.e_lfanew, FILE_BEGIN, &ulRead)) {
189 goto end;
190 }
191 //read signature dword
192 if(DosRead(dllfile, (LPVOID)&signature, sizeof(signature), &ulRead)) {
193 goto end;
194 }
195 //read pe header
196 if(DosRead(dllfile, (LPVOID)&fh, sizeof(fh), &ulRead)) {
197 goto end;
198 }
199 //read optional header
200 if(DosRead(dllfile, (LPVOID)&oh, sizeof(oh), &ulRead)) {
201 goto end;
202 }
203 if(doshdr.e_magic != IMAGE_DOS_SIGNATURE || signature != IMAGE_NT_SIGNATURE) {
204 goto end;
205 }
206 if(!(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)) {
207 goto end; //no need to allocate anything now
208 }
209
210 // check for high memory support
211 rc = DosQuerySysInfo(QSV_VIRTUALADDRESSLIMIT, QSV_VIRTUALADDRESSLIMIT, &ulSysinfo, sizeof(ulSysinfo));
212 if (rc == 0 && ulSysinfo > 512) //VirtualAddresslimit is in MB
213 {
214 flAllocMem = PAG_ANY; // high memory support. Let's use it!
215 }
216
217 //Reserve enough space to store 4096 pointers to 1MB memory chunks
218 memallocs = (ULONG *)alloca(4096*sizeof(ULONG *));
219 if(memallocs == NULL) {
220 goto end; //oops
221 }
222
223 if(oh.ImageBase < 512*1024*1024) {
224 flAllocMem = 0;
225 }
226 else {
227 if(flAllocMem == 0) {
228 goto end; //no support for > 512 MB
229 }
230 }
231 while(TRUE) {
232 rc = DosAllocMem((PPVOID)&address, FALLOC_SIZE, PAG_READ | flAllocMem);
233 if(rc) break;
234
235 if(address + FALLOC_SIZE >= oh.ImageBase) {
236 if(address > oh.ImageBase) {//we've passed it!
237 DosFreeMem((PVOID)address);
238 break;
239 }
240 //found the right address
241 DosFreeMem((PVOID)address);
242
243 diff = oh.ImageBase - address;
244 if(diff) {
245 rc = DosAllocMem((PPVOID)&address, diff, PAG_READ | flAllocMem);
246 if(rc) break;
247 }
248 rc = DosAllocMem((PPVOID)&baseAddress, oh.SizeOfImage, PAG_READ | PAG_WRITE | flAllocMem);
249 if(rc) break;
250
251 if(diff) DosFreeMem((PVOID)address);
252
253 reservedMemory = baseAddress;
254 break;
255 }
256 memallocs[alloccnt++] = address;
257 }
258 for(i=0;i<alloccnt;i++) {
259 DosFreeMem((PVOID)memallocs[i]);
260 }
261end:
262 if(dllfile) DosClose(dllfile);
263 return;
264}
265//******************************************************************************
266//******************************************************************************
Note: See TracBrowser for help on using the repository browser.