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

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

exception handler changes/fixes (after ExitProcess has been called

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