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

Last change on this file since 3404 was 3404, checked in by sandervl, 25 years ago

put back dll search method + loadlibraryex fix

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