source: trunk/src/kernel32/windllbase.cpp@ 2802

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

Added new logging feature

File size: 13.2 KB
Line 
1/* $Id: windllbase.cpp,v 1.9 2000-02-16 14:22:11 sandervl Exp $ */
2
3/*
4 * Win32 Dll base class
5 *
6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * TODO: Unloading of system dlls is not correct for the PE loader
9 * (they're always put at the head of the list even though there
10 * might be a dependency with a win32 dll)
11 *
12 * Project Odin Software License can be found in LICENSE.TXT
13 *
14 */
15#define INCL_DOSFILEMGR /* File Manager values */
16#define INCL_DOSERRORS /* DOS Error values */
17#define INCL_DOSPROCESS /* DOS Process values */
18#define INCL_DOSMODULEMGR
19#define INCL_DOSMISC /* DOS Miscellanous values */
20#define INCL_WIN
21#include <os2wrap.h> //Odin32 OS/2 api wrappers
22#include <stdio.h>
23#include <string.h>
24#include <stdlib.h>
25#include <iostream.h>
26#include <fstream.h>
27#include <misc.h>
28#include <win32type.h>
29#include <pefile.h>
30#include <windllbase.h>
31#include <wprocess.h>
32#include "exceptions.h"
33#include "exceptutil.h"
34#include "cio.h"
35#include "vmutex.h"
36#include "oslibmisc.h"
37#include "oslibdos.h"
38#include "profile.h"
39
40#define DBG_LOCALLOG DBG_windllbase
41#include "dbglocal.h"
42
43VMutex dlllistmutex; //protects linked lists of heaps
44
45//******************************************************************************
46//******************************************************************************
47Win32DllBase::Win32DllBase(HINSTANCE hinstance, WIN32DLLENTRY DllEntryPoint,
48 Win32ImageBase *parent)
49 : Win32ImageBase(hinstance),
50 referenced(0), fSkipEntryCalls(FALSE),
51 fAttachedToProcess(FALSE), fUnloaded(FALSE)
52{
53 dllEntryPoint = DllEntryPoint;
54
55 dlllistmutex.enter();
56 //unload of dlls needs to be done in reverse order of dependencies
57 //Note: Only necessary for pe loader; the OS/2 loader takes care of this
58 //for win32k/pe2lx
59 if(parent && parent->isDll()) {
60 Win32DllBase *dll = head;
61 while(dll) {
62 if(dll->getInstanceHandle() == parent->getInstanceHandle()) {
63 break;
64 }
65 dll = dll->next;
66 }
67 if(dll) {
68 //insert this dll in list after it's parent
69 next = dll->next;
70 dll->next = this;
71 }
72 else DebugInt3();
73 }
74 else {
75 next = head;
76 head = this;
77 }
78 dlllistmutex.leave();
79
80#ifdef DEBUG_ENABLELOG_LEVEL2
81 dlllistmutex.enter();
82 Win32DllBase *dll = head;
83
84 dprintf2(("Win32DllBase::Win32DllBase: List of loaded dlls:"));
85 while(dll) {
86 dprintf2(("DLL %s", dll->szModule));
87 dll = dll->next;
88 }
89 dlllistmutex.leave();
90#endif
91
92 dprintf(("Win32DllBase::Win32DllBase %x %s", hinstance, szModule));
93}
94//******************************************************************************
95//******************************************************************************
96Win32DllBase::~Win32DllBase()
97{
98 Win32DllBase *dll = head;
99
100 dprintf(("Win32DllBase::~Win32DllBase %s", szModule));
101
102 if(errorState == NO_ERROR && !fUnloaded)
103 {
104 detachProcess();
105 }
106
107 dlllistmutex.enter();
108 if(head == this) {
109 head = next;
110 }
111 else {
112 while(dll && dll->next != this) {
113 dll = dll->next;
114 }
115 if(dll == NULL) {
116 dprintf(("~Win32DllBase: Can't find dll!\n"));
117 dlllistmutex.leave();
118 return;
119 }
120 dll->next = next;
121 }
122 dlllistmutex.leave();
123}
124//******************************************************************************
125//ASSUMPTION: called by FreeLibrary
126//******************************************************************************
127ULONG Win32DllBase::Release()
128{
129 ULONG ret = --referenced;
130
131 if(ret == 0) {
132 dprintf(("Win32DllBase::Release, referenced == 0\n"));
133 delete this;
134 }
135 return(ret);
136}
137//******************************************************************************
138//******************************************************************************
139BOOL Win32DllBase::attachProcess()
140{
141 WINEXCEPTION_FRAME exceptFrame;
142 USHORT sel;
143 THDB *thdb;
144 BOOL rc, fSetExceptionHandler;
145
146 if(fAttachedToProcess)
147 return TRUE;
148
149 fAttachedToProcess = TRUE;
150
151 thdb = GetThreadTHDB();
152 fSetExceptionHandler = (!thdb || thdb->teb_sel != GetFS());
153
154 //Note: The Win32 exception structure references by FS:[0] is the same
155 // in OS/2
156 if(fSetExceptionHandler) {
157 OS2SetExceptionHandler((void *)&exceptFrame);
158 sel = SetWin32TIB();
159 }
160
161 //Allocate TLS index for this module
162 tlsAlloc();
163 tlsAttachThread(); //setup TLS (main thread)
164
165 if(fSkipEntryCalls || dllEntryPoint == NULL) {
166 dprintf(("attachProcess not required for dll %s", szModule));
167 if(fSetExceptionHandler) {
168 SetFS(sel);
169 OS2UnsetExceptionHandler((void *)&exceptFrame);
170 }
171 return(TRUE);
172 }
173
174 dprintf(("attachProcess to dll %s", szModule));
175
176 rc = dllEntryPoint(hinstance, DLL_PROCESS_ATTACH, 0);
177
178 dprintf(("attachProcess to dll %s DONE", szModule));
179
180 if(fSetExceptionHandler) {
181 SetFS(sel);
182 OS2UnsetExceptionHandler((void *)&exceptFrame);
183 }
184 return rc;
185}
186//******************************************************************************
187//******************************************************************************
188BOOL Win32DllBase::detachProcess()
189{
190 WINEXCEPTION_FRAME exceptFrame;
191 USHORT sel;
192 BOOL rc;
193
194 if(fSkipEntryCalls || dllEntryPoint == NULL) {
195 tlsDetachThread(); //destroy TLS (main thread)
196 fUnloaded = TRUE;
197 return(TRUE);
198 }
199
200 dprintf(("detachProcess from dll %s", szModule));
201
202 //Note: The Win32 exception structure references by FS:[0] is the same
203 // in OS/2
204 OS2SetExceptionHandler((void *)&exceptFrame);
205
206 fUnloaded = TRUE;
207 sel = SetWin32TIB();
208 rc = dllEntryPoint(hinstance, DLL_PROCESS_DETACH, 0);
209 SetFS(sel);
210 tlsDetachThread(); //destroy TLS (main thread)
211 tlsDelete();
212
213 OS2UnsetExceptionHandler((void *)&exceptFrame);
214
215 return rc;
216}
217//******************************************************************************
218//******************************************************************************
219BOOL Win32DllBase::attachThread()
220{
221 WINEXCEPTION_FRAME exceptFrame;
222 BOOL rc;
223
224 if(fSkipEntryCalls || dllEntryPoint == NULL)
225 return(TRUE);
226
227 dprintf(("attachThread to dll %s", szModule));
228
229 rc = dllEntryPoint(hinstance, DLL_THREAD_ATTACH, 0);
230
231 dprintf(("attachThread to dll %s DONE", szModule));
232
233 return rc;
234}
235//******************************************************************************
236//******************************************************************************
237BOOL Win32DllBase::detachThread()
238{
239 WINEXCEPTION_FRAME exceptFrame;
240 BOOL rc;
241
242 if(fSkipEntryCalls || dllEntryPoint == NULL)
243 return(TRUE);
244
245 dprintf(("detachThread from dll %s", szModule));
246
247 rc = dllEntryPoint(hinstance, DLL_THREAD_DETACH, 0);
248 return rc;
249}
250//******************************************************************************
251//Send DLL_THREAD_ATTACH message to all dlls for a new thread
252//******************************************************************************
253void Win32DllBase::attachThreadToAllDlls()
254{
255 Win32DllBase *dll = Win32DllBase::head;
256 while(dll) {
257 dll->attachThread();
258 dll = dll->getNext();
259 }
260}
261//******************************************************************************
262//Send DLL_THREAD_DETACH message to all dlls for thread that's about to die
263//******************************************************************************
264void Win32DllBase::detachThreadFromAllDlls()
265{
266 Win32DllBase *dll = Win32DllBase::head;
267 while(dll) {
268 dll->detachThread();
269 dll = dll->getNext();
270 }
271}
272//******************************************************************************
273//Setup TLS structure for all dlls for a new thread
274//******************************************************************************
275void Win32DllBase::tlsAttachThreadToAllDlls()
276{
277 Win32DllBase *dll = Win32DllBase::head;
278 while(dll) {
279 dll->tlsAttachThread();
280 dll = dll->getNext();
281 }
282}
283//******************************************************************************
284//Destroy TLS structure for all dlls for a thread that's about to die
285//******************************************************************************
286void Win32DllBase::tlsDetachThreadFromAllDlls()
287{
288 Win32DllBase *dll = Win32DllBase::head;
289 while(dll) {
290 dll->tlsDetachThread();
291 dll = dll->getNext();
292 }
293}
294//******************************************************************************
295//******************************************************************************
296void Win32DllBase::deleteAll()
297{
298#ifdef DEBUG
299 dlllistmutex.enter();
300 Win32DllBase *dll = head;
301
302 dprintf(("Win32DllBase::deleteAll: List of loaded dlls:"));
303 while(dll) {
304 dprintf(("DLL %s", dll->szModule));
305 dll = dll->next;
306 }
307 dlllistmutex.leave();
308#endif
309
310 while(Win32DllBase::head) {
311 delete Win32DllBase::head;
312 }
313}
314//******************************************************************************
315//Add renaming profile strings for ole32 & netapi32 to odin.ini if they aren't
316//already there
317//******************************************************************************
318void Win32DllBase::setDefaultRenaming()
319{
320 char renameddll[CCHMAXPATH];
321
322 if(ODIN_PROFILE_GetOdinIniString(DLLRENAMEWIN_SECTION, "OLE32", "", renameddll,
323 sizeof(renameddll)-1) <= 1)
324 {
325 ODIN_PROFILE_SetOdinIniString(DLLRENAMEWIN_SECTION, "OLE32", "OLE32OS2");
326 ODIN_PROFILE_SetOdinIniString(DLLRENAMEOS2_SECTION, "OLE32OS2", "OLE32");
327 }
328 if(ODIN_PROFILE_GetOdinIniString(DLLRENAMEWIN_SECTION, "OLEAUT32", "", renameddll,
329 sizeof(renameddll)-1) <= 1)
330 {
331 ODIN_PROFILE_SetOdinIniString(DLLRENAMEWIN_SECTION, "OLEAUT32", "OLAUTOS2");
332 ODIN_PROFILE_SetOdinIniString(DLLRENAMEOS2_SECTION, "OLAUTOS2", "OLEAUT32");
333 }
334 if(ODIN_PROFILE_GetOdinIniString(DLLRENAMEWIN_SECTION, "NETAPI32", "", renameddll,
335 sizeof(renameddll)-1) <= 1)
336 {
337 ODIN_PROFILE_SetOdinIniString(DLLRENAMEWIN_SECTION, "NETAPI32", "WNETAP32");
338 ODIN_PROFILE_SetOdinIniString(DLLRENAMEOS2_SECTION, "WNETAP32", "NETAPI32");
339 }
340}
341//******************************************************************************
342//rename dll if necessary:
343// Win32 to OS/2 : (i.e. OLE32 -> OLE32OS2)
344// or
345// OS/2 to Win32 : (i.e. OLE32OS2 -> OLE32)
346//******************************************************************************
347void Win32DllBase::renameDll(char *dllname, BOOL fWinToOS2)
348{
349 char modname[CCHMAXPATH];
350 char renameddll[CCHMAXPATH];
351 char *namestart;
352 char *sectionname;
353
354 if(fWinToOS2) {
355 sectionname = DLLRENAMEWIN_SECTION;
356 }
357 else {
358 sectionname = DLLRENAMEOS2_SECTION;
359 }
360 namestart = OSLibStripPath(dllname);
361 strcpy(modname, namestart);
362 char *dot = strrchr(modname, '.');
363 if(dot)
364 *dot = 0;
365 strupr(modname);
366 if(ODIN_PROFILE_GetOdinIniString(sectionname, modname, "", renameddll,
367 sizeof(renameddll)-1) > 1)
368 {
369 if(namestart == dllname) {
370 strcpy(dllname, renameddll);
371 }
372 else {
373 *namestart = 0;
374 strcat(dllname, renameddll);
375 }
376 strcat(dllname, ".dll");
377 }
378 return;
379}
380//******************************************************************************
381//******************************************************************************
382Win32DllBase *Win32DllBase::findModule(char *dllname)
383{
384 Win32DllBase *dll;
385 char szDllName[CCHMAXPATH];
386 char *dot, *temp;
387
388 dprintf(("findModule %s", dllname));
389
390 strcpy(szDllName, OSLibStripPath(dllname));
391 strupr(szDllName);
392 dot = strstr(szDllName, ".");
393 if(dot)
394 *dot = 0;
395
396 dlllistmutex.enter();
397 dll = head;
398 while(dll) {
399 if(strcmpi(szDllName, dll->szModule) == 0) {
400 dlllistmutex.leave();
401 return(dll);
402 }
403
404 dll = dll->next;
405 }
406 dlllistmutex.leave();
407 return(NULL);
408}
409//******************************************************************************
410//******************************************************************************
411Win32DllBase *Win32DllBase::findModule(WIN32DLLENTRY DllEntryPoint)
412{
413 dprintf(("findModule %X", DllEntryPoint));
414
415 dlllistmutex.enter();
416 Win32DllBase *mod = Win32DllBase::head;
417 while(mod != NULL) {
418 dbgCheckObj(mod);
419 if(mod->dllEntryPoint == DllEntryPoint) {
420 dlllistmutex.leave();
421 return(mod);
422 }
423 mod = mod->next;
424 }
425 dlllistmutex.leave();
426 return(NULL);
427}
428//******************************************************************************
429//******************************************************************************
430Win32DllBase *Win32DllBase::findModule(HINSTANCE hinstance)
431{
432 dlllistmutex.enter();
433
434 Win32DllBase *mod = Win32DllBase::head;
435 while(mod != NULL) {
436 dbgCheckObj(mod);
437 if(mod->hinstance == hinstance) {
438 dlllistmutex.leave();
439 return(mod);
440 }
441 mod = mod->next;
442 }
443 dlllistmutex.leave();
444 return(NULL);
445}
446//******************************************************************************
447//******************************************************************************
448BOOL Win32DllBase::isDll()
449{
450 return TRUE;
451}
452//******************************************************************************
453//******************************************************************************
454void Win32DllBase::setThreadLibraryCalls(BOOL fEnable)
455{
456 // if fEnable == true, do call the ATTACH_THREAD, DETACH_THREAD functions
457 // if fEnable == false, do not call the ATTACH_THREAD, DETACH_THREAD functions
458 fSkipEntryCalls = !fEnable;
459}
460
461//******************************************************************************
462//******************************************************************************
463Win32DllBase *Win32DllBase::head = NULL;
Note: See TracBrowser for help on using the repository browser.