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

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

LoadLibrary change: refuse to load non-Odin OS/2 dlls

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