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

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

reset FPU before calling entrypoints; search executable in CreateProcess

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