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

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

custom build fixes

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