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