Suppressed the inclusion of OpenGL headers.
[wine.git] / loader / ne / segment.c
blobaf59970ed73ed1e9d1c824a3bb29fd79d4194c27
1 /*
2 * NE segment loading
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
6 */
8 #include <assert.h>
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>
19 #include "wine/winbase16.h"
20 #include "neexe.h"
21 #include "global.h"
22 #include "task.h"
23 #include "selectors.h"
24 #include "callback.h"
25 #include "file.h"
26 #include "module.h"
27 #include "stackframe.h"
28 #include "debugtools.h"
29 #include "xmalloc.h"
30 #include "toolhelp.h"
32 DECLARE_DEBUG_CHANNEL(dll)
33 DECLARE_DEBUG_CHANNEL(fixup)
34 DECLARE_DEBUG_CHANNEL(module)
35 DECLARE_DEBUG_CHANNEL(segment)
37 #define SEL(x) ((x)|1)
39 static void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum);
41 /***********************************************************************
42 * NE_GetRelocAddrName
44 static const char *NE_GetRelocAddrName( BYTE addr_type, int additive )
46 switch(addr_type & 0x7f)
48 case NE_RADDR_LOWBYTE: return additive ? "BYTE add" : "BYTE";
49 case NE_RADDR_OFFSET16: return additive ? "OFFSET16 add" : "OFFSET16";
50 case NE_RADDR_POINTER32: return additive ? "POINTER32 add" : "POINTER32";
51 case NE_RADDR_SELECTOR: return additive ? "SELECTOR add" : "SELECTOR";
52 case NE_RADDR_POINTER48: return additive ? "POINTER48 add" : "POINTER48";
53 case NE_RADDR_OFFSET32: return additive ? "OFFSET32 add" : "OFFSET32";
55 return "???";
59 /***********************************************************************
60 * NE_LoadSegment
62 BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
64 SEGTABLEENTRY *pSegTable, *pSeg;
65 WORD *pModuleTable;
66 WORD count, i, offset, next_offset;
67 HMODULE16 module;
68 FARPROC16 address = 0;
69 HFILE hf;
70 DWORD res;
71 struct relocation_entry_s *rep, *reloc_entries;
72 BYTE *func_name;
73 int size;
74 char* mem;
76 char buffer[256];
77 int ordinal, additive;
78 unsigned short *sp;
80 pSegTable = NE_SEG_TABLE( pModule );
81 pSeg = pSegTable + segnum - 1;
83 if (pSeg->flags & NE_SEGFLAGS_LOADED) /* already loaded ? */
84 return TRUE;
86 if (!pSeg->filepos) return TRUE; /* No file image, just return */
88 pModuleTable = NE_MODULE_TABLE( pModule );
90 hf = NE_OpenFile( pModule );
91 TRACE_(module)("Loading segment %d, hSeg=%04x, flags=%04x\n",
92 segnum, pSeg->hSeg, pSeg->flags );
93 SetFilePointer( hf, pSeg->filepos << pModule->alignment, NULL, SEEK_SET );
94 if (pSeg->size) size = pSeg->size;
95 else size = pSeg->minsize ? pSeg->minsize : 0x10000;
96 mem = GlobalLock16(pSeg->hSeg);
97 if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1)
99 /* Implement self-loading segments */
100 SELFLOADHEADER *selfloadheader;
101 DWORD oldstack;
102 HFILE hFile32;
103 HFILE16 hFile16;
105 selfloadheader = (SELFLOADHEADER *)
106 PTR_SEG_OFF_TO_LIN(SEL(pSegTable->hSeg),0);
107 oldstack = NtCurrentTeb()->cur_stack;
108 NtCurrentTeb()->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
109 0xff00 - sizeof(STACK16FRAME));
111 TRACE_(dll)("CallLoadAppSegProc(hmodule=0x%04x,hf=0x%04x,segnum=%d\n",
112 pModule->self,hf,segnum );
113 DuplicateHandle( GetCurrentProcess(), hf, GetCurrentProcess(), &hFile32,
114 0, FALSE, DUPLICATE_SAME_ACCESS );
115 hFile16 = FILE_AllocDosHandle( hFile32 );
116 pSeg->hSeg = Callbacks->CallLoadAppSegProc( selfloadheader->LoadAppSeg,
117 pModule->self, hFile16,
118 segnum );
119 TRACE_(dll)("Ret CallLoadAppSegProc: hSeg = 0x%04x\n", pSeg->hSeg);
120 _lclose16( hFile16 );
121 NtCurrentTeb()->cur_stack = oldstack;
123 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
124 ReadFile(hf, mem, size, &res, NULL);
125 else {
127 The following bit of code for "iterated segments" was written without
128 any documentation on the format of these segments. It seems to work,
129 but may be missing something. If you have any doc please either send
130 it to me or fix the code yourself. gfm@werple.mira.net.au
132 char* buff = xmalloc(size);
133 char* curr = buff;
134 ReadFile(hf, buff, size, &res, NULL);
135 while(curr < buff + size) {
136 unsigned int rept = *((short*) curr)++;
137 unsigned int len = *((short*) curr)++;
138 for(; rept > 0; rept--) {
139 char* bytes = curr;
140 unsigned int byte;
141 for(byte = 0; byte < len; byte++)
142 *mem++ = *bytes++;
144 curr += len;
146 free(buff);
149 pSeg->flags |= NE_SEGFLAGS_LOADED;
151 /* Perform exported function prolog fixups */
152 NE_FixupSegmentPrologs( pModule, segnum );
154 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
155 return TRUE; /* No relocation data, we are done */
157 ReadFile(hf, &count, sizeof(count), &res, NULL);
158 if (!count) return TRUE;
160 TRACE_(fixup)("Fixups for %.*s, segment %d, hSeg %04x\n",
161 *((BYTE *)pModule + pModule->name_table),
162 (char *)pModule + pModule->name_table + 1,
163 segnum, pSeg->hSeg );
164 TRACE_(segment)("Fixups for %.*s, segment %d, hSeg %04x\n",
165 *((BYTE *)pModule + pModule->name_table),
166 (char *)pModule + pModule->name_table + 1,
167 segnum, pSeg->hSeg );
169 reloc_entries = (struct relocation_entry_s *)xmalloc(count * sizeof(struct relocation_entry_s));
170 if (!ReadFile( hf, reloc_entries, count * sizeof(struct relocation_entry_s), &res, NULL) ||
171 (res != count * sizeof(struct relocation_entry_s)))
173 WARN_(fixup)("Unable to read relocation information\n" );
174 return FALSE;
178 * Go through the relocation table one entry at a time.
180 rep = reloc_entries;
181 for (i = 0; i < count; i++, rep++)
184 * Get the target address corresponding to this entry.
187 /* If additive, there is no target chain list. Instead, add source
188 and target */
189 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
190 rep->relocation_type &= 0x3;
192 switch (rep->relocation_type)
194 case NE_RELTYPE_ORDINAL:
195 module = pModuleTable[rep->target1-1];
196 ordinal = rep->target2;
197 address = NE_GetEntryPoint( module, ordinal );
198 if (!address)
200 NE_MODULE *pTarget = NE_GetPtr( module );
201 if (!pTarget)
202 WARN_(module)("Module not found: %04x, reference %d of module %*.*s\n",
203 module, rep->target1,
204 *((BYTE *)pModule + pModule->name_table),
205 *((BYTE *)pModule + pModule->name_table),
206 (char *)pModule + pModule->name_table + 1 );
207 else
209 ERR_(fixup)("No implementation for %.*s.%d, setting to 0xdeadbeef\n",
210 *((BYTE *)pTarget + pTarget->name_table),
211 (char *)pTarget + pTarget->name_table + 1,
212 ordinal );
213 address = (FARPROC16)0xdeadbeef;
216 if (TRACE_ON(fixup))
218 NE_MODULE *pTarget = NE_GetPtr( module );
219 TRACE_(fixup)("%d: %.*s.%d=%04x:%04x %s\n", i + 1,
220 *((BYTE *)pTarget + pTarget->name_table),
221 (char *)pTarget + pTarget->name_table + 1,
222 ordinal, HIWORD(address), LOWORD(address),
223 NE_GetRelocAddrName( rep->address_type, additive ) );
225 break;
227 case NE_RELTYPE_NAME:
228 module = pModuleTable[rep->target1-1];
229 func_name = (char *)pModule + pModule->import_table + rep->target2;
230 memcpy( buffer, func_name+1, *func_name );
231 buffer[*func_name] = '\0';
232 func_name = buffer;
233 ordinal = NE_GetOrdinal( module, func_name );
234 address = NE_GetEntryPoint( module, ordinal );
236 if (ERR_ON(fixup) && !address)
238 NE_MODULE *pTarget = NE_GetPtr( module );
239 ERR_(fixup)("No implementation for %.*s.%s, setting to 0xdeadbeef\n",
240 *((BYTE *)pTarget + pTarget->name_table),
241 (char *)pTarget + pTarget->name_table + 1, func_name );
243 if (!address) address = (FARPROC16) 0xdeadbeef;
244 if (TRACE_ON(fixup))
246 NE_MODULE *pTarget = NE_GetPtr( module );
247 TRACE_(fixup)("%d: %.*s.%s=%04x:%04x %s\n", i + 1,
248 *((BYTE *)pTarget + pTarget->name_table),
249 (char *)pTarget + pTarget->name_table + 1,
250 func_name, HIWORD(address), LOWORD(address),
251 NE_GetRelocAddrName( rep->address_type, additive ) );
253 break;
255 case NE_RELTYPE_INTERNAL:
256 if ((rep->target1 & 0xff) == 0xff)
258 address = NE_GetEntryPoint( pModule->self, rep->target2 );
260 else
262 address = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( SEL(pSegTable[rep->target1-1].hSeg), rep->target2 );
265 TRACE_(fixup)("%d: %04x:%04x %s\n",
266 i + 1, HIWORD(address), LOWORD(address),
267 NE_GetRelocAddrName( rep->address_type, additive ) );
268 break;
270 case NE_RELTYPE_OSFIXUP:
271 /* Relocation type 7:
273 * These appear to be used as fixups for the Windows
274 * floating point emulator. Let's just ignore them and
275 * try to use the hardware floating point. Linux should
276 * successfully emulate the coprocessor if it doesn't
277 * exist.
279 TRACE_(fixup)("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
280 i + 1, rep->relocation_type, rep->offset,
281 rep->target1, rep->target2,
282 NE_GetRelocAddrName( rep->address_type, additive ) );
283 continue;
286 offset = rep->offset;
288 /* Apparently, high bit of address_type is sometimes set; */
289 /* we ignore it for now */
290 if (rep->address_type > NE_RADDR_OFFSET32)
292 char module[10];
293 GetModuleName16( pModule->self, module, sizeof(module) );
294 ERR_(fixup)("WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
295 module, rep->address_type );
298 if (additive)
300 sp = PTR_SEG_OFF_TO_LIN( SEL(pSeg->hSeg), offset );
301 TRACE_(fixup)(" %04x:%04x\n", offset, *sp );
302 switch (rep->address_type & 0x7f)
304 case NE_RADDR_LOWBYTE:
305 *(BYTE *)sp += LOBYTE((int)address);
306 break;
307 case NE_RADDR_OFFSET16:
308 *sp += LOWORD(address);
309 break;
310 case NE_RADDR_POINTER32:
311 *sp += LOWORD(address);
312 *(sp+1) = HIWORD(address);
313 break;
314 case NE_RADDR_SELECTOR:
315 /* Borland creates additive records with offset zero. Strange, but OK */
316 if (*sp)
317 ERR_(fixup)("Additive selector to %04x.Please report\n",*sp);
318 else
319 *sp = HIWORD(address);
320 break;
321 default:
322 goto unknown;
325 else /* non-additive fixup */
329 sp = PTR_SEG_OFF_TO_LIN( SEL(pSeg->hSeg), offset );
330 next_offset = *sp;
331 TRACE_(fixup)(" %04x:%04x\n", offset, *sp );
332 switch (rep->address_type & 0x7f)
334 case NE_RADDR_LOWBYTE:
335 *(BYTE *)sp = LOBYTE((int)address);
336 break;
337 case NE_RADDR_OFFSET16:
338 *sp = LOWORD(address);
339 break;
340 case NE_RADDR_POINTER32:
341 *(FARPROC16 *)sp = address;
342 break;
343 case NE_RADDR_SELECTOR:
344 *sp = SELECTOROF(address);
345 break;
346 default:
347 goto unknown;
349 if (next_offset == offset) break; /* avoid infinite loop */
350 if (next_offset >= GlobalSize16(pSeg->hSeg)) break;
351 offset = next_offset;
352 } while (offset != 0xffff);
356 free(reloc_entries);
357 return TRUE;
359 unknown:
360 WARN_(fixup)("WARNING: %d: unknown ADDR TYPE %d, "
361 "TYPE %d, OFFSET %04x, TARGET %04x %04x\n",
362 i + 1, rep->address_type, rep->relocation_type,
363 rep->offset, rep->target1, rep->target2);
364 free(reloc_entries);
365 return FALSE;
369 /***********************************************************************
370 * NE_LoadAllSegments
372 BOOL NE_LoadAllSegments( NE_MODULE *pModule )
374 int i;
375 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
377 if (pModule->flags & NE_FFLAGS_SELFLOAD)
379 HFILE hf;
380 HFILE16 hFile16;
381 /* Handle self-loading modules */
382 SELFLOADHEADER *selfloadheader;
383 HMODULE16 hselfload = GetModuleHandle16("WPROCS");
384 DWORD oldstack;
386 TRACE_(module)("%.*s is a self-loading module!\n",
387 *((BYTE*)pModule + pModule->name_table),
388 (char *)pModule + pModule->name_table + 1);
389 if (!NE_LoadSegment( pModule, 1 )) return FALSE;
390 selfloadheader = (SELFLOADHEADER *)
391 PTR_SEG_OFF_TO_LIN(SEL(pSegTable->hSeg), 0);
392 selfloadheader->EntryAddrProc = NE_GetEntryPoint(hselfload,27);
393 selfloadheader->MyAlloc = NE_GetEntryPoint(hselfload,28);
394 selfloadheader->SetOwner = NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
395 pModule->self_loading_sel = SEL(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, FALSE, FALSE, FALSE));
396 oldstack = NtCurrentTeb()->cur_stack;
397 NtCurrentTeb()->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
398 0xff00 - sizeof(STACK16FRAME) );
400 DuplicateHandle( GetCurrentProcess(), NE_OpenFile(pModule),
401 GetCurrentProcess(), &hf, 0, FALSE, DUPLICATE_SAME_ACCESS );
402 hFile16 = FILE_AllocDosHandle( hf );
403 TRACE_(dll)("CallBootAppProc(hModule=0x%04x,hf=0x%04x)\n",
404 pModule->self,hFile16);
405 Callbacks->CallBootAppProc(selfloadheader->BootApp, pModule->self,hFile16);
406 TRACE_(dll)("Return from CallBootAppProc\n");
407 _lclose16(hf);
408 NtCurrentTeb()->cur_stack = oldstack;
410 for (i = 2; i <= pModule->seg_count; i++)
411 if (!NE_LoadSegment( pModule, i )) return FALSE;
413 else
415 for (i = 1; i <= pModule->seg_count; i++)
416 if (!NE_LoadSegment( pModule, i )) return FALSE;
418 return TRUE;
422 /***********************************************************************
423 * NE_FixupSegmentPrologs
425 * Fixup exported functions prologs of one segment
427 static void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum)
429 SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
430 ET_BUNDLE *bundle;
431 ET_ENTRY *entry;
432 WORD dgroup, num_entries, sel = SEL(pSegTable[segnum-1].hSeg);
433 BYTE *pSeg, *pFunc;
435 TRACE_(module)("(%d);\n", segnum);
437 if (pSegTable[segnum-1].flags & NE_SEGFLAGS_DATA)
439 pSegTable[segnum-1].flags |= NE_SEGFLAGS_LOADED;
440 return;
443 if (!pModule->dgroup) return;
445 if (!(dgroup = SEL(pSegTable[pModule->dgroup-1].hSeg))) return;
447 pSeg = PTR_SEG_OFF_TO_LIN(sel, 0);
449 bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table);
451 do {
452 TRACE_(module)("num_entries: %d, bundle: %p, next: %04x, pSeg: %p\n", bundle->last - bundle->first, bundle, bundle->next, pSeg);
453 if (!(num_entries = bundle->last - bundle->first))
454 return;
455 entry = (ET_ENTRY *)((BYTE *)bundle+6);
456 while (num_entries--)
458 /*TRACE(module, "entry: %p, entry->segnum: %d, entry->offs: %04x\n", entry, entry->segnum, entry->offs);*/
459 if (entry->segnum == segnum)
461 pFunc = ((BYTE *)pSeg+entry->offs);
462 TRACE_(module)("pFunc: %p, *(DWORD *)pFunc: %08lx, num_entries: %d\n", pFunc, *(DWORD *)pFunc, num_entries);
463 if (*(pFunc+2) == 0x90)
465 if (*(WORD *)pFunc == 0x581e) /* push ds, pop ax */
467 TRACE_(module)("patch %04x:%04x -> mov ax, ds\n", sel, entry->offs);
468 *(WORD *)pFunc = 0xd88c; /* mov ax, ds */
471 if (*(WORD *)pFunc == 0xd88c)
473 if ((entry->flags & 2)) /* public data ? */
475 TRACE_(module)("patch %04x:%04x -> mov ax, dgroup [%04x]\n", sel, entry->offs, dgroup);
476 *pFunc = 0xb8; /* mov ax, */
477 *(WORD *)(pFunc+1) = dgroup;
479 else
480 if ((pModule->flags & NE_FFLAGS_MULTIPLEDATA)
481 && (entry->flags & 1)) /* exported ? */
483 TRACE_(module)("patch %04x:%04x -> nop, nop\n", sel, entry->offs);
484 *(WORD *)pFunc = 0x9090; /* nop, nop */
489 entry++;
491 } while ( (bundle->next)
492 && (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
496 /***********************************************************************
497 * PatchCodeHandle
499 * Needed for self-loading modules.
501 DWORD WINAPI PatchCodeHandle16(HANDLE16 hSeg)
503 WORD segnum;
504 WORD sel = SEL(hSeg);
505 NE_MODULE *pModule = NE_GetPtr(FarGetOwner16(sel));
506 SEGTABLEENTRY *pSegTable = NE_SEG_TABLE(pModule);
508 TRACE_(module)("(%04x);\n", hSeg);
510 /* find the segment number of the module that belongs to hSeg */
511 for (segnum = 1; segnum <= pModule->seg_count; segnum++)
513 if (SEL(pSegTable[segnum-1].hSeg) == sel)
515 NE_FixupSegmentPrologs(pModule, segnum);
516 break;
520 return MAKELONG(hSeg, sel);
524 /***********************************************************************
525 * NE_GetDLLInitParams
527 static VOID NE_GetDLLInitParams( NE_MODULE *pModule,
528 WORD *hInst, WORD *ds, WORD *heap )
530 SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
532 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
534 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
536 /* Not SINGLEDATA */
537 ERR_(dll)("Library is not marked SINGLEDATA\n");
538 exit(1);
540 else /* DATA NONE DLL */
542 *ds = 0;
543 *heap = 0;
546 else /* DATA SINGLE DLL */
548 if (pModule->dgroup) {
549 *ds = SEL(pSegTable[pModule->dgroup-1].hSeg);
550 *heap = pModule->heap_size;
552 else /* hmm, DLL has no dgroup,
553 but why has it NE_FFLAGS_SINGLEDATA set ?
554 Buggy DLL compiler ? */
556 *ds = 0;
557 *heap = 0;
561 *hInst = *ds ? *ds : pModule->self;
565 /***********************************************************************
566 * NE_InitDLL
568 * Call the DLL initialization code
570 static BOOL NE_InitDLL( TDB* pTask, NE_MODULE *pModule )
572 SEGTABLEENTRY *pSegTable;
573 WORD hInst, ds, heap;
574 CONTEXT86 context;
576 pSegTable = NE_SEG_TABLE( pModule );
578 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
579 (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
581 /* Call USER signal handler for Win3.1 compatibility. */
582 TASK_CallTaskSignalProc( USIG16_DLL_LOAD, pModule->self );
584 if (!pModule->cs) return TRUE; /* no initialization code */
587 /* Registers at initialization must be:
588 * cx heap size
589 * di library instance
590 * ds data segment if any
591 * es:si command line (always 0)
594 memset( &context, 0, sizeof(context) );
596 NE_GetDLLInitParams( pModule, &hInst, &ds, &heap );
598 ECX_reg(&context) = heap;
599 EDI_reg(&context) = hInst;
600 DS_reg(&context) = ds;
601 ES_reg(&context) = ds; /* who knows ... */
603 CS_reg(&context) = SEL(pSegTable[pModule->cs-1].hSeg);
604 EIP_reg(&context) = pModule->ip;
605 EBP_reg(&context) = OFFSETOF(NtCurrentTeb()->cur_stack) + (WORD)&((STACK16FRAME*)0)->bp;
608 pModule->cs = 0; /* Don't initialize it twice */
609 TRACE_(dll)("Calling LibMain, cs:ip=%04lx:%04lx ds=%04lx di=%04x cx=%04x\n",
610 CS_reg(&context), EIP_reg(&context), DS_reg(&context),
611 DI_reg(&context), CX_reg(&context) );
612 Callbacks->CallRegisterShortProc( &context, 0 );
613 return TRUE;
616 /***********************************************************************
617 * NE_CallDllEntryPoint
619 * Call the DllEntryPoint of DLLs with subsystem >= 4.0
622 static void NE_CallDllEntryPoint( NE_MODULE *pModule, DWORD dwReason )
624 WORD hInst, ds, heap;
625 FARPROC16 entryPoint;
626 WORD ordinal;
627 CONTEXT86 context;
628 LPBYTE stack = (LPBYTE)CURRENT_STACK16;
630 if (!(pModule->flags & NE_FFLAGS_BUILTIN) && pModule->expected_version < 0x0400) return;
631 if (!(ordinal = NE_GetOrdinal( pModule->self, "DllEntryPoint" ))) return;
632 if (!(entryPoint = NE_GetEntryPoint( pModule->self, ordinal ))) return;
634 memset( &context, 0, sizeof(context) );
636 NE_GetDLLInitParams( pModule, &hInst, &ds, &heap );
638 DS_reg(&context) = ds;
639 ES_reg(&context) = ds; /* who knows ... */
641 CS_reg(&context) = HIWORD(entryPoint);
642 EIP_reg(&context) = LOWORD(entryPoint);
643 EBP_reg(&context) = OFFSETOF( NtCurrentTeb()->cur_stack )
644 + (WORD)&((STACK16FRAME*)0)->bp;
646 *(DWORD *)(stack - 4) = dwReason; /* dwReason */
647 *(WORD *) (stack - 6) = hInst; /* hInst */
648 *(WORD *) (stack - 8) = ds; /* wDS */
649 *(WORD *) (stack - 10) = heap; /* wHeapSize */
650 *(DWORD *)(stack - 14) = 0; /* dwReserved1 */
651 *(WORD *) (stack - 16) = 0; /* wReserved2 */
653 TRACE_(dll)("Calling DllEntryPoint, cs:ip=%04lx:%04lx\n",
654 CS_reg(&context), EIP_reg(&context));
656 Callbacks->CallRegisterShortProc( &context, 16 );
660 /***********************************************************************
661 * NE_InitializeDLLs
663 * Recursively initialize all DLLs (according to the order in which
664 * they where loaded).
666 void NE_InitializeDLLs( HMODULE16 hModule )
668 TDB* pTask = (TDB*)GlobalLock16(GetCurrentTask());
669 NE_MODULE *pModule;
670 HMODULE16 *pDLL;
672 if (!(pModule = NE_GetPtr( hModule ))) return;
673 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
675 if (pModule->dlls_to_init)
677 HGLOBAL16 to_init = pModule->dlls_to_init;
678 pModule->dlls_to_init = 0;
679 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
681 NE_InitializeDLLs( *pDLL );
683 GlobalFree16( to_init );
685 NE_InitDLL( pTask, pModule );
686 NE_CallDllEntryPoint( pModule, DLL_PROCESS_ATTACH );
690 /***********************************************************************
691 * NE_Ne2MemFlags
693 * This function translates NE segment flags to GlobalAlloc flags
695 static WORD NE_Ne2MemFlags(WORD flags)
697 WORD memflags = 0;
698 #if 1
699 if (flags & NE_SEGFLAGS_DISCARDABLE)
700 memflags |= GMEM_DISCARDABLE;
701 if (flags & NE_SEGFLAGS_MOVEABLE ||
702 ( ! (flags & NE_SEGFLAGS_DATA) &&
703 ! (flags & NE_SEGFLAGS_LOADED) &&
704 ! (flags & NE_SEGFLAGS_ALLOCATED)
707 memflags |= GMEM_MOVEABLE;
708 memflags |= GMEM_ZEROINIT;
709 #else
710 memflags = GMEM_ZEROINIT | GMEM_FIXED;
711 #endif
712 return memflags;
715 /***********************************************************************
716 * NE_AllocateSegment (WPROCS.26)
718 * MyAlloc() function for self-loading apps.
720 DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
722 WORD size = wSize << wElem;
723 HANDLE16 hMem = 0;
725 if (wSize || (wFlags & NE_SEGFLAGS_MOVEABLE))
726 hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
728 if ( ((wFlags & 0x7) != 0x1) && /* DATA */
729 ((wFlags & 0x7) != 0x7) ) /* DATA|ALLOCATED|LOADED */
731 WORD hSel = SEL(hMem);
732 WORD access = SelectorAccessRights16(hSel,0,0);
734 access |= 2<<2; /* SEGMENT_CODE */
735 SelectorAccessRights16(hSel,1,access);
737 if (size)
738 return MAKELONG( hMem, SEL(hMem) );
739 else
740 return MAKELONG( 0, hMem );
743 /***********************************************************************
744 * NE_GetInstance
746 HINSTANCE16 NE_GetInstance( NE_MODULE *pModule )
748 if ( !pModule->dgroup )
749 return pModule->self;
750 else
752 SEGTABLEENTRY *pSegment;
753 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
755 return SEL(pSegment->hSeg);
759 /***********************************************************************
760 * NE_CreateSegment
762 BOOL NE_CreateSegment( NE_MODULE *pModule, int segnum )
764 SEGTABLEENTRY *pSegment = NE_SEG_TABLE( pModule ) + segnum - 1;
765 int minsize;
767 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
769 if ( segnum < 1 || segnum > pModule->seg_count )
770 return FALSE;
772 if ( (pModule->flags & NE_FFLAGS_SELFLOAD) && segnum != 1 )
773 return TRUE; /* selfloader allocates segment itself */
775 if ( (pSegment->flags & NE_SEGFLAGS_ALLOCATED) && segnum != pModule->dgroup )
776 return TRUE; /* all but DGROUP only allocated once */
778 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
779 if ( segnum == pModule->ss ) minsize += pModule->stack_size;
780 if ( segnum == pModule->dgroup ) minsize += pModule->heap_size;
782 pSegment->hSeg = GLOBAL_Alloc( NE_Ne2MemFlags(pSegment->flags),
783 minsize, pModule->self,
784 !(pSegment->flags & NE_SEGFLAGS_DATA),
785 (pSegment->flags & NE_SEGFLAGS_32BIT) != 0,
786 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
787 if (!pSegment->hSeg) return FALSE;
789 pSegment->flags |= NE_SEGFLAGS_ALLOCATED;
790 return TRUE;
793 /***********************************************************************
794 * NE_CreateAllSegments
796 BOOL NE_CreateAllSegments( NE_MODULE *pModule )
798 int i;
799 for ( i = 1; i <= pModule->seg_count; i++ )
800 if ( !NE_CreateSegment( pModule, i ) )
801 return FALSE;
803 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
804 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
805 return TRUE;
809 /**********************************************************************
810 * IsSharedSelector (KERNEL.345)
812 BOOL16 WINAPI IsSharedSelector16( HANDLE16 selector )
814 /* Check whether the selector belongs to a DLL */
815 NE_MODULE *pModule = NE_GetPtr( selector );
816 if (!pModule) return FALSE;
817 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;