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