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

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

Disallow loading of LX files if env.var. ODIN32.FAIL_IF_UNREGISTEREDLX is set. This fixes the int 3 when running Opera/2 on debug odin.

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