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

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

* empty log message *

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