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

Last change on this file since 3128 was 3128, checked in by sandervl, 25 years ago

handlemanager support for thread handles + WaitForSingleObject (thread) fix

File size: 33.9 KB
Line 
1/* $Id: wprocess.cpp,v 1.73 2000-03-16 19:20:40 sandervl Exp $ */
2
3/*
4 * Win32 process functions
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * NOTE: Even though Odin32 OS/2 apps don't switch FS selectors,
9 * we still allocate a TEB to store misc information.
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 */
14#include <odin.h>
15#include <odinwrap.h>
16#include <os2win.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include <unicode.h>
22#include "windllbase.h"
23#include "winexebase.h"
24#include "windllpeldr.h"
25#include "winexepe2lx.h"
26#include "winfakepeldr.h"
27#include <vmutex.h>
28#include <handlemanager.h>
29
30#ifdef __IBMCPP__
31#include <builtin.h>
32#endif
33
34#include "exceptutil.h"
35#include "oslibmisc.h"
36#include "oslibdebug.h"
37
38#include "console.h"
39#include "cio.h"
40#include "versionos2.h" /*PLF Wed 98-03-18 02:36:51*/
41#include <wprocess.h>
42#include "mmap.h"
43
44#define DBG_LOCALLOG DBG_wprocess
45#include "dbglocal.h"
46
47ODINDEBUGCHANNEL(KERNEL32-WPROCESS)
48
49
50//******************************************************************************
51//******************************************************************************
52BOOL fFreeLibrary = FALSE;
53BOOL fIsOS2Image = FALSE; //TRUE -> Odin32 OS/2 application (not converted!)
54 //FALSE -> otherwise
55//Process database
56PDB ProcessPDB = {0};
57USHORT ProcessTIBSel = 0;
58DWORD *TIBFlatPtr = 0;
59
60//list of thread database structures
61static THDB *threadList = 0;
62static VMutex threadListMutex;
63//******************************************************************************
64//******************************************************************************
65TEB *WIN32API GetThreadTEB()
66{
67 if(TIBFlatPtr == NULL)
68 return 0;
69
70 return (TEB *)*TIBFlatPtr;
71}
72//******************************************************************************
73//******************************************************************************
74THDB *WIN32API GetThreadTHDB()
75{
76 TEB *winteb;
77 THDB *thdb;
78
79 if(TIBFlatPtr == NULL)
80 return 0;
81
82 winteb = (TEB *)*TIBFlatPtr;
83 if(winteb == NULL) {
84 return NULL;
85 }
86 thdb = (THDB *)(winteb+1);
87
88 return thdb;
89}
90//******************************************************************************
91//******************************************************************************
92THDB *WIN32API GetTHDBFromThreadId(ULONG threadId)
93{
94 THDB *thdb = threadList;
95
96 threadListMutex.enter();
97 while(thdb) {
98 if(thdb->threadId == threadId) {
99 break;
100 }
101 thdb = thdb->next;
102 }
103 threadListMutex.leave();
104 return thdb;
105}
106//******************************************************************************
107//******************************************************************************
108THDB *WIN32API GetTHDBFromThreadHandle(HANDLE hThread)
109{
110 THDB *thdb = threadList;
111
112 threadListMutex.enter();
113 while(thdb) {
114 if(thdb->hThread == hThread) {
115 break;
116 }
117 thdb = thdb->next;
118 }
119 threadListMutex.leave();
120 return thdb;
121}
122//******************************************************************************
123// Set up the TIB selector and memory for the current thread
124//******************************************************************************
125TEB *InitializeTIB(BOOL fMainThread)
126{
127 TEB *winteb;
128 THDB *thdb;
129 ULONG hThreadMain;
130 USHORT tibsel;
131
132 //Allocate one dword to store the flat address of our TEB
133 if(fMainThread) {
134 TIBFlatPtr = (DWORD *)OSLibAllocThreadLocalMemory(1);
135 if(TIBFlatPtr == 0) {
136 dprintf(("InitializeTIB: local thread memory alloc failed!!"));
137 DebugInt3();
138 return NULL;
139 }
140 HMHandleAllocate(&hThreadMain, O32_GetCurrentThread());
141 }
142 if(OSLibAllocSel(PAGE_SIZE, &tibsel) == FALSE)
143 {
144 dprintf(("InitializeTIB: selector alloc failed!!"));
145 DebugInt3();
146 return NULL;
147 }
148 winteb = (TEB *)OSLibSelToFlat(tibsel);
149 if(winteb == NULL)
150 {
151 dprintf(("InitializeTIB: DosSelToFlat failed!!"));
152 DebugInt3();
153 return NULL;
154 }
155 memset(winteb, 0, PAGE_SIZE);
156 thdb = (THDB *)(winteb+1);
157 *TIBFlatPtr = (DWORD)winteb;
158
159 winteb->except = (PVOID)-1; /* 00 Head of exception handling chain */
160 winteb->stack_top = (PVOID)OSLibGetTIB(TIB_STACKTOP); /* 04 Top of thread stack */
161 winteb->stack_low = (PVOID)OSLibGetTIB(TIB_STACKLOW); /* 08 Stack low-water mark */
162 winteb->htask16 = (USHORT)OSLibGetPIB(PIB_TASKHNDL); /* 0c Win16 task handle */
163 winteb->stack_sel = getSS(); /* 0e 16-bit stack selector */
164 winteb->self = winteb; /* 18 Pointer to this structure */
165 winteb->flags = TEBF_WIN32; /* 1c Flags */
166 winteb->queue = 0; /* 28 Message queue */
167 winteb->tls_ptr = &thdb->tls_array[0]; /* 2c Pointer to TLS array */
168 winteb->process = &ProcessPDB; /* 30 owning process (used by NT3.51 applets)*/
169
170 memcpy(&thdb->teb, winteb, sizeof(TEB));
171 thdb->process = &ProcessPDB;
172 thdb->exit_code = 0x103; /* STILL_ACTIVE */
173 thdb->teb_sel = tibsel;
174 thdb->OrgTIBSel = GetFS();
175 thdb->pWsockData = NULL;
176 thdb->threadId = GetCurrentThreadId();
177 if(fMainThread) {
178 thdb->hThread = hThreadMain;
179 }
180 else thdb->hThread = GetCurrentThread();
181
182 threadListMutex.enter();
183 THDB *thdblast = threadList;
184 if(!thdblast) {
185 threadList = thdb;
186 }
187 else {
188 while(thdblast->next) {
189 thdblast = thdblast->next;
190 }
191 thdblast->next = thdb;
192 }
193 thdb->next = NULL;
194 threadListMutex.leave();
195
196 if(OSLibGetPIB(PIB_TASKTYPE) == TASKTYPE_PM)
197 {
198 thdb->flags = 0; //todo gui
199 }
200 else thdb->flags = 0; //todo textmode
201
202 if(fMainThread)
203 {
204 //todo initialize PDB during process creation
205 //todo: initialize TLS array if required
206 //TLS in executable always TLS index 0?
207 ProcessTIBSel = tibsel;
208 ProcessPDB.exit_code = 0x103; /* STILL_ACTIVE */
209 ProcessPDB.threads = 1;
210 ProcessPDB.running_threads = 1;
211 ProcessPDB.ring0_threads = 1;
212 ProcessPDB.system_heap = GetProcessHeap();
213 ProcessPDB.parent = 0;
214 ProcessPDB.group = &ProcessPDB;
215 ProcessPDB.priority = 8; /* Normal */
216 ProcessPDB.heap = ProcessPDB.system_heap; /* will be changed later on */
217 ProcessPDB.next = NULL;
218 ProcessPDB.winver = 0xffff; /* to be determined */
219 ProcessPDB.server_pid = (void *)GetCurrentProcessId();
220
221 GetSystemTime(&ProcessPDB.creationTime);
222
223 /* Initialize the critical section */
224 InitializeCriticalSection( &ProcessPDB.crit_section );
225 }
226 dprintf(("InitializeTIB setup TEB with selector %x", tibsel));
227 dprintf(("InitializeTIB: FS(%x):[0] = %x", GetFS(), QueryExceptionChain()));
228 return winteb;
229}
230//******************************************************************************
231// Destroy the TIB selector and memory for the current thread
232//******************************************************************************
233void DestroyTIB()
234{
235 SHORT orgtibsel;
236 TEB *winteb;
237 THDB *thdb;
238
239 dprintf(("DestroyTIB: FS = %x", GetFS()));
240 dprintf(("DestroyTIB: FS:[0] = %x", QueryExceptionChain()));
241
242 winteb = (TEB *)*TIBFlatPtr;
243 if(winteb) {
244 thdb = (THDB *)(winteb+1);
245 orgtibsel = thdb->OrgTIBSel;
246
247 threadListMutex.enter();
248 THDB *curthdb = threadList;
249 if(curthdb == thdb) {
250 threadList = thdb->next;
251 }
252 else {
253 while(curthdb->next != thdb) {
254 curthdb = curthdb->next;
255 if(curthdb == NULL) {
256 dprintf(("DestroyTIB: couldn't find thdb %x", thdb));
257 DebugInt3();
258 break;
259 }
260 }
261 if(curthdb) {
262 curthdb->next = thdb->next;
263 }
264 }
265 threadListMutex.leave();
266
267 //Restore our original FS selector
268 SetFS(orgtibsel);
269
270 //And free our own
271 OSLibFreeSel(thdb->teb_sel);
272
273 *TIBFlatPtr = 0;
274 }
275 else dprintf(("Already destroyed TIB"));
276
277 dprintf(("DestroyTIB: FS(%x):[0] = %x", GetFS(), QueryExceptionChain()));
278 return;
279}
280/******************************************************************************/
281/******************************************************************************/
282void SetPDBInstance(HINSTANCE hInstance)
283{
284 ProcessPDB.hInstance = hInstance;
285}
286/******************************************************************************/
287/******************************************************************************/
288void WIN32API RestoreOS2TIB()
289{
290 SHORT orgtibsel;
291 TEB *winteb;
292 THDB *thdb;
293
294 //If we're running an Odin32 OS/2 application (not converted!), then we
295 //we don't switch FS selectors
296 if(fIsOS2Image) {
297 return;
298 }
299
300 winteb = (TEB *)*TIBFlatPtr;
301 if(winteb) {
302 thdb = (THDB *)(winteb+1);
303 orgtibsel = thdb->OrgTIBSel;
304
305 //Restore our original FS selector
306 SetFS(orgtibsel);
307 }
308}
309/******************************************************************************/
310/******************************************************************************/
311USHORT WIN32API SetWin32TIB()
312{
313 SHORT win32tibsel;
314 TEB *winteb;
315 THDB *thdb;
316
317 //If we're running an Odin32 OS/2 application (not converted!), then we
318 //we don't switch FS selectors
319 if(fIsOS2Image) {
320 return GetFS();
321 }
322
323 winteb = (TEB *)*TIBFlatPtr;
324 if(winteb) {
325 thdb = (THDB *)(winteb+1);
326 win32tibsel = thdb->teb_sel;
327
328 //Restore our win32 FS selector
329 return SetReturnFS(win32tibsel);
330 }
331 else {
332 //we didn't create this thread, so allocate a selector now
333 //NOTE: Possible memory leak (i.e. DART threads in WINMM)
334 winteb = InitializeTIB();
335 if(winteb == NULL) {
336 DebugInt3();
337 return GetFS();
338 }
339 thdb = (THDB *)(winteb+1);
340 win32tibsel = thdb->teb_sel;
341
342 //Restore our win32 FS selector
343 return SetReturnFS(win32tibsel);
344 }
345 // nested calls are OK, OS2ToWinCallback for instance
346 //else DebugInt3();
347
348 return GetFS();
349}
350//******************************************************************************
351//******************************************************************************
352VOID WIN32API ExitProcess(DWORD exitcode)
353{
354 dprintf(("KERNEL32: ExitProcess %d\n", exitcode));
355 dprintf(("KERNEL32: ExitProcess FS = %x\n", GetFS()));
356
357 SetOS2ExceptionChain(-1);
358
359 if(WinExe) {
360 delete(WinExe);
361 WinExe = NULL;
362 }
363
364 //Note: Needs to be done after deleting WinExe (destruction of exe + dll objects)
365 //Flush and delete all open memory mapped files
366 Win32MemMap::deleteAll();
367
368 //Restore original OS/2 TIB selector
369 DestroyTIB();
370 SetExceptionChain((ULONG)-1);
371
372 //avoid crashes since win32 & OS/2 exception handler aren't identical
373 //(terminate process generates two exceptions)
374 /* @@@PH 1998/02/12 Added Console Support */
375 if (iConsoleIsActive())
376 iConsoleWaitClose();
377
378 O32_ExitProcess(exitcode);
379}
380//******************************************************************************
381//******************************************************************************
382BOOL WIN32API FreeLibrary(HINSTANCE hinstance)
383{
384 Win32DllBase *winmod;
385 BOOL rc;
386
387 winmod = Win32DllBase::findModule(hinstance);
388 if(winmod) {
389 dprintf(("FreeLibrary %s", winmod->getName()));
390 //Only free it when the nrDynamicLibRef != 0
391 //This prevent problems after ExitProcess:
392 //i.e. dll A is referenced by our exe and loaded with LoadLibrary by dll B
393 // During ExitProcess it's unloaded once (before dll B), dll B calls
394 // FreeLibrary, but our exe also has a reference -> unloaded too many times
395 if(winmod->isDynamicLib()) {
396 winmod->decDynamicLib();
397 winmod->Release();
398 }
399 else {
400 dprintf(("Skipping dynamic unload as nrDynamicLibRef == 0"));
401 }
402 return(TRUE);
403 }
404 dprintf(("KERNEL32: FreeLibrary %s %X\n", OSLibGetDllName(hinstance), hinstance));
405
406 //TODO: Not thread safe
407 fFreeLibrary = TRUE; //ditch dll
408 rc = O32_FreeLibrary(hinstance);
409 fFreeLibrary = FALSE;
410 dprintf(("FreeLibrary returned %X\n", rc));
411 return(TRUE);
412}
413/******************************************************************************/
414/******************************************************************************/
415static HINSTANCE iLoadLibraryA(LPCTSTR lpszLibFile, DWORD dwFlags)
416{
417 char modname[CCHMAXPATH];
418 HINSTANCE hDll;
419 Win32DllBase *module;
420
421 module = Win32DllBase::findModule((LPSTR)lpszLibFile);
422 if(module) {
423 if(module->isLxDll() && !module->isLoaded() && !fPe2Lx) {
424 //can happen with i.e. wininet
425 //wininet depends on wsock32; when the app loads wsock32 afterwards
426 //with LoadLibrary or as a child of another dll, we need to make
427 //sure it's loaded once with DosLoadModule
428 module->setLoadLibrary();
429 }
430 module->incDynamicLib();
431 module->AddRef();
432 dprintf(("iLoadLibrary: found %s -> handle %x", lpszLibFile, module->getInstanceHandle()));
433 return module->getInstanceHandle();
434 }
435
436 strcpy(modname, lpszLibFile);
437 strupr(modname);
438 //rename dll if necessary (i.e. OLE32 -> OLE32OS2)
439 Win32DllBase::renameDll(modname);
440
441 hDll = O32_LoadLibrary(modname);
442 dprintf(("KERNEL32: iLoadLibraryA %s returned %X (%d)\n",
443 lpszLibFile,
444 hDll,
445 GetLastError()));
446 if(hDll)
447 {
448 module = Win32DllBase::findModule(hDll);
449 if(module && module->isLxDll() && !fPe2Lx) {
450 module->setLoadLibrary();
451 module->AddRef();
452 }
453 if(module)
454 module->incDynamicLib();
455 //system dll, converted dll or win32k took care of it
456 return hDll;
457 }
458
459 if(!strstr(modname, ".")) {
460 strcat(modname,".DLL");
461 }
462
463 if(Win32ImageBase::isPEImage((char *)modname))
464 {
465 module = Win32DllBase::findModule((char *)modname);
466 if(module) {//don't load it again
467 module->incDynamicLib();
468 module->AddRef();
469 return module->getInstanceHandle();
470 }
471
472 Win32PeLdrDll *peldrDll = new Win32PeLdrDll((char *)modname);
473 if(peldrDll == NULL)
474 return(0);
475
476 peldrDll->init(0);
477 if(peldrDll->getError() != NO_ERROR) {
478 dprintf(("LoadLibary %s failed (::init)\n", lpszLibFile));
479 delete(peldrDll);
480 return(0);
481 }
482 if(dwFlags & DONT_RESOLVE_DLL_REFERENCES) {
483 peldrDll->setNoEntryCalls();
484 }
485 peldrDll->incDynamicLib();
486 peldrDll->AddRef();
487
488 if(peldrDll->attachProcess() == FALSE) {
489 dprintf(("LoadLibary %s failed (::attachProcess)\n", lpszLibFile));
490 delete(peldrDll);
491 return(0);
492 }
493 return peldrDll->getInstanceHandle();
494 }
495 else return(0);
496}
497//******************************************************************************
498//******************************************************************************
499HINSTANCE16 WIN32API LoadLibrary16(LPCTSTR lpszLibFile)
500{
501 dprintf(("ERROR: LoadLibrary16 %s, not implemented", lpszLibFile));
502 return 0;
503}
504//******************************************************************************
505//******************************************************************************
506VOID WIN32API FreeLibrary16(HINSTANCE16 hinstance)
507{
508 dprintf(("ERROR: FreeLibrary16 %x, not implemented", hinstance));
509}
510//******************************************************************************
511//******************************************************************************
512FARPROC WIN32API GetProcAddress16(HMODULE hModule, LPCSTR lpszProc)
513{
514 dprintf(("ERROR: GetProcAddress16 %x %x, not implemented", hModule, lpszProc));
515 return 0;
516}
517//******************************************************************************
518//******************************************************************************
519HINSTANCE WIN32API LoadLibraryA(LPCTSTR lpszLibFile)
520{
521 HINSTANCE hDll;
522
523 dprintf(("KERNEL32: LoadLibraryA(%s)\n",
524 lpszLibFile));
525 dprintf(("KERNEL32: LoadLibrary %x FS = %x\n", GetCurrentThreadId(), GetFS()));
526
527 hDll = iLoadLibraryA(lpszLibFile, 0);
528 if (hDll == 0)
529 {
530 char * pszName;
531
532 // remove path from the image name
533 pszName = strrchr((char *)lpszLibFile,
534 '\\');
535 if (pszName != NULL)
536 {
537 pszName++; // skip backslash
538
539 // now try again without fully qualified path
540 hDll = iLoadLibraryA(pszName, 0);
541 }
542 }
543
544 return hDll;
545}
546//******************************************************************************
547//******************************************************************************
548HINSTANCE WIN32API LoadLibraryExA(LPCTSTR lpszLibFile, HANDLE hFile, DWORD dwFlags)
549{
550 HINSTANCE hDll;
551
552 dprintf(("KERNEL32: LoadLibraryExA %s (%X)\n", lpszLibFile, dwFlags));
553 hDll = iLoadLibraryA(lpszLibFile, dwFlags);
554 if (hDll == 0)
555 {
556 char * pszName;
557
558 // remove path from the image name
559 pszName = strrchr((char *)lpszLibFile,
560 '\\');
561 if (pszName != NULL)
562 {
563 pszName++; // skip backslash
564
565 // now try again without fully qualified path
566 hDll = iLoadLibraryA(pszName, dwFlags);
567 }
568 }
569
570 return hDll;
571}
572//******************************************************************************
573//******************************************************************************
574HINSTANCE WIN32API LoadLibraryW(LPCWSTR lpModule)
575{
576 char *asciimodule;
577 HINSTANCE rc;
578
579 asciimodule = UnicodeToAsciiString((LPWSTR)lpModule);
580 dprintf(("KERNEL32: OS2LoadLibraryW %s\n", asciimodule));
581 rc = LoadLibraryA(asciimodule);
582 free(asciimodule);
583 return(rc);
584}
585//******************************************************************************
586//******************************************************************************
587HINSTANCE WIN32API LoadLibraryExW(LPCWSTR lpModule, HANDLE hFile, DWORD dwFlags)
588{
589 char *asciimodule;
590 HINSTANCE rc;
591
592 asciimodule = UnicodeToAsciiString((LPWSTR)lpModule);
593 dprintf(("KERNEL32: OS2LoadLibraryExW %s (%d)\n", asciimodule, dwFlags));
594 rc = LoadLibraryExA(asciimodule, hFile, dwFlags);
595 free(asciimodule);
596 return(rc);
597}
598//******************************************************************************
599//******************************************************************************
600LPCSTR WIN32API GetCommandLineA()
601{
602 LPTSTR cmdline = NULL;
603
604 if(WinExe) {
605 cmdline = WinExe->getCommandLineA();
606 }
607 if(cmdline == NULL) //not used for converted exes
608 cmdline = O32_GetCommandLine();
609
610 dprintf(("KERNEL32: GetCommandLine %s\n", cmdline));
611 dprintf(("KERNEL32: FS = %x\n", GetFS()));
612 return(cmdline);
613}
614//******************************************************************************
615//******************************************************************************
616LPCWSTR WIN32API GetCommandLineW(void)
617{
618 static WCHAR *UnicodeCmdLine = NULL;
619 char *asciicmdline = NULL;
620
621 dprintf(("KERNEL32: FS = %x\n", GetFS()));
622
623 if(UnicodeCmdLine)
624 return(UnicodeCmdLine); //already called before
625
626 if(WinExe) {
627 if(WinExe->getCommandLineW())
628 return WinExe->getCommandLineW();
629 }
630 if(asciicmdline == NULL) //not used for converted exes
631 asciicmdline = O32_GetCommandLine();
632
633 if(asciicmdline) {
634 UnicodeCmdLine = (WCHAR *)malloc(strlen(asciicmdline)*2 + 2);
635 AsciiToUnicode(asciicmdline, UnicodeCmdLine);
636 dprintf(("KERNEL32: OS2GetCommandLineW: %s\n", asciicmdline));
637 return(UnicodeCmdLine);
638 }
639 dprintf(("KERNEL32: OS2GetCommandLineW: asciicmdline == NULL\n"));
640 return NULL;
641}
642//******************************************************************************
643//******************************************************************************
644DWORD WIN32API GetModuleFileNameA(HMODULE hinstModule, LPTSTR lpszPath, DWORD cchPath)
645{
646 DWORD rc;
647 Win32ImageBase *module;
648 char *fpath = NULL;
649
650 dprintf(("GetModuleFileName %X", hinstModule));
651 if(hinstModule == 0 || hinstModule == -1 || (WinExe && hinstModule == WinExe->getInstanceHandle())) {
652 module = (Win32ImageBase *)WinExe;
653 }
654 else {
655 module = (Win32ImageBase *)Win32DllBase::findModule(hinstModule);
656 }
657
658 if(module) {
659 fpath = module->getFullPath();
660 }
661 if(fpath) {
662 //SvL: 13-9-98: +1
663 rc = min(strlen(fpath)+1, cchPath);
664 strncpy(lpszPath, fpath, rc);
665 }
666 else rc = O32_GetModuleFileName(hinstModule, lpszPath, cchPath);
667
668 if(rc) {
669 dprintf(("KERNEL32: GetModuleFileName %s %d\n", lpszPath, hinstModule));
670 }
671 return(rc);
672}
673//******************************************************************************
674//******************************************************************************
675DWORD WIN32API GetModuleFileNameW(HMODULE hModule, LPWSTR lpFileName, DWORD nSize)
676{
677 char *asciifilename = (char *)malloc(nSize+1);
678 DWORD rc;
679
680 dprintf(("KERNEL32: OSLibGetModuleFileNameW\n"));
681 rc = GetModuleFileNameA(hModule, asciifilename, nSize);
682 if(rc) AsciiToUnicode(asciifilename, lpFileName);
683 free(asciifilename);
684 return(rc);
685}
686//******************************************************************************
687//NOTE: GetModuleHandleA does NOT support files with multiple dots (i.e.
688// very.weird.exe)
689//******************************************************************************
690HANDLE WIN32API GetModuleHandleA(LPCTSTR lpszModule)
691{
692 HANDLE hMod;
693 Win32DllBase *windll;
694 char szModule[CCHMAXPATH];
695 BOOL fDllModule = FALSE;
696
697 if(lpszModule == NULL) {
698 if(WinExe)
699 hMod = WinExe->getInstanceHandle();
700 else hMod = -1;
701 }
702 else {
703 strcpy(szModule, OSLibStripPath((char *)lpszModule));
704 strupr(szModule);
705 if(strstr(szModule, ".DLL")) {
706 fDllModule = TRUE;
707 }
708 else {
709 if(!strstr(szModule, ".")) {
710 //if there's no extension or trainling dot, we
711 //assume it's a dll (see Win32 SDK docs)
712 fDllModule = TRUE;
713 }
714 }
715 char *dot = strstr(szModule, ".");
716 if(dot)
717 *dot = 0;
718
719 if(!fDllModule && WinExe && !strcmpi(szModule, WinExe->getModuleName())) {
720 hMod = WinExe->getInstanceHandle();
721 }
722 else {
723 windll = Win32DllBase::findModule(szModule);
724 if(windll) {
725 hMod = windll->getInstanceHandle();
726 }
727 else hMod = OSLibiGetModuleHandleA((char *)lpszModule);
728 }
729 }
730
731 dprintf(("KERNEL32: GetModuleHandle %s returned %X\n", lpszModule, hMod));
732 return(hMod);
733}
734//******************************************************************************
735//******************************************************************************
736HMODULE WIN32API GetModuleHandleW(LPCWSTR arg1)
737{
738 HMODULE rc;
739 char *astring;
740
741 astring = UnicodeToAsciiString((LPWSTR)arg1);
742 rc = GetModuleHandleA(astring);
743 dprintf(("KERNEL32: OS2GetModuleHandleW %s returned %X\n", astring, rc));
744 FreeAsciiString(astring);
745 return(rc);
746}
747//******************************************************************************
748//******************************************************************************
749BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
750 LPSECURITY_ATTRIBUTES lpProcessAttributes,
751 LPSECURITY_ATTRIBUTES lpThreadAttributes,
752 BOOL bInheritHandles, DWORD dwCreationFlags,
753 LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
754 LPSTARTUPINFOA lpStartupInfo,
755 LPPROCESS_INFORMATION lpProcessInfo )
756{
757 THDB *pThreadDB = (THDB*)GetThreadTHDB();
758 char *cmdline = NULL;
759 BOOL rc;
760
761 dprintf(("KERNEL32: CreateProcessA %s cline:%s inherit:%d cFlags:%x Env:%x CurDir:%s StartupFlags:%x\n",
762 lpApplicationName, lpCommandLine, bInheritHandles, dwCreationFlags,
763 lpEnvironment, lpCurrentDirectory, lpStartupInfo));
764
765 // open32 does not support DEBUG_ONLY_THIS_PROCESS
766 if(dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
767 dwCreationFlags |= DEBUG_PROCESS;
768
769 if(O32_CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes,
770 lpThreadAttributes, bInheritHandles, dwCreationFlags,
771 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
772 lpProcessInfo) == TRUE)
773 {
774 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
775 {
776 if(pThreadDB->pidDebuggee != 0)
777 {
778 // TODO: handle this
779 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
780 }
781 else
782 {
783 pThreadDB->pidDebuggee = lpProcessInfo->dwProcessId;
784 OSLibStartDebugger((ULONG*)&pThreadDB->pidDebuggee);
785 }
786 }
787 else pThreadDB->pidDebuggee = 0;
788
789 return(TRUE);
790 }
791 //probably a win32 exe, so run it in the pe loader
792 if(lpApplicationName) {
793 if(lpCommandLine) {
794 //skip exe name in lpCommandLine
795 while(*lpCommandLine != 0 && *lpCommandLine != ' ')
796 lpCommandLine++;
797
798 if(*lpCommandLine != 0) {
799 lpCommandLine++;
800 }
801 cmdline = (char *)malloc(strlen(lpApplicationName)+strlen(lpCommandLine) + 16);
802 sprintf(cmdline, "PE.EXE %s %s", lpApplicationName, lpCommandLine);
803 }
804 else {
805 cmdline = (char *)malloc(strlen(lpApplicationName) + 16);
806 sprintf(cmdline, "PE.EXE %s", lpApplicationName);
807 }
808 }
809 else {
810 cmdline = (char *)malloc(strlen(lpCommandLine) + 16);
811 sprintf(cmdline, "PE.EXE %s", lpCommandLine);
812 }
813 dprintf(("KERNEL32: CreateProcess %s\n", cmdline));
814 rc = O32_CreateProcess("PE.EXE", (LPCSTR)cmdline,lpProcessAttributes,
815 lpThreadAttributes, bInheritHandles, dwCreationFlags,
816 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
817 lpProcessInfo);
818 if(rc == TRUE) {
819 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
820 {
821 if(pThreadDB->pidDebuggee != 0)
822 {
823 // TODO: handle this
824 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
825 }
826 else
827 {
828 pThreadDB->pidDebuggee = lpProcessInfo->dwProcessId;
829 OSLibStartDebugger((ULONG*)&pThreadDB->pidDebuggee);
830 }
831 }
832 else
833 pThreadDB->pidDebuggee = 0;
834 }
835 if(cmdline)
836 free(cmdline);
837
838 if(lpProcessInfo)
839 dprintf(("KERNEL32: CreateProcess returned %d hPro:%x hThr:%x pid:%x tid:%x\n",
840 rc, lpProcessInfo->hProcess, lpProcessInfo->hThread,
841 lpProcessInfo->dwProcessId,lpProcessInfo->dwThreadId));
842 else
843 dprintf(("KERNEL32: CreateProcess returned %d\n", rc));
844 return(rc);
845}
846//******************************************************************************
847//******************************************************************************
848BOOL WIN32API CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
849 PSECURITY_ATTRIBUTES lpProcessAttributes,
850 PSECURITY_ATTRIBUTES lpThreadAttributes,
851 BOOL bInheritHandles, DWORD dwCreationFlags,
852 LPVOID lpEnvironment,
853 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
854 LPPROCESS_INFORMATION lpProcessInfo)
855{
856 BOOL rc;
857 char *astring1 = 0, *astring2 = 0, *astring3 = 0;
858
859 dprintf(("KERNEL32: CreateProcessW"));
860 if(lpApplicationName)
861 astring1 = UnicodeToAsciiString((LPWSTR)lpApplicationName);
862 if(lpCommandLine)
863 astring2 = UnicodeToAsciiString(lpCommandLine);
864 if(lpCurrentDirectory)
865 astring3 = UnicodeToAsciiString((LPWSTR)lpCurrentDirectory);
866 rc = CreateProcessA(astring1, astring2, lpProcessAttributes, lpThreadAttributes,
867 bInheritHandles, dwCreationFlags, lpEnvironment,
868 astring3, (LPSTARTUPINFOA)lpStartupInfo,
869 lpProcessInfo);
870 if(astring3) FreeAsciiString(astring3);
871 if(astring2) FreeAsciiString(astring2);
872 if(astring1) FreeAsciiString(astring1);
873 return(rc);
874}
875//******************************************************************************
876//******************************************************************************
877HINSTANCE WIN32API WinExec(LPCSTR lpCmdLine, UINT nCmdShow)
878{
879 STARTUPINFOA startinfo = {0};
880 PROCESS_INFORMATION procinfo;
881 DWORD rc;
882
883 dprintf(("KERNEL32: WinExec %s\n", lpCmdLine));
884 startinfo.dwFlags = nCmdShow;
885 if(CreateProcessA(NULL, (LPSTR)lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL,
886 &startinfo, &procinfo) == FALSE)
887 {
888 return 0;
889 }
890 //block until the launched app waits for input (or a timeout of 15 seconds)
891 //TODO: Shouldn't call Open32, but the api in user32..
892 rc = O32_WaitForInputIdle(procinfo.hProcess, 15000);
893 if(rc != 0) {
894 dprintf(("WinExec: WaitForInputIdle %x returned %x", procinfo.hProcess, rc));
895 }
896 return procinfo.hProcess; //correct?
897}
898//******************************************************************************
899//******************************************************************************
900FARPROC WIN32API GetProcAddress(HMODULE hModule, LPCSTR lpszProc)
901{
902 Win32ImageBase *winmod;
903 FARPROC proc;
904 ULONG ulAPIOrdinal;
905
906 if(hModule == 0 || hModule == -1 || (WinExe && hModule == WinExe->getInstanceHandle())) {
907 winmod = WinExe;
908 }
909 else winmod = (Win32ImageBase *)Win32DllBase::findModule((HINSTANCE)hModule);
910
911 if(winmod) {
912 ulAPIOrdinal = (ULONG)lpszProc;
913 if (ulAPIOrdinal <= 0x0000FFFF) {
914 proc = (FARPROC)winmod->getApi((int)ulAPIOrdinal);
915 }
916 else proc = (FARPROC)winmod->getApi((char *)lpszProc);
917 if(proc == 0) {
918 SetLastError(ERROR_PROC_NOT_FOUND);
919 }
920 return proc;
921 }
922 proc = O32_GetProcAddress(hModule, lpszProc);
923 if(HIWORD(lpszProc))
924 dprintf(("KERNEL32: GetProcAddress %s from %X returned %X\n", lpszProc, hModule, proc));
925 else dprintf(("KERNEL32: GetProcAddress %x from %X returned %X\n", lpszProc, hModule, proc));
926 return(proc);
927}
928//******************************************************************************
929//Retrieve the version
930//******************************************************************************
931BOOL SYSTEM GetVersionStruct(char *lpszModName, char *verstruct, ULONG bufLength)
932{
933 Win32ImageBase *winimage;
934 Win32PeLdrRsrcImg *rsrcimg;
935
936 dprintf(("GetVersionStruct of module %s", lpszModName));
937 if(WinExe && !stricmp(WinExe->getFullPath(), lpszModName)) {
938 winimage = (Win32ImageBase *)WinExe;
939 }
940 else {
941 winimage = (Win32ImageBase *)Win32DllBase::findModule(lpszModName);
942 if(winimage == NULL)
943 {
944 char modname[CCHMAXPATH];
945
946 strcpy(modname, lpszModName);
947 //rename dll if necessary (i.e. OLE32 -> OLE32OS2)
948 Win32DllBase::renameDll(modname);
949
950 if(Win32ImageBase::isPEImage(modname) == FALSE)
951 {
952 HINSTANCE hInstance;
953
954 //must be an LX dll, just load it (app will probably load it anyway)
955 hInstance = LoadLibraryA(modname);
956 if(hInstance == 0)
957 return 0;
958 winimage = (Win32ImageBase *)Win32DllBase::findModule(hInstance);
959 if(winimage) {
960 return winimage->getVersionStruct(verstruct, bufLength);
961 }
962 return 0;
963 }
964 //SvL: Try to load it
965 rsrcimg = new Win32PeLdrRsrcImg(modname);
966 if(rsrcimg == NULL)
967 return 0;
968
969 rsrcimg->init(0);
970 if(rsrcimg->getError() != NO_ERROR)
971 {
972 dprintf(("GetVersionStruct can't load %s\n", modname));
973 delete rsrcimg;
974 return(FALSE);
975 }
976 BOOL rc = rsrcimg->getVersionStruct(verstruct, bufLength);
977 delete rsrcimg;
978 return rc;
979 }
980 }
981 return winimage->getVersionStruct(verstruct, bufLength);
982}
983//******************************************************************************
984//******************************************************************************
985ULONG SYSTEM GetVersionSize(char *lpszModName)
986{
987 Win32ImageBase *winimage;
988 Win32PeLdrRsrcImg *rsrcimg;
989
990 dprintf(("GetVersionSize of %s\n", lpszModName));
991
992 if(WinExe && !stricmp(WinExe->getFullPath(), lpszModName)) {
993 winimage = (Win32ImageBase *)WinExe;
994 }
995 else {
996 winimage = (Win32ImageBase *)Win32DllBase::findModule(lpszModName);
997 if(winimage == NULL)
998 {
999 char modname[CCHMAXPATH];
1000
1001 strcpy(modname, lpszModName);
1002 //rename dll if necessary (i.e. OLE32 -> OLE32OS2)
1003 Win32DllBase::renameDll(modname);
1004
1005 if(Win32ImageBase::isPEImage(modname) == FALSE)
1006 {
1007 HINSTANCE hInstance;
1008
1009 //must be an LX dll, just load it (app will probably load it anyway)
1010 hInstance = LoadLibraryA(modname);
1011 if(hInstance == 0)
1012 return 0;
1013 winimage = (Win32ImageBase *)Win32DllBase::findModule(hInstance);
1014 if(winimage) {
1015 return winimage->getVersionSize();
1016 }
1017 return 0;
1018 }
1019
1020 //SvL: Try to load it
1021 rsrcimg = new Win32PeLdrRsrcImg(modname);
1022 if(rsrcimg == NULL)
1023 return 0;
1024
1025 rsrcimg->init(0);
1026 if(rsrcimg->getError() != NO_ERROR)
1027 {
1028 dprintf(("GetVersionSize can't load %s\n", modname));
1029 delete rsrcimg;
1030 return(FALSE);
1031 }
1032 int size = rsrcimg->getVersionSize();
1033 delete rsrcimg;
1034 return size;
1035 }
1036 }
1037 return winimage->getVersionSize();
1038}
1039//******************************************************************************
1040//TODO:What does this do exactly??
1041//******************************************************************************
1042ODINFUNCTION1(BOOL,DisableThreadLibraryCalls,HMODULE,hModule)
1043{
1044 Win32DllBase *winmod;
1045 FARPROC proc;
1046 ULONG ulAPIOrdinal;
1047
1048 winmod = Win32DllBase::findModule((HINSTANCE)hModule);
1049 if(winmod)
1050 {
1051 // don't call ATTACH/DETACH thread functions in DLL
1052 winmod->setThreadLibraryCalls(FALSE);
1053 return TRUE;
1054 }
1055 else
1056 {
1057 // raise error condition
1058 SetLastError(ERROR_INVALID_HANDLE);
1059 return FALSE;
1060 }
1061}
1062//******************************************************************************
1063//******************************************************************************
Note: See TracBrowser for help on using the repository browser.