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 != 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;
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 = pSegTable[pModule->dgroup-1].selector;
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 BOOL32 NE_InitDLL( TDB* pTask, NE_MODULE *pModule )
572 SEGTABLEENTRY *pSegTable;
573 WORD hInst, ds, heap, fs;
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. This is necessary to install a
582 * proper loader for HICON and HCURSOR resources that this DLL
583 * may contain. InitApp() does this for task modules. */
585 if (pTask && pTask->userhandler)
587 pTask->userhandler( pModule->self, USIG_DLL_LOAD, 0, pTask->hInstance,
591 if (!pModule->cs) return TRUE; /* no initialization code */
594 /* Registers at initialization must be:
596 * di library instance
597 * ds data segment if any
598 * es:si command line (always 0)
601 memset( &context, 0, sizeof(context) );
603 NE_GetDLLInitParams( pModule, &hInst, &ds, &heap );
606 ECX_reg(&context) = heap;
607 EDI_reg(&context) = hInst;
608 DS_reg(&context) = ds;
609 ES_reg(&context) = ds; /* who knows ... */
610 FS_reg(&context) = fs;
612 CS_reg(&context) = pSegTable[pModule->cs-1].selector;
613 EIP_reg(&context) = pModule->ip;
614 EBP_reg(&context) = OFFSETOF(THREAD_Current()->cur_stack)
615 + (WORD)&((STACK16FRAME*)0)->bp;
618 pModule->cs = 0; /* Don't initialize it twice */
619 TRACE(dll, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
620 CS_reg(&context), IP_reg(&context), DS_reg(&context),
621 DI_reg(&context), CX_reg(&context) );
622 Callbacks->CallRegisterShortProc( &context, 0 );
626 /***********************************************************************
627 * NE_CallDllEntryPoint
629 * Call the DllEntryPoint of DLLs with subsystem >= 4.0
632 static void NE_CallDllEntryPoint( NE_MODULE *pModule, DWORD dwReason )
634 WORD hInst, ds, heap, fs;
635 FARPROC16 entryPoint;
638 THDB *thdb = THREAD_Current();
639 LPBYTE stack = (LPBYTE)THREAD_STACK16(thdb);
641 if (pModule->expected_version < 0x0400) return;
642 if (!(ordinal = NE_GetOrdinal( pModule->self, "DllEntryPoint" ))) return;
643 if (!(entryPoint = NE_GetEntryPoint( pModule->self, ordinal ))) return;
645 memset( &context, 0, sizeof(context) );
647 NE_GetDLLInitParams( pModule, &hInst, &ds, &heap );
650 DS_reg(&context) = ds;
651 ES_reg(&context) = ds; /* who knows ... */
652 FS_reg(&context) = fs;
654 CS_reg(&context) = HIWORD(entryPoint);
655 IP_reg(&context) = LOWORD(entryPoint);
656 EBP_reg(&context) = OFFSETOF( thdb->cur_stack )
657 + (WORD)&((STACK16FRAME*)0)->bp;
659 *(DWORD *)(stack - 4) = dwReason; /* dwReason */
660 *(WORD *) (stack - 6) = hInst; /* hInst */
661 *(WORD *) (stack - 8) = ds; /* wDS */
662 *(WORD *) (stack - 10) = heap; /* wHeapSize */
663 *(DWORD *)(stack - 14) = 0; /* dwReserved1 */
664 *(WORD *) (stack - 16) = 0; /* wReserved2 */
666 TRACE(dll, "Calling DllEntryPoint, cs:ip=%04lx:%04x\n",
667 CS_reg(&context), IP_reg(&context));
669 Callbacks->CallRegisterShortProc( &context, 16 );
673 /***********************************************************************
676 * Recursively initialize all DLLs (according to the order in which
677 * they where loaded).
679 void NE_InitializeDLLs( HMODULE16 hModule )
681 TDB* pTask = (TDB*)GlobalLock16(GetCurrentTask());
685 if (!(pModule = NE_GetPtr( hModule ))) return;
686 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
688 if (pModule->dlls_to_init)
690 HGLOBAL16 to_init = pModule->dlls_to_init;
691 pModule->dlls_to_init = 0;
692 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
694 NE_InitializeDLLs( *pDLL );
696 GlobalFree16( to_init );
698 NE_InitDLL( pTask, pModule );
699 NE_CallDllEntryPoint( pModule, DLL_PROCESS_ATTACH );
703 /***********************************************************************
706 * If lib_only is TRUE, handle the module like a library even if it is a .EXE
708 HINSTANCE16 NE_CreateInstance( NE_MODULE *pModule, HINSTANCE16 *prev,
711 SEGTABLEENTRY *pSegment;
713 HINSTANCE16 hNewInstance;
715 if (pModule->dgroup == 0)
717 if (prev) *prev = pModule->self;
718 return pModule->self;
721 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
722 if (prev) *prev = pSegment->selector;
724 /* if it's a library, create a new instance only the first time */
725 if (pSegment->selector)
727 if (pModule->flags & NE_FFLAGS_LIBMODULE) return pSegment->selector;
728 if (lib_only) return pSegment->selector;
731 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
732 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
733 minsize += pModule->heap_size;
734 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED, minsize,
735 pModule->self, FALSE, FALSE, FALSE );
736 if (!hNewInstance) return 0;
737 pSegment->selector = hNewInstance;
742 /***********************************************************************
745 * Needed for self-loading modules.
748 /* It does nothing */
749 void WINAPI PatchCodeHandle(HANDLE16 hSel)
751 FIXME(module,"(%04x): stub.\n",hSel);
755 /***********************************************************************
758 * This function translates NE segment flags to GlobalAlloc flags
760 static WORD NE_Ne2MemFlags(WORD flags)
764 if (flags & NE_SEGFLAGS_DISCARDABLE)
765 memflags |= GMEM_DISCARDABLE;
766 if (flags & NE_SEGFLAGS_MOVEABLE ||
767 ( ! (flags & NE_SEGFLAGS_DATA) &&
768 ! (flags & NE_SEGFLAGS_LOADED) &&
769 ! (flags & NE_SEGFLAGS_ALLOCATED)
772 memflags |= GMEM_MOVEABLE;
773 memflags |= GMEM_ZEROINIT;
775 memflags = GMEM_ZEROINIT | GMEM_FIXED;
780 /***********************************************************************
781 * NE_AllocateSegment (WPROCS.26)
783 DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
785 WORD size = wSize << wElem;
786 HANDLE16 hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
787 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
791 /***********************************************************************
794 BOOL32 NE_CreateSegments( NE_MODULE *pModule )
796 SEGTABLEENTRY *pSegment;
799 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
801 pSegment = NE_SEG_TABLE( pModule );
802 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
804 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
805 if (i == pModule->ss) minsize += pModule->stack_size;
806 /* The DGROUP is allocated by NE_CreateInstance */
807 if (i == pModule->dgroup) continue;
808 pSegment->selector = GLOBAL_Alloc( NE_Ne2MemFlags(pSegment->flags),
809 minsize, pModule->self,
810 !(pSegment->flags & NE_SEGFLAGS_DATA),
812 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
813 if (!pSegment->selector) return FALSE;
816 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
817 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
822 /**********************************************************************
823 * IsSharedSelector (KERNEL.345)
825 BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
827 /* Check whether the selector belongs to a DLL */
828 NE_MODULE *pModule = NE_GetPtr( selector );
829 if (!pModule) return FALSE;
830 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;