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