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

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

TLS changes

File size: 55.1 KB
Line 
1/* $Id: wprocess.cpp,v 1.85 2000-08-09 18:59:03 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 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(("KERNEL32: FreeLibrary %s %X\n", OSLibGetDllName(hinstance), hinstance));
451
452 //TODO: Not thread safe
453 fFreeLibrary = TRUE; //ditch dll
454 rc = O32_FreeLibrary(hinstance);
455 fFreeLibrary = FALSE;
456 dprintf(("FreeLibrary returned %X\n", rc));
457 return(TRUE);
458}
459/******************************************************************************/
460/******************************************************************************/
461/**
462 * LoadLibraryA can be used to map a DLL module into the calling process's
463 * addressspace. It returns a handle that can be used with GetProcAddress to
464 * get addresses of exported entry points (functions and variables).
465 *
466 * LoadLibraryA can also be used to map executable (.exe) modules into the
467 * address to access resources in the module. However, LoadLibrary can't be
468 * used to run an executable (.exe) module.
469 *
470 * @returns Handle to the library which was loaded.
471 * @param lpszLibFile Pointer to zero ASCII string giving the name of the
472 * executable image (either a Dll or an Exe) which is to be
473 * loaded.
474 *
475 * If no extention is specified the default .DLL extention is
476 * appended to the name. End the filename with an '.' if the
477 * file does not have an extention (and don't want the .DLL
478 * appended).
479 *
480 * If no path is specified, this API will use the Odin32
481 * standard search strategy to find the file. This strategy
482 * is described in the method Win32ImageBase::findDLL.
483 *
484 * This API likes to have backslashes (\), but will probably
485 * accept forward slashes too. Win32 SDK docs says that it
486 * should not contain forward slashes.
487 *
488 * Win32 SDK docs adds:
489 * "The name specified is the file name of the module and
490 * is not related to the name stored in the library module
491 * itself, as specified by the LIBRARY keyword in the
492 * module-definition (.def) file."
493 *
494 * @sketch Call LoadLibraryExA with flags set to 0.
495 * @status Odin32 Completely Implemented.
496 * @author Sander van Leeuwen (sandervl@xs4all.nl)
497 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
498 * @remark Forwards to LoadLibraryExA.
499 */
500HINSTANCE WIN32API LoadLibraryA(LPCTSTR lpszLibFile)
501{
502 HINSTANCE hDll;
503
504 dprintf(("KERNEL32: LoadLibraryA(%s) --> LoadLibraryExA(lpszLibFile, 0, 0)",
505 lpszLibFile));
506 hDll = LoadLibraryExA(lpszLibFile, 0, 0);
507 dprintf(("KERNEL32: LoadLibraryA(%s) returns 0x%x",
508 lpszLibFile, hDll));
509 return hDll;
510}
511
512
513/**
514 * LoadLibraryW can be used to map a DLL module into the calling process's
515 * addressspace. It returns a handle that can be used with GetProcAddress to
516 * get addresses of exported entry points (functions and variables).
517 *
518 * LoadLibraryW can also be used to map executable (.exe) modules into the
519 * address to access resources in the module. However, LoadLibrary can't be
520 * used to run an executable (.exe) module.
521 *
522 * @returns Handle to the library which was loaded.
523 * @param lpszLibFile Pointer to Unicode string giving the name of
524 * the executable image (either a Dll or an Exe) which is to
525 * be loaded.
526 *
527 * If no extention is specified the default .DLL extention is
528 * appended to the name. End the filename with an '.' if the
529 * file does not have an extention (and don't want the .DLL
530 * appended).
531 *
532 * If no path is specified, this API will use the Odin32
533 * standard search strategy to find the file. This strategy
534 * is described in the method Win32ImageBase::findDLL.
535 *
536 * This API likes to have backslashes (\), but will probably
537 * accept forward slashes too. Win32 SDK docs says that it
538 * should not contain forward slashes.
539 *
540 * Win32 SDK docs adds:
541 * "The name specified is the file name of the module and
542 * is not related to the name stored in the library module
543 * itself, as specified by the LIBRARY keyword in the
544 * module-definition (.def) file."
545 *
546 * @sketch Convert Unicode name to ascii.
547 * Call LoadLibraryExA with flags set to 0.
548 * free ascii string.
549 * @status Odin32 Completely Implemented.
550 * @author Sander van Leeuwen (sandervl@xs4all.nl)
551 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
552 * @remark Forwards to LoadLibraryExA.
553 */
554HINSTANCE WIN32API LoadLibraryW(LPCWSTR lpszLibFile)
555{
556 char * pszAsciiLibFile;
557 HINSTANCE hDll;
558
559 pszAsciiLibFile = UnicodeToAsciiString(lpszLibFile);
560 dprintf(("KERNEL32: LoadLibraryW(%s) --> LoadLibraryExA(lpszLibFile, 0, 0)",
561 pszAsciiLibFile));
562 hDll = LoadLibraryExA(pszAsciiLibFile, NULL, 0);
563 dprintf(("KERNEL32: LoadLibraryW(%s) returns 0x%x",
564 pszAsciiLibFile, hDll));
565 free(pszAsciiLibFile);
566
567 return hDll;
568}
569
570
571/**
572 * LoadLibraryExA can be used to map a DLL module into the calling process's
573 * addressspace. It returns a handle that can be used with GetProcAddress to
574 * get addresses of exported entry points (functions and variables).
575 *
576 * LoadLibraryExA can also be used to map executable (.exe) modules into the
577 * address to access resources in the module. However, LoadLibrary can't be
578 * used to run an executable (.exe) module.
579 *
580 * @returns Handle to the library which was loaded.
581 * @param lpszLibFile Pointer to Unicode string giving the name of
582 * the executable image (either a Dll or an Exe) which is to
583 * be loaded.
584 *
585 * If no extention is specified the default .DLL extention is
586 * appended to the name. End the filename with an '.' if the
587 * file does not have an extention (and don't want the .DLL
588 * appended).
589 *
590 * If no path is specified, this API will use the Odin32
591 * standard search strategy to find the file. This strategy
592 * is described in the method Win32ImageBase::findDLL.
593 * This may be alterned by the LOAD_WITH_ALTERED_SEARCH_PATH
594 * flag, see below.
595 *
596 * This API likes to have backslashes (\), but will probably
597 * accept forward slashes too. Win32 SDK docs says that it
598 * should not contain forward slashes.
599 *
600 * Win32 SDK docs adds:
601 * "The name specified is the file name of the module and
602 * is not related to the name stored in the library module
603 * itself, as specified by the LIBRARY keyword in the
604 * module-definition (.def) file."
605 *
606 * @param hFile Reserved. Must be 0.
607 *
608 * @param dwFlags Flags which specifies the taken when loading the module.
609 * The value 0 makes it identical to LoadLibraryA/W.
610 *
611 * Flags:
612 *
613 * DONT_RESOLVE_DLL_REFERENCES
614 * (WinNT/2K feature): Don't load imported modules and
615 * hence don't resolve imported symbols.
616 * DllMain isn't called either. (Which is obvious since
617 * it may use one of the importe symbols.)
618 *
619 * On the other hand, if this flag is NOT set, the system
620 * load imported modules, resolves imported symbols, calls
621 * DllMain for process and thread init and term (if wished
622 * by the module).
623 *
624 * partially implemented yet - imports are resolved it seems.
625 *
626 * LOAD_LIBRARY_AS_DATAFILE
627 * If this flag is set, the module is mapped into the
628 * address space but is not prepared for execution. Though
629 * it's preparted for resource API. Hence, you'll use this
630 * flag when you want to load a DLL for extracting
631 * messages or resources from it.
632 *
633 * The resulting handle can be used with any Odin32 API
634 * which operates on resources.
635 * (WinNt/2k supports all resource APIs while Win9x don't
636 * support the specialized resource APIs: LoadBitmap,
637 * LoadCursor, LoadIcon, LoadImage, LoadMenu.)
638 *
639 * not implemented yet.
640 *
641 * LOAD_WITH_ALTERED_SEARCH_PATH
642 * If this flag is set and lpszLibFile specifies a path
643 * we'll use an alternative file search strategy to find
644 * imported modules. This stratgy is simply to use the
645 * path of the module being loaded instead of the path
646 * of the executable module as the first location
647 * to search for imported modules.
648 *
649 * If this flag is clear, the standard Odin32 standard
650 * search strategy. See Win32ImageBase::findDll for
651 * further information.
652 *
653 * not implemented yet.
654 *
655 * @status Open32 Partially Implemented.
656 * @author Sander van Leeuwen (sandervl@xs4all.nl)
657 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
658 * @remark Forwards to LoadLibraryExA.
659 */
660HINSTANCE WIN32API LoadLibraryExA(LPCTSTR lpszLibFile, HANDLE hFile, DWORD dwFlags)
661{
662 HINSTANCE hDll;
663 Win32DllBase * pModule;
664 char szModname[CCHMAXPATH];
665 BOOL fPath; /* Flags which is set if the */
666 /* lpszLibFile contains a path. */
667 ULONG fPE; /* isPEImage return value. */
668
669 /** @sketch
670 * Some parameter validations is probably useful.
671 */
672 if (!VALID_PSZ(lpszLibFile))
673 {
674 dprintf(("KERNEL32: LoadLibraryExA(0x%x, 0x%x, 0x%x): invalid pointer lpszLibFile = 0x%x\n",
675 lpszLibFile, hFile, dwFlags, lpszLibFile));
676 SetLastError(ERROR_INVALID_PARAMETER); //or maybe ERROR_ACCESS_DENIED is more appropriate?
677 return NULL;
678 }
679 if (!VALID_PSZMAXSIZE(lpszLibFile, CCHMAXPATH))
680 {
681 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): lpszLibFile string too long, %d\n",
682 lpszLibFile, hFile, dwFlags, strlen(lpszLibFile)));
683 SetLastError(ERROR_INVALID_PARAMETER);
684 return NULL;
685 }
686 if ((dwFlags & ~(DONT_RESOLVE_DLL_REFERENCES | LOAD_WITH_ALTERED_SEARCH_PATH | LOAD_LIBRARY_AS_DATAFILE)) != 0)
687 {
688 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): dwFlags have invalid or unsupported flags\n",
689 lpszLibFile, hFile, dwFlags));
690 SetLastError(ERROR_INVALID_PARAMETER);
691 return NULL;
692 }
693
694
695 /** @sketch
696 * First we'll see if the module is allready loaded.
697 * IF allready loaded THEN
698 * IF it's a LX dll which isn't loaded and we're using the PeLoader THEN
699 * Set Load library.
700 * Endif
701 * Inc dynamic reference count.
702 * Inc reference count.
703 * RETURN instance handle.
704 * Endif
705 */
706 pModule = Win32DllBase::findModule((LPSTR)lpszLibFile);
707 if (pModule)
708 {
709 if (pModule->isLxDll() && !pModule->isLoaded() && fPeLoader)
710 {
711 //can happen with i.e. wininet
712 //wininet depends on wsock32; when the app loads wsock32 afterwards
713 //with LoadLibrary or as a child of another dll, we need to make
714 //sure it's loaded once with DosLoadModule
715 pModule->setLoadLibrary();
716 }
717 pModule->incDynamicLib();
718 pModule->AddRef();
719 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): returns 0x%x. Dll found %s",
720 lpszLibFile, hFile, dwFlags, pModule->getInstanceHandle(), pModule->getFullPath()));
721 return pModule->getInstanceHandle();
722 }
723
724
725 /** @sketch
726 * Test if lpszLibFile has a path or not.
727 * Copy the lpszLibFile to szModname, rename the dll and uppercase the name.
728 * IF it hasn't a path THEN
729 * Issue a findDll to find the dll/executable to be loaded.
730 * IF the Dll isn't found THEN
731 * Set last error and RETURN.
732 * Endif.
733 * Endif
734 */
735 fPath = strchr(lpszLibFile, '\\') || strchr(lpszLibFile, '/');
736 strcpy(szModname, lpszLibFile);
737 Win32DllBase::renameDll(szModname);
738 strupr(szModname);
739
740 if (!fPath)
741 {
742 char szModName2[CCHMAXPATH];
743 strcpy(szModName2, szModname);
744 if (!Win32ImageBase::findDll(szModName2, szModname, sizeof(szModname)))
745 {
746 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): module wasn't found. returns NULL",
747 lpszLibFile, hFile, dwFlags));
748 SetLastError(ERROR_FILE_NOT_FOUND);
749 return NULL;
750 }
751 }
752
753
754 /** @sketch
755 * IF dwFlags == 0 THEN
756 * Try load the executable using LoadLibrary
757 * IF successfully loaded THEN
758 * IF LX dll and is using the PE Loader THEN
759 * Set Load library.
760 * Inc reference count.
761 * Endif
762 * Inc dynamic reference count.
763 * RETURN successfully.
764 * Endif
765 * Endif
766 */
767 if (dwFlags == 0)
768 {
769 hDll = O32_LoadLibrary(szModname);
770 if (hDll)
771 {
772 /* OS/2 dll, system dll, converted dll or win32k took care of it.*/
773 pModule = Win32DllBase::findModule(hDll);
774 if (pModule)
775 {
776 if (pModule->isLxDll() && fPeLoader)
777 {
778 pModule->setLoadLibrary();
779 pModule->AddRef();
780 }
781 pModule->incDynamicLib();
782 }
783 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): returns 0x%x. Loaded %s using O32_LoadLibrary.",
784 lpszLibFile, hFile, dwFlags, hDll, szModname));
785 return hDll;
786 }
787 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): O32_LoadLibrary(%s) failed. LastError=%d",
788 lpszLibFile, hFile, dwFlags, szModname, GetLastError()));
789 }
790 else
791 hDll = NULL;
792
793
794 /** @sketch
795 * If PE image THEN
796 * IF LOAD_LIBRARY_AS_DATAFILE or Executable THEN
797 *
798 *
799 * Try load the file using the Win32PeLdrDll class.
800 * <sketch continued further down>
801 * Else
802 * Set last error.
803 * (hDll is NULL)
804 * Endif
805 * return hDll.
806 */
807 fPE = Win32ImageBase::isPEImage(szModname);
808 if(fPE == ERROR_SUCCESS)
809 {
810 Win32PeLdrDll * peldrDll;
811 /* TODO!
812 * We might use the fake loader class to do the LOAD_LIBRARY_AS_DATAFILE and
813 * executable image loading. These are both loaded for accessing resource.
814 * But this requires that they behaves like Dlls...
815 if (dwFlags & LOAD_LIBRARY_AS_DATAFILE || fPE == 2)
816 {
817 peldrDll = new Win32PeLdrRsrcImg(szModname);
818 }
819 else
820 */
821
822 peldrDll = new Win32PeLdrDll(szModname);
823 if (peldrDll == NULL)
824 {
825 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Failed to created instance of Win32PeLdrDll. returns NULL.",
826 lpszLibFile, hFile, dwFlags));
827 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
828 return NULL;
829 }
830
831 /** @sketch
832 * Process dwFlags
833 */
834 if (dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE))
835 {
836 peldrDll->disableThreadLibraryCalls();
837 //peldrDll->setDontProcessImports(); not implemented?
838 }
839 if (dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH)
840 {
841 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Warning dwFlags LOAD_WITH_ALTERED_SEARCH_PATH is not implemented.",
842 lpszLibFile, hFile, dwFlags));
843 //peldrDll->setLoadWithAlteredSearchPath();
844 }
845 if (dwFlags & LOAD_LIBRARY_AS_DATAFILE)
846 {
847 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Warning dwFlags LOAD_LIBRARY_AS_DATAFILE is not implemented.",
848 lpszLibFile, hFile, dwFlags));
849 //peldrDll->setLoadAsDatafile();
850 }
851
852 /** @sketch
853 * Initiate the peldr DLL.
854 * IF successful init THEN
855 * Inc dynamic ref count.
856 * Inc ref count.
857 * Attach to process
858 * IF successful THEN
859 * hDLL <- instance handle.
860 * ELSE
861 * set last error
862 * delete Win32PeLdrDll instance.
863 * Endif
864 * ELSE
865 * set last error
866 * delete Win32PeLdrDll instance.
867 * Endif.
868 */
869 if (peldrDll->init(0))
870 {
871 peldrDll->AddRef();
872 if (peldrDll->attachProcess()) {
873 hDll = peldrDll->getInstanceHandle();
874 //Must be called *after* attachprocess, since attachprocess may also
875 //trigger LoadLibrary calls
876 //Those dlls must not be put in front of this dll in the dynamic
877 //dll list; or else the unload order is wrong:
878 //i.e. RPAP3260 loads PNRS3260 in DLL_PROCESS_ATTACH
879 // this means that in ExitProcess, PNRS3260 needs to be removed
880 // first since RPAP3260 depends on it
881 peldrDll->incDynamicLib();
882 }
883 else
884 {
885 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): attachProcess call to Win32PeLdrDll instance failed. returns NULL.",
886 lpszLibFile, hFile, dwFlags));
887 SetLastError(ERROR_DLL_INIT_FAILED);
888 delete peldrDll;
889 }
890 }
891 else
892 {
893 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Failed to init Win32PeLdrDll instance. error=%d returns NULL.",
894 lpszLibFile, hFile, dwFlags, peldrDll->getError()));
895 SetLastError(ERROR_INVALID_EXE_SIGNATURE);
896 delete peldrDll;
897 }
898 }
899 else
900 {
901 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x) library wasn't found (%s) or isn't loadable; err %x",
902 lpszLibFile, hFile, dwFlags, szModname, fPE));
903 SetLastError(fPE);
904 }
905
906 return hDll;
907}
908
909
910/**
911 * LoadLibraryExW can be used to map a DLL module into the calling process's
912 * addressspace. It returns a handle that can be used with GetProcAddress to
913 * get addresses of exported entry points (functions and variables).
914 *
915 * LoadLibraryExW can also be used to map executable (.exe) modules into the
916 * address to access resources in the module. However, LoadLibrary can't be
917 * used to run an executable (.exe) module.
918 *
919 * @returns Handle to the library which was loaded.
920 * @param lpszLibFile Pointer to Unicode string giving the name of
921 * the executable image (either a Dll or an Exe) which is to
922 * be loaded.
923 *
924 * If no extention is specified the default .DLL extention is
925 * appended to the name. End the filename with an '.' if the
926 * file does not have an extention (and don't want the .DLL
927 * appended).
928 *
929 * If no path is specified, this API will use the Odin32
930 * standard search strategy to find the file. This strategy
931 * is described in the method Win32ImageBase::findDLL.
932 * This may be alterned by the LOAD_WITH_ALTERED_SEARCH_PATH
933 * flag, see below.
934 *
935 * This API likes to have backslashes (\), but will probably
936 * accept forward slashes too. Win32 SDK docs says that it
937 * should not contain forward slashes.
938 *
939 * Win32 SDK docs adds:
940 * "The name specified is the file name of the module and
941 * is not related to the name stored in the library module
942 * itself, as specified by the LIBRARY keyword in the
943 * module-definition (.def) file."
944 *
945 * @param hFile Reserved. Must be 0.
946 *
947 * @param dwFlags Flags which specifies the taken when loading the module.
948 * The value 0 makes it identical to LoadLibraryA/W.
949 *
950 * Flags:
951 *
952 * DONT_RESOLVE_DLL_REFERENCES
953 * (WinNT/2K feature): Don't load imported modules and
954 * hence don't resolve imported symbols.
955 * DllMain isn't called either. (Which is obvious since
956 * it may use one of the importe symbols.)
957 *
958 * On the other hand, if this flag is NOT set, the system
959 * load imported modules, resolves imported symbols, calls
960 * DllMain for process and thread init and term (if wished
961 * by the module).
962 *
963 * LOAD_LIBRARY_AS_DATAFILE
964 * If this flag is set, the module is mapped into the
965 * address space but is not prepared for execution. Though
966 * it's preparted for resource API. Hence, you'll use this
967 * flag when you want to load a DLL for extracting
968 * messages or resources from it.
969 *
970 * The resulting handle can be used with any Odin32 API
971 * which operates on resources.
972 * (WinNt/2k supports all resource APIs while Win9x don't
973 * support the specialized resource APIs: LoadBitmap,
974 * LoadCursor, LoadIcon, LoadImage, LoadMenu.)
975 *
976 * LOAD_WITH_ALTERED_SEARCH_PATH
977 * If this flag is set and lpszLibFile specifies a path
978 * we'll use an alternative file search strategy to find
979 * imported modules. This stratgy is simply to use the
980 * path of the module being loaded instead of the path
981 * of the executable module as the first location
982 * to search for imported modules.
983 *
984 * If this flag is clear, the standard Odin32 standard
985 * search strategy. See Win32ImageBase::findDll for
986 * further information.
987 *
988 * @sketch Convert Unicode name to ascii.
989 * Call LoadLibraryExA.
990 * Free ascii string.
991 * return handle from LoadLibraryExA.
992 * @status Open32 Partially Implemented.
993 * @author Sander van Leeuwen (sandervl@xs4all.nl)
994 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
995 * @remark Forwards to LoadLibraryExA.
996 */
997HINSTANCE WIN32API LoadLibraryExW(LPCWSTR lpszLibFile, HANDLE hFile, DWORD dwFlags)
998{
999 char * pszAsciiLibFile;
1000 HINSTANCE hDll;
1001
1002 pszAsciiLibFile = UnicodeToAsciiString(lpszLibFile);
1003 dprintf(("KERNEL32: LoadLibraryExW(%s, 0x%x, 0x%x) --> LoadLibraryExA",
1004 pszAsciiLibFile, hFile, dwFlags));
1005 hDll = LoadLibraryExA(pszAsciiLibFile, hFile, dwFlags);
1006 dprintf(("KERNEL32: LoadLibraryExW(%s, 0x%x, 0x%x) returns 0x%x",
1007 pszAsciiLibFile, hFile, dwFlags, hDll));
1008 free(pszAsciiLibFile);
1009
1010 return hDll;
1011}
1012//******************************************************************************
1013//******************************************************************************
1014HINSTANCE16 WIN32API LoadLibrary16(LPCTSTR lpszLibFile)
1015{
1016 dprintf(("ERROR: LoadLibrary16 %s, not implemented", lpszLibFile));
1017 return 0;
1018}
1019//******************************************************************************
1020//******************************************************************************
1021VOID WIN32API FreeLibrary16(HINSTANCE16 hinstance)
1022{
1023 dprintf(("ERROR: FreeLibrary16 %x, not implemented", hinstance));
1024}
1025//******************************************************************************
1026//******************************************************************************
1027FARPROC WIN32API GetProcAddress16(HMODULE hModule, LPCSTR lpszProc)
1028{
1029 dprintf(("ERROR: GetProcAddress16 %x %x, not implemented", hModule, lpszProc));
1030 return 0;
1031}
1032//******************************************************************************
1033//******************************************************************************
1034LPCSTR WIN32API GetCommandLineA()
1035{
1036 LPTSTR cmdline = NULL;
1037
1038 if(WinExe) {
1039 cmdline = WinExe->getCommandLineA();
1040 }
1041 if(cmdline == NULL) //not used for converted exes
1042 cmdline = O32_GetCommandLine();
1043
1044 dprintf(("KERNEL32: GetCommandLine %s\n", cmdline));
1045 dprintf(("KERNEL32: FS = %x\n", GetFS()));
1046 return(cmdline);
1047}
1048//******************************************************************************
1049//******************************************************************************
1050LPCWSTR WIN32API GetCommandLineW(void)
1051{
1052 static WCHAR *UnicodeCmdLine = NULL;
1053 char *asciicmdline = NULL;
1054
1055 dprintf(("KERNEL32: FS = %x\n", GetFS()));
1056
1057 if(UnicodeCmdLine)
1058 return(UnicodeCmdLine); //already called before
1059
1060 if(WinExe) {
1061 if(WinExe->getCommandLineW())
1062 return WinExe->getCommandLineW();
1063 }
1064 if(asciicmdline == NULL) //not used for converted exes
1065 asciicmdline = O32_GetCommandLine();
1066
1067 if(asciicmdline) {
1068 UnicodeCmdLine = (WCHAR *)malloc(strlen(asciicmdline)*2 + 2);
1069 AsciiToUnicode(asciicmdline, UnicodeCmdLine);
1070 dprintf(("KERNEL32: OS2GetCommandLineW: %s\n", asciicmdline));
1071 return(UnicodeCmdLine);
1072 }
1073 dprintf(("KERNEL32: OS2GetCommandLineW: asciicmdline == NULL\n"));
1074 return NULL;
1075}
1076//******************************************************************************
1077//******************************************************************************
1078DWORD WIN32API GetModuleFileNameA(HMODULE hinstModule, LPTSTR lpszPath, DWORD cchPath)
1079{
1080 DWORD rc;
1081 Win32ImageBase *module;
1082 char *fpath = NULL;
1083
1084 dprintf(("GetModuleFileName %X", hinstModule));
1085 if(hinstModule == 0 || hinstModule == -1 || (WinExe && hinstModule == WinExe->getInstanceHandle())) {
1086 module = (Win32ImageBase *)WinExe;
1087 }
1088 else {
1089 module = (Win32ImageBase *)Win32DllBase::findModule(hinstModule);
1090 }
1091
1092 if(module) {
1093 fpath = module->getFullPath();
1094 }
1095 if(fpath) {
1096 //SvL: 13-9-98: +1
1097 rc = min(strlen(fpath)+1, cchPath);
1098 strncpy(lpszPath, fpath, rc);
1099 lpszPath[rc-1] = 0;
1100 }
1101 else rc = O32_GetModuleFileName(hinstModule, lpszPath, cchPath);
1102
1103 if(rc) {
1104 dprintf(("KERNEL32: GetModuleFileName %s %d\n", lpszPath, hinstModule));
1105 }
1106 return(rc);
1107}
1108//******************************************************************************
1109//******************************************************************************
1110DWORD WIN32API GetModuleFileNameW(HMODULE hModule, LPWSTR lpFileName, DWORD nSize)
1111{
1112 char *asciifilename = (char *)malloc(nSize+1);
1113 DWORD rc;
1114
1115 dprintf(("KERNEL32: OSLibGetModuleFileNameW\n"));
1116 rc = GetModuleFileNameA(hModule, asciifilename, nSize);
1117 if(rc) AsciiToUnicode(asciifilename, lpFileName);
1118 free(asciifilename);
1119 return(rc);
1120}
1121//******************************************************************************
1122//NOTE: GetModuleHandleA does NOT support files with multiple dots (i.e.
1123// very.weird.exe)
1124//******************************************************************************
1125HANDLE WIN32API GetModuleHandleA(LPCTSTR lpszModule)
1126{
1127 HANDLE hMod;
1128 Win32DllBase *windll;
1129 char szModule[CCHMAXPATH];
1130 BOOL fDllModule = FALSE;
1131
1132 if(lpszModule == NULL) {
1133 if(WinExe)
1134 hMod = WinExe->getInstanceHandle();
1135 else hMod = -1;
1136 }
1137 else {
1138 strcpy(szModule, OSLibStripPath((char *)lpszModule));
1139 strupr(szModule);
1140 if(strstr(szModule, ".DLL")) {
1141 fDllModule = TRUE;
1142 }
1143 else {
1144 if(!strstr(szModule, ".")) {
1145 //if there's no extension or trainling dot, we
1146 //assume it's a dll (see Win32 SDK docs)
1147 fDllModule = TRUE;
1148 }
1149 }
1150 char *dot = strstr(szModule, ".");
1151 if(dot)
1152 *dot = 0;
1153
1154 if(!fDllModule && WinExe && !strcmpi(szModule, WinExe->getModuleName())) {
1155 hMod = WinExe->getInstanceHandle();
1156 }
1157 else {
1158 windll = Win32DllBase::findModule(szModule);
1159 if(windll) {
1160 hMod = windll->getInstanceHandle();
1161 }
1162 else hMod = OSLibiGetModuleHandleA((char *)lpszModule);
1163 }
1164 }
1165
1166 dprintf(("KERNEL32: GetModuleHandle %s returned %X\n", lpszModule, hMod));
1167 return(hMod);
1168}
1169//******************************************************************************
1170//******************************************************************************
1171HMODULE WIN32API GetModuleHandleW(LPCWSTR arg1)
1172{
1173 HMODULE rc;
1174 char *astring;
1175
1176 astring = UnicodeToAsciiString((LPWSTR)arg1);
1177 rc = GetModuleHandleA(astring);
1178 dprintf(("KERNEL32: OS2GetModuleHandleW %s returned %X\n", astring, rc));
1179 FreeAsciiString(astring);
1180 return(rc);
1181}
1182//******************************************************************************
1183//******************************************************************************
1184BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
1185 LPSECURITY_ATTRIBUTES lpProcessAttributes,
1186 LPSECURITY_ATTRIBUTES lpThreadAttributes,
1187 BOOL bInheritHandles, DWORD dwCreationFlags,
1188 LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
1189 LPSTARTUPINFOA lpStartupInfo,
1190 LPPROCESS_INFORMATION lpProcessInfo )
1191{
1192 THDB *pThreadDB = (THDB*)GetThreadTHDB();
1193 char *cmdline = NULL;
1194 BOOL rc;
1195
1196 dprintf(("KERNEL32: CreateProcessA %s cline:%s inherit:%d cFlags:%x Env:%x CurDir:%s StartupFlags:%x\n",
1197 lpApplicationName, lpCommandLine, bInheritHandles, dwCreationFlags,
1198 lpEnvironment, lpCurrentDirectory, lpStartupInfo));
1199
1200 // open32 does not support DEBUG_ONLY_THIS_PROCESS
1201 if(dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
1202 dwCreationFlags |= DEBUG_PROCESS;
1203
1204 if(O32_CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes,
1205 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1206 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1207 lpProcessInfo) == TRUE)
1208 {
1209 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
1210 {
1211 if(pThreadDB->pidDebuggee != 0)
1212 {
1213 // TODO: handle this
1214 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
1215 }
1216 else
1217 {
1218 pThreadDB->pidDebuggee = lpProcessInfo->dwProcessId;
1219 OSLibStartDebugger((ULONG*)&pThreadDB->pidDebuggee);
1220 }
1221 }
1222 else pThreadDB->pidDebuggee = 0;
1223
1224 return(TRUE);
1225 }
1226 //probably a win32 exe, so run it in the pe loader
1227 if(lpApplicationName) {
1228 if(lpCommandLine) {
1229 //skip exe name in lpCommandLine
1230 while(*lpCommandLine != 0 && *lpCommandLine != ' ')
1231 lpCommandLine++;
1232
1233 if(*lpCommandLine != 0) {
1234 lpCommandLine++;
1235 }
1236 cmdline = (char *)malloc(strlen(lpApplicationName)+strlen(lpCommandLine) + 16);
1237 sprintf(cmdline, "PE.EXE %s %s", lpApplicationName, lpCommandLine);
1238 }
1239 else {
1240 cmdline = (char *)malloc(strlen(lpApplicationName) + 16);
1241 sprintf(cmdline, "PE.EXE %s", lpApplicationName);
1242 }
1243 }
1244 else {
1245 cmdline = (char *)malloc(strlen(lpCommandLine) + 16);
1246 sprintf(cmdline, "PE.EXE %s", lpCommandLine);
1247 }
1248 dprintf(("KERNEL32: CreateProcess %s\n", cmdline));
1249 rc = O32_CreateProcess("PE.EXE", (LPCSTR)cmdline,lpProcessAttributes,
1250 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1251 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1252 lpProcessInfo);
1253 if(rc == TRUE) {
1254 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
1255 {
1256 if(pThreadDB->pidDebuggee != 0)
1257 {
1258 // TODO: handle this
1259 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
1260 }
1261 else
1262 {
1263 pThreadDB->pidDebuggee = lpProcessInfo->dwProcessId;
1264 OSLibStartDebugger((ULONG*)&pThreadDB->pidDebuggee);
1265 }
1266 }
1267 else
1268 pThreadDB->pidDebuggee = 0;
1269 }
1270 if(cmdline)
1271 free(cmdline);
1272
1273 if(lpProcessInfo)
1274 dprintf(("KERNEL32: CreateProcess returned %d hPro:%x hThr:%x pid:%x tid:%x\n",
1275 rc, lpProcessInfo->hProcess, lpProcessInfo->hThread,
1276 lpProcessInfo->dwProcessId,lpProcessInfo->dwThreadId));
1277 else
1278 dprintf(("KERNEL32: CreateProcess returned %d\n", rc));
1279 return(rc);
1280}
1281//******************************************************************************
1282//******************************************************************************
1283BOOL WIN32API CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
1284 PSECURITY_ATTRIBUTES lpProcessAttributes,
1285 PSECURITY_ATTRIBUTES lpThreadAttributes,
1286 BOOL bInheritHandles, DWORD dwCreationFlags,
1287 LPVOID lpEnvironment,
1288 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
1289 LPPROCESS_INFORMATION lpProcessInfo)
1290{
1291 BOOL rc;
1292 char *astring1 = 0, *astring2 = 0, *astring3 = 0;
1293
1294 dprintf(("KERNEL32: CreateProcessW"));
1295 if(lpApplicationName)
1296 astring1 = UnicodeToAsciiString((LPWSTR)lpApplicationName);
1297 if(lpCommandLine)
1298 astring2 = UnicodeToAsciiString(lpCommandLine);
1299 if(lpCurrentDirectory)
1300 astring3 = UnicodeToAsciiString((LPWSTR)lpCurrentDirectory);
1301 rc = CreateProcessA(astring1, astring2, lpProcessAttributes, lpThreadAttributes,
1302 bInheritHandles, dwCreationFlags, lpEnvironment,
1303 astring3, (LPSTARTUPINFOA)lpStartupInfo,
1304 lpProcessInfo);
1305 if(astring3) FreeAsciiString(astring3);
1306 if(astring2) FreeAsciiString(astring2);
1307 if(astring1) FreeAsciiString(astring1);
1308 return(rc);
1309}
1310//******************************************************************************
1311//******************************************************************************
1312HINSTANCE WIN32API WinExec(LPCSTR lpCmdLine, UINT nCmdShow)
1313{
1314 STARTUPINFOA startinfo = {0};
1315 PROCESS_INFORMATION procinfo;
1316 DWORD rc;
1317
1318 dprintf(("KERNEL32: WinExec %s\n", lpCmdLine));
1319 startinfo.dwFlags = nCmdShow;
1320 if(CreateProcessA(NULL, (LPSTR)lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL,
1321 &startinfo, &procinfo) == FALSE)
1322 {
1323 return 0;
1324 }
1325 //block until the launched app waits for input (or a timeout of 15 seconds)
1326 //TODO: Shouldn't call Open32, but the api in user32..
1327 rc = O32_WaitForInputIdle(procinfo.hProcess, 15000);
1328 if(rc != 0) {
1329 dprintf(("WinExec: WaitForInputIdle %x returned %x", procinfo.hProcess, rc));
1330 }
1331 return procinfo.hProcess; //correct?
1332}
1333//******************************************************************************
1334//******************************************************************************
1335FARPROC WIN32API GetProcAddress(HMODULE hModule, LPCSTR lpszProc)
1336{
1337 Win32ImageBase *winmod;
1338 FARPROC proc;
1339 ULONG ulAPIOrdinal;
1340
1341 if(hModule == 0 || hModule == -1 || (WinExe && hModule == WinExe->getInstanceHandle())) {
1342 winmod = WinExe;
1343 }
1344 else winmod = (Win32ImageBase *)Win32DllBase::findModule((HINSTANCE)hModule);
1345
1346 if(winmod) {
1347 ulAPIOrdinal = (ULONG)lpszProc;
1348 if (ulAPIOrdinal <= 0x0000FFFF) {
1349 proc = (FARPROC)winmod->getApi((int)ulAPIOrdinal);
1350 }
1351 else proc = (FARPROC)winmod->getApi((char *)lpszProc);
1352 if(proc == 0) {
1353#ifdef DEBUG
1354 if(ulAPIOrdinal <= 0x0000FFFF) {
1355 dprintf(("GetProcAddress %x %x not found!", hModule, ulAPIOrdinal));
1356 }
1357 else dprintf(("GetProcAddress %x %s not found!", hModule, lpszProc));
1358#endif
1359 SetLastError(ERROR_PROC_NOT_FOUND);
1360 }
1361 return proc;
1362 }
1363 proc = O32_GetProcAddress(hModule, lpszProc);
1364 if(HIWORD(lpszProc))
1365 dprintf(("KERNEL32: GetProcAddress %s from %X returned %X\n", lpszProc, hModule, proc));
1366 else dprintf(("KERNEL32: GetProcAddress %x from %X returned %X\n", lpszProc, hModule, proc));
1367 return(proc);
1368}
1369//******************************************************************************
1370//Retrieve the version
1371//******************************************************************************
1372BOOL SYSTEM GetVersionStruct(char *lpszModName, char *verstruct, ULONG bufLength)
1373{
1374 Win32ImageBase *winimage;
1375 Win32PeLdrRsrcImg *rsrcimg;
1376
1377 dprintf(("GetVersionStruct of module %s", lpszModName));
1378 if(WinExe && !stricmp(WinExe->getFullPath(), lpszModName)) {
1379 winimage = (Win32ImageBase *)WinExe;
1380 }
1381 else {
1382 winimage = (Win32ImageBase *)Win32DllBase::findModule(lpszModName);
1383 if(winimage == NULL)
1384 {
1385 char modname[CCHMAXPATH];
1386
1387 strcpy(modname, lpszModName);
1388 //rename dll if necessary (i.e. OLE32 -> OLE32OS2)
1389 Win32DllBase::renameDll(modname);
1390
1391 if(Win32ImageBase::isPEImage(modname) != ERROR_SUCCESS)
1392 {
1393 HINSTANCE hInstance;
1394
1395 //must be an LX dll, just load it (app will probably load it anyway)
1396 hInstance = LoadLibraryA(modname);
1397 if(hInstance == 0)
1398 return 0;
1399 winimage = (Win32ImageBase *)Win32DllBase::findModule(hInstance);
1400 if(winimage) {
1401 return winimage->getVersionStruct(verstruct, bufLength);
1402 }
1403 return 0;
1404 }
1405 //SvL: Try to load it
1406 rsrcimg = new Win32PeLdrRsrcImg(modname);
1407 if(rsrcimg == NULL)
1408 return 0;
1409
1410 rsrcimg->init(0);
1411 if(rsrcimg->getError() != NO_ERROR)
1412 {
1413 dprintf(("GetVersionStruct can't load %s\n", modname));
1414 delete rsrcimg;
1415 return(FALSE);
1416 }
1417 BOOL rc = rsrcimg->getVersionStruct(verstruct, bufLength);
1418 delete rsrcimg;
1419 return rc;
1420 }
1421 }
1422 return winimage->getVersionStruct(verstruct, bufLength);
1423}
1424//******************************************************************************
1425//******************************************************************************
1426ULONG SYSTEM GetVersionSize(char *lpszModName)
1427{
1428 Win32ImageBase *winimage;
1429 Win32PeLdrRsrcImg *rsrcimg;
1430
1431 dprintf(("GetVersionSize of %s\n", lpszModName));
1432
1433 if(WinExe && !stricmp(WinExe->getFullPath(), lpszModName)) {
1434 winimage = (Win32ImageBase *)WinExe;
1435 }
1436 else {
1437 winimage = (Win32ImageBase *)Win32DllBase::findModule(lpszModName);
1438 if(winimage == NULL)
1439 {
1440 char modname[CCHMAXPATH];
1441
1442 strcpy(modname, lpszModName);
1443 //rename dll if necessary (i.e. OLE32 -> OLE32OS2)
1444 Win32DllBase::renameDll(modname);
1445
1446 if(Win32ImageBase::isPEImage(modname) != ERROR_SUCCESS)
1447 {
1448 HINSTANCE hInstance;
1449
1450 //must be an LX dll, just load it (app will probably load it anyway)
1451 hInstance = LoadLibraryA(modname);
1452 if(hInstance == 0)
1453 return 0;
1454 winimage = (Win32ImageBase *)Win32DllBase::findModule(hInstance);
1455 if(winimage) {
1456 return winimage->getVersionSize();
1457 }
1458 return 0;
1459 }
1460
1461 //SvL: Try to load it
1462 rsrcimg = new Win32PeLdrRsrcImg(modname);
1463 if(rsrcimg == NULL)
1464 return 0;
1465
1466 rsrcimg->init(0);
1467 if(rsrcimg->getError() != NO_ERROR)
1468 {
1469 dprintf(("GetVersionSize can't load %s\n", modname));
1470 delete rsrcimg;
1471 return(FALSE);
1472 }
1473 int size = rsrcimg->getVersionSize();
1474 delete rsrcimg;
1475 return size;
1476 }
1477 }
1478 return winimage->getVersionSize();
1479}
1480//******************************************************************************
1481//TODO:What does this do exactly??
1482//******************************************************************************
1483ODINFUNCTION1(BOOL,DisableThreadLibraryCalls,HMODULE,hModule)
1484{
1485 Win32DllBase *winmod;
1486 FARPROC proc;
1487 ULONG ulAPIOrdinal;
1488
1489 winmod = Win32DllBase::findModule((HINSTANCE)hModule);
1490 if(winmod)
1491 {
1492 // don't call ATTACH/DETACH thread functions in DLL
1493 winmod->disableThreadLibraryCalls();
1494 return TRUE;
1495 }
1496 else
1497 {
1498 // raise error condition
1499 SetLastError(ERROR_INVALID_HANDLE);
1500 return FALSE;
1501 }
1502}
1503//******************************************************************************
1504//******************************************************************************
Note: See TracBrowser for help on using the repository browser.