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

Last change on this file since 4249 was 4249, checked in by bird, 25 years ago

Added compare function matchModName.

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