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

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