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

Last change on this file since 3400 was 3400, checked in by bird, 25 years ago

Rewrote iLoadLibraryA and moved it into LoadLibraryExA.

File size: 53.1 KB
Line 
1/* $Id: wprocess.cpp,v 1.77 2000-04-16 06:49:07 bird Exp $ */
2
3/*
4 * Win32 process functions
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * NOTE: Even though Odin32 OS/2 apps don't switch FS selectors,
9 * we still allocate a TEB to store misc information.
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 */
14
15
16
17/*******************************************************************************
18* Header Files *
19*******************************************************************************/
20#include <odin.h>
21#include <odinwrap.h>
22#include <os2win.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include <unicode.h>
28#include "windllbase.h"
29#include "winexebase.h"
30#include "windllpeldr.h"
31#include "winexepeldr.h"
32#include "winfakepeldr.h"
33#include <vmutex.h>
34#include <handlemanager.h>
35
36#ifdef __IBMCPP__
37#include <builtin.h>
38#endif
39
40#include "odin32validate.h"
41#include "exceptutil.h"
42#include "oslibmisc.h"
43#include "oslibdebug.h"
44
45#include "console.h"
46#include "cio.h"
47#include "versionos2.h" /*PLF Wed 98-03-18 02:36:51*/
48#include <wprocess.h>
49#include "mmap.h"
50
51#define DBG_LOCALLOG DBG_wprocess
52#include "dbglocal.h"
53
54ODINDEBUGCHANNEL(KERNEL32-WPROCESS)
55
56
57/******************************************************************************
58* Global Variables *
59******************************************************************************/
60BOOL fFreeLibrary = FALSE;
61BOOL fIsOS2Image = FALSE; //TRUE -> Odin32 OS/2 application (not converted!)
62 //FALSE -> otherwise
63//Process database
64PDB ProcessPDB = {0};
65USHORT ProcessTIBSel = 0;
66DWORD *TIBFlatPtr = 0;
67
68//list of thread database structures
69static THDB *threadList = 0;
70static VMutex threadListMutex;
71
72
73
74//******************************************************************************
75//******************************************************************************
76TEB *WIN32API GetThreadTEB()
77{
78 if(TIBFlatPtr == NULL)
79 return 0;
80
81 return (TEB *)*TIBFlatPtr;
82}
83//******************************************************************************
84//******************************************************************************
85THDB *WIN32API GetThreadTHDB()
86{
87 TEB *winteb;
88 THDB *thdb;
89
90 if(TIBFlatPtr == NULL)
91 return 0;
92
93 winteb = (TEB *)*TIBFlatPtr;
94 if(winteb == NULL) {
95 return NULL;
96 }
97 thdb = (THDB *)(winteb+1);
98
99 return thdb;
100}
101//******************************************************************************
102//******************************************************************************
103THDB *WIN32API GetTHDBFromThreadId(ULONG threadId)
104{
105 THDB *thdb = threadList;
106
107 threadListMutex.enter();
108 while(thdb) {
109 if(thdb->threadId == threadId) {
110 break;
111 }
112 thdb = thdb->next;
113 }
114 threadListMutex.leave();
115 return thdb;
116}
117//******************************************************************************
118//******************************************************************************
119THDB *WIN32API GetTHDBFromThreadHandle(HANDLE hThread)
120{
121 THDB *thdb = threadList;
122
123 threadListMutex.enter();
124 while(thdb) {
125 if(thdb->hThread == hThread) {
126 break;
127 }
128 thdb = thdb->next;
129 }
130 threadListMutex.leave();
131 return thdb;
132}
133//******************************************************************************
134// Set up the TIB selector and memory for the current thread
135//******************************************************************************
136TEB *InitializeTIB(BOOL fMainThread)
137{
138 TEB *winteb;
139 THDB *thdb;
140 ULONG hThreadMain;
141 USHORT tibsel;
142
143 //Allocate one dword to store the flat address of our TEB
144 if(fMainThread) {
145 TIBFlatPtr = (DWORD *)OSLibAllocThreadLocalMemory(1);
146 if(TIBFlatPtr == 0) {
147 dprintf(("InitializeTIB: local thread memory alloc failed!!"));
148 DebugInt3();
149 return NULL;
150 }
151 //SvL: This doesn't really create a thread, but only sets up the
152 // handle of thread 0
153 hThreadMain = HMCreateThread(NULL, 0, 0, 0, 0, 0, TRUE);
154 }
155 if(OSLibAllocSel(PAGE_SIZE, &tibsel) == FALSE)
156 {
157 dprintf(("InitializeTIB: selector alloc failed!!"));
158 DebugInt3();
159 return NULL;
160 }
161 winteb = (TEB *)OSLibSelToFlat(tibsel);
162 if(winteb == NULL)
163 {
164 dprintf(("InitializeTIB: DosSelToFlat failed!!"));
165 DebugInt3();
166 return NULL;
167 }
168 memset(winteb, 0, PAGE_SIZE);
169 thdb = (THDB *)(winteb+1);
170 *TIBFlatPtr = (DWORD)winteb;
171
172 winteb->except = (PVOID)-1; /* 00 Head of exception handling chain */
173 winteb->stack_top = (PVOID)OSLibGetTIB(TIB_STACKTOP); /* 04 Top of thread stack */
174 winteb->stack_low = (PVOID)OSLibGetTIB(TIB_STACKLOW); /* 08 Stack low-water mark */
175 winteb->htask16 = (USHORT)OSLibGetPIB(PIB_TASKHNDL); /* 0c Win16 task handle */
176 winteb->stack_sel = getSS(); /* 0e 16-bit stack selector */
177 winteb->self = winteb; /* 18 Pointer to this structure */
178 winteb->flags = TEBF_WIN32; /* 1c Flags */
179 winteb->queue = 0; /* 28 Message queue */
180 winteb->tls_ptr = &thdb->tls_array[0]; /* 2c Pointer to TLS array */
181 winteb->process = &ProcessPDB; /* 30 owning process (used by NT3.51 applets)*/
182
183 memcpy(&thdb->teb, winteb, sizeof(TEB));
184 thdb->process = &ProcessPDB;
185 thdb->exit_code = 0x103; /* STILL_ACTIVE */
186 thdb->teb_sel = tibsel;
187 thdb->OrgTIBSel = GetFS();
188 thdb->pWsockData = NULL;
189 thdb->threadId = GetCurrentThreadId();
190 if(fMainThread) {
191 thdb->hThread = hThreadMain;
192 }
193 else thdb->hThread = GetCurrentThread();
194
195 threadListMutex.enter();
196 THDB *thdblast = threadList;
197 if(!thdblast) {
198 threadList = thdb;
199 }
200 else {
201 while(thdblast->next) {
202 thdblast = thdblast->next;
203 }
204 thdblast->next = thdb;
205 }
206 thdb->next = NULL;
207 threadListMutex.leave();
208
209 if(OSLibGetPIB(PIB_TASKTYPE) == TASKTYPE_PM)
210 {
211 thdb->flags = 0; //todo gui
212 }
213 else thdb->flags = 0; //todo textmode
214
215 if(fMainThread)
216 {
217 //todo initialize PDB during process creation
218 //todo: initialize TLS array if required
219 //TLS in executable always TLS index 0?
220 ProcessTIBSel = tibsel;
221 ProcessPDB.exit_code = 0x103; /* STILL_ACTIVE */
222 ProcessPDB.threads = 1;
223 ProcessPDB.running_threads = 1;
224 ProcessPDB.ring0_threads = 1;
225 ProcessPDB.system_heap = GetProcessHeap();
226 ProcessPDB.parent = 0;
227 ProcessPDB.group = &ProcessPDB;
228 ProcessPDB.priority = 8; /* Normal */
229 ProcessPDB.heap = ProcessPDB.system_heap; /* will be changed later on */
230 ProcessPDB.next = NULL;
231 ProcessPDB.winver = 0xffff; /* to be determined */
232 ProcessPDB.server_pid = (void *)GetCurrentProcessId();
233
234 GetSystemTime(&ProcessPDB.creationTime);
235
236 /* Initialize the critical section */
237 InitializeCriticalSection( &ProcessPDB.crit_section );
238 }
239 dprintf(("InitializeTIB setup TEB with selector %x", tibsel));
240 dprintf(("InitializeTIB: FS(%x):[0] = %x", GetFS(), QueryExceptionChain()));
241 return winteb;
242}
243//******************************************************************************
244// Destroy the TIB selector and memory for the current thread
245//******************************************************************************
246void DestroyTIB()
247{
248 SHORT orgtibsel;
249 TEB *winteb;
250 THDB *thdb;
251
252 dprintf(("DestroyTIB: FS = %x", GetFS()));
253 dprintf(("DestroyTIB: FS:[0] = %x", QueryExceptionChain()));
254
255 winteb = (TEB *)*TIBFlatPtr;
256 if(winteb) {
257 thdb = (THDB *)(winteb+1);
258 orgtibsel = thdb->OrgTIBSel;
259
260 threadListMutex.enter();
261 THDB *curthdb = threadList;
262 if(curthdb == thdb) {
263 threadList = thdb->next;
264 }
265 else {
266 while(curthdb->next != thdb) {
267 curthdb = curthdb->next;
268 if(curthdb == NULL) {
269 dprintf(("DestroyTIB: couldn't find thdb %x", thdb));
270 DebugInt3();
271 break;
272 }
273 }
274 if(curthdb) {
275 curthdb->next = thdb->next;
276 }
277 }
278 threadListMutex.leave();
279
280 //Restore our original FS selector
281 SetFS(orgtibsel);
282
283 //And free our own
284 OSLibFreeSel(thdb->teb_sel);
285
286 *TIBFlatPtr = 0;
287 }
288 else dprintf(("Already destroyed TIB"));
289
290 dprintf(("DestroyTIB: FS(%x):[0] = %x", GetFS(), QueryExceptionChain()));
291 return;
292}
293/******************************************************************************/
294/******************************************************************************/
295void SetPDBInstance(HINSTANCE hInstance)
296{
297 ProcessPDB.hInstance = hInstance;
298}
299/******************************************************************************/
300/******************************************************************************/
301void WIN32API RestoreOS2TIB()
302{
303 SHORT orgtibsel;
304 TEB *winteb;
305 THDB *thdb;
306
307 //If we're running an Odin32 OS/2 application (not converted!), then we
308 //we don't switch FS selectors
309 if(fIsOS2Image) {
310 return;
311 }
312
313 winteb = (TEB *)*TIBFlatPtr;
314 if(winteb) {
315 thdb = (THDB *)(winteb+1);
316 orgtibsel = thdb->OrgTIBSel;
317
318 //Restore our original FS selector
319 SetFS(orgtibsel);
320 }
321}
322/******************************************************************************/
323/******************************************************************************/
324USHORT WIN32API SetWin32TIB()
325{
326 SHORT win32tibsel;
327 TEB *winteb;
328 THDB *thdb;
329
330 //If we're running an Odin32 OS/2 application (not converted!), then we
331 //we don't switch FS selectors
332 if(fIsOS2Image) {
333 return GetFS();
334 }
335
336 winteb = (TEB *)*TIBFlatPtr;
337 if(winteb) {
338 thdb = (THDB *)(winteb+1);
339 win32tibsel = thdb->teb_sel;
340
341 //Restore our win32 FS selector
342 return SetReturnFS(win32tibsel);
343 }
344 else {
345 //we didn't create this thread, so allocate a selector now
346 //NOTE: Possible memory leak (i.e. DART threads in WINMM)
347 winteb = InitializeTIB();
348 if(winteb == NULL) {
349 DebugInt3();
350 return GetFS();
351 }
352 thdb = (THDB *)(winteb+1);
353 win32tibsel = thdb->teb_sel;
354
355 //Restore our win32 FS selector
356 return SetReturnFS(win32tibsel);
357 }
358 // nested calls are OK, OS2ToWinCallback for instance
359 //else DebugInt3();
360
361 return GetFS();
362}
363//******************************************************************************
364//******************************************************************************
365VOID WIN32API ExitProcess(DWORD exitcode)
366{
367 dprintf(("KERNEL32: ExitProcess %d\n", exitcode));
368 dprintf(("KERNEL32: ExitProcess FS = %x\n", GetFS()));
369
370 SetOS2ExceptionChain(-1);
371
372 if(WinExe) {
373 delete(WinExe);
374 WinExe = NULL;
375 }
376
377 //Note: Needs to be done after deleting WinExe (destruction of exe + dll objects)
378 //Flush and delete all open memory mapped files
379 Win32MemMap::deleteAll();
380
381 //Restore original OS/2 TIB selector
382 DestroyTIB();
383 SetExceptionChain((ULONG)-1);
384
385 //avoid crashes since win32 & OS/2 exception handler aren't identical
386 //(terminate process generates two exceptions)
387 /* @@@PH 1998/02/12 Added Console Support */
388 if (iConsoleIsActive())
389 iConsoleWaitClose();
390
391 O32_ExitProcess(exitcode);
392}
393//******************************************************************************
394//******************************************************************************
395BOOL WIN32API FreeLibrary(HINSTANCE hinstance)
396{
397 Win32DllBase *winmod;
398 BOOL rc;
399
400 winmod = Win32DllBase::findModule(hinstance);
401 if(winmod) {
402 dprintf(("FreeLibrary %s", winmod->getName()));
403 //Only free it when the nrDynamicLibRef != 0
404 //This prevent problems after ExitProcess:
405 //i.e. dll A is referenced by our exe and loaded with LoadLibrary by dll B
406 // During ExitProcess it's unloaded once (before dll B), dll B calls
407 // FreeLibrary, but our exe also has a reference -> unloaded too many times
408 if(winmod->isDynamicLib()) {
409 winmod->decDynamicLib();
410 winmod->Release();
411 }
412 else {
413 dprintf(("Skipping dynamic unload as nrDynamicLibRef == 0"));
414 }
415 return(TRUE);
416 }
417 dprintf(("KERNEL32: FreeLibrary %s %X\n", OSLibGetDllName(hinstance), hinstance));
418
419 //TODO: Not thread safe
420 fFreeLibrary = TRUE; //ditch dll
421 rc = O32_FreeLibrary(hinstance);
422 fFreeLibrary = FALSE;
423 dprintf(("FreeLibrary returned %X\n", rc));
424 return(TRUE);
425}
426/******************************************************************************/
427//******************************************************************************
428HINSTANCE16 WIN32API LoadLibrary16(LPCTSTR lpszLibFile)
429{
430 dprintf(("ERROR: LoadLibrary16 %s, not implemented", lpszLibFile));
431 return 0;
432}
433//******************************************************************************
434//******************************************************************************
435VOID WIN32API FreeLibrary16(HINSTANCE16 hinstance)
436{
437 dprintf(("ERROR: FreeLibrary16 %x, not implemented", hinstance));
438}
439//******************************************************************************
440//******************************************************************************
441FARPROC WIN32API GetProcAddress16(HMODULE hModule, LPCSTR lpszProc)
442{
443 dprintf(("ERROR: GetProcAddress16 %x %x, not implemented", hModule, lpszProc));
444 return 0;
445}
446//******************************************************************************
447
448/**
449 * LoadLibraryA can be used to map a DLL module into the calling process's
450 * addressspace. It returns a handle that can be used with GetProcAddress to
451 * get addresses of exported entry points (functions and variables).
452 *
453 * LoadLibraryA can also be used to map executable (.exe) modules into the
454 * address to access resources in the module. However, LoadLibrary can't be
455 * used to run an executable (.exe) module.
456 *
457 * @returns Handle to the library which was loaded.
458 * @param lpszLibFile Pointer to zero ASCII string giving the name of the
459 * executable image (either a Dll or an Exe) which is to be
460 * loaded.
461 *
462 * If no extention is specified the default .DLL extention is
463 * appended to the name. End the filename with an '.' if the
464 * file does not have an extention (and don't want the .DLL
465 * appended).
466 *
467 * If no path is specified, this API will use the Odin32
468 * standard search strategy to find the file. This strategy
469 * is described in the method Win32ImageBase::findDLL.
470 *
471 * This API likes to have backslashes (\), but will probably
472 * accept forward slashes too. Win32 SDK docs says that it
473 * should not contain forward slashes.
474 *
475 * Win32 SDK docs adds:
476 * "The name specified is the file name of the module and
477 * is not related to the name stored in the library module
478 * itself, as specified by the LIBRARY keyword in the
479 * module-definition (.def) file."
480 *
481 * @sketch Call LoadLibraryExA with flags set to 0.
482 * @status Odin32 Completely Implemented.
483 * @author Sander van Leeuwen (sandervl@xs4all.nl)
484 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
485 * @remark Forwards to LoadLibraryExA.
486 */
487HINSTANCE WIN32API LoadLibraryA(LPCTSTR lpszLibFile)
488{
489 HINSTANCE hDll;
490
491 dprintf(("KERNEL32: LoadLibraryA(%s) --> LoadLibraryExA(lpszLibFile, 0, 0)",
492 lpszLibFile));
493 hDll = LoadLibraryExA(lpszLibFile, 0, 0);
494 dprintf(("KERNEL32: LoadLibraryA(%s) returns 0x%x",
495 lpszLibFile, hDll));
496 return hDll;
497}
498
499
500/**
501 * LoadLibraryW can be used to map a DLL module into the calling process's
502 * addressspace. It returns a handle that can be used with GetProcAddress to
503 * get addresses of exported entry points (functions and variables).
504 *
505 * LoadLibraryW can also be used to map executable (.exe) modules into the
506 * address to access resources in the module. However, LoadLibrary can't be
507 * used to run an executable (.exe) module.
508 *
509 * @returns Handle to the library which was loaded.
510 * @param lpszLibFile Pointer to Unicode string giving the name of
511 * the executable image (either a Dll or an Exe) which is to
512 * be loaded.
513 *
514 * If no extention is specified the default .DLL extention is
515 * appended to the name. End the filename with an '.' if the
516 * file does not have an extention (and don't want the .DLL
517 * appended).
518 *
519 * If no path is specified, this API will use the Odin32
520 * standard search strategy to find the file. This strategy
521 * is described in the method Win32ImageBase::findDLL.
522 *
523 * This API likes to have backslashes (\), but will probably
524 * accept forward slashes too. Win32 SDK docs says that it
525 * should not contain forward slashes.
526 *
527 * Win32 SDK docs adds:
528 * "The name specified is the file name of the module and
529 * is not related to the name stored in the library module
530 * itself, as specified by the LIBRARY keyword in the
531 * module-definition (.def) file."
532 *
533 * @sketch Convert Unicode name to ascii.
534 * Call LoadLibraryExA with flags set to 0.
535 * free ascii string.
536 * @status Odin32 Completely Implemented.
537 * @author Sander van Leeuwen (sandervl@xs4all.nl)
538 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
539 * @remark Forwards to LoadLibraryExA.
540 */
541HINSTANCE WIN32API LoadLibraryW(LPCWSTR lpszLibFile)
542{
543 char * pszAsciiLibFile;
544 HINSTANCE hDll;
545
546 pszAsciiLibFile = UnicodeToAsciiString(lpszLibFile);
547 dprintf(("KERNEL32: LoadLibraryW(%s) --> LoadLibraryExA(lpszLibFile, 0, 0)",
548 pszAsciiLibFile));
549 hDll = LoadLibraryExA(pszAsciiLibFile, NULL, 0);
550 dprintf(("KERNEL32: LoadLibraryW(%s) returns 0x%x",
551 pszAsciiLibFile, hDll));
552 free(pszAsciiLibFile);
553
554 return hDll;
555}
556
557
558/**
559 * LoadLibraryExA can be used to map a DLL module into the calling process's
560 * addressspace. It returns a handle that can be used with GetProcAddress to
561 * get addresses of exported entry points (functions and variables).
562 *
563 * LoadLibraryExA can also be used to map executable (.exe) modules into the
564 * address to access resources in the module. However, LoadLibrary can't be
565 * used to run an executable (.exe) module.
566 *
567 * @returns Handle to the library which was loaded.
568 * @param lpszLibFile Pointer to Unicode string giving the name of
569 * the executable image (either a Dll or an Exe) which is to
570 * be loaded.
571 *
572 * If no extention is specified the default .DLL extention is
573 * appended to the name. End the filename with an '.' if the
574 * file does not have an extention (and don't want the .DLL
575 * appended).
576 *
577 * If no path is specified, this API will use the Odin32
578 * standard search strategy to find the file. This strategy
579 * is described in the method Win32ImageBase::findDLL.
580 * This may be alterned by the LOAD_WITH_ALTERED_SEARCH_PATH
581 * flag, see below.
582 *
583 * This API likes to have backslashes (\), but will probably
584 * accept forward slashes too. Win32 SDK docs says that it
585 * should not contain forward slashes.
586 *
587 * Win32 SDK docs adds:
588 * "The name specified is the file name of the module and
589 * is not related to the name stored in the library module
590 * itself, as specified by the LIBRARY keyword in the
591 * module-definition (.def) file."
592 *
593 * @param hFile Reserved. Must be 0.
594 *
595 * @param dwFlags Flags which specifies the taken when loading the module.
596 * The value 0 makes it identical to LoadLibraryA/W.
597 *
598 * Flags:
599 *
600 * DONT_RESOLVE_DLL_REFERENCES
601 * (WinNT/2K feature): Don't load imported modules and
602 * hence don't resolve imported symbols.
603 * DllMain isn't called either. (Which is obvious since
604 * it may use one of the importe symbols.)
605 *
606 * On the other hand, if this flag is NOT set, the system
607 * load imported modules, resolves imported symbols, calls
608 * DllMain for process and thread init and term (if wished
609 * by the module).
610 *
611 * partially implemented yet - imports are resolved it seems.
612 *
613 * LOAD_LIBRARY_AS_DATAFILE
614 * If this flag is set, the module is mapped into the
615 * address space but is not prepared for execution. Though
616 * it's preparted for resource API. Hence, you'll use this
617 * flag when you want to load a DLL for extracting
618 * messages or resources from it.
619 *
620 * The resulting handle can be used with any Odin32 API
621 * which operates on resources.
622 * (WinNt/2k supports all resource APIs while Win9x don't
623 * support the specialized resource APIs: LoadBitmap,
624 * LoadCursor, LoadIcon, LoadImage, LoadMenu.)
625 *
626 * not implemented yet.
627 *
628 * LOAD_WITH_ALTERED_SEARCH_PATH
629 * If this flag is set and lpszLibFile specifies a path
630 * we'll use an alternative file search strategy to find
631 * imported modules. This stratgy is simply to use the
632 * path of the module being loaded instead of the path
633 * of the executable module as the first location
634 * to search for imported modules.
635 *
636 * If this flag is clear, the standard Odin32 standard
637 * search strategy. See Win32ImageBase::findDll for
638 * further information.
639 *
640 * not implemented yet.
641 *
642 * @status Open32 Partially Implemented.
643 * @author Sander van Leeuwen (sandervl@xs4all.nl)
644 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
645 * @remark Forwards to LoadLibraryExA.
646 */
647HINSTANCE WIN32API LoadLibraryExA(LPCTSTR lpszLibFile, HANDLE hFile, DWORD dwFlags)
648{
649 HINSTANCE hDll;
650 Win32DllBase * pModule;
651 char szModname[CCHMAXPATH];
652 BOOL fPath; /* Flags which is set if the */
653 /* lpszLibFile contains a path. */
654 BOOL fPE; /* isPEImage return value. */
655
656 /** @sketch
657 * Some parameter validations is probably useful.
658 */
659 if (!VALID_PSZ(lpszLibFile))
660 {
661 dprintf(("KERNEL32: LoadLibraryExA(0x%x, 0x%x, 0x%x): invalid pointer lpszLibFile = 0x%x\n",
662 lpszLibFile, hFile, dwFlags, lpszLibFile));
663 SetLastError(ERROR_INVALID_PARAMETER); //or maybe ERROR_ACCESS_DENIED is more appropriate?
664 return NULL;
665 }
666 if (!VALID_PSZMAXSIZE(lpszLibFile, CCHMAXPATH))
667 {
668 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): lpszLibFile string too long, %d\n",
669 lpszLibFile, hFile, dwFlags, strlen(lpszLibFile)));
670 SetLastError(ERROR_INVALID_PARAMETER);
671 return NULL;
672 }
673 if ((dwFlags & ~(DONT_RESOLVE_DLL_REFERENCES | LOAD_WITH_ALTERED_SEARCH_PATH | LOAD_LIBRARY_AS_DATAFILE)) != 0)
674 {
675 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): dwFlags have invalid or unsupported flags\n",
676 lpszLibFile, hFile, dwFlags));
677 SetLastError(ERROR_INVALID_PARAMETER);
678 }
679
680
681 /** @sketch
682 * First we'll see if the module is allready loaded.
683 * IF allready loaded THEN
684 * IF it's a LX dll which isn't loaded and we're using the PeLoader THEN
685 * Set Load library.
686 * Endif
687 * Inc dynamic reference count.
688 * Inc reference count.
689 * RETURN instance handle.
690 * Endif
691 */
692 pModule = Win32DllBase::findModule((LPSTR)lpszLibFile);
693 if (pModule)
694 {
695 if (pModule->isLxDll() && !pModule->isLoaded() && fPeLoader)
696 {
697 //can happen with i.e. wininet
698 //wininet depends on wsock32; when the app loads wsock32 afterwards
699 //with LoadLibrary or as a child of another dll, we need to make
700 //sure it's loaded once with DosLoadModule
701 pModule->setLoadLibrary();
702 }
703 pModule->incDynamicLib();
704 pModule->AddRef();
705 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): returns 0x%x. Dll found %s",
706 lpszLibFile, hFile, dwFlags, pModule->getInstanceHandle(), pModule->getFullPath()));
707 return pModule->getInstanceHandle();
708 }
709
710
711 /** @sketch
712 * Test if lpszLibFile has a path or not.
713 * Copy the lpszLibFile to szModname, rename the dll and uppercase the name.
714 * IF it hasn't a path THEN
715 * Issue a findDll to find the dll/executable to be loaded.
716 * IF the Dll isn't found THEN
717 * Set last error and RETURN.
718 * Endif.
719 * Endif
720 */
721 fPath = strchr(lpszLibFile, '\\') || strchr(lpszLibFile, '/');
722 strcpy(szModname, lpszLibFile);
723 Win32DllBase::renameDll(szModname);
724 strupr(szModname);
725
726 if (!fPath)
727 {
728 char szModName2[CCHMAXPATH];
729 strcpy(szModName2, szModname);
730 if (!Win32ImageBase::findDll(szModName2, szModname, sizeof(szModname)))
731 {
732 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): module wasn't found. returns NULL",
733 lpszLibFile, hFile, dwFlags));
734 SetLastError(ERROR_FILE_NOT_FOUND);
735 return NULL;
736 }
737 }
738
739
740 /** @sketch
741 * IF dwFlags == 0 THEN
742 * Try load the executable using LoadLibrary
743 * IF successfully loaded THEN
744 * IF LX dll and is using the PE Loader THEN
745 * Set Load library.
746 * Inc reference count.
747 * Endif
748 * Inc dynamic reference count.
749 * RETURN successfully.
750 * Endif
751 * Endif
752 */
753 if (dwFlags == 0)
754 {
755 hDll = O32_LoadLibrary(szModname);
756 if (hDll)
757 {
758 /* OS/2 dll, system dll, converted dll or win32k took care of it.*/
759 pModule = Win32DllBase::findModule(hDll);
760 if (pModule)
761 {
762 if (pModule->isLxDll() && fPeLoader)
763 {
764 pModule->setLoadLibrary();
765 pModule->AddRef();
766 }
767 pModule->incDynamicLib();
768 }
769 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): returns 0x%x. Loaded %s using O32_LoadLibrary.",
770 lpszLibFile, hFile, dwFlags, hDll, szModname));
771 return hDll;
772 }
773 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): O32_LoadLibrary(%s) failed. LastError=%d",
774 lpszLibFile, hFile, dwFlags, szModname, GetLastError()));
775 }
776 else
777 hDll = NULL;
778
779
780 /** @sketch
781 * If PE image THEN
782 * Check again(!) if the module is allready loaded.
783 * IF Allready loaded THEN
784 * Inc dynamic ref count.
785 * Inc ref count.
786 * hDll <- instance handle.
787 * ELSE
788 * Try load the file using the Win32PeLdrDll class.
789 * <sketch continued further down>
790 * Endif
791 * Try load the file using the peldr.
792 * Else
793 * Set last error.
794 * (hDll is NULL)
795 * Endif
796 * return hDll.
797 */
798
799 if ((fPE = Win32ImageBase::isPEImage(szModname)))
800 {
801 pModule = Win32DllBase::findModule(szModname); /* This should _NEVER_ succeed! */
802 if (pModule)
803 {
804 pModule->incDynamicLib();
805 pModule->AddRef();
806 hDll = pModule->getInstanceHandle();
807 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): returns 0x%x, Dll found (2) %s",
808 lpszLibFile, hFile, dwFlags, pModule->getInstanceHandle(), pModule->getFullPath()));
809 }
810 else
811 {
812 /* TODO EXE loading - will use the Win32PeLdrRsrcImg for that */
813 Win32PeLdrDll * peldrDll;
814
815 peldrDll = new Win32PeLdrDll(szModname);
816 if (peldrDll == NULL)
817 {
818 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Failed to created instance of Win32PeLdrDll. returns NULL.",
819 lpszLibFile, hFile, dwFlags));
820 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
821 return NULL;
822 }
823
824 /** @sketch
825 * Process dwFlags
826 */
827 if (dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE))
828 {
829 peldrDll->setNoEntryCalls();
830 //peldrDll->setDontProcessImports(); not implemented?
831 }
832 if (dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH)
833 {
834 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Warning dwFlags LOAD_WITH_ALTERED_SEARCH_PATH is not implemented.",
835 lpszLibFile, hFile, dwFlags));
836 //peldrDll->setLoadWithAlteredSearchPath();
837 }
838 if (dwFlags & LOAD_LIBRARY_AS_DATAFILE)
839 {
840 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Warning dwFlags LOAD_LIBRARY_AS_DATAFILE is not implemented.",
841 lpszLibFile, hFile, dwFlags));
842 //peldrDll->setLoadAsDatafile();
843 }
844
845 /** @sketch
846 * Initiate the peldr DLL.
847 * IF successful init THEN
848 * Inc dynamic ref count.
849 * Inc ref count.
850 * Attach to process
851 * IF successful THEN
852 * hDLL <- instance handle.
853 * ELSE
854 * set last error
855 * delete Win32PeLdrDll instance.
856 * Endif
857 * ELSE
858 * set last error
859 * delete Win32PeLdrDll instance.
860 * Endif.
861 */
862 if (peldrDll->init(0))
863 {
864 peldrDll->incDynamicLib();
865 peldrDll->AddRef();
866 if (peldrDll->attachProcess())
867 hDll = peldrDll->getInstanceHandle();
868 else
869 {
870 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): attachProcess call to Win32PeLdrDll instance failed. returns NULL.",
871 lpszLibFile, hFile, dwFlags));
872 SetLastError(ERROR_DLL_INIT_FAILED);
873 delete peldrDll;
874 }
875 }
876 else
877 {
878 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x): Failed to init Win32PeLdrDll instance. error=%d returns NULL.",
879 lpszLibFile, hFile, dwFlags, peldrDll->getError()));
880 SetLastError(ERROR_INVALID_EXE_SIGNATURE);
881 delete peldrDll;
882 }
883 }
884 }
885 else
886 {
887 dprintf(("KERNEL32: LoadLibraryExA(%s, 0x%x, 0x%x) library were found (%s) but it's not loadable!",
888 lpszLibFile, hFile, dwFlags, szModname));
889 SetLastError(ERROR_INVALID_EXE_SIGNATURE);
890 }
891
892 return hDll;
893}
894
895
896/**
897 * LoadLibraryExW can be used to map a DLL module into the calling process's
898 * addressspace. It returns a handle that can be used with GetProcAddress to
899 * get addresses of exported entry points (functions and variables).
900 *
901 * LoadLibraryExW can also be used to map executable (.exe) modules into the
902 * address to access resources in the module. However, LoadLibrary can't be
903 * used to run an executable (.exe) module.
904 *
905 * @returns Handle to the library which was loaded.
906 * @param lpszLibFile Pointer to Unicode string giving the name of
907 * the executable image (either a Dll or an Exe) which is to
908 * be loaded.
909 *
910 * If no extention is specified the default .DLL extention is
911 * appended to the name. End the filename with an '.' if the
912 * file does not have an extention (and don't want the .DLL
913 * appended).
914 *
915 * If no path is specified, this API will use the Odin32
916 * standard search strategy to find the file. This strategy
917 * is described in the method Win32ImageBase::findDLL.
918 * This may be alterned by the LOAD_WITH_ALTERED_SEARCH_PATH
919 * flag, see below.
920 *
921 * This API likes to have backslashes (\), but will probably
922 * accept forward slashes too. Win32 SDK docs says that it
923 * should not contain forward slashes.
924 *
925 * Win32 SDK docs adds:
926 * "The name specified is the file name of the module and
927 * is not related to the name stored in the library module
928 * itself, as specified by the LIBRARY keyword in the
929 * module-definition (.def) file."
930 *
931 * @param hFile Reserved. Must be 0.
932 *
933 * @param dwFlags Flags which specifies the taken when loading the module.
934 * The value 0 makes it identical to LoadLibraryA/W.
935 *
936 * Flags:
937 *
938 * DONT_RESOLVE_DLL_REFERENCES
939 * (WinNT/2K feature): Don't load imported modules and
940 * hence don't resolve imported symbols.
941 * DllMain isn't called either. (Which is obvious since
942 * it may use one of the importe symbols.)
943 *
944 * On the other hand, if this flag is NOT set, the system
945 * load imported modules, resolves imported symbols, calls
946 * DllMain for process and thread init and term (if wished
947 * by the module).
948 *
949 * LOAD_LIBRARY_AS_DATAFILE
950 * If this flag is set, the module is mapped into the
951 * address space but is not prepared for execution. Though
952 * it's preparted for resource API. Hence, you'll use this
953 * flag when you want to load a DLL for extracting
954 * messages or resources from it.
955 *
956 * The resulting handle can be used with any Odin32 API
957 * which operates on resources.
958 * (WinNt/2k supports all resource APIs while Win9x don't
959 * support the specialized resource APIs: LoadBitmap,
960 * LoadCursor, LoadIcon, LoadImage, LoadMenu.)
961 *
962 * LOAD_WITH_ALTERED_SEARCH_PATH
963 * If this flag is set and lpszLibFile specifies a path
964 * we'll use an alternative file search strategy to find
965 * imported modules. This stratgy is simply to use the
966 * path of the module being loaded instead of the path
967 * of the executable module as the first location
968 * to search for imported modules.
969 *
970 * If this flag is clear, the standard Odin32 standard
971 * search strategy. See Win32ImageBase::findDll for
972 * further information.
973 *
974 * @sketch Convert Unicode name to ascii.
975 * Call LoadLibraryExA.
976 * Free ascii string.
977 * return handle from LoadLibraryExA.
978 * @status Open32 Partially Implemented.
979 * @author Sander van Leeuwen (sandervl@xs4all.nl)
980 * knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
981 * @remark Forwards to LoadLibraryExA.
982 */
983HINSTANCE WIN32API LoadLibraryExW(LPCWSTR lpszLibFile, HANDLE hFile, DWORD dwFlags)
984{
985 char * pszAsciiLibFile;
986 HINSTANCE hDll;
987
988 pszAsciiLibFile = UnicodeToAsciiString(lpszLibFile);
989 dprintf(("KERNEL32: LoadLibraryExW(%s, 0x%x, 0x%x) --> LoadLibraryExA",
990 pszAsciiLibFile, hFile, dwFlags));
991 hDll = LoadLibraryExA(pszAsciiLibFile, hFile, dwFlags);
992 dprintf(("KERNEL32: LoadLibraryExW(%s, 0x%x, 0x%x) returns 0x%x",
993 pszAsciiLibFile, hFile, dwFlags, hDll));
994 free(pszAsciiLibFile);
995
996 return hDll;
997}
998//******************************************************************************
999//******************************************************************************
1000LPCSTR WIN32API GetCommandLineA()
1001{
1002 LPTSTR cmdline = NULL;
1003
1004 if(WinExe) {
1005 cmdline = WinExe->getCommandLineA();
1006 }
1007 if(cmdline == NULL) //not used for converted exes
1008 cmdline = O32_GetCommandLine();
1009
1010 dprintf(("KERNEL32: GetCommandLine %s\n", cmdline));
1011 dprintf(("KERNEL32: FS = %x\n", GetFS()));
1012 return(cmdline);
1013}
1014//******************************************************************************
1015//******************************************************************************
1016LPCWSTR WIN32API GetCommandLineW(void)
1017{
1018 static WCHAR *UnicodeCmdLine = NULL;
1019 char *asciicmdline = NULL;
1020
1021 dprintf(("KERNEL32: FS = %x\n", GetFS()));
1022
1023 if(UnicodeCmdLine)
1024 return(UnicodeCmdLine); //already called before
1025
1026 if(WinExe) {
1027 if(WinExe->getCommandLineW())
1028 return WinExe->getCommandLineW();
1029 }
1030 if(asciicmdline == NULL) //not used for converted exes
1031 asciicmdline = O32_GetCommandLine();
1032
1033 if(asciicmdline) {
1034 UnicodeCmdLine = (WCHAR *)malloc(strlen(asciicmdline)*2 + 2);
1035 AsciiToUnicode(asciicmdline, UnicodeCmdLine);
1036 dprintf(("KERNEL32: OS2GetCommandLineW: %s\n", asciicmdline));
1037 return(UnicodeCmdLine);
1038 }
1039 dprintf(("KERNEL32: OS2GetCommandLineW: asciicmdline == NULL\n"));
1040 return NULL;
1041}
1042//******************************************************************************
1043//******************************************************************************
1044DWORD WIN32API GetModuleFileNameA(HMODULE hinstModule, LPTSTR lpszPath, DWORD cchPath)
1045{
1046 DWORD rc;
1047 Win32ImageBase *module;
1048 char *fpath = NULL;
1049
1050 dprintf(("GetModuleFileName %X", hinstModule));
1051 if(hinstModule == 0 || hinstModule == -1 || (WinExe && hinstModule == WinExe->getInstanceHandle())) {
1052 module = (Win32ImageBase *)WinExe;
1053 }
1054 else {
1055 module = (Win32ImageBase *)Win32DllBase::findModule(hinstModule);
1056 }
1057
1058 if(module) {
1059 fpath = module->getFullPath();
1060 }
1061 if(fpath) {
1062 //SvL: 13-9-98: +1
1063 rc = min(strlen(fpath)+1, cchPath);
1064 strncpy(lpszPath, fpath, rc);
1065 }
1066 else rc = O32_GetModuleFileName(hinstModule, lpszPath, cchPath);
1067
1068 if(rc) {
1069 dprintf(("KERNEL32: GetModuleFileName %s %d\n", lpszPath, hinstModule));
1070 }
1071 return(rc);
1072}
1073//******************************************************************************
1074//******************************************************************************
1075DWORD WIN32API GetModuleFileNameW(HMODULE hModule, LPWSTR lpFileName, DWORD nSize)
1076{
1077 char *asciifilename = (char *)malloc(nSize+1);
1078 DWORD rc;
1079
1080 dprintf(("KERNEL32: OSLibGetModuleFileNameW\n"));
1081 rc = GetModuleFileNameA(hModule, asciifilename, nSize);
1082 if(rc) AsciiToUnicode(asciifilename, lpFileName);
1083 free(asciifilename);
1084 return(rc);
1085}
1086//******************************************************************************
1087//NOTE: GetModuleHandleA does NOT support files with multiple dots (i.e.
1088// very.weird.exe)
1089//******************************************************************************
1090HANDLE WIN32API GetModuleHandleA(LPCTSTR lpszModule)
1091{
1092 HANDLE hMod;
1093 Win32DllBase *windll;
1094 char szModule[CCHMAXPATH];
1095 BOOL fDllModule = FALSE;
1096
1097 if(lpszModule == NULL) {
1098 if(WinExe)
1099 hMod = WinExe->getInstanceHandle();
1100 else hMod = -1;
1101 }
1102 else {
1103 strcpy(szModule, OSLibStripPath((char *)lpszModule));
1104 strupr(szModule);
1105 if(strstr(szModule, ".DLL")) {
1106 fDllModule = TRUE;
1107 }
1108 else {
1109 if(!strstr(szModule, ".")) {
1110 //if there's no extension or trainling dot, we
1111 //assume it's a dll (see Win32 SDK docs)
1112 fDllModule = TRUE;
1113 }
1114 }
1115 char *dot = strstr(szModule, ".");
1116 if(dot)
1117 *dot = 0;
1118
1119 if(!fDllModule && WinExe && !strcmpi(szModule, WinExe->getModuleName())) {
1120 hMod = WinExe->getInstanceHandle();
1121 }
1122 else {
1123 windll = Win32DllBase::findModule(szModule);
1124 if(windll) {
1125 hMod = windll->getInstanceHandle();
1126 }
1127 else hMod = OSLibiGetModuleHandleA((char *)lpszModule);
1128 }
1129 }
1130
1131 dprintf(("KERNEL32: GetModuleHandle %s returned %X\n", lpszModule, hMod));
1132 return(hMod);
1133}
1134//******************************************************************************
1135//******************************************************************************
1136HMODULE WIN32API GetModuleHandleW(LPCWSTR arg1)
1137{
1138 HMODULE rc;
1139 char *astring;
1140
1141 astring = UnicodeToAsciiString((LPWSTR)arg1);
1142 rc = GetModuleHandleA(astring);
1143 dprintf(("KERNEL32: OS2GetModuleHandleW %s returned %X\n", astring, rc));
1144 FreeAsciiString(astring);
1145 return(rc);
1146}
1147//******************************************************************************
1148//******************************************************************************
1149BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
1150 LPSECURITY_ATTRIBUTES lpProcessAttributes,
1151 LPSECURITY_ATTRIBUTES lpThreadAttributes,
1152 BOOL bInheritHandles, DWORD dwCreationFlags,
1153 LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
1154 LPSTARTUPINFOA lpStartupInfo,
1155 LPPROCESS_INFORMATION lpProcessInfo )
1156{
1157 THDB *pThreadDB = (THDB*)GetThreadTHDB();
1158 char *cmdline = NULL;
1159 BOOL rc;
1160
1161 dprintf(("KERNEL32: CreateProcessA %s cline:%s inherit:%d cFlags:%x Env:%x CurDir:%s StartupFlags:%x\n",
1162 lpApplicationName, lpCommandLine, bInheritHandles, dwCreationFlags,
1163 lpEnvironment, lpCurrentDirectory, lpStartupInfo));
1164
1165 // open32 does not support DEBUG_ONLY_THIS_PROCESS
1166 if(dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
1167 dwCreationFlags |= DEBUG_PROCESS;
1168
1169 if(O32_CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes,
1170 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1171 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1172 lpProcessInfo) == TRUE)
1173 {
1174 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
1175 {
1176 if(pThreadDB->pidDebuggee != 0)
1177 {
1178 // TODO: handle this
1179 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
1180 }
1181 else
1182 {
1183 pThreadDB->pidDebuggee = lpProcessInfo->dwProcessId;
1184 OSLibStartDebugger((ULONG*)&pThreadDB->pidDebuggee);
1185 }
1186 }
1187 else pThreadDB->pidDebuggee = 0;
1188
1189 return(TRUE);
1190 }
1191 //probably a win32 exe, so run it in the pe loader
1192 if(lpApplicationName) {
1193 if(lpCommandLine) {
1194 //skip exe name in lpCommandLine
1195 while(*lpCommandLine != 0 && *lpCommandLine != ' ')
1196 lpCommandLine++;
1197
1198 if(*lpCommandLine != 0) {
1199 lpCommandLine++;
1200 }
1201 cmdline = (char *)malloc(strlen(lpApplicationName)+strlen(lpCommandLine) + 16);
1202 sprintf(cmdline, "PE.EXE %s %s", lpApplicationName, lpCommandLine);
1203 }
1204 else {
1205 cmdline = (char *)malloc(strlen(lpApplicationName) + 16);
1206 sprintf(cmdline, "PE.EXE %s", lpApplicationName);
1207 }
1208 }
1209 else {
1210 cmdline = (char *)malloc(strlen(lpCommandLine) + 16);
1211 sprintf(cmdline, "PE.EXE %s", lpCommandLine);
1212 }
1213 dprintf(("KERNEL32: CreateProcess %s\n", cmdline));
1214 rc = O32_CreateProcess("PE.EXE", (LPCSTR)cmdline,lpProcessAttributes,
1215 lpThreadAttributes, bInheritHandles, dwCreationFlags,
1216 lpEnvironment, lpCurrentDirectory, lpStartupInfo,
1217 lpProcessInfo);
1218 if(rc == TRUE) {
1219 if (dwCreationFlags & DEBUG_PROCESS && pThreadDB != NULL)
1220 {
1221 if(pThreadDB->pidDebuggee != 0)
1222 {
1223 // TODO: handle this
1224 dprintf(("KERNEL32: CreateProcess ERROR: This thread is already a debugger\n"));
1225 }
1226 else
1227 {
1228 pThreadDB->pidDebuggee = lpProcessInfo->dwProcessId;
1229 OSLibStartDebugger((ULONG*)&pThreadDB->pidDebuggee);
1230 }
1231 }
1232 else
1233 pThreadDB->pidDebuggee = 0;
1234 }
1235 if(cmdline)
1236 free(cmdline);
1237
1238 if(lpProcessInfo)
1239 dprintf(("KERNEL32: CreateProcess returned %d hPro:%x hThr:%x pid:%x tid:%x\n",
1240 rc, lpProcessInfo->hProcess, lpProcessInfo->hThread,
1241 lpProcessInfo->dwProcessId,lpProcessInfo->dwThreadId));
1242 else
1243 dprintf(("KERNEL32: CreateProcess returned %d\n", rc));
1244 return(rc);
1245}
1246//******************************************************************************
1247//******************************************************************************
1248BOOL WIN32API CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
1249 PSECURITY_ATTRIBUTES lpProcessAttributes,
1250 PSECURITY_ATTRIBUTES lpThreadAttributes,
1251 BOOL bInheritHandles, DWORD dwCreationFlags,
1252 LPVOID lpEnvironment,
1253 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
1254 LPPROCESS_INFORMATION lpProcessInfo)
1255{
1256 BOOL rc;
1257 char *astring1 = 0, *astring2 = 0, *astring3 = 0;
1258
1259 dprintf(("KERNEL32: CreateProcessW"));
1260 if(lpApplicationName)
1261 astring1 = UnicodeToAsciiString((LPWSTR)lpApplicationName);
1262 if(lpCommandLine)
1263 astring2 = UnicodeToAsciiString(lpCommandLine);
1264 if(lpCurrentDirectory)
1265 astring3 = UnicodeToAsciiString((LPWSTR)lpCurrentDirectory);
1266 rc = CreateProcessA(astring1, astring2, lpProcessAttributes, lpThreadAttributes,
1267 bInheritHandles, dwCreationFlags, lpEnvironment,
1268 astring3, (LPSTARTUPINFOA)lpStartupInfo,
1269 lpProcessInfo);
1270 if(astring3) FreeAsciiString(astring3);
1271 if(astring2) FreeAsciiString(astring2);
1272 if(astring1) FreeAsciiString(astring1);
1273 return(rc);
1274}
1275//******************************************************************************
1276//******************************************************************************
1277HINSTANCE WIN32API WinExec(LPCSTR lpCmdLine, UINT nCmdShow)
1278{
1279 STARTUPINFOA startinfo = {0};
1280 PROCESS_INFORMATION procinfo;
1281 DWORD rc;
1282
1283 dprintf(("KERNEL32: WinExec %s\n", lpCmdLine));
1284 startinfo.dwFlags = nCmdShow;
1285 if(CreateProcessA(NULL, (LPSTR)lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL,
1286 &startinfo, &procinfo) == FALSE)
1287 {
1288 return 0;
1289 }
1290 //block until the launched app waits for input (or a timeout of 15 seconds)
1291 //TODO: Shouldn't call Open32, but the api in user32..
1292 rc = O32_WaitForInputIdle(procinfo.hProcess, 15000);
1293 if(rc != 0) {
1294 dprintf(("WinExec: WaitForInputIdle %x returned %x", procinfo.hProcess, rc));
1295 }
1296 return procinfo.hProcess; //correct?
1297}
1298//******************************************************************************
1299//******************************************************************************
1300FARPROC WIN32API GetProcAddress(HMODULE hModule, LPCSTR lpszProc)
1301{
1302 Win32ImageBase *winmod;
1303 FARPROC proc;
1304 ULONG ulAPIOrdinal;
1305
1306 winmod = Win32ImageBase::findModule(hModule);
1307 if(winmod) {
1308 ulAPIOrdinal = (ULONG)lpszProc;
1309 if (ulAPIOrdinal <= 0x0000FFFF) {
1310 proc = (FARPROC)winmod->getApi((int)ulAPIOrdinal);
1311 }
1312 else proc = (FARPROC)winmod->getApi((char *)lpszProc);
1313 if(proc == 0) {
1314 SetLastError(ERROR_PROC_NOT_FOUND);
1315 }
1316 return proc;
1317 }
1318 proc = O32_GetProcAddress(hModule, lpszProc);
1319 if(HIWORD(lpszProc))
1320 dprintf(("KERNEL32: GetProcAddress %s from %X returned %X\n", lpszProc, hModule, proc));
1321 else dprintf(("KERNEL32: GetProcAddress %x from %X returned %X\n", lpszProc, hModule, proc));
1322 return(proc);
1323}
1324//******************************************************************************
1325//Retrieve the version
1326//******************************************************************************
1327BOOL SYSTEM GetVersionStruct(char *lpszModName, char *verstruct, ULONG bufLength)
1328{
1329 Win32ImageBase *winimage;
1330 Win32PeLdrRsrcImg *rsrcimg;
1331
1332 dprintf(("GetVersionStruct of module %s", lpszModName));
1333 if(WinExe && !stricmp(WinExe->getFullPath(), lpszModName)) {
1334 winimage = (Win32ImageBase *)WinExe;
1335 }
1336 else {
1337 winimage = (Win32ImageBase *)Win32DllBase::findModule(lpszModName);
1338 if(winimage == NULL)
1339 {
1340 char modname[CCHMAXPATH];
1341
1342 strcpy(modname, lpszModName);
1343 //rename dll if necessary (i.e. OLE32 -> OLE32OS2)
1344 Win32DllBase::renameDll(modname);
1345
1346 if(Win32ImageBase::isPEImage(modname) == FALSE)
1347 {
1348 HINSTANCE hInstance;
1349
1350 //must be an LX dll, just load it (app will probably load it anyway)
1351 hInstance = LoadLibraryA(modname);
1352 if(hInstance == 0)
1353 return 0;
1354 winimage = (Win32ImageBase *)Win32DllBase::findModule(hInstance);
1355 if(winimage) {
1356 return winimage->getVersionStruct(verstruct, bufLength);
1357 }
1358 return 0;
1359 }
1360 //SvL: Try to load it
1361 rsrcimg = new Win32PeLdrRsrcImg(modname);
1362 if(rsrcimg == NULL)
1363 return 0;
1364
1365 rsrcimg->init(0);
1366 if(rsrcimg->getError() != NO_ERROR)
1367 {
1368 dprintf(("GetVersionStruct can't load %s\n", modname));
1369 delete rsrcimg;
1370 return(FALSE);
1371 }
1372 BOOL rc = rsrcimg->getVersionStruct(verstruct, bufLength);
1373 delete rsrcimg;
1374 return rc;
1375 }
1376 }
1377 return winimage->getVersionStruct(verstruct, bufLength);
1378}
1379//******************************************************************************
1380//******************************************************************************
1381ULONG SYSTEM GetVersionSize(char *lpszModName)
1382{
1383 Win32ImageBase *winimage;
1384 Win32PeLdrRsrcImg *rsrcimg;
1385
1386 dprintf(("GetVersionSize of %s\n", lpszModName));
1387
1388 if(WinExe && !stricmp(WinExe->getFullPath(), lpszModName)) {
1389 winimage = (Win32ImageBase *)WinExe;
1390 }
1391 else {
1392 winimage = (Win32ImageBase *)Win32DllBase::findModule(lpszModName);
1393 if(winimage == NULL)
1394 {
1395 char modname[CCHMAXPATH];
1396
1397 strcpy(modname, lpszModName);
1398 //rename dll if necessary (i.e. OLE32 -> OLE32OS2)
1399 Win32DllBase::renameDll(modname);
1400
1401 if(Win32ImageBase::isPEImage(modname) == FALSE)
1402 {
1403 HINSTANCE hInstance;
1404
1405 //must be an LX dll, just load it (app will probably load it anyway)
1406 hInstance = LoadLibraryA(modname);
1407 if(hInstance == 0)
1408 return 0;
1409 winimage = (Win32ImageBase *)Win32DllBase::findModule(hInstance);
1410 if(winimage) {
1411 return winimage->getVersionSize();
1412 }
1413 return 0;
1414 }
1415
1416 //SvL: Try to load it
1417 rsrcimg = new Win32PeLdrRsrcImg(modname);
1418 if(rsrcimg == NULL)
1419 return 0;
1420
1421 rsrcimg->init(0);
1422 if(rsrcimg->getError() != NO_ERROR)
1423 {
1424 dprintf(("GetVersionSize can't load %s\n", modname));
1425 delete rsrcimg;
1426 return(FALSE);
1427 }
1428 int size = rsrcimg->getVersionSize();
1429 delete rsrcimg;
1430 return size;
1431 }
1432 }
1433 return winimage->getVersionSize();
1434}
1435//******************************************************************************
1436//TODO:What does this do exactly??
1437//******************************************************************************
1438ODINFUNCTION1(BOOL,DisableThreadLibraryCalls,HMODULE,hModule)
1439{
1440 Win32DllBase *winmod;
1441 FARPROC proc;
1442 ULONG ulAPIOrdinal;
1443
1444 winmod = Win32DllBase::findModule((HINSTANCE)hModule);
1445 if(winmod)
1446 {
1447 // don't call ATTACH/DETACH thread functions in DLL
1448 winmod->setThreadLibraryCalls(FALSE);
1449 return TRUE;
1450 }
1451 else
1452 {
1453 // raise error condition
1454 SetLastError(ERROR_INVALID_HANDLE);
1455 return FALSE;
1456 }
1457}
1458//******************************************************************************
1459//******************************************************************************
Note: See TracBrowser for help on using the repository browser.