Release 971130
[wine] / loader / module.c
1 /*
2  * Modules
3  *
4  * Copyright 1995 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 #include "windows.h"
15 #include "class.h"
16 #include "file.h"
17 #include "global.h"
18 #include "heap.h"
19 #include "hook.h"
20 #include "module.h"
21 #include "neexe.h"
22 #include "resource.h"
23 #include "selectors.h"
24 #include "stackframe.h"
25 #include "task.h"
26 #include "toolhelp.h"
27 #include "stddebug.h"
28 #include "debug.h"
29 #include "callback.h"
30
31 extern HINSTANCE16 PE_LoadModule( HFILE32 hf, OFSTRUCT *ofs, LOADPARAMS* params );
32
33 static HMODULE16 hFirstModule = 0;
34 static HMODULE16 hCachedModule = 0;  /* Module cached by MODULE_OpenFile */
35
36
37 /***********************************************************************
38  *           MODULE_GetPtr
39  */
40 NE_MODULE *MODULE_GetPtr( HMODULE32 hModule )
41 {
42     HMODULE16 hnd =MODULE_HANDLEtoHMODULE16(hModule);
43
44     if (!hnd)
45         return NULL;
46     return (NE_MODULE*)GlobalLock16(hnd);
47 }
48
49 /***********************************************************************
50  *           MODULE_HANDLEtoHMODULE16
51  */
52 HMODULE16
53 MODULE_HANDLEtoHMODULE16(HANDLE32 handle) {
54     NE_MODULE   *pModule;
55
56     if (HIWORD(handle))
57     {
58         /* this is a HMODULE32 */
59
60         /* walk the list looking for the correct startaddress */
61         pModule = (NE_MODULE *)GlobalLock16( hFirstModule );
62         while (pModule)
63         {
64             if (pModule->module32 == handle) return pModule->self;
65             pModule = (NE_MODULE*)GlobalLock16(pModule->next);
66         }
67         return 0;
68     }
69     return GetExePtr(handle);
70 }
71
72 /***********************************************************************
73  *           MODULE_HANDLEtoHMODULE32
74  * return HMODULE32, if possible, HMODULE16 otherwise
75  */
76 HMODULE32
77 MODULE_HANDLEtoHMODULE32(HANDLE32 handle) {
78     NE_MODULE *pModule;
79
80     if (HIWORD(handle))
81         return (HMODULE32)handle;
82     else {
83         handle = GetExePtr(handle);
84         if (!handle)
85             return 0;
86         pModule = (NE_MODULE *)GlobalLock16( handle );
87         if (!pModule)
88             return 0;
89         
90         if (pModule->module32) return pModule->module32;
91         return handle;
92     }
93 }
94
95 /***********************************************************************
96  *           MODULE_DumpModule
97  */
98 void MODULE_DumpModule( HMODULE32 hModule )
99 {
100     int i, ordinal;
101     SEGTABLEENTRY *pSeg;
102     BYTE *pstr;
103     WORD *pword;
104     NE_MODULE *pModule;
105
106     if (!(pModule = MODULE_GetPtr( hModule )))
107     {
108         fprintf( stderr, "**** %04x is not a module handle\n", hModule );
109         return;
110     }
111
112       /* Dump the module info */
113
114     printf( "Module %04x:\n", hModule );
115     printf( "count=%d flags=%04x heap=%d stack=%d\n",
116             pModule->count, pModule->flags,
117             pModule->heap_size, pModule->stack_size );
118     printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
119            pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
120            pModule->seg_count, pModule->modref_count );
121     printf( "os_flags=%d swap_area=%d version=%04x\n",
122             pModule->os_flags, pModule->min_swap_area,
123             pModule->expected_version );
124     if (pModule->flags & NE_FFLAGS_WIN32)
125         printf( "PE module=%08x\n", pModule->module32 );
126
127       /* Dump the file info */
128
129     printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
130
131       /* Dump the segment table */
132
133     printf( "\nSegment table:\n" );
134     pSeg = NE_SEG_TABLE( pModule );
135     for (i = 0; i < pModule->seg_count; i++, pSeg++)
136         printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
137                 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
138                 pSeg->minsize, pSeg->selector );
139
140       /* Dump the resource table */
141
142     printf( "\nResource table:\n" );
143     if (pModule->res_table)
144     {
145         pword = (WORD *)((BYTE *)pModule + pModule->res_table);
146         printf( "Alignment: %d\n", *pword++ );
147         while (*pword)
148         {
149             struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
150             struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
151             printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
152             for (i = 0; i < ptr->count; i++, pname++)
153                 printf( "offset=%d len=%d id=%04x\n",
154                        pname->offset, pname->length, pname->id );
155             pword = (WORD *)pname;
156         }
157     }
158     else printf( "None\n" );
159
160       /* Dump the resident name table */
161
162     printf( "\nResident-name table:\n" );
163     pstr = (char *)pModule + pModule->name_table;
164     while (*pstr)
165     {
166         printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
167                 *(WORD *)(pstr + *pstr + 1) );
168         pstr += *pstr + 1 + sizeof(WORD);
169     }
170
171       /* Dump the module reference table */
172
173     printf( "\nModule ref table:\n" );
174     if (pModule->modref_table)
175     {
176         pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
177         for (i = 0; i < pModule->modref_count; i++, pword++)
178         {
179             printf( "%d: %04x -> '%s'\n", i, *pword,
180                     MODULE_GetModuleName(*pword));
181         }
182     }
183     else printf( "None\n" );
184
185       /* Dump the entry table */
186
187     printf( "\nEntry table:\n" );
188     pstr = (char *)pModule + pModule->entry_table;
189     ordinal = 1;
190     while (*pstr)
191     {
192         printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
193         if (!pstr[1])
194         {
195             ordinal += *pstr;
196             pstr += 2;
197         }
198         else if ((BYTE)pstr[1] == 0xff)  /* moveable */
199         {
200             struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
201             for (i = 0; i < *pstr; i++, pe++)
202                 printf( "%d: %02x:%04x (moveable)\n",
203                         ordinal++, pe->seg_number, pe->offset );
204             pstr = (char *)pe;
205         }
206         else  /* fixed */
207         {
208             struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
209             for (i = 0; i < *pstr; i++, pe++)
210                 printf( "%d: %04x (fixed)\n",
211                         ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
212             pstr = (char *)pe;
213         }
214     }
215
216     /* Dump the non-resident names table */
217
218     printf( "\nNon-resident names table:\n" );
219     if (pModule->nrname_handle)
220     {
221         pstr = (char *)GlobalLock16( pModule->nrname_handle );
222         while (*pstr)
223         {
224             printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
225                    *(WORD *)(pstr + *pstr + 1) );
226             pstr += *pstr + 1 + sizeof(WORD);
227         }
228     }
229     printf( "\n" );
230 }
231
232
233 /***********************************************************************
234  *           MODULE_WalkModules
235  *
236  * Walk the module list and print the modules.
237  */
238 void MODULE_WalkModules(void)
239 {
240     HMODULE16 hModule = hFirstModule;
241     fprintf( stderr, "Module Flags Name\n" );
242     while (hModule)
243     {
244         NE_MODULE *pModule = MODULE_GetPtr( hModule );
245         if (!pModule)
246         {
247             fprintf( stderr, "**** Bad module %04x in list\n", hModule );
248             return;
249         }
250         fprintf( stderr, " %04x  %04x  %.*s\n", hModule, pModule->flags,
251                  *((char *)pModule + pModule->name_table),
252                  (char *)pModule + pModule->name_table + 1 );
253         hModule = pModule->next;
254     }
255 }
256
257
258 /***********************************************************************
259  *           MODULE_OpenFile
260  */
261 int MODULE_OpenFile( HMODULE32 hModule )
262 {
263     NE_MODULE *pModule;
264     DOS_FULL_NAME full_name;
265     char *name;
266
267     static int cachedfd = -1;
268
269     hModule = MODULE_HANDLEtoHMODULE16(hModule);
270     dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
271                     hModule, hCachedModule, cachedfd );
272     if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
273     if (hCachedModule == hModule) return cachedfd;
274     close( cachedfd );
275     hCachedModule = hModule;
276     name = NE_MODULE_NAME( pModule );
277     if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
278         (cachedfd = open( full_name.long_name, O_RDONLY )) == -1)
279         fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
280                  name, hModule );
281     dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
282                     name, cachedfd );
283     return cachedfd;
284 }
285
286
287 /***********************************************************************
288  *           MODULE_Ne2MemFlags
289  *
290  * This function translates NE segment flags to GlobalAlloc flags
291  */
292 static WORD MODULE_Ne2MemFlags(WORD flags)
293
294     WORD memflags = 0;
295 #if 0
296     if (flags & NE_SEGFLAGS_DISCARDABLE) 
297       memflags |= GMEM_DISCARDABLE;
298     if (flags & NE_SEGFLAGS_MOVEABLE || 
299         ( ! (flags & NE_SEGFLAGS_DATA) &&
300           ! (flags & NE_SEGFLAGS_LOADED) &&
301           ! (flags & NE_SEGFLAGS_ALLOCATED)
302          )
303         )
304       memflags |= GMEM_MOVEABLE;
305     memflags |= GMEM_ZEROINIT;
306 #else
307     memflags = GMEM_ZEROINIT | GMEM_FIXED;
308     return memflags;
309 #endif
310 }
311
312 /***********************************************************************
313  *           MODULE_AllocateSegment (WPROCS.26)
314  */
315
316 DWORD WINAPI MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
317 {
318     WORD size = wSize << wElem;
319     HANDLE16 hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
320     return MAKELONG( hMem, GlobalHandleToSel(hMem) );
321 }
322
323 /***********************************************************************
324  *           MODULE_CreateSegments
325  */
326 static BOOL32 MODULE_CreateSegments( HMODULE32 hModule )
327 {
328     SEGTABLEENTRY *pSegment;
329     NE_MODULE *pModule;
330     int i, minsize;
331
332     if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
333     pSegment = NE_SEG_TABLE( pModule );
334     for (i = 1; i <= pModule->seg_count; i++, pSegment++)
335     {
336         minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
337         if (i == pModule->ss) minsize += pModule->stack_size;
338         /* The DGROUP is allocated by MODULE_CreateInstance */
339         if (i == pModule->dgroup) continue;
340         pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
341                                       minsize, hModule,
342                                       !(pSegment->flags & NE_SEGFLAGS_DATA),
343                                       FALSE,
344                             FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
345         if (!pSegment->selector) return FALSE;
346     }
347
348     pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
349                             (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
350     return TRUE;
351 }
352
353
354 /***********************************************************************
355  *           MODULE_GetInstance
356  */
357 HINSTANCE16 MODULE_GetInstance( HMODULE32 hModule )
358 {
359     SEGTABLEENTRY *pSegment;
360     NE_MODULE *pModule;
361     
362     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
363     if (pModule->dgroup == 0) return hModule;
364
365     pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
366     
367     return pSegment->selector;
368 }
369
370
371 /***********************************************************************
372  *           MODULE_CreateInstance
373  */
374 HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
375 {
376     SEGTABLEENTRY *pSegment;
377     NE_MODULE *pModule;
378     int minsize;
379     HINSTANCE16 hNewInstance, hPrevInstance;
380
381     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
382     if (pModule->dgroup == 0) return hModule;
383
384     pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
385     hPrevInstance = pSegment->selector;
386
387       /* if it's a library, create a new instance only the first time */
388     if (hPrevInstance)
389     {
390         if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
391         if (params == (LOADPARAMS*)-1) return hPrevInstance;
392     }
393
394     minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
395     if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
396     minsize += pModule->heap_size;
397     hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
398                                  minsize, hModule, FALSE, FALSE, FALSE );
399     if (!hNewInstance) return 0;
400     pSegment->selector = hNewInstance;
401     return hNewInstance;
402 }
403
404
405 /***********************************************************************
406  *           MODULE_CreateDummyModule
407  *
408  * Create a dummy NE module for Win32 or Winelib.
409  */
410 HMODULE32 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
411 {
412     HMODULE32 hModule;
413     NE_MODULE *pModule;
414     SEGTABLEENTRY *pSegment;
415     char *pStr,*s;
416     int len;
417     const char* basename;
418
419     INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
420                     + strlen(ofs->szPathName) + 1;
421     INT32 size = sizeof(NE_MODULE) +
422                  /* loaded file info */
423                  of_size +
424                  /* segment table: DS,CS */
425                  2 * sizeof(SEGTABLEENTRY) +
426                  /* name table */
427                  9 +
428                  /* several empty tables */
429                  8;
430
431     hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
432     if (!hModule) return (HMODULE32)11;  /* invalid exe */
433
434     FarSetOwner( hModule, hModule );
435     pModule = (NE_MODULE *)GlobalLock16( hModule );
436
437     /* Set all used entries */
438     pModule->magic            = IMAGE_OS2_SIGNATURE;
439     pModule->count            = 1;
440     pModule->next             = 0;
441     pModule->flags            = 0;
442     pModule->dgroup           = 1;
443     pModule->ss               = 1;
444     pModule->cs               = 2;
445     pModule->heap_size        = 0xe000;
446     pModule->stack_size       = 0x1000;
447     pModule->seg_count        = 2;
448     pModule->modref_count     = 0;
449     pModule->nrname_size      = 0;
450     pModule->fileinfo         = sizeof(NE_MODULE);
451     pModule->os_flags         = NE_OSFLAGS_WINDOWS;
452     pModule->expected_version = 0x030a;
453     pModule->self             = hModule;
454
455     /* Set loaded file information */
456     memcpy( pModule + 1, ofs, of_size );
457     ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
458
459     pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
460     pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
461     /* Data segment */
462     pSegment->size    = 0;
463     pSegment->flags   = NE_SEGFLAGS_DATA;
464     pSegment->minsize = 0x1000;
465     pSegment++;
466     /* Code segment */
467     pSegment->flags   = 0;
468     pSegment++;
469
470     /* Module name */
471     pStr = (char *)pSegment;
472     pModule->name_table = (int)pStr - (int)pModule;
473     basename = strrchr(ofs->szPathName,'\\');
474     if (!basename) basename = ofs->szPathName;
475     else basename++;
476     len = strlen(basename);
477     if ((s = strchr(basename,'.'))) len = s - basename;
478     if (len > 8) len = 8;
479     *pStr = len;
480     strncpy( pStr+1, basename, len );
481     if (len < 8) pStr[len+1] = 0;
482     pStr += 9;
483
484     /* All tables zero terminated */
485     pModule->res_table = pModule->import_table = pModule->entry_table =
486                 (int)pStr - (int)pModule;
487
488     MODULE_RegisterModule( pModule );
489     return hModule;
490 }
491
492
493 /***********************************************************************
494  *           MODULE_LoadExeHeader
495  */
496 static HMODULE32 MODULE_LoadExeHeader( HFILE32 hFile, OFSTRUCT *ofs )
497 {
498     IMAGE_DOS_HEADER mz_header;
499     IMAGE_OS2_HEADER ne_header;
500     int size;
501     HMODULE32 hModule;
502     NE_MODULE *pModule;
503     BYTE *pData;
504     char *buffer, *fastload = NULL;
505     int fastload_offset = 0, fastload_length = 0;
506
507   /* Read a block from either the file or the fast-load area. */
508 #define READ(offset,size,buffer) \
509        ((fastload && ((offset) >= fastload_offset) && \
510          ((offset)+(size) <= fastload_offset+fastload_length)) ? \
511         (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
512         (_llseek32( hFile, (offset), SEEK_SET), \
513          _lread32( hFile, (buffer), (size) ) == (size)))
514
515     _llseek32( hFile, 0, SEEK_SET );
516     if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
517         (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
518         return (HMODULE32)11;  /* invalid exe */
519
520     _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
521     if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
522         return (HMODULE32)11;  /* invalid exe */
523
524     if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE32)21;  /* win32 exe */
525     if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE32)11;  /* invalid exe */
526
527     if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
528       fprintf(stderr, "Sorry, this is an OS/2 linear executable (LX) file !\n");
529       return (HMODULE32)11;
530     }
531     /* We now have a valid NE header */
532
533     size = sizeof(NE_MODULE) +
534              /* loaded file info */
535            sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
536              /* segment table */
537            ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
538              /* resource table */
539            ne_header.rname_tab_offset - ne_header.resource_tab_offset +
540              /* resident names table */
541            ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
542              /* module ref table */
543            ne_header.n_mod_ref_tab * sizeof(WORD) + 
544              /* imported names table */
545            ne_header.entry_tab_offset - ne_header.iname_tab_offset +
546              /* entry table length */
547            ne_header.entry_tab_length;
548
549     hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
550     if (!hModule) return (HMODULE32)11;  /* invalid exe */
551     FarSetOwner( hModule, hModule );
552     pModule = (NE_MODULE *)GlobalLock16( hModule );
553     memcpy( pModule, &ne_header, sizeof(ne_header) );
554     pModule->count = 0;
555     pModule->module32 = 0;
556     pModule->self = hModule;
557     pModule->self_loading_sel = 0;
558     pData = (BYTE *)(pModule + 1);
559
560     /* Clear internal Wine flags in case they are set in the EXE file */
561
562     pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
563
564     /* Read the fast-load area */
565
566     if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
567     {
568         fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
569         fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
570         dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
571                         fastload_offset, fastload_length );
572         if ((fastload = HeapAlloc( SystemHeap, 0, fastload_length )) != NULL)
573         {
574             _llseek32( hFile, fastload_offset, SEEK_SET);
575             if (_lread32(hFile, fastload, fastload_length) != fastload_length)
576             {
577                 HeapFree( SystemHeap, 0, fastload );
578                 fprintf(stderr, "Error reading fast-load area !\n");
579                 fastload = NULL;
580             }
581         }
582     }
583
584     /* Store the filename information */
585
586     pModule->fileinfo = (int)pData - (int)pModule;
587     size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
588     memcpy( pData, ofs, size );
589     ((OFSTRUCT *)pData)->cBytes = size - 1;
590     pData += size;
591
592     /* Get the segment table */
593
594     pModule->seg_table = (int)pData - (int)pModule;
595     buffer = HeapAlloc( SystemHeap, 0, ne_header.n_segment_tab *
596                                       sizeof(struct ne_segment_table_entry_s));
597     if (buffer)
598     {
599         int i;
600         struct ne_segment_table_entry_s *pSeg;
601
602         if (!READ( mz_header.e_lfanew + ne_header.segment_tab_offset,
603              ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
604              buffer ))
605         {
606             HeapFree( SystemHeap, 0, buffer );
607             if (fastload) HeapFree( SystemHeap, 0, fastload );
608             GlobalFree16( hModule );
609             return (HMODULE32)11;  /* invalid exe */
610         }
611         pSeg = (struct ne_segment_table_entry_s *)buffer;
612         for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
613         {
614             memcpy( pData, pSeg, sizeof(*pSeg) );
615             pData += sizeof(SEGTABLEENTRY);
616         }
617         HeapFree( SystemHeap, 0, buffer );
618     }
619     else
620     {
621         if (fastload) HeapFree( SystemHeap, 0, fastload );
622         GlobalFree16( hModule );
623         return (HMODULE32)11;  /* invalid exe */
624     }
625
626     /* Get the resource table */
627
628     if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
629     {
630         pModule->res_table = (int)pData - (int)pModule;
631         if (!READ(mz_header.e_lfanew + ne_header.resource_tab_offset,
632                   ne_header.rname_tab_offset - ne_header.resource_tab_offset,
633                   pData )) return (HMODULE32)11;  /* invalid exe */
634         pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
635         NE_InitResourceHandler( hModule );
636     }
637     else pModule->res_table = 0;  /* No resource table */
638
639     /* Get the resident names table */
640
641     pModule->name_table = (int)pData - (int)pModule;
642     if (!READ( mz_header.e_lfanew + ne_header.rname_tab_offset,
643                ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
644                pData ))
645     {
646         if (fastload) HeapFree( SystemHeap, 0, fastload );
647         GlobalFree16( hModule );
648         return (HMODULE32)11;  /* invalid exe */
649     }
650     pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
651
652     /* Get the module references table */
653
654     if (ne_header.n_mod_ref_tab > 0)
655     {
656         pModule->modref_table = (int)pData - (int)pModule;
657         if (!READ( mz_header.e_lfanew + ne_header.moduleref_tab_offset,
658                   ne_header.n_mod_ref_tab * sizeof(WORD),
659                   pData ))
660         {
661             if (fastload) HeapFree( SystemHeap, 0, fastload );
662             GlobalFree16( hModule );
663             return (HMODULE32)11;  /* invalid exe */
664         }
665         pData += ne_header.n_mod_ref_tab * sizeof(WORD);
666     }
667     else pModule->modref_table = 0;  /* No module references */
668
669     /* Get the imported names table */
670
671     pModule->import_table = (int)pData - (int)pModule;
672     if (!READ( mz_header.e_lfanew + ne_header.iname_tab_offset, 
673                ne_header.entry_tab_offset - ne_header.iname_tab_offset,
674                pData ))
675     {
676         if (fastload) HeapFree( SystemHeap, 0, fastload );
677         GlobalFree16( hModule );
678         return (HMODULE32)11;  /* invalid exe */
679     }
680     pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
681
682     /* Get the entry table */
683
684     pModule->entry_table = (int)pData - (int)pModule;
685     if (!READ( mz_header.e_lfanew + ne_header.entry_tab_offset,
686                ne_header.entry_tab_length,
687                pData ))
688     {
689         if (fastload) HeapFree( SystemHeap, 0, fastload );
690         GlobalFree16( hModule );
691         return (HMODULE32)11;  /* invalid exe */
692     }
693     pData += ne_header.entry_tab_length;
694
695     /* Free the fast-load area */
696
697 #undef READ
698     if (fastload) HeapFree( SystemHeap, 0, fastload );
699
700     /* Get the non-resident names table */
701
702     if (ne_header.nrname_tab_length)
703     {
704         pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
705                                                hModule, FALSE, FALSE, FALSE );
706         if (!pModule->nrname_handle)
707         {
708             GlobalFree16( hModule );
709             return (HMODULE32)11;  /* invalid exe */
710         }
711         buffer = GlobalLock16( pModule->nrname_handle );
712         _llseek32( hFile, ne_header.nrname_tab_offset, SEEK_SET );
713         if (_lread32( hFile, buffer, ne_header.nrname_tab_length )
714               != ne_header.nrname_tab_length)
715         {
716             GlobalFree16( pModule->nrname_handle );
717             GlobalFree16( hModule );
718             return (HMODULE32)11;  /* invalid exe */
719         }
720     }
721     else pModule->nrname_handle = 0;
722
723     /* Allocate a segment for the implicitly-loaded DLLs */
724
725     if (pModule->modref_count)
726     {
727         pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
728                                     (pModule->modref_count+1)*sizeof(HMODULE32),
729                                     hModule, FALSE, FALSE, FALSE );
730         if (!pModule->dlls_to_init)
731         {
732             if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
733             GlobalFree16( hModule );
734             return (HMODULE32)11;  /* invalid exe */
735         }
736     }
737     else pModule->dlls_to_init = 0;
738
739     MODULE_RegisterModule( pModule );
740     return hModule;
741 }
742
743
744 /***********************************************************************
745  *           MODULE_GetOrdinal
746  *
747  * Lookup the ordinal for a given name.
748  */
749 WORD MODULE_GetOrdinal( HMODULE32 hModule, const char *name )
750 {
751     unsigned char buffer[256], *cpnt;
752     BYTE len;
753     NE_MODULE *pModule;
754
755     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
756
757     dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
758                     hModule, name );
759
760       /* First handle names of the form '#xxxx' */
761
762     if (name[0] == '#') return atoi( name + 1 );
763
764       /* Now copy and uppercase the string */
765
766     strcpy( buffer, name );
767     CharUpper32A( buffer );
768     len = strlen( buffer );
769
770       /* First search the resident names */
771
772     cpnt = (char *)pModule + pModule->name_table;
773
774       /* Skip the first entry (module name) */
775     cpnt += *cpnt + 1 + sizeof(WORD);
776     while (*cpnt)
777     {
778         if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
779         {
780             dprintf_module( stddeb, "  Found: ordinal=%d\n",
781                             *(WORD *)(cpnt + *cpnt + 1) );
782             return *(WORD *)(cpnt + *cpnt + 1);
783         }
784         cpnt += *cpnt + 1 + sizeof(WORD);
785     }
786
787       /* Now search the non-resident names table */
788
789     if (!pModule->nrname_handle) return 0;  /* No non-resident table */
790     cpnt = (char *)GlobalLock16( pModule->nrname_handle );
791
792       /* Skip the first entry (module description string) */
793     cpnt += *cpnt + 1 + sizeof(WORD);
794     while (*cpnt)
795     {
796         if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
797         {
798             dprintf_module( stddeb, "  Found: ordinal=%d\n",
799                             *(WORD *)(cpnt + *cpnt + 1) );
800             return *(WORD *)(cpnt + *cpnt + 1);
801         }
802         cpnt += *cpnt + 1 + sizeof(WORD);
803     }
804     return 0;
805 }
806
807
808 /***********************************************************************
809  *           MODULE_GetEntryPoint
810  *
811  * Return the entry point for a given ordinal.
812  */
813 FARPROC16 MODULE_GetEntryPoint( HMODULE32 hModule, WORD ordinal )
814 {
815     NE_MODULE *pModule;
816     WORD curOrdinal = 1;
817     BYTE *p;
818     WORD sel, offset;
819
820     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
821
822     p = (BYTE *)pModule + pModule->entry_table;
823     while (*p && (curOrdinal + *p <= ordinal))
824     {
825           /* Skipping this bundle */
826         curOrdinal += *p;
827         switch(p[1])
828         {
829             case 0:    p += 2; break;  /* unused */
830             case 0xff: p += 2 + *p * 6; break;  /* moveable */
831             default:   p += 2 + *p * 3; break;  /* fixed */
832         }
833     }
834     if (!*p) return 0;
835
836     switch(p[1])
837     {
838         case 0:  /* unused */
839             return 0;
840         case 0xff:  /* moveable */
841             p += 2 + 6 * (ordinal - curOrdinal);
842             sel = p[3];
843             offset = *(WORD *)(p + 4);
844             break;
845         default:  /* fixed */
846             sel = p[1];
847             p += 2 + 3 * (ordinal - curOrdinal);
848             offset = *(WORD *)(p + 1);
849             break;
850     }
851
852     if (sel == 0xfe) sel = 0xffff;  /* constant entry */
853     else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
854     return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
855 }
856
857
858 /***********************************************************************
859  *           EntryAddrProc   (WPROCS.27)
860  */
861 FARPROC16 WINAPI EntryAddrProc( HMODULE16 hModule, WORD ordinal )
862 {
863     return MODULE_GetEntryPoint( hModule, ordinal );
864 }
865
866
867 /***********************************************************************
868  *           MODULE_SetEntryPoint
869  *
870  * Change the value of an entry point. Use with caution!
871  * It can only change the offset value, not the selector.
872  */
873 BOOL16 MODULE_SetEntryPoint( HMODULE32 hModule, WORD ordinal, WORD offset )
874 {
875     NE_MODULE *pModule;
876     WORD curOrdinal = 1;
877     BYTE *p;
878
879     if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
880
881     p = (BYTE *)pModule + pModule->entry_table;
882     while (*p && (curOrdinal + *p <= ordinal))
883     {
884           /* Skipping this bundle */
885         curOrdinal += *p;
886         switch(p[1])
887         {
888             case 0:    p += 2; break;  /* unused */
889             case 0xff: p += 2 + *p * 6; break;  /* moveable */
890             default:   p += 2 + *p * 3; break;  /* fixed */
891         }
892     }
893     if (!*p) return FALSE;
894
895     switch(p[1])
896     {
897         case 0:  /* unused */
898             return FALSE;
899         case 0xff:  /* moveable */
900             p += 2 + 6 * (ordinal - curOrdinal);
901             *(WORD *)(p + 4) = offset;
902             break;
903         default:  /* fixed */
904             p += 2 + 3 * (ordinal - curOrdinal);
905             *(WORD *)(p + 1) = offset;
906             break;
907     }
908     return TRUE;
909 }
910
911
912 /***********************************************************************
913  *           MODULE_GetWndProcEntry16  (not a Windows API function)
914  *
915  * Return an entry point from the WPROCS dll.
916  */
917 FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name )
918 {
919     FARPROC16 ret = NULL;
920
921     if (__winelib)
922     {
923         /* FIXME: hack for Winelib */
924         extern LRESULT ColorDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
925         extern LRESULT FileOpenDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
926         extern LRESULT FileSaveDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
927         extern LRESULT FindTextDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
928         extern LRESULT PrintDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
929         extern LRESULT PrintSetupDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
930         extern LRESULT ReplaceTextDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
931
932         if (!strcmp(name,"ColorDlgProc"))
933             return (FARPROC16)ColorDlgProc;
934         if (!strcmp(name,"FileOpenDlgProc"))
935             return (FARPROC16)FileOpenDlgProc;
936         if (!strcmp(name,"FileSaveDlgProc"))
937             return (FARPROC16)FileSaveDlgProc;
938         if (!strcmp(name,"FindTextDlgProc"))
939             return (FARPROC16)FindTextDlgProc;
940         if (!strcmp(name,"PrintDlgProc"))
941             return (FARPROC16)PrintDlgProc;
942         if (!strcmp(name,"PrintSetupDlgProc"))
943             return (FARPROC16)PrintSetupDlgProc;
944         if (!strcmp(name,"ReplaceTextDlgProc"))
945             return (FARPROC16)ReplaceTextDlgProc;
946         fprintf(stderr,"warning: No mapping for %s(), add one in library/miscstubs.c\n",name);
947         assert( FALSE );
948         return NULL;
949     }
950     else
951     {
952         WORD ordinal;
953         static HMODULE32 hModule = 0;
954
955         if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
956         ordinal = MODULE_GetOrdinal( hModule, name );
957         if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
958         {            
959             fprintf( stderr, "GetWndProc16: %s not found\n", name );
960             assert( FALSE );
961         }
962     }
963     return ret;
964 }
965
966
967 /***********************************************************************
968  *           MODULE_GetModuleName
969  */
970 LPSTR MODULE_GetModuleName( HMODULE32 hModule )
971 {
972     NE_MODULE *pModule;
973     BYTE *p, len;
974     static char buffer[10];
975
976     if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
977     p = (BYTE *)pModule + pModule->name_table;
978     len = MIN( *p, 8 );
979     memcpy( buffer, p + 1, len );
980     buffer[len] = '\0';
981     return buffer;
982 }
983
984
985 /**********************************************************************
986  *           MODULE_RegisterModule
987  */
988 void MODULE_RegisterModule( NE_MODULE *pModule )
989 {
990     pModule->next = hFirstModule;
991     hFirstModule = pModule->self;
992 }
993
994
995 /**********************************************************************
996  *          MODULE_FindModule
997  *
998  * Find a module from a path name.
999  */
1000 HMODULE32 MODULE_FindModule( LPCSTR path )
1001 {
1002     HMODULE32 hModule = hFirstModule;
1003     LPCSTR filename, dotptr, modulepath, modulename;
1004     BYTE len, *name_table;
1005
1006     if (!(filename = strrchr( path, '\\' ))) filename = path;
1007     else filename++;
1008     if ((dotptr = strrchr( filename, '.' )) != NULL)
1009         len = (BYTE)(dotptr - filename);
1010     else len = strlen( filename );
1011
1012     while(hModule)
1013     {
1014         NE_MODULE *pModule = MODULE_GetPtr( hModule );
1015         if (!pModule) break;
1016         modulepath = NE_MODULE_NAME(pModule);
1017         if (!(modulename = strrchr( modulepath, '\\' )))
1018             modulename = modulepath;
1019         else modulename++;
1020         if (!lstrcmpi32A( modulename, filename )) return hModule;
1021
1022         name_table = (BYTE *)pModule + pModule->name_table;
1023         if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
1024             return hModule;
1025         hModule = pModule->next;
1026     }
1027     return 0;
1028 }
1029
1030
1031 /**********************************************************************
1032  *          MODULE_CallWEP
1033  *
1034  * Call a DLL's WEP, allowing it to shut down.
1035  * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
1036  */
1037 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
1038 {
1039     FARPROC16 WEP = (FARPROC16)0;
1040     WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
1041
1042     if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
1043     if (!WEP)
1044     {
1045         dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
1046         return FALSE;
1047     }
1048     return Callbacks->CallWindowsExitProc( WEP, WEP_FREE_DLL );
1049 }
1050
1051
1052 /**********************************************************************
1053  *          MODULE_FreeModule
1054  *
1055  * Remove a module from memory.
1056  */
1057 BOOL16 MODULE_FreeModule( HMODULE32 hModule, TDB* pTaskContext )
1058 {
1059     HMODULE16 *hPrevModule;
1060     NE_MODULE *pModule;
1061     SEGTABLEENTRY *pSegment;
1062     HMODULE16 *pModRef;
1063     int i;
1064
1065     if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1066     hModule = pModule->self;
1067
1068     if (((INT16)(--pModule->count)) > 0 ) return TRUE;
1069     else pModule->count = 0;
1070
1071     if (pModule->flags & NE_FFLAGS_BUILTIN)
1072         return FALSE;  /* Can't free built-in module */
1073
1074     if (pModule->flags & NE_FFLAGS_LIBMODULE) 
1075     {
1076         MODULE_CallWEP( hModule );
1077
1078         /* Free the objects owned by the DLL module */
1079
1080         if( pTaskContext && pTaskContext->userhandler )
1081         {
1082             pTaskContext->userhandler( hModule, USIG_DLL_UNLOAD, 0,
1083                                        pTaskContext->hInstance,
1084                                        pTaskContext->hQueue );
1085         }
1086     }
1087     /* Clear magic number just in case */
1088
1089     pModule->magic = pModule->self = 0;
1090
1091       /* Remove it from the linked list */
1092
1093     hPrevModule = &hFirstModule;
1094     while (*hPrevModule && (*hPrevModule != hModule))
1095     {
1096         hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
1097     }
1098     if (*hPrevModule) *hPrevModule = pModule->next;
1099
1100       /* Free all the segments */
1101
1102     pSegment = NE_SEG_TABLE( pModule );
1103     for (i = 1; i <= pModule->seg_count; i++, pSegment++)
1104     {
1105         GlobalFree16( pSegment->selector );
1106     }
1107
1108       /* Free the referenced modules */
1109
1110     pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
1111     for (i = 0; i < pModule->modref_count; i++, pModRef++)
1112     {
1113         FreeModule16( *pModRef );
1114     }
1115
1116       /* Free the module storage */
1117
1118     if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
1119     if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
1120     GlobalFree16( hModule );
1121
1122       /* Remove module from cache */
1123
1124     if (hCachedModule == hModule) hCachedModule = 0;
1125
1126     return TRUE;
1127 }
1128
1129
1130 /**********************************************************************
1131  *          MODULE_Load
1132  *
1133  * Implementation of LoadModule()
1134  */
1135 HINSTANCE16 MODULE_Load( LPCSTR name, LPVOID paramBlock, UINT16 uFlags)
1136 {
1137     HMODULE32 hModule;
1138     HINSTANCE16 hInstance, hPrevInstance;
1139     NE_MODULE *pModule;
1140     LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1141     OFSTRUCT ofs;
1142     HFILE32 hFile;
1143
1144     if (__winelib)
1145     {
1146         lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
1147         if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
1148         pModule = (NE_MODULE *)GlobalLock16( hModule );
1149         hPrevInstance = 0;
1150         hInstance = MODULE_CreateInstance( hModule, params );
1151     }
1152     else
1153     {
1154         hModule = MODULE_FindModule( name );
1155
1156         if (!hModule)  /* We have to load the module */
1157         {
1158             /* Try to load the built-in first if not disabled */
1159             if ((hModule = BUILTIN_LoadModule( name, FALSE )))
1160                 return MODULE_HANDLEtoHMODULE16( hModule );
1161             
1162             if ((hFile = OpenFile32( name, &ofs, OF_READ )) == HFILE_ERROR32)
1163             {
1164                 /* Now try the built-in even if disabled */
1165                 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
1166                 {
1167                     fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1168                     return MODULE_HANDLEtoHMODULE16( hModule );
1169                 }
1170                 return 2;  /* File not found */
1171             }
1172
1173             /* Create the module structure */
1174
1175             hModule = MODULE_LoadExeHeader( hFile, &ofs );
1176             if (hModule < 32)
1177             {
1178                 if (hModule == 21)
1179                     hModule = PE_LoadModule( hFile, &ofs, paramBlock );
1180                 else _lclose32( hFile );
1181
1182                 if (hModule < 32)
1183                     fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1184                              name, hModule );
1185                 return hModule;
1186             }
1187             _lclose32( hFile );
1188             pModule = MODULE_GetPtr( hModule );
1189             pModule->flags |= uFlags; /* stamp implicitly loaded modules */
1190
1191             /* Allocate the segments for this module */
1192
1193             MODULE_CreateSegments( hModule );
1194             hPrevInstance = 0;
1195             hInstance = MODULE_CreateInstance(hModule,(LOADPARAMS*)paramBlock);
1196
1197             /* Load the referenced DLLs */
1198
1199             if (!NE_LoadDLLs( pModule )) return 2;  /* File not found */
1200
1201             /* Load the segments */
1202
1203             NE_LoadAllSegments( pModule );
1204
1205             /* Fixup the functions prologs */
1206
1207             NE_FixupPrologs( pModule );
1208
1209             /* Make sure the usage count is 1 on the first loading of  */
1210             /* the module, even if it contains circular DLL references */
1211
1212             pModule->count = 1;
1213
1214             /* Call initialization rountines for all loaded DLLs. Note that
1215              * when we load implicitly linked DLLs this will be done by InitTask().
1216              */
1217
1218             if ((pModule->flags & (NE_FFLAGS_LIBMODULE | NE_FFLAGS_IMPLICIT)) ==
1219                                        NE_FFLAGS_LIBMODULE )
1220                 NE_InitializeDLLs( hModule );
1221         }
1222         else /* module is already loaded, just create a new data segment if it's a task */
1223         {
1224             pModule = MODULE_GetPtr( hModule );
1225             hPrevInstance = MODULE_GetInstance( hModule );
1226             hInstance = MODULE_CreateInstance( hModule, params );
1227             if (hInstance != hPrevInstance)  /* not a library */
1228                 NE_LoadSegment( pModule, pModule->dgroup );
1229             pModule->count++;
1230         }
1231     } /* !winelib */
1232
1233     /* Create a task for this instance */
1234
1235     if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1236     {
1237         HTASK16 hTask;
1238         WORD    showcmd;
1239
1240         pModule->flags |= NE_FFLAGS_GUI;
1241
1242         /* PowerPoint passes NULL as showCmd */
1243         if (params->showCmd)
1244                 showcmd = *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1);
1245         else
1246                 showcmd = 0; /* FIXME: correct */
1247
1248         hTask = TASK_CreateTask( hModule, hInstance, hPrevInstance,
1249                                  params->hEnvironment,
1250                                 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1251                                  showcmd );
1252
1253         if( hTask && TASK_GetNextTask(hTask)) Yield16();
1254     }
1255
1256     return hInstance;
1257 }
1258
1259
1260 /**********************************************************************
1261  *          LoadModule16    (KERNEL.45)
1262  */
1263 HINSTANCE16 LoadModule16( LPCSTR name, LPVOID paramBlock )
1264 {
1265     return MODULE_Load( name, paramBlock, 0 );
1266 }
1267
1268 /**********************************************************************
1269  *          LoadModule32    (KERNEL32)
1270  * FIXME: check this function
1271  */
1272 DWORD LoadModule32( LPCSTR name, LPVOID paramBlock ) 
1273 {
1274     return MODULE_Load( name, paramBlock, 0 );
1275 }
1276
1277
1278 /**********************************************************************
1279  *          FreeModule16    (KERNEL.46)
1280  */
1281 BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
1282 {
1283     NE_MODULE *pModule;
1284
1285     if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1286     dprintf_module( stddeb, "FreeModule16: %s count %d\n", 
1287                     MODULE_GetModuleName(hModule), pModule->count );
1288
1289     return MODULE_FreeModule( hModule, GlobalLock16(GetCurrentTask()) );
1290 }
1291
1292
1293 /**********************************************************************
1294  *          GetModuleHandle16    (KERNEL.47)
1295  */
1296 HMODULE16 WINAPI WIN16_GetModuleHandle( SEGPTR name )
1297 {
1298     if (HIWORD(name) == 0) return MODULE_HANDLEtoHMODULE16( (HINSTANCE16)name );
1299     return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1300 }
1301
1302 HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
1303 {
1304     return MODULE_FindModule( name );
1305 }
1306
1307 /***********************************************************************
1308  *              GetModuleHandle         (KERNEL32.237)
1309  */
1310 HMODULE32 WINAPI GetModuleHandle32A(LPCSTR module)
1311 {
1312     HMODULE32   hModule;
1313
1314     dprintf_win32(stddeb, "GetModuleHandleA: %s\n", module ? module : "NULL");
1315 /* Freecell uses the result of GetModuleHandleA(0) as the hInstance in
1316 all calls to e.g. CreateWindowEx. */
1317     if (module == NULL) {
1318         TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1319         hModule = pTask->hInstance;
1320     } else
1321         hModule = MODULE_FindModule(module);
1322     return MODULE_HANDLEtoHMODULE32(hModule);
1323 }
1324
1325 HMODULE32 WINAPI GetModuleHandle32W(LPCWSTR module)
1326 {
1327     HMODULE32 hModule;
1328     LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
1329     hModule = GetModuleHandle32A( modulea );
1330     HeapFree( GetProcessHeap(), 0, modulea );
1331     return hModule;
1332 }
1333
1334
1335 /**********************************************************************
1336  *          GetModuleUsage    (KERNEL.48)
1337  */
1338 INT16 WINAPI GetModuleUsage( HINSTANCE16 hModule )
1339 {
1340     NE_MODULE *pModule;
1341
1342     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1343     dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1344                     hModule, pModule->count );
1345     return pModule->count;
1346 }
1347
1348
1349 /**********************************************************************
1350  *          GetModuleFileName16    (KERNEL.49)
1351  */
1352 INT16 WINAPI GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName,
1353                                   INT16 nSize )
1354 {
1355     NE_MODULE *pModule;
1356
1357     if (!hModule) hModule = GetCurrentTask();
1358     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1359     lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1360     dprintf_module( stddeb, "GetModuleFileName16: %s\n", lpFileName );
1361     return strlen(lpFileName);
1362 }
1363
1364
1365 /***********************************************************************
1366  *              GetModuleFileName32A      (KERNEL32.235)
1367  */
1368 DWORD WINAPI GetModuleFileName32A( HMODULE32 hModule, LPSTR lpFileName,
1369                                    DWORD size )
1370 {                   
1371     NE_MODULE *pModule;
1372            
1373     if (!hModule)
1374     {
1375         TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1376         hModule = pTask->hInstance;
1377     }
1378     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1379     lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), size );
1380     dprintf_module( stddeb, "GetModuleFileName32A: %s\n", lpFileName );
1381     return strlen(lpFileName);
1382 }                   
1383  
1384
1385 /***********************************************************************
1386  *              GetModuleFileName32W      (KERNEL32.236)
1387  */
1388 DWORD WINAPI GetModuleFileName32W( HMODULE32 hModule, LPWSTR lpFileName,
1389                                    DWORD size )
1390 {
1391     LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1392     DWORD res = GetModuleFileName32A( hModule, fnA, size );
1393     lstrcpynAtoW( lpFileName, fnA, size );
1394     HeapFree( GetProcessHeap(), 0, fnA );
1395     return res;
1396 }
1397
1398
1399 /**********************************************************************
1400  *          GetModuleName    (KERNEL.27)
1401  */
1402 BOOL16 WINAPI GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 nSize )
1403 {
1404     LPSTR name = MODULE_GetModuleName(hinst);
1405
1406     if (!name) return FALSE;
1407     lstrcpyn32A( buf, name, nSize );
1408     return TRUE;
1409 }
1410
1411
1412 /***********************************************************************
1413  *           LoadLibraryEx32W   (KERNEL.513)
1414  * FIXME
1415  */
1416 HMODULE32 WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
1417                                        DWORD flags )
1418 {
1419     fprintf(stderr,"LoadLibraryEx32W(%s,%d,%08lx)\n",libname,hf,flags);
1420     return LoadLibraryEx32A(libname,hf,flags);
1421 }
1422
1423 /***********************************************************************
1424  *           LoadLibraryEx32A   (KERNEL32)
1425  */
1426 HMODULE32 WINAPI LoadLibraryEx32A(LPCSTR libname,HFILE32 hfile,DWORD flags)
1427 {
1428     HMODULE32 hmod;
1429     
1430     hmod = PE_LoadLibraryEx32A(libname,hfile,flags);
1431     if (hmod <= 32) {
1432         char buffer[256];
1433
1434         strcpy( buffer, libname );
1435         strcat( buffer, ".dll" );
1436         hmod = PE_LoadLibraryEx32A(buffer,hfile,flags);
1437     }
1438     /* initialize all DLLs, which haven't been initialized yet. */
1439     PE_InitializeDLLs( GetCurrentProcessId(), DLL_PROCESS_ATTACH, NULL);
1440     return hmod;
1441 }
1442
1443 /***********************************************************************
1444  *           LoadLibraryA         (KERNEL32)
1445  */
1446 HMODULE32 WINAPI LoadLibrary32A(LPCSTR libname) {
1447         return LoadLibraryEx32A(libname,0,0);
1448 }
1449
1450 /***********************************************************************
1451  *           LoadLibraryW         (KERNEL32)
1452  */
1453 HMODULE32 WINAPI LoadLibrary32W(LPCWSTR libnameW)
1454 {
1455     return LoadLibraryEx32W(libnameW,0,0);
1456 }
1457
1458 /***********************************************************************
1459  *           LoadLibraryExW       (KERNEL32)
1460  */
1461 HMODULE32 WINAPI LoadLibraryEx32W(LPCWSTR libnameW,HFILE32 hfile,DWORD flags)
1462 {
1463     LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
1464     HMODULE32 ret = LoadLibraryEx32A( libnameA , hfile, flags );
1465
1466     HeapFree( GetProcessHeap(), 0, libnameA );
1467     return ret;
1468 }
1469
1470 /***********************************************************************
1471  *           FreeLibrary
1472  */
1473 BOOL32 WINAPI FreeLibrary32(HINSTANCE32 hLibModule)
1474 {
1475         fprintf(stderr,"FreeLibrary: empty stub\n");
1476         return TRUE;
1477 }
1478
1479
1480 /***********************************************************************
1481  *           LoadLibrary   (KERNEL.95)
1482  */
1483 HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
1484 {
1485     HINSTANCE16 handle;
1486
1487     if (__winelib)
1488     {
1489         fprintf( stderr, "LoadLibrary not supported in Winelib\n" );
1490         return 0;
1491     }
1492     dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1493
1494     handle = MODULE_Load( libname, (LPVOID)-1, 0 );
1495     if (handle == (HINSTANCE16)2)  /* file not found */
1496     {
1497         char buffer[256];
1498         lstrcpyn32A( buffer, libname, 252 );
1499         strcat( buffer, ".dll" );
1500         handle = MODULE_Load( buffer, (LPVOID)-1, 0 );
1501     }
1502     return handle;
1503 }
1504
1505
1506 /***********************************************************************
1507  *           PrivateLoadLibrary       (KERNEL32)
1508  *
1509  * FIXME: rough guesswork, don't know what "Private" means
1510  */
1511 HMODULE32 WINAPI PrivateLoadLibrary(LPCSTR libname)
1512 {
1513         return LoadLibrary16(libname);
1514 }
1515
1516
1517 /***********************************************************************
1518  *           FreeLibrary16   (KERNEL.96)
1519  */
1520 void WINAPI FreeLibrary16( HINSTANCE16 handle )
1521 {
1522     dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1523     FreeModule16( handle );
1524 }
1525
1526
1527 /***********************************************************************
1528  *           PrivateFreeLibrary       (KERNEL32)
1529  *
1530  * FIXME: rough guesswork, don't know what "Private" means
1531  */
1532 void WINAPI PrivateFreeLibrary(HMODULE32 handle)
1533 {
1534         FreeLibrary16(handle);
1535 }
1536
1537
1538 /***********************************************************************
1539  *           WinExec16   (KERNEL.166)
1540  */
1541 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
1542 {
1543     return WinExec32( lpCmdLine, nCmdShow );
1544 }
1545
1546
1547 /***********************************************************************
1548  *           WinExec32   (KERNEL32.566)
1549  */
1550 HINSTANCE32 WINAPI WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow )
1551 {
1552     LOADPARAMS params;
1553     HGLOBAL16 cmdShowHandle, cmdLineHandle;
1554     HINSTANCE16 handle = 2;
1555     WORD *cmdShowPtr;
1556     char *p, *cmdline, filename[256];
1557     static int use_load_module = 1;
1558     int  spacelimit = 0, exhausted = 0;
1559
1560     if (!lpCmdLine)
1561         return 2;  /* File not found */
1562     if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1563         return 8;  /* Out of memory */
1564     if (!(cmdLineHandle = GlobalAlloc16( 0, 2048 )))
1565     {
1566         GlobalFree16( cmdShowHandle );
1567         return 8;  /* Out of memory */
1568     }
1569
1570     /* Keep trying to load a file by trying different filenames; e.g.,
1571        for the cmdline "abcd efg hij", try "abcd" with args "efg hij",
1572        then "abcd efg" with arg "hij", and finally "abcd efg hij" with
1573        no args */
1574
1575     while(!exhausted && handle == 2) {
1576         int spacecount = 0;
1577
1578         /* Store nCmdShow */
1579
1580         cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1581         cmdShowPtr[0] = 2;
1582         cmdShowPtr[1] = nCmdShow;
1583
1584         /* Build the filename and command-line */
1585
1586         cmdline = (char *)GlobalLock16( cmdLineHandle );
1587         lstrcpyn32A(filename, lpCmdLine,
1588                     sizeof(filename) - 4 /* for extension */);
1589
1590         /* Keep grabbing characters until end-of-string, tab, or until the
1591            number of spaces is greater than the spacelimit */
1592
1593         for (p = filename; ; p++) {
1594             if(*p == ' ') {
1595                 ++spacecount;
1596                 if(spacecount > spacelimit) {
1597                     ++spacelimit;
1598                     break;
1599                 }
1600             }
1601
1602             if(*p == '\0' || *p == '\t') {
1603                 exhausted = 1;
1604                 break;
1605             }
1606         }
1607
1608         if (*p)
1609             lstrcpyn32A( cmdline + 1, p + 1, 255 );
1610         else
1611             cmdline[1] = '\0';
1612
1613         cmdline[0] = strlen( cmdline + 1 );
1614         *p = '\0';
1615         /* this is a (hopefully acceptable hack to get the whole
1616            commandline for PROCESS_Create
1617            we put it after the processed one */
1618         lstrcpyn32A(cmdline + (unsigned char)cmdline[0] +2,
1619                     lpCmdLine, 2048 - 256);
1620
1621         /* Now load the executable file */
1622
1623         if (use_load_module)
1624         {
1625             /* Winelib: Use LoadModule() only for the program itself */
1626             if (__winelib) use_load_module = 0;
1627             params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() );
1628             params.cmdLine  = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1629             params.showCmd  = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1630             params.reserved = 0;
1631             handle = LoadModule16( filename, &params );
1632             if (handle == 2)  /* file not found */
1633             {
1634                 /* Check that the original file name did not have a suffix */
1635                 p = strrchr(filename, '.');
1636                 /* if there is a '.', check if either \ OR / follow */
1637                 if (!p || strchr(p, '/') || strchr(p, '\\'))
1638                 {
1639                     p = filename + strlen(filename);
1640                     strcpy( p, ".exe" );
1641                     handle = LoadModule16( filename, &params );
1642                     *p = '\0';  /* Remove extension */
1643                 }
1644             }
1645         }
1646         else
1647             handle = 2; /* file not found */
1648
1649         if (handle < 32)
1650         {
1651             /* Try to start it as a unix program */
1652             if (!fork())
1653             {
1654                 /* Child process */
1655                 DOS_FULL_NAME full_name;
1656                 const char *unixfilename = NULL;
1657                 const char *argv[256], **argptr;
1658                 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1659                               nCmdShow == SW_SHOWMINNOACTIVE);
1660
1661                 /* get unixfilename */
1662                 if (strchr(filename, '/') ||
1663                     strchr(filename, ':') ||
1664                     strchr(filename, '\\'))
1665                 {
1666                     if (DOSFS_GetFullName( filename, TRUE, &full_name ))
1667                         unixfilename = full_name.long_name;
1668                 }
1669                 else unixfilename = filename;
1670
1671                 if (unixfilename)
1672                 {
1673                     /* build argv */
1674                     argptr = argv;
1675                     if (iconic) *argptr++ = "-iconic";
1676                     *argptr++ = unixfilename;
1677                     p = cmdline + 1;
1678                     while (1)
1679                     {
1680                         while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1681                         if (!*p) break;
1682                         *argptr++ = p;
1683                         while (*p && *p != ' ' && *p != '\t') p++;
1684                     }
1685                     *argptr++ = 0;
1686
1687                     /* Execute */
1688                     execvp(argv[0], (char**)argv);
1689                 }
1690
1691                 /* Failed ! */
1692
1693                 if (__winelib)
1694                 {
1695                     /* build argv */
1696                     argptr = argv;
1697                     *argptr++ = "wine";
1698                     if (iconic) *argptr++ = "-iconic";
1699                     *argptr++ = lpCmdLine;
1700                     *argptr++ = 0;
1701
1702                     /* Execute */
1703                     execvp(argv[0] , (char**)argv);
1704
1705                     /* Failed ! */
1706                     fprintf(stderr, "WinExec: can't exec 'wine %s'\n",
1707                             lpCmdLine);
1708                 }
1709                 exit(1);
1710             }
1711         }
1712     } /* while (!exhausted && handle < 32) */
1713
1714     GlobalFree16( cmdShowHandle );
1715     GlobalFree16( cmdLineHandle );
1716     return handle;
1717 }
1718
1719
1720 /***********************************************************************
1721  *           WIN32_GetProcAddress16   (KERNEL32.36)
1722  * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1723  */
1724 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE32 hModule, LPSTR name )
1725 {
1726     WORD        ordinal;
1727     FARPROC16   ret;
1728
1729     if (!hModule) {
1730         fprintf(stderr,"WIN32_GetProcAddress16: hModule may not be 0!\n");
1731         return (FARPROC16)0;
1732     }
1733     hModule = MODULE_HANDLEtoHMODULE16(hModule);
1734     if (HIWORD(name)) {
1735         ordinal = MODULE_GetOrdinal( hModule, name );
1736         dprintf_module( stddeb, "WIN32_GetProcAddress16: %04x '%s'\n",
1737                         hModule, name );
1738     } else {
1739         ordinal = LOWORD(name);
1740         dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1741                         hModule, ordinal );
1742     }
1743     if (!ordinal) return (FARPROC16)0;
1744     ret = MODULE_GetEntryPoint( hModule, ordinal );
1745     dprintf_module(stddeb,"WIN32_GetProcAddress16: returning %08x\n",(UINT32)ret);
1746     return ret;
1747 }
1748
1749 /***********************************************************************
1750  *           GetProcAddress16   (KERNEL.50)
1751  */
1752 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1753 {
1754     WORD ordinal;
1755     FARPROC16 ret;
1756
1757     if (!hModule) hModule = GetCurrentTask();
1758     hModule = MODULE_HANDLEtoHMODULE16( hModule );
1759
1760     if (HIWORD(name) != 0)
1761     {
1762         ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1763         dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1764                         hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1765     }
1766     else
1767     {
1768         ordinal = LOWORD(name);
1769         dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1770                         hModule, ordinal );
1771     }
1772     if (!ordinal) return (FARPROC16)0;
1773
1774     ret = MODULE_GetEntryPoint( hModule, ordinal );
1775
1776     dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1777     return ret;
1778 }
1779
1780
1781 /***********************************************************************
1782  *           GetProcAddress32   (KERNEL32.257)
1783  */
1784 FARPROC32 WINAPI GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1785 {
1786     NE_MODULE *pModule;
1787
1788     if (HIWORD(function))
1789         dprintf_win32(stddeb,"GetProcAddress32(%08lx,%s)\n",(DWORD)hModule,function);
1790     else
1791         dprintf_win32(stddeb,"GetProcAddress32(%08lx,%p)\n",(DWORD)hModule,function);
1792     if (!(pModule = MODULE_GetPtr( hModule )))
1793         return (FARPROC32)0;
1794     if (!pModule->module32)
1795     {
1796         fprintf(stderr,"Oops, Module 0x%08lx has got no module32?\n",
1797                 (DWORD)MODULE_HANDLEtoHMODULE32(hModule)
1798         );
1799         return (FARPROC32)0;
1800     }
1801     return PE_FindExportedFunction( pModule->module32, function );
1802 }
1803
1804 /***********************************************************************
1805  *           RtlImageNtHeaders   (NTDLL)
1806  */
1807 LPIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE32 hModule)
1808 {
1809     /* basically:
1810      * return  hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew); 
1811      * but we could get HMODULE16 or the like (think builtin modules)
1812      */
1813
1814     NE_MODULE *pModule;
1815
1816     if (!(pModule = MODULE_GetPtr( hModule )))
1817         return (LPIMAGE_NT_HEADERS)0;
1818     if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->module32)
1819         return (LPIMAGE_NT_HEADERS)0;
1820     return PE_HEADER(pModule->module32);
1821 }
1822
1823
1824 /**********************************************************************
1825  *          GetExpWinVer    (KERNEL.167)
1826  */
1827 WORD WINAPI GetExpWinVer( HMODULE16 hModule )
1828 {
1829     NE_MODULE *pModule = MODULE_GetPtr( hModule );
1830     return pModule ? pModule->expected_version : 0;
1831 }
1832
1833
1834 /**********************************************************************
1835  *          IsSharedSelector    (KERNEL.345)
1836  */
1837 BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
1838 {
1839     /* Check whether the selector belongs to a DLL */
1840     NE_MODULE *pModule = MODULE_GetPtr( selector );
1841     if (!pModule) return FALSE;
1842     return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
1843 }
1844
1845
1846 /**********************************************************************
1847  *          ModuleFirst    (TOOLHELP.59)
1848  */
1849 BOOL16 WINAPI ModuleFirst( MODULEENTRY *lpme )
1850 {
1851     lpme->wNext = hFirstModule;
1852     return ModuleNext( lpme );
1853 }
1854
1855
1856 /**********************************************************************
1857  *          ModuleNext    (TOOLHELP.60)
1858  */
1859 BOOL16 WINAPI ModuleNext( MODULEENTRY *lpme )
1860 {
1861     NE_MODULE *pModule;
1862     char *name;
1863
1864     if (!lpme->wNext) return FALSE;
1865     if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1866     name = (char *)pModule + pModule->name_table;
1867     memcpy( lpme->szModule, name + 1, *name );
1868     lpme->szModule[(BYTE)*name] = '\0';
1869     lpme->hModule = lpme->wNext;
1870     lpme->wcUsage = pModule->count;
1871     strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1872     lpme->szExePath[MAX_PATH] = '\0';
1873     lpme->wNext = pModule->next;
1874     return TRUE;
1875 }
1876
1877
1878 /**********************************************************************
1879  *          ModuleFindName    (TOOLHELP.61)
1880  */
1881 BOOL16 WINAPI ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1882 {
1883     lpme->wNext = GetModuleHandle16( name );
1884     return ModuleNext( lpme );
1885 }
1886
1887
1888 /**********************************************************************
1889  *          ModuleFindHandle    (TOOLHELP.62)
1890  */
1891 BOOL16 WINAPI ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1892 {
1893     hModule = MODULE_HANDLEtoHMODULE16( hModule );
1894     lpme->wNext = hModule;
1895     return ModuleNext( lpme );
1896 }