4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
22 #include "selectors.h"
26 #include "stackframe.h"
31 /***********************************************************************
34 static const char *NE_GetRelocAddrName( BYTE addr_type
, int additive
)
36 switch(addr_type
& 0x7f)
38 case NE_RADDR_LOWBYTE
: return additive
? "BYTE add" : "BYTE";
39 case NE_RADDR_OFFSET16
: return additive
? "OFFSET16 add" : "OFFSET16";
40 case NE_RADDR_POINTER32
: return additive
? "POINTER32 add" : "POINTER32";
41 case NE_RADDR_SELECTOR
: return additive
? "SELECTOR add" : "SELECTOR";
42 case NE_RADDR_POINTER48
: return additive
? "POINTER48 add" : "POINTER48";
43 case NE_RADDR_OFFSET32
: return additive
? "OFFSET32 add" : "OFFSET32";
49 /***********************************************************************
52 BOOL32
NE_LoadSegment( NE_MODULE
*pModule
, WORD segnum
)
54 SEGTABLEENTRY
*pSegTable
, *pSeg
;
56 WORD count
, i
, offset
, next_offset
;
58 FARPROC16 address
= 0;
60 struct relocation_entry_s
*rep
, *reloc_entries
;
66 int ordinal
, additive
;
69 pSegTable
= NE_SEG_TABLE( pModule
);
70 pSeg
= pSegTable
+ segnum
- 1;
71 pModuleTable
= NE_MODULE_TABLE( pModule
);
73 if (!pSeg
->filepos
) return TRUE
; /* No file image, just return */
75 fd
= NE_OpenFile( pModule
);
76 TRACE(module
, "Loading segment %d, selector=%04x, flags=%04x\n",
77 segnum
, pSeg
->selector
, pSeg
->flags
);
78 lseek( fd
, pSeg
->filepos
<< pModule
->alignment
, SEEK_SET
);
79 if (pSeg
->size
) size
= pSeg
->size
;
80 else if (pSeg
->minsize
) size
= pSeg
->minsize
;
82 mem
= GlobalLock16(pSeg
->selector
);
83 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
&& segnum
> 1)
85 /* Implement self loading segments */
86 SELFLOADHEADER
*selfloadheader
;
87 STACK16FRAME
*stack16Top
;
89 WORD oldselector
, newselector
;
90 THDB
*thdb
= THREAD_Current();
91 HFILE32 hf
= FILE_DupUnixHandle( fd
);
93 selfloadheader
= (SELFLOADHEADER
*)
94 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
,0);
95 oldstack
= thdb
->cur_stack
;
96 oldselector
= pSeg
->selector
;
97 thdb
->cur_stack
= PTR_SEG_OFF_TO_SEGPTR(pModule
->self_loading_sel
,
98 0xff00 - sizeof(*stack16Top
));
99 stack16Top
= (STACK16FRAME
*)PTR_SEG_TO_LIN(thdb
->cur_stack
);
100 stack16Top
->frame32
= 0;
101 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
102 stack16Top
->entry_point
= 0;
103 stack16Top
->entry_ip
= 0;
104 stack16Top
->entry_cs
= 0;
108 newselector
= Callbacks
->CallLoadAppSegProc(selfloadheader
->LoadAppSeg
,
109 pModule
->self
, hf
, segnum
);
111 if (newselector
!= oldselector
) {
112 /* Self loaders like creating their own selectors;
113 * they love asking for trouble to Wine developers
115 if (segnum
== pModule
->dgroup
) {
116 memcpy(PTR_SEG_OFF_TO_LIN(oldselector
,0),
117 PTR_SEG_OFF_TO_LIN(newselector
,0),
118 pSeg
->minsize
? pSeg
->minsize
: 0x10000);
119 FreeSelector(newselector
);
120 pSeg
->selector
= oldselector
;
121 TRACE(module
, "New selector allocated for dgroup segment:Old=%d,New=%d\n",
122 oldselector
, newselector
);
124 FreeSelector(pSeg
->selector
);
125 pSeg
->selector
= newselector
;
129 thdb
->cur_stack
= oldstack
;
131 else if (!(pSeg
->flags
& NE_SEGFLAGS_ITERATED
))
135 The following bit of code for "iterated segments" was written without
136 any documentation on the format of these segments. It seems to work,
137 but may be missing something. If you have any doc please either send
138 it to me or fix the code yourself. gfm@werple.mira.net.au
140 char* buff
= xmalloc(size
);
142 read(fd
, buff
, size
);
143 while(curr
< buff
+ size
) {
144 unsigned int rept
= *((short*) curr
)++;
145 unsigned int len
= *((short*) curr
)++;
146 for(; rept
> 0; rept
--) {
149 for(byte
= 0; byte
< len
; byte
++)
157 pSeg
->flags
|= NE_SEGFLAGS_LOADED
;
158 if (!(pSeg
->flags
& NE_SEGFLAGS_RELOC_DATA
))
159 return TRUE
; /* No relocation data, we are done */
161 read( fd
, &count
, sizeof(count
) );
162 if (!count
) return TRUE
;
164 TRACE(fixup
, "Fixups for %.*s, segment %d, selector %04x\n",
165 *((BYTE
*)pModule
+ pModule
->name_table
),
166 (char *)pModule
+ pModule
->name_table
+ 1,
167 segnum
, pSeg
->selector
);
168 TRACE(segment
, "Fixups for %.*s, segment %d, selector %04x\n",
169 *((BYTE
*)pModule
+ pModule
->name_table
),
170 (char *)pModule
+ pModule
->name_table
+ 1,
171 segnum
, pSeg
->selector
);
173 reloc_entries
= (struct relocation_entry_s
*)xmalloc(count
* sizeof(struct relocation_entry_s
));
174 if (read( fd
, reloc_entries
, count
* sizeof(struct relocation_entry_s
)) !=
175 count
* sizeof(struct relocation_entry_s
))
177 WARN(fixup
, "Unable to read relocation information\n" );
182 * Go through the relocation table one entry at a time.
185 for (i
= 0; i
< count
; i
++, rep
++)
188 * Get the target address corresponding to this entry.
191 /* If additive, there is no target chain list. Instead, add source
193 additive
= rep
->relocation_type
& NE_RELFLAG_ADDITIVE
;
194 rep
->relocation_type
&= 0x3;
196 switch (rep
->relocation_type
)
198 case NE_RELTYPE_ORDINAL
:
199 module
= pModuleTable
[rep
->target1
-1];
200 ordinal
= rep
->target2
;
201 address
= NE_GetEntryPoint( module
, ordinal
);
204 NE_MODULE
*pTarget
= NE_GetPtr( module
);
206 WARN(module
, "Module not found: %04x, reference %d of module %*.*s\n",
207 module
, rep
->target1
,
208 *((BYTE
*)pModule
+ pModule
->name_table
),
209 *((BYTE
*)pModule
+ pModule
->name_table
),
210 (char *)pModule
+ pModule
->name_table
+ 1 );
212 WARN(module
, "No handler for %.*s.%d, setting to 0:0\n",
213 *((BYTE
*)pTarget
+ pTarget
->name_table
),
214 (char *)pTarget
+ pTarget
->name_table
+ 1,
219 NE_MODULE
*pTarget
= NE_GetPtr( module
);
220 TRACE( fixup
, "%d: %.*s.%d=%04x:%04x %s\n", i
+ 1,
221 *((BYTE
*)pTarget
+ pTarget
->name_table
),
222 (char *)pTarget
+ pTarget
->name_table
+ 1,
223 ordinal
, HIWORD(address
), LOWORD(address
),
224 NE_GetRelocAddrName( rep
->address_type
, additive
) );
228 case NE_RELTYPE_NAME
:
229 module
= pModuleTable
[rep
->target1
-1];
230 func_name
= (char *)pModule
+ pModule
->import_table
+ rep
->target2
;
231 memcpy( buffer
, func_name
+1, *func_name
);
232 buffer
[*func_name
] = '\0';
234 ordinal
= NE_GetOrdinal( module
, func_name
);
235 address
= NE_GetEntryPoint( module
, ordinal
);
237 if (ERR_ON(fixup
) && !address
)
239 NE_MODULE
*pTarget
= NE_GetPtr( module
);
240 ERR(fixup
, "Warning: no handler for %.*s.%s, setting to 0:0\n",
241 *((BYTE
*)pTarget
+ pTarget
->name_table
),
242 (char *)pTarget
+ pTarget
->name_table
+ 1, func_name
);
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( pSegTable
[rep
->target1
-1].selector
, 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 GetModuleName( 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( pSeg
->selector
, 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( pSeg
->selector
, 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
->selector
)) break;
351 offset
= next_offset
;
352 } while (offset
&& (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 BOOL32
NE_LoadAllSegments( NE_MODULE
*pModule
)
376 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
)
379 /* Handle self loading modules */
380 SEGTABLEENTRY
* pSegTable
= (SEGTABLEENTRY
*) NE_SEG_TABLE(pModule
);
381 SELFLOADHEADER
*selfloadheader
;
382 STACK16FRAME
*stack16Top
;
383 THDB
*thdb
= THREAD_Current();
384 HMODULE16 hselfload
= GetModuleHandle16("WPROCS");
386 WORD saved_dgroup
= pSegTable
[pModule
->dgroup
- 1].selector
;
388 TRACE(module
, "%.*s is a self-loading module!\n",
389 *((BYTE
*)pModule
+ pModule
->name_table
),
390 (char *)pModule
+ pModule
->name_table
+ 1);
391 if (!NE_LoadSegment( pModule
, 1 )) return FALSE
;
392 selfloadheader
= (SELFLOADHEADER
*)
393 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
, 0);
394 selfloadheader
->EntryAddrProc
= NE_GetEntryPoint(hselfload
,27);
395 selfloadheader
->MyAlloc
= NE_GetEntryPoint(hselfload
,28);
396 selfloadheader
->SetOwner
= NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
397 pModule
->self_loading_sel
= GlobalHandleToSel(GLOBAL_Alloc(GMEM_ZEROINIT
, 0xFF00, pModule
->self
, FALSE
, FALSE
, FALSE
));
398 oldstack
= thdb
->cur_stack
;
399 thdb
->cur_stack
= PTR_SEG_OFF_TO_SEGPTR(pModule
->self_loading_sel
,
400 0xff00 - sizeof(*stack16Top
) );
401 stack16Top
= (STACK16FRAME
*)PTR_SEG_TO_LIN(thdb
->cur_stack
);
402 stack16Top
->frame32
= 0;
404 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
405 stack16Top
->entry_point
= 0;
406 stack16Top
->entry_ip
= 0;
407 stack16Top
->entry_cs
= 0;
412 hf
= FILE_DupUnixHandle( NE_OpenFile( pModule
) );
413 Callbacks
->CallBootAppProc(selfloadheader
->BootApp
, pModule
->self
, hf
);
415 /* some BootApp procs overwrite the selector of dgroup */
416 pSegTable
[pModule
->dgroup
- 1].selector
= saved_dgroup
;
417 thdb
->cur_stack
= oldstack
;
418 for (i
= 2; i
<= pModule
->seg_count
; i
++)
419 if (!NE_LoadSegment( pModule
, i
)) return FALSE
;
423 for (i
= 1; i
<= pModule
->seg_count
; i
++)
424 if (!NE_LoadSegment( pModule
, i
)) return FALSE
;
430 /***********************************************************************
433 * Fixup the exported functions prologs.
435 void NE_FixupPrologs( NE_MODULE
*pModule
)
437 SEGTABLEENTRY
*pSegTable
;
440 BYTE
*p
, *fixup_ptr
, count
;
441 dbg_decl_str(module
, 512);
443 pSegTable
= NE_SEG_TABLE(pModule
);
444 if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
445 dgroup
= pSegTable
[pModule
->dgroup
-1].selector
;
447 TRACE(module
, "(%04x)\n", pModule
->self
);
448 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
451 if (p
[1] == 0) /* Unused entry */
453 p
+= 2; /* Skip it */
456 if (p
[1] == 0xfe) /* Constant entry */
458 p
+= 2 + *p
* 3; /* Skip it */
462 /* Now fixup the entries of this bundle */
468 dbg_reset_str(module
);
469 dsprintf(module
,"Flags: %04x, sel %02x ", *p
, sel
);
470 /* According to the output generated by TDUMP, the flags mean:
471 * 0x0001 function is exported
472 * 0x0002 Single data (seems to occur only in DLLs)
474 if (sel
== 0xff) { /* moveable */
475 dsprintf(module
, "(%02x) o %04x", p
[3], *(WORD
*)(p
+4) );
476 fixup_ptr
= (char *)GET_SEL_BASE(pSegTable
[p
[3]-1].selector
) + *(WORD
*)(p
+ 4);
478 dsprintf(module
, "offset %04x", *(WORD
*)(p
+1) );
479 fixup_ptr
= (char *)GET_SEL_BASE(pSegTable
[sel
-1].selector
) +
482 TRACE(module
, "%s Signature: %02x %02x %02x,ff %x\n",
483 dbg_str(module
), fixup_ptr
[0], fixup_ptr
[1],
484 fixup_ptr
[2], pModule
->flags
);
487 /* Verify the signature */
488 if (((fixup_ptr
[0] == 0x1e && fixup_ptr
[1] == 0x58)
489 || (fixup_ptr
[0] == 0x8c && fixup_ptr
[1] == 0xd8))
490 && fixup_ptr
[2] == 0x90)
494 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
)
496 /* can this happen? */
497 ERR(fixup
, "FixupPrologs got confused\n" );
499 else if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
501 *fixup_ptr
= 0xb8; /* MOV AX, */
502 *(WORD
*)(fixup_ptr
+1) = dgroup
;
507 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
508 fixup_ptr
[0] = 0x90; /* non-library: NOPs */
514 WARN(fixup
, "Unknown signature\n" );
519 p
+= (sel
== 0xff) ? 6 : 3;
525 /***********************************************************************
528 * Call the DLL initialization code
530 static BOOL32
NE_InitDLL( TDB
* pTask
, NE_MODULE
*pModule
)
532 SEGTABLEENTRY
*pSegTable
;
535 /* Registers at initialization must be:
537 * di library instance
538 * ds data segment if any
539 * es:si command line (always 0)
542 pSegTable
= NE_SEG_TABLE( pModule
);
544 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) ||
545 (pModule
->flags
& NE_FFLAGS_WIN32
)) return TRUE
; /*not a library*/
547 /* Call USER signal handler. This is necessary to install a
548 * proper loader for HICON and HCURSOR resources that this DLL
549 * may contain. InitApp() does this for task modules. */
551 if (pTask
&& pTask
->userhandler
)
553 pTask
->userhandler( pModule
->self
, USIG_DLL_LOAD
, 0, pTask
->hInstance
,
557 if (!pModule
->cs
) return TRUE
; /* no initialization code */
559 memset( &context
, 0, sizeof(context
) );
561 if (!(pModule
->flags
& NE_FFLAGS_SINGLEDATA
))
563 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
|| pModule
->dgroup
)
566 ERR(dll
, "Library is not marked SINGLEDATA\n");
569 else /* DATA NONE DLL */
571 DS_reg(&context
) = 0;
572 ECX_reg(&context
) = 0;
575 else /* DATA SINGLE DLL */
577 if (pModule
->dgroup
) {
578 DS_reg(&context
) = pSegTable
[pModule
->dgroup
-1].selector
;
579 ECX_reg(&context
) = pModule
->heap_size
;
581 else /* hmm, DLL has no dgroup,
582 but why has it NE_FFLAGS_SINGLEDATA set ?
583 Buggy DLL compiler ? */
585 DS_reg(&context
) = 0;
586 ECX_reg(&context
) = 0;
590 CS_reg(&context
) = pSegTable
[pModule
->cs
-1].selector
;
591 EIP_reg(&context
) = pModule
->ip
;
592 EBP_reg(&context
) = OFFSETOF(THREAD_Current()->cur_stack
)
593 + (WORD
)&((STACK16FRAME
*)0)->bp
;
594 EDI_reg(&context
) = DS_reg(&context
) ? DS_reg(&context
) : pModule
->self
;
597 pModule
->cs
= 0; /* Don't initialize it twice */
598 TRACE(dll
, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
599 CS_reg(&context
), IP_reg(&context
), DS_reg(&context
),
600 DI_reg(&context
), CX_reg(&context
) );
601 Callbacks
->CallRegisterShortProc( &context
, 0 );
605 /***********************************************************************
606 * NE_CallDllEntryPoint
608 * Call the DllEntryPoint of DLLs with subsystem >= 4.0
611 static void NE_CallDllEntryPoint( NE_MODULE
*pModule
, DWORD dwReason
)
613 FARPROC16 entryPoint
;
616 THDB
*thdb
= THREAD_Current();
617 LPBYTE stack
= (LPBYTE
)THREAD_STACK16(thdb
);
619 if (pModule
->expected_version
< 0x0400) return;
620 if (!(ordinal
= NE_GetOrdinal( pModule
->self
, "DllEntryPoint" ))) return;
621 if (!(entryPoint
= NE_GetEntryPoint( pModule
->self
, ordinal
))) return;
623 memset( &context
, 0, sizeof(context
) );
625 CS_reg(&context
) = HIWORD(entryPoint
);
626 IP_reg(&context
) = LOWORD(entryPoint
);
627 EBP_reg(&context
) = OFFSETOF( thdb
->cur_stack
)
628 + (WORD
)&((STACK16FRAME
*)0)->bp
;
630 *(DWORD
*)(stack
- 4) = dwReason
; /* dwReason */
631 *(WORD
*) (stack
- 6) = pModule
->self
; /* hInst */
632 *(WORD
*) (stack
- 8) = 0; /* wDS */
633 *(WORD
*) (stack
- 10) = 0; /* wHeapSize */
634 *(DWORD
*)(stack
- 14) = 0; /* dwReserved1 */
635 *(WORD
*) (stack
- 16) = 0; /* wReserved2 */
637 TRACE(dll
, "Calling DllEntryPoint, cs:ip=%04lx:%04x\n",
638 CS_reg(&context
), IP_reg(&context
));
640 Callbacks
->CallRegisterShortProc( &context
, 16 );
644 /***********************************************************************
647 * Recursively initialize all DLLs (according to the order in which
648 * they where loaded).
650 void NE_InitializeDLLs( HMODULE16 hModule
)
652 TDB
* pTask
= (TDB
*)GlobalLock16(GetCurrentTask());
656 if (!(pModule
= NE_GetPtr( hModule
))) return;
657 assert( !(pModule
->flags
& NE_FFLAGS_WIN32
) );
659 if (pModule
->dlls_to_init
)
661 HGLOBAL16 to_init
= pModule
->dlls_to_init
;
662 pModule
->dlls_to_init
= 0;
663 for (pDLL
= (HMODULE16
*)GlobalLock16( to_init
); *pDLL
; pDLL
++)
665 NE_InitializeDLLs( *pDLL
);
667 GlobalFree16( to_init
);
669 NE_InitDLL( pTask
, pModule
);
670 NE_CallDllEntryPoint( pModule
, DLL_PROCESS_ATTACH
);
674 /***********************************************************************
677 * If lib_only is TRUE, handle the module like a library even if it is a .EXE
679 HINSTANCE16
NE_CreateInstance( NE_MODULE
*pModule
, HINSTANCE16
*prev
,
682 SEGTABLEENTRY
*pSegment
;
684 HINSTANCE16 hNewInstance
;
686 if (pModule
->dgroup
== 0)
688 if (prev
) *prev
= pModule
->self
;
689 return pModule
->self
;
692 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
693 if (prev
) *prev
= pSegment
->selector
;
695 /* if it's a library, create a new instance only the first time */
696 if (pSegment
->selector
)
698 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return pSegment
->selector
;
699 if (lib_only
) return pSegment
->selector
;
702 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
703 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
704 minsize
+= pModule
->heap_size
;
705 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
, minsize
,
706 pModule
->self
, FALSE
, FALSE
, FALSE
);
707 if (!hNewInstance
) return 0;
708 pSegment
->selector
= hNewInstance
;
713 /***********************************************************************
716 * Needed for self-loading modules.
719 /* It does nothing */
720 void WINAPI
PatchCodeHandle(HANDLE16 hSel
)
722 FIXME(module
,"(%04x): stub.\n",hSel
);
726 /***********************************************************************
729 * This function translates NE segment flags to GlobalAlloc flags
731 static WORD
NE_Ne2MemFlags(WORD flags
)
735 if (flags
& NE_SEGFLAGS_DISCARDABLE
)
736 memflags
|= GMEM_DISCARDABLE
;
737 if (flags
& NE_SEGFLAGS_MOVEABLE
||
738 ( ! (flags
& NE_SEGFLAGS_DATA
) &&
739 ! (flags
& NE_SEGFLAGS_LOADED
) &&
740 ! (flags
& NE_SEGFLAGS_ALLOCATED
)
743 memflags
|= GMEM_MOVEABLE
;
744 memflags
|= GMEM_ZEROINIT
;
746 memflags
= GMEM_ZEROINIT
| GMEM_FIXED
;
751 /***********************************************************************
752 * NE_AllocateSegment (WPROCS.26)
754 DWORD WINAPI
NE_AllocateSegment( WORD wFlags
, WORD wSize
, WORD wElem
)
756 WORD size
= wSize
<< wElem
;
757 HANDLE16 hMem
= GlobalAlloc16( NE_Ne2MemFlags(wFlags
), size
);
758 return MAKELONG( hMem
, GlobalHandleToSel(hMem
) );
762 /***********************************************************************
765 BOOL32
NE_CreateSegments( NE_MODULE
*pModule
)
767 SEGTABLEENTRY
*pSegment
;
770 assert( !(pModule
->flags
& NE_FFLAGS_WIN32
) );
772 pSegment
= NE_SEG_TABLE( pModule
);
773 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
775 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
776 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
777 /* The DGROUP is allocated by NE_CreateInstance */
778 if (i
== pModule
->dgroup
) continue;
779 pSegment
->selector
= GLOBAL_Alloc( NE_Ne2MemFlags(pSegment
->flags
),
780 minsize
, pModule
->self
,
781 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
783 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
784 if (!pSegment
->selector
) return FALSE
;
787 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
788 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
793 /**********************************************************************
794 * IsSharedSelector (KERNEL.345)
796 BOOL16 WINAPI
IsSharedSelector( HANDLE16 selector
)
798 /* Check whether the selector belongs to a DLL */
799 NE_MODULE
*pModule
= NE_GetPtr( selector
);
800 if (!pModule
) return FALSE
;
801 return (pModule
->flags
& NE_FFLAGS_LIBMODULE
) != 0;