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

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

Bugfixes + def files changes

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