source: trunk/src/kernel32/wprocess.cpp@ 109

Last change on this file since 109 was 108, checked in by phaller, 26 years ago

Fix: LoadLibraryA not skips specified path to DLL image if loading failed on 1st attempt.

File size: 18.5 KB
Line 
1/* $Id: wprocess.cpp,v 1.5 1999-06-15 17:57:34 phaller Exp $ */
2
3/*
4 *
5 * Project Odin Software License can be found in LICENSE.TXT
6 *
7 */
8/*
9 * Win32 process functions
10 *
11 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
12 *
13 */
14#include <os2win.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include "unicode.h"
19#include "windll.h"
20#include "winexe.h"
21#ifdef __IBMCPP__
22#include <builtin.h>
23#endif
24#include "except.h"
25#include "os2util.h"
26#include "console2.h"
27#include "cio.h"
28#include "versionos2.h" /*PLF Wed 98-03-18 02:36:51*/
29
30BOOL fExeStarted = FALSE;
31BOOL fFreeLibrary = FALSE;
32
33/******************************************************************************/
34//SvL: 4-10-'98: Put in separate procedure, as ICC changes FS:0 when there
35// are new or delete calls present.
36//******************************************************************************
37void RegisterExe(LONG Win32TableId, LONG NameTableId, LONG VersionResId,
38 LONG Pe2lxVersion, HINSTANCE hinstance)
39{
40 if(WinExe != NULL) //should never happen
41 delete(WinExe);
42
43 //SvL: Use 0 instead of the real instance handle (for resource lookup)
44 Win32Exe *winexe = new Win32Exe(0, NameTableId, Win32TableId);
45 if(winexe) {
46 winexe->setVersionId(VersionResId);
47 winexe->setOS2InstanceHandle(hinstance);
48 }
49 else {
50 eprintf(("Win32Exe creation failed!\n"));
51 DebugInt3();
52 }
53 char *modname;
54 if(modname = getenv("WIN32MODULE")) {
55 dprintf(("Set full path for exe to %s", modname));
56 winexe->setFullPath(modname);
57 }
58
59 fExeStarted = TRUE;
60}
61//******************************************************************************
62//******************************************************************************
63VOID WIN32API RegisterResourceUsage(LONG Win32TableId, LONG NameTableId,
64 LONG VersionResId, LONG Pe2lxVersion,
65 HINSTANCE hinstance)
66{
67 if(getenv("WIN32_IOPL2")) {
68 io_init1();
69 }
70 dprintf(("RegisterResourceUsage %X resid = %d\n", hinstance, VersionResId));
71
72 CheckVersion(Pe2lxVersion, OS2GetDllName(hinstance));
73
74 RegisterExe(Win32TableId, NameTableId, VersionResId, Pe2lxVersion, hinstance);
75
76 //NOTE: Breaks Quake 2 if enabled
77 if(getenv("WIN32_NOEXCEPTION")) {
78 ChangeTIBStack(); //disable exceptions
79 }
80}
81//******************************************************************************
82//******************************************************************************
83void CreateDll(LONG Win32TableId, LONG NameTableId, LONG VersionResId,
84 HINSTANCE hinstance, WIN32DLLENTRY pfnDllEntry)
85{
86 Win32Dll *winmod = Win32Dll::findModule(hinstance);
87
88 if(winmod != NULL) {
89 //dll manually loaded by PE loader (Win32Dll::init)
90 winmod->OS2DllInit(hinstance, NameTableId, Win32TableId, pfnDllEntry);
91 return;
92 }
93
94 //converted win32 dll loaded by OS/2 loader
95 winmod = new Win32Dll(hinstance, NameTableId, Win32TableId, pfnDllEntry);
96 if(winmod == NULL) {
97 eprintf(("Failed to allocate module object!\n"));
98 DebugInt3();
99 return;
100 }
101 //SvL: 19-8-'98
102 winmod->AddRef();
103 winmod->setVersionId(VersionResId);
104}
105//******************************************************************************
106//******************************************************************************
107VOID WIN32API RegisterDll(LONG Win32TableId, LONG NameTableId,
108 LONG VersionResId, LONG Pe2lxVersion,
109 HINSTANCE hinstance)
110{
111 WIN32DLLENTRY pfnDllEntry;
112 char *name;
113
114 pfnDllEntry = (WIN32DLLENTRY)GetDllEntryPoint(); //== return address
115
116 if(getenv("WIN32_IOPL2")) {
117 io_init1();
118 }
119 name = OS2GetDllName(hinstance);
120 CheckVersion(Pe2lxVersion, name);
121
122 dprintf(("RegisterDll %X %s\n", hinstance, name));
123
124 CreateDll(Win32TableId, NameTableId, VersionResId, hinstance, pfnDllEntry);
125
126 /* @@@PH 1998/03/17 console devices initialization */
127 ConsoleDevicesRegister();
128}
129//******************************************************************************
130//******************************************************************************
131void _System Win32DllExitList(ULONG reason)
132{
133 dprintf(("Win32DllExitList %d\n", reason));
134
135 if(WinExe) {
136 delete WinExe;
137 WinExe = NULL;
138 }
139 return;
140}
141//******************************************************************************
142//Called when a dll is detached (either at process exit or when FreeLibrary is called)
143//******************************************************************************
144BOOL WIN32API DLLExitList(HINSTANCE hInstance)
145{
146// dprintf(("DLLExitList"));
147 Win32Dll *winmod = Win32Dll::findModule(hInstance);
148
149 if(winmod == NULL) {//probably called after we manually unloaded it in ExitProcess
150 return(1); //remove it from memory
151 }
152 dprintf(("DllExitList for %s (%X)\n", OS2GetDllName(winmod->getInstanceHandle()), winmod->getInstanceHandle()));
153 delete(winmod);
154
155 if(fFreeLibrary) {
156 dprintf(("KERNEL32: DLLExitList Ditched by FreeLibrary\n"));
157 return(1); //remove it as we no longer need it
158 }
159 return(0); //don't remove it (OS/2 can unload them at process exit in the wrong order!)
160}
161//******************************************************************************
162//******************************************************************************
163VOID WIN32API ExitProcess(DWORD exitcode)
164{
165 dprintf(("KERNEL32: ExitProcess %d\n", exitcode));
166
167 //avoid crashes since win32 & OS/2 exception handler aren't identical
168 //(terminate process generates two exceptions)
169 /* @@@PH 1998/02/12 Added Console Support */
170 if (ConsoleIsActive())
171 ConsoleWaitClose();
172
173 try {
174 Win32DllExitList(-1);
175 }
176 catch(...) {
177 dprintf(("dll exitlist exception\n"));
178 }
179 SetExceptionChain((ULONG)-1);
180 O32_ExitProcess(exitcode);
181}
182//******************************************************************************
183//******************************************************************************
184BOOL WIN32API FreeLibrary(HINSTANCE hinstance)
185{
186 Win32Dll *winmod;
187 BOOL rc;
188
189 dprintf(("FreeLibrary"));
190 winmod = Win32Dll::findModule(hinstance);
191 if(winmod) {
192 winmod->Release();
193 return(TRUE);
194 }
195 dprintf(("KERNEL32: FreeLibrary %s %X\n", OS2GetDllName(hinstance), hinstance));
196
197 //TODO: Not thread safe
198 fFreeLibrary = TRUE; //ditch dll
199 rc = O32_FreeLibrary(hinstance);
200 fFreeLibrary = FALSE;
201 dprintf(("FreeLibrary returned %X\n", rc));
202 return(TRUE);
203}
204/******************************************************************************/
205/******************************************************************************/
206static HINSTANCE iLoadLibraryA(LPCTSTR lpszLibFile)
207{
208 HINSTANCE hDll;
209 Win32Dll *module;
210
211 hDll = O32_LoadLibrary(lpszLibFile);
212 dprintf(("KERNEL32: iLoadLibraryA %s returned %X (%d)\n",
213 lpszLibFile,
214 hDll,
215 GetLastError()));
216 if(hDll)
217 {
218 return hDll; //converted dll or win32k took care of it
219 }
220
221 if(Win32Image::isPEImage((char *)lpszLibFile)) {
222 module = Win32Dll::findModule((char *)lpszLibFile);
223 if(module) {//don't load it again
224 module->AddRef();
225 return module->getInstanceHandle();
226 }
227 module = new Win32Dll((char *)lpszLibFile);
228 if(module == NULL)
229 return(0);
230
231 module->init();
232 if(module->getError() != NO_ERROR) {
233 dprintf(("LoadLibary %s failed (::init)\n", lpszLibFile));
234 delete module;
235 return(0);
236 }
237 if(module->attachProcess() == FALSE) {
238 dprintf(("LoadLibary %s failed (::attachProcess)\n", lpszLibFile));
239 delete module;
240 return(0);
241 }
242 module->AddRef();
243 return module->getInstanceHandle();
244 }
245 else
246 return(0);
247}
248
249
250HINSTANCE WIN32API LoadLibraryA(LPCTSTR lpszLibFile)
251{
252 HINSTANCE hDll;
253
254 dprintf(("KERNEL32: LoadLibraryA(%s)\n",
255 lpszLibFile));
256
257 hDll = iLoadLibraryA(lpszLibFile);
258 if (hDll == 0)
259 {
260 PSZ pszName;
261
262 // remove path from the image name
263 pszName = strrchr((PSZ)lpszLibFile,
264 '\\');
265 if (pszName != NULL)
266 {
267 pszName++; // skip backslash
268
269 // now try again without fully qualified path
270 hDll = iLoadLibraryA(pszName);
271 }
272 }
273
274 return hDll;
275}
276
277
278//******************************************************************************
279//******************************************************************************
280HINSTANCE WIN32API LoadLibraryExA(LPCTSTR lpszLibFile, HANDLE hFile, DWORD dwFlags)
281{
282 Win32Dll *module;
283 HINSTANCE hDll;
284
285 dprintf(("KERNEL32: LoadLibraryExA %s (%X)\n", lpszLibFile, dwFlags));
286 hDll = O32_LoadLibrary(lpszLibFile);
287 if(hDll) {
288 return hDll; //converted dll or win32k took care of it
289 }
290
291 if(Win32Image::isPEImage((char *)lpszLibFile)) {
292 module = Win32Dll::findModule((char *)lpszLibFile);
293 if(module) {//don't load it again
294 module->AddRef();
295 return module->getInstanceHandle();
296 }
297 module = new Win32Dll((char *)lpszLibFile);
298 if(module == NULL)
299 return(0);
300
301 module->init();
302 if(module->getError() != NO_ERROR) {
303 dprintf(("LoadLibary %s failed (::init)\n", lpszLibFile));
304 delete module;
305 return(0);
306 }
307 if(dwFlags & DONT_RESOLVE_DLL_REFERENCES) {
308 module->setNoEntryCalls();
309 }
310 if(module->attachProcess() == FALSE) {
311 dprintf(("LoadLibary %s failed (::attachProcess)\n", lpszLibFile));
312 delete module;
313 return(0);
314 }
315 module->AddRef();
316 return module->getInstanceHandle();
317 }
318 return(0);
319}
320//******************************************************************************
321//******************************************************************************
322HINSTANCE WIN32API LoadLibraryW(LPCWSTR lpModule)
323{
324 char *asciimodule;
325 HINSTANCE rc;
326
327 asciimodule = UnicodeToAsciiString((LPWSTR)lpModule);
328 dprintf(("KERNEL32: OS2LoadLibraryW %s\n", asciimodule));
329 rc = LoadLibraryA(asciimodule);
330 free(asciimodule);
331 return(rc);
332}
333//******************************************************************************
334//******************************************************************************
335HINSTANCE WIN32API LoadLibraryExW(LPCWSTR lpModule, HANDLE hFile, DWORD dwFlags)
336{
337 char *asciimodule;
338 HINSTANCE rc;
339
340 asciimodule = UnicodeToAsciiString((LPWSTR)lpModule);
341 dprintf(("KERNEL32: OS2LoadLibraryExW %s (%d)\n", asciimodule, dwFlags));
342 rc = LoadLibraryExA(asciimodule, hFile, dwFlags);
343 free(asciimodule);
344 return(rc);
345}
346//******************************************************************************
347//******************************************************************************
348LPCSTR WIN32API GetCommandLineA()
349{
350 LPTSTR cmdline = NULL;
351
352 if(WinExe) {
353 cmdline = WinExe->getCommandLine();
354 }
355 if(cmdline == NULL) //not used for converted exes
356 cmdline = O32_GetCommandLine();
357
358 dprintf(("KERNEL32: GetCommandLine %s\n", cmdline));
359 //SvL: Replace original startup code exception handler
360 ReplaceExceptionHandler();
361 return(cmdline);
362}
363//******************************************************************************
364//******************************************************************************
365LPCWSTR WIN32API GetCommandLineW(void)
366{
367 static WCHAR *UnicodeCmdLine = NULL;
368 char *asciicmdline = NULL;
369
370 //SvL: Replace original startup code exception handler
371 ReplaceExceptionHandler();
372
373 if(UnicodeCmdLine)
374 return(UnicodeCmdLine); //already called before
375
376 if(WinExe) {
377 asciicmdline = WinExe->getCommandLine();
378 }
379 if(asciicmdline == NULL) //not used for converted exes
380 asciicmdline = O32_GetCommandLine();
381
382 if(asciicmdline) {
383 UnicodeCmdLine = (WCHAR *)malloc(strlen(asciicmdline)*2 + 2);
384 AsciiToUnicode(asciicmdline, UnicodeCmdLine);
385 dprintf(("KERNEL32: OS2GetCommandLineW: %s\n", asciicmdline));
386 return(UnicodeCmdLine);
387 }
388 dprintf(("KERNEL32: OS2GetCommandLineW: asciicmdline == NULL\n"));
389 return NULL;
390}
391//******************************************************************************
392//******************************************************************************
393DWORD WIN32API GetModuleFileNameA(HMODULE hinstModule, LPTSTR lpszPath, DWORD cchPath)
394{
395 DWORD rc;
396 Win32Image *module;
397 char *fpath = NULL;
398
399 dprintf(("GetModuleFileName %X", hinstModule));
400 if(hinstModule == 0 || hinstModule == -1 || (WinExe && hinstModule == WinExe->getOS2InstanceHandle())) {
401 module = (Win32Image *)WinExe;
402 }
403 else {
404 module = (Win32Image *)Win32Dll::findModule(hinstModule);
405 }
406
407 if(module) {
408 fpath = module->getFullPath();
409 }
410 if(fpath) {
411 //SvL: 13-9-98: +1
412 rc = min(strlen(fpath)+1, cchPath);
413 strncpy(lpszPath, fpath, rc);
414 }
415 else rc = O32_GetModuleFileName(hinstModule, lpszPath, cchPath);
416
417 if(rc) {
418 dprintf(("KERNEL32: GetModuleFileName %s %d\n", lpszPath, hinstModule));
419 }
420 return(rc);
421}
422//******************************************************************************
423//******************************************************************************
424DWORD WIN32API GetModuleFileNameW(HMODULE hModule, LPWSTR lpFileName, DWORD nSize)
425{
426 char *asciifilename = (char *)malloc(nSize+1);
427 DWORD rc;
428
429 dprintf(("KERNEL32: OS2GetModuleFileNameW\n"));
430 rc = GetModuleFileNameA(hModule, asciifilename, nSize);
431 if(rc) AsciiToUnicode(asciifilename, lpFileName);
432 free(asciifilename);
433 return(rc);
434}
435//******************************************************************************
436//******************************************************************************
437BOOL WIN32API CreateProcessA(LPCSTR lpszImageName, LPSTR lpszCommandLine,
438 PSECURITY_ATTRIBUTES arg3,
439 PSECURITY_ATTRIBUTES arg4, BOOL arg5, DWORD arg6,
440 PVOID arg7, LPCSTR arg8, LPSTARTUPINFOA arg9,
441 LPPROCESS_INFORMATION arg10)
442{
443 BOOL rc;
444 char *cmdline;
445 BOOL fAllocStr = FALSE;
446
447 if(O32_CreateProcess(lpszImageName, lpszCommandLine, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) == TRUE)
448 return(TRUE);
449
450 //probably a win32 exe, so run it in the pe loader
451 if(lpszImageName) {
452 if(lpszCommandLine) {
453 cmdline = (char *)malloc(strlen(lpszImageName)+strlen(lpszCommandLine) + 16);
454 sprintf(cmdline, "%s %s", lpszImageName, lpszCommandLine);
455 fAllocStr = TRUE;
456 }
457 else cmdline = (char *)lpszImageName;
458 }
459 else cmdline = (char *)lpszCommandLine;
460
461 dprintf(("KERNEL32: CreateProcess %s\n", cmdline));
462 rc = O32_CreateProcess("PE.EXE", (LPCSTR)cmdline, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
463 if(fAllocStr)
464 free(cmdline);
465
466 dprintf(("KERNEL32: CreateProcess returned %d\n", rc));
467 return(rc);
468}
469//******************************************************************************
470//******************************************************************************
471BOOL WIN32API CreateProcessW(LPCWSTR arg1, LPWSTR arg2,
472 PSECURITY_ATTRIBUTES arg3,
473 PSECURITY_ATTRIBUTES arg4,
474 BOOL arg5, DWORD arg6, PVOID arg7,
475 LPCWSTR arg8, LPSTARTUPINFOW arg9,
476 LPPROCESS_INFORMATION arg10)
477{
478 BOOL rc;
479 char *astring1, *astring2, *astring3;
480
481 dprintf(("KERNEL32: OS2CreateProcessW DOESN't WORK"));
482 astring1 = UnicodeToAsciiString((LPWSTR)arg1);
483 astring2 = UnicodeToAsciiString(arg2);
484 astring3 = UnicodeToAsciiString((LPWSTR)arg8);
485 // NOTE: This will not work as is (needs UNICODE support)
486 rc = CreateProcessA(astring1, astring2, arg3, arg4, arg5, arg6, arg7,
487 astring3, (LPSTARTUPINFOA)arg9, arg10);
488 FreeAsciiString(astring3);
489 FreeAsciiString(astring2);
490 FreeAsciiString(astring1);
491 return(rc);
492}
493//******************************************************************************
494//******************************************************************************
495FARPROC WIN32API GetProcAddress(HMODULE hModule, LPCSTR lpszProc)
496{
497 Win32Dll *winmod;
498 FARPROC proc;
499 ULONG ulAPIOrdinal;
500
501 winmod = Win32Dll::findModule((HINSTANCE)hModule);
502 if(winmod) {
503 ulAPIOrdinal = (ULONG)lpszProc;
504 if (ulAPIOrdinal <= 0x0000FFFF) {
505 return (FARPROC)winmod->getApi((int)ulAPIOrdinal);
506 }
507 else return (FARPROC)winmod->getApi((char *)lpszProc);
508 }
509 proc = O32_GetProcAddress(hModule, lpszProc);
510 dprintf(("KERNEL32: GetProcAddress %s from %X returned %X\n", lpszProc, hModule, proc));
511 return(proc);
512}
513//******************************************************************************
514//Retrieve the version
515//******************************************************************************
516BOOL SYSTEM GetVersionStruct(char *modname, char *verstruct, ULONG bufLength)
517{
518 HINSTANCE hinstance;
519 Win32Image *winimage;
520
521 dprintf(("GetVersionStruct"));
522 hinstance = OS2QueryModuleHandle(modname);
523 if(hinstance == 0) {
524 dprintf(("GetVersionStruct can't find handle for %s\n", modname));
525 return(FALSE);
526 }
527 if(WinExe && WinExe->getOS2InstanceHandle() == hinstance) {
528 winimage = (Win32Image *)WinExe;
529 }
530 else {
531 winimage = (Win32Image *)Win32Dll::findModule(hinstance);
532 if(winimage == NULL) {
533 dprintf(("GetVersionStruct can't find Win32Image for %s\n", modname));
534 return(FALSE);
535 }
536 }
537 if(winimage->getVersionId() == -1) {
538 dprintf(("GetVersionStruct: %s has no version resource!\n", modname));
539 return(FALSE);
540 }
541 return OS2GetResource(hinstance, winimage->getVersionId(), verstruct, bufLength);
542}
543//******************************************************************************
544//******************************************************************************
545ULONG SYSTEM GetVersionSize(char *modname)
546{
547 HINSTANCE hinstance;
548 Win32Image *winimage;
549
550 dprintf(("GetVersionSize of %s\n", modname));
551 hinstance = OS2QueryModuleHandle(modname);
552 if(hinstance == 0) {
553 dprintf(("GetVersionSize can't find handle for %s\n", modname));
554 return(FALSE);
555 }
556
557 if(WinExe && WinExe->getOS2InstanceHandle() == hinstance) {
558 winimage = (Win32Image *)WinExe;
559 }
560 else {
561 winimage = (Win32Image *)Win32Dll::findModule(hinstance);
562 if(winimage == NULL) {
563 dprintf(("GetVersionSize can't find Win32Image for %s\n", modname));
564 return(FALSE);
565 }
566 }
567 if(winimage->getVersionId() == -1) {
568 dprintf(("GetVersionSize: %s has no version resource!\n", modname));
569 return(FALSE);
570 }
571 ULONG size = OS2GetResourceSize(hinstance, winimage->getVersionId());
572
573 dprintf(("Version resource size = %d, id %d\n", size, winimage->getVersionId()));
574 return(size);
575}
576//******************************************************************************
577//******************************************************************************
Note: See TracBrowser for help on using the repository browser.