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

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

GetFileTime bugfix + FindResource(Ex)A/W changes + setup thread security objects during creation

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