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