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

Last change on this file since 3005 was 3005, checked in by sandervl, 25 years ago

DosOpen (file handle error) & dll destruction bugfixes

File size: 13.3 KB
Line 
1/* $Id: windllbase.cpp,v 1.10 2000-03-04 19:52:36 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), fDynamicLoad(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 dprintf(("Win32DllBase::~Win32DllBase %s", szModule));
99
100 if(errorState == NO_ERROR && !fUnloaded)
101 {
102 detachProcess();
103 }
104
105 dlllistmutex.enter();
106 if(head == this) {
107 head = next;
108 }
109 else {
110 Win32DllBase *dll = head;
111 while(dll && dll->next != this) {
112 dll = dll->next;
113 }
114 if(dll == NULL) {
115 dprintf(("~Win32DllBase: Can't find dll!\n"));
116 dlllistmutex.leave();
117 return;
118 }
119 dll->next = next;
120 }
121 dlllistmutex.leave();
122}
123//******************************************************************************
124//ASSUMPTION: called by FreeLibrary
125//******************************************************************************
126ULONG Win32DllBase::Release()
127{
128 ULONG ret = --referenced;
129
130 if(ret == 0) {
131 dprintf(("Win32DllBase::Release, referenced == 0\n"));
132 delete this;
133 }
134 return(ret);
135}
136//******************************************************************************
137//******************************************************************************
138BOOL Win32DllBase::attachProcess()
139{
140 WINEXCEPTION_FRAME exceptFrame;
141 USHORT sel;
142 THDB *thdb;
143 BOOL rc, fSetExceptionHandler;
144
145 if(fAttachedToProcess)
146 return TRUE;
147
148 fAttachedToProcess = TRUE;
149
150 thdb = GetThreadTHDB();
151 fSetExceptionHandler = (!thdb || thdb->teb_sel != GetFS());
152
153 //Note: The Win32 exception structure references by FS:[0] is the same
154 // in OS/2
155 if(fSetExceptionHandler) {
156 OS2SetExceptionHandler((void *)&exceptFrame);
157 sel = SetWin32TIB();
158 }
159
160 //Allocate TLS index for this module
161 tlsAlloc();
162 tlsAttachThread(); //setup TLS (main thread)
163
164 if(fSkipEntryCalls || dllEntryPoint == NULL) {
165 dprintf(("attachProcess not required for dll %s", szModule));
166 if(fSetExceptionHandler) {
167 SetFS(sel);
168 OS2UnsetExceptionHandler((void *)&exceptFrame);
169 }
170 return(TRUE);
171 }
172
173 dprintf(("attachProcess to dll %s", szModule));
174
175 rc = dllEntryPoint(hinstance, DLL_PROCESS_ATTACH, 0);
176
177 dprintf(("attachProcess to dll %s DONE", szModule));
178
179 if(fSetExceptionHandler) {
180 SetFS(sel);
181 OS2UnsetExceptionHandler((void *)&exceptFrame);
182 }
183 return rc;
184}
185//******************************************************************************
186//******************************************************************************
187BOOL Win32DllBase::detachProcess()
188{
189 WINEXCEPTION_FRAME exceptFrame;
190 USHORT sel;
191 BOOL rc;
192
193 if(fSkipEntryCalls || dllEntryPoint == NULL) {
194 tlsDetachThread(); //destroy TLS (main thread)
195 fUnloaded = TRUE;
196 return(TRUE);
197 }
198
199 dprintf(("detachProcess from dll %s", szModule));
200
201 //Note: The Win32 exception structure references by FS:[0] is the same
202 // in OS/2
203 OS2SetExceptionHandler((void *)&exceptFrame);
204
205 fUnloaded = TRUE;
206 sel = SetWin32TIB();
207 rc = dllEntryPoint(hinstance, DLL_PROCESS_DETACH, 0);
208 SetFS(sel);
209 tlsDetachThread(); //destroy TLS (main thread)
210 tlsDelete();
211
212 OS2UnsetExceptionHandler((void *)&exceptFrame);
213
214 return rc;
215}
216//******************************************************************************
217//******************************************************************************
218BOOL Win32DllBase::attachThread()
219{
220 WINEXCEPTION_FRAME exceptFrame;
221 BOOL rc;
222
223 if(fSkipEntryCalls || dllEntryPoint == NULL)
224 return(TRUE);
225
226 dprintf(("attachThread to dll %s", szModule));
227
228 rc = dllEntryPoint(hinstance, DLL_THREAD_ATTACH, 0);
229
230 dprintf(("attachThread to dll %s DONE", szModule));
231
232 return rc;
233}
234//******************************************************************************
235//******************************************************************************
236BOOL Win32DllBase::detachThread()
237{
238 WINEXCEPTION_FRAME exceptFrame;
239 BOOL rc;
240
241 if(fSkipEntryCalls || dllEntryPoint == NULL)
242 return(TRUE);
243
244 dprintf(("detachThread from dll %s", szModule));
245
246 rc = dllEntryPoint(hinstance, DLL_THREAD_DETACH, 0);
247 return rc;
248}
249//******************************************************************************
250//Send DLL_THREAD_ATTACH message to all dlls for a new thread
251//******************************************************************************
252void Win32DllBase::attachThreadToAllDlls()
253{
254 Win32DllBase *dll = Win32DllBase::head;
255 while(dll) {
256 dll->attachThread();
257 dll = dll->getNext();
258 }
259}
260//******************************************************************************
261//Send DLL_THREAD_DETACH message to all dlls for thread that's about to die
262//******************************************************************************
263void Win32DllBase::detachThreadFromAllDlls()
264{
265 Win32DllBase *dll = Win32DllBase::head;
266 while(dll) {
267 dll->detachThread();
268 dll = dll->getNext();
269 }
270}
271//******************************************************************************
272//Setup TLS structure for all dlls for a new thread
273//******************************************************************************
274void Win32DllBase::tlsAttachThreadToAllDlls()
275{
276 Win32DllBase *dll = Win32DllBase::head;
277 while(dll) {
278 dll->tlsAttachThread();
279 dll = dll->getNext();
280 }
281}
282//******************************************************************************
283//Destroy TLS structure for all dlls for a thread that's about to die
284//******************************************************************************
285void Win32DllBase::tlsDetachThreadFromAllDlls()
286{
287 Win32DllBase *dll = Win32DllBase::head;
288 while(dll) {
289 dll->tlsDetachThread();
290 dll = dll->getNext();
291 }
292}
293//******************************************************************************
294//******************************************************************************
295void Win32DllBase::deleteAll(BOOL fDynamicLoad)
296{
297 Win32DllBase *dll = Win32DllBase::head, *tmp;
298
299#ifdef DEBUG
300 dlllistmutex.enter();
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 dll = Win32DllBase::head;
309#endif
310
311 while(dll) {
312 if(fDynamicLoad || !dll->fDynamicLoad) {
313 tmp = dll->next;
314 dll->Release();
315 dll = tmp;
316 }
317 else dll = dll->next;
318 }
319}
320//******************************************************************************
321//Add renaming profile strings for ole32 & netapi32 to odin.ini if they aren't
322//already there
323//******************************************************************************
324void Win32DllBase::setDefaultRenaming()
325{
326 char renameddll[CCHMAXPATH];
327
328 if(ODIN_PROFILE_GetOdinIniString(DLLRENAMEWIN_SECTION, "OLE32", "", renameddll,
329 sizeof(renameddll)-1) <= 1)
330 {
331 ODIN_PROFILE_SetOdinIniString(DLLRENAMEWIN_SECTION, "OLE32", "OLE32OS2");
332 ODIN_PROFILE_SetOdinIniString(DLLRENAMEOS2_SECTION, "OLE32OS2", "OLE32");
333 }
334 if(ODIN_PROFILE_GetOdinIniString(DLLRENAMEWIN_SECTION, "OLEAUT32", "", renameddll,
335 sizeof(renameddll)-1) <= 1)
336 {
337 ODIN_PROFILE_SetOdinIniString(DLLRENAMEWIN_SECTION, "OLEAUT32", "OLAUTOS2");
338 ODIN_PROFILE_SetOdinIniString(DLLRENAMEOS2_SECTION, "OLAUTOS2", "OLEAUT32");
339 }
340 if(ODIN_PROFILE_GetOdinIniString(DLLRENAMEWIN_SECTION, "NETAPI32", "", renameddll,
341 sizeof(renameddll)-1) <= 1)
342 {
343 ODIN_PROFILE_SetOdinIniString(DLLRENAMEWIN_SECTION, "NETAPI32", "WNETAP32");
344 ODIN_PROFILE_SetOdinIniString(DLLRENAMEOS2_SECTION, "WNETAP32", "NETAPI32");
345 }
346}
347//******************************************************************************
348//rename dll if necessary:
349// Win32 to OS/2 : (i.e. OLE32 -> OLE32OS2)
350// or
351// OS/2 to Win32 : (i.e. OLE32OS2 -> OLE32)
352//******************************************************************************
353void Win32DllBase::renameDll(char *dllname, BOOL fWinToOS2)
354{
355 char modname[CCHMAXPATH];
356 char renameddll[CCHMAXPATH];
357 char *namestart;
358 char *sectionname;
359
360 if(fWinToOS2) {
361 sectionname = DLLRENAMEWIN_SECTION;
362 }
363 else {
364 sectionname = DLLRENAMEOS2_SECTION;
365 }
366 namestart = OSLibStripPath(dllname);
367 strcpy(modname, namestart);
368 char *dot = strrchr(modname, '.');
369 if(dot)
370 *dot = 0;
371 strupr(modname);
372 if(ODIN_PROFILE_GetOdinIniString(sectionname, modname, "", renameddll,
373 sizeof(renameddll)-1) > 1)
374 {
375 if(namestart == dllname) {
376 strcpy(dllname, renameddll);
377 }
378 else {
379 *namestart = 0;
380 strcat(dllname, renameddll);
381 }
382 strcat(dllname, ".dll");
383 }
384 return;
385}
386//******************************************************************************
387//******************************************************************************
388Win32DllBase *Win32DllBase::findModule(char *dllname)
389{
390 Win32DllBase *dll;
391 char szDllName[CCHMAXPATH];
392 char *dot, *temp;
393
394 dprintf(("findModule %s", dllname));
395
396 strcpy(szDllName, OSLibStripPath(dllname));
397 strupr(szDllName);
398 dot = strstr(szDllName, ".");
399 if(dot)
400 *dot = 0;
401
402 dlllistmutex.enter();
403 dll = head;
404 while(dll) {
405 if(strcmpi(szDllName, dll->szModule) == 0) {
406 dlllistmutex.leave();
407 return(dll);
408 }
409
410 dll = dll->next;
411 }
412 dlllistmutex.leave();
413 return(NULL);
414}
415//******************************************************************************
416//******************************************************************************
417Win32DllBase *Win32DllBase::findModule(WIN32DLLENTRY DllEntryPoint)
418{
419 dprintf(("findModule %X", DllEntryPoint));
420
421 dlllistmutex.enter();
422 Win32DllBase *mod = Win32DllBase::head;
423 while(mod != NULL) {
424 dbgCheckObj(mod);
425 if(mod->dllEntryPoint == DllEntryPoint) {
426 dlllistmutex.leave();
427 return(mod);
428 }
429 mod = mod->next;
430 }
431 dlllistmutex.leave();
432 return(NULL);
433}
434//******************************************************************************
435//******************************************************************************
436Win32DllBase *Win32DllBase::findModule(HINSTANCE hinstance)
437{
438 dlllistmutex.enter();
439
440 Win32DllBase *mod = Win32DllBase::head;
441 while(mod != NULL) {
442 dbgCheckObj(mod);
443 if(mod->hinstance == hinstance) {
444 dlllistmutex.leave();
445 return(mod);
446 }
447 mod = mod->next;
448 }
449 dlllistmutex.leave();
450 return(NULL);
451}
452//******************************************************************************
453//******************************************************************************
454BOOL Win32DllBase::isDll()
455{
456 return TRUE;
457}
458//******************************************************************************
459//******************************************************************************
460void Win32DllBase::setThreadLibraryCalls(BOOL fEnable)
461{
462 // if fEnable == true, do call the ATTACH_THREAD, DETACH_THREAD functions
463 // if fEnable == false, do not call the ATTACH_THREAD, DETACH_THREAD functions
464 fSkipEntryCalls = !fEnable;
465}
466
467//******************************************************************************
468//******************************************************************************
469Win32DllBase *Win32DllBase::head = NULL;
Note: See TracBrowser for help on using the repository browser.