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

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

create additional keys during install (display driver related) + extra logging for GetProcAddress

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