Fixed some issues found by winapi_check.
[wine] / loader / module.c
1 /*
2  * Modules
3  *
4  * Copyright 1995 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <fcntl.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #include "wine/winbase16.h"
34 #include "winerror.h"
35 #include "winternl.h"
36 #include "heap.h"
37 #include "file.h"
38 #include "module.h"
39 #include "wine/debug.h"
40 #include "wine/server.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(module);
43 WINE_DECLARE_DEBUG_CHANNEL(win32);
44 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
45
46 WINE_MODREF *MODULE_modref_list = NULL;
47
48 static WINE_MODREF *exe_modref;
49 static int free_lib_count;   /* recursion depth of FreeLibrary calls */
50 static int process_detaching;  /* set on process detach to avoid deadlocks with thread detach */
51
52 static CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" );
53
54 /***********************************************************************
55  *           wait_input_idle
56  *
57  * Wrapper to call WaitForInputIdle USER function
58  */
59 typedef DWORD (WINAPI *WaitForInputIdle_ptr)( HANDLE hProcess, DWORD dwTimeOut );
60
61 static DWORD wait_input_idle( HANDLE process, DWORD timeout )
62 {
63     HMODULE mod = GetModuleHandleA( "user32.dll" );
64     if (mod)
65     {
66         WaitForInputIdle_ptr ptr = (WaitForInputIdle_ptr)GetProcAddress( mod, "WaitForInputIdle" );
67         if (ptr) return ptr( process, timeout );
68     }
69     return 0;
70 }
71
72
73 /*************************************************************************
74  *              MODULE32_LookupHMODULE
75  * looks for the referenced HMODULE in the current process
76  * NOTE: Assumes that the process critical section is held!
77  */
78 static WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod )
79 {
80     WINE_MODREF *wm;
81
82     if (!hmod)
83         return exe_modref;
84
85     if (!HIWORD(hmod)) {
86         ERR("tried to lookup 0x%04x in win32 module handler!\n",hmod);
87         SetLastError( ERROR_INVALID_HANDLE );
88         return NULL;
89     }
90     for ( wm = MODULE_modref_list; wm; wm=wm->next )
91         if (wm->module == hmod)
92             return wm;
93     SetLastError( ERROR_INVALID_HANDLE );
94     return NULL;
95 }
96
97 /*************************************************************************
98  *              MODULE_AllocModRef
99  *
100  * Allocate a WINE_MODREF structure and add it to the process list
101  * NOTE: Assumes that the process critical section is held!
102  */
103 WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename )
104 {
105     WINE_MODREF *wm;
106
107     DWORD long_len = strlen( filename );
108     DWORD short_len = GetShortPathNameA( filename, NULL, 0 );
109
110     if ((wm = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
111                          sizeof(*wm) + long_len + short_len + 1 )))
112     {
113         wm->module = hModule;
114         wm->tlsindex = -1;
115
116         wm->filename = wm->data;
117         memcpy( wm->filename, filename, long_len + 1 );
118         if ((wm->modname = strrchr( wm->filename, '\\' ))) wm->modname++;
119         else wm->modname = wm->filename;
120
121         wm->short_filename = wm->filename + long_len + 1;
122         GetShortPathNameA( wm->filename, wm->short_filename, short_len + 1 );
123         if ((wm->short_modname = strrchr( wm->short_filename, '\\' ))) wm->short_modname++;
124         else wm->short_modname = wm->short_filename;
125
126         wm->next = MODULE_modref_list;
127         if (wm->next) wm->next->prev = wm;
128         MODULE_modref_list = wm;
129
130         if (!(RtlImageNtHeader(hModule)->FileHeader.Characteristics & IMAGE_FILE_DLL))
131         {
132             if (!exe_modref) exe_modref = wm;
133             else FIXME( "Trying to load second .EXE file: %s\n", filename );
134         }
135     }
136     return wm;
137 }
138
139 /*************************************************************************
140  *              MODULE_InitDLL
141  */
142 static BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
143 {
144     BOOL retv = TRUE;
145
146     static LPCSTR typeName[] = { "PROCESS_DETACH", "PROCESS_ATTACH",
147                                  "THREAD_ATTACH", "THREAD_DETACH" };
148     assert( wm );
149
150     /* Skip calls for modules loaded with special load flags */
151
152     if (wm->flags & WINE_MODREF_DONT_RESOLVE_REFS) return TRUE;
153
154     TRACE("(%s,%s,%p) - CALL\n", wm->modname, typeName[type], lpReserved );
155
156     /* Call the initialization routine */
157     retv = PE_InitDLL( wm->module, type, lpReserved );
158
159     /* The state of the module list may have changed due to the call
160        to PE_InitDLL. We cannot assume that this module has not been
161        deleted.  */
162     TRACE("(%p,%s,%p) - RETURN %d\n", wm, typeName[type], lpReserved, retv );
163
164     return retv;
165 }
166
167 /*************************************************************************
168  *              MODULE_DllProcessAttach
169  *
170  * Send the process attach notification to all DLLs the given module
171  * depends on (recursively). This is somewhat complicated due to the fact that
172  *
173  * - we have to respect the module dependencies, i.e. modules implicitly
174  *   referenced by another module have to be initialized before the module
175  *   itself can be initialized
176  *
177  * - the initialization routine of a DLL can itself call LoadLibrary,
178  *   thereby introducing a whole new set of dependencies (even involving
179  *   the 'old' modules) at any time during the whole process
180  *
181  * (Note that this routine can be recursively entered not only directly
182  *  from itself, but also via LoadLibrary from one of the called initialization
183  *  routines.)
184  *
185  * Furthermore, we need to rearrange the main WINE_MODREF list to allow
186  * the process *detach* notifications to be sent in the correct order.
187  * This must not only take into account module dependencies, but also
188  * 'hidden' dependencies created by modules calling LoadLibrary in their
189  * attach notification routine.
190  *
191  * The strategy is rather simple: we move a WINE_MODREF to the head of the
192  * list after the attach notification has returned.  This implies that the
193  * detach notifications are called in the reverse of the sequence the attach
194  * notifications *returned*.
195  */
196 BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
197 {
198     BOOL retv = TRUE;
199     int i;
200
201     RtlEnterCriticalSection( &loader_section );
202
203     if (!wm)
204     {
205         wm = exe_modref;
206         PE_InitTls();
207     }
208     assert( wm );
209
210     /* prevent infinite recursion in case of cyclical dependencies */
211     if (    ( wm->flags & WINE_MODREF_MARKER )
212          || ( wm->flags & WINE_MODREF_PROCESS_ATTACHED ) )
213         goto done;
214
215     TRACE("(%s,%p) - START\n", wm->modname, lpReserved );
216
217     /* Tag current MODREF to prevent recursive loop */
218     wm->flags |= WINE_MODREF_MARKER;
219
220     /* Recursively attach all DLLs this one depends on */
221     for ( i = 0; retv && i < wm->nDeps; i++ )
222         if ( wm->deps[i] )
223             retv = MODULE_DllProcessAttach( wm->deps[i], lpReserved );
224
225     /* Call DLL entry point */
226     if ( retv )
227     {
228         retv = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved );
229         if ( retv )
230             wm->flags |= WINE_MODREF_PROCESS_ATTACHED;
231     }
232
233     /* Re-insert MODREF at head of list */
234     if ( retv && wm->prev )
235     {
236         wm->prev->next = wm->next;
237         if ( wm->next ) wm->next->prev = wm->prev;
238
239         wm->prev = NULL;
240         wm->next = MODULE_modref_list;
241         MODULE_modref_list = wm->next->prev = wm;
242     }
243
244     /* Remove recursion flag */
245     wm->flags &= ~WINE_MODREF_MARKER;
246
247     TRACE("(%s,%p) - END\n", wm->modname, lpReserved );
248
249  done:
250     RtlLeaveCriticalSection( &loader_section );
251     return retv;
252 }
253
254 /*************************************************************************
255  *              MODULE_DllProcessDetach
256  *
257  * Send DLL process detach notifications.  See the comment about calling
258  * sequence at MODULE_DllProcessAttach.  Unless the bForceDetach flag
259  * is set, only DLLs with zero refcount are notified.
260  */
261 void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved )
262 {
263     WINE_MODREF *wm;
264
265     RtlEnterCriticalSection( &loader_section );
266     if (bForceDetach) process_detaching = 1;
267     do
268     {
269         for ( wm = MODULE_modref_list; wm; wm = wm->next )
270         {
271             /* Check whether to detach this DLL */
272             if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) )
273                 continue;
274             if ( wm->refCount > 0 && !bForceDetach )
275                 continue;
276
277             /* Call detach notification */
278             wm->flags &= ~WINE_MODREF_PROCESS_ATTACHED;
279             MODULE_InitDLL( wm, DLL_PROCESS_DETACH, lpReserved );
280
281             /* Restart at head of WINE_MODREF list, as entries might have
282                been added and/or removed while performing the call ... */
283             break;
284         }
285     } while ( wm );
286
287     RtlLeaveCriticalSection( &loader_section );
288 }
289
290 /*************************************************************************
291  *              MODULE_DllThreadAttach
292  *
293  * Send DLL thread attach notifications. These are sent in the
294  * reverse sequence of process detach notification.
295  *
296  */
297 void MODULE_DllThreadAttach( LPVOID lpReserved )
298 {
299     WINE_MODREF *wm;
300
301     /* don't do any attach calls if process is exiting */
302     if (process_detaching) return;
303     /* FIXME: there is still a race here */
304
305     RtlEnterCriticalSection( &loader_section );
306
307     PE_InitTls();
308
309     for ( wm = MODULE_modref_list; wm; wm = wm->next )
310         if ( !wm->next )
311             break;
312
313     for ( ; wm; wm = wm->prev )
314     {
315         if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) )
316             continue;
317         if ( wm->flags & WINE_MODREF_NO_DLL_CALLS )
318             continue;
319
320         MODULE_InitDLL( wm, DLL_THREAD_ATTACH, lpReserved );
321     }
322
323     RtlLeaveCriticalSection( &loader_section );
324 }
325
326 /*************************************************************************
327  *              MODULE_DllThreadDetach
328  *
329  * Send DLL thread detach notifications. These are sent in the
330  * same sequence as process detach notification.
331  *
332  */
333 void MODULE_DllThreadDetach( LPVOID lpReserved )
334 {
335     WINE_MODREF *wm;
336
337     /* don't do any detach calls if process is exiting */
338     if (process_detaching) return;
339     /* FIXME: there is still a race here */
340
341     RtlEnterCriticalSection( &loader_section );
342
343     for ( wm = MODULE_modref_list; wm; wm = wm->next )
344     {
345         if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) )
346             continue;
347         if ( wm->flags & WINE_MODREF_NO_DLL_CALLS )
348             continue;
349
350         MODULE_InitDLL( wm, DLL_THREAD_DETACH, lpReserved );
351     }
352
353     RtlLeaveCriticalSection( &loader_section );
354 }
355
356 /****************************************************************************
357  *              DisableThreadLibraryCalls (KERNEL32.@)
358  *
359  * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
360  */
361 BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
362 {
363     WINE_MODREF *wm;
364     BOOL retval = TRUE;
365
366     RtlEnterCriticalSection( &loader_section );
367
368     wm = MODULE32_LookupHMODULE( hModule );
369     if ( !wm )
370         retval = FALSE;
371     else
372         wm->flags |= WINE_MODREF_NO_DLL_CALLS;
373
374     RtlLeaveCriticalSection( &loader_section );
375
376     return retval;
377 }
378
379
380 /***********************************************************************
381  *           MODULE_CreateDummyModule
382  *
383  * Create a dummy NE module for Win32 or Winelib.
384  */
385 HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 )
386 {
387     HMODULE16 hModule;
388     NE_MODULE *pModule;
389     SEGTABLEENTRY *pSegment;
390     char *pStr,*s;
391     unsigned int len;
392     const char* basename;
393     OFSTRUCT *ofs;
394     int of_size, size;
395
396     /* Extract base filename */
397     basename = strrchr(filename, '\\');
398     if (!basename) basename = filename;
399     else basename++;
400     len = strlen(basename);
401     if ((s = strchr(basename, '.'))) len = s - basename;
402
403     /* Allocate module */
404     of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
405                     + strlen(filename) + 1;
406     size = sizeof(NE_MODULE) +
407                  /* loaded file info */
408                  ((of_size + 3) & ~3) +
409                  /* segment table: DS,CS */
410                  2 * sizeof(SEGTABLEENTRY) +
411                  /* name table */
412                  len + 2 +
413                  /* several empty tables */
414                  8;
415
416     hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
417     if (!hModule) return (HMODULE16)11;  /* invalid exe */
418
419     FarSetOwner16( hModule, hModule );
420     pModule = (NE_MODULE *)GlobalLock16( hModule );
421
422     /* Set all used entries */
423     pModule->magic            = IMAGE_OS2_SIGNATURE;
424     pModule->count            = 1;
425     pModule->next             = 0;
426     pModule->flags            = 0;
427     pModule->dgroup           = 0;
428     pModule->ss               = 1;
429     pModule->cs               = 2;
430     pModule->heap_size        = 0;
431     pModule->stack_size       = 0;
432     pModule->seg_count        = 2;
433     pModule->modref_count     = 0;
434     pModule->nrname_size      = 0;
435     pModule->fileinfo         = sizeof(NE_MODULE);
436     pModule->os_flags         = NE_OSFLAGS_WINDOWS;
437     pModule->self             = hModule;
438     pModule->module32         = module32;
439
440     /* Set version and flags */
441     if (module32)
442     {
443         IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module32 );
444         pModule->expected_version = ((nt->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 ) |
445                                      (nt->OptionalHeader.MinorSubsystemVersion & 0xff);
446         pModule->flags |= NE_FFLAGS_WIN32;
447         if (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)
448             pModule->flags |= NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA;
449     }
450
451     /* Set loaded file information */
452     ofs = (OFSTRUCT *)(pModule + 1);
453     memset( ofs, 0, of_size );
454     ofs->cBytes = of_size < 256 ? of_size : 255;   /* FIXME */
455     strcpy( ofs->szPathName, filename );
456
457     pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + ((of_size + 3) & ~3));
458     pModule->seg_table = (int)pSegment - (int)pModule;
459     /* Data segment */
460     pSegment->size    = 0;
461     pSegment->flags   = NE_SEGFLAGS_DATA;
462     pSegment->minsize = 0x1000;
463     pSegment++;
464     /* Code segment */
465     pSegment->flags   = 0;
466     pSegment++;
467
468     /* Module name */
469     pStr = (char *)pSegment;
470     pModule->name_table = (int)pStr - (int)pModule;
471     assert(len<256);
472     *pStr = len;
473     lstrcpynA( pStr+1, basename, len+1 );
474     pStr += len+2;
475
476     /* All tables zero terminated */
477     pModule->res_table = pModule->import_table = pModule->entry_table =
478                 (int)pStr - (int)pModule;
479
480     NE_RegisterModule( pModule );
481     return hModule;
482 }
483
484
485 /**********************************************************************
486  *          MODULE_FindModule
487  *
488  * Find a (loaded) win32 module depending on path
489  *
490  * RETURNS
491  *      the module handle if found
492  *      0 if not
493  */
494 WINE_MODREF *MODULE_FindModule(
495         LPCSTR path     /* [in] pathname of module/library to be found */
496 ) {
497     WINE_MODREF *wm;
498     char dllname[260], *p;
499
500     /* Append .DLL to name if no extension present */
501     strcpy( dllname, path );
502     if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
503             strcat( dllname, ".DLL" );
504
505     for ( wm = MODULE_modref_list; wm; wm = wm->next )
506     {
507         if ( !FILE_strcasecmp( dllname, wm->modname ) )
508             break;
509         if ( !FILE_strcasecmp( dllname, wm->filename ) )
510             break;
511         if ( !FILE_strcasecmp( dllname, wm->short_modname ) )
512             break;
513         if ( !FILE_strcasecmp( dllname, wm->short_filename ) )
514             break;
515     }
516
517     return wm;
518 }
519
520
521 /* Check whether a file is an OS/2 or a very old Windows executable
522  * by testing on import of KERNEL.
523  *
524  * FIXME: is reading the module imports the only way of discerning
525  *        old Windows binaries from OS/2 ones ? At least it seems so...
526  */
527 static enum binary_type MODULE_Decide_OS2_OldWin(HANDLE hfile, const IMAGE_DOS_HEADER *mz,
528                                                  const IMAGE_OS2_HEADER *ne)
529 {
530     DWORD currpos = SetFilePointer( hfile, 0, NULL, SEEK_CUR);
531     enum binary_type ret = BINARY_OS216;
532     LPWORD modtab = NULL;
533     LPSTR nametab = NULL;
534     DWORD len;
535     int i;
536
537     /* read modref table */
538     if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_modtab, NULL, SEEK_SET ) == -1)
539       || (!(modtab = HeapAlloc( GetProcessHeap(), 0, ne->ne_cmod*sizeof(WORD))))
540       || (!(ReadFile(hfile, modtab, ne->ne_cmod*sizeof(WORD), &len, NULL)))
541       || (len != ne->ne_cmod*sizeof(WORD)) )
542         goto broken;
543
544     /* read imported names table */
545     if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_imptab, NULL, SEEK_SET ) == -1)
546       || (!(nametab = HeapAlloc( GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab)))
547       || (!(ReadFile(hfile, nametab, ne->ne_enttab - ne->ne_imptab, &len, NULL)))
548       || (len != ne->ne_enttab - ne->ne_imptab) )
549         goto broken;
550
551     for (i=0; i < ne->ne_cmod; i++)
552     {
553         LPSTR module = &nametab[modtab[i]];
554         TRACE("modref: %.*s\n", module[0], &module[1]);
555         if (!(strncmp(&module[1], "KERNEL", module[0])))
556         { /* very old Windows file */
557             MESSAGE("This seems to be a very old (pre-3.0) Windows executable. Expect crashes, especially if this is a real-mode binary !\n");
558             ret = BINARY_WIN16;
559             goto good;
560         }
561     }
562
563 broken:
564     ERR("Hmm, an error occurred. Is this binary file broken ?\n");
565
566 good:
567     HeapFree( GetProcessHeap(), 0, modtab);
568     HeapFree( GetProcessHeap(), 0, nametab);
569     SetFilePointer( hfile, currpos, NULL, SEEK_SET); /* restore filepos */
570     return ret;
571 }
572
573 /***********************************************************************
574  *           MODULE_GetBinaryType
575  */
576 enum binary_type MODULE_GetBinaryType( HANDLE hfile )
577 {
578     union
579     {
580         struct
581         {
582             unsigned char magic[4];
583             unsigned char ignored[12];
584             unsigned short type;
585         } elf;
586         IMAGE_DOS_HEADER mz;
587     } header;
588
589     char magic[4];
590     DWORD len;
591
592     /* Seek to the start of the file and read the header information. */
593     if (SetFilePointer( hfile, 0, NULL, SEEK_SET ) == -1)
594         return BINARY_UNKNOWN;
595     if (!ReadFile( hfile, &header, sizeof(header), &len, NULL ) || len != sizeof(header))
596         return BINARY_UNKNOWN;
597
598     if (!memcmp( header.elf.magic, "\177ELF", 4 ))
599     {
600         /* FIXME: we don't bother to check byte order, architecture, etc. */
601         switch(header.elf.type)
602         {
603         case 2: return BINARY_UNIX_EXE;
604         case 3: return BINARY_UNIX_LIB;
605         }
606         return BINARY_UNKNOWN;
607     }
608
609     /* Not ELF, try DOS */
610
611     if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
612     {
613         /* We do have a DOS image so we will now try to seek into
614          * the file by the amount indicated by the field
615          * "Offset to extended header" and read in the
616          * "magic" field information at that location.
617          * This will tell us if there is more header information
618          * to read or not.
619          */
620         /* But before we do we will make sure that header
621          * structure encompasses the "Offset to extended header"
622          * field.
623          */
624         if ((header.mz.e_cparhdr << 4) < sizeof(IMAGE_DOS_HEADER))
625             return BINARY_DOS;
626         if (header.mz.e_crlc && (header.mz.e_lfarlc < sizeof(IMAGE_DOS_HEADER)))
627             return BINARY_DOS;
628         if (header.mz.e_lfanew < sizeof(IMAGE_DOS_HEADER))
629             return BINARY_DOS;
630         if (SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) == -1)
631             return BINARY_DOS;
632         if (!ReadFile( hfile, magic, sizeof(magic), &len, NULL ) || len != sizeof(magic))
633             return BINARY_DOS;
634
635         /* Reading the magic field succeeded so
636          * we will try to determine what type it is.
637          */
638         if (!memcmp( magic, "PE\0\0", 4 ))
639         {
640             IMAGE_FILE_HEADER FileHeader;
641
642             if (ReadFile( hfile, &FileHeader, sizeof(FileHeader), &len, NULL ) && len == sizeof(FileHeader))
643             {
644                 if (FileHeader.Characteristics & IMAGE_FILE_DLL) return BINARY_PE_DLL;
645                 return BINARY_PE_EXE;
646             }
647             return BINARY_DOS;
648         }
649
650         if (!memcmp( magic, "NE", 2 ))
651         {
652             /* This is a Windows executable (NE) header.  This can
653              * mean either a 16-bit OS/2 or a 16-bit Windows or even a
654              * DOS program (running under a DOS extender).  To decide
655              * which, we'll have to read the NE header.
656              */
657             IMAGE_OS2_HEADER ne;
658             if (    SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) != -1
659                     && ReadFile( hfile, &ne, sizeof(ne), &len, NULL )
660                     && len == sizeof(ne) )
661             {
662                 switch ( ne.ne_exetyp )
663                 {
664                 case 2:  return BINARY_WIN16;
665                 case 5:  return BINARY_DOS;
666                 default: return MODULE_Decide_OS2_OldWin(hfile, &header.mz, &ne);
667                 }
668             }
669             /* Couldn't read header, so abort. */
670             return BINARY_DOS;
671         }
672
673         /* Unknown extended header, but this file is nonetheless DOS-executable. */
674         return BINARY_DOS;
675     }
676
677     return BINARY_UNKNOWN;
678 }
679
680 /***********************************************************************
681  *             GetBinaryTypeA                     [KERNEL32.@]
682  *             GetBinaryType                      [KERNEL32.@]
683  *
684  * The GetBinaryType function determines whether a file is executable
685  * or not and if it is it returns what type of executable it is.
686  * The type of executable is a property that determines in which
687  * subsystem an executable file runs under.
688  *
689  * Binary types returned:
690  * SCS_32BIT_BINARY: A Win32 based application
691  * SCS_DOS_BINARY: An MS-Dos based application
692  * SCS_WOW_BINARY: A Win16 based application
693  * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
694  * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
695  * SCS_OS216_BINARY: A 16bit OS/2 based application
696  *
697  * Returns TRUE if the file is an executable in which case
698  * the value pointed by lpBinaryType is set.
699  * Returns FALSE if the file is not an executable or if the function fails.
700  *
701  * To do so it opens the file and reads in the header information
702  * if the extended header information is not present it will
703  * assume that the file is a DOS executable.
704  * If the extended header information is present it will
705  * determine if the file is a 16 or 32 bit Windows executable
706  * by check the flags in the header.
707  *
708  * Note that .COM and .PIF files are only recognized by their
709  * file name extension; but Windows does it the same way ...
710  */
711 BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
712 {
713     BOOL ret = FALSE;
714     HANDLE hfile;
715     char *ptr;
716
717     TRACE_(win32)("%s\n", lpApplicationName );
718
719     /* Sanity check.
720      */
721     if ( lpApplicationName == NULL || lpBinaryType == NULL )
722         return FALSE;
723
724     /* Open the file indicated by lpApplicationName for reading.
725      */
726     hfile = CreateFileA( lpApplicationName, GENERIC_READ, FILE_SHARE_READ,
727                          NULL, OPEN_EXISTING, 0, 0 );
728     if ( hfile == INVALID_HANDLE_VALUE )
729         return FALSE;
730
731     /* Check binary type
732      */
733     switch(MODULE_GetBinaryType( hfile ))
734     {
735     case BINARY_UNKNOWN:
736         /* try to determine from file name */
737         ptr = strrchr( lpApplicationName, '.' );
738         if (!ptr) break;
739         if (!FILE_strcasecmp( ptr, ".COM" ))
740         {
741             *lpBinaryType = SCS_DOS_BINARY;
742             ret = TRUE;
743         }
744         else if (!FILE_strcasecmp( ptr, ".PIF" ))
745         {
746             *lpBinaryType = SCS_PIF_BINARY;
747             ret = TRUE;
748         }
749         break;
750     case BINARY_PE_EXE:
751     case BINARY_PE_DLL:
752         *lpBinaryType = SCS_32BIT_BINARY;
753         ret = TRUE;
754         break;
755     case BINARY_WIN16:
756         *lpBinaryType = SCS_WOW_BINARY;
757         ret = TRUE;
758         break;
759     case BINARY_OS216:
760         *lpBinaryType = SCS_OS216_BINARY;
761         ret = TRUE;
762         break;
763     case BINARY_DOS:
764         *lpBinaryType = SCS_DOS_BINARY;
765         ret = TRUE;
766         break;
767     case BINARY_UNIX_EXE:
768     case BINARY_UNIX_LIB:
769         ret = FALSE;
770         break;
771     }
772
773     CloseHandle( hfile );
774     return ret;
775 }
776
777 /***********************************************************************
778  *             GetBinaryTypeW                      [KERNEL32.@]
779  */
780 BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
781 {
782     BOOL ret = FALSE;
783     LPSTR strNew = NULL;
784
785     TRACE_(win32)("%s\n", debugstr_w(lpApplicationName) );
786
787     /* Sanity check.
788      */
789     if ( lpApplicationName == NULL || lpBinaryType == NULL )
790         return FALSE;
791
792     /* Convert the wide string to a ascii string.
793      */
794     strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
795
796     if ( strNew != NULL )
797     {
798         ret = GetBinaryTypeA( strNew, lpBinaryType );
799
800         /* Free the allocated string.
801          */
802         HeapFree( GetProcessHeap(), 0, strNew );
803     }
804
805     return ret;
806 }
807
808
809 /***********************************************************************
810  *           WinExec     (KERNEL.166)
811  */
812 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
813 {
814     LPCSTR p, args = NULL;
815     LPCSTR name_beg, name_end;
816     LPSTR name, cmdline;
817     int arglen;
818     HINSTANCE16 ret;
819     char buffer[MAX_PATH];
820
821     if (*lpCmdLine == '"') /* has to be only one and only at beginning ! */
822     {
823       name_beg = lpCmdLine+1;
824       p = strchr ( lpCmdLine+1, '"' );
825       if (p)
826       {
827           name_end = p;
828           args = strchr ( p, ' ' );
829       }
830       else /* yes, even valid with trailing '"' missing */
831           name_end = lpCmdLine+strlen(lpCmdLine);
832     }
833     else
834     {
835       name_beg = lpCmdLine;
836       args = strchr( lpCmdLine, ' ' );
837       name_end = args ? args : lpCmdLine+strlen(lpCmdLine);
838     }
839
840     if ((name_beg == lpCmdLine) && (!args))
841     { /* just use the original cmdline string as file name */
842         name = (LPSTR)lpCmdLine;
843     }
844     else
845     {
846         if (!(name = HeapAlloc( GetProcessHeap(), 0, name_end - name_beg + 1 )))
847             return ERROR_NOT_ENOUGH_MEMORY;
848         memcpy( name, name_beg, name_end - name_beg );
849         name[name_end - name_beg] = '\0';
850     }
851
852     if (args)
853     {
854         args++;
855         arglen = strlen(args);
856         cmdline = HeapAlloc( GetProcessHeap(), 0, 2 + arglen );
857         cmdline[0] = (BYTE)arglen;
858         strcpy( cmdline + 1, args );
859     }
860     else
861     {
862         cmdline = HeapAlloc( GetProcessHeap(), 0, 2 );
863         cmdline[0] = cmdline[1] = 0;
864     }
865
866     TRACE("name: '%s', cmdline: '%.*s'\n", name, cmdline[0], &cmdline[1]);
867
868     if (SearchPathA( NULL, name, ".exe", sizeof(buffer), buffer, NULL ))
869     {
870         LOADPARAMS16 params;
871         WORD showCmd[2];
872         showCmd[0] = 2;
873         showCmd[1] = nCmdShow;
874
875         params.hEnvironment = 0;
876         params.cmdLine = MapLS( cmdline );
877         params.showCmd = MapLS( showCmd );
878         params.reserved = 0;
879
880         ret = LoadModule16( buffer, &params );
881         UnMapLS( params.cmdLine );
882         UnMapLS( params.showCmd );
883     }
884     else ret = GetLastError();
885
886     HeapFree( GetProcessHeap(), 0, cmdline );
887     if (name != lpCmdLine) HeapFree( GetProcessHeap(), 0, name );
888
889     if (ret == 21)  /* 32-bit module */
890     {
891         DWORD count;
892         ReleaseThunkLock( &count );
893         ret = LOWORD( WinExec( lpCmdLine, nCmdShow ) );
894         RestoreThunkLock( count );
895     }
896     return ret;
897 }
898
899 /***********************************************************************
900  *           WinExec   (KERNEL32.@)
901  */
902 UINT WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow )
903 {
904     PROCESS_INFORMATION info;
905     STARTUPINFOA startup;
906     char *cmdline;
907     UINT ret;
908
909     memset( &startup, 0, sizeof(startup) );
910     startup.cb = sizeof(startup);
911     startup.dwFlags = STARTF_USESHOWWINDOW;
912     startup.wShowWindow = nCmdShow;
913
914     /* cmdline needs to be writeable for CreateProcess */
915     if (!(cmdline = HeapAlloc( GetProcessHeap(), 0, strlen(lpCmdLine)+1 ))) return 0;
916     strcpy( cmdline, lpCmdLine );
917
918     if (CreateProcessA( NULL, cmdline, NULL, NULL, FALSE,
919                         0, NULL, NULL, &startup, &info ))
920     {
921         /* Give 30 seconds to the app to come up */
922         if (wait_input_idle( info.hProcess, 30000 ) == 0xFFFFFFFF)
923             WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
924         ret = 33;
925         /* Close off the handles */
926         CloseHandle( info.hThread );
927         CloseHandle( info.hProcess );
928     }
929     else if ((ret = GetLastError()) >= 32)
930     {
931         FIXME("Strange error set by CreateProcess: %d\n", ret );
932         ret = 11;
933     }
934     HeapFree( GetProcessHeap(), 0, cmdline );
935     return ret;
936 }
937
938 /**********************************************************************
939  *          LoadModule    (KERNEL32.@)
940  */
941 HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
942 {
943     LOADPARAMS *params = (LOADPARAMS *)paramBlock;
944     PROCESS_INFORMATION info;
945     STARTUPINFOA startup;
946     HINSTANCE hInstance;
947     LPSTR cmdline, p;
948     char filename[MAX_PATH];
949     BYTE len;
950
951     if (!name) return (HINSTANCE)ERROR_FILE_NOT_FOUND;
952
953     if (!SearchPathA( NULL, name, ".exe", sizeof(filename), filename, NULL ) &&
954         !SearchPathA( NULL, name, NULL, sizeof(filename), filename, NULL ))
955         return (HINSTANCE)GetLastError();
956
957     len = (BYTE)params->lpCmdLine[0];
958     if (!(cmdline = HeapAlloc( GetProcessHeap(), 0, strlen(filename) + len + 2 )))
959         return (HINSTANCE)ERROR_NOT_ENOUGH_MEMORY;
960
961     strcpy( cmdline, filename );
962     p = cmdline + strlen(cmdline);
963     *p++ = ' ';
964     memcpy( p, params->lpCmdLine + 1, len );
965     p[len] = 0;
966
967     memset( &startup, 0, sizeof(startup) );
968     startup.cb = sizeof(startup);
969     if (params->lpCmdShow)
970     {
971         startup.dwFlags = STARTF_USESHOWWINDOW;
972         startup.wShowWindow = params->lpCmdShow[1];
973     }
974
975     if (CreateProcessA( filename, cmdline, NULL, NULL, FALSE, 0,
976                         params->lpEnvAddress, NULL, &startup, &info ))
977     {
978         /* Give 30 seconds to the app to come up */
979         if (wait_input_idle( info.hProcess, 30000 ) ==  0xFFFFFFFF )
980             WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
981         hInstance = (HINSTANCE)33;
982         /* Close off the handles */
983         CloseHandle( info.hThread );
984         CloseHandle( info.hProcess );
985     }
986     else if ((hInstance = (HINSTANCE)GetLastError()) >= (HINSTANCE)32)
987     {
988         FIXME("Strange error set by CreateProcess: %d\n", hInstance );
989         hInstance = (HINSTANCE)11;
990     }
991
992     HeapFree( GetProcessHeap(), 0, cmdline );
993     return hInstance;
994 }
995
996
997 /***********************************************************************
998  *              GetModuleHandleA         (KERNEL32.@)
999  *              GetModuleHandle32        (KERNEL.488)
1000  */
1001 HMODULE WINAPI GetModuleHandleA(LPCSTR module)
1002 {
1003     WINE_MODREF *wm;
1004
1005     if ( module == NULL )
1006         wm = exe_modref;
1007     else
1008         wm = MODULE_FindModule( module );
1009
1010     return wm? wm->module : 0;
1011 }
1012
1013 /***********************************************************************
1014  *              GetModuleHandleW (KERNEL32.@)
1015  */
1016 HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
1017 {
1018     HMODULE hModule;
1019     LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
1020     hModule = GetModuleHandleA( modulea );
1021     HeapFree( GetProcessHeap(), 0, modulea );
1022     return hModule;
1023 }
1024
1025
1026 /***********************************************************************
1027  *              GetModuleFileNameA      (KERNEL32.@)
1028  *              GetModuleFileName32     (KERNEL.487)
1029  *
1030  * GetModuleFileNameA seems to *always* return the long path;
1031  * it's only GetModuleFileName16 that decides between short/long path
1032  * by checking if exe version >= 4.0.
1033  * (SDK docu doesn't mention this)
1034  */
1035 DWORD WINAPI GetModuleFileNameA(
1036         HMODULE hModule,        /* [in] module handle (32bit) */
1037         LPSTR lpFileName,       /* [out] filenamebuffer */
1038         DWORD size )            /* [in] size of filenamebuffer */
1039 {
1040     RtlEnterCriticalSection( &loader_section );
1041
1042     lpFileName[0] = 0;
1043     if (!hModule && !(NtCurrentTeb()->tibflags & TEBF_WIN32))
1044     {
1045         /* 16-bit task - get current NE module name */
1046         NE_MODULE *pModule = NE_GetPtr( GetCurrentTask() );
1047         if (pModule) GetLongPathNameA(NE_MODULE_NAME(pModule), lpFileName, size);
1048     }
1049     else
1050     {
1051         WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1052         if (wm) lstrcpynA( lpFileName, wm->filename, size );
1053     }
1054
1055     RtlLeaveCriticalSection( &loader_section );
1056     TRACE("%s\n", lpFileName );
1057     return strlen(lpFileName);
1058 }
1059
1060
1061 /***********************************************************************
1062  *              GetModuleFileNameW      (KERNEL32.@)
1063  */
1064 DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName, DWORD size )
1065 {
1066     LPSTR fnA = HeapAlloc( GetProcessHeap(), 0, size * 2 );
1067     if (!fnA) return 0;
1068     GetModuleFileNameA( hModule, fnA, size * 2 );
1069     if (size > 0 && !MultiByteToWideChar( CP_ACP, 0, fnA, -1, lpFileName, size ))
1070         lpFileName[size-1] = 0;
1071     HeapFree( GetProcessHeap(), 0, fnA );
1072     return strlenW(lpFileName);
1073 }
1074
1075
1076 /***********************************************************************
1077  *           LoadLibraryExA   (KERNEL32.@)
1078  */
1079 HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
1080 {
1081         WINE_MODREF *wm;
1082
1083         if(!libname)
1084         {
1085                 SetLastError(ERROR_INVALID_PARAMETER);
1086                 return 0;
1087         }
1088
1089         if (flags & LOAD_LIBRARY_AS_DATAFILE)
1090         {
1091             char filename[256];
1092             HMODULE hmod = 0;
1093
1094             /* This method allows searching for the 'native' libraries only */
1095             if (SearchPathA( NULL, libname, ".dll", sizeof(filename), filename, NULL ))
1096             {
1097                 /* FIXME: maybe we should use the hfile parameter instead */
1098                 HANDLE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ,
1099                                             NULL, OPEN_EXISTING, 0, 0 );
1100                 if (hFile != INVALID_HANDLE_VALUE)
1101                 {
1102                     HANDLE mapping;
1103                     switch (MODULE_GetBinaryType( hFile ))
1104                     {
1105                     case BINARY_PE_EXE:
1106                     case BINARY_PE_DLL:
1107                         mapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
1108                         if (mapping)
1109                         {
1110                             hmod = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
1111                             CloseHandle( mapping );
1112                         }
1113                         break;
1114                     default:
1115                         break;
1116                     }
1117                     CloseHandle( hFile );
1118                 }
1119                 if (hmod) return (HMODULE)((ULONG_PTR)hmod + 1);
1120             }
1121             flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
1122             /* Fallback to normal behaviour */
1123         }
1124
1125         RtlEnterCriticalSection( &loader_section );
1126
1127         wm = MODULE_LoadLibraryExA( libname, hfile, flags );
1128         if ( wm )
1129         {
1130                 if ( !MODULE_DllProcessAttach( wm, NULL ) )
1131                 {
1132                         WARN_(module)("Attach failed for module '%s'.\n", libname);
1133                         MODULE_FreeLibrary(wm);
1134                         SetLastError(ERROR_DLL_INIT_FAILED);
1135                         wm = NULL;
1136                 }
1137         }
1138
1139         RtlLeaveCriticalSection( &loader_section );
1140         return wm ? wm->module : 0;
1141 }
1142
1143 /***********************************************************************
1144  *      allocate_lib_dir
1145  *
1146  * helper for MODULE_LoadLibraryExA.  Allocate space to hold the directory
1147  * portion of the provided name and put the name in it.
1148  *
1149  */
1150 static LPCSTR allocate_lib_dir(LPCSTR libname)
1151 {
1152     LPCSTR p, pmax;
1153     LPSTR result;
1154     int length;
1155
1156     pmax = libname;
1157     if ((p = strrchr( pmax, '\\' ))) pmax = p + 1;
1158     if ((p = strrchr( pmax, '/' ))) pmax = p + 1; /* Naughty.  MSDN says don't */
1159     if (pmax == libname && pmax[0] && pmax[1] == ':') pmax += 2;
1160
1161     length = pmax - libname;
1162
1163     result = HeapAlloc (GetProcessHeap(), 0, length+1);
1164
1165     if (result)
1166     {
1167         strncpy (result, libname, length);
1168         result [length] = '\0';
1169     }
1170
1171     return result;
1172 }
1173
1174 /***********************************************************************
1175  *      MODULE_LoadLibraryExA   (internal)
1176  *
1177  * Load a PE style module according to the load order.
1178  *
1179  * The HFILE parameter is not used and marked reserved in the SDK. I can
1180  * only guess that it should force a file to be mapped, but I rather
1181  * ignore the parameter because it would be extremely difficult to
1182  * integrate this with different types of module representations.
1183  *
1184  * libdir is used to support LOAD_WITH_ALTERED_SEARCH_PATH during the recursion
1185  *        on this function.  When first called from LoadLibraryExA it will be
1186  *        NULL but thereafter it may point to a buffer containing the path
1187  *        portion of the library name.  Note that the recursion all occurs
1188  *        within a Critical section (see LoadLibraryExA) so the use of a
1189  *        static is acceptable.
1190  *        (We have to use a static variable at some point anyway, to pass the
1191  *        information from BUILTIN32_dlopen through dlopen and the builtin's
1192  *        init function into load_library).
1193  * allocated_libdir is TRUE in the stack frame that allocated libdir
1194  */
1195 WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HANDLE hfile, DWORD flags )
1196 {
1197         DWORD err = GetLastError();
1198         WINE_MODREF *pwm;
1199         int i;
1200         enum loadorder_type loadorder[LOADORDER_NTYPES];
1201         LPSTR filename;
1202         const char *filetype = "";
1203         DWORD found;
1204         BOOL allocated_libdir = FALSE;
1205         static LPCSTR libdir = NULL; /* See above */
1206
1207         if ( !libname ) return NULL;
1208
1209         filename = HeapAlloc ( GetProcessHeap(), 0, MAX_PATH + 1 );
1210         if ( !filename ) return NULL;
1211         *filename = 0; /* Just in case we don't set it before goto error */
1212
1213         RtlEnterCriticalSection( &loader_section );
1214
1215         if ((flags & LOAD_WITH_ALTERED_SEARCH_PATH) && FILE_contains_path(libname))
1216         {
1217             if (!(libdir = allocate_lib_dir(libname))) goto error;
1218             allocated_libdir = TRUE;
1219         }
1220
1221         if (!libdir || allocated_libdir)
1222             found = SearchPathA(NULL, libname, ".dll", MAX_PATH, filename, NULL);
1223         else
1224             found = DIR_SearchAlternatePath(libdir, libname, ".dll", MAX_PATH, filename, NULL);
1225
1226         /* build the modules filename */
1227         if (!found)
1228         {
1229             if (!MODULE_GetBuiltinPath( libname, ".dll", filename, MAX_PATH )) goto error;
1230         }
1231
1232         /* Check for already loaded module */
1233         if (!(pwm = MODULE_FindModule(filename)) && !FILE_contains_path(libname))
1234         {
1235             LPSTR       fn = HeapAlloc ( GetProcessHeap(), 0, MAX_PATH + 1 );
1236             if (fn)
1237             {
1238                 /* since the default loading mechanism uses a more detailed algorithm
1239                  * than SearchPath (like using PATH, which can even be modified between
1240                  * two attempts of loading the same DLL), the look-up above (with
1241                  * SearchPath) can have put the file in system directory, whereas it
1242                  * has already been loaded but with a different path. So do a specific
1243                  * look-up with filename (without any path)
1244                  */
1245                 strcpy ( fn, libname );
1246                 /* if the filename doesn't have an extension append .DLL */
1247                 if (!strrchr( fn, '.')) strcat( fn, ".dll" );
1248                 if ((pwm = MODULE_FindModule( fn )) != NULL)
1249                    strcpy( filename, fn );
1250                 HeapFree( GetProcessHeap(), 0, fn );
1251             }
1252         }
1253         if (pwm)
1254         {
1255                 if(!(pwm->flags & WINE_MODREF_MARKER))
1256                         pwm->refCount++;
1257
1258                 if ((pwm->flags & WINE_MODREF_DONT_RESOLVE_REFS) &&
1259                     !(flags & DONT_RESOLVE_DLL_REFERENCES))
1260                 {
1261                     pwm->flags &= ~WINE_MODREF_DONT_RESOLVE_REFS;
1262                     PE_fixup_imports( pwm );
1263                 }
1264                 TRACE("Already loaded module '%s' at 0x%08x, count=%d\n", filename, pwm->module, pwm->refCount);
1265                 if (allocated_libdir)
1266                 {
1267                     HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
1268                     libdir = NULL;
1269                 }
1270                 RtlLeaveCriticalSection( &loader_section );
1271                 HeapFree ( GetProcessHeap(), 0, filename );
1272                 return pwm;
1273         }
1274
1275         MODULE_GetLoadOrder( loadorder, filename, TRUE);
1276
1277         for(i = 0; i < LOADORDER_NTYPES; i++)
1278         {
1279                 if (loadorder[i] == LOADORDER_INVALID) break;
1280                 SetLastError( ERROR_FILE_NOT_FOUND );
1281
1282                 switch(loadorder[i])
1283                 {
1284                 case LOADORDER_DLL:
1285                         TRACE("Trying native dll '%s'\n", filename);
1286                         pwm = PE_LoadLibraryExA(filename, flags);
1287                         filetype = "native";
1288                         break;
1289
1290                 case LOADORDER_SO:
1291                         TRACE("Trying so-library '%s'\n", filename);
1292                         pwm = ELF_LoadLibraryExA(filename, flags);
1293                         filetype = "so";
1294                         break;
1295
1296                 case LOADORDER_BI:
1297                         TRACE("Trying built-in '%s'\n", filename);
1298                         pwm = BUILTIN32_LoadLibraryExA(filename, flags);
1299                         filetype = "builtin";
1300                         break;
1301
1302                 default:
1303                         pwm = NULL;
1304                         break;
1305                 }
1306
1307                 if(pwm)
1308                 {
1309                         /* Initialize DLL just loaded */
1310                         TRACE("Loaded module '%s' at 0x%08x\n", filename, pwm->module);
1311                         if (!TRACE_ON(module))
1312                             TRACE_(loaddll)("Loaded module '%s' : %s\n", filename, filetype);
1313                         /* Set the refCount here so that an attach failure will */
1314                         /* decrement the dependencies through the MODULE_FreeLibrary call. */
1315                         pwm->refCount++;
1316
1317                         if (allocated_libdir)
1318                         {
1319                             HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
1320                             libdir = NULL;
1321                         }
1322                         RtlLeaveCriticalSection( &loader_section );
1323                         SetLastError( err );  /* restore last error */
1324                         HeapFree ( GetProcessHeap(), 0, filename );
1325                         return pwm;
1326                 }
1327
1328                 if(GetLastError() != ERROR_FILE_NOT_FOUND)
1329                 {
1330                     WARN("Loading of %s DLL %s failed (error %ld).\n",
1331                          filetype, filename, GetLastError());
1332                     break;
1333                 }
1334         }
1335
1336  error:
1337         if (allocated_libdir)
1338         {
1339             HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
1340             libdir = NULL;
1341         }
1342         RtlLeaveCriticalSection( &loader_section );
1343         WARN("Failed to load module '%s'; error=%ld\n", filename, GetLastError());
1344         HeapFree ( GetProcessHeap(), 0, filename );
1345         return NULL;
1346 }
1347
1348 /***********************************************************************
1349  *           LoadLibraryA         (KERNEL32.@)
1350  */
1351 HMODULE WINAPI LoadLibraryA(LPCSTR libname) {
1352         return LoadLibraryExA(libname,0,0);
1353 }
1354
1355 /***********************************************************************
1356  *           LoadLibraryW         (KERNEL32.@)
1357  */
1358 HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
1359 {
1360     return LoadLibraryExW(libnameW,0,0);
1361 }
1362
1363 /***********************************************************************
1364  *           LoadLibrary32        (KERNEL.452)
1365  *           LoadSystemLibrary32  (KERNEL.482)
1366  */
1367 HMODULE WINAPI LoadLibrary32_16( LPCSTR libname )
1368 {
1369     HMODULE hModule;
1370     DWORD count;
1371
1372     ReleaseThunkLock( &count );
1373     hModule = LoadLibraryA( libname );
1374     RestoreThunkLock( count );
1375     return hModule;
1376 }
1377
1378 /***********************************************************************
1379  *           LoadLibraryExW       (KERNEL32.@)
1380  */
1381 HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW,HANDLE hfile,DWORD flags)
1382 {
1383     LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
1384     HMODULE ret = LoadLibraryExA( libnameA , hfile, flags );
1385
1386     HeapFree( GetProcessHeap(), 0, libnameA );
1387     return ret;
1388 }
1389
1390 /***********************************************************************
1391  *           MODULE_FlushModrefs
1392  *
1393  * NOTE: Assumes that the process critical section is held!
1394  *
1395  * Remove all unused modrefs and call the internal unloading routines
1396  * for the library type.
1397  */
1398 static void MODULE_FlushModrefs(void)
1399 {
1400         WINE_MODREF *wm, *next;
1401
1402         for(wm = MODULE_modref_list; wm; wm = next)
1403         {
1404                 next = wm->next;
1405
1406                 if(wm->refCount)
1407                         continue;
1408
1409                 /* Unlink this modref from the chain */
1410                 if(wm->next)
1411                         wm->next->prev = wm->prev;
1412                 if(wm->prev)
1413                         wm->prev->next = wm->next;
1414                 if(wm == MODULE_modref_list)
1415                         MODULE_modref_list = wm->next;
1416
1417                 TRACE(" unloading %s\n", wm->filename);
1418                 if (!TRACE_ON(module))
1419                     TRACE_(loaddll)("Unloaded module '%s' : %s\n", wm->filename,
1420                                     wm->dlhandle ? "builtin" : "native" );
1421
1422                 if (wm->dlhandle) wine_dll_unload( wm->dlhandle );
1423                 else UnmapViewOfFile( (LPVOID)wm->module );
1424                 FreeLibrary16(wm->hDummyMod);
1425                 HeapFree( GetProcessHeap(), 0, wm->deps );
1426                 HeapFree( GetProcessHeap(), 0, wm );
1427         }
1428 }
1429
1430 /***********************************************************************
1431  *           FreeLibrary   (KERNEL32.@)
1432  *           FreeLibrary32 (KERNEL.486)
1433  */
1434 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
1435 {
1436     BOOL retv = FALSE;
1437     WINE_MODREF *wm;
1438
1439     if (!hLibModule)
1440     {
1441         SetLastError( ERROR_INVALID_HANDLE );
1442         return FALSE;
1443     }
1444
1445     if ((ULONG_PTR)hLibModule & 1)
1446     {
1447         /* this is a LOAD_LIBRARY_AS_DATAFILE module */
1448         char *ptr = (char *)hLibModule - 1;
1449         UnmapViewOfFile( ptr );
1450         return TRUE;
1451     }
1452
1453     RtlEnterCriticalSection( &loader_section );
1454     free_lib_count++;
1455
1456     if ((wm = MODULE32_LookupHMODULE( hLibModule ))) retv = MODULE_FreeLibrary( wm );
1457
1458     free_lib_count--;
1459     RtlLeaveCriticalSection( &loader_section );
1460
1461     return retv;
1462 }
1463
1464 /***********************************************************************
1465  *           MODULE_DecRefCount
1466  *
1467  * NOTE: Assumes that the process critical section is held!
1468  */
1469 static void MODULE_DecRefCount( WINE_MODREF *wm )
1470 {
1471     int i;
1472
1473     if ( wm->flags & WINE_MODREF_MARKER )
1474         return;
1475
1476     if ( wm->refCount <= 0 )
1477         return;
1478
1479     --wm->refCount;
1480     TRACE("(%s) refCount: %d\n", wm->modname, wm->refCount );
1481
1482     if ( wm->refCount == 0 )
1483     {
1484         wm->flags |= WINE_MODREF_MARKER;
1485
1486         for ( i = 0; i < wm->nDeps; i++ )
1487             if ( wm->deps[i] )
1488                 MODULE_DecRefCount( wm->deps[i] );
1489
1490         wm->flags &= ~WINE_MODREF_MARKER;
1491     }
1492 }
1493
1494 /***********************************************************************
1495  *           MODULE_FreeLibrary
1496  *
1497  * NOTE: Assumes that the process critical section is held!
1498  */
1499 BOOL MODULE_FreeLibrary( WINE_MODREF *wm )
1500 {
1501     TRACE("(%s) - START\n", wm->modname );
1502
1503     /* Recursively decrement reference counts */
1504     MODULE_DecRefCount( wm );
1505
1506     /* Call process detach notifications */
1507     if ( free_lib_count <= 1 )
1508     {
1509         MODULE_DllProcessDetach( FALSE, NULL );
1510         SERVER_START_REQ( unload_dll )
1511         {
1512             req->base = (void *)wm->module;
1513             wine_server_call( req );
1514         }
1515         SERVER_END_REQ;
1516         MODULE_FlushModrefs();
1517     }
1518
1519     TRACE("END\n");
1520
1521     return TRUE;
1522 }
1523
1524
1525 /***********************************************************************
1526  *           FreeLibraryAndExitThread (KERNEL32.@)
1527  */
1528 VOID WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
1529 {
1530     FreeLibrary(hLibModule);
1531     ExitThread(dwExitCode);
1532 }
1533
1534 /***********************************************************************
1535  *           PrivateLoadLibrary       (KERNEL32.@)
1536  *
1537  * FIXME: rough guesswork, don't know what "Private" means
1538  */
1539 HINSTANCE16 WINAPI PrivateLoadLibrary(LPCSTR libname)
1540 {
1541     return LoadLibrary16(libname);
1542 }
1543
1544
1545
1546 /***********************************************************************
1547  *           PrivateFreeLibrary       (KERNEL32.@)
1548  *
1549  * FIXME: rough guesswork, don't know what "Private" means
1550  */
1551 void WINAPI PrivateFreeLibrary(HINSTANCE16 handle)
1552 {
1553     FreeLibrary16(handle);
1554 }
1555
1556
1557 /***********************************************************************
1558  *           GetProcAddress16   (KERNEL32.37)
1559  * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1560  */
1561 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hModule, LPCSTR name )
1562 {
1563     if (!hModule) {
1564         WARN("hModule may not be 0!\n");
1565         return (FARPROC16)0;
1566     }
1567     if (HIWORD(hModule))
1568     {
1569         WARN("hModule is Win32 handle (%08x)\n", hModule );
1570         return (FARPROC16)0;
1571     }
1572     return GetProcAddress16( LOWORD(hModule), name );
1573 }
1574
1575 /***********************************************************************
1576  *           GetProcAddress   (KERNEL.50)
1577  */
1578 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, LPCSTR name )
1579 {
1580     WORD ordinal;
1581     FARPROC16 ret;
1582
1583     if (!hModule) hModule = GetCurrentTask();
1584     hModule = GetExePtr( hModule );
1585
1586     if (HIWORD(name) != 0)
1587     {
1588         ordinal = NE_GetOrdinal( hModule, name );
1589         TRACE("%04x '%s'\n", hModule, name );
1590     }
1591     else
1592     {
1593         ordinal = LOWORD(name);
1594         TRACE("%04x %04x\n", hModule, ordinal );
1595     }
1596     if (!ordinal) return (FARPROC16)0;
1597
1598     ret = NE_GetEntryPoint( hModule, ordinal );
1599
1600     TRACE("returning %08x\n", (UINT)ret );
1601     return ret;
1602 }
1603
1604
1605 /***********************************************************************
1606  *           GetProcAddress             (KERNEL32.@)
1607  */
1608 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
1609 {
1610     return MODULE_GetProcAddress( hModule, function, -1, TRUE );
1611 }
1612
1613 /***********************************************************************
1614  *           GetProcAddress32                   (KERNEL.453)
1615  */
1616 FARPROC WINAPI GetProcAddress32_16( HMODULE hModule, LPCSTR function )
1617 {
1618     return MODULE_GetProcAddress( hModule, function, -1, FALSE );
1619 }
1620
1621 /***********************************************************************
1622  *           MODULE_GetProcAddress              (internal)
1623  */
1624 FARPROC MODULE_GetProcAddress(
1625         HMODULE hModule,        /* [in] current module handle */
1626         LPCSTR function,        /* [in] function to be looked up */
1627         int hint,
1628         BOOL snoop )
1629 {
1630     WINE_MODREF *wm;
1631     FARPROC     retproc = 0;
1632
1633     if (HIWORD(function))
1634         TRACE_(win32)("(%08lx,%s (%d))\n",(DWORD)hModule,function,hint);
1635     else
1636         TRACE_(win32)("(%08lx,%p)\n",(DWORD)hModule,function);
1637
1638     RtlEnterCriticalSection( &loader_section );
1639     if ((wm = MODULE32_LookupHMODULE( hModule )))
1640     {
1641         retproc = wm->find_export( wm, function, hint, snoop );
1642         if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
1643     }
1644     RtlLeaveCriticalSection( &loader_section );
1645     return retproc;
1646 }
1647
1648
1649 /***************************************************************************
1650  *              HasGPHandler                    (KERNEL.338)
1651  */
1652
1653 #include "pshpack1.h"
1654 typedef struct _GPHANDLERDEF
1655 {
1656     WORD selector;
1657     WORD rangeStart;
1658     WORD rangeEnd;
1659     WORD handler;
1660 } GPHANDLERDEF;
1661 #include "poppack.h"
1662
1663 SEGPTR WINAPI HasGPHandler16( SEGPTR address )
1664 {
1665     HMODULE16 hModule;
1666     int gpOrdinal;
1667     SEGPTR gpPtr;
1668     GPHANDLERDEF *gpHandler;
1669
1670     if (    (hModule = FarGetOwner16( SELECTOROF(address) )) != 0
1671          && (gpOrdinal = NE_GetOrdinal( hModule, "__GP" )) != 0
1672          && (gpPtr = (SEGPTR)NE_GetEntryPointEx( hModule, gpOrdinal, FALSE )) != 0
1673          && !IsBadReadPtr16( gpPtr, sizeof(GPHANDLERDEF) )
1674          && (gpHandler = MapSL( gpPtr )) != NULL )
1675     {
1676         while (gpHandler->selector)
1677         {
1678             if (    SELECTOROF(address) == gpHandler->selector
1679                  && OFFSETOF(address)   >= gpHandler->rangeStart
1680                  && OFFSETOF(address)   <  gpHandler->rangeEnd  )
1681                 return MAKESEGPTR( gpHandler->selector, gpHandler->handler );
1682             gpHandler++;
1683         }
1684     }
1685
1686     return 0;
1687 }