Added __attribute__ ((unused)) on static inline functions declared in
[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 "winerror.h"
16 #include "class.h"
17 #include "file.h"
18 #include "global.h"
19 #include "heap.h"
20 #include "module.h"
21 #include "neexe.h"
22 #include "pe_image.h"
23 #include "dosexe.h"
24 #include "process.h"
25 #include "thread.h"
26 #include "selectors.h"
27 #include "stackframe.h"
28 #include "task.h"
29 #include "debug.h"
30 #include "callback.h"
31
32 extern BOOL32 THREAD_InitDone;
33
34
35 /*************************************************************************
36  *              MODULE32_LookupHMODULE
37  * looks for the referenced HMODULE in the current process
38  */
39 WINE_MODREF *MODULE32_LookupHMODULE( HMODULE32 hmod )
40 {
41     WINE_MODREF *wm;
42
43     if (!hmod) 
44         return PROCESS_Current()->exe_modref;
45
46     if (!HIWORD(hmod)) {
47         ERR(module,"tried to lookup 0x%04x in win32 module handler!\n",hmod);
48         return NULL;
49     }
50     for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next )
51         if (wm->module == hmod)
52             return wm;
53     return NULL;
54 }
55
56 /*************************************************************************
57  *              MODULE_InitializeDLLs
58  * 
59  * Call the initialization routines of all DLLs belonging to the
60  * current process. This is somewhat complicated due to the fact that
61  *
62  * - we have to respect the module dependencies, i.e. modules implicitly
63  *   referenced by another module have to be initialized before the module
64  *   itself can be initialized
65  * 
66  * - the initialization routine of a DLL can itself call LoadLibrary,
67  *   thereby introducing a whole new set of dependencies (even involving
68  *   the 'old' modules) at any time during the whole process
69  *
70  * (Note that this routine can be recursively entered not only directly
71  *  from itself, but also via LoadLibrary from one of the called initialization
72  *  routines.)
73  */
74 static void MODULE_DoInitializeDLLs( WINE_MODREF *wm,
75                                      DWORD type, LPVOID lpReserved )
76 {
77     int i;
78
79     assert( wm && !wm->initDone );
80     TRACE( module, "(%08x,%ld,%p) - START\n", 
81            wm->module, type, lpReserved );
82
83     /* Tag current MODREF to prevent recursive loop */
84     wm->initDone = TRUE;
85
86     /* Recursively initialize all child DLLs */
87     for ( i = 0; i < wm->nDeps; i++ )
88         if ( wm->deps[i] && !wm->deps[i]->initDone )
89             MODULE_DoInitializeDLLs( wm->deps[i], type, lpReserved );
90
91     /* Now we can call the initialization routine */
92     switch ( wm->type )
93     {
94     case MODULE32_PE:
95         PE_InitDLL( wm, type, lpReserved );
96         break;
97
98     case MODULE32_ELF:
99         /* no need to do that, dlopen() already does */
100         break;
101     default:
102         ERR(module, "wine_modref type %d not handled.\n", wm->type);
103         break;
104     }
105
106     TRACE( module, "(%08x,%ld,%p) - END\n", 
107            wm->module, type, lpReserved );
108 }
109
110 void MODULE_InitializeDLLs( HMODULE32 root, DWORD type, LPVOID lpReserved )
111 {
112     BOOL32 inProgress = FALSE;
113     WINE_MODREF *wm;
114
115     /* Grab the process critical section to protect the recursion flags */
116     /* FIXME: This is probably overkill! */
117     EnterCriticalSection( &PROCESS_Current()->crit_section );
118
119     TRACE( module, "(%08x,%ld,%p) - START\n", root, type, lpReserved );
120
121     /* First, check whether initialization is currently in progress */
122     for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
123         if ( wm->initDone )
124         {
125             inProgress = TRUE;
126             break;
127         }
128
129     if ( inProgress )
130     {
131         /* 
132          * If this a LoadLibrary call from within an initialization routine,
133          * treat it analogously to an implicitly referenced DLL.
134          * Anything else may not happen at this point!
135          */
136         if ( root )
137         {
138             wm = MODULE32_LookupHMODULE( root );
139             if ( wm && !wm->initDone )
140                 MODULE_DoInitializeDLLs( wm, type, lpReserved );
141         }
142         else
143             FIXME(module, "Invalid recursion!\n");
144     }
145     else
146     {
147         /* If we arrive here, this is the start of an initialization run */
148         if ( !root )
149         {
150             /* If called for main EXE, initialize all DLLs */
151             for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
152                 if ( !wm->initDone )
153                     MODULE_DoInitializeDLLs( wm, type, lpReserved );
154         }
155         else
156         {
157             /* If called for a specific DLL, initialize only it and its children */
158             wm = MODULE32_LookupHMODULE( root );
159             if (wm) MODULE_DoInitializeDLLs( wm, type, lpReserved );
160         }
161
162         /* We're finished, so we reset all recursion flags */
163         for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
164             wm->initDone = FALSE;
165     }
166
167     TRACE( module, "(%08x,%ld,%p) - END\n", root, type, lpReserved );
168
169     /* Release critical section */
170     LeaveCriticalSection( &PROCESS_Current()->crit_section );
171 }
172
173
174 /***********************************************************************
175  *           MODULE_CreateDummyModule
176  *
177  * Create a dummy NE module for Win32 or Winelib.
178  */
179 HMODULE32 MODULE_CreateDummyModule( const OFSTRUCT *ofs, LPCSTR modName )
180 {
181     HMODULE32 hModule;
182     NE_MODULE *pModule;
183     SEGTABLEENTRY *pSegment;
184     char *pStr,*s;
185     int len;
186     const char* basename;
187
188     INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
189                     + strlen(ofs->szPathName) + 1;
190     INT32 size = sizeof(NE_MODULE) +
191                  /* loaded file info */
192                  of_size +
193                  /* segment table: DS,CS */
194                  2 * sizeof(SEGTABLEENTRY) +
195                  /* name table */
196                  9 +
197                  /* several empty tables */
198                  8;
199
200     hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
201     if (!hModule) return (HMODULE32)11;  /* invalid exe */
202
203     FarSetOwner( hModule, hModule );
204     pModule = (NE_MODULE *)GlobalLock16( hModule );
205
206     /* Set all used entries */
207     pModule->magic            = IMAGE_OS2_SIGNATURE;
208     pModule->count            = 1;
209     pModule->next             = 0;
210     pModule->flags            = 0;
211     pModule->dgroup           = 1;
212     pModule->ss               = 1;
213     pModule->cs               = 2;
214     pModule->heap_size        = 0xe000;
215     pModule->stack_size       = 0x1000;
216     pModule->seg_count        = 2;
217     pModule->modref_count     = 0;
218     pModule->nrname_size      = 0;
219     pModule->fileinfo         = sizeof(NE_MODULE);
220     pModule->os_flags         = NE_OSFLAGS_WINDOWS;
221     pModule->expected_version = 0x030a;
222     pModule->self             = hModule;
223
224     /* Set loaded file information */
225     memcpy( pModule + 1, ofs, of_size );
226     ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
227
228     pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
229     pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
230     /* Data segment */
231     pSegment->size    = 0;
232     pSegment->flags   = NE_SEGFLAGS_DATA;
233     pSegment->minsize = 0x1000;
234     pSegment++;
235     /* Code segment */
236     pSegment->flags   = 0;
237     pSegment++;
238
239     /* Module name */
240     pStr = (char *)pSegment;
241     pModule->name_table = (int)pStr - (int)pModule;
242     if ( modName )
243         basename = modName;
244     else
245     {
246         basename = strrchr(ofs->szPathName,'\\');
247         if (!basename) basename = ofs->szPathName;
248         else basename++;
249     }
250     len = strlen(basename);
251     if ((s = strchr(basename,'.'))) len = s - basename;
252     if (len > 8) len = 8;
253     *pStr = len;
254     strncpy( pStr+1, basename, len );
255     if (len < 8) pStr[len+1] = 0;
256     pStr += 9;
257
258     /* All tables zero terminated */
259     pModule->res_table = pModule->import_table = pModule->entry_table =
260                 (int)pStr - (int)pModule;
261
262     NE_RegisterModule( pModule );
263     return hModule;
264 }
265
266
267 /***********************************************************************
268  *           MODULE_GetWndProcEntry16  (not a Windows API function)
269  *
270  * Return an entry point from the WPROCS dll.
271  */
272 FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name )
273 {
274     FARPROC16 ret = NULL;
275
276     if (__winelib)
277     {
278         /* FIXME: hack for Winelib */
279         extern LRESULT ColorDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
280         extern LRESULT FileOpenDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
281         extern LRESULT FileSaveDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
282         extern LRESULT FindTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
283         extern LRESULT PrintDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
284         extern LRESULT PrintSetupDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
285         extern LRESULT ReplaceTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
286
287         if (!strcmp(name,"ColorDlgProc"))
288             return (FARPROC16)ColorDlgProc;
289         if (!strcmp(name,"FileOpenDlgProc"))
290             return (FARPROC16)FileOpenDlgProc;
291         if (!strcmp(name,"FileSaveDlgProc"))
292             return (FARPROC16)FileSaveDlgProc;
293         if (!strcmp(name,"FindTextDlgProc"))
294             return (FARPROC16)FindTextDlgProc16;
295         if (!strcmp(name,"PrintDlgProc"))
296             return (FARPROC16)PrintDlgProc;
297         if (!strcmp(name,"PrintSetupDlgProc"))
298             return (FARPROC16)PrintSetupDlgProc;
299         if (!strcmp(name,"ReplaceTextDlgProc"))
300             return (FARPROC16)ReplaceTextDlgProc16;
301         if (!strcmp(name,"DefResourceHandler"))
302             return (FARPROC16)NE_DefResourceHandler;
303         if (!strcmp(name,"LoadDIBIconHandler"))
304             return (FARPROC16)LoadDIBIconHandler;
305         if (!strcmp(name,"LoadDIBCursorHandler"))
306             return (FARPROC16)LoadDIBCursorHandler;
307         FIXME(module,"No mapping for %s(), add one in library/miscstubs.c\n",name);
308         assert( FALSE );
309         return NULL;
310     }
311     else
312     {
313         WORD ordinal;
314         static HMODULE32 hModule = 0;
315
316         if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
317         ordinal = NE_GetOrdinal( hModule, name );
318         if (!(ret = NE_GetEntryPoint( hModule, ordinal )))
319         {            
320             WARN( module, "%s not found\n", name );
321             assert( FALSE );
322         }
323     }
324     return ret;
325 }
326
327
328 /**********************************************************************
329  *          MODULE_FindModule32
330  *
331  * Find a (loaded) win32 module depending on path
332  * The handling of '.' is a bit weird, but we need it that way, 
333  * for sometimes the programs use '<name>.exe' and '<name>.dll' and
334  * this is the only way to differentiate. (mainly hypertrm.exe)
335  *
336  * RETURNS
337  *      the module handle if found
338  *      0 if not
339  */
340 HMODULE32 MODULE_FindModule32(
341         LPCSTR path     /* [in] pathname of module/library to be found */
342 ) {
343     LPSTR       filename;
344     LPSTR       dotptr;
345     WINE_MODREF *wm;
346
347     if (!(filename = strrchr( path, '\\' )))
348         filename = HEAP_strdupA( GetProcessHeap(), 0, path );
349     else 
350         filename = HEAP_strdupA( GetProcessHeap(), 0, filename+1 );
351     dotptr=strrchr(filename,'.');
352
353     for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next ) {
354         LPSTR   xmodname,xdotptr;
355
356         assert (wm->modname);
357         xmodname = HEAP_strdupA( GetProcessHeap(), 0, wm->modname );
358         xdotptr=strrchr(xmodname,'.');
359         if (    (xdotptr && !dotptr) ||
360                 (!xdotptr && dotptr)
361         ) {
362             if (dotptr) *dotptr         = '\0';
363             if (xdotptr) *xdotptr       = '\0';
364         }
365         if (!strcasecmp( filename, xmodname)) {
366             HeapFree( GetProcessHeap(), 0, filename );
367             HeapFree( GetProcessHeap(), 0, xmodname );
368             return wm->module;
369         }
370         if (dotptr) *dotptr='.';
371         /* FIXME: add paths, shortname */
372         HeapFree( GetProcessHeap(), 0, xmodname );
373     }
374     /* if that fails, try looking for the filename... */
375     for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next ) {
376         LPSTR   xlname,xdotptr;
377
378         assert (wm->longname);
379         xlname = strrchr(wm->longname,'\\');
380         if (!xlname) 
381             xlname = wm->longname;
382         else
383             xlname++;
384         xlname = HEAP_strdupA( GetProcessHeap(), 0, xlname );
385         xdotptr=strrchr(xlname,'.');
386         if (    (xdotptr && !dotptr) ||
387                 (!xdotptr && dotptr)
388         ) {
389             if (dotptr) *dotptr         = '\0';
390             if (xdotptr) *xdotptr       = '\0';
391         }
392         if (!strcasecmp( filename, xlname)) {
393             HeapFree( GetProcessHeap(), 0, filename );
394             HeapFree( GetProcessHeap(), 0, xlname );
395             return wm->module;
396         }
397         if (dotptr) *dotptr='.';
398         /* FIXME: add paths, shortname */
399         HeapFree( GetProcessHeap(), 0, xlname );
400     }
401     HeapFree( GetProcessHeap(), 0, filename );
402     return 0;
403 }
404
405
406
407 /**********************************************************************
408  *          NE_CreateProcess
409  */
410 static HINSTANCE16 NE_CreateProcess( LPCSTR name, LPCSTR cmd_line, LPCSTR env, 
411                                      BOOL32 inherit, LPSTARTUPINFO32A startup, 
412                                      LPPROCESS_INFORMATION info )
413 {
414     HINSTANCE16 hInstance, hPrevInstance;
415     NE_MODULE *pModule;
416
417     /* Load module */
418
419     hInstance = NE_LoadModule( name, &hPrevInstance, TRUE, FALSE );
420     if (hInstance < 32) return hInstance;
421
422     if (   !(pModule = NE_GetPtr(hInstance)) 
423         ||  (pModule->flags & NE_FFLAGS_LIBMODULE))
424     {
425         /* FIXME: cleanup */
426         return 11;
427     }
428
429     /* Create a task for this instance */
430
431     pModule->flags |= NE_FFLAGS_GUI;  /* FIXME: is this necessary? */
432
433     PROCESS_Create( pModule, cmd_line, env, hInstance,
434                     hPrevInstance, inherit, startup, info );
435
436     return hInstance;
437 }
438
439
440 /**********************************************************************
441  *          LoadModule16    (KERNEL.45)
442  */
443 HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
444 {
445     LOADPARAMS *params;
446     LPSTR cmd_line, new_cmd_line;
447     LPCVOID env = NULL;
448     STARTUPINFO32A startup;
449     PROCESS_INFORMATION info;
450     HINSTANCE16 hInstance, hPrevInstance;
451     NE_MODULE *pModule;
452     PDB32 *pdb;
453
454     /* Load module */
455
456     if (!paramBlock || (paramBlock == (LPVOID)-1))
457         return LoadLibrary16( name );
458
459     hInstance = NE_LoadModule( name, &hPrevInstance, FALSE, FALSE );
460     if (   hInstance < 32 || !(pModule = NE_GetPtr(hInstance))
461         || (pModule->flags & NE_FFLAGS_LIBMODULE)) 
462         return hInstance;
463
464     /* Create a task for this instance */
465
466     pModule->flags |= NE_FFLAGS_GUI;  /* FIXME: is this necessary? */
467
468     params = (LOADPARAMS *)paramBlock;
469     cmd_line = (LPSTR)PTR_SEG_TO_LIN( params->cmdLine );
470     if (!cmd_line) cmd_line = "";
471     else if (*cmd_line) cmd_line++;  /* skip the length byte */
472
473     if (!(new_cmd_line = HeapAlloc( GetProcessHeap(), 0,
474                                     strlen(cmd_line)+strlen(name)+2 )))
475         return 0;
476     strcpy( new_cmd_line, name );
477     strcat( new_cmd_line, " " );
478     strcat( new_cmd_line, cmd_line );
479
480     if (params->hEnvironment) env = GlobalLock16( params->hEnvironment );
481
482     memset( &info, '\0', sizeof(info) );
483     memset( &startup, '\0', sizeof(startup) );
484     startup.cb = sizeof(startup);
485     if (params->showCmd)
486     {
487         startup.dwFlags = STARTF_USESHOWWINDOW;
488         startup.wShowWindow = ((UINT16 *)PTR_SEG_TO_LIN(params->showCmd))[1];
489     }
490
491     pdb = PROCESS_Create( pModule, new_cmd_line, env, 
492                           hInstance, hPrevInstance, TRUE, &startup, &info );
493
494     CloseHandle( info.hThread );
495     CloseHandle( info.hProcess );
496
497     if (params->hEnvironment) GlobalUnlock16( params->hEnvironment );
498     HeapFree( GetProcessHeap(), 0, new_cmd_line );
499
500     /* Start task */
501
502     if (pdb) TASK_StartTask( pdb->task );
503
504     return hInstance;
505 }
506
507 /**********************************************************************
508  *          LoadModule32    (KERNEL32.499)
509  */
510 HINSTANCE32 WINAPI LoadModule32( LPCSTR name, LPVOID paramBlock ) 
511 {
512     LOADPARAMS32 *params = (LOADPARAMS32 *)paramBlock;
513     PROCESS_INFORMATION info;
514     STARTUPINFO32A startup;
515     HINSTANCE32 hInstance;
516     PDB32 *pdb;
517     TDB *tdb;
518
519     memset( &startup, '\0', sizeof(startup) );
520     startup.cb = sizeof(startup);
521     startup.dwFlags = STARTF_USESHOWWINDOW;
522     startup.wShowWindow = params->lpCmdShow? params->lpCmdShow[1] : 0;
523
524     if (!CreateProcess32A( name, params->lpCmdLine,
525                            NULL, NULL, FALSE, 0, params->lpEnvAddress,
526                            NULL, &startup, &info ))
527         return GetLastError();  /* guaranteed to be < 32 */
528     
529     /* Get 16-bit hInstance/hTask from process */
530     pdb = PROCESS_IdToPDB( info.dwProcessId );
531     tdb = pdb? (TDB *)GlobalLock16( pdb->task ) : NULL;
532     hInstance = tdb && tdb->hInstance? tdb->hInstance : pdb? pdb->task : 0;
533
534     /* Close off the handles */
535     CloseHandle( info.hThread );
536     CloseHandle( info.hProcess );
537
538     return hInstance;
539 }
540
541 /**********************************************************************
542  *       CreateProcess32A          (KERNEL32.171)
543  */
544 BOOL32 WINAPI CreateProcess32A( LPCSTR lpApplicationName, LPSTR lpCommandLine, 
545                                 LPSECURITY_ATTRIBUTES lpProcessAttributes,
546                                 LPSECURITY_ATTRIBUTES lpThreadAttributes,
547                                 BOOL32 bInheritHandles, DWORD dwCreationFlags,
548                                 LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
549                                 LPSTARTUPINFO32A lpStartupInfo,
550                                 LPPROCESS_INFORMATION lpProcessInfo )
551 {
552     HINSTANCE16 hInstance;
553     LPCSTR cmdline;
554     PDB32 *pdb;
555     char name[256];
556
557     /* Get name and command line */
558
559     if (!lpApplicationName && !lpCommandLine)
560     {
561         SetLastError( ERROR_FILE_NOT_FOUND );
562         return FALSE;
563     }
564
565     cmdline = lpCommandLine? lpCommandLine : lpApplicationName;
566
567     if (lpApplicationName)
568         lstrcpyn32A(name, lpApplicationName, sizeof(name) - 4);
569     else {
570         char    *ptr;
571         int     len;
572
573         /* Take care off .exes with spaces in their names */
574         ptr = strchr(lpCommandLine, ' ');
575         do {
576             len = (ptr? ptr-lpCommandLine : strlen(lpCommandLine)) + 1;
577             if (len > sizeof(name) - 4) len = sizeof(name) - 4;
578             lstrcpyn32A(name, lpCommandLine, len);
579             if (!strchr(name, '\\') && !strchr(name, '.'))
580                 strcat(name, ".exe");
581             if (GetFileAttributes32A(name)!=-1)
582                 break;
583             /* if there is a space and no file found yet, include the word
584              * up to the next space too. If there is no next space, just
585              * use the first word.
586              */
587             if (ptr) {
588                 ptr = strchr(ptr+1, ' ');
589             } else {
590                 ptr = strchr(lpCommandLine, ' ');
591                 len = (ptr? ptr-lpCommandLine : strlen(lpCommandLine)) + 1;
592                 if (len > sizeof(name) - 4) len = sizeof(name) - 4;
593                 lstrcpyn32A(name, lpCommandLine, len);
594                 break;
595             }
596         } while (1);
597     }
598
599     if (!strchr(name, '\\') && !strchr(name, '.'))
600         strcat(name, ".exe");
601
602
603     /* Warn if unsupported features are used */
604
605     if (lpProcessAttributes)
606         FIXME(module, "(%s,...): lpProcessAttributes ignored\n", name);
607     if (lpThreadAttributes)
608         FIXME(module, "(%s,...): lpThreadAttributes ignored\n", name);
609     if (dwCreationFlags & DEBUG_PROCESS)
610         FIXME(module, "(%s,...): DEBUG_PROCESS ignored\n", name);
611     if (dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
612         FIXME(module, "(%s,...): DEBUG_ONLY_THIS_PROCESS ignored\n", name);
613     if (dwCreationFlags & CREATE_SUSPENDED)
614         FIXME(module, "(%s,...): CREATE_SUSPENDED ignored\n", name);
615     if (dwCreationFlags & DETACHED_PROCESS)
616         FIXME(module, "(%s,...): DETACHED_PROCESS ignored\n", name);
617     if (dwCreationFlags & CREATE_NEW_CONSOLE)
618         FIXME(module, "(%s,...): CREATE_NEW_CONSOLE ignored\n", name);
619     if (dwCreationFlags & NORMAL_PRIORITY_CLASS)
620         FIXME(module, "(%s,...): NORMAL_PRIORITY_CLASS ignored\n", name);
621     if (dwCreationFlags & IDLE_PRIORITY_CLASS)
622         FIXME(module, "(%s,...): IDLE_PRIORITY_CLASS ignored\n", name);
623     if (dwCreationFlags & HIGH_PRIORITY_CLASS)
624         FIXME(module, "(%s,...): HIGH_PRIORITY_CLASS ignored\n", name);
625     if (dwCreationFlags & REALTIME_PRIORITY_CLASS)
626         FIXME(module, "(%s,...): REALTIME_PRIORITY_CLASS ignored\n", name);
627     if (dwCreationFlags & CREATE_NEW_PROCESS_GROUP)
628         FIXME(module, "(%s,...): CREATE_NEW_PROCESS_GROUP ignored\n", name);
629     if (dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)
630         FIXME(module, "(%s,...): CREATE_UNICODE_ENVIRONMENT ignored\n", name);
631     if (dwCreationFlags & CREATE_SEPARATE_WOW_VDM)
632         FIXME(module, "(%s,...): CREATE_SEPARATE_WOW_VDM ignored\n", name);
633     if (dwCreationFlags & CREATE_SHARED_WOW_VDM)
634         FIXME(module, "(%s,...): CREATE_SHARED_WOW_VDM ignored\n", name);
635     if (dwCreationFlags & CREATE_DEFAULT_ERROR_MODE)
636         FIXME(module, "(%s,...): CREATE_DEFAULT_ERROR_MODE ignored\n", name);
637     if (dwCreationFlags & CREATE_NO_WINDOW)
638         FIXME(module, "(%s,...): CREATE_NO_WINDOW ignored\n", name);
639     if (dwCreationFlags & PROFILE_USER)
640         FIXME(module, "(%s,...): PROFILE_USER ignored\n", name);
641     if (dwCreationFlags & PROFILE_KERNEL)
642         FIXME(module, "(%s,...): PROFILE_KERNEL ignored\n", name);
643     if (dwCreationFlags & PROFILE_SERVER)
644         FIXME(module, "(%s,...): PROFILE_SERVER ignored\n", name);
645     if (lpCurrentDirectory)
646         FIXME(module, "(%s,...): lpCurrentDirectory %s ignored\n", 
647                       name, lpCurrentDirectory);
648     if (lpStartupInfo->lpDesktop)
649         FIXME(module, "(%s,...): lpStartupInfo->lpDesktop %s ignored\n", 
650                       name, lpStartupInfo->lpDesktop);
651     if (lpStartupInfo->lpTitle)
652         FIXME(module, "(%s,...): lpStartupInfo->lpTitle %s ignored\n", 
653                       name, lpStartupInfo->lpTitle);
654     if (lpStartupInfo->dwFlags & STARTF_USECOUNTCHARS)
655         FIXME(module, "(%s,...): STARTF_USECOUNTCHARS (%ld,%ld) ignored\n", 
656                       name, lpStartupInfo->dwXCountChars, lpStartupInfo->dwYCountChars);
657     if (lpStartupInfo->dwFlags & STARTF_USEFILLATTRIBUTE)
658         FIXME(module, "(%s,...): STARTF_USEFILLATTRIBUTE %lx ignored\n", 
659                       name, lpStartupInfo->dwFillAttribute);
660     if (lpStartupInfo->dwFlags & STARTF_RUNFULLSCREEN)
661         FIXME(module, "(%s,...): STARTF_RUNFULLSCREEN ignored\n", name);
662     if (lpStartupInfo->dwFlags & STARTF_FORCEONFEEDBACK)
663         FIXME(module, "(%s,...): STARTF_FORCEONFEEDBACK ignored\n", name);
664     if (lpStartupInfo->dwFlags & STARTF_FORCEOFFFEEDBACK)
665         FIXME(module, "(%s,...): STARTF_FORCEOFFFEEDBACK ignored\n", name);
666     if (lpStartupInfo->dwFlags & STARTF_USEHOTKEY)
667         FIXME(module, "(%s,...): STARTF_USEHOTKEY ignored\n", name);
668
669
670     /* Try NE module */
671     hInstance = NE_CreateProcess( name, cmdline, lpEnvironment, bInheritHandles,
672                                   lpStartupInfo, lpProcessInfo );
673
674     /* Try PE module */
675     if (hInstance == 21)
676         hInstance = PE_CreateProcess( name, cmdline, lpEnvironment, bInheritHandles,
677                                       lpStartupInfo, lpProcessInfo );
678
679     /* Try DOS module */
680     if (hInstance == 11)
681         hInstance = MZ_CreateProcess( name, cmdline, lpEnvironment, bInheritHandles,
682                                       lpStartupInfo, lpProcessInfo );
683
684     if (hInstance < 32)
685     {
686         SetLastError( hInstance );
687         return FALSE;
688     }
689
690     /* Get hTask from process and start the task */
691     pdb = PROCESS_IdToPDB( lpProcessInfo->dwProcessId );
692     if (pdb) TASK_StartTask( pdb->task );
693
694     return TRUE;
695 }
696
697 /**********************************************************************
698  *       CreateProcess32W          (KERNEL32.172)
699  * NOTES
700  *  lpReserved is not converted
701  */
702 BOOL32 WINAPI CreateProcess32W( LPCWSTR lpApplicationName, LPWSTR lpCommandLine, 
703                                 LPSECURITY_ATTRIBUTES lpProcessAttributes,
704                                 LPSECURITY_ATTRIBUTES lpThreadAttributes,
705                                 BOOL32 bInheritHandles, DWORD dwCreationFlags,
706                                 LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
707                                 LPSTARTUPINFO32W lpStartupInfo,
708                                 LPPROCESS_INFORMATION lpProcessInfo )
709 {   BOOL32 ret;
710     STARTUPINFO32A StartupInfoA;
711     
712     LPSTR lpApplicationNameA = HEAP_strdupWtoA (GetProcessHeap(),0,lpApplicationName);
713     LPSTR lpCommandLineA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCommandLine);
714     LPSTR lpCurrentDirectoryA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCurrentDirectory);
715
716     memcpy (&StartupInfoA, lpStartupInfo, sizeof(STARTUPINFO32A));
717     StartupInfoA.lpDesktop = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpDesktop);
718     StartupInfoA.lpTitle = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpTitle);
719
720     TRACE(win32, "(%s,%s,...)\n", debugstr_w(lpApplicationName), debugstr_w(lpCommandLine));
721
722     if (lpStartupInfo->lpReserved)
723       FIXME(win32,"StartupInfo.lpReserved is used, please report (%s)\n", debugstr_w(lpStartupInfo->lpReserved));
724       
725     ret = CreateProcess32A(  lpApplicationNameA,  lpCommandLineA, 
726                              lpProcessAttributes, lpThreadAttributes,
727                              bInheritHandles, dwCreationFlags,
728                              lpEnvironment, lpCurrentDirectoryA,
729                              &StartupInfoA, lpProcessInfo );
730
731     HeapFree( GetProcessHeap(), 0, lpCurrentDirectoryA );
732     HeapFree( GetProcessHeap(), 0, lpCommandLineA );
733     HeapFree( GetProcessHeap(), 0, StartupInfoA.lpDesktop );
734     HeapFree( GetProcessHeap(), 0, StartupInfoA.lpTitle );
735
736     return ret;
737 }
738
739 /***********************************************************************
740  *              GetModuleHandle         (KERNEL32.237)
741  */
742 HMODULE32 WINAPI GetModuleHandle32A(LPCSTR module)
743 {
744     if (module == NULL)
745         return PROCESS_Current()->exe_modref->module;
746     else
747         return MODULE_FindModule32( module );
748 }
749
750 HMODULE32 WINAPI GetModuleHandle32W(LPCWSTR module)
751 {
752     HMODULE32 hModule;
753     LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
754     hModule = GetModuleHandle32A( modulea );
755     HeapFree( GetProcessHeap(), 0, modulea );
756     return hModule;
757 }
758
759
760 /***********************************************************************
761  *              GetModuleFileName32A      (KERNEL32.235)
762  */
763 DWORD WINAPI GetModuleFileName32A( 
764         HMODULE32 hModule,      /* [in] module handle (32bit) */
765         LPSTR lpFileName,       /* [out] filenamebuffer */
766         DWORD size              /* [in] size of filenamebuffer */
767 ) {                   
768     WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
769
770     if (!wm) /* can happen on start up or the like */
771         return 0;
772
773     if (PE_HEADER(wm->module)->OptionalHeader.MajorOperatingSystemVersion >= 4.0)
774       lstrcpyn32A( lpFileName, wm->longname, size );
775     else
776       lstrcpyn32A( lpFileName, wm->shortname, size );
777        
778     TRACE(module, "%s\n", lpFileName );
779     return strlen(lpFileName);
780 }                   
781  
782
783 /***********************************************************************
784  *              GetModuleFileName32W      (KERNEL32.236)
785  */
786 DWORD WINAPI GetModuleFileName32W( HMODULE32 hModule, LPWSTR lpFileName,
787                                    DWORD size )
788 {
789     LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
790     DWORD res = GetModuleFileName32A( hModule, fnA, size );
791     lstrcpynAtoW( lpFileName, fnA, size );
792     HeapFree( GetProcessHeap(), 0, fnA );
793     return res;
794 }
795
796
797 /***********************************************************************
798  *           LoadLibraryEx32W   (KERNEL.513)
799  * FIXME
800  */
801 HMODULE32 WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
802                                        DWORD flags )
803 {
804     TRACE(module,"(%s,%d,%08lx)\n",libname,hf,flags);
805     return LoadLibraryEx32A(libname, hf,flags);
806 }
807
808 /***********************************************************************
809  *           LoadLibraryEx32A   (KERNEL32)
810  */
811 HMODULE32 WINAPI LoadLibraryEx32A(LPCSTR libname,HFILE32 hfile,DWORD flags)
812 {
813     HMODULE32 hmod;
814     hmod = MODULE_LoadLibraryEx32A( libname, hfile, flags );
815
816     /* at least call not the dllmain...*/
817     if ( DONT_RESOLVE_DLL_REFERENCES==flags || LOAD_LIBRARY_AS_DATAFILE==flags )
818     { FIXME(module,"flag not properly supported %lx\n", flags);
819       return hmod;
820     }
821
822     /* initialize DLL just loaded */
823     if ( hmod >= 32 )       
824         MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, (LPVOID)-1 );
825
826     return hmod;
827 }
828
829 HMODULE32 MODULE_LoadLibraryEx32A( LPCSTR libname, HFILE32 hfile, DWORD flags )
830 {
831     HMODULE32 hmod;
832     
833     hmod = ELF_LoadLibraryEx32A( libname, hfile, flags );
834     if (hmod) return hmod;
835
836     hmod = PE_LoadLibraryEx32A( libname, hfile, flags );
837     return hmod;
838 }
839
840 /***********************************************************************
841  *           LoadLibraryA         (KERNEL32)
842  */
843 HMODULE32 WINAPI LoadLibrary32A(LPCSTR libname) {
844         return LoadLibraryEx32A(libname,0,0);
845 }
846
847 /***********************************************************************
848  *           LoadLibraryW         (KERNEL32)
849  */
850 HMODULE32 WINAPI LoadLibrary32W(LPCWSTR libnameW)
851 {
852     return LoadLibraryEx32W(libnameW,0,0);
853 }
854
855 /***********************************************************************
856  *           LoadLibraryExW       (KERNEL32)
857  */
858 HMODULE32 WINAPI LoadLibraryEx32W(LPCWSTR libnameW,HFILE32 hfile,DWORD flags)
859 {
860     LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
861     HMODULE32 ret = LoadLibraryEx32A( libnameA , hfile, flags );
862
863     HeapFree( GetProcessHeap(), 0, libnameA );
864     return ret;
865 }
866
867 /***********************************************************************
868  *           FreeLibrary
869  */
870 BOOL32 WINAPI FreeLibrary32(HINSTANCE32 hLibModule)
871 {
872     FIXME(module,"(0x%08x): stub\n", hLibModule);
873     return TRUE;  /* FIXME */
874 }
875
876
877 /***********************************************************************
878  *           PrivateLoadLibrary       (KERNEL32)
879  *
880  * FIXME: rough guesswork, don't know what "Private" means
881  */
882 HINSTANCE32 WINAPI PrivateLoadLibrary(LPCSTR libname)
883 {
884         return (HINSTANCE32)LoadLibrary16(libname);
885 }
886
887
888
889 /***********************************************************************
890  *           PrivateFreeLibrary       (KERNEL32)
891  *
892  * FIXME: rough guesswork, don't know what "Private" means
893  */
894 void WINAPI PrivateFreeLibrary(HINSTANCE32 handle)
895 {
896         FreeLibrary16((HINSTANCE16)handle);
897 }
898
899
900 /***********************************************************************
901  *           WinExec16   (KERNEL.166)
902  */
903 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
904 {
905     return WinExec32( lpCmdLine, nCmdShow );
906 }
907
908
909 /***********************************************************************
910  *           WinExec32   (KERNEL32.566)
911  */
912 HINSTANCE32 WINAPI WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow )
913 {
914     HINSTANCE32 handle = 2;
915     char *p, filename[256];
916     int  spacelimit = 0, exhausted = 0;
917     LOADPARAMS32 params;
918     UINT16 paramCmdShow[2];
919
920     if (!lpCmdLine)
921         return 2;  /* File not found */
922
923     /* Set up LOADPARAMS32 buffer for LoadModule32 */
924
925     memset( &params, '\0', sizeof(params) );
926     params.lpCmdLine    = (LPSTR)lpCmdLine;
927     params.lpCmdShow    = paramCmdShow;
928     params.lpCmdShow[0] = 2;
929     params.lpCmdShow[1] = nCmdShow;
930
931
932     /* Keep trying to load a file by trying different filenames; e.g.,
933        for the cmdline "abcd efg hij", try "abcd" with args "efg hij",
934        then "abcd efg" with arg "hij", and finally "abcd efg hij" with
935        no args */
936
937     while(!exhausted && handle == 2) {
938         int spacecount = 0;
939
940         /* Build the filename and command-line */
941
942         lstrcpyn32A(filename, lpCmdLine,
943                     sizeof(filename) - 4 /* for extension */);
944
945         /* Keep grabbing characters until end-of-string, tab, or until the
946            number of spaces is greater than the spacelimit */
947
948         for (p = filename; ; p++) {
949             if(*p == ' ') {
950                 ++spacecount;
951                 if(spacecount > spacelimit) {
952                     ++spacelimit;
953                     break;
954                 }
955             }
956
957             if(*p == '\0' || *p == '\t') {
958                 exhausted = 1;
959                 break;
960             }
961         }
962
963         *p = '\0';
964
965         /* Now load the executable file */
966
967         if (!__winelib)
968         {
969             handle = LoadModule32( filename, &params );
970             if (handle == 2)  /* file not found */
971             {
972                 /* Check that the original file name did not have a suffix */
973                 p = strrchr(filename, '.');
974                 /* if there is a '.', check if either \ OR / follow */
975                 if (!p || strchr(p, '/') || strchr(p, '\\'))
976                 {
977                     p = filename + strlen(filename);
978                     strcpy( p, ".exe" );
979                     handle = LoadModule32( filename, &params );
980                     *p = '\0';  /* Remove extension */
981                 }
982             }
983         }
984         else
985             handle = 2; /* file not found */
986
987         if (handle < 32)
988         {
989             /* Try to start it as a unix program */
990             if (!fork())
991             {
992                 /* Child process */
993                 DOS_FULL_NAME full_name;
994                 const char *unixfilename = NULL;
995                 const char *argv[256], **argptr;
996                 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
997                               nCmdShow == SW_SHOWMINNOACTIVE);
998
999                 THREAD_InitDone = FALSE; /* we didn't init this process */
1000                 /* get unixfilename */
1001                 if (strchr(filename, '/') ||
1002                     strchr(filename, ':') ||
1003                     strchr(filename, '\\'))
1004                 {
1005                     if (DOSFS_GetFullName( filename, TRUE, &full_name ))
1006                         unixfilename = full_name.long_name;
1007                 }
1008                 else unixfilename = filename;
1009
1010                 if (unixfilename)
1011                 {
1012                     /* build argv */
1013                     argptr = argv;
1014                     if (iconic) *argptr++ = "-iconic";
1015                     *argptr++ = unixfilename;
1016                     p = strdup(lpCmdLine);
1017                     while (1)
1018                     {
1019                         while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1020                         if (!*p) break;
1021                         *argptr++ = p;
1022                         while (*p && *p != ' ' && *p != '\t') p++;
1023                     }
1024                     *argptr++ = 0;
1025
1026                     /* Execute */
1027                     execvp(argv[0], (char**)argv);
1028                 }
1029
1030                 /* Failed ! */
1031
1032                 if (__winelib)
1033                 {
1034                     /* build argv */
1035                     argptr = argv;
1036                     *argptr++ = "wine";
1037                     if (iconic) *argptr++ = "-iconic";
1038                     *argptr++ = lpCmdLine;
1039                     *argptr++ = 0;
1040
1041                     /* Execute */
1042                     execvp(argv[0] , (char**)argv);
1043
1044                     /* Failed ! */
1045                     MSG("WinExec: can't exec 'wine %s'\n",
1046                             lpCmdLine);
1047                 }
1048                 exit(1);
1049             }
1050         }
1051     } /* while (!exhausted && handle < 32) */
1052
1053     return handle;
1054 }
1055
1056
1057 /***********************************************************************
1058  *           WIN32_GetProcAddress16   (KERNEL32.36)
1059  * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1060  */
1061 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE32 hModule, LPCSTR name )
1062 {
1063     WORD        ordinal;
1064     FARPROC16   ret;
1065
1066     if (!hModule) {
1067         WARN(module,"hModule may not be 0!\n");
1068         return (FARPROC16)0;
1069     }
1070     if (HIWORD(hModule))
1071     {
1072         WARN( module, "hModule is Win32 handle (%08x)\n", hModule );
1073         return (FARPROC16)0;
1074     }
1075     hModule = GetExePtr( hModule );
1076     if (HIWORD(name)) {
1077         ordinal = NE_GetOrdinal( hModule, name );
1078         TRACE(module, "%04x '%s'\n",
1079                         hModule, name );
1080     } else {
1081         ordinal = LOWORD(name);
1082         TRACE(module, "%04x %04x\n",
1083                         hModule, ordinal );
1084     }
1085     if (!ordinal) return (FARPROC16)0;
1086     ret = NE_GetEntryPoint( hModule, ordinal );
1087     TRACE(module,"returning %08x\n",(UINT32)ret);
1088     return ret;
1089 }
1090
1091 /***********************************************************************
1092  *           GetProcAddress16   (KERNEL.50)
1093  */
1094 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1095 {
1096     WORD ordinal;
1097     FARPROC16 ret;
1098
1099     if (!hModule) hModule = GetCurrentTask();
1100     hModule = GetExePtr( hModule );
1101
1102     if (HIWORD(name) != 0)
1103     {
1104         ordinal = NE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1105         TRACE(module, "%04x '%s'\n",
1106                         hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1107     }
1108     else
1109     {
1110         ordinal = LOWORD(name);
1111         TRACE(module, "%04x %04x\n",
1112                         hModule, ordinal );
1113     }
1114     if (!ordinal) return (FARPROC16)0;
1115
1116     ret = NE_GetEntryPoint( hModule, ordinal );
1117
1118     TRACE(module, "returning %08x\n", (UINT32)ret );
1119     return ret;
1120 }
1121
1122
1123 /***********************************************************************
1124  *           GetProcAddress32                   (KERNEL32.257)
1125  */
1126 FARPROC32 WINAPI GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1127 {
1128     return MODULE_GetProcAddress32( hModule, function, TRUE );
1129 }
1130
1131 /***********************************************************************
1132  *           WIN16_GetProcAddress32             (KERNEL.453)
1133  */
1134 FARPROC32 WINAPI WIN16_GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1135 {
1136     return MODULE_GetProcAddress32( hModule, function, FALSE );
1137 }
1138
1139 /***********************************************************************
1140  *           MODULE_GetProcAddress32            (internal)
1141  */
1142 FARPROC32 MODULE_GetProcAddress32( 
1143         HMODULE32 hModule,      /* [in] current module handle */
1144         LPCSTR function,        /* [in] function to be looked up */
1145         BOOL32 snoop )
1146 {
1147     WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1148
1149     if (HIWORD(function))
1150         TRACE(win32,"(%08lx,%s)\n",(DWORD)hModule,function);
1151     else
1152         TRACE(win32,"(%08lx,%p)\n",(DWORD)hModule,function);
1153     if (!wm)
1154         return (FARPROC32)0;
1155     switch (wm->type)
1156     {
1157     case MODULE32_PE:
1158         return PE_FindExportedFunction( wm, function, snoop );
1159     case MODULE32_ELF:
1160         return ELF_FindExportedFunction( wm, function);
1161     default:
1162         ERR(module,"wine_modref type %d not handled.\n",wm->type);
1163         return (FARPROC32)0;
1164     }
1165 }
1166
1167
1168 /***********************************************************************
1169  *           RtlImageNtHeaders   (NTDLL)
1170  */
1171 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE32 hModule)
1172 {
1173     /* basically:
1174      * return  hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew); 
1175      * but we could get HMODULE16 or the like (think builtin modules)
1176      */
1177
1178     WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1179     if (!wm || (wm->type != MODULE32_PE)) return (PIMAGE_NT_HEADERS)0;
1180     return PE_HEADER(wm->module);
1181 }
1182
1183
1184 /***************************************************************************
1185  *              HasGPHandler                    (KERNEL.338)
1186  */
1187
1188 #pragma pack(1)
1189 typedef struct _GPHANDLERDEF
1190 {
1191     WORD selector;
1192     WORD rangeStart;
1193     WORD rangeEnd;
1194     WORD handler;
1195 } GPHANDLERDEF;
1196 #pragma pack(4)
1197
1198 SEGPTR WINAPI HasGPHandler( SEGPTR address )
1199 {
1200     HMODULE16 hModule;
1201     int gpOrdinal;
1202     SEGPTR gpPtr;
1203     GPHANDLERDEF *gpHandler;
1204    
1205     if (    (hModule = FarGetOwner( SELECTOROF(address) )) != 0
1206          && (gpOrdinal = NE_GetOrdinal( hModule, "__GP" )) != 0
1207          && (gpPtr = (SEGPTR)NE_GetEntryPointEx( hModule, gpOrdinal, FALSE )) != 0
1208          && !IsBadReadPtr16( gpPtr, sizeof(GPHANDLERDEF) )
1209          && (gpHandler = PTR_SEG_TO_LIN( gpPtr )) != NULL )
1210     {
1211         while (gpHandler->selector)
1212         {
1213             if (    SELECTOROF(address) == gpHandler->selector
1214                  && OFFSETOF(address)   >= gpHandler->rangeStart
1215                  && OFFSETOF(address)   <  gpHandler->rangeEnd  )
1216                 return PTR_SEG_OFF_TO_SEGPTR( gpHandler->selector,
1217                                               gpHandler->handler );
1218             gpHandler++;
1219         }
1220     }
1221
1222     return 0;
1223 }
1224