Release 940722
[wine/multimedia.git] / loader / selector.c
blobc2faab80227945cb776fcd519e46f735206a29b5
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
25 #include "dlls.h"
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();
63 extern char *WIN_ProgramName;
64 extern char WindowsPath[256];
66 extern char **Argv;
67 extern int Argc;
68 extern char **environ;
70 /**********************************************************************
71 * FindUnusedSelectors
73 int
74 FindUnusedSelectors(int n_selectors)
76 int i;
77 int n_found;
79 n_found = 0;
80 for (i = LastUsedSelector + 1; i != LastUsedSelector; i++)
82 if (i >= MAX_SELECTORS)
84 n_found = 0;
85 i = FIRST_SELECTOR;
88 if (!SelectorMap[i] && ++n_found == n_selectors)
89 break;
92 if (i == LastUsedSelector)
93 return 0;
95 LastUsedSelector = i;
96 return i - n_selectors + 1;
99 #ifdef HAVE_IPC
100 /**********************************************************************
101 * IPCCopySelector
103 * Created a shared memory copy of a segment:
105 * - at a new selector location (if "new" is a 16-bit value)
106 * - at an arbitrary memory location (if "new" is a 32-bit value)
109 IPCCopySelector(int i_old, unsigned long new, int swap_type)
111 SEGDESC *s_new, *s_old;
112 int i_new;
113 void *base_addr;
115 s_old = &Segments[i_old];
117 if (new & 0xffff0000)
119 /**************************************************************
120 * Let's set the address parameter for no segment.
122 i_new = -1;
123 s_new = NULL;
124 base_addr = (void *) new;
126 else
128 /***************************************************************
129 * We need to fill in the segment descriptor for segment "new".
131 i_new = new;
132 s_new = &Segments[i_new];
134 SelectorMap[i_new] = i_new;
136 s_new->selector = (i_new << 3) | 0x0007;
137 s_new->base_addr = (void *) ((long) s_new->selector << 16);
138 s_new->length = s_old->length;
139 s_new->flags = s_old->flags;
140 s_new->owner = s_old->owner;
141 if (swap_type)
143 if (s_old->type == MODIFY_LDT_CONTENTS_DATA)
144 s_new->type = MODIFY_LDT_CONTENTS_CODE;
145 else
146 s_new->type = MODIFY_LDT_CONTENTS_DATA;
148 else
149 s_new->type = s_old->type;
151 base_addr = s_new->base_addr;
154 /******************************************************************
155 * If we don't have a shared memory key for s_old, then we need
156 * to get one. In this case, we'll also have to copy the data
157 * to protect it.
159 if (s_old->shm_key == 0)
161 s_old->shm_key = shmget(IPC_PRIVATE, s_old->length, 0600);
162 if (s_old->shm_key == 0)
164 if (s_new)
165 memset(s_new, 0, sizeof(*s_new));
166 return -1;
168 if (shmat(s_old->shm_key, base_addr, 0) == NULL)
170 if (s_new)
171 memset(s_new, 0, sizeof(*s_new));
172 shmctl(s_old->shm_key, IPC_RMID, NULL);
173 return -1;
175 memcpy(base_addr, s_old->base_addr, s_old->length);
176 munmap(s_old->base_addr,
177 ((s_old->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
178 shmat(s_old->shm_key, s_old->base_addr, 0);
180 /******************************************************************
181 * If have shared memory key s_old, then just attach the new
182 * address.
184 else
186 if (shmat(s_old->shm_key, base_addr, 0) == NULL)
188 if (s_new)
189 memset(s_new, 0, sizeof(*s_new));
190 return -1;
194 /******************************************************************
195 * If we are creating a new segment, then we also need to update
196 * the LDT to include the new selector. In this return the
197 * new selector.
199 if (s_new)
201 s_new->shm_key = s_old->shm_key;
203 if (set_ldt_entry(i_new, (unsigned long) base_addr,
204 s_old->length - 1, 0, s_new->type, 0, 0) < 0)
206 return -1;
209 return s_new->selector;
211 /******************************************************************
212 * No new segment. So, just return the shared memory key.
214 else
215 return s_old->shm_key;
217 #endif
219 /**********************************************************************
220 * AllocSelector
222 * This is very bad!!! This function is implemented for Windows
223 * compatibility only. Do not call this from the emulation library.
225 WORD AllocSelector(WORD old_selector)
227 SEGDESC *s_new, *s_old;
228 int i_new, i_old;
229 int selector;
231 i_new = FindUnusedSelectors(1);
232 s_new = &Segments[i_new];
234 if (old_selector)
236 i_old = (old_selector >> 3);
237 #ifdef HAVE_IPC
238 selector = IPCCopySelector(i_old, i_new, 0);
239 if (selector < 0)
240 return 0;
241 else
242 return selector;
243 #else
244 s_old = &Segments[i_old];
245 s_new->selector = (i_new << 3) | 0x0007;
246 *s_new = *s_old;
247 SelectorMap[i_new] = SelectorMap[i_old];
249 if (set_ldt_entry(i_new, s_new->base_addr,
250 s_new->length - 1, 0,
251 s_new->type, 0, 0) < 0)
253 return 0;
255 #endif
257 else
259 memset(s_new, 0, sizeof(*s_new));
260 SelectorMap[i_new] = i_new;
263 return (i_new << 3) | 0x0007;
266 /**********************************************************************
267 * PrestoChangoSelector
269 * This is very bad!!! This function is implemented for Windows
270 * compatibility only. Do not call this from the emulation library.
272 unsigned int PrestoChangoSelector(unsigned src_selector, unsigned dst_selector)
274 #ifdef HAVE_IPC
275 SEGDESC *src_s;
276 int src_idx, dst_idx;
278 src_idx = src_selector >> 3;
279 dst_idx = dst_selector >> 3;
281 if (src_idx == dst_idx)
283 src_s = &Segments[src_idx];
285 if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
286 src_s->type = MODIFY_LDT_CONTENTS_CODE;
287 else
288 src_s->type = MODIFY_LDT_CONTENTS_DATA;
290 if (set_ldt_entry(src_idx, (long) src_s->base_addr,
291 src_s->length - 1, 0, src_s->type, 0, 0) < 0)
293 return 0;
296 return src_s->selector;
298 else
300 return IPCCopySelector(src_idx, dst_idx, 1);
302 #else /* HAVE_IPC */
303 SEGDESC *src_s, *dst_s;
304 char *p;
305 int src_idx, dst_idx;
306 int alias_count;
307 int i;
309 src_idx = (SelectorMap[src_selector >> 3]);
310 dst_idx = dst_selector >> 3;
311 src_s = &Segments[src_idx];
312 dst_s = &Segments[dst_idx];
314 alias_count = 0;
315 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
316 if (SelectorMap[i] == src_idx)
317 alias_count++;
319 if (src_s->type == MODIFY_LDT_CONTENTS_DATA
320 || alias_count > 1 || src_idx == dst_idx)
322 *dst_s = *src_s;
324 if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
325 dst_s->type = MODIFY_LDT_CONTENTS_CODE;
326 else
327 dst_s->type = MODIFY_LDT_CONTENTS_DATA;
329 SelectorMap[dst_idx] = SelectorMap[src_idx];
330 if (set_ldt_entry(dst_idx, (long) dst_s->base_addr,
331 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
333 return 0;
336 else
339 * We're changing an unaliased code segment into a data
340 * segment. The SAFEST (but ugliest) way to deal with
341 * this is to map the new segment and copy all the contents.
343 SelectorMap[dst_idx] = dst_idx;
344 *dst_s = *src_s;
345 dst_s->selector = (dst_idx << 3) | 0x0007;
346 dst_s->base_addr = (void *) ((unsigned int) dst_s->selector << 16);
347 dst_s->type = MODIFY_LDT_CONTENTS_DATA;
348 #ifdef DEV_ZERO
349 if (zfile == NULL)
350 zfile = fopen("/dev/zero","r");
351 p = (void *) mmap((char *) dst_s->base_addr,
352 ((dst_s->length + PAGE_SIZE)
353 & ~(PAGE_SIZE - 1)),
354 PROT_EXEC | PROT_READ | PROT_WRITE,
355 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
356 #else
357 p = (void *) mmap((char *) dst_s->base_addr,
358 ((dst_s->length + PAGE_SIZE)
359 & ~(PAGE_SIZE - 1)),
360 PROT_EXEC | PROT_READ | PROT_WRITE,
361 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
362 #endif
363 if (p == NULL)
364 return 0;
366 memcpy((void *) dst_s->base_addr, (void *) src_s->base_addr,
367 dst_s->length);
368 if (set_ldt_entry(src_idx, dst_s->base_addr,
369 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
371 return 0;
373 if (set_ldt_entry(dst_idx, dst_s->base_addr,
374 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
376 return 0;
379 munmap(src_s->base_addr,
380 (src_s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1));
381 SelectorMap[src_idx] = dst_idx;
382 src_s->base_addr = dst_s->base_addr;
385 return dst_s->selector;
386 #endif /* HAVE_IPC */
389 /**********************************************************************
390 * AllocCStoDSAlias
392 WORD AllocDStoCSAlias(WORD ds_selector)
394 unsigned int cs_selector;
396 if (ds_selector == 0)
397 return 0;
399 cs_selector = AllocSelector(0);
400 return PrestoChangoSelector(ds_selector, cs_selector);
403 /**********************************************************************
404 * FreeSelector
406 WORD FreeSelector(WORD sel)
408 SEGDESC *s;
409 int sel_idx;
410 int alias_count;
411 int i;
413 #ifdef HAVE_IPC
414 sel_idx = sel >> 3;
416 if (sel_idx < FIRST_SELECTOR || sel_idx >= MAX_SELECTORS)
417 return 0;
419 s = &Segments[sel_idx];
420 if (s->shm_key == 0)
422 munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
423 memset(s, 0, sizeof(*s));
424 SelectorMap[sel_idx] = 0;
426 else
428 shmdt(s->base_addr);
430 alias_count = 0;
431 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
432 if (SelectorMap[i] && Segments[i].shm_key == s->shm_key)
433 alias_count++;
435 if (alias_count == 1)
436 shmctl(s->shm_key, IPC_RMID, NULL);
438 memset(s, 0, sizeof(*s));
439 SelectorMap[sel_idx] = 0;
442 #else /* HAVE_IPC */
443 sel_idx = SelectorMap[sel >> 3];
445 if (sel_idx < FIRST_SELECTOR || sel_idx >= MAX_SELECTORS)
446 return 0;
448 if (sel_idx != (sel >> 3))
450 SelectorMap[sel >> 3] = 0;
451 return 0;
454 alias_count = 0;
455 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
456 if (SelectorMap[i] == sel_idx)
457 alias_count++;
459 if (alias_count == 1)
461 s = &Segments[sel_idx];
462 munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
463 memset(s, 0, sizeof(*s));
464 SelectorMap[sel >> 3] = 0;
466 #endif /* HAVE_IPC */
468 return 0;
471 /**********************************************************************
472 * CreateNewSegments
474 SEGDESC *
475 CreateNewSegments(int code_flag, int read_only, int length, int n_segments)
477 SEGDESC *s, *first_segment;
478 int contents;
479 int i, last_i;
481 i = FindUnusedSelectors(n_segments);
483 #ifdef DEBUG_SELECTORS
484 fprintf(stderr,
485 "Using %d segments starting at index %d.\n", n_segments, i);
486 #endif
489 * Fill in selector info.
491 first_segment = s = &Segments[i];
492 for (last_i = i + n_segments; i < last_i; i++, s++)
494 if (code_flag)
496 contents = MODIFY_LDT_CONTENTS_CODE;
497 s->flags = 0;
499 else
501 contents = MODIFY_LDT_CONTENTS_DATA;
502 s->flags = NE_SEGFLAGS_DATA;
505 s->selector = (i << 3) | 0x0007;
506 s->length = length;
507 #ifdef DEV_ZERO
508 if (zfile == NULL)
509 zfile = fopen("/dev/zero","r");
510 s->base_addr = (void *) mmap((char *) (s->selector << 16),
511 ((s->length + PAGE_SIZE - 1) &
512 ~(PAGE_SIZE - 1)),
513 PROT_EXEC | PROT_READ | PROT_WRITE,
514 MAP_FIXED | MAP_PRIVATE,
515 fileno(zfile), 0);
516 #else
517 s->base_addr = (void *) mmap((char *) (s->selector << 16),
518 ((s->length + PAGE_SIZE - 1) &
519 ~(PAGE_SIZE - 1)),
520 PROT_EXEC | PROT_READ | PROT_WRITE,
521 MAP_FIXED | MAP_PRIVATE | MAP_ANON,
522 -1, 0);
523 #endif
525 if (set_ldt_entry(i, (unsigned long) s->base_addr,
526 (s->length - 1) & 0xffff, 0,
527 contents, read_only, 0) < 0)
529 memset(s, 0, sizeof(*s));
530 return NULL;
533 SelectorMap[i] = (unsigned short) i;
534 s->type = contents;
537 return first_segment;
540 /**********************************************************************
541 * GetNextSegment
543 SEGDESC *
544 GetNextSegment(unsigned int flags, unsigned int limit)
546 return CreateNewSegments(0, 0, limit, 1);
549 /**********************************************************************
550 * GetEntryPointFromOrdinal
552 union lookup{
553 struct entry_tab_header_s *eth;
554 struct entry_tab_movable_s *etm;
555 struct entry_tab_fixed_s *etf;
556 char * cpnt;
559 unsigned int GetEntryDLLName(char * dll_name, char * function, int * sel,
560 int * addr)
562 struct dll_table_entry_s *dll_table;
563 struct w_files * wpnt;
564 char * cpnt;
565 int ordinal, j, len;
567 dll_table = FindDLLTable(dll_name);
569 if(dll_table) {
570 ordinal = FindOrdinalFromName(dll_table, function);
571 *sel = dll_table[ordinal].selector;
572 *addr = (unsigned int) dll_table[ordinal].address;
573 #ifdef WINESTAT
574 dll_table[ordinal].used++;
575 #endif
576 return 0;
579 /* We need a means of determining the ordinal for the function. */
580 /* Not a builtin symbol, look to see what the file has for us */
581 for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
582 if(strcasecmp(wpnt->name, dll_name)) continue;
583 cpnt = wpnt->nrname_table;
584 while(1==1){
585 if( ((int) cpnt) - ((int)wpnt->nrname_table) >
586 wpnt->ne_header->nrname_tab_length) return 1;
587 len = *cpnt++;
588 if(strncmp(cpnt, function, len) == 0) break;
589 cpnt += len + 2;
591 ordinal = *((unsigned short *) (cpnt + len));
592 j = GetEntryPointFromOrdinal(wpnt, ordinal);
593 *addr = j & 0xffff;
594 j = j >> 16;
595 *sel = j;
596 return 0;
598 return 1;
601 unsigned int GetEntryDLLOrdinal(char * dll_name, int ordinal, int * sel,
602 int * addr)
604 struct dll_table_entry_s *dll_table;
605 struct w_files * wpnt;
606 int j;
608 dll_table = FindDLLTable(dll_name);
610 if(dll_table) {
611 *sel = dll_table[ordinal].selector;
612 *addr = (unsigned int) dll_table[ordinal].address;
613 #ifdef WINESTAT
614 dll_table[ordinal].used++;
615 #endif
616 return 0;
619 /* Not a builtin symbol, look to see what the file has for us */
620 for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
621 if(strcasecmp(wpnt->name, dll_name)) continue;
622 j = GetEntryPointFromOrdinal(wpnt, ordinal);
623 *addr = j & 0xffff;
624 j = j >> 16;
625 *sel = j;
626 return 0;
628 return 1;
631 unsigned int
632 GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal)
634 int fd = wpnt->fd;
635 struct mz_header_s *mz_header = wpnt->mz_header;
636 struct ne_header_s *ne_header = wpnt->ne_header;
639 union lookup entry_tab_pointer;
640 struct entry_tab_header_s *eth;
641 struct entry_tab_movable_s *etm;
642 struct entry_tab_fixed_s *etf;
643 int current_ordinal;
644 int i;
647 entry_tab_pointer.cpnt = wpnt->lookup_table;
649 * Let's walk through the table until we get to our entry.
651 current_ordinal = 1;
652 while (1)
655 * Read header for this bundle.
657 eth = entry_tab_pointer.eth++;
659 if (eth->n_entries == 0)
660 return 0xffffffff; /* Yikes - we went off the end of the table */
662 if (eth->seg_number == 0)
664 current_ordinal += eth->n_entries;
665 if(current_ordinal > ordinal) return 0;
666 continue;
670 * Read each of the bundle entries.
672 for (i = 0; i < eth->n_entries; i++, current_ordinal++)
674 if (eth->seg_number >= 0xfe)
676 etm = entry_tab_pointer.etm++;
678 if (current_ordinal == ordinal)
680 return ((unsigned int)
681 (wpnt->selector_table[etm->seg_number - 1].base_addr +
682 etm->offset));
685 else
687 etf = entry_tab_pointer.etf++;
689 if (current_ordinal == ordinal)
691 return ((unsigned int)
692 (wpnt->selector_table[eth->seg_number - 1].base_addr +
693 (int) etf->offset[0] +
694 ((int) etf->offset[1] << 8)));
701 /**********************************************************************
703 void
704 FixupFunctionPrologs(struct w_files * wpnt)
706 struct mz_header_s *mz_header = wpnt->mz_header;
707 struct ne_header_s *ne_header = wpnt->ne_header;
708 union lookup entry_tab_pointer;
709 struct entry_tab_header_s *eth;
710 struct entry_tab_movable_s *etm;
711 struct entry_tab_fixed_s *etf;
712 unsigned char *fixup_ptr;
713 int i;
715 if (!(ne_header->format_flags & 0x0001))
716 return;
718 entry_tab_pointer.cpnt = wpnt->lookup_table;
720 * Let's walk through the table and fixup prologs as we go.
722 while (1)
724 /* Get bundle header */
725 eth = entry_tab_pointer.eth++;
727 /* Check for end of table */
728 if (eth->n_entries == 0)
729 return;
731 /* Check for empty bundle */
732 if (eth->seg_number == 0)
733 continue;
735 /* Examine each bundle */
736 for (i = 0; i < eth->n_entries; i++)
738 /* Moveable segment */
739 if (eth->seg_number >= 0xfe)
741 etm = entry_tab_pointer.etm++;
742 fixup_ptr = (wpnt->selector_table[etm->seg_number-1].base_addr
743 + etm->offset);
745 else
747 etf = entry_tab_pointer.etf++;
748 fixup_ptr = (wpnt->selector_table[eth->seg_number-1].base_addr
749 + (int) etf->offset[0]
750 + ((int) etf->offset[1] << 8));
754 /* Verify the signature */
755 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
756 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
757 && fixup_ptr[2] == 0x90)
759 fixup_ptr[0] = 0xb8; /* MOV AX, */
760 fixup_ptr[1] = wpnt->hinstance;
761 fixup_ptr[2] = (wpnt->hinstance >> 8);
768 /**********************************************************************
769 * GetDOSEnvironment
771 LPSTR GetDOSEnvironment(void)
773 return (LPSTR) EnvironmentSelector->base_addr;
776 /**********************************************************************
777 * CreateEnvironment
779 static SEGDESC *
780 CreateEnvironment(void)
782 char **e;
783 char *p;
784 unsigned short *w;
785 SEGDESC * s;
787 s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
788 if (s == NULL)
789 return NULL;
792 * Fill environment with Windows path, the Unix environment,
793 * and program name.
795 p = (char *) s->base_addr;
796 strcpy(p, "PATH=");
797 strcat(p, WindowsPath);
798 p += strlen(p) + 1;
800 for (e = environ; *e; e++)
802 if (strncasecmp(*e, "path", 4))
804 strcpy(p, *e);
805 p += strlen(p) + 1;
809 *p++ = '\0';
810 w = (unsigned short *) p;
811 *w = strlen(WIN_ProgramName);
812 strcpy(p + 2, WIN_ProgramName);
815 * Display environment
817 fprintf(stderr, "Environment at %08.8x\n", s->base_addr);
818 for (p = s->base_addr; *p; p += strlen(p) + 1)
819 fprintf(stderr, " %s\n", p);
820 p += 3;
821 fprintf(stderr, " Program: %s\n", p);
823 return s;
826 /**********************************************************************
828 WORD GetCurrentPDB()
830 return PSPSelector;
833 /**********************************************************************
834 * CreatePSP
836 static SEGDESC *
837 CreatePSP(void)
839 struct dos_psp_s *psp;
840 unsigned short *usp;
841 SEGDESC * s;
842 char *p1, *p2;
843 int i;
845 s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
848 * Fill PSP
850 PSPSelector = s->selector;
851 psp = (struct dos_psp_s *) s->base_addr;
852 psp->pspInt20 = 0x20cd;
853 psp->pspDispatcher[0] = 0x9a;
854 usp = (unsigned short *) &psp->pspDispatcher[1];
855 *usp = (unsigned short) KERNEL_Ordinal_102;
856 *(usp + 1) = UTEXTSEL;
857 psp->pspTerminateVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
858 psp->pspTerminateVector[1] = UTEXTSEL;
859 psp->pspControlCVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
860 psp->pspControlCVector[1] = UTEXTSEL;
861 psp->pspCritErrorVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
862 psp->pspCritErrorVector[1] = UTEXTSEL;
863 psp->pspEnvironment = EnvironmentSelector->selector;
865 p1 = psp->pspCommandTail;
866 for (i = 1; i < Argc; i++)
868 if ((int) ((int) p1 - (int) psp->pspCommandTail) +
869 strlen(Argv[i]) > 124)
870 break;
872 if (i != 1)
873 *p1++ = ' ';
875 for (p2 = Argv[i]; *p2 != '\0'; )
876 *p1++ = *p2++;
879 *p1 = '\0';
880 psp->pspCommandTailCount = strlen(psp->pspCommandTail);
882 return s;
885 /**********************************************************************
886 * CreateSelectors
888 SEGDESC *
889 CreateSelectors(struct w_files * wpnt)
891 int fd = wpnt->fd;
892 struct ne_segment_table_entry_s *seg_table = wpnt->seg_table;
893 struct ne_header_s *ne_header = wpnt->ne_header;
894 SEGDESC *selectors, *s, *stmp;
895 unsigned short auto_data_sel;
896 int contents, read_only;
897 int SelectorTableLength;
898 int i;
899 int status;
900 int old_length, file_image_length;
901 int saved_old_length;
904 * Allocate memory for the table to keep track of all selectors.
906 SelectorTableLength = ne_header->n_segment_tab;
907 selectors = malloc(SelectorTableLength * sizeof(*selectors));
908 if (selectors == NULL)
909 return NULL;
912 * Step through the segment table in the exe header.
914 s = selectors;
915 for (i = 0; i < ne_header->n_segment_tab; i++, s++)
918 * Store the flags in our table.
920 s->flags = seg_table[i].seg_flags;
923 * Is there an image for this segment in the file?
925 if (seg_table[i].seg_data_offset == 0)
928 * No image in exe file, let's allocate some memory for it.
930 s->length = seg_table[i].min_alloc;
932 else
935 * Image in file, let's just point to the image in memory.
937 s->length = seg_table[i].min_alloc;
938 file_image_length = seg_table[i].seg_data_length;
939 if (file_image_length == 0) file_image_length = 0x10000;
942 if (s->length == 0)
943 s->length = 0x10000;
944 old_length = s->length;
947 * If this is the automatic data segment, its size must be adjusted.
948 * First we need to check for local heap. Second we nee to see if
949 * this is also the stack segment.
951 if (i + 1 == ne_header->auto_data_seg || i + 1 == ne_header->ss)
953 s->length = 0x10000;
954 ne_header->sp = s->length - 2;
958 * Is this a DATA or CODE segment?
960 read_only = 0;
961 if (s->flags & NE_SEGFLAGS_DATA)
963 contents = MODIFY_LDT_CONTENTS_DATA;
964 if (s->flags & NE_SEGFLAGS_READONLY)
965 read_only = 1;
967 else
969 contents = MODIFY_LDT_CONTENTS_CODE;
970 if (s->flags & NE_SEGFLAGS_EXECUTEONLY)
971 read_only = 1;
974 #if 0
975 stmp = CreateNewSegments(!(s->flags & NE_SEGFLAGS_DATA), read_only,
976 s->length, 1);
977 s->base_addr = stmp->base_addr;
978 s->selector = stmp->selector;
979 #endif
980 s->selector = GlobalAlloc(GMEM_FIXED, s->length);
981 if (s->selector == 0)
982 myerror("CreateSelectors: GlobalAlloc() failed");
984 s->base_addr = (void *) ((LONG) s->selector << 16);
985 if (!(s->flags & NE_SEGFLAGS_DATA))
986 PrestoChangoSelector(s->selector, s->selector);
987 else
988 memset(s->base_addr, 0, s->length);
990 if (seg_table[i].seg_data_offset != 0)
993 * Image in file.
995 status = lseek(fd, seg_table[i].seg_data_offset *
996 (1 << ne_header->align_shift_count), SEEK_SET);
997 if(read(fd, s->base_addr, file_image_length) != file_image_length)
998 myerror("Unable to read segment from file");
1002 * If this is the automatic data segment, then we must initialize
1003 * the local heap.
1005 if (i + 1 == ne_header->auto_data_seg)
1007 auto_data_sel = s->selector;
1008 saved_old_length = old_length;
1012 s = selectors;
1013 for (i = 0; i < ne_header->n_segment_tab; i++, s++)
1015 Segments[s->selector >> 3].owner = auto_data_sel;
1016 if (s->selector == auto_data_sel)
1017 HEAP_LocalInit(auto_data_sel, s->base_addr + saved_old_length,
1018 0x10000 - 2 - saved_old_length
1019 - ne_header->stack_length);
1022 if(!EnvironmentSelector) {
1023 EnvironmentSelector = CreateEnvironment();
1024 PSP_Selector = CreatePSP();
1025 MakeProcThunks = CreateNewSegments(1, 0, 0x10000, 1);
1028 return selectors;
1031 /***********************************************************************
1032 * GetSelectorBase (KERNEL.186)
1034 DWORD GetSelectorBase(WORD wSelector)
1036 fprintf(stderr, "GetSelectorBase(selector %4X) stub!\n", wSelector);
1039 /***********************************************************************
1040 * SetSelectorBase (KERNEL.187)
1042 void SetSelectorBase(WORD wSelector, DWORD dwBase)
1044 fprintf(stderr, "SetSelectorBase(selector %4X, base %8X) stub!\n",
1045 wSelector, dwBase);
1048 /***********************************************************************
1049 * GetSelectorLimit (KERNEL.188)
1051 DWORD GetSelectorLimit(WORD wSelector)
1053 fprintf(stderr, "GetSelectorLimit(selector %4X) stub!\n", wSelector);
1055 return 0xffff;
1058 /***********************************************************************
1059 * SetSelectorLimit (KERNEL.189)
1061 void SetSelectorLimit(WORD wSelector, DWORD dwLimit)
1063 fprintf(stderr, "SetSelectorLimit(selector %4X, base %8X) stub!\n",
1064 wSelector, dwLimit);
1067 #endif /* ifndef WINELIB */