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

Last change on this file since 9752 was 9617, checked in by sandervl, 23 years ago

added dll load hook and function to override named or ordinal exports

File size: 13.7 KB
Line 
1/* $Id: winimagebase.cpp,v 1.36 2003-01-05 12:31: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), fIsPEImage(FALSE)
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//******************************************************************************
156ULONG Win32ImageBase::setApi(char *name, ULONG pfnNewProc)
157{
158 return -1; //only implemented for PE modules
159}
160//******************************************************************************
161//******************************************************************************
162ULONG Win32ImageBase::setApi(int ordinal, ULONG pfnNewProc)
163{
164 return -1; //only implemented for PE modules
165}
166//******************************************************************************
167//******************************************************************************
168BOOL Win32ImageBase::findDll(const char *szFileName, char *szFullName,
169 int cchFullFileName, const char *pszAltPath)
170{
171 char modname[CCHMAXPATH];
172 HFILE dllfile = NULL;
173 char *imagepath;
174
175 strcpy(szFullName, szFileName);
176 strupr(szFullName);
177 if(!strchr(szFullName, (int)'.')) {
178 strcat(szFullName, DLL_EXTENSION);
179 }
180
181 //search order:
182 //1) exe dir
183 //2) current dir
184 //3) windows system dir (kernel32 path)
185 //4) windows dir
186 //5) path
187 if(WinExe) {
188 strcpy(modname, WinExe->getFullPath());
189 //remove file name from full path
190 imagepath = modname + strlen(modname) - 1;
191 while(*imagepath != '\\')
192 imagepath--;
193 imagepath[1] = 0;
194 strcat(modname, szFullName);
195 dllfile = OSLibDosOpen(modname, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
196 }
197 if(dllfile == NULL)
198 {
199 strcpy(modname, szFullName);
200 dllfile = OSLibDosOpen(szFullName, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
201 if(dllfile == NULL)
202 {
203 strcpy(modname, InternalGetSystemDirectoryA());
204 strcat(modname, "\\");
205 strcat(modname, szFullName);
206 dllfile = OSLibDosOpen(modname, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
207 if(dllfile == NULL)
208 {
209 strcpy(modname, InternalGetWindowsDirectoryA());
210 strcat(modname, "\\");
211 strcat(modname, szFullName);
212 dllfile = OSLibDosOpen(modname, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
213 if(dllfile == NULL) {
214 if(OSLibDosSearchPath(OSLIB_SEARCHENV, "PATH", szFullName, modname, sizeof(modname)) == 0)
215 return FALSE;
216 }
217 }
218 }
219 }
220 strcpy(szFullName, modname);
221 if(dllfile) OSLibDosClose(dllfile);
222 return TRUE;
223}
224
225//******************************************************************************
226//returns ERROR_SUCCESS or error code (Characteristics will contain
227//the Characteristics member of the file header structure)
228//******************************************************************************
229ULONG Win32ImageBase::isPEImage(char *szFileName, DWORD *Characteristics,
230 DWORD *subsystem, DWORD *fNEExe)
231{
232 char filename[CCHMAXPATH];
233 char *syspath;
234 HFILE dllfile;
235 IMAGE_FILE_HEADER fh;
236 IMAGE_OPTIONAL_HEADER oh;
237 HFILE win32handle;
238 ULONG ulAction = 0; /* Action taken by DosOpen */
239 ULONG ulLocal = 0; /* File pointer position after DosSetFilePtr */
240 APIRET rc = NO_ERROR; /* Return code */
241 LPVOID win32file = NULL;
242 ULONG ulRead;
243 int nSections, i;
244
245 if(fNEExe)
246 *fNEExe = FALSE;
247
248 if (!findDll(szFileName, filename, sizeof(filename)))
249 {
250 dprintf(("KERNEL32:Win32ImageBase::isPEImage(%s) findDll failed to find the file.\n",
251 szFileName, rc));
252 return ERROR_FILE_NOT_FOUND_W;
253 }
254 rc = DosOpen(filename, /* File path name */
255 &win32handle, /* File handle */
256 &ulAction, /* Action taken */
257 0L, /* File primary allocation */
258 0L, /* File attribute */
259 OPEN_ACTION_FAIL_IF_NEW |
260 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
261 OPEN_FLAGS_NOINHERIT |
262 OPEN_SHARE_DENYNONE |
263 OPEN_ACCESS_READONLY, /* Open mode of the file */
264 0L); /* No extended attribute */
265
266 if (rc != NO_ERROR)
267 {
268 dprintf(("KERNEL32:Win32ImageBase::isPEImage(%s) failed with %u\n",
269 szFileName, rc));
270 return ERROR_FILE_NOT_FOUND_W;
271 }
272
273 /* Move the file pointer back to the beginning of the file */
274 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
275
276 IMAGE_DOS_HEADER *pdoshdr = (IMAGE_DOS_HEADER *)malloc(sizeof(IMAGE_DOS_HEADER));
277 if(pdoshdr == NULL) {
278 DosClose(win32handle); /* Close the file */
279 return ERROR_INVALID_EXE_SIGNATURE_W;
280 }
281 rc = DosRead(win32handle, pdoshdr, sizeof(IMAGE_DOS_HEADER), &ulRead);
282 if(rc != NO_ERROR || ulRead != sizeof(IMAGE_DOS_HEADER)) {
283 free(pdoshdr);
284 DosClose(win32handle); /* Close the file */
285 return ERROR_INVALID_EXE_SIGNATURE_W;
286 }
287 if(pdoshdr->e_magic != IMAGE_DOS_SIGNATURE) {
288 free(pdoshdr);
289 DosClose(win32handle); /* Close the file */
290 return ERROR_INVALID_EXE_SIGNATURE_W;
291 }
292 ULONG hdrsize = pdoshdr->e_lfanew + SIZE_OF_NT_SIGNATURE + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER);
293 free(pdoshdr);
294
295 /* Move the file pointer back to the beginning of the file */
296 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
297
298 win32file = malloc(hdrsize);
299 if(win32file == NULL) {
300 DosClose(win32handle); /* Close the file */
301 return ERROR_NOT_ENOUGH_MEMORY_W;
302 }
303 rc = DosRead(win32handle, win32file, hdrsize, &ulRead);
304 if(rc != NO_ERROR || ulRead != hdrsize) {
305 goto failure;
306 }
307
308 if(GetPEFileHeader (win32file, &fh) == FALSE)
309 {
310 if(*(WORD *)PE_HEADER(win32file) == IMAGE_OS2_SIGNATURE) {
311 if(fNEExe)
312 *fNEExe = TRUE;
313 }
314 goto failure;
315 }
316 if(GetPEOptionalHeader (win32file, &oh) == FALSE) {
317 goto failure;
318 }
319
320 if(!(fh.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {//not valid
321 goto failure;
322 }
323 if(fh.Machine != IMAGE_FILE_MACHINE_I386) {
324 goto failure;
325 }
326 //IMAGE_FILE_SYSTEM == only drivers (device/file system/video etc)?
327 if(fh.Characteristics & IMAGE_FILE_SYSTEM) {
328 goto failure;
329 }
330 if(Characteristics) {
331 *Characteristics = fh.Characteristics;
332 }
333 if(subsystem) {
334 *subsystem = oh.Subsystem;
335 }
336
337 free(win32file);
338 DosClose(win32handle);
339 return ERROR_SUCCESS_W;
340
341failure:
342 free(win32file);
343 DosClose(win32handle);
344 return ERROR_INVALID_EXE_SIGNATURE_W;
345}
346//******************************************************************************
347//******************************************************************************
348/**
349 * Static helper which finds the Win32ImageBase object corresponding to hModule.
350 * @returns Pointer to Win32ImageBase object corresponding to hModule.
351 * @param hModule Odin32 modulehandler. 0 and -1 is aliases for the executable module
352 * @status completely implemented and tested.
353 * @author knut st. osmundsen
354 */
355Win32ImageBase * Win32ImageBase::findModule(HMODULE hModule)
356{
357 Win32ImageBase *pRet;
358
359 if (hModule == -1 || hModule == 0 || /* note: WinNt 4, SP4 don't accept -1 as the EXE handle.*/
360 (WinExe != NULL && hModule == WinExe->getInstanceHandle())
361 )
362 pRet = WinExe;
363 else
364 pRet = Win32DllBase::findModule(hModule);
365
366 if (pRet == NULL)
367 {
368 if (WinExe == NULL)
369 dprintf(("Win32ImageBase::findModule: Module not found. WinExe is NULL, hModule=%#x\n", hModule));
370 else
371 dprintf(("Win32ImageBase::findModule: Module not found, hModule=%#x\n", hModule));
372 }
373
374 return pRet;
375}
376
377
378/**
379 * Matches a given filename or module name with the module name of
380 * this object.
381 * @returns TRUE: The modulenames matches.
382 * FALSE: Don't match.
383 * @param pszFilename Pointer to filename or module name.
384 * @status completely implemented.
385 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
386 * @remark Just a clarification:
387 * A module name is the filename of a executable image without
388 * path, but *with* extention.
389 */
390BOOL Win32ImageBase::matchModName(const char *pszFilename) const
391{
392 const char *pszModName; /* Pointer to the modulename. */
393 const char *pszModNameEnd = NULL; /* Pointer to the dot starting the extention. (if any) */
394 register char ch;
395
396 /** @sketch
397 * Search the filename string finding the modulename start and end.
398 * The loop ends when we have passed one char left of the module name.
399 */
400 pszModName = pszFilename + strlen(pszFilename) - 1;
401 while (pszModName >= pszFilename
402 && (ch = *pszModName) != '\\'
403 && ch != '/'
404 && ch != ':'
405 )
406 {
407 pszModName--;
408 }
409 pszModName++;
410
411 /** @sketch
412 * Compare the names caseinsensitivly.
413 */
414 return stricmp(pszModName, szModule) == 0;
415}
Note: See TracBrowser for help on using the repository browser.