Release 960805
[wine] / loader / module.c
1 /*
2  * Modules
3  *
4  * Copyright 1995 Alexandre Julliard
5  */
6
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <unistd.h>
13 #include "windows.h"
14 #include "class.h"
15 #include "dos_fs.h"
16 #include "file.h"
17 #include "global.h"
18 #include "hook.h"
19 #include "ldt.h"
20 #include "module.h"
21 #include "neexe.h"
22 #include "registers.h"
23 #include "stackframe.h"
24 #include "task.h"
25 #include "toolhelp.h"
26 #include "stddebug.h"
27 #include "debug.h"
28 #include "callback.h"
29
30 extern HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
31
32 static HMODULE16 hFirstModule = 0;
33 static HMODULE16 hCachedModule = 0;  /* Module cached by MODULE_OpenFile */
34
35 #ifndef WINELIB
36 static HANDLE hInitialStack32 = 0;
37 #endif
38
39
40 /***********************************************************************
41  *           MODULE_GetPtr
42  */
43 NE_MODULE *MODULE_GetPtr( HMODULE16 hModule )
44 {
45     NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule );
46     if (!pModule || (pModule->magic != NE_SIGNATURE) ||
47         (pModule->self != hModule)) return NULL;
48     return pModule;
49 }
50
51
52 /***********************************************************************
53  *           MODULE_DumpModule
54  */
55 void MODULE_DumpModule( HMODULE16 hmodule )
56 {
57     int i, ordinal;
58     SEGTABLEENTRY *pSeg;
59     BYTE *pstr;
60     WORD *pword;
61     NE_MODULE *pModule;
62
63     if (!(pModule = MODULE_GetPtr( hmodule )))
64     {
65         fprintf( stderr, "**** %04x is not a module handle\n", hmodule );
66         return;
67     }
68
69       /* Dump the module info */
70
71     printf( "Module %04x:\n", hmodule );
72     printf( "count=%d flags=%04x heap=%d stack=%d\n",
73             pModule->count, pModule->flags,
74             pModule->heap_size, pModule->stack_size );
75     printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
76            pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
77            pModule->seg_count, pModule->modref_count );
78     printf( "os_flags=%d swap_area=%d version=%04x\n",
79             pModule->os_flags, pModule->min_swap_area,
80             pModule->expected_version );
81     if (pModule->flags & NE_FFLAGS_WIN32)
82         printf( "PE module=%08x\n", (unsigned int)pModule->pe_module );
83
84       /* Dump the file info */
85
86     printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
87
88       /* Dump the segment table */
89
90     printf( "\nSegment table:\n" );
91     pSeg = NE_SEG_TABLE( pModule );
92     for (i = 0; i < pModule->seg_count; i++, pSeg++)
93         printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
94                 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
95                 pSeg->minsize, pSeg->selector );
96
97       /* Dump the resource table */
98
99     printf( "\nResource table:\n" );
100     if (pModule->res_table)
101     {
102         pword = (WORD *)((BYTE *)pModule + pModule->res_table);
103         printf( "Alignment: %d\n", *pword++ );
104         while (*pword)
105         {
106             struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
107             struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
108             printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
109             for (i = 0; i < ptr->count; i++, pname++)
110                 printf( "offset=%d len=%d id=%04x\n",
111                        pname->offset, pname->length, pname->id );
112             pword = (WORD *)pname;
113         }
114     }
115     else printf( "None\n" );
116
117       /* Dump the resident name table */
118
119     printf( "\nResident-name table:\n" );
120     pstr = (char *)pModule + pModule->name_table;
121     while (*pstr)
122     {
123         printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
124                 *(WORD *)(pstr + *pstr + 1) );
125         pstr += *pstr + 1 + sizeof(WORD);
126     }
127
128       /* Dump the module reference table */
129
130     printf( "\nModule ref table:\n" );
131     if (pModule->modref_table)
132     {
133         pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
134         for (i = 0; i < pModule->modref_count; i++, pword++)
135         {
136             printf( "%d: %04x -> '%s'\n", i, *pword,
137                     MODULE_GetModuleName(*pword));
138         }
139     }
140     else printf( "None\n" );
141
142       /* Dump the entry table */
143
144     printf( "\nEntry table:\n" );
145     pstr = (char *)pModule + pModule->entry_table;
146     ordinal = 1;
147     while (*pstr)
148     {
149         printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
150         if (!pstr[1])
151         {
152             ordinal += *pstr;
153             pstr += 2;
154         }
155         else if ((BYTE)pstr[1] == 0xff)  /* moveable */
156         {
157             struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
158             for (i = 0; i < *pstr; i++, pe++)
159                 printf( "%d: %02x:%04x (moveable)\n",
160                         ordinal++, pe->seg_number, pe->offset );
161             pstr = (char *)pe;
162         }
163         else  /* fixed */
164         {
165             struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
166             for (i = 0; i < *pstr; i++, pe++)
167                 printf( "%d: %04x (fixed)\n",
168                         ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
169             pstr = (char *)pe;
170         }
171     }
172
173     /* Dump the non-resident names table */
174
175     printf( "\nNon-resident names table:\n" );
176     if (pModule->nrname_handle)
177     {
178         pstr = (char *)GlobalLock16( pModule->nrname_handle );
179         while (*pstr)
180         {
181             printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
182                    *(WORD *)(pstr + *pstr + 1) );
183             pstr += *pstr + 1 + sizeof(WORD);
184         }
185     }
186     printf( "\n" );
187 }
188
189
190 /***********************************************************************
191  *           MODULE_WalkModules
192  *
193  * Walk the module list and print the modules.
194  */
195 void MODULE_WalkModules(void)
196 {
197     HMODULE16 hModule = hFirstModule;
198     fprintf( stderr, "Module Flags Name\n" );
199     while (hModule)
200     {
201         NE_MODULE *pModule = MODULE_GetPtr( hModule );
202         if (!pModule)
203         {
204             fprintf( stderr, "**** Bad module %04x in list\n", hModule );
205             return;
206         }
207         fprintf( stderr, " %04x  %04x  %.*s\n", hModule, pModule->flags,
208                  *((char *)pModule + pModule->name_table),
209                  (char *)pModule + pModule->name_table + 1 );
210         hModule = pModule->next;
211     }
212 }
213
214
215 /***********************************************************************
216  *           MODULE_OpenFile
217  */
218 int MODULE_OpenFile( HMODULE16 hModule )
219 {
220     NE_MODULE *pModule;
221     char *name;
222     const char *unixName;
223
224     static int cachedfd = -1;
225
226     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
227     dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
228                     hModule, hCachedModule, cachedfd );
229     if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
230     if (hCachedModule == hModule) return cachedfd;
231     close( cachedfd );
232     hCachedModule = hModule;
233     name = NE_MODULE_NAME( pModule );
234     if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) ||
235         (cachedfd = open( unixName, O_RDONLY )) == -1)
236         fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
237                  name, hModule );
238     dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
239                     name, cachedfd );
240     return cachedfd;
241 }
242
243
244 /***********************************************************************
245  *           MODULE_Ne2MemFlags
246  *
247  * This function translates NE segment flags to GlobalAlloc flags
248  */
249 static WORD MODULE_Ne2MemFlags(WORD flags)
250
251     WORD memflags = 0;
252 #if 0
253     if (flags & NE_SEGFLAGS_DISCARDABLE) 
254       memflags |= GMEM_DISCARDABLE;
255     if (flags & NE_SEGFLAGS_MOVEABLE || 
256         ( ! (flags & NE_SEGFLAGS_DATA) &&
257           ! (flags & NE_SEGFLAGS_LOADED) &&
258           ! (flags & NE_SEGFLAGS_ALLOCATED)
259          )
260         )
261       memflags |= GMEM_MOVEABLE;
262     memflags |= GMEM_ZEROINIT;
263 #else
264     memflags = GMEM_ZEROINIT | GMEM_FIXED;
265     return memflags;
266 #endif
267 }
268
269 /***********************************************************************
270  *           MODULE_AllocateSegment (WPROCS.26)
271  */
272
273 DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
274 {
275     WORD size = wSize << wElem;
276     HANDLE16 hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
277     return MAKELONG( hMem, GlobalHandleToSel(hMem) );
278 }
279
280 /***********************************************************************
281  *           MODULE_CreateSegments
282  */
283 #ifndef WINELIB32
284 static BOOL MODULE_CreateSegments( HMODULE16 hModule )
285 {
286     SEGTABLEENTRY *pSegment;
287     NE_MODULE *pModule;
288     int i, minsize;
289
290     if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
291     pSegment = NE_SEG_TABLE( pModule );
292     for (i = 1; i <= pModule->seg_count; i++, pSegment++)
293     {
294         minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
295         if (i == pModule->ss) minsize += pModule->stack_size;
296         /* The DGROUP is allocated by MODULE_CreateInstance */
297         if (i == pModule->dgroup) continue;
298         pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
299                                       minsize, hModule,
300                                       !(pSegment->flags & NE_SEGFLAGS_DATA),
301                                       FALSE,
302                             FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
303         if (!pSegment->selector) return FALSE;
304     }
305
306     pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
307                             (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
308     return TRUE;
309 }
310 #endif
311
312
313 /***********************************************************************
314  *           MODULE_GetInstance
315  */
316 HINSTANCE16 MODULE_GetInstance( HMODULE16 hModule )
317 {
318     SEGTABLEENTRY *pSegment;
319     NE_MODULE *pModule;
320     
321     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
322     if (pModule->dgroup == 0) return hModule;
323
324     pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
325     
326     return pSegment->selector;
327 }
328
329
330 /***********************************************************************
331  *           MODULE_CreateInstance
332  */
333 HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
334 {
335     SEGTABLEENTRY *pSegment;
336     NE_MODULE *pModule;
337     int minsize;
338     HINSTANCE hNewInstance, hPrevInstance;
339
340     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
341     if (pModule->dgroup == 0) return hModule;
342
343     pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
344     hPrevInstance = pSegment->selector;
345
346       /* if it's a library, create a new instance only the first time */
347     if (hPrevInstance)
348     {
349         if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
350         if (params == (LOADPARAMS*)-1) return hPrevInstance;
351     }
352
353     minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
354     if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
355     minsize += pModule->heap_size;
356     hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
357                                  minsize, hModule, FALSE, FALSE, FALSE );
358     if (!hNewInstance) return 0;
359     pSegment->selector = hNewInstance;
360     return hNewInstance;
361 }
362
363
364 /***********************************************************************
365  *           MODULE_CreateDummyModule
366  *
367  * Create a dummy NE module for Win32 or Winelib.
368  */
369 HMODULE16 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
370 {
371     HMODULE16 hModule;
372     NE_MODULE *pModule;
373     SEGTABLEENTRY *pSegment;
374     char *pStr;
375
376     INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
377                     + strlen(ofs->szPathName) + 1;
378     INT32 size = sizeof(NE_MODULE) +
379                  /* loaded file info */
380                  of_size +
381                  /* segment table: DS,CS */
382                  2 * sizeof(SEGTABLEENTRY) +
383                  /* name table */
384                  9 +
385                  /* several empty tables */
386                  8;
387
388     hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
389     if (!hModule) return (HMODULE16)11;  /* invalid exe */
390
391     FarSetOwner( hModule, hModule );
392     pModule = (NE_MODULE *)GlobalLock16( hModule );
393
394     /* Set all used entries */
395     pModule->magic            = NE_SIGNATURE;
396     pModule->count            = 1;
397     pModule->next             = 0;
398     pModule->flags            = 0;
399     pModule->dgroup           = 1;
400     pModule->ss               = 1;
401     pModule->cs               = 2;
402     pModule->heap_size        = 0xe000;
403     pModule->stack_size       = 0x1000;
404     pModule->seg_count        = 2;
405     pModule->modref_count     = 0;
406     pModule->nrname_size      = 0;
407     pModule->fileinfo         = sizeof(NE_MODULE);
408     pModule->os_flags         = NE_OSFLAGS_WINDOWS;
409     pModule->expected_version = 0x030a;
410     pModule->self             = hModule;
411
412     /* Set loaded file information */
413     memcpy( pModule + 1, ofs, of_size );
414     ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
415
416     pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
417     pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
418     /* Data segment */
419     pSegment->size    = 0;
420     pSegment->flags   = NE_SEGFLAGS_DATA;
421     pSegment->minsize = 0x1000;
422     pSegment++;
423     /* Code segment */
424     pSegment->flags   = 0;
425     pSegment++;
426
427     /* Module name */
428     pStr = (char *)pSegment;
429     pModule->name_table = (int)pStr - (int)pModule;
430     strcpy( pStr, "\x08W32SXXXX" );
431     pStr += 9;
432
433     /* All tables zero terminated */
434     pModule->res_table = pModule->import_table = pModule->entry_table =
435                 (int)pStr - (int)pModule;
436
437     MODULE_RegisterModule( pModule );
438     return hModule;
439 }
440
441
442 /***********************************************************************
443  *           MODULE_LoadExeHeader
444  */
445 static HMODULE16 MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs )
446 {
447     struct mz_header_s mz_header;
448     struct ne_header_s ne_header;
449     int size;
450     HMODULE16 hModule;
451     NE_MODULE *pModule;
452     BYTE *pData;
453     char *buffer, *fastload = NULL;
454     int fastload_offset = 0, fastload_length = 0;
455
456   /* Read a block from either the file or the fast-load area. */
457 #define READ(offset,size,buffer) \
458        ((fastload && ((offset) >= fastload_offset) && \
459          ((offset)+(size) <= fastload_offset+fastload_length)) ? \
460         (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
461         (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
462          FILE_Read( hFile, (buffer), (size) ) == (size)))
463
464     _llseek( hFile, 0, SEEK_SET );
465     if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
466         (mz_header.mz_magic != MZ_SIGNATURE))
467         return (HMODULE16)11;  /* invalid exe */
468
469     _llseek( hFile, mz_header.ne_offset, SEEK_SET );
470     if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
471         return (HMODULE16)11;  /* invalid exe */
472
473     if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE16)21;  /* win32 exe */
474     if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE16)11;  /* invalid exe */
475
476     /* We now have a valid NE header */
477
478     size = sizeof(NE_MODULE) +
479              /* loaded file info */
480            sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
481              /* segment table */
482            ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
483              /* resource table */
484            ne_header.rname_tab_offset - ne_header.resource_tab_offset +
485              /* resident names table */
486            ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
487              /* module ref table */
488            ne_header.n_mod_ref_tab * sizeof(WORD) + 
489              /* imported names table */
490            ne_header.entry_tab_offset - ne_header.iname_tab_offset +
491              /* entry table length */
492            ne_header.entry_tab_length;
493
494     hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
495     if (!hModule) return (HMODULE16)11;  /* invalid exe */
496     FarSetOwner( hModule, hModule );
497     pModule = (NE_MODULE *)GlobalLock16( hModule );
498     memcpy( pModule, &ne_header, sizeof(ne_header) );
499     pModule->count = 0;
500     pModule->pe_module = NULL;
501     pModule->self = hModule;
502     pModule->self_loading_sel = 0;
503     pData = (BYTE *)(pModule + 1);
504
505     /* Clear internal Wine flags in case they are set in the EXE file */
506
507     pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
508
509     /* Read the fast-load area */
510
511     if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
512     {
513         fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
514         fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
515         dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
516                         fastload_offset, fastload_length );
517         if ((fastload = (char *)malloc( fastload_length )) != NULL)
518         {
519             _llseek( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET );
520             if (FILE_Read( hFile, fastload, fastload_length ) != fastload_length)
521             {
522                 free( fastload );
523                 fastload = NULL;
524             }
525         }
526     }
527
528     /* Store the filename information */
529
530     pModule->fileinfo = (int)pData - (int)pModule;
531     size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
532     memcpy( pData, ofs, size );
533     ((OFSTRUCT *)pData)->cBytes = size - 1;
534     pData += size;
535
536     /* Get the segment table */
537
538     pModule->seg_table = (int)pData - (int)pModule;
539     buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
540     if (buffer)
541     {
542         int i;
543         struct ne_segment_table_entry_s *pSeg;
544
545         if (!READ( ne_header.segment_tab_offset,
546              ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
547              buffer )) return (HMODULE16)11;  /* invalid exe */
548         pSeg = (struct ne_segment_table_entry_s *)buffer;
549         for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
550         {
551             memcpy( pData, pSeg, sizeof(*pSeg) );
552             pData += sizeof(SEGTABLEENTRY);
553         }
554         free( buffer );
555     }
556     else
557     {
558         GlobalFree16( hModule );
559         return (HMODULE16)11;  /* invalid exe */
560     }
561
562     /* Get the resource table */
563
564     if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
565     {
566         pModule->res_table = (int)pData - (int)pModule;
567         if (!READ(ne_header.resource_tab_offset,
568                   ne_header.rname_tab_offset - ne_header.resource_tab_offset,
569                   pData )) return (HMODULE16)11;  /* invalid exe */
570         pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
571     }
572     else pModule->res_table = 0;  /* No resource table */
573
574     /* Get the resident names table */
575
576     pModule->name_table = (int)pData - (int)pModule;
577     if (!READ( ne_header.rname_tab_offset,
578                ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
579                pData ))
580     {
581         GlobalFree16( hModule );
582         return (HMODULE16)11;  /* invalid exe */
583     }
584     pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
585
586     /* Get the module references table */
587
588     if (ne_header.n_mod_ref_tab > 0)
589     {
590         pModule->modref_table = (int)pData - (int)pModule;
591         if (!READ( ne_header.moduleref_tab_offset,
592                   ne_header.n_mod_ref_tab * sizeof(WORD),
593                   pData )) return (HMODULE16)11;  /* invalid exe */
594         pData += ne_header.n_mod_ref_tab * sizeof(WORD);
595     }
596     else pModule->modref_table = 0;  /* No module references */
597
598     /* Get the imported names table */
599
600     pModule->import_table = (int)pData - (int)pModule;
601     if (!READ( ne_header.iname_tab_offset, 
602                ne_header.entry_tab_offset - ne_header.iname_tab_offset,
603                pData ))
604     {
605         GlobalFree16( hModule );
606         return (HMODULE16)11;  /* invalid exe */
607     }
608     pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
609
610     /* Get the entry table */
611
612     pModule->entry_table = (int)pData - (int)pModule;
613     if (!READ( ne_header.entry_tab_offset,
614                ne_header.entry_tab_length,
615                pData ))
616     {
617         GlobalFree16( hModule );
618         return (HMODULE16)11;  /* invalid exe */
619     }
620     pData += ne_header.entry_tab_length;
621
622     /* Get the non-resident names table */
623
624     if (ne_header.nrname_tab_length)
625     {
626         pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
627                                                hModule, FALSE, FALSE, FALSE );
628         if (!pModule->nrname_handle)
629         {
630             GlobalFree16( hModule );
631             return (HMODULE16)11;  /* invalid exe */
632         }
633         buffer = GlobalLock16( pModule->nrname_handle );
634         _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
635         if (FILE_Read( hFile, buffer, ne_header.nrname_tab_length )
636               != ne_header.nrname_tab_length)
637         {
638             GlobalFree16( pModule->nrname_handle );
639             GlobalFree16( hModule );
640             return (HMODULE16)11;  /* invalid exe */
641         }
642     }
643     else pModule->nrname_handle = 0;
644
645     /* Allocate a segment for the implicitly-loaded DLLs */
646
647     if (pModule->modref_count)
648     {
649         pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
650                                     (pModule->modref_count+1)*sizeof(HMODULE16),
651                                     hModule, FALSE, FALSE, FALSE );
652         if (!pModule->dlls_to_init)
653         {
654             if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
655             GlobalFree16( hModule );
656             return (HMODULE16)11;  /* invalid exe */
657         }
658     }
659     else pModule->dlls_to_init = 0;
660
661     MODULE_RegisterModule( pModule );
662     return hModule;
663 #undef READ
664 }
665
666
667 /***********************************************************************
668  *           MODULE_GetOrdinal
669  *
670  * Lookup the ordinal for a given name.
671  */
672 WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name )
673 {
674     char buffer[256], *cpnt;
675     BYTE len;
676     NE_MODULE *pModule;
677
678     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
679
680     dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
681                     hModule, name );
682
683       /* First handle names of the form '#xxxx' */
684
685     if (name[0] == '#') return atoi( name + 1 );
686
687       /* Now copy and uppercase the string */
688
689     strcpy( buffer, name );
690     AnsiUpper( buffer );
691     len = strlen( buffer );
692
693       /* First search the resident names */
694
695     cpnt = (char *)pModule + pModule->name_table;
696
697       /* Skip the first entry (module name) */
698     cpnt += *cpnt + 1 + sizeof(WORD);
699     while (*cpnt)
700     {
701         if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
702         {
703             dprintf_module( stddeb, "  Found: ordinal=%d\n",
704                             *(WORD *)(cpnt + *cpnt + 1) );
705             return *(WORD *)(cpnt + *cpnt + 1);
706         }
707         cpnt += *cpnt + 1 + sizeof(WORD);
708     }
709
710       /* Now search the non-resident names table */
711
712     if (!pModule->nrname_handle) return 0;  /* No non-resident table */
713     cpnt = (char *)GlobalLock16( pModule->nrname_handle );
714
715       /* Skip the first entry (module description string) */
716     cpnt += *cpnt + 1 + sizeof(WORD);
717     while (*cpnt)
718     {
719         if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
720         {
721             dprintf_module( stddeb, "  Found: ordinal=%d\n",
722                             *(WORD *)(cpnt + *cpnt + 1) );
723             return *(WORD *)(cpnt + *cpnt + 1);
724         }
725         cpnt += *cpnt + 1 + sizeof(WORD);
726     }
727     return 0;
728 }
729
730
731 /***********************************************************************
732  *           MODULE_GetEntryPoint
733  *
734  * Return the entry point for a given ordinal.
735  */
736 FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
737 {
738     NE_MODULE *pModule;
739     WORD curOrdinal = 1;
740     BYTE *p;
741     WORD sel, offset;
742
743     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
744
745     p = (BYTE *)pModule + pModule->entry_table;
746     while (*p && (curOrdinal + *p <= ordinal))
747     {
748           /* Skipping this bundle */
749         curOrdinal += *p;
750         switch(p[1])
751         {
752             case 0:    p += 2; break;  /* unused */
753             case 0xff: p += 2 + *p * 6; break;  /* moveable */
754             default:   p += 2 + *p * 3; break;  /* fixed */
755         }
756     }
757     if (!*p) return 0;
758
759     switch(p[1])
760     {
761         case 0:  /* unused */
762             return 0;
763         case 0xff:  /* moveable */
764             p += 2 + 6 * (ordinal - curOrdinal);
765             sel = p[3];
766             offset = *(WORD *)(p + 4);
767             break;
768         default:  /* fixed */
769             sel = p[1];
770             p += 2 + 3 * (ordinal - curOrdinal);
771             offset = *(WORD *)(p + 1);
772             break;
773     }
774
775     if (sel == 0xfe) sel = 0xffff;  /* constant entry */
776     else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
777     return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
778 }
779
780
781 /***********************************************************************
782  *           MODULE_SetEntryPoint
783  *
784  * Change the value of an entry point. Use with caution!
785  * It can only change the offset value, not the selector.
786  */
787 BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
788 {
789     NE_MODULE *pModule;
790     WORD curOrdinal = 1;
791     BYTE *p;
792
793     if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
794
795     p = (BYTE *)pModule + pModule->entry_table;
796     while (*p && (curOrdinal + *p <= ordinal))
797     {
798           /* Skipping this bundle */
799         curOrdinal += *p;
800         switch(p[1])
801         {
802             case 0:    p += 2; break;  /* unused */
803             case 0xff: p += 2 + *p * 6; break;  /* moveable */
804             default:   p += 2 + *p * 3; break;  /* fixed */
805         }
806     }
807     if (!*p) return FALSE;
808
809     switch(p[1])
810     {
811         case 0:  /* unused */
812             return FALSE;
813         case 0xff:  /* moveable */
814             p += 2 + 6 * (ordinal - curOrdinal);
815             *(WORD *)(p + 4) = offset;
816             break;
817         default:  /* fixed */
818             p += 2 + 3 * (ordinal - curOrdinal);
819             *(WORD *)(p + 1) = offset;
820             break;
821     }
822     return TRUE;
823 }
824
825
826 /***********************************************************************
827  *           MODULE_GetWndProcEntry16  (not a Windows API function)
828  *
829  * Return an entry point from the WPROCS dll.
830  */
831 #ifndef WINELIB
832 FARPROC16 MODULE_GetWndProcEntry16( const char *name )
833 {
834     WORD ordinal;
835     FARPROC16 ret;
836     static HMODULE16 hModule = 0;
837
838     if (!hModule) hModule = GetModuleHandle( "WPROCS" );
839     ordinal = MODULE_GetOrdinal( hModule, name );
840     if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
841         fprintf( stderr, "GetWndProc16: %s not found, please report\n", name );
842     return ret;
843 }
844 #endif
845
846
847 /***********************************************************************
848  *           MODULE_GetModuleName
849  */
850 LPSTR MODULE_GetModuleName( HMODULE16 hModule )
851 {
852     NE_MODULE *pModule;
853     BYTE *p, len;
854     static char buffer[10];
855
856     if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
857     p = (BYTE *)pModule + pModule->name_table;
858     len = MIN( *p, 8 );
859     memcpy( buffer, p + 1, len );
860     buffer[len] = '\0';
861     return buffer;
862 }
863
864
865 /**********************************************************************
866  *           MODULE_RegisterModule
867  */
868 void MODULE_RegisterModule( NE_MODULE *pModule )
869 {
870     pModule->next = hFirstModule;
871     hFirstModule = pModule->self;
872 }
873
874
875 /**********************************************************************
876  *          MODULE_FindModule
877  *
878  * Find a module from a path name.
879  */
880 HMODULE16 MODULE_FindModule( LPCSTR path )
881 {
882     HMODULE16 hModule = hFirstModule;
883     LPCSTR filename, dotptr, modulepath, modulename;
884     BYTE len, *name_table;
885
886     if (!(filename = strrchr( path, '\\' ))) filename = path;
887     else filename++;
888     if ((dotptr = strrchr( filename, '.' )) != NULL)
889         len = (BYTE)(dotptr - filename);
890     else len = strlen( filename );
891
892     while(hModule)
893     {
894         NE_MODULE *pModule = MODULE_GetPtr( hModule );
895         if (!pModule) break;
896         modulepath = NE_MODULE_NAME(pModule);
897         if (!(modulename = strrchr( modulepath, '\\' )))
898             modulename = modulepath;
899         else modulename++;
900         if (!lstrcmpi32A( modulename, filename )) return hModule;
901
902         name_table = (BYTE *)pModule + pModule->name_table;
903         if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
904             return hModule;
905         hModule = pModule->next;
906     }
907     return 0;
908 }
909
910
911 /**********************************************************************
912  *          MODULE_CallWEP
913  *
914  * Call a DLL's WEP, allowing it to shut down.
915  * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
916  */
917 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
918 {
919     FARPROC16 WEP = (FARPROC16)0;
920     WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
921
922     if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
923     if (!WEP)
924     {
925         dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
926         return FALSE;
927     }
928     return CallWindowsExitProc( WEP, WEP_FREE_DLL );
929 }
930
931
932 /**********************************************************************
933  *          MODULE_FreeModule
934  *
935  * Remove a module from memory.
936  */
937 static void MODULE_FreeModule( HMODULE16 hModule )
938 {
939     HMODULE16 *hPrevModule;
940     NE_MODULE *pModule;
941     SEGTABLEENTRY *pSegment;
942     HMODULE16 *pModRef;
943     int i;
944
945     if (!(pModule = MODULE_GetPtr( hModule ))) return;
946     if (pModule->flags & NE_FFLAGS_BUILTIN)
947         return;  /* Can't free built-in module */
948
949     if (pModule->flags & NE_FFLAGS_LIBMODULE) MODULE_CallWEP( hModule );
950
951     /* Free the objects owned by the module */
952
953     HOOK_FreeModuleHooks( hModule );
954     CLASS_FreeModuleClasses( hModule );
955
956     /* Clear magic number just in case */
957
958     pModule->magic = pModule->self = 0;
959
960       /* Remove it from the linked list */
961
962     hPrevModule = &hFirstModule;
963     while (*hPrevModule && (*hPrevModule != hModule))
964     {
965         hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
966     }
967     if (*hPrevModule) *hPrevModule = pModule->next;
968
969       /* Free all the segments */
970
971     pSegment = NE_SEG_TABLE( pModule );
972     for (i = 1; i <= pModule->seg_count; i++, pSegment++)
973     {
974         GlobalFree16( pSegment->selector );
975     }
976
977       /* Free the referenced modules */
978
979     pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
980     for (i = 0; i < pModule->modref_count; i++, pModRef++)
981     {
982         FreeModule16( *pModRef );
983     }
984
985       /* Free the module storage */
986
987     if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
988     if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
989     GlobalFree16( hModule );
990
991       /* Remove module from cache */
992
993     if (hCachedModule == hModule) hCachedModule = 0;
994 }
995
996
997 /**********************************************************************
998  *          LoadModule    (KERNEL.45)
999  */
1000 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
1001 {
1002     HMODULE16 hModule;
1003     HANDLE hInstance, hPrevInstance;
1004     NE_MODULE *pModule;
1005     LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1006     OFSTRUCT ofs;
1007 #ifndef WINELIB
1008     WORD *pModRef, *pDLLs;
1009     HFILE hFile;
1010     int i;
1011
1012     hModule = MODULE_FindModule( name );
1013
1014     if (!hModule)  /* We have to load the module */
1015     {
1016         /* Try to load the built-in first if not disabled */
1017         if ((hModule = BUILTIN_LoadModule( name, FALSE ))) return hModule;
1018
1019         if ((hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR)
1020         {
1021             /* Now try the built-in even if disabled */
1022             if ((hModule = BUILTIN_LoadModule( name, TRUE )))
1023             {
1024                 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1025                 return hModule;
1026             }
1027             return 2;  /* File not found */
1028         }
1029
1030           /* Create the module structure */
1031
1032         hModule = MODULE_LoadExeHeader( hFile, &ofs );
1033         if (hModule < 32)
1034         {
1035             /* FIXME: Hack because PE_LoadModule is recursive */
1036             int fd = dup( FILE_GetUnixHandle(hFile) );
1037             _lclose( hFile );
1038             if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
1039             close( fd );
1040             if (hModule < 32)
1041                 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1042                          name, hModule );
1043             return hModule;
1044         }
1045         _lclose( hFile );
1046         pModule = MODULE_GetPtr( hModule );
1047
1048           /* Allocate the segments for this module */
1049
1050         MODULE_CreateSegments( hModule );
1051
1052         hPrevInstance = 0;
1053         hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1054
1055           /* Load the referenced DLLs */
1056
1057         pModRef = (WORD *)((char *)pModule + pModule->modref_table);
1058         pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
1059         for (i = 0; i < pModule->modref_count; i++, pModRef++)
1060         {
1061             char buffer[256];
1062             BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
1063             memcpy( buffer, pstr + 1, *pstr );
1064             strcpy( buffer + *pstr, ".dll" );
1065             dprintf_module( stddeb, "Loading '%s'\n", buffer );
1066             if (!(*pModRef = MODULE_FindModule( buffer )))
1067             {
1068                 /* If the DLL is not loaded yet, load it and store */
1069                 /* its handle in the list of DLLs to initialize.   */
1070                 HMODULE16 hDLL;
1071
1072                 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2)  /* file not found */
1073                 {
1074                     char *p;
1075
1076                     /* Try with prepending the path of the current module */
1077                     GetModuleFileName( hModule, buffer, sizeof(buffer) );
1078                     if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1079                     memcpy( p + 1, pstr + 1, *pstr );
1080                     strcpy( p + 1 + *pstr, ".dll" );
1081                     hDLL = LoadModule( buffer, (LPVOID)-1 );
1082                 }
1083                 if (hDLL < 32)
1084                 {
1085                     fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1086                              buffer, name, hDLL );
1087                     return 2;  /* file not found */
1088                 }
1089                 *pModRef = GetExePtr( hDLL );
1090                 *pDLLs++ = *pModRef;
1091             }
1092             else  /* Increment the reference count of the DLL */
1093             {
1094                 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
1095                 if (pOldDLL) pOldDLL->count++;
1096             }
1097         }
1098
1099           /* Load the segments */
1100
1101         if (pModule->flags & NE_FFLAGS_SELFLOAD)
1102         {
1103                 HFILE hf;
1104                 /* Handle self loading modules */
1105                 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1106                 SELFLOADHEADER *selfloadheader;
1107                 STACK16FRAME *stack16Top;
1108                 HMODULE16 hselfload = GetModuleHandle("WPROCS");
1109                 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1110                 fprintf (stderr, "Warning:  %*.*s is a self-loading module\n"
1111                                 "Support for self-loading modules is very experimental\n",
1112                 *((BYTE*)pModule + pModule->name_table),
1113                 *((BYTE*)pModule + pModule->name_table),
1114                 (char *)pModule + pModule->name_table + 1);
1115                 NE_LoadSegment( hModule, 1 );
1116                 selfloadheader = (SELFLOADHEADER *)
1117                         PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1118                 selfloadheader->EntryAddrProc = 
1119                                            MODULE_GetEntryPoint(hselfload,27);
1120                 selfloadheader->MyAlloc  = MODULE_GetEntryPoint(hselfload,28);
1121                 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1122                 pModule->self_loading_sel = GlobalHandleToSel(
1123                                         GLOBAL_Alloc (GMEM_ZEROINIT,
1124                                         0xFF00, hModule, FALSE, FALSE, FALSE)
1125                                         );
1126                 oldss = IF1632_Saved16_ss;
1127                 oldsp = IF1632_Saved16_sp;
1128                 IF1632_Saved16_ss = pModule->self_loading_sel;
1129                 IF1632_Saved16_sp = 0xFF00 - sizeof(*stack16Top);
1130                 stack16Top = CURRENT_STACK16;
1131                 stack16Top->saved_ss = 0;
1132                 stack16Top->saved_sp = 0;
1133                 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
1134                 stack16Top->entry_point = 0;
1135                 stack16Top->entry_ip = 0;
1136                 stack16Top->entry_cs = 0;
1137                 stack16Top->bp = 0;
1138                 stack16Top->ip = 0;
1139                 stack16Top->cs = 0;
1140
1141                 if (!IF1632_Stack32_base) {
1142                   STACK32FRAME* frame32;
1143                   char *stack32Top;
1144                   /* Setup an initial 32 bit stack frame */
1145                   hInitialStack32 =  GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1146                                                   hModule, FALSE, FALSE, 
1147                                                   FALSE );
1148
1149                   /* Create the 32-bit stack frame */
1150                   
1151                   *(DWORD *)GlobalLock16(hInitialStack32) = 0xDEADBEEF;
1152                   stack32Top = (char*)GlobalLock16(hInitialStack32) + 
1153                     0x10000;
1154                   frame32 = (STACK32FRAME *)stack32Top - 1;
1155                   frame32->saved_esp = (DWORD)stack32Top;
1156                   frame32->edi = 0;
1157                   frame32->esi = 0;
1158                   frame32->edx = 0;
1159                   frame32->ecx = 0;
1160                   frame32->ebx = 0;
1161                   frame32->ebp = 0;
1162                   frame32->retaddr = 0;
1163                   frame32->codeselector = WINE_CODE_SELECTOR;
1164                   /* pTask->esp = (DWORD)frame32; */
1165                   IF1632_Stack32_base = WIN16_GlobalLock16(hInitialStack32);
1166
1167                 }
1168                 /* FIXME: we probably need a DOS handle here */
1169                 hf = FILE_DupUnixHandle( MODULE_OpenFile( hModule ) );
1170                 CallTo16_word_ww( selfloadheader->BootApp, hModule, hf );
1171                 _lclose(hf);
1172                 /* some BootApp procs overwrite the selector of dgroup */
1173                 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1174                 IF1632_Saved16_ss = oldss;
1175                 IF1632_Saved16_sp = oldsp;
1176                 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1177                 if (hInitialStack32){
1178                   GlobalFree16(hInitialStack32);
1179                   IF1632_Stack32_base = hInitialStack32 = 0;
1180                 }
1181         } 
1182         else
1183         {
1184             for (i = 1; i <= pModule->seg_count; i++)
1185                 NE_LoadSegment( hModule, i );
1186         }
1187
1188           /* Fixup the functions prologs */
1189
1190         NE_FixupPrologs( pModule );
1191
1192           /* Make sure the usage count is 1 on the first loading of  */
1193           /* the module, even if it contains circular DLL references */
1194
1195         pModule->count = 1;
1196     }
1197     else
1198     {
1199         pModule = MODULE_GetPtr( hModule );
1200         hPrevInstance = MODULE_GetInstance( hModule );
1201         hInstance = MODULE_CreateInstance( hModule, params );
1202         if (hInstance != hPrevInstance)  /* not a library */
1203             NE_LoadSegment( hModule, pModule->dgroup );
1204         pModule->count++;
1205     }
1206 #else
1207     lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
1208     if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
1209     pModule = (NE_MODULE *)GlobalLock16( hModule );
1210     hPrevInstance = 0;
1211     hInstance = MODULE_CreateInstance( hModule, params );
1212 #endif /* WINELIB */
1213
1214       /* Create a task for this instance */
1215
1216     if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1217     {
1218         TASK_CreateTask( hModule, hInstance, hPrevInstance,
1219                          params->hEnvironment,
1220                          (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1221                          *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1222     }
1223
1224     return hInstance;
1225 }
1226
1227
1228 /**********************************************************************
1229  *          FreeModule16    (KERNEL.46)
1230  */
1231 BOOL16 FreeModule16( HMODULE16 hModule )
1232 {
1233     NE_MODULE *pModule;
1234
1235     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
1236     if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1237
1238     dprintf_module( stddeb, "FreeModule16: %s count %d\n", 
1239                     MODULE_GetModuleName(hModule), pModule->count );
1240     if (--pModule->count == 0) MODULE_FreeModule( hModule );
1241     return TRUE;
1242 }
1243
1244
1245 /**********************************************************************
1246  *          GetModuleHandle    (KERNEL.47)
1247  */
1248 HMODULE16 WIN16_GetModuleHandle( SEGPTR name )
1249 {
1250     if (HIWORD(name) == 0) return GetExePtr( (HANDLE)name );
1251     return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1252 }
1253
1254 HMODULE16 GetModuleHandle( LPCSTR name )
1255 {
1256     return MODULE_FindModule( name );
1257 }
1258
1259
1260 /**********************************************************************
1261  *          GetModuleUsage    (KERNEL.48)
1262  */
1263 int GetModuleUsage( HANDLE hModule )
1264 {
1265     NE_MODULE *pModule;
1266
1267     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
1268     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1269     dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1270                     hModule, pModule->count );
1271     return pModule->count;
1272 }
1273
1274
1275 /**********************************************************************
1276  *          GetModuleFileName    (KERNEL.49)
1277  */
1278 int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1279 {
1280     NE_MODULE *pModule;
1281
1282     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
1283     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1284     lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1285     dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
1286     return strlen(lpFileName);
1287 }
1288
1289
1290 /***********************************************************************
1291  *           LoadLibrary   (KERNEL.95)
1292  */
1293 HANDLE LoadLibrary( LPCSTR libname )
1294 {
1295     HANDLE handle;
1296
1297     if (__winelib)
1298     {
1299         fprintf( stderr, "LoadLibrary not supported in Winelib\n" );
1300         return (HANDLE)0;
1301     }
1302     dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1303
1304     /* This does not increment the module reference count, and will
1305      * therefore cause crashes on FreeLibrary calls.
1306     if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1307      */
1308     handle = LoadModule( libname, (LPVOID)-1 );
1309     if (handle == (HANDLE)2)  /* file not found */
1310     {
1311         char buffer[256];
1312         lstrcpyn32A( buffer, libname, 252 );
1313         strcat( buffer, ".dll" );
1314         handle = LoadModule( buffer, (LPVOID)-1 );
1315     }
1316 #ifndef WINELIB
1317     if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
1318 #endif
1319     return handle;
1320 }
1321
1322
1323 /***********************************************************************
1324  *           FreeLibrary   (KERNEL.96)
1325  */
1326 void FreeLibrary( HANDLE handle )
1327 {
1328     dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1329     FreeModule16( handle );
1330 }
1331
1332
1333 /***********************************************************************
1334  *           WinExec   (KERNEL.166)
1335  */
1336 HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1337 {
1338     LOADPARAMS params;
1339     HGLOBAL16 cmdShowHandle, cmdLineHandle;
1340     HANDLE handle;
1341     WORD *cmdShowPtr;
1342     char *p, *cmdline, filename[256];
1343     static int use_load_module = 1;
1344
1345     if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1346         return 8;  /* Out of memory */
1347     if (!(cmdLineHandle = GlobalAlloc16( 0, 256 )))
1348     {
1349         GlobalFree16( cmdShowHandle );
1350         return 8;  /* Out of memory */
1351     }
1352
1353       /* Store nCmdShow */
1354
1355     cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1356     cmdShowPtr[0] = 2;
1357     cmdShowPtr[1] = nCmdShow;
1358
1359       /* Build the filename and command-line */
1360
1361     cmdline = (char *)GlobalLock16( cmdLineHandle );
1362     lstrcpyn32A(filename, lpCmdLine, sizeof(filename) - 4 /* for extension */);
1363     for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1364     if (*p) lstrcpyn32A( cmdline, p + 1, 128 );
1365     else cmdline[0] = '\0';
1366     *p = '\0';
1367
1368       /* Now load the executable file */
1369
1370     if (use_load_module)
1371     {
1372 #ifdef WINELIB
1373         /* WINELIB: Use LoadModule() only for the program itself */
1374         use_load_module = 0;
1375         params.hEnvironment = (HANDLE)GetDOSEnvironment();
1376 #else
1377         params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1378 #endif  /* WINELIB */
1379         params.cmdLine  = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1380         params.showCmd  = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1381         params.reserved = 0;
1382         handle = LoadModule( filename, &params );
1383         if (handle == 2)  /* file not found */
1384         {
1385             /* Check that the original file name did not have a suffix */
1386             p = strrchr(filename, '.');
1387             if (!p || (strchr(p, '/') && strchr(p, '\\')))
1388             {
1389                 p = filename + strlen(filename);
1390                 strcpy( p, ".exe" );
1391                 handle = LoadModule( filename, &params );
1392                 *p = '\0';  /* Remove extension */
1393             }
1394         }
1395     }
1396     else handle = 2;
1397
1398     if (handle < 32)
1399     {
1400         /* Try to start it as a unix program */
1401         if (!fork())
1402         {
1403             /* Child process */
1404             const char *unixfilename;
1405             const char *argv[256], **argptr;
1406             int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1407                           nCmdShow == SW_SHOWMINNOACTIVE);
1408
1409             /* get unixfilename */
1410             if (strchr(filename, '/') ||
1411                 strchr(filename, ':') ||
1412                 strchr(filename, '\\'))
1413                 unixfilename = DOSFS_GetUnixFileName(filename, 1);
1414             else unixfilename = filename;
1415
1416             if (unixfilename)
1417             {
1418                 /* build argv */
1419                 argptr = argv;
1420                 if (iconic) *argptr++ = "-iconic";
1421                 *argptr++ = unixfilename;
1422                 p = cmdline;
1423                 while (1)
1424                 {
1425                     while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1426                     if (!*p) break;
1427                     *argptr++ = p;
1428                     while (*p && *p != ' ' && *p != '\t') p++;
1429                 }
1430                 *argptr++ = 0;
1431
1432                 /* Execute */
1433                 execvp(argv[0], (char**)argv);
1434             }
1435
1436             /* Failed ! */
1437
1438             if (__winelib)
1439             {
1440                 /* build argv */
1441                 argptr = argv;
1442                 *argptr++ = "wine";
1443                 if (iconic) *argptr++ = "-iconic";
1444                 *argptr++ = lpCmdLine;
1445                 *argptr++ = 0;
1446
1447                 /* Execute */
1448                 execvp(argv[0] , (char**)argv);
1449
1450                 /* Failed ! */
1451                 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1452             }
1453             exit(1);
1454         }
1455     }
1456
1457     GlobalFree16( cmdShowHandle );
1458     GlobalFree16( cmdLineHandle );
1459
1460 #if 0
1461     if (handle < (HANDLE)32)    /* Error? */
1462         return handle;
1463     
1464 /* FIXME: Yield never returns! 
1465    We may want to run more applications or start the debugger
1466    before calling Yield. If we don't Yield will be called immdiately
1467    after returning.  Why is it needed for Word anyway? */
1468     Yield();    /* program is executed immediately ....needed for word */
1469
1470 #endif
1471     return handle;
1472 }
1473
1474
1475 /***********************************************************************
1476  *           GetProcAddress16   (KERNEL.50)
1477  */
1478 FARPROC16 GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1479 {
1480     WORD ordinal;
1481     FARPROC16 ret;
1482
1483     if (!hModule) hModule = GetCurrentTask();
1484     hModule = GetExePtr( hModule );
1485
1486     if (HIWORD(name) != 0)
1487     {
1488         ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1489         dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1490                         hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1491     }
1492     else
1493     {
1494         ordinal = LOWORD(name);
1495         dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1496                         hModule, ordinal );
1497     }
1498     if (!ordinal) return (FARPROC16)0;
1499
1500     ret = MODULE_GetEntryPoint( hModule, ordinal );
1501
1502     dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1503     return ret;
1504 }
1505
1506
1507 /***********************************************************************
1508  *           GetProcAddress32   (KERNEL32.257)
1509  */
1510 FARPROC32 GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1511 {
1512 #ifndef WINELIB
1513     NE_MODULE *pModule;
1514
1515     hModule = GetExePtr( hModule );
1516     if (!(pModule = MODULE_GetPtr( hModule )))
1517         return (FARPROC32)0;
1518     if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
1519         return (FARPROC32)0;
1520     if (pModule->flags & NE_FFLAGS_BUILTIN)
1521         return BUILTIN_GetProcAddress32( pModule, function );
1522     return PE_FindExportedFunction( pModule->pe_module, function );
1523 #else
1524     return NULL;
1525 #endif
1526 }
1527
1528
1529 /**********************************************************************
1530  *          GetExpWinVer    (KERNEL.167)
1531  */
1532 WORD GetExpWinVer( HMODULE16 hModule )
1533 {
1534     NE_MODULE *pModule = MODULE_GetPtr( hModule );
1535     return pModule ? pModule->expected_version : 0;
1536 }
1537
1538
1539 /**********************************************************************
1540  *          IsSharedSelector    (KERNEL.345)
1541  */
1542 BOOL16 IsSharedSelector( HANDLE16 selector )
1543 {
1544     /* Check whether the selector belongs to a DLL */
1545     NE_MODULE *pModule = MODULE_GetPtr( GetExePtr( selector ));
1546     if (!pModule) return FALSE;
1547     return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
1548 }
1549
1550
1551 /**********************************************************************
1552  *          ModuleFirst    (TOOLHELP.59)
1553  */
1554 BOOL16 ModuleFirst( MODULEENTRY *lpme )
1555 {
1556     lpme->wNext = hFirstModule;
1557     return ModuleNext( lpme );
1558 }
1559
1560
1561 /**********************************************************************
1562  *          ModuleNext    (TOOLHELP.60)
1563  */
1564 BOOL16 ModuleNext( MODULEENTRY *lpme )
1565 {
1566     NE_MODULE *pModule;
1567
1568     if (!lpme->wNext) return FALSE;
1569     if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1570     strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1571              MAX_MODULE_NAME );
1572     lpme->szModule[MAX_MODULE_NAME] = '\0';
1573     lpme->hModule = lpme->wNext;
1574     lpme->wcUsage = pModule->count;
1575     strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1576     lpme->szExePath[MAX_PATH] = '\0';
1577     lpme->wNext = pModule->next;
1578     return TRUE;
1579 }
1580
1581
1582 /**********************************************************************
1583  *          ModuleFindName    (TOOLHELP.61)
1584  */
1585 BOOL16 ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1586 {
1587     lpme->wNext = GetModuleHandle( name );
1588     return ModuleNext( lpme );
1589 }
1590
1591
1592 /**********************************************************************
1593  *          ModuleFindHandle    (TOOLHELP.62)
1594  */
1595 BOOL16 ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1596 {
1597     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
1598     lpme->wNext = hModule;
1599     return ModuleNext( lpme );
1600 }