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

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

pe loader fixes, add system32\drivers dir during installation, add build date + time during kernel32 load

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