Release 940405
[wine/multimedia.git] / loader / selector.c
blob834e25229a2d6f2291299aa4315878a59d0306d4
1 #ifndef WINELIB
2 static char RCSId[] = "$Id: selector.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
3 static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <errno.h>
14 #ifdef __linux__
15 #include <linux/unistd.h>
16 #include <linux/head.h>
17 #include <linux/mman.h>
18 #include <linux/a.out.h>
19 #include <linux/ldt.h>
20 #endif
21 #if defined(__NetBSD__) || defined(__FreeBSD__)
22 #include <sys/mman.h>
23 #include <machine/segments.h>
24 #endif
26 #include "neexe.h"
27 #include "segmem.h"
28 #include "wine.h"
29 #include "windows.h"
30 #include "prototypes.h"
32 /* #define DEBUG_SELECTORS */
34 #ifdef linux
35 #define DEV_ZERO
36 #define UTEXTSEL 0x23
37 #endif
39 #if defined(__NetBSD__) || defined(__FreeBSD__)
40 #define PAGE_SIZE getpagesize()
41 #define MODIFY_LDT_CONTENTS_DATA 0
42 #define MODIFY_LDT_CONTENTS_STACK 1
43 #define MODIFY_LDT_CONTENTS_CODE 2
44 #define UTEXTSEL 0x1f
45 #endif
47 static SEGDESC * EnvironmentSelector = NULL;
48 static SEGDESC * PSP_Selector = NULL;
49 SEGDESC * MakeProcThunks = NULL;
50 unsigned short PSPSelector;
51 unsigned char ran_out = 0;
52 int LastUsedSelector = FIRST_SELECTOR - 1;
54 unsigned short SelectorMap[MAX_SELECTORS];
55 SEGDESC Segments[MAX_SELECTORS];
57 #ifdef DEV_ZERO
58 static FILE *zfile = NULL;
59 #endif
61 extern void KERNEL_Ordinal_102();
62 extern void UNIXLIB_Ordinal_0();
64 extern char **Argv;
65 extern int Argc;
67 /**********************************************************************
68 * FindUnusedSelectors
70 int
71 FindUnusedSelectors(int n_selectors)
73 int i;
74 int n_found;
76 n_found = 0;
77 for (i = LastUsedSelector + 1; i != LastUsedSelector; i++)
79 if (i >= MAX_SELECTORS)
81 n_found = 0;
82 i = FIRST_SELECTOR;
85 if (!SelectorMap[i] && ++n_found == n_selectors)
86 break;
89 if (i == LastUsedSelector)
90 return 0;
92 LastUsedSelector = i;
93 return i - n_selectors + 1;
96 #ifdef HAVE_IPC
97 /**********************************************************************
98 * IPCCopySelector
100 * Created a shared memory copy of a segment:
102 * - at a new selector location (if "new" is a 16-bit value)
103 * - at an arbitrary memory location (if "new" is a 32-bit value)
106 IPCCopySelector(int i_old, unsigned long new, int swap_type)
108 SEGDESC *s_new, *s_old;
109 int i_new;
110 void *base_addr;
112 s_old = &Segments[i_old];
114 if (new & 0xffff0000)
116 /**************************************************************
117 * Let's set the address parameter for no segment.
119 i_new = -1;
120 s_new = NULL;
121 base_addr = (void *) new;
123 else
125 /***************************************************************
126 * We need to fill in the segment descriptor for segment "new".
128 i_new = new;
129 s_new = &Segments[i_new];
131 SelectorMap[i_new] = i_new;
133 s_new->selector = (i_new << 3) | 0x0007;
134 s_new->base_addr = (void *) ((long) s_new->selector << 16);
135 s_new->length = s_old->length;
136 s_new->flags = s_old->flags;
137 s_new->owner = s_old->owner;
138 if (swap_type)
140 if (s_old->type == MODIFY_LDT_CONTENTS_DATA)
141 s_new->type = MODIFY_LDT_CONTENTS_CODE;
142 else
143 s_new->type = MODIFY_LDT_CONTENTS_DATA;
145 else
146 s_new->type = s_old->type;
148 base_addr = s_new->base_addr;
151 /******************************************************************
152 * If we don't have a shared memory key for s_old, then we need
153 * to get one. In this case, we'll also have to copy the data
154 * to protect it.
156 if (s_old->shm_key == 0)
158 s_old->shm_key = shmget(IPC_PRIVATE, s_old->length, 0600);
159 if (s_old->shm_key == 0)
161 if (s_new)
162 memset(s_new, 0, sizeof(*s_new));
163 return -1;
165 if (shmat(s_old->shm_key, base_addr, 0) == NULL)
167 if (s_new)
168 memset(s_new, 0, sizeof(*s_new));
169 shmctl(s_old->shm_key, IPC_RMID, NULL);
170 return -1;
172 memcpy(base_addr, s_old->base_addr, s_old->length);
173 munmap(s_old->base_addr,
174 ((s_old->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
175 shmat(s_old->shm_key, s_old->base_addr, 0);
177 /******************************************************************
178 * If have shared memory key s_old, then just attach the new
179 * address.
181 else
183 if (shmat(s_old->shm_key, base_addr, 0) == NULL)
185 if (s_new)
186 memset(s_new, 0, sizeof(*s_new));
187 return -1;
191 /******************************************************************
192 * If we are creating a new segment, then we also need to update
193 * the LDT to include the new selector. In this return the
194 * new selector.
196 if (s_new)
198 s_new->shm_key = s_old->shm_key;
200 if (set_ldt_entry(i_new, (unsigned long) base_addr,
201 s_old->length - 1, 0, s_new->type, 0, 0) < 0)
203 return -1;
206 return s_new->selector;
208 /******************************************************************
209 * No new segment. So, just return the shared memory key.
211 else
212 return s_old->shm_key;
214 #endif
216 /**********************************************************************
217 * AllocSelector
219 * This is very bad!!! This function is implemented for Windows
220 * compatibility only. Do not call this from the emulation library.
222 WORD AllocSelector(WORD old_selector)
224 SEGDESC *s_new, *s_old;
225 int i_new, i_old;
226 int selector;
228 i_new = FindUnusedSelectors(1);
229 s_new = &Segments[i_new];
231 if (old_selector)
233 i_old = (old_selector >> 3);
234 #ifdef HAVE_IPC
235 selector = IPCCopySelector(i_old, i_new, 0);
236 if (selector < 0)
237 return 0;
238 else
239 return selector;
240 #else
241 s_old = &Segments[i_old];
242 s_new->selector = (i_new << 3) | 0x0007;
243 *s_new = *s_old;
244 SelectorMap[i_new] = SelectorMap[i_old];
246 if (set_ldt_entry(i_new, s_new->base_addr,
247 s_new->length - 1, 0,
248 s_new->type, 0, 0) < 0)
250 return 0;
252 #endif
254 else
256 memset(s_new, 0, sizeof(*s_new));
257 SelectorMap[i_new] = i_new;
260 return (i_new << 3) | 0x0007;
263 /**********************************************************************
264 * PrestoChangoSelector
266 * This is very bad!!! This function is implemented for Windows
267 * compatibility only. Do not call this from the emulation library.
269 unsigned int PrestoChangoSelector(unsigned src_selector, unsigned dst_selector)
271 #ifdef HAVE_IPC
272 SEGDESC *src_s;
273 int src_idx, dst_idx;
275 src_idx = src_selector >> 3;
276 dst_idx = dst_selector >> 3;
278 if (src_idx == dst_idx)
280 src_s = &Segments[src_idx];
282 if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
283 src_s->type = MODIFY_LDT_CONTENTS_CODE;
284 else
285 src_s->type = MODIFY_LDT_CONTENTS_DATA;
287 if (set_ldt_entry(src_idx, (long) src_s->base_addr,
288 src_s->length - 1, 0, src_s->type, 0, 0) < 0)
290 return 0;
293 return src_s->selector;
295 else
297 return IPCCopySelector(src_idx, dst_idx, 1);
299 #else /* HAVE_IPC */
300 SEGDESC *src_s, *dst_s;
301 char *p;
302 int src_idx, dst_idx;
303 int alias_count;
304 int i;
306 src_idx = (SelectorMap[src_selector >> 3]);
307 dst_idx = dst_selector >> 3;
308 src_s = &Segments[src_idx];
309 dst_s = &Segments[dst_idx];
311 alias_count = 0;
312 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
313 if (SelectorMap[i] == src_idx)
314 alias_count++;
316 if (src_s->type == MODIFY_LDT_CONTENTS_DATA
317 || alias_count > 1 || src_idx == dst_idx)
319 *dst_s = *src_s;
321 if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
322 dst_s->type = MODIFY_LDT_CONTENTS_CODE;
323 else
324 dst_s->type = MODIFY_LDT_CONTENTS_DATA;
326 SelectorMap[dst_idx] = SelectorMap[src_idx];
327 if (set_ldt_entry(dst_idx, (long) dst_s->base_addr,
328 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
330 return 0;
333 else
336 * We're changing an unaliased code segment into a data
337 * segment. The SAFEST (but ugliest) way to deal with
338 * this is to map the new segment and copy all the contents.
340 SelectorMap[dst_idx] = dst_idx;
341 *dst_s = *src_s;
342 dst_s->selector = (dst_idx << 3) | 0x0007;
343 dst_s->base_addr = (void *) ((unsigned int) dst_s->selector << 16);
344 dst_s->type = MODIFY_LDT_CONTENTS_DATA;
345 #ifdef DEV_ZERO
346 if (zfile == NULL)
347 zfile = fopen("/dev/zero","r");
348 p = (void *) mmap((char *) dst_s->base_addr,
349 ((dst_s->length + PAGE_SIZE)
350 & ~(PAGE_SIZE - 1)),
351 PROT_EXEC | PROT_READ | PROT_WRITE,
352 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
353 #else
354 p = (void *) mmap((char *) dst_s->base_addr,
355 ((dst_s->length + PAGE_SIZE)
356 & ~(PAGE_SIZE - 1)),
357 PROT_EXEC | PROT_READ | PROT_WRITE,
358 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
359 #endif
360 if (p == NULL)
361 return 0;
363 memcpy((void *) dst_s->base_addr, (void *) src_s->base_addr,
364 dst_s->length);
365 if (set_ldt_entry(src_idx, dst_s->base_addr,
366 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
368 return 0;
370 if (set_ldt_entry(dst_idx, dst_s->base_addr,
371 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
373 return 0;
376 munmap(src_s->base_addr,
377 (src_s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1));
378 SelectorMap[src_idx] = dst_idx;
379 src_s->base_addr = dst_s->base_addr;
382 return dst_s->selector;
383 #endif /* HAVE_IPC */
386 /**********************************************************************
387 * AllocCStoDSAlias
389 WORD AllocDStoCSAlias(WORD ds_selector)
391 unsigned int cs_selector;
393 if (ds_selector == 0)
394 return 0;
396 cs_selector = AllocSelector(0);
397 return PrestoChangoSelector(ds_selector, cs_selector);
400 /**********************************************************************
401 * FreeSelector
403 WORD FreeSelector(WORD sel)
405 SEGDESC *s;
406 int sel_idx;
407 int alias_count;
408 int i;
410 #ifdef HAVE_IPC
411 sel_idx = sel >> 3;
413 if (sel_idx < FIRST_SELECTOR || sel_idx >= MAX_SELECTORS)
414 return 0;
416 s = &Segments[sel_idx];
417 if (s->shm_key == 0)
419 munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
420 memcpy(s, 0, sizeof(*s));
421 SelectorMap[sel_idx] = 0;
423 else
425 shmdt(s->base_addr);
427 alias_count = 0;
428 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
429 if (SelectorMap[i] && Segments[i].shm_key == s->shm_key)
430 alias_count++;
432 if (alias_count == 1)
433 shmctl(s->shm_key, IPC_RMID, NULL);
435 memcpy(s, 0, sizeof(*s));
436 SelectorMap[sel_idx] = 0;
439 #else /* HAVE_IPC */
440 sel_idx = SelectorMap[sel >> 3];
442 if (sel_idx < FIRST_SELECTOR || sel_idx >= MAX_SELECTORS)
443 return 0;
445 if (sel_idx != (sel >> 3))
447 SelectorMap[sel >> 3] = 0;
448 return 0;
451 alias_count = 0;
452 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
453 if (SelectorMap[i] == sel_idx)
454 alias_count++;
456 if (alias_count == 1)
458 s = &Segments[sel_idx];
459 munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
460 memcpy(s, 0, sizeof(*s));
461 SelectorMap[sel >> 3] = 0;
463 #endif /* HAVE_IPC */
465 return 0;
468 /**********************************************************************
469 * CreateNewSegments
471 SEGDESC *
472 CreateNewSegments(int code_flag, int read_only, int length, int n_segments)
474 SEGDESC *s, *first_segment;
475 int contents;
476 int i, last_i;
478 i = FindUnusedSelectors(n_segments);
480 #ifdef DEBUG_SELECTORS
481 fprintf(stderr,
482 "Using %d segments starting at index %d.\n", n_segments, i);
483 #endif
486 * Fill in selector info.
488 first_segment = s = &Segments[i];
489 for (last_i = i + n_segments; i < last_i; i++, s++)
491 if (code_flag)
493 contents = MODIFY_LDT_CONTENTS_CODE;
494 s->flags = 0;
496 else
498 contents = MODIFY_LDT_CONTENTS_DATA;
499 s->flags = NE_SEGFLAGS_DATA;
502 s->selector = (i << 3) | 0x0007;
503 s->length = length;
504 #ifdef DEV_ZERO
505 if (zfile == NULL)
506 zfile = fopen("/dev/zero","r");
507 s->base_addr = (void *) mmap((char *) (s->selector << 16),
508 ((s->length + PAGE_SIZE - 1) &
509 ~(PAGE_SIZE - 1)),
510 PROT_EXEC | PROT_READ | PROT_WRITE,
511 MAP_FIXED | MAP_PRIVATE,
512 fileno(zfile), 0);
513 #else
514 s->base_addr = (void *) mmap((char *) (s->selector << 16),
515 ((s->length + PAGE_SIZE - 1) &
516 ~(PAGE_SIZE - 1)),
517 PROT_EXEC | PROT_READ | PROT_WRITE,
518 MAP_FIXED | MAP_PRIVATE | MAP_ANON,
519 -1, 0);
520 #endif
522 if (set_ldt_entry(i, (unsigned long) s->base_addr,
523 (s->length - 1) & 0xffff, 0,
524 contents, read_only, 0) < 0)
526 memset(s, 0, sizeof(*s));
527 return NULL;
530 SelectorMap[i] = (unsigned short) i;
531 s->type = contents;
534 return first_segment;
537 /**********************************************************************
538 * GetNextSegment
540 SEGDESC *
541 GetNextSegment(unsigned int flags, unsigned int limit)
543 return CreateNewSegments(0, 0, limit, 1);
546 /**********************************************************************
547 * GetEntryPointFromOrdinal
549 union lookup{
550 struct entry_tab_header_s *eth;
551 struct entry_tab_movable_s *etm;
552 struct entry_tab_fixed_s *etf;
553 char * cpnt;
556 unsigned int GetEntryDLLName(char * dll_name, char * function, int * sel,
557 int * addr)
559 struct dll_table_entry_s *dll_table;
560 struct w_files * wpnt;
561 char * cpnt;
562 int ordinal, j, len;
564 dll_table = FindDLLTable(dll_name);
566 if(dll_table) {
567 ordinal = FindOrdinalFromName(dll_table, function);
568 *sel = dll_table[ordinal].selector;
569 *addr = (unsigned int) dll_table[ordinal].address;
570 #ifdef WINESTAT
571 dll_table[ordinal].used++;
572 #endif
573 return 0;
576 /* We need a means of determining the ordinal for the function. */
577 /* Not a builtin symbol, look to see what the file has for us */
578 for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
579 if(strcmp(wpnt->name, dll_name)) continue;
580 cpnt = wpnt->nrname_table;
581 while(1==1){
582 if( ((int) cpnt) - ((int)wpnt->nrname_table) >
583 wpnt->ne_header->nrname_tab_length) return 1;
584 len = *cpnt++;
585 if(strncmp(cpnt, function, len) == 0) break;
586 cpnt += len + 2;
588 ordinal = *((unsigned short *) (cpnt + len));
589 j = GetEntryPointFromOrdinal(wpnt, ordinal);
590 *addr = j & 0xffff;
591 j = j >> 16;
592 *sel = j;
593 return 0;
595 return 1;
598 unsigned int GetEntryDLLOrdinal(char * dll_name, int ordinal, int * sel,
599 int * addr)
601 struct dll_table_entry_s *dll_table;
602 struct w_files * wpnt;
603 int j;
605 dll_table = FindDLLTable(dll_name);
607 if(dll_table) {
608 *sel = dll_table[ordinal].selector;
609 *addr = (unsigned int) dll_table[ordinal].address;
610 #ifdef WINESTAT
611 dll_table[ordinal].used++;
612 #endif
613 return 0;
616 /* Not a builtin symbol, look to see what the file has for us */
617 for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
618 if(strcmp(wpnt->name, dll_name)) continue;
619 j = GetEntryPointFromOrdinal(wpnt, ordinal);
620 *addr = j & 0xffff;
621 j = j >> 16;
622 *sel = j;
623 return 0;
625 return 1;
628 unsigned int
629 GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal)
631 int fd = wpnt->fd;
632 struct mz_header_s *mz_header = wpnt->mz_header;
633 struct ne_header_s *ne_header = wpnt->ne_header;
636 union lookup entry_tab_pointer;
637 struct entry_tab_header_s *eth;
638 struct entry_tab_movable_s *etm;
639 struct entry_tab_fixed_s *etf;
640 int current_ordinal;
641 int i;
644 entry_tab_pointer.cpnt = wpnt->lookup_table;
646 * Let's walk through the table until we get to our entry.
648 current_ordinal = 1;
649 while (1)
652 * Read header for this bundle.
654 eth = entry_tab_pointer.eth++;
656 if (eth->n_entries == 0)
657 return 0xffffffff; /* Yikes - we went off the end of the table */
659 if (eth->seg_number == 0)
661 current_ordinal += eth->n_entries;
662 if(current_ordinal > ordinal) return 0;
663 continue;
667 * Read each of the bundle entries.
669 for (i = 0; i < eth->n_entries; i++, current_ordinal++)
671 if (eth->seg_number >= 0xfe)
673 etm = entry_tab_pointer.etm++;
675 if (current_ordinal == ordinal)
677 return ((unsigned int)
678 (wpnt->selector_table[etm->seg_number - 1].base_addr +
679 etm->offset));
682 else
684 etf = entry_tab_pointer.etf++;
686 if (current_ordinal == ordinal)
688 return ((unsigned int)
689 (wpnt->selector_table[eth->seg_number - 1].base_addr +
690 (int) etf->offset[0] +
691 ((int) etf->offset[1] << 8)));
698 /**********************************************************************
699 * GetDOSEnvironment
701 LPSTR GetDOSEnvironment(void)
703 return (LPSTR) EnvironmentSelector->base_addr;
706 /**********************************************************************
707 * CreateEnvironment
709 static SEGDESC *
710 CreateEnvironment(void)
712 char *p;
713 SEGDESC * s;
715 s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
716 if (s == NULL)
717 return NULL;
720 * Fill environment with meaningless babble.
722 p = (char *) s->base_addr;
723 strcpy(p, "PATH=C:\\WINDOWS");
724 p += strlen(p) + 1;
725 *p++ = '\0';
726 *p++ = 11;
727 *p++ = 0;
728 strcpy(p, "C:\\TEST.EXE");
730 return s;
733 /**********************************************************************
734 * CreatePSP
736 static SEGDESC *
737 CreatePSP(void)
739 struct dos_psp_s *psp;
740 unsigned short *usp;
741 SEGDESC * s;
742 char *p1, *p2;
743 int i;
745 s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
748 * Fill PSP
750 PSPSelector = s->selector;
751 psp = (struct dos_psp_s *) s->base_addr;
752 psp->pspInt20 = 0x20cd;
753 psp->pspDispatcher[0] = 0x9a;
754 usp = (unsigned short *) &psp->pspDispatcher[1];
755 *usp = (unsigned short) KERNEL_Ordinal_102;
756 *(usp + 1) = UTEXTSEL;
757 psp->pspTerminateVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
758 psp->pspTerminateVector[1] = UTEXTSEL;
759 psp->pspControlCVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
760 psp->pspControlCVector[1] = UTEXTSEL;
761 psp->pspCritErrorVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
762 psp->pspCritErrorVector[1] = UTEXTSEL;
763 psp->pspEnvironment = EnvironmentSelector->selector;
765 p1 = psp->pspCommandTail;
766 for (i = 1; i < Argc; i++)
768 if ((int) ((int) p1 - (int) psp->pspCommandTail) +
769 strlen(Argv[i]) > 124)
770 break;
772 for (p2 = Argv[i]; *p2 != '\0'; )
773 *p1++ = *p2++;
775 *p1++ = ' ';
777 *p1++ = '\r';
778 *p1 = '\0';
779 psp->pspCommandTailCount = strlen(psp->pspCommandTail);
781 return s;
784 /**********************************************************************
785 * CreateSelectors
787 SEGDESC *
788 CreateSelectors(struct w_files * wpnt)
790 int fd = wpnt->fd;
791 struct ne_segment_table_entry_s *seg_table = wpnt->seg_table;
792 struct ne_header_s *ne_header = wpnt->ne_header;
793 SEGDESC *selectors, *s, *stmp;
794 unsigned short auto_data_sel;
795 int contents, read_only;
796 int SelectorTableLength;
797 int i;
798 int status;
799 int old_length, file_image_length;
800 int saved_old_length;
803 * Allocate memory for the table to keep track of all selectors.
805 SelectorTableLength = ne_header->n_segment_tab;
806 selectors = malloc(SelectorTableLength * sizeof(*selectors));
807 if (selectors == NULL)
808 return NULL;
811 * Step through the segment table in the exe header.
813 s = selectors;
814 for (i = 0; i < ne_header->n_segment_tab; i++, s++)
817 * Store the flags in our table.
819 s->flags = seg_table[i].seg_flags;
822 * Is there an image for this segment in the file?
824 if (seg_table[i].seg_data_offset == 0)
827 * No image in exe file, let's allocate some memory for it.
829 s->length = seg_table[i].min_alloc;
831 else
834 * Image in file, let's just point to the image in memory.
836 s->length = seg_table[i].min_alloc;
837 file_image_length = seg_table[i].seg_data_length;
838 if (file_image_length == 0) file_image_length = 0x10000;
841 if (s->length == 0)
842 s->length = 0x10000;
843 old_length = s->length;
846 * If this is the automatic data segment, its size must be adjusted.
847 * First we need to check for local heap. Second we nee to see if
848 * this is also the stack segment.
850 if (i + 1 == ne_header->auto_data_seg)
852 s->length += ne_header->local_heap_length;
854 if (i + 1 == ne_header->ss)
856 s->length += ne_header->stack_length;
857 ne_header->sp = s->length;
862 * Is this a DATA or CODE segment?
864 read_only = 0;
865 if (s->flags & NE_SEGFLAGS_DATA)
867 contents = MODIFY_LDT_CONTENTS_DATA;
868 if (s->flags & NE_SEGFLAGS_READONLY)
869 read_only = 1;
871 else
873 contents = MODIFY_LDT_CONTENTS_CODE;
874 if (s->flags & NE_SEGFLAGS_EXECUTEONLY)
875 read_only = 1;
878 stmp = CreateNewSegments(!(s->flags & NE_SEGFLAGS_DATA), read_only,
879 s->length, 1);
880 s->base_addr = stmp->base_addr;
881 s->selector = stmp->selector;
883 if (seg_table[i].seg_data_offset != 0)
886 * Image in file.
888 status = lseek(fd, seg_table[i].seg_data_offset *
889 (1 << ne_header->align_shift_count), SEEK_SET);
890 if(read(fd, s->base_addr, file_image_length) != file_image_length)
891 myerror("Unable to read segment from file");
895 * If this is the automatic data segment, then we must initialize
896 * the local heap.
898 if (i + 1 == ne_header->auto_data_seg)
900 auto_data_sel = s->selector;
901 saved_old_length = old_length;
905 s = selectors;
906 for (i = 0; i < ne_header->n_segment_tab; i++, s++)
908 Segments[s->selector >> 3].owner = auto_data_sel;
909 if (s->selector == auto_data_sel)
910 HEAP_LocalInit(auto_data_sel, s->base_addr + saved_old_length,
911 ne_header->local_heap_length);
914 if(!EnvironmentSelector) {
915 EnvironmentSelector = CreateEnvironment();
916 PSP_Selector = CreatePSP();
917 MakeProcThunks = CreateNewSegments(1, 0, 0x10000, 1);
920 return selectors;
922 #endif /* ifndef WINELIB */