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

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

Fix: major restructuring of Open32 handle management, HandleManager

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