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