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

Last change on this file since 4 was 4, checked in by ktk, 26 years ago

Import

File size: 12.0 KB
Line 
1/* $Id: windll.cpp,v 1.1 1999-05-24 20:19:49 ktk Exp $ */
2
3/*
4 *
5 * Project Odin Software License can be found in LICENSE.TXT
6 *
7 */
8/*
9 * Win32 DLL class
10 *
11 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
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 <os2.h>
21#include <stdio.h>
22#include <string.h>
23#include <stdlib.h>
24#include <iostream.h>
25#include <fstream.h>
26#include "misc.h"
27#include "nameid.h"
28#include "win32type.h"
29#include "pefile.h"
30#include "windll.h"
31#include "cio.h"
32#include "os2util.h"
33
34/***********************************
35 * PH: fixups for missing os2win.h *
36 ***********************************/
37
38void _System SetLastError(ULONG ulError);
39
40
41//******************************************************************************
42//******************************************************************************
43Win32Dll::Win32Dll(char *szDllName) : Win32Image(szDllName), referenced(0),
44 fSkipEntryCalls(FALSE), fSystemDll(FALSE)
45{
46 fSystemDll = isSystemDll(szFileName);
47 fUnloaded = FALSE;
48 next = head;
49 head = this;
50
51 strcpy(szModule, StripPath(szFileName));
52 UpCase(szModule);
53 char *dot = strstr(szModule, ".");
54 if(dot)
55 *dot = 0;
56}
57//******************************************************************************
58//******************************************************************************
59Win32Dll::Win32Dll(HINSTANCE hinstance, int NameTableId, int Win32TableId,
60 WIN32DLLENTRY DllEntryPoint) :
61 Win32Image(hinstance, NameTableId, Win32TableId),
62 referenced(0), fSkipEntryCalls(FALSE), fSystemDll(FALSE)
63{
64 dllEntryPoint = DllEntryPoint;
65 fUnloaded = FALSE;
66 next = head;
67 head = this;
68
69 char *name = OS2GetDllName(hinstance);
70 strcpy(szModule, name);
71 UpCase(szModule);
72 char *dot = strstr(szModule, ".");
73 if(dot)
74 *dot = 0;
75
76}
77//******************************************************************************
78//******************************************************************************
79void Win32Dll::OS2DllInit(HINSTANCE hinstance, int NameTableId, int Win32TableId,
80 WIN32DLLENTRY DllEntryPoint)
81{
82 dllEntryPoint = DllEntryPoint;
83 fUnloaded = FALSE;
84
85 char *name = OS2GetDllName(hinstance);
86 strcpy(szModule, name);
87 UpCase(szModule);
88 char *dot = strstr(szModule, ".");
89 if(dot)
90 *dot = 0;
91
92 Win32Image::OS2ImageInit(hinstance, NameTableId, Win32TableId);
93}
94//******************************************************************************
95//******************************************************************************
96Win32Dll::~Win32Dll()
97{
98 Win32Dll *dll = head;
99
100 //first remove it from the linked list so converted win32 dlls won't
101 //be deleted twice (as DosFreeModule results in a call to DllExitList (wprocess.cpp)
102 if(head == this) {
103 head = next;
104 }
105 else {
106 while(dll && dll->next != this) {
107 dll = dll->next;
108 }
109 if(dll == NULL) {
110 dprintf(("~Win32Dll: Can't find dll!\n"));
111 return;
112 }
113 dll->next = next;
114 }
115 if(errorState == NO_ERROR && !fUnloaded) {
116 if(fNativePEImage) {
117 detachProcess();
118 }
119 else {
120 if(!fSystemDll) //let OS/2 unload them, unless ordered by FreeLibrary (see ::Release)
121 DosFreeModule((HMODULE)hinstance);
122 }
123 }
124}
125//******************************************************************************
126//ASSUMPTION: called by FreeLibrary
127//******************************************************************************
128ULONG Win32Dll::Release()
129{
130 ULONG ret = --referenced;
131
132 if(ret == 0) {
133 dprintf(("Win32Dll::Release, referenced == 0\n"));
134 if(fSystemDll) {
135 DosFreeModule((HMODULE)hinstance);
136 fUnloaded = TRUE;
137 }
138 delete this;
139 }
140 return(ret);
141}
142//******************************************************************************
143//******************************************************************************
144BOOL Win32Dll::init()
145{
146 char *syspath;
147 FILE *dllfile;
148 APIRET rc;
149 BOOL fRet;
150
151 if(fSystemDll == FALSE && fNativePEImage == TRUE)
152 {//might be win32 dll, so check this
153 dllfile = fopen(szFileName, "r");
154 if(dllfile == NULL) {//search in libpath for dll
155 syspath = getenv("WIN32LIBPATH");
156 if(syspath) {
157 strcpy(szModule, syspath);
158 if(szModule[strlen(szModule)-1] != '\\') {
159 strcat(szModule, "\\");
160 }
161 strcat(szModule, szFileName);
162 szFileName = szModule;
163 }
164 }
165 else fclose(dllfile);
166 if(isPEImage(szFileName) == TRUE) {
167 fRet = Win32Image::init();
168 dllEntryPoint = (WIN32DLLENTRY)entryPoint;
169 return fRet;
170 }
171 //converted win32 dll
172 fNativePEImage = FALSE;
173 }
174 //else load system dlls using DosLoadModule
175 char szModuleFailure[CCHMAXPATH] = "";
176
177 rc = DosLoadModule(szModuleFailure, sizeof(szModuleFailure), szFileName, (HMODULE *)&hinstance);
178 if(rc) {
179 dprintf(("DosLoadModule returned %X for %s\n", rc, szModuleFailure));
180 errorState = rc;
181 return(FALSE);
182 }
183 return(TRUE);
184}
185//******************************************************************************
186char *sysmodules[] = {"KERNEL32", "USER32", "GDI32", "WINMM", "DSOUND", "DDRAW",
187 "WNETAP32", "MPR", "OLE32", "ADVAPI32", "COMMDLG",
188 "WINSPOOL", "SHELL32", "TAPI32", "CAPI32", "VERSION",
189 "WSOCK32"};
190//******************************************************************************
191BOOL Win32Dll::isSystemDll(char *szFileName)
192{
193 int i;
194 char *dot;
195 char szModule[CCHMAXPATH];
196
197 strcpy(szModule, szFileName);
198 UpCase(szModule);
199 dot = strstr(szModule, ".");
200 if(dot)
201 *dot = 0;
202
203 for(i=0;i<sizeof(sysmodules)/sizeof(char *);i++) {
204 if(!strcmp(szModule, sysmodules[i]))
205 return(TRUE);
206 }
207 return(FALSE);
208}
209//******************************************************************************
210//Could be more efficient, but I bet this is faster than the OS/2 loader!
211//******************************************************************************
212ULONG Win32Dll::getApi(char *name)
213{
214 APIRET rc;
215 ULONG apiaddr, i, apilen;
216 char *apiname;
217 char tmp[4];
218 NameExport *curexport;
219 ULONG ulAPIOrdinal; /* api requested by ordinal */
220
221 apilen = strlen(name) + 1;
222 if(apilen < 4)
223 {
224 *(ULONG *)tmp = 0;
225 strcpy(tmp, name);
226 apiname = tmp;
227 }
228 else apiname = name;
229
230 curexport = nameexports;
231 for(i=0;
232 i<nrNameExports;
233 i++)
234 {
235 if(apilen == curexport->nlength &&
236 *(ULONG *)curexport->name == *(ULONG *)name)
237 {
238 if(strcmp(curexport->name, name) == 0)
239 return(curexport->virtaddr);
240 }
241 curexport = (NameExport *)((ULONG)curexport->name + curexport->nlength);
242 }
243
244 if(fSystemDll || !fNativePEImage)
245 {
246 rc = DosQueryProcAddr(hinstance, 0, name, (PFN *)&apiaddr);
247 if(rc)
248 {
249 SetLastError(rc); /* raise error condition */
250 return(0);
251 }
252
253 //Add to lookkup table, so we don't have to call DosQueryProcAddr
254 //multiple times for the same api (when imported by other dlls)
255 AddNameExport(apiaddr, name, 0);
256 return(apiaddr);
257 }
258 return(0);
259}
260//******************************************************************************
261//******************************************************************************
262ULONG Win32Dll::getApi(int ordinal)
263{
264 APIRET rc;
265 ULONG apiaddr, i;
266 OrdExport *curexport;
267 NameExport *nexport;
268
269 if(fSystemDll || !fNativePEImage) {
270 rc = DosQueryProcAddr(hinstance, ordinal, NULL, (PFN *)&apiaddr);
271 if(rc) return(0);
272 else return(apiaddr);
273 }
274 curexport = ordexports;
275 for(i=0;i<nrOrdExports;i++) {
276 if(curexport->ordinal == ordinal)
277 return(curexport->virtaddr);
278 curexport++;
279 }
280 //Name exports also contain an ordinal, so check this
281 nexport = nameexports;
282 for(i=0;i<nrNameExports;i++) {
283 if(nexport->ordinal == ordinal)
284 return(nexport->virtaddr);
285 nexport = (NameExport *)((ULONG)nexport->name + nexport->nlength);
286 }
287 return(0);
288}
289//******************************************************************************
290//******************************************************************************
291BOOL Win32Dll::attachProcess()
292{
293 if(fSystemDll || fSkipEntryCalls || !fNativePEImage)
294 return(TRUE);
295
296 if(getenv("WIN32_IOPL2")) {
297 io_init1();
298 }
299 return dllEntryPoint((ULONG)this, DLL_PROCESS_ATTACH, 0);
300}
301//******************************************************************************
302//******************************************************************************
303BOOL Win32Dll::detachProcess()
304{
305 if(fSystemDll || fSkipEntryCalls)
306 return(TRUE);
307
308 if(fNativePEImage)
309 return dllEntryPoint((ULONG)this, DLL_PROCESS_DETACH, 0);
310 else return dllEntryPoint((ULONG)this, DLL_PROCESS_ATTACH, 0); //reversed in converted code
311}
312//******************************************************************************
313//******************************************************************************
314BOOL Win32Dll::attachThread()
315{
316 if(fSystemDll || fSkipEntryCalls)
317 return(TRUE);
318
319 return dllEntryPoint((ULONG)this, DLL_THREAD_ATTACH, 0);
320}
321//******************************************************************************
322//******************************************************************************
323BOOL Win32Dll::detachThread()
324{
325 if(fSystemDll || fSkipEntryCalls)
326 return(TRUE);
327
328 return dllEntryPoint((ULONG)this, DLL_THREAD_DETACH, 0);
329}
330//******************************************************************************
331//******************************************************************************
332void Win32Dll::deleteAll()
333{
334 //LIFO removal
335 while(Win32Dll::head) {
336 delete Win32Dll::head;
337 }
338}
339//******************************************************************************
340//******************************************************************************
341Win32Dll *Win32Dll::findModule(char *dllname)
342{
343 Win32Dll *dll = head;
344 char szDllName[CCHMAXPATH];
345 char *dot;
346
347 dprintf(("findModule %s", dllname));
348 strcpy(szDllName, dllname);
349 UpCase(szDllName);
350 dot = strstr(szDllName, ".");
351 if(dot)
352 *dot = 0;
353
354 while(dll) {
355 if(strcmpi(szDllName, dll->szModule) == 0)
356 return(dll);
357
358 dll = dll->next;
359 }
360 return(NULL);
361}
362//******************************************************************************
363//******************************************************************************
364Win32Dll *Win32Dll::findModule(WIN32DLLENTRY DllEntryPoint)
365{
366 Win32Dll *mod = Win32Dll::head;
367
368 dprintf(("findModule %X", DllEntryPoint));
369 while(mod != NULL) {
370 dbgCheckObj(mod);
371 if(mod->dllEntryPoint == DllEntryPoint)
372 return(mod);
373 mod = mod->next;
374 }
375 return(NULL);
376}
377//******************************************************************************
378//******************************************************************************
379Win32Dll *Win32Dll::findModule(HINSTANCE hinstance)
380{
381 Win32Dll *mod = Win32Dll::head;
382
383// eprintf(("findModule inst %X", hinstance));
384 while(mod != NULL) {
385 dbgCheckObj(mod);
386 if(mod->hinstance == hinstance)
387 return(mod);
388 mod = mod->next;
389 }
390 return(NULL);
391}
392//******************************************************************************
393//******************************************************************************
394char *Win32Dll::StripPath(char *path)
395{
396 /* @@@PH what does this function do ? Strip the path from a FQFN name ? */
397 char *pszFilename;
398
399 pszFilename = strrchr(path, '\\'); /* find rightmost slash */
400 if (pszFilename != NULL)
401 return (pszFilename++); /* return pointer to next character */
402
403 pszFilename = strrchr(path, '/'); /* find rightmost slash */
404 if (pszFilename != NULL)
405 return (pszFilename++); /* return pointer to next character */
406
407 return (path); /* default return value */
408
409#if 0
410 char *fname = path, *prevname = path-1;
411
412 while(TRUE)
413 {
414 @@@PH causes endless loop here !
415 fname = strchr(fname, '\\');
416 if(fname == NULL)
417 break;
418
419 prevname = fname;
420 }
421 return(prevname+1);
422#endif
423}
424/******************************************************************************/
425/******************************************************************************/
426Win32Dll *Win32Dll::head = NULL;
Note: See TracBrowser for help on using the repository browser.