source: trunk/src/kernel32/windll.cpp@ 596

Last change on this file since 596 was 550, checked in by sandervl, 26 years ago

PE loader changes

File size: 12.7 KB
Line 
1/* $Id: windll.cpp,v 1.10 1999-08-18 17:18:00 sandervl Exp $ */
2
3/*
4 * Win32 DLL class
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#define INCL_DOSFILEMGR /* File Manager values */
13#define INCL_DOSERRORS /* DOS Error values */
14#define INCL_DOSPROCESS /* DOS Process values */
15#define INCL_DOSMODULEMGR
16#define INCL_DOSMISC /* DOS Miscellanous values */
17#define INCL_WIN
18#include <os2wrap.h> //Odin32 OS/2 api wrappers
19#include <stdio.h>
20#include <string.h>
21#include <stdlib.h>
22#include <iostream.h>
23#include <fstream.h>
24#include <misc.h>
25#include <nameid.h>
26#include <win32type.h>
27#include <pefile.h>
28#include <windll.h>
29#include <wprocess.h>
30#include "cio.h"
31
32/***********************************
33 * PH: fixups for missing os2win.h *
34 ***********************************/
35
36void _System SetLastError(ULONG ulError);
37
38//******************************************************************************
39//******************************************************************************
40Win32Dll::Win32Dll(char *szDllName) : Win32Image(szDllName), referenced(0),
41 fSkipEntryCalls(FALSE), fSystemDll(FALSE)
42{
43 fSystemDll = isSystemDll(szFileName);
44 fUnloaded = FALSE;
45 next = head;
46 head = this;
47
48 dprintf(("Win32Dll::Win32Dll %s %s", szFileName, szModule));
49}
50//******************************************************************************
51//******************************************************************************
52Win32Dll::Win32Dll(HINSTANCE hinstance, int NameTableId, int Win32TableId,
53 WIN32DLLENTRY DllEntryPoint) :
54 Win32Image(hinstance, NameTableId, Win32TableId),
55 referenced(0), fSkipEntryCalls(FALSE), fSystemDll(FALSE)
56{
57 dllEntryPoint = DllEntryPoint;
58 fUnloaded = FALSE;
59 next = head;
60 head = this;
61
62 dprintf(("Win32Dll::Win32Dll %s", szModule));
63}
64//******************************************************************************
65//******************************************************************************
66void Win32Dll::OS2DllInit(HINSTANCE hinstance, int NameTableId, int Win32TableId,
67 WIN32DLLENTRY DllEntryPoint)
68{
69 dllEntryPoint = DllEntryPoint;
70 fUnloaded = FALSE;
71
72 Win32Image::OS2ImageInit(hinstance, NameTableId, Win32TableId);
73}
74//******************************************************************************
75//******************************************************************************
76Win32Dll::~Win32Dll()
77{
78 Win32Dll *dll = head;
79
80 dprintf(("Win32Dll::~Win32Dll %s", szModule));
81
82 //first remove it from the linked list so converted win32 dlls won't
83 //be deleted twice (as DosFreeModule results in a call to DllExitList (wprocess.cpp)
84 if(head == this) {
85 head = next;
86 }
87 else {
88 while(dll && dll->next != this) {
89 dll = dll->next;
90 }
91 if(dll == NULL) {
92 dprintf(("~Win32Dll: Can't find dll!\n"));
93 return;
94 }
95 dll->next = next;
96 }
97 if(errorState == NO_ERROR && !fUnloaded)
98 {
99 detachProcess();
100 }
101}
102//******************************************************************************
103//ASSUMPTION: called by FreeLibrary
104//******************************************************************************
105ULONG Win32Dll::Release()
106{
107 ULONG ret = --referenced;
108
109 if(ret == 0) {
110 dprintf(("Win32Dll::Release, referenced == 0\n"));
111 if(fSystemDll) {
112 DosFreeModule((HMODULE)hinstance);
113 fUnloaded = TRUE;
114 }
115 delete this;
116 }
117 return(ret);
118}
119//******************************************************************************
120//******************************************************************************
121BOOL Win32Dll::init(ULONG reservedMem)
122{
123 char *syspath;
124 FILE *dllfile;
125 APIRET rc;
126 BOOL fRet;
127
128 if(fSystemDll == FALSE && fNativePEImage == TRUE)
129 {//might be win32 dll, so check this
130 dllfile = fopen(szFileName, "r");
131 if(dllfile == NULL) {//search in libpath for dll
132 syspath = getenv("WIN32LIBPATH");
133 if(syspath) {
134 strcpy(szModule, syspath);
135 if(szModule[strlen(szModule)-1] != '\\') {
136 strcat(szModule, "\\");
137 }
138 strcat(szModule, szFileName);
139 szFileName = szModule;
140 }
141 }
142 else fclose(dllfile);
143 if(isPEImage(szFileName) == TRUE) {
144 fRet = Win32Image::init(0);
145 dllEntryPoint = (WIN32DLLENTRY)entryPoint;
146 return fRet;
147 }
148 //converted win32 dll
149 fNativePEImage = FALSE;
150 }
151 //else load system dlls using DosLoadModule
152 char szModuleFailure[CCHMAXPATH] = "";
153
154 rc = DosLoadModule(szModuleFailure, sizeof(szModuleFailure), szFileName, (HMODULE *)&hinstance);
155 if(rc) {
156 dprintf(("DosLoadModule returned %X for %s\n", rc, szModuleFailure));
157 errorState = rc;
158 return(FALSE);
159 }
160 return(TRUE);
161}
162//******************************************************************************
163char *sysmodules[] = {"KERNEL32", "USER32", "GDI32", "WINMM", "DSOUND", "DDRAW",
164 "WNETAP32", "MPR", "OLE32", "ADVAPI32", "COMDLG32",
165 "WINSPOOL", "SHELL32", "TAPI32", "CAPI32", "VERSION",
166 "WSOCK32", "COMCTL32", "NTDLL"};
167//******************************************************************************
168BOOL Win32Dll::isSystemDll(char *szFileName)
169{
170 int i;
171 char *dot;
172 char szModule[CCHMAXPATH];
173
174 strcpy(szModule, szFileName);
175 strupr(szModule);
176 dot = strstr(szModule, ".");
177 if(dot)
178 *dot = 0;
179
180 for(i=0;i<sizeof(sysmodules)/sizeof(char *);i++) {
181 if(!strcmp(szModule, sysmodules[i]))
182 return(TRUE);
183 }
184 return(FALSE);
185}
186//******************************************************************************
187//Could be more efficient, but I bet this is faster than the OS/2 loader!
188//******************************************************************************
189ULONG Win32Dll::getApi(char *name)
190{
191 APIRET rc;
192 ULONG apiaddr, i, apilen;
193 char *apiname;
194 char tmp[4];
195 NameExport *curexport;
196 ULONG ulAPIOrdinal; /* api requested by ordinal */
197
198 apilen = strlen(name) + 1;
199 if(apilen < 4)
200 {
201 *(ULONG *)tmp = 0;
202 strcpy(tmp, name);
203 apiname = tmp;
204 }
205 else apiname = name;
206
207 curexport = nameexports;
208 for(i=0;
209 i<nrNameExports;
210 i++)
211 {
212 if(apilen == curexport->nlength &&
213 *(ULONG *)curexport->name == *(ULONG *)name)
214 {
215 if(strcmp(curexport->name, name) == 0)
216 return(curexport->virtaddr);
217 }
218 curexport = (NameExport *)((ULONG)curexport->name + curexport->nlength);
219 }
220
221 if(fSystemDll || !fNativePEImage)
222 {
223 rc = DosQueryProcAddr(hinstance, 0, name, (PFN *)&apiaddr);
224 if(rc)
225 {
226 SetLastError(rc); /* raise error condition */
227 return(0);
228 }
229
230 //Add to lookup table, so we don't have to call DosQueryProcAddr
231 //multiple times for the same api (when imported by other dlls)
232 AddNameExport(apiaddr, name, 0);
233 return(apiaddr);
234 }
235 return(0);
236}
237//******************************************************************************
238//******************************************************************************
239ULONG Win32Dll::getApi(int ordinal)
240{
241 APIRET rc;
242 ULONG apiaddr, i;
243 OrdExport *curexport;
244 NameExport *nexport;
245
246 if(fSystemDll || !fNativePEImage) {
247 rc = DosQueryProcAddr(hinstance, ordinal, NULL, (PFN *)&apiaddr);
248 if(rc) return(0);
249 else return(apiaddr);
250 }
251 curexport = ordexports;
252 for(i=0;i<nrOrdExports;i++) {
253 if(curexport->ordinal == ordinal)
254 return(curexport->virtaddr);
255 curexport++;
256 }
257 //Name exports also contain an ordinal, so check this
258 nexport = nameexports;
259 for(i=0;i<nrNameExports;i++) {
260 if(nexport->ordinal == ordinal)
261 return(nexport->virtaddr);
262 nexport = (NameExport *)((ULONG)nexport->name + nexport->nlength);
263 }
264 return(0);
265}
266//******************************************************************************
267//******************************************************************************
268BOOL Win32Dll::attachProcess()
269{
270 BOOL rc;
271 USHORT sel;
272
273 //Allocate TLS index for this module
274 tlsAlloc();
275 tlsAttachThread(); //setup TLS (main thread)
276
277 if(fSystemDll || fSkipEntryCalls) {
278 dprintf(("attachProcess not required for dll %s", szModule));
279 return(TRUE);
280 }
281
282 dprintf(("attachProcess to dll %s", szModule));
283
284 sel = SetWin32TIB();
285 rc = dllEntryPoint(hinstance, DLL_PROCESS_ATTACH, 0);
286 SetFS(sel);
287 return rc;
288}
289//******************************************************************************
290//******************************************************************************
291BOOL Win32Dll::detachProcess()
292{
293 BOOL rc;
294 USHORT sel;
295
296 if(fSystemDll || fSkipEntryCalls) {
297 tlsDetachThread(); //destroy TLS (main thread)
298 return(TRUE);
299 }
300
301 dprintf(("detachProcess from dll %s", szModule));
302
303 fUnloaded = TRUE;
304 sel = SetWin32TIB();
305 rc = dllEntryPoint(hinstance, DLL_PROCESS_DETACH, 0);
306 SetFS(sel);
307 tlsDetachThread(); //destroy TLS (main thread)
308 tlsDelete();
309 return rc;
310}
311//******************************************************************************
312//******************************************************************************
313BOOL Win32Dll::attachThread()
314{
315 if(fSystemDll || fSkipEntryCalls)
316 return(TRUE);
317
318 dprintf(("attachThread to dll %s", szModule));
319 return dllEntryPoint(hinstance, DLL_THREAD_ATTACH, 0);
320}
321//******************************************************************************
322//******************************************************************************
323BOOL Win32Dll::detachThread()
324{
325 if(fSystemDll || fSkipEntryCalls)
326 return(TRUE);
327
328 dprintf(("attachThread from dll %s", szModule));
329 return dllEntryPoint(hinstance, DLL_THREAD_DETACH, 0);
330}
331//******************************************************************************
332//Send DLL_THREAD_ATTACH message to all dlls for a new thread
333//******************************************************************************
334void Win32Dll::attachThreadToAllDlls()
335{
336 Win32Dll *dll = Win32Dll::head;
337
338 while(dll) {
339 dll->attachThread();
340 dll = dll->getNext();
341 }
342}
343//******************************************************************************
344//Send DLL_THREAD_DETACH message to all dlls for thread that's about to die
345//******************************************************************************
346void Win32Dll::detachThreadFromAllDlls()
347{
348 Win32Dll *dll = Win32Dll::head;
349
350 while(dll) {
351 dll->detachThread();
352 dll = dll->getNext();
353 }
354}
355//******************************************************************************
356//Setup TLS structure for all dlls for a new thread
357//******************************************************************************
358void Win32Dll::tlsAttachThreadToAllDlls()
359{
360 Win32Dll *dll = Win32Dll::head;
361
362 while(dll) {
363 dll->tlsAttachThread();
364 dll = dll->getNext();
365 }
366}
367//******************************************************************************
368//Destroy TLS structure for all dlls for a thread that's about to die
369//******************************************************************************
370void Win32Dll::tlsDetachThreadFromAllDlls()
371{
372 Win32Dll *dll = Win32Dll::head;
373
374 while(dll) {
375 dll->tlsDetachThread();
376 dll = dll->getNext();
377 }
378}
379//******************************************************************************
380//******************************************************************************
381void Win32Dll::deleteAll()
382{
383 //LIFO removal
384 while(Win32Dll::head) {
385 delete Win32Dll::head;
386 }
387}
388//******************************************************************************
389//******************************************************************************
390Win32Dll *Win32Dll::findModule(char *dllname)
391{
392 Win32Dll *dll = head;
393 char szDllName[CCHMAXPATH];
394 char *dot, *temp;
395
396 dprintf(("findModule %s", dllname));
397
398 strcpy(szDllName, StripPath(dllname));
399 strupr(szDllName);
400 dot = strstr(szDllName, ".");
401 if(dot)
402 *dot = 0;
403
404 while(dll) {
405 if(strcmpi(szDllName, dll->szModule) == 0)
406 return(dll);
407
408 dll = dll->next;
409 }
410 return(NULL);
411}
412//******************************************************************************
413//******************************************************************************
414Win32Dll *Win32Dll::findModule(WIN32DLLENTRY DllEntryPoint)
415{
416 Win32Dll *mod = Win32Dll::head;
417
418 dprintf(("findModule %X", DllEntryPoint));
419 while(mod != NULL) {
420 dbgCheckObj(mod);
421 if(mod->dllEntryPoint == DllEntryPoint)
422 return(mod);
423 mod = mod->next;
424 }
425 return(NULL);
426}
427//******************************************************************************
428//******************************************************************************
429Win32Dll *Win32Dll::findModule(HINSTANCE hinstance)
430{
431 Win32Dll *mod = Win32Dll::head;
432
433// eprintf(("findModule inst %X", hinstance));
434 while(mod != NULL) {
435 dbgCheckObj(mod);
436 if(mod->hinstance == hinstance)
437 return(mod);
438 mod = mod->next;
439 }
440 return(NULL);
441}
442//******************************************************************************
443//******************************************************************************
444Win32Dll *Win32Dll::head = NULL;
Note: See TracBrowser for help on using the repository browser.