4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
19 #include "wine/winbase16.h"
23 #include "selectors.h"
27 #include "stackframe.h"
28 #include "debugtools.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 /***********************************************************************
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";
59 /***********************************************************************
62 BOOL
NE_LoadSegment( NE_MODULE
*pModule
, WORD segnum
)
64 SEGTABLEENTRY
*pSegTable
, *pSeg
;
66 WORD count
, i
, offset
, next_offset
;
68 FARPROC16 address
= 0;
71 struct relocation_entry_s
*rep
, *reloc_entries
;
77 int ordinal
, additive
;
80 pSegTable
= NE_SEG_TABLE( pModule
);
81 pSeg
= pSegTable
+ segnum
- 1;
83 if (pSeg
->flags
& NE_SEGFLAGS_LOADED
) /* already loaded ? */
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
;
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
,
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
);
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
);
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
--) {
141 for(byte
= 0; byte
< len
; byte
++)
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" );
178 * Go through the relocation table one entry at a time.
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
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
);
200 NE_MODULE
*pTarget
= NE_GetPtr( module
);
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 );
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,
213 address
= (FARPROC16
)0xdeadbeef;
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
) );
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';
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;
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
) );
255 case NE_RELTYPE_INTERNAL
:
256 if ((rep
->target1
& 0xff) == 0xff)
258 address
= NE_GetEntryPoint( pModule
->self
, rep
->target2
);
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
) );
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
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
) );
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
)
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
);
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
);
307 case NE_RADDR_OFFSET16
:
308 *sp
+= LOWORD(address
);
310 case NE_RADDR_POINTER32
:
311 *sp
+= LOWORD(address
);
312 *(sp
+1) = HIWORD(address
);
314 case NE_RADDR_SELECTOR
:
315 /* Borland creates additive records with offset zero. Strange, but OK */
317 ERR_(fixup
)("Additive selector to %04x.Please report\n",*sp
);
319 *sp
= HIWORD(address
);
325 else /* non-additive fixup */
329 sp
= PTR_SEG_OFF_TO_LIN( SEL(pSeg
->hSeg
), offset
);
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
);
337 case NE_RADDR_OFFSET16
:
338 *sp
= LOWORD(address
);
340 case NE_RADDR_POINTER32
:
341 *(FARPROC16
*)sp
= address
;
343 case NE_RADDR_SELECTOR
:
344 *sp
= SELECTOROF(address
);
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);
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
);
369 /***********************************************************************
372 BOOL
NE_LoadAllSegments( NE_MODULE
*pModule
)
375 SEGTABLEENTRY
* pSegTable
= (SEGTABLEENTRY
*) NE_SEG_TABLE(pModule
);
377 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
)
381 /* Handle self-loading modules */
382 SELFLOADHEADER
*selfloadheader
;
383 HMODULE16 hselfload
= GetModuleHandle16("WPROCS");
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");
408 NtCurrentTeb()->cur_stack
= oldstack
;
410 for (i
= 2; i
<= pModule
->seg_count
; i
++)
411 if (!NE_LoadSegment( pModule
, i
)) return FALSE
;
415 for (i
= 1; i
<= pModule
->seg_count
; i
++)
416 if (!NE_LoadSegment( pModule
, i
)) return FALSE
;
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
);
432 WORD dgroup
, num_entries
, sel
= SEL(pSegTable
[segnum
-1].hSeg
);
435 TRACE_(module
)("(%d);\n", segnum
);
437 if (pSegTable
[segnum
-1].flags
& NE_SEGFLAGS_DATA
)
439 pSegTable
[segnum
-1].flags
|= NE_SEGFLAGS_LOADED
;
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
);
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
))
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
;
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 */
491 } while ( (bundle
->next
)
492 && (bundle
= ((ET_BUNDLE
*)((BYTE
*)pModule
+ bundle
->next
))) );
496 /***********************************************************************
499 * Needed for self-loading modules.
501 DWORD WINAPI
PatchCodeHandle16(HANDLE16 hSeg
)
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
);
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
)
537 ERR_(dll
)("Library is not marked SINGLEDATA\n");
540 else /* DATA NONE DLL */
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 ? */
561 *hInst
= *ds
? *ds
: pModule
->self
;
565 /***********************************************************************
568 * Call the DLL initialization code
570 static BOOL
NE_InitDLL( TDB
* pTask
, NE_MODULE
*pModule
)
572 SEGTABLEENTRY
*pSegTable
;
573 WORD hInst
, ds
, heap
;
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:
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 );
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
;
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 /***********************************************************************
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());
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 /***********************************************************************
693 * This function translates NE segment flags to GlobalAlloc flags
695 static WORD
NE_Ne2MemFlags(WORD flags
)
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
;
710 memflags
= GMEM_ZEROINIT
| GMEM_FIXED
;
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
;
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
);
738 return MAKELONG( hMem
, SEL(hMem
) );
740 return MAKELONG( 0, hMem
);
743 /***********************************************************************
746 HINSTANCE16
NE_GetInstance( NE_MODULE
*pModule
)
748 if ( !pModule
->dgroup
)
749 return pModule
->self
;
752 SEGTABLEENTRY
*pSegment
;
753 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
755 return SEL(pSegment
->hSeg
);
759 /***********************************************************************
762 BOOL
NE_CreateSegment( NE_MODULE
*pModule
, int segnum
)
764 SEGTABLEENTRY
*pSegment
= NE_SEG_TABLE( pModule
) + segnum
- 1;
767 assert( !(pModule
->flags
& NE_FFLAGS_WIN32
) );
769 if ( segnum
< 1 || segnum
> pModule
->seg_count
)
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
;
793 /***********************************************************************
794 * NE_CreateAllSegments
796 BOOL
NE_CreateAllSegments( NE_MODULE
*pModule
)
799 for ( i
= 1; i
<= pModule
->seg_count
; i
++ )
800 if ( !NE_CreateSegment( pModule
, i
) )
803 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
804 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
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;