Release 940912
[wine/multimedia.git] / loader / selector.c
blob03711aa446cd419f9e69e136d9a027314f309b77
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 == -1)
161 s_old->shm_key = shmget(IPC_PRIVATE, s_old->length, IPC_CREAT);
162 if (s_old->shm_key == -1)
164 if (s_new) {
165 memset(s_new, 0, sizeof(*s_new));
166 s_new->shm_key = -1;
168 return -1;
170 if (shmat(s_old->shm_key, base_addr, 0) == (char *) -1)
172 if (s_new) {
173 memset(s_new, 0, sizeof(*s_new));
174 s_new->shm_key = -1;
176 shmctl(s_old->shm_key, IPC_RMID, NULL);
177 return -1;
179 memcpy(base_addr, s_old->base_addr, s_old->length);
180 munmap(s_old->base_addr,
181 ((s_old->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
182 shmat(s_old->shm_key, s_old->base_addr, 0);
184 /******************************************************************
185 * If have shared memory key s_old, then just attach the new
186 * address.
188 else
190 if (shmat(s_old->shm_key, base_addr, 0) == (char *) -1)
192 if (s_new) {
193 memset(s_new, 0, sizeof(*s_new));
194 s_new->shm_key = -1;
196 return -1;
200 /******************************************************************
201 * If we are creating a new segment, then we also need to update
202 * the LDT to include the new selector. In this return the
203 * new selector.
205 if (s_new)
207 s_new->shm_key = s_old->shm_key;
209 if (set_ldt_entry(i_new, (unsigned long) base_addr,
210 s_old->length - 1, 0, s_new->type, 0, 0) < 0)
212 return -1;
215 return s_new->selector;
217 /******************************************************************
218 * No new segment. So, just return the shared memory key.
220 else
221 return s_old->shm_key;
223 #endif
225 /**********************************************************************
226 * AllocSelector
228 * This is very bad!!! This function is implemented for Windows
229 * compatibility only. Do not call this from the emulation library.
231 WORD AllocSelector(WORD old_selector)
233 SEGDESC *s_new, *s_old;
234 int i_new, i_old;
235 int selector;
237 i_new = FindUnusedSelectors(1);
238 s_new = &Segments[i_new];
240 if (old_selector)
242 i_old = (old_selector >> 3);
243 #ifdef HAVE_IPC
244 selector = IPCCopySelector(i_old, i_new, 0);
245 if (selector < 0)
246 return 0;
247 else
248 return selector;
249 #else
250 s_old = &Segments[i_old];
251 s_new->selector = (i_new << 3) | 0x0007;
252 *s_new = *s_old;
253 SelectorMap[i_new] = SelectorMap[i_old];
255 if (set_ldt_entry(i_new, s_new->base_addr,
256 s_new->length - 1, 0,
257 s_new->type, 0, 0) < 0)
259 return 0;
261 #endif
263 else
265 memset(s_new, 0, sizeof(*s_new));
266 #ifdef HAVE_IPC
267 s_new->shm_key = -1;
268 #endif
269 SelectorMap[i_new] = i_new;
272 return (i_new << 3) | 0x0007;
275 /**********************************************************************
276 * PrestoChangoSelector
278 * This is very bad!!! This function is implemented for Windows
279 * compatibility only. Do not call this from the emulation library.
281 unsigned int PrestoChangoSelector(unsigned src_selector, unsigned dst_selector)
283 #ifdef HAVE_IPC
284 SEGDESC *src_s;
285 int src_idx, dst_idx;
287 src_idx = src_selector >> 3;
288 dst_idx = dst_selector >> 3;
290 if (src_idx == dst_idx)
292 src_s = &Segments[src_idx];
294 if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
295 src_s->type = MODIFY_LDT_CONTENTS_CODE;
296 else
297 src_s->type = MODIFY_LDT_CONTENTS_DATA;
299 if (set_ldt_entry(src_idx, (long) src_s->base_addr,
300 src_s->length - 1, 0, src_s->type, 0, 0) < 0)
302 return 0;
305 return src_s->selector;
307 else
309 return IPCCopySelector(src_idx, dst_idx, 1);
311 #else /* HAVE_IPC */
312 SEGDESC *src_s, *dst_s;
313 char *p;
314 int src_idx, dst_idx;
315 int alias_count;
316 int i;
318 src_idx = (SelectorMap[src_selector >> 3]);
319 dst_idx = dst_selector >> 3;
320 src_s = &Segments[src_idx];
321 dst_s = &Segments[dst_idx];
323 alias_count = 0;
324 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
325 if (SelectorMap[i] == src_idx)
326 alias_count++;
328 if (src_s->type == MODIFY_LDT_CONTENTS_DATA
329 || alias_count > 1 || src_idx == dst_idx)
331 *dst_s = *src_s;
333 if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
334 dst_s->type = MODIFY_LDT_CONTENTS_CODE;
335 else
336 dst_s->type = MODIFY_LDT_CONTENTS_DATA;
338 SelectorMap[dst_idx] = SelectorMap[src_idx];
339 if (set_ldt_entry(dst_idx, (long) dst_s->base_addr,
340 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
342 return 0;
345 else
348 * We're changing an unaliased code segment into a data
349 * segment. The SAFEST (but ugliest) way to deal with
350 * this is to map the new segment and copy all the contents.
352 SelectorMap[dst_idx] = dst_idx;
353 *dst_s = *src_s;
354 dst_s->selector = (dst_idx << 3) | 0x0007;
355 dst_s->base_addr = (void *) ((unsigned int) dst_s->selector << 16);
356 dst_s->type = MODIFY_LDT_CONTENTS_DATA;
357 #ifdef DEV_ZERO
358 if (zfile == NULL)
359 zfile = fopen("/dev/zero","r");
360 p = (void *) mmap((char *) dst_s->base_addr,
361 ((dst_s->length + PAGE_SIZE)
362 & ~(PAGE_SIZE - 1)),
363 PROT_EXEC | PROT_READ | PROT_WRITE,
364 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
365 #else
366 p = (void *) mmap((char *) dst_s->base_addr,
367 ((dst_s->length + PAGE_SIZE)
368 & ~(PAGE_SIZE - 1)),
369 PROT_EXEC | PROT_READ | PROT_WRITE,
370 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
371 #endif
372 if (p == NULL)
373 return 0;
375 memcpy((void *) dst_s->base_addr, (void *) src_s->base_addr,
376 dst_s->length);
377 if (set_ldt_entry(src_idx, dst_s->base_addr,
378 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
380 return 0;
382 if (set_ldt_entry(dst_idx, dst_s->base_addr,
383 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
385 return 0;
388 munmap(src_s->base_addr,
389 (src_s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1));
390 SelectorMap[src_idx] = dst_idx;
391 src_s->base_addr = dst_s->base_addr;
394 return dst_s->selector;
395 #endif /* HAVE_IPC */
398 /**********************************************************************
399 * AllocCStoDSAlias
401 WORD AllocDStoCSAlias(WORD ds_selector)
403 unsigned int cs_selector;
405 if (ds_selector == 0)
406 return 0;
408 cs_selector = AllocSelector(0);
409 return PrestoChangoSelector(ds_selector, cs_selector);
412 /**********************************************************************
413 * CleanupSelectors
416 void CleanupSelectors(void)
418 int sel_idx;
420 for (sel_idx = FIRST_SELECTOR; sel_idx < MAX_SELECTORS; sel_idx++)
421 if (SelectorMap[sel_idx])
422 FreeSelector((sel_idx << 3) | 7);
425 /**********************************************************************
426 * FreeSelector
428 WORD FreeSelector(WORD sel)
430 SEGDESC *s;
431 int sel_idx;
432 int alias_count;
433 int i;
435 #ifdef HAVE_IPC
436 sel_idx = sel >> 3;
438 if (sel_idx < FIRST_SELECTOR || sel_idx >= MAX_SELECTORS)
439 return 0;
441 s = &Segments[sel_idx];
442 if (s->shm_key == -1)
444 munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
445 memset(s, 0, sizeof(*s));
446 s->shm_key = -1;
447 SelectorMap[sel_idx] = 0;
449 else
451 shmdt(s->base_addr);
453 alias_count = 0;
454 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
455 if (SelectorMap[i] && Segments[i].shm_key == s->shm_key)
456 alias_count++;
458 if (alias_count == 1)
459 shmctl(s->shm_key, IPC_RMID, NULL);
461 memset(s, 0, sizeof(*s));
462 s->shm_key = -1;
463 SelectorMap[sel_idx] = 0;
466 #else /* HAVE_IPC */
467 sel_idx = SelectorMap[sel >> 3];
469 if (sel_idx < FIRST_SELECTOR || sel_idx >= MAX_SELECTORS)
470 return 0;
472 if (sel_idx != (sel >> 3))
474 SelectorMap[sel >> 3] = 0;
475 return 0;
478 alias_count = 0;
479 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
480 if (SelectorMap[i] == sel_idx)
481 alias_count++;
483 if (alias_count == 1)
485 s = &Segments[sel_idx];
486 munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
487 memset(s, 0, sizeof(*s));
488 SelectorMap[sel >> 3] = 0;
490 #endif /* HAVE_IPC */
492 return 0;
495 /**********************************************************************
496 * CreateNewSegments
498 SEGDESC *
499 CreateNewSegments(int code_flag, int read_only, int length, int n_segments)
501 SEGDESC *s, *first_segment;
502 int contents;
503 int i, last_i;
505 i = FindUnusedSelectors(n_segments);
507 #ifdef DEBUG_SELECTORS
508 fprintf(stderr,
509 "Using %d segments starting at index %d.\n", n_segments, i);
510 #endif
513 * Fill in selector info.
515 first_segment = s = &Segments[i];
516 for (last_i = i + n_segments; i < last_i; i++, s++)
518 if (code_flag)
520 contents = MODIFY_LDT_CONTENTS_CODE;
521 s->flags = 0;
523 else
525 contents = MODIFY_LDT_CONTENTS_DATA;
526 s->flags = NE_SEGFLAGS_DATA;
529 s->selector = (i << 3) | 0x0007;
530 s->length = length;
531 #ifdef DEV_ZERO
532 if (zfile == NULL)
533 zfile = fopen("/dev/zero","r");
534 s->base_addr = (void *) mmap((char *) (s->selector << 16),
535 ((s->length + PAGE_SIZE - 1) &
536 ~(PAGE_SIZE - 1)),
537 PROT_EXEC | PROT_READ | PROT_WRITE,
538 MAP_FIXED | MAP_PRIVATE,
539 fileno(zfile), 0);
540 #else
541 s->base_addr = (void *) mmap((char *) (s->selector << 16),
542 ((s->length + PAGE_SIZE - 1) &
543 ~(PAGE_SIZE - 1)),
544 PROT_EXEC | PROT_READ | PROT_WRITE,
545 MAP_FIXED | MAP_PRIVATE | MAP_ANON,
546 -1, 0);
547 #endif
548 #ifdef HAVE_IPC
549 s->shm_key = -1;
550 #endif
551 if (set_ldt_entry(i, (unsigned long) s->base_addr,
552 (s->length - 1) & 0xffff, 0,
553 contents, read_only, 0) < 0)
555 memset(s, 0, sizeof(*s));
556 #ifdef HAVE_IPC
557 s->shm_key = -1;
558 #endif
559 return NULL;
562 SelectorMap[i] = (unsigned short) i;
563 s->type = contents;
566 return first_segment;
569 /**********************************************************************
570 * GetNextSegment
572 SEGDESC *
573 GetNextSegment(unsigned int flags, unsigned int limit)
575 return CreateNewSegments(0, 0, limit, 1);
578 /**********************************************************************
579 * GetEntryPointFromOrdinal
581 union lookup{
582 struct entry_tab_header_s *eth;
583 struct entry_tab_movable_s *etm;
584 struct entry_tab_fixed_s *etf;
585 char * cpnt;
588 unsigned int GetEntryDLLName(char * dll_name, char * function, int * sel,
589 int * addr)
591 struct dll_table_entry_s *dll_table;
592 struct w_files * wpnt;
593 char * cpnt;
594 int ordinal, j, len;
596 dll_table = FindDLLTable(dll_name);
598 if(dll_table) {
599 ordinal = FindOrdinalFromName(dll_table, function);
600 *sel = dll_table[ordinal].selector;
601 *addr = (unsigned int) dll_table[ordinal].address;
602 #ifdef WINESTAT
603 dll_table[ordinal].used++;
604 #endif
605 return 0;
608 /* We need a means of determining the ordinal for the function. */
609 /* Not a builtin symbol, look to see what the file has for us */
610 for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
611 if(strcasecmp(wpnt->name, dll_name)) continue;
612 cpnt = wpnt->nrname_table;
613 while(1==1){
614 if( ((int) cpnt) - ((int)wpnt->nrname_table) >
615 wpnt->ne_header->nrname_tab_length) return 1;
616 len = *cpnt++;
617 if(strncmp(cpnt, function, len) == 0) break;
618 cpnt += len + 2;
620 ordinal = *((unsigned short *) (cpnt + len));
621 j = GetEntryPointFromOrdinal(wpnt, ordinal);
622 *addr = j & 0xffff;
623 j = j >> 16;
624 *sel = j;
625 return 0;
627 return 1;
630 unsigned int GetEntryDLLOrdinal(char * dll_name, int ordinal, int * sel,
631 int * addr)
633 struct dll_table_entry_s *dll_table;
634 struct w_files * wpnt;
635 int j;
637 dll_table = FindDLLTable(dll_name);
639 if(dll_table) {
640 *sel = dll_table[ordinal].selector;
641 *addr = (unsigned int) dll_table[ordinal].address;
642 #ifdef WINESTAT
643 dll_table[ordinal].used++;
644 #endif
645 return 0;
648 /* Not a builtin symbol, look to see what the file has for us */
649 for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
650 if(strcasecmp(wpnt->name, dll_name)) continue;
651 j = GetEntryPointFromOrdinal(wpnt, ordinal);
652 *addr = j & 0xffff;
653 j = j >> 16;
654 *sel = j;
655 return 0;
657 return 1;
660 unsigned int
661 GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal)
663 int fd = wpnt->fd;
664 struct mz_header_s *mz_header = wpnt->mz_header;
665 struct ne_header_s *ne_header = wpnt->ne_header;
668 union lookup entry_tab_pointer;
669 struct entry_tab_header_s *eth;
670 struct entry_tab_movable_s *etm;
671 struct entry_tab_fixed_s *etf;
672 int current_ordinal;
673 int i;
676 entry_tab_pointer.cpnt = wpnt->lookup_table;
678 * Let's walk through the table until we get to our entry.
680 current_ordinal = 1;
681 while (1)
684 * Read header for this bundle.
686 eth = entry_tab_pointer.eth++;
688 if (eth->n_entries == 0)
689 return 0xffffffff; /* Yikes - we went off the end of the table */
691 if (eth->seg_number == 0)
693 current_ordinal += eth->n_entries;
694 if(current_ordinal > ordinal) return 0;
695 continue;
699 * Read each of the bundle entries.
701 for (i = 0; i < eth->n_entries; i++, current_ordinal++)
703 if (eth->seg_number >= 0xfe)
705 etm = entry_tab_pointer.etm++;
707 if (current_ordinal == ordinal)
709 return ((unsigned int)
710 (wpnt->selector_table[etm->seg_number - 1].base_addr +
711 etm->offset));
714 else
716 etf = entry_tab_pointer.etf++;
718 if (current_ordinal == ordinal)
720 return ((unsigned int)
721 (wpnt->selector_table[eth->seg_number - 1].base_addr +
722 (int) etf->offset[0] +
723 ((int) etf->offset[1] << 8)));
730 /**********************************************************************
732 void
733 FixupFunctionPrologs(struct w_files * wpnt)
735 struct mz_header_s *mz_header = wpnt->mz_header;
736 struct ne_header_s *ne_header = wpnt->ne_header;
737 union lookup entry_tab_pointer;
738 struct entry_tab_header_s *eth;
739 struct entry_tab_movable_s *etm;
740 struct entry_tab_fixed_s *etf;
741 unsigned char *fixup_ptr;
742 int i;
744 if (!(ne_header->format_flags & 0x0001))
745 return;
747 entry_tab_pointer.cpnt = wpnt->lookup_table;
749 * Let's walk through the table and fixup prologs as we go.
751 while (1)
753 /* Get bundle header */
754 eth = entry_tab_pointer.eth++;
756 /* Check for end of table */
757 if (eth->n_entries == 0)
758 return;
760 /* Check for empty bundle */
761 if (eth->seg_number == 0)
762 continue;
764 /* Examine each bundle */
765 for (i = 0; i < eth->n_entries; i++)
767 /* Moveable segment */
768 if (eth->seg_number >= 0xfe)
770 etm = entry_tab_pointer.etm++;
771 fixup_ptr = (wpnt->selector_table[etm->seg_number-1].base_addr
772 + etm->offset);
774 else
776 etf = entry_tab_pointer.etf++;
777 fixup_ptr = (wpnt->selector_table[eth->seg_number-1].base_addr
778 + (int) etf->offset[0]
779 + ((int) etf->offset[1] << 8));
783 /* Verify the signature */
784 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
785 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
786 && fixup_ptr[2] == 0x90)
788 fixup_ptr[0] = 0xb8; /* MOV AX, */
789 fixup_ptr[1] = wpnt->hinstance;
790 fixup_ptr[2] = (wpnt->hinstance >> 8);
797 /**********************************************************************
798 * GetDOSEnvironment
800 LPSTR GetDOSEnvironment(void)
802 return (LPSTR) EnvironmentSelector->base_addr;
805 /**********************************************************************
806 * CreateEnvironment
808 static SEGDESC *
809 CreateEnvironment(void)
811 char **e;
812 char *p;
813 unsigned short *w;
814 SEGDESC * s;
816 s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
817 if (s == NULL)
818 return NULL;
821 * Fill environment with Windows path, the Unix environment,
822 * and program name.
824 p = (char *) s->base_addr;
825 strcpy(p, "PATH=");
826 strcat(p, WindowsPath);
827 p += strlen(p) + 1;
829 for (e = environ; *e; e++)
831 if (strncasecmp(*e, "path", 4))
833 strcpy(p, *e);
834 p += strlen(p) + 1;
838 *p++ = '\0';
839 w = (unsigned short *) p;
840 *w = strlen(WIN_ProgramName);
841 strcpy(p + 2, WIN_ProgramName);
844 * Display environment
846 fprintf(stderr, "Environment at %08.8x\n", s->base_addr);
847 for (p = s->base_addr; *p; p += strlen(p) + 1)
848 fprintf(stderr, " %s\n", p);
849 p += 3;
850 fprintf(stderr, " Program: %s\n", p);
852 return s;
855 /**********************************************************************
857 WORD GetCurrentPDB()
859 return PSPSelector;
862 /**********************************************************************
863 * CreatePSP
865 static SEGDESC *
866 CreatePSP(void)
868 struct dos_psp_s *psp;
869 unsigned short *usp;
870 SEGDESC * s;
871 char *p1, *p2;
872 int i;
874 s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
877 * Fill PSP
879 PSPSelector = s->selector;
880 psp = (struct dos_psp_s *) s->base_addr;
881 psp->pspInt20 = 0x20cd;
882 psp->pspDispatcher[0] = 0x9a;
883 usp = (unsigned short *) &psp->pspDispatcher[1];
884 *usp = (unsigned short) KERNEL_Ordinal_102;
885 *(usp + 1) = UTEXTSEL;
886 psp->pspTerminateVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
887 psp->pspTerminateVector[1] = UTEXTSEL;
888 psp->pspControlCVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
889 psp->pspControlCVector[1] = UTEXTSEL;
890 psp->pspCritErrorVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
891 psp->pspCritErrorVector[1] = UTEXTSEL;
892 psp->pspEnvironment = EnvironmentSelector->selector;
894 p1 = psp->pspCommandTail;
895 for (i = 1; i < Argc; i++)
897 if ((int) ((int) p1 - (int) psp->pspCommandTail) +
898 strlen(Argv[i]) > 124)
899 break;
901 if (i != 1)
902 *p1++ = ' ';
904 for (p2 = Argv[i]; *p2 != '\0'; )
905 *p1++ = *p2++;
908 *p1 = '\0';
909 psp->pspCommandTailCount = strlen(psp->pspCommandTail);
911 return s;
914 /**********************************************************************
915 * CreateSelectors
917 SEGDESC *
918 CreateSelectors(struct w_files * wpnt)
920 int fd = wpnt->fd;
921 struct ne_segment_table_entry_s *seg_table = wpnt->seg_table;
922 struct ne_header_s *ne_header = wpnt->ne_header;
923 SEGDESC *selectors, *s, *stmp;
924 unsigned short auto_data_sel;
925 int contents, read_only;
926 int SelectorTableLength;
927 int i;
928 int status;
929 int old_length, file_image_length;
930 int saved_old_length;
933 * Allocate memory for the table to keep track of all selectors.
935 SelectorTableLength = ne_header->n_segment_tab;
936 selectors = malloc(SelectorTableLength * sizeof(*selectors));
937 if (selectors == NULL)
938 return NULL;
941 * Step through the segment table in the exe header.
943 s = selectors;
944 for (i = 0; i < ne_header->n_segment_tab; i++, s++)
947 * Store the flags in our table.
949 s->flags = seg_table[i].seg_flags;
952 * Is there an image for this segment in the file?
954 if (seg_table[i].seg_data_offset == 0)
957 * No image in exe file, let's allocate some memory for it.
959 s->length = seg_table[i].min_alloc;
961 else
964 * Image in file, let's just point to the image in memory.
966 s->length = seg_table[i].min_alloc;
967 file_image_length = seg_table[i].seg_data_length;
968 if (file_image_length == 0) file_image_length = 0x10000;
971 if (s->length == 0)
972 s->length = 0x10000;
973 old_length = s->length;
976 * If this is the automatic data segment, its size must be adjusted.
977 * First we need to check for local heap. Second we nee to see if
978 * this is also the stack segment.
980 if (i + 1 == ne_header->auto_data_seg || i + 1 == ne_header->ss)
982 s->length = 0x10000;
983 ne_header->sp = s->length - 2;
987 * Is this a DATA or CODE segment?
989 read_only = 0;
990 if (s->flags & NE_SEGFLAGS_DATA)
992 contents = MODIFY_LDT_CONTENTS_DATA;
993 if (s->flags & NE_SEGFLAGS_READONLY)
994 read_only = 1;
996 else
998 contents = MODIFY_LDT_CONTENTS_CODE;
999 if (s->flags & NE_SEGFLAGS_EXECUTEONLY)
1000 read_only = 1;
1003 #if 0
1004 stmp = CreateNewSegments(!(s->flags & NE_SEGFLAGS_DATA), read_only,
1005 s->length, 1);
1006 s->base_addr = stmp->base_addr;
1007 s->selector = stmp->selector;
1008 #endif
1009 s->selector = GlobalAlloc(GMEM_FIXED, s->length);
1010 if (s->selector == 0)
1011 myerror("CreateSelectors: GlobalAlloc() failed");
1013 s->base_addr = (void *) ((LONG) s->selector << 16);
1014 #ifdef HAVE_IPC
1015 s->shm_key = -1;
1016 #endif
1017 if (!(s->flags & NE_SEGFLAGS_DATA))
1018 PrestoChangoSelector(s->selector, s->selector);
1019 else
1020 memset(s->base_addr, 0, s->length);
1022 if (seg_table[i].seg_data_offset != 0)
1025 * Image in file.
1027 status = lseek(fd, seg_table[i].seg_data_offset *
1028 (1 << ne_header->align_shift_count), SEEK_SET);
1029 if(read(fd, s->base_addr, file_image_length) != file_image_length)
1030 myerror("Unable to read segment from file");
1034 * If this is the automatic data segment, then we must initialize
1035 * the local heap.
1037 if (i + 1 == ne_header->auto_data_seg)
1039 auto_data_sel = s->selector;
1040 saved_old_length = old_length;
1044 s = selectors;
1045 for (i = 0; i < ne_header->n_segment_tab; i++, s++)
1047 Segments[s->selector >> 3].owner = auto_data_sel;
1048 if (s->selector == auto_data_sel)
1049 HEAP_LocalInit(auto_data_sel, s->base_addr + saved_old_length,
1050 0x10000 - 2 - saved_old_length
1051 - ne_header->stack_length);
1054 if(!EnvironmentSelector) {
1055 EnvironmentSelector = CreateEnvironment();
1056 PSP_Selector = CreatePSP();
1057 MakeProcThunks = CreateNewSegments(1, 0, 0x10000, 1);
1060 return selectors;
1063 /***********************************************************************
1064 * GetSelectorBase (KERNEL.186)
1066 DWORD GetSelectorBase(WORD wSelector)
1068 fprintf(stderr, "GetSelectorBase(selector %4X) stub!\n", wSelector);
1071 /***********************************************************************
1072 * SetSelectorBase (KERNEL.187)
1074 void SetSelectorBase(WORD wSelector, DWORD dwBase)
1076 fprintf(stderr, "SetSelectorBase(selector %4X, base %8X) stub!\n",
1077 wSelector, dwBase);
1080 /***********************************************************************
1081 * GetSelectorLimit (KERNEL.188)
1083 DWORD GetSelectorLimit(WORD wSelector)
1085 fprintf(stderr, "GetSelectorLimit(selector %4X) stub!\n", wSelector);
1087 return 0xffff;
1090 /***********************************************************************
1091 * SetSelectorLimit (KERNEL.189)
1093 void SetSelectorLimit(WORD wSelector, DWORD dwLimit)
1095 fprintf(stderr, "SetSelectorLimit(selector %4X, base %8X) stub!\n",
1096 wSelector, dwLimit);
1099 #endif /* ifndef WINELIB */