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

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

Cleanup

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