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