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

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

check executable type in CreateProcess and use PEC for VIO and PE for GUI apps

File size: 12.7 KB
Line 
1/* $Id: winimagebase.cpp,v 1.31 2001-04-02 22:51:58 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, DWORD *subsystem)
207{
208 char filename[CCHMAXPATH];
209 char *syspath;
210 HFILE dllfile;
211 IMAGE_FILE_HEADER fh;
212 IMAGE_OPTIONAL_HEADER oh;
213 HFILE win32handle;
214 ULONG ulAction = 0; /* Action taken by DosOpen */
215 ULONG ulLocal = 0; /* File pointer position after DosSetFilePtr */
216 APIRET rc = NO_ERROR; /* Return code */
217 LPVOID win32file = NULL;
218 ULONG ulRead;
219 int nSections, i;
220
221 if (!findDll(szFileName, filename, sizeof(filename)))
222 {
223 dprintf(("KERNEL32:Win32ImageBase::isPEImage(%s) findDll failed to find the file.\n",
224 szFileName, rc));
225 return ERROR_FILE_NOT_FOUND_W;
226 }
227 rc = DosOpen(filename, /* File path name */
228 &win32handle, /* File handle */
229 &ulAction, /* Action taken */
230 0L, /* File primary allocation */
231 0L, /* File attribute */
232 OPEN_ACTION_FAIL_IF_NEW |
233 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
234 OPEN_FLAGS_NOINHERIT |
235 OPEN_SHARE_DENYNONE |
236 OPEN_ACCESS_READONLY, /* Open mode of the file */
237 0L); /* No extended attribute */
238
239 if (rc != NO_ERROR)
240 {
241 dprintf(("KERNEL32:Win32ImageBase::isPEImage(%s) failed with %u\n",
242 szFileName, rc));
243 return ERROR_FILE_NOT_FOUND_W;
244 }
245
246 /* Move the file pointer back to the beginning of the file */
247 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
248
249 IMAGE_DOS_HEADER *pdoshdr = (IMAGE_DOS_HEADER *)malloc(sizeof(IMAGE_DOS_HEADER));
250 if(pdoshdr == NULL) {
251 DosClose(win32handle); /* Close the file */
252 return ERROR_INVALID_EXE_SIGNATURE_W;
253 }
254 rc = DosRead(win32handle, pdoshdr, sizeof(IMAGE_DOS_HEADER), &ulRead);
255 if(rc != NO_ERROR || ulRead != sizeof(IMAGE_DOS_HEADER)) {
256 free(pdoshdr);
257 DosClose(win32handle); /* Close the file */
258 return ERROR_INVALID_EXE_SIGNATURE_W;
259 }
260 if(pdoshdr->e_magic != IMAGE_DOS_SIGNATURE) {
261 free(pdoshdr);
262 DosClose(win32handle); /* Close the file */
263 return ERROR_INVALID_EXE_SIGNATURE_W;
264 }
265 ULONG hdrsize = pdoshdr->e_lfanew + SIZE_OF_NT_SIGNATURE + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER);
266 free(pdoshdr);
267
268 /* Move the file pointer back to the beginning of the file */
269 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
270
271 win32file = malloc(hdrsize);
272 if(win32file == NULL) {
273 DosClose(win32handle); /* Close the file */
274 return ERROR_NOT_ENOUGH_MEMORY_W;
275 }
276 rc = DosRead(win32handle, win32file, hdrsize, &ulRead);
277 if(rc != NO_ERROR || ulRead != hdrsize) {
278 goto failure;
279 }
280
281 if(GetPEFileHeader (win32file, &fh) == FALSE) {
282 goto failure;
283 }
284 if(GetPEOptionalHeader (win32file, &oh) == FALSE) {
285 goto failure;
286 }
287
288 if(!(fh.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {//not valid
289 goto failure;
290 }
291 if(fh.Machine != IMAGE_FILE_MACHINE_I386) {
292 goto failure;
293 }
294 //IMAGE_FILE_SYSTEM == only drivers (device/file system/video etc)?
295 if(fh.Characteristics & IMAGE_FILE_SYSTEM) {
296 goto failure;
297 }
298 if(Characteristics) {
299 *Characteristics = fh.Characteristics;
300 }
301 if(subsystem) {
302 *subsystem = oh.Subsystem;
303 }
304 DosClose(win32handle);
305 return ERROR_SUCCESS_W;
306
307failure:
308 free(win32file);
309 DosClose(win32handle);
310 return ERROR_INVALID_EXE_SIGNATURE_W;
311}
312//******************************************************************************
313//******************************************************************************
314/**
315 * Static helper which finds the Win32ImageBase object corresponding to hModule.
316 * @returns Pointer to Win32ImageBase object corresponding to hModule.
317 * @param hModule Odin32 modulehandler. 0 and -1 is aliases for the executable module
318 * @status completely implemented and tested.
319 * @author knut st. osmundsen
320 */
321Win32ImageBase * Win32ImageBase::findModule(HMODULE hModule)
322{
323 Win32ImageBase *pRet;
324
325 if (hModule == -1 || hModule == 0 || /* note: WinNt 4, SP4 don't accept -1 as the EXE handle.*/
326 (WinExe != NULL && hModule == WinExe->getInstanceHandle())
327 )
328 pRet = WinExe;
329 else
330 pRet = Win32DllBase::findModule(hModule);
331
332 if (pRet == NULL)
333 {
334 if (WinExe == NULL)
335 dprintf(("Win32ImageBase::findModule: Module not found. WinExe is NULL, hModule=%#x\n", hModule));
336 else
337 dprintf(("Win32ImageBase::findModule: Module not found, hModule=%#x\n", hModule));
338 }
339
340 return pRet;
341}
342
343
344/**
345 * Matches a given filename or module name with the module name of
346 * this object.
347 * @returns TRUE: The modulenames matches.
348 * FALSE: Don't match.
349 * @param pszFilename Pointer to filename or module name.
350 * @status completely implemented.
351 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
352 * @remark Just a clarification:
353 * A module name is the filename of a executable image without
354 * path, but *with* extention.
355 */
356BOOL Win32ImageBase::matchModName(const char *pszFilename) const
357{
358 const char *pszModName; /* Pointer to the modulename. */
359 const char *pszModNameEnd = NULL; /* Pointer to the dot starting the extention. (if any) */
360 register char ch;
361
362 /** @sketch
363 * Search the filename string finding the modulename start and end.
364 * The loop ends when we have passed one char left of the module name.
365 */
366 pszModName = pszFilename + strlen(pszFilename) - 1;
367 while (pszModName >= pszFilename
368 && (ch = *pszModName) != '\\'
369 && ch != '/'
370 && ch != ':'
371 )
372 {
373 pszModName--;
374 }
375 pszModName++;
376
377 /** @sketch
378 * Compare the names caseinsensitivly.
379 */
380 return stricmp(pszModName, szModule) == 0;
381}
Note: See TracBrowser for help on using the repository browser.