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

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

Backup copy of old kernel32

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