Changed some debug messages from one channel to another, to clean up a
[wine/hacks.git] / loader / module.c
blob52d18bee4b697058b782b32540383799cbafcdc0
1 /*
2 * Modules
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <unistd.h>
13 #include "wine/winuser16.h"
14 #include "wine/winbase16.h"
15 #include "windef.h"
16 #include "winerror.h"
17 #include "class.h"
18 #include "file.h"
19 #include "global.h"
20 #include "heap.h"
21 #include "module.h"
22 #include "neexe.h"
23 #include "pe_image.h"
24 #include "dosexe.h"
25 #include "process.h"
26 #include "thread.h"
27 #include "selectors.h"
28 #include "stackframe.h"
29 #include "task.h"
30 #include "debug.h"
31 #include "callback.h"
34 /*************************************************************************
35 * MODULE32_LookupHMODULE
36 * looks for the referenced HMODULE in the current process
38 WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod )
40 WINE_MODREF *wm;
42 if (!hmod)
43 return PROCESS_Current()->exe_modref;
45 if (!HIWORD(hmod)) {
46 ERR(module,"tried to lookup 0x%04x in win32 module handler!\n",hmod);
47 return NULL;
49 for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next )
50 if (wm->module == hmod)
51 return wm;
52 return NULL;
55 /*************************************************************************
56 * MODULE_InitializeDLLs
58 * Call the initialization routines of all DLLs belonging to the
59 * current process. This is somewhat complicated due to the fact that
61 * - we have to respect the module dependencies, i.e. modules implicitly
62 * referenced by another module have to be initialized before the module
63 * itself can be initialized
65 * - the initialization routine of a DLL can itself call LoadLibrary,
66 * thereby introducing a whole new set of dependencies (even involving
67 * the 'old' modules) at any time during the whole process
69 * (Note that this routine can be recursively entered not only directly
70 * from itself, but also via LoadLibrary from one of the called initialization
71 * routines.)
73 static void MODULE_DoInitializeDLLs( WINE_MODREF *wm,
74 DWORD type, LPVOID lpReserved )
76 WINE_MODREF *xwm;
77 int i, skip = FALSE;
79 assert( wm && !(wm->flags & WINE_MODREF_MARKER) );
80 TRACE( module, "(%s,%08x,%ld,%p) - START\n",
81 wm->modname, wm->module, type, lpReserved );
83 /* Tag current MODREF to prevent recursive loop */
84 wm->flags |= WINE_MODREF_MARKER;
86 switch ( type )
88 default:
89 case DLL_PROCESS_ATTACH:
90 case DLL_THREAD_ATTACH:
91 /* Recursively attach all DLLs this one depends on */
92 for ( i = 0; i < wm->nDeps; i++ )
93 if ( wm->deps[i] && !(wm->deps[i]->flags & WINE_MODREF_MARKER) )
94 MODULE_DoInitializeDLLs( wm->deps[i], type, lpReserved );
95 break;
97 case DLL_PROCESS_DETACH:
98 case DLL_THREAD_DETACH:
99 /* Recursively detach all DLLs that depend on this one */
100 for ( xwm = PROCESS_Current()->modref_list; xwm; xwm = xwm->next )
101 if ( !(xwm->flags & WINE_MODREF_MARKER) )
102 for ( i = 0; i < xwm->nDeps; i++ )
103 if ( xwm->deps[i] == wm )
105 MODULE_DoInitializeDLLs( xwm, type, lpReserved );
106 break;
108 break;
111 /* Evaluate module flags */
113 if ( ( wm->flags & WINE_MODREF_NO_DLL_CALLS )
114 || ( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS )
115 || ( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) )
116 skip = TRUE;
118 if ( type == DLL_PROCESS_ATTACH )
119 if ( wm->flags & WINE_MODREF_PROCESS_ATTACHED )
120 skip = TRUE;
121 else
122 wm->flags |= WINE_MODREF_PROCESS_ATTACHED;
124 if ( type == DLL_PROCESS_DETACH )
125 if ( wm->flags & WINE_MODREF_PROCESS_DETACHED )
126 skip = TRUE;
127 else
128 wm->flags |= WINE_MODREF_PROCESS_DETACHED;
130 if ( !skip )
132 /* Now we can call the initialization routine */
133 TRACE( module, "(%s,%08x,%ld,%p) - CALL\n",
134 wm->modname, wm->module, type, lpReserved );
136 switch ( wm->type )
138 case MODULE32_PE:
139 PE_InitDLL( wm, type, lpReserved );
140 break;
142 case MODULE32_ELF:
143 /* no need to do that, dlopen() already does */
144 break;
146 default:
147 ERR(module, "wine_modref type %d not handled.\n", wm->type);
148 break;
152 TRACE( module, "(%s,%08x,%ld,%p) - END\n",
153 wm->modname, wm->module, type, lpReserved );
156 void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved )
158 BOOL inProgress = FALSE;
159 WINE_MODREF *wm;
161 /* Grab the process critical section to protect the recursion flags */
162 /* FIXME: This is probably overkill! */
163 EnterCriticalSection( &PROCESS_Current()->crit_section );
165 TRACE( module, "(%08x,%ld,%p) - START\n", root, type, lpReserved );
167 /* First, check whether initialization is currently in progress */
168 for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
169 if ( wm->flags & WINE_MODREF_MARKER )
171 inProgress = TRUE;
172 break;
175 if ( inProgress )
178 * If this a LoadLibrary call from within an initialization routine,
179 * treat it analogously to an implicitly referenced DLL.
180 * Anything else may not happen at this point!
182 if ( root )
184 wm = MODULE32_LookupHMODULE( root );
185 if ( wm && !(wm->flags & WINE_MODREF_MARKER) )
186 MODULE_DoInitializeDLLs( wm, type, lpReserved );
188 else
189 FIXME(module, "Invalid recursion!\n");
191 else
193 /* If we arrive here, this is the start of an initialization run */
194 if ( !root )
196 /* If called for main EXE, initialize all DLLs */
197 switch ( type )
199 default: /* Hmmm. */
200 case DLL_PROCESS_ATTACH:
201 case DLL_THREAD_ATTACH:
202 for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
203 if ( !wm->next )
204 break;
205 for ( ; wm; wm = wm->prev )
206 if ( !(wm->flags & WINE_MODREF_MARKER) )
207 MODULE_DoInitializeDLLs( wm, type, lpReserved );
208 break;
210 case DLL_PROCESS_DETACH:
211 case DLL_THREAD_DETACH:
212 for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
213 if ( !(wm->flags & WINE_MODREF_MARKER) )
214 MODULE_DoInitializeDLLs( wm, type, lpReserved );
215 break;
218 else
220 /* If called for a specific DLL, initialize only it and its children */
221 wm = MODULE32_LookupHMODULE( root );
222 if (wm) MODULE_DoInitializeDLLs( wm, type, lpReserved );
225 /* We're finished, so we reset all recursion flags */
226 for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
227 wm->flags &= ~WINE_MODREF_MARKER;
230 TRACE( module, "(%08x,%ld,%p) - END\n", root, type, lpReserved );
232 /* Release critical section */
233 LeaveCriticalSection( &PROCESS_Current()->crit_section );
236 /****************************************************************************
237 * DisableThreadLibraryCalls (KERNEL32.74)
239 * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
241 BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
243 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
244 if ( !wm ) return FALSE;
246 wm->flags |= WINE_MODREF_NO_DLL_CALLS;
247 return TRUE;
250 /****************************************************************************
251 * MODULE_IncRefCount
253 static void MODULE_IncRefCount( HMODULE hModule )
255 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
256 if ( !wm ) return;
258 EnterCriticalSection( &PROCESS_Current()->crit_section );
259 wm->refCount++;
260 LeaveCriticalSection( &PROCESS_Current()->crit_section );
263 /****************************************************************************
264 * MODULE_DecRefCount
266 static int MODULE_DecRefCount( HMODULE hModule )
268 int retv;
269 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
270 if ( !wm ) return 0;
272 EnterCriticalSection( &PROCESS_Current()->crit_section );
273 if ( ( retv = wm->refCount ) > 0 ) wm->refCount--;
274 LeaveCriticalSection( &PROCESS_Current()->crit_section );
276 return retv;
280 /***********************************************************************
281 * MODULE_CreateDummyModule
283 * Create a dummy NE module for Win32 or Winelib.
285 HMODULE MODULE_CreateDummyModule( const OFSTRUCT *ofs, LPCSTR modName )
287 HMODULE hModule;
288 NE_MODULE *pModule;
289 SEGTABLEENTRY *pSegment;
290 char *pStr,*s;
291 int len;
292 const char* basename;
294 INT of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
295 + strlen(ofs->szPathName) + 1;
296 INT size = sizeof(NE_MODULE) +
297 /* loaded file info */
298 of_size +
299 /* segment table: DS,CS */
300 2 * sizeof(SEGTABLEENTRY) +
301 /* name table */
303 /* several empty tables */
306 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
307 if (!hModule) return (HMODULE)11; /* invalid exe */
309 FarSetOwner16( hModule, hModule );
310 pModule = (NE_MODULE *)GlobalLock16( hModule );
312 /* Set all used entries */
313 pModule->magic = IMAGE_OS2_SIGNATURE;
314 pModule->count = 1;
315 pModule->next = 0;
316 pModule->flags = 0;
317 pModule->dgroup = 0;
318 pModule->ss = 1;
319 pModule->cs = 2;
320 pModule->heap_size = 0;
321 pModule->stack_size = 0;
322 pModule->seg_count = 2;
323 pModule->modref_count = 0;
324 pModule->nrname_size = 0;
325 pModule->fileinfo = sizeof(NE_MODULE);
326 pModule->os_flags = NE_OSFLAGS_WINDOWS;
327 pModule->expected_version = 0x030a;
328 pModule->self = hModule;
330 /* Set loaded file information */
331 memcpy( pModule + 1, ofs, of_size );
332 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
334 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
335 pModule->seg_table = (int)pSegment - (int)pModule;
336 /* Data segment */
337 pSegment->size = 0;
338 pSegment->flags = NE_SEGFLAGS_DATA;
339 pSegment->minsize = 0x1000;
340 pSegment++;
341 /* Code segment */
342 pSegment->flags = 0;
343 pSegment++;
345 /* Module name */
346 pStr = (char *)pSegment;
347 pModule->name_table = (int)pStr - (int)pModule;
348 if ( modName )
349 basename = modName;
350 else
352 basename = strrchr(ofs->szPathName,'\\');
353 if (!basename) basename = ofs->szPathName;
354 else basename++;
356 len = strlen(basename);
357 if ((s = strchr(basename,'.'))) len = s - basename;
358 if (len > 8) len = 8;
359 *pStr = len;
360 strncpy( pStr+1, basename, len );
361 if (len < 8) pStr[len+1] = 0;
362 pStr += 9;
364 /* All tables zero terminated */
365 pModule->res_table = pModule->import_table = pModule->entry_table =
366 (int)pStr - (int)pModule;
368 NE_RegisterModule( pModule );
369 return hModule;
373 /***********************************************************************
374 * MODULE_GetWndProcEntry16 (not a Windows API function)
376 * Return an entry point from the WPROCS dll.
378 FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name )
380 FARPROC16 ret = NULL;
382 if (__winelib)
384 /* FIXME: hack for Winelib */
385 extern LRESULT ColorDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
386 extern LRESULT FileOpenDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
387 extern LRESULT FileSaveDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
388 extern LRESULT FindTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
389 extern LRESULT PrintDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
390 extern LRESULT PrintSetupDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
391 extern LRESULT ReplaceTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
393 if (!strcmp(name,"ColorDlgProc"))
394 return (FARPROC16)ColorDlgProc16;
395 if (!strcmp(name,"FileOpenDlgProc"))
396 return (FARPROC16)FileOpenDlgProc16;
397 if (!strcmp(name,"FileSaveDlgProc"))
398 return (FARPROC16)FileSaveDlgProc16;
399 if (!strcmp(name,"FindTextDlgProc"))
400 return (FARPROC16)FindTextDlgProc16;
401 if (!strcmp(name,"PrintDlgProc"))
402 return (FARPROC16)PrintDlgProc16;
403 if (!strcmp(name,"PrintSetupDlgProc"))
404 return (FARPROC16)PrintSetupDlgProc16;
405 if (!strcmp(name,"ReplaceTextDlgProc"))
406 return (FARPROC16)ReplaceTextDlgProc16;
407 if (!strcmp(name,"DefResourceHandler"))
408 return (FARPROC16)NE_DefResourceHandler;
409 FIXME(module,"No mapping for %s(), add one in library/miscstubs.c\n",name);
410 assert( FALSE );
411 return NULL;
413 else
415 WORD ordinal;
416 static HMODULE hModule = 0;
418 if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
419 ordinal = NE_GetOrdinal( hModule, name );
420 if (!(ret = NE_GetEntryPoint( hModule, ordinal )))
422 WARN( module, "%s not found\n", name );
423 assert( FALSE );
426 return ret;
430 /**********************************************************************
431 * MODULE_FindModule32
433 * Find a (loaded) win32 module depending on path
434 * The handling of '.' is a bit weird, but we need it that way,
435 * for sometimes the programs use '<name>.exe' and '<name>.dll' and
436 * this is the only way to differentiate. (mainly hypertrm.exe)
438 * RETURNS
439 * the module handle if found
440 * 0 if not
442 HMODULE MODULE_FindModule(
443 LPCSTR path /* [in] pathname of module/library to be found */
445 LPSTR filename;
446 LPSTR dotptr;
447 WINE_MODREF *wm;
449 if (!(filename = strrchr( path, '\\' )))
450 filename = HEAP_strdupA( GetProcessHeap(), 0, path );
451 else
452 filename = HEAP_strdupA( GetProcessHeap(), 0, filename+1 );
453 dotptr=strrchr(filename,'.');
455 for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next ) {
456 LPSTR xmodname,xdotptr;
458 assert (wm->modname);
459 xmodname = HEAP_strdupA( GetProcessHeap(), 0, wm->modname );
460 xdotptr=strrchr(xmodname,'.');
461 if ( (xdotptr && !dotptr) ||
462 (!xdotptr && dotptr)
464 if (dotptr) *dotptr = '\0';
465 if (xdotptr) *xdotptr = '\0';
467 if (!strcasecmp( filename, xmodname)) {
468 HeapFree( GetProcessHeap(), 0, filename );
469 HeapFree( GetProcessHeap(), 0, xmodname );
470 return wm->module;
472 if (dotptr) *dotptr='.';
473 /* FIXME: add paths, shortname */
474 HeapFree( GetProcessHeap(), 0, xmodname );
476 /* if that fails, try looking for the filename... */
477 for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next ) {
478 LPSTR xlname,xdotptr;
480 assert (wm->longname);
481 xlname = strrchr(wm->longname,'\\');
482 if (!xlname)
483 xlname = wm->longname;
484 else
485 xlname++;
486 xlname = HEAP_strdupA( GetProcessHeap(), 0, xlname );
487 xdotptr=strrchr(xlname,'.');
488 if ( (xdotptr && !dotptr) ||
489 (!xdotptr && dotptr)
491 if (dotptr) *dotptr = '\0';
492 if (xdotptr) *xdotptr = '\0';
494 if (!strcasecmp( filename, xlname)) {
495 HeapFree( GetProcessHeap(), 0, filename );
496 HeapFree( GetProcessHeap(), 0, xlname );
497 return wm->module;
499 if (dotptr) *dotptr='.';
500 /* FIXME: add paths, shortname */
501 HeapFree( GetProcessHeap(), 0, xlname );
503 HeapFree( GetProcessHeap(), 0, filename );
504 return 0;
507 /***********************************************************************
508 * MODULE_GetBinaryType
510 * The GetBinaryType function determines whether a file is executable
511 * or not and if it is it returns what type of executable it is.
512 * The type of executable is a property that determines in which
513 * subsystem an executable file runs under.
515 * Binary types returned:
516 * SCS_32BIT_BINARY: A Win32 based application
517 * SCS_DOS_BINARY: An MS-Dos based application
518 * SCS_WOW_BINARY: A Win16 based application
519 * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
520 * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
521 * SCS_OS216_BINARY: A 16bit OS/2 based application ( Not implemented )
523 * Returns TRUE if the file is an executable in which case
524 * the value pointed by lpBinaryType is set.
525 * Returns FALSE if the file is not an executable or if the function fails.
527 * To do so it opens the file and reads in the header information
528 * if the extended header information is not presend it will
529 * assume that that the file is a DOS executable.
530 * If the extended header information is present it will
531 * determine if the file is an 16 or 32 bit Windows executable
532 * by check the flags in the header.
534 * Note that .COM and .PIF files are only recognized by their
535 * file name extension; but Windows does it the same way ...
537 static BOOL MODULE_GetBinaryType( HFILE hfile, OFSTRUCT *ofs,
538 LPDWORD lpBinaryType )
540 IMAGE_DOS_HEADER mz_header;
541 char magic[4], *ptr;
543 /* Seek to the start of the file and read the DOS header information.
545 if ( _llseek( hfile, 0, SEEK_SET ) >= 0 &&
546 _lread( hfile, &mz_header, sizeof(mz_header) ) == sizeof(mz_header) )
548 /* Now that we have the header check the e_magic field
549 * to see if this is a dos image.
551 if ( mz_header.e_magic == IMAGE_DOS_SIGNATURE )
553 BOOL lfanewValid = FALSE;
554 /* We do have a DOS image so we will now try to seek into
555 * the file by the amount indicated by the field
556 * "Offset to extended header" and read in the
557 * "magic" field information at that location.
558 * This will tell us if there is more header information
559 * to read or not.
561 /* But before we do we will make sure that header
562 * structure encompasses the "Offset to extended header"
563 * field.
565 if ( (mz_header.e_cparhdr<<4) >= sizeof(IMAGE_DOS_HEADER) )
566 if ( ( mz_header.e_crlc == 0 && mz_header.e_lfarlc == 0 ) ||
567 ( mz_header.e_lfarlc >= sizeof(IMAGE_DOS_HEADER) ) )
568 if ( mz_header.e_lfanew >= sizeof(IMAGE_DOS_HEADER) &&
569 _llseek( hfile, mz_header.e_lfanew, SEEK_SET ) >= 0 &&
570 _lread( hfile, magic, sizeof(magic) ) == sizeof(magic) )
571 lfanewValid = TRUE;
573 if ( !lfanewValid )
575 /* If we cannot read this "extended header" we will
576 * assume that we have a simple DOS executable.
578 *lpBinaryType = SCS_DOS_BINARY;
579 return TRUE;
581 else
583 /* Reading the magic field succeeded so
584 * we will try to determine what type it is.
586 if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE )
588 /* This is an NT signature.
590 *lpBinaryType = SCS_32BIT_BINARY;
591 return TRUE;
593 else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
595 /* The IMAGE_OS2_SIGNATURE indicates that the
596 * "extended header is a Windows executable (NE)
597 * header. This is a bit misleading, but it is
598 * documented in the SDK. ( for more details see
599 * the neexe.h file )
601 *lpBinaryType = SCS_WOW_BINARY;
602 return TRUE;
604 else
606 /* Unknown extended header, so abort.
608 return FALSE;
614 /* If we get here, we don't even have a correct MZ header.
615 * Try to check the file extension for known types ...
617 ptr = strrchr( ofs->szPathName, '.' );
618 if ( ptr && !strchr( ptr, '\\' ) && !strchr( ptr, '/' ) )
620 if ( !lstrcmpiA( ptr, ".COM" ) )
622 *lpBinaryType = SCS_DOS_BINARY;
623 return TRUE;
626 if ( !lstrcmpiA( ptr, ".PIF" ) )
628 *lpBinaryType = SCS_PIF_BINARY;
629 return TRUE;
633 return FALSE;
636 /***********************************************************************
637 * GetBinaryTypeA [KERNEL32.280]
639 BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
641 BOOL ret = FALSE;
642 HFILE hfile;
643 OFSTRUCT ofs;
645 TRACE( win32, "%s\n", lpApplicationName );
647 /* Sanity check.
649 if ( lpApplicationName == NULL || lpBinaryType == NULL )
650 return FALSE;
652 /* Open the file indicated by lpApplicationName for reading.
654 if ( (hfile = OpenFile( lpApplicationName, &ofs, OF_READ )) == HFILE_ERROR )
655 return FALSE;
657 /* Check binary type
659 ret = MODULE_GetBinaryType( hfile, &ofs, lpBinaryType );
661 /* Close the file.
663 CloseHandle( hfile );
665 return ret;
668 /***********************************************************************
669 * GetBinaryTypeW [KERNEL32.281]
671 BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
673 BOOL ret = FALSE;
674 LPSTR strNew = NULL;
676 TRACE( win32, "%s\n", debugstr_w(lpApplicationName) );
678 /* Sanity check.
680 if ( lpApplicationName == NULL || lpBinaryType == NULL )
681 return FALSE;
683 /* Convert the wide string to a ascii string.
685 strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
687 if ( strNew != NULL )
689 ret = GetBinaryTypeA( strNew, lpBinaryType );
691 /* Free the allocated string.
693 HeapFree( GetProcessHeap(), 0, strNew );
696 return ret;
699 /**********************************************************************
700 * MODULE_CreateUnixProcess
702 static BOOL MODULE_CreateUnixProcess( LPCSTR filename, LPCSTR lpCmdLine,
703 LPSTARTUPINFOA lpStartupInfo,
704 LPPROCESS_INFORMATION lpProcessInfo,
705 BOOL useWine )
707 DOS_FULL_NAME full_name;
708 const char *unixfilename = filename;
709 const char *argv[256], **argptr;
710 BOOL iconic = FALSE;
712 /* Get Unix file name and iconic flag */
714 if ( lpStartupInfo->dwFlags & STARTF_USESHOWWINDOW )
715 if ( lpStartupInfo->wShowWindow == SW_SHOWMINIMIZED
716 || lpStartupInfo->wShowWindow == SW_SHOWMINNOACTIVE )
717 iconic = TRUE;
719 if ( strchr(filename, '/')
720 || strchr(filename, ':')
721 || strchr(filename, '\\') )
723 if ( DOSFS_GetFullName( filename, TRUE, &full_name ) )
724 unixfilename = full_name.long_name;
727 if ( !unixfilename )
729 SetLastError( ERROR_FILE_NOT_FOUND );
730 return FALSE;
733 /* Build argument list */
735 argptr = argv;
736 if ( !useWine )
738 char *p = strdup(lpCmdLine);
739 *argptr++ = unixfilename;
740 if (iconic) *argptr++ = "-iconic";
741 while (1)
743 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
744 if (!*p) break;
745 *argptr++ = p;
746 while (*p && *p != ' ' && *p != '\t') p++;
749 else
751 *argptr++ = "wine";
752 if (iconic) *argptr++ = "-iconic";
753 *argptr++ = lpCmdLine;
755 *argptr++ = 0;
757 /* Fork and execute */
759 if ( !fork() )
761 /* Note: don't use Wine routines here, as this process
762 has not been correctly initialized! */
764 execvp( argv[0], (char**)argv );
766 /* Failed ! */
767 if ( useWine )
768 fprintf( stderr, "CreateProcess: can't exec 'wine %s'\n",
769 lpCmdLine );
770 exit( 1 );
773 /* Fake success return value */
775 memset( lpProcessInfo, '\0', sizeof( *lpProcessInfo ) );
776 lpProcessInfo->hProcess = INVALID_HANDLE_VALUE;
777 lpProcessInfo->hThread = INVALID_HANDLE_VALUE;
779 SetLastError( ERROR_SUCCESS );
780 return TRUE;
783 /***********************************************************************
784 * WinExec16 (KERNEL.166)
786 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
788 return WinExec( lpCmdLine, nCmdShow );
791 /***********************************************************************
792 * WinExec (KERNEL32.566)
794 HINSTANCE WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow )
796 LOADPARAMS params;
797 UINT16 paramCmdShow[2];
799 if (!lpCmdLine)
800 return 2; /* File not found */
802 /* Set up LOADPARAMS buffer for LoadModule */
804 memset( &params, '\0', sizeof(params) );
805 params.lpCmdLine = (LPSTR)lpCmdLine;
806 params.lpCmdShow = paramCmdShow;
807 params.lpCmdShow[0] = 2;
808 params.lpCmdShow[1] = nCmdShow;
810 /* Now load the executable file */
812 return LoadModule( NULL, &params );
815 /**********************************************************************
816 * LoadModule (KERNEL32.499)
818 HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
820 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
821 PROCESS_INFORMATION info;
822 STARTUPINFOA startup;
823 HINSTANCE hInstance;
824 PDB *pdb;
825 TDB *tdb;
827 memset( &startup, '\0', sizeof(startup) );
828 startup.cb = sizeof(startup);
829 startup.dwFlags = STARTF_USESHOWWINDOW;
830 startup.wShowWindow = params->lpCmdShow? params->lpCmdShow[1] : 0;
832 if ( !CreateProcessA( name, params->lpCmdLine,
833 NULL, NULL, FALSE, 0, params->lpEnvAddress,
834 NULL, &startup, &info ) )
836 hInstance = GetLastError();
837 if ( hInstance < 32 ) return hInstance;
839 FIXME( module, "Strange error set by CreateProcess: %d\n", hInstance );
840 return 11;
843 /* Get 16-bit hInstance/hTask from process */
844 pdb = PROCESS_IdToPDB( info.dwProcessId );
845 tdb = pdb? (TDB *)GlobalLock16( pdb->task ) : NULL;
846 hInstance = tdb && tdb->hInstance? tdb->hInstance : pdb? pdb->task : 0;
848 /* Close off the handles */
849 CloseHandle( info.hThread );
850 CloseHandle( info.hProcess );
852 return hInstance;
856 static void get_executable_name( LPCSTR line, LPSTR name, int namelen,
857 LPCSTR *after, BOOL extension )
859 int len = 0;
860 LPCSTR p = NULL, pcmd = NULL;
862 while ( *line == ' ' ) line++;
863 if ( *line == '"' )
865 line++; /* skip '"' */
866 if ((pcmd = strchr(line, '"'))) /* closing '"' available, too ? */
867 len = ++pcmd - line;
869 else
871 if((p = strchr(line, ' ')))
873 len = p - line;
874 pcmd = p+1;
876 else
877 len = strlen(line);
879 len++;
881 if(len > (namelen - 4)) len = namelen - 4;
882 lstrcpynA(name, line, len);
883 if(extension && (strrchr(name, '.') <= strrchr(name, '\\')) )
884 strcat(name, ".exe");
885 if (after) *after = pcmd;
888 /**********************************************************************
889 * CreateProcessA (KERNEL32.171)
891 BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
892 LPSECURITY_ATTRIBUTES lpProcessAttributes,
893 LPSECURITY_ATTRIBUTES lpThreadAttributes,
894 BOOL bInheritHandles, DWORD dwCreationFlags,
895 LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
896 LPSTARTUPINFOA lpStartupInfo,
897 LPPROCESS_INFORMATION lpProcessInfo )
899 BOOL retv = FALSE;
900 HFILE hFile;
901 OFSTRUCT ofs;
902 DWORD type;
903 char name[256];
904 LPCSTR cmdline;
906 /* Get name and command line */
908 if (!lpApplicationName && !lpCommandLine)
910 SetLastError( ERROR_FILE_NOT_FOUND );
911 return FALSE;
914 name[0] = '\0';
916 if (lpApplicationName) {
917 get_executable_name( lpApplicationName, name, sizeof(name), NULL, TRUE );
919 else {
920 get_executable_name( lpCommandLine, name, sizeof ( name ), NULL, TRUE );
922 if (!lpCommandLine)
923 cmdline = lpApplicationName;
924 else cmdline = lpCommandLine;
926 /* Warn if unsupported features are used */
928 if (dwCreationFlags & DEBUG_PROCESS)
929 FIXME(module, "(%s,...): DEBUG_PROCESS ignored\n", name);
930 if (dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
931 FIXME(module, "(%s,...): DEBUG_ONLY_THIS_PROCESS ignored\n", name);
932 if (dwCreationFlags & CREATE_SUSPENDED)
933 FIXME(module, "(%s,...): CREATE_SUSPENDED ignored\n", name);
934 if (dwCreationFlags & DETACHED_PROCESS)
935 FIXME(module, "(%s,...): DETACHED_PROCESS ignored\n", name);
936 if (dwCreationFlags & CREATE_NEW_CONSOLE)
937 FIXME(module, "(%s,...): CREATE_NEW_CONSOLE ignored\n", name);
938 if (dwCreationFlags & NORMAL_PRIORITY_CLASS)
939 FIXME(module, "(%s,...): NORMAL_PRIORITY_CLASS ignored\n", name);
940 if (dwCreationFlags & IDLE_PRIORITY_CLASS)
941 FIXME(module, "(%s,...): IDLE_PRIORITY_CLASS ignored\n", name);
942 if (dwCreationFlags & HIGH_PRIORITY_CLASS)
943 FIXME(module, "(%s,...): HIGH_PRIORITY_CLASS ignored\n", name);
944 if (dwCreationFlags & REALTIME_PRIORITY_CLASS)
945 FIXME(module, "(%s,...): REALTIME_PRIORITY_CLASS ignored\n", name);
946 if (dwCreationFlags & CREATE_NEW_PROCESS_GROUP)
947 FIXME(module, "(%s,...): CREATE_NEW_PROCESS_GROUP ignored\n", name);
948 if (dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)
949 FIXME(module, "(%s,...): CREATE_UNICODE_ENVIRONMENT ignored\n", name);
950 if (dwCreationFlags & CREATE_SEPARATE_WOW_VDM)
951 FIXME(module, "(%s,...): CREATE_SEPARATE_WOW_VDM ignored\n", name);
952 if (dwCreationFlags & CREATE_SHARED_WOW_VDM)
953 FIXME(module, "(%s,...): CREATE_SHARED_WOW_VDM ignored\n", name);
954 if (dwCreationFlags & CREATE_DEFAULT_ERROR_MODE)
955 FIXME(module, "(%s,...): CREATE_DEFAULT_ERROR_MODE ignored\n", name);
956 if (dwCreationFlags & CREATE_NO_WINDOW)
957 FIXME(module, "(%s,...): CREATE_NO_WINDOW ignored\n", name);
958 if (dwCreationFlags & PROFILE_USER)
959 FIXME(module, "(%s,...): PROFILE_USER ignored\n", name);
960 if (dwCreationFlags & PROFILE_KERNEL)
961 FIXME(module, "(%s,...): PROFILE_KERNEL ignored\n", name);
962 if (dwCreationFlags & PROFILE_SERVER)
963 FIXME(module, "(%s,...): PROFILE_SERVER ignored\n", name);
964 if (lpCurrentDirectory)
965 FIXME(module, "(%s,...): lpCurrentDirectory %s ignored\n",
966 name, lpCurrentDirectory);
967 if (lpStartupInfo->lpDesktop)
968 FIXME(module, "(%s,...): lpStartupInfo->lpDesktop %s ignored\n",
969 name, lpStartupInfo->lpDesktop);
970 if (lpStartupInfo->lpTitle)
971 FIXME(module, "(%s,...): lpStartupInfo->lpTitle %s ignored\n",
972 name, lpStartupInfo->lpTitle);
973 if (lpStartupInfo->dwFlags & STARTF_USECOUNTCHARS)
974 FIXME(module, "(%s,...): STARTF_USECOUNTCHARS (%ld,%ld) ignored\n",
975 name, lpStartupInfo->dwXCountChars, lpStartupInfo->dwYCountChars);
976 if (lpStartupInfo->dwFlags & STARTF_USEFILLATTRIBUTE)
977 FIXME(module, "(%s,...): STARTF_USEFILLATTRIBUTE %lx ignored\n",
978 name, lpStartupInfo->dwFillAttribute);
979 if (lpStartupInfo->dwFlags & STARTF_RUNFULLSCREEN)
980 FIXME(module, "(%s,...): STARTF_RUNFULLSCREEN ignored\n", name);
981 if (lpStartupInfo->dwFlags & STARTF_FORCEONFEEDBACK)
982 FIXME(module, "(%s,...): STARTF_FORCEONFEEDBACK ignored\n", name);
983 if (lpStartupInfo->dwFlags & STARTF_FORCEOFFFEEDBACK)
984 FIXME(module, "(%s,...): STARTF_FORCEOFFFEEDBACK ignored\n", name);
985 if (lpStartupInfo->dwFlags & STARTF_USEHOTKEY)
986 FIXME(module, "(%s,...): STARTF_USEHOTKEY ignored\n", name);
989 /* When in WineLib, always fork new Unix process */
991 if ( __winelib )
992 return MODULE_CreateUnixProcess( name, cmdline,
993 lpStartupInfo, lpProcessInfo, TRUE );
995 /* Check for special case: second instance of NE module */
997 lstrcpynA( ofs.szPathName, name, sizeof( ofs.szPathName ) );
998 retv = NE_CreateProcess( HFILE_ERROR, &ofs, cmdline, lpEnvironment,
999 lpProcessAttributes, lpThreadAttributes,
1000 bInheritHandles, lpStartupInfo, lpProcessInfo );
1002 /* Load file and create process */
1004 if ( !retv )
1006 /* Open file and determine executable type */
1008 if ( (hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR )
1010 SetLastError( ERROR_FILE_NOT_FOUND );
1011 return FALSE;
1014 if ( !MODULE_GetBinaryType( hFile, &ofs, &type ) )
1016 CloseHandle( hFile );
1018 /* FIXME: Try Unix executable only when appropriate! */
1019 if ( MODULE_CreateUnixProcess( name, cmdline,
1020 lpStartupInfo, lpProcessInfo, FALSE ) )
1021 return TRUE;
1023 SetLastError( ERROR_BAD_FORMAT );
1024 return FALSE;
1028 /* Create process */
1030 switch ( type )
1032 case SCS_32BIT_BINARY:
1033 retv = PE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
1034 lpProcessAttributes, lpThreadAttributes,
1035 bInheritHandles, lpStartupInfo, lpProcessInfo );
1036 break;
1038 case SCS_DOS_BINARY:
1039 retv = MZ_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
1040 lpProcessAttributes, lpThreadAttributes,
1041 bInheritHandles, lpStartupInfo, lpProcessInfo );
1042 break;
1044 case SCS_WOW_BINARY:
1045 retv = NE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
1046 lpProcessAttributes, lpThreadAttributes,
1047 bInheritHandles, lpStartupInfo, lpProcessInfo );
1048 break;
1050 case SCS_PIF_BINARY:
1051 case SCS_POSIX_BINARY:
1052 case SCS_OS216_BINARY:
1053 FIXME( module, "Unsupported executable type: %ld\n", type );
1054 /* fall through */
1056 default:
1057 SetLastError( ERROR_BAD_FORMAT );
1058 retv = FALSE;
1059 break;
1062 CloseHandle( hFile );
1064 return retv;
1067 /**********************************************************************
1068 * CreateProcessW (KERNEL32.172)
1069 * NOTES
1070 * lpReserved is not converted
1072 BOOL WINAPI CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
1073 LPSECURITY_ATTRIBUTES lpProcessAttributes,
1074 LPSECURITY_ATTRIBUTES lpThreadAttributes,
1075 BOOL bInheritHandles, DWORD dwCreationFlags,
1076 LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
1077 LPSTARTUPINFOW lpStartupInfo,
1078 LPPROCESS_INFORMATION lpProcessInfo )
1079 { BOOL ret;
1080 STARTUPINFOA StartupInfoA;
1082 LPSTR lpApplicationNameA = HEAP_strdupWtoA (GetProcessHeap(),0,lpApplicationName);
1083 LPSTR lpCommandLineA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCommandLine);
1084 LPSTR lpCurrentDirectoryA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCurrentDirectory);
1086 memcpy (&StartupInfoA, lpStartupInfo, sizeof(STARTUPINFOA));
1087 StartupInfoA.lpDesktop = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpDesktop);
1088 StartupInfoA.lpTitle = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpTitle);
1090 TRACE(win32, "(%s,%s,...)\n", debugstr_w(lpApplicationName), debugstr_w(lpCommandLine));
1092 if (lpStartupInfo->lpReserved)
1093 FIXME(win32,"StartupInfo.lpReserved is used, please report (%s)\n", debugstr_w(lpStartupInfo->lpReserved));
1095 ret = CreateProcessA( lpApplicationNameA, lpCommandLineA,
1096 lpProcessAttributes, lpThreadAttributes,
1097 bInheritHandles, dwCreationFlags,
1098 lpEnvironment, lpCurrentDirectoryA,
1099 &StartupInfoA, lpProcessInfo );
1101 HeapFree( GetProcessHeap(), 0, lpCurrentDirectoryA );
1102 HeapFree( GetProcessHeap(), 0, lpCommandLineA );
1103 HeapFree( GetProcessHeap(), 0, StartupInfoA.lpDesktop );
1104 HeapFree( GetProcessHeap(), 0, StartupInfoA.lpTitle );
1106 return ret;
1109 /***********************************************************************
1110 * GetModuleHandle (KERNEL32.237)
1112 HMODULE WINAPI GetModuleHandleA(LPCSTR module)
1114 if (module == NULL)
1115 return PROCESS_Current()->exe_modref->module;
1116 else
1117 return MODULE_FindModule( module );
1120 HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
1122 HMODULE hModule;
1123 LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
1124 hModule = GetModuleHandleA( modulea );
1125 HeapFree( GetProcessHeap(), 0, modulea );
1126 return hModule;
1130 /***********************************************************************
1131 * GetModuleFileName32A (KERNEL32.235)
1133 DWORD WINAPI GetModuleFileNameA(
1134 HMODULE hModule, /* [in] module handle (32bit) */
1135 LPSTR lpFileName, /* [out] filenamebuffer */
1136 DWORD size /* [in] size of filenamebuffer */
1137 ) {
1138 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1140 if (!wm) /* can happen on start up or the like */
1141 return 0;
1143 if (PE_HEADER(wm->module)->OptionalHeader.MajorOperatingSystemVersion >= 4.0)
1144 lstrcpynA( lpFileName, wm->longname, size );
1145 else
1146 lstrcpynA( lpFileName, wm->shortname, size );
1148 TRACE(module, "%s\n", lpFileName );
1149 return strlen(lpFileName);
1153 /***********************************************************************
1154 * GetModuleFileName32W (KERNEL32.236)
1156 DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName,
1157 DWORD size )
1159 LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1160 DWORD res = GetModuleFileNameA( hModule, fnA, size );
1161 lstrcpynAtoW( lpFileName, fnA, size );
1162 HeapFree( GetProcessHeap(), 0, fnA );
1163 return res;
1167 /***********************************************************************
1168 * LoadLibraryEx32W (KERNEL.513)
1169 * FIXME
1171 HMODULE WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
1172 DWORD flags )
1174 TRACE(module,"(%s,%d,%08lx)\n",libname,hf,flags);
1175 return LoadLibraryExA(libname, hf,flags);
1178 /***********************************************************************
1179 * LoadLibraryEx32A (KERNEL32)
1181 HMODULE WINAPI LoadLibraryExA(LPCSTR libname,HFILE hfile,DWORD flags)
1183 HMODULE hmod;
1184 hmod = MODULE_LoadLibraryExA( libname, hfile, flags );
1186 if ( hmod >= 32 )
1188 /* Increment RefCount */
1189 MODULE_IncRefCount( hmod );
1191 /* Initialize DLL just loaded */
1192 MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, NULL );
1195 return hmod;
1198 HMODULE MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags )
1200 HMODULE hmod;
1202 hmod = ELF_LoadLibraryExA( libname, hfile, flags );
1203 if (hmod) return hmod;
1205 hmod = PE_LoadLibraryExA( libname, hfile, flags );
1206 return hmod;
1209 /***********************************************************************
1210 * LoadLibraryA (KERNEL32)
1212 HMODULE WINAPI LoadLibraryA(LPCSTR libname) {
1213 return LoadLibraryExA(libname,0,0);
1216 /***********************************************************************
1217 * LoadLibraryW (KERNEL32)
1219 HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
1221 return LoadLibraryExW(libnameW,0,0);
1224 /***********************************************************************
1225 * LoadLibraryExW (KERNEL32)
1227 HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW,HFILE hfile,DWORD flags)
1229 LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
1230 HMODULE ret = LoadLibraryExA( libnameA , hfile, flags );
1232 HeapFree( GetProcessHeap(), 0, libnameA );
1233 return ret;
1236 /***********************************************************************
1237 * FreeLibrary
1239 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
1241 if ( MODULE_DecRefCount( hLibModule ) != 1 ) return TRUE;
1243 FIXME(module,"(0x%08x): should unload now\n", hLibModule);
1244 return TRUE; /* FIXME */
1247 /***********************************************************************
1248 * FreeLibraryAndExitThread
1250 VOID WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
1252 FreeLibrary(hLibModule);
1253 ExitThread(dwExitCode);
1256 /***********************************************************************
1257 * PrivateLoadLibrary (KERNEL32)
1259 * FIXME: rough guesswork, don't know what "Private" means
1261 HINSTANCE WINAPI PrivateLoadLibrary(LPCSTR libname)
1263 return (HINSTANCE)LoadLibrary16(libname);
1268 /***********************************************************************
1269 * PrivateFreeLibrary (KERNEL32)
1271 * FIXME: rough guesswork, don't know what "Private" means
1273 void WINAPI PrivateFreeLibrary(HINSTANCE handle)
1275 FreeLibrary16((HINSTANCE16)handle);
1279 /***********************************************************************
1280 * WIN32_GetProcAddress16 (KERNEL32.36)
1281 * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1283 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hModule, LPCSTR name )
1285 WORD ordinal;
1286 FARPROC16 ret;
1288 if (!hModule) {
1289 WARN(module,"hModule may not be 0!\n");
1290 return (FARPROC16)0;
1292 if (HIWORD(hModule))
1294 WARN( module, "hModule is Win32 handle (%08x)\n", hModule );
1295 return (FARPROC16)0;
1297 hModule = GetExePtr( hModule );
1298 if (HIWORD(name)) {
1299 ordinal = NE_GetOrdinal( hModule, name );
1300 TRACE(module, "%04x '%s'\n",
1301 hModule, name );
1302 } else {
1303 ordinal = LOWORD(name);
1304 TRACE(module, "%04x %04x\n",
1305 hModule, ordinal );
1307 if (!ordinal) return (FARPROC16)0;
1308 ret = NE_GetEntryPoint( hModule, ordinal );
1309 TRACE(module,"returning %08x\n",(UINT)ret);
1310 return ret;
1313 /***********************************************************************
1314 * GetProcAddress16 (KERNEL.50)
1316 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1318 WORD ordinal;
1319 FARPROC16 ret;
1321 if (!hModule) hModule = GetCurrentTask();
1322 hModule = GetExePtr( hModule );
1324 if (HIWORD(name) != 0)
1326 ordinal = NE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1327 TRACE(module, "%04x '%s'\n",
1328 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1330 else
1332 ordinal = LOWORD(name);
1333 TRACE(module, "%04x %04x\n",
1334 hModule, ordinal );
1336 if (!ordinal) return (FARPROC16)0;
1338 ret = NE_GetEntryPoint( hModule, ordinal );
1340 TRACE(module, "returning %08x\n", (UINT)ret );
1341 return ret;
1345 /***********************************************************************
1346 * GetProcAddress32 (KERNEL32.257)
1348 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
1350 return MODULE_GetProcAddress( hModule, function, TRUE );
1353 /***********************************************************************
1354 * WIN16_GetProcAddress32 (KERNEL.453)
1356 FARPROC WINAPI GetProcAddress32_16( HMODULE hModule, LPCSTR function )
1358 return MODULE_GetProcAddress( hModule, function, FALSE );
1361 /***********************************************************************
1362 * MODULE_GetProcAddress32 (internal)
1364 FARPROC MODULE_GetProcAddress(
1365 HMODULE hModule, /* [in] current module handle */
1366 LPCSTR function, /* [in] function to be looked up */
1367 BOOL snoop )
1369 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1371 if (HIWORD(function))
1372 TRACE(win32,"(%08lx,%s)\n",(DWORD)hModule,function);
1373 else
1374 TRACE(win32,"(%08lx,%p)\n",(DWORD)hModule,function);
1375 if (!wm)
1376 return (FARPROC)0;
1377 switch (wm->type)
1379 case MODULE32_PE:
1380 return PE_FindExportedFunction( wm, function, snoop );
1381 case MODULE32_ELF:
1382 return ELF_FindExportedFunction( wm, function);
1383 default:
1384 ERR(module,"wine_modref type %d not handled.\n",wm->type);
1385 return (FARPROC)0;
1390 /***********************************************************************
1391 * RtlImageNtHeaders (NTDLL)
1393 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
1395 /* basically:
1396 * return hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew);
1397 * but we could get HMODULE16 or the like (think builtin modules)
1400 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1401 if (!wm || (wm->type != MODULE32_PE)) return (PIMAGE_NT_HEADERS)0;
1402 return PE_HEADER(wm->module);
1406 /***************************************************************************
1407 * HasGPHandler (KERNEL.338)
1410 #pragma pack(1)
1411 typedef struct _GPHANDLERDEF
1413 WORD selector;
1414 WORD rangeStart;
1415 WORD rangeEnd;
1416 WORD handler;
1417 } GPHANDLERDEF;
1418 #pragma pack(4)
1420 SEGPTR WINAPI HasGPHandler16( SEGPTR address )
1422 HMODULE16 hModule;
1423 int gpOrdinal;
1424 SEGPTR gpPtr;
1425 GPHANDLERDEF *gpHandler;
1427 if ( (hModule = FarGetOwner16( SELECTOROF(address) )) != 0
1428 && (gpOrdinal = NE_GetOrdinal( hModule, "__GP" )) != 0
1429 && (gpPtr = (SEGPTR)NE_GetEntryPointEx( hModule, gpOrdinal, FALSE )) != 0
1430 && !IsBadReadPtr16( gpPtr, sizeof(GPHANDLERDEF) )
1431 && (gpHandler = PTR_SEG_TO_LIN( gpPtr )) != NULL )
1433 while (gpHandler->selector)
1435 if ( SELECTOROF(address) == gpHandler->selector
1436 && OFFSETOF(address) >= gpHandler->rangeStart
1437 && OFFSETOF(address) < gpHandler->rangeEnd )
1438 return PTR_SEG_OFF_TO_SEGPTR( gpHandler->selector,
1439 gpHandler->handler );
1440 gpHandler++;
1444 return 0;