fonts: Remove the rules for font symlinks and go back to standard VPATH usage.
[wine] / dlls / krnl386.exe16 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <string.h>
25
26 #include "wine/winbase16.h"
27 #include "wine/server.h"
28 #include "wine/debug.h"
29 #include "kernel16_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(selector);
32
33 #define LDT_SIZE 8192
34
35 /* get the number of selectors needed to cover up to the selector limit */
36 static inline WORD get_sel_count( WORD sel )
37 {
38     return (wine_ldt_copy.limit[sel >> __AHSHIFT] >> 16) + 1;
39 }
40
41
42 /***********************************************************************
43  *           AllocSelectorArray   (KERNEL.206)
44  */
45 WORD WINAPI AllocSelectorArray16( WORD count )
46 {
47     WORD i, sel = wine_ldt_alloc_entries( count );
48
49     if (sel)
50     {
51         LDT_ENTRY entry;
52         wine_ldt_set_base( &entry, 0 );
53         wine_ldt_set_limit( &entry, 1 ); /* avoid 0 base and limit */
54         wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_DATA );
55         for (i = 0; i < count; i++) wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
56     }
57     return sel;
58 }
59
60
61 /***********************************************************************
62  *           AllocSelector   (KERNEL.175)
63  */
64 WORD WINAPI AllocSelector16( WORD sel )
65 {
66     WORD newsel, count, i;
67
68     count = sel ? get_sel_count(sel) : 1;
69     newsel = wine_ldt_alloc_entries( count );
70     TRACE("(%04x): returning %04x\n", sel, newsel );
71     if (!newsel) return 0;
72     if (!sel) return newsel;  /* nothing to copy */
73     for (i = 0; i < count; i++)
74     {
75         LDT_ENTRY entry;
76         wine_ldt_get_entry( sel + (i << __AHSHIFT), &entry );
77         wine_ldt_set_entry( newsel + (i << __AHSHIFT), &entry );
78     }
79     return newsel;
80 }
81
82
83 /***********************************************************************
84  *           FreeSelector   (KERNEL.176)
85  */
86 WORD WINAPI FreeSelector16( WORD sel )
87 {
88     LDT_ENTRY entry;
89
90     wine_ldt_get_entry( sel, &entry );
91     if (wine_ldt_is_empty( &entry )) return sel;  /* error */
92     /* Check if we are freeing current %fs selector */
93     if (!((wine_get_fs() ^ sel) & ~3))
94         WARN("Freeing %%fs selector (%04x), not good.\n", wine_get_fs() );
95     wine_ldt_free_entries( sel, 1 );
96     return 0;
97 }
98
99
100 /***********************************************************************
101  *           SELECTOR_SetEntries
102  *
103  * Set the LDT entries for an array of selectors.
104  */
105 static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size, unsigned char flags )
106 {
107     LDT_ENTRY entry;
108     WORD i, count;
109
110     wine_ldt_set_base( &entry, base );
111     wine_ldt_set_limit( &entry, size - 1 );
112     wine_ldt_set_flags( &entry, flags );
113     count = (size + 0xffff) / 0x10000;
114     for (i = 0; i < count; i++)
115     {
116         wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
117         wine_ldt_set_base( &entry, (char*)wine_ldt_get_base(&entry) + 0x10000);
118         /* yep, Windows sets limit like that, not 64K sel units */
119         wine_ldt_set_limit( &entry, wine_ldt_get_limit(&entry) - 0x10000 );
120     }
121 }
122
123
124 /***********************************************************************
125  *           SELECTOR_AllocBlock
126  *
127  * Allocate selectors for a block of linear memory.
128  */
129 WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags )
130 {
131     WORD sel, count;
132
133     if (!size) return 0;
134     count = (size + 0xffff) / 0x10000;
135     sel = wine_ldt_alloc_entries( count );
136     if (sel) SELECTOR_SetEntries( sel, base, size, flags );
137     return sel;
138 }
139
140
141 /***********************************************************************
142  *           SELECTOR_FreeBlock
143  *
144  * Free a block of selectors.
145  */
146 void SELECTOR_FreeBlock( WORD sel )
147 {
148     WORD i, count = get_sel_count( sel );
149
150     TRACE("(%04x,%d)\n", sel, count );
151     for (i = 0; i < count; i++) FreeSelector16( sel + (i << __AHSHIFT) );
152 }
153
154
155 /***********************************************************************
156  *           SELECTOR_ReallocBlock
157  *
158  * Change the size of a block of selectors.
159  */
160 WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size )
161 {
162     LDT_ENTRY entry;
163     int oldcount, newcount;
164
165     if (!size) size = 1;
166     wine_ldt_get_entry( sel, &entry );
167     oldcount = (wine_ldt_get_limit(&entry) >> 16) + 1;
168     newcount = (size + 0xffff) >> 16;
169
170     sel = wine_ldt_realloc_entries( sel, oldcount, newcount );
171     if (sel) SELECTOR_SetEntries( sel, base, size, wine_ldt_get_flags(&entry) );
172     return sel;
173 }
174
175
176 /***********************************************************************
177  *           PrestoChangoSelector   (KERNEL.177)
178  */
179 WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
180 {
181     LDT_ENTRY entry;
182     wine_ldt_get_entry( selSrc, &entry );
183     /* toggle the executable bit */
184     entry.HighWord.Bits.Type ^= (WINE_LDT_FLAGS_CODE ^ WINE_LDT_FLAGS_DATA);
185     wine_ldt_set_entry( selDst, &entry );
186     return selDst;
187 }
188
189
190 /***********************************************************************
191  *           AllocCStoDSAlias   (KERNEL.170)
192  *           AllocAlias         (KERNEL.172)
193  */
194 WORD WINAPI AllocCStoDSAlias16( WORD sel )
195 {
196     WORD newsel;
197     LDT_ENTRY entry;
198
199     newsel = wine_ldt_alloc_entries( 1 );
200     TRACE("(%04x): returning %04x\n",
201                       sel, newsel );
202     if (!newsel) return 0;
203     wine_ldt_get_entry( sel, &entry );
204     entry.HighWord.Bits.Type = WINE_LDT_FLAGS_DATA;
205     wine_ldt_set_entry( newsel, &entry );
206     return newsel;
207 }
208
209
210 /***********************************************************************
211  *           AllocDStoCSAlias   (KERNEL.171)
212  */
213 WORD WINAPI AllocDStoCSAlias16( WORD sel )
214 {
215     WORD newsel;
216     LDT_ENTRY entry;
217
218     newsel = wine_ldt_alloc_entries( 1 );
219     TRACE("(%04x): returning %04x\n",
220                       sel, newsel );
221     if (!newsel) return 0;
222     wine_ldt_get_entry( sel, &entry );
223     entry.HighWord.Bits.Type = WINE_LDT_FLAGS_CODE;
224     wine_ldt_set_entry( newsel, &entry );
225     return newsel;
226 }
227
228
229 /***********************************************************************
230  *           LongPtrAdd   (KERNEL.180)
231  */
232 void WINAPI LongPtrAdd16( DWORD ptr, DWORD add )
233 {
234     LDT_ENTRY entry;
235     wine_ldt_get_entry( SELECTOROF(ptr), &entry );
236     wine_ldt_set_base( &entry, (char *)wine_ldt_get_base(&entry) + add );
237     wine_ldt_set_entry( SELECTOROF(ptr), &entry );
238 }
239
240
241 /***********************************************************************
242  *             GetSelectorBase   (KERNEL.186)
243  */
244 DWORD WINAPI GetSelectorBase( WORD sel )
245 {
246     void *base = wine_ldt_copy.base[sel >> __AHSHIFT];
247
248     /* if base points into DOSMEM, assume we have to
249      * return pointer into physical lower 1MB */
250
251     return DOSMEM_MapLinearToDos( base );
252 }
253
254
255 /***********************************************************************
256  *             SetSelectorBase   (KERNEL.187)
257  */
258 WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
259 {
260     LDT_ENTRY entry;
261     wine_ldt_get_entry( sel, &entry );
262     wine_ldt_set_base( &entry, DOSMEM_MapDosToLinear(base) );
263     wine_ldt_set_entry( sel, &entry );
264     return sel;
265 }
266
267
268 /***********************************************************************
269  *           GetSelectorLimit   (KERNEL.188)
270  */
271 DWORD WINAPI GetSelectorLimit16( WORD sel )
272 {
273     return wine_ldt_copy.limit[sel >> __AHSHIFT];
274 }
275
276
277 /***********************************************************************
278  *           SetSelectorLimit   (KERNEL.189)
279  */
280 WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
281 {
282     LDT_ENTRY entry;
283     wine_ldt_get_entry( sel, &entry );
284     wine_ldt_set_limit( &entry, limit );
285     wine_ldt_set_entry( sel, &entry );
286     return sel;
287 }
288
289
290 /***********************************************************************
291  *           SelectorAccessRights   (KERNEL.196)
292  */
293 WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
294 {
295     LDT_ENTRY entry;
296     wine_ldt_get_entry( sel, &entry );
297
298     if (op == 0)  /* get */
299     {
300         return entry.HighWord.Bytes.Flags1 | ((entry.HighWord.Bytes.Flags2 << 8) & 0xf0);
301     }
302     else  /* set */
303     {
304         entry.HighWord.Bytes.Flags1 = LOBYTE(val) | 0xf0;
305         entry.HighWord.Bytes.Flags2 = (entry.HighWord.Bytes.Flags2 & 0x0f) | (HIBYTE(val) & 0xf0);
306         wine_ldt_set_entry( sel, &entry );
307         return 0;
308     }
309 }
310
311
312 /***********************************************************************
313  *           IsBadCodePtr   (KERNEL.336)
314  */
315 BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
316 {
317     WORD sel;
318     LDT_ENTRY entry;
319
320     sel = SELECTOROF(lpfn);
321     if (!sel) return TRUE;
322     wine_ldt_get_entry( sel, &entry );
323     if (wine_ldt_is_empty( &entry )) return TRUE;
324     /* check for code segment, ignoring conforming, read-only and accessed bits */
325     if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_CODE) & 0x18) return TRUE;
326     if (OFFSETOF(lpfn) > wine_ldt_get_limit(&entry)) return TRUE;
327     return FALSE;
328 }
329
330
331 /***********************************************************************
332  *           IsBadStringPtr   (KERNEL.337)
333  */
334 BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
335 {
336     WORD sel;
337     LDT_ENTRY entry;
338
339     sel = SELECTOROF(ptr);
340     if (!sel) return TRUE;
341     wine_ldt_get_entry( sel, &entry );
342     if (wine_ldt_is_empty( &entry )) return TRUE;
343     /* check for data or readable code segment */
344     if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE;  /* system descriptor */
345     if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE;  /* non-readable code segment */
346     if (strlen(MapSL(ptr)) < size) size = strlen(MapSL(ptr)) + 1;
347     if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit(&entry))) return TRUE;
348     return FALSE;
349 }
350
351
352 /***********************************************************************
353  *           IsBadHugeReadPtr   (KERNEL.346)
354  */
355 BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
356 {
357     WORD sel;
358     LDT_ENTRY entry;
359
360     sel = SELECTOROF(ptr);
361     if (!sel) return TRUE;
362     wine_ldt_get_entry( sel, &entry );
363     if (wine_ldt_is_empty( &entry )) return TRUE;
364     /* check for data or readable code segment */
365     if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE;  /* system descriptor */
366     if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE;  /* non-readable code segment */
367     if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
368     return FALSE;
369 }
370
371
372 /***********************************************************************
373  *           IsBadHugeWritePtr   (KERNEL.347)
374  */
375 BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
376 {
377     WORD sel;
378     LDT_ENTRY entry;
379
380     sel = SELECTOROF(ptr);
381     if (!sel) return TRUE;
382     wine_ldt_get_entry( sel, &entry );
383     if (wine_ldt_is_empty( &entry )) return TRUE;
384     /* check for writable data segment, ignoring expand-down and accessed flags */
385     if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_DATA) & ~5) return TRUE;
386     if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
387     return FALSE;
388 }
389
390 /***********************************************************************
391  *           IsBadReadPtr   (KERNEL.334)
392  */
393 BOOL16 WINAPI IsBadReadPtr16( SEGPTR ptr, UINT16 size )
394 {
395     return IsBadHugeReadPtr16( ptr, size );
396 }
397
398
399 /***********************************************************************
400  *           IsBadWritePtr   (KERNEL.335)
401  */
402 BOOL16 WINAPI IsBadWritePtr16( SEGPTR ptr, UINT16 size )
403 {
404     return IsBadHugeWritePtr16( ptr, size );
405 }
406
407
408 /***********************************************************************
409  *           IsBadFlatReadWritePtr   (KERNEL.627)
410  */
411 BOOL16 WINAPI IsBadFlatReadWritePtr16( SEGPTR ptr, DWORD size, BOOL16 bWrite )
412 {
413     return bWrite? IsBadHugeWritePtr16( ptr, size )
414                  : IsBadHugeReadPtr16( ptr, size );
415 }
416
417
418 /************************************* Win95 pointer mapping functions *
419  *
420  */
421
422 struct mapls_entry
423 {
424     struct mapls_entry *next;
425     void               *addr;   /* linear address */
426     int                 count;  /* ref count */
427     WORD                sel;    /* selector */
428 };
429
430 static struct mapls_entry *first_entry;
431
432
433 /***********************************************************************
434  *           MapLS   (KERNEL32.@)
435  *           MapLS   (KERNEL.358)
436  *
437  * Maps linear pointer to segmented.
438  */
439 SEGPTR WINAPI MapLS( LPCVOID ptr )
440 {
441     struct mapls_entry *entry, *free = NULL;
442     const void *base;
443     SEGPTR ret = 0;
444
445     if (!HIWORD(ptr)) return (SEGPTR)LOWORD(ptr);
446
447     base = (const char *)ptr - ((ULONG_PTR)ptr & 0x7fff);
448     HeapLock( GetProcessHeap() );
449     for (entry = first_entry; entry; entry = entry->next)
450     {
451         if (entry->addr == base) break;
452         if (!entry->count) free = entry;
453     }
454
455     if (!entry)
456     {
457         if (!free)  /* no free entry found, create a new one */
458         {
459             if (!(free = HeapAlloc( GetProcessHeap(), 0, sizeof(*free) ))) goto done;
460             if (!(free->sel = SELECTOR_AllocBlock( base, 0x10000, WINE_LDT_FLAGS_DATA )))
461             {
462                 HeapFree( GetProcessHeap(), 0, free );
463                 goto done;
464             }
465             free->count = 0;
466             free->next = first_entry;
467             first_entry = free;
468         }
469         SetSelectorBase( free->sel, (DWORD)base );
470         free->addr = (void*)base;
471         entry = free;
472     }
473     entry->count++;
474     ret = MAKESEGPTR( entry->sel, (const char *)ptr - (char *)entry->addr );
475  done:
476     HeapUnlock( GetProcessHeap() );
477     return ret;
478 }
479
480 /***********************************************************************
481  *           UnMapLS   (KERNEL32.@)
482  *           UnMapLS   (KERNEL.359)
483  *
484  * Free mapped selector.
485  */
486 void WINAPI UnMapLS( SEGPTR sptr )
487 {
488     struct mapls_entry *entry;
489     WORD sel = SELECTOROF(sptr);
490
491     if (sel)
492     {
493         HeapLock( GetProcessHeap() );
494         for (entry = first_entry; entry; entry = entry->next) if (entry->sel == sel) break;
495         if (entry && entry->count > 0) entry->count--;
496         HeapUnlock( GetProcessHeap() );
497     }
498 }
499
500 /***********************************************************************
501  *           MapSL   (KERNEL32.@)
502  *           MapSL   (KERNEL.357)
503  *
504  * Maps fixed segmented pointer to linear.
505  */
506 LPVOID WINAPI MapSL( SEGPTR sptr )
507 {
508     return (char *)wine_ldt_copy.base[SELECTOROF(sptr) >> __AHSHIFT] + OFFSETOF(sptr);
509 }
510
511 /***********************************************************************
512  *           MapSLFix   (KERNEL32.@)
513  *
514  * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
515  * unexpected linear address change when GlobalCompact() shuffles
516  * moveable blocks.
517  */
518
519 LPVOID WINAPI MapSLFix( SEGPTR sptr )
520 {
521     return MapSL(sptr);
522 }
523
524
525 /***********************************************************************
526  *           UnMapSLFixArray   (KERNEL32.@)
527  *
528  * Must not change EAX, hence defined as asm function.
529  */
530 __ASM_STDCALL_FUNC( UnMapSLFixArray, 8, "ret $8" )
531
532 /***********************************************************************
533  *              SMapLS (KERNEL32.@)
534  */
535 __ASM_STDCALL_FUNC( SMapLS, 0,
536                    "xor %edx,%edx\n\t"
537                    "testl $0xffff0000,%eax\n\t"
538                    "jz 1f\n\t"
539                    "pushl %eax\n\t"
540                    "call " __ASM_NAME("MapLS") __ASM_STDCALL(4) "\n\t"
541                    "movl %eax,%edx\n"
542                    "1:\tret" )
543
544 /***********************************************************************
545  *              SUnMapLS (KERNEL32.@)
546  */
547 __ASM_STDCALL_FUNC( SUnMapLS, 0,
548                    "pushl %eax\n\t"  /* preserve eax */
549                    "pushl %eax\n\t"
550                    "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t"
551                    "popl %eax\n\t"
552                    "ret" )
553
554 /***********************************************************************
555  *              SMapLS_IP_EBP_8 (KERNEL32.@)
556  *              SMapLS_IP_EBP_12 (KERNEL32.@)
557  *              SMapLS_IP_EBP_16 (KERNEL32.@)
558  *              SMapLS_IP_EBP_20 (KERNEL32.@)
559  *              SMapLS_IP_EBP_24 (KERNEL32.@)
560  *              SMapLS_IP_EBP_28 (KERNEL32.@)
561  *              SMapLS_IP_EBP_32 (KERNEL32.@)
562  *              SMapLS_IP_EBP_36 (KERNEL32.@)
563  *              SMapLS_IP_EBP_40 (KERNEL32.@)
564  *
565  * These functions map linear pointers at [EBP+xxx] to segmented pointers
566  * and return them.
567  * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
568  * unravel them at SUnMapLS. We just store the segmented pointer there.
569  */
570 #define DEFINE_SMapLS(n) \
571   __ASM_STDCALL_FUNC( SMapLS_IP_EBP_ ## n, 0, \
572                      "movl " #n "(%ebp),%eax\n\t" \
573                      "call " __ASM_NAME("SMapLS") __ASM_STDCALL(4) "\n\t" \
574                      "movl %edx," #n "(%ebp)\n\t" \
575                      "ret" )
576
577 DEFINE_SMapLS(8)
578 DEFINE_SMapLS(12)
579 DEFINE_SMapLS(16)
580 DEFINE_SMapLS(20)
581 DEFINE_SMapLS(24)
582 DEFINE_SMapLS(28)
583 DEFINE_SMapLS(32)
584 DEFINE_SMapLS(36)
585 DEFINE_SMapLS(40)
586
587
588 /***********************************************************************
589  *              SUnMapLS_IP_EBP_8 (KERNEL32.@)
590  *              SUnMapLS_IP_EBP_12 (KERNEL32.@)
591  *              SUnMapLS_IP_EBP_16 (KERNEL32.@)
592  *              SUnMapLS_IP_EBP_20 (KERNEL32.@)
593  *              SUnMapLS_IP_EBP_24 (KERNEL32.@)
594  *              SUnMapLS_IP_EBP_28 (KERNEL32.@)
595  *              SUnMapLS_IP_EBP_32 (KERNEL32.@)
596  *              SUnMapLS_IP_EBP_36 (KERNEL32.@)
597  *              SUnMapLS_IP_EBP_40 (KERNEL32.@)
598  */
599
600 #define DEFINE_SUnMapLS(n) \
601   __ASM_STDCALL_FUNC( SUnMapLS_IP_EBP_ ## n, 0, \
602                      "pushl %eax\n\t"  /* preserve eax */ \
603                      "pushl " #n "(%ebp)\n\t" \
604                      "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t" \
605                      "movl $0," #n "(%ebp)\n\t" \
606                      "popl %eax\n\t" \
607                      "ret" )
608
609 DEFINE_SUnMapLS(8)
610 DEFINE_SUnMapLS(12)
611 DEFINE_SUnMapLS(16)
612 DEFINE_SUnMapLS(20)
613 DEFINE_SUnMapLS(24)
614 DEFINE_SUnMapLS(28)
615 DEFINE_SUnMapLS(32)
616 DEFINE_SUnMapLS(36)
617 DEFINE_SUnMapLS(40)