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

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

Major changes in PE2LX/KERNEL32 for TLS support. DLL VERSION INCREASED TO 3 AS THIS CHANGE MAKES IT INCOMPATIBLE WITH APPS CONVERTED WITH PREVIOUS VERSION OF PE2LX (OR WIN32K)

File size: 14.3 KB
Line 
1/* $Id: windll.cpp,v 1.7 1999-07-07 08:11:10 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 return rc;
344}
345//******************************************************************************
346//******************************************************************************
347BOOL Win32Dll::attachThread()
348{
349 if(fSystemDll || fSkipEntryCalls)
350 return(TRUE);
351
352 dprintf(("attachThread to dll %s", szModule));
353 return dllEntryPoint(hinstance, DLL_THREAD_ATTACH, 0);
354}
355//******************************************************************************
356//******************************************************************************
357BOOL Win32Dll::detachThread()
358{
359 if(fSystemDll || fSkipEntryCalls)
360 return(TRUE);
361
362 dprintf(("attachThread from dll %s", szModule));
363 return dllEntryPoint(hinstance, DLL_THREAD_DETACH, 0);
364}
365//******************************************************************************
366//Send DLL_THREAD_ATTACH message to all dlls for a new thread
367//******************************************************************************
368void Win32Dll::attachThreadToAllDlls()
369{
370 Win32Dll *dll = Win32Dll::head;
371
372 while(dll) {
373 dll->attachThread();
374 dll = dll->getNext();
375 }
376}
377//******************************************************************************
378//Send DLL_THREAD_DETACH message to all dlls for thread that's about to die
379//******************************************************************************
380void Win32Dll::detachThreadFromAllDlls()
381{
382 Win32Dll *dll = Win32Dll::head;
383
384 while(dll) {
385 dll->detachThread();
386 dll = dll->getNext();
387 }
388}
389//******************************************************************************
390//Setup TLS structure for all dlls for a new thread
391//******************************************************************************
392void Win32Dll::tlsAttachThreadToAllDlls()
393{
394 Win32Dll *dll = Win32Dll::head;
395
396 while(dll) {
397 dll->tlsAttachThread();
398 dll = dll->getNext();
399 }
400}
401//******************************************************************************
402//Destroy TLS structure for all dlls for a thread that's about to die
403//******************************************************************************
404void Win32Dll::tlsDetachThreadFromAllDlls()
405{
406 Win32Dll *dll = Win32Dll::head;
407
408 while(dll) {
409 dll->tlsDetachThread();
410 dll = dll->getNext();
411 }
412}
413//******************************************************************************
414//******************************************************************************
415void Win32Dll::deleteAll()
416{
417 //LIFO removal
418 while(Win32Dll::head) {
419 delete Win32Dll::head;
420 }
421}
422//******************************************************************************
423//******************************************************************************
424Win32Dll *Win32Dll::findModule(char *dllname)
425{
426 Win32Dll *dll = head;
427 char szDllName[CCHMAXPATH];
428 char *dot;
429
430 dprintf(("findModule %s", dllname));
431 strcpy(szDllName, dllname);
432 UpCase(szDllName);
433 dot = strstr(szDllName, ".");
434 if(dot)
435 *dot = 0;
436
437 while(dll) {
438 if(strcmpi(szDllName, dll->szModule) == 0)
439 return(dll);
440
441 dll = dll->next;
442 }
443 return(NULL);
444}
445//******************************************************************************
446//******************************************************************************
447Win32Dll *Win32Dll::findModule(WIN32DLLENTRY DllEntryPoint)
448{
449 Win32Dll *mod = Win32Dll::head;
450
451 dprintf(("findModule %X", DllEntryPoint));
452 while(mod != NULL) {
453 dbgCheckObj(mod);
454 if(mod->dllEntryPoint == DllEntryPoint)
455 return(mod);
456 mod = mod->next;
457 }
458 return(NULL);
459}
460//******************************************************************************
461//******************************************************************************
462Win32Dll *Win32Dll::findModule(HINSTANCE hinstance)
463{
464 Win32Dll *mod = Win32Dll::head;
465
466// eprintf(("findModule inst %X", hinstance));
467 while(mod != NULL) {
468 dbgCheckObj(mod);
469 if(mod->hinstance == hinstance)
470 return(mod);
471 mod = mod->next;
472 }
473 return(NULL);
474}
475//******************************************************************************
476//******************************************************************************
477char *Win32Dll::StripPath(char *path)
478{
479 /* @@@PH what does this function do ? Strip the path from a FQFN name ? */
480 char *pszFilename;
481
482 pszFilename = strrchr(path, '\\'); /* find rightmost slash */
483 if (pszFilename != NULL)
484 return (pszFilename++); /* return pointer to next character */
485
486 pszFilename = strrchr(path, '/'); /* find rightmost slash */
487 if (pszFilename != NULL)
488 return (pszFilename++); /* return pointer to next character */
489
490 return (path); /* default return value */
491
492#if 0
493 char *fname = path, *prevname = path-1;
494
495 while(TRUE)
496 {
497 @@@PH causes endless loop here !
498 fname = strchr(fname, '\\');
499 if(fname == NULL)
500 break;
501
502 prevname = fname;
503 }
504 return(prevname+1);
505#endif
506}
507/******************************************************************************/
508/******************************************************************************/
509Win32Dll *Win32Dll::head = NULL;
Note: See TracBrowser for help on using the repository browser.