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

Last change on this file since 623 was 617, checked in by sandervl, 26 years ago

Exception handler changes

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