source: trunk/src/kernel32/windlllx.cpp@ 4407

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

misc updates + fixes

File size: 9.5 KB
Line 
1/* $Id: windlllx.cpp,v 1.15 2000-10-03 17:28:31 sandervl Exp $ */
2
3/*
4 * Win32 LX Dll class (compiled in OS/2 using Odin32 api)
5 *
6 * Copyright 1999-2000 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * TODO: Unloading of dlls probably needs to be fixed due to OS/2 bug
9 * (wrong unload order of dlls)
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 */
14#define INCL_DOSFILEMGR /* File Manager values */
15#define INCL_DOSERRORS /* DOS Error values */
16#define INCL_DOSPROCESS /* DOS Process values */
17#define INCL_DOSMODULEMGR
18#define INCL_DOSMISC /* DOS Miscellanous values */
19#define INCL_WIN
20#include <os2wrap.h> //Odin32 OS/2 api wrappers
21#include <os2newapi.h>
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 <windllbase.h>
30#include <windlllx.h>
31#include "winexepe2lx.h"
32#include "winexepeldr.h"
33#include <odinlx.h>
34#include "oslibmisc.h"
35
36#include <exe386.h>
37
38#define DBG_LOCALLOG DBG_windlllx
39#include "dbglocal.h"
40
41//******************************************************************************
42//Create LX Dll object and send process attach message
43//System dlls set EntryPoint to 0
44//Parameters:
45// HINSTANCE hInstance - OS/2 module handle
46// WIN32DLLENTRY EntryPoint - Win32 dll entrypoint address
47// PVOID pResData - pointer to win32 resource data
48// DWORD MajorImageVersion - major image/os version (for fake win32 header)
49// DWORD MinorImageVersion - minor image/os version (for fake win32 header)
50// DWORD Subsystem - subsystem type (for fake win32 header)
51// (IMAGE_SUBSYSTEM_WINDOWS_CUI/IMAGE_SUBSYSTEM_WINDOWS_GUI)
52//
53//Returns: Odin32 module handle
54//******************************************************************************
55DWORD WIN32API RegisterLxDll(HINSTANCE hInstance, WIN32DLLENTRY EntryPoint,
56 PVOID pResData,
57 DWORD MajorImageVersion,
58 DWORD MinorImageVersion,
59 DWORD Subsystem)
60{
61 APIRET rc;
62 Win32LxDll *windll;
63 Win32DllBase *windlldep;
64 char szFileName[CCHMAXPATH], szErrName[CCHMAXPATH];
65
66 if(OSLibGetDllName(hInstance, szFileName, sizeof(szFileName)) == FALSE) {
67 dprintf(("ERROR: RegisterLxDll: OSLibGetDllName %x failed!!", hInstance));
68 return 0;
69 }
70 //Make sure DosLoadModule is called at least
71 //once for a dll (to make sure OS/2 doesn't unload the dll when it's
72 //still needed)
73 rc = DosLoadModule(szErrName, sizeof(szErrName), szFileName, &hInstance);
74 if(rc != 0) {
75 dprintf(("ERROR: RegisterLxDll: DosLoadModule %s failed (rc=%d)!!", szFileName, rc));
76 return 0;
77 }
78 windll = new Win32LxDll(hInstance, EntryPoint, pResData, MajorImageVersion,
79 MinorImageVersion, Subsystem);
80 if(windll == NULL) {
81 dprintf(("RegisterLxDll: windll == NULL!!!"));
82 return 0;
83 }
84 if(!fPeLoader) {
85 windll->AddRef();
86
87 if(windll->attachProcess() == 0)
88 return 0;
89
90 return windll->getInstanceHandle();
91 }
92 IMAGE_DOS_HEADER doshdr;
93 struct e32_exe lxhdr;
94 ULONG offset;
95 char modulename[CCHMAXPATH];
96 char modsize;
97 int i;
98
99 //SvL: This code reads the import name table of the dll to get the dependencies
100 // on other dlls.
101 //DosQueryHeaderInfo is an undocumented api, but works very well.
102 //(no need to save FS here as we'll return to OS/2 immediately)
103 rc = DosQueryHeaderInfo(hInstance, 0, &doshdr, sizeof(IMAGE_DOS_HEADER), QHINF_READFILE);
104 if(rc) {
105 goto hdrerror;
106 }
107 rc = DosQueryHeaderInfo(hInstance, doshdr.e_lfanew, &lxhdr, sizeof(e32_exe), QHINF_READFILE);
108 if(rc) {
109 goto hdrerror;
110 }
111 offset = doshdr.e_lfanew + lxhdr.e32_impmod;
112 for(i=0;i<lxhdr.e32_impmodcnt;i++) {
113 rc = DosQueryHeaderInfo(hInstance, offset, &modsize, 1, QHINF_READFILE);
114 if(rc) {
115 goto hdrerror;
116 }
117 rc = DosQueryHeaderInfo(hInstance, offset+1, &modulename, min(modsize, sizeof(modulename)), QHINF_READFILE);
118 if(rc) {
119 goto hdrerror;
120 }
121 modulename[modsize] = 0;
122 windlldep = Win32DllBase::findModule(modulename, TRUE);
123 if(windlldep) {
124 dprintf(("RegisterLxDll: Add dependency %s -> %s", windll->getModuleName(), modulename));
125 windll->addDependency(windlldep);
126 }
127 offset += modsize + 1;
128 }
129 return windll->getInstanceHandle();
130
131hdrerror:
132 dprintf(("DosQueryHeaderInfo returned %d", rc));
133 return windll->getInstanceHandle();
134}
135//******************************************************************************
136//Destroy LX Dll object
137//******************************************************************************
138BOOL WIN32API UnregisterLxDll(HINSTANCE hInstance)
139{
140 Win32DllBase *windll;
141
142 //Don't proceed for pe2lx/win32k (os/2 dll unload dependency bug)
143 //Don't do it either after ExitProcess has been called
144 if(!fPeLoader || WinExe == NULL)
145 return TRUE;
146
147 windll = Win32DllBase::findModule(hInstance);
148 if(!windll) {
149 dprintf(("UnregisterLxDll: Can't find dll with handle %x (already deleted)", hInstance));
150 return TRUE; //already deleted by Win32LxDll::Release
151 }
152 dprintf(("UnregisterLxDll %s", windll->getModuleName()));
153 //This can only happen for LX dependencies (i.e. wininet loads wsock32)
154 delete windll;
155 return TRUE;
156}
157//******************************************************************************
158//******************************************************************************
159Win32LxDll::Win32LxDll(HINSTANCE hInstance, WIN32DLLENTRY EntryPoint, PVOID pResData,
160 DWORD MajorImageVersion, DWORD MinorImageVersion,
161 DWORD Subsystem)
162 : Win32ImageBase(hInstance),
163 Win32LxImage(hInstance, pResData),
164 Win32DllBase(hInstance, EntryPoint)
165{
166 if(EntryPoint == NULL) {
167 fSkipThreadEntryCalls = TRUE;
168 fAttachedToProcess = TRUE;
169 }
170 hinstanceOS2 = hInstance;
171 //new win32 instance handle must be pointer to PE header
172 hinstance = (HINSTANCE)buildHeader(MajorImageVersion, MinorImageVersion,
173 Subsystem);
174}
175//******************************************************************************
176//******************************************************************************
177Win32LxDll::~Win32LxDll()
178{
179}
180//******************************************************************************
181//Returns reference count or -1 if load failed (PE loader only!)
182//******************************************************************************
183#ifdef DEBUG
184ULONG Win32LxDll::AddRef(char *parentname)
185#else
186ULONG Win32LxDll::AddRef()
187#endif
188{
189 Win32DllBase *dll;
190 QueueItem *item;
191 ULONG ret;
192
193#ifdef DEBUG
194 ret = Win32DllBase::AddRef(parentname);
195#else
196 ret = Win32DllBase::AddRef();
197#endif
198
199 if(!fPeLoader)
200 return ret;
201
202 if(referenced == 1)
203 {
204 item = loadedDlls.Head();
205 while(item) {
206 dll = (Win32DllBase *)loadedDlls.getItem(item);
207 if(dll == NULL) {
208 dprintf(("ERROR: Win32DllBase::AddRef: dll item == NULL!!"));
209 DebugInt3();
210 return -1;
211 }
212#ifdef DEBUG
213 dll->AddRef(getModuleName());
214#else
215 dll->AddRef();
216#endif
217 item = loadedDlls.getNext(item);
218 }
219 if(attachProcess() == 0) {
220 dprintf(("WARNING: Dll %s refused to be loaded; aborting", getName()));
221 return -1;
222 }
223 }
224 return ret;
225}
226//******************************************************************************
227//******************************************************************************
228ULONG Win32LxDll::Release()
229{
230 HINSTANCE hinst;
231 ULONG ret;
232 APIRET rc;
233 BOOL fNoUnload = fDisableUnload; //only set for kernel32.dll
234
235 hinst = hinstanceOS2;
236 ret = Win32DllBase::Release();
237 if(ret == 0 && !fNoUnload) {//only set for kernel32.dll (fDisableUnload)
238 //DosFreeModule sends a termination message to the dll.
239 //The LX dll informs us when it's removed (UnregisterDll call)
240 rc = DosFreeModule(hinst);
241 if(rc) {
242 dprintf(("Win32LxDll::Release: DosFreeModule %x returned %d", hinst, rc));
243 }
244 }
245 return(ret);
246}
247//******************************************************************************
248//******************************************************************************
249BOOL Win32LxDll::isLxDll()
250{
251 return TRUE;
252}
253//******************************************************************************
254//******************************************************************************
255void Win32LxDll::setDllHandleOS2(HINSTANCE hInstanceOS2)
256{
257 //Loaded with LoadLibrary(Ex); no need for a 2nd DosLoadModule
258 //Dlls that are indirectly loaded (i.e. GDI32->KERNEL32 dependancy) need
259 //this additional DosLoadModule (and setDllHandleOS2 isn't called for those)
260 if(this->hinstanceOS2) {
261 DosFreeModule(this->hinstanceOS2);
262 }
263 this->hinstanceOS2 = hInstanceOS2;
264}
265//******************************************************************************
266//******************************************************************************
267Win32LxDll *Win32LxDll::findModuleByOS2Handle(HINSTANCE hinstance)
268{
269 dlllistmutex.enter();
270
271 Win32DllBase *mod = Win32DllBase::getFirst();
272 while(mod != NULL) {
273 if(mod->isLxDll()) {
274 Win32LxDll *lxdll = (Win32LxDll *)mod;
275 if(lxdll->hinstanceOS2 == hinstance) {
276 dlllistmutex.leave();
277 return(lxdll);
278 }
279 }
280 mod = mod->getNext();
281 }
282 dlllistmutex.leave();
283 return(NULL);
284}
285//******************************************************************************
286//******************************************************************************
Note: See TracBrowser for help on using the repository browser.