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";
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>
22 #if defined(__NetBSD__) || defined(__FreeBSD__)
24 #include <machine/segments.h>
32 #include "prototypes.h"
34 /* #define DEBUG_SELECTORS */
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
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 #define MAX_SELECTORS (512 * 2)
64 int max_selectors = 0;
65 unsigned short* SelectorMap;
69 static FILE *zfile = NULL;
72 extern void KERNEL_Ordinal_102();
73 extern void UNIXLIB_Ordinal_0();
74 extern char WindowsPath[256];
78 extern char **environ;
81 GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal);
84 /**********************************************************************
91 max_selectors = MAX_SELECTORS;
92 SelectorMap = malloc(max_selectors * sizeof(unsigned short));
93 Segments = malloc(max_selectors * sizeof(SEGDESC));
94 for (i = 0; i < max_selectors; i++) {
95 if (i < FIRST_SELECTOR) {
96 SelectorMap[i] = SELECTOR_IS32BIT;
98 /* quick hack, just reserves 4 meg for wine. */
99 } else if ((i << (16 + __AHSHIFT)) >= 0x8000000 &&
100 (i << (16 + __AHSHIFT)) <= 0x8400000) {
101 SelectorMap[i]= SELECTOR_IS32BIT;
109 if (set_ldt_entry(1, 0x8000000, 65535, 1,0x1a ,1,0)) {
110 perror ("set_ldt_entry");
116 /**********************************************************************
117 * FindUnusedSelectors
120 FindUnusedSelectors(int n_selectors)
126 for (i = LastUsedSelector + 1; i != LastUsedSelector; i++)
128 if (i >= max_selectors)
131 max_selectors += MAX_SELECTORS;
132 dprintf_selectors(stddeb, "Expanding no of segments to %d.\n",
135 realloc(SelectorMap, max_selectors * sizeof(unsigned short));
136 Segments = realloc(Segments, max_selectors * sizeof(SEGDESC));
137 if (!SelectorMap || !Segments)
140 "FindUnusedSelectors: Out of memory! Exiting\n");
143 for (j = max_selectors - MAX_SELECTORS; j < max_selectors; j++)
147 if (SelectorMap[i] && n_found) n_found=0;
149 if (!SelectorMap[i] && ++n_found == n_selectors)
153 if (i == LastUsedSelector)
156 LastUsedSelector = i;
157 return i - n_selectors + 1;
161 /**********************************************************************
164 * Created a shared memory copy of a segment:
166 * - at a new selector location (if "new" is a 16-bit value)
167 * - at an arbitrary memory location (if "new" is a 32-bit value)
170 IPCCopySelector(int i_old, unsigned long new, int swap_type)
172 SEGDESC *s_new, *s_old;
176 s_old = &Segments[i_old];
178 if (new & 0xffff0000)
180 /**************************************************************
181 * Let's set the address parameter for no segment.
185 base_addr = (void *) new;
189 /***************************************************************
190 * We need to fill in the segment descriptor for segment "new".
193 s_new = &Segments[i_new];
195 SelectorMap[i_new] = i_new;
197 s_new->selector = (i_new << __AHSHIFT) | 0x0007;
198 s_new->base_addr = (void *) ((long) s_new->selector << 16);
199 s_new->length = s_old->length;
200 s_new->flags = s_old->flags;
201 s_new->owner = s_old->owner;
204 if (s_old->type == MODIFY_LDT_CONTENTS_DATA)
205 s_new->type = MODIFY_LDT_CONTENTS_CODE;
207 s_new->type = MODIFY_LDT_CONTENTS_DATA;
210 s_new->type = s_old->type;
212 base_addr = s_new->base_addr;
215 /******************************************************************
216 * If we don't have a shared memory key for s_old, then we need
217 * to get one. In this case, we'll also have to copy the data
220 if (s_old->shm_key == -1)
222 s_old->shm_key = shmget(IPC_PRIVATE, s_old->length, IPC_CREAT | 0600);
223 if (s_old->shm_key == -1)
226 memset(s_new, 0, sizeof(*s_new));
231 if (shmat(s_old->shm_key, base_addr, 0) == (char *) -1)
234 memset(s_new, 0, sizeof(*s_new));
237 shmctl(s_old->shm_key, IPC_RMID, NULL);
240 memcpy(base_addr, s_old->base_addr, s_old->length);
241 munmap(s_old->base_addr,
242 ((s_old->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
243 shmat(s_old->shm_key, s_old->base_addr, 0);
245 /******************************************************************
246 * If have shared memory key s_old, then just attach the new
251 if (shmat(s_old->shm_key, base_addr, 0) == (char *) -1)
254 memset(s_new, 0, sizeof(*s_new));
261 /******************************************************************
262 * If we are creating a new segment, then we also need to update
263 * the LDT to include the new selector. In this return the
268 s_new->shm_key = s_old->shm_key;
270 if (set_ldt_entry(i_new, (unsigned long) base_addr,
271 s_old->length - 1, 0, s_new->type, 0, 0) < 0)
276 return s_new->selector;
278 /******************************************************************
279 * No new segment. So, just return the shared memory key.
282 return s_old->shm_key;
286 /**********************************************************************
289 * This is very bad!!! This function is implemented for Windows
290 * compatibility only. Do not call this from the emulation library.
292 WORD AllocSelector(WORD old_selector)
298 i_new = FindUnusedSelectors(1);
299 s_new = &Segments[i_new];
303 i_old = (old_selector >> __AHSHIFT);
305 selector = IPCCopySelector(i_old, i_new, 0);
311 s_old = &Segments[i_old];
312 s_new->selector = (i_new << __AHSHIFT) | 0x0007;
314 SelectorMap[i_new] = SelectorMap[i_old];
316 if (set_ldt_entry(i_new, s_new->base_addr,
317 s_new->length - 1, 0,
318 s_new->type, 0, 0) < 0)
326 memset(s_new, 0, sizeof(*s_new));
330 SelectorMap[i_new] = i_new;
333 return (i_new << __AHSHIFT) | 0x0007;
336 /**********************************************************************
337 * PrestoChangoSelector
339 * This is very bad!!! This function is implemented for Windows
340 * compatibility only. Do not call this from the emulation library.
342 unsigned int PrestoChangoSelector(unsigned src_selector, unsigned dst_selector)
346 int src_idx, dst_idx;
348 src_idx = src_selector >> __AHSHIFT;
349 dst_idx = dst_selector >> __AHSHIFT;
351 if (src_idx == dst_idx)
353 src_s = &Segments[src_idx];
355 if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
356 src_s->type = MODIFY_LDT_CONTENTS_CODE;
358 src_s->type = MODIFY_LDT_CONTENTS_DATA;
360 if (set_ldt_entry(src_idx, (long) src_s->base_addr,
361 src_s->length - 1, 0, src_s->type, 0, 0) < 0)
366 return src_s->selector;
370 return IPCCopySelector(src_idx, dst_idx, 1);
373 SEGDESC *src_s, *dst_s;
375 int src_idx, dst_idx;
379 src_idx = (SelectorMap[src_selector >> __AHSHIFT]);
380 dst_idx = dst_selector >> __AHSHIFT;
381 src_s = &Segments[src_idx];
382 dst_s = &Segments[dst_idx];
385 for (i = FIRST_SELECTOR; i < max_selectors; i++)
386 if (SelectorMap[i] == src_idx)
389 if (src_s->type == MODIFY_LDT_CONTENTS_DATA
390 || alias_count > 1 || src_idx == dst_idx)
394 if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
395 dst_s->type = MODIFY_LDT_CONTENTS_CODE;
397 dst_s->type = MODIFY_LDT_CONTENTS_DATA;
399 SelectorMap[dst_idx] = SelectorMap[src_idx];
400 if (set_ldt_entry(dst_idx, (long) dst_s->base_addr,
401 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
409 * We're changing an unaliased code segment into a data
410 * segment. The SAFEST (but ugliest) way to deal with
411 * this is to map the new segment and copy all the contents.
413 SelectorMap[dst_idx] = dst_idx;
415 dst_s->selector = (dst_idx << __AHSHIFT) | 0x0007;
416 dst_s->base_addr = (void *) ((unsigned int) dst_s->selector << 16);
417 dst_s->type = MODIFY_LDT_CONTENTS_DATA;
420 zfile = fopen("/dev/zero","r");
421 p = (void *) mmap((char *) dst_s->base_addr,
422 ((dst_s->length + PAGE_SIZE-1)
424 PROT_EXEC | PROT_READ | PROT_WRITE,
425 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
427 p = (void *) mmap((char *) dst_s->base_addr,
428 ((dst_s->length + PAGE_SIZE-1)
430 PROT_EXEC | PROT_READ | PROT_WRITE,
431 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
436 memcpy((void *) dst_s->base_addr, (void *) src_s->base_addr,
438 if (set_ldt_entry(src_idx, dst_s->base_addr,
439 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
443 if (set_ldt_entry(dst_idx, dst_s->base_addr,
444 dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
449 munmap(src_s->base_addr,
450 (src_s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1));
451 SelectorMap[src_idx] = dst_idx;
452 src_s->base_addr = dst_s->base_addr;
455 return dst_s->selector;
456 #endif /* HAVE_IPC */
459 /**********************************************************************
462 WORD AllocDStoCSAlias(WORD ds_selector)
464 unsigned int cs_selector;
466 if (ds_selector == 0)
469 cs_selector = AllocSelector(0);
470 return PrestoChangoSelector(ds_selector, cs_selector);
473 /**********************************************************************
477 void CleanupSelectors(void)
481 for (sel_idx = FIRST_SELECTOR; sel_idx < max_selectors; sel_idx++)
482 if (SelectorMap[sel_idx])
483 FreeSelector((sel_idx << __AHSHIFT) | 7);
486 /**********************************************************************
489 WORD FreeSelector(WORD sel)
497 sel_idx = sel >> __AHSHIFT;
499 if (sel_idx < FIRST_SELECTOR || sel_idx >= max_selectors)
502 s = &Segments[sel_idx];
503 if (s->shm_key == -1)
505 munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
506 memset(s, 0, sizeof(*s));
508 SelectorMap[sel_idx] = 0;
515 for (i = FIRST_SELECTOR; i < max_selectors; i++)
516 if (SelectorMap[i] && Segments[i].shm_key == s->shm_key)
519 if (alias_count == 1)
520 shmctl(s->shm_key, IPC_RMID, NULL);
522 memset(s, 0, sizeof(*s));
524 SelectorMap[sel_idx] = 0;
528 sel_idx = SelectorMap[sel >> __AHSHIFT];
530 if (sel_idx < FIRST_SELECTOR || sel_idx >= max_selectors)
533 if (sel_idx != (sel >> __AHSHIFT))
535 SelectorMap[sel >> __AHSHIFT] = 0;
540 for (i = FIRST_SELECTOR; i < max_selectors; i++)
541 if (SelectorMap[i] == sel_idx)
544 if (alias_count == 1)
546 s = &Segments[sel_idx];
547 munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
548 memset(s, 0, sizeof(*s));
549 SelectorMap[sel >> __AHSHIFT] = 0;
551 #endif /* HAVE_IPC */
556 /**********************************************************************
560 CreateNewSegments(int code_flag, int read_only, int length, int n_segments)
562 SEGDESC *s, *first_segment;
566 i = FindUnusedSelectors(n_segments);
568 dprintf_selectors(stddeb, "Using %d segments starting at index %d.\n",
572 * Fill in selector info.
574 first_segment = s = &Segments[i];
575 for (last_i = i + n_segments; i < last_i; i++, s++)
579 contents = MODIFY_LDT_CONTENTS_CODE;
584 contents = MODIFY_LDT_CONTENTS_DATA;
585 s->flags = NE_SEGFLAGS_DATA;
588 s->selector = (i << __AHSHIFT) | 0x0007;
592 zfile = fopen("/dev/zero","r");
593 s->base_addr = (void *) mmap((char *) (s->selector << 16),
594 ((s->length + PAGE_SIZE - 1) &
596 PROT_EXEC | PROT_READ | PROT_WRITE,
597 MAP_FIXED | MAP_PRIVATE,
600 s->base_addr = (void *) mmap((char *) (s->selector << 16),
601 ((s->length + PAGE_SIZE - 1) &
603 PROT_EXEC | PROT_READ | PROT_WRITE,
604 MAP_FIXED | MAP_PRIVATE | MAP_ANON,
610 if (set_ldt_entry(i, (unsigned long) s->base_addr,
611 (s->length - 1) & 0xffff, 0,
612 contents, read_only, 0) < 0)
614 memset(s, 0, sizeof(*s));
621 SelectorMap[i] = (unsigned short) i;
625 return first_segment;
628 /**********************************************************************
632 GetNextSegment(unsigned int flags, unsigned int limit)
634 return CreateNewSegments(0, 0, limit, 1);
637 /**********************************************************************
638 * GetEntryPointFromOrdinal
641 struct entry_tab_header_s *eth;
642 struct entry_tab_movable_s *etm;
643 struct entry_tab_fixed_s *etf;
647 unsigned int GetEntryDLLName(char * dll_name, char * function, int * sel,
650 struct dll_table_entry_s *dll_table;
651 struct w_files * wpnt;
655 dll_table = FindDLLTable(dll_name);
658 ordinal = FindOrdinalFromName(dll_table, function);
659 *sel = dll_table[ordinal].selector;
660 *addr = (unsigned int) dll_table[ordinal].address;
662 dll_table[ordinal].used++;
667 /* We need a means of determining the ordinal for the function. */
668 /* Not a builtin symbol, look to see what the file has for us */
669 for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
670 if(strcasecmp(wpnt->name, dll_name)) continue;
671 cpnt = wpnt->ne->nrname_table;
673 if( ((int) cpnt) - ((int)wpnt->ne->nrname_table) >
674 wpnt->ne->ne_header->nrname_tab_length) return 1;
676 if(strncmp(cpnt, function, len) == 0) break;
679 ordinal = *((unsigned short *) (cpnt + len));
680 j = GetEntryPointFromOrdinal(wpnt, ordinal);
689 unsigned int GetEntryDLLOrdinal(char * dll_name, int ordinal, int * sel,
692 struct dll_table_entry_s *dll_table;
693 struct w_files * wpnt;
696 dll_table = FindDLLTable(dll_name);
699 *sel = dll_table[ordinal].selector;
700 *addr = (unsigned int) dll_table[ordinal].address;
702 dll_table[ordinal].used++;
707 /* Not a builtin symbol, look to see what the file has for us */
708 for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
709 if(strcasecmp(wpnt->name, dll_name)) continue;
710 j = GetEntryPointFromOrdinal(wpnt, ordinal);
720 GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal)
722 union lookup entry_tab_pointer;
723 struct entry_tab_header_s *eth;
724 struct entry_tab_movable_s *etm;
725 struct entry_tab_fixed_s *etf;
729 entry_tab_pointer.cpnt = wpnt->ne->lookup_table;
731 * Let's walk through the table until we get to our entry.
737 * Read header for this bundle.
739 eth = entry_tab_pointer.eth++;
741 if (eth->n_entries == 0)
742 return 0xffffffff; /* Yikes - we went off the end of the table */
744 if (eth->seg_number == 0)
746 current_ordinal += eth->n_entries;
747 if(current_ordinal > ordinal) return 0;
752 * Read each of the bundle entries.
754 for (i = 0; i < eth->n_entries; i++, current_ordinal++)
756 if (eth->seg_number >= 0xfe)
758 etm = entry_tab_pointer.etm++;
760 if (current_ordinal == ordinal)
762 return ((unsigned int)
763 (wpnt->ne->selector_table[etm->seg_number - 1].base_addr +
769 etf = entry_tab_pointer.etf++;
771 if (current_ordinal == ordinal)
773 return ((unsigned int)
774 (wpnt->ne->selector_table[eth->seg_number - 1].base_addr +
775 (int) etf->offset[0] +
776 ((int) etf->offset[1] << 8)));
783 /**********************************************************************
786 LPSTR GetDOSEnvironment(void)
788 return (LPSTR) EnvironmentSelector->base_addr;
791 /**********************************************************************
795 CreateEnvironment(void)
801 s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
806 * Fill environment with Windows path, the Unix environment,
809 p = (char *) s->base_addr;
811 strcat(p, WindowsPath);
814 for (e = environ; *e; e++)
816 if (strncasecmp(*e, "path", 4))
826 * Display environment
828 dprintf_selectors(stddeb, "Environment at %p\n", s->base_addr);
829 for (p = s->base_addr; *p; p += strlen(p) + 1)
830 dprintf_selectors(stddeb, " %s\n", p);
835 /**********************************************************************
842 /**********************************************************************
848 struct dos_psp_s *psp;
854 s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
859 PSPSelector = s->selector;
860 psp = (struct dos_psp_s *) s->base_addr;
861 psp->pspInt20 = 0x20cd;
862 psp->pspDispatcher[0] = 0x9a;
863 usp = (unsigned short *) &psp->pspDispatcher[1];
864 *usp = (unsigned short) KERNEL_Ordinal_102;
865 *(usp + 1) = UTEXTSEL;
866 psp->pspTerminateVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
867 psp->pspTerminateVector[1] = UTEXTSEL;
868 psp->pspControlCVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
869 psp->pspControlCVector[1] = UTEXTSEL;
870 psp->pspCritErrorVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
871 psp->pspCritErrorVector[1] = UTEXTSEL;
872 psp->pspEnvironment = EnvironmentSelector->selector;
874 p1 = psp->pspCommandTail;
875 for (i = 1; i < Argc; i++)
877 if ((int) ((int) p1 - (int) psp->pspCommandTail) +
878 strlen(Argv[i]) > 124)
884 for (p2 = Argv[i]; *p2 != '\0'; )
889 psp->pspCommandTailCount = strlen(psp->pspCommandTail);
894 /**********************************************************************
898 CreateSelectors(struct w_files * wpnt)
901 struct ne_segment_table_entry_s *seg_table = wpnt->ne->seg_table;
902 struct ne_header_s *ne_header = wpnt->ne->ne_header;
903 SEGDESC *selectors, *s;
904 unsigned short auto_data_sel;
905 int contents, read_only;
906 int SelectorTableLength;
909 int old_length, file_image_length = 0;
910 int saved_old_length = 0;
914 * Allocate memory for the table to keep track of all selectors.
916 SelectorTableLength = ne_header->n_segment_tab;
917 selectors = malloc(SelectorTableLength * sizeof(*selectors));
918 if (selectors == NULL)
922 * Step through the segment table in the exe header.
925 for (i = 0; i < ne_header->n_segment_tab; i++, s++)
928 * Store the flags in our table.
930 s->flags = seg_table[i].seg_flags;
933 * Is there an image for this segment in the file?
935 if (seg_table[i].seg_data_offset == 0)
938 * No image in exe file, let's allocate some memory for it.
940 s->length = seg_table[i].min_alloc;
945 * Image in file, let's just point to the image in memory.
947 s->length = seg_table[i].min_alloc;
948 file_image_length = seg_table[i].seg_data_length;
949 if (file_image_length == 0) file_image_length = 0x10000;
954 old_length = s->length;
957 * If this is the automatic data segment, its size must be adjusted.
958 * First we need to check for local heap. Second we nee to see if
959 * this is also the stack segment.
961 if (i + 1 == ne_header->auto_data_seg || i + 1 == ne_header->ss)
964 ne_header->sp = s->length - 2;
968 * Is this a DATA or CODE segment?
971 if (s->flags & NE_SEGFLAGS_DATA)
973 contents = MODIFY_LDT_CONTENTS_DATA;
974 if (s->flags & NE_SEGFLAGS_READONLY)
979 contents = MODIFY_LDT_CONTENTS_CODE;
980 if (s->flags & NE_SEGFLAGS_EXECUTEONLY)
985 stmp = CreateNewSegments(!(s->flags & NE_SEGFLAGS_DATA), read_only,
987 s->base_addr = stmp->base_addr;
988 s->selector = stmp->selector;
990 s->selector = GlobalAlloc(GMEM_FIXED, s->length);
991 if (s->selector == 0)
992 myerror("CreateSelectors: GlobalAlloc() failed");
994 s->base_addr = (void *) ((LONG) s->selector << 16);
998 if (!(s->flags & NE_SEGFLAGS_DATA))
999 PrestoChangoSelector(s->selector, s->selector);
1001 memset(s->base_addr, 0, s->length);
1003 if (seg_table[i].seg_data_offset != 0)
1008 status = lseek(fd, seg_table[i].seg_data_offset *
1009 (1 << ne_header->align_shift_count), SEEK_SET);
1010 if(read(fd, s->base_addr, file_image_length) != file_image_length)
1011 myerror("Unable to read segment from file");
1015 * If this is the automatic data segment, then we must initialize
1018 if (i + 1 == ne_header->auto_data_seg)
1020 auto_data_sel = s->selector;
1021 saved_old_length = old_length;
1025 if(!auto_data_sel)dprintf_selectors(stddeb,"Warning: No auto_data_sel\n");
1027 for (i = 0; i < ne_header->n_segment_tab; i++, s++)
1029 Segments[s->selector >> __AHSHIFT].owner = auto_data_sel;
1030 if (s->selector == auto_data_sel)
1031 HEAP_LocalInit(auto_data_sel, s->base_addr + saved_old_length,
1032 0x10000 - 2 - saved_old_length
1033 - ne_header->stack_length);
1036 if(!EnvironmentSelector) {
1037 EnvironmentSelector = CreateEnvironment();
1038 PSP_Selector = CreatePSP();
1039 MakeProcThunks = CreateNewSegments(1, 0, 0x10000, 1);
1044 /**********************************************************************
1047 FixupFunctionPrologs(struct w_files * wpnt)
1049 struct ne_header_s *ne_header = wpnt->ne->ne_header;
1050 union lookup entry_tab_pointer;
1051 struct entry_tab_header_s *eth;
1052 struct entry_tab_movable_s *etm;
1053 struct entry_tab_fixed_s *etf;
1054 unsigned char *fixup_ptr;
1057 if (!(ne_header->format_flags & 0x0001))
1060 entry_tab_pointer.cpnt = wpnt->ne->lookup_table;
1062 * Let's walk through the table and fixup prologs as we go.
1066 /* Get bundle header */
1067 eth = entry_tab_pointer.eth++;
1069 /* Check for end of table */
1070 if (eth->n_entries == 0)
1073 /* Check for empty bundle */
1074 if (eth->seg_number == 0)
1077 /* Examine each bundle */
1078 for (i = 0; i < eth->n_entries; i++)
1080 /* Moveable segment */
1081 if (eth->seg_number >= 0xfe)
1083 etm = entry_tab_pointer.etm++;
1084 fixup_ptr = (wpnt->ne->selector_table[etm->seg_number-1].base_addr
1089 etf = entry_tab_pointer.etf++;
1090 fixup_ptr = (wpnt->ne->selector_table[eth->seg_number-1].base_addr
1091 + (int) etf->offset[0]
1092 + ((int) etf->offset[1] << 8));
1096 /* Verify the signature */
1097 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
1098 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
1099 && fixup_ptr[2] == 0x90)
1101 fixup_ptr[0] = 0xb8; /* MOV AX, */
1102 fixup_ptr[1] = wpnt->hinstance;
1103 fixup_ptr[2] = (wpnt->hinstance >> 8);
1109 /***********************************************************************
1110 * GetSelectorBase (KERNEL.186)
1112 DWORD GetSelectorBase(WORD wSelector)
1114 fprintf(stdnimp, "GetSelectorBase(selector %4X) stub!\n", wSelector);
1118 /***********************************************************************
1119 * SetSelectorBase (KERNEL.187)
1121 void SetSelectorBase(WORD wSelector, DWORD dwBase)
1123 fprintf(stdnimp, "SetSelectorBase(selector %4X, base %8lX) stub!\n",
1127 /***********************************************************************
1128 * GetSelectorLimit (KERNEL.188)
1130 DWORD GetSelectorLimit(WORD wSelector)
1132 fprintf(stdnimp, "GetSelectorLimit(selector %4X) stub!\n", wSelector);
1137 /***********************************************************************
1138 * SetSelectorLimit (KERNEL.189)
1140 void SetSelectorLimit(WORD wSelector, DWORD dwLimit)
1142 fprintf(stdnimp, "SetSelectorLimit(selector %4X, base %8lX) stub!\n",
1143 wSelector, dwLimit);
1146 #endif /* ifndef WINELIB */