Release 950122
[wine/multimedia.git] / loader / selector.c
blob82544602e777c108b4c441183f225fa6279d60c1
1 #ifndef WINELIB
2 /*
3 static char RCSId[] = "$Id: selector.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
4 static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
5 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #ifdef __linux__
15 #include <sys/mman.h>
16 #include <linux/unistd.h>
17 #include <linux/head.h>
18 #include <linux/mman.h>
19 #include <linux/a.out.h>
20 #include <linux/ldt.h>
21 #endif
22 #if defined(__NetBSD__) || defined(__FreeBSD__)
23 #include <sys/mman.h>
24 #include <machine/segments.h>
25 #endif
26 #include "dlls.h"
27 #include "neexe.h"
28 #include "segmem.h"
29 #include "wine.h"
30 #include "if1632.h"
31 #include "windows.h"
32 #include "prototypes.h"
33 #include "stddebug.h"
34 /* #define DEBUG_SELECTORS */
35 #include "debug.h"
38 #ifdef linux
39 #define DEV_ZERO
40 #ifdef __ELF__
41 #define UTEXTSEL 0x0f
42 #else
43 #define UTEXTSEL 0x23
44 #endif
45 #endif
47 #if defined(__NetBSD__) || defined(__FreeBSD__)
48 #define PAGE_SIZE getpagesize()
49 #define MODIFY_LDT_CONTENTS_DATA 0
50 #define MODIFY_LDT_CONTENTS_STACK 1
51 #define MODIFY_LDT_CONTENTS_CODE 2
52 #define UTEXTSEL 0x1f
53 #endif
55 static SEGDESC * EnvironmentSelector = NULL;
56 static SEGDESC * PSP_Selector = NULL;
57 SEGDESC * MakeProcThunks = NULL;
58 unsigned short PSPSelector;
59 unsigned char ran_out = 0;
60 int LastUsedSelector = FIRST_SELECTOR - 1;
62 unsigned short SelectorMap[MAX_SELECTORS];
63 SEGDESC Segments[MAX_SELECTORS];
65 #ifdef DEV_ZERO
66 static FILE *zfile = NULL;
67 #endif
69 extern void KERNEL_Ordinal_102();
70 extern void UNIXLIB_Ordinal_0();
71 extern char WindowsPath[256];
73 extern char **Argv;
74 extern int Argc;
75 extern char **environ;
77 unsigned int
78 GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal);
81 /**********************************************************************
82 * InitSelectors
84 void
85 InitSelectors(void) {
86 int i;
87 for (i = 0; i < MAX_SELECTORS; i++) {
88 if (i < FIRST_SELECTOR) {
89 SelectorMap[i] = SELECTOR_IS32BIT;
90 #ifdef __ELF__
91 /* quick hack, just reserves 4 meg for wine. */
92 } else if ((i << 19) >= 0x8000000 &&
93 (i << 19) <= 0x8400000) {
94 SelectorMap[i]= SELECTOR_IS32BIT;
95 #endif
96 } else {
97 SelectorMap[i]=0;
100 #ifdef __ELF__
101 /* create an ldt. */
102 if (set_ldt_entry(1, 0x8000000, 65535, 1,0x1a ,1,0)) {
103 perror ("set_ldt_entry");
104 exit (1);
106 #endif
109 /**********************************************************************
110 * FindUnusedSelectors
113 FindUnusedSelectors(int n_selectors)
115 int i;
116 int n_found;
118 n_found = 0;
119 for (i = LastUsedSelector + 1; i != LastUsedSelector; i++)
121 if (i >= MAX_SELECTORS)
123 n_found = 0;
124 i = FIRST_SELECTOR;
127 if (SelectorMap[i] && n_found) n_found=0;
129 if (!SelectorMap[i] && ++n_found == n_selectors)
130 break;
133 if (i == LastUsedSelector)
134 return 0;
136 LastUsedSelector = i;
137 return i - n_selectors + 1;
140 #ifdef HAVE_IPC
141 /**********************************************************************
142 * IPCCopySelector
144 * Created a shared memory copy of a segment:
146 * - at a new selector location (if "new" is a 16-bit value)
147 * - at an arbitrary memory location (if "new" is a 32-bit value)
150 IPCCopySelector(int i_old, unsigned long new, int swap_type)
152 SEGDESC *s_new, *s_old;
153 int i_new;
154 void *base_addr;
156 s_old = &Segments[i_old];
158 if (new & 0xffff0000)
160 /**************************************************************
161 * Let's set the address parameter for no segment.
163 i_new = -1;
164 s_new = NULL;
165 base_addr = (void *) new;
167 else
169 /***************************************************************
170 * We need to fill in the segment descriptor for segment "new".
172 i_new = new;
173 s_new = &Segments[i_new];
175 SelectorMap[i_new] = i_new;
177 s_new->selector = (i_new << 3) | 0x0007;
178 s_new->base_addr = (void *) ((long) s_new->selector << 16);
179 s_new->length = s_old->length;
180 s_new->flags = s_old->flags;
181 s_new->owner = s_old->owner;
182 if (swap_type)
184 if (s_old->type == MODIFY_LDT_CONTENTS_DATA)
185 s_new->type = MODIFY_LDT_CONTENTS_CODE;
186 else
187 s_new->type = MODIFY_LDT_CONTENTS_DATA;
189 else
190 s_new->type = s_old->type;
192 base_addr = s_new->base_addr;
195 /******************************************************************
196 * If we don't have a shared memory key for s_old, then we need
197 * to get one. In this case, we'll also have to copy the data
198 * to protect it.
200 if (s_old->shm_key == -1)
202 s_old->shm_key = shmget(IPC_PRIVATE, s_old->length, IPC_CREAT | 0600);
203 if (s_old->shm_key == -1)
205 if (s_new) {
206 memset(s_new, 0, sizeof(*s_new));
207 s_new->shm_key = -1;
209 return -1;
211 if (shmat(s_old->shm_key, base_addr, 0) == (char *) -1)
213 if (s_new) {
214 memset(s_new, 0, sizeof(*s_new));
215 s_new->shm_key = -1;
217 shmctl(s_old->shm_key, IPC_RMID, NULL);
218 return -1;
220 memcpy(base_addr, s_old->base_addr, s_old->length);
221 munmap(s_old->base_addr,
222 ((s_old->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
223 shmat(s_old->shm_key, s_old->base_addr, 0);
225 /******************************************************************
226 * If have shared memory key s_old, then just attach the new
227 * address.
229 else
231 if (shmat(s_old->shm_key, base_addr, 0) == (char *) -1)
233 if (s_new) {
234 memset(s_new, 0, sizeof(*s_new));
235 s_new->shm_key = -1;
237 return -1;
241 /******************************************************************
242 * If we are creating a new segment, then we also need to update
243 * the LDT to include the new selector. In this return the
244 * new selector.
246 if (s_new)
248 s_new->shm_key = s_old->shm_key;
250 if (set_ldt_entry(i_new, (unsigned long) base_addr,
251 s_old->length - 1, 0, s_new->type, 0, 0) < 0)
253 return -1;
256 return s_new->selector;
258 /******************************************************************
259 * No new segment. So, just return the shared memory key.
261 else
262 return s_old->shm_key;
264 #endif
266 /**********************************************************************
267 * AllocSelector
269 * This is very bad!!! This function is implemented for Windows
270 * compatibility only. Do not call this from the emulation library.
272 WORD AllocSelector(WORD old_selector)
274 SEGDESC *s_new;
275 int i_new, i_old;
276 int selector;
278 i_new = FindUnusedSelectors(1);
279 s_new = &Segments[i_new];
281 if (old_selector)
283 i_old = (old_selector >> 3);
284 #ifdef HAVE_IPC
285 selector = IPCCopySelector(i_old, i_new, 0);
286 if (selector < 0)
287 return 0;
288 else
289 return selector;
290 #else
291 s_old = &Segments[i_old];
292 s_new->selector = (i_new << 3) | 0x0007;
293 *s_new = *s_old;
294 SelectorMap[i_new] = SelectorMap[i_old];
296 if (set_ldt_entry(i_new, s_new->base_addr,
297 s_new->length - 1, 0,
298 s_new->type, 0, 0) < 0)
300 return 0;
302 #endif
304 else
306 memset(s_new, 0, sizeof(*s_new));
307 #ifdef HAVE_IPC
308 s_new->shm_key = -1;
309 #endif
310 SelectorMap[i_new] = i_new;
313 return (i_new << 3) | 0x0007;
316 /**********************************************************************
317 * PrestoChangoSelector
319 * This is very bad!!! This function is implemented for Windows
320 * compatibility only. Do not call this from the emulation library.
322 unsigned int PrestoChangoSelector(unsigned src_selector, unsigned dst_selector)
324 #ifdef HAVE_IPC
325 SEGDESC *src_s;
326 int src_idx, dst_idx;
328 src_idx = src_selector >> 3;
329 dst_idx = dst_selector >> 3;
331 if (src_idx == dst_idx)
333 src_s = &Segments[src_idx];
335 if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
336 src_s->type = MODIFY_LDT_CONTENTS_CODE;
337 else
338 src_s->type = MODIFY_LDT_CONTENTS_DATA;
340 if (set_ldt_entry(src_idx, (long) src_s->base_addr,
341 src_s->length - 1, 0, src_s->type, 0, 0) < 0)
343 return 0;
346 return src_s->selector;
348 else
350 return IPCCopySelector(src_idx, dst_idx, 1);
352 #else /* HAVE_IPC */
353 SEGDESC *src_s, *dst_s;
354 char *p;
355 int src_idx, dst_idx;
356 int alias_count;
357 int i;
359 src_idx = (SelectorMap[src_selector >> 3]);
360 dst_idx = dst_selector >> 3;
361 src_s = &Segments[src_idx];
362 dst_s = &Segments[dst_idx];
364 alias_count = 0;
365 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
366 if (SelectorMap[i] == src_idx)
367 alias_count++;
369 if (src_s->type == MODIFY_LDT_CONTENTS_DATA
370 || alias_count > 1 || src_idx == dst_idx)
372 *dst_s = *src_s;
374 if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
375 dst_s->type = MODIFY_LDT_CONTENTS_CODE;
376 else
377 dst_s->type = MODIFY_LDT_CONTENTS_DATA;
379 SelectorMap[dst_idx] = SelectorMap[src_idx];
380 if (set_ldt_entry(dst_idx, (long) dst_s->base_addr,
381 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
383 return 0;
386 else
389 * We're changing an unaliased code segment into a data
390 * segment. The SAFEST (but ugliest) way to deal with
391 * this is to map the new segment and copy all the contents.
393 SelectorMap[dst_idx] = dst_idx;
394 *dst_s = *src_s;
395 dst_s->selector = (dst_idx << 3) | 0x0007;
396 dst_s->base_addr = (void *) ((unsigned int) dst_s->selector << 16);
397 dst_s->type = MODIFY_LDT_CONTENTS_DATA;
398 #ifdef DEV_ZERO
399 if (zfile == NULL)
400 zfile = fopen("/dev/zero","r");
401 p = (void *) mmap((char *) dst_s->base_addr,
402 ((dst_s->length + PAGE_SIZE-1)
403 & ~(PAGE_SIZE - 1)),
404 PROT_EXEC | PROT_READ | PROT_WRITE,
405 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
406 #else
407 p = (void *) mmap((char *) dst_s->base_addr,
408 ((dst_s->length + PAGE_SIZE-1)
409 & ~(PAGE_SIZE - 1)),
410 PROT_EXEC | PROT_READ | PROT_WRITE,
411 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
412 #endif
413 if (p == NULL)
414 return 0;
416 memcpy((void *) dst_s->base_addr, (void *) src_s->base_addr,
417 dst_s->length);
418 if (set_ldt_entry(src_idx, dst_s->base_addr,
419 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
421 return 0;
423 if (set_ldt_entry(dst_idx, dst_s->base_addr,
424 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
426 return 0;
429 munmap(src_s->base_addr,
430 (src_s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1));
431 SelectorMap[src_idx] = dst_idx;
432 src_s->base_addr = dst_s->base_addr;
435 return dst_s->selector;
436 #endif /* HAVE_IPC */
439 /**********************************************************************
440 * AllocCStoDSAlias
442 WORD AllocDStoCSAlias(WORD ds_selector)
444 unsigned int cs_selector;
446 if (ds_selector == 0)
447 return 0;
449 cs_selector = AllocSelector(0);
450 return PrestoChangoSelector(ds_selector, cs_selector);
453 /**********************************************************************
454 * CleanupSelectors
457 void CleanupSelectors(void)
459 int sel_idx;
461 for (sel_idx = FIRST_SELECTOR; sel_idx < MAX_SELECTORS; sel_idx++)
462 if (SelectorMap[sel_idx])
463 FreeSelector((sel_idx << 3) | 7);
466 /**********************************************************************
467 * FreeSelector
469 WORD FreeSelector(WORD sel)
471 SEGDESC *s;
472 int sel_idx;
473 int alias_count;
474 int i;
476 #ifdef HAVE_IPC
477 sel_idx = sel >> 3;
479 if (sel_idx < FIRST_SELECTOR || sel_idx >= MAX_SELECTORS)
480 return 0;
482 s = &Segments[sel_idx];
483 if (s->shm_key == -1)
485 munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
486 memset(s, 0, sizeof(*s));
487 s->shm_key = -1;
488 SelectorMap[sel_idx] = 0;
490 else
492 shmdt(s->base_addr);
494 alias_count = 0;
495 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
496 if (SelectorMap[i] && Segments[i].shm_key == s->shm_key)
497 alias_count++;
499 if (alias_count == 1)
500 shmctl(s->shm_key, IPC_RMID, NULL);
502 memset(s, 0, sizeof(*s));
503 s->shm_key = -1;
504 SelectorMap[sel_idx] = 0;
507 #else /* HAVE_IPC */
508 sel_idx = SelectorMap[sel >> 3];
510 if (sel_idx < FIRST_SELECTOR || sel_idx >= MAX_SELECTORS)
511 return 0;
513 if (sel_idx != (sel >> 3))
515 SelectorMap[sel >> 3] = 0;
516 return 0;
519 alias_count = 0;
520 for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
521 if (SelectorMap[i] == sel_idx)
522 alias_count++;
524 if (alias_count == 1)
526 s = &Segments[sel_idx];
527 munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
528 memset(s, 0, sizeof(*s));
529 SelectorMap[sel >> 3] = 0;
531 #endif /* HAVE_IPC */
533 return 0;
536 /**********************************************************************
537 * CreateNewSegments
539 SEGDESC *
540 CreateNewSegments(int code_flag, int read_only, int length, int n_segments)
542 SEGDESC *s, *first_segment;
543 int contents;
544 int i, last_i;
546 i = FindUnusedSelectors(n_segments);
548 dprintf_selectors(stddeb, "Using %d segments starting at index %d.\n",
549 n_segments, i);
552 * Fill in selector info.
554 first_segment = s = &Segments[i];
555 for (last_i = i + n_segments; i < last_i; i++, s++)
557 if (code_flag)
559 contents = MODIFY_LDT_CONTENTS_CODE;
560 s->flags = 0;
562 else
564 contents = MODIFY_LDT_CONTENTS_DATA;
565 s->flags = NE_SEGFLAGS_DATA;
568 s->selector = (i << 3) | 0x0007;
569 s->length = length;
570 #ifdef DEV_ZERO
571 if (zfile == NULL)
572 zfile = fopen("/dev/zero","r");
573 s->base_addr = (void *) mmap((char *) (s->selector << 16),
574 ((s->length + PAGE_SIZE - 1) &
575 ~(PAGE_SIZE - 1)),
576 PROT_EXEC | PROT_READ | PROT_WRITE,
577 MAP_FIXED | MAP_PRIVATE,
578 fileno(zfile), 0);
579 #else
580 s->base_addr = (void *) mmap((char *) (s->selector << 16),
581 ((s->length + PAGE_SIZE - 1) &
582 ~(PAGE_SIZE - 1)),
583 PROT_EXEC | PROT_READ | PROT_WRITE,
584 MAP_FIXED | MAP_PRIVATE | MAP_ANON,
585 -1, 0);
586 #endif
587 #ifdef HAVE_IPC
588 s->shm_key = -1;
589 #endif
590 if (set_ldt_entry(i, (unsigned long) s->base_addr,
591 (s->length - 1) & 0xffff, 0,
592 contents, read_only, 0) < 0)
594 memset(s, 0, sizeof(*s));
595 #ifdef HAVE_IPC
596 s->shm_key = -1;
597 #endif
598 return NULL;
601 SelectorMap[i] = (unsigned short) i;
602 s->type = contents;
605 return first_segment;
608 /**********************************************************************
609 * GetNextSegment
611 SEGDESC *
612 GetNextSegment(unsigned int flags, unsigned int limit)
614 return CreateNewSegments(0, 0, limit, 1);
617 /**********************************************************************
618 * GetEntryPointFromOrdinal
620 union lookup{
621 struct entry_tab_header_s *eth;
622 struct entry_tab_movable_s *etm;
623 struct entry_tab_fixed_s *etf;
624 char * cpnt;
627 unsigned int GetEntryDLLName(char * dll_name, char * function, int * sel,
628 int * addr)
630 struct dll_table_entry_s *dll_table;
631 struct w_files * wpnt;
632 char * cpnt;
633 int ordinal, j, len;
635 dll_table = FindDLLTable(dll_name);
637 if(dll_table) {
638 ordinal = FindOrdinalFromName(dll_table, function);
639 *sel = dll_table[ordinal].selector;
640 *addr = (unsigned int) dll_table[ordinal].address;
641 #ifdef WINESTAT
642 dll_table[ordinal].used++;
643 #endif
644 return 0;
647 /* We need a means of determining the ordinal for the function. */
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 cpnt = wpnt->ne->nrname_table;
652 while(1==1){
653 if( ((int) cpnt) - ((int)wpnt->ne->nrname_table) >
654 wpnt->ne->ne_header->nrname_tab_length) return 1;
655 len = *cpnt++;
656 if(strncmp(cpnt, function, len) == 0) break;
657 cpnt += len + 2;
659 ordinal = *((unsigned short *) (cpnt + len));
660 j = GetEntryPointFromOrdinal(wpnt, ordinal);
661 *addr = j & 0xffff;
662 j = j >> 16;
663 *sel = j;
664 return 0;
666 return 1;
669 unsigned int GetEntryDLLOrdinal(char * dll_name, int ordinal, int * sel,
670 int * addr)
672 struct dll_table_entry_s *dll_table;
673 struct w_files * wpnt;
674 int j;
676 dll_table = FindDLLTable(dll_name);
678 if(dll_table) {
679 *sel = dll_table[ordinal].selector;
680 *addr = (unsigned int) dll_table[ordinal].address;
681 #ifdef WINESTAT
682 dll_table[ordinal].used++;
683 #endif
684 return 0;
687 /* Not a builtin symbol, look to see what the file has for us */
688 for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
689 if(strcasecmp(wpnt->name, dll_name)) continue;
690 j = GetEntryPointFromOrdinal(wpnt, ordinal);
691 *addr = j & 0xffff;
692 j = j >> 16;
693 *sel = j;
694 return 0;
696 return 1;
699 unsigned int
700 GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal)
702 union lookup entry_tab_pointer;
703 struct entry_tab_header_s *eth;
704 struct entry_tab_movable_s *etm;
705 struct entry_tab_fixed_s *etf;
706 int current_ordinal;
707 int i;
709 entry_tab_pointer.cpnt = wpnt->ne->lookup_table;
711 * Let's walk through the table until we get to our entry.
713 current_ordinal = 1;
714 while (1)
717 * Read header for this bundle.
719 eth = entry_tab_pointer.eth++;
721 if (eth->n_entries == 0)
722 return 0xffffffff; /* Yikes - we went off the end of the table */
724 if (eth->seg_number == 0)
726 current_ordinal += eth->n_entries;
727 if(current_ordinal > ordinal) return 0;
728 continue;
732 * Read each of the bundle entries.
734 for (i = 0; i < eth->n_entries; i++, current_ordinal++)
736 if (eth->seg_number >= 0xfe)
738 etm = entry_tab_pointer.etm++;
740 if (current_ordinal == ordinal)
742 return ((unsigned int)
743 (wpnt->ne->selector_table[etm->seg_number - 1].base_addr +
744 etm->offset));
747 else
749 etf = entry_tab_pointer.etf++;
751 if (current_ordinal == ordinal)
753 return ((unsigned int)
754 (wpnt->ne->selector_table[eth->seg_number - 1].base_addr +
755 (int) etf->offset[0] +
756 ((int) etf->offset[1] << 8)));
763 /**********************************************************************
764 * GetDOSEnvironment
766 LPSTR GetDOSEnvironment(void)
768 return (LPSTR) EnvironmentSelector->base_addr;
771 /**********************************************************************
772 * CreateEnvironment
774 static SEGDESC *
775 CreateEnvironment(void)
777 char **e;
778 char *p;
779 SEGDESC * s;
781 s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
782 if (s == NULL)
783 return NULL;
786 * Fill environment with Windows path, the Unix environment,
787 * and program name.
789 p = (char *) s->base_addr;
790 strcpy(p, "PATH=");
791 strcat(p, WindowsPath);
792 p += strlen(p) + 1;
794 for (e = environ; *e; e++)
796 if (strncasecmp(*e, "path", 4))
798 strcpy(p, *e);
799 p += strlen(p) + 1;
803 *p++ = '\0';
806 * Display environment
808 dprintf_selectors(stddeb, "Environment at %p\n", s->base_addr);
809 for (p = s->base_addr; *p; p += strlen(p) + 1)
810 dprintf_selectors(stddeb, " %s\n", p);
812 return s;
815 /**********************************************************************
817 WORD GetCurrentPDB()
819 return PSPSelector;
822 /**********************************************************************
823 * CreatePSP
825 static SEGDESC *
826 CreatePSP(void)
828 struct dos_psp_s *psp;
829 unsigned short *usp;
830 SEGDESC * s;
831 char *p1, *p2;
832 int i;
834 s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
837 * Fill PSP
839 PSPSelector = s->selector;
840 psp = (struct dos_psp_s *) s->base_addr;
841 psp->pspInt20 = 0x20cd;
842 psp->pspDispatcher[0] = 0x9a;
843 usp = (unsigned short *) &psp->pspDispatcher[1];
844 *usp = (unsigned short) KERNEL_Ordinal_102;
845 *(usp + 1) = UTEXTSEL;
846 psp->pspTerminateVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
847 psp->pspTerminateVector[1] = UTEXTSEL;
848 psp->pspControlCVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
849 psp->pspControlCVector[1] = UTEXTSEL;
850 psp->pspCritErrorVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
851 psp->pspCritErrorVector[1] = UTEXTSEL;
852 psp->pspEnvironment = EnvironmentSelector->selector;
854 p1 = psp->pspCommandTail;
855 for (i = 1; i < Argc; i++)
857 if ((int) ((int) p1 - (int) psp->pspCommandTail) +
858 strlen(Argv[i]) > 124)
859 break;
861 if (i != 1)
862 *p1++ = ' ';
864 for (p2 = Argv[i]; *p2 != '\0'; )
865 *p1++ = *p2++;
868 *p1 = '\0';
869 psp->pspCommandTailCount = strlen(psp->pspCommandTail);
871 return s;
874 /**********************************************************************
875 * CreateSelectors
877 SEGDESC *
878 CreateSelectors(struct w_files * wpnt)
880 int fd = wpnt->fd;
881 struct ne_segment_table_entry_s *seg_table = wpnt->ne->seg_table;
882 struct ne_header_s *ne_header = wpnt->ne->ne_header;
883 SEGDESC *selectors, *s;
884 unsigned short auto_data_sel;
885 int contents, read_only;
886 int SelectorTableLength;
887 int i;
888 int status;
889 int old_length, file_image_length;
890 int saved_old_length;
892 auto_data_sel=0;
894 * Allocate memory for the table to keep track of all selectors.
896 SelectorTableLength = ne_header->n_segment_tab;
897 selectors = malloc(SelectorTableLength * sizeof(*selectors));
898 if (selectors == NULL)
899 return NULL;
902 * Step through the segment table in the exe header.
904 s = selectors;
905 for (i = 0; i < ne_header->n_segment_tab; i++, s++)
908 * Store the flags in our table.
910 s->flags = seg_table[i].seg_flags;
913 * Is there an image for this segment in the file?
915 if (seg_table[i].seg_data_offset == 0)
918 * No image in exe file, let's allocate some memory for it.
920 s->length = seg_table[i].min_alloc;
922 else
925 * Image in file, let's just point to the image in memory.
927 s->length = seg_table[i].min_alloc;
928 file_image_length = seg_table[i].seg_data_length;
929 if (file_image_length == 0) file_image_length = 0x10000;
932 if (s->length == 0)
933 s->length = 0x10000;
934 old_length = s->length;
937 * If this is the automatic data segment, its size must be adjusted.
938 * First we need to check for local heap. Second we nee to see if
939 * this is also the stack segment.
941 if (i + 1 == ne_header->auto_data_seg || i + 1 == ne_header->ss)
943 s->length = 0x10000;
944 ne_header->sp = s->length - 2;
948 * Is this a DATA or CODE segment?
950 read_only = 0;
951 if (s->flags & NE_SEGFLAGS_DATA)
953 contents = MODIFY_LDT_CONTENTS_DATA;
954 if (s->flags & NE_SEGFLAGS_READONLY)
955 read_only = 1;
957 else
959 contents = MODIFY_LDT_CONTENTS_CODE;
960 if (s->flags & NE_SEGFLAGS_EXECUTEONLY)
961 read_only = 1;
964 #if 0
965 stmp = CreateNewSegments(!(s->flags & NE_SEGFLAGS_DATA), read_only,
966 s->length, 1);
967 s->base_addr = stmp->base_addr;
968 s->selector = stmp->selector;
969 #endif
970 s->selector = GlobalAlloc(GMEM_FIXED, s->length);
971 if (s->selector == 0)
972 myerror("CreateSelectors: GlobalAlloc() failed");
974 s->base_addr = (void *) ((LONG) s->selector << 16);
975 #ifdef HAVE_IPC
976 s->shm_key = -1;
977 #endif
978 if (!(s->flags & NE_SEGFLAGS_DATA))
979 PrestoChangoSelector(s->selector, s->selector);
980 else
981 memset(s->base_addr, 0, s->length);
983 if (seg_table[i].seg_data_offset != 0)
986 * Image in file.
988 status = lseek(fd, seg_table[i].seg_data_offset *
989 (1 << ne_header->align_shift_count), SEEK_SET);
990 if(read(fd, s->base_addr, file_image_length) != file_image_length)
991 myerror("Unable to read segment from file");
995 * If this is the automatic data segment, then we must initialize
996 * the local heap.
998 if (i + 1 == ne_header->auto_data_seg)
1000 auto_data_sel = s->selector;
1001 saved_old_length = old_length;
1005 if(!auto_data_sel)dprintf_selectors(stddeb,"Warning: No auto_data_sel\n");
1006 s = selectors;
1007 for (i = 0; i < ne_header->n_segment_tab; i++, s++)
1009 Segments[s->selector >> 3].owner = auto_data_sel;
1010 if (s->selector == auto_data_sel)
1011 HEAP_LocalInit(auto_data_sel, s->base_addr + saved_old_length,
1012 0x10000 - 2 - saved_old_length
1013 - ne_header->stack_length);
1016 if(!EnvironmentSelector) {
1017 EnvironmentSelector = CreateEnvironment();
1018 PSP_Selector = CreatePSP();
1019 MakeProcThunks = CreateNewSegments(1, 0, 0x10000, 1);
1022 return selectors;
1024 /**********************************************************************
1026 void
1027 FixupFunctionPrologs(struct w_files * wpnt)
1029 struct ne_header_s *ne_header = wpnt->ne->ne_header;
1030 union lookup entry_tab_pointer;
1031 struct entry_tab_header_s *eth;
1032 struct entry_tab_movable_s *etm;
1033 struct entry_tab_fixed_s *etf;
1034 unsigned char *fixup_ptr;
1035 int i;
1037 if (!(ne_header->format_flags & 0x0001))
1038 return;
1040 entry_tab_pointer.cpnt = wpnt->ne->lookup_table;
1042 * Let's walk through the table and fixup prologs as we go.
1044 while (1)
1046 /* Get bundle header */
1047 eth = entry_tab_pointer.eth++;
1049 /* Check for end of table */
1050 if (eth->n_entries == 0)
1051 return;
1053 /* Check for empty bundle */
1054 if (eth->seg_number == 0)
1055 continue;
1057 /* Examine each bundle */
1058 for (i = 0; i < eth->n_entries; i++)
1060 /* Moveable segment */
1061 if (eth->seg_number >= 0xfe)
1063 etm = entry_tab_pointer.etm++;
1064 fixup_ptr = (wpnt->ne->selector_table[etm->seg_number-1].base_addr
1065 + etm->offset);
1067 else
1069 etf = entry_tab_pointer.etf++;
1070 fixup_ptr = (wpnt->ne->selector_table[eth->seg_number-1].base_addr
1071 + (int) etf->offset[0]
1072 + ((int) etf->offset[1] << 8));
1076 /* Verify the signature */
1077 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
1078 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
1079 && fixup_ptr[2] == 0x90)
1081 fixup_ptr[0] = 0xb8; /* MOV AX, */
1082 fixup_ptr[1] = wpnt->hinstance;
1083 fixup_ptr[2] = (wpnt->hinstance >> 8);
1089 /***********************************************************************
1090 * GetSelectorBase (KERNEL.186)
1092 DWORD GetSelectorBase(WORD wSelector)
1094 fprintf(stdnimp, "GetSelectorBase(selector %4X) stub!\n", wSelector);
1095 return 0;
1098 /***********************************************************************
1099 * SetSelectorBase (KERNEL.187)
1101 void SetSelectorBase(WORD wSelector, DWORD dwBase)
1103 fprintf(stdnimp, "SetSelectorBase(selector %4X, base %8lX) stub!\n",
1104 wSelector, dwBase);
1107 /***********************************************************************
1108 * GetSelectorLimit (KERNEL.188)
1110 DWORD GetSelectorLimit(WORD wSelector)
1112 fprintf(stdnimp, "GetSelectorLimit(selector %4X) stub!\n", wSelector);
1114 return 0xffff;
1117 /***********************************************************************
1118 * SetSelectorLimit (KERNEL.189)
1120 void SetSelectorLimit(WORD wSelector, DWORD dwLimit)
1122 fprintf(stdnimp, "SetSelectorLimit(selector %4X, base %8lX) stub!\n",
1123 wSelector, dwLimit);
1126 #endif /* ifndef WINELIB */