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

Last change on this file since 6015 was 6015, checked in by bird, 24 years ago

Corrected Pe2Lx bug in LoadLibrary. Added isPe2LxDLL.

File size: 76.9 KB
Line 
1/* $Id: wprocess.cpp,v 1.125 2001-06-15 09:42:49 bird Exp $ */
2
3/*
4 * Win32 process functions
5 *
6 * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
8 *
9 * NOTE: Even though Odin32 OS/2 apps don't switch FS selectors,
10 * we still allocate a TEB to store misc information.
11 *
12 * TODO: What happens when a dll is first loaded as LOAD_LIBRARY_AS_DATAFILE
13 * and then for real? (first one not freed of course)
14 *
15 * Project Odin Software License can be found in LICENSE.TXT
16 *
17 */
18#include <odin.h>
19#include <odinwrap.h>
20#include <os2win.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <unicode.h>
26#include "windllbase.h"
27#include "winexebase.h"
28#include "windllpeldr.h"
29#include "winexepeldr.h"
30#include "windlllx.h"
31#include <vmutex.h>
32#include <handlemanager.h>
33
34#include "odin32validate.h"
35#include "exceptutil.h"
36#include "oslibdos.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* Global Variables *
54*******************************************************************************/
55BOOL fIsOS2Image = FALSE; /* TRUE -> Odin32 OS/2 application (not converted!) */
56 /* FALSE -> otherwise */
57BOOL fExitProcess = FALSE;
58
59//Commandlines
60PCSTR pszCmdLineA; /* ASCII/ANSII commandline. */
61PCWSTR pszCmdLineW; /* Unicode commandline. */
62
63//Process database
64PDB ProcessPDB = {0};
65USHORT ProcessTIBSel = 0;
66DWORD *TIBFlatPtr = 0;
67
68//list of thread database structures
69static TEB *threadList = 0;
70static VMutex threadListMutex;
71
72//TODO: This should not be here: (need to rearrange NTDLL; kernel32 can't depend on ntdll)
73BOOLEAN (* WINAPI RtlAllocateAndInitializeSid) ( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
74 BYTE nSubAuthorityCount,
75 DWORD nSubAuthority0,
76 DWORD nSubAuthority1,
77 DWORD nSubAuthority2,
78 DWORD nSubAuthority3,
79 DWORD nSubAuthority4,
80 DWORD nSubAuthority5,
81 DWORD nSubAuthority6,
82 DWORD nSubAuthority7,
83 PSID *pSid);
84static HINSTANCE hInstNTDll = 0;
85
86//******************************************************************************
87//******************************************************************************
88TEB *WIN32API GetThreadTEB()
89{
90 if(TIBFlatPtr == NULL) {
91 return 0;
92 }
93 return (TEB *)*TIBFlatPtr;
94}
95//******************************************************************************
96//******************************************************************************
97TEB *WIN32API GetTEBFromThreadId(ULONG threadId)
98{
99 TEB *teb = threadList;
100
101 threadListMutex.enter();
102 while(teb) {
103 if(teb->o.odin.threadId == threadId) {
104 break;
105 }
106 teb = teb->o.odin.next;
107 }
108 threadListMutex.leave();
109 return teb;
110}
111//******************************************************************************
112//******************************************************************************
113TEB *WIN32API GetTEBFromThreadHandle(HANDLE hThread)
114{
115 TEB *teb = threadList;
116
117 threadListMutex.enter();
118 while(teb) {
119 if(teb->o.odin.hThread == hThread) {
120 break;
121 }
122 teb = teb->o.odin.next;
123 }
124 threadListMutex.leave();
125 return teb;
126}
127//******************************************************************************
128// Set up the TIB selector and memory for the current thread
129//******************************************************************************
130TEB * WIN32API InitializeTIB(BOOL fMainThread)
131{
132 TEB *winteb;
133 ULONG hThreadMain;
134 USHORT tibsel;
135
136 //Allocate one dword to store the flat address of our TEB
137 if(fMainThread) {
138 TIBFlatPtr = (DWORD *)OSLibAllocThreadLocalMemory(1);
139 if(TIBFlatPtr == 0) {
140 dprintf(("InitializeTIB: local thread memory alloc failed!!"));
141 DebugInt3();
142 return NULL;
143 }
144 //SvL: This doesn't really create a thread, but only sets up the
145 // handle of thread 0
146 hThreadMain = HMCreateThread(NULL, 0, 0, 0, 0, 0, TRUE);
147 }
148 if(OSLibAllocSel(sizeof(TEB), &tibsel) == FALSE)
149 {
150 dprintf(("InitializeTIB: selector alloc failed!!"));
151 DebugInt3();
152 return NULL;
153 }
154 winteb = (TEB *)OSLibSelToFlat(tibsel);
155 if(winteb == NULL)
156 {
157 dprintf(("InitializeTIB: DosSelToFlat failed!!"));
158 DebugInt3();
159 return NULL;
160 }
161 memset(winteb, 0, sizeof(TEB));
162 *TIBFlatPtr = (DWORD)winteb;
163
164 winteb->except = (PVOID)-1; /* 00 Head of exception handling chain */
165 winteb->stack_top = (PVOID)OSLibGetTIB(TIB_STACKTOP); /* 04 Top of thread stack */
166 winteb->stack_low = (PVOID)OSLibGetTIB(TIB_STACKLOW); /* 08 Stack low-water mark */
167 winteb->htask16 = (USHORT)OSLibGetPIB(PIB_TASKHNDL); /* 0c Win16 task handle */
168 winteb->stack_sel = getSS(); /* 0e 16-bit stack selector */
169 winteb->self = winteb; /* 18 Pointer to this structure */
170 winteb->flags = TEBF_WIN32; /* 1c Flags */
171 winteb->queue = 0; /* 28 Message queue */
172 winteb->tls_ptr = &winteb->tls_array[0]; /* 2c Pointer to TLS array */
173 winteb->process = &ProcessPDB; /* 30 owning process (used by NT3.51 applets)*/
174
175 winteb->process = &ProcessPDB;
176 winteb->exit_code = 0x103; /* STILL_ACTIVE */
177 winteb->teb_sel = tibsel;
178 winteb->o.odin.OrgTIBSel = GetFS();
179 winteb->o.odin.pWsockData = NULL;
180 winteb->o.odin.threadId = GetCurrentThreadId();
181 if(fMainThread) {
182 winteb->o.odin.hThread = hThreadMain;
183 }
184 else winteb->o.odin.hThread = GetCurrentThread();
185 winteb->o.odin.lcid = GetUserDefaultLCID();
186
187 threadListMutex.enter();
188 TEB *teblast = threadList;
189 if(!teblast) {
190 threadList = winteb;
191 }
192 else {
193 while(teblast->o.odin.next) {
194 teblast = teblast->o.odin.next;
195 }
196 teblast->o.odin.next = winteb;
197 }
198 winteb->o.odin.next = NULL;
199 threadListMutex.leave();
200
201 if(OSLibGetPIB(PIB_TASKTYPE) == TASKTYPE_PM)
202 {
203 winteb->flags = 0; //todo gui
204 }
205 else winteb->flags = 0; //todo textmode
206
207 //Initialize thread security objects (TODO: Not complete)
208 if(hInstNTDll == 0) {
209 hInstNTDll = LoadLibraryA("NTDLL.DLL");
210 *(ULONG *)&RtlAllocateAndInitializeSid = (ULONG)GetProcAddress(hInstNTDll, "RtlAllocateAndInitializeSid");
211 if(RtlAllocateAndInitializeSid == NULL) {
212 DebugInt3();
213 }
214 }
215 SID_IDENTIFIER_AUTHORITY sidIdAuth = {0};
216 winteb->o.odin.threadinfo.dwType = SECTYPE_PROCESS | SECTYPE_INITIALIZED;
217 RtlAllocateAndInitializeSid(&sidIdAuth, 1, 0, 0, 0, 0, 0, 0, 0, 0, &winteb->o.odin.threadinfo.SidUser.User.Sid);
218 winteb->o.odin.threadinfo.SidUser.User.Attributes = 0; //?????????
219
220 winteb->o.odin.threadinfo.pTokenGroups = (TOKEN_GROUPS*)malloc(sizeof(TOKEN_GROUPS));
221 winteb->o.odin.threadinfo.pTokenGroups->GroupCount = 1;
222 RtlAllocateAndInitializeSid(&sidIdAuth, 1, 0, 0, 0, 0, 0, 0, 0, 0, &winteb->o.odin.threadinfo.PrimaryGroup.PrimaryGroup);
223 winteb->o.odin.threadinfo.pTokenGroups->Groups[0].Sid = winteb->o.odin.threadinfo.PrimaryGroup.PrimaryGroup;
224 winteb->o.odin.threadinfo.pTokenGroups->Groups[0].Attributes = 0; //????
225// pPrivilegeSet = NULL;
226// pTokenPrivileges= NULL;
227// TokenOwner = {0};
228// DefaultDACL = {0};
229// TokenSource = {0};
230 winteb->o.odin.threadinfo.TokenType = TokenPrimary;
231
232 if(fMainThread)
233 {
234 //todo initialize PDB during process creation
235 //todo: initialize TLS array if required
236 //TLS in executable always TLS index 0?
237 ProcessTIBSel = tibsel;
238 ProcessPDB.exit_code = 0x103; /* STILL_ACTIVE */
239 ProcessPDB.threads = 1;
240 ProcessPDB.running_threads = 1;
241 ProcessPDB.ring0_threads = 1;
242 ProcessPDB.system_heap = GetProcessHeap();
243 ProcessPDB.parent = 0;
244 ProcessPDB.group = &ProcessPDB;
245 ProcessPDB.priority = 8; /* Normal */
246 ProcessPDB.heap = ProcessPDB.system_heap; /* will be changed later on */
247 ProcessPDB.next = NULL;
248 ProcessPDB.winver = 0xffff; /* to be determined */
249 ProcessPDB.server_pid = (void *)GetCurrentProcessId();
250 ProcessPDB.tls_bits[0] = 0; //all tls slots are free
251 ProcessPDB.tls_bits[1] = 0;
252
253 GetSystemTime(&ProcessPDB.creationTime) ;
254
255 /* Initialize the critical section */
256 InitializeCriticalSection( &ProcessPDB.crit_section );
257 }
258 dprintf(("InitializeTIB setup TEB with selector %x", tibsel));
259 dprintf(("InitializeTIB: FS(%x):[0] = %x", GetFS(), QueryExceptionChain()));
260 return winteb;
261}
262//******************************************************************************
263//******************************************************************************
264ULONG WIN32API GetProcessTIBSel()
265{
266 if(fExitProcess) {
267 return 0;
268 }
269 return ProcessTIBSel;
270}
271//******************************************************************************
272// Destroy the TIB selector and memory for the current thread
273//******************************************************************************
274void WIN32API DestroyTIB()
275{
276 SHORT orgtibsel;
277 TEB *winteb;
278
279 dprintf(("DestroyTIB: FS = %x", GetFS()));
280 dprintf(("DestroyTIB: FS:[0] = %x", QueryExceptionChain()));
281
282 winteb = (TEB *)*TIBFlatPtr;
283 if(winteb) {
284 orgtibsel = winteb->o.odin.OrgTIBSel;
285
286 dprintf(("DestroyTIB: OSLibFreeSel %x", winteb->teb_sel));
287
288 threadListMutex.enter();
289 TEB *curteb = threadList;
290 if(curteb == winteb) {
291 threadList = winteb->o.odin.next;
292 }
293 else {
294 while(curteb->o.odin.next != winteb) {
295 curteb = curteb->o.odin.next;
296 if(curteb == NULL) {
297 dprintf(("DestroyTIB: couldn't find teb %x", winteb));
298 DebugInt3();
299 break;
300 }
301 }
302 if(curteb) {
303 curteb->o.odin.next = winteb->o.odin.next;
304 }
305 }
306 threadListMutex.leave();
307
308 //Restore our original FS selector
309 SetFS(orgtibsel);
310
311 //And free our own
312 OSLibFreeSel(winteb->teb_sel);
313
314 *TIBFlatPtr = 0;
315 }
316 else dprintf(("Already destroyed TIB"));
317
318 dprintf(("DestroyTIB: FS(%x):[0] = %x", GetFS(), QueryExceptionChain()));
319 return;
320}
321/******************************************************************************/
322/******************************************************************************/
323void SetPDBInstance(HINSTANCE hInstance)
324{
325 ProcessPDB.hInstance = hInstance;
326}
327/******************************************************************************/
328/******************************************************************************/
329void WIN32API RestoreOS2TIB()
330{
331 SHORT orgtibsel;
332 TEB *winteb;
333
334 //If we're running an Odin32 OS/2 application (not converted!), then we
335 //we don't switch FS selectors
336 if(fIsOS2Image) {
337 return;
338 }
339
340 winteb = (TEB *)*TIBFlatPtr;
341 if(winteb) {
342 orgtibsel = winteb->o.odin.OrgTIBSel;
343
344 //Restore our original FS selector
345 SetFS(orgtibsel);
346 }
347}
348/******************************************************************************/
349/******************************************************************************/
350USHORT WIN32API SetWin32TIB()
351{
352 SHORT win32tibsel;
353 TEB *winteb;
354
355 //If we're running an Odin32 OS/2 application (not converted!), then we
356 //we don't switch FS selectors
357 if(fIsOS2Image) {
358 return GetFS();
359 }
360
361 winteb = (TEB *)*TIBFlatPtr;
362 if(winteb) {
363 win32tibsel = winteb->teb_sel;
364
365 //Restore our win32 FS selector
366 return SetReturnFS(win32tibsel);
367 }
368 else {
369 //we didn't create this thread, so allocate a selector now
370 //NOTE: Possible memory leak (i.e. DART threads in WINMM)
371 winteb = InitializeTIB();
372 if(winteb == NULL) {
373 DebugInt3();
374 return GetFS();
375 }
376 win32tibsel = winteb->teb_sel;
377
378 //Restore our win32 FS selector
379 return SetReturnFS(win32tibsel);
380 }
381 // nested calls are OK, OS2ToWinCallback for instance
382 //else DebugInt3();
383
384 return GetFS();
385}
386//******************************************************************************
387//******************************************************************************
388VOID WIN32API ExitProcess(DWORD exitcode)
389{
390 dprintf(("KERNEL32: ExitProcess %d\n", exitcode));
391 dprintf(("KERNEL32: ExitProcess FS = %x\n", GetFS()));
392
393 fExitProcess = TRUE;
394
395 SetOS2ExceptionChain(-1);
396
397 if(WinExe) {
398 delete(WinExe);
399 WinExe = NULL;
400 }
401
402 //Note: Needs to be done after deleting WinExe (destruction of exe + dll objects)
403 //Flush and delete all open memory mapped files
404 Win32MemMap::deleteAll();
405
406 //SvL: We must make sure no threads are still suspended (with SuspendThread)
407 // OS/2 seems to be unable to terminate the process otherwise (exitlist hang)
408 TEB *teb = threadList;
409 threadListMutex.enter();
410 while(teb) {
411 ResumeThread(teb->o.odin.hThread);
412 teb = teb->o.odin.next;
413 }
414 threadListMutex.leave();
415
416 //Restore original OS/2 TIB selector
417 DestroyTIB();
418 SetExceptionChain((ULONG)-1);
419
420 //avoid crashes since win32 & OS/2 exception handler aren't identical
421 //(terminate process generates two exceptions)
422 /* @@@PH 1998/02/12 Added Console Support */
423 if (iConsoleIsActive())
424 iConsoleWaitClose();
425
426 O32_ExitProcess(exitcode);
427}
428//******************************************************************************
429//******************************************************************************
430BOOL WIN32API FreeLibrary(HINSTANCE hinstance)
431{
432 Win32DllBase *winmod;
433 BOOL rc;
434
435 SetLastError(ERROR_SUCCESS);
436 //SvL: Ignore FreeLibary for executable
437 if(WinExe && hinstance == WinExe->getInstanceHandle()) {
438 return TRUE;
439 }
440
441 winmod = Win32DllBase::findModule(hinstance);
442 if(winmod) {
443 dprintf(("FreeLibrary %s", winmod->getName()));
444 //Only free it when the nrDynamicLibRef != 0
445 //This prevent problems after ExitProcess:
446 //i.e. dll A is referenced by our exe and loaded with LoadLibrary by dll B
447 // During ExitProcess it's unloaded once (before dll B), dll B calls
448 // FreeLibrary, but our exe also has a reference -> unloaded too many times
449 if(winmod->isDynamicLib()) {
450 winmod->decDynamicLib();
451 winmod->Release();
452 }
453 else {
454 dprintf(("Skipping dynamic unload as nrDynamicLibRef == 0"));
455 }
456 return(TRUE);
457 }
458 dprintf(("WARNING: KERNEL32: FreeLibrary %s %x NOT FOUND!", OSLibGetDllName(hinstance), hinstance));
459 return(TRUE);
460}
461/*****************************************************************************
462 * Name : VOID WIN32API FreeLibraryAndExitThread
463 * Purpose : The FreeLibraryAndExitThread function decrements the reference
464 * count of a loaded dynamic-link library (DLL) by one, and then
465 * calls ExitThread to terminate the calling thread.
466 * The function does not return.
467 *
468 * The FreeLibraryAndExitThread function gives threads that are
469 * created and executed within a dynamic-link library an opportunity
470 * to safely unload the DLL and terminate themselves.
471 * Parameters:
472 * Variables :
473 * Result :
474 * Remark :
475 *****************************************************************************/
476VOID WIN32API FreeLibraryAndExitThread( HMODULE hLibModule, DWORD dwExitCode)
477{
478
479 dprintf(("KERNEL32: FreeLibraryAndExitThread(%08x,%08x)", hLibModule, dwExitCode));
480 FreeLibrary(hLibModule);
481 ExitThread(dwExitCode);
482}
483/******************************************************************************/
484/******************************************************************************/
485/**
486 * LoadLibraryA can be used to map a DLL module into the calling process's
487 * addressspace. It returns a handle that can be used with GetProcAddress to
488 * get addresses of exported entry points (functions and variables).
489 *
490 * LoadLibraryA can also be used to map executable (.exe) modules into the
491 * address to access resources in the module. However, LoadLibrary can't be
492 * used to run an executable (.exe) module.
493 *
494 * @returns Handle to the library which was loaded.
495 * @param lpszLibFile Pointer to zero ASCII string giving the name of the
496 * executable image (either a Dll or an Exe) which is to be
497 * loaded.
498 *
499 * If no extention is specified the default .DLL extention is
500 * appended to the name. End the filename with an '.' if the
501 * file does not have an extention (and don't want the .DLL
502 * appended).
503 *
504 * If no path is specified, this API will use the Odin32
505 * standard search strategy to find the file. This strategy
506 * is described in the method Win32ImageBase::findDLL.
507 *
508 * This API likes to have backslashes (\), but will probably
509 * accept forward slashes too. Win32 SDK docs says that it
510 * should not contain forward slashes.
511 *
512 * Win32 SDK docs adds:
513 * "The name specified is the file name of the module and
514 * is not related to the name stored in the library module
515 * itself, as specified by the LIBRARY keyword in the
516 * module-definition (.def) file."
517 *
518 * @sketch Call LoadLibraryExA with flags set to 0.
519 * @status Odin32 Completely Implemented.
520 * @author Sander van Leeuwen (sandervl@xs4all.nl)
521 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
522 * @remark Forwards to LoadLibraryExA.
523 */
524HINSTANCE WIN32API LoadLibraryA(LPCTSTR lpszLibFile)
525{
526 HINSTANCE hDll;
527
528 dprintf(("KERNEL32: LoadLibraryA(%s) --> LoadLibraryExA(lpszLibFile, 0, 0)",
529 lpszLibFile));
530 hDll = LoadLibraryExA(lpszLibFile, 0, 0);
531 dprintf(("KERNEL32: LoadLibraryA(%s) returns 0x%x",
532 lpszLibFile, hDll));
533 return hDll;
534}
535
536
537/**
538 * LoadLibraryW can be used to map a DLL module into the calling process's
539 * addressspace. It returns a handle that can be used with GetProcAddress to
540 * get addresses of exported entry points (functions and variables).
541 *
542 * LoadLibraryW can also be used to map executable (.exe) modules into the
543 * address to access resources in the module. However, LoadLibrary can't be
544 * used to run an executable (.exe) module.
545 *
546 * @returns Handle to the library which was loaded.
547 * @param lpszLibFile Pointer to Unicode string giving the name of
548 * the executable image (either a Dll or an Exe) which is to
549 * be loaded.
550 *
551 * If no extention is specified the default .DLL extention is
552 * appended to the name. End the filename with an '.' if the
553 * file does not have an extention (and don't want the .DLL
554 * appended).
555 *
556 * If no path is specified, this API will use the Odin32
557 * standard search strategy to find the file. This strategy
558 * is described in the method Win32ImageBase::findDLL.
559 *
560 * This API likes to have backslashes (\), but will probably
561 * accept forward slashes too. Win32 SDK docs says that it
562 * should not contain forward slashes.
563 *
564 * Win32 SDK docs adds:
565 * "The name specified is the file name of the module and
566 * is not related to the name stored in the library module
567 * itself, as specified by the LIBRARY keyword in the
568 * module-definition (.def) file."
569 *
570 * @sketch Convert Unicode name to ascii.
571 * Call LoadLibraryExA with flags set to 0.
572 * free ascii string.
573 * @status Odin32 Completely Implemented.
574 * @author Sander van Leeuwen (sandervl@xs4all.nl)
575 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
576 * @remark Forwards to LoadLibraryExA.
577 */
578HINSTANCE WIN32API LoadLibraryW(LPCWSTR lpszLibFile)
579{
580 char * pszAsciiLibFile;
581 HINSTANCE hDll;
582
583 pszAsciiLibFile = UnicodeToAsciiString(lpszLibFile);
584 dprintf(("KERNEL32: LoadLibraryW(%s) --> LoadLibraryExA(lpszLibFile, 0, 0)",
585 pszAsciiLibFile));
586 hDll = LoadLibraryExA(pszAsciiLibFile, NULL, 0);
587 dprintf(("KERNEL32: LoadLibraryW(%s) returns 0x%x",
588 pszAsciiLibFile, hDll));
589 FreeAsciiString(pszAsciiLibFile);
590
591 return hDll;
592}
593
594
595/**
596 * LoadLibraryExA can be used to map a DLL module into the calling process's
597 * addressspace. It returns a handle that can be used with GetProcAddress to
598 * get addresses of exported entry points (functions and variables).
599 *
600 * LoadLibraryExA can also be used to map executable (.exe) modules into the
601 * address to access resources in the module. However, LoadLibrary can't be
602 * used to run an executable (.exe) module.
603 *
604 * @returns Handle to the library which was loaded.
605 * @param lpszLibFile Pointer to Unicode string giving the name of
606 * the executable image (either a Dll or an Exe) which is to
607 * be loaded.
608 *
609 * If no extention is specified the default .DLL extention is
610 * appended to the name. End the filename with an '.' if the
611 * file does not have an extention (and don't want the .DLL
612 * appended).
613 *
614 * If no path is specified, this API will use the Odin32
615 * standard search strategy to find the file. This strategy
616 * is described in the method Win32ImageBase::findDLL.
617 * This may be alterned by the LOAD_WITH_ALTERED_SEARCH_PATH
618 * flag, see below.
619 *
620 * This API likes to have backslashes (\), but will probably
621 * accept forward slashes too. Win32 SDK docs says that it
622 * should not contain forward slashes.
623 *
624 * Win32 SDK docs adds:
625 * "The name specified is the file name of the module and
626 * is not related to the name stored in the library module
627 * itself, as specified by the LIBRARY keyword in the
628 * module-definition (.def) file."
629 *
630 * @param hFile Reserved. Must be 0.
631 *
632 * @param dwFlags Flags which specifies the taken when loading the module.
633 * The value 0 makes it identical to LoadLibraryA/W.
634 *
635 * Flags:
636 *
637 * DONT_RESOLVE_DLL_REFERENCES
638 * (WinNT/2K feature): Don't load imported modules and
639 * hence don't resolve imported symbols.
640 * DllMain isn't called either. (Which is obvious since
641 * it may use one of the importe symbols.)
642 *
643 * On the other hand, if this flag is NOT set, the system
644 * load imported modules, resolves imported symbols, calls
645 * DllMain for process and thread init and term (if wished
646 * by the module).
647 *
648 *
649 * LOAD_LIBRARY_AS_DATAFILE
650 * If this flag is set, the module is mapped into the
651 * address space but is not prepared for execution. Though
652 * it's preparted for resource API. Hence, you'll use this
653 * flag when you want to load a DLL for extracting
654 * messages or resources from it.
655 *
656 * The resulting handle can be used with any Odin32 API
657 * which operates on resources.
658 * (WinNt/2k supports all resource APIs while Win9x don't
659 * support the specialized resource APIs: LoadBitmap,
660 * LoadCursor, LoadIcon, LoadImage, LoadMenu.)
661 *
662 *
663 * LOAD_WITH_ALTERED_SEARCH_PATH
664 * If this flag is set and lpszLibFile specifies a path
665 * we'll use an alternative file search strategy to find
666 * imported modules. This stratgy is simply to use the
667 * path of the module being loaded instead of the path
668 * of the executable module as the first location
669 * to search for imported modules.
670 *
671 * If this flag is clear, the standard Odin32 standard
672 * search strategy. See Win32ImageBase::findDll for
673 * further information.
674 *
675 * not implemented yet.
676 *
677 * @status Open32 Partially Implemented.
678 * @author Sander van Leeuwen (sandervl@xs4all.nl)
679 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
680 * @remark Forwards to LoadLibraryExA.
681 */
682HINSTANCE WIN32API LoadLibraryExA(LPCTSTR lpszLibFile, HANDLE hFile, DWORD dwFlags)
683{
684 HINSTANCE hDll;
685 Win32DllBase * pModule;
686 char szModname[CCHMAXPATH];
687 BOOL fPath; /* Flags which is set if the */
688 /* lpszLibFile contains a path. */
689 ULONG fPE; /* isPEImage return value. */
690 DWORD Characteristics; //file header's Characteristics
691 char *dot;
692
693 /** @sketch
694 * Some parameter validations is probably useful.
695 */
696 if (!VALID_PSZ(lpszLibFile))
697 {
698 dprintf(("KERNEL32: LoadLibraryExA(0x%x, 0x%x, 0x%x): invalid pointer lpszLibFile = 0x%x\n",
699 lpszLibFile, hFile, dwFlags, lpszLibFile));
700 SetLastError(ERROR_INVALID_PARAMETER); //or maybe ERROR_ACCESS_DENIED is more appropriate?
701 return NULL;
702 }
703 if (!VALID_PSZMAXSIZE(lpszLibFile, CCHMAXPATH))
704 {
705 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): lpszLibFile string too long, %d\n",
706 lpszLibFile, hFile, dwFlags, strlen(lpszLibFile)));
707 SetLastError(ERROR_INVALID_PARAMETER);
708 return NULL;
709 }
710 if ((dwFlags & ~(DONT_RESOLVE_DLL_REFERENCES | LOAD_WITH_ALTERED_SEARCH_PATH | LOAD_LIBRARY_AS_DATAFILE)) != 0)
711 {
712 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): dwFlags have invalid or unsupported flags\n",
713 lpszLibFile, hFile, dwFlags));
714 SetLastError(ERROR_INVALID_PARAMETER);
715 return NULL;
716 }
717
718
719 /** @sketch
720 * First we'll see if the module is allready loaded - either as the EXE or as DLL.
721 * IF Executable present AND libfile matches the modname of the executable THEN
722 * RETURN instance handle of executable.
723 * Endif
724 * IF allready loaded THEN
725 * IF it's a LX dll which isn't loaded and we're using the PeLoader THEN
726 * Set Load library.
727 * Endif
728 * Inc dynamic reference count.
729 * Inc reference count.
730 * RETURN instance handle.
731 * Endif
732 */
733 strcpy(szModname, lpszLibFile);
734 strupr(szModname);
735 dot = strchr(szModname, '.');
736 if(dot == NULL) {
737 //if there's no extension or trainling dot, we
738 //assume it's a dll (see Win32 SDK docs)
739 strcat(szModname, DLL_EXTENSION);
740 }
741 else {
742 if(dot[1] == 0) {
743 //a trailing dot means the module has no extension (SDK docs)
744 *dot = 0;
745 }
746 }
747 if (WinExe != NULL && WinExe->matchModName(szModname))
748 return WinExe->getInstanceHandle();
749
750 pModule = Win32DllBase::findModule((LPSTR)szModname);
751 if (pModule)
752 {
753 pModule->incDynamicLib();
754 pModule->AddRef();
755 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): returns 0x%x. Dll found %s",
756 szModname, hFile, dwFlags, pModule->getInstanceHandle(), pModule->getFullPath()));
757 return pModule->getInstanceHandle();
758 }
759
760
761 /** @sketch
762 * Test if lpszLibFile has a path or not.
763 * Copy the lpszLibFile to szModname, rename the dll and uppercase the name.
764 * IF it hasn't a path THEN
765 * Issue a findDll to find the dll/executable to be loaded.
766 * IF the Dll isn't found THEN
767 * Set last error and RETURN.
768 * Endif.
769 * Endif
770 */
771 fPath = strchr(szModname, '\\') || strchr(szModname, '/');
772 Win32DllBase::renameDll(szModname);
773
774 if (!fPath)
775 {
776 char szModName2[CCHMAXPATH];
777 strcpy(szModName2, szModname);
778 if (!Win32ImageBase::findDll(szModName2, szModname, sizeof(szModname)))
779 {
780 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): module wasn't found. returns NULL",
781 lpszLibFile, hFile, dwFlags));
782 SetLastError(ERROR_FILE_NOT_FOUND);
783 return NULL;
784 }
785 }
786
787 //test if dll is in PE or LX format
788 fPE = Win32ImageBase::isPEImage(szModname, &Characteristics, NULL);
789
790 /** @sketch
791 * IF (!fPeLoader || fPE == failure) THEN
792 * Try load the executable using LoadLibrary
793 * IF successfully loaded THEN
794 * IF LX dll and is using the PE Loader THEN
795 * Set Load library.
796 * Inc reference count.
797 * Endif
798 * Inc dynamic reference count.
799 * RETURN successfully.
800 * Endif
801 * Endif
802 */
803 //only call OS/2 if LX binary or win32k process
804 if (!fPeLoader || fPE != ERROR_SUCCESS)
805 {
806 hDll = OSLibDosLoadModule(szModname);
807 if (hDll)
808 {
809 /* OS/2 dll, system dll, converted dll or win32k took care of it. */
810 pModule = Win32DllBase::findModuleByOS2Handle(hDll);
811 if (pModule)
812 {
813 if (pModule->isLxDll())
814 {
815 ((Win32LxDll *)pModule)->setDllHandleOS2(hDll);
816 if (fPeLoader && pModule->AddRef() == -1)
817 { //-1 -> load failed (attachProcess)
818 delete pModule;
819 SetLastError(ERROR_INVALID_EXE_SIGNATURE);
820 dprintf(("Dll %s refused to be loaded; aborting", szModname));
821 return 0;
822 }
823
824 }
825 pModule->incDynamicLib();
826 }
827 else if (fExeStarted) {
828 OSLibDosFreeModule(hDll);
829 SetLastError(ERROR_INVALID_EXE_SIGNATURE);
830 dprintf(("Dll %s is not an Odin dll; unload & return failure", szModname));
831 return 0;
832 }
833 else
834 return hDll; //happens when LoadLibrary is called in kernel32's initterm (nor harmful)
835
836 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): returns 0x%x. Loaded %s using DosLoadModule.",
837 lpszLibFile, hFile, dwFlags, hDll, szModname));
838 return pModule->getInstanceHandle();
839 }
840 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): DosLoadModule (%s) failed. LastError=%d",
841 lpszLibFile, hFile, dwFlags, szModname, GetLastError()));
842 }
843 else
844 hDll = NULL;
845
846
847 /** @sketch
848 * If PE image THEN
849 * IF LOAD_LIBRARY_AS_DATAFILE or Executable THEN
850 *
851 *
852 * Try load the file using the Win32PeLdrDll class.
853 * <sketch continued further down>
854 * Else
855 * Set last error.
856 * (hDll is NULL)
857 * Endif
858 * return hDll.
859 */
860 if(fPE == ERROR_SUCCESS)
861 {
862 Win32PeLdrDll *peldrDll;
863
864 //SvL: If executable -> load as data file (only resources)
865 if(!(Characteristics & IMAGE_FILE_DLL))
866 {
867 dwFlags |= (LOAD_LIBRARY_AS_DATAFILE | DONT_RESOLVE_DLL_REFERENCES);
868 }
869
870 peldrDll = new Win32PeLdrDll(szModname);
871 if (peldrDll == NULL)
872 {
873 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Failed to created instance of Win32PeLdrDll. returns NULL.",
874 lpszLibFile, hFile, dwFlags));
875 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
876 return NULL;
877 }
878
879 /** @sketch
880 * Process dwFlags
881 */
882 if (dwFlags & LOAD_LIBRARY_AS_DATAFILE)
883 {
884 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): LOAD_LIBRARY_AS_DATAFILE",
885 lpszLibFile, hFile, dwFlags));
886 peldrDll->setLoadAsDataFile();
887 peldrDll->disableLibraryCalls();
888 }
889 if (dwFlags & DONT_RESOLVE_DLL_REFERENCES)
890 {
891 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): DONT_RESOLVE_DLL_REFERENCES",
892 lpszLibFile, hFile, dwFlags));
893 peldrDll->disableLibraryCalls();
894 peldrDll->disableImportHandling();
895 }
896 if (dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH)
897 {
898 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Warning dwFlags LOAD_WITH_ALTERED_SEARCH_PATH is not implemented.",
899 lpszLibFile, hFile, dwFlags));
900 //peldrDll->setLoadWithAlteredSearchPath();
901 }
902
903 /** @sketch
904 * Initiate the peldr DLL.
905 * IF successful init THEN
906 * Inc dynamic ref count.
907 * Inc ref count.
908 * Attach to process
909 * IF successful THEN
910 * hDLL <- instance handle.
911 * ELSE
912 * set last error
913 * delete Win32PeLdrDll instance.
914 * Endif
915 * ELSE
916 * set last error
917 * delete Win32PeLdrDll instance.
918 * Endif.
919 */
920 if (peldrDll->init(0))
921 {
922 peldrDll->AddRef();
923 if (peldrDll->attachProcess())
924 {
925 hDll = peldrDll->getInstanceHandle();
926 //Must be called *after* attachprocess, since attachprocess may also
927 //trigger LoadLibrary calls
928 //Those dlls must not be put in front of this dll in the dynamic
929 //dll list; or else the unload order is wrong:
930 //i.e. RPAP3260 loads PNRS3260 in DLL_PROCESS_ATTACH
931 // this means that in ExitProcess, PNRS3260 needs to be removed
932 // first since RPAP3260 depends on it
933 peldrDll->incDynamicLib();
934 }
935 else
936 {
937 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): attachProcess call to Win32PeLdrDll instance failed. returns NULL.",
938 lpszLibFile, hFile, dwFlags));
939 SetLastError(ERROR_DLL_INIT_FAILED);
940 delete peldrDll;
941 return NULL;
942 }
943 }
944 else
945 {
946 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Failed to init Win32PeLdrDll instance. error=%d returns NULL.",
947 lpszLibFile, hFile, dwFlags, peldrDll->getError()));
948 SetLastError(ERROR_INVALID_EXE_SIGNATURE);
949 delete peldrDll;
950 return NULL;
951 }
952 }
953 else
954 {
955 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x) library wasn't found (%s) or isn't loadable; err %x",
956 lpszLibFile, hFile, dwFlags, szModname, fPE));
957 SetLastError(fPE);
958 return NULL;
959 }
960
961 return hDll;
962}
963
964
965/**
966 * LoadLibraryExW can be used to map a DLL module into the calling process's
967 * addressspace. It returns a handle that can be used with GetProcAddress to
968 * get addresses of exported entry points (functions and variables).
969 *
970 * LoadLibraryExW can also be used to map executable (.exe) modules into the
971 * address to access resources in the module. However, LoadLibrary can't be
972 * used to run an executable (.exe) module.
973 *
974 * @returns Handle to the library which was loaded.
975 * @param lpszLibFile Pointer to Unicode string giving the name of
976 * the executable image (either a Dll or an Exe) which is to
977 * be loaded.
978 *
979 * If no extention is specified the default .DLL extention is
980 * appended to the name. End the filename with an '.' if the
981 * file does not have an extention (and don't want the .DLL
982 * appended).
983 *
984 * If no path is specified, this API will use the Odin32
985 * standard search strategy to find the file. This strategy
986 * is described in the method Win32ImageBase::findDLL.
987 * This may be alterned by the LOAD_WITH_ALTERED_SEARCH_PATH
988 * flag, see below.
989 *
990 * This API likes to have backslashes (\), but will probably
991 * accept forward slashes too. Win32 SDK docs says that it
992 * should not contain forward slashes.
993 *
994 * Win32 SDK docs adds:
995 * "The name specified is the file name of the module and
996 * is not related to the name stored in the library module
997 * itself, as specified by the LIBRARY keyword in the
998 * module-definition (.def) file."
999 *
1000 * @param hFile Reserved. Must be 0.
1001 *
1002 * @param dwFlags Flags which specifies the taken when loading the module.
1003 * The value 0 makes it identical to LoadLibraryA/W.
1004 *
1005 * Flags:
1006 *
1007 * DONT_RESOLVE_DLL_REFERENCES
1008 * (WinNT/2K feature): Don't load imported modules and
1009 * hence don't resolve imported symbols.
1010 * DllMain isn't called either. (Which is obvious since
1011 * it may use one of the importe symbols.)
1012 *
1013 * On the other hand, if this flag is NOT set, the system
1014 * load imported modules, resolves imported symbols, calls
1015 * DllMain for process and thread init and term (if wished
1016 * by the module).
1017 *
1018 * LOAD_LIBRARY_AS_DATAFILE
1019 * If this flag is set, the module is mapped into the
1020 * address space but is not prepared for execution. Though
1021 * it's preparted for resource API. Hence, you'll use this
1022 * flag when you want to load a DLL for extracting
1023 * messages or resources from it.
1024 *
1025 * The resulting handle can be used with any Odin32 API
1026 * which operates on resources.
1027 * (WinNt/2k supports all resource APIs while Win9x don't
1028 * support the specialized resource APIs: LoadBitmap,
1029 * LoadCursor, LoadIcon, LoadImage, LoadMenu.)
1030 *
1031 * LOAD_WITH_ALTERED_SEARCH_PATH
1032 * If this flag is set and lpszLibFile specifies a path
1033 * we'll use an alternative file search strategy to find
1034 * imported modules. This stratgy is simply to use the
1035 * path of the module being loaded instead of the path
1036 * of the executable module as the first location
1037 * to search for imported modules.
1038 *
1039 * If this flag is clear, the standard Odin32 standard
1040 * search strategy. See Win32ImageBase::findDll for
1041 * further information.
1042 *
1043 * @sketch Convert Unicode name to ascii.
1044 * Call LoadLibraryExA.
1045 * Free ascii string.
1046 * return handle from LoadLibraryExA.
1047 * @status Open32 Partially Implemented.
1048 * @author Sander van Leeuwen (sandervl@xs4all.nl)
1049 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1050 * @remark Forwards to LoadLibraryExA.
1051 */
1052HINSTANCE WIN32API LoadLibraryExW(LPCWSTR lpszLibFile, HANDLE hFile, DWORD dwFlags)
1053{
1054 char * pszAsciiLibFile;
1055 HINSTANCE hDll;
1056
1057 pszAsciiLibFile = UnicodeToAsciiString(lpszLibFile);
1058 dprintf(("KERNEL32: LoadLibraryExW(%s, 0x%x, 0x%x) --> LoadLibraryExA",
1059 pszAsciiLibFile, hFile, dwFlags));
1060 hDll = LoadLibraryExA(pszAsciiLibFile, hFile, dwFlags);
1061 dprintf(("KERNEL32: LoadLibraryExW(%s, 0x%x, 0x%x) returns 0x%x",
1062 pszAsciiLibFile, hFile, dwFlags, hDll));
1063 FreeAsciiString(pszAsciiLibFile);
1064
1065 return hDll;
1066}
1067//******************************************************************************
1068//******************************************************************************
1069HINSTANCE16 WIN32API LoadLibrary16(LPCTSTR lpszLibFile)
1070{
1071 dprintf(("ERROR: LoadLibrary16 %s, not implemented", lpszLibFile));
1072 return 0;
1073}
1074//******************************************************************************
1075//******************************************************************************
1076VOID WIN32API FreeLibrary16(HINSTANCE16 hinstance)
1077{
1078 dprintf(("ERROR: FreeLibrary16 %x, not implemented", hinstance));
1079}
1080//******************************************************************************
1081//******************************************************************************
1082FARPROC WIN32API GetProcAddress16(HMODULE hModule, LPCSTR lpszProc)
1083{
1084 dprintf(("ERROR: GetProcAddress16 %x %x, not implemented", hModule, lpszProc));
1085 return 0;
1086}
1087
1088
1089/**
1090 * Internal function which gets the commandline (string) used to start the current process.
1091 * @returns OS/2 / Windows return code
1092 * On successful return (NO_ERROR) the global variables
1093 * pszCmdLineA and pszCmdLineW are set.
1094 *
1095 * @param pszPeExe Pass in the name of the PE exe of this process. We'll
1096 * us this as exename and skip the first argument (ie. argv[1]).
1097 * If NULL we'll use the commandline from OS/2 as it is.
1098 * @status Completely implemented and tested.
1099 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1100 */
1101ULONG InitCommandLine(const char *pszPeExe)
1102{
1103 PCHAR pib_pchcmd; /* PIB pointer to commandline. */
1104 CHAR szFilename[CCHMAXPATH]; /* Filename buffer used to get the exe filename in. */
1105 ULONG cch; /* Commandline string length. (including terminator) */
1106 PSZ psz; /* Temporary string pointer. */
1107 PSZ psz2; /* Temporary string pointer. */
1108 APIRET rc; /* OS/2 return code. */
1109 BOOL fQuotes; /* Flag used to remember if the exe filename should be in quotes. */
1110
1111 /** @sketch
1112 * Get commandline from the PIB.
1113 */
1114 pib_pchcmd = (PCHAR)OSLibGetPIB(PIB_PCHCMD);
1115
1116 /** @sketch
1117 * Two methods of making the commandline:
1118 * (1) The first argument is skipped and the second is used as exe filname.
1119 * This applies to PE.EXE launched processes only.
1120 * (2) No skipping. First argument is the exe filename.
1121 * This applies to all but PE.EXE launched processes.
1122 *
1123 * Note: We could do some code size optimization here. Much of the code for
1124 * the two methods are nearly identical.
1125 *
1126 */
1127 if(pszPeExe)
1128 {
1129 /** @sketch
1130 * Allocate memory for the commandline.
1131 * Build commandline:
1132 * Copy exe filename.
1133 * Add arguments.
1134 */
1135 cch = strlen(pszPeExe)+1;
1136 pszCmdLineA = psz = (PSZ)malloc(cch);
1137 if (psz == NULL)
1138 {
1139 dprintf(("KERNEL32: InitCommandLine(%p): malloc(%d) failed\n", pszPeExe, cch));
1140 return ERROR_NOT_ENOUGH_MEMORY;
1141 }
1142 strcpy((char *)pszCmdLineA, pszPeExe);
1143
1144 rc = NO_ERROR;
1145 }
1146 else
1147 {
1148 /** @sketch Method (2):
1149 * First we'll have to determin the size of the commandline.
1150 *
1151 * As we don't assume that OS/2 allways puts a fully qualified EXE name
1152 * as the first string, we'll check if it's empty - and get the modulename
1153 * in that case - and allways get the fully qualified filename.
1154 */
1155 if (pib_pchcmd == NULL || pib_pchcmd[0] == '\0')
1156 {
1157 rc = OSLibDosQueryModuleName(OSLibGetPIB(PIB_HMTE), sizeof(szFilename), szFilename);
1158 if (rc != NO_ERROR)
1159 {
1160 dprintf(("KERNEL32: InitCommandLine(%p): OSLibQueryModuleName(0x%x,...) failed with rc=%d\n",
1161 pszPeExe, OSLibGetPIB(PIB_HMTE), rc));
1162 return rc;
1163 }
1164 }
1165 else
1166 {
1167 rc = OSLibDosQueryPathInfo(pib_pchcmd, FIL_QUERYFULLNAME, szFilename, sizeof(szFilename));
1168 if (rc != NO_ERROR)
1169 {
1170 dprintf(("KERNEL32: InitCommandLine(%p): (info) OSLibDosQueryPathInfo failed with rc=%d\n", pszPeExe, rc));
1171 strcpy(szFilename, pib_pchcmd);
1172 rc = NO_ERROR;
1173 }
1174 }
1175
1176 /** @sketch
1177 * We're still measuring the size of the commandline:
1178 * Check if we have to quote the exe filename.
1179 * Determin the length of the executable name including quotes and '\0'-terminator.
1180 * Count the length of the arguments. (We here count's all argument strings.)
1181 */
1182 fQuotes = strchr(szFilename, ' ') != NULL;
1183 cch = strlen(szFilename) + fQuotes*2 + 1;
1184 if (pib_pchcmd != NULL)
1185 {
1186 psz2 = pib_pchcmd + strlen(pib_pchcmd) + 1;
1187 while (*psz2 != '\0')
1188 {
1189 register int cchTmp = strlen(psz2) + 1; /* + 1 is for terminator (psz2) and space (cch). */
1190 psz2 += cchTmp;
1191 cch += cchTmp;
1192 }
1193 }
1194
1195 /** @sketch
1196 * Allocate memory for the commandline.
1197 * Build commandline:
1198 * Copy exe filename.
1199 * Add arguments.
1200 */
1201 pszCmdLineA = psz = (PSZ)malloc(cch);
1202 if (psz == NULL)
1203 {
1204 dprintf(("KERNEL32: InitCommandLine(%p): malloc(%d) failed\n", pszPeExe, cch));
1205 return ERROR_NOT_ENOUGH_MEMORY;
1206 }
1207
1208 if (fQuotes)
1209 *psz++ = '"';
1210 strcpy(psz, szFilename);
1211 psz += strlen(psz);
1212 if (fQuotes)
1213 {
1214 *psz++ = '"';
1215 *psz = '\0';
1216 }
1217
1218 if (pib_pchcmd != NULL)
1219 {
1220 psz2 = pib_pchcmd + strlen(pib_pchcmd) + 1;
1221 while (*psz2 != '\0')
1222 {
1223 register int cchTmp = strlen(psz2) + 1; /* + 1 is for terminator (psz). */
1224 *psz++ = ' '; /* add space */
1225 memcpy(psz, psz2, cchTmp);
1226 psz2 += cchTmp;
1227 psz += cchTmp - 1;
1228 }
1229 }
1230 }
1231
1232 /** @sketch
1233 * If successfully build ASCII commandline then convert it to UniCode.
1234 */
1235 if (rc == NO_ERROR)
1236 {
1237 pszCmdLineW = (WCHAR*)malloc(cch * 2);
1238 if (pszCmdLineW != NULL)
1239 AsciiToUnicode(pszCmdLineA, (WCHAR*)pszCmdLineW);
1240 else
1241 {
1242 dprintf(("KERNEL32: InitCommandLine(%p): malloc(%d) failed (2)\n", pszPeExe, cch));
1243 rc = ERROR_NOT_ENOUGH_MEMORY;
1244 }
1245 }
1246
1247 return rc;
1248}
1249
1250/**
1251 * Gets the command line of the current process.
1252 * @returns On success:
1253 * Command line of the current process. One single string.
1254 * The first part of the command line string is the executable filename
1255 * of the current process. It might be in quotes if it contains spaces.
1256 * The rest of the string is arguments.
1257 *
1258 * On error:
1259 * NULL. Last error set. (does Win32 set last error this?)
1260 * @sketch IF not inited THEN
1261 * Init commandline assuming !PE.EXE
1262 * IF init failes THEN set last error.
1263 * ENDIF
1264 * return ASCII/ANSI commandline.
1265 * @status Completely implemented and tested.
1266 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1267 * @remark The Ring-3 PeLdr is resposible for calling InitCommandLine before anyone
1268 * is able to call this function.
1269 */
1270LPCSTR WIN32API GetCommandLineA(VOID)
1271{
1272 /*
1273 * Check if the commandline is initiated.
1274 * If not we'll have to do it.
1275 * ASSUMES that if not inited this isn't a PE.EXE lauched process.
1276 */
1277 if (pszCmdLineA == NULL)
1278 {
1279 APIRET rc;
1280 rc = InitCommandLine(NULL);
1281 if (rc != NULL)
1282 SetLastError(rc);
1283 }
1284
1285 dprintf(("KERNEL32: GetCommandLineA: %s\n", pszCmdLineA));
1286 return pszCmdLineA;
1287}
1288
1289
1290/**
1291 * Gets the command line of the current process.
1292 * @returns On success:
1293 * Command line of the current process. One single string.
1294 * The first part of the command line string is the executable filename
1295 * of the current process. It might be in quotes if it contains spaces.
1296 * The rest of the string is arguments.
1297 *
1298 * On error:
1299 * NULL. Last error set. (does Win32 set last error this?)
1300 * @sketch IF not inited THEN
1301 * Init commandline assuming !PE.EXE
1302 * IF init failes THEN set last error.
1303 * ENDIF
1304 * return Unicode commandline.
1305 * @status Completely implemented and tested.
1306 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1307 * @remark The Ring-3 PeLdr is resposible for calling InitCommandLine before anyone
1308 * is able to call this function.
1309 */
1310LPCWSTR WIN32API GetCommandLineW(void)
1311{
1312 /*
1313 * Check if the commandline is initiated.
1314 * If not we'll have to do it.
1315 * ASSUMES that if not inited this isn't a PE.EXE lauched process.
1316 */
1317 if (pszCmdLineW == NULL)
1318 {
1319 APIRET rc;
1320 rc = InitCommandLine(NULL);
1321 if (rc != NULL)
1322 SetLastError(rc);
1323 }
1324
1325 dprintf(("KERNEL32: GetCommandLineW: %s\n", pszCmdLineA));
1326 return pszCmdLineW;
1327}
1328
1329
1330/**
1331 * GetModuleFileName gets the full path and file name for the specified module.
1332 * @returns Bytes written to the buffer (lpszPath). This count includes the
1333 * terminating '\0'.
1334 * On error 0 is returned. Last error is set.
1335 * @param hModule Handle to the module you like to get the file name to.
1336 * @param lpszPath Output buffer for full path and file name.
1337 * @param cchPath Size of the lpszPath buffer.
1338 * @sketch Validate lpszPath.
1339 * Find the module object using handle.
1340 * If found Then
1341 * Get full path from module object.
1342 * If found path Then
1343 * Copy path to buffer and set the number of bytes written.
1344 * Else
1345 * IPE!
1346 * Else
1347 * Call Open32 GetModuleFileName. (kernel32 initterm needs/needed this)
1348 * Log result.
1349 * Return number of bytes written to the buffer.
1350 *
1351 * @status Completely implemented, Open32.
1352 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1353 * Sander van Leeuwen (sandervl@xs4all.nl)
1354 * @remark - Do we still have to call Open32?
1355 * - Do we set ERROR_BUFFER_OVERFLOW when cch > cchPath?
1356 * - Does NT really set the last error?
1357 */
1358DWORD WIN32API GetModuleFileNameA(HMODULE hModule, LPTSTR lpszPath, DWORD cchPath)
1359{
1360 Win32ImageBase * pMod; /* Pointer to the module object. */
1361 DWORD cch; /* Length of the */
1362
1363 if (!VALID_PSZ(lpszPath))
1364 {
1365 dprintf(("KERNEL32: GetModuleFileNameA(0x%x, 0x%x, 0x%x): invalid pointer lpszLibFile = 0x%x\n",
1366 hModule, lpszPath, cchPath, lpszPath));
1367 SetLastError(ERROR_INVALID_PARAMETER); //or maybe ERROR_ACCESS_DENIED is more appropriate?
1368 return 0;
1369 }
1370
1371 pMod = Win32ImageBase::findModule(hModule);
1372 if (pMod != NULL)
1373 {
1374 const char *pszFn = pMod->getFullPath();
1375 if (pszFn)
1376 {
1377 cch = strlen(pszFn) + 1;
1378 if (cch > cchPath)
1379 cch = cchPath;
1380 memcpy(lpszPath, pszFn, cch);
1381 lpszPath[cch - 1] = '\0';
1382 }
1383 else
1384 {
1385 dprintf(("KERNEL32: GetModuleFileNameA(%x,...): IPE - getFullPath returned NULL or empty string\n"));
1386 DebugInt3();
1387 SetLastError(ERROR_INVALID_HANDLE);
1388 }
1389 }
1390 else
1391 {
1392 SetLastError(ERROR_INVALID_HANDLE);
1393 //only needed for call inside kernel32's initterm (profile init)
1394 //(console init only it seems...)
1395 cch = O32_GetModuleFileName(hModule, lpszPath, cchPath);
1396 if (cch > 0) cch++; /* Open32 doesn't count the terminator. */
1397 }
1398
1399 if (cch > 0)
1400 dprintf(("KERNEL32: GetModuleFileNameA(%x %x): %s %d\n", hModule, lpszPath, lpszPath, cch));
1401 else
1402 dprintf(("KERNEL32: WARNING: GetModuleFileNameA(%x,...) - not found!", hModule));
1403
1404 return cch;
1405}
1406
1407
1408/**
1409 * GetModuleFileName gets the full path and file name for the specified module.
1410 * @returns Bytes written to the buffer (lpszPath). This count includes the
1411 * terminating '\0'.
1412 * On error 0 is returned. Last error is set.
1413 * @param hModule Handle to the module you like to get the file name to.
1414 * @param lpszPath Output buffer for full path and file name.
1415 * @param cchPath Size of the lpszPath buffer.
1416 * @sketch Find the module object using handle.
1417 * If found Then
1418 * get full path from module object.
1419 * If found path Then
1420 * Determin path length.
1421 * Translate the path to into the buffer.
1422 * Else
1423 * IPE.
1424 * else
1425 * SetLastError to invalid handle.
1426 * Log result.
1427 * return number of bytes written to the buffer.
1428 *
1429 * @status Completely implemented.
1430 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1431 * @remark - We do _NOT_ call Open32.
1432 * - Do we set ERROR_BUFFER_OVERFLOW when cch > cchPath?
1433 * - Does NT really set the last error?
1434 */
1435DWORD WIN32API GetModuleFileNameW(HMODULE hModule, LPWSTR lpszPath, DWORD cchPath)
1436{
1437 Win32ImageBase * pMod;
1438 DWORD cch = 0;
1439
1440 if (!VALID_PSZ(lpszPath))
1441 {
1442 dprintf(("KERNEL32: GetModuleFileNameW(0x%x, 0x%x, 0x%x): invalid pointer lpszLibFile = 0x%x\n",
1443 hModule, lpszPath, cchPath, lpszPath));
1444 SetLastError(ERROR_INVALID_PARAMETER); //or maybe ERROR_ACCESS_DENIED is more appropriate?
1445 return 0;
1446 }
1447
1448 pMod = Win32ImageBase::findModule(hModule);
1449 if (pMod != NULL)
1450 {
1451 const char *pszFn = pMod->getFullPath();
1452 if (pszFn || *pszFn != '\0')
1453 {
1454 cch = strlen(pszFn) + 1;
1455 if (cch > cchPath)
1456 cch = cchPath;
1457 AsciiToUnicodeN(pszFn, lpszPath, cch);
1458 }
1459 else
1460 {
1461 dprintf(("KERNEL32: GetModuleFileNameW(%x,...): IPE - getFullPath returned NULL or empty string\n"));
1462 DebugInt3();
1463 SetLastError(ERROR_INVALID_HANDLE);
1464 }
1465 }
1466 else
1467 SetLastError(ERROR_INVALID_HANDLE);
1468
1469 if (cch > 0)
1470 dprintf(("KERNEL32: GetModuleFileNameW(%x,...): %s %d\n", hModule, lpszPath, cch));
1471 else
1472 dprintf(("KERNEL32: WARNING: GetModuleFileNameW(%x,...) - not found!", hModule));
1473
1474 return cch;
1475}
1476
1477
1478//******************************************************************************
1479//NOTE: GetModuleHandleA does NOT support files with multiple dots (i.e.
1480// very.weird.exe)
1481//
1482// hinst = LoadLibrary("WINSPOOL.DRV"); -> succeeds
1483// hinst2 = GetModuleHandle("WINSPOOL.DRV"); -> succeeds
1484// hinst3 = GetModuleHandle("WINSPOOL."); -> fails
1485// hinst4 = GetModuleHandle("WINSPOOL"); -> fails
1486// hinst = LoadLibrary("KERNEL32.DLL"); -> succeeds
1487// hinst2 = GetModuleHandle("KERNEL32.DLL"); -> succeeds
1488// hinst3 = GetModuleHandle("KERNEL32."); -> fails
1489// hinst4 = GetModuleHandle("KERNEL32"); -> succeeds
1490// Same behaviour as observed in NT4, SP6
1491//******************************************************************************
1492HANDLE WIN32API GetModuleHandleA(LPCTSTR lpszModule)
1493{
1494 HANDLE hMod = 0;
1495 Win32DllBase *windll;
1496 char szModule[CCHMAXPATH];
1497 char *dot;
1498
1499 if(lpszModule == NULL)
1500 {
1501 if(WinExe)
1502 hMod = WinExe->getInstanceHandle();
1503 else hMod = -1;
1504 }
1505 else
1506 {
1507 strcpy(szModule, OSLibStripPath((char *)lpszModule));
1508 strupr(szModule);
1509 dot = strchr(szModule, '.');
1510 if(dot == NULL) {
1511 //if no extension -> add .DLL (see SDK docs)
1512 strcat(szModule, DLL_EXTENSION);
1513 }
1514 else {
1515 if(dot[1] == 0) {
1516 //a trailing dot means the module has no extension (SDK docs)
1517 *dot = 0;
1518 }
1519 }
1520 if(WinExe && WinExe->matchModName(szModule)) {
1521 hMod = WinExe->getInstanceHandle();
1522 }
1523 else {
1524 windll = Win32DllBase::findModule(szModule);
1525 if(windll) {
1526 hMod = windll->getInstanceHandle();
1527 }
1528 }
1529 }
1530 dprintf(("KERNEL32: GetModuleHandle %s returned %X\n", lpszModule, hMod));
1531 return(hMod);
1532}
1533//******************************************************************************
1534//******************************************************************************
1535HMODULE WIN32API GetModuleHandleW(LPCWSTR arg1)
1536{
1537 HMODULE rc;
1538 char *astring;
1539
1540 astring = UnicodeToAsciiString((LPWSTR)arg1);
1541 rc = GetModuleHandleA(astring);
1542 dprintf(("KERNEL32: OS2GetModuleHandleW %s returned %X\n", astring, rc));
1543 FreeAsciiString(astring);
1544 return(rc);
1545}
1546//******************************************************************************
1547//******************************************************************************
1548BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
1549 LPSECURITY_ATTRIBUTES lpProcessAttributes,
1550 LPSECURITY_ATTRIBUTES lpThreadAttributes,
1551 BOOL bInheritHandles, DWORD dwCreationFlags,
1552 LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
1553 LPSTARTUPINFOA lpStartupInfo,
1554 LPPROCESS_INFORMATION lpProcessInfo )
1555{
1556 TEB *pThreadDB = (TEB*)GetThreadTEB();
1557 char *cmdline = NULL;
1558 BOOL rc;
1559
1560 dprintf(("KERNEL32: CreateProcessA %s cline:%s inherit:%d cFlags:%x Env:%x CurDir:%s StartupFlags:%x\n",
1561 lpApplicationName, lpCommandLine, bInheritHandles, dwCreationFlags,
1562 lpEnvironment, lpCurrentDirectory, lpStartupInfo));
1563
1564#ifdef DEBUG
1565 if(lpStartupInfo) {
1566 dprintf(("lpStartupInfo->lpReserved %x", lpStartupInfo->lpReserved));
1567 dprintf(("lpStartupInfo->lpDesktop %x", lpStartupInfo->lpDesktop));
1568 dprintf(("lpStartupInfo->lpTitle %s", lpStartupInfo->lpTitle));
1569 dprintf(("lpStartupInfo->dwX %x", lpStartupInfo->dwX));
1570 dprintf(("lpStartupInfo->dwY %x", lpStartupInfo->dwY));
1571 dprintf(("lpStartupInfo->dwXSize %x", lpStartupInfo->dwXSize));
1572 dprintf(("lpStartupInfo->dwYSize %x", lpStartupInfo->dwYSize));
1573 dprintf(("lpStartupInfo->dwXCountChars %x", lpStartupInfo->dwXCountChars));
1574 dprintf(("lpStartupInfo->dwYCountChars %x", lpStartupInfo->dwYCountChars));
1575 dprintf(("lpStartupInfo->dwFillAttribute %x", lpStartupInfo->dwFillAttribute));
1576 dprintf(("lpStartupInfo->dwFlags %x", lpStartupInfo->dwFlags));
1577 dprintf(("lpStartupInfo->wShowWindow %x", lpStartupInfo->wShowWindow));
1578 dprintf(("lpStartupInfo->hStdInput %x", lpStartupInfo->hStdInput));
1579 dprintf(("lpStartupInfo->hStdOutput %x", lpStartupInfo->hStdOutput));
1580 dprintf(("lpStartupInfo->hStdError %x", lpStartupInfo->hStdError));
1581 }
1582#endif
1583
1584 // open32 does not support DEBUG_ONLY_THIS_PROCESS
1585 if(dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
1586 dwCreationFlags |= DEBUG_PROCESS;
1587
1588 if(O32_CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes,
1589 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1590 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1591 lpProcessInfo) == TRUE)
1592 {
1593 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
1594 {
1595 if(pThreadDB->o.odin.pidDebuggee != 0)
1596 {
1597 // TODO: handle this
1598 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
1599 }
1600 else
1601 {
1602 pThreadDB->o.odin.pidDebuggee = lpProcessInfo->dwProcessId;
1603 OSLibStartDebugger((ULONG*)&pThreadDB->o.odin.pidDebuggee);
1604 }
1605 }
1606 else pThreadDB->o.odin.pidDebuggee = 0;
1607
1608 return(TRUE);
1609 }
1610
1611 // PH 2001-05-07
1612 // verify why O32_CreateProcess actually failed.
1613 // If GetLastError() == 191 (ERROR_INVALID_EXE_SIGNATURE)
1614 // we can continue to call "PE.EXE".
1615 // Note: Open32 does not translate ERROR_INVALID_EXE_SIGNATURE,
1616 // it is also valid in Win32.
1617 DWORD dwError = GetLastError();
1618 if (ERROR_INVALID_EXE_SIGNATURE != dwError && ERROR_FILE_NOT_FOUND != dwError)
1619 {
1620 dprintf(("CreateProcess: O32_CreateProcess failed with rc=%d, not PE-executable !",
1621 dwError));
1622
1623 // the current value of GetLastError() is still valid.
1624
1625 return FALSE;
1626 }
1627
1628 // else ...
1629
1630 //probably a win32 exe, so run it in the pe loader
1631 if(lpApplicationName) {
1632 if(lpCommandLine) {
1633 //skip exe name in lpCommandLine
1634 //TODO: doesn't work for directories with spaces!
1635 while(*lpCommandLine != 0 && *lpCommandLine != ' ')
1636 lpCommandLine++;
1637
1638 if(*lpCommandLine != 0) {
1639 lpCommandLine++;
1640 }
1641 cmdline = (char *)malloc(strlen(lpApplicationName)+strlen(lpCommandLine) + 16);
1642 sprintf(cmdline, "%s %s", lpApplicationName, lpCommandLine);
1643 }
1644 else {
1645 cmdline = (char *)malloc(strlen(lpApplicationName) + 16);
1646 sprintf(cmdline, "%s", lpApplicationName);
1647 }
1648 }
1649 else {
1650 cmdline = (char *)malloc(strlen(lpCommandLine) + 16);
1651 sprintf(cmdline, "%s", lpCommandLine);
1652 }
1653
1654 char szAppName[255];
1655 DWORD fileAttr;
1656 char *exename = szAppName;
1657 strncpy(szAppName, cmdline, sizeof(szAppName));
1658 szAppName[254] = 0;
1659 if(*exename == '"') {
1660 exename++;
1661 while(*exename != 0 && *exename != '"')
1662 exename++;
1663
1664 if(*exename != 0) {
1665 *exename = 0;
1666 }
1667 exename = &szAppName[1];
1668 }
1669 else {
1670 BOOL fTerminate = FALSE;
1671 DWORD fileAttr;
1672
1673 while(*exename != 0) {
1674 while(*exename != 0 && *exename != ' ')
1675 exename++;
1676
1677 if(*exename != 0) {
1678 *exename = 0;
1679 fTerminate = TRUE;
1680 }
1681
1682 fileAttr = GetFileAttributesA(szAppName);
1683 if(fileAttr != -1 && !(fileAttr & FILE_ATTRIBUTE_DIRECTORY)) {
1684 break;
1685 }
1686 if(fTerminate) {
1687 *exename = ' ';
1688 exename++;
1689 fTerminate = FALSE;
1690 }
1691 }
1692 exename = szAppName;
1693 }
1694 fileAttr = GetFileAttributesA(exename);
1695 if(fileAttr == -1 || (fileAttr & FILE_ATTRIBUTE_DIRECTORY)) {
1696 dprintf(("CreateProcess: can't find executable!"));
1697 SetLastError(ERROR_FILE_NOT_FOUND);
1698 return FALSE;
1699 }
1700
1701 dprintf(("KERNEL32: CreateProcess %s\n", cmdline));
1702
1703 DWORD Characteristics, SubSystem, fNEExe;
1704 if(Win32ImageBase::isPEImage(exename, &Characteristics, &SubSystem, &fNEExe) == 0) {
1705 char *lpszPE;
1706 if(SubSystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) {
1707 lpszPE = "PEC.EXE";
1708 }
1709 else lpszPE = "PE.EXE";
1710
1711 //SvL: Allright. Before we call O32_CreateProcess, we must take care of
1712 // lpCurrentDirectory ourselves. (Open32 ignores it!)
1713 if(lpCurrentDirectory) {
1714 char *newcmdline;
1715
1716 newcmdline = (char *)malloc(strlen(lpCurrentDirectory) + strlen(cmdline) + 32);
1717 sprintf(newcmdline, "%s /OPT:[CURDIR=%s] %s", lpszPE, lpCurrentDirectory, cmdline);
1718 free(cmdline);
1719 cmdline = newcmdline;
1720 }
1721 else {
1722 char *newcmdline;
1723
1724 newcmdline = (char *)malloc(strlen(cmdline) + 16);
1725 sprintf(newcmdline, "%s %s", lpszPE, cmdline);
1726 free(cmdline);
1727 cmdline = newcmdline;
1728 }
1729 rc = O32_CreateProcess(lpszPE, (LPCSTR)cmdline,lpProcessAttributes,
1730 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1731 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1732 lpProcessInfo);
1733 }
1734 else
1735 if(fNEExe) {//16 bits windows app
1736 char *newcmdline;
1737
1738 newcmdline = (char *)malloc(strlen(cmdline) + 16);
1739 sprintf(newcmdline, "w16odin.exe %s", cmdline);
1740 free(cmdline);
1741 cmdline = newcmdline;
1742 //Force Open32 to use DosStartSession (DosExecPgm won't do)
1743 dwCreationFlags |= CREATE_NEW_PROCESS_GROUP;
1744 rc = O32_CreateProcess("w16odin.exe", (LPCSTR)cmdline, lpProcessAttributes,
1745 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1746 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1747 lpProcessInfo);
1748 }
1749 else {//os/2 app??
1750 rc = O32_CreateProcess(NULL, (LPCSTR)cmdline,lpProcessAttributes,
1751 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1752 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1753 lpProcessInfo);
1754 }
1755 if(rc == TRUE)
1756 {
1757 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
1758 {
1759 if(pThreadDB->o.odin.pidDebuggee != 0)
1760 {
1761 // TODO: handle this
1762 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
1763 }
1764 else
1765 {
1766 pThreadDB->o.odin.pidDebuggee = lpProcessInfo->dwProcessId;
1767 OSLibStartDebugger((ULONG*)&pThreadDB->o.odin.pidDebuggee);
1768 }
1769 }
1770 else
1771 pThreadDB->o.odin.pidDebuggee = 0;
1772 }
1773 if(cmdline)
1774 free(cmdline);
1775
1776 if(lpProcessInfo)
1777 dprintf(("KERNEL32: CreateProcess returned %d hPro:%x hThr:%x pid:%x tid:%x\n",
1778 rc, lpProcessInfo->hProcess, lpProcessInfo->hThread,
1779 lpProcessInfo->dwProcessId,lpProcessInfo->dwThreadId));
1780 else
1781 dprintf(("KERNEL32: CreateProcess returned %d\n", rc));
1782 return(rc);
1783}
1784//******************************************************************************
1785//******************************************************************************
1786BOOL WIN32API CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
1787 PSECURITY_ATTRIBUTES lpProcessAttributes,
1788 PSECURITY_ATTRIBUTES lpThreadAttributes,
1789 BOOL bInheritHandles, DWORD dwCreationFlags,
1790 LPVOID lpEnvironment,
1791 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
1792 LPPROCESS_INFORMATION lpProcessInfo)
1793{
1794 BOOL rc;
1795 char *astring1 = 0, *astring2 = 0, *astring3 = 0;
1796
1797 dprintf(("KERNEL32: CreateProcessW"));
1798 if(lpApplicationName)
1799 astring1 = UnicodeToAsciiString((LPWSTR)lpApplicationName);
1800 if(lpCommandLine)
1801 astring2 = UnicodeToAsciiString(lpCommandLine);
1802 if(lpCurrentDirectory)
1803 astring3 = UnicodeToAsciiString((LPWSTR)lpCurrentDirectory);
1804 rc = CreateProcessA(astring1, astring2, lpProcessAttributes, lpThreadAttributes,
1805 bInheritHandles, dwCreationFlags, lpEnvironment,
1806 astring3, (LPSTARTUPINFOA)lpStartupInfo,
1807 lpProcessInfo);
1808 if(astring3) FreeAsciiString(astring3);
1809 if(astring2) FreeAsciiString(astring2);
1810 if(astring1) FreeAsciiString(astring1);
1811 return(rc);
1812}
1813//******************************************************************************
1814//******************************************************************************
1815HINSTANCE WIN32API WinExec(LPCSTR lpCmdLine, UINT nCmdShow)
1816{
1817 STARTUPINFOA startinfo = {0};
1818 PROCESS_INFORMATION procinfo;
1819 DWORD rc;
1820 HINSTANCE hInstance;
1821
1822 dprintf(("KERNEL32: WinExec %s\n", lpCmdLine));
1823 startinfo.dwFlags = nCmdShow;
1824 if(CreateProcessA(NULL, (LPSTR)lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL,
1825 &startinfo, &procinfo) == FALSE)
1826 {
1827 hInstance = (HINSTANCE)GetLastError();
1828 if(hInstance >= 32) {
1829 hInstance = 11;
1830 }
1831 dprintf(("KERNEL32: WinExec failed with rc %d", hInstance));
1832 return hInstance;
1833 }
1834 //block until the launched app waits for input (or a timeout of 15 seconds)
1835 //TODO: Shouldn't call Open32, but the api in user32..
1836 rc = O32_WaitForInputIdle(procinfo.hProcess, 15000);
1837 if(rc != 0) {
1838 dprintf(("WinExec: WaitForInputIdle %x returned %x", procinfo.hProcess, rc));
1839 }
1840 CloseHandle(procinfo.hThread);
1841 CloseHandle(procinfo.hProcess);
1842 return 33;
1843}
1844//******************************************************************************
1845//******************************************************************************
1846VOID WIN32API Sleep(DWORD arg1)
1847{
1848 dprintf2(("KERNEL32: Sleep %d\n", arg1));
1849 O32_Sleep(arg1);
1850}
1851//******************************************************************************
1852//******************************************************************************
1853DWORD WIN32API GetPriorityClass(HANDLE hProcess)
1854{
1855 dprintf(("KERNEL32: GetPriorityClass %x", hProcess));
1856 return O32_GetPriorityClass(hProcess);
1857}
1858//******************************************************************************
1859//******************************************************************************
1860BOOL WIN32API SetPriorityClass(HANDLE hProcess, DWORD dwPriority)
1861{
1862 dprintf(("KERNEL32: SetPriorityClass %x %x", hProcess, dwPriority));
1863 return O32_SetPriorityClass(hProcess, dwPriority);
1864}
1865/**********************************************************************
1866 * LoadModule (KERNEL32.499)
1867 *
1868 * Wine: 20000909
1869 *
1870 * Copyright 1995 Alexandre Julliard
1871 */
1872HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
1873{
1874 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1875 PROCESS_INFORMATION info;
1876 STARTUPINFOA startup;
1877 HINSTANCE hInstance;
1878 LPSTR cmdline, p;
1879 char filename[MAX_PATH];
1880 BYTE len;
1881
1882 dprintf(("LoadModule %s %x", name, paramBlock));
1883
1884 if (!name) return ERROR_FILE_NOT_FOUND;
1885
1886 if (!SearchPathA( NULL, name, ".exe", sizeof(filename), filename, NULL ) &&
1887 !SearchPathA( NULL, name, NULL, sizeof(filename), filename, NULL ))
1888 return GetLastError();
1889
1890 len = (BYTE)params->lpCmdLine[0];
1891 if (!(cmdline = (LPSTR)HeapAlloc( GetProcessHeap(), 0, strlen(filename) + len + 2 )))
1892 return ERROR_NOT_ENOUGH_MEMORY;
1893
1894 strcpy( cmdline, filename );
1895 p = cmdline + strlen(cmdline);
1896 *p++ = ' ';
1897 memcpy( p, params->lpCmdLine + 1, len );
1898 p[len] = 0;
1899
1900 memset( &startup, 0, sizeof(startup) );
1901 startup.cb = sizeof(startup);
1902 if (params->lpCmdShow)
1903 {
1904 startup.dwFlags = STARTF_USESHOWWINDOW;
1905 startup.wShowWindow = params->lpCmdShow[1];
1906 }
1907
1908 if (CreateProcessA( filename, cmdline, NULL, NULL, FALSE, 0,
1909 params->lpEnvAddress, NULL, &startup, &info ))
1910 {
1911 /* Give 15 seconds to the app to come up */
1912 if ( O32_WaitForInputIdle ( info.hProcess, 15000 ) == 0xFFFFFFFF )
1913 dprintf(("ERROR: WaitForInputIdle failed: Error %ld\n", GetLastError() ));
1914 hInstance = 33;
1915 /* Close off the handles */
1916 CloseHandle( info.hThread );
1917 CloseHandle( info.hProcess );
1918 }
1919 else if ((hInstance = GetLastError()) >= 32)
1920 {
1921 dprintf(("ERROR: Strange error set by CreateProcess: %d\n", hInstance ));
1922 hInstance = 11;
1923 }
1924
1925 HeapFree( GetProcessHeap(), 0, cmdline );
1926 return hInstance;
1927}
1928//******************************************************************************
1929//******************************************************************************
1930FARPROC WIN32API GetProcAddress(HMODULE hModule, LPCSTR lpszProc)
1931{
1932 Win32ImageBase *winmod;
1933 FARPROC proc;
1934 ULONG ulAPIOrdinal;
1935
1936 if(hModule == 0 || hModule == -1 || (WinExe && hModule == WinExe->getInstanceHandle())) {
1937 winmod = WinExe;
1938 }
1939 else winmod = (Win32ImageBase *)Win32DllBase::findModule((HINSTANCE)hModule);
1940
1941 if(winmod) {
1942 ulAPIOrdinal = (ULONG)lpszProc;
1943 if (ulAPIOrdinal <= 0x0000FFFF) {
1944 proc = (FARPROC)winmod->getApi((int)ulAPIOrdinal);
1945 }
1946 else proc = (FARPROC)winmod->getApi((char *)lpszProc);
1947 if(proc == 0) {
1948#ifdef DEBUG
1949 if(ulAPIOrdinal <= 0x0000FFFF) {
1950 dprintf(("GetProcAddress %x %x not found!", hModule, ulAPIOrdinal));
1951 }
1952 else dprintf(("GetProcAddress %x %s not found!", hModule, lpszProc));
1953#endif
1954 SetLastError(ERROR_PROC_NOT_FOUND);
1955 }
1956 if(HIWORD(lpszProc))
1957 dprintf(("KERNEL32: GetProcAddress %s from %X returned %X\n", lpszProc, hModule, proc));
1958 else dprintf(("KERNEL32: GetProcAddress %x from %X returned %X\n", lpszProc, hModule, proc));
1959 return proc;
1960 }
1961 proc = O32_GetProcAddress(hModule, lpszProc);
1962 if(HIWORD(lpszProc))
1963 dprintf(("KERNEL32: GetProcAddress %s from %X returned %X\n", lpszProc, hModule, proc));
1964 else dprintf(("KERNEL32: GetProcAddress %x from %X returned %X\n", lpszProc, hModule, proc));
1965 return(proc);
1966}
1967//******************************************************************************
1968//Retrieve the version
1969//******************************************************************************
1970BOOL SYSTEM GetVersionStruct(char *lpszModName, char *verstruct, ULONG bufLength)
1971{
1972 Win32ImageBase *winimage;
1973 HINSTANCE hDll;
1974 BOOL rc = FALSE;
1975
1976 dprintf(("GetVersionStruct of module %s %x %d", lpszModName, verstruct, bufLength));
1977 if(verstruct == NULL) {
1978 SetLastError(ERROR_INVALID_PARAMETER);
1979 return FALSE;
1980 }
1981 if (WinExe != NULL && WinExe->matchModName(lpszModName)) {
1982 return WinExe->getVersionStruct(verstruct, bufLength);
1983 }
1984 hDll = LoadLibraryExA(lpszModName, 0, LOAD_LIBRARY_AS_DATAFILE);
1985 if(hDll == 0) {
1986 dprintf(("ERROR: GetVersionStruct: Unable to load module!!"));
1987 return 0;
1988 }
1989 winimage = (Win32ImageBase *)Win32DllBase::findModule(hDll);
1990 if(winimage != NULL) {
1991 rc = winimage->getVersionStruct(verstruct, bufLength);
1992 }
1993 else {
1994 dprintf(("GetVersionStruct; just loaded dll %s, but can't find it now!", lpszModName));
1995 DebugInt3();
1996 }
1997 FreeLibrary(hDll);
1998 return rc;
1999}
2000//******************************************************************************
2001//******************************************************************************
2002ULONG SYSTEM GetVersionSize(char *lpszModName)
2003{
2004 Win32ImageBase *winimage;
2005 HINSTANCE hDll;
2006 ULONG size = 0;
2007
2008 dprintf(("GetVersionSize of %s", lpszModName));
2009 if (WinExe != NULL && WinExe->matchModName(lpszModName)) {
2010 return WinExe->getVersionSize();
2011 }
2012
2013 hDll = LoadLibraryExA(lpszModName, 0, LOAD_LIBRARY_AS_DATAFILE);
2014 if(hDll == 0) {
2015 dprintf(("ERROR: GetVersionStruct: Unable to load module!!"));
2016 return 0;
2017 }
2018 winimage = (Win32ImageBase *)Win32DllBase::findModule(hDll);
2019 if(winimage != NULL) {
2020 size = winimage->getVersionSize();
2021 }
2022 else {
2023 dprintf(("GetVersionSize; just loaded dll %s, but can't find it now!", lpszModName));
2024 DebugInt3();
2025 }
2026 FreeLibrary(hDll);
2027 return size;
2028}
2029//******************************************************************************
2030//******************************************************************************
2031ODINFUNCTION1(BOOL,DisableThreadLibraryCalls,HMODULE,hModule)
2032{
2033 Win32DllBase *winmod;
2034 FARPROC proc;
2035 ULONG ulAPIOrdinal;
2036
2037 winmod = Win32DllBase::findModule((HINSTANCE)hModule);
2038 if(winmod)
2039 {
2040 // don't call ATTACH/DETACH thread functions in DLL
2041 winmod->disableThreadLibraryCalls();
2042 return TRUE;
2043 }
2044 else
2045 {
2046 // raise error condition
2047 SetLastError(ERROR_INVALID_HANDLE);
2048 return FALSE;
2049 }
2050}
2051//******************************************************************************
2052//******************************************************************************
Note: See TracBrowser for help on using the repository browser.