Release 980503
[wine/hacks.git] / loader / ne / segment.c
blob99f78ce911f1bc3224e5d2105f83b1dc4611e943
1 /*
2 * NE segment loading
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
6 */
8 #include <assert.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <ctype.h>
16 #include <string.h>
17 #include <errno.h>
18 #include "neexe.h"
19 #include "windows.h"
20 #include "global.h"
21 #include "task.h"
22 #include "selectors.h"
23 #include "callback.h"
24 #include "file.h"
25 #include "module.h"
26 #include "stackframe.h"
27 #include "debug.h"
28 #include "xmalloc.h"
31 /***********************************************************************
32 * NE_GetRelocAddrName
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";
45 return "???";
49 /***********************************************************************
50 * NE_LoadSegment
52 BOOL32 NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
54 SEGTABLEENTRY *pSegTable, *pSeg;
55 WORD *pModuleTable;
56 WORD count, i, offset, next_offset;
57 HMODULE16 module;
58 FARPROC16 address = 0;
59 int fd;
60 struct relocation_entry_s *rep, *reloc_entries;
61 BYTE *func_name;
62 int size;
63 char* mem;
65 char buffer[256];
66 int ordinal, additive;
67 unsigned short *sp;
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 = MODULE_OpenFile( pModule->self );
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;
81 else size = 0x10000;
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;
88 DWORD oldstack;
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;
105 stack16Top->bp = 0;
106 stack16Top->ip = 0;
107 stack16Top->cs = 0;
108 newselector = Callbacks->CallLoadAppSegProc(selfloadheader->LoadAppSeg,
109 pModule->self, hf, segnum );
110 _lclose32( hf );
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 fprintf(stderr, "A new selector was allocated for the dgroup segment\n"
122 "Old selector is %d, new one is %d", oldselector, newselector);
123 } else {
124 FreeSelector(pSeg->selector);
125 pSeg->selector = newselector;
129 thdb->cur_stack = oldstack;
131 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
132 read(fd, mem, size);
133 else {
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);
141 char* curr = buff;
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--) {
147 char* bytes = curr;
148 unsigned int byte;
149 for(byte = 0; byte < len; byte++)
150 *mem++ = *bytes++;
152 curr += len;
154 free(buff);
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" );
178 return FALSE;
182 * Go through the relocation table one entry at a time.
184 rep = reloc_entries;
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
192 and target */
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 );
202 if (!address)
204 NE_MODULE *pTarget = MODULE_GetPtr16( module );
205 if (!pTarget)
206 fprintf( stderr, "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 );
211 else
212 fprintf( stderr, "Warning: no handler for %.*s.%d, setting to 0:0\n",
213 *((BYTE *)pTarget + pTarget->name_table),
214 (char *)pTarget + pTarget->name_table + 1,
215 ordinal );
217 if (TRACE_ON(fixup))
219 NE_MODULE *pTarget = MODULE_GetPtr16( 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 ) );
226 break;
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';
233 func_name = buffer;
234 ordinal = NE_GetOrdinal( module, func_name );
235 address = NE_GetEntryPoint( module, ordinal );
237 if (ERR_ON(fixup) && !address)
239 NE_MODULE *pTarget = MODULE_GetPtr16( 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 );
244 if (TRACE_ON(fixup))
246 NE_MODULE *pTarget = MODULE_GetPtr16( 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 ) );
253 break;
255 case NE_RELTYPE_INTERNAL:
256 if ((rep->target1 & 0xff) == 0xff)
258 address = NE_GetEntryPoint( pModule->self, rep->target2 );
260 else
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 ) );
268 break;
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
277 * exist.
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 ) );
283 continue;
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)
291 ERR( fixup, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
292 MODULE_GetModuleName(pModule->self), rep->address_type );
294 if (additive)
296 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
297 TRACE( fixup," %04x:%04x\n", offset, *sp );
298 switch (rep->address_type & 0x7f)
300 case NE_RADDR_LOWBYTE:
301 *(BYTE *)sp += LOBYTE((int)address);
302 break;
303 case NE_RADDR_OFFSET16:
304 *sp += LOWORD(address);
305 break;
306 case NE_RADDR_POINTER32:
307 *sp += LOWORD(address);
308 *(sp+1) = HIWORD(address);
309 break;
310 case NE_RADDR_SELECTOR:
311 /* Borland creates additive records with offset zero. Strange, but OK */
312 if (*sp)
313 ERR(fixup,"Additive selector to %04x.Please report\n",*sp);
314 else
315 *sp = HIWORD(address);
316 break;
317 default:
318 goto unknown;
321 else /* non-additive fixup */
325 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
326 next_offset = *sp;
327 TRACE( fixup," %04x:%04x\n", offset, *sp );
328 switch (rep->address_type & 0x7f)
330 case NE_RADDR_LOWBYTE:
331 *(BYTE *)sp = LOBYTE((int)address);
332 break;
333 case NE_RADDR_OFFSET16:
334 *sp = LOWORD(address);
335 break;
336 case NE_RADDR_POINTER32:
337 *(FARPROC16 *)sp = address;
338 break;
339 case NE_RADDR_SELECTOR:
340 *sp = SELECTOROF(address);
341 break;
342 default:
343 goto unknown;
345 if (next_offset == offset) break; /* avoid infinite loop */
346 if (next_offset >= GlobalSize16(pSeg->selector)) break;
347 offset = next_offset;
348 } while (offset && (offset != 0xffff));
352 free(reloc_entries);
353 return TRUE;
355 unknown:
356 WARN(fixup, "WARNING: %d: unknown ADDR TYPE %d, "
357 "TYPE %d, OFFSET %04x, TARGET %04x %04x\n",
358 i + 1, rep->address_type, rep->relocation_type,
359 rep->offset, rep->target1, rep->target2);
360 free(reloc_entries);
361 return FALSE;
365 /***********************************************************************
366 * NE_LoadAllSegments
368 BOOL32 NE_LoadAllSegments( NE_MODULE *pModule )
370 int i;
372 if (pModule->flags & NE_FFLAGS_SELFLOAD)
374 HFILE32 hf;
375 /* Handle self loading modules */
376 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
377 SELFLOADHEADER *selfloadheader;
378 STACK16FRAME *stack16Top;
379 THDB *thdb = THREAD_Current();
380 HMODULE16 hselfload = GetModuleHandle16("WPROCS");
381 DWORD oldstack;
382 WORD saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
384 TRACE(module, "%.*s is a self-loading module!\n",
385 *((BYTE*)pModule + pModule->name_table),
386 (char *)pModule + pModule->name_table + 1);
387 if (!NE_LoadSegment( pModule, 1 )) return FALSE;
388 selfloadheader = (SELFLOADHEADER *)
389 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
390 selfloadheader->EntryAddrProc = NE_GetEntryPoint(hselfload,27);
391 selfloadheader->MyAlloc = NE_GetEntryPoint(hselfload,28);
392 selfloadheader->SetOwner = NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
393 pModule->self_loading_sel = GlobalHandleToSel(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, FALSE, FALSE, FALSE));
394 oldstack = thdb->cur_stack;
395 thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
396 0xff00 - sizeof(*stack16Top) );
397 stack16Top = (STACK16FRAME *)PTR_SEG_TO_LIN(thdb->cur_stack);
398 stack16Top->frame32 = 0;
399 stack16Top->ebp = 0;
400 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
401 stack16Top->entry_point = 0;
402 stack16Top->entry_ip = 0;
403 stack16Top->entry_cs = 0;
404 stack16Top->bp = 0;
405 stack16Top->ip = 0;
406 stack16Top->cs = 0;
408 hf = FILE_DupUnixHandle( MODULE_OpenFile( pModule->self ) );
409 Callbacks->CallBootAppProc(selfloadheader->BootApp, pModule->self, hf);
410 _lclose32(hf);
411 /* some BootApp procs overwrite the selector of dgroup */
412 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
413 thdb->cur_stack = oldstack;
414 for (i = 2; i <= pModule->seg_count; i++)
415 if (!NE_LoadSegment( pModule, i )) return FALSE;
417 else
419 for (i = 1; i <= pModule->seg_count; i++)
420 if (!NE_LoadSegment( pModule, i )) return FALSE;
422 return TRUE;
426 /***********************************************************************
427 * NE_FixupPrologs
429 * Fixup the exported functions prologs.
431 void NE_FixupPrologs( NE_MODULE *pModule )
433 SEGTABLEENTRY *pSegTable;
434 WORD dgroup = 0;
435 WORD sel;
436 BYTE *p, *fixup_ptr, count;
437 dbg_decl_str(module, 512);
439 pSegTable = NE_SEG_TABLE(pModule);
440 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
441 dgroup = pSegTable[pModule->dgroup-1].selector;
443 TRACE(module, "(%04x)\n", pModule->self );
444 p = (BYTE *)pModule + pModule->entry_table;
445 while (*p)
447 if (p[1] == 0) /* Unused entry */
449 p += 2; /* Skip it */
450 continue;
452 if (p[1] == 0xfe) /* Constant entry */
454 p += 2 + *p * 3; /* Skip it */
455 continue;
458 /* Now fixup the entries of this bundle */
459 count = *p;
460 sel = p[1];
461 p += 2;
462 while (count-- > 0)
464 dbg_reset_str(module);
465 dsprintf(module,"Flags: %04x, sel %02x ", *p, sel);
466 /* According to the output generated by TDUMP, the flags mean:
467 * 0x0001 function is exported
468 * 0x0002 Single data (seems to occur only in DLLs)
470 if (sel == 0xff) { /* moveable */
471 dsprintf(module, "(%02x) o %04x", p[3], *(WORD *)(p+4) );
472 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
473 } else { /* fixed */
474 dsprintf(module, "offset %04x", *(WORD *)(p+1) );
475 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) +
476 *(WORD *)(p + 1);
478 TRACE(module, "%s Signature: %02x %02x %02x,ff %x\n",
479 dbg_str(module), fixup_ptr[0], fixup_ptr[1],
480 fixup_ptr[2], pModule->flags );
481 if (*p & 0x0001)
483 /* Verify the signature */
484 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
485 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
486 && fixup_ptr[2] == 0x90)
488 if (*p & 0x0002)
490 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA)
492 /* can this happen? */
493 fprintf( stderr, "FixupPrologs got confused\n" );
495 else if (pModule->flags & NE_FFLAGS_SINGLEDATA)
497 *fixup_ptr = 0xb8; /* MOV AX, */
498 *(WORD *)(fixup_ptr+1) = dgroup;
501 else
503 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
504 fixup_ptr[0] = 0x90; /* non-library: NOPs */
505 fixup_ptr[1] = 0x90;
506 fixup_ptr[2] = 0x90;
509 } else {
510 WARN(fixup, "Unknown signature\n" );
513 else
514 TRACE(module,"\n");
515 p += (sel == 0xff) ? 6 : 3;
521 /***********************************************************************
522 * NE_InitDLL
524 * Call the DLL initialization code
526 static BOOL32 NE_InitDLL( TDB* pTask, HMODULE16 hModule )
528 NE_MODULE *pModule;
529 SEGTABLEENTRY *pSegTable;
530 CONTEXT context;
532 /* Registers at initialization must be:
533 * cx heap size
534 * di library instance
535 * ds data segment if any
536 * es:si command line (always 0)
539 if (!(pModule = MODULE_GetPtr16( hModule ))) return FALSE;
540 pSegTable = NE_SEG_TABLE( pModule );
542 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
543 (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
545 /* Call USER signal handler. This is necessary to install a
546 * proper loader for HICON and HCURSOR resources that this DLL
547 * may contain. InitApp() does this for task modules. */
549 if (pTask && pTask->userhandler)
551 pTask->userhandler( hModule, USIG_DLL_LOAD, 0, pTask->hInstance,
552 pTask->hQueue );
555 if (!pModule->cs) return TRUE; /* no initialization code */
557 memset( &context, 0, sizeof(context) );
559 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
561 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
563 /* Not SINGLEDATA */
564 fprintf(stderr, "Library is not marked SINGLEDATA\n");
565 exit(1);
567 else /* DATA NONE DLL */
569 DS_reg(&context) = 0;
570 ECX_reg(&context) = 0;
573 else /* DATA SINGLE DLL */
575 if (pModule->dgroup) {
576 DS_reg(&context) = pSegTable[pModule->dgroup-1].selector;
577 ECX_reg(&context) = pModule->heap_size;
579 else /* hmm, DLL has no dgroup,
580 but why has it NE_FFLAGS_SINGLEDATA set ?
581 Buggy DLL compiler ? */
583 DS_reg(&context) = 0;
584 ECX_reg(&context) = 0;
588 CS_reg(&context) = pSegTable[pModule->cs-1].selector;
589 EIP_reg(&context) = pModule->ip;
590 EBP_reg(&context) = OFFSETOF(THREAD_Current()->cur_stack)
591 + (WORD)&((STACK16FRAME*)0)->bp;
592 EDI_reg(&context) = DS_reg(&context) ? DS_reg(&context) : hModule;
595 pModule->cs = 0; /* Don't initialize it twice */
596 TRACE(dll, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
597 CS_reg(&context), IP_reg(&context), DS_reg(&context),
598 DI_reg(&context), CX_reg(&context) );
599 Callbacks->CallRegisterShortProc( &context, 0 );
600 return TRUE;
604 /***********************************************************************
605 * NE_InitializeDLLs
607 * Recursively initialize all DLLs (according to the order in which
608 * they where loaded).
610 void NE_InitializeDLLs( HMODULE16 hModule )
612 TDB* pTask = (TDB*)GlobalLock16(GetCurrentTask());
613 NE_MODULE *pModule;
614 HMODULE16 *pDLL;
616 if (!(pModule = MODULE_GetPtr16( hModule ))) return;
617 if (pModule->flags & NE_FFLAGS_WIN32) return;
619 if (pModule->dlls_to_init)
621 HGLOBAL16 to_init = pModule->dlls_to_init;
622 pModule->dlls_to_init = 0;
623 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
625 NE_InitializeDLLs( *pDLL );
627 GlobalFree16( to_init );
629 NE_InitDLL( pTask, hModule );
633 /***********************************************************************
634 * PatchCodeHandle
636 * Needed for self-loading modules.
639 /* It does nothing */
640 void WINAPI PatchCodeHandle(HANDLE16 hSel)
642 fprintf(stderr,"PatchCodeHandle(%04x),stub!\n",hSel);
646 /***********************************************************************
647 * NE_Ne2MemFlags
649 * This function translates NE segment flags to GlobalAlloc flags
651 static WORD NE_Ne2MemFlags(WORD flags)
653 WORD memflags = 0;
654 #if 0
655 if (flags & NE_SEGFLAGS_DISCARDABLE)
656 memflags |= GMEM_DISCARDABLE;
657 if (flags & NE_SEGFLAGS_MOVEABLE ||
658 ( ! (flags & NE_SEGFLAGS_DATA) &&
659 ! (flags & NE_SEGFLAGS_LOADED) &&
660 ! (flags & NE_SEGFLAGS_ALLOCATED)
663 memflags |= GMEM_MOVEABLE;
664 memflags |= GMEM_ZEROINIT;
665 #else
666 memflags = GMEM_ZEROINIT | GMEM_FIXED;
667 return memflags;
668 #endif
671 /***********************************************************************
672 * NE_AllocateSegment (WPROCS.26)
674 DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
676 WORD size = wSize << wElem;
677 HANDLE16 hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
678 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
682 /***********************************************************************
683 * NE_CreateSegments
685 BOOL32 NE_CreateSegments( HMODULE16 hModule )
687 SEGTABLEENTRY *pSegment;
688 NE_MODULE *pModule;
689 int i, minsize;
691 if (!(pModule = MODULE_GetPtr16( hModule ))) return FALSE;
692 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
694 pSegment = NE_SEG_TABLE( pModule );
695 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
697 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
698 if (i == pModule->ss) minsize += pModule->stack_size;
699 /* The DGROUP is allocated by MODULE_CreateInstance */
700 if (i == pModule->dgroup) continue;
701 pSegment->selector = GLOBAL_Alloc( NE_Ne2MemFlags(pSegment->flags),
702 minsize, hModule,
703 !(pSegment->flags & NE_SEGFLAGS_DATA),
704 FALSE,
705 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
706 if (!pSegment->selector) return FALSE;
709 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
710 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
711 return TRUE;