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;
72 pModuleTable
= NE_MODULE_TABLE( pModule
);
74 if (!pSeg
->filepos
) return TRUE
; /* No file image, just return */
76 fd
= NE_OpenFile( pModule
);
77 TRACE(module
, "Loading segment %d, hSeg=%04x, flags=%04x\n",
78 segnum
, pSeg
->hSeg
, pSeg
->flags
);
79 lseek( fd
, pSeg
->filepos
<< pModule
->alignment
, SEEK_SET
);
80 if (pSeg
->size
) size
= pSeg
->size
;
81 else if (pSeg
->minsize
) size
= pSeg
->minsize
;
83 mem
= GlobalLock16(pSeg
->hSeg
);
84 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
&& segnum
> 1)
86 /* Implement self loading segments */
87 SELFLOADHEADER
*selfloadheader
;
88 STACK16FRAME
*stack16Top
;
90 WORD old_hSeg
, new_hSeg
;
91 THDB
*thdb
= THREAD_Current();
92 HFILE32 hf
= FILE_DupUnixHandle( fd
);
94 selfloadheader
= (SELFLOADHEADER
*)
95 PTR_SEG_OFF_TO_LIN(SEL(pSegTable
->hSeg
),0);
96 oldstack
= thdb
->cur_stack
;
97 old_hSeg
= pSeg
->hSeg
;
98 thdb
->cur_stack
= PTR_SEG_OFF_TO_SEGPTR(pModule
->self_loading_sel
,
99 0xff00 - sizeof(*stack16Top
));
100 stack16Top
= (STACK16FRAME
*)PTR_SEG_TO_LIN(thdb
->cur_stack
);
101 stack16Top
->frame32
= 0;
102 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
103 stack16Top
->entry_point
= 0;
104 stack16Top
->entry_ip
= 0;
105 stack16Top
->entry_cs
= 0;
109 TRACE(dll
,"CallLoadAppSegProc(hmodule=0x%04x,hf=0x%04x,segnum=%d\n",
110 pModule
->self
,hf
,segnum
);
111 new_hSeg
= Callbacks
->CallLoadAppSegProc(selfloadheader
->LoadAppSeg
,
113 HFILE32_TO_HFILE16(hf
),
115 TRACE(dll
,"Ret CallLoadAppSegProc: hSeg = 0x%04x\n",new_hSeg
);
117 if (SEL(new_hSeg
) != SEL(old_hSeg
)) {
118 /* Self loaders like creating their own selectors;
119 * they love asking for trouble to Wine developers
121 if (segnum
== pModule
->dgroup
) {
122 memcpy(PTR_SEG_OFF_TO_LIN(SEL(old_hSeg
),0),
123 PTR_SEG_OFF_TO_LIN(SEL(new_hSeg
),0),
124 pSeg
->minsize
? pSeg
->minsize
: 0x10000);
125 FreeSelector(SEL(new_hSeg
));
126 pSeg
->hSeg
= old_hSeg
;
127 TRACE(module
, "New hSeg allocated for dgroup segment:Old=%d,New=%d\n",
130 FreeSelector(SEL(pSeg
->hSeg
));
131 pSeg
->hSeg
= new_hSeg
;
135 thdb
->cur_stack
= oldstack
;
137 else if (!(pSeg
->flags
& NE_SEGFLAGS_ITERATED
))
141 The following bit of code for "iterated segments" was written without
142 any documentation on the format of these segments. It seems to work,
143 but may be missing something. If you have any doc please either send
144 it to me or fix the code yourself. gfm@werple.mira.net.au
146 char* buff
= xmalloc(size
);
148 read(fd
, buff
, size
);
149 while(curr
< buff
+ size
) {
150 unsigned int rept
= *((short*) curr
)++;
151 unsigned int len
= *((short*) curr
)++;
152 for(; rept
> 0; rept
--) {
155 for(byte
= 0; byte
< len
; byte
++)
163 pSeg
->flags
|= NE_SEGFLAGS_LOADED
;
164 if (!(pSeg
->flags
& NE_SEGFLAGS_RELOC_DATA
))
165 return TRUE
; /* No relocation data, we are done */
167 read( fd
, &count
, sizeof(count
) );
168 if (!count
) return TRUE
;
170 TRACE(fixup
, "Fixups for %.*s, segment %d, hSeg %04x\n",
171 *((BYTE
*)pModule
+ pModule
->name_table
),
172 (char *)pModule
+ pModule
->name_table
+ 1,
173 segnum
, pSeg
->hSeg
);
174 TRACE(segment
, "Fixups for %.*s, segment %d, hSeg %04x\n",
175 *((BYTE
*)pModule
+ pModule
->name_table
),
176 (char *)pModule
+ pModule
->name_table
+ 1,
177 segnum
, pSeg
->hSeg
);
179 reloc_entries
= (struct relocation_entry_s
*)xmalloc(count
* sizeof(struct relocation_entry_s
));
180 if (read( fd
, reloc_entries
, count
* sizeof(struct relocation_entry_s
)) !=
181 count
* sizeof(struct relocation_entry_s
))
183 WARN(fixup
, "Unable to read relocation information\n" );
188 * Go through the relocation table one entry at a time.
191 for (i
= 0; i
< count
; i
++, rep
++)
194 * Get the target address corresponding to this entry.
197 /* If additive, there is no target chain list. Instead, add source
199 additive
= rep
->relocation_type
& NE_RELFLAG_ADDITIVE
;
200 rep
->relocation_type
&= 0x3;
202 switch (rep
->relocation_type
)
204 case NE_RELTYPE_ORDINAL
:
205 module
= pModuleTable
[rep
->target1
-1];
206 ordinal
= rep
->target2
;
207 address
= NE_GetEntryPoint( module
, ordinal
);
210 NE_MODULE
*pTarget
= NE_GetPtr( module
);
212 WARN(module
, "Module not found: %04x, reference %d of module %*.*s\n",
213 module
, rep
->target1
,
214 *((BYTE
*)pModule
+ pModule
->name_table
),
215 *((BYTE
*)pModule
+ pModule
->name_table
),
216 (char *)pModule
+ pModule
->name_table
+ 1 );
219 ERR(fixup
, "No handler for %.*s.%d, setting to 0xdeadbeef\n",
220 *((BYTE
*)pTarget
+ pTarget
->name_table
),
221 (char *)pTarget
+ pTarget
->name_table
+ 1,
223 address
= (FARPROC16
)0xdeadbeef;
228 NE_MODULE
*pTarget
= NE_GetPtr( module
);
229 TRACE( fixup
, "%d: %.*s.%d=%04x:%04x %s\n", i
+ 1,
230 *((BYTE
*)pTarget
+ pTarget
->name_table
),
231 (char *)pTarget
+ pTarget
->name_table
+ 1,
232 ordinal
, HIWORD(address
), LOWORD(address
),
233 NE_GetRelocAddrName( rep
->address_type
, additive
) );
237 case NE_RELTYPE_NAME
:
238 module
= pModuleTable
[rep
->target1
-1];
239 func_name
= (char *)pModule
+ pModule
->import_table
+ rep
->target2
;
240 memcpy( buffer
, func_name
+1, *func_name
);
241 buffer
[*func_name
] = '\0';
243 ordinal
= NE_GetOrdinal( module
, func_name
);
244 address
= NE_GetEntryPoint( module
, ordinal
);
246 if (ERR_ON(fixup
) && !address
)
248 NE_MODULE
*pTarget
= NE_GetPtr( module
);
249 ERR(fixup
, "Warning: no handler for %.*s.%s, setting to 0xdeadbeef\n",
250 *((BYTE
*)pTarget
+ pTarget
->name_table
),
251 (char *)pTarget
+ pTarget
->name_table
+ 1, func_name
);
253 if (!address
) address
= (FARPROC16
) 0xdeadbeef;
256 NE_MODULE
*pTarget
= NE_GetPtr( module
);
257 TRACE( fixup
, "%d: %.*s.%s=%04x:%04x %s\n", i
+ 1,
258 *((BYTE
*)pTarget
+ pTarget
->name_table
),
259 (char *)pTarget
+ pTarget
->name_table
+ 1,
260 func_name
, HIWORD(address
), LOWORD(address
),
261 NE_GetRelocAddrName( rep
->address_type
, additive
) );
265 case NE_RELTYPE_INTERNAL
:
266 if ((rep
->target1
& 0xff) == 0xff)
268 address
= NE_GetEntryPoint( pModule
->self
, rep
->target2
);
272 address
= (FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( SEL(pSegTable
[rep
->target1
-1].hSeg
), rep
->target2
);
275 TRACE( fixup
,"%d: %04x:%04x %s\n",
276 i
+ 1, HIWORD(address
), LOWORD(address
),
277 NE_GetRelocAddrName( rep
->address_type
, additive
) );
280 case NE_RELTYPE_OSFIXUP
:
281 /* Relocation type 7:
283 * These appear to be used as fixups for the Windows
284 * floating point emulator. Let's just ignore them and
285 * try to use the hardware floating point. Linux should
286 * successfully emulate the coprocessor if it doesn't
289 TRACE( fixup
, "%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
290 i
+ 1, rep
->relocation_type
, rep
->offset
,
291 rep
->target1
, rep
->target2
,
292 NE_GetRelocAddrName( rep
->address_type
, additive
) );
296 offset
= rep
->offset
;
298 /* Apparently, high bit of address_type is sometimes set; */
299 /* we ignore it for now */
300 if (rep
->address_type
> NE_RADDR_OFFSET32
)
303 GetModuleName( pModule
->self
, module
, sizeof(module
) );
304 ERR( fixup
, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
305 module
, rep
->address_type
);
310 sp
= PTR_SEG_OFF_TO_LIN( SEL(pSeg
->hSeg
), offset
);
311 TRACE( fixup
," %04x:%04x\n", offset
, *sp
);
312 switch (rep
->address_type
& 0x7f)
314 case NE_RADDR_LOWBYTE
:
315 *(BYTE
*)sp
+= LOBYTE((int)address
);
317 case NE_RADDR_OFFSET16
:
318 *sp
+= LOWORD(address
);
320 case NE_RADDR_POINTER32
:
321 *sp
+= LOWORD(address
);
322 *(sp
+1) = HIWORD(address
);
324 case NE_RADDR_SELECTOR
:
325 /* Borland creates additive records with offset zero. Strange, but OK */
327 ERR(fixup
,"Additive selector to %04x.Please report\n",*sp
);
329 *sp
= HIWORD(address
);
335 else /* non-additive fixup */
339 sp
= PTR_SEG_OFF_TO_LIN( SEL(pSeg
->hSeg
), offset
);
341 TRACE( fixup
," %04x:%04x\n", offset
, *sp
);
342 switch (rep
->address_type
& 0x7f)
344 case NE_RADDR_LOWBYTE
:
345 *(BYTE
*)sp
= LOBYTE((int)address
);
347 case NE_RADDR_OFFSET16
:
348 *sp
= LOWORD(address
);
350 case NE_RADDR_POINTER32
:
351 *(FARPROC16
*)sp
= address
;
353 case NE_RADDR_SELECTOR
:
354 *sp
= SELECTOROF(address
);
359 if (next_offset
== offset
) break; /* avoid infinite loop */
360 if (next_offset
>= GlobalSize16(pSeg
->hSeg
)) break;
361 offset
= next_offset
;
362 } while (offset
!= 0xffff);
370 WARN(fixup
, "WARNING: %d: unknown ADDR TYPE %d, "
371 "TYPE %d, OFFSET %04x, TARGET %04x %04x\n",
372 i
+ 1, rep
->address_type
, rep
->relocation_type
,
373 rep
->offset
, rep
->target1
, rep
->target2
);
379 /***********************************************************************
382 BOOL32
NE_LoadAllSegments( NE_MODULE
*pModule
)
386 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
)
389 /* Handle self loading modules */
390 SEGTABLEENTRY
* pSegTable
= (SEGTABLEENTRY
*) NE_SEG_TABLE(pModule
);
391 SELFLOADHEADER
*selfloadheader
;
392 STACK16FRAME
*stack16Top
;
393 THDB
*thdb
= THREAD_Current();
394 HMODULE16 hselfload
= GetModuleHandle16("WPROCS");
396 WORD saved_hSeg
= pSegTable
[pModule
->dgroup
- 1].hSeg
;
398 TRACE(module
, "%.*s is a self-loading module!\n",
399 *((BYTE
*)pModule
+ pModule
->name_table
),
400 (char *)pModule
+ pModule
->name_table
+ 1);
401 if (!NE_LoadSegment( pModule
, 1 )) return FALSE
;
402 selfloadheader
= (SELFLOADHEADER
*)
403 PTR_SEG_OFF_TO_LIN(SEL(pSegTable
->hSeg
), 0);
404 selfloadheader
->EntryAddrProc
= NE_GetEntryPoint(hselfload
,27);
405 selfloadheader
->MyAlloc
= NE_GetEntryPoint(hselfload
,28);
406 selfloadheader
->SetOwner
= NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
407 pModule
->self_loading_sel
= GlobalHandleToSel(GLOBAL_Alloc(GMEM_ZEROINIT
, 0xFF00, pModule
->self
, FALSE
, FALSE
, FALSE
));
408 oldstack
= thdb
->cur_stack
;
409 thdb
->cur_stack
= PTR_SEG_OFF_TO_SEGPTR(pModule
->self_loading_sel
,
410 0xff00 - sizeof(*stack16Top
) );
411 stack16Top
= (STACK16FRAME
*)PTR_SEG_TO_LIN(thdb
->cur_stack
);
412 stack16Top
->frame32
= 0;
414 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
415 stack16Top
->entry_point
= 0;
416 stack16Top
->entry_ip
= 0;
417 stack16Top
->entry_cs
= 0;
422 hf
= FILE_DupUnixHandle( NE_OpenFile( pModule
) );
423 TRACE(dll
,"CallBootAppProc(hModule=0x%04x,hf=0x%04x)\n",pModule
->self
,
424 HFILE32_TO_HFILE16(hf
));
425 Callbacks
->CallBootAppProc(selfloadheader
->BootApp
, pModule
->self
,
426 HFILE32_TO_HFILE16(hf
));
427 TRACE(dll
,"Return from CallBootAppProc\n");
429 /* some BootApp procs overwrite the segment handle of dgroup */
430 pSegTable
[pModule
->dgroup
- 1].hSeg
= saved_hSeg
;
431 thdb
->cur_stack
= oldstack
;
434 commented out by Andreas Mohr;
435 some self-loading exe ("BLINKER") relies on non-primary segs not loaded.
436 contact me if you experience problems */
437 /*for (i = 2; i <= pModule->seg_count; i++)
438 if (!NE_LoadSegment( pModule, i )) return FALSE;*/
442 for (i
= 1; i
<= pModule
->seg_count
; i
++)
443 if (!NE_LoadSegment( pModule
, i
)) return FALSE
;
449 /***********************************************************************
452 * Fixup the exported functions prologs.
454 void NE_FixupPrologs( NE_MODULE
*pModule
)
456 SEGTABLEENTRY
*pSegTable
;
459 BYTE
*p
, *fixup_ptr
, count
;
460 dbg_decl_str(module
, 512);
462 pSegTable
= NE_SEG_TABLE(pModule
);
463 if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
464 dgroup
= SEL(pSegTable
[pModule
->dgroup
-1].hSeg
);
466 TRACE(module
, "(%04x)\n", pModule
->self
);
467 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
470 if (p
[1] == 0) /* Unused entry */
472 p
+= 2; /* Skip it */
475 if (p
[1] == 0xfe) /* Constant entry */
477 p
+= 2 + *p
* 3; /* Skip it */
481 /* Now fixup the entries of this bundle */
487 dbg_reset_str(module
);
488 dsprintf(module
,"Flags: %04x, sel %02x ", *p
, sel
);
489 /* According to the output generated by TDUMP, the flags mean:
490 * 0x0001 function is exported
491 * 0x0002 Single data (seems to occur only in DLLs)
493 if (sel
== 0xff) { /* moveable */
494 dsprintf(module
, "(%02x) o %04x", p
[3], *(WORD
*)(p
+4) );
495 fixup_ptr
= (char *)GET_SEL_BASE(SEL(pSegTable
[p
[3]-1].hSeg
)) + *(WORD
*)(p
+ 4);
497 dsprintf(module
, "offset %04x", *(WORD
*)(p
+1) );
498 fixup_ptr
= (char *)GET_SEL_BASE(SEL(pSegTable
[sel
-1].hSeg
)) +
501 TRACE(module
, "%s Signature: %02x %02x %02x,ff %x\n",
502 dbg_str(module
), fixup_ptr
[0], fixup_ptr
[1],
503 fixup_ptr
[2], pModule
->flags
);
506 /* Verify the signature */
507 if (((fixup_ptr
[0] == 0x1e && fixup_ptr
[1] == 0x58)
508 || (fixup_ptr
[0] == 0x8c && fixup_ptr
[1] == 0xd8))
509 && fixup_ptr
[2] == 0x90)
513 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
)
515 /* can this happen? */
516 ERR(fixup
, "FixupPrologs got confused\n" );
518 else if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
520 *fixup_ptr
= 0xb8; /* MOV AX, */
521 *(WORD
*)(fixup_ptr
+1) = dgroup
;
526 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
527 fixup_ptr
[0] = 0x90; /* non-library: NOPs */
533 WARN(fixup
, "Unknown signature\n" );
538 p
+= (sel
== 0xff) ? 6 : 3;
543 /***********************************************************************
544 * NE_GetDLLInitParams
546 static VOID
NE_GetDLLInitParams( NE_MODULE
*pModule
,
547 WORD
*hInst
, WORD
*ds
, WORD
*heap
)
549 SEGTABLEENTRY
*pSegTable
= NE_SEG_TABLE( pModule
);
551 if (!(pModule
->flags
& NE_FFLAGS_SINGLEDATA
))
553 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
|| pModule
->dgroup
)
556 ERR(dll
, "Library is not marked SINGLEDATA\n");
559 else /* DATA NONE DLL */
565 else /* DATA SINGLE DLL */
567 if (pModule
->dgroup
) {
568 *ds
= SEL(pSegTable
[pModule
->dgroup
-1].hSeg
);
569 *heap
= pModule
->heap_size
;
571 else /* hmm, DLL has no dgroup,
572 but why has it NE_FFLAGS_SINGLEDATA set ?
573 Buggy DLL compiler ? */
580 *hInst
= *ds
? *ds
: pModule
->self
;
584 /***********************************************************************
587 * Call the DLL initialization code
589 static BOOL32
NE_InitDLL( TDB
* pTask
, NE_MODULE
*pModule
)
591 SEGTABLEENTRY
*pSegTable
;
592 WORD hInst
, ds
, heap
;
595 pSegTable
= NE_SEG_TABLE( pModule
);
597 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) ||
598 (pModule
->flags
& NE_FFLAGS_WIN32
)) return TRUE
; /*not a library*/
600 /* Call USER signal handler. This is necessary to install a
601 * proper loader for HICON and HCURSOR resources that this DLL
602 * may contain. InitApp() does this for task modules. */
604 if (pTask
&& pTask
->userhandler
)
606 pTask
->userhandler( pModule
->self
, USIG_DLL_LOAD
, 0, pTask
->hInstance
,
610 if (!pModule
->cs
) return TRUE
; /* no initialization code */
613 /* Registers at initialization must be:
615 * di library instance
616 * ds data segment if any
617 * es:si command line (always 0)
620 memset( &context
, 0, sizeof(context
) );
622 NE_GetDLLInitParams( pModule
, &hInst
, &ds
, &heap
);
624 ECX_reg(&context
) = heap
;
625 EDI_reg(&context
) = hInst
;
626 DS_reg(&context
) = ds
;
627 ES_reg(&context
) = ds
; /* who knows ... */
629 CS_reg(&context
) = SEL(pSegTable
[pModule
->cs
-1].hSeg
);
630 EIP_reg(&context
) = pModule
->ip
;
631 EBP_reg(&context
) = OFFSETOF(THREAD_Current()->cur_stack
)
632 + (WORD
)&((STACK16FRAME
*)0)->bp
;
635 pModule
->cs
= 0; /* Don't initialize it twice */
636 TRACE(dll
, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
637 CS_reg(&context
), IP_reg(&context
), DS_reg(&context
),
638 DI_reg(&context
), CX_reg(&context
) );
639 Callbacks
->CallRegisterShortProc( &context
, 0 );
643 /***********************************************************************
644 * NE_CallDllEntryPoint
646 * Call the DllEntryPoint of DLLs with subsystem >= 4.0
649 static void NE_CallDllEntryPoint( NE_MODULE
*pModule
, DWORD dwReason
)
651 WORD hInst
, ds
, heap
;
652 FARPROC16 entryPoint
;
655 THDB
*thdb
= THREAD_Current();
656 LPBYTE stack
= (LPBYTE
)THREAD_STACK16(thdb
);
658 if (pModule
->expected_version
< 0x0400) return;
659 if (!(ordinal
= NE_GetOrdinal( pModule
->self
, "DllEntryPoint" ))) return;
660 if (!(entryPoint
= NE_GetEntryPoint( pModule
->self
, ordinal
))) return;
662 memset( &context
, 0, sizeof(context
) );
664 NE_GetDLLInitParams( pModule
, &hInst
, &ds
, &heap
);
666 DS_reg(&context
) = ds
;
667 ES_reg(&context
) = ds
; /* who knows ... */
669 CS_reg(&context
) = HIWORD(entryPoint
);
670 IP_reg(&context
) = LOWORD(entryPoint
);
671 EBP_reg(&context
) = OFFSETOF( thdb
->cur_stack
)
672 + (WORD
)&((STACK16FRAME
*)0)->bp
;
674 *(DWORD
*)(stack
- 4) = dwReason
; /* dwReason */
675 *(WORD
*) (stack
- 6) = hInst
; /* hInst */
676 *(WORD
*) (stack
- 8) = ds
; /* wDS */
677 *(WORD
*) (stack
- 10) = heap
; /* wHeapSize */
678 *(DWORD
*)(stack
- 14) = 0; /* dwReserved1 */
679 *(WORD
*) (stack
- 16) = 0; /* wReserved2 */
681 TRACE(dll
, "Calling DllEntryPoint, cs:ip=%04lx:%04x\n",
682 CS_reg(&context
), IP_reg(&context
));
684 Callbacks
->CallRegisterShortProc( &context
, 16 );
688 /***********************************************************************
691 * Recursively initialize all DLLs (according to the order in which
692 * they where loaded).
694 void NE_InitializeDLLs( HMODULE16 hModule
)
696 TDB
* pTask
= (TDB
*)GlobalLock16(GetCurrentTask());
700 if (!(pModule
= NE_GetPtr( hModule
))) return;
701 assert( !(pModule
->flags
& NE_FFLAGS_WIN32
) );
703 if (pModule
->dlls_to_init
)
705 HGLOBAL16 to_init
= pModule
->dlls_to_init
;
706 pModule
->dlls_to_init
= 0;
707 for (pDLL
= (HMODULE16
*)GlobalLock16( to_init
); *pDLL
; pDLL
++)
709 NE_InitializeDLLs( *pDLL
);
711 GlobalFree16( to_init
);
713 NE_InitDLL( pTask
, pModule
);
714 NE_CallDllEntryPoint( pModule
, DLL_PROCESS_ATTACH
);
718 /***********************************************************************
721 * If lib_only is TRUE, handle the module like a library even if it is a .EXE
723 HINSTANCE16
NE_CreateInstance( NE_MODULE
*pModule
, HINSTANCE16
*prev
,
726 SEGTABLEENTRY
*pSegment
;
728 HINSTANCE16 hNewInstance
;
730 if (pModule
->dgroup
== 0)
732 if (prev
) *prev
= pModule
->self
;
733 return pModule
->self
;
736 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
737 if (prev
) *prev
= SEL(pSegment
->hSeg
);
739 /* if it's a library, create a new instance only the first time */
742 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return SEL(pSegment
->hSeg
);
743 if (lib_only
) return SEL(pSegment
->hSeg
);
746 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
747 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
748 minsize
+= pModule
->heap_size
;
749 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
, minsize
,
750 pModule
->self
, FALSE
, FALSE
, FALSE
);
751 if (!hNewInstance
) return 0;
752 pSegment
->hSeg
= hNewInstance
;
753 pSegment
->flags
|= NE_SEGFLAGS_ALLOCATED
;
758 /***********************************************************************
761 * Needed for self-loading modules.
764 /* It does nothing */
765 void WINAPI
PatchCodeHandle(HANDLE16 hSel
)
767 FIXME(module
,"(%04x): stub.\n",hSel
);
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;