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

Last change on this file since 5959 was 5959, checked in by sandervl, 24 years ago

CreateProcess: launch win16 loader for NE executables

File size: 76.7 KB
Line 
1/* $Id: wprocess.cpp,v 1.123 2001-06-10 22:32:18 sandervl 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 dwFlags == 0 && (!fPeLoader || !fPE) 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 *)Win32LxDll::findModuleByOS2Handle(hDll);
811 if(pModule)
812 {
813 if(pModule->isLxDll())
814 {
815 ((Win32LxDll *)pModule)->setDllHandleOS2(hDll);
816 if(fPeLoader)
817 {
818 if(pModule->AddRef() == -1) {//-1 -> load failed (attachProcess)
819 dprintf(("Dll %s refused to be loaded; aborting", szModname));
820 delete pModule;
821 return 0;
822 }
823 }
824 }
825 pModule->incDynamicLib();
826 }
827 else
828 return hDll; //happens when LoadLibrary is called in kernel32's initterm (nor harmful)
829
830 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): returns 0x%x. Loaded %s using DosLoadModule.",
831 lpszLibFile, hFile, dwFlags, hDll, szModname));
832 return pModule->getInstanceHandle();
833 }
834 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): DosLoadModule (%s) failed. LastError=%d",
835 lpszLibFile, hFile, dwFlags, szModname, GetLastError()));
836 }
837 else
838 hDll = NULL;
839
840
841 /** @sketch
842 * If PE image THEN
843 * IF LOAD_LIBRARY_AS_DATAFILE or Executable THEN
844 *
845 *
846 * Try load the file using the Win32PeLdrDll class.
847 * <sketch continued further down>
848 * Else
849 * Set last error.
850 * (hDll is NULL)
851 * Endif
852 * return hDll.
853 */
854 if(fPE == ERROR_SUCCESS)
855 {
856 Win32PeLdrDll *peldrDll;
857
858 //SvL: If executable -> load as data file (only resources)
859 if(!(Characteristics & IMAGE_FILE_DLL))
860 {
861 dwFlags |= (LOAD_LIBRARY_AS_DATAFILE | DONT_RESOLVE_DLL_REFERENCES);
862 }
863
864 peldrDll = new Win32PeLdrDll(szModname);
865 if (peldrDll == NULL)
866 {
867 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Failed to created instance of Win32PeLdrDll. returns NULL.",
868 lpszLibFile, hFile, dwFlags));
869 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
870 return NULL;
871 }
872
873 /** @sketch
874 * Process dwFlags
875 */
876 if (dwFlags & LOAD_LIBRARY_AS_DATAFILE)
877 {
878 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): LOAD_LIBRARY_AS_DATAFILE",
879 lpszLibFile, hFile, dwFlags));
880 peldrDll->setLoadAsDataFile();
881 peldrDll->disableLibraryCalls();
882 }
883 if (dwFlags & DONT_RESOLVE_DLL_REFERENCES)
884 {
885 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): DONT_RESOLVE_DLL_REFERENCES",
886 lpszLibFile, hFile, dwFlags));
887 peldrDll->disableLibraryCalls();
888 peldrDll->disableImportHandling();
889 }
890 if (dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH)
891 {
892 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Warning dwFlags LOAD_WITH_ALTERED_SEARCH_PATH is not implemented.",
893 lpszLibFile, hFile, dwFlags));
894 //peldrDll->setLoadWithAlteredSearchPath();
895 }
896
897 /** @sketch
898 * Initiate the peldr DLL.
899 * IF successful init THEN
900 * Inc dynamic ref count.
901 * Inc ref count.
902 * Attach to process
903 * IF successful THEN
904 * hDLL <- instance handle.
905 * ELSE
906 * set last error
907 * delete Win32PeLdrDll instance.
908 * Endif
909 * ELSE
910 * set last error
911 * delete Win32PeLdrDll instance.
912 * Endif.
913 */
914 if (peldrDll->init(0))
915 {
916 peldrDll->AddRef();
917 if (peldrDll->attachProcess())
918 {
919 hDll = peldrDll->getInstanceHandle();
920 //Must be called *after* attachprocess, since attachprocess may also
921 //trigger LoadLibrary calls
922 //Those dlls must not be put in front of this dll in the dynamic
923 //dll list; or else the unload order is wrong:
924 //i.e. RPAP3260 loads PNRS3260 in DLL_PROCESS_ATTACH
925 // this means that in ExitProcess, PNRS3260 needs to be removed
926 // first since RPAP3260 depends on it
927 peldrDll->incDynamicLib();
928 }
929 else
930 {
931 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): attachProcess call to Win32PeLdrDll instance failed. returns NULL.",
932 lpszLibFile, hFile, dwFlags));
933 SetLastError(ERROR_DLL_INIT_FAILED);
934 delete peldrDll;
935 return NULL;
936 }
937 }
938 else
939 {
940 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Failed to init Win32PeLdrDll instance. error=%d returns NULL.",
941 lpszLibFile, hFile, dwFlags, peldrDll->getError()));
942 SetLastError(ERROR_INVALID_EXE_SIGNATURE);
943 delete peldrDll;
944 return NULL;
945 }
946 }
947 else
948 {
949 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x) library wasn't found (%s) or isn't loadable; err %x",
950 lpszLibFile, hFile, dwFlags, szModname, fPE));
951 SetLastError(fPE);
952 return NULL;
953 }
954
955 return hDll;
956}
957
958
959/**
960 * LoadLibraryExW can be used to map a DLL module into the calling process's
961 * addressspace. It returns a handle that can be used with GetProcAddress to
962 * get addresses of exported entry points (functions and variables).
963 *
964 * LoadLibraryExW can also be used to map executable (.exe) modules into the
965 * address to access resources in the module. However, LoadLibrary can't be
966 * used to run an executable (.exe) module.
967 *
968 * @returns Handle to the library which was loaded.
969 * @param lpszLibFile Pointer to Unicode string giving the name of
970 * the executable image (either a Dll or an Exe) which is to
971 * be loaded.
972 *
973 * If no extention is specified the default .DLL extention is
974 * appended to the name. End the filename with an '.' if the
975 * file does not have an extention (and don't want the .DLL
976 * appended).
977 *
978 * If no path is specified, this API will use the Odin32
979 * standard search strategy to find the file. This strategy
980 * is described in the method Win32ImageBase::findDLL.
981 * This may be alterned by the LOAD_WITH_ALTERED_SEARCH_PATH
982 * flag, see below.
983 *
984 * This API likes to have backslashes (\), but will probably
985 * accept forward slashes too. Win32 SDK docs says that it
986 * should not contain forward slashes.
987 *
988 * Win32 SDK docs adds:
989 * "The name specified is the file name of the module and
990 * is not related to the name stored in the library module
991 * itself, as specified by the LIBRARY keyword in the
992 * module-definition (.def) file."
993 *
994 * @param hFile Reserved. Must be 0.
995 *
996 * @param dwFlags Flags which specifies the taken when loading the module.
997 * The value 0 makes it identical to LoadLibraryA/W.
998 *
999 * Flags:
1000 *
1001 * DONT_RESOLVE_DLL_REFERENCES
1002 * (WinNT/2K feature): Don't load imported modules and
1003 * hence don't resolve imported symbols.
1004 * DllMain isn't called either. (Which is obvious since
1005 * it may use one of the importe symbols.)
1006 *
1007 * On the other hand, if this flag is NOT set, the system
1008 * load imported modules, resolves imported symbols, calls
1009 * DllMain for process and thread init and term (if wished
1010 * by the module).
1011 *
1012 * LOAD_LIBRARY_AS_DATAFILE
1013 * If this flag is set, the module is mapped into the
1014 * address space but is not prepared for execution. Though
1015 * it's preparted for resource API. Hence, you'll use this
1016 * flag when you want to load a DLL for extracting
1017 * messages or resources from it.
1018 *
1019 * The resulting handle can be used with any Odin32 API
1020 * which operates on resources.
1021 * (WinNt/2k supports all resource APIs while Win9x don't
1022 * support the specialized resource APIs: LoadBitmap,
1023 * LoadCursor, LoadIcon, LoadImage, LoadMenu.)
1024 *
1025 * LOAD_WITH_ALTERED_SEARCH_PATH
1026 * If this flag is set and lpszLibFile specifies a path
1027 * we'll use an alternative file search strategy to find
1028 * imported modules. This stratgy is simply to use the
1029 * path of the module being loaded instead of the path
1030 * of the executable module as the first location
1031 * to search for imported modules.
1032 *
1033 * If this flag is clear, the standard Odin32 standard
1034 * search strategy. See Win32ImageBase::findDll for
1035 * further information.
1036 *
1037 * @sketch Convert Unicode name to ascii.
1038 * Call LoadLibraryExA.
1039 * Free ascii string.
1040 * return handle from LoadLibraryExA.
1041 * @status Open32 Partially Implemented.
1042 * @author Sander van Leeuwen (sandervl@xs4all.nl)
1043 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1044 * @remark Forwards to LoadLibraryExA.
1045 */
1046HINSTANCE WIN32API LoadLibraryExW(LPCWSTR lpszLibFile, HANDLE hFile, DWORD dwFlags)
1047{
1048 char * pszAsciiLibFile;
1049 HINSTANCE hDll;
1050
1051 pszAsciiLibFile = UnicodeToAsciiString(lpszLibFile);
1052 dprintf(("KERNEL32: LoadLibraryExW(%s, 0x%x, 0x%x) --> LoadLibraryExA",
1053 pszAsciiLibFile, hFile, dwFlags));
1054 hDll = LoadLibraryExA(pszAsciiLibFile, hFile, dwFlags);
1055 dprintf(("KERNEL32: LoadLibraryExW(%s, 0x%x, 0x%x) returns 0x%x",
1056 pszAsciiLibFile, hFile, dwFlags, hDll));
1057 FreeAsciiString(pszAsciiLibFile);
1058
1059 return hDll;
1060}
1061//******************************************************************************
1062//******************************************************************************
1063HINSTANCE16 WIN32API LoadLibrary16(LPCTSTR lpszLibFile)
1064{
1065 dprintf(("ERROR: LoadLibrary16 %s, not implemented", lpszLibFile));
1066 return 0;
1067}
1068//******************************************************************************
1069//******************************************************************************
1070VOID WIN32API FreeLibrary16(HINSTANCE16 hinstance)
1071{
1072 dprintf(("ERROR: FreeLibrary16 %x, not implemented", hinstance));
1073}
1074//******************************************************************************
1075//******************************************************************************
1076FARPROC WIN32API GetProcAddress16(HMODULE hModule, LPCSTR lpszProc)
1077{
1078 dprintf(("ERROR: GetProcAddress16 %x %x, not implemented", hModule, lpszProc));
1079 return 0;
1080}
1081
1082
1083/**
1084 * Internal function which gets the commandline (string) used to start the current process.
1085 * @returns OS/2 / Windows return code
1086 * On successful return (NO_ERROR) the global variables
1087 * pszCmdLineA and pszCmdLineW are set.
1088 *
1089 * @param pszPeExe Pass in the name of the PE exe of this process. We'll
1090 * us this as exename and skip the first argument (ie. argv[1]).
1091 * If NULL we'll use the commandline from OS/2 as it is.
1092 * @status Completely implemented and tested.
1093 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1094 */
1095ULONG InitCommandLine(const char *pszPeExe)
1096{
1097 PCHAR pib_pchcmd; /* PIB pointer to commandline. */
1098 CHAR szFilename[CCHMAXPATH]; /* Filename buffer used to get the exe filename in. */
1099 ULONG cch; /* Commandline string length. (including terminator) */
1100 PSZ psz; /* Temporary string pointer. */
1101 PSZ psz2; /* Temporary string pointer. */
1102 APIRET rc; /* OS/2 return code. */
1103 BOOL fQuotes; /* Flag used to remember if the exe filename should be in quotes. */
1104
1105 /** @sketch
1106 * Get commandline from the PIB.
1107 */
1108 pib_pchcmd = (PCHAR)OSLibGetPIB(PIB_PCHCMD);
1109
1110 /** @sketch
1111 * Two methods of making the commandline:
1112 * (1) The first argument is skipped and the second is used as exe filname.
1113 * This applies to PE.EXE launched processes only.
1114 * (2) No skipping. First argument is the exe filename.
1115 * This applies to all but PE.EXE launched processes.
1116 *
1117 * Note: We could do some code size optimization here. Much of the code for
1118 * the two methods are nearly identical.
1119 *
1120 */
1121 if(pszPeExe)
1122 {
1123 /** @sketch
1124 * Allocate memory for the commandline.
1125 * Build commandline:
1126 * Copy exe filename.
1127 * Add arguments.
1128 */
1129 cch = strlen(pszPeExe)+1;
1130 pszCmdLineA = psz = (PSZ)malloc(cch);
1131 if (psz == NULL)
1132 {
1133 dprintf(("KERNEL32: InitCommandLine(%p): malloc(%d) failed\n", pszPeExe, cch));
1134 return ERROR_NOT_ENOUGH_MEMORY;
1135 }
1136 strcpy((char *)pszCmdLineA, pszPeExe);
1137
1138 rc = NO_ERROR;
1139 }
1140 else
1141 {
1142 /** @sketch Method (2):
1143 * First we'll have to determin the size of the commandline.
1144 *
1145 * As we don't assume that OS/2 allways puts a fully qualified EXE name
1146 * as the first string, we'll check if it's empty - and get the modulename
1147 * in that case - and allways get the fully qualified filename.
1148 */
1149 if (pib_pchcmd == NULL || pib_pchcmd[0] == '\0')
1150 {
1151 rc = OSLibDosQueryModuleName(OSLibGetPIB(PIB_HMTE), sizeof(szFilename), szFilename);
1152 if (rc != NO_ERROR)
1153 {
1154 dprintf(("KERNEL32: InitCommandLine(%p): OSLibQueryModuleName(0x%x,...) failed with rc=%d\n",
1155 pszPeExe, OSLibGetPIB(PIB_HMTE), rc));
1156 return rc;
1157 }
1158 }
1159 else
1160 {
1161 rc = OSLibDosQueryPathInfo(pib_pchcmd, FIL_QUERYFULLNAME, szFilename, sizeof(szFilename));
1162 if (rc != NO_ERROR)
1163 {
1164 dprintf(("KERNEL32: InitCommandLine(%p): (info) OSLibDosQueryPathInfo failed with rc=%d\n", pszPeExe, rc));
1165 strcpy(szFilename, pib_pchcmd);
1166 rc = NO_ERROR;
1167 }
1168 }
1169
1170 /** @sketch
1171 * We're still measuring the size of the commandline:
1172 * Check if we have to quote the exe filename.
1173 * Determin the length of the executable name including quotes and '\0'-terminator.
1174 * Count the length of the arguments. (We here count's all argument strings.)
1175 */
1176 fQuotes = strchr(szFilename, ' ') != NULL;
1177 cch = strlen(szFilename) + fQuotes*2 + 1;
1178 if (pib_pchcmd != NULL)
1179 {
1180 psz2 = pib_pchcmd + strlen(pib_pchcmd) + 1;
1181 while (*psz2 != '\0')
1182 {
1183 register int cchTmp = strlen(psz2) + 1; /* + 1 is for terminator (psz2) and space (cch). */
1184 psz2 += cchTmp;
1185 cch += cchTmp;
1186 }
1187 }
1188
1189 /** @sketch
1190 * Allocate memory for the commandline.
1191 * Build commandline:
1192 * Copy exe filename.
1193 * Add arguments.
1194 */
1195 pszCmdLineA = psz = (PSZ)malloc(cch);
1196 if (psz == NULL)
1197 {
1198 dprintf(("KERNEL32: InitCommandLine(%p): malloc(%d) failed\n", pszPeExe, cch));
1199 return ERROR_NOT_ENOUGH_MEMORY;
1200 }
1201
1202 if (fQuotes)
1203 *psz++ = '"';
1204 strcpy(psz, szFilename);
1205 psz += strlen(psz);
1206 if (fQuotes)
1207 {
1208 *psz++ = '"';
1209 *psz = '\0';
1210 }
1211
1212 if (pib_pchcmd != NULL)
1213 {
1214 psz2 = pib_pchcmd + strlen(pib_pchcmd) + 1;
1215 while (*psz2 != '\0')
1216 {
1217 register int cchTmp = strlen(psz2) + 1; /* + 1 is for terminator (psz). */
1218 *psz++ = ' '; /* add space */
1219 memcpy(psz, psz2, cchTmp);
1220 psz2 += cchTmp;
1221 psz += cchTmp - 1;
1222 }
1223 }
1224 }
1225
1226 /** @sketch
1227 * If successfully build ASCII commandline then convert it to UniCode.
1228 */
1229 if (rc == NO_ERROR)
1230 {
1231 pszCmdLineW = (WCHAR*)malloc(cch * 2);
1232 if (pszCmdLineW != NULL)
1233 AsciiToUnicode(pszCmdLineA, (WCHAR*)pszCmdLineW);
1234 else
1235 {
1236 dprintf(("KERNEL32: InitCommandLine(%p): malloc(%d) failed (2)\n", pszPeExe, cch));
1237 rc = ERROR_NOT_ENOUGH_MEMORY;
1238 }
1239 }
1240
1241 return rc;
1242}
1243
1244/**
1245 * Gets the command line of the current process.
1246 * @returns On success:
1247 * Command line of the current process. One single string.
1248 * The first part of the command line string is the executable filename
1249 * of the current process. It might be in quotes if it contains spaces.
1250 * The rest of the string is arguments.
1251 *
1252 * On error:
1253 * NULL. Last error set. (does Win32 set last error this?)
1254 * @sketch IF not inited THEN
1255 * Init commandline assuming !PE.EXE
1256 * IF init failes THEN set last error.
1257 * ENDIF
1258 * return ASCII/ANSI commandline.
1259 * @status Completely implemented and tested.
1260 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1261 * @remark The Ring-3 PeLdr is resposible for calling InitCommandLine before anyone
1262 * is able to call this function.
1263 */
1264LPCSTR WIN32API GetCommandLineA(VOID)
1265{
1266 /*
1267 * Check if the commandline is initiated.
1268 * If not we'll have to do it.
1269 * ASSUMES that if not inited this isn't a PE.EXE lauched process.
1270 */
1271 if (pszCmdLineA == NULL)
1272 {
1273 APIRET rc;
1274 rc = InitCommandLine(NULL);
1275 if (rc != NULL)
1276 SetLastError(rc);
1277 }
1278
1279 dprintf(("KERNEL32: GetCommandLineA: %s\n", pszCmdLineA));
1280 return pszCmdLineA;
1281}
1282
1283
1284/**
1285 * Gets the command line of the current process.
1286 * @returns On success:
1287 * Command line of the current process. One single string.
1288 * The first part of the command line string is the executable filename
1289 * of the current process. It might be in quotes if it contains spaces.
1290 * The rest of the string is arguments.
1291 *
1292 * On error:
1293 * NULL. Last error set. (does Win32 set last error this?)
1294 * @sketch IF not inited THEN
1295 * Init commandline assuming !PE.EXE
1296 * IF init failes THEN set last error.
1297 * ENDIF
1298 * return Unicode commandline.
1299 * @status Completely implemented and tested.
1300 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1301 * @remark The Ring-3 PeLdr is resposible for calling InitCommandLine before anyone
1302 * is able to call this function.
1303 */
1304LPCWSTR WIN32API GetCommandLineW(void)
1305{
1306 /*
1307 * Check if the commandline is initiated.
1308 * If not we'll have to do it.
1309 * ASSUMES that if not inited this isn't a PE.EXE lauched process.
1310 */
1311 if (pszCmdLineW == NULL)
1312 {
1313 APIRET rc;
1314 rc = InitCommandLine(NULL);
1315 if (rc != NULL)
1316 SetLastError(rc);
1317 }
1318
1319 dprintf(("KERNEL32: GetCommandLineW: %s\n", pszCmdLineA));
1320 return pszCmdLineW;
1321}
1322
1323
1324/**
1325 * GetModuleFileName gets the full path and file name for the specified module.
1326 * @returns Bytes written to the buffer (lpszPath). This count includes the
1327 * terminating '\0'.
1328 * On error 0 is returned. Last error is set.
1329 * @param hModule Handle to the module you like to get the file name to.
1330 * @param lpszPath Output buffer for full path and file name.
1331 * @param cchPath Size of the lpszPath buffer.
1332 * @sketch Validate lpszPath.
1333 * Find the module object using handle.
1334 * If found Then
1335 * Get full path from module object.
1336 * If found path Then
1337 * Copy path to buffer and set the number of bytes written.
1338 * Else
1339 * IPE!
1340 * Else
1341 * Call Open32 GetModuleFileName. (kernel32 initterm needs/needed this)
1342 * Log result.
1343 * Return number of bytes written to the buffer.
1344 *
1345 * @status Completely implemented, Open32.
1346 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1347 * Sander van Leeuwen (sandervl@xs4all.nl)
1348 * @remark - Do we still have to call Open32?
1349 * - Do we set ERROR_BUFFER_OVERFLOW when cch > cchPath?
1350 * - Does NT really set the last error?
1351 */
1352DWORD WIN32API GetModuleFileNameA(HMODULE hModule, LPTSTR lpszPath, DWORD cchPath)
1353{
1354 Win32ImageBase * pMod; /* Pointer to the module object. */
1355 DWORD cch; /* Length of the */
1356
1357 if (!VALID_PSZ(lpszPath))
1358 {
1359 dprintf(("KERNEL32: GetModuleFileNameA(0x%x, 0x%x, 0x%x): invalid pointer lpszLibFile = 0x%x\n",
1360 hModule, lpszPath, cchPath, lpszPath));
1361 SetLastError(ERROR_INVALID_PARAMETER); //or maybe ERROR_ACCESS_DENIED is more appropriate?
1362 return 0;
1363 }
1364
1365 pMod = Win32ImageBase::findModule(hModule);
1366 if (pMod != NULL)
1367 {
1368 const char *pszFn = pMod->getFullPath();
1369 if (pszFn)
1370 {
1371 cch = strlen(pszFn) + 1;
1372 if (cch > cchPath)
1373 cch = cchPath;
1374 memcpy(lpszPath, pszFn, cch);
1375 lpszPath[cch - 1] = '\0';
1376 }
1377 else
1378 {
1379 dprintf(("KERNEL32: GetModuleFileNameA(%x,...): IPE - getFullPath returned NULL or empty string\n"));
1380 DebugInt3();
1381 SetLastError(ERROR_INVALID_HANDLE);
1382 }
1383 }
1384 else
1385 {
1386 SetLastError(ERROR_INVALID_HANDLE);
1387 //only needed for call inside kernel32's initterm (profile init)
1388 //(console init only it seems...)
1389 cch = O32_GetModuleFileName(hModule, lpszPath, cchPath);
1390 if (cch > 0) cch++; /* Open32 doesn't count the terminator. */
1391 }
1392
1393 if (cch > 0)
1394 dprintf(("KERNEL32: GetModuleFileNameA(%x %x): %s %d\n", hModule, lpszPath, lpszPath, cch));
1395 else
1396 dprintf(("KERNEL32: WARNING: GetModuleFileNameA(%x,...) - not found!", hModule));
1397
1398 return cch;
1399}
1400
1401
1402/**
1403 * GetModuleFileName gets the full path and file name for the specified module.
1404 * @returns Bytes written to the buffer (lpszPath). This count includes the
1405 * terminating '\0'.
1406 * On error 0 is returned. Last error is set.
1407 * @param hModule Handle to the module you like to get the file name to.
1408 * @param lpszPath Output buffer for full path and file name.
1409 * @param cchPath Size of the lpszPath buffer.
1410 * @sketch Find the module object using handle.
1411 * If found Then
1412 * get full path from module object.
1413 * If found path Then
1414 * Determin path length.
1415 * Translate the path to into the buffer.
1416 * Else
1417 * IPE.
1418 * else
1419 * SetLastError to invalid handle.
1420 * Log result.
1421 * return number of bytes written to the buffer.
1422 *
1423 * @status Completely implemented.
1424 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1425 * @remark - We do _NOT_ call Open32.
1426 * - Do we set ERROR_BUFFER_OVERFLOW when cch > cchPath?
1427 * - Does NT really set the last error?
1428 */
1429DWORD WIN32API GetModuleFileNameW(HMODULE hModule, LPWSTR lpszPath, DWORD cchPath)
1430{
1431 Win32ImageBase * pMod;
1432 DWORD cch = 0;
1433
1434 if (!VALID_PSZ(lpszPath))
1435 {
1436 dprintf(("KERNEL32: GetModuleFileNameW(0x%x, 0x%x, 0x%x): invalid pointer lpszLibFile = 0x%x\n",
1437 hModule, lpszPath, cchPath, lpszPath));
1438 SetLastError(ERROR_INVALID_PARAMETER); //or maybe ERROR_ACCESS_DENIED is more appropriate?
1439 return 0;
1440 }
1441
1442 pMod = Win32ImageBase::findModule(hModule);
1443 if (pMod != NULL)
1444 {
1445 const char *pszFn = pMod->getFullPath();
1446 if (pszFn || *pszFn != '\0')
1447 {
1448 cch = strlen(pszFn) + 1;
1449 if (cch > cchPath)
1450 cch = cchPath;
1451 AsciiToUnicodeN(pszFn, lpszPath, cch);
1452 }
1453 else
1454 {
1455 dprintf(("KERNEL32: GetModuleFileNameW(%x,...): IPE - getFullPath returned NULL or empty string\n"));
1456 DebugInt3();
1457 SetLastError(ERROR_INVALID_HANDLE);
1458 }
1459 }
1460 else
1461 SetLastError(ERROR_INVALID_HANDLE);
1462
1463 if (cch > 0)
1464 dprintf(("KERNEL32: GetModuleFileNameW(%x,...): %s %d\n", hModule, lpszPath, cch));
1465 else
1466 dprintf(("KERNEL32: WARNING: GetModuleFileNameW(%x,...) - not found!", hModule));
1467
1468 return cch;
1469}
1470
1471
1472//******************************************************************************
1473//NOTE: GetModuleHandleA does NOT support files with multiple dots (i.e.
1474// very.weird.exe)
1475//
1476// hinst = LoadLibrary("WINSPOOL.DRV"); -> succeeds
1477// hinst2 = GetModuleHandle("WINSPOOL.DRV"); -> succeeds
1478// hinst3 = GetModuleHandle("WINSPOOL."); -> fails
1479// hinst4 = GetModuleHandle("WINSPOOL"); -> fails
1480// hinst = LoadLibrary("KERNEL32.DLL"); -> succeeds
1481// hinst2 = GetModuleHandle("KERNEL32.DLL"); -> succeeds
1482// hinst3 = GetModuleHandle("KERNEL32."); -> fails
1483// hinst4 = GetModuleHandle("KERNEL32"); -> succeeds
1484// Same behaviour as observed in NT4, SP6
1485//******************************************************************************
1486HANDLE WIN32API GetModuleHandleA(LPCTSTR lpszModule)
1487{
1488 HANDLE hMod = 0;
1489 Win32DllBase *windll;
1490 char szModule[CCHMAXPATH];
1491 char *dot;
1492
1493 if(lpszModule == NULL)
1494 {
1495 if(WinExe)
1496 hMod = WinExe->getInstanceHandle();
1497 else hMod = -1;
1498 }
1499 else
1500 {
1501 strcpy(szModule, OSLibStripPath((char *)lpszModule));
1502 strupr(szModule);
1503 dot = strchr(szModule, '.');
1504 if(dot == NULL) {
1505 //if no extension -> add .DLL (see SDK docs)
1506 strcat(szModule, DLL_EXTENSION);
1507 }
1508 else {
1509 if(dot[1] == 0) {
1510 //a trailing dot means the module has no extension (SDK docs)
1511 *dot = 0;
1512 }
1513 }
1514 if(WinExe && WinExe->matchModName(szModule)) {
1515 hMod = WinExe->getInstanceHandle();
1516 }
1517 else {
1518 windll = Win32DllBase::findModule(szModule);
1519 if(windll) {
1520 hMod = windll->getInstanceHandle();
1521 }
1522 }
1523 }
1524 dprintf(("KERNEL32: GetModuleHandle %s returned %X\n", lpszModule, hMod));
1525 return(hMod);
1526}
1527//******************************************************************************
1528//******************************************************************************
1529HMODULE WIN32API GetModuleHandleW(LPCWSTR arg1)
1530{
1531 HMODULE rc;
1532 char *astring;
1533
1534 astring = UnicodeToAsciiString((LPWSTR)arg1);
1535 rc = GetModuleHandleA(astring);
1536 dprintf(("KERNEL32: OS2GetModuleHandleW %s returned %X\n", astring, rc));
1537 FreeAsciiString(astring);
1538 return(rc);
1539}
1540//******************************************************************************
1541//******************************************************************************
1542BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
1543 LPSECURITY_ATTRIBUTES lpProcessAttributes,
1544 LPSECURITY_ATTRIBUTES lpThreadAttributes,
1545 BOOL bInheritHandles, DWORD dwCreationFlags,
1546 LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
1547 LPSTARTUPINFOA lpStartupInfo,
1548 LPPROCESS_INFORMATION lpProcessInfo )
1549{
1550 TEB *pThreadDB = (TEB*)GetThreadTEB();
1551 char *cmdline = NULL;
1552 BOOL rc;
1553
1554 dprintf(("KERNEL32: CreateProcessA %s cline:%s inherit:%d cFlags:%x Env:%x CurDir:%s StartupFlags:%x\n",
1555 lpApplicationName, lpCommandLine, bInheritHandles, dwCreationFlags,
1556 lpEnvironment, lpCurrentDirectory, lpStartupInfo));
1557
1558#ifdef DEBUG
1559 if(lpStartupInfo) {
1560 dprintf(("lpStartupInfo->lpReserved %x", lpStartupInfo->lpReserved));
1561 dprintf(("lpStartupInfo->lpDesktop %x", lpStartupInfo->lpDesktop));
1562 dprintf(("lpStartupInfo->lpTitle %s", lpStartupInfo->lpTitle));
1563 dprintf(("lpStartupInfo->dwX %x", lpStartupInfo->dwX));
1564 dprintf(("lpStartupInfo->dwY %x", lpStartupInfo->dwY));
1565 dprintf(("lpStartupInfo->dwXSize %x", lpStartupInfo->dwXSize));
1566 dprintf(("lpStartupInfo->dwYSize %x", lpStartupInfo->dwYSize));
1567 dprintf(("lpStartupInfo->dwXCountChars %x", lpStartupInfo->dwXCountChars));
1568 dprintf(("lpStartupInfo->dwYCountChars %x", lpStartupInfo->dwYCountChars));
1569 dprintf(("lpStartupInfo->dwFillAttribute %x", lpStartupInfo->dwFillAttribute));
1570 dprintf(("lpStartupInfo->dwFlags %x", lpStartupInfo->dwFlags));
1571 dprintf(("lpStartupInfo->wShowWindow %x", lpStartupInfo->wShowWindow));
1572 dprintf(("lpStartupInfo->hStdInput %x", lpStartupInfo->hStdInput));
1573 dprintf(("lpStartupInfo->hStdOutput %x", lpStartupInfo->hStdOutput));
1574 dprintf(("lpStartupInfo->hStdError %x", lpStartupInfo->hStdError));
1575 }
1576#endif
1577
1578 // open32 does not support DEBUG_ONLY_THIS_PROCESS
1579 if(dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
1580 dwCreationFlags |= DEBUG_PROCESS;
1581
1582 if(O32_CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes,
1583 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1584 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1585 lpProcessInfo) == TRUE)
1586 {
1587 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
1588 {
1589 if(pThreadDB->o.odin.pidDebuggee != 0)
1590 {
1591 // TODO: handle this
1592 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
1593 }
1594 else
1595 {
1596 pThreadDB->o.odin.pidDebuggee = lpProcessInfo->dwProcessId;
1597 OSLibStartDebugger((ULONG*)&pThreadDB->o.odin.pidDebuggee);
1598 }
1599 }
1600 else pThreadDB->o.odin.pidDebuggee = 0;
1601
1602 return(TRUE);
1603 }
1604
1605 // PH 2001-05-07
1606 // verify why O32_CreateProcess actually failed.
1607 // If GetLastError() == 191 (ERROR_INVALID_EXE_SIGNATURE)
1608 // we can continue to call "PE.EXE".
1609 // Note: Open32 does not translate ERROR_INVALID_EXE_SIGNATURE,
1610 // it is also valid in Win32.
1611 DWORD dwError = GetLastError();
1612 if (ERROR_INVALID_EXE_SIGNATURE != dwError && ERROR_FILE_NOT_FOUND != dwError)
1613 {
1614 dprintf(("CreateProcess: O32_CreateProcess failed with rc=%d, not PE-executable !",
1615 dwError));
1616
1617 // the current value of GetLastError() is still valid.
1618
1619 return FALSE;
1620 }
1621
1622 // else ...
1623
1624 //probably a win32 exe, so run it in the pe loader
1625 if(lpApplicationName) {
1626 if(lpCommandLine) {
1627 //skip exe name in lpCommandLine
1628 //TODO: doesn't work for directories with spaces!
1629 while(*lpCommandLine != 0 && *lpCommandLine != ' ')
1630 lpCommandLine++;
1631
1632 if(*lpCommandLine != 0) {
1633 lpCommandLine++;
1634 }
1635 cmdline = (char *)malloc(strlen(lpApplicationName)+strlen(lpCommandLine) + 16);
1636 sprintf(cmdline, "%s %s", lpApplicationName, lpCommandLine);
1637 }
1638 else {
1639 cmdline = (char *)malloc(strlen(lpApplicationName) + 16);
1640 sprintf(cmdline, "%s", lpApplicationName);
1641 }
1642 }
1643 else {
1644 cmdline = (char *)malloc(strlen(lpCommandLine) + 16);
1645 sprintf(cmdline, "%s", lpCommandLine);
1646 }
1647
1648 char szAppName[255];
1649 DWORD fileAttr;
1650 char *exename = szAppName;
1651 strncpy(szAppName, cmdline, sizeof(szAppName));
1652 szAppName[254] = 0;
1653 if(*exename == '"') {
1654 exename++;
1655 while(*exename != 0 && *exename != '"')
1656 exename++;
1657
1658 if(*exename != 0) {
1659 *exename = 0;
1660 }
1661 exename = &szAppName[1];
1662 }
1663 else {
1664 BOOL fTerminate = FALSE;
1665 DWORD fileAttr;
1666
1667 while(*exename != 0) {
1668 while(*exename != 0 && *exename != ' ')
1669 exename++;
1670
1671 if(*exename != 0) {
1672 *exename = 0;
1673 fTerminate = TRUE;
1674 }
1675
1676 fileAttr = GetFileAttributesA(szAppName);
1677 if(fileAttr != -1 && !(fileAttr & FILE_ATTRIBUTE_DIRECTORY)) {
1678 break;
1679 }
1680 if(fTerminate) {
1681 *exename = ' ';
1682 exename++;
1683 fTerminate = FALSE;
1684 }
1685 }
1686 exename = szAppName;
1687 }
1688 fileAttr = GetFileAttributesA(exename);
1689 if(fileAttr == -1 || (fileAttr & FILE_ATTRIBUTE_DIRECTORY)) {
1690 dprintf(("CreateProcess: can't find executable!"));
1691 SetLastError(ERROR_FILE_NOT_FOUND);
1692 return FALSE;
1693 }
1694
1695 dprintf(("KERNEL32: CreateProcess %s\n", cmdline));
1696
1697 DWORD Characteristics, SubSystem, fNEExe;
1698 if(Win32ImageBase::isPEImage(exename, &Characteristics, &SubSystem, &fNEExe) == 0) {
1699 char *lpszPE;
1700 if(SubSystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) {
1701 lpszPE = "PEC.EXE";
1702 }
1703 else lpszPE = "PE.EXE";
1704
1705 //SvL: Allright. Before we call O32_CreateProcess, we must take care of
1706 // lpCurrentDirectory ourselves. (Open32 ignores it!)
1707 if(lpCurrentDirectory) {
1708 char *newcmdline;
1709
1710 newcmdline = (char *)malloc(strlen(lpCurrentDirectory) + strlen(cmdline) + 32);
1711 sprintf(newcmdline, "%s /OPT:[CURDIR=%s] %s", lpszPE, lpCurrentDirectory, cmdline);
1712 free(cmdline);
1713 cmdline = newcmdline;
1714 }
1715 else {
1716 char *newcmdline;
1717
1718 newcmdline = (char *)malloc(strlen(cmdline) + 16);
1719 sprintf(newcmdline, "%s %s", lpszPE, cmdline);
1720 free(cmdline);
1721 cmdline = newcmdline;
1722 }
1723 rc = O32_CreateProcess(lpszPE, (LPCSTR)cmdline,lpProcessAttributes,
1724 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1725 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1726 lpProcessInfo);
1727 }
1728 else
1729 if(fNEExe) {//16 bits windows app
1730 char *newcmdline;
1731
1732 newcmdline = (char *)malloc(strlen(cmdline) + 16);
1733 sprintf(newcmdline, "w16odin.exe %s", cmdline);
1734 free(cmdline);
1735 cmdline = newcmdline;
1736 //Force Open32 to use DosStartSession (DosExecPgm won't do)
1737 dwCreationFlags |= CREATE_NEW_PROCESS_GROUP;
1738 rc = O32_CreateProcess("w16odin.exe", (LPCSTR)cmdline, lpProcessAttributes,
1739 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1740 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1741 lpProcessInfo);
1742 }
1743 else {//os/2 app??
1744 rc = O32_CreateProcess(NULL, (LPCSTR)cmdline,lpProcessAttributes,
1745 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1746 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1747 lpProcessInfo);
1748 }
1749 if(rc == TRUE)
1750 {
1751 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
1752 {
1753 if(pThreadDB->o.odin.pidDebuggee != 0)
1754 {
1755 // TODO: handle this
1756 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
1757 }
1758 else
1759 {
1760 pThreadDB->o.odin.pidDebuggee = lpProcessInfo->dwProcessId;
1761 OSLibStartDebugger((ULONG*)&pThreadDB->o.odin.pidDebuggee);
1762 }
1763 }
1764 else
1765 pThreadDB->o.odin.pidDebuggee = 0;
1766 }
1767 if(cmdline)
1768 free(cmdline);
1769
1770 if(lpProcessInfo)
1771 dprintf(("KERNEL32: CreateProcess returned %d hPro:%x hThr:%x pid:%x tid:%x\n",
1772 rc, lpProcessInfo->hProcess, lpProcessInfo->hThread,
1773 lpProcessInfo->dwProcessId,lpProcessInfo->dwThreadId));
1774 else
1775 dprintf(("KERNEL32: CreateProcess returned %d\n", rc));
1776 return(rc);
1777}
1778//******************************************************************************
1779//******************************************************************************
1780BOOL WIN32API CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
1781 PSECURITY_ATTRIBUTES lpProcessAttributes,
1782 PSECURITY_ATTRIBUTES lpThreadAttributes,
1783 BOOL bInheritHandles, DWORD dwCreationFlags,
1784 LPVOID lpEnvironment,
1785 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
1786 LPPROCESS_INFORMATION lpProcessInfo)
1787{
1788 BOOL rc;
1789 char *astring1 = 0, *astring2 = 0, *astring3 = 0;
1790
1791 dprintf(("KERNEL32: CreateProcessW"));
1792 if(lpApplicationName)
1793 astring1 = UnicodeToAsciiString((LPWSTR)lpApplicationName);
1794 if(lpCommandLine)
1795 astring2 = UnicodeToAsciiString(lpCommandLine);
1796 if(lpCurrentDirectory)
1797 astring3 = UnicodeToAsciiString((LPWSTR)lpCurrentDirectory);
1798 rc = CreateProcessA(astring1, astring2, lpProcessAttributes, lpThreadAttributes,
1799 bInheritHandles, dwCreationFlags, lpEnvironment,
1800 astring3, (LPSTARTUPINFOA)lpStartupInfo,
1801 lpProcessInfo);
1802 if(astring3) FreeAsciiString(astring3);
1803 if(astring2) FreeAsciiString(astring2);
1804 if(astring1) FreeAsciiString(astring1);
1805 return(rc);
1806}
1807//******************************************************************************
1808//******************************************************************************
1809HINSTANCE WIN32API WinExec(LPCSTR lpCmdLine, UINT nCmdShow)
1810{
1811 STARTUPINFOA startinfo = {0};
1812 PROCESS_INFORMATION procinfo;
1813 DWORD rc;
1814 HINSTANCE hInstance;
1815
1816 dprintf(("KERNEL32: WinExec %s\n", lpCmdLine));
1817 startinfo.dwFlags = nCmdShow;
1818 if(CreateProcessA(NULL, (LPSTR)lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL,
1819 &startinfo, &procinfo) == FALSE)
1820 {
1821 hInstance = (HINSTANCE)GetLastError();
1822 if(hInstance >= 32) {
1823 hInstance = 11;
1824 }
1825 dprintf(("KERNEL32: WinExec failed with rc %d", hInstance));
1826 return hInstance;
1827 }
1828 //block until the launched app waits for input (or a timeout of 15 seconds)
1829 //TODO: Shouldn't call Open32, but the api in user32..
1830 rc = O32_WaitForInputIdle(procinfo.hProcess, 15000);
1831 if(rc != 0) {
1832 dprintf(("WinExec: WaitForInputIdle %x returned %x", procinfo.hProcess, rc));
1833 }
1834 CloseHandle(procinfo.hThread);
1835 CloseHandle(procinfo.hProcess);
1836 return 33;
1837}
1838//******************************************************************************
1839//******************************************************************************
1840VOID WIN32API Sleep(DWORD arg1)
1841{
1842 dprintf2(("KERNEL32: Sleep %d\n", arg1));
1843 O32_Sleep(arg1);
1844}
1845//******************************************************************************
1846//******************************************************************************
1847DWORD WIN32API GetPriorityClass(HANDLE hProcess)
1848{
1849 dprintf(("KERNEL32: GetPriorityClass %x", hProcess));
1850 return O32_GetPriorityClass(hProcess);
1851}
1852//******************************************************************************
1853//******************************************************************************
1854BOOL WIN32API SetPriorityClass(HANDLE hProcess, DWORD dwPriority)
1855{
1856 dprintf(("KERNEL32: SetPriorityClass %x %x", hProcess, dwPriority));
1857 return O32_SetPriorityClass(hProcess, dwPriority);
1858}
1859/**********************************************************************
1860 * LoadModule (KERNEL32.499)
1861 *
1862 * Wine: 20000909
1863 *
1864 * Copyright 1995 Alexandre Julliard
1865 */
1866HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
1867{
1868 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1869 PROCESS_INFORMATION info;
1870 STARTUPINFOA startup;
1871 HINSTANCE hInstance;
1872 LPSTR cmdline, p;
1873 char filename[MAX_PATH];
1874 BYTE len;
1875
1876 dprintf(("LoadModule %s %x", name, paramBlock));
1877
1878 if (!name) return ERROR_FILE_NOT_FOUND;
1879
1880 if (!SearchPathA( NULL, name, ".exe", sizeof(filename), filename, NULL ) &&
1881 !SearchPathA( NULL, name, NULL, sizeof(filename), filename, NULL ))
1882 return GetLastError();
1883
1884 len = (BYTE)params->lpCmdLine[0];
1885 if (!(cmdline = (LPSTR)HeapAlloc( GetProcessHeap(), 0, strlen(filename) + len + 2 )))
1886 return ERROR_NOT_ENOUGH_MEMORY;
1887
1888 strcpy( cmdline, filename );
1889 p = cmdline + strlen(cmdline);
1890 *p++ = ' ';
1891 memcpy( p, params->lpCmdLine + 1, len );
1892 p[len] = 0;
1893
1894 memset( &startup, 0, sizeof(startup) );
1895 startup.cb = sizeof(startup);
1896 if (params->lpCmdShow)
1897 {
1898 startup.dwFlags = STARTF_USESHOWWINDOW;
1899 startup.wShowWindow = params->lpCmdShow[1];
1900 }
1901
1902 if (CreateProcessA( filename, cmdline, NULL, NULL, FALSE, 0,
1903 params->lpEnvAddress, NULL, &startup, &info ))
1904 {
1905 /* Give 15 seconds to the app to come up */
1906 if ( O32_WaitForInputIdle ( info.hProcess, 15000 ) == 0xFFFFFFFF )
1907 dprintf(("ERROR: WaitForInputIdle failed: Error %ld\n", GetLastError() ));
1908 hInstance = 33;
1909 /* Close off the handles */
1910 CloseHandle( info.hThread );
1911 CloseHandle( info.hProcess );
1912 }
1913 else if ((hInstance = GetLastError()) >= 32)
1914 {
1915 dprintf(("ERROR: Strange error set by CreateProcess: %d\n", hInstance ));
1916 hInstance = 11;
1917 }
1918
1919 HeapFree( GetProcessHeap(), 0, cmdline );
1920 return hInstance;
1921}
1922//******************************************************************************
1923//******************************************************************************
1924FARPROC WIN32API GetProcAddress(HMODULE hModule, LPCSTR lpszProc)
1925{
1926 Win32ImageBase *winmod;
1927 FARPROC proc;
1928 ULONG ulAPIOrdinal;
1929
1930 if(hModule == 0 || hModule == -1 || (WinExe && hModule == WinExe->getInstanceHandle())) {
1931 winmod = WinExe;
1932 }
1933 else winmod = (Win32ImageBase *)Win32DllBase::findModule((HINSTANCE)hModule);
1934
1935 if(winmod) {
1936 ulAPIOrdinal = (ULONG)lpszProc;
1937 if (ulAPIOrdinal <= 0x0000FFFF) {
1938 proc = (FARPROC)winmod->getApi((int)ulAPIOrdinal);
1939 }
1940 else proc = (FARPROC)winmod->getApi((char *)lpszProc);
1941 if(proc == 0) {
1942#ifdef DEBUG
1943 if(ulAPIOrdinal <= 0x0000FFFF) {
1944 dprintf(("GetProcAddress %x %x not found!", hModule, ulAPIOrdinal));
1945 }
1946 else dprintf(("GetProcAddress %x %s not found!", hModule, lpszProc));
1947#endif
1948 SetLastError(ERROR_PROC_NOT_FOUND);
1949 }
1950 if(HIWORD(lpszProc))
1951 dprintf(("KERNEL32: GetProcAddress %s from %X returned %X\n", lpszProc, hModule, proc));
1952 else dprintf(("KERNEL32: GetProcAddress %x from %X returned %X\n", lpszProc, hModule, proc));
1953 return proc;
1954 }
1955 proc = O32_GetProcAddress(hModule, lpszProc);
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//******************************************************************************
1962//Retrieve the version
1963//******************************************************************************
1964BOOL SYSTEM GetVersionStruct(char *lpszModName, char *verstruct, ULONG bufLength)
1965{
1966 Win32ImageBase *winimage;
1967 HINSTANCE hDll;
1968 BOOL rc = FALSE;
1969
1970 dprintf(("GetVersionStruct of module %s %x %d", lpszModName, verstruct, bufLength));
1971 if(verstruct == NULL) {
1972 SetLastError(ERROR_INVALID_PARAMETER);
1973 return FALSE;
1974 }
1975 if (WinExe != NULL && WinExe->matchModName(lpszModName)) {
1976 return WinExe->getVersionStruct(verstruct, bufLength);
1977 }
1978 hDll = LoadLibraryExA(lpszModName, 0, LOAD_LIBRARY_AS_DATAFILE);
1979 if(hDll == 0) {
1980 dprintf(("ERROR: GetVersionStruct: Unable to load module!!"));
1981 return 0;
1982 }
1983 winimage = (Win32ImageBase *)Win32DllBase::findModule(hDll);
1984 if(winimage != NULL) {
1985 rc = winimage->getVersionStruct(verstruct, bufLength);
1986 }
1987 else {
1988 dprintf(("GetVersionStruct; just loaded dll %s, but can't find it now!", lpszModName));
1989 DebugInt3();
1990 }
1991 FreeLibrary(hDll);
1992 return rc;
1993}
1994//******************************************************************************
1995//******************************************************************************
1996ULONG SYSTEM GetVersionSize(char *lpszModName)
1997{
1998 Win32ImageBase *winimage;
1999 HINSTANCE hDll;
2000 ULONG size = 0;
2001
2002 dprintf(("GetVersionSize of %s", lpszModName));
2003 if (WinExe != NULL && WinExe->matchModName(lpszModName)) {
2004 return WinExe->getVersionSize();
2005 }
2006
2007 hDll = LoadLibraryExA(lpszModName, 0, LOAD_LIBRARY_AS_DATAFILE);
2008 if(hDll == 0) {
2009 dprintf(("ERROR: GetVersionStruct: Unable to load module!!"));
2010 return 0;
2011 }
2012 winimage = (Win32ImageBase *)Win32DllBase::findModule(hDll);
2013 if(winimage != NULL) {
2014 size = winimage->getVersionSize();
2015 }
2016 else {
2017 dprintf(("GetVersionSize; just loaded dll %s, but can't find it now!", lpszModName));
2018 DebugInt3();
2019 }
2020 FreeLibrary(hDll);
2021 return size;
2022}
2023//******************************************************************************
2024//******************************************************************************
2025ODINFUNCTION1(BOOL,DisableThreadLibraryCalls,HMODULE,hModule)
2026{
2027 Win32DllBase *winmod;
2028 FARPROC proc;
2029 ULONG ulAPIOrdinal;
2030
2031 winmod = Win32DllBase::findModule((HINSTANCE)hModule);
2032 if(winmod)
2033 {
2034 // don't call ATTACH/DETACH thread functions in DLL
2035 winmod->disableThreadLibraryCalls();
2036 return TRUE;
2037 }
2038 else
2039 {
2040 // raise error condition
2041 SetLastError(ERROR_INVALID_HANDLE);
2042 return FALSE;
2043 }
2044}
2045//******************************************************************************
2046//******************************************************************************
Note: See TracBrowser for help on using the repository browser.