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

Last change on this file since 628 was 624, checked in by sandervl, 26 years ago

Exception handler changes

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