Don't build d3d8 if we don't have OpenGL support.
[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 WIN16_GetSelectorBase( WORD sel )
321 {
322     /*
323      * Note: For Win32s processes, the whole linear address space is
324      *       shifted by 0x10000 relative to the OS linear address space.
325      *       See the comment in msdos/vxd.c.
326      */
327
328     DWORD base = GetSelectorBase( sel );
329     return W32S_WINE2APP( base );
330 }
331
332 /***********************************************************************
333  *              GetSelectorBase
334  */
335 DWORD WINAPI GetSelectorBase( WORD sel )
336 {
337     void *base = wine_ldt_copy.base[sel >> __AHSHIFT];
338
339     /* if base points into DOSMEM, assume we have to
340      * return pointer into physical lower 1MB */
341
342     return DOSMEM_MapLinearToDos( base );
343 }
344
345
346 /***********************************************************************
347  *           SetSelectorBase   (KERNEL.187)
348  */
349 DWORD WINAPI WIN16_SetSelectorBase( WORD sel, DWORD base )
350 {
351     /*
352      * Note: For Win32s processes, the whole linear address space is
353      *       shifted by 0x10000 relative to the OS linear address space.
354      *       See the comment in msdos/vxd.c.
355      */
356
357     SetSelectorBase( sel, W32S_APP2WINE( base ) );
358     return sel;
359 }
360
361 /***********************************************************************
362  *              SetSelectorBase
363  */
364 WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
365 {
366     LDT_ENTRY entry;
367     wine_ldt_get_entry( sel, &entry );
368     wine_ldt_set_base( &entry, DOSMEM_MapDosToLinear(base) );
369     wine_ldt_set_entry( sel, &entry );
370     return sel;
371 }
372
373
374 /***********************************************************************
375  *           GetSelectorLimit   (KERNEL.188)
376  */
377 DWORD WINAPI GetSelectorLimit16( WORD sel )
378 {
379     return wine_ldt_copy.limit[sel >> __AHSHIFT];
380 }
381
382
383 /***********************************************************************
384  *           SetSelectorLimit   (KERNEL.189)
385  */
386 WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
387 {
388     LDT_ENTRY entry;
389     wine_ldt_get_entry( sel, &entry );
390     wine_ldt_set_limit( &entry, limit );
391     wine_ldt_set_entry( sel, &entry );
392     return sel;
393 }
394
395
396 /***********************************************************************
397  *           SelectorAccessRights   (KERNEL.196)
398  */
399 WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
400 {
401     LDT_ENTRY entry;
402     wine_ldt_get_entry( sel, &entry );
403
404     if (op == 0)  /* get */
405     {
406         return entry.HighWord.Bytes.Flags1 | ((entry.HighWord.Bytes.Flags2 << 8) & 0xf0);
407     }
408     else  /* set */
409     {
410         entry.HighWord.Bytes.Flags1 = LOBYTE(val) | 0xf0;
411         entry.HighWord.Bytes.Flags2 = (entry.HighWord.Bytes.Flags2 & 0x0f) | (HIBYTE(val) & 0xf0);
412         wine_ldt_set_entry( sel, &entry );
413         return 0;
414     }
415 }
416
417
418 /***********************************************************************
419  *           IsBadCodePtr   (KERNEL.336)
420  */
421 BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
422 {
423     WORD sel;
424     LDT_ENTRY entry;
425
426     sel = SELECTOROF(lpfn);
427     if (!sel) return TRUE;
428     if (IS_SELECTOR_FREE(sel)) return TRUE;
429     wine_ldt_get_entry( sel, &entry );
430     /* check for code segment, ignoring conforming, read-only and accessed bits */
431     if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_CODE) & 0x18) return TRUE;
432     if (OFFSETOF(lpfn) > wine_ldt_get_limit(&entry)) return TRUE;
433     return FALSE;
434 }
435
436
437 /***********************************************************************
438  *           IsBadStringPtr   (KERNEL.337)
439  */
440 BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
441 {
442     WORD sel;
443     LDT_ENTRY entry;
444
445     sel = SELECTOROF(ptr);
446     if (!sel) return TRUE;
447     if (IS_SELECTOR_FREE(sel)) return TRUE;
448     wine_ldt_get_entry( sel, &entry );
449     /* check for data or readable code segment */
450     if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE;  /* system descriptor */
451     if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE;  /* non-readable code segment */
452     if (strlen(MapSL(ptr)) < size) size = strlen(MapSL(ptr)) + 1;
453     if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit(&entry))) return TRUE;
454     return FALSE;
455 }
456
457
458 /***********************************************************************
459  *           IsBadHugeReadPtr   (KERNEL.346)
460  */
461 BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
462 {
463     WORD sel;
464     LDT_ENTRY entry;
465
466     sel = SELECTOROF(ptr);
467     if (!sel) return TRUE;
468     if (IS_SELECTOR_FREE(sel)) return TRUE;
469     wine_ldt_get_entry( sel, &entry );
470     /* check for data or readable code segment */
471     if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE;  /* system descriptor */
472     if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE;  /* non-readable code segment */
473     if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
474     return FALSE;
475 }
476
477
478 /***********************************************************************
479  *           IsBadHugeWritePtr   (KERNEL.347)
480  */
481 BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
482 {
483     WORD sel;
484     LDT_ENTRY entry;
485
486     sel = SELECTOROF(ptr);
487     if (!sel) return TRUE;
488     if (IS_SELECTOR_FREE(sel)) return TRUE;
489     wine_ldt_get_entry( sel, &entry );
490     /* check for writeable data segment, ignoring expand-down and accessed flags */
491     if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_DATA) & ~5) return TRUE;
492     if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
493     return FALSE;
494 }
495
496 /***********************************************************************
497  *           IsBadReadPtr   (KERNEL.334)
498  */
499 BOOL16 WINAPI IsBadReadPtr16( SEGPTR ptr, UINT16 size )
500 {
501     return IsBadHugeReadPtr16( ptr, size );
502 }
503
504
505 /***********************************************************************
506  *           IsBadWritePtr   (KERNEL.335)
507  */
508 BOOL16 WINAPI IsBadWritePtr16( SEGPTR ptr, UINT16 size )
509 {
510     return IsBadHugeWritePtr16( ptr, size );
511 }
512
513
514 /***********************************************************************
515  *           IsBadFlatReadWritePtr   (KERNEL.627)
516  */
517 BOOL16 WINAPI IsBadFlatReadWritePtr16( SEGPTR ptr, DWORD size, BOOL16 bWrite )
518 {
519     return bWrite? IsBadHugeWritePtr16( ptr, size )
520                  : IsBadHugeReadPtr16( ptr, size );
521 }
522
523
524 /***********************************************************************
525  *           MemoryRead   (TOOLHELP.78)
526  */
527 DWORD WINAPI MemoryRead16( WORD sel, DWORD offset, void *buffer, DWORD count )
528 {
529     WORD index = sel >> __AHSHIFT;
530
531     if (!(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED)) return 0;
532     if (offset > wine_ldt_copy.limit[index]) return 0;
533     if (offset + count > wine_ldt_copy.limit[index] + 1)
534         count = wine_ldt_copy.limit[index] + 1 - offset;
535     memcpy( buffer, (char *)wine_ldt_copy.base[index] + offset, count );
536     return count;
537 }
538
539
540 /***********************************************************************
541  *           MemoryWrite   (TOOLHELP.79)
542  */
543 DWORD WINAPI MemoryWrite16( WORD sel, DWORD offset, void *buffer, DWORD count )
544 {
545     WORD index = sel >> __AHSHIFT;
546
547     if (!(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED)) return 0;
548     if (offset > wine_ldt_copy.limit[index]) return 0;
549     if (offset + count > wine_ldt_copy.limit[index] + 1)
550         count = wine_ldt_copy.limit[index] + 1 - offset;
551     memcpy( (char *)wine_ldt_copy.base[index] + offset, buffer, count );
552     return count;
553 }
554
555 /************************************* Win95 pointer mapping functions *
556  *
557  */
558
559 struct mapls_entry
560 {
561     struct mapls_entry *next;
562     void               *addr;   /* linear address */
563     int                 count;  /* ref count */
564     WORD                sel;    /* selector */
565 };
566
567 static struct mapls_entry *first_entry;
568
569
570 /***********************************************************************
571  *           MapLS   (KERNEL32.@)
572  *           MapLS   (KERNEL.358)
573  *
574  * Maps linear pointer to segmented.
575  */
576 SEGPTR WINAPI MapLS( LPCVOID ptr )
577 {
578     struct mapls_entry *entry, *free = NULL;
579     void *base;
580     SEGPTR ret = 0;
581
582     if (!HIWORD(ptr)) return (SEGPTR)ptr;
583
584     base = (char *)ptr - ((unsigned int)ptr & 0x7fff);
585     HeapLock( GetProcessHeap() );
586     for (entry = first_entry; entry; entry = entry->next)
587     {
588         if (entry->addr == base) break;
589         if (!entry->count) free = entry;
590     }
591
592     if (!entry)
593     {
594         if (!free)  /* no free entry found, create a new one */
595         {
596             if (!(free = HeapAlloc( GetProcessHeap(), 0, sizeof(*free) ))) goto done;
597             if (!(free->sel = SELECTOR_AllocBlock( base, 0x10000, WINE_LDT_FLAGS_DATA )))
598             {
599                 HeapFree( GetProcessHeap(), 0, free );
600                 goto done;
601             }
602             free->count = 0;
603             free->next = first_entry;
604             first_entry = free;
605         }
606         SetSelectorBase( free->sel, (DWORD)base );
607         free->addr = base;
608         entry = free;
609     }
610     entry->count++;
611     ret = MAKESEGPTR( entry->sel, (char *)ptr - (char *)entry->addr );
612  done:
613     HeapUnlock( GetProcessHeap() );
614     return ret;
615 }
616
617 /***********************************************************************
618  *           UnMapLS   (KERNEL32.@)
619  *           UnMapLS   (KERNEL.359)
620  *
621  * Free mapped selector.
622  */
623 void WINAPI UnMapLS( SEGPTR sptr )
624 {
625     struct mapls_entry *entry;
626     WORD sel = SELECTOROF(sptr);
627
628     if (sel)
629     {
630         HeapLock( GetProcessHeap() );
631         for (entry = first_entry; entry; entry = entry->next) if (entry->sel == sel) break;
632         if (entry && entry->count > 0) entry->count--;
633         HeapUnlock( GetProcessHeap() );
634     }
635 }
636
637 /***********************************************************************
638  *           MapSL   (KERNEL32.@)
639  *           MapSL   (KERNEL.357)
640  *
641  * Maps fixed segmented pointer to linear.
642  */
643 LPVOID WINAPI MapSL( SEGPTR sptr )
644 {
645     return (char *)wine_ldt_copy.base[SELECTOROF(sptr) >> __AHSHIFT] + OFFSETOF(sptr);
646 }
647
648 /***********************************************************************
649  *           MapSLFix   (KERNEL32.@)
650  *
651  * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
652  * unexpected linear address change when GlobalCompact() shuffles
653  * moveable blocks.
654  */
655
656 LPVOID WINAPI MapSLFix( SEGPTR sptr )
657 {
658     return MapSL(sptr);
659 }
660
661 /***********************************************************************
662  *           UnMapSLFixArray   (KERNEL32.@)
663  */
664
665 void WINAPI UnMapSLFixArray( SEGPTR sptr[], INT length, CONTEXT86 *context )
666 {
667     /* Must not change EAX, hence defined as 'register' function */
668 }
669
670 /***********************************************************************
671  *           GetThreadSelectorEntry   (KERNEL32.@)
672  */
673 BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldtent)
674 {
675 #ifdef __i386__
676     BOOL ret;
677
678     if (!(sel & 4))  /* GDT selector */
679     {
680         sel &= ~3;  /* ignore RPL */
681         if (!sel)  /* null selector */
682         {
683             memset( ldtent, 0, sizeof(*ldtent) );
684             return TRUE;
685         }
686         ldtent->BaseLow                   = 0;
687         ldtent->HighWord.Bits.BaseMid     = 0;
688         ldtent->HighWord.Bits.BaseHi      = 0;
689         ldtent->LimitLow                  = 0xffff;
690         ldtent->HighWord.Bits.LimitHi     = 0xf;
691         ldtent->HighWord.Bits.Dpl         = 3;
692         ldtent->HighWord.Bits.Sys         = 0;
693         ldtent->HighWord.Bits.Pres        = 1;
694         ldtent->HighWord.Bits.Granularity = 1;
695         ldtent->HighWord.Bits.Default_Big = 1;
696         ldtent->HighWord.Bits.Type        = 0x12;
697         /* it has to be one of the system GDT selectors */
698         if (sel == (wine_get_ds() & ~3)) return TRUE;
699         if (sel == (wine_get_ss() & ~3)) return TRUE;
700         if (sel == (wine_get_cs() & ~3))
701         {
702             ldtent->HighWord.Bits.Type |= 8;  /* code segment */
703             return TRUE;
704         }
705         SetLastError( ERROR_NOACCESS );
706         return FALSE;
707     }
708
709     SERVER_START_REQ( get_selector_entry )
710     {
711         req->handle = hthread;
712         req->entry = sel >> __AHSHIFT;
713         if ((ret = !wine_server_call_err( req )))
714         {
715             if (!(reply->flags & WINE_LDT_FLAGS_ALLOCATED))
716             {
717                 SetLastError( ERROR_MR_MID_NOT_FOUND );  /* sic */
718                 ret = FALSE;
719             }
720             else
721             {
722                 wine_ldt_set_base( ldtent, (void *)reply->base );
723                 wine_ldt_set_limit( ldtent, reply->limit );
724                 wine_ldt_set_flags( ldtent, reply->flags );
725             }
726         }
727     }
728     SERVER_END_REQ;
729     return ret;
730 #else
731     SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
732     return FALSE;
733 #endif
734 }
735
736
737 /**********************************************************************
738  *              SMapLS*         (KERNEL32)
739  * These functions map linear pointers at [EBP+xxx] to segmented pointers
740  * and return them.
741  * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
742  * unravel them at SUnMapLS. We just store the segmented pointer there.
743  */
744 static void
745 x_SMapLS_IP_EBP_x(CONTEXT86 *context,int argoff) {
746     DWORD       val,ptr;
747
748     val =*(DWORD*)(context->Ebp + argoff);
749     if (val<0x10000) {
750         ptr=val;
751         *(DWORD*)(context->Ebp + argoff) = 0;
752     } else {
753         ptr = MapLS((LPVOID)val);
754         *(DWORD*)(context->Ebp + argoff) = ptr;
755     }
756     context->Eax = ptr;
757 }
758
759 /***********************************************************************
760  *              SMapLS_IP_EBP_8 (KERNEL32.@)
761  */
762 void WINAPI SMapLS_IP_EBP_8 (CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context, 8);}
763
764 /***********************************************************************
765  *              SMapLS_IP_EBP_12 (KERNEL32.@)
766  */
767 void WINAPI SMapLS_IP_EBP_12(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,12);}
768
769 /***********************************************************************
770  *              SMapLS_IP_EBP_16 (KERNEL32.@)
771  */
772 void WINAPI SMapLS_IP_EBP_16(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,16);}
773
774 /***********************************************************************
775  *              SMapLS_IP_EBP_20 (KERNEL32.@)
776  */
777 void WINAPI SMapLS_IP_EBP_20(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,20);}
778
779 /***********************************************************************
780  *              SMapLS_IP_EBP_24 (KERNEL32.@)
781  */
782 void WINAPI SMapLS_IP_EBP_24(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,24);}
783
784 /***********************************************************************
785  *              SMapLS_IP_EBP_28 (KERNEL32.@)
786  */
787 void WINAPI SMapLS_IP_EBP_28(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,28);}
788
789 /***********************************************************************
790  *              SMapLS_IP_EBP_32 (KERNEL32.@)
791  */
792 void WINAPI SMapLS_IP_EBP_32(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,32);}
793
794 /***********************************************************************
795  *              SMapLS_IP_EBP_36 (KERNEL32.@)
796  */
797 void WINAPI SMapLS_IP_EBP_36(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,36);}
798
799 /***********************************************************************
800  *              SMapLS_IP_EBP_40 (KERNEL32.@)
801  */
802 void WINAPI SMapLS_IP_EBP_40(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,40);}
803
804 /***********************************************************************
805  *              SMapLS (KERNEL32.@)
806  */
807 void WINAPI SMapLS( CONTEXT86 *context )
808 {
809     if (HIWORD(context->Eax))
810     {
811         context->Eax = MapLS( (LPVOID)context->Eax );
812         context->Edx = context->Eax;
813     } else {
814         context->Edx = 0;
815     }
816 }
817
818 /***********************************************************************
819  *              SUnMapLS (KERNEL32.@)
820  */
821
822 void WINAPI SUnMapLS( CONTEXT86 *context )
823 {
824     if (HIWORD(context->Eax)) UnMapLS( (SEGPTR)context->Eax );
825 }
826
827 inline static void x_SUnMapLS_IP_EBP_x(CONTEXT86 *context,int argoff)
828 {
829     SEGPTR *ptr = (SEGPTR *)(context->Ebp + argoff);
830     if (*ptr)
831     {
832         UnMapLS( *ptr );
833         *ptr = 0;
834     }
835 }
836
837 /***********************************************************************
838  *              SUnMapLS_IP_EBP_8 (KERNEL32.@)
839  */
840 void WINAPI SUnMapLS_IP_EBP_8 (CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context, 8); }
841
842 /***********************************************************************
843  *              SUnMapLS_IP_EBP_12 (KERNEL32.@)
844  */
845 void WINAPI SUnMapLS_IP_EBP_12(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,12); }
846
847 /***********************************************************************
848  *              SUnMapLS_IP_EBP_16 (KERNEL32.@)
849  */
850 void WINAPI SUnMapLS_IP_EBP_16(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,16); }
851
852 /***********************************************************************
853  *              SUnMapLS_IP_EBP_20 (KERNEL32.@)
854  */
855 void WINAPI SUnMapLS_IP_EBP_20(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,20); }
856
857 /***********************************************************************
858  *              SUnMapLS_IP_EBP_24 (KERNEL32.@)
859  */
860 void WINAPI SUnMapLS_IP_EBP_24(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,24); }
861
862 /***********************************************************************
863  *              SUnMapLS_IP_EBP_28 (KERNEL32.@)
864  */
865 void WINAPI SUnMapLS_IP_EBP_28(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,28); }
866
867 /***********************************************************************
868  *              SUnMapLS_IP_EBP_32 (KERNEL32.@)
869  */
870 void WINAPI SUnMapLS_IP_EBP_32(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,32); }
871
872 /***********************************************************************
873  *              SUnMapLS_IP_EBP_36 (KERNEL32.@)
874  */
875 void WINAPI SUnMapLS_IP_EBP_36(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,36); }
876
877 /***********************************************************************
878  *              SUnMapLS_IP_EBP_40 (KERNEL32.@)
879  */
880 void WINAPI SUnMapLS_IP_EBP_40(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,40); }
881
882 /**********************************************************************
883  *              AllocMappedBuffer       (KERNEL32.38)
884  *
885  * This is a undocumented KERNEL32 function that
886  * SMapLS's a GlobalAlloc'ed buffer.
887  *
888  * Input:   EDI register: size of buffer to allocate
889  * Output:  EDI register: pointer to buffer
890  *
891  * Note: The buffer is preceded by 8 bytes:
892  *        ...
893  *       edi+0   buffer
894  *       edi-4   SEGPTR to buffer
895  *       edi-8   some magic Win95 needs for SUnMapLS
896  *               (we use it for the memory handle)
897  *
898  *       The SEGPTR is used by the caller!
899  */
900
901 void WINAPI AllocMappedBuffer( CONTEXT86 *context )
902 {
903     HGLOBAL handle = GlobalAlloc(0, context->Edi + 8);
904     DWORD *buffer = (DWORD *)GlobalLock(handle);
905     SEGPTR ptr = 0;
906
907     if (buffer)
908         if (!(ptr = MapLS(buffer + 2)))
909         {
910             GlobalUnlock(handle);
911             GlobalFree(handle);
912         }
913
914     if (!ptr)
915         context->Eax = context->Edi = 0;
916     else
917     {
918         buffer[0] = (DWORD)handle;
919         buffer[1] = ptr;
920
921         context->Eax = (DWORD) ptr;
922         context->Edi = (DWORD)(buffer + 2);
923     }
924 }
925
926 /**********************************************************************
927  *              FreeMappedBuffer        (KERNEL32.39)
928  *
929  * Free a buffer allocated by AllocMappedBuffer
930  *
931  * Input: EDI register: pointer to buffer
932  */
933
934 void WINAPI FreeMappedBuffer( CONTEXT86 *context )
935 {
936     if (context->Edi)
937     {
938         DWORD *buffer = (DWORD *)context->Edi - 2;
939
940         UnMapLS(buffer[1]);
941
942         GlobalUnlock((HGLOBAL)buffer[0]);
943         GlobalFree((HGLOBAL)buffer[0]);
944     }
945 }