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

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

* empty log message *

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