Bugfix: cope with quoted arguments for CreateProcess().
[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     while ( *line == ' ' ) line++;
756     if ( *line == '"' )
757     {
758         line++;      /* skip '"' */
759         if ((pcmd = strchr(line, '"'))) /* closing '"' available, too ? */
760             len = ++pcmd - line;
761     }
762
763     if (!len)
764     {
765         p = strchr(line, ' ');
766         do {
767             len = (p? p-line : strlen(line)) + 1;
768             if (len > namelen - 4) len = namelen - 4;
769             lstrcpynA(name, line, len);
770             if (extension && !strchr(name, '\\') && !strchr(name, '.'))
771                 strcat(name, ".exe");
772             if (GetFileAttributesA(name) != -1) {
773                 pcmd = p ? p : line+strlen(line);
774                 break;
775             }
776             /* if there is a space and no file found yet, include the word
777              * up to the next space too. If there is no next space, just
778              * use the first word.
779              */
780             if (p) {
781                 p = strchr(p+1, ' ');
782             } else {
783                 p = strchr(line, ' ');
784                 len = (p? p-line : strlen(line)) + 1;
785                 if (len > namelen - 4)
786                     len = namelen - 4;
787                 pcmd = p ? p + 1 : line+strlen(line);
788                 break;
789             }
790         } while (1);
791     }
792     lstrcpynA(name, line, len);
793     if (after) *after = pcmd;
794 }
795
796 /**********************************************************************
797  *       CreateProcessA          (KERNEL32.171)
798  */
799 BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine, 
800                             LPSECURITY_ATTRIBUTES lpProcessAttributes,
801                             LPSECURITY_ATTRIBUTES lpThreadAttributes,
802                             BOOL bInheritHandles, DWORD dwCreationFlags,
803                             LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
804                             LPSTARTUPINFOA lpStartupInfo,
805                             LPPROCESS_INFORMATION lpProcessInfo )
806 {
807     BOOL retv = FALSE;
808     HFILE hFile;
809     OFSTRUCT ofs;
810     DWORD type;
811     char name[256];
812     LPCSTR cmdline;
813 #if 0
814     LPCSTR p = NULL;
815 #endif
816
817     /* Get name and command line */
818
819     if (!lpApplicationName && !lpCommandLine)
820     {
821         SetLastError( ERROR_FILE_NOT_FOUND );
822         return FALSE;
823     }
824
825     name[0] = '\0';
826
827     if (lpApplicationName) {
828         get_executable_name( lpApplicationName, name, sizeof(name), NULL, FALSE);
829 #if 0
830         p = strrchr(name, '.');
831         if (p >= name+strlen(name)-4) /* FIXME */
832             *p = '\0';
833 #endif
834     }
835     else {
836       get_executable_name ( lpCommandLine, name, sizeof ( name ), NULL, FALSE );
837     }
838     if (!lpCommandLine) 
839       cmdline = lpApplicationName;
840     else cmdline = lpCommandLine;
841
842     if (!strchr(name, '\\') && !strchr(name, '.'))
843         strcat(name, ".exe");
844
845
846     /* Warn if unsupported features are used */
847
848     if (dwCreationFlags & DEBUG_PROCESS)
849         FIXME(module, "(%s,...): DEBUG_PROCESS ignored\n", name);
850     if (dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
851         FIXME(module, "(%s,...): DEBUG_ONLY_THIS_PROCESS ignored\n", name);
852     if (dwCreationFlags & CREATE_SUSPENDED)
853         FIXME(module, "(%s,...): CREATE_SUSPENDED ignored\n", name);
854     if (dwCreationFlags & DETACHED_PROCESS)
855         FIXME(module, "(%s,...): DETACHED_PROCESS ignored\n", name);
856     if (dwCreationFlags & CREATE_NEW_CONSOLE)
857         FIXME(module, "(%s,...): CREATE_NEW_CONSOLE ignored\n", name);
858     if (dwCreationFlags & NORMAL_PRIORITY_CLASS)
859         FIXME(module, "(%s,...): NORMAL_PRIORITY_CLASS ignored\n", name);
860     if (dwCreationFlags & IDLE_PRIORITY_CLASS)
861         FIXME(module, "(%s,...): IDLE_PRIORITY_CLASS ignored\n", name);
862     if (dwCreationFlags & HIGH_PRIORITY_CLASS)
863         FIXME(module, "(%s,...): HIGH_PRIORITY_CLASS ignored\n", name);
864     if (dwCreationFlags & REALTIME_PRIORITY_CLASS)
865         FIXME(module, "(%s,...): REALTIME_PRIORITY_CLASS ignored\n", name);
866     if (dwCreationFlags & CREATE_NEW_PROCESS_GROUP)
867         FIXME(module, "(%s,...): CREATE_NEW_PROCESS_GROUP ignored\n", name);
868     if (dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)
869         FIXME(module, "(%s,...): CREATE_UNICODE_ENVIRONMENT ignored\n", name);
870     if (dwCreationFlags & CREATE_SEPARATE_WOW_VDM)
871         FIXME(module, "(%s,...): CREATE_SEPARATE_WOW_VDM ignored\n", name);
872     if (dwCreationFlags & CREATE_SHARED_WOW_VDM)
873         FIXME(module, "(%s,...): CREATE_SHARED_WOW_VDM ignored\n", name);
874     if (dwCreationFlags & CREATE_DEFAULT_ERROR_MODE)
875         FIXME(module, "(%s,...): CREATE_DEFAULT_ERROR_MODE ignored\n", name);
876     if (dwCreationFlags & CREATE_NO_WINDOW)
877         FIXME(module, "(%s,...): CREATE_NO_WINDOW ignored\n", name);
878     if (dwCreationFlags & PROFILE_USER)
879         FIXME(module, "(%s,...): PROFILE_USER ignored\n", name);
880     if (dwCreationFlags & PROFILE_KERNEL)
881         FIXME(module, "(%s,...): PROFILE_KERNEL ignored\n", name);
882     if (dwCreationFlags & PROFILE_SERVER)
883         FIXME(module, "(%s,...): PROFILE_SERVER ignored\n", name);
884     if (lpCurrentDirectory)
885         FIXME(module, "(%s,...): lpCurrentDirectory %s ignored\n", 
886                       name, lpCurrentDirectory);
887     if (lpStartupInfo->lpDesktop)
888         FIXME(module, "(%s,...): lpStartupInfo->lpDesktop %s ignored\n", 
889                       name, lpStartupInfo->lpDesktop);
890     if (lpStartupInfo->lpTitle)
891         FIXME(module, "(%s,...): lpStartupInfo->lpTitle %s ignored\n", 
892                       name, lpStartupInfo->lpTitle);
893     if (lpStartupInfo->dwFlags & STARTF_USECOUNTCHARS)
894         FIXME(module, "(%s,...): STARTF_USECOUNTCHARS (%ld,%ld) ignored\n", 
895                       name, lpStartupInfo->dwXCountChars, lpStartupInfo->dwYCountChars);
896     if (lpStartupInfo->dwFlags & STARTF_USEFILLATTRIBUTE)
897         FIXME(module, "(%s,...): STARTF_USEFILLATTRIBUTE %lx ignored\n", 
898                       name, lpStartupInfo->dwFillAttribute);
899     if (lpStartupInfo->dwFlags & STARTF_RUNFULLSCREEN)
900         FIXME(module, "(%s,...): STARTF_RUNFULLSCREEN ignored\n", name);
901     if (lpStartupInfo->dwFlags & STARTF_FORCEONFEEDBACK)
902         FIXME(module, "(%s,...): STARTF_FORCEONFEEDBACK ignored\n", name);
903     if (lpStartupInfo->dwFlags & STARTF_FORCEOFFFEEDBACK)
904         FIXME(module, "(%s,...): STARTF_FORCEOFFFEEDBACK ignored\n", name);
905     if (lpStartupInfo->dwFlags & STARTF_USEHOTKEY)
906         FIXME(module, "(%s,...): STARTF_USEHOTKEY ignored\n", name);
907
908
909     /* When in WineLib, always fork new Unix process */
910
911     if ( __winelib )
912         return MODULE_CreateUnixProcess( name, cmdline, 
913                                          lpStartupInfo, lpProcessInfo, TRUE );
914
915     /* Check for special case: second instance of NE module */
916
917     lstrcpynA( ofs.szPathName, name, sizeof( ofs.szPathName ) );
918     retv = NE_CreateProcess( HFILE_ERROR, &ofs, cmdline, lpEnvironment, 
919                              lpProcessAttributes, lpThreadAttributes,
920                              bInheritHandles, lpStartupInfo, lpProcessInfo );
921
922     /* Load file and create process */
923
924     if ( !retv )
925     {
926         /* Open file and determine executable type */
927
928         if ( (hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR )
929         {
930             SetLastError( ERROR_FILE_NOT_FOUND );
931             return FALSE;
932         }
933
934         if ( !MODULE_GetBinaryType( hFile, &ofs, &type ) )
935         {
936             CloseHandle( hFile );
937
938             /* FIXME: Try Unix executable only when appropriate! */
939             if ( MODULE_CreateUnixProcess( name, cmdline, 
940                                            lpStartupInfo, lpProcessInfo, FALSE ) )
941                 return TRUE;
942
943             SetLastError( ERROR_BAD_FORMAT );
944             return FALSE;
945         }
946
947
948         /* Create process */
949
950         switch ( type )
951         {
952         case SCS_32BIT_BINARY:
953             retv = PE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment, 
954                                      lpProcessAttributes, lpThreadAttributes,
955                                      bInheritHandles, lpStartupInfo, lpProcessInfo );
956             break;
957     
958         case SCS_DOS_BINARY:
959             retv = MZ_CreateProcess( hFile, &ofs, cmdline, lpEnvironment, 
960                                      lpProcessAttributes, lpThreadAttributes,
961                                      bInheritHandles, lpStartupInfo, lpProcessInfo );
962             break;
963
964         case SCS_WOW_BINARY:
965             retv = NE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment, 
966                                      lpProcessAttributes, lpThreadAttributes,
967                                      bInheritHandles, lpStartupInfo, lpProcessInfo );
968             break;
969
970         case SCS_PIF_BINARY:
971         case SCS_POSIX_BINARY:
972         case SCS_OS216_BINARY:
973             FIXME( module, "Unsupported executable type: %ld\n", type );
974             /* fall through */
975     
976         default:
977             SetLastError( ERROR_BAD_FORMAT );
978             retv = FALSE;
979             break;
980         }
981
982         CloseHandle( hFile );
983     }
984     return retv;
985 }
986
987 /**********************************************************************
988  *       CreateProcessW          (KERNEL32.172)
989  * NOTES
990  *  lpReserved is not converted
991  */
992 BOOL WINAPI CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine, 
993                                 LPSECURITY_ATTRIBUTES lpProcessAttributes,
994                                 LPSECURITY_ATTRIBUTES lpThreadAttributes,
995                                 BOOL bInheritHandles, DWORD dwCreationFlags,
996                                 LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
997                                 LPSTARTUPINFOW lpStartupInfo,
998                                 LPPROCESS_INFORMATION lpProcessInfo )
999 {   BOOL ret;
1000     STARTUPINFOA StartupInfoA;
1001     
1002     LPSTR lpApplicationNameA = HEAP_strdupWtoA (GetProcessHeap(),0,lpApplicationName);
1003     LPSTR lpCommandLineA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCommandLine);
1004     LPSTR lpCurrentDirectoryA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCurrentDirectory);
1005
1006     memcpy (&StartupInfoA, lpStartupInfo, sizeof(STARTUPINFOA));
1007     StartupInfoA.lpDesktop = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpDesktop);
1008     StartupInfoA.lpTitle = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpTitle);
1009
1010     TRACE(win32, "(%s,%s,...)\n", debugstr_w(lpApplicationName), debugstr_w(lpCommandLine));
1011
1012     if (lpStartupInfo->lpReserved)
1013       FIXME(win32,"StartupInfo.lpReserved is used, please report (%s)\n", debugstr_w(lpStartupInfo->lpReserved));
1014       
1015     ret = CreateProcessA(  lpApplicationNameA,  lpCommandLineA, 
1016                              lpProcessAttributes, lpThreadAttributes,
1017                              bInheritHandles, dwCreationFlags,
1018                              lpEnvironment, lpCurrentDirectoryA,
1019                              &StartupInfoA, lpProcessInfo );
1020
1021     HeapFree( GetProcessHeap(), 0, lpCurrentDirectoryA );
1022     HeapFree( GetProcessHeap(), 0, lpCommandLineA );
1023     HeapFree( GetProcessHeap(), 0, StartupInfoA.lpDesktop );
1024     HeapFree( GetProcessHeap(), 0, StartupInfoA.lpTitle );
1025
1026     return ret;
1027 }
1028
1029 /***********************************************************************
1030  *              GetModuleHandle         (KERNEL32.237)
1031  */
1032 HMODULE WINAPI GetModuleHandleA(LPCSTR module)
1033 {
1034     if (module == NULL)
1035         return PROCESS_Current()->exe_modref->module;
1036     else
1037         return MODULE_FindModule( module );
1038 }
1039
1040 HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
1041 {
1042     HMODULE hModule;
1043     LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
1044     hModule = GetModuleHandleA( modulea );
1045     HeapFree( GetProcessHeap(), 0, modulea );
1046     return hModule;
1047 }
1048
1049
1050 /***********************************************************************
1051  *              GetModuleFileName32A      (KERNEL32.235)
1052  */
1053 DWORD WINAPI GetModuleFileNameA( 
1054         HMODULE hModule,        /* [in] module handle (32bit) */
1055         LPSTR lpFileName,       /* [out] filenamebuffer */
1056         DWORD size              /* [in] size of filenamebuffer */
1057 ) {                   
1058     WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1059
1060     if (!wm) /* can happen on start up or the like */
1061         return 0;
1062
1063     if (PE_HEADER(wm->module)->OptionalHeader.MajorOperatingSystemVersion >= 4.0)
1064       lstrcpynA( lpFileName, wm->longname, size );
1065     else
1066       lstrcpynA( lpFileName, wm->shortname, size );
1067        
1068     TRACE(module, "%s\n", lpFileName );
1069     return strlen(lpFileName);
1070 }                   
1071  
1072
1073 /***********************************************************************
1074  *              GetModuleFileName32W      (KERNEL32.236)
1075  */
1076 DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName,
1077                                    DWORD size )
1078 {
1079     LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1080     DWORD res = GetModuleFileNameA( hModule, fnA, size );
1081     lstrcpynAtoW( lpFileName, fnA, size );
1082     HeapFree( GetProcessHeap(), 0, fnA );
1083     return res;
1084 }
1085
1086
1087 /***********************************************************************
1088  *           LoadLibraryEx32W   (KERNEL.513)
1089  * FIXME
1090  */
1091 HMODULE WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
1092                                        DWORD flags )
1093 {
1094     TRACE(module,"(%s,%d,%08lx)\n",libname,hf,flags);
1095     return LoadLibraryExA(libname, hf,flags);
1096 }
1097
1098 /***********************************************************************
1099  *           LoadLibraryEx32A   (KERNEL32)
1100  */
1101 HMODULE WINAPI LoadLibraryExA(LPCSTR libname,HFILE hfile,DWORD flags)
1102 {
1103     HMODULE hmod;
1104     hmod = MODULE_LoadLibraryExA( libname, hfile, flags );
1105
1106     /* at least call not the dllmain...*/
1107     if ( DONT_RESOLVE_DLL_REFERENCES==flags || LOAD_LIBRARY_AS_DATAFILE==flags )
1108     { FIXME(module,"flag not properly supported %lx\n", flags);
1109       return hmod;
1110     }
1111
1112     /* initialize DLL just loaded */
1113     if ( hmod >= 32 )       
1114         MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, (LPVOID)-1 );
1115
1116     return hmod;
1117 }
1118
1119 HMODULE MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags )
1120 {
1121     HMODULE hmod;
1122     
1123     hmod = ELF_LoadLibraryExA( libname, hfile, flags );
1124     if (hmod) return hmod;
1125
1126     hmod = PE_LoadLibraryExA( libname, hfile, flags );
1127     return hmod;
1128 }
1129
1130 /***********************************************************************
1131  *           LoadLibraryA         (KERNEL32)
1132  */
1133 HMODULE WINAPI LoadLibraryA(LPCSTR libname) {
1134         return LoadLibraryExA(libname,0,0);
1135 }
1136
1137 /***********************************************************************
1138  *           LoadLibraryW         (KERNEL32)
1139  */
1140 HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
1141 {
1142     return LoadLibraryExW(libnameW,0,0);
1143 }
1144
1145 /***********************************************************************
1146  *           LoadLibraryExW       (KERNEL32)
1147  */
1148 HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW,HFILE hfile,DWORD flags)
1149 {
1150     LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
1151     HMODULE ret = LoadLibraryExA( libnameA , hfile, flags );
1152
1153     HeapFree( GetProcessHeap(), 0, libnameA );
1154     return ret;
1155 }
1156
1157 /***********************************************************************
1158  *           FreeLibrary
1159  */
1160 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
1161 {
1162     FIXME(module,"(0x%08x): stub\n", hLibModule);
1163     return TRUE;  /* FIXME */
1164 }
1165
1166 /***********************************************************************
1167  *           FreeLibraryAndExitThread
1168  */
1169 VOID WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
1170 {
1171     FreeLibrary(hLibModule);
1172     ExitThread(dwExitCode);
1173 }
1174
1175 /***********************************************************************
1176  *           PrivateLoadLibrary       (KERNEL32)
1177  *
1178  * FIXME: rough guesswork, don't know what "Private" means
1179  */
1180 HINSTANCE WINAPI PrivateLoadLibrary(LPCSTR libname)
1181 {
1182         return (HINSTANCE)LoadLibrary16(libname);
1183 }
1184
1185
1186
1187 /***********************************************************************
1188  *           PrivateFreeLibrary       (KERNEL32)
1189  *
1190  * FIXME: rough guesswork, don't know what "Private" means
1191  */
1192 void WINAPI PrivateFreeLibrary(HINSTANCE handle)
1193 {
1194         FreeLibrary16((HINSTANCE16)handle);
1195 }
1196
1197
1198 /***********************************************************************
1199  *           WIN32_GetProcAddress16   (KERNEL32.36)
1200  * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1201  */
1202 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hModule, LPCSTR name )
1203 {
1204     WORD        ordinal;
1205     FARPROC16   ret;
1206
1207     if (!hModule) {
1208         WARN(module,"hModule may not be 0!\n");
1209         return (FARPROC16)0;
1210     }
1211     if (HIWORD(hModule))
1212     {
1213         WARN( module, "hModule is Win32 handle (%08x)\n", hModule );
1214         return (FARPROC16)0;
1215     }
1216     hModule = GetExePtr( hModule );
1217     if (HIWORD(name)) {
1218         ordinal = NE_GetOrdinal( hModule, name );
1219         TRACE(module, "%04x '%s'\n",
1220                         hModule, name );
1221     } else {
1222         ordinal = LOWORD(name);
1223         TRACE(module, "%04x %04x\n",
1224                         hModule, ordinal );
1225     }
1226     if (!ordinal) return (FARPROC16)0;
1227     ret = NE_GetEntryPoint( hModule, ordinal );
1228     TRACE(module,"returning %08x\n",(UINT)ret);
1229     return ret;
1230 }
1231
1232 /***********************************************************************
1233  *           GetProcAddress16   (KERNEL.50)
1234  */
1235 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1236 {
1237     WORD ordinal;
1238     FARPROC16 ret;
1239
1240     if (!hModule) hModule = GetCurrentTask();
1241     hModule = GetExePtr( hModule );
1242
1243     if (HIWORD(name) != 0)
1244     {
1245         ordinal = NE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1246         TRACE(module, "%04x '%s'\n",
1247                         hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1248     }
1249     else
1250     {
1251         ordinal = LOWORD(name);
1252         TRACE(module, "%04x %04x\n",
1253                         hModule, ordinal );
1254     }
1255     if (!ordinal) return (FARPROC16)0;
1256
1257     ret = NE_GetEntryPoint( hModule, ordinal );
1258
1259     TRACE(module, "returning %08x\n", (UINT)ret );
1260     return ret;
1261 }
1262
1263
1264 /***********************************************************************
1265  *           GetProcAddress32                   (KERNEL32.257)
1266  */
1267 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
1268 {
1269     return MODULE_GetProcAddress( hModule, function, TRUE );
1270 }
1271
1272 /***********************************************************************
1273  *           WIN16_GetProcAddress32             (KERNEL.453)
1274  */
1275 FARPROC WINAPI GetProcAddress32_16( HMODULE hModule, LPCSTR function )
1276 {
1277     return MODULE_GetProcAddress( hModule, function, FALSE );
1278 }
1279
1280 /***********************************************************************
1281  *           MODULE_GetProcAddress32            (internal)
1282  */
1283 FARPROC MODULE_GetProcAddress( 
1284         HMODULE hModule,        /* [in] current module handle */
1285         LPCSTR function,        /* [in] function to be looked up */
1286         BOOL snoop )
1287 {
1288     WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1289
1290     if (HIWORD(function))
1291         TRACE(win32,"(%08lx,%s)\n",(DWORD)hModule,function);
1292     else
1293         TRACE(win32,"(%08lx,%p)\n",(DWORD)hModule,function);
1294     if (!wm)
1295         return (FARPROC)0;
1296     switch (wm->type)
1297     {
1298     case MODULE32_PE:
1299         return PE_FindExportedFunction( wm, function, snoop );
1300     case MODULE32_ELF:
1301         return ELF_FindExportedFunction( wm, function);
1302     default:
1303         ERR(module,"wine_modref type %d not handled.\n",wm->type);
1304         return (FARPROC)0;
1305     }
1306 }
1307
1308
1309 /***********************************************************************
1310  *           RtlImageNtHeaders   (NTDLL)
1311  */
1312 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
1313 {
1314     /* basically:
1315      * return  hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew); 
1316      * but we could get HMODULE16 or the like (think builtin modules)
1317      */
1318
1319     WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1320     if (!wm || (wm->type != MODULE32_PE)) return (PIMAGE_NT_HEADERS)0;
1321     return PE_HEADER(wm->module);
1322 }
1323
1324
1325 /***************************************************************************
1326  *              HasGPHandler                    (KERNEL.338)
1327  */
1328
1329 #pragma pack(1)
1330 typedef struct _GPHANDLERDEF
1331 {
1332     WORD selector;
1333     WORD rangeStart;
1334     WORD rangeEnd;
1335     WORD handler;
1336 } GPHANDLERDEF;
1337 #pragma pack(4)
1338
1339 SEGPTR WINAPI HasGPHandler16( SEGPTR address )
1340 {
1341     HMODULE16 hModule;
1342     int gpOrdinal;
1343     SEGPTR gpPtr;
1344     GPHANDLERDEF *gpHandler;
1345    
1346     if (    (hModule = FarGetOwner16( SELECTOROF(address) )) != 0
1347          && (gpOrdinal = NE_GetOrdinal( hModule, "__GP" )) != 0
1348          && (gpPtr = (SEGPTR)NE_GetEntryPointEx( hModule, gpOrdinal, FALSE )) != 0
1349          && !IsBadReadPtr16( gpPtr, sizeof(GPHANDLERDEF) )
1350          && (gpHandler = PTR_SEG_TO_LIN( gpPtr )) != NULL )
1351     {
1352         while (gpHandler->selector)
1353         {
1354             if (    SELECTOROF(address) == gpHandler->selector
1355                  && OFFSETOF(address)   >= gpHandler->rangeStart
1356                  && OFFSETOF(address)   <  gpHandler->rangeEnd  )
1357                 return PTR_SEG_OFF_TO_SEGPTR( gpHandler->selector,
1358                                               gpHandler->handler );
1359             gpHandler++;
1360         }
1361     }
1362
1363     return 0;
1364 }
1365