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