Added tracing for delayed imports and removed the fixme.
[wine] / loader / module.c
1 /*
2  * Modules
3  *
4  * Copyright 1995 Alexandre Julliard
5  */
6
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"
32
33
34 /*************************************************************************
35  *              MODULE32_LookupHMODULE
36  * looks for the referenced HMODULE in the current process
37  */
38 WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod )
39 {
40     WINE_MODREF *wm;
41
42     if (!hmod) 
43         return PROCESS_Current()->exe_modref;
44
45     if (!HIWORD(hmod)) {
46         ERR(module,"tried to lookup 0x%04x in win32 module handler!\n",hmod);
47         return NULL;
48     }
49     for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next )
50         if (wm->module == hmod)
51             return wm;
52     return NULL;
53 }
54
55 /*************************************************************************
56  *              MODULE_InitializeDLLs
57  * 
58  * Call the initialization routines of all DLLs belonging to the
59  * current process. This is somewhat complicated due to the fact that
60  *
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
64  * 
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
68  *
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.)
72  */
73 static void MODULE_DoInitializeDLLs( WINE_MODREF *wm,
74                                      DWORD type, LPVOID lpReserved )
75 {
76     int i;
77
78     assert( wm && !wm->initDone );
79     TRACE( module, "(%08x,%ld,%p) - START\n", 
80            wm->module, type, lpReserved );
81
82     /* Tag current MODREF to prevent recursive loop */
83     wm->initDone = TRUE;
84
85     /* Recursively initialize all child DLLs */
86     for ( i = 0; i < wm->nDeps; i++ )
87         if ( wm->deps[i] && !wm->deps[i]->initDone )
88             MODULE_DoInitializeDLLs( wm->deps[i], type, lpReserved );
89
90     /* Now we can call the initialization routine */
91     switch ( wm->type )
92     {
93     case MODULE32_PE:
94         PE_InitDLL( wm, type, lpReserved );
95         break;
96
97     case MODULE32_ELF:
98         /* no need to do that, dlopen() already does */
99         break;
100     default:
101         ERR(module, "wine_modref type %d not handled.\n", wm->type);
102         break;
103     }
104
105     TRACE( module, "(%08x,%ld,%p) - END\n", 
106            wm->module, type, lpReserved );
107 }
108
109 void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved )
110 {
111     BOOL inProgress = FALSE;
112     WINE_MODREF *wm;
113
114     /* Grab the process critical section to protect the recursion flags */
115     /* FIXME: This is probably overkill! */
116     EnterCriticalSection( &PROCESS_Current()->crit_section );
117
118     TRACE( module, "(%08x,%ld,%p) - START\n", root, type, lpReserved );
119
120     /* First, check whether initialization is currently in progress */
121     for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
122         if ( wm->initDone )
123         {
124             inProgress = TRUE;
125             break;
126         }
127
128     if ( inProgress )
129     {
130         /* 
131          * If this a LoadLibrary call from within an initialization routine,
132          * treat it analogously to an implicitly referenced DLL.
133          * Anything else may not happen at this point!
134          */
135         if ( root )
136         {
137             wm = MODULE32_LookupHMODULE( root );
138             if ( wm && !wm->initDone )
139                 MODULE_DoInitializeDLLs( wm, type, lpReserved );
140         }
141         else
142             FIXME(module, "Invalid recursion!\n");
143     }
144     else
145     {
146         /* If we arrive here, this is the start of an initialization run */
147         if ( !root )
148         {
149             /* If called for main EXE, initialize all DLLs */
150             for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
151                 if ( !wm->initDone )
152                     MODULE_DoInitializeDLLs( wm, type, lpReserved );
153         }
154         else
155         {
156             /* If called for a specific DLL, initialize only it and its children */
157             wm = MODULE32_LookupHMODULE( root );
158             if (wm) MODULE_DoInitializeDLLs( wm, type, lpReserved );
159         }
160
161         /* We're finished, so we reset all recursion flags */
162         for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
163             wm->initDone = FALSE;
164     }
165
166     TRACE( module, "(%08x,%ld,%p) - END\n", root, type, lpReserved );
167
168     /* Release critical section */
169     LeaveCriticalSection( &PROCESS_Current()->crit_section );
170 }
171
172
173 /***********************************************************************
174  *           MODULE_CreateDummyModule
175  *
176  * Create a dummy NE module for Win32 or Winelib.
177  */
178 HMODULE MODULE_CreateDummyModule( const OFSTRUCT *ofs, LPCSTR modName )
179 {
180     HMODULE hModule;
181     NE_MODULE *pModule;
182     SEGTABLEENTRY *pSegment;
183     char *pStr,*s;
184     int len;
185     const char* basename;
186
187     INT of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
188                     + strlen(ofs->szPathName) + 1;
189     INT size = sizeof(NE_MODULE) +
190                  /* loaded file info */
191                  of_size +
192                  /* segment table: DS,CS */
193                  2 * sizeof(SEGTABLEENTRY) +
194                  /* name table */
195                  9 +
196                  /* several empty tables */
197                  8;
198
199     hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
200     if (!hModule) return (HMODULE)11;  /* invalid exe */
201
202     FarSetOwner16( hModule, hModule );
203     pModule = (NE_MODULE *)GlobalLock16( hModule );
204
205     /* Set all used entries */
206     pModule->magic            = IMAGE_OS2_SIGNATURE;
207     pModule->count            = 1;
208     pModule->next             = 0;
209     pModule->flags            = 0;
210     pModule->dgroup           = 0;
211     pModule->ss               = 1;
212     pModule->cs               = 2;
213     pModule->heap_size        = 0;
214     pModule->stack_size       = 0;
215     pModule->seg_count        = 2;
216     pModule->modref_count     = 0;
217     pModule->nrname_size      = 0;
218     pModule->fileinfo         = sizeof(NE_MODULE);
219     pModule->os_flags         = NE_OSFLAGS_WINDOWS;
220     pModule->expected_version = 0x030a;
221     pModule->self             = hModule;
222
223     /* Set loaded file information */
224     memcpy( pModule + 1, ofs, of_size );
225     ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
226
227     pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
228     pModule->seg_table = (int)pSegment - (int)pModule;
229     /* Data segment */
230     pSegment->size    = 0;
231     pSegment->flags   = NE_SEGFLAGS_DATA;
232     pSegment->minsize = 0x1000;
233     pSegment++;
234     /* Code segment */
235     pSegment->flags   = 0;
236     pSegment++;
237
238     /* Module name */
239     pStr = (char *)pSegment;
240     pModule->name_table = (int)pStr - (int)pModule;
241     if ( modName )
242         basename = modName;
243     else
244     {
245         basename = strrchr(ofs->szPathName,'\\');
246         if (!basename) basename = ofs->szPathName;
247         else basename++;
248     }
249     len = strlen(basename);
250     if ((s = strchr(basename,'.'))) len = s - basename;
251     if (len > 8) len = 8;
252     *pStr = len;
253     strncpy( pStr+1, basename, len );
254     if (len < 8) pStr[len+1] = 0;
255     pStr += 9;
256
257     /* All tables zero terminated */
258     pModule->res_table = pModule->import_table = pModule->entry_table =
259                 (int)pStr - (int)pModule;
260
261     NE_RegisterModule( pModule );
262     return hModule;
263 }
264
265
266 /***********************************************************************
267  *           MODULE_GetWndProcEntry16  (not a Windows API function)
268  *
269  * Return an entry point from the WPROCS dll.
270  */
271 FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name )
272 {
273     FARPROC16 ret = NULL;
274
275     if (__winelib)
276     {
277         /* FIXME: hack for Winelib */
278         extern LRESULT ColorDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
279         extern LRESULT FileOpenDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
280         extern LRESULT FileSaveDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
281         extern LRESULT FindTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
282         extern LRESULT PrintDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
283         extern LRESULT PrintSetupDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
284         extern LRESULT ReplaceTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
285
286         if (!strcmp(name,"ColorDlgProc"))
287             return (FARPROC16)ColorDlgProc16;
288         if (!strcmp(name,"FileOpenDlgProc"))
289             return (FARPROC16)FileOpenDlgProc16;
290         if (!strcmp(name,"FileSaveDlgProc"))
291             return (FARPROC16)FileSaveDlgProc16;
292         if (!strcmp(name,"FindTextDlgProc"))
293             return (FARPROC16)FindTextDlgProc16;
294         if (!strcmp(name,"PrintDlgProc"))
295             return (FARPROC16)PrintDlgProc16;
296         if (!strcmp(name,"PrintSetupDlgProc"))
297             return (FARPROC16)PrintSetupDlgProc16;
298         if (!strcmp(name,"ReplaceTextDlgProc"))
299             return (FARPROC16)ReplaceTextDlgProc16;
300         if (!strcmp(name,"DefResourceHandler"))
301             return (FARPROC16)NE_DefResourceHandler;
302         FIXME(module,"No mapping for %s(), add one in library/miscstubs.c\n",name);
303         assert( FALSE );
304         return NULL;
305     }
306     else
307     {
308         WORD ordinal;
309         static HMODULE hModule = 0;
310
311         if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
312         ordinal = NE_GetOrdinal( hModule, name );
313         if (!(ret = NE_GetEntryPoint( hModule, ordinal )))
314         {            
315             WARN( module, "%s not found\n", name );
316             assert( FALSE );
317         }
318     }
319     return ret;
320 }
321
322
323 /**********************************************************************
324  *          MODULE_FindModule32
325  *
326  * Find a (loaded) win32 module depending on path
327  * The handling of '.' is a bit weird, but we need it that way, 
328  * for sometimes the programs use '<name>.exe' and '<name>.dll' and
329  * this is the only way to differentiate. (mainly hypertrm.exe)
330  *
331  * RETURNS
332  *      the module handle if found
333  *      0 if not
334  */
335 HMODULE MODULE_FindModule(
336         LPCSTR path     /* [in] pathname of module/library to be found */
337 ) {
338     LPSTR       filename;
339     LPSTR       dotptr;
340     WINE_MODREF *wm;
341
342     if (!(filename = strrchr( path, '\\' )))
343         filename = HEAP_strdupA( GetProcessHeap(), 0, path );
344     else 
345         filename = HEAP_strdupA( GetProcessHeap(), 0, filename+1 );
346     dotptr=strrchr(filename,'.');
347
348     for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next ) {
349         LPSTR   xmodname,xdotptr;
350
351         assert (wm->modname);
352         xmodname = HEAP_strdupA( GetProcessHeap(), 0, wm->modname );
353         xdotptr=strrchr(xmodname,'.');
354         if (    (xdotptr && !dotptr) ||
355                 (!xdotptr && dotptr)
356         ) {
357             if (dotptr) *dotptr         = '\0';
358             if (xdotptr) *xdotptr       = '\0';
359         }
360         if (!strcasecmp( filename, xmodname)) {
361             HeapFree( GetProcessHeap(), 0, filename );
362             HeapFree( GetProcessHeap(), 0, xmodname );
363             return wm->module;
364         }
365         if (dotptr) *dotptr='.';
366         /* FIXME: add paths, shortname */
367         HeapFree( GetProcessHeap(), 0, xmodname );
368     }
369     /* if that fails, try looking for the filename... */
370     for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next ) {
371         LPSTR   xlname,xdotptr;
372
373         assert (wm->longname);
374         xlname = strrchr(wm->longname,'\\');
375         if (!xlname) 
376             xlname = wm->longname;
377         else
378             xlname++;
379         xlname = HEAP_strdupA( GetProcessHeap(), 0, xlname );
380         xdotptr=strrchr(xlname,'.');
381         if (    (xdotptr && !dotptr) ||
382                 (!xdotptr && dotptr)
383         ) {
384             if (dotptr) *dotptr         = '\0';
385             if (xdotptr) *xdotptr       = '\0';
386         }
387         if (!strcasecmp( filename, xlname)) {
388             HeapFree( GetProcessHeap(), 0, filename );
389             HeapFree( GetProcessHeap(), 0, xlname );
390             return wm->module;
391         }
392         if (dotptr) *dotptr='.';
393         /* FIXME: add paths, shortname */
394         HeapFree( GetProcessHeap(), 0, xlname );
395     }
396     HeapFree( GetProcessHeap(), 0, filename );
397     return 0;
398 }
399
400 /***********************************************************************
401  *           MODULE_GetBinaryType
402  *
403  * The GetBinaryType function determines whether a file is executable
404  * or not and if it is it returns what type of executable it is.
405  * The type of executable is a property that determines in which
406  * subsystem an executable file runs under.
407  *
408  * Binary types returned:
409  * SCS_32BIT_BINARY: A Win32 based application
410  * SCS_DOS_BINARY: An MS-Dos based application
411  * SCS_WOW_BINARY: A Win16 based application
412  * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
413  * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
414  * SCS_OS216_BINARY: A 16bit OS/2 based application ( Not implemented )
415  *
416  * Returns TRUE if the file is an executable in which case
417  * the value pointed by lpBinaryType is set.
418  * Returns FALSE if the file is not an executable or if the function fails.
419  *
420  * To do so it opens the file and reads in the header information
421  * if the extended header information is not presend it will
422  * assume that that the file is a DOS executable.
423  * If the extended header information is present it will
424  * determine if the file is an 16 or 32 bit Windows executable
425  * by check the flags in the header.
426  *
427  * Note that .COM and .PIF files are only recognized by their
428  * file name extension; but Windows does it the same way ...
429  */
430 static BOOL MODULE_GetBinaryType( HFILE hfile, OFSTRUCT *ofs, 
431                                   LPDWORD lpBinaryType )
432 {
433     IMAGE_DOS_HEADER mz_header;
434     char magic[4], *ptr;
435
436     /* Seek to the start of the file and read the DOS header information.
437      */
438     if ( _llseek( hfile, 0, SEEK_SET ) >= 0  &&
439          _lread( hfile, &mz_header, sizeof(mz_header) ) == sizeof(mz_header) )
440     {
441         /* Now that we have the header check the e_magic field
442          * to see if this is a dos image.
443          */
444         if ( mz_header.e_magic == IMAGE_DOS_SIGNATURE )
445         {
446             BOOL lfanewValid = FALSE;
447             /* We do have a DOS image so we will now try to seek into
448              * the file by the amount indicated by the field
449              * "Offset to extended header" and read in the
450              * "magic" field information at that location.
451              * This will tell us if there is more header information
452              * to read or not.
453              */
454             /* But before we do we will make sure that header
455              * structure encompasses the "Offset to extended header"
456              * field.
457              */
458             if ( (mz_header.e_cparhdr<<4) >= sizeof(IMAGE_DOS_HEADER) )
459                 if ( ( mz_header.e_crlc == 0 && mz_header.e_lfarlc == 0 ) ||
460                      ( mz_header.e_lfarlc >= sizeof(IMAGE_DOS_HEADER) ) )
461                     if ( mz_header.e_lfanew >= sizeof(IMAGE_DOS_HEADER) &&
462                          _llseek( hfile, mz_header.e_lfanew, SEEK_SET ) >= 0 &&
463                          _lread( hfile, magic, sizeof(magic) ) == sizeof(magic) )
464                         lfanewValid = TRUE;
465
466             if ( !lfanewValid )
467             {
468                 /* If we cannot read this "extended header" we will
469                  * assume that we have a simple DOS executable.
470                  */
471                 *lpBinaryType = SCS_DOS_BINARY;
472                 return TRUE;
473             }
474             else
475             {
476                 /* Reading the magic field succeeded so
477                  * we will try to determine what type it is.
478                  */
479                 if ( *(DWORD*)magic      == IMAGE_NT_SIGNATURE )
480                 {
481                     /* This is an NT signature.
482                      */
483                     *lpBinaryType = SCS_32BIT_BINARY;
484                     return TRUE;
485                 }
486                 else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
487                 {
488                     /* The IMAGE_OS2_SIGNATURE indicates that the
489                      * "extended header is a Windows executable (NE)
490                      * header.      This is a bit misleading, but it is
491                      * documented in the SDK. ( for more details see
492                      * the neexe.h file )
493                      */
494                      *lpBinaryType = SCS_WOW_BINARY;
495                      return TRUE;
496                 }
497                 else
498                 {
499                     /* Unknown extended header, so abort.
500                      */
501                     return FALSE;
502                 }
503             }
504         }
505     }
506
507     /* If we get here, we don't even have a correct MZ header.
508      * Try to check the file extension for known types ...
509      */
510     ptr = strrchr( ofs->szPathName, '.' );
511     if ( ptr && !strchr( ptr, '\\' ) && !strchr( ptr, '/' ) )
512     {
513         if ( !lstrcmpiA( ptr, ".COM" ) )
514         {
515             *lpBinaryType = SCS_DOS_BINARY;
516             return TRUE;
517         }
518
519         if ( !lstrcmpiA( ptr, ".PIF" ) )
520         {
521             *lpBinaryType = SCS_PIF_BINARY;
522             return TRUE;
523         }
524     }
525
526     return FALSE;
527 }
528
529 /***********************************************************************
530  *             GetBinaryTypeA                     [KERNEL32.280]
531  */
532 BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
533 {
534     BOOL ret = FALSE;
535     HFILE hfile;
536     OFSTRUCT ofs;
537
538     TRACE( win32, "%s\n", lpApplicationName );
539
540     /* Sanity check.
541      */
542     if ( lpApplicationName == NULL || lpBinaryType == NULL )
543         return FALSE;
544
545     /* Open the file indicated by lpApplicationName for reading.
546      */
547     if ( (hfile = OpenFile( lpApplicationName, &ofs, OF_READ )) == HFILE_ERROR )
548         return FALSE;
549
550     /* Check binary type
551      */
552     ret = MODULE_GetBinaryType( hfile, &ofs, lpBinaryType );
553
554     /* Close the file.
555      */
556     CloseHandle( hfile );
557
558     return ret;
559 }
560
561 /***********************************************************************
562  *             GetBinaryTypeW                      [KERNEL32.281]
563  */
564 BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
565 {
566     BOOL ret = FALSE;
567     LPSTR strNew = NULL;
568
569     TRACE( win32, "%s\n", debugstr_w(lpApplicationName) );
570
571     /* Sanity check.
572      */
573     if ( lpApplicationName == NULL || lpBinaryType == NULL )
574         return FALSE;
575
576     /* Convert the wide string to a ascii string.
577      */
578     strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
579
580     if ( strNew != NULL )
581     {
582         ret = GetBinaryTypeA( strNew, lpBinaryType );
583
584         /* Free the allocated string.
585          */
586         HeapFree( GetProcessHeap(), 0, strNew );
587     }
588
589     return ret;
590 }
591
592 /**********************************************************************
593  *          MODULE_CreateUnixProcess
594  */
595 static BOOL MODULE_CreateUnixProcess( LPCSTR filename, LPCSTR lpCmdLine,
596                                       LPSTARTUPINFOA lpStartupInfo,
597                                       LPPROCESS_INFORMATION lpProcessInfo,
598                                       BOOL useWine )
599 {
600     DOS_FULL_NAME full_name;
601     const char *unixfilename = filename;
602     const char *argv[256], **argptr;
603     BOOL iconic = FALSE;
604
605     /* Get Unix file name and iconic flag */
606
607     if ( lpStartupInfo->dwFlags & STARTF_USESHOWWINDOW )
608         if (    lpStartupInfo->wShowWindow == SW_SHOWMINIMIZED
609              || lpStartupInfo->wShowWindow == SW_SHOWMINNOACTIVE )
610             iconic = TRUE;
611
612     if (    strchr(filename, '/') 
613          || strchr(filename, ':') 
614          || strchr(filename, '\\') )
615     {
616         if ( DOSFS_GetFullName( filename, TRUE, &full_name ) )
617             unixfilename = full_name.long_name;
618     }
619
620     if ( !unixfilename )
621     {
622         SetLastError( ERROR_FILE_NOT_FOUND );
623         return FALSE;
624     }
625
626     /* Build argument list */
627
628     argptr = argv;
629     if ( !useWine )
630     {
631         char *p = strdup(lpCmdLine);
632         *argptr++ = unixfilename;
633         if (iconic) *argptr++ = "-iconic";
634         while (1)
635         {
636             while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
637             if (!*p) break;
638             *argptr++ = p;
639             while (*p && *p != ' ' && *p != '\t') p++;
640         }
641     }
642     else
643     {
644         *argptr++ = "wine";
645         if (iconic) *argptr++ = "-iconic";
646         *argptr++ = lpCmdLine;
647     }
648     *argptr++ = 0;
649
650     /* Fork and execute */
651
652     if ( !fork() )
653     {
654         /* Note: don't use Wine routines here, as this process
655                  has not been correctly initialized! */
656
657         execvp( argv[0], (char**)argv );
658
659         /* Failed ! */
660         if ( useWine )
661             fprintf( stderr, "CreateProcess: can't exec 'wine %s'\n", 
662                              lpCmdLine );
663         exit( 1 );
664     }
665
666     /* Fake success return value */
667
668     memset( lpProcessInfo, '\0', sizeof( *lpProcessInfo ) );
669     lpProcessInfo->hProcess = INVALID_HANDLE_VALUE;
670     lpProcessInfo->hThread  = INVALID_HANDLE_VALUE;
671
672     SetLastError( ERROR_SUCCESS );
673     return TRUE;
674 }
675
676 /***********************************************************************
677  *           WinExec16   (KERNEL.166)
678  */
679 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
680 {
681     return WinExec( lpCmdLine, nCmdShow );
682 }
683
684 /***********************************************************************
685  *           WinExec   (KERNEL32.566)
686  */
687 HINSTANCE WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow )
688 {
689     LOADPARAMS params;
690     UINT16 paramCmdShow[2];
691
692     if (!lpCmdLine)
693         return 2;  /* File not found */
694
695     /* Set up LOADPARAMS buffer for LoadModule */
696
697     memset( &params, '\0', sizeof(params) );
698     params.lpCmdLine    = (LPSTR)lpCmdLine;
699     params.lpCmdShow    = paramCmdShow;
700     params.lpCmdShow[0] = 2;
701     params.lpCmdShow[1] = nCmdShow;
702
703     /* Now load the executable file */
704
705     return LoadModule( NULL, &params );
706 }
707
708 /**********************************************************************
709  *          LoadModule    (KERNEL32.499)
710  */
711 HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock ) 
712 {
713     LOADPARAMS *params = (LOADPARAMS *)paramBlock;
714     PROCESS_INFORMATION info;
715     STARTUPINFOA startup;
716     HINSTANCE hInstance;
717     PDB *pdb;
718     TDB *tdb;
719
720     memset( &startup, '\0', sizeof(startup) );
721     startup.cb = sizeof(startup);
722     startup.dwFlags = STARTF_USESHOWWINDOW;
723     startup.wShowWindow = params->lpCmdShow? params->lpCmdShow[1] : 0;
724
725     if ( !CreateProcessA( name, params->lpCmdLine,
726                           NULL, NULL, FALSE, 0, params->lpEnvAddress,
727                           NULL, &startup, &info ) )
728     {
729         hInstance = GetLastError();
730         if ( hInstance < 32 ) return hInstance;
731
732         FIXME( module, "Strange error set by CreateProcess: %d\n", hInstance );
733         return 11;
734     }
735     
736     /* Get 16-bit hInstance/hTask from process */
737     pdb = PROCESS_IdToPDB( info.dwProcessId );
738     tdb = pdb? (TDB *)GlobalLock16( pdb->task ) : NULL;
739     hInstance = tdb && tdb->hInstance? tdb->hInstance : pdb? pdb->task : 0;
740
741     /* Close off the handles */
742     CloseHandle( info.hThread );
743     CloseHandle( info.hProcess );
744
745     return hInstance;
746 }
747
748
749 static void get_executable_name( LPCSTR line, LPSTR name, int namelen,
750                                  LPCSTR *after, BOOL extension )
751 {
752     int len = 0;
753     LPCSTR p = NULL, pcmd = NULL;
754
755     if ((p = strchr(line, '"')))
756     {
757         p++;      /* skip '"' */
758         line = p;
759         if ((pcmd = strchr(p, '"'))) { /* closing '"' available, too ? */
760             pcmd++;
761             len = (int)pcmd - (int)p;
762         } 
763     }
764
765     if (!len)
766     {
767         p = strchr(line, ' ');
768         do {
769             len = (p? p-line : strlen(line)) + 1;
770             if (len > namelen - 4) len = namelen - 4;
771             lstrcpynA(name, line, len);
772             if (extension && !strchr(name, '\\') && !strchr(name, '.'))
773                 strcat(name, ".exe");
774             if (GetFileAttributesA(name) != -1) {
775                 pcmd = p ? p : line+strlen(line);
776                 break;
777             }
778             /* if there is a space and no file found yet, include the word
779              * up to the next space too. If there is no next space, just
780              * use the first word.
781              */
782             if (p) {
783                 p = strchr(p+1, ' ');
784             } else {
785                 p = strchr(line, ' ');
786                 len = (p? p-line : strlen(line)) + 1;
787                 if (len > namelen - 4)
788                     len = namelen - 4;
789                 pcmd = p ? p + 1 : line+strlen(line);
790                 break;
791             }
792         } while (1);
793     }
794     lstrcpynA(name, line, len);
795     if (after) *after = pcmd;
796 }
797
798 /**********************************************************************
799  *       CreateProcessA          (KERNEL32.171)
800  */
801 BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine, 
802                             LPSECURITY_ATTRIBUTES lpProcessAttributes,
803                             LPSECURITY_ATTRIBUTES lpThreadAttributes,
804                             BOOL bInheritHandles, DWORD dwCreationFlags,
805                             LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
806                             LPSTARTUPINFOA lpStartupInfo,
807                             LPPROCESS_INFORMATION lpProcessInfo )
808 {
809     BOOL retv = FALSE;
810     HFILE hFile;
811     OFSTRUCT ofs;
812     DWORD type;
813     char name[256];
814     LPCSTR cmdline;
815 #if 0
816     LPCSTR p = NULL;
817 #endif
818
819     /* Get name and command line */
820
821     if (!lpApplicationName && !lpCommandLine)
822     {
823         SetLastError( ERROR_FILE_NOT_FOUND );
824         return FALSE;
825     }
826
827     name[0] = '\0';
828
829     if (lpApplicationName) {
830         get_executable_name( lpApplicationName, name, sizeof(name), NULL, FALSE);
831 #if 0
832         p = strrchr(name, '.');
833         if (p >= name+strlen(name)-4) /* FIXME */
834             *p = '\0';
835 #endif
836     }
837     else {
838       get_executable_name ( lpCommandLine, name, sizeof ( name ), NULL, FALSE );
839     }
840     if (!lpCommandLine) 
841       cmdline = lpApplicationName;
842     else cmdline = lpCommandLine;
843
844     if (!strchr(name, '\\') && !strchr(name, '.'))
845         strcat(name, ".exe");
846
847
848     /* Warn if unsupported features are used */
849
850     if (lpProcessAttributes)
851         FIXME(module, "(%s,...): lpProcessAttributes ignored\n", name);
852     if (lpThreadAttributes)
853         FIXME(module, "(%s,...): lpThreadAttributes ignored\n", name);
854     if (dwCreationFlags & DEBUG_PROCESS)
855         FIXME(module, "(%s,...): DEBUG_PROCESS ignored\n", name);
856     if (dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
857         FIXME(module, "(%s,...): DEBUG_ONLY_THIS_PROCESS ignored\n", name);
858     if (dwCreationFlags & CREATE_SUSPENDED)
859         FIXME(module, "(%s,...): CREATE_SUSPENDED ignored\n", name);
860     if (dwCreationFlags & DETACHED_PROCESS)
861         FIXME(module, "(%s,...): DETACHED_PROCESS ignored\n", name);
862     if (dwCreationFlags & CREATE_NEW_CONSOLE)
863         FIXME(module, "(%s,...): CREATE_NEW_CONSOLE ignored\n", name);
864     if (dwCreationFlags & NORMAL_PRIORITY_CLASS)
865         FIXME(module, "(%s,...): NORMAL_PRIORITY_CLASS ignored\n", name);
866     if (dwCreationFlags & IDLE_PRIORITY_CLASS)
867         FIXME(module, "(%s,...): IDLE_PRIORITY_CLASS ignored\n", name);
868     if (dwCreationFlags & HIGH_PRIORITY_CLASS)
869         FIXME(module, "(%s,...): HIGH_PRIORITY_CLASS ignored\n", name);
870     if (dwCreationFlags & REALTIME_PRIORITY_CLASS)
871         FIXME(module, "(%s,...): REALTIME_PRIORITY_CLASS ignored\n", name);
872     if (dwCreationFlags & CREATE_NEW_PROCESS_GROUP)
873         FIXME(module, "(%s,...): CREATE_NEW_PROCESS_GROUP ignored\n", name);
874     if (dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)
875         FIXME(module, "(%s,...): CREATE_UNICODE_ENVIRONMENT ignored\n", name);
876     if (dwCreationFlags & CREATE_SEPARATE_WOW_VDM)
877         FIXME(module, "(%s,...): CREATE_SEPARATE_WOW_VDM ignored\n", name);
878     if (dwCreationFlags & CREATE_SHARED_WOW_VDM)
879         FIXME(module, "(%s,...): CREATE_SHARED_WOW_VDM ignored\n", name);
880     if (dwCreationFlags & CREATE_DEFAULT_ERROR_MODE)
881         FIXME(module, "(%s,...): CREATE_DEFAULT_ERROR_MODE ignored\n", name);
882     if (dwCreationFlags & CREATE_NO_WINDOW)
883         FIXME(module, "(%s,...): CREATE_NO_WINDOW ignored\n", name);
884     if (dwCreationFlags & PROFILE_USER)
885         FIXME(module, "(%s,...): PROFILE_USER ignored\n", name);
886     if (dwCreationFlags & PROFILE_KERNEL)
887         FIXME(module, "(%s,...): PROFILE_KERNEL ignored\n", name);
888     if (dwCreationFlags & PROFILE_SERVER)
889         FIXME(module, "(%s,...): PROFILE_SERVER ignored\n", name);
890     if (lpCurrentDirectory)
891         FIXME(module, "(%s,...): lpCurrentDirectory %s ignored\n", 
892                       name, lpCurrentDirectory);
893     if (lpStartupInfo->lpDesktop)
894         FIXME(module, "(%s,...): lpStartupInfo->lpDesktop %s ignored\n", 
895                       name, lpStartupInfo->lpDesktop);
896     if (lpStartupInfo->lpTitle)
897         FIXME(module, "(%s,...): lpStartupInfo->lpTitle %s ignored\n", 
898                       name, lpStartupInfo->lpTitle);
899     if (lpStartupInfo->dwFlags & STARTF_USECOUNTCHARS)
900         FIXME(module, "(%s,...): STARTF_USECOUNTCHARS (%ld,%ld) ignored\n", 
901                       name, lpStartupInfo->dwXCountChars, lpStartupInfo->dwYCountChars);
902     if (lpStartupInfo->dwFlags & STARTF_USEFILLATTRIBUTE)
903         FIXME(module, "(%s,...): STARTF_USEFILLATTRIBUTE %lx ignored\n", 
904                       name, lpStartupInfo->dwFillAttribute);
905     if (lpStartupInfo->dwFlags & STARTF_RUNFULLSCREEN)
906         FIXME(module, "(%s,...): STARTF_RUNFULLSCREEN ignored\n", name);
907     if (lpStartupInfo->dwFlags & STARTF_FORCEONFEEDBACK)
908         FIXME(module, "(%s,...): STARTF_FORCEONFEEDBACK ignored\n", name);
909     if (lpStartupInfo->dwFlags & STARTF_FORCEOFFFEEDBACK)
910         FIXME(module, "(%s,...): STARTF_FORCEOFFFEEDBACK ignored\n", name);
911     if (lpStartupInfo->dwFlags & STARTF_USEHOTKEY)
912         FIXME(module, "(%s,...): STARTF_USEHOTKEY ignored\n", name);
913
914
915     /* When in WineLib, always fork new Unix process */
916
917     if ( __winelib )
918         return MODULE_CreateUnixProcess( name, cmdline, 
919                                          lpStartupInfo, lpProcessInfo, TRUE );
920
921     /* Check for special case: second instance of NE module */
922
923     lstrcpynA( ofs.szPathName, name, sizeof( ofs.szPathName ) );
924     retv = NE_CreateProcess( HFILE_ERROR, &ofs, cmdline, lpEnvironment, 
925                              bInheritHandles, lpStartupInfo, lpProcessInfo );
926
927     /* Load file and create process */
928
929     if ( !retv )
930     {
931         /* Open file and determine executable type */
932
933         if ( (hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR )
934         {
935             SetLastError( ERROR_FILE_NOT_FOUND );
936             return FALSE;
937         }
938
939         if ( !MODULE_GetBinaryType( hFile, &ofs, &type ) )
940         {
941             CloseHandle( hFile );
942
943             /* FIXME: Try Unix executable only when appropriate! */
944             if ( MODULE_CreateUnixProcess( name, cmdline, 
945                                            lpStartupInfo, lpProcessInfo, FALSE ) )
946                 return TRUE;
947
948             SetLastError( ERROR_BAD_FORMAT );
949             return FALSE;
950         }
951
952
953         /* Create process */
954
955         switch ( type )
956         {
957         case SCS_32BIT_BINARY:
958             retv = PE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment, 
959                                      bInheritHandles, lpStartupInfo, lpProcessInfo );
960             break;
961     
962         case SCS_DOS_BINARY:
963             retv = MZ_CreateProcess( hFile, &ofs, cmdline, lpEnvironment, 
964                                      bInheritHandles, lpStartupInfo, lpProcessInfo );
965             break;
966
967         case SCS_WOW_BINARY:
968             retv = NE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment, 
969                                      bInheritHandles, lpStartupInfo, lpProcessInfo );
970             break;
971
972         case SCS_PIF_BINARY:
973         case SCS_POSIX_BINARY:
974         case SCS_OS216_BINARY:
975             FIXME( module, "Unsupported executable type: %ld\n", type );
976             /* fall through */
977     
978         default:
979             SetLastError( ERROR_BAD_FORMAT );
980             retv = FALSE;
981             break;
982         }
983
984         CloseHandle( hFile );
985     }
986
987     /* Get hTask from process and start the task */
988
989     if ( retv )
990     {
991         PDB *pdb = PROCESS_IdToPDB( lpProcessInfo->dwProcessId );
992         if (pdb) TASK_StartTask( pdb->task );
993     }
994
995     return retv;
996 }
997
998 /**********************************************************************
999  *       CreateProcessW          (KERNEL32.172)
1000  * NOTES
1001  *  lpReserved is not converted
1002  */
1003 BOOL WINAPI CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine, 
1004                                 LPSECURITY_ATTRIBUTES lpProcessAttributes,
1005                                 LPSECURITY_ATTRIBUTES lpThreadAttributes,
1006                                 BOOL bInheritHandles, DWORD dwCreationFlags,
1007                                 LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
1008                                 LPSTARTUPINFOW lpStartupInfo,
1009                                 LPPROCESS_INFORMATION lpProcessInfo )
1010 {   BOOL ret;
1011     STARTUPINFOA StartupInfoA;
1012     
1013     LPSTR lpApplicationNameA = HEAP_strdupWtoA (GetProcessHeap(),0,lpApplicationName);
1014     LPSTR lpCommandLineA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCommandLine);
1015     LPSTR lpCurrentDirectoryA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCurrentDirectory);
1016
1017     memcpy (&StartupInfoA, lpStartupInfo, sizeof(STARTUPINFOA));
1018     StartupInfoA.lpDesktop = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpDesktop);
1019     StartupInfoA.lpTitle = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpTitle);
1020
1021     TRACE(win32, "(%s,%s,...)\n", debugstr_w(lpApplicationName), debugstr_w(lpCommandLine));
1022
1023     if (lpStartupInfo->lpReserved)
1024       FIXME(win32,"StartupInfo.lpReserved is used, please report (%s)\n", debugstr_w(lpStartupInfo->lpReserved));
1025       
1026     ret = CreateProcessA(  lpApplicationNameA,  lpCommandLineA, 
1027                              lpProcessAttributes, lpThreadAttributes,
1028                              bInheritHandles, dwCreationFlags,
1029                              lpEnvironment, lpCurrentDirectoryA,
1030                              &StartupInfoA, lpProcessInfo );
1031
1032     HeapFree( GetProcessHeap(), 0, lpCurrentDirectoryA );
1033     HeapFree( GetProcessHeap(), 0, lpCommandLineA );
1034     HeapFree( GetProcessHeap(), 0, StartupInfoA.lpDesktop );
1035     HeapFree( GetProcessHeap(), 0, StartupInfoA.lpTitle );
1036
1037     return ret;
1038 }
1039
1040 /***********************************************************************
1041  *              GetModuleHandle         (KERNEL32.237)
1042  */
1043 HMODULE WINAPI GetModuleHandleA(LPCSTR module)
1044 {
1045     if (module == NULL)
1046         return PROCESS_Current()->exe_modref->module;
1047     else
1048         return MODULE_FindModule( module );
1049 }
1050
1051 HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
1052 {
1053     HMODULE hModule;
1054     LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
1055     hModule = GetModuleHandleA( modulea );
1056     HeapFree( GetProcessHeap(), 0, modulea );
1057     return hModule;
1058 }
1059
1060
1061 /***********************************************************************
1062  *              GetModuleFileName32A      (KERNEL32.235)
1063  */
1064 DWORD WINAPI GetModuleFileNameA( 
1065         HMODULE hModule,        /* [in] module handle (32bit) */
1066         LPSTR lpFileName,       /* [out] filenamebuffer */
1067         DWORD size              /* [in] size of filenamebuffer */
1068 ) {                   
1069     WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1070
1071     if (!wm) /* can happen on start up or the like */
1072         return 0;
1073
1074     if (PE_HEADER(wm->module)->OptionalHeader.MajorOperatingSystemVersion >= 4.0)
1075       lstrcpynA( lpFileName, wm->longname, size );
1076     else
1077       lstrcpynA( lpFileName, wm->shortname, size );
1078        
1079     TRACE(module, "%s\n", lpFileName );
1080     return strlen(lpFileName);
1081 }                   
1082  
1083
1084 /***********************************************************************
1085  *              GetModuleFileName32W      (KERNEL32.236)
1086  */
1087 DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName,
1088                                    DWORD size )
1089 {
1090     LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1091     DWORD res = GetModuleFileNameA( hModule, fnA, size );
1092     lstrcpynAtoW( lpFileName, fnA, size );
1093     HeapFree( GetProcessHeap(), 0, fnA );
1094     return res;
1095 }
1096
1097
1098 /***********************************************************************
1099  *           LoadLibraryEx32W   (KERNEL.513)
1100  * FIXME
1101  */
1102 HMODULE WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
1103                                        DWORD flags )
1104 {
1105     TRACE(module,"(%s,%d,%08lx)\n",libname,hf,flags);
1106     return LoadLibraryExA(libname, hf,flags);
1107 }
1108
1109 /***********************************************************************
1110  *           LoadLibraryEx32A   (KERNEL32)
1111  */
1112 HMODULE WINAPI LoadLibraryExA(LPCSTR libname,HFILE hfile,DWORD flags)
1113 {
1114     HMODULE hmod;
1115     hmod = MODULE_LoadLibraryExA( libname, hfile, flags );
1116
1117     /* at least call not the dllmain...*/
1118     if ( DONT_RESOLVE_DLL_REFERENCES==flags || LOAD_LIBRARY_AS_DATAFILE==flags )
1119     { FIXME(module,"flag not properly supported %lx\n", flags);
1120       return hmod;
1121     }
1122
1123     /* initialize DLL just loaded */
1124     if ( hmod >= 32 )       
1125         MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, (LPVOID)-1 );
1126
1127     return hmod;
1128 }
1129
1130 HMODULE MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags )
1131 {
1132     HMODULE hmod;
1133     
1134     hmod = ELF_LoadLibraryExA( libname, hfile, flags );
1135     if (hmod) return hmod;
1136
1137     hmod = PE_LoadLibraryExA( libname, hfile, flags );
1138     return hmod;
1139 }
1140
1141 /***********************************************************************
1142  *           LoadLibraryA         (KERNEL32)
1143  */
1144 HMODULE WINAPI LoadLibraryA(LPCSTR libname) {
1145         return LoadLibraryExA(libname,0,0);
1146 }
1147
1148 /***********************************************************************
1149  *           LoadLibraryW         (KERNEL32)
1150  */
1151 HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
1152 {
1153     return LoadLibraryExW(libnameW,0,0);
1154 }
1155
1156 /***********************************************************************
1157  *           LoadLibraryExW       (KERNEL32)
1158  */
1159 HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW,HFILE hfile,DWORD flags)
1160 {
1161     LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
1162     HMODULE ret = LoadLibraryExA( libnameA , hfile, flags );
1163
1164     HeapFree( GetProcessHeap(), 0, libnameA );
1165     return ret;
1166 }
1167
1168 /***********************************************************************
1169  *           FreeLibrary
1170  */
1171 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
1172 {
1173     FIXME(module,"(0x%08x): stub\n", hLibModule);
1174     return TRUE;  /* FIXME */
1175 }
1176
1177
1178 /***********************************************************************
1179  *           PrivateLoadLibrary       (KERNEL32)
1180  *
1181  * FIXME: rough guesswork, don't know what "Private" means
1182  */
1183 HINSTANCE WINAPI PrivateLoadLibrary(LPCSTR libname)
1184 {
1185         return (HINSTANCE)LoadLibrary16(libname);
1186 }
1187
1188
1189
1190 /***********************************************************************
1191  *           PrivateFreeLibrary       (KERNEL32)
1192  *
1193  * FIXME: rough guesswork, don't know what "Private" means
1194  */
1195 void WINAPI PrivateFreeLibrary(HINSTANCE handle)
1196 {
1197         FreeLibrary16((HINSTANCE16)handle);
1198 }
1199
1200
1201 /***********************************************************************
1202  *           WIN32_GetProcAddress16   (KERNEL32.36)
1203  * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1204  */
1205 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hModule, LPCSTR name )
1206 {
1207     WORD        ordinal;
1208     FARPROC16   ret;
1209
1210     if (!hModule) {
1211         WARN(module,"hModule may not be 0!\n");
1212         return (FARPROC16)0;
1213     }
1214     if (HIWORD(hModule))
1215     {
1216         WARN( module, "hModule is Win32 handle (%08x)\n", hModule );
1217         return (FARPROC16)0;
1218     }
1219     hModule = GetExePtr( hModule );
1220     if (HIWORD(name)) {
1221         ordinal = NE_GetOrdinal( hModule, name );
1222         TRACE(module, "%04x '%s'\n",
1223                         hModule, name );
1224     } else {
1225         ordinal = LOWORD(name);
1226         TRACE(module, "%04x %04x\n",
1227                         hModule, ordinal );
1228     }
1229     if (!ordinal) return (FARPROC16)0;
1230     ret = NE_GetEntryPoint( hModule, ordinal );
1231     TRACE(module,"returning %08x\n",(UINT)ret);
1232     return ret;
1233 }
1234
1235 /***********************************************************************
1236  *           GetProcAddress16   (KERNEL.50)
1237  */
1238 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1239 {
1240     WORD ordinal;
1241     FARPROC16 ret;
1242
1243     if (!hModule) hModule = GetCurrentTask();
1244     hModule = GetExePtr( hModule );
1245
1246     if (HIWORD(name) != 0)
1247     {
1248         ordinal = NE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1249         TRACE(module, "%04x '%s'\n",
1250                         hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1251     }
1252     else
1253     {
1254         ordinal = LOWORD(name);
1255         TRACE(module, "%04x %04x\n",
1256                         hModule, ordinal );
1257     }
1258     if (!ordinal) return (FARPROC16)0;
1259
1260     ret = NE_GetEntryPoint( hModule, ordinal );
1261
1262     TRACE(module, "returning %08x\n", (UINT)ret );
1263     return ret;
1264 }
1265
1266
1267 /***********************************************************************
1268  *           GetProcAddress32                   (KERNEL32.257)
1269  */
1270 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
1271 {
1272     return MODULE_GetProcAddress( hModule, function, TRUE );
1273 }
1274
1275 /***********************************************************************
1276  *           WIN16_GetProcAddress32             (KERNEL.453)
1277  */
1278 FARPROC WINAPI GetProcAddress32_16( HMODULE hModule, LPCSTR function )
1279 {
1280     return MODULE_GetProcAddress( hModule, function, FALSE );
1281 }
1282
1283 /***********************************************************************
1284  *           MODULE_GetProcAddress32            (internal)
1285  */
1286 FARPROC MODULE_GetProcAddress( 
1287         HMODULE hModule,        /* [in] current module handle */
1288         LPCSTR function,        /* [in] function to be looked up */
1289         BOOL snoop )
1290 {
1291     WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1292
1293     if (HIWORD(function))
1294         TRACE(win32,"(%08lx,%s)\n",(DWORD)hModule,function);
1295     else
1296         TRACE(win32,"(%08lx,%p)\n",(DWORD)hModule,function);
1297     if (!wm)
1298         return (FARPROC)0;
1299     switch (wm->type)
1300     {
1301     case MODULE32_PE:
1302         return PE_FindExportedFunction( wm, function, snoop );
1303     case MODULE32_ELF:
1304         return ELF_FindExportedFunction( wm, function);
1305     default:
1306         ERR(module,"wine_modref type %d not handled.\n",wm->type);
1307         return (FARPROC)0;
1308     }
1309 }
1310
1311
1312 /***********************************************************************
1313  *           RtlImageNtHeaders   (NTDLL)
1314  */
1315 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
1316 {
1317     /* basically:
1318      * return  hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew); 
1319      * but we could get HMODULE16 or the like (think builtin modules)
1320      */
1321
1322     WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1323     if (!wm || (wm->type != MODULE32_PE)) return (PIMAGE_NT_HEADERS)0;
1324     return PE_HEADER(wm->module);
1325 }
1326
1327
1328 /***************************************************************************
1329  *              HasGPHandler                    (KERNEL.338)
1330  */
1331
1332 #pragma pack(1)
1333 typedef struct _GPHANDLERDEF
1334 {
1335     WORD selector;
1336     WORD rangeStart;
1337     WORD rangeEnd;
1338     WORD handler;
1339 } GPHANDLERDEF;
1340 #pragma pack(4)
1341
1342 SEGPTR WINAPI HasGPHandler16( SEGPTR address )
1343 {
1344     HMODULE16 hModule;
1345     int gpOrdinal;
1346     SEGPTR gpPtr;
1347     GPHANDLERDEF *gpHandler;
1348    
1349     if (    (hModule = FarGetOwner16( SELECTOROF(address) )) != 0
1350          && (gpOrdinal = NE_GetOrdinal( hModule, "__GP" )) != 0
1351          && (gpPtr = (SEGPTR)NE_GetEntryPointEx( hModule, gpOrdinal, FALSE )) != 0
1352          && !IsBadReadPtr16( gpPtr, sizeof(GPHANDLERDEF) )
1353          && (gpHandler = PTR_SEG_TO_LIN( gpPtr )) != NULL )
1354     {
1355         while (gpHandler->selector)
1356         {
1357             if (    SELECTOROF(address) == gpHandler->selector
1358                  && OFFSETOF(address)   >= gpHandler->rangeStart
1359                  && OFFSETOF(address)   <  gpHandler->rangeEnd  )
1360                 return PTR_SEG_OFF_TO_SEGPTR( gpHandler->selector,
1361                                               gpHandler->handler );
1362             gpHandler++;
1363         }
1364     }
1365
1366     return 0;
1367 }
1368