4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
22 #include "selectors.h"
26 #include "stackframe.h"
30 #define SEL(x) GlobalHandleToSel(x)
32 /***********************************************************************
35 static const char *NE_GetRelocAddrName( BYTE addr_type
, int additive
)
37 switch(addr_type
& 0x7f)
39 case NE_RADDR_LOWBYTE
: return additive
? "BYTE add" : "BYTE";
40 case NE_RADDR_OFFSET16
: return additive
? "OFFSET16 add" : "OFFSET16";
41 case NE_RADDR_POINTER32
: return additive
? "POINTER32 add" : "POINTER32";
42 case NE_RADDR_SELECTOR
: return additive
? "SELECTOR add" : "SELECTOR";
43 case NE_RADDR_POINTER48
: return additive
? "POINTER48 add" : "POINTER48";
44 case NE_RADDR_OFFSET32
: return additive
? "OFFSET32 add" : "OFFSET32";
50 /***********************************************************************
53 BOOL32
NE_LoadSegment( NE_MODULE
*pModule
, WORD segnum
)
55 SEGTABLEENTRY
*pSegTable
, *pSeg
;
57 WORD count
, i
, offset
, next_offset
;
59 FARPROC16 address
= 0;
61 struct relocation_entry_s
*rep
, *reloc_entries
;
67 int ordinal
, additive
;
70 pSegTable
= NE_SEG_TABLE( pModule
);
71 pSeg
= pSegTable
+ segnum
- 1;
73 if (pSeg
->flags
& NE_SEGFLAGS_LOADED
) /* already loaded ? */
76 if (!pSeg
->filepos
) return TRUE
; /* No file image, just return */
78 pModuleTable
= NE_MODULE_TABLE( pModule
);
80 fd
= NE_OpenFile( pModule
);
81 TRACE(module
, "Loading segment %d, hSeg=%04x, flags=%04x\n",
82 segnum
, pSeg
->hSeg
, pSeg
->flags
);
83 lseek( fd
, pSeg
->filepos
<< pModule
->alignment
, SEEK_SET
);
84 if (pSeg
->size
) size
= pSeg
->size
;
85 else size
= pSeg
->minsize
? pSeg
->minsize
: 0x10000;
86 mem
= GlobalLock16(pSeg
->hSeg
);
87 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
&& segnum
> 1)
89 /* Implement self loading segments */
90 SELFLOADHEADER
*selfloadheader
;
91 STACK16FRAME
*stack16Top
;
93 WORD old_hSeg
, new_hSeg
;
94 THDB
*thdb
= THREAD_Current();
95 HFILE32 hf
= FILE_DupUnixHandle( fd
);
97 selfloadheader
= (SELFLOADHEADER
*)
98 PTR_SEG_OFF_TO_LIN(SEL(pSegTable
->hSeg
),0);
99 oldstack
= thdb
->cur_stack
;
100 old_hSeg
= pSeg
->hSeg
;
101 thdb
->cur_stack
= PTR_SEG_OFF_TO_SEGPTR(pModule
->self_loading_sel
,
102 0xff00 - sizeof(*stack16Top
));
103 stack16Top
= (STACK16FRAME
*)PTR_SEG_TO_LIN(thdb
->cur_stack
);
104 stack16Top
->frame32
= 0;
105 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
106 stack16Top
->entry_point
= 0;
107 stack16Top
->entry_ip
= 0;
108 stack16Top
->entry_cs
= 0;
112 TRACE(dll
,"CallLoadAppSegProc(hmodule=0x%04x,hf=0x%04x,segnum=%d\n",
113 pModule
->self
,hf
,segnum
);
114 new_hSeg
= Callbacks
->CallLoadAppSegProc(selfloadheader
->LoadAppSeg
,
116 HFILE32_TO_HFILE16(hf
),
118 TRACE(dll
,"Ret CallLoadAppSegProc: hSeg = 0x%04x\n",new_hSeg
);
120 if (SEL(new_hSeg
) != SEL(old_hSeg
)) {
121 /* Self loaders like creating their own selectors;
122 * they love asking for trouble to Wine developers
124 if (segnum
== pModule
->dgroup
) {
125 memcpy(PTR_SEG_OFF_TO_LIN(SEL(old_hSeg
),0),
126 PTR_SEG_OFF_TO_LIN(SEL(new_hSeg
),0),
127 pSeg
->minsize
? pSeg
->minsize
: 0x10000);
128 FreeSelector(SEL(new_hSeg
));
129 pSeg
->hSeg
= old_hSeg
;
130 TRACE(module
, "New hSeg allocated for dgroup segment:Old=%d,New=%d\n",
133 FreeSelector(SEL(pSeg
->hSeg
));
134 pSeg
->hSeg
= new_hSeg
;
138 thdb
->cur_stack
= oldstack
;
140 else if (!(pSeg
->flags
& NE_SEGFLAGS_ITERATED
))
144 The following bit of code for "iterated segments" was written without
145 any documentation on the format of these segments. It seems to work,
146 but may be missing something. If you have any doc please either send
147 it to me or fix the code yourself. gfm@werple.mira.net.au
149 char* buff
= xmalloc(size
);
151 read(fd
, buff
, size
);
152 while(curr
< buff
+ size
) {
153 unsigned int rept
= *((short*) curr
)++;
154 unsigned int len
= *((short*) curr
)++;
155 for(; rept
> 0; rept
--) {
158 for(byte
= 0; byte
< len
; byte
++)
166 pSeg
->flags
|= NE_SEGFLAGS_LOADED
;
167 if (!(pSeg
->flags
& NE_SEGFLAGS_RELOC_DATA
))
168 return TRUE
; /* No relocation data, we are done */
170 read( fd
, &count
, sizeof(count
) );
171 if (!count
) return TRUE
;
173 TRACE(fixup
, "Fixups for %.*s, segment %d, hSeg %04x\n",
174 *((BYTE
*)pModule
+ pModule
->name_table
),
175 (char *)pModule
+ pModule
->name_table
+ 1,
176 segnum
, pSeg
->hSeg
);
177 TRACE(segment
, "Fixups for %.*s, segment %d, hSeg %04x\n",
178 *((BYTE
*)pModule
+ pModule
->name_table
),
179 (char *)pModule
+ pModule
->name_table
+ 1,
180 segnum
, pSeg
->hSeg
);
182 reloc_entries
= (struct relocation_entry_s
*)xmalloc(count
* sizeof(struct relocation_entry_s
));
183 if (read( fd
, reloc_entries
, count
* sizeof(struct relocation_entry_s
)) !=
184 count
* sizeof(struct relocation_entry_s
))
186 WARN(fixup
, "Unable to read relocation information\n" );
191 * Go through the relocation table one entry at a time.
194 for (i
= 0; i
< count
; i
++, rep
++)
197 * Get the target address corresponding to this entry.
200 /* If additive, there is no target chain list. Instead, add source
202 additive
= rep
->relocation_type
& NE_RELFLAG_ADDITIVE
;
203 rep
->relocation_type
&= 0x3;
205 switch (rep
->relocation_type
)
207 case NE_RELTYPE_ORDINAL
:
208 module
= pModuleTable
[rep
->target1
-1];
209 ordinal
= rep
->target2
;
210 address
= NE_GetEntryPoint( module
, ordinal
);
213 NE_MODULE
*pTarget
= NE_GetPtr( module
);
215 WARN(module
, "Module not found: %04x, reference %d of module %*.*s\n",
216 module
, rep
->target1
,
217 *((BYTE
*)pModule
+ pModule
->name_table
),
218 *((BYTE
*)pModule
+ pModule
->name_table
),
219 (char *)pModule
+ pModule
->name_table
+ 1 );
222 ERR(fixup
, "No handler for %.*s.%d, setting to 0xdeadbeef\n",
223 *((BYTE
*)pTarget
+ pTarget
->name_table
),
224 (char *)pTarget
+ pTarget
->name_table
+ 1,
226 address
= (FARPROC16
)0xdeadbeef;
231 NE_MODULE
*pTarget
= NE_GetPtr( module
);
232 TRACE( fixup
, "%d: %.*s.%d=%04x:%04x %s\n", i
+ 1,
233 *((BYTE
*)pTarget
+ pTarget
->name_table
),
234 (char *)pTarget
+ pTarget
->name_table
+ 1,
235 ordinal
, HIWORD(address
), LOWORD(address
),
236 NE_GetRelocAddrName( rep
->address_type
, additive
) );
240 case NE_RELTYPE_NAME
:
241 module
= pModuleTable
[rep
->target1
-1];
242 func_name
= (char *)pModule
+ pModule
->import_table
+ rep
->target2
;
243 memcpy( buffer
, func_name
+1, *func_name
);
244 buffer
[*func_name
] = '\0';
246 ordinal
= NE_GetOrdinal( module
, func_name
);
247 address
= NE_GetEntryPoint( module
, ordinal
);
249 if (ERR_ON(fixup
) && !address
)
251 NE_MODULE
*pTarget
= NE_GetPtr( module
);
252 ERR(fixup
, "Warning: no handler for %.*s.%s, setting to 0xdeadbeef\n",
253 *((BYTE
*)pTarget
+ pTarget
->name_table
),
254 (char *)pTarget
+ pTarget
->name_table
+ 1, func_name
);
256 if (!address
) address
= (FARPROC16
) 0xdeadbeef;
259 NE_MODULE
*pTarget
= NE_GetPtr( module
);
260 TRACE( fixup
, "%d: %.*s.%s=%04x:%04x %s\n", i
+ 1,
261 *((BYTE
*)pTarget
+ pTarget
->name_table
),
262 (char *)pTarget
+ pTarget
->name_table
+ 1,
263 func_name
, HIWORD(address
), LOWORD(address
),
264 NE_GetRelocAddrName( rep
->address_type
, additive
) );
268 case NE_RELTYPE_INTERNAL
:
269 if ((rep
->target1
& 0xff) == 0xff)
271 address
= NE_GetEntryPoint( pModule
->self
, rep
->target2
);
275 address
= (FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( SEL(pSegTable
[rep
->target1
-1].hSeg
), rep
->target2
);
278 TRACE( fixup
,"%d: %04x:%04x %s\n",
279 i
+ 1, HIWORD(address
), LOWORD(address
),
280 NE_GetRelocAddrName( rep
->address_type
, additive
) );
283 case NE_RELTYPE_OSFIXUP
:
284 /* Relocation type 7:
286 * These appear to be used as fixups for the Windows
287 * floating point emulator. Let's just ignore them and
288 * try to use the hardware floating point. Linux should
289 * successfully emulate the coprocessor if it doesn't
292 TRACE( fixup
, "%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
293 i
+ 1, rep
->relocation_type
, rep
->offset
,
294 rep
->target1
, rep
->target2
,
295 NE_GetRelocAddrName( rep
->address_type
, additive
) );
299 offset
= rep
->offset
;
301 /* Apparently, high bit of address_type is sometimes set; */
302 /* we ignore it for now */
303 if (rep
->address_type
> NE_RADDR_OFFSET32
)
306 GetModuleName( pModule
->self
, module
, sizeof(module
) );
307 ERR( fixup
, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
308 module
, rep
->address_type
);
313 sp
= PTR_SEG_OFF_TO_LIN( SEL(pSeg
->hSeg
), offset
);
314 TRACE( fixup
," %04x:%04x\n", offset
, *sp
);
315 switch (rep
->address_type
& 0x7f)
317 case NE_RADDR_LOWBYTE
:
318 *(BYTE
*)sp
+= LOBYTE((int)address
);
320 case NE_RADDR_OFFSET16
:
321 *sp
+= LOWORD(address
);
323 case NE_RADDR_POINTER32
:
324 *sp
+= LOWORD(address
);
325 *(sp
+1) = HIWORD(address
);
327 case NE_RADDR_SELECTOR
:
328 /* Borland creates additive records with offset zero. Strange, but OK */
330 ERR(fixup
,"Additive selector to %04x.Please report\n",*sp
);
332 *sp
= HIWORD(address
);
338 else /* non-additive fixup */
342 sp
= PTR_SEG_OFF_TO_LIN( SEL(pSeg
->hSeg
), offset
);
344 TRACE( fixup
," %04x:%04x\n", offset
, *sp
);
345 switch (rep
->address_type
& 0x7f)
347 case NE_RADDR_LOWBYTE
:
348 *(BYTE
*)sp
= LOBYTE((int)address
);
350 case NE_RADDR_OFFSET16
:
351 *sp
= LOWORD(address
);
353 case NE_RADDR_POINTER32
:
354 *(FARPROC16
*)sp
= address
;
356 case NE_RADDR_SELECTOR
:
357 *sp
= SELECTOROF(address
);
362 if (next_offset
== offset
) break; /* avoid infinite loop */
363 if (next_offset
>= GlobalSize16(pSeg
->hSeg
)) break;
364 offset
= next_offset
;
365 } while (offset
!= 0xffff);
373 WARN(fixup
, "WARNING: %d: unknown ADDR TYPE %d, "
374 "TYPE %d, OFFSET %04x, TARGET %04x %04x\n",
375 i
+ 1, rep
->address_type
, rep
->relocation_type
,
376 rep
->offset
, rep
->target1
, rep
->target2
);
382 /***********************************************************************
385 BOOL32
NE_LoadAllSegments( NE_MODULE
*pModule
)
388 SEGTABLEENTRY
* pSegTable
= (SEGTABLEENTRY
*) NE_SEG_TABLE(pModule
);
390 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
)
393 /* Handle self loading modules */
394 SELFLOADHEADER
*selfloadheader
;
395 STACK16FRAME
*stack16Top
;
396 THDB
*thdb
= THREAD_Current();
397 HMODULE16 hselfload
= GetModuleHandle16("WPROCS");
399 WORD saved_hSeg
= pSegTable
[pModule
->dgroup
- 1].hSeg
;
401 TRACE(module
, "%.*s is a self-loading module!\n",
402 *((BYTE
*)pModule
+ pModule
->name_table
),
403 (char *)pModule
+ pModule
->name_table
+ 1);
404 if (!NE_LoadSegment( pModule
, 1 )) return FALSE
;
405 selfloadheader
= (SELFLOADHEADER
*)
406 PTR_SEG_OFF_TO_LIN(SEL(pSegTable
->hSeg
), 0);
407 selfloadheader
->EntryAddrProc
= NE_GetEntryPoint(hselfload
,27);
408 selfloadheader
->MyAlloc
= NE_GetEntryPoint(hselfload
,28);
409 selfloadheader
->SetOwner
= NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
410 pModule
->self_loading_sel
= GlobalHandleToSel(GLOBAL_Alloc(GMEM_ZEROINIT
, 0xFF00, pModule
->self
, FALSE
, FALSE
, FALSE
));
411 oldstack
= thdb
->cur_stack
;
412 thdb
->cur_stack
= PTR_SEG_OFF_TO_SEGPTR(pModule
->self_loading_sel
,
413 0xff00 - sizeof(*stack16Top
) );
414 stack16Top
= (STACK16FRAME
*)PTR_SEG_TO_LIN(thdb
->cur_stack
);
415 stack16Top
->frame32
= 0;
417 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
418 stack16Top
->entry_point
= 0;
419 stack16Top
->entry_ip
= 0;
420 stack16Top
->entry_cs
= 0;
425 hf
= FILE_DupUnixHandle( NE_OpenFile( pModule
) );
426 TRACE(dll
,"CallBootAppProc(hModule=0x%04x,hf=0x%04x)\n",pModule
->self
,
427 HFILE32_TO_HFILE16(hf
));
428 Callbacks
->CallBootAppProc(selfloadheader
->BootApp
, pModule
->self
,
429 HFILE32_TO_HFILE16(hf
));
430 TRACE(dll
,"Return from CallBootAppProc\n");
432 /* some BootApp procs overwrite the segment handle of dgroup */
433 pSegTable
[pModule
->dgroup
- 1].hSeg
= saved_hSeg
;
434 thdb
->cur_stack
= oldstack
;
436 for (i
= 2; i
<= pModule
->seg_count
; i
++)
437 if (!NE_LoadSegment( pModule
, i
)) return FALSE
;
441 for (i
= 1; i
<= pModule
->seg_count
; i
++)
442 if (!NE_LoadSegment( pModule
, i
)) return FALSE
;
448 /***********************************************************************
451 * Needed for self-loading modules.
454 /* It does nothing */
455 DWORD WINAPI
PatchCodeHandle(HANDLE16 hSel
)
457 FIXME(module
,"(%04x): stub.\n",hSel
);
462 /***********************************************************************
465 * Fixup the exported functions prologs.
467 void NE_FixupPrologs( NE_MODULE
*pModule
)
469 SEGTABLEENTRY
*pSegTable
;
472 BYTE
*p
, *fixup_ptr
, count
;
473 dbg_decl_str(module
, 512);
475 pSegTable
= NE_SEG_TABLE(pModule
);
476 if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
477 dgroup
= SEL(pSegTable
[pModule
->dgroup
-1].hSeg
);
479 TRACE(module
, "(%04x)\n", pModule
->self
);
480 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
483 if (p
[1] == 0) /* Unused entry */
485 p
+= 2; /* Skip it */
488 if (p
[1] == 0xfe) /* Constant entry */
490 p
+= 2 + *p
* 3; /* Skip it */
494 /* Now fixup the entries of this bundle */
500 dbg_reset_str(module
);
501 dsprintf(module
,"Flags: %04x, sel %02x ", *p
, sel
);
502 /* According to the output generated by TDUMP, the flags mean:
503 * 0x0001 function is exported
504 * 0x0002 Single data (seems to occur only in DLLs)
506 if (sel
== 0xff) { /* moveable */
507 dsprintf(module
, "(%02x) o %04x", p
[3], *(WORD
*)(p
+4) );
508 fixup_ptr
= (char *)GET_SEL_BASE(SEL(pSegTable
[p
[3]-1].hSeg
)) + *(WORD
*)(p
+ 4);
510 dsprintf(module
, "offset %04x", *(WORD
*)(p
+1) );
511 fixup_ptr
= (char *)GET_SEL_BASE(SEL(pSegTable
[sel
-1].hSeg
)) +
514 TRACE(module
, "%s Signature: %02x %02x %02x,ff %x\n",
515 dbg_str(module
), fixup_ptr
[0], fixup_ptr
[1],
516 fixup_ptr
[2], pModule
->flags
);
519 /* Verify the signature */
520 if (((fixup_ptr
[0] == 0x1e && fixup_ptr
[1] == 0x58)
521 || (fixup_ptr
[0] == 0x8c && fixup_ptr
[1] == 0xd8))
522 && fixup_ptr
[2] == 0x90)
526 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
)
528 /* can this happen? */
529 ERR(fixup
, "FixupPrologs got confused\n" );
531 else if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
533 *fixup_ptr
= 0xb8; /* MOV AX, */
534 *(WORD
*)(fixup_ptr
+1) = dgroup
;
539 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
540 fixup_ptr
[0] = 0x90; /* non-library: NOPs */
546 WARN(fixup
, "Unknown signature\n" );
551 p
+= (sel
== 0xff) ? 6 : 3;
556 /***********************************************************************
557 * NE_GetDLLInitParams
559 static VOID
NE_GetDLLInitParams( NE_MODULE
*pModule
,
560 WORD
*hInst
, WORD
*ds
, WORD
*heap
)
562 SEGTABLEENTRY
*pSegTable
= NE_SEG_TABLE( pModule
);
564 if (!(pModule
->flags
& NE_FFLAGS_SINGLEDATA
))
566 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
|| pModule
->dgroup
)
569 ERR(dll
, "Library is not marked SINGLEDATA\n");
572 else /* DATA NONE DLL */
578 else /* DATA SINGLE DLL */
580 if (pModule
->dgroup
) {
581 *ds
= SEL(pSegTable
[pModule
->dgroup
-1].hSeg
);
582 *heap
= pModule
->heap_size
;
584 else /* hmm, DLL has no dgroup,
585 but why has it NE_FFLAGS_SINGLEDATA set ?
586 Buggy DLL compiler ? */
593 *hInst
= *ds
? *ds
: pModule
->self
;
597 /***********************************************************************
600 * Call the DLL initialization code
602 static BOOL32
NE_InitDLL( TDB
* pTask
, NE_MODULE
*pModule
)
604 SEGTABLEENTRY
*pSegTable
;
605 WORD hInst
, ds
, heap
;
608 pSegTable
= NE_SEG_TABLE( pModule
);
610 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) ||
611 (pModule
->flags
& NE_FFLAGS_WIN32
)) return TRUE
; /*not a library*/
613 /* Call USER signal handler. This is necessary to install a
614 * proper loader for HICON and HCURSOR resources that this DLL
615 * may contain. InitApp() does this for task modules. */
617 if (pTask
&& pTask
->userhandler
)
619 pTask
->userhandler( pModule
->self
, USIG_DLL_LOAD
, 0, pTask
->hInstance
,
623 if (!pModule
->cs
) return TRUE
; /* no initialization code */
626 /* Registers at initialization must be:
628 * di library instance
629 * ds data segment if any
630 * es:si command line (always 0)
633 memset( &context
, 0, sizeof(context
) );
635 NE_GetDLLInitParams( pModule
, &hInst
, &ds
, &heap
);
637 ECX_reg(&context
) = heap
;
638 EDI_reg(&context
) = hInst
;
639 DS_reg(&context
) = ds
;
640 ES_reg(&context
) = ds
; /* who knows ... */
642 CS_reg(&context
) = SEL(pSegTable
[pModule
->cs
-1].hSeg
);
643 EIP_reg(&context
) = pModule
->ip
;
644 EBP_reg(&context
) = OFFSETOF(THREAD_Current()->cur_stack
)
645 + (WORD
)&((STACK16FRAME
*)0)->bp
;
648 pModule
->cs
= 0; /* Don't initialize it twice */
649 TRACE(dll
, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
650 CS_reg(&context
), IP_reg(&context
), DS_reg(&context
),
651 DI_reg(&context
), CX_reg(&context
) );
652 Callbacks
->CallRegisterShortProc( &context
, 0 );
656 /***********************************************************************
657 * NE_CallDllEntryPoint
659 * Call the DllEntryPoint of DLLs with subsystem >= 4.0
662 static void NE_CallDllEntryPoint( NE_MODULE
*pModule
, DWORD dwReason
)
664 WORD hInst
, ds
, heap
;
665 FARPROC16 entryPoint
;
668 THDB
*thdb
= THREAD_Current();
669 LPBYTE stack
= (LPBYTE
)THREAD_STACK16(thdb
);
671 if (pModule
->expected_version
< 0x0400) return;
672 if (!(ordinal
= NE_GetOrdinal( pModule
->self
, "DllEntryPoint" ))) return;
673 if (!(entryPoint
= NE_GetEntryPoint( pModule
->self
, ordinal
))) return;
675 memset( &context
, 0, sizeof(context
) );
677 NE_GetDLLInitParams( pModule
, &hInst
, &ds
, &heap
);
679 DS_reg(&context
) = ds
;
680 ES_reg(&context
) = ds
; /* who knows ... */
682 CS_reg(&context
) = HIWORD(entryPoint
);
683 IP_reg(&context
) = LOWORD(entryPoint
);
684 EBP_reg(&context
) = OFFSETOF( thdb
->cur_stack
)
685 + (WORD
)&((STACK16FRAME
*)0)->bp
;
687 *(DWORD
*)(stack
- 4) = dwReason
; /* dwReason */
688 *(WORD
*) (stack
- 6) = hInst
; /* hInst */
689 *(WORD
*) (stack
- 8) = ds
; /* wDS */
690 *(WORD
*) (stack
- 10) = heap
; /* wHeapSize */
691 *(DWORD
*)(stack
- 14) = 0; /* dwReserved1 */
692 *(WORD
*) (stack
- 16) = 0; /* wReserved2 */
694 TRACE(dll
, "Calling DllEntryPoint, cs:ip=%04lx:%04x\n",
695 CS_reg(&context
), IP_reg(&context
));
697 Callbacks
->CallRegisterShortProc( &context
, 16 );
701 /***********************************************************************
704 * Recursively initialize all DLLs (according to the order in which
705 * they where loaded).
707 void NE_InitializeDLLs( HMODULE16 hModule
)
709 TDB
* pTask
= (TDB
*)GlobalLock16(GetCurrentTask());
713 if (!(pModule
= NE_GetPtr( hModule
))) return;
714 assert( !(pModule
->flags
& NE_FFLAGS_WIN32
) );
716 if (pModule
->dlls_to_init
)
718 HGLOBAL16 to_init
= pModule
->dlls_to_init
;
719 pModule
->dlls_to_init
= 0;
720 for (pDLL
= (HMODULE16
*)GlobalLock16( to_init
); *pDLL
; pDLL
++)
722 NE_InitializeDLLs( *pDLL
);
724 GlobalFree16( to_init
);
726 NE_InitDLL( pTask
, pModule
);
727 NE_CallDllEntryPoint( pModule
, DLL_PROCESS_ATTACH
);
731 /***********************************************************************
734 * If lib_only is TRUE, handle the module like a library even if it is a .EXE
736 HINSTANCE16
NE_CreateInstance( NE_MODULE
*pModule
, HINSTANCE16
*prev
,
739 SEGTABLEENTRY
*pSegment
;
741 HINSTANCE16 hNewInstance
;
743 if (pModule
->dgroup
== 0)
745 if (prev
) *prev
= pModule
->self
;
746 return pModule
->self
;
749 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
750 if (prev
) *prev
= SEL(pSegment
->hSeg
);
752 /* if it's a library, create a new instance only the first time */
755 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return SEL(pSegment
->hSeg
);
756 if (lib_only
) return SEL(pSegment
->hSeg
);
759 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
760 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
761 minsize
+= pModule
->heap_size
;
762 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
, minsize
,
763 pModule
->self
, FALSE
, FALSE
, FALSE
);
764 if (!hNewInstance
) return 0;
765 pSegment
->hSeg
= hNewInstance
;
766 pSegment
->flags
|= NE_SEGFLAGS_ALLOCATED
;
771 /***********************************************************************
774 * This function translates NE segment flags to GlobalAlloc flags
776 static WORD
NE_Ne2MemFlags(WORD flags
)
780 if (flags
& NE_SEGFLAGS_DISCARDABLE
)
781 memflags
|= GMEM_DISCARDABLE
;
782 if (flags
& NE_SEGFLAGS_MOVEABLE
||
783 ( ! (flags
& NE_SEGFLAGS_DATA
) &&
784 ! (flags
& NE_SEGFLAGS_LOADED
) &&
785 ! (flags
& NE_SEGFLAGS_ALLOCATED
)
788 memflags
|= GMEM_MOVEABLE
;
789 memflags
|= GMEM_ZEROINIT
;
791 memflags
= GMEM_ZEROINIT
| GMEM_FIXED
;
796 /***********************************************************************
797 * NE_AllocateSegment (WPROCS.26)
799 DWORD WINAPI
NE_AllocateSegment( WORD wFlags
, WORD wSize
, WORD wElem
)
801 WORD size
= wSize
<< wElem
;
802 HANDLE16 hMem
= GlobalAlloc16( NE_Ne2MemFlags(wFlags
), size
);
803 return MAKELONG( hMem
, GlobalHandleToSel(hMem
) );
807 /***********************************************************************
810 BOOL32
NE_CreateSegments( NE_MODULE
*pModule
)
812 SEGTABLEENTRY
*pSegment
;
815 assert( !(pModule
->flags
& NE_FFLAGS_WIN32
) );
817 pSegment
= NE_SEG_TABLE( pModule
);
818 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
820 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
821 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
822 /* The DGROUP is allocated by NE_CreateInstance */
823 if (i
== pModule
->dgroup
) continue;
824 pSegment
->hSeg
= GLOBAL_Alloc( NE_Ne2MemFlags(pSegment
->flags
),
825 minsize
, pModule
->self
,
826 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
828 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
829 if (!pSegment
->hSeg
) return FALSE
;
830 pSegment
->flags
|= NE_SEGFLAGS_ALLOCATED
;
833 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
834 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
839 /**********************************************************************
840 * IsSharedSelector (KERNEL.345)
842 BOOL16 WINAPI
IsSharedSelector( HANDLE16 selector
)
844 /* Check whether the selector belongs to a DLL */
845 NE_MODULE
*pModule
= NE_GetPtr( selector
);
846 if (!pModule
) return FALSE
;
847 return (pModule
->flags
& NE_FFLAGS_LIBMODULE
) != 0;