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

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

Updates for fake system dll headers

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