~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/kernel32/ne_module.c

Version: ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * NE modules
  3  *
  4  * Copyright 1995 Alexandre Julliard
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #include "config.h"
 22 #include "wine/port.h"
 23 
 24 #include <assert.h>
 25 #include <fcntl.h>
 26 #include <stdarg.h>
 27 #include <stdio.h>
 28 #include <stdlib.h>
 29 #include <string.h>
 30 #ifdef HAVE_UNISTD_H
 31 # include <unistd.h>
 32 #endif
 33 #include <ctype.h>
 34 
 35 #include "windef.h"
 36 #include "wine/winbase16.h"
 37 #include "wownt32.h"
 38 #include "winternl.h"
 39 #include "toolhelp.h"
 40 #include "kernel_private.h"
 41 #include "kernel16_private.h"
 42 #include "wine/exception.h"
 43 #include "wine/debug.h"
 44 
 45 WINE_DEFAULT_DEBUG_CHANNEL(module);
 46 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
 47 WINE_DECLARE_DEBUG_CHANNEL(relay);
 48 
 49 #include "pshpack1.h"
 50 typedef struct _GPHANDLERDEF
 51 {
 52     WORD selector;
 53     WORD rangeStart;
 54     WORD rangeEnd;
 55     WORD handler;
 56 } GPHANDLERDEF;
 57 #include "poppack.h"
 58 
 59 /*
 60  * Segment table entry
 61  */
 62 struct ne_segment_table_entry_s
 63 {
 64     WORD seg_data_offset;   /* Sector offset of segment data    */
 65     WORD seg_data_length;   /* Length of segment data           */
 66     WORD seg_flags;         /* Flags associated with this segment       */
 67     WORD min_alloc;         /* Minimum allocation size for this */
 68 };
 69 
 70 #define hFirstModule (pThhook->hExeHead)
 71 
 72 struct builtin_dll
 73 {
 74     const IMAGE_DOS_HEADER *header;      /* module headers */
 75     const char             *file_name;   /* module file name */
 76 };
 77 
 78 /* Table of all built-in DLLs */
 79 
 80 #define MAX_DLLS 50
 81 
 82 static struct builtin_dll builtin_dlls[MAX_DLLS];
 83 
 84 static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only );
 85 static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep );
 86 
 87 static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only );
 88 
 89 static HMODULE16 NE_GetModuleByFilename( LPCSTR name );
 90 
 91 
 92 /* patch all the flat cs references of the code segment if necessary */
 93 static inline void patch_code_segment( NE_MODULE *pModule )
 94 {
 95 #ifdef __i386__
 96     int i;
 97     CALLFROM16 *call;
 98     SEGTABLEENTRY *pSeg = NE_SEG_TABLE( pModule );
 99 
100     for (i = 0; i < pModule->ne_cseg; i++, pSeg++)
101         if (!(pSeg->flags & NE_SEGFLAGS_DATA)) break;  /* found the code segment */
102 
103     call = GlobalLock16( pSeg->hSeg );
104 
105     /* patch glue code address and code selector */
106     for (i = 0; call[i].pushl == 0x68; i++)
107     {
108         if (call[i].ret[0] == 0xca66 || call[i].ret[0] == 0xcb66)  /* register entry point? */
109             call[i].glue = __wine_call_from_16_regs;
110         else
111             call[i].glue = __wine_call_from_16;
112         call[i].flatcs = wine_get_cs();
113     }
114 
115     if (TRACE_ON(relay))  /* patch relay functions to all point to relay_call_from_16 */
116         for (i = 0; call[i].pushl == 0x68; i++) call[i].relay = relay_call_from_16;
117 #endif
118 }
119 
120 
121 /***********************************************************************
122  *              NE_strcasecmp
123  *
124  * locale-independent case conversion for module lookups
125  */
126 static int NE_strcasecmp( const char *str1, const char *str2 )
127 {
128     int ret = 0;
129     for ( ; ; str1++, str2++)
130         if ((ret = RtlUpperChar(*str1) - RtlUpperChar(*str2)) || !*str1) break;
131     return ret;
132 }
133 
134 
135 /***********************************************************************
136  *              NE_strncasecmp
137  *
138  * locale-independent case conversion for module lookups
139  */
140 static int NE_strncasecmp( const char *str1, const char *str2, int len )
141 {
142     int ret = 0;
143     for ( ; len > 0; len--, str1++, str2++)
144         if ((ret = RtlUpperChar(*str1) - RtlUpperChar(*str2)) || !*str1) break;
145     return ret;
146 }
147 
148 
149 /***********************************************************************
150  *           find_dll_descr
151  *
152  * Find a descriptor in the list
153  */
154 static const IMAGE_DOS_HEADER *find_dll_descr( const char *dllname, const char **file_name )
155 {
156     int i;
157     const IMAGE_DOS_HEADER *mz_header;
158     const IMAGE_OS2_HEADER *ne_header;
159     const BYTE *name_table;
160 
161     for (i = 0; i < MAX_DLLS; i++)
162     {
163         mz_header = builtin_dlls[i].header;
164         if (mz_header)
165         {
166             ne_header = (const IMAGE_OS2_HEADER *)((const char *)mz_header + mz_header->e_lfanew);
167             name_table = (const BYTE *)ne_header + ne_header->ne_restab;
168 
169             /* check the dll file name */
170             if (!NE_strcasecmp( builtin_dlls[i].file_name, dllname ) ||
171             /* check the dll module name (without extension) */
172                 (!NE_strncasecmp( dllname, (const char*)name_table+1, *name_table ) &&
173                  !strcmp( dllname + *name_table, ".dll" )))
174             {
175                 *file_name = builtin_dlls[i].file_name;
176                 return builtin_dlls[i].header;
177             }
178         }
179     }
180     return NULL;
181 }
182 
183 
184 /***********************************************************************
185  *           __wine_dll_register_16 (KERNEL32.@)
186  *
187  * Register a built-in DLL descriptor.
188  */
189 void __wine_dll_register_16( const IMAGE_DOS_HEADER *header, const char *file_name )
190 {
191     int i;
192 
193     for (i = 0; i < MAX_DLLS; i++)
194     {
195         if (builtin_dlls[i].header) continue;
196         builtin_dlls[i].header = header;
197         builtin_dlls[i].file_name = file_name;
198         break;
199     }
200     assert( i < MAX_DLLS );
201 }
202 
203 
204 /***********************************************************************
205  *           __wine_dll_unregister_16 (KERNEL32.@)
206  *
207  * Unregister a built-in DLL descriptor.
208  */
209 void __wine_dll_unregister_16( const IMAGE_DOS_HEADER *header )
210 {
211     int i;
212 
213     for (i = 0; i < MAX_DLLS; i++)
214     {
215         if (builtin_dlls[i].header != header) continue;
216         builtin_dlls[i].header = NULL;
217         break;
218     }
219 }
220 
221 
222 /***********************************************************************
223  *           NE_GetPtr
224  */
225 NE_MODULE *NE_GetPtr( HMODULE16 hModule )
226 {
227     return (NE_MODULE *)GlobalLock16( GetExePtr(hModule) );
228 }
229 
230 
231 /**********************************************************************
232  *           NE_RegisterModule
233  */
234 static void NE_RegisterModule( NE_MODULE *pModule )
235 {
236     pModule->next = hFirstModule;
237     hFirstModule = pModule->self;
238 }
239 
240 
241 /***********************************************************************
242  *           NE_DumpModule
243  */
244 void NE_DumpModule( HMODULE16 hModule )
245 {
246     int i, ordinal;
247     SEGTABLEENTRY *pSeg;
248     BYTE *pstr;
249     WORD *pword;
250     NE_MODULE *pModule;
251     ET_BUNDLE *bundle;
252     ET_ENTRY *entry;
253 
254     if (!(pModule = NE_GetPtr( hModule )))
255     {
256         ERR( "**** %04x is not a module handle\n", hModule );
257         return;
258     }
259 
260       /* Dump the module info */
261     TRACE( "---\n" );
262     TRACE( "Module %04x:\n", hModule );
263     TRACE( "count=%d flags=%04x heap=%d stack=%d\n",
264              pModule->count, pModule->ne_flags,
265              pModule->ne_heap, pModule->ne_stack );
266     TRACE( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
267              SELECTOROF(pModule->ne_csip), OFFSETOF(pModule->ne_csip),
268              SELECTOROF(pModule->ne_sssp), OFFSETOF(pModule->ne_sssp),
269              pModule->ne_autodata, pModule->ne_cseg, pModule->ne_cmod );
270     TRACE( "os_flags=%d swap_area=%d version=%04x\n",
271              pModule->ne_exetyp, pModule->ne_swaparea, pModule->ne_expver );
272     if (pModule->ne_flags & NE_FFLAGS_WIN32)
273         TRACE( "PE module=%p\n", pModule->module32 );
274 
275       /* Dump the file info */
276     TRACE( "---\n" );
277     TRACE( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
278 
279       /* Dump the segment table */
280     TRACE( "---\n" );
281     TRACE( "Segment table:\n" );
282     pSeg = NE_SEG_TABLE( pModule );
283     for (i = 0; i < pModule->ne_cseg; i++, pSeg++)
284         TRACE( "%02x: pos=%d size=%d flags=%04x minsize=%d hSeg=%04x\n",
285                  i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
286                  pSeg->minsize, pSeg->hSeg );
287 
288       /* Dump the resource table */
289     TRACE( "---\n" );
290     TRACE( "Resource table:\n" );
291     if (pModule->ne_rsrctab)
292     {
293         pword = (WORD *)((BYTE *)pModule + pModule->ne_rsrctab);
294         TRACE( "Alignment: %d\n", *pword++ );
295         while (*pword)
296         {
297             NE_TYPEINFO *ptr = (NE_TYPEINFO *)pword;
298             NE_NAMEINFO *pname = (NE_NAMEINFO *)(ptr + 1);
299             TRACE( "id=%04x count=%d\n", ptr->type_id, ptr->count );
300             for (i = 0; i < ptr->count; i++, pname++)
301                 TRACE( "offset=%d len=%d id=%04x\n",
302                       pname->offset, pname->length, pname->id );
303             pword = (WORD *)pname;
304         }
305     }
306     else TRACE( "None\n" );
307 
308       /* Dump the resident name table */
309     TRACE( "---\n" );
310     TRACE( "Resident-name table:\n" );
311     pstr = (BYTE*) pModule + pModule->ne_restab;
312     while (*pstr)
313     {
314         TRACE( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
315                  *(WORD *)(pstr + *pstr + 1) );
316         pstr += *pstr + 1 + sizeof(WORD);
317     }
318 
319       /* Dump the module reference table */
320     TRACE( "---\n" );
321     TRACE( "Module ref table:\n" );
322     if (pModule->ne_modtab)
323     {
324         pword = (WORD *)((BYTE *)pModule + pModule->ne_modtab);
325         for (i = 0; i < pModule->ne_cmod; i++, pword++)
326         {
327             char name[10];
328             GetModuleName16( *pword, name, sizeof(name) );
329             TRACE( "%d: %04x -> '%s'\n", i, *pword, name );
330         }
331     }
332     else TRACE( "None\n" );
333 
334       /* Dump the entry table */
335     TRACE( "---\n" );
336     TRACE( "Entry table:\n" );
337     bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->ne_enttab);
338     do {
339         entry = (ET_ENTRY *)((BYTE *)bundle+6);
340         TRACE( "Bundle %d-%d: %02x\n", bundle->first, bundle->last, entry->type);
341         ordinal = bundle->first;
342         while (ordinal < bundle->last)
343         {
344             if (entry->type == 0xff)
345                 TRACE("%d: %02x:%04x (moveable)\n", ordinal++, entry->segnum, entry->offs);
346             else
347                 TRACE("%d: %02x:%04x (fixed)\n", ordinal++, entry->segnum, entry->offs);
348             entry++;
349         }
350     } while ( (bundle->next) && (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
351 
352     /* Dump the non-resident names table */
353     TRACE( "---\n" );
354     TRACE( "Non-resident names table:\n" );
355     if (pModule->nrname_handle)
356     {
357         pstr = GlobalLock16( pModule->nrname_handle );
358         while (*pstr)
359         {
360             TRACE( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
361                    *(WORD *)(pstr + *pstr + 1) );
362             pstr += *pstr + 1 + sizeof(WORD);
363         }
364     }
365     TRACE( "\n" );
366 }
367 
368 
369 /***********************************************************************
370  *           NE_WalkModules
371  *
372  * Walk the module list and print the modules.
373  */
374 void NE_WalkModules(void)
375 {
376     HMODULE16 hModule = hFirstModule;
377     MESSAGE( "Module Flags Name\n" );
378     while (hModule)
379     {
380         NE_MODULE *pModule = NE_GetPtr( hModule );
381         if (!pModule)
382         {
383             MESSAGE( "Bad module %04x in list\n", hModule );
384             return;
385         }
386         MESSAGE( " %04x  %04x  %.*s\n", hModule, pModule->ne_flags,
387                  *((char *)pModule + pModule->ne_restab),
388                  (char *)pModule + pModule->ne_restab + 1 );
389         hModule = pModule->next;
390     }
391 }
392 
393 
394 /***********************************************************************
395  *           NE_InitResourceHandler
396  *
397  * Fill in 'resloader' fields in the resource table.
398  */
399 static void NE_InitResourceHandler( HMODULE16 hModule )
400 {
401     static FARPROC16 proc;
402 
403     NE_TYPEINFO *pTypeInfo;
404     NE_MODULE *pModule;
405 
406     if (!(pModule = NE_GetPtr( hModule )) || !pModule->ne_rsrctab) return;
407 
408     TRACE("InitResourceHandler[%04x]\n", hModule );
409 
410     if (!proc) proc = GetProcAddress16( GetModuleHandle16("KERNEL"), "DefResourceHandler" );
411 
412     pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->ne_rsrctab + 2);
413     while(pTypeInfo->type_id)
414     {
415         memcpy_unaligned( &pTypeInfo->resloader, &proc, sizeof(FARPROC16) );
416         pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo + 1) + pTypeInfo->count * sizeof(NE_NAMEINFO));
417     }
418 }
419 
420 
421 /***********************************************************************
422  *           NE_GetOrdinal
423  *
424  * Lookup the ordinal for a given name.
425  */
426 WORD NE_GetOrdinal( HMODULE16 hModule, const char *name )
427 {
428     char buffer[256], *p;
429     BYTE *cpnt;
430     BYTE len;
431     NE_MODULE *pModule;
432 
433     if (!(pModule = NE_GetPtr( hModule ))) return 0;
434     if (pModule->ne_flags & NE_FFLAGS_WIN32) return 0;
435 
436     TRACE("(%04x,'%s')\n", hModule, name );
437 
438       /* First handle names of the form '#xxxx' */
439 
440     if (name[0] == '#') return atoi( name + 1 );
441 
442       /* Now copy and uppercase the string */
443 
444     strcpy( buffer, name );
445     for (p = buffer; *p; p++) *p = RtlUpperChar(*p);
446     len = p - buffer;
447 
448       /* First search the resident names */
449 
450     cpnt = (BYTE *)pModule + pModule->ne_restab;
451 
452       /* Skip the first entry (module name) */
453     cpnt += *cpnt + 1 + sizeof(WORD);
454     while (*cpnt)
455     {
456         if ((*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
457         {
458             WORD ordinal;
459             memcpy( &ordinal, cpnt + *cpnt + 1, sizeof(ordinal) );
460             TRACE("  Found: ordinal=%d\n", ordinal );
461             return ordinal;
462         }
463         cpnt += *cpnt + 1 + sizeof(WORD);
464     }
465 
466       /* Now search the non-resident names table */
467 
468     if (!pModule->nrname_handle) return 0;  /* No non-resident table */
469     cpnt = GlobalLock16( pModule->nrname_handle );
470 
471       /* Skip the first entry (module description string) */
472     cpnt += *cpnt + 1 + sizeof(WORD);
473     while (*cpnt)
474     {
475         if ((*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
476         {
477             WORD ordinal;
478             memcpy( &ordinal, cpnt + *cpnt + 1, sizeof(ordinal) );
479             TRACE("  Found: ordinal=%d\n", ordinal );
480             return ordinal;
481         }
482         cpnt += *cpnt + 1 + sizeof(WORD);
483     }
484     return 0;
485 }
486 
487 
488 /***********************************************************************
489  *              NE_GetEntryPoint
490  */
491 FARPROC16 WINAPI NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
492 {
493     return NE_GetEntryPointEx( hModule, ordinal, TRUE );
494 }
495 
496 /***********************************************************************
497  *              NE_GetEntryPointEx
498  */
499 FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop )
500 {
501     NE_MODULE *pModule;
502     WORD sel, offset, i;
503 
504     ET_ENTRY *entry;
505     ET_BUNDLE *bundle;
506 
507     if (!(pModule = NE_GetPtr( hModule ))) return 0;
508     assert( !(pModule->ne_flags & NE_FFLAGS_WIN32) );
509 
510     bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->ne_enttab);
511     while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
512     {
513         if (!(bundle->next))
514             return 0;
515         bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
516     }
517 
518     entry = (ET_ENTRY *)((BYTE *)bundle+6);
519     for (i=0; i < (ordinal - bundle->first - 1); i++)
520         entry++;
521 
522     sel = entry->segnum;
523     memcpy( &offset, &entry->offs, sizeof(WORD) );
524 
525     if (sel == 0xfe) sel = 0xffff;  /* constant entry */
526     else sel = GlobalHandleToSel16(NE_SEG_TABLE(pModule)[sel-1].hSeg);
527     if (sel==0xffff)
528         return (FARPROC16)MAKESEGPTR( sel, offset );
529     if (!snoop)
530         return (FARPROC16)MAKESEGPTR( sel, offset );
531     else
532         return SNOOP16_GetProcAddress16(hModule,ordinal,(FARPROC16)MAKESEGPTR( sel, offset ));
533 }
534 
535 
536 /***********************************************************************
537  *              EntryAddrProc (KERNEL.667) Wine-specific export
538  *
539  * Return the entry point for a given ordinal.
540  */
541 FARPROC16 WINAPI EntryAddrProc16( HMODULE16 hModule, WORD ordinal )
542 {
543     FARPROC16 ret = NE_GetEntryPointEx( hModule, ordinal, TRUE );
544     CURRENT_STACK16->ecx = hModule; /* FIXME: might be incorrect value */
545     return ret;
546 }
547 
548 /***********************************************************************
549  *           NE_SetEntryPoint
550  *
551  * Change the value of an entry point. Use with caution!
552  * It can only change the offset value, not the selector.
553  */
554 BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
555 {
556     NE_MODULE *pModule;
557     ET_ENTRY *entry;
558     ET_BUNDLE *bundle;
559     int i;
560 
561     if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
562     assert( !(pModule->ne_flags & NE_FFLAGS_WIN32) );
563 
564     bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->ne_enttab);
565     while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
566     {
567         bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
568         if (!(bundle->next)) return 0;
569     }
570 
571     entry = (ET_ENTRY *)((BYTE *)bundle+6);
572     for (i=0; i < (ordinal - bundle->first - 1); i++)
573         entry++;
574 
575     memcpy( &entry->offs, &offset, sizeof(WORD) );
576     return TRUE;
577 }
578 
579 
580 /***********************************************************************
581  *           build_bundle_data
582  *
583  * Build the entry table bundle data from the on-disk format. Helper for build_module.
584  */
585 static void *build_bundle_data( NE_MODULE *pModule, void *dest, const BYTE *table )
586 {
587     ET_BUNDLE *oldbundle, *bundle = dest;
588     ET_ENTRY *entry;
589     BYTE nr_entries, type;
590 
591     memset(bundle, 0, sizeof(ET_BUNDLE)); /* in case no entry table exists */
592     entry = (ET_ENTRY *)((BYTE *)bundle+6);
593 
594     while ((nr_entries = *table++))
595     {
596         if ((type = *table++))
597         {
598             bundle->last += nr_entries;
599             if (type == 0xff)
600             {
601                 while (nr_entries--)
602                 {
603                     entry->type   = type;
604                     entry->flags  = *table++;
605                     table += sizeof(WORD);
606                     entry->segnum = *table++;
607                     entry->offs   = *(const WORD *)table;
608                     table += sizeof(WORD);
609                     entry++;
610                 }
611             }
612             else
613             {
614                 while (nr_entries--)
615                 {
616                     entry->type   = type;
617                     entry->flags  = *table++;
618                     entry->segnum = type;
619                     entry->offs   = *(const WORD *)table;
620                     table += sizeof(WORD);
621                     entry++;
622                 }
623             }
624         }
625         else
626         {
627             if (bundle->first == bundle->last)
628             {
629                 bundle->first += nr_entries;
630                 bundle->last += nr_entries;
631             }
632             else
633             {
634                 oldbundle = bundle;
635                 oldbundle->next = (char *)entry - (char *)pModule;
636                 bundle = (ET_BUNDLE *)entry;
637                 bundle->first = bundle->last = oldbundle->last + nr_entries;
638                 bundle->next = 0;
639                 entry = (ET_ENTRY*)(((BYTE*)entry)+sizeof(ET_BUNDLE));
640             }
641         }
642     }
643     return entry;
644 }
645 
646 
647 /***********************************************************************
648  *           build_module
649  *
650  * Build the in-memory module from the on-disk data.
651  */
652 static HMODULE16 build_module( const void *mapping, SIZE_T mapping_size, LPCSTR path )
653 {
654     const IMAGE_DOS_HEADER *mz_header = mapping;
655     const IMAGE_OS2_HEADER *ne_header;
656     const struct ne_segment_table_entry_s *pSeg;
657     const void *ptr;
658     int i;
659     size_t size;
660     HMODULE16 hModule;
661     NE_MODULE *pModule;
662     BYTE *buffer, *pData, *end;
663     OFSTRUCT *ofs;
664 
665     if (mapping_size < sizeof(*mz_header)) return ERROR_BAD_FORMAT;
666     if (mz_header->e_magic != IMAGE_DOS_SIGNATURE) return ERROR_BAD_FORMAT;
667     ne_header = (const IMAGE_OS2_HEADER *)((const char *)mapping + mz_header->e_lfanew);
668     if (mz_header->e_lfanew + sizeof(*ne_header) > mapping_size) return ERROR_BAD_FORMAT;
669     if (ne_header->ne_magic == IMAGE_NT_SIGNATURE) return 21;  /* win32 exe */
670     if (ne_header->ne_magic == IMAGE_OS2_SIGNATURE_LX)
671     {
672         MESSAGE("Sorry, %s is an OS/2 linear executable (LX) file!\n", path);
673         return 12;
674     }
675     if (ne_header->ne_magic != IMAGE_OS2_SIGNATURE) return ERROR_BAD_FORMAT;
676 
677     /* We now have a valid NE header */
678 
679     /* check to be able to fall back to loading OS/2 programs as DOS
680      * FIXME: should this check be reversed in order to be less strict?
681      * (only fail for OS/2 ne_exetyp 0x01 here?) */
682     if ((ne_header->ne_exetyp != 0x02 /* Windows */)
683         && (ne_header->ne_exetyp != 0x04) /* Windows 386 */)
684         return ERROR_BAD_FORMAT;
685 
686     size = sizeof(NE_MODULE) +
687              /* segment table */
688            ne_header->ne_cseg * sizeof(SEGTABLEENTRY) +
689              /* resource table */
690            ne_header->ne_restab - ne_header->ne_rsrctab +
691              /* resident names table */
692            ne_header->ne_modtab - ne_header->ne_restab +
693              /* module ref table */
694            ne_header->ne_cmod * sizeof(WORD) +
695              /* imported names table */
696            ne_header->ne_enttab - ne_header->ne_imptab +
697              /* entry table length */
698            ne_header->ne_cbenttab +
699              /* entry table extra conversion space */
700            sizeof(ET_BUNDLE) +
701            2 * (ne_header->ne_cbenttab - ne_header->ne_cmovent*6) +
702              /* loaded file info */
703            sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path) + 1;
704 
705     hModule = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, size );
706     if (!hModule) return ERROR_BAD_FORMAT;
707 
708     FarSetOwner16( hModule, hModule );
709     pModule = (NE_MODULE *)GlobalLock16( hModule );
710     memcpy( pModule, ne_header, sizeof(*ne_header) );
711     pModule->count = 0;
712     /* check programs for default minimal stack size */
713     if (!(pModule->ne_flags & NE_FFLAGS_LIBMODULE) && (pModule->ne_stack < 0x1400))
714         pModule->ne_stack = 0x1400;
715 
716     pModule->self         = hModule;
717     pModule->mapping      = mapping;
718     pModule->mapping_size = mapping_size;
719 
720     pData = (BYTE *)(pModule + 1);
721 
722     /* Clear internal Wine flags in case they are set in the EXE file */
723 
724     pModule->ne_flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
725 
726     /* Get the segment table */
727 
728     pModule->ne_segtab = pData - (BYTE *)pModule;
729     if (!(pSeg = NE_GET_DATA( pModule, mz_header->e_lfanew + ne_header->ne_segtab,
730                               ne_header->ne_cseg * sizeof(struct ne_segment_table_entry_s) )))
731         goto failed;
732     for (i = ne_header->ne_cseg; i > 0; i--, pSeg++)
733     {
734         memcpy( pData, pSeg, sizeof(*pSeg) );
735         pData += sizeof(SEGTABLEENTRY);
736     }
737 
738     /* Get the resource table */
739 
740     if (ne_header->ne_rsrctab < ne_header->ne_restab)
741     {
742         pModule->ne_rsrctab = pData - (BYTE *)pModule;
743         if (!NE_READ_DATA( pModule, pData, mz_header->e_lfanew + ne_header->ne_rsrctab,
744                            ne_header->ne_restab - ne_header->ne_rsrctab )) goto failed;
745         pData += ne_header->ne_restab - ne_header->ne_rsrctab;
746     }
747     else pModule->ne_rsrctab = 0;  /* No resource table */
748 
749     /* Get the resident names table */
750 
751     pModule->ne_restab = pData - (BYTE *)pModule;
752     if (!NE_READ_DATA( pModule, pData, mz_header->e_lfanew + ne_header->ne_restab,
753                        ne_header->ne_modtab - ne_header->ne_restab )) goto failed;
754     pData += ne_header->ne_modtab - ne_header->ne_restab;
755 
756     /* Get the module references table */
757 
758     if (ne_header->ne_cmod > 0)
759     {
760         pModule->ne_modtab = pData - (BYTE *)pModule;
761         if (!NE_READ_DATA( pModule, pData, mz_header->e_lfanew + ne_header->ne_modtab,
762                            ne_header->ne_cmod * sizeof(WORD) )) goto failed;
763         pData += ne_header->ne_cmod * sizeof(WORD);
764     }
765     else pModule->ne_modtab = 0;  /* No module references */
766 
767     /* Get the imported names table */
768 
769     pModule->ne_imptab = pData - (BYTE *)pModule;
770     if (!NE_READ_DATA( pModule, pData, mz_header->e_lfanew + ne_header->ne_imptab,
771                        ne_header->ne_enttab - ne_header->ne_imptab )) goto failed;
772     pData += ne_header->ne_enttab - ne_header->ne_imptab;
773 
774     /* Load entry table, convert it to the optimized version used by Windows */
775 
776     pModule->ne_enttab = pData - (BYTE *)pModule;
777     if (!(ptr = NE_GET_DATA( pModule, mz_header->e_lfanew + ne_header->ne_enttab,
778                              ne_header->ne_cbenttab ))) goto failed;
779     end = build_bundle_data( pModule, pData, ptr );
780 
781     pData += ne_header->ne_cbenttab + sizeof(ET_BUNDLE) +
782         2 * (ne_header->ne_cbenttab - ne_header->ne_cmovent*6);
783 
784     if (end > pData)
785     {
786         FIXME( "not enough space for entry table for %s\n", debugstr_a(path) );
787         goto failed;
788     }
789 
790     /* Store the filename information */
791 
792     pModule->fileinfo = pData - (BYTE *)pModule;
793     ofs = (OFSTRUCT *)pData;
794     ofs->cBytes = sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path);
795     ofs->fFixedDisk = 1;
796     strcpy( ofs->szPathName, path );
797     pData += ofs->cBytes + 1;
798     assert( (BYTE *)pModule + size <= pData );
799 
800     /* Get the non-resident names table */
801 
802     if (ne_header->ne_cbnrestab)
803     {
804         pModule->nrname_handle = GlobalAlloc16( 0, ne_header->ne_cbnrestab );
805         if (!pModule->nrname_handle) goto failed;
806         FarSetOwner16( pModule->nrname_handle, hModule );
807         buffer = GlobalLock16( pModule->nrname_handle );
808         if (!NE_READ_DATA( pModule, buffer, ne_header->ne_nrestab, ne_header->ne_cbnrestab ))
809         {
810             GlobalFree16( pModule->nrname_handle );
811             goto failed;
812         }
813     }
814     else pModule->nrname_handle = 0;
815 
816     /* Allocate a segment for the implicitly-loaded DLLs */
817 
818     if (pModule->ne_cmod)
819     {
820         pModule->dlls_to_init = GlobalAlloc16( GMEM_ZEROINIT,
821                                                (pModule->ne_cmod+1)*sizeof(HMODULE16) );
822         if (!pModule->dlls_to_init)
823         {
824             if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
825             goto failed;
826         }
827         FarSetOwner16( pModule->dlls_to_init, hModule );
828     }
829     else pModule->dlls_to_init = 0;
830 
831     NE_RegisterModule( pModule );
832     return hModule;
833 
834 failed:
835     GlobalFree16( hModule );
836     return ERROR_BAD_FORMAT;
837 }
838 
839 
840 /***********************************************************************
841  *           NE_LoadDLLs
842  *
843  * Load all DLLs implicitly linked to a module.
844  */
845 static BOOL NE_LoadDLLs( NE_MODULE *pModule )
846 {
847     int i;
848     WORD *pModRef = (WORD *)((char *)pModule + pModule->ne_modtab);
849     WORD *pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
850 
851     for (i = 0; i < pModule->ne_cmod; i++, pModRef++)
852     {
853         char buffer[260], *p;
854         BYTE *pstr = (BYTE *)pModule + pModule->ne_imptab + *pModRef;
855         memcpy( buffer, pstr + 1, *pstr );
856         *(buffer + *pstr) = 0; /* terminate it */
857 
858         TRACE("Loading '%s'\n", buffer );
859         if (!(*pModRef = GetModuleHandle16( buffer )))
860         {
861             /* If the DLL is not loaded yet, load it and store */
862             /* its handle in the list of DLLs to initialize.   */
863             HMODULE16 hDLL;
864 
865             /* Append .DLL to name if no extension present */
866             if (!(p = strrchr( buffer, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
867                     strcat( buffer, ".DLL" );
868 
869             if ((hDLL = MODULE_LoadModule16( buffer, TRUE, TRUE )) < 32)
870             {
871                 /* FIXME: cleanup what was done */
872 
873                 MESSAGE( "Could not load '%s' required by '%.*s', error=%d\n",
874                      buffer, *((BYTE*)pModule + pModule->ne_restab),
875                      (char *)pModule + pModule->ne_restab + 1, hDLL );
876                 return FALSE;
877             }
878             *pModRef = GetExePtr( hDLL );
879             *pDLLs++ = *pModRef;
880         }
881         else  /* Increment the reference count of the DLL */
882         {
883             NE_MODULE *pOldDLL = NE_GetPtr( *pModRef );
884             if (pOldDLL) pOldDLL->count++;
885         }
886     }
887     return TRUE;
888 }
889 
890 
891 /**********************************************************************
892  *          NE_DoLoadModule
893  *
894  * Load first instance of NE module from file.
895  *
896  * pModule must point to a module structure prepared by build_module.
897  * This routine must never be called twice on a module.
898  */
899 static HINSTANCE16 NE_DoLoadModule( NE_MODULE *pModule )
900 {
901     /* Allocate the segments for this module */
902 
903     if (!NE_CreateAllSegments( pModule ))
904         return ERROR_NOT_ENOUGH_MEMORY; /* 8 */
905 
906     /* Load the referenced DLLs */
907 
908     if (!NE_LoadDLLs( pModule ))
909         return ERROR_FILE_NOT_FOUND; /* 2 */
910 
911     /* Load the segments */
912 
913     NE_LoadAllSegments( pModule );
914 
915     /* Make sure the usage count is 1 on the first loading of  */
916     /* the module, even if it contains circular DLL references */
917 
918     pModule->count = 1;
919 
920     return NE_GetInstance( pModule );
921 }
922 
923 /**********************************************************************
924  *          NE_LoadModule
925  *
926  * Load first instance of NE module. (Note: caller is responsible for
927  * ensuring the module isn't already loaded!)
928  *
929  * If the module turns out to be an executable module, only a
930  * handle to a module stub is returned; this needs to be initialized
931  * by calling NE_DoLoadModule later, in the context of the newly
932  * created process.
933  *
934  * If lib_only is TRUE, however, the module is perforce treated
935  * like a DLL module, even if it is an executable module.
936  *
937  */
938 static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only )
939 {
940     NE_MODULE *pModule;
941     HMODULE16 hModule;
942     HINSTANCE16 hInstance;
943     HFILE16 hFile;
944     OFSTRUCT ofs;
945     HANDLE mapping;
946     void *ptr;
947     MEMORY_BASIC_INFORMATION info;
948 
949     /* Open file */
950     if ((hFile = OpenFile16( name, &ofs, OF_READ|OF_SHARE_DENY_WRITE )) == HFILE_ERROR16)
951         return ERROR_FILE_NOT_FOUND;
952 
953     mapping = CreateFileMappingW( DosFileHandleToWin3