source: trunk/src/kernel32/winimagebase.cpp@ 5959

Last change on this file since 5959 was 5959, checked in by sandervl, 24 years ago

CreateProcess: launch win16 loader for NE executables

File size: 12.9 KB
Line 
1/* $Id: winimagebase.cpp,v 1.32 2001-06-10 22:32:17 sandervl Exp $ */
2
3/*
4 * Win32 PE Image base class
5 *
6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998-2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13#define INCL_DOSFILEMGR /* File Manager values */
14#define INCL_DOSMODULEMGR
15#define INCL_DOSERRORS /* DOS Error values */
16#define INCL_DOSPROCESS /* DOS Process values */
17#define INCL_DOSMISC /* DOS Miscellanous values */
18#define INCL_WIN
19#define INCL_BASE
20#include <os2wrap.h> //Odin32 OS/2 api wrappers
21
22#include <stdio.h>
23#include <string.h>
24#include <stdlib.h>
25
26#include <assert.h>
27#include <misc.h>
28#include <win32type.h>
29#include <winimagebase.h>
30#include <windllbase.h>
31#include <winexebase.h>
32#include <pefile.h>
33#include <unicode.h>
34#include "oslibmisc.h"
35#include "oslibdos.h"
36#include "initterm.h"
37#include "directory.h"
38#include <win\virtual.h>
39#include <winconst.h>
40
41#define DBG_LOCALLOG DBG_winimagebase
42#include "dbglocal.h"
43
44//******************************************************************************
45//******************************************************************************
46Win32ImageBase::Win32ImageBase(HINSTANCE hInstance) :
47 errorState(NO_ERROR), entryPoint(0), fullpath(NULL),
48 tlsAddress(0), tlsIndexAddr(0), tlsInitSize(0), tlsTotalSize(0),
49 tlsCallBackAddr(0), tlsIndex(-1), pResRootDir(NULL),
50 ulRVAResourceSection(0)
51{
52 magic = MAGIC_WINIMAGE;
53
54 if(hInstance != -1) {
55 this->hinstance = hInstance;
56
57 char *name = OSLibGetDllName(hinstance);
58 strcpy(szFileName, name);
59 strupr(szFileName);
60
61 //rename dll (os/2 -> win32) if necessary (i.e. OLE32OS2 -> OLE32)
62 Win32DllBase::renameDll(szFileName, FALSE);
63
64 name = strrchr(szFileName, '\\')+1;
65 strcpy(szModule, name);
66 }
67 else {
68 szModule[0] = 0;
69 this->hinstance = -1;
70 }
71}
72//******************************************************************************
73//******************************************************************************
74Win32ImageBase::~Win32ImageBase()
75{
76 if(fullpath)
77 free(fullpath);
78}
79//******************************************************************************
80//******************************************************************************
81void Win32ImageBase::setFullPath(char *name)
82{
83 if(fullpath)
84 free(fullpath);
85 fullpath = (char *)malloc(strlen(name)+1);
86 strcpy(fullpath, name);
87}
88//******************************************************************************
89//Add image to dependency list of this image
90//******************************************************************************
91void Win32ImageBase::addDependency(Win32DllBase *image)
92{
93 loadedDlls.Push((ULONG)image);
94}
95//******************************************************************************
96//******************************************************************************
97BOOL Win32ImageBase::dependsOn(Win32DllBase *image)
98{
99 QueueItem *item;
100 BOOL ret = FALSE;
101
102 dlllistmutex.enter();
103 item = loadedDlls.Head();
104 while(item) {
105 if(loadedDlls.getItem(item) == (ULONG)image) {
106 ret = TRUE;
107 break;
108 }
109 item = loadedDlls.getNext(item);
110 }
111 dlllistmutex.leave();
112 return ret;
113}
114//******************************************************************************
115//Returns required OS version for this image
116//******************************************************************************
117ULONG Win32ImageBase::getVersion()
118{
119 dprintf(("Win32ImageBase::getVersion: NOT IMPLEMENTED!"));
120 return 0x40000; //NT 4
121}
122//******************************************************************************
123//******************************************************************************
124BOOL Win32ImageBase::insideModule(ULONG address)
125{
126 //dummy
127 return FALSE;
128}
129//******************************************************************************
130//******************************************************************************
131BOOL Win32ImageBase::insideModuleCode(ULONG address)
132{
133 //dummy
134 return FALSE;
135}
136//******************************************************************************
137//******************************************************************************
138ULONG Win32ImageBase::getImageSize()
139{
140 //dummy
141 return 0;
142}
143//******************************************************************************
144//******************************************************************************
145BOOL Win32ImageBase::findDll(const char *szFileName, char *szFullName,
146 int cchFullFileName, const char *pszAltPath)
147{
148 char modname[CCHMAXPATH];
149 HFILE dllfile = NULL;
150 char *imagepath;
151
152 strcpy(szFullName, szFileName);
153 strupr(szFullName);
154 if(!strchr(szFullName, (int)'.')) {
155 strcat(szFullName, DLL_EXTENSION);
156 }
157
158 //search order:
159 //1) exe dir
160 //2) current dir
161 //3) windows system dir (kernel32 path)
162 //4) windows dir
163 //5) path
164 if(WinExe) {
165 strcpy(modname, WinExe->getFullPath());
166 //remove file name from full path
167 imagepath = modname + strlen(modname) - 1;
168 while(*imagepath != '\\')
169 imagepath--;
170 imagepath[1] = 0;
171 strcat(modname, szFullName);
172 dllfile = OSLibDosOpen(modname, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
173 }
174 if(dllfile == NULL)
175 {
176 strcpy(modname, szFullName);
177 dllfile = OSLibDosOpen(szFullName, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
178 if(dllfile == NULL)
179 {
180 strcpy(modname, InternalGetSystemDirectoryA());
181 strcat(modname, "\\");
182 strcat(modname, szFullName);
183 dllfile = OSLibDosOpen(modname, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
184 if(dllfile == NULL)
185 {
186 strcpy(modname, InternalGetWindowsDirectoryA());
187 strcat(modname, "\\");
188 strcat(modname, szFullName);
189 dllfile = OSLibDosOpen(modname, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
190 if(dllfile == NULL) {
191 if(OSLibDosSearchPath(OSLIB_SEARCHENV, "PATH", szFullName, modname, sizeof(modname)) == 0)
192 return FALSE;
193 }
194 }
195 }
196 }
197 strcpy(szFullName, modname);
198 if(dllfile) OSLibDosClose(dllfile);
199 return TRUE;
200}
201
202//******************************************************************************
203//returns ERROR_SUCCESS or error code (Characteristics will contain
204//the Characteristics member of the file header structure)
205//******************************************************************************
206ULONG Win32ImageBase::isPEImage(char *szFileName, DWORD *Characteristics,
207 DWORD *subsystem, DWORD *fNEExe)
208{
209 char filename[CCHMAXPATH];
210 char *syspath;
211 HFILE dllfile;
212 IMAGE_FILE_HEADER fh;
213 IMAGE_OPTIONAL_HEADER oh;
214 HFILE win32handle;
215 ULONG ulAction = 0; /* Action taken by DosOpen */
216 ULONG ulLocal = 0; /* File pointer position after DosSetFilePtr */
217 APIRET rc = NO_ERROR; /* Return code */
218 LPVOID win32file = NULL;
219 ULONG ulRead;
220 int nSections, i;
221
222 if(fNEExe)
223 *fNEExe = FALSE;
224
225 if (!findDll(szFileName, filename, sizeof(filename)))
226 {
227 dprintf(("KERNEL32:Win32ImageBase::isPEImage(%s) findDll failed to find the file.\n",
228 szFileName, rc));
229 return ERROR_FILE_NOT_FOUND_W;
230 }
231 rc = DosOpen(filename, /* File path name */
232 &win32handle, /* File handle */
233 &ulAction, /* Action taken */
234 0L, /* File primary allocation */
235 0L, /* File attribute */
236 OPEN_ACTION_FAIL_IF_NEW |
237 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
238 OPEN_FLAGS_NOINHERIT |
239 OPEN_SHARE_DENYNONE |
240 OPEN_ACCESS_READONLY, /* Open mode of the file */
241 0L); /* No extended attribute */
242
243 if (rc != NO_ERROR)
244 {
245 dprintf(("KERNEL32:Win32ImageBase::isPEImage(%s) failed with %u\n",
246 szFileName, rc));
247 return ERROR_FILE_NOT_FOUND_W;
248 }
249
250 /* Move the file pointer back to the beginning of the file */
251 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
252
253 IMAGE_DOS_HEADER *pdoshdr = (IMAGE_DOS_HEADER *)malloc(sizeof(IMAGE_DOS_HEADER));
254 if(pdoshdr == NULL) {
255 DosClose(win32handle); /* Close the file */
256 return ERROR_INVALID_EXE_SIGNATURE_W;
257 }
258 rc = DosRead(win32handle, pdoshdr, sizeof(IMAGE_DOS_HEADER), &ulRead);
259 if(rc != NO_ERROR || ulRead != sizeof(IMAGE_DOS_HEADER)) {
260 free(pdoshdr);
261 DosClose(win32handle); /* Close the file */
262 return ERROR_INVALID_EXE_SIGNATURE_W;
263 }
264 if(pdoshdr->e_magic != IMAGE_DOS_SIGNATURE) {
265 free(pdoshdr);
266 DosClose(win32handle); /* Close the file */
267 return ERROR_INVALID_EXE_SIGNATURE_W;
268 }
269 ULONG hdrsize = pdoshdr->e_lfanew + SIZE_OF_NT_SIGNATURE + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER);
270 free(pdoshdr);
271
272 /* Move the file pointer back to the beginning of the file */
273 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
274
275 win32file = malloc(hdrsize);
276 if(win32file == NULL) {
277 DosClose(win32handle); /* Close the file */
278 return ERROR_NOT_ENOUGH_MEMORY_W;
279 }
280 rc = DosRead(win32handle, win32file, hdrsize, &ulRead);
281 if(rc != NO_ERROR || ulRead != hdrsize) {
282 goto failure;
283 }
284
285 if(GetPEFileHeader (win32file, &fh) == FALSE)
286 {
287 if(*(WORD *)PE_HEADER(win32file) == IMAGE_OS2_SIGNATURE) {
288 if(fNEExe)
289 *fNEExe = TRUE;
290 }
291 goto failure;
292 }
293 if(GetPEOptionalHeader (win32file, &oh) == FALSE) {
294 goto failure;
295 }
296
297 if(!(fh.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {//not valid
298 goto failure;
299 }
300 if(fh.Machine != IMAGE_FILE_MACHINE_I386) {
301 goto failure;
302 }
303 //IMAGE_FILE_SYSTEM == only drivers (device/file system/video etc)?
304 if(fh.Characteristics & IMAGE_FILE_SYSTEM) {
305 goto failure;
306 }
307 if(Characteristics) {
308 *Characteristics = fh.Characteristics;
309 }
310 if(subsystem) {
311 *subsystem = oh.Subsystem;
312 }
313 DosClose(win32handle);
314 return ERROR_SUCCESS_W;
315
316failure:
317 free(win32file);
318 DosClose(win32handle);
319 return ERROR_INVALID_EXE_SIGNATURE_W;
320}
321//******************************************************************************
322//******************************************************************************
323/**
324 * Static helper which finds the Win32ImageBase object corresponding to hModule.
325 * @returns Pointer to Win32ImageBase object corresponding to hModule.
326 * @param hModule Odin32 modulehandler. 0 and -1 is aliases for the executable module
327 * @status completely implemented and tested.
328 * @author knut st. osmundsen
329 */
330Win32ImageBase * Win32ImageBase::findModule(HMODULE hModule)
331{
332 Win32ImageBase *pRet;
333
334 if (hModule == -1 || hModule == 0 || /* note: WinNt 4, SP4 don't accept -1 as the EXE handle.*/
335 (WinExe != NULL && hModule == WinExe->getInstanceHandle())
336 )
337 pRet = WinExe;
338 else
339 pRet = Win32DllBase::findModule(hModule);
340
341 if (pRet == NULL)
342 {
343 if (WinExe == NULL)
344 dprintf(("Win32ImageBase::findModule: Module not found. WinExe is NULL, hModule=%#x\n", hModule));
345 else
346 dprintf(("Win32ImageBase::findModule: Module not found, hModule=%#x\n", hModule));
347 }
348
349 return pRet;
350}
351
352
353/**
354 * Matches a given filename or module name with the module name of
355 * this object.
356 * @returns TRUE: The modulenames matches.
357 * FALSE: Don't match.
358 * @param pszFilename Pointer to filename or module name.
359 * @status completely implemented.
360 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
361 * @remark Just a clarification:
362 * A module name is the filename of a executable image without
363 * path, but *with* extention.
364 */
365BOOL Win32ImageBase::matchModName(const char *pszFilename) const
366{
367 const char *pszModName; /* Pointer to the modulename. */
368 const char *pszModNameEnd = NULL; /* Pointer to the dot starting the extention. (if any) */
369 register char ch;
370
371 /** @sketch
372 * Search the filename string finding the modulename start and end.
373 * The loop ends when we have passed one char left of the module name.
374 */
375 pszModName = pszFilename + strlen(pszFilename) - 1;
376 while (pszModName >= pszFilename
377 && (ch = *pszModName) != '\\'
378 && ch != '/'
379 && ch != ':'
380 )
381 {
382 pszModName--;
383 }
384 pszModName++;
385
386 /** @sketch
387 * Compare the names caseinsensitivly.
388 */
389 return stricmp(pszModName, szModule) == 0;
390}
Note: See TracBrowser for help on using the repository browser.