Fixed ShellExecute functions when ddeexec was present in registry.
[wine] / loader / ne / module.c
1 /*
2  * NE modules
3  *
4  * Copyright 1995 Alexandre Julliard
5  */
6
7 #include "config.h"
8 #include "wine/port.h" 
9
10 #include <assert.h>
11 #include <fcntl.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <ctype.h>
16
17 #include "wine/winbase16.h"
18 #include "wine/library.h"
19 #include "winerror.h"
20 #include "module.h"
21 #include "toolhelp.h"
22 #include "file.h"
23 #include "task.h"
24 #include "snoop.h"
25 #include "builtin16.h"
26 #include "stackframe.h"
27 #include "debugtools.h"
28
29 DEFAULT_DEBUG_CHANNEL(module);
30 DECLARE_DEBUG_CHANNEL(loaddll);
31
32 /*
33  * Segment table entry
34  */
35 struct ne_segment_table_entry_s
36 {
37     WORD seg_data_offset;   /* Sector offset of segment data    */
38     WORD seg_data_length;   /* Length of segment data           */
39     WORD seg_flags;         /* Flags associated with this segment       */
40     WORD min_alloc;         /* Minimum allocation size for this */
41 };
42
43 #define hFirstModule (pThhook->hExeHead)
44
45 static NE_MODULE *pCachedModule = 0;  /* Module cached by NE_OpenFile */
46
47 static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only );
48 static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep );
49
50 static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only );
51
52 static HMODULE16 NE_GetModuleByFilename( LPCSTR name );
53
54 /* ### start build ### */
55 extern WORD CALLBACK NE_CallTo16_word_w(FARPROC16,WORD);
56 /* ### stop build ### */
57
58 /***********************************************************************
59  *           NE_GetPtr
60  */
61 NE_MODULE *NE_GetPtr( HMODULE16 hModule )
62 {
63     return (NE_MODULE *)GlobalLock16( GetExePtr(hModule) );
64 }
65
66
67 /***********************************************************************
68  *           NE_DumpModule
69  */
70 void NE_DumpModule( HMODULE16 hModule )
71 {
72     int i, ordinal;
73     SEGTABLEENTRY *pSeg;
74     BYTE *pstr;
75     WORD *pword;
76     NE_MODULE *pModule;
77     ET_BUNDLE *bundle;
78     ET_ENTRY *entry;
79
80     if (!(pModule = NE_GetPtr( hModule )))
81     {
82         MESSAGE( "**** %04x is not a module handle\n", hModule );
83         return;
84     }
85
86       /* Dump the module info */
87     DPRINTF( "---\n" );
88     DPRINTF( "Module %04x:\n", hModule );
89     DPRINTF( "count=%d flags=%04x heap=%d stack=%d\n",
90           pModule->count, pModule->flags,
91           pModule->heap_size, pModule->stack_size );
92     DPRINTF( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
93           pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
94           pModule->seg_count, pModule->modref_count );
95     DPRINTF( "os_flags=%d swap_area=%d version=%04x\n",
96           pModule->os_flags, pModule->min_swap_area,
97           pModule->expected_version );
98     if (pModule->flags & NE_FFLAGS_WIN32)
99         DPRINTF( "PE module=%08x\n", pModule->module32 );
100
101       /* Dump the file info */
102     DPRINTF( "---\n" );
103     DPRINTF( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
104
105       /* Dump the segment table */
106     DPRINTF( "---\n" );
107     DPRINTF( "Segment table:\n" );
108     pSeg = NE_SEG_TABLE( pModule );
109     for (i = 0; i < pModule->seg_count; i++, pSeg++)
110         DPRINTF( "%02x: pos=%d size=%d flags=%04x minsize=%d hSeg=%04x\n",
111               i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
112               pSeg->minsize, pSeg->hSeg );
113
114       /* Dump the resource table */
115     DPRINTF( "---\n" );
116     DPRINTF( "Resource table:\n" );
117     if (pModule->res_table)
118     {
119         pword = (WORD *)((BYTE *)pModule + pModule->res_table);
120         DPRINTF( "Alignment: %d\n", *pword++ );
121         while (*pword)
122         {
123             NE_TYPEINFO *ptr = (NE_TYPEINFO *)pword;
124             NE_NAMEINFO *pname = (NE_NAMEINFO *)(ptr + 1);
125             DPRINTF( "id=%04x count=%d\n", ptr->type_id, ptr->count );
126             for (i = 0; i < ptr->count; i++, pname++)
127                 DPRINTF( "offset=%d len=%d id=%04x\n",
128                       pname->offset, pname->length, pname->id );
129             pword = (WORD *)pname;
130         }
131     }
132     else DPRINTF( "None\n" );
133
134       /* Dump the resident name table */
135     DPRINTF( "---\n" );
136     DPRINTF( "Resident-name table:\n" );
137     pstr = (char *)pModule + pModule->name_table;
138     while (*pstr)
139     {
140         DPRINTF( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
141               *(WORD *)(pstr + *pstr + 1) );
142         pstr += *pstr + 1 + sizeof(WORD);
143     }
144
145       /* Dump the module reference table */
146     DPRINTF( "---\n" );
147     DPRINTF( "Module ref table:\n" );
148     if (pModule->modref_table)
149     {
150         pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
151         for (i = 0; i < pModule->modref_count; i++, pword++)
152         {
153             char name[10];
154             GetModuleName16( *pword, name, sizeof(name) );
155             DPRINTF( "%d: %04x -> '%s'\n", i, *pword, name );
156         }
157     }
158     else DPRINTF( "None\n" );
159
160       /* Dump the entry table */
161     DPRINTF( "---\n" );
162     DPRINTF( "Entry table:\n" );
163     bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table);    
164     do {
165         entry = (ET_ENTRY *)((BYTE *)bundle+6);
166         DPRINTF( "Bundle %d-%d: %02x\n", bundle->first, bundle->last, entry->type);
167         ordinal = bundle->first;
168         while (ordinal < bundle->last)
169         {
170             if (entry->type == 0xff)
171                 DPRINTF("%d: %02x:%04x (moveable)\n", ordinal++, entry->segnum, entry->offs);
172             else
173                 DPRINTF("%d: %02x:%04x (fixed)\n", ordinal++, entry->segnum, entry->offs);
174             entry++;
175     }
176     } while ( (bundle->next)
177            && (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
178
179     /* Dump the non-resident names table */
180     DPRINTF( "---\n" );
181     DPRINTF( "Non-resident names table:\n" );
182     if (pModule->nrname_handle)
183     {
184         pstr = (char *)GlobalLock16( pModule->nrname_handle );
185         while (*pstr)
186         {
187             DPRINTF( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
188                    *(WORD *)(pstr + *pstr + 1) );
189             pstr += *pstr + 1 + sizeof(WORD);
190         }
191     }
192     DPRINTF( "\n" );
193 }
194
195
196 /***********************************************************************
197  *           NE_WalkModules
198  *
199  * Walk the module list and print the modules.
200  */
201 void NE_WalkModules(void)
202 {
203     HMODULE16 hModule = hFirstModule;
204     MESSAGE( "Module Flags Name\n" );
205     while (hModule)
206     {
207         NE_MODULE *pModule = NE_GetPtr( hModule );
208         if (!pModule)
209         {
210             MESSAGE( "Bad module %04x in list\n", hModule );
211             return;
212         }
213         MESSAGE( " %04x  %04x  %.*s\n", hModule, pModule->flags,
214                  *((char *)pModule + pModule->name_table),
215                  (char *)pModule + pModule->name_table + 1 );
216         hModule = pModule->next;
217     }
218 }
219
220
221 /**********************************************************************
222  *           NE_RegisterModule
223  */
224 void NE_RegisterModule( NE_MODULE *pModule )
225 {
226     pModule->next = hFirstModule;
227     hFirstModule = pModule->self;
228 }
229
230
231 /***********************************************************************
232  *           NE_GetOrdinal
233  *
234  * Lookup the ordinal for a given name.
235  */
236 WORD NE_GetOrdinal( HMODULE16 hModule, const char *name )
237 {
238     unsigned char buffer[256], *cpnt;
239     BYTE len;
240     NE_MODULE *pModule;
241
242     if (!(pModule = NE_GetPtr( hModule ))) return 0;
243     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
244
245     TRACE("(%04x,'%s')\n", hModule, name );
246
247       /* First handle names of the form '#xxxx' */
248
249     if (name[0] == '#') return atoi( name + 1 );
250
251       /* Now copy and uppercase the string */
252
253     strcpy( buffer, name );
254     for (cpnt = buffer; *cpnt; cpnt++) *cpnt = FILE_toupper(*cpnt);
255     len = cpnt - buffer;
256
257       /* First search the resident names */
258
259     cpnt = (char *)pModule + pModule->name_table;
260
261       /* Skip the first entry (module name) */
262     cpnt += *cpnt + 1 + sizeof(WORD);
263     while (*cpnt)
264     {
265         if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
266         {
267             WORD ordinal = GET_UA_WORD( cpnt + *cpnt + 1 );
268             TRACE("  Found: ordinal=%d\n", ordinal );
269             return ordinal;
270         }
271         cpnt += *cpnt + 1 + sizeof(WORD);
272     }
273
274       /* Now search the non-resident names table */
275
276     if (!pModule->nrname_handle) return 0;  /* No non-resident table */
277     cpnt = (char *)GlobalLock16( pModule->nrname_handle );
278
279       /* Skip the first entry (module description string) */
280     cpnt += *cpnt + 1 + sizeof(WORD);
281     while (*cpnt)
282     {
283         if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
284         {
285             WORD ordinal = GET_UA_WORD( cpnt + *cpnt + 1 );
286             TRACE("  Found: ordinal=%d\n", ordinal );
287             return ordinal;
288         }
289         cpnt += *cpnt + 1 + sizeof(WORD);
290     }
291     return 0;
292 }
293
294
295 /***********************************************************************
296  *              EntryAddrProc (KERNEL.667) Wine-specific export
297  *
298  * Return the entry point for a given ordinal.
299  */
300 FARPROC16 WINAPI EntryAddrProc16( HMODULE16 hModule, WORD ordinal )
301 {
302     FARPROC16 ret = NE_GetEntryPointEx( hModule, ordinal, TRUE );
303     CURRENT_STACK16->ecx = hModule; /* FIXME: might be incorrect value */
304     return ret;
305 }
306
307 /***********************************************************************
308  *              NE_GetEntryPoint
309  */
310 FARPROC16 WINAPI NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
311 {
312     return NE_GetEntryPointEx( hModule, ordinal, TRUE );
313 }
314
315 /***********************************************************************
316  *              NE_GetEntryPointEx
317  */
318 FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop )
319 {
320     NE_MODULE *pModule;
321     WORD sel, offset, i;
322
323     ET_ENTRY *entry;
324     ET_BUNDLE *bundle;
325
326     if (!(pModule = NE_GetPtr( hModule ))) return 0;
327     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
328
329     bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
330     while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
331     {
332         if (!(bundle->next))
333             return 0;
334         bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
335     }
336
337     entry = (ET_ENTRY *)((BYTE *)bundle+6);
338     for (i=0; i < (ordinal - bundle->first - 1); i++)
339         entry++;
340
341     sel = entry->segnum;
342     offset = GET_UA_WORD( &entry->offs );
343
344     if (sel == 0xfe) sel = 0xffff;  /* constant entry */
345     else sel = GlobalHandleToSel16(NE_SEG_TABLE(pModule)[sel-1].hSeg);
346     if (sel==0xffff)
347         return (FARPROC16)MAKESEGPTR( sel, offset );
348     if (!snoop)
349         return (FARPROC16)MAKESEGPTR( sel, offset );
350     else
351         return (FARPROC16)SNOOP16_GetProcAddress16(hModule,ordinal,(FARPROC16)MAKESEGPTR( sel, offset ));
352 }
353
354
355 /***********************************************************************
356  *           NE_SetEntryPoint
357  *
358  * Change the value of an entry point. Use with caution!
359  * It can only change the offset value, not the selector.
360  */
361 BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
362 {
363     NE_MODULE *pModule;
364     ET_ENTRY *entry;
365     ET_BUNDLE *bundle;
366     int i;
367
368     if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
369     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
370
371     bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
372     while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
373         {
374         bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
375         if (!(bundle->next))
376             return 0;
377     }
378
379     entry = (ET_ENTRY *)((BYTE *)bundle+6);
380     for (i=0; i < (ordinal - bundle->first - 1); i++)
381         entry++;
382
383     PUT_UA_WORD( &entry->offs, offset );
384     return TRUE;
385 }
386
387
388 /***********************************************************************
389  *           NE_OpenFile
390  */
391 HANDLE NE_OpenFile( NE_MODULE *pModule )
392 {
393     char *name;
394
395     static HANDLE cachedfd = INVALID_HANDLE_VALUE;
396
397     TRACE("(%p) cache: mod=%p fd=%d\n",
398            pModule, pCachedModule, cachedfd );
399     if (pCachedModule == pModule) return cachedfd;
400     CloseHandle( cachedfd );
401     pCachedModule = pModule;
402     name = NE_MODULE_NAME( pModule );
403     if ((cachedfd = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ,
404                                    NULL, OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
405         MESSAGE( "Can't open file '%s' for module %04x\n", name, pModule->self );
406     TRACE("opened '%s' -> %d\n",
407                     name, cachedfd );
408     return cachedfd;
409 }
410
411
412 /***********************************************************************
413  *           NE_LoadExeHeader
414  */
415 static HMODULE16 NE_LoadExeHeader( HANDLE hFile, LPCSTR path )
416 {
417     IMAGE_DOS_HEADER mz_header;
418     IMAGE_OS2_HEADER ne_header;
419     int size;
420     HMODULE16 hModule;
421     NE_MODULE *pModule;
422     BYTE *pData, *pTempEntryTable;
423     char *buffer, *fastload = NULL;
424     int fastload_offset = 0, fastload_length = 0;
425     ET_ENTRY *entry;
426     ET_BUNDLE *bundle, *oldbundle;
427     OFSTRUCT *ofs;
428
429   /* Read a block from either the file or the fast-load area. */
430 #define READ(offset,size,buffer) \
431        ((fastload && ((offset) >= fastload_offset) && \
432          ((offset)+(size) <= fastload_offset+fastload_length)) ? \
433         (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
434         (_llseek( hFile, (offset), SEEK_SET), \
435          _lread( hFile, (buffer), (size) ) == (size)))
436
437     _llseek( hFile, 0, SEEK_SET );
438     if ((_lread(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
439         (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
440         return (HMODULE16)11;  /* invalid exe */
441
442     _llseek( hFile, mz_header.e_lfanew, SEEK_SET );
443     if (_lread( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
444         return (HMODULE16)11;  /* invalid exe */
445
446     if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE16)21;  /* win32 exe */
447     if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
448         MESSAGE("Sorry, this is an OS/2 linear executable (LX) file !\n");
449         return (HMODULE16)12;
450     }
451     if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE16)11;  /* invalid exe */
452
453     /* We now have a valid NE header */
454
455     size = sizeof(NE_MODULE) +
456              /* segment table */
457            ne_header.ne_cseg * sizeof(SEGTABLEENTRY) +
458              /* resource table */
459            ne_header.ne_restab - ne_header.ne_rsrctab +
460              /* resident names table */
461            ne_header.ne_modtab - ne_header.ne_restab +
462              /* module ref table */
463            ne_header.ne_cmod * sizeof(WORD) + 
464              /* imported names table */
465            ne_header.ne_enttab - ne_header.ne_imptab +
466              /* entry table length */
467            ne_header.ne_cbenttab +
468              /* entry table extra conversion space */
469            sizeof(ET_BUNDLE) +
470            2 * (ne_header.ne_cbenttab - ne_header.ne_cmovent*6) +
471              /* loaded file info */
472            sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path) + 1;
473
474     hModule = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, size );
475     if (!hModule) return (HMODULE16)11;  /* invalid exe */
476
477     FarSetOwner16( hModule, hModule );
478     pModule = (NE_MODULE *)GlobalLock16( hModule );
479     memcpy( pModule, &ne_header, sizeof(ne_header) );
480     pModule->count = 0;
481     /* check *programs* for default minimal stack size */
482     if ( (!(pModule->flags & NE_FFLAGS_LIBMODULE))
483                 && (pModule->stack_size < 0x1400) )
484                 pModule->stack_size = 0x1400;
485     pModule->module32 = 0;
486     pModule->self = hModule;
487     pModule->self_loading_sel = 0;
488     pData = (BYTE *)(pModule + 1);
489
490     /* Clear internal Wine flags in case they are set in the EXE file */
491
492     pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
493
494     /* Read the fast-load area */
495
496     if (ne_header.ne_flagsothers & NE_AFLAGS_FASTLOAD)
497     {
498         fastload_offset=ne_header.fastload_offset << ne_header.ne_align;
499         fastload_length=ne_header.fastload_length << ne_header.ne_align;
500         TRACE("Using fast-load area offset=%x len=%d\n",
501                         fastload_offset, fastload_length );
502         if ((fastload = HeapAlloc( GetProcessHeap(), 0, fastload_length )) != NULL)
503         {
504             _llseek( hFile, fastload_offset, SEEK_SET);
505             if (_lread(hFile, fastload, fastload_length) != fastload_length)
506             {
507                 HeapFree( GetProcessHeap(), 0, fastload );
508                 WARN("Error reading fast-load area!\n");
509                 fastload = NULL;
510             }
511         }
512     }
513
514     /* Get the segment table */
515
516     pModule->seg_table = pData - (BYTE *)pModule;
517     buffer = HeapAlloc( GetProcessHeap(), 0, ne_header.ne_cseg *
518                                       sizeof(struct ne_segment_table_entry_s));
519     if (buffer)
520     {
521         int i;
522         struct ne_segment_table_entry_s *pSeg;
523
524         if (!READ( mz_header.e_lfanew + ne_header.ne_segtab,
525              ne_header.ne_cseg * sizeof(struct ne_segment_table_entry_s),
526              buffer ))
527         {
528             HeapFree( GetProcessHeap(), 0, buffer );
529             if (fastload)
530                 HeapFree( GetProcessHeap(), 0, fastload );
531             GlobalFree16( hModule );
532             return (HMODULE16)11;  /* invalid exe */
533         }
534         pSeg = (struct ne_segment_table_entry_s *)buffer;
535         for (i = ne_header.ne_cseg; i > 0; i--, pSeg++)
536         {
537             memcpy( pData, pSeg, sizeof(*pSeg) );
538             pData += sizeof(SEGTABLEENTRY);
539         }
540         HeapFree( GetProcessHeap(), 0, buffer );
541     }
542     else
543     {
544         if (fastload)
545             HeapFree( GetProcessHeap(), 0, fastload );
546         GlobalFree16( hModule );
547         return (HMODULE16)11;  /* invalid exe */
548     }
549
550     /* Get the resource table */
551
552     if (ne_header.ne_rsrctab < ne_header.ne_restab)
553     {
554         pModule->res_table = pData - (BYTE *)pModule;
555         if (!READ(mz_header.e_lfanew + ne_header.ne_rsrctab,
556                   ne_header.ne_restab - ne_header.ne_rsrctab,
557                   pData )) 
558             return (HMODULE16)11;  /* invalid exe */
559         pData += ne_header.ne_restab - ne_header.ne_rsrctab;
560         NE_InitResourceHandler( hModule );
561     }
562     else pModule->res_table = 0;  /* No resource table */
563
564     /* Get the resident names table */
565
566     pModule->name_table = pData - (BYTE *)pModule;
567     if (!READ( mz_header.e_lfanew + ne_header.ne_restab,
568                ne_header.ne_modtab - ne_header.ne_restab,
569                pData ))
570     {
571         if (fastload)
572             HeapFree( GetProcessHeap(), 0, fastload );
573         GlobalFree16( hModule );
574         return (HMODULE16)11;  /* invalid exe */
575     }
576     pData += ne_header.ne_modtab - ne_header.ne_restab;
577
578     /* Get the module references table */
579
580     if (ne_header.ne_cmod > 0)
581     {
582         pModule->modref_table = pData - (BYTE *)pModule;
583         if (!READ( mz_header.e_lfanew + ne_header.ne_modtab,
584                   ne_header.ne_cmod * sizeof(WORD),
585                   pData ))
586         {
587             if (fastload)
588                 HeapFree( GetProcessHeap(), 0, fastload );
589             GlobalFree16( hModule );
590             return (HMODULE16)11;  /* invalid exe */
591         }
592         pData += ne_header.ne_cmod * sizeof(WORD);
593     }
594     else pModule->modref_table = 0;  /* No module references */
595
596     /* Get the imported names table */
597
598     pModule->import_table = pData - (BYTE *)pModule;
599     if (!READ( mz_header.e_lfanew + ne_header.ne_imptab, 
600                ne_header.ne_enttab - ne_header.ne_imptab,
601                pData ))
602     {
603         if (fastload)
604             HeapFree( GetProcessHeap(), 0, fastload );
605         GlobalFree16( hModule );
606         return (HMODULE16)11;  /* invalid exe */
607     }
608     pData += ne_header.ne_enttab - ne_header.ne_imptab;
609
610     /* Load entry table, convert it to the optimized version used by Windows */
611
612     if ((pTempEntryTable = HeapAlloc( GetProcessHeap(), 0, ne_header.ne_cbenttab)) != NULL)
613     {
614         BYTE nr_entries, type, *s;
615
616         TRACE("Converting entry table.\n");
617     pModule->entry_table = pData - (BYTE *)pModule;
618     if (!READ( mz_header.e_lfanew + ne_header.ne_enttab,
619                 ne_header.ne_cbenttab, pTempEntryTable ))
620     {
621             HeapFree( GetProcessHeap(), 0, pTempEntryTable );
622             if (fastload)
623                 HeapFree( GetProcessHeap(), 0, fastload );
624         GlobalFree16( hModule );
625         return (HMODULE16)11;  /* invalid exe */
626     }
627
628         s = pTempEntryTable;
629         TRACE("entry table: offs %04x, len %04x, entries %d\n", ne_header.ne_enttab, ne_header.ne_cbenttab, *s);
630
631         bundle = (ET_BUNDLE *)pData;
632         TRACE("first bundle: %p\n", bundle);
633         memset(bundle, 0, sizeof(ET_BUNDLE)); /* in case no entry table exists */
634         entry = (ET_ENTRY *)((BYTE *)bundle+6);
635
636         while ((nr_entries = *s++))
637         {
638             if ((type = *s++))
639             {
640                 bundle->last += nr_entries;
641                 if (type == 0xff)
642                 while (nr_entries--)
643                 {
644                     entry->type   = type;
645                     entry->flags  = *s++;
646                     s += 2;
647                     entry->segnum = *s++;
648                     entry->offs   = *(WORD *)s; s += 2;
649                     /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
650                     entry++;
651                 }
652                 else
653                 while (nr_entries--)
654                 {
655                     entry->type   = type;
656                     entry->flags  = *s++;
657                     entry->segnum = type;
658                     entry->offs   = *(WORD *)s; s += 2;
659                     /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
660                     entry++;
661                 }
662             }
663             else
664             {
665                 if (bundle->first == bundle->last)
666                 {
667                     bundle->first += nr_entries;
668                     bundle->last += nr_entries;
669                 }
670                 else
671                 {
672                     oldbundle = bundle;
673                     oldbundle->next = ((int)entry - (int)pModule);
674                     bundle = (ET_BUNDLE *)entry;
675                     TRACE("new bundle: %p\n", bundle);
676                     bundle->first = bundle->last =
677                         oldbundle->last + nr_entries;
678                     bundle->next = 0;
679                     (BYTE *)entry += sizeof(ET_BUNDLE);
680                 }
681             }
682         }
683         HeapFree( GetProcessHeap(), 0, pTempEntryTable );
684     }
685     else
686     {
687         if (fastload)
688             HeapFree( GetProcessHeap(), 0, fastload );
689         GlobalFree16( hModule );
690         return (HMODULE16)11;  /* invalid exe */
691     }
692
693     pData += ne_header.ne_cbenttab + sizeof(ET_BUNDLE) +
694              2 * (ne_header.ne_cbenttab - ne_header.ne_cmovent*6);
695
696     if ((DWORD)entry > (DWORD)pData)
697        ERR("converted entry table bigger than reserved space !!!\nentry: %p, pData: %p. Please report !\n", entry, pData);
698
699     /* Store the filename information */
700
701     pModule->fileinfo = pData - (BYTE *)pModule;
702     size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path) + 1;
703     ofs = (OFSTRUCT *)pData;
704     ofs->cBytes = size - 1;
705     ofs->fFixedDisk = 1;
706     strcpy( ofs->szPathName, path );
707     pData += size;
708
709     /* Free the fast-load area */
710
711 #undef READ
712     if (fastload)
713         HeapFree( GetProcessHeap(), 0, fastload );
714
715     /* Get the non-resident names table */
716
717     if (ne_header.ne_cbnrestab)
718     {
719         pModule->nrname_handle = GlobalAlloc16( 0, ne_header.ne_cbnrestab );
720         if (!pModule->nrname_handle)
721         {
722             GlobalFree16( hModule );
723             return (HMODULE16)11;  /* invalid exe */
724         }
725         FarSetOwner16( pModule->nrname_handle, hModule );
726         buffer = GlobalLock16( pModule->nrname_handle );
727         _llseek( hFile, ne_header.ne_nrestab, SEEK_SET );
728         if (_lread( hFile, buffer, ne_header.ne_cbnrestab )
729               != ne_header.ne_cbnrestab)
730         {
731             GlobalFree16( pModule->nrname_handle );
732             GlobalFree16( hModule );
733             return (HMODULE16)11;  /* invalid exe */
734         }
735     }
736     else pModule->nrname_handle = 0;
737
738     /* Allocate a segment for the implicitly-loaded DLLs */
739
740     if (pModule->modref_count)
741     {
742         pModule->dlls_to_init = GlobalAlloc16( GMEM_ZEROINIT,
743                                                (pModule->modref_count+1)*sizeof(HMODULE16) );
744         if (!pModule->dlls_to_init)
745         {
746             if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
747             GlobalFree16( hModule );
748             return (HMODULE16)11;  /* invalid exe */
749         }
750         FarSetOwner16( pModule->dlls_to_init, hModule );
751     }
752     else pModule->dlls_to_init = 0;
753
754     NE_RegisterModule( pModule );
755     SNOOP16_RegisterDLL(pModule,path);
756     return hModule;
757 }
758
759
760 /***********************************************************************
761  *           NE_LoadDLLs
762  *
763  * Load all DLLs implicitly linked to a module.
764  */
765 static BOOL NE_LoadDLLs( NE_MODULE *pModule )
766 {
767     int i;
768     WORD *pModRef = (WORD *)((char *)pModule + pModule->modref_table);
769     WORD *pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
770
771     for (i = 0; i < pModule->modref_count; i++, pModRef++)
772     {
773         char buffer[260], *p;
774         BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
775         memcpy( buffer, pstr + 1, *pstr );
776         *(buffer + *pstr) = 0; /* terminate it */
777
778         TRACE("Loading '%s'\n", buffer );
779         if (!(*pModRef = GetModuleHandle16( buffer )))
780         {
781             /* If the DLL is not loaded yet, load it and store */
782             /* its handle in the list of DLLs to initialize.   */
783             HMODULE16 hDLL;
784
785             /* Append .DLL to name if no extension present */
786             if (!(p = strrchr( buffer, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
787                     strcat( buffer, ".DLL" );
788
789             if ((hDLL = MODULE_LoadModule16( buffer, TRUE, TRUE )) < 32)
790             {
791                 /* FIXME: cleanup what was done */
792
793                 MESSAGE( "Could not load '%s' required by '%.*s', error=%d\n",
794                      buffer, *((BYTE*)pModule + pModule->name_table),
795                      (char *)pModule + pModule->name_table + 1, hDLL );
796                 return FALSE;
797             }
798             *pModRef = GetExePtr( hDLL );
799             *pDLLs++ = *pModRef;
800         }
801         else  /* Increment the reference count of the DLL */
802         {
803             NE_MODULE *pOldDLL;
804
805             pOldDLL = NE_GetPtr( *pModRef );
806             if (pOldDLL) pOldDLL->count++;
807         }
808     }
809     return TRUE;
810 }
811
812
813 /**********************************************************************
814  *          NE_DoLoadModule
815  *
816  * Load first instance of NE module from file.
817  *
818  * pModule must point to a module structure prepared by NE_LoadExeHeader.
819  * This routine must never be called twice on a module.
820  *
821  */
822 static HINSTANCE16 NE_DoLoadModule( NE_MODULE *pModule )
823 {
824     /* Allocate the segments for this module */
825
826     if (!NE_CreateAllSegments( pModule ))
827         return ERROR_NOT_ENOUGH_MEMORY; /* 8 */
828
829     /* Load the referenced DLLs */
830
831     if (!NE_LoadDLLs( pModule ))
832         return ERROR_FILE_NOT_FOUND; /* 2 */
833
834     /* Load the segments */
835
836     NE_LoadAllSegments( pModule );
837
838     /* Make sure the usage count is 1 on the first loading of  */
839     /* the module, even if it contains circular DLL references */
840
841     pModule->count = 1;
842
843     return NE_GetInstance( pModule );
844 }
845
846 /**********************************************************************
847  *          NE_LoadModule
848  *
849  * Load first instance of NE module. (Note: caller is responsible for 
850  * ensuring the module isn't already loaded!)
851  *
852  * If the module turns out to be an executable module, only a 
853  * handle to a module stub is returned; this needs to be initialized
854  * by calling NE_DoLoadModule later, in the context of the newly
855  * created process.
856  *
857  * If lib_only is TRUE, however, the module is perforce treated
858  * like a DLL module, even if it is an executable module.
859  * 
860  */
861 static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only )
862 {
863     NE_MODULE *pModule;
864     HMODULE16 hModule;
865     HINSTANCE16 hInstance;
866     HFILE16 hFile;
867     OFSTRUCT ofs;
868
869     /* Open file */
870     if ((hFile = OpenFile16( name, &ofs, OF_READ )) == HFILE_ERROR16)
871         return (HMODULE16)2;  /* File not found */
872
873     hModule = NE_LoadExeHeader( DosFileHandleToWin32Handle(hFile), ofs.szPathName );
874     _lclose16( hFile );
875     if (hModule < 32) return hModule;
876
877     pModule = NE_GetPtr( hModule );
878     if ( !pModule ) return hModule;
879
880     if ( !lib_only && !( pModule->flags & NE_FFLAGS_LIBMODULE ) )
881         return hModule;
882
883     hInstance = NE_DoLoadModule( pModule );
884     if ( hInstance < 32 )
885     {
886         /* cleanup ... */
887         NE_FreeModule( hModule, 0 );
888     }
889
890     return hInstance;
891 }
892
893
894 /**********************************************************************
895  *          MODULE_LoadModule16
896  *
897  * Load a NE module in the order of the loadorder specification.
898  * The caller is responsible that the module is not loaded already.
899  *
900  */
901 static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only )
902 {
903         HINSTANCE16 hinst = 2;
904         enum loadorder_type loadorder[LOADORDER_NTYPES];
905         int i;
906         const char *filetype = "";
907
908         MODULE_GetLoadOrder(loadorder, libname, FALSE);
909
910         for(i = 0; i < LOADORDER_NTYPES; i++)
911         {
912             if (loadorder[i] == LOADORDER_INVALID) break;
913
914                 switch(loadorder[i])
915                 {
916                 case LOADORDER_DLL:
917                         TRACE("Trying native dll '%s'\n", libname);
918                         hinst = NE_LoadModule(libname, lib_only);
919                         filetype = "native";
920                         break;
921
922                 case LOADORDER_BI:
923                         TRACE("Trying built-in '%s'\n", libname);
924                         hinst = BUILTIN_LoadModule(libname);
925                         filetype = "builtin";
926                         break;
927
928                 case LOADORDER_SO: /* This is not supported for NE modules */
929                 default:
930                         hinst = 2;
931                         break;
932                 }
933
934                 if(hinst >= 32)
935                 {
936                         if(!implicit)
937                         {
938                                 HMODULE16 hModule;
939                                 NE_MODULE *pModule;
940
941                                 hModule = GetModuleHandle16(libname);
942                                 if(!hModule)
943                                 {
944                                         ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get module handle. Filename too long ?\n",
945                                                 libname, hinst);
946                                         return 6;       /* ERROR_INVALID_HANDLE seems most appropriate */
947                                 }
948
949                                 pModule = NE_GetPtr(hModule);
950                                 if(!pModule)
951                                 {
952                                         ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get NE_MODULE pointer\n",
953                                                 libname, hinst);
954                                         return 6;       /* ERROR_INVALID_HANDLE seems most appropriate */
955                                 }
956
957                                 TRACE("Loaded module '%s' at 0x%04x.\n", libname, hinst);
958                                 if (!TRACE_ON(module))
959                                     TRACE_(loaddll)("Loaded module '%s' : %s\n", libname, filetype);
960
961                                 /*
962                                  * Call initialization routines for all loaded DLLs. Note that
963                                  * when we load implicitly linked DLLs this will be done by InitTask().
964                                  */
965                                 if(pModule->flags & NE_FFLAGS_LIBMODULE)
966                                 {
967                                         NE_InitializeDLLs(hModule);
968                                         NE_DllProcessAttach(hModule);
969                                 }
970                         }
971                         return hinst;
972                 }
973
974                 if(hinst != 2)
975                 {
976                         /* We quit searching when we get another error than 'File not found' */
977                         break;
978                 }
979         }
980         return hinst;   /* The last error that occured */
981 }
982
983
984 /**********************************************************************
985  *          NE_CreateThread
986  *
987  * Create the thread for a 16-bit module.
988  */
989 static HINSTANCE16 NE_CreateThread( NE_MODULE *pModule, WORD cmdShow, LPCSTR cmdline )
990 {
991     HANDLE hThread;
992     TDB *pTask;
993     HTASK16 hTask;
994     HINSTANCE16 instance = 0;
995
996     if (!(hTask = TASK_SpawnTask( pModule, cmdShow, cmdline + 1, *cmdline, &hThread )))
997         return 0;
998
999     /* Post event to start the task */
1000     PostEvent16( hTask );
1001
1002     /* Wait until we get the instance handle */
1003     do
1004     {
1005         DirectedYield16( hTask );
1006         if (!IsTask16( hTask ))  /* thread has died */
1007         {
1008             DWORD exit_code;
1009             WaitForSingleObject( hThread, INFINITE );
1010             GetExitCodeThread( hThread, &exit_code );
1011             CloseHandle( hThread );
1012             return exit_code;
1013         }
1014         if (!(pTask = TASK_GetPtr( hTask ))) break;
1015         instance = pTask->hInstance;
1016         GlobalUnlock16( hTask );
1017     } while (!instance);
1018
1019     CloseHandle( hThread );
1020     return instance;
1021 }
1022
1023
1024 /**********************************************************************
1025  *          LoadModule      (KERNEL.45)
1026  *          LoadModule16    (KERNEL32.@)
1027  */
1028 HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
1029 {
1030     BOOL lib_only = !paramBlock || (paramBlock == (LPVOID)-1);
1031     LOADPARAMS16 *params;
1032     HMODULE16 hModule;
1033     NE_MODULE *pModule;
1034     LPSTR cmdline;
1035     WORD cmdShow;
1036
1037     /* Load module */
1038
1039     if ( (hModule = NE_GetModuleByFilename(name) ) != 0 )
1040     {
1041         /* Special case: second instance of an already loaded NE module */
1042
1043         if ( !( pModule = NE_GetPtr( hModule ) ) ) return (HINSTANCE16)11;
1044         if ( pModule->module32 ) return (HINSTANCE16)21;
1045
1046         /* Increment refcount */
1047
1048         pModule->count++;
1049     }
1050     else
1051     {
1052         /* Main case: load first instance of NE module */
1053
1054         if ( (hModule = MODULE_LoadModule16( name, FALSE, lib_only )) < 32 )
1055             return hModule;
1056
1057         if ( !(pModule = NE_GetPtr( hModule )) )
1058             return (HINSTANCE16)11;
1059     }
1060
1061     /* If library module, we just retrieve the instance handle */
1062
1063     if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
1064         return NE_GetInstance( pModule );
1065
1066     /*
1067      *  At this point, we need to create a new process.
1068      *
1069      *  pModule points either to an already loaded module, whose refcount
1070      *  has already been incremented (to avoid having the module vanish 
1071      *  in the meantime), or else to a stub module which contains only header 
1072      *  information.
1073      */
1074     params = (LOADPARAMS16 *)paramBlock;
1075     cmdShow = ((WORD *)MapSL(params->showCmd))[1];
1076     cmdline = MapSL( params->cmdLine );
1077     return NE_CreateThread( pModule, cmdShow, cmdline );
1078 }
1079
1080
1081 /**********************************************************************
1082  *          NE_StartMain
1083  *
1084  * Start the main NE task.
1085  */
1086 HINSTANCE16 NE_StartMain( LPCSTR name, HANDLE file )
1087 {
1088     STARTUPINFOA info;
1089     HMODULE16 hModule;
1090     NE_MODULE *pModule;
1091     INT len;
1092     LPSTR pCmdLine, cmdline = GetCommandLineA();
1093
1094     if ((hModule = NE_LoadExeHeader( file, name )) < 32) return hModule;
1095
1096     if (!(pModule = NE_GetPtr( hModule ))) return (HINSTANCE16)11;
1097     if (pModule->flags & NE_FFLAGS_LIBMODULE)
1098     {
1099         MESSAGE( "%s is not a valid Win16 executable\n", name );
1100         ExitProcess( ERROR_BAD_EXE_FORMAT );
1101     }
1102
1103     while (*cmdline && *cmdline != ' ') cmdline++;
1104     if (*cmdline) cmdline++;
1105     len = strlen(cmdline);
1106     pCmdLine = HeapAlloc(GetProcessHeap(), 0, len+2);
1107     if (pCmdLine)
1108     {
1109         strcpy(pCmdLine+1, cmdline);
1110         *pCmdLine = len;
1111     }
1112     GetStartupInfoA( &info );
1113     if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = 1;
1114
1115     return NE_CreateThread( pModule, info.wShowWindow, pCmdLine );
1116 }
1117
1118
1119 /**********************************************************************
1120  *          NE_StartTask
1121  *
1122  * Startup code for a new 16-bit task.
1123  */
1124 DWORD NE_StartTask(void)
1125 {
1126     TDB *pTask = TASK_GetCurrent();
1127     NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
1128     HINSTANCE16 hInstance, hPrevInstance;
1129     SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
1130     WORD sp;
1131
1132     if ( pModule->count > 0 )
1133     {
1134         /* Second instance of an already loaded NE module */
1135         /* Note that the refcount was already incremented by the parent */
1136
1137         hPrevInstance = NE_GetInstance( pModule );
1138
1139         if ( pModule->dgroup )
1140             if ( NE_CreateSegment( pModule, pModule->dgroup ) )
1141                 NE_LoadSegment( pModule, pModule->dgroup );
1142
1143         hInstance = NE_GetInstance( pModule );
1144         TRACE("created second instance %04x[%d] of instance %04x.\n", hInstance, pModule->dgroup, hPrevInstance);
1145
1146     }
1147     else
1148     {
1149         /* Load first instance of NE module */
1150
1151         pModule->flags |= NE_FFLAGS_GUI;  /* FIXME: is this necessary? */
1152
1153         hInstance = NE_DoLoadModule( pModule );
1154         hPrevInstance = 0;
1155     }
1156
1157     if ( hInstance >= 32 )
1158     {
1159         CONTEXT86 context;
1160
1161         /* Enter instance handles into task struct */
1162
1163         pTask->hInstance = hInstance;
1164         pTask->hPrevInstance = hPrevInstance;
1165
1166         /* Free the previous stack selector */
1167         FreeSelector16( SELECTOROF(pTask->teb->cur_stack) );
1168
1169         /* Use DGROUP for 16-bit stack */
1170
1171         if (!(sp = pModule->sp))
1172             sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
1173         sp &= ~1;
1174         sp -= sizeof(STACK16FRAME);
1175         pTask->teb->cur_stack = MAKESEGPTR( GlobalHandleToSel16(hInstance), sp );
1176
1177         /* Registers at initialization must be:
1178          * ax   zero
1179          * bx   stack size in bytes
1180          * cx   heap size in bytes
1181          * si   previous app instance
1182          * di   current app instance
1183          * bp   zero
1184          * es   selector to the PSP
1185          * ds   dgroup of the application
1186          * ss   stack selector
1187          * sp   top of the stack
1188          */
1189         memset( &context, 0, sizeof(context) );
1190         context.SegCs  = GlobalHandleToSel16(pSegTable[pModule->cs - 1].hSeg);
1191         context.SegDs  = GlobalHandleToSel16(pTask->hInstance);
1192         context.SegEs  = pTask->hPDB;
1193         context.Eip    = pModule->ip;
1194         context.Ebx    = pModule->stack_size;
1195         context.Ecx    = pModule->heap_size;
1196         context.Edi    = pTask->hInstance;
1197         context.Esi    = pTask->hPrevInstance;
1198
1199         /* Now call 16-bit entry point */
1200
1201         TRACE("Starting main program: cs:ip=%04lx:%04lx ds=%04lx ss:sp=%04x:%04x\n",
1202               context.SegCs, context.Eip, context.SegDs,
1203               SELECTOROF(pTask->teb->cur_stack),
1204               OFFSETOF(pTask->teb->cur_stack) );
1205
1206         wine_call_to_16_regs_short( &context, 0 );
1207         ExitThread( LOWORD(context.Eax) );
1208     }
1209     return hInstance;  /* error code */
1210 }
1211
1212 /***********************************************************************
1213  *           LoadLibrary     (KERNEL.95)
1214  *           LoadLibrary16   (KERNEL32.35)
1215  */
1216 HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
1217 {
1218     return LoadModule16(libname, (LPVOID)-1 );
1219 }
1220
1221
1222 /**********************************************************************
1223  *          MODULE_CallWEP
1224  *
1225  * Call a DLL's WEP, allowing it to shut down.
1226  * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
1227  */
1228 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
1229 {
1230     FARPROC16 WEP = GetProcAddress16( hModule, "WEP" );
1231     if (!WEP) return FALSE;
1232     return NE_CallTo16_word_w( WEP, WEP_FREE_DLL );
1233 }
1234
1235
1236 /**********************************************************************
1237  *          NE_FreeModule
1238  *
1239  * Implementation of FreeModule16().
1240  */
1241 static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep )
1242 {
1243     HMODULE16 *hPrevModule;
1244     NE_MODULE *pModule;
1245     HMODULE16 *pModRef;
1246     int i;
1247
1248     if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
1249     hModule = pModule->self;
1250
1251     TRACE("%04x count %d\n", hModule, pModule->count );
1252
1253     if (((INT16)(--pModule->count)) > 0 ) return TRUE;
1254     else pModule->count = 0;
1255
1256     if (pModule->flags & NE_FFLAGS_BUILTIN)
1257         return FALSE;  /* Can't free built-in module */
1258
1259     if (call_wep && !(pModule->flags & NE_FFLAGS_WIN32))
1260     {
1261         if (pModule->flags & NE_FFLAGS_LIBMODULE)
1262         {
1263             MODULE_CallWEP( hModule );
1264
1265             /* Free the objects owned by the DLL module */
1266             TASK_CallTaskSignalProc( USIG16_DLL_UNLOAD, hModule );
1267             PROCESS_CallUserSignalProc( USIG_DLL_UNLOAD_WIN16, hModule );
1268         }
1269         else
1270             call_wep = FALSE;  /* We are freeing a task -> no more WEPs */
1271     }
1272     
1273
1274     /* Clear magic number just in case */
1275
1276     pModule->magic = pModule->self = 0;
1277
1278       /* Remove it from the linked list */
1279
1280     hPrevModule = &hFirstModule;
1281     while (*hPrevModule && (*hPrevModule != hModule))
1282     {
1283         hPrevModule = &(NE_GetPtr( *hPrevModule ))->next;
1284     }
1285     if (*hPrevModule) *hPrevModule = pModule->next;
1286
1287     /* Free the referenced modules */
1288
1289     pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
1290     for (i = 0; i < pModule->modref_count; i++, pModRef++)
1291     {
1292         NE_FreeModule( *pModRef, call_wep );
1293     }
1294
1295     /* Free the module storage */
1296
1297     GlobalFreeAll16( hModule );
1298
1299     /* Remove module from cache */
1300
1301     if (pCachedModule == pModule) pCachedModule = NULL;
1302     return TRUE;
1303 }
1304
1305
1306 /**********************************************************************
1307  *          FreeModule    (KERNEL.46)
1308  */
1309 BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
1310 {
1311     return NE_FreeModule( hModule, TRUE );
1312 }
1313
1314
1315 /***********************************************************************
1316  *           FreeLibrary     (KERNEL.96)
1317  *           FreeLibrary16   (KERNEL32.36)
1318  */
1319 void WINAPI FreeLibrary16( HINSTANCE16 handle )
1320 {
1321     TRACE("%04x\n", handle );
1322     FreeModule16( handle );
1323 }
1324
1325
1326 /**********************************************************************
1327  *          GetModuleName    (KERNEL.27)
1328  */
1329 BOOL16 WINAPI GetModuleName16( HINSTANCE16 hinst, LPSTR buf, INT16 count )
1330 {
1331     NE_MODULE *pModule;
1332     BYTE *p;
1333
1334     if (!(pModule = NE_GetPtr( hinst ))) return FALSE;
1335     p = (BYTE *)pModule + pModule->name_table;
1336     if (count > *p) count = *p + 1;
1337     if (count > 0)
1338     {
1339         memcpy( buf, p + 1, count - 1 );
1340         buf[count-1] = '\0';
1341     }
1342     return TRUE;
1343 }
1344
1345
1346 /**********************************************************************
1347  *          GetModuleUsage    (KERNEL.48)
1348  */
1349 INT16 WINAPI GetModuleUsage16( HINSTANCE16 hModule )
1350 {
1351     NE_MODULE *pModule = NE_GetPtr( hModule );
1352     return pModule ? pModule->count : 0;
1353 }
1354
1355
1356 /**********************************************************************
1357  *          GetExpWinVer    (KERNEL.167)
1358  */
1359 WORD WINAPI GetExpWinVer16( HMODULE16 hModule )
1360 {
1361     NE_MODULE *pModule = NE_GetPtr( hModule );
1362     if ( !pModule ) return 0;
1363
1364     /* 
1365      * For built-in modules, fake the expected version the module should
1366      * have according to the Windows version emulated by Wine
1367      */
1368     if ( !pModule->expected_version )
1369     {
1370         OSVERSIONINFOA versionInfo;
1371         versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
1372
1373         if ( GetVersionExA( &versionInfo ) )
1374             pModule->expected_version =   
1375                      (versionInfo.dwMajorVersion & 0xff) << 8
1376                    | (versionInfo.dwMinorVersion & 0xff);
1377     }
1378
1379     return pModule->expected_version;
1380 }
1381
1382
1383 /**********************************************************************
1384  *          GetModuleFileName      (KERNEL.49)
1385  *          GetModuleFileName16    (KERNEL32.@)
1386  *
1387  * Comment: see GetModuleFileNameA
1388  *
1389  * Even if invoked by second instance of a program,
1390  * it still returns path of first one.
1391  */
1392 INT16 WINAPI GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName,
1393                                   INT16 nSize )
1394 {
1395     NE_MODULE *pModule;
1396
1397     /* Win95 does not query hModule if set to 0 !
1398      * Is this wrong or maybe Win3.1 only ? */
1399     if (!hModule) hModule = GetCurrentTask();
1400
1401     if (!(pModule = NE_GetPtr( hModule ))) return 0;
1402     lstrcpynA( lpFileName, NE_MODULE_NAME(pModule), nSize );
1403     if (pModule->expected_version >= 0x400)
1404         GetLongPathNameA(NE_MODULE_NAME(pModule), lpFileName, nSize);
1405     TRACE("%04x -> '%s'\n", hModule, lpFileName );
1406     return strlen(lpFileName);
1407 }
1408
1409
1410 /**********************************************************************
1411  *          GetModuleHandle    (KERNEL.47)
1412  *
1413  * Find a module from a module name.
1414  *
1415  * NOTE: The current implementation works the same way the Windows 95 one
1416  *       does. Do not try to 'fix' it, fix the callers.
1417  *       + It does not do ANY extension handling (except that strange .EXE bit)!
1418  *       + It does not care about paths, just about basenames. (same as Windows)
1419  *
1420  * RETURNS
1421  *   LOWORD:
1422  *      the win16 module handle if found
1423  *      0 if not
1424  *   HIWORD (undocumented, see "Undocumented Windows", chapter 5):
1425  *      Always hFirstModule
1426  */
1427 DWORD WINAPI WIN16_GetModuleHandle( SEGPTR name )
1428 {
1429     if (HIWORD(name) == 0)
1430         return MAKELONG(GetExePtr( (HINSTANCE16)name), hFirstModule );
1431     return MAKELONG(GetModuleHandle16( MapSL(name)), hFirstModule );
1432 }
1433
1434 /***********************************************************************
1435  *          GetModuleHandle16 (KERNEL32.@)
1436  */
1437 HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
1438 {
1439     HMODULE16   hModule = hFirstModule;
1440     LPSTR       s;
1441     BYTE        len, *name_table;
1442     char        tmpstr[MAX_PATH];
1443     NE_MODULE *pModule;
1444
1445     TRACE("(%s)\n", name);
1446
1447     if (!HIWORD(name))
1448         return GetExePtr(LOWORD(name));
1449
1450     len = strlen(name);
1451     if (!len)
1452         return 0;
1453
1454     lstrcpynA(tmpstr, name, sizeof(tmpstr));
1455
1456     /* If 'name' matches exactly the module name of a module:
1457      * Return its handle.
1458      */
1459     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1460     {
1461         pModule = NE_GetPtr( hModule );
1462         if (!pModule) break;
1463         if (pModule->flags & NE_FFLAGS_WIN32) continue;
1464
1465         name_table = (BYTE *)pModule + pModule->name_table;
1466         if ((*name_table == len) && !strncmp(name, name_table+1, len))
1467             return hModule;
1468     }
1469
1470     /* If uppercased 'name' matches exactly the module name of a module:
1471      * Return its handle
1472      */
1473     for (s = tmpstr; *s; s++) *s = FILE_toupper(*s);
1474
1475     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1476     {
1477         pModule = NE_GetPtr( hModule );
1478         if (!pModule) break;
1479         if (pModule->flags & NE_FFLAGS_WIN32) continue;
1480
1481         name_table = (BYTE *)pModule + pModule->name_table;
1482         /* FIXME: the strncasecmp is WRONG. It should not be case insensitive,
1483          * but case sensitive! (Unfortunately Winword 6 and subdlls have
1484          * lowercased module names, but try to load uppercase DLLs, so this
1485          * 'i' compare is just a quickfix until the loader handles that
1486          * correctly. -MM 990705
1487          */
1488         if ((*name_table == len) && !FILE_strncasecmp(tmpstr, name_table+1, len))
1489             return hModule;
1490     }
1491
1492     /* If the base filename of 'name' matches the base filename of the module
1493      * filename of some module (case-insensitive compare):
1494      * Return its handle.
1495      */
1496
1497     /* basename: search backwards in passed name to \ / or : */
1498     s = tmpstr + strlen(tmpstr);
1499     while (s > tmpstr)
1500     {
1501         if (s[-1]=='/' || s[-1]=='\\' || s[-1]==':')
1502                 break;
1503         s--;
1504     }
1505
1506     /* search this in loaded filename list */
1507     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1508     {
1509         char            *loadedfn;
1510         OFSTRUCT        *ofs;
1511
1512         pModule = NE_GetPtr( hModule );
1513         if (!pModule) break;
1514         if (!pModule->fileinfo) continue;
1515         if (pModule->flags & NE_FFLAGS_WIN32) continue;
1516
1517         ofs = (OFSTRUCT*)((BYTE *)pModule + pModule->fileinfo);
1518         loadedfn = ((char*)ofs->szPathName) + strlen(ofs->szPathName);
1519         /* basename: search backwards in pathname to \ / or : */
1520         while (loadedfn > (char*)ofs->szPathName)
1521         {
1522             if (loadedfn[-1]=='/' || loadedfn[-1]=='\\' || loadedfn[-1]==':')
1523                     break;
1524             loadedfn--;
1525         }
1526         /* case insensitive compare ... */
1527         if (!FILE_strcasecmp(loadedfn, s))
1528             return hModule;
1529     }
1530
1531     /* If the extension of 'name' is '.EXE' and the base filename of 'name'
1532      * matches the base filename of the module filename of some 32-bit module:
1533      * Return the corresponding 16-bit dummy module handle. 
1534      */
1535     if (len >= 4 && !FILE_strcasecmp(name+len-4, ".EXE"))
1536     {
1537         HMODULE hModule = GetModuleHandleA( name );
1538         if ( hModule )
1539             return MapHModuleLS( hModule );
1540     }
1541
1542     if (!strcmp(tmpstr,"MSDOS"))
1543         return 1;
1544
1545     if (!strcmp(tmpstr,"TIMER"))
1546     {
1547         FIXME("Eh... Should return caller's code segment, expect crash\n");
1548         return 0;
1549     }
1550
1551     return 0;
1552 }
1553
1554 /**********************************************************************
1555  *          NE_GetModuleByFilename
1556  */
1557 static HMODULE16 NE_GetModuleByFilename( LPCSTR name )
1558 {
1559     HMODULE16   hModule;
1560     LPSTR       s, p;
1561     BYTE        len, *name_table;
1562     char        tmpstr[MAX_PATH];
1563     NE_MODULE *pModule;
1564
1565     lstrcpynA(tmpstr, name, sizeof(tmpstr));
1566
1567     /* If the base filename of 'name' matches the base filename of the module
1568      * filename of some module (case-insensitive compare):
1569      * Return its handle.
1570      */
1571
1572     /* basename: search backwards in passed name to \ / or : */
1573     s = tmpstr + strlen(tmpstr);
1574     while (s > tmpstr)
1575     {
1576         if (s[-1]=='/' || s[-1]=='\\' || s[-1]==':')
1577                 break;
1578         s--;
1579     }
1580
1581     /* search this in loaded filename list */
1582     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1583     {
1584         char            *loadedfn;
1585         OFSTRUCT        *ofs;
1586
1587         pModule = NE_GetPtr( hModule );
1588         if (!pModule) break;
1589         if (!pModule->fileinfo) continue;
1590         if (pModule->flags & NE_FFLAGS_WIN32) continue;
1591
1592         ofs = (OFSTRUCT*)((BYTE *)pModule + pModule->fileinfo);
1593         loadedfn = ((char*)ofs->szPathName) + strlen(ofs->szPathName);
1594         /* basename: search backwards in pathname to \ / or : */
1595         while (loadedfn > (char*)ofs->szPathName)
1596         {
1597             if (loadedfn[-1]=='/' || loadedfn[-1]=='\\' || loadedfn[-1]==':')
1598                     break;
1599             loadedfn--;
1600         }
1601         /* case insensitive compare ... */
1602         if (!FILE_strcasecmp(loadedfn, s))
1603             return hModule;
1604     }
1605     /* If basename (without ext) matches the module name of a module:
1606      * Return its handle.
1607      */
1608
1609     if ( (p = strrchr( s, '.' )) != NULL ) *p = '\0';
1610     len = strlen(s);
1611
1612     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1613     {
1614         pModule = NE_GetPtr( hModule );
1615         if (!pModule) break;
1616         if (pModule->flags & NE_FFLAGS_WIN32) continue;
1617
1618         name_table = (BYTE *)pModule + pModule->name_table;
1619         if ((*name_table == len) && !FILE_strncasecmp(s, name_table+1, len))
1620             return hModule;
1621     }
1622
1623     return 0;
1624 }
1625
1626 /**********************************************************************
1627  *          ModuleFirst    (TOOLHELP.59)
1628  */
1629 BOOL16 WINAPI ModuleFirst16( MODULEENTRY *lpme )
1630 {
1631     lpme->wNext = hFirstModule;
1632     return ModuleNext16( lpme );
1633 }
1634
1635
1636 /**********************************************************************
1637  *          ModuleNext    (TOOLHELP.60)
1638  */
1639 BOOL16 WINAPI ModuleNext16( MODULEENTRY *lpme )
1640 {
1641     NE_MODULE *pModule;
1642     char *name;
1643
1644     if (!lpme->wNext) return FALSE;
1645     if (!(pModule = NE_GetPtr( lpme->wNext ))) return FALSE;
1646     name = (char *)pModule + pModule->name_table;
1647     memcpy( lpme->szModule, name + 1, min(*name, MAX_MODULE_NAME) );
1648     lpme->szModule[min(*name, MAX_MODULE_NAME)] = '\0';
1649     lpme->hModule = lpme->wNext;
1650     lpme->wcUsage = pModule->count;
1651     lstrcpynA( lpme->szExePath, NE_MODULE_NAME(pModule), sizeof(lpme->szExePath) );
1652     lpme->wNext = pModule->next;
1653     return TRUE;
1654 }
1655
1656
1657 /**********************************************************************
1658  *          ModuleFindName    (TOOLHELP.61)
1659  */
1660 BOOL16 WINAPI ModuleFindName16( MODULEENTRY *lpme, LPCSTR name )
1661 {
1662     lpme->wNext = GetModuleHandle16( name );
1663     return ModuleNext16( lpme );
1664 }
1665
1666
1667 /**********************************************************************
1668  *          ModuleFindHandle    (TOOLHELP.62)
1669  */
1670 BOOL16 WINAPI ModuleFindHandle16( MODULEENTRY *lpme, HMODULE16 hModule )
1671 {
1672     hModule = GetExePtr( hModule );
1673     lpme->wNext = hModule;
1674     return ModuleNext16( lpme );
1675 }
1676
1677
1678 /***************************************************************************
1679  *          IsRomModule    (KERNEL.323)
1680  */
1681 BOOL16 WINAPI IsRomModule16( HMODULE16 unused )
1682 {
1683     return FALSE;
1684 }
1685
1686 /***************************************************************************
1687  *          IsRomFile    (KERNEL.326)
1688  */
1689 BOOL16 WINAPI IsRomFile16( HFILE16 unused )
1690 {
1691     return FALSE;
1692 }
1693
1694 /***************************************************************************
1695  *              MapHModuleLS                    (KERNEL32.@)
1696  */
1697 HMODULE16 WINAPI MapHModuleLS(HMODULE hmod) {
1698         NE_MODULE       *pModule;
1699
1700         if (!hmod)
1701                 return TASK_GetCurrent()->hInstance;
1702         if (!HIWORD(hmod))
1703                 return hmod; /* we already have a 16 bit module handle */
1704         pModule = (NE_MODULE*)GlobalLock16(hFirstModule);
1705         while (pModule)  {
1706                 if (pModule->module32 == hmod)
1707                         return pModule->self;
1708                 pModule = (NE_MODULE*)GlobalLock16(pModule->next);
1709         }
1710         return 0;
1711 }
1712
1713 /***************************************************************************
1714  *              MapHModuleSL                    (KERNEL32.@)
1715  */
1716 HMODULE WINAPI MapHModuleSL(HMODULE16 hmod) {
1717         NE_MODULE       *pModule;
1718
1719         if (!hmod) {
1720                 TDB *pTask = TASK_GetCurrent();
1721                 hmod = pTask->hModule;
1722         }
1723         pModule = (NE_MODULE*)GlobalLock16(hmod);
1724         if (    (pModule->magic!=IMAGE_OS2_SIGNATURE)   ||
1725                 !(pModule->flags & NE_FFLAGS_WIN32)
1726         )
1727                 return 0;
1728         return pModule->module32;
1729 }
1730
1731 /***************************************************************************
1732  *              MapHInstLS                      (KERNEL32.@)
1733  *              MapHInstLS                      (KERNEL.472)
1734  */
1735 void WINAPI MapHInstLS( CONTEXT86 *context )
1736 {
1737     context->Eax = MapHModuleLS(context->Eax);
1738 }
1739
1740 /***************************************************************************
1741  *              MapHInstSL                      (KERNEL32.@)
1742  *              MapHInstSL                      (KERNEL.473)
1743  */
1744 void WINAPI MapHInstSL( CONTEXT86 *context )
1745 {
1746     context->Eax = MapHModuleSL(context->Eax);
1747 }
1748
1749 /***************************************************************************
1750  *              MapHInstLS_PN                   (KERNEL32.@)
1751  */
1752 void WINAPI MapHInstLS_PN( CONTEXT86 *context )
1753 {
1754     if (context->Eax) context->Eax = MapHModuleLS(context->Eax);
1755 }
1756
1757 /***************************************************************************
1758  *              MapHInstSL_PN                   (KERNEL32.@)
1759  */
1760 void WINAPI MapHInstSL_PN( CONTEXT86 *context )
1761 {
1762     if (context->Eax) context->Eax = MapHModuleSL(context->Eax);
1763 }
1764