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

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

misc fixes

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