Moved all references to file descriptors out of the generic object
[wine] / memory / selector.c
1 /*
2  * Selector manipulation functions
3  *
4  * Copyright 1995 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <string.h>
25
26 #include "winerror.h"
27 #include "wine/winbase16.h"
28 #include "miscemu.h"
29 #include "selectors.h"
30 #include "stackframe.h"
31 #include "wine/server.h"
32 #include "wine/debug.h"
33 #include "toolhelp.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(selector);
36
37 #define LDT_SIZE 8192
38
39 /* get the number of selectors needed to cover up to the selector limit */
40 inline static WORD get_sel_count( WORD sel )
41 {
42     return (wine_ldt_copy.limit[sel >> __AHSHIFT] >> 16) + 1;
43 }
44
45 static const LDT_ENTRY null_entry;  /* all-zeros, used to clear LDT entries */
46
47 /***********************************************************************
48  *           SELECTOR_AllocArray
49  *
50  * Allocate a selector array without setting the LDT entries
51  */
52 static WORD SELECTOR_AllocArray( WORD count )
53 {
54     WORD i, sel, size = 0;
55
56     if (!count) return 0;
57     for (i = FIRST_LDT_ENTRY_TO_ALLOC; i < LDT_SIZE; i++)
58     {
59         if (wine_ldt_copy.flags[i] & WINE_LDT_FLAGS_ALLOCATED) size = 0;
60         else if (++size >= count) break;
61     }
62     if (i == LDT_SIZE) return 0;
63     sel = i - size + 1;
64
65     /* mark selectors as allocated */
66     for (i = 0; i < count; i++) wine_ldt_copy.flags[sel + i] |= WINE_LDT_FLAGS_ALLOCATED;
67
68     return (sel << __AHSHIFT) | 7;
69 }
70
71
72 /***********************************************************************
73  *           AllocSelectorArray   (KERNEL.206)
74  */
75 WORD WINAPI AllocSelectorArray16( WORD count )
76 {
77     WORD i, sel = SELECTOR_AllocArray( count );
78
79     if (sel)
80     {
81         LDT_ENTRY entry;
82         wine_ldt_set_base( &entry, 0 );
83         wine_ldt_set_limit( &entry, 1 ); /* avoid 0 base and limit */
84         wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_DATA );
85         for (i = 0; i < count; i++) wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
86     }
87     return sel;
88 }
89
90
91 /***********************************************************************
92  *           AllocSelector   (KERNEL.175)
93  */
94 WORD WINAPI AllocSelector16( WORD sel )
95 {
96     WORD newsel, count, i;
97
98     count = sel ? get_sel_count(sel) : 1;
99     newsel = SELECTOR_AllocArray( count );
100     TRACE("(%04x): returning %04x\n", sel, newsel );
101     if (!newsel) return 0;
102     if (!sel) return newsel;  /* nothing to copy */
103     for (i = 0; i < count; i++)
104     {
105         LDT_ENTRY entry;
106         wine_ldt_get_entry( sel + (i << __AHSHIFT), &entry );
107         wine_ldt_set_entry( newsel + (i << __AHSHIFT), &entry );
108     }
109     return newsel;
110 }
111
112
113 /***********************************************************************
114  *           FreeSelector   (KERNEL.176)
115  */
116 WORD WINAPI FreeSelector16( WORD sel )
117 {
118     if (IS_SELECTOR_FREE(sel)) return sel;  /* error */
119
120 #ifdef __i386__
121     /* Check if we are freeing current %fs or %gs selector */
122     if (!((wine_get_fs() ^ sel) & ~3))
123     {
124         WARN("Freeing %%fs selector (%04x), not good.\n", wine_get_fs() );
125         wine_set_fs( 0 );
126     }
127     if (!((wine_get_gs() ^ sel) & ~3)) wine_set_gs( 0 );
128 #endif  /* __i386__ */
129
130     wine_ldt_set_entry( sel, &null_entry );
131     wine_ldt_copy.flags[sel >> __AHSHIFT] &= ~WINE_LDT_FLAGS_ALLOCATED;
132     return 0;
133 }
134
135
136 /***********************************************************************
137  *           SELECTOR_FreeFs
138  *
139  * Free the current %fs selector.
140  */
141 void SELECTOR_FreeFs(void)
142 {
143     WORD fs = wine_get_fs();
144     if (fs)
145     {
146         wine_ldt_copy.flags[fs >> __AHSHIFT] &= ~WINE_LDT_FLAGS_ALLOCATED;
147         wine_set_fs(0);
148         wine_ldt_set_entry( fs, &null_entry );
149     }
150 }
151
152
153 /***********************************************************************
154  *           SELECTOR_SetEntries
155  *
156  * Set the LDT entries for an array of selectors.
157  */
158 static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size, unsigned char flags )
159 {
160     LDT_ENTRY entry;
161     WORD i, count;
162
163     wine_ldt_set_base( &entry, base );
164     wine_ldt_set_limit( &entry, size - 1 );
165     wine_ldt_set_flags( &entry, flags );
166     count = (size + 0xffff) / 0x10000;
167     for (i = 0; i < count; i++)
168     {
169         wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
170         wine_ldt_set_base( &entry, (char*)wine_ldt_get_base(&entry) + 0x10000);
171         /* yep, Windows sets limit like that, not 64K sel units */
172         wine_ldt_set_limit( &entry, wine_ldt_get_limit(&entry) - 0x10000 );
173     }
174 }
175
176
177 /***********************************************************************
178  *           SELECTOR_AllocBlock
179  *
180  * Allocate selectors for a block of linear memory.
181  */
182 WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags )
183 {
184     WORD sel, count;
185
186     if (!size) return 0;
187     count = (size + 0xffff) / 0x10000;
188     sel = SELECTOR_AllocArray( count );
189     if (sel) SELECTOR_SetEntries( sel, base, size, flags );
190     return sel;
191 }
192
193
194 /***********************************************************************
195  *           SELECTOR_FreeBlock
196  *
197  * Free a block of selectors.
198  */
199 void SELECTOR_FreeBlock( WORD sel )
200 {
201     WORD i, count = get_sel_count( sel );
202
203     TRACE("(%04x,%d)\n", sel, count );
204     for (i = 0; i < count; i++) FreeSelector16( sel + (i << __AHSHIFT) );
205 }
206
207
208 /***********************************************************************
209  *           SELECTOR_ReallocBlock
210  *
211  * Change the size of a block of selectors.
212  */
213 WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size )
214 {
215     LDT_ENTRY entry;
216     WORD i, oldcount, newcount;
217
218     if (!size) size = 1;
219     oldcount = get_sel_count( sel );
220     newcount = (size + 0xffff) >> 16;
221     wine_ldt_get_entry( sel, &entry );
222
223     if (oldcount < newcount)  /* We need to add selectors */
224     {
225         WORD index = sel >> __AHSHIFT;
226           /* Check if the next selectors are free */
227         if (index + newcount > LDT_SIZE) i = oldcount;
228         else
229             for (i = oldcount; i < newcount; i++)
230                 if (wine_ldt_copy.flags[index+i] & WINE_LDT_FLAGS_ALLOCATED) break;
231
232         if (i < newcount)  /* they are not free */
233         {
234             SELECTOR_FreeBlock( sel );
235             sel = SELECTOR_AllocArray( newcount );
236         }
237         else  /* mark the selectors as allocated */
238         {
239             for (i = oldcount; i < newcount; i++)
240                 wine_ldt_copy.flags[index+i] |= WINE_LDT_FLAGS_ALLOCATED;
241         }
242     }
243     else if (oldcount > newcount) /* We need to remove selectors */
244     {
245         SELECTOR_FreeBlock( sel + (newcount << __AHSHIFT) );
246     }
247     if (sel) SELECTOR_SetEntries( sel, base, size, wine_ldt_get_flags(&entry) );
248     return sel;
249 }
250
251
252 /***********************************************************************
253  *           PrestoChangoSelector   (KERNEL.177)
254  */
255 WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
256 {
257     LDT_ENTRY entry;
258     wine_ldt_get_entry( selSrc, &entry );
259     /* toggle the executable bit */
260     entry.HighWord.Bits.Type ^= (WINE_LDT_FLAGS_CODE ^ WINE_LDT_FLAGS_DATA);
261     wine_ldt_set_entry( selDst, &entry );
262     return selDst;
263 }
264
265
266 /***********************************************************************
267  *           AllocCStoDSAlias   (KERNEL.170)
268  *           AllocAlias         (KERNEL.172)
269  */
270 WORD WINAPI AllocCStoDSAlias16( WORD sel )
271 {
272     WORD newsel;
273     LDT_ENTRY entry;
274
275     newsel = SELECTOR_AllocArray( 1 );
276     TRACE("(%04x): returning %04x\n",
277                       sel, newsel );
278     if (!newsel) return 0;
279     wine_ldt_get_entry( sel, &entry );
280     entry.HighWord.Bits.Type = WINE_LDT_FLAGS_DATA;
281     wine_ldt_set_entry( newsel, &entry );
282     return newsel;
283 }
284
285
286 /***********************************************************************
287  *           AllocDStoCSAlias   (KERNEL.171)
288  */
289 WORD WINAPI AllocDStoCSAlias16( WORD sel )
290 {
291     WORD newsel;
292     LDT_ENTRY entry;
293
294     newsel = SELECTOR_AllocArray( 1 );
295     TRACE("(%04x): returning %04x\n",
296                       sel, newsel );
297     if (!newsel) return 0;
298     wine_ldt_get_entry( sel, &entry );
299     entry.HighWord.Bits.Type = WINE_LDT_FLAGS_CODE;
300     wine_ldt_set_entry( newsel, &entry );
301     return newsel;
302 }
303
304
305 /***********************************************************************
306  *           LongPtrAdd   (KERNEL.180)
307  */
308 void WINAPI LongPtrAdd16( DWORD ptr, DWORD add )
309 {
310     LDT_ENTRY entry;
311     wine_ldt_get_entry( SELECTOROF(ptr), &entry );
312     wine_ldt_set_base( &entry, (char *)wine_ldt_get_base(&entry) + add );
313     wine_ldt_set_entry( SELECTOROF(ptr), &entry );
314 }
315
316
317 /***********************************************************************
318  *             GetSelectorBase   (KERNEL.186)
319  */
320 DWORD WINAPI GetSelectorBase( WORD sel )
321 {
322     void *base = wine_ldt_copy.base[sel >> __AHSHIFT];
323
324     /* if base points into DOSMEM, assume we have to
325      * return pointer into physical lower 1MB */
326
327     return DOSMEM_MapLinearToDos( base );
328 }
329
330
331 /***********************************************************************
332  *             SetSelectorBase   (KERNEL.187)
333  */
334 WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
335 {
336     LDT_ENTRY entry;
337     wine_ldt_get_entry( sel, &entry );
338     wine_ldt_set_base( &entry, DOSMEM_MapDosToLinear(base) );
339     wine_ldt_set_entry( sel, &entry );
340     return sel;
341 }
342
343
344 /***********************************************************************
345  *           GetSelectorLimit   (KERNEL.188)
346  */
347 DWORD WINAPI GetSelectorLimit16( WORD sel )
348 {
349     return wine_ldt_copy.limit[sel >> __AHSHIFT];
350 }
351
352
353 /***********************************************************************
354  *           SetSelectorLimit   (KERNEL.189)
355  */
356 WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
357 {
358     LDT_ENTRY entry;
359     wine_ldt_get_entry( sel, &entry );
360     wine_ldt_set_limit( &entry, limit );
361     wine_ldt_set_entry( sel, &entry );
362     return sel;
363 }
364
365
366 /***********************************************************************
367  *           SelectorAccessRights   (KERNEL.196)
368  */
369 WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
370 {
371     LDT_ENTRY entry;
372     wine_ldt_get_entry( sel, &entry );
373
374     if (op == 0)  /* get */
375     {
376         return entry.HighWord.Bytes.Flags1 | ((entry.HighWord.Bytes.Flags2 << 8) & 0xf0);
377     }
378     else  /* set */
379     {
380         entry.HighWord.Bytes.Flags1 = LOBYTE(val) | 0xf0;
381         entry.HighWord.Bytes.Flags2 = (entry.HighWord.Bytes.Flags2 & 0x0f) | (HIBYTE(val) & 0xf0);
382         wine_ldt_set_entry( sel, &entry );
383         return 0;
384     }
385 }
386
387
388 /***********************************************************************
389  *           IsBadCodePtr   (KERNEL.336)
390  */
391 BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
392 {
393     WORD sel;
394     LDT_ENTRY entry;
395
396     sel = SELECTOROF(lpfn);
397     if (!sel) return TRUE;
398     if (IS_SELECTOR_FREE(sel)) return TRUE;
399     wine_ldt_get_entry( sel, &entry );
400     /* check for code segment, ignoring conforming, read-only and accessed bits */
401     if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_CODE) & 0x18) return TRUE;
402     if (OFFSETOF(lpfn) > wine_ldt_get_limit(&entry)) return TRUE;
403     return FALSE;
404 }
405
406
407 /***********************************************************************
408  *           IsBadStringPtr   (KERNEL.337)
409  */
410 BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
411 {
412     WORD sel;
413     LDT_ENTRY entry;
414
415     sel = SELECTOROF(ptr);
416     if (!sel) return TRUE;
417     if (IS_SELECTOR_FREE(sel)) return TRUE;
418     wine_ldt_get_entry( sel, &entry );
419     /* check for data or readable code segment */
420     if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE;  /* system descriptor */
421     if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE;  /* non-readable code segment */
422     if (strlen(MapSL(ptr)) < size) size = strlen(MapSL(ptr)) + 1;
423     if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit(&entry))) return TRUE;
424     return FALSE;
425 }
426
427
428 /***********************************************************************
429  *           IsBadHugeReadPtr   (KERNEL.346)
430  */
431 BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
432 {
433     WORD sel;
434     LDT_ENTRY entry;
435
436     sel = SELECTOROF(ptr);
437     if (!sel) return TRUE;
438     if (IS_SELECTOR_FREE(sel)) return TRUE;
439     wine_ldt_get_entry( sel, &entry );
440     /* check for data or readable code segment */
441     if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE;  /* system descriptor */
442     if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE;  /* non-readable code segment */
443     if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
444     return FALSE;
445 }
446
447
448 /***********************************************************************
449  *           IsBadHugeWritePtr   (KERNEL.347)
450  */
451 BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
452 {
453     WORD sel;
454     LDT_ENTRY entry;
455
456     sel = SELECTOROF(ptr);
457     if (!sel) return TRUE;
458     if (IS_SELECTOR_FREE(sel)) return TRUE;
459     wine_ldt_get_entry( sel, &entry );
460     /* check for writeable data segment, ignoring expand-down and accessed flags */
461     if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_DATA) & ~5) return TRUE;
462     if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
463     return FALSE;
464 }
465
466 /***********************************************************************
467  *           IsBadReadPtr   (KERNEL.334)
468  */
469 BOOL16 WINAPI IsBadReadPtr16( SEGPTR ptr, UINT16 size )
470 {
471     return IsBadHugeReadPtr16( ptr, size );
472 }
473
474
475 /***********************************************************************
476  *           IsBadWritePtr   (KERNEL.335)
477  */
478 BOOL16 WINAPI IsBadWritePtr16( SEGPTR ptr, UINT16 size )
479 {
480     return IsBadHugeWritePtr16( ptr, size );
481 }
482
483
484 /***********************************************************************
485  *           IsBadFlatReadWritePtr   (KERNEL.627)
486  */
487 BOOL16 WINAPI IsBadFlatReadWritePtr16( SEGPTR ptr, DWORD size, BOOL16 bWrite )
488 {
489     return bWrite? IsBadHugeWritePtr16( ptr, size )
490                  : IsBadHugeReadPtr16( ptr, size );
491 }
492
493
494 /***********************************************************************
495  *           MemoryRead   (TOOLHELP.78)
496  */
497 DWORD WINAPI MemoryRead16( WORD sel, DWORD offset, void *buffer, DWORD count )
498 {
499     WORD index = sel >> __AHSHIFT;
500
501     if (!(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED)) return 0;
502     if (offset > wine_ldt_copy.limit[index]) return 0;
503     if (offset + count > wine_ldt_copy.limit[index] + 1)
504         count = wine_ldt_copy.limit[index] + 1 - offset;
505     memcpy( buffer, (char *)wine_ldt_copy.base[index] + offset, count );
506     return count;
507 }
508
509
510 /***********************************************************************
511  *           MemoryWrite   (TOOLHELP.79)
512  */
513 DWORD WINAPI MemoryWrite16( WORD sel, DWORD offset, void *buffer, DWORD count )
514 {
515     WORD index = sel >> __AHSHIFT;
516
517     if (!(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED)) return 0;
518     if (offset > wine_ldt_copy.limit[index]) return 0;
519     if (offset + count > wine_ldt_copy.limit[index] + 1)
520         count = wine_ldt_copy.limit[index] + 1 - offset;
521     memcpy( (char *)wine_ldt_copy.base[index] + offset, buffer, count );
522     return count;
523 }
524
525 /************************************* Win95 pointer mapping functions *
526  *
527  */
528
529 struct mapls_entry
530 {
531     struct mapls_entry *next;
532     void               *addr;   /* linear address */
533     int                 count;  /* ref count */
534     WORD                sel;    /* selector */
535 };
536
537 static struct mapls_entry *first_entry;
538
539
540 /***********************************************************************
541  *           MapLS   (KERNEL32.@)
542  *           MapLS   (KERNEL.358)
543  *
544  * Maps linear pointer to segmented.
545  */
546 SEGPTR WINAPI MapLS( LPCVOID ptr )
547 {
548     struct mapls_entry *entry, *free = NULL;
549     void *base;
550     SEGPTR ret = 0;
551
552     if (!HIWORD(ptr)) return (SEGPTR)ptr;
553
554     base = (char *)ptr - ((unsigned int)ptr & 0x7fff);
555     HeapLock( GetProcessHeap() );
556     for (entry = first_entry; entry; entry = entry->next)
557     {
558         if (entry->addr == base) break;
559         if (!entry->count) free = entry;
560     }
561
562     if (!entry)
563     {
564         if (!free)  /* no free entry found, create a new one */
565         {
566             if (!(free = HeapAlloc( GetProcessHeap(), 0, sizeof(*free) ))) goto done;
567             if (!(free->sel = SELECTOR_AllocBlock( base, 0x10000, WINE_LDT_FLAGS_DATA )))
568             {
569                 HeapFree( GetProcessHeap(), 0, free );
570                 goto done;
571             }
572             free->count = 0;
573             free->next = first_entry;
574             first_entry = free;
575         }
576         SetSelectorBase( free->sel, (DWORD)base );
577         free->addr = base;
578         entry = free;
579     }
580     entry->count++;
581     ret = MAKESEGPTR( entry->sel, (char *)ptr - (char *)entry->addr );
582  done:
583     HeapUnlock( GetProcessHeap() );
584     return ret;
585 }
586
587 /***********************************************************************
588  *           UnMapLS   (KERNEL32.@)
589  *           UnMapLS   (KERNEL.359)
590  *
591  * Free mapped selector.
592  */
593 void WINAPI UnMapLS( SEGPTR sptr )
594 {
595     struct mapls_entry *entry;
596     WORD sel = SELECTOROF(sptr);
597
598     if (sel)
599     {
600         HeapLock( GetProcessHeap() );
601         for (entry = first_entry; entry; entry = entry->next) if (entry->sel == sel) break;
602         if (entry && entry->count > 0) entry->count--;
603         HeapUnlock( GetProcessHeap() );
604     }
605 }
606
607 /***********************************************************************
608  *           MapSL   (KERNEL32.@)
609  *           MapSL   (KERNEL.357)
610  *
611  * Maps fixed segmented pointer to linear.
612  */
613 LPVOID WINAPI MapSL( SEGPTR sptr )
614 {
615     return (char *)wine_ldt_copy.base[SELECTOROF(sptr) >> __AHSHIFT] + OFFSETOF(sptr);
616 }
617
618 /***********************************************************************
619  *           MapSLFix   (KERNEL32.@)
620  *
621  * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
622  * unexpected linear address change when GlobalCompact() shuffles
623  * moveable blocks.
624  */
625
626 LPVOID WINAPI MapSLFix( SEGPTR sptr )
627 {
628     return MapSL(sptr);
629 }
630
631 /***********************************************************************
632  *           UnMapSLFixArray   (KERNEL32.@)
633  */
634
635 void WINAPI UnMapSLFixArray( SEGPTR sptr[], INT length, CONTEXT86 *context )
636 {
637     /* Must not change EAX, hence defined as 'register' function */
638 }
639
640 /***********************************************************************
641  *           GetThreadSelectorEntry   (KERNEL32.@)
642  */
643 BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldtent)
644 {
645 #ifdef __i386__
646     BOOL ret;
647
648     if (!(sel & 4))  /* GDT selector */
649     {
650         sel &= ~3;  /* ignore RPL */
651         if (!sel)  /* null selector */
652         {
653             memset( ldtent, 0, sizeof(*ldtent) );
654             return TRUE;
655         }
656         ldtent->BaseLow                   = 0;
657         ldtent->HighWord.Bits.BaseMid     = 0;
658         ldtent->HighWord.Bits.BaseHi      = 0;
659         ldtent->LimitLow                  = 0xffff;
660         ldtent->HighWord.Bits.LimitHi     = 0xf;
661         ldtent->HighWord.Bits.Dpl         = 3;
662         ldtent->HighWord.Bits.Sys         = 0;
663         ldtent->HighWord.Bits.Pres        = 1;
664         ldtent->HighWord.Bits.Granularity = 1;
665         ldtent->HighWord.Bits.Default_Big = 1;
666         ldtent->HighWord.Bits.Type        = 0x12;
667         /* it has to be one of the system GDT selectors */
668         if (sel == (wine_get_ds() & ~3)) return TRUE;
669         if (sel == (wine_get_ss() & ~3)) return TRUE;
670         if (sel == (wine_get_cs() & ~3))
671         {
672             ldtent->HighWord.Bits.Type |= 8;  /* code segment */
673             return TRUE;
674         }
675         SetLastError( ERROR_NOACCESS );
676         return FALSE;
677     }
678
679     SERVER_START_REQ( get_selector_entry )
680     {
681         req->handle = hthread;
682         req->entry = sel >> __AHSHIFT;
683         if ((ret = !wine_server_call_err( req )))
684         {
685             if (!(reply->flags & WINE_LDT_FLAGS_ALLOCATED))
686             {
687                 SetLastError( ERROR_MR_MID_NOT_FOUND );  /* sic */
688                 ret = FALSE;
689             }
690             else
691             {
692                 wine_ldt_set_base( ldtent, (void *)reply->base );
693                 wine_ldt_set_limit( ldtent, reply->limit );
694                 wine_ldt_set_flags( ldtent, reply->flags );
695             }
696         }
697     }
698     SERVER_END_REQ;
699     return ret;
700 #else
701     SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
702     return FALSE;
703 #endif
704 }
705
706
707 /**********************************************************************
708  *              SMapLS*         (KERNEL32)
709  * These functions map linear pointers at [EBP+xxx] to segmented pointers
710  * and return them.
711  * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
712  * unravel them at SUnMapLS. We just store the segmented pointer there.
713  */
714 static void
715 x_SMapLS_IP_EBP_x(CONTEXT86 *context,int argoff) {
716     DWORD       val,ptr;
717
718     val =*(DWORD*)(context->Ebp + argoff);
719     if (val<0x10000) {
720         ptr=val;
721         *(DWORD*)(context->Ebp + argoff) = 0;
722     } else {
723         ptr = MapLS((LPVOID)val);
724         *(DWORD*)(context->Ebp + argoff) = ptr;
725     }
726     context->Eax = ptr;
727 }
728
729 /***********************************************************************
730  *              SMapLS_IP_EBP_8 (KERNEL32.@)
731  */
732 void WINAPI SMapLS_IP_EBP_8 (CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context, 8);}
733
734 /***********************************************************************
735  *              SMapLS_IP_EBP_12 (KERNEL32.@)
736  */
737 void WINAPI SMapLS_IP_EBP_12(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,12);}
738
739 /***********************************************************************
740  *              SMapLS_IP_EBP_16 (KERNEL32.@)
741  */
742 void WINAPI SMapLS_IP_EBP_16(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,16);}
743
744 /***********************************************************************
745  *              SMapLS_IP_EBP_20 (KERNEL32.@)
746  */
747 void WINAPI SMapLS_IP_EBP_20(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,20);}
748
749 /***********************************************************************
750  *              SMapLS_IP_EBP_24 (KERNEL32.@)
751  */
752 void WINAPI SMapLS_IP_EBP_24(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,24);}
753
754 /***********************************************************************
755  *              SMapLS_IP_EBP_28 (KERNEL32.@)
756  */
757 void WINAPI SMapLS_IP_EBP_28(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,28);}
758
759 /***********************************************************************
760  *              SMapLS_IP_EBP_32 (KERNEL32.@)
761  */
762 void WINAPI SMapLS_IP_EBP_32(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,32);}
763
764 /***********************************************************************
765  *              SMapLS_IP_EBP_36 (KERNEL32.@)
766  */
767 void WINAPI SMapLS_IP_EBP_36(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,36);}
768
769 /***********************************************************************
770  *              SMapLS_IP_EBP_40 (KERNEL32.@)
771  */
772 void WINAPI SMapLS_IP_EBP_40(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,40);}
773
774 /***********************************************************************
775  *              SMapLS (KERNEL32.@)
776  */
777 void WINAPI SMapLS( CONTEXT86 *context )
778 {
779     if (HIWORD(context->Eax))
780     {
781         context->Eax = MapLS( (LPVOID)context->Eax );
782         context->Edx = context->Eax;
783     } else {
784         context->Edx = 0;
785     }
786 }
787
788 /***********************************************************************
789  *              SUnMapLS (KERNEL32.@)
790  */
791
792 void WINAPI SUnMapLS( CONTEXT86 *context )
793 {
794     if (HIWORD(context->Eax)) UnMapLS( (SEGPTR)context->Eax );
795 }
796
797 inline static void x_SUnMapLS_IP_EBP_x(CONTEXT86 *context,int argoff)
798 {
799     SEGPTR *ptr = (SEGPTR *)(context->Ebp + argoff);
800     if (*ptr)
801     {
802         UnMapLS( *ptr );
803         *ptr = 0;
804     }
805 }
806
807 /***********************************************************************
808  *              SUnMapLS_IP_EBP_8 (KERNEL32.@)
809  */
810 void WINAPI SUnMapLS_IP_EBP_8 (CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context, 8); }
811
812 /***********************************************************************
813  *              SUnMapLS_IP_EBP_12 (KERNEL32.@)
814  */
815 void WINAPI SUnMapLS_IP_EBP_12(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,12); }
816
817 /***********************************************************************
818  *              SUnMapLS_IP_EBP_16 (KERNEL32.@)
819  */
820 void WINAPI SUnMapLS_IP_EBP_16(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,16); }
821
822 /***********************************************************************
823  *              SUnMapLS_IP_EBP_20 (KERNEL32.@)
824  */
825 void WINAPI SUnMapLS_IP_EBP_20(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,20); }
826
827 /***********************************************************************
828  *              SUnMapLS_IP_EBP_24 (KERNEL32.@)
829  */
830 void WINAPI SUnMapLS_IP_EBP_24(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,24); }
831
832 /***********************************************************************
833  *              SUnMapLS_IP_EBP_28 (KERNEL32.@)
834  */
835 void WINAPI SUnMapLS_IP_EBP_28(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,28); }
836
837 /***********************************************************************
838  *              SUnMapLS_IP_EBP_32 (KERNEL32.@)
839  */
840 void WINAPI SUnMapLS_IP_EBP_32(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,32); }
841
842 /***********************************************************************
843  *              SUnMapLS_IP_EBP_36 (KERNEL32.@)
844  */
845 void WINAPI SUnMapLS_IP_EBP_36(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,36); }
846
847 /***********************************************************************
848  *              SUnMapLS_IP_EBP_40 (KERNEL32.@)
849  */
850 void WINAPI SUnMapLS_IP_EBP_40(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,40); }
851
852 /**********************************************************************
853  *              AllocMappedBuffer       (KERNEL32.38)
854  *
855  * This is a undocumented KERNEL32 function that
856  * SMapLS's a GlobalAlloc'ed buffer.
857  *
858  * Input:   EDI register: size of buffer to allocate
859  * Output:  EDI register: pointer to buffer
860  *
861  * Note: The buffer is preceded by 8 bytes:
862  *        ...
863  *       edi+0   buffer
864  *       edi-4   SEGPTR to buffer
865  *       edi-8   some magic Win95 needs for SUnMapLS
866  *               (we use it for the memory handle)
867  *
868  *       The SEGPTR is used by the caller!
869  */
870
871 void WINAPI AllocMappedBuffer( CONTEXT86 *context )
872 {
873     HGLOBAL handle = GlobalAlloc(0, context->Edi + 8);
874     DWORD *buffer = (DWORD *)GlobalLock(handle);
875     SEGPTR ptr = 0;
876
877     if (buffer)
878         if (!(ptr = MapLS(buffer + 2)))
879         {
880             GlobalUnlock(handle);
881             GlobalFree(handle);
882         }
883
884     if (!ptr)
885         context->Eax = context->Edi = 0;
886     else
887     {
888         buffer[0] = (DWORD)handle;
889         buffer[1] = ptr;
890
891         context->Eax = (DWORD) ptr;
892         context->Edi = (DWORD)(buffer + 2);
893     }
894 }
895
896 /**********************************************************************
897  *              FreeMappedBuffer        (KERNEL32.39)
898  *
899  * Free a buffer allocated by AllocMappedBuffer
900  *
901  * Input: EDI register: pointer to buffer
902  */
903
904 void WINAPI FreeMappedBuffer( CONTEXT86 *context )
905 {
906     if (context->Edi)
907     {
908         DWORD *buffer = (DWORD *)context->Edi - 2;
909
910         UnMapLS(buffer[1]);
911
912         GlobalUnlock((HGLOBAL)buffer[0]);
913         GlobalFree((HGLOBAL)buffer[0]);
914     }
915 }