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

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

fix for handle of thread 0

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