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

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

Activated Win32 TIB code and fixes some other things (see ChangeLog)

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