Release 960428
[wine/multimedia.git] / loader / ne_image.c
blob447b500404950d8f673ee69daa93bcb5545d5b5b
1 #ifndef WINELIB
2 /*
3 * NE modules
5 * Copyright 1993 Robert J. Amstadt
6 * Copyright 1995 Alexandre Julliard
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <ctype.h>
16 #include <string.h>
17 #include <errno.h>
18 #include "neexe.h"
19 #include "windows.h"
20 #include "arch.h"
21 #include "selectors.h"
22 #include "callback.h"
23 #include "module.h"
24 #include "stackframe.h"
25 #include "stddebug.h"
26 #include "debug.h"
27 #include "xmalloc.h"
30 /***********************************************************************
31 * NE_LoadSegment
33 BOOL NE_LoadSegment( HMODULE hModule, WORD segnum )
35 NE_MODULE *pModule;
36 SEGTABLEENTRY *pSegTable, *pSeg;
37 WORD *pModuleTable;
38 WORD count, i, offset;
39 HMODULE module;
40 DWORD address;
41 int fd;
42 struct relocation_entry_s *rep, *reloc_entries;
43 BYTE *func_name;
44 int size;
45 char* mem;
47 char buffer[100];
48 int ordinal, additive;
49 unsigned short *sp;
51 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
52 pSegTable = NE_SEG_TABLE( pModule );
53 pSeg = pSegTable + segnum - 1;
54 pModuleTable = NE_MODULE_TABLE( pModule );
56 if (!pSeg->filepos) return TRUE; /* No file image, just return */
58 fd = MODULE_OpenFile( hModule );
59 dprintf_module( stddeb, "Loading segment %d, selector=%04x\n",
60 segnum, pSeg->selector );
61 lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
62 size = pSeg->size ? pSeg->size : 0x10000;
63 mem = GlobalLock(pSeg->selector);
64 if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1) {
65 #ifndef WINELIB
66 /* Implement self loading segments */
67 SELFLOADHEADER *selfloadheader;
68 WORD oldss, oldsp, oldselector, newselector;
69 selfloadheader = (SELFLOADHEADER *)
70 PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
71 oldss = IF1632_Saved16_ss;
72 oldsp = IF1632_Saved16_sp;
73 oldselector = pSeg->selector;
74 IF1632_Saved16_ss = pModule->self_loading_sel;
75 IF1632_Saved16_sp = 0xFF00;
76 /* FIXME: we probably need to pass a DOS file handle here */
77 newselector = CallTo16_word_www(selfloadheader->LoadAppSeg,
78 pModule->self_loading_sel, hModule, fd, segnum);
79 if (newselector != oldselector) {
80 /* Self loaders like creating their own selectors;
81 * they love asking for trouble to Wine developers
83 if (segnum == pModule->dgroup) {
84 memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
85 PTR_SEG_OFF_TO_LIN(newselector,0),
86 pSeg->minsize ? pSeg->minsize : 0x10000);
87 FreeSelector(newselector);
88 pSeg->selector = oldselector;
89 fprintf(stderr, "A new selector was allocated for the dgroup segment\n"
90 "Old selector is %d, new one is %d", oldselector, newselector);
91 } else {
92 FreeSelector(pSeg->selector);
93 pSeg->selector = newselector;
97 IF1632_Saved16_ss = oldss;
98 IF1632_Saved16_sp = oldsp;
99 #else
100 fprintf(stderr,"JBP: Ignoring self loading segments in NE_LoadSegment.\n");
101 #endif
103 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
104 read(fd, mem, size);
105 else {
107 The following bit of code for "iterated segments" was written without
108 any documentation on the format of these segments. It seems to work,
109 but may be missing something. If you have any doco please either send
110 it to me or fix the code yourself. gfm@werple.mira.net.au
112 char* buff = xmalloc(size);
113 char* curr = buff;
114 read(fd, buff, size);
115 while(curr < buff + size) {
116 unsigned int rept = *((short*) curr)++;
117 unsigned int len = *((short*) curr)++;
118 for(; rept > 0; rept--) {
119 char* bytes = curr;
120 unsigned int byte;
121 for(byte = 0; byte < len; byte++)
122 *mem++ = *bytes++;
124 curr += len;
126 free(buff);
129 pSeg->flags |= NE_SEGFLAGS_LOADED;
130 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
131 return TRUE; /* No relocation data, we are done */
133 read( fd, &count, sizeof(count) );
134 if (!count) return TRUE;
136 dprintf_fixup( stddeb, "Fixups for %*.*s, segment %d, selector %04x\n",
137 *((BYTE *)pModule + pModule->name_table),
138 *((BYTE *)pModule + pModule->name_table),
139 (char *)pModule + pModule->name_table + 1,
140 segnum, pSeg->selector );
142 reloc_entries = (struct relocation_entry_s *)xmalloc(count * sizeof(struct relocation_entry_s));
143 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
144 count * sizeof(struct relocation_entry_s))
146 dprintf_fixup( stddeb, "Unable to read relocation information\n" );
147 return FALSE;
151 * Go through the relocation table on entry at a time.
153 rep = reloc_entries;
154 for (i = 0; i < count; i++, rep++)
157 * Get the target address corresponding to this entry.
160 /* If additive, there is no target chain list. Instead, add source
161 and target */
162 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
163 rep->relocation_type &= 0x3;
165 switch (rep->relocation_type)
167 case NE_RELTYPE_ORDINAL:
168 module = pModuleTable[rep->target1-1];
169 ordinal = rep->target2;
170 address = MODULE_GetEntryPoint( module, ordinal );
171 if (!address)
173 NE_MODULE *pTarget = MODULE_GetPtr( module );
174 if (!pTarget)
175 fprintf( stderr, "Module not found: %04x, reference %d of module %*.*s\n",
176 module, rep->target1,
177 *((BYTE *)pModule + pModule->name_table),
178 *((BYTE *)pModule + pModule->name_table),
179 (char *)pModule + pModule->name_table + 1 );
180 else
181 fprintf( stderr, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
182 *((BYTE *)pTarget + pTarget->name_table),
183 *((BYTE *)pTarget + pTarget->name_table),
184 (char *)pTarget + pTarget->name_table + 1,
185 ordinal );
187 if (debugging_fixup)
189 NE_MODULE *pTarget = MODULE_GetPtr( module );
190 fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1,
191 *((BYTE *)pTarget + pTarget->name_table),
192 *((BYTE *)pTarget + pTarget->name_table),
193 (char *)pTarget + pTarget->name_table + 1,
194 ordinal, HIWORD(address), LOWORD(address) );
196 break;
198 case NE_RELTYPE_NAME:
199 module = pModuleTable[rep->target1-1];
200 func_name = (char *)pModule + pModule->import_table + rep->target2;
201 memcpy( buffer, func_name+1, *func_name );
202 buffer[*func_name] = '\0';
203 func_name = buffer;
204 ordinal = MODULE_GetOrdinal( module, func_name );
206 address = MODULE_GetEntryPoint( module, ordinal );
208 if (!address)
210 NE_MODULE *pTarget = MODULE_GetPtr( module );
211 fprintf( stderr, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
212 *((BYTE *)pTarget + pTarget->name_table),
213 *((BYTE *)pTarget + pTarget->name_table),
214 (char *)pTarget + pTarget->name_table + 1, func_name );
216 if (debugging_fixup)
218 NE_MODULE *pTarget = MODULE_GetPtr( module );
219 fprintf( stddeb,"%d: %*.*s.%s=%04x:%04x\n", i + 1,
220 *((BYTE *)pTarget + pTarget->name_table),
221 *((BYTE *)pTarget + pTarget->name_table),
222 (char *)pTarget + pTarget->name_table + 1,
223 func_name, HIWORD(address), LOWORD(address) );
225 break;
227 case NE_RELTYPE_INTERNAL:
228 if (rep->target1 == 0x00ff)
230 address = MODULE_GetEntryPoint( hModule, rep->target2 );
232 else
234 address = MAKELONG( rep->target2, pSegTable[rep->target1-1].selector );
237 dprintf_fixup(stddeb,"%d: %04x:%04x\n",
238 i + 1, HIWORD(address), LOWORD(address) );
239 break;
241 case NE_RELTYPE_OSFIXUP:
242 /* Relocation type 7:
244 * These appear to be used as fixups for the Windows
245 * floating point emulator. Let's just ignore them and
246 * try to use the hardware floating point. Linux should
247 * successfully emulate the coprocessor if it doesn't
248 * exist.
250 dprintf_fixup(stddeb,
251 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
252 i + 1, rep->address_type, rep->relocation_type,
253 rep->offset);
254 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
255 rep->target1, rep->target2);
256 continue;
258 default:
259 dprintf_fixup(stddeb,
260 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
261 i + 1, rep->address_type, rep->relocation_type,
262 rep->offset);
263 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
264 rep->target1, rep->target2);
265 free(reloc_entries);
266 return FALSE;
269 offset = rep->offset;
271 switch (rep->address_type)
273 case NE_RADDR_LOWBYTE:
274 do {
275 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
276 dprintf_fixup(stddeb," %04x:%04x:%04x BYTE%s\n",
277 pSeg->selector, offset, *sp, additive ? " additive":"");
278 offset = *sp;
279 if(additive)
280 *(unsigned char*)sp = (unsigned char)((address+offset) & 0xFF);
281 else
282 *(unsigned char*)sp = (unsigned char)(address & 0xFF);
284 while (offset != 0xffff && !additive);
285 break;
287 case NE_RADDR_OFFSET16:
288 do {
289 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
290 dprintf_fixup(stddeb," %04x:%04x:%04x OFFSET16%s\n",
291 pSeg->selector, offset, *sp, additive ? " additive" : "" );
292 offset = *sp;
293 *sp = LOWORD(address);
294 if (additive) *sp += offset;
296 while (offset != 0xffff && !additive);
297 break;
299 case NE_RADDR_POINTER32:
300 do {
301 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
302 dprintf_fixup(stddeb," %04x:%04x:%04x POINTER32%s\n",
303 pSeg->selector, offset, *sp, additive ? " additive" : "" );
304 offset = *sp;
305 *sp = LOWORD(address);
306 if (additive) *sp += offset;
307 *(sp+1) = HIWORD(address);
309 while (offset != 0xffff && !additive);
310 break;
312 case NE_RADDR_SELECTOR:
313 do {
314 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
315 dprintf_fixup(stddeb," %04x:%04x:%04x SELECTOR%s\n",
316 pSeg->selector, offset, *sp, additive ? " additive" : "" );
317 offset = *sp;
318 *sp = HIWORD(address);
319 /* Borland creates additive records with offset zero. Strange, but OK */
320 if(additive && offset)
321 fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
323 /* FIXME: Quicken 5 has a zero offset fixup. This seems to work */
324 while (offset && offset != 0xffff && !additive);
325 break;
327 default:
328 dprintf_fixup(stddeb,
329 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
330 i + 1, rep->address_type, rep->relocation_type,
331 rep->offset);
332 dprintf_fixup(stddeb,
333 "TARGET %04x %04x\n", rep->target1, rep->target2);
334 free(reloc_entries);
335 return FALSE;
339 free(reloc_entries);
340 return TRUE;
344 /***********************************************************************
345 * NE_FixupPrologs
347 * Fixup the exported functions prologs.
349 void NE_FixupPrologs( NE_MODULE *pModule )
351 #ifdef WINELIB
352 fprintf(stderr,"NE_FixupPrologs should not be called for libwine\n");
353 #else
354 SEGTABLEENTRY *pSegTable;
355 WORD dgroup = 0;
356 WORD sel;
357 BYTE *p, *fixup_ptr, count;
359 pSegTable = NE_SEG_TABLE(pModule);
360 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
361 dgroup = pSegTable[pModule->dgroup-1].selector;
363 dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", pModule->self );
364 p = (BYTE *)pModule + pModule->entry_table;
365 while (*p)
367 if (p[1] == 0) /* Unused entry */
369 p += 2; /* Skip it */
370 continue;
372 if (p[1] == 0xfe) /* Constant entry */
374 p += 2 + *p * 3; /* Skip it */
375 continue;
378 /* Now fixup the entries of this bundle */
379 count = *p;
380 sel = p[1];
381 p += 2;
382 while (count-- > 0)
384 dprintf_module( stddeb,"Flags: %04x, sel %02x ", *p, sel);
385 /* According to the output generated by TDUMP, the flags mean:
386 * 0x0001 function is exported
387 * 0x0002 Single data (seems to occur only in DLLs)
389 if (sel == 0xff) { /* moveable */
390 dprintf_module( stddeb, "(%02x) o %04x ", p[3], *(WORD *)(p+4) );
391 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
392 } else { /* fixed */
393 dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
394 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
396 dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
397 fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
398 pModule->flags );
399 if (*p & 0x0001)
401 /* Verify the signature */
402 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
403 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
404 && fixup_ptr[2] == 0x90)
406 if (*p & 0x0002)
408 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
409 /* can this happen? */
410 fprintf( stderr, "FixupPrologs got confused\n" );
412 *fixup_ptr = 0xb8; /* MOV AX, */
413 *(WORD *)(fixup_ptr+1) = dgroup;
415 else
417 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
418 fixup_ptr[0] = 0x90; /* non-library: NOPs */
419 fixup_ptr[1] = 0x90;
420 fixup_ptr[2] = 0x90;
423 } else {
424 dprintf_fixup( stddeb, "Unknown signature\n" );
427 else
428 dprintf_module( stddeb,"\n");
429 p += (sel == 0xff) ? 6 : 3;
432 #endif
436 /***********************************************************************
437 * NE_InitDLL
439 * Call the DLL initialization code
441 static BOOL NE_InitDLL( HMODULE hModule )
443 #ifndef WINELIB
444 int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, bp_reg;
445 NE_MODULE *pModule;
446 SEGTABLEENTRY *pSegTable;
448 /* Registers at initialization must be:
449 * cx heap size
450 * di library instance
451 * ds data segment if any
452 * es:si command line (always 0)
455 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
456 pSegTable = NE_SEG_TABLE( pModule );
458 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
459 (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
460 if (!pModule->cs) return TRUE; /* no initialization code */
462 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
464 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
466 /* Not SINGLEDATA */
467 fprintf(stderr, "Library is not marked SINGLEDATA\n");
468 exit(1);
470 else /* DATA NONE DLL */
472 ds_reg = 0;
473 cx_reg = 0;
476 else /* DATA SINGLE DLL */
478 ds_reg = pSegTable[pModule->dgroup-1].selector;
479 cx_reg = pModule->heap_size;
482 cs_reg = pSegTable[pModule->cs-1].selector;
483 ip_reg = pModule->ip;
484 di_reg = ds_reg ? ds_reg : hModule;
485 bp_reg = IF1632_Saved16_sp + ((WORD)&((STACK16FRAME*)1)->bp - 1);
487 pModule->cs = 0; /* Don't initialize it twice */
488 dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
489 cs_reg, ip_reg, ds_reg, di_reg, cx_reg );
490 return CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
491 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
492 cx_reg, 0 /*dx*/, 0 /*si*/, di_reg );
493 #else
494 fprintf( stderr,"JBP: Ignoring call to LibMain\n" );
495 return FALSE;
496 #endif
500 /***********************************************************************
501 * NE_InitializeDLLs
503 * Initialize the loaded DLLs.
505 void NE_InitializeDLLs( HMODULE hModule )
507 NE_MODULE *pModule;
508 HMODULE *pDLL;
510 if (!(pModule = MODULE_GetPtr( hModule ))) return;
511 if (pModule->flags & NE_FFLAGS_WIN32)
513 PE_InitializeDLLs(hModule);
514 return;
516 if (pModule->dlls_to_init)
518 HANDLE to_init = pModule->dlls_to_init;
519 pModule->dlls_to_init = 0;
520 for (pDLL = (HMODULE *)GlobalLock( to_init ); *pDLL; pDLL++)
522 NE_InitializeDLLs( *pDLL );
523 NE_InitDLL( *pDLL );
525 GlobalFree( to_init );
527 NE_InitDLL( hModule );
531 /***********************************************************************
532 * NE_PatchCodeHandle
534 * Needed for self-loading modules.
537 /* It does nothing */
538 void PatchCodeHandle(HANDLE hSel)
541 #endif /* WINELIB */