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

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

dll unload fix + detach skip fix

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