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

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

strncpy call changes + language api updates/fixes

File size: 54.5 KB
Line 
1/* $Id: wprocess.cpp,v 1.83 2000-07-06 21:18:45 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 "winexepeldr.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 "odin32validate.h"
35#include "exceptutil.h"
36#include "oslibmisc.h"
37#include "oslibdebug.h"
38
39#include "console.h"
40#include "cio.h"
41#include "versionos2.h" /*PLF Wed 98-03-18 02:36:51*/
42#include <wprocess.h>
43#include "mmap.h"
44
45#define DBG_LOCALLOG DBG_wprocess
46#include "dbglocal.h"
47
48ODINDEBUGCHANNEL(KERNEL32-WPROCESS)
49
50
51//******************************************************************************
52//******************************************************************************
53BOOL fFreeLibrary = FALSE;
54BOOL fIsOS2Image = FALSE; //TRUE -> Odin32 OS/2 application (not converted!)
55 //FALSE -> otherwise
56//Process database
57PDB ProcessPDB = {0};
58USHORT ProcessTIBSel = 0;
59DWORD *TIBFlatPtr = 0;
60
61//list of thread database structures
62static THDB *threadList = 0;
63static VMutex threadListMutex;
64
65//TODO: This should not be here: (need to rearrange NTDLL; kernel32 can't depend on ntdll)
66BOOLEAN (* WINAPI RtlAllocateAndInitializeSid) ( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
67 BYTE nSubAuthorityCount,
68 DWORD nSubAuthority0,
69 DWORD nSubAuthority1,
70 DWORD nSubAuthority2,
71 DWORD nSubAuthority3,
72 DWORD nSubAuthority4,
73 DWORD nSubAuthority5,
74 DWORD nSubAuthority6,
75 DWORD nSubAuthority7,
76 PSID *pSid);
77static HINSTANCE hInstNTDll = 0;
78//******************************************************************************
79//******************************************************************************
80TEB *WIN32API GetThreadTEB()
81{
82 if(TIBFlatPtr == NULL)
83 return 0;
84
85 return (TEB *)*TIBFlatPtr;
86}
87//******************************************************************************
88//******************************************************************************
89THDB *WIN32API GetThreadTHDB()
90{
91 TEB *winteb;
92 THDB *thdb;
93
94 if(TIBFlatPtr == NULL)
95 return 0;
96
97 winteb = (TEB *)*TIBFlatPtr;
98 if(winteb == NULL) {
99 return NULL;
100 }
101 thdb = (THDB *)(winteb+1);
102
103 return thdb;
104}
105//******************************************************************************
106//******************************************************************************
107THDB *WIN32API GetTHDBFromThreadId(ULONG threadId)
108{
109 THDB *thdb = threadList;
110
111 threadListMutex.enter();
112 while(thdb) {
113 if(thdb->threadId == threadId) {
114 break;
115 }
116 thdb = thdb->next;
117 }
118 threadListMutex.leave();
119 return thdb;
120}
121//******************************************************************************
122//******************************************************************************
123THDB *WIN32API GetTHDBFromThreadHandle(HANDLE hThread)
124{
125 THDB *thdb = threadList;
126
127 threadListMutex.enter();
128 while(thdb) {
129 if(thdb->hThread == hThread) {
130 break;
131 }
132 thdb = thdb->next;
133 }
134 threadListMutex.leave();
135 return thdb;
136}
137//******************************************************************************
138// Set up the TIB selector and memory for the current thread
139//******************************************************************************
140TEB *InitializeTIB(BOOL fMainThread)
141{
142 TEB *winteb;
143 THDB *thdb;
144 ULONG hThreadMain;
145 USHORT tibsel;
146
147 //Allocate one dword to store the flat address of our TEB
148 if(fMainThread) {
149 TIBFlatPtr = (DWORD *)OSLibAllocThreadLocalMemory(1);
150 if(TIBFlatPtr == 0) {
151 dprintf(("InitializeTIB: local thread memory alloc failed!!"));
152 DebugInt3();
153 return NULL;
154 }
155 //SvL: This doesn't really create a thread, but only sets up the
156 // handle of thread 0
157 hThreadMain = HMCreateThread(NULL, 0, 0, 0, 0, 0, TRUE);
158 }
159 if(OSLibAllocSel(PAGE_SIZE, &tibsel) == FALSE)
160 {
161 dprintf(("InitializeTIB: selector alloc failed!!"));
162 DebugInt3();
163 return NULL;
164 }
165 winteb = (TEB *)OSLibSelToFlat(tibsel);
166 if(winteb == NULL)
167 {
168 dprintf(("InitializeTIB: DosSelToFlat failed!!"));
169 DebugInt3();
170 return NULL;
171 }
172 memset(winteb, 0, PAGE_SIZE);
173 thdb = (THDB *)(winteb+1);
174 *TIBFlatPtr = (DWORD)winteb;
175
176 winteb->except = (PVOID)-1; /* 00 Head of exception handling chain */
177 winteb->stack_top = (PVOID)OSLibGetTIB(TIB_STACKTOP); /* 04 Top of thread stack */
178 winteb->stack_low = (PVOID)OSLibGetTIB(TIB_STACKLOW); /* 08 Stack low-water mark */
179 winteb->htask16 = (USHORT)OSLibGetPIB(PIB_TASKHNDL); /* 0c Win16 task handle */
180 winteb->stack_sel = getSS(); /* 0e 16-bit stack selector */
181 winteb->self = winteb; /* 18 Pointer to this structure */
182 winteb->flags = TEBF_WIN32; /* 1c Flags */
183 winteb->queue = 0; /* 28 Message queue */
184 winteb->tls_ptr = &thdb->tls_array[0]; /* 2c Pointer to TLS array */
185 winteb->process = &ProcessPDB; /* 30 owning process (used by NT3.51 applets)*/
186
187 memcpy(&thdb->teb, winteb, sizeof(TEB));
188 thdb->process = &ProcessPDB;
189 thdb->exit_code = 0x103; /* STILL_ACTIVE */
190 thdb->teb_sel = tibsel;
191 thdb->OrgTIBSel = GetFS();
192 thdb->pWsockData = NULL;
193 thdb->threadId = GetCurrentThreadId();
194 if(fMainThread) {
195 thdb->hThread = hThreadMain;
196 }
197 else thdb->hThread = GetCurrentThread();
198 thdb->lcid = GetUserDefaultLCID();
199
200 threadListMutex.enter();
201 THDB *thdblast = threadList;
202 if(!thdblast) {
203 threadList = thdb;
204 }
205 else {
206 while(thdblast->next) {
207 thdblast = thdblast->next;
208 }
209 thdblast->next = thdb;
210 }
211 thdb->next = NULL;
212 threadListMutex.leave();
213
214 if(OSLibGetPIB(PIB_TASKTYPE) == TASKTYPE_PM)
215 {
216 thdb->flags = 0; //todo gui
217 }
218 else thdb->flags = 0; //todo textmode
219
220 //Initialize thread security objects (TODO: Not complete)
221 if(hInstNTDll == 0) {
222 hInstNTDll = LoadLibraryA("NTDLL.DLL");
223 *(ULONG *)&RtlAllocateAndInitializeSid = (ULONG)GetProcAddress(hInstNTDll, "RtlAllocateAndInitializeSid");
224 if(RtlAllocateAndInitializeSid == NULL) {
225 DebugInt3();
226 }
227 }
228 SID_IDENTIFIER_AUTHORITY sidIdAuth = {0};
229 thdb->threadinfo.dwType = SECTYPE_PROCESS | SECTYPE_INITIALIZED;
230 RtlAllocateAndInitializeSid(&sidIdAuth, 1, 0, 0, 0, 0, 0, 0, 0, 0, &thdb->threadinfo.SidUser.User.Sid);
231 thdb->threadinfo.SidUser.User.Attributes = 0; //?????????
232
233 thdb->threadinfo.pTokenGroups = (TOKEN_GROUPS*)malloc(sizeof(TOKEN_GROUPS));
234 thdb->threadinfo.pTokenGroups->GroupCount = 1;
235 RtlAllocateAndInitializeSid(&sidIdAuth, 1, 0, 0, 0, 0, 0, 0, 0, 0, &thdb->threadinfo.PrimaryGroup.PrimaryGroup);
236 thdb->threadinfo.pTokenGroups->Groups[0].Sid = thdb->threadinfo.PrimaryGroup.PrimaryGroup;
237 thdb->threadinfo.pTokenGroups->Groups[0].Attributes = 0; //????
238// pPrivilegeSet = NULL;
239// pTokenPrivileges= NULL;
240// TokenOwner = {0};
241// DefaultDACL = {0};
242// TokenSource = {0};
243 thdb->threadinfo.TokenType = TokenPrimary;
244
245 if(fMainThread)
246 {
247 //todo initialize PDB during process creation
248 //todo: initialize TLS array if required
249 //TLS in executable always TLS index 0?
250 ProcessTIBSel = tibsel;
251 ProcessPDB.exit_code = 0x103; /* STILL_ACTIVE */
252 ProcessPDB.threads = 1;
253 ProcessPDB.running_threads = 1;
254 ProcessPDB.ring0_threads = 1;
255 ProcessPDB.system_heap = GetProcessHeap();
256 ProcessPDB.parent = 0;
257 ProcessPDB.group = &ProcessPDB;
258 ProcessPDB.priority = 8; /* Normal */
259 ProcessPDB.heap = ProcessPDB.system_heap; /* will be changed later on */
260 ProcessPDB.next = NULL;
261 ProcessPDB.winver = 0xffff; /* to be determined */
262 ProcessPDB.server_pid = (void *)GetCurrentProcessId();
263
264 GetSystemTime(&ProcessPDB.creationTime);
265
266 /* Initialize the critical section */
267 InitializeCriticalSection( &ProcessPDB.crit_section );
268 }
269 dprintf(("InitializeTIB setup TEB with selector %x", tibsel));
270 dprintf(("InitializeTIB: FS(%x):[0] = %x", GetFS(), QueryExceptionChain()));
271 return winteb;
272}
273//******************************************************************************
274// Destroy the TIB selector and memory for the current thread
275//******************************************************************************
276void DestroyTIB()
277{
278 SHORT orgtibsel;
279 TEB *winteb;
280 THDB *thdb;
281
282 dprintf(("DestroyTIB: FS = %x", GetFS()));
283 dprintf(("DestroyTIB: FS:[0] = %x", QueryExceptionChain()));
284
285 winteb = (TEB *)*TIBFlatPtr;
286 if(winteb) {
287 thdb = (THDB *)(winteb+1);
288 orgtibsel = thdb->OrgTIBSel;
289
290 threadListMutex.enter();
291 THDB *curthdb = threadList;
292 if(curthdb == thdb) {
293 threadList = thdb->next;
294 }
295 else {
296 while(curthdb->next != thdb) {
297 curthdb = curthdb->next;
298 if(curthdb == NULL) {
299 dprintf(("DestroyTIB: couldn't find thdb %x", thdb));
300 DebugInt3();
301 break;
302 }
303 }
304 if(curthdb) {
305 curthdb->next = thdb->next;
306 }
307 }
308 threadListMutex.leave();
309
310 //Restore our original FS selector
311 SetFS(orgtibsel);
312
313 //And free our own
314 OSLibFreeSel(thdb->teb_sel);
315
316 *TIBFlatPtr = 0;
317 }
318 else dprintf(("Already destroyed TIB"));
319
320 dprintf(("DestroyTIB: FS(%x):[0] = %x", GetFS(), QueryExceptionChain()));
321 return;
322}
323/******************************************************************************/
324/******************************************************************************/
325void SetPDBInstance(HINSTANCE hInstance)
326{
327 ProcessPDB.hInstance = hInstance;
328}
329/******************************************************************************/
330/******************************************************************************/
331void WIN32API RestoreOS2TIB()
332{
333 SHORT orgtibsel;
334 TEB *winteb;
335 THDB *thdb;
336
337 //If we're running an Odin32 OS/2 application (not converted!), then we
338 //we don't switch FS selectors
339 if(fIsOS2Image) {
340 return;
341 }
342
343 winteb = (TEB *)*TIBFlatPtr;
344 if(winteb) {
345 thdb = (THDB *)(winteb+1);
346 orgtibsel = thdb->OrgTIBSel;
347
348 //Restore our original FS selector
349 SetFS(orgtibsel);
350 }
351}
352/******************************************************************************/
353/******************************************************************************/
354USHORT WIN32API SetWin32TIB()
355{
356 SHORT win32tibsel;
357 TEB *winteb;
358 THDB *thdb;
359
360 //If we're running an Odin32 OS/2 application (not converted!), then we
361 //we don't switch FS selectors
362 if(fIsOS2Image) {
363 return GetFS();
364 }
365
366 winteb = (TEB *)*TIBFlatPtr;
367 if(winteb) {
368 thdb = (THDB *)(winteb+1);
369 win32tibsel = thdb->teb_sel;
370
371 //Restore our win32 FS selector
372 return SetReturnFS(win32tibsel);
373 }
374 else {
375 //we didn't create this thread, so allocate a selector now
376 //NOTE: Possible memory leak (i.e. DART threads in WINMM)
377 winteb = InitializeTIB();
378 if(winteb == NULL) {
379 DebugInt3();
380 return GetFS();
381 }
382 thdb = (THDB *)(winteb+1);
383 win32tibsel = thdb->teb_sel;
384
385 //Restore our win32 FS selector
386 return SetReturnFS(win32tibsel);
387 }
388 // nested calls are OK, OS2ToWinCallback for instance
389 //else DebugInt3();
390
391 return GetFS();
392}
393//******************************************************************************
394//******************************************************************************
395VOID WIN32API ExitProcess(DWORD exitcode)
396{
397 dprintf(("KERNEL32: ExitProcess %d\n", exitcode));
398 dprintf(("KERNEL32: ExitProcess FS = %x\n", GetFS()));
399
400 SetOS2ExceptionChain(-1);
401
402 if(WinExe) {
403 delete(WinExe);
404 WinExe = NULL;
405 }
406
407 //Note: Needs to be done after deleting WinExe (destruction of exe + dll objects)
408 //Flush and delete all open memory mapped files
409 Win32MemMap::deleteAll();
410
411 //Restore original OS/2 TIB selector
412 DestroyTIB();
413 SetExceptionChain((ULONG)-1);
414
415 //avoid crashes since win32 & OS/2 exception handler aren't identical
416 //(terminate process generates two exceptions)
417 /* @@@PH 1998/02/12 Added Console Support */
418 if (iConsoleIsActive())
419 iConsoleWaitClose();
420
421 O32_ExitProcess(exitcode);
422}
423//******************************************************************************
424//******************************************************************************
425BOOL WIN32API FreeLibrary(HINSTANCE hinstance)
426{
427 Win32DllBase *winmod;
428 BOOL rc;
429
430 winmod = Win32DllBase::findModule(hinstance);
431 if(winmod) {
432 dprintf(("FreeLibrary %s", winmod->getName()));
433 //Only free it when the nrDynamicLibRef != 0
434 //This prevent problems after ExitProcess:
435 //i.e. dll A is referenced by our exe and loaded with LoadLibrary by dll B
436 // During ExitProcess it's unloaded once (before dll B), dll B calls
437 // FreeLibrary, but our exe also has a reference -> unloaded too many times
438 if(winmod->isDynamicLib()) {
439 winmod->decDynamicLib();
440 winmod->Release();
441 }
442 else {
443 dprintf(("Skipping dynamic unload as nrDynamicLibRef == 0"));
444 }
445 return(TRUE);
446 }
447 dprintf(("KERNEL32: FreeLibrary %s %X\n", OSLibGetDllName(hinstance), hinstance));
448
449 //TODO: Not thread safe
450 fFreeLibrary = TRUE; //ditch dll
451 rc = O32_FreeLibrary(hinstance);
452 fFreeLibrary = FALSE;
453 dprintf(("FreeLibrary returned %X\n", rc));
454 return(TRUE);
455}
456/******************************************************************************/
457/******************************************************************************/
458/**
459 * LoadLibraryA can be used to map a DLL module into the calling process's
460 * addressspace. It returns a handle that can be used with GetProcAddress to
461 * get addresses of exported entry points (functions and variables).
462 *
463 * LoadLibraryA can also be used to map executable (.exe) modules into the
464 * address to access resources in the module. However, LoadLibrary can't be
465 * used to run an executable (.exe) module.
466 *
467 * @returns Handle to the library which was loaded.
468 * @param lpszLibFile Pointer to zero ASCII string giving the name of the
469 * executable image (either a Dll or an Exe) which is to be
470 * loaded.
471 *
472 * If no extention is specified the default .DLL extention is
473 * appended to the name. End the filename with an '.' if the
474 * file does not have an extention (and don't want the .DLL
475 * appended).
476 *
477 * If no path is specified, this API will use the Odin32
478 * standard search strategy to find the file. This strategy
479 * is described in the method Win32ImageBase::findDLL.
480 *
481 * This API likes to have backslashes (\), but will probably
482 * accept forward slashes too. Win32 SDK docs says that it
483 * should not contain forward slashes.
484 *
485 * Win32 SDK docs adds:
486 * "The name specified is the file name of the module and
487 * is not related to the name stored in the library module
488 * itself, as specified by the LIBRARY keyword in the
489 * module-definition (.def) file."
490 *
491 * @sketch Call LoadLibraryExA with flags set to 0.
492 * @status Odin32 Completely Implemented.
493 * @author Sander van Leeuwen (sandervl@xs4all.nl)
494 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
495 * @remark Forwards to LoadLibraryExA.
496 */
497HINSTANCE WIN32API LoadLibraryA(LPCTSTR lpszLibFile)
498{
499 HINSTANCE hDll;
500
501 dprintf(("KERNEL32: LoadLibraryA(%s) --> LoadLibraryExA(lpszLibFile, 0, 0)",
502 lpszLibFile));
503 hDll = LoadLibraryExA(lpszLibFile, 0, 0);
504 dprintf(("KERNEL32: LoadLibraryA(%s) returns 0x%x",
505 lpszLibFile, hDll));
506 return hDll;
507}
508
509
510/**
511 * LoadLibraryW can be used to map a DLL module into the calling process's
512 * addressspace. It returns a handle that can be used with GetProcAddress to
513 * get addresses of exported entry points (functions and variables).
514 *
515 * LoadLibraryW can also be used to map executable (.exe) modules into the
516 * address to access resources in the module. However, LoadLibrary can't be
517 * used to run an executable (.exe) module.
518 *
519 * @returns Handle to the library which was loaded.
520 * @param lpszLibFile Pointer to Unicode string giving the name of
521 * the executable image (either a Dll or an Exe) which is to
522 * be loaded.
523 *
524 * If no extention is specified the default .DLL extention is
525 * appended to the name. End the filename with an '.' if the
526 * file does not have an extention (and don't want the .DLL
527 * appended).
528 *
529 * If no path is specified, this API will use the Odin32
530 * standard search strategy to find the file. This strategy
531 * is described in the method Win32ImageBase::findDLL.
532 *
533 * This API likes to have backslashes (\), but will probably
534 * accept forward slashes too. Win32 SDK docs says that it
535 * should not contain forward slashes.
536 *
537 * Win32 SDK docs adds:
538 * "The name specified is the file name of the module and
539 * is not related to the name stored in the library module
540 * itself, as specified by the LIBRARY keyword in the
541 * module-definition (.def) file."
542 *
543 * @sketch Convert Unicode name to ascii.
544 * Call LoadLibraryExA with flags set to 0.
545 * free ascii string.
546 * @status Odin32 Completely Implemented.
547 * @author Sander van Leeuwen (sandervl@xs4all.nl)
548 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
549 * @remark Forwards to LoadLibraryExA.
550 */
551HINSTANCE WIN32API LoadLibraryW(LPCWSTR lpszLibFile)
552{
553 char * pszAsciiLibFile;
554 HINSTANCE hDll;
555
556 pszAsciiLibFile = UnicodeToAsciiString(lpszLibFile);
557 dprintf(("KERNEL32: LoadLibraryW(%s) --> LoadLibraryExA(lpszLibFile, 0, 0)",
558 pszAsciiLibFile));
559 hDll = LoadLibraryExA(pszAsciiLibFile, NULL, 0);
560 dprintf(("KERNEL32: LoadLibraryW(%s) returns 0x%x",
561 pszAsciiLibFile, hDll));
562 free(pszAsciiLibFile);
563
564 return hDll;
565}
566
567
568/**
569 * LoadLibraryExA can be used to map a DLL module into the calling process's
570 * addressspace. It returns a handle that can be used with GetProcAddress to
571 * get addresses of exported entry points (functions and variables).
572 *
573 * LoadLibraryExA can also be used to map executable (.exe) modules into the
574 * address to access resources in the module. However, LoadLibrary can't be
575 * used to run an executable (.exe) module.
576 *
577 * @returns Handle to the library which was loaded.
578 * @param lpszLibFile Pointer to Unicode string giving the name of
579 * the executable image (either a Dll or an Exe) which is to
580 * be loaded.
581 *
582 * If no extention is specified the default .DLL extention is
583 * appended to the name. End the filename with an '.' if the
584 * file does not have an extention (and don't want the .DLL
585 * appended).
586 *
587 * If no path is specified, this API will use the Odin32
588 * standard search strategy to find the file. This strategy
589 * is described in the method Win32ImageBase::findDLL.
590 * This may be alterned by the LOAD_WITH_ALTERED_SEARCH_PATH
591 * flag, see below.
592 *
593 * This API likes to have backslashes (\), but will probably
594 * accept forward slashes too. Win32 SDK docs says that it
595 * should not contain forward slashes.
596 *
597 * Win32 SDK docs adds:
598 * "The name specified is the file name of the module and
599 * is not related to the name stored in the library module
600 * itself, as specified by the LIBRARY keyword in the
601 * module-definition (.def) file."
602 *
603 * @param hFile Reserved. Must be 0.
604 *
605 * @param dwFlags Flags which specifies the taken when loading the module.
606 * The value 0 makes it identical to LoadLibraryA/W.
607 *
608 * Flags:
609 *
610 * DONT_RESOLVE_DLL_REFERENCES
611 * (WinNT/2K feature): Don't load imported modules and
612 * hence don't resolve imported symbols.
613 * DllMain isn't called either. (Which is obvious since
614 * it may use one of the importe symbols.)
615 *
616 * On the other hand, if this flag is NOT set, the system
617 * load imported modules, resolves imported symbols, calls
618 * DllMain for process and thread init and term (if wished
619 * by the module).
620 *
621 * partially implemented yet - imports are resolved it seems.
622 *
623 * LOAD_LIBRARY_AS_DATAFILE
624 * If this flag is set, the module is mapped into the
625 * address space but is not prepared for execution. Though
626 * it's preparted for resource API. Hence, you'll use this
627 * flag when you want to load a DLL for extracting
628 * messages or resources from it.
629 *
630 * The resulting handle can be used with any Odin32 API
631 * which operates on resources.
632 * (WinNt/2k supports all resource APIs while Win9x don't
633 * support the specialized resource APIs: LoadBitmap,
634 * LoadCursor, LoadIcon, LoadImage, LoadMenu.)
635 *
636 * not implemented yet.
637 *
638 * LOAD_WITH_ALTERED_SEARCH_PATH
639 * If this flag is set and lpszLibFile specifies a path
640 * we'll use an alternative file search strategy to find
641 * imported modules. This stratgy is simply to use the
642 * path of the module being loaded instead of the path
643 * of the executable module as the first location
644 * to search for imported modules.
645 *
646 * If this flag is clear, the standard Odin32 standard
647 * search strategy. See Win32ImageBase::findDll for
648 * further information.
649 *
650 * not implemented yet.
651 *
652 * @status Open32 Partially Implemented.
653 * @author Sander van Leeuwen (sandervl@xs4all.nl)
654 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
655 * @remark Forwards to LoadLibraryExA.
656 */
657HINSTANCE WIN32API LoadLibraryExA(LPCTSTR lpszLibFile, HANDLE hFile, DWORD dwFlags)
658{
659 HINSTANCE hDll;
660 Win32DllBase * pModule;
661 char szModname[CCHMAXPATH];
662 BOOL fPath; /* Flags which is set if the */
663 /* lpszLibFile contains a path. */
664 ULONG fPE; /* isPEImage return value. */
665
666 /** @sketch
667 * Some parameter validations is probably useful.
668 */
669 if (!VALID_PSZ(lpszLibFile))
670 {
671 dprintf(("KERNEL32: LoadLibraryExA(0x%x, 0x%x, 0x%x): invalid pointer lpszLibFile = 0x%x\n",
672 lpszLibFile, hFile, dwFlags, lpszLibFile));
673 SetLastError(ERROR_INVALID_PARAMETER); //or maybe ERROR_ACCESS_DENIED is more appropriate?
674 return NULL;
675 }
676 if (!VALID_PSZMAXSIZE(lpszLibFile, CCHMAXPATH))
677 {
678 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): lpszLibFile string too long, %d\n",
679 lpszLibFile, hFile, dwFlags, strlen(lpszLibFile)));
680 SetLastError(ERROR_INVALID_PARAMETER);
681 return NULL;
682 }
683 if ((dwFlags & ~(DONT_RESOLVE_DLL_REFERENCES | LOAD_WITH_ALTERED_SEARCH_PATH | LOAD_LIBRARY_AS_DATAFILE)) != 0)
684 {
685 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): dwFlags have invalid or unsupported flags\n",
686 lpszLibFile, hFile, dwFlags));
687 SetLastError(ERROR_INVALID_PARAMETER);
688 return NULL;
689 }
690
691
692 /** @sketch
693 * First we'll see if the module is allready loaded.
694 * IF allready loaded THEN
695 * IF it's a LX dll which isn't loaded and we're using the PeLoader THEN
696 * Set Load library.
697 * Endif
698 * Inc dynamic reference count.
699 * Inc reference count.
700 * RETURN instance handle.
701 * Endif
702 */
703 pModule = Win32DllBase::findModule((LPSTR)lpszLibFile);
704 if (pModule)
705 {
706 if (pModule->isLxDll() && !pModule->isLoaded() && fPeLoader)
707 {
708 //can happen with i.e. wininet
709 //wininet depends on wsock32; when the app loads wsock32 afterwards
710 //with LoadLibrary or as a child of another dll, we need to make
711 //sure it's loaded once with DosLoadModule
712 pModule->setLoadLibrary();
713 }
714 pModule->incDynamicLib();
715 pModule->AddRef();
716 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): returns 0x%x. Dll found %s",
717 lpszLibFile, hFile, dwFlags, pModule->getInstanceHandle(), pModule->getFullPath()));
718 return pModule->getInstanceHandle();
719 }
720
721
722 /** @sketch
723 * Test if lpszLibFile has a path or not.
724 * Copy the lpszLibFile to szModname, rename the dll and uppercase the name.
725 * IF it hasn't a path THEN
726 * Issue a findDll to find the dll/executable to be loaded.
727 * IF the Dll isn't found THEN
728 * Set last error and RETURN.
729 * Endif.
730 * Endif
731 */
732 fPath = strchr(lpszLibFile, '\\') || strchr(lpszLibFile, '/');
733 strcpy(szModname, lpszLibFile);
734 Win32DllBase::renameDll(szModname);
735 strupr(szModname);
736
737 if (!fPath)
738 {
739 char szModName2[CCHMAXPATH];
740 strcpy(szModName2, szModname);
741 if (!Win32ImageBase::findDll(szModName2, szModname, sizeof(szModname)))
742 {
743 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): module wasn't found. returns NULL",
744 lpszLibFile, hFile, dwFlags));
745 SetLastError(ERROR_FILE_NOT_FOUND);
746 return NULL;
747 }
748 }
749
750
751 /** @sketch
752 * IF dwFlags == 0 THEN
753 * Try load the executable using LoadLibrary
754 * IF successfully loaded THEN
755 * IF LX dll and is using the PE Loader THEN
756 * Set Load library.
757 * Inc reference count.
758 * Endif
759 * Inc dynamic reference count.
760 * RETURN successfully.
761 * Endif
762 * Endif
763 */
764 if (dwFlags == 0)
765 {
766 hDll = O32_LoadLibrary(szModname);
767 if (hDll)
768 {
769 /* OS/2 dll, system dll, converted dll or win32k took care of it.*/
770 pModule = Win32DllBase::findModule(hDll);
771 if (pModule)
772 {
773 if (pModule->isLxDll() && fPeLoader)
774 {
775 pModule->setLoadLibrary();
776 pModule->AddRef();
777 }
778 pModule->incDynamicLib();
779 }
780 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): returns 0x%x. Loaded %s using O32_LoadLibrary.",
781 lpszLibFile, hFile, dwFlags, hDll, szModname));
782 return hDll;
783 }
784 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): O32_LoadLibrary(%s) failed. LastError=%d",
785 lpszLibFile, hFile, dwFlags, szModname, GetLastError()));
786 }
787 else
788 hDll = NULL;
789
790
791 /** @sketch
792 * If PE image THEN
793 * IF LOAD_LIBRARY_AS_DATAFILE or Executable THEN
794 *
795 *
796 * Try load the file using the Win32PeLdrDll class.
797 * <sketch continued further down>
798 * Else
799 * Set last error.
800 * (hDll is NULL)
801 * Endif
802 * return hDll.
803 */
804 fPE = Win32ImageBase::isPEImage(szModname);
805 if(fPE == ERROR_SUCCESS)
806 {
807 Win32PeLdrDll * peldrDll;
808 /* TODO!
809 * We might use the fake loader class to do the LOAD_LIBRARY_AS_DATAFILE and
810 * executable image loading. These are both loaded for accessing resource.
811 * But this requires that they behaves like Dlls...
812 if (dwFlags & LOAD_LIBRARY_AS_DATAFILE || fPE == 2)
813 {
814 peldrDll = new Win32PeLdrRsrcImg(szModname);
815 }
816 else
817 */
818
819 peldrDll = new Win32PeLdrDll(szModname);
820 if (peldrDll == NULL)
821 {
822 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Failed to created instance of Win32PeLdrDll. returns NULL.",
823 lpszLibFile, hFile, dwFlags));
824 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
825 return NULL;
826 }
827
828 /** @sketch
829 * Process dwFlags
830 */
831 if (dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE))
832 {
833 peldrDll->setNoEntryCalls();
834 //peldrDll->setDontProcessImports(); not implemented?
835 }
836 if (dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH)
837 {
838 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Warning dwFlags LOAD_WITH_ALTERED_SEARCH_PATH is not implemented.",
839 lpszLibFile, hFile, dwFlags));
840 //peldrDll->setLoadWithAlteredSearchPath();
841 }
842 if (dwFlags & LOAD_LIBRARY_AS_DATAFILE)
843 {
844 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Warning dwFlags LOAD_LIBRARY_AS_DATAFILE is not implemented.",
845 lpszLibFile, hFile, dwFlags));
846 //peldrDll->setLoadAsDatafile();
847 }
848
849 /** @sketch
850 * Initiate the peldr DLL.
851 * IF successful init THEN
852 * Inc dynamic ref count.
853 * Inc ref count.
854 * Attach to process
855 * IF successful THEN
856 * hDLL <- instance handle.
857 * ELSE
858 * set last error
859 * delete Win32PeLdrDll instance.
860 * Endif
861 * ELSE
862 * set last error
863 * delete Win32PeLdrDll instance.
864 * Endif.
865 */
866 if (peldrDll->init(0))
867 {
868 peldrDll->incDynamicLib();
869 peldrDll->AddRef();
870 if (peldrDll->attachProcess())
871 hDll = peldrDll->getInstanceHandle();
872 else
873 {
874 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): attachProcess call to Win32PeLdrDll instance failed. returns NULL.",
875 lpszLibFile, hFile, dwFlags));
876 SetLastError(ERROR_DLL_INIT_FAILED);
877 delete peldrDll;
878 }
879 }
880 else
881 {
882 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Failed to init Win32PeLdrDll instance. error=%d returns NULL.",
883 lpszLibFile, hFile, dwFlags, peldrDll->getError()));
884 SetLastError(ERROR_INVALID_EXE_SIGNATURE);
885 delete peldrDll;
886 }
887 }
888 else
889 {
890 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x) library wasn't found (%s) or isn't loadable; err %x",
891 lpszLibFile, hFile, dwFlags, szModname, fPE));
892 SetLastError(fPE);
893 }
894
895 return hDll;
896}
897
898
899/**
900 * LoadLibraryExW can be used to map a DLL module into the calling process's
901 * addressspace. It returns a handle that can be used with GetProcAddress to
902 * get addresses of exported entry points (functions and variables).
903 *
904 * LoadLibraryExW can also be used to map executable (.exe) modules into the
905 * address to access resources in the module. However, LoadLibrary can't be
906 * used to run an executable (.exe) module.
907 *
908 * @returns Handle to the library which was loaded.
909 * @param lpszLibFile Pointer to Unicode string giving the name of
910 * the executable image (either a Dll or an Exe) which is to
911 * be loaded.
912 *
913 * If no extention is specified the default .DLL extention is
914 * appended to the name. End the filename with an '.' if the
915 * file does not have an extention (and don't want the .DLL
916 * appended).
917 *
918 * If no path is specified, this API will use the Odin32
919 * standard search strategy to find the file. This strategy
920 * is described in the method Win32ImageBase::findDLL.
921 * This may be alterned by the LOAD_WITH_ALTERED_SEARCH_PATH
922 * flag, see below.
923 *
924 * This API likes to have backslashes (\), but will probably
925 * accept forward slashes too. Win32 SDK docs says that it
926 * should not contain forward slashes.
927 *
928 * Win32 SDK docs adds:
929 * "The name specified is the file name of the module and
930 * is not related to the name stored in the library module
931 * itself, as specified by the LIBRARY keyword in the
932 * module-definition (.def) file."
933 *
934 * @param hFile Reserved. Must be 0.
935 *
936 * @param dwFlags Flags which specifies the taken when loading the module.
937 * The value 0 makes it identical to LoadLibraryA/W.
938 *
939 * Flags:
940 *
941 * DONT_RESOLVE_DLL_REFERENCES
942 * (WinNT/2K feature): Don't load imported modules and
943 * hence don't resolve imported symbols.
944 * DllMain isn't called either. (Which is obvious since
945 * it may use one of the importe symbols.)
946 *
947 * On the other hand, if this flag is NOT set, the system
948 * load imported modules, resolves imported symbols, calls
949 * DllMain for process and thread init and term (if wished
950 * by the module).
951 *
952 * LOAD_LIBRARY_AS_DATAFILE
953 * If this flag is set, the module is mapped into the
954 * address space but is not prepared for execution. Though
955 * it's preparted for resource API. Hence, you'll use this
956 * flag when you want to load a DLL for extracting
957 * messages or resources from it.
958 *
959 * The resulting handle can be used with any Odin32 API
960 * which operates on resources.
961 * (WinNt/2k supports all resource APIs while Win9x don't
962 * support the specialized resource APIs: LoadBitmap,
963 * LoadCursor, LoadIcon, LoadImage, LoadMenu.)
964 *
965 * LOAD_WITH_ALTERED_SEARCH_PATH
966 * If this flag is set and lpszLibFile specifies a path
967 * we'll use an alternative file search strategy to find
968 * imported modules. This stratgy is simply to use the
969 * path of the module being loaded instead of the path
970 * of the executable module as the first location
971 * to search for imported modules.
972 *
973 * If this flag is clear, the standard Odin32 standard
974 * search strategy. See Win32ImageBase::findDll for
975 * further information.
976 *
977 * @sketch Convert Unicode name to ascii.
978 * Call LoadLibraryExA.
979 * Free ascii string.
980 * return handle from LoadLibraryExA.
981 * @status Open32 Partially Implemented.
982 * @author Sander van Leeuwen (sandervl@xs4all.nl)
983 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
984 * @remark Forwards to LoadLibraryExA.
985 */
986HINSTANCE WIN32API LoadLibraryExW(LPCWSTR lpszLibFile, HANDLE hFile, DWORD dwFlags)
987{
988 char * pszAsciiLibFile;
989 HINSTANCE hDll;
990
991 pszAsciiLibFile = UnicodeToAsciiString(lpszLibFile);
992 dprintf(("KERNEL32: LoadLibraryExW(%s, 0x%x, 0x%x) --> LoadLibraryExA",
993 pszAsciiLibFile, hFile, dwFlags));
994 hDll = LoadLibraryExA(pszAsciiLibFile, hFile, dwFlags);
995 dprintf(("KERNEL32: LoadLibraryExW(%s, 0x%x, 0x%x) returns 0x%x",
996 pszAsciiLibFile, hFile, dwFlags, hDll));
997 free(pszAsciiLibFile);
998
999 return hDll;
1000}
1001//******************************************************************************
1002//******************************************************************************
1003HINSTANCE16 WIN32API LoadLibrary16(LPCTSTR lpszLibFile)
1004{
1005 dprintf(("ERROR: LoadLibrary16 %s, not implemented", lpszLibFile));
1006 return 0;
1007}
1008//******************************************************************************
1009//******************************************************************************
1010VOID WIN32API FreeLibrary16(HINSTANCE16 hinstance)
1011{
1012 dprintf(("ERROR: FreeLibrary16 %x, not implemented", hinstance));
1013}
1014//******************************************************************************
1015//******************************************************************************
1016FARPROC WIN32API GetProcAddress16(HMODULE hModule, LPCSTR lpszProc)
1017{
1018 dprintf(("ERROR: GetProcAddress16 %x %x, not implemented", hModule, lpszProc));
1019 return 0;
1020}
1021//******************************************************************************
1022//******************************************************************************
1023LPCSTR WIN32API GetCommandLineA()
1024{
1025 LPTSTR cmdline = NULL;
1026
1027 if(WinExe) {
1028 cmdline = WinExe->getCommandLineA();
1029 }
1030 if(cmdline == NULL) //not used for converted exes
1031 cmdline = O32_GetCommandLine();
1032
1033 dprintf(("KERNEL32: GetCommandLine %s\n", cmdline));
1034 dprintf(("KERNEL32: FS = %x\n", GetFS()));
1035 return(cmdline);
1036}
1037//******************************************************************************
1038//******************************************************************************
1039LPCWSTR WIN32API GetCommandLineW(void)
1040{
1041 static WCHAR *UnicodeCmdLine = NULL;
1042 char *asciicmdline = NULL;
1043
1044 dprintf(("KERNEL32: FS = %x\n", GetFS()));
1045
1046 if(UnicodeCmdLine)
1047 return(UnicodeCmdLine); //already called before
1048
1049 if(WinExe) {
1050 if(WinExe->getCommandLineW())
1051 return WinExe->getCommandLineW();
1052 }
1053 if(asciicmdline == NULL) //not used for converted exes
1054 asciicmdline = O32_GetCommandLine();
1055
1056 if(asciicmdline) {
1057 UnicodeCmdLine = (WCHAR *)malloc(strlen(asciicmdline)*2 + 2);
1058 AsciiToUnicode(asciicmdline, UnicodeCmdLine);
1059 dprintf(("KERNEL32: OS2GetCommandLineW: %s\n", asciicmdline));
1060 return(UnicodeCmdLine);
1061 }
1062 dprintf(("KERNEL32: OS2GetCommandLineW: asciicmdline == NULL\n"));
1063 return NULL;
1064}
1065//******************************************************************************
1066//******************************************************************************
1067DWORD WIN32API GetModuleFileNameA(HMODULE hinstModule, LPTSTR lpszPath, DWORD cchPath)
1068{
1069 DWORD rc;
1070 Win32ImageBase *module;
1071 char *fpath = NULL;
1072
1073 dprintf(("GetModuleFileName %X", hinstModule));
1074 if(hinstModule == 0 || hinstModule == -1 || (WinExe && hinstModule == WinExe->getInstanceHandle())) {
1075 module = (Win32ImageBase *)WinExe;
1076 }
1077 else {
1078 module = (Win32ImageBase *)Win32DllBase::findModule(hinstModule);
1079 }
1080
1081 if(module) {
1082 fpath = module->getFullPath();
1083 }
1084 if(fpath) {
1085 //SvL: 13-9-98: +1
1086 rc = min(strlen(fpath)+1, cchPath);
1087 strncpy(lpszPath, fpath, rc);
1088 lpszPath[rc-1] = 0;
1089 }
1090 else rc = O32_GetModuleFileName(hinstModule, lpszPath, cchPath);
1091
1092 if(rc) {
1093 dprintf(("KERNEL32: GetModuleFileName %s %d\n", lpszPath, hinstModule));
1094 }
1095 return(rc);
1096}
1097//******************************************************************************
1098//******************************************************************************
1099DWORD WIN32API GetModuleFileNameW(HMODULE hModule, LPWSTR lpFileName, DWORD nSize)
1100{
1101 char *asciifilename = (char *)malloc(nSize+1);
1102 DWORD rc;
1103
1104 dprintf(("KERNEL32: OSLibGetModuleFileNameW\n"));
1105 rc = GetModuleFileNameA(hModule, asciifilename, nSize);
1106 if(rc) AsciiToUnicode(asciifilename, lpFileName);
1107 free(asciifilename);
1108 return(rc);
1109}
1110//******************************************************************************
1111//NOTE: GetModuleHandleA does NOT support files with multiple dots (i.e.
1112// very.weird.exe)
1113//******************************************************************************
1114HANDLE WIN32API GetModuleHandleA(LPCTSTR lpszModule)
1115{
1116 HANDLE hMod;
1117 Win32DllBase *windll;
1118 char szModule[CCHMAXPATH];
1119 BOOL fDllModule = FALSE;
1120
1121 if(lpszModule == NULL) {
1122 if(WinExe)
1123 hMod = WinExe->getInstanceHandle();
1124 else hMod = -1;
1125 }
1126 else {
1127 strcpy(szModule, OSLibStripPath((char *)lpszModule));
1128 strupr(szModule);
1129 if(strstr(szModule, ".DLL")) {
1130 fDllModule = TRUE;
1131 }
1132 else {
1133 if(!strstr(szModule, ".")) {
1134 //if there's no extension or trainling dot, we
1135 //assume it's a dll (see Win32 SDK docs)
1136 fDllModule = TRUE;
1137 }
1138 }
1139 char *dot = strstr(szModule, ".");
1140 if(dot)
1141 *dot = 0;
1142
1143 if(!fDllModule && WinExe && !strcmpi(szModule, WinExe->getModuleName())) {
1144 hMod = WinExe->getInstanceHandle();
1145 }
1146 else {
1147 windll = Win32DllBase::findModule(szModule);
1148 if(windll) {
1149 hMod = windll->getInstanceHandle();
1150 }
1151 else hMod = OSLibiGetModuleHandleA((char *)lpszModule);
1152 }
1153 }
1154
1155 dprintf(("KERNEL32: GetModuleHandle %s returned %X\n", lpszModule, hMod));
1156 return(hMod);
1157}
1158//******************************************************************************
1159//******************************************************************************
1160HMODULE WIN32API GetModuleHandleW(LPCWSTR arg1)
1161{
1162 HMODULE rc;
1163 char *astring;
1164
1165 astring = UnicodeToAsciiString((LPWSTR)arg1);
1166 rc = GetModuleHandleA(astring);
1167 dprintf(("KERNEL32: OS2GetModuleHandleW %s returned %X\n", astring, rc));
1168 FreeAsciiString(astring);
1169 return(rc);
1170}
1171//******************************************************************************
1172//******************************************************************************
1173BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
1174 LPSECURITY_ATTRIBUTES lpProcessAttributes,
1175 LPSECURITY_ATTRIBUTES lpThreadAttributes,
1176 BOOL bInheritHandles, DWORD dwCreationFlags,
1177 LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
1178 LPSTARTUPINFOA lpStartupInfo,
1179 LPPROCESS_INFORMATION lpProcessInfo )
1180{
1181 THDB *pThreadDB = (THDB*)GetThreadTHDB();
1182 char *cmdline = NULL;
1183 BOOL rc;
1184
1185 dprintf(("KERNEL32: CreateProcessA %s cline:%s inherit:%d cFlags:%x Env:%x CurDir:%s StartupFlags:%x\n",
1186 lpApplicationName, lpCommandLine, bInheritHandles, dwCreationFlags,
1187 lpEnvironment, lpCurrentDirectory, lpStartupInfo));
1188
1189 // open32 does not support DEBUG_ONLY_THIS_PROCESS
1190 if(dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
1191 dwCreationFlags |= DEBUG_PROCESS;
1192
1193 if(O32_CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes,
1194 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1195 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1196 lpProcessInfo) == TRUE)
1197 {
1198 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
1199 {
1200 if(pThreadDB->pidDebuggee != 0)
1201 {
1202 // TODO: handle this
1203 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
1204 }
1205 else
1206 {
1207 pThreadDB->pidDebuggee = lpProcessInfo->dwProcessId;
1208 OSLibStartDebugger((ULONG*)&pThreadDB->pidDebuggee);
1209 }
1210 }
1211 else pThreadDB->pidDebuggee = 0;
1212
1213 return(TRUE);
1214 }
1215 //probably a win32 exe, so run it in the pe loader
1216 if(lpApplicationName) {
1217 if(lpCommandLine) {
1218 //skip exe name in lpCommandLine
1219 while(*lpCommandLine != 0 && *lpCommandLine != ' ')
1220 lpCommandLine++;
1221
1222 if(*lpCommandLine != 0) {
1223 lpCommandLine++;
1224 }
1225 cmdline = (char *)malloc(strlen(lpApplicationName)+strlen(lpCommandLine) + 16);
1226 sprintf(cmdline, "PE.EXE %s %s", lpApplicationName, lpCommandLine);
1227 }
1228 else {
1229 cmdline = (char *)malloc(strlen(lpApplicationName) + 16);
1230 sprintf(cmdline, "PE.EXE %s", lpApplicationName);
1231 }
1232 }
1233 else {
1234 cmdline = (char *)malloc(strlen(lpCommandLine) + 16);
1235 sprintf(cmdline, "PE.EXE %s", lpCommandLine);
1236 }
1237 dprintf(("KERNEL32: CreateProcess %s\n", cmdline));
1238 rc = O32_CreateProcess("PE.EXE", (LPCSTR)cmdline,lpProcessAttributes,
1239 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1240 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1241 lpProcessInfo);
1242 if(rc == TRUE) {
1243 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
1244 {
1245 if(pThreadDB->pidDebuggee != 0)
1246 {
1247 // TODO: handle this
1248 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
1249 }
1250 else
1251 {
1252 pThreadDB->pidDebuggee = lpProcessInfo->dwProcessId;
1253 OSLibStartDebugger((ULONG*)&pThreadDB->pidDebuggee);
1254 }
1255 }
1256 else
1257 pThreadDB->pidDebuggee = 0;
1258 }
1259 if(cmdline)
1260 free(cmdline);
1261
1262 if(lpProcessInfo)
1263 dprintf(("KERNEL32: CreateProcess returned %d hPro:%x hThr:%x pid:%x tid:%x\n",
1264 rc, lpProcessInfo->hProcess, lpProcessInfo->hThread,
1265 lpProcessInfo->dwProcessId,lpProcessInfo->dwThreadId));
1266 else
1267 dprintf(("KERNEL32: CreateProcess returned %d\n", rc));
1268 return(rc);
1269}
1270//******************************************************************************
1271//******************************************************************************
1272BOOL WIN32API CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
1273 PSECURITY_ATTRIBUTES lpProcessAttributes,
1274 PSECURITY_ATTRIBUTES lpThreadAttributes,
1275 BOOL bInheritHandles, DWORD dwCreationFlags,
1276 LPVOID lpEnvironment,
1277 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
1278 LPPROCESS_INFORMATION lpProcessInfo)
1279{
1280 BOOL rc;
1281 char *astring1 = 0, *astring2 = 0, *astring3 = 0;
1282
1283 dprintf(("KERNEL32: CreateProcessW"));
1284 if(lpApplicationName)
1285 astring1 = UnicodeToAsciiString((LPWSTR)lpApplicationName);
1286 if(lpCommandLine)
1287 astring2 = UnicodeToAsciiString(lpCommandLine);
1288 if(lpCurrentDirectory)
1289 astring3 = UnicodeToAsciiString((LPWSTR)lpCurrentDirectory);
1290 rc = CreateProcessA(astring1, astring2, lpProcessAttributes, lpThreadAttributes,
1291 bInheritHandles, dwCreationFlags, lpEnvironment,
1292 astring3, (LPSTARTUPINFOA)lpStartupInfo,
1293 lpProcessInfo);
1294 if(astring3) FreeAsciiString(astring3);
1295 if(astring2) FreeAsciiString(astring2);
1296 if(astring1) FreeAsciiString(astring1);
1297 return(rc);
1298}
1299//******************************************************************************
1300//******************************************************************************
1301HINSTANCE WIN32API WinExec(LPCSTR lpCmdLine, UINT nCmdShow)
1302{
1303 STARTUPINFOA startinfo = {0};
1304 PROCESS_INFORMATION procinfo;
1305 DWORD rc;
1306
1307 dprintf(("KERNEL32: WinExec %s\n", lpCmdLine));
1308 startinfo.dwFlags = nCmdShow;
1309 if(CreateProcessA(NULL, (LPSTR)lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL,
1310 &startinfo, &procinfo) == FALSE)
1311 {
1312 return 0;
1313 }
1314 //block until the launched app waits for input (or a timeout of 15 seconds)
1315 //TODO: Shouldn't call Open32, but the api in user32..
1316 rc = O32_WaitForInputIdle(procinfo.hProcess, 15000);
1317 if(rc != 0) {
1318 dprintf(("WinExec: WaitForInputIdle %x returned %x", procinfo.hProcess, rc));
1319 }
1320 return procinfo.hProcess; //correct?
1321}
1322//******************************************************************************
1323//******************************************************************************
1324FARPROC WIN32API GetProcAddress(HMODULE hModule, LPCSTR lpszProc)
1325{
1326 Win32ImageBase *winmod;
1327 FARPROC proc;
1328 ULONG ulAPIOrdinal;
1329
1330 if(hModule == 0 || hModule == -1 || (WinExe && hModule == WinExe->getInstanceHandle())) {
1331 winmod = WinExe;
1332 }
1333 else winmod = (Win32ImageBase *)Win32DllBase::findModule((HINSTANCE)hModule);
1334
1335 if(winmod) {
1336 ulAPIOrdinal = (ULONG)lpszProc;
1337 if (ulAPIOrdinal <= 0x0000FFFF) {
1338 proc = (FARPROC)winmod->getApi((int)ulAPIOrdinal);
1339 }
1340 else proc = (FARPROC)winmod->getApi((char *)lpszProc);
1341 if(proc == 0) {
1342#ifdef DEBUG
1343 if(ulAPIOrdinal <= 0x0000FFFF) {
1344 dprintf(("GetProcAddress %x %x not found!", hModule, ulAPIOrdinal));
1345 }
1346 else dprintf(("GetProcAddress %x %s not found!", hModule, lpszProc));
1347#endif
1348 SetLastError(ERROR_PROC_NOT_FOUND);
1349 }
1350 return proc;
1351 }
1352 proc = O32_GetProcAddress(hModule, lpszProc);
1353 if(HIWORD(lpszProc))
1354 dprintf(("KERNEL32: GetProcAddress %s from %X returned %X\n", lpszProc, hModule, proc));
1355 else dprintf(("KERNEL32: GetProcAddress %x from %X returned %X\n", lpszProc, hModule, proc));
1356 return(proc);
1357}
1358//******************************************************************************
1359//Retrieve the version
1360//******************************************************************************
1361BOOL SYSTEM GetVersionStruct(char *lpszModName, char *verstruct, ULONG bufLength)
1362{
1363 Win32ImageBase *winimage;
1364 Win32PeLdrRsrcImg *rsrcimg;
1365
1366 dprintf(("GetVersionStruct of module %s", lpszModName));
1367 if(WinExe && !stricmp(WinExe->getFullPath(), lpszModName)) {
1368 winimage = (Win32ImageBase *)WinExe;
1369 }
1370 else {
1371 winimage = (Win32ImageBase *)Win32DllBase::findModule(lpszModName);
1372 if(winimage == NULL)
1373 {
1374 char modname[CCHMAXPATH];
1375
1376 strcpy(modname, lpszModName);
1377 //rename dll if necessary (i.e. OLE32 -> OLE32OS2)
1378 Win32DllBase::renameDll(modname);
1379
1380 if(Win32ImageBase::isPEImage(modname) != ERROR_SUCCESS)
1381 {
1382 HINSTANCE hInstance;
1383
1384 //must be an LX dll, just load it (app will probably load it anyway)
1385 hInstance = LoadLibraryA(modname);
1386 if(hInstance == 0)
1387 return 0;
1388 winimage = (Win32ImageBase *)Win32DllBase::findModule(hInstance);
1389 if(winimage) {
1390 return winimage->getVersionStruct(verstruct, bufLength);
1391 }
1392 return 0;
1393 }
1394 //SvL: Try to load it
1395 rsrcimg = new Win32PeLdrRsrcImg(modname);
1396 if(rsrcimg == NULL)
1397 return 0;
1398
1399 rsrcimg->init(0);
1400 if(rsrcimg->getError() != NO_ERROR)
1401 {
1402 dprintf(("GetVersionStruct can't load %s\n", modname));
1403 delete rsrcimg;
1404 return(FALSE);
1405 }
1406 BOOL rc = rsrcimg->getVersionStruct(verstruct, bufLength);
1407 delete rsrcimg;
1408 return rc;
1409 }
1410 }
1411 return winimage->getVersionStruct(verstruct, bufLength);
1412}
1413//******************************************************************************
1414//******************************************************************************
1415ULONG SYSTEM GetVersionSize(char *lpszModName)
1416{
1417 Win32ImageBase *winimage;
1418 Win32PeLdrRsrcImg *rsrcimg;
1419
1420 dprintf(("GetVersionSize of %s\n", lpszModName));
1421
1422 if(WinExe && !stricmp(WinExe->getFullPath(), lpszModName)) {
1423 winimage = (Win32ImageBase *)WinExe;
1424 }
1425 else {
1426 winimage = (Win32ImageBase *)Win32DllBase::findModule(lpszModName);
1427 if(winimage == NULL)
1428 {
1429 char modname[CCHMAXPATH];
1430
1431 strcpy(modname, lpszModName);
1432 //rename dll if necessary (i.e. OLE32 -> OLE32OS2)
1433 Win32DllBase::renameDll(modname);
1434
1435 if(Win32ImageBase::isPEImage(modname) != ERROR_SUCCESS)
1436 {
1437 HINSTANCE hInstance;
1438
1439 //must be an LX dll, just load it (app will probably load it anyway)
1440 hInstance = LoadLibraryA(modname);
1441 if(hInstance == 0)
1442 return 0;
1443 winimage = (Win32ImageBase *)Win32DllBase::findModule(hInstance);
1444 if(winimage) {
1445 return winimage->getVersionSize();
1446 }
1447 return 0;
1448 }
1449
1450 //SvL: Try to load it
1451 rsrcimg = new Win32PeLdrRsrcImg(modname);
1452 if(rsrcimg == NULL)
1453 return 0;
1454
1455 rsrcimg->init(0);
1456 if(rsrcimg->getError() != NO_ERROR)
1457 {
1458 dprintf(("GetVersionSize can't load %s\n", modname));
1459 delete rsrcimg;
1460 return(FALSE);
1461 }
1462 int size = rsrcimg->getVersionSize();
1463 delete rsrcimg;
1464 return size;
1465 }
1466 }
1467 return winimage->getVersionSize();
1468}
1469//******************************************************************************
1470//TODO:What does this do exactly??
1471//******************************************************************************
1472ODINFUNCTION1(BOOL,DisableThreadLibraryCalls,HMODULE,hModule)
1473{
1474 Win32DllBase *winmod;
1475 FARPROC proc;
1476 ULONG ulAPIOrdinal;
1477
1478 winmod = Win32DllBase::findModule((HINSTANCE)hModule);
1479 if(winmod)
1480 {
1481 // don't call ATTACH/DETACH thread functions in DLL
1482 winmod->setThreadLibraryCalls(FALSE);
1483 return TRUE;
1484 }
1485 else
1486 {
1487 // raise error condition
1488 SetLastError(ERROR_INVALID_HANDLE);
1489 return FALSE;
1490 }
1491}
1492//******************************************************************************
1493//******************************************************************************
Note: See TracBrowser for help on using the repository browser.