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