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

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

PDB.exit_code must point to some unknown structure

File size: 77.4 KB
Line 
1/* $Id: wprocess.cpp,v 1.126 2001-06-15 18:58:39 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[255];
1663 DWORD fileAttr;
1664 char *exename = szAppName;
1665 strncpy(szAppName, cmdline, sizeof(szAppName));
1666 szAppName[254] = 0;
1667 if(*exename == '"') {
1668 exename++;
1669 while(*exename != 0 && *exename != '"')
1670 exename++;
1671
1672 if(*exename != 0) {
1673 *exename = 0;
1674 }
1675 exename = &szAppName[1];
1676 }
1677 else {
1678 BOOL fTerminate = FALSE;
1679 DWORD fileAttr;
1680
1681 while(*exename != 0) {
1682 while(*exename != 0 && *exename != ' ')
1683 exename++;
1684
1685 if(*exename != 0) {
1686 *exename = 0;
1687 fTerminate = TRUE;
1688 }
1689
1690 fileAttr = GetFileAttributesA(szAppName);
1691 if(fileAttr != -1 && !(fileAttr & FILE_ATTRIBUTE_DIRECTORY)) {
1692 break;
1693 }
1694 if(fTerminate) {
1695 *exename = ' ';
1696 exename++;
1697 fTerminate = FALSE;
1698 }
1699 }
1700 exename = szAppName;
1701 }
1702 fileAttr = GetFileAttributesA(exename);
1703 if(fileAttr == -1 || (fileAttr & FILE_ATTRIBUTE_DIRECTORY)) {
1704 dprintf(("CreateProcess: can't find executable!"));
1705 SetLastError(ERROR_FILE_NOT_FOUND);
1706 return FALSE;
1707 }
1708
1709 dprintf(("KERNEL32: CreateProcess %s\n", cmdline));
1710
1711 DWORD Characteristics, SubSystem, fNEExe;
1712 if(Win32ImageBase::isPEImage(exename, &Characteristics, &SubSystem, &fNEExe) == 0) {
1713 char *lpszPE;
1714 if(SubSystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) {
1715 lpszPE = "PEC.EXE";
1716 }
1717 else lpszPE = "PE.EXE";
1718
1719 //SvL: Allright. Before we call O32_CreateProcess, we must take care of
1720 // lpCurrentDirectory ourselves. (Open32 ignores it!)
1721 if(lpCurrentDirectory) {
1722 char *newcmdline;
1723
1724 newcmdline = (char *)malloc(strlen(lpCurrentDirectory) + strlen(cmdline) + 32);
1725 sprintf(newcmdline, "%s /OPT:[CURDIR=%s] %s", lpszPE, lpCurrentDirectory, cmdline);
1726 free(cmdline);
1727 cmdline = newcmdline;
1728 }
1729 else {
1730 char *newcmdline;
1731
1732 newcmdline = (char *)malloc(strlen(cmdline) + 16);
1733 sprintf(newcmdline, "%s %s", lpszPE, cmdline);
1734 free(cmdline);
1735 cmdline = newcmdline;
1736 }
1737 rc = O32_CreateProcess(lpszPE, (LPCSTR)cmdline,lpProcessAttributes,
1738 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1739 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1740 lpProcessInfo);
1741 }
1742 else
1743 if(fNEExe) {//16 bits windows app
1744 char *newcmdline;
1745
1746 newcmdline = (char *)malloc(strlen(cmdline) + 16);
1747 sprintf(newcmdline, "w16odin.exe %s", cmdline);
1748 free(cmdline);
1749 cmdline = newcmdline;
1750 //Force Open32 to use DosStartSession (DosExecPgm won't do)
1751 dwCreationFlags |= CREATE_NEW_PROCESS_GROUP;
1752 rc = O32_CreateProcess("w16odin.exe", (LPCSTR)cmdline, lpProcessAttributes,
1753 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1754 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1755 lpProcessInfo);
1756 }
1757 else {//os/2 app??
1758 rc = O32_CreateProcess(NULL, (LPCSTR)cmdline,lpProcessAttributes,
1759 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1760 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1761 lpProcessInfo);
1762 }
1763 if(rc == TRUE)
1764 {
1765 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
1766 {
1767 if(pThreadDB->o.odin.pidDebuggee != 0)
1768 {
1769 // TODO: handle this
1770 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
1771 }
1772 else
1773 {
1774 pThreadDB->o.odin.pidDebuggee = lpProcessInfo->dwProcessId;
1775 OSLibStartDebugger((ULONG*)&pThreadDB->o.odin.pidDebuggee);
1776 }
1777 }
1778 else
1779 pThreadDB->o.odin.pidDebuggee = 0;
1780 }
1781 if(cmdline)
1782 free(cmdline);
1783
1784 if(lpProcessInfo)
1785 dprintf(("KERNEL32: CreateProcess returned %d hPro:%x hThr:%x pid:%x tid:%x\n",
1786 rc, lpProcessInfo->hProcess, lpProcessInfo->hThread,
1787 lpProcessInfo->dwProcessId,lpProcessInfo->dwThreadId));
1788 else
1789 dprintf(("KERNEL32: CreateProcess returned %d\n", rc));
1790 return(rc);
1791}
1792//******************************************************************************
1793//******************************************************************************
1794BOOL WIN32API CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
1795 PSECURITY_ATTRIBUTES lpProcessAttributes,
1796 PSECURITY_ATTRIBUTES lpThreadAttributes,
1797 BOOL bInheritHandles, DWORD dwCreationFlags,
1798 LPVOID lpEnvironment,
1799 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
1800 LPPROCESS_INFORMATION lpProcessInfo)
1801{
1802 BOOL rc;
1803 char *astring1 = 0, *astring2 = 0, *astring3 = 0;
1804
1805 dprintf(("KERNEL32: CreateProcessW"));
1806 if(lpApplicationName)
1807 astring1 = UnicodeToAsciiString((LPWSTR)lpApplicationName);
1808 if(lpCommandLine)
1809 astring2 = UnicodeToAsciiString(lpCommandLine);
1810 if(lpCurrentDirectory)
1811 astring3 = UnicodeToAsciiString((LPWSTR)lpCurrentDirectory);
1812 rc = CreateProcessA(astring1, astring2, lpProcessAttributes, lpThreadAttributes,
1813 bInheritHandles, dwCreationFlags, lpEnvironment,
1814 astring3, (LPSTARTUPINFOA)lpStartupInfo,
1815 lpProcessInfo);
1816 if(astring3) FreeAsciiString(astring3);
1817 if(astring2) FreeAsciiString(astring2);
1818 if(astring1) FreeAsciiString(astring1);
1819 return(rc);
1820}
1821//******************************************************************************
1822//******************************************************************************
1823HINSTANCE WIN32API WinExec(LPCSTR lpCmdLine, UINT nCmdShow)
1824{
1825 STARTUPINFOA startinfo = {0};
1826 PROCESS_INFORMATION procinfo;
1827 DWORD rc;
1828 HINSTANCE hInstance;
1829
1830 dprintf(("KERNEL32: WinExec %s\n", lpCmdLine));
1831 startinfo.dwFlags = nCmdShow;
1832 if(CreateProcessA(NULL, (LPSTR)lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL,
1833 &startinfo, &procinfo) == FALSE)
1834 {
1835 hInstance = (HINSTANCE)GetLastError();
1836 if(hInstance >= 32) {
1837 hInstance = 11;
1838 }
1839 dprintf(("KERNEL32: WinExec failed with rc %d", hInstance));
1840 return hInstance;
1841 }
1842 //block until the launched app waits for input (or a timeout of 15 seconds)
1843 //TODO: Shouldn't call Open32, but the api in user32..
1844 rc = O32_WaitForInputIdle(procinfo.hProcess, 15000);
1845 if(rc != 0) {
1846 dprintf(("WinExec: WaitForInputIdle %x returned %x", procinfo.hProcess, rc));
1847 }
1848 CloseHandle(procinfo.hThread);
1849 CloseHandle(procinfo.hProcess);
1850 return 33;
1851}
1852//******************************************************************************
1853//******************************************************************************
1854VOID WIN32API Sleep(DWORD arg1)
1855{
1856 dprintf2(("KERNEL32: Sleep %d\n", arg1));
1857 O32_Sleep(arg1);
1858}
1859//******************************************************************************
1860//******************************************************************************
1861DWORD WIN32API GetPriorityClass(HANDLE hProcess)
1862{
1863 dprintf(("KERNEL32: GetPriorityClass %x", hProcess));
1864 return O32_GetPriorityClass(hProcess);
1865}
1866//******************************************************************************
1867//******************************************************************************
1868BOOL WIN32API SetPriorityClass(HANDLE hProcess, DWORD dwPriority)
1869{
1870 dprintf(("KERNEL32: SetPriorityClass %x %x", hProcess, dwPriority));
1871 return O32_SetPriorityClass(hProcess, dwPriority);
1872}
1873/**********************************************************************
1874 * LoadModule (KERNEL32.499)
1875 *
1876 * Wine: 20000909
1877 *
1878 * Copyright 1995 Alexandre Julliard
1879 */
1880HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
1881{
1882 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1883 PROCESS_INFORMATION info;
1884 STARTUPINFOA startup;
1885 HINSTANCE hInstance;
1886 LPSTR cmdline, p;
1887 char filename[MAX_PATH];
1888 BYTE len;
1889
1890 dprintf(("LoadModule %s %x", name, paramBlock));
1891
1892 if (!name) return ERROR_FILE_NOT_FOUND;
1893
1894 if (!SearchPathA( NULL, name, ".exe", sizeof(filename), filename, NULL ) &&
1895 !SearchPathA( NULL, name, NULL, sizeof(filename), filename, NULL ))
1896 return GetLastError();
1897
1898 len = (BYTE)params->lpCmdLine[0];
1899 if (!(cmdline = (LPSTR)HeapAlloc( GetProcessHeap(), 0, strlen(filename) + len + 2 )))
1900 return ERROR_NOT_ENOUGH_MEMORY;
1901
1902 strcpy( cmdline, filename );
1903 p = cmdline + strlen(cmdline);
1904 *p++ = ' ';
1905 memcpy( p, params->lpCmdLine + 1, len );
1906 p[len] = 0;
1907
1908 memset( &startup, 0, sizeof(startup) );
1909 startup.cb = sizeof(startup);
1910 if (params->lpCmdShow)
1911 {
1912 startup.dwFlags = STARTF_USESHOWWINDOW;
1913 startup.wShowWindow = params->lpCmdShow[1];
1914 }
1915
1916 if (CreateProcessA( filename, cmdline, NULL, NULL, FALSE, 0,
1917 params->lpEnvAddress, NULL, &startup, &info ))
1918 {
1919 /* Give 15 seconds to the app to come up */
1920 if ( O32_WaitForInputIdle ( info.hProcess, 15000 ) == 0xFFFFFFFF )
1921 dprintf(("ERROR: WaitForInputIdle failed: Error %ld\n", GetLastError() ));
1922 hInstance = 33;
1923 /* Close off the handles */
1924 CloseHandle( info.hThread );
1925 CloseHandle( info.hProcess );
1926 }
1927 else if ((hInstance = GetLastError()) >= 32)
1928 {
1929 dprintf(("ERROR: Strange error set by CreateProcess: %d\n", hInstance ));
1930 hInstance = 11;
1931 }
1932
1933 HeapFree( GetProcessHeap(), 0, cmdline );
1934 return hInstance;
1935}
1936//******************************************************************************
1937//******************************************************************************
1938FARPROC WIN32API GetProcAddress(HMODULE hModule, LPCSTR lpszProc)
1939{
1940 Win32ImageBase *winmod;
1941 FARPROC proc;
1942 ULONG ulAPIOrdinal;
1943
1944 if(hModule == 0 || hModule == -1 || (WinExe && hModule == WinExe->getInstanceHandle())) {
1945 winmod = WinExe;
1946 }
1947 else winmod = (Win32ImageBase *)Win32DllBase::findModule((HINSTANCE)hModule);
1948
1949 if(winmod) {
1950 ulAPIOrdinal = (ULONG)lpszProc;
1951 if (ulAPIOrdinal <= 0x0000FFFF) {
1952 proc = (FARPROC)winmod->getApi((int)ulAPIOrdinal);
1953 }
1954 else proc = (FARPROC)winmod->getApi((char *)lpszProc);
1955 if(proc == 0) {
1956#ifdef DEBUG
1957 if(ulAPIOrdinal <= 0x0000FFFF) {
1958 dprintf(("GetProcAddress %x %x not found!", hModule, ulAPIOrdinal));
1959 }
1960 else dprintf(("GetProcAddress %x %s not found!", hModule, lpszProc));
1961#endif
1962 SetLastError(ERROR_PROC_NOT_FOUND);
1963 }
1964 if(HIWORD(lpszProc))
1965 dprintf(("KERNEL32: GetProcAddress %s from %X returned %X\n", lpszProc, hModule, proc));
1966 else dprintf(("KERNEL32: GetProcAddress %x from %X returned %X\n", lpszProc, hModule, proc));
1967 return proc;
1968 }
1969 proc = O32_GetProcAddress(hModule, lpszProc);
1970 if(HIWORD(lpszProc))
1971 dprintf(("KERNEL32: GetProcAddress %s from %X returned %X\n", lpszProc, hModule, proc));
1972 else dprintf(("KERNEL32: GetProcAddress %x from %X returned %X\n", lpszProc, hModule, proc));
1973 return(proc);
1974}
1975//******************************************************************************
1976//Retrieve the version
1977//******************************************************************************
1978BOOL SYSTEM GetVersionStruct(char *lpszModName, char *verstruct, ULONG bufLength)
1979{
1980 Win32ImageBase *winimage;
1981 HINSTANCE hDll;
1982 BOOL rc = FALSE;
1983
1984 dprintf(("GetVersionStruct of module %s %x %d", lpszModName, verstruct, bufLength));
1985 if(verstruct == NULL) {
1986 SetLastError(ERROR_INVALID_PARAMETER);
1987 return FALSE;
1988 }
1989 if (WinExe != NULL && WinExe->matchModName(lpszModName)) {
1990 return WinExe->getVersionStruct(verstruct, bufLength);
1991 }
1992 hDll = LoadLibraryExA(lpszModName, 0, LOAD_LIBRARY_AS_DATAFILE);
1993 if(hDll == 0) {
1994 dprintf(("ERROR: GetVersionStruct: Unable to load module!!"));
1995 return 0;
1996 }
1997 winimage = (Win32ImageBase *)Win32DllBase::findModule(hDll);
1998 if(winimage != NULL) {
1999 rc = winimage->getVersionStruct(verstruct, bufLength);
2000 }
2001 else {
2002 dprintf(("GetVersionStruct; just loaded dll %s, but can't find it now!", lpszModName));
2003 DebugInt3();
2004 }
2005 FreeLibrary(hDll);
2006 return rc;
2007}
2008//******************************************************************************
2009//******************************************************************************
2010ULONG SYSTEM GetVersionSize(char *lpszModName)
2011{
2012 Win32ImageBase *winimage;
2013 HINSTANCE hDll;
2014 ULONG size = 0;
2015
2016 dprintf(("GetVersionSize of %s", lpszModName));
2017 if (WinExe != NULL && WinExe->matchModName(lpszModName)) {
2018 return WinExe->getVersionSize();
2019 }
2020
2021 hDll = LoadLibraryExA(lpszModName, 0, LOAD_LIBRARY_AS_DATAFILE);
2022 if(hDll == 0) {
2023 dprintf(("ERROR: GetVersionStruct: Unable to load module!!"));
2024 return 0;
2025 }
2026 winimage = (Win32ImageBase *)Win32DllBase::findModule(hDll);
2027 if(winimage != NULL) {
2028 size = winimage->getVersionSize();
2029 }
2030 else {
2031 dprintf(("GetVersionSize; just loaded dll %s, but can't find it now!", lpszModName));
2032 DebugInt3();
2033 }
2034 FreeLibrary(hDll);
2035 return size;
2036}
2037//******************************************************************************
2038//******************************************************************************
2039ODINFUNCTION1(BOOL,DisableThreadLibraryCalls,HMODULE,hModule)
2040{
2041 Win32DllBase *winmod;
2042 FARPROC proc;
2043 ULONG ulAPIOrdinal;
2044
2045 winmod = Win32DllBase::findModule((HINSTANCE)hModule);
2046 if(winmod)
2047 {
2048 // don't call ATTACH/DETACH thread functions in DLL
2049 winmod->disableThreadLibraryCalls();
2050 return TRUE;
2051 }
2052 else
2053 {
2054 // raise error condition
2055 SetLastError(ERROR_INVALID_HANDLE);
2056 return FALSE;
2057 }
2058}
2059//******************************************************************************
2060//******************************************************************************
Note: See TracBrowser for help on using the repository browser.