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

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

changes for OpenThreadToken

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