source: trunk/src/kernel32/old/windll.cpp@ 1570

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

Compilation fixes

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