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 TRACE(dll,"CallLoadAppSegProc(hmodule=0x%04x,hf=0x%04x,segnum=%d\n",
109 pModule->self,hf,segnum
111 newselector = Callbacks->CallLoadAppSegProc(selfloadheader->LoadAppSeg,
112 pModule->self, hf, segnum );
113 TRACE(dll,"Ret CallLoadAppSegProc: selector = 0x%04x\n",newselector);
115 if (newselector != oldselector) {
116 /* Self loaders like creating their own selectors;
117 * they love asking for trouble to Wine developers
119 if (segnum == pModule->dgroup) {
120 memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
121 PTR_SEG_OFF_TO_LIN(newselector,0),
122 pSeg->minsize ? pSeg->minsize : 0x10000);
123 FreeSelector(newselector);
124 pSeg->selector = oldselector;
125 TRACE(module, "New selector allocated for dgroup segment:Old=%d,New=%d\n",
126 oldselector, newselector);
128 FreeSelector(pSeg->selector);
129 pSeg->selector = newselector;
133 thdb->cur_stack = oldstack;
135 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
139 The following bit of code for "iterated segments" was written without
140 any documentation on the format of these segments. It seems to work,
141 but may be missing something. If you have any doc please either send
142 it to me or fix the code yourself. gfm@werple.mira.net.au
144 char* buff = xmalloc(size);
146 read(fd, buff, size);
147 while(curr < buff + size) {
148 unsigned int rept = *((short*) curr)++;
149 unsigned int len = *((short*) curr)++;
150 for(; rept > 0; rept--) {
153 for(byte = 0; byte < len; byte++)
161 pSeg->flags |= NE_SEGFLAGS_LOADED;
162 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
163 return TRUE; /* No relocation data, we are done */
165 read( fd, &count, sizeof(count) );
166 if (!count) return TRUE;
168 TRACE(fixup, "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 );
172 TRACE(segment, "Fixups for %.*s, segment %d, selector %04x\n",
173 *((BYTE *)pModule + pModule->name_table),
174 (char *)pModule + pModule->name_table + 1,
175 segnum, pSeg->selector );
177 reloc_entries = (struct relocation_entry_s *)xmalloc(count * sizeof(struct relocation_entry_s));
178 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
179 count * sizeof(struct relocation_entry_s))
181 WARN(fixup, "Unable to read relocation information\n" );
186 * Go through the relocation table one entry at a time.
189 for (i = 0; i < count; i++, rep++)
192 * Get the target address corresponding to this entry.
195 /* If additive, there is no target chain list. Instead, add source
197 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
198 rep->relocation_type &= 0x3;
200 switch (rep->relocation_type)
202 case NE_RELTYPE_ORDINAL:
203 module = pModuleTable[rep->target1-1];
204 ordinal = rep->target2;
205 address = NE_GetEntryPoint( module, ordinal );
208 NE_MODULE *pTarget = NE_GetPtr( module );
210 WARN(module, "Module not found: %04x, reference %d of module %*.*s\n",
211 module, rep->target1,
212 *((BYTE *)pModule + pModule->name_table),
213 *((BYTE *)pModule + pModule->name_table),
214 (char *)pModule + pModule->name_table + 1 );
216 WARN(module, "No handler for %.*s.%d, setting to 0:0\n",
217 *((BYTE *)pTarget + pTarget->name_table),
218 (char *)pTarget + pTarget->name_table + 1,
223 NE_MODULE *pTarget = NE_GetPtr( module );
224 TRACE( fixup, "%d: %.*s.%d=%04x:%04x %s\n", i + 1,
225 *((BYTE *)pTarget + pTarget->name_table),
226 (char *)pTarget + pTarget->name_table + 1,
227 ordinal, HIWORD(address), LOWORD(address),
228 NE_GetRelocAddrName( rep->address_type, additive ) );
232 case NE_RELTYPE_NAME:
233 module = pModuleTable[rep->target1-1];
234 func_name = (char *)pModule + pModule->import_table + rep->target2;
235 memcpy( buffer, func_name+1, *func_name );
236 buffer[*func_name] = '\0';
238 ordinal = NE_GetOrdinal( module, func_name );
239 address = NE_GetEntryPoint( module, ordinal );
241 if (ERR_ON(fixup) && !address)
243 NE_MODULE *pTarget = NE_GetPtr( module );
244 ERR(fixup, "Warning: no handler for %.*s.%s, setting to 0:0\n",
245 *((BYTE *)pTarget + pTarget->name_table),
246 (char *)pTarget + pTarget->name_table + 1, func_name );
250 NE_MODULE *pTarget = NE_GetPtr( module );
251 TRACE( fixup, "%d: %.*s.%s=%04x:%04x %s\n", i + 1,
252 *((BYTE *)pTarget + pTarget->name_table),
253 (char *)pTarget + pTarget->name_table + 1,
254 func_name, HIWORD(address), LOWORD(address),
255 NE_GetRelocAddrName( rep->address_type, additive ) );
259 case NE_RELTYPE_INTERNAL:
260 if ((rep->target1 & 0xff) == 0xff)
262 address = NE_GetEntryPoint( pModule->self, rep->target2 );
266 address = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( pSegTable[rep->target1-1].selector, rep->target2 );
269 TRACE( fixup,"%d: %04x:%04x %s\n",
270 i + 1, HIWORD(address), LOWORD(address),
271 NE_GetRelocAddrName( rep->address_type, additive ) );
274 case NE_RELTYPE_OSFIXUP:
275 /* Relocation type 7:
277 * These appear to be used as fixups for the Windows
278 * floating point emulator. Let's just ignore them and
279 * try to use the hardware floating point. Linux should
280 * successfully emulate the coprocessor if it doesn't
283 TRACE( fixup, "%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
284 i + 1, rep->relocation_type, rep->offset,
285 rep->target1, rep->target2,
286 NE_GetRelocAddrName( rep->address_type, additive ) );
290 offset = rep->offset;
292 /* Apparently, high bit of address_type is sometimes set; */
293 /* we ignore it for now */
294 if (rep->address_type > NE_RADDR_OFFSET32)
297 GetModuleName( pModule->self, module, sizeof(module) );
298 ERR( fixup, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
299 module, rep->address_type );
304 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
305 TRACE( fixup," %04x:%04x\n", offset, *sp );
306 switch (rep->address_type & 0x7f)
308 case NE_RADDR_LOWBYTE:
309 *(BYTE *)sp += LOBYTE((int)address);
311 case NE_RADDR_OFFSET16:
312 *sp += LOWORD(address);
314 case NE_RADDR_POINTER32:
315 *sp += LOWORD(address);
316 *(sp+1) = HIWORD(address);
318 case NE_RADDR_SELECTOR:
319 /* Borland creates additive records with offset zero. Strange, but OK */
321 ERR(fixup,"Additive selector to %04x.Please report\n",*sp);
323 *sp = HIWORD(address);
329 else /* non-additive fixup */
333 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
335 TRACE( fixup," %04x:%04x\n", offset, *sp );
336 switch (rep->address_type & 0x7f)
338 case NE_RADDR_LOWBYTE:
339 *(BYTE *)sp = LOBYTE((int)address);
341 case NE_RADDR_OFFSET16:
342 *sp = LOWORD(address);
344 case NE_RADDR_POINTER32:
345 *(FARPROC16 *)sp = address;
347 case NE_RADDR_SELECTOR:
348 *sp = SELECTOROF(address);
353 if (next_offset == offset) break; /* avoid infinite loop */
354 if (next_offset >= GlobalSize16(pSeg->selector)) break;
355 offset = next_offset;
356 } while (offset != 0xffff);
364 WARN(fixup, "WARNING: %d: unknown ADDR TYPE %d, "
365 "TYPE %d, OFFSET %04x, TARGET %04x %04x\n",
366 i + 1, rep->address_type, rep->relocation_type,
367 rep->offset, rep->target1, rep->target2);
373 /***********************************************************************
376 BOOL32 NE_LoadAllSegments( NE_MODULE *pModule )
380 if (pModule->flags & NE_FFLAGS_SELFLOAD)
383 /* Handle self loading modules */
384 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
385 SELFLOADHEADER *selfloadheader;
386 STACK16FRAME *stack16Top;
387 THDB *thdb = THREAD_Current();
388 HMODULE16 hselfload = GetModuleHandle16("WPROCS");
390 WORD saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
392 TRACE(module, "%.*s is a self-loading module!\n",
393 *((BYTE*)pModule + pModule->name_table),
394 (char *)pModule + pModule->name_table + 1);
395 if (!NE_LoadSegment( pModule, 1 )) return FALSE;
396 selfloadheader = (SELFLOADHEADER *)
397 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
398 selfloadheader->EntryAddrProc = NE_GetEntryPoint(hselfload,27);
399 selfloadheader->MyAlloc = NE_GetEntryPoint(hselfload,28);
400 selfloadheader->SetOwner = NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
401 pModule->self_loading_sel = GlobalHandleToSel(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, FALSE, FALSE, FALSE));
402 oldstack = thdb->cur_stack;
403 thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
404 0xff00 - sizeof(*stack16Top) );
405 stack16Top = (STACK16FRAME *)PTR_SEG_TO_LIN(thdb->cur_stack);
406 stack16Top->frame32 = 0;
408 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
409 stack16Top->entry_point = 0;
410 stack16Top->entry_ip = 0;
411 stack16Top->entry_cs = 0;
416 hf = FILE_DupUnixHandle( NE_OpenFile( pModule ) );
417 TRACE(dll,"CallBootAppProc(hModule=0x%04x,hf=0x%04x)\n",pModule->self,hf);
418 Callbacks->CallBootAppProc(selfloadheader->BootApp, pModule->self, hf);
419 TRACE(dll,"Return from CallBootAppProc\n");
421 /* some BootApp procs overwrite the selector of dgroup */
422 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
423 thdb->cur_stack = oldstack;
424 for (i = 2; i <= pModule->seg_count; i++)
425 if (!NE_LoadSegment( pModule, i )) return FALSE;
429 for (i = 1; i <= pModule->seg_count; i++)
430 if (!NE_LoadSegment( pModule, i )) return FALSE;
436 /***********************************************************************
439 * Fixup the exported functions prologs.
441 void NE_FixupPrologs( NE_MODULE *pModule )
443 SEGTABLEENTRY *pSegTable;
446 BYTE *p, *fixup_ptr, count;
447 dbg_decl_str(module, 512);
449 pSegTable = NE_SEG_TABLE(pModule);
450 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
451 dgroup = pSegTable[pModule->dgroup-1].selector;
453 TRACE(module, "(%04x)\n", pModule->self );
454 p = (BYTE *)pModule + pModule->entry_table;
457 if (p[1] == 0) /* Unused entry */
459 p += 2; /* Skip it */
462 if (p[1] == 0xfe) /* Constant entry */
464 p += 2 + *p * 3; /* Skip it */
468 /* Now fixup the entries of this bundle */
474 dbg_reset_str(module);
475 dsprintf(module,"Flags: %04x, sel %02x ", *p, sel);
476 /* According to the output generated by TDUMP, the flags mean:
477 * 0x0001 function is exported
478 * 0x0002 Single data (seems to occur only in DLLs)
480 if (sel == 0xff) { /* moveable */
481 dsprintf(module, "(%02x) o %04x", p[3], *(WORD *)(p+4) );
482 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
484 dsprintf(module, "offset %04x", *(WORD *)(p+1) );
485 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) +
488 TRACE(module, "%s Signature: %02x %02x %02x,ff %x\n",
489 dbg_str(module), fixup_ptr[0], fixup_ptr[1],
490 fixup_ptr[2], pModule->flags );
493 /* Verify the signature */
494 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
495 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
496 && fixup_ptr[2] == 0x90)
500 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA)
502 /* can this happen? */
503 ERR(fixup, "FixupPrologs got confused\n" );
505 else if (pModule->flags & NE_FFLAGS_SINGLEDATA)
507 *fixup_ptr = 0xb8; /* MOV AX, */
508 *(WORD *)(fixup_ptr+1) = dgroup;
513 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
514 fixup_ptr[0] = 0x90; /* non-library: NOPs */
520 WARN(fixup, "Unknown signature\n" );
525 p += (sel == 0xff) ? 6 : 3;
530 /***********************************************************************
531 * NE_GetDLLInitParams
533 static VOID NE_GetDLLInitParams( NE_MODULE *pModule,
534 WORD *hInst, WORD *ds, WORD *heap )
536 SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
538 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
540 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
543 ERR(dll, "Library is not marked SINGLEDATA\n");
546 else /* DATA NONE DLL */
552 else /* DATA SINGLE DLL */
554 if (pModule->dgroup) {
555 *ds = pSegTable[pModule->dgroup-1].selector;
556 *heap = pModule->heap_size;
558 else /* hmm, DLL has no dgroup,
559 but why has it NE_FFLAGS_SINGLEDATA set ?
560 Buggy DLL compiler ? */
567 *hInst = *ds ? *ds : pModule->self;
571 /***********************************************************************
574 * Call the DLL initialization code
576 static BOOL32 NE_InitDLL( TDB* pTask, NE_MODULE *pModule )
578 SEGTABLEENTRY *pSegTable;
579 WORD hInst, ds, heap, fs;
582 pSegTable = NE_SEG_TABLE( pModule );
584 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
585 (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
587 /* Call USER signal handler. This is necessary to install a
588 * proper loader for HICON and HCURSOR resources that this DLL
589 * may contain. InitApp() does this for task modules. */
591 if (pTask && pTask->userhandler)
593 pTask->userhandler( pModule->self, USIG_DLL_LOAD, 0, pTask->hInstance,
597 if (!pModule->cs) return TRUE; /* no initialization code */
600 /* Registers at initialization must be:
602 * di library instance
603 * ds data segment if any
604 * es:si command line (always 0)
607 memset( &context, 0, sizeof(context) );
609 NE_GetDLLInitParams( pModule, &hInst, &ds, &heap );
612 ECX_reg(&context) = heap;
613 EDI_reg(&context) = hInst;
614 DS_reg(&context) = ds;
615 ES_reg(&context) = ds; /* who knows ... */
616 FS_reg(&context) = fs;
618 CS_reg(&context) = pSegTable[pModule->cs-1].selector;
619 EIP_reg(&context) = pModule->ip;
620 EBP_reg(&context) = OFFSETOF(THREAD_Current()->cur_stack)
621 + (WORD)&((STACK16FRAME*)0)->bp;
624 pModule->cs = 0; /* Don't initialize it twice */
625 TRACE(dll, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
626 CS_reg(&context), IP_reg(&context), DS_reg(&context),
627 DI_reg(&context), CX_reg(&context) );
628 Callbacks->CallRegisterShortProc( &context, 0 );
632 /***********************************************************************
633 * NE_CallDllEntryPoint
635 * Call the DllEntryPoint of DLLs with subsystem >= 4.0
638 static void NE_CallDllEntryPoint( NE_MODULE *pModule, DWORD dwReason )
640 WORD hInst, ds, heap, fs;
641 FARPROC16 entryPoint;
644 THDB *thdb = THREAD_Current();
645 LPBYTE stack = (LPBYTE)THREAD_STACK16(thdb);
647 if (pModule->expected_version < 0x0400) return;
648 if (!(ordinal = NE_GetOrdinal( pModule->self, "DllEntryPoint" ))) return;
649 if (!(entryPoint = NE_GetEntryPoint( pModule->self, ordinal ))) return;
651 memset( &context, 0, sizeof(context) );
653 NE_GetDLLInitParams( pModule, &hInst, &ds, &heap );
656 DS_reg(&context) = ds;
657 ES_reg(&context) = ds; /* who knows ... */
658 FS_reg(&context) = fs;
660 CS_reg(&context) = HIWORD(entryPoint);
661 IP_reg(&context) = LOWORD(entryPoint);
662 EBP_reg(&context) = OFFSETOF( thdb->cur_stack )
663 + (WORD)&((STACK16FRAME*)0)->bp;
665 *(DWORD *)(stack - 4) = dwReason; /* dwReason */
666 *(WORD *) (stack - 6) = hInst; /* hInst */
667 *(WORD *) (stack - 8) = ds; /* wDS */
668 *(WORD *) (stack - 10) = heap; /* wHeapSize */
669 *(DWORD *)(stack - 14) = 0; /* dwReserved1 */
670 *(WORD *) (stack - 16) = 0; /* wReserved2 */
672 TRACE(dll, "Calling DllEntryPoint, cs:ip=%04lx:%04x\n",
673 CS_reg(&context), IP_reg(&context));
675 Callbacks->CallRegisterShortProc( &context, 16 );
679 /***********************************************************************
682 * Recursively initialize all DLLs (according to the order in which
683 * they where loaded).
685 void NE_InitializeDLLs( HMODULE16 hModule )
687 TDB* pTask = (TDB*)GlobalLock16(GetCurrentTask());
691 if (!(pModule = NE_GetPtr( hModule ))) return;
692 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
694 if (pModule->dlls_to_init)
696 HGLOBAL16 to_init = pModule->dlls_to_init;
697 pModule->dlls_to_init = 0;
698 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
700 NE_InitializeDLLs( *pDLL );
702 GlobalFree16( to_init );
704 NE_InitDLL( pTask, pModule );
705 NE_CallDllEntryPoint( pModule, DLL_PROCESS_ATTACH );
709 /***********************************************************************
712 * If lib_only is TRUE, handle the module like a library even if it is a .EXE
714 HINSTANCE16 NE_CreateInstance( NE_MODULE *pModule, HINSTANCE16 *prev,
717 SEGTABLEENTRY *pSegment;
719 HINSTANCE16 hNewInstance;
721 if (pModule->dgroup == 0)
723 if (prev) *prev = pModule->self;
724 return pModule->self;
727 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
728 if (prev) *prev = pSegment->selector;
730 /* if it's a library, create a new instance only the first time */
731 if (pSegment->selector)
733 if (pModule->flags & NE_FFLAGS_LIBMODULE) return pSegment->selector;
734 if (lib_only) return pSegment->selector;
737 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
738 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
739 minsize += pModule->heap_size;
740 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED, minsize,
741 pModule->self, FALSE, FALSE, FALSE );
742 if (!hNewInstance) return 0;
743 pSegment->selector = hNewInstance;
748 /***********************************************************************
751 * Needed for self-loading modules.
754 /* It does nothing */
755 void WINAPI PatchCodeHandle(HANDLE16 hSel)
757 FIXME(module,"(%04x): stub.\n",hSel);
761 /***********************************************************************
764 * This function translates NE segment flags to GlobalAlloc flags
766 static WORD NE_Ne2MemFlags(WORD flags)
770 if (flags & NE_SEGFLAGS_DISCARDABLE)
771 memflags |= GMEM_DISCARDABLE;
772 if (flags & NE_SEGFLAGS_MOVEABLE ||
773 ( ! (flags & NE_SEGFLAGS_DATA) &&
774 ! (flags & NE_SEGFLAGS_LOADED) &&
775 ! (flags & NE_SEGFLAGS_ALLOCATED)
778 memflags |= GMEM_MOVEABLE;
779 memflags |= GMEM_ZEROINIT;
781 memflags = GMEM_ZEROINIT | GMEM_FIXED;
786 /***********************************************************************
787 * NE_AllocateSegment (WPROCS.26)
789 DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
791 WORD size = wSize << wElem;
792 HANDLE16 hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
793 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
797 /***********************************************************************
800 BOOL32 NE_CreateSegments( NE_MODULE *pModule )
802 SEGTABLEENTRY *pSegment;
805 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
807 pSegment = NE_SEG_TABLE( pModule );
808 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
810 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
811 if (i == pModule->ss) minsize += pModule->stack_size;
812 /* The DGROUP is allocated by NE_CreateInstance */
813 if (i == pModule->dgroup) continue;
814 pSegment->selector = GLOBAL_Alloc( NE_Ne2MemFlags(pSegment->flags),
815 minsize, pModule->self,
816 !(pSegment->flags & NE_SEGFLAGS_DATA),
818 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
819 if (!pSegment->selector) return FALSE;
822 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
823 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
828 /**********************************************************************
829 * IsSharedSelector (KERNEL.345)
831 BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
833 /* Check whether the selector belongs to a DLL */
834 NE_MODULE *pModule = NE_GetPtr( selector );
835 if (!pModule) return FALSE;
836 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;