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

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

heap corruption fix (initcommandline) + handlemanager class for disks

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