Release 980118
[wine] / memory / selector.c
1 /*
2  * Selector manipulation functions
3  *
4  * Copyright 1995 Alexandre Julliard
5  */
6
7 #include <string.h>
8 #include "windows.h"
9 #include "ldt.h"
10 #include "miscemu.h"
11 #include "selectors.h"
12 #include "stackframe.h"
13 #include "stddebug.h"
14 #include "debug.h"
15
16
17 #define FIRST_LDT_ENTRY_TO_ALLOC  17
18
19
20 /***********************************************************************
21  *           AllocSelectorArray   (KERNEL.206)
22  */
23 WORD WINAPI AllocSelectorArray( WORD count )
24 {
25     WORD i, sel, size = 0;
26     ldt_entry entry;
27
28     if (!count) return 0;
29     for (i = FIRST_LDT_ENTRY_TO_ALLOC; i < LDT_SIZE; i++)
30     {
31         if (!IS_LDT_ENTRY_FREE(i)) size = 0;
32         else if (++size >= count) break;
33     }
34     if (i == LDT_SIZE) return 0;
35     sel = i - size + 1;
36
37     entry.base           = 0;
38     entry.type           = SEGMENT_DATA;
39     entry.seg_32bit      = FALSE;
40     entry.read_only      = FALSE;
41     entry.limit_in_pages = FALSE;
42     entry.limit          = 1;  /* avoid 0 base and limit */
43
44     for (i = 0; i < count; i++)
45     {
46         /* Mark selector as allocated */
47         ldt_flags_copy[sel + i] |= LDT_FLAGS_ALLOCATED;
48         LDT_SetEntry( sel + i, &entry );
49     }
50     return ENTRY_TO_SELECTOR( sel );
51 }
52
53
54 /***********************************************************************
55  *           AllocSelector   (KERNEL.175)
56  */
57 WORD WINAPI AllocSelector( WORD sel )
58 {
59     WORD newsel, count, i;
60
61     count = sel ? ((GET_SEL_LIMIT(sel) >> 16) + 1) : 1;
62     newsel = AllocSelectorArray( count );
63     dprintf_selector( stddeb, "AllocSelector(%04x): returning %04x\n",
64                       sel, newsel );
65     if (!newsel) return 0;
66     if (!sel) return newsel;  /* nothing to copy */
67     for (i = 0; i < count; i++)
68     {
69         ldt_entry entry;
70         LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
71         LDT_SetEntry( SELECTOR_TO_ENTRY(newsel) + i, &entry );
72     }
73     return newsel;
74 }
75
76
77 /***********************************************************************
78  *           FreeSelector   (KERNEL.176)
79  */
80 WORD WINAPI FreeSelector( WORD sel )
81 {
82     if (IS_SELECTOR_FREE(sel)) return sel;  /* error */
83     SELECTOR_FreeBlock( sel, 1 );
84     return 0;
85 }
86
87
88 /***********************************************************************
89  *           SELECTOR_SetEntries
90  *
91  * Set the LDT entries for an array of selectors.
92  */
93 static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size,
94                                  enum seg_type type, BOOL32 is32bit,
95                                  BOOL32 readonly )
96 {
97     ldt_entry entry;
98     WORD i, count;
99
100     /* The limit for the first selector is the whole */
101     /* block. The next selectors get a 64k limit.    */
102     entry.base           = (unsigned long)base;
103     entry.type           = type;
104     entry.seg_32bit      = is32bit;
105     entry.read_only      = readonly;
106     entry.limit_in_pages = (size > 0x100000);
107     if (entry.limit_in_pages) entry.limit = ((size + 0xfff) >> 12) - 1;
108     else entry.limit = size - 1;
109     /* Make sure base and limit are not 0 together if the size is not 0 */
110     if (!base && !entry.limit && size) entry.limit = 1;
111     count = (size + 0xffff) / 0x10000;
112     for (i = 0; i < count; i++)
113     {
114         LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
115         entry.base += 0x10000;
116         /* Apparently the next selectors should *not* get a 64k limit. */
117         /* Can't remember where I read they should... --AJ */
118         entry.limit -= entry.limit_in_pages ? 0x10 : 0x10000;
119     }
120 }
121
122
123 /***********************************************************************
124  *           SELECTOR_AllocBlock
125  *
126  * Allocate selectors for a block of linear memory.
127  */
128 WORD SELECTOR_AllocBlock( const void *base, DWORD size, enum seg_type type,
129                           BOOL32 is32bit, BOOL32 readonly )
130 {
131     WORD sel, count;
132
133     if (!size) return 0;
134     count = (size + 0xffff) / 0x10000;
135     sel = AllocSelectorArray( count );
136     if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
137     return sel;
138 }
139
140
141 /***********************************************************************
142  *           SELECTOR_FreeBlock
143  *
144  * Free a block of selectors.
145  */
146 void SELECTOR_FreeBlock( WORD sel, WORD count )
147 {
148     WORD i, nextsel;
149     ldt_entry entry;
150     STACK16FRAME *frame;
151
152     dprintf_selector( stddeb, "SELECTOR_FreeBlock(%04x,%d)\n", sel, count );
153     sel &= ~(__AHINCR - 1);  /* clear bottom bits of selector */
154     nextsel = sel + (count << __AHSHIFT);
155
156 #ifdef __i386__
157     {
158         /* Check if we are freeing current %fs or %gs selector */
159
160         WORD fs, gs;
161         GET_FS(fs);
162         if ((fs >= sel) && (fs < nextsel))
163         {
164             fprintf( stderr, "SELECTOR_FreeBlock: freeing %%fs selector (%04x), not good.\n", fs );
165             SET_FS( 0 );
166         }
167         GET_GS(gs);
168         if ((gs >= sel) && (gs < nextsel)) SET_GS( 0 );
169     }
170 #endif  /* __i386__ */
171
172     memset( &entry, 0, sizeof(entry) );  /* clear the LDT entries */
173     for (i = SELECTOR_TO_ENTRY(sel); count; i++, count--)
174     {
175         LDT_SetEntry( i, &entry );
176         ldt_flags_copy[i] &= ~LDT_FLAGS_ALLOCATED;
177     }
178
179     /* Clear the saved 16-bit selector */
180     frame = CURRENT_STACK16;
181     while (frame)
182     {
183         if ((frame->ds >= sel) && (frame->ds < nextsel)) frame->ds = 0;
184         if ((frame->es >= sel) && (frame->es < nextsel)) frame->es = 0;
185         if (!frame->frame32) break;
186         frame = PTR_SEG_TO_LIN( frame->frame32->frame16 );
187     }
188 }
189
190
191 /***********************************************************************
192  *           SELECTOR_ReallocBlock
193  *
194  * Change the size of a block of selectors.
195  */
196 WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size,
197                            enum seg_type type, BOOL32 is32bit, BOOL32 readonly)
198 {
199     WORD i, oldcount, newcount;
200
201     if (!size) size = 1;
202     oldcount = (GET_SEL_LIMIT(sel) >> 16) + 1;
203     newcount = (size + 0xffff) >> 16;
204
205     if (oldcount < newcount)  /* We need to add selectors */
206     {
207           /* Check if the next selectors are free */
208         if (SELECTOR_TO_ENTRY(sel) + newcount > LDT_SIZE) i = oldcount;
209         else
210             for (i = oldcount; i < newcount; i++)
211                 if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel)+i)) break;
212
213         if (i < newcount)  /* they are not free */
214         {
215             SELECTOR_FreeBlock( sel, oldcount );
216             sel = AllocSelectorArray( newcount );
217         }
218         else  /* mark the selectors as allocated */
219         {
220             for (i = oldcount; i < newcount; i++)
221                 ldt_flags_copy[SELECTOR_TO_ENTRY(sel)+i] |=LDT_FLAGS_ALLOCATED;
222         }
223     }
224     else if (oldcount > newcount) /* We need to remove selectors */
225     {
226         SELECTOR_FreeBlock( ENTRY_TO_SELECTOR(SELECTOR_TO_ENTRY(sel)+newcount),
227                             oldcount - newcount );
228     }
229     if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
230     return sel;
231 }
232
233
234 /***********************************************************************
235  *           PrestoChangoSelector   (KERNEL.177)
236  */
237 WORD WINAPI PrestoChangoSelector( WORD selSrc, WORD selDst )
238 {
239     ldt_entry entry;
240     LDT_GetEntry( SELECTOR_TO_ENTRY( selSrc ), &entry );
241     entry.type ^= SEGMENT_CODE;  /* toggle the executable bit */
242     LDT_SetEntry( SELECTOR_TO_ENTRY( selDst ), &entry );
243     return selDst;
244 }
245
246
247 /***********************************************************************
248  *           AllocCStoDSAlias   (KERNEL.170)
249  */
250 WORD WINAPI AllocCStoDSAlias( WORD sel )
251 {
252     WORD newsel;
253     ldt_entry entry;
254
255     newsel = AllocSelectorArray( 1 );
256     dprintf_selector( stddeb, "AllocCStoDSAlias(%04x): returning %04x\n",
257                       sel, newsel );
258     if (!newsel) return 0;
259     LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
260     entry.type = SEGMENT_DATA;
261     LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
262     return newsel;
263 }
264
265
266 /***********************************************************************
267  *           AllocDStoCSAlias   (KERNEL.171)
268  */
269 WORD WINAPI AllocDStoCSAlias( WORD sel )
270 {
271     WORD newsel;
272     ldt_entry entry;
273
274     newsel = AllocSelectorArray( 1 );
275     dprintf_selector( stddeb, "AllocDStoCSAlias(%04x): returning %04x\n",
276                       sel, newsel );
277     if (!newsel) return 0;
278     LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
279     entry.type = SEGMENT_CODE;
280     LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
281     return newsel;
282 }
283
284
285 /***********************************************************************
286  *           LongPtrAdd   (KERNEL.180)
287  */
288 void WINAPI LongPtrAdd( DWORD ptr, DWORD add )
289 {
290     ldt_entry entry;
291     LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
292     entry.base += add;
293     LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
294 }
295
296
297 /***********************************************************************
298  *           GetSelectorBase   (KERNEL.186)
299  */
300 DWORD WINAPI GetSelectorBase( WORD sel )
301 {
302     DWORD base = GET_SEL_BASE(sel);
303
304     /* if base points into DOSMEM, assume we have to
305      * return pointer into physical lower 1MB */
306
307     return DOSMEM_MapLinearToDos( (LPVOID)base );
308 }
309
310
311 /***********************************************************************
312  *           SetSelectorBase   (KERNEL.187)
313  */
314 WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
315 {
316     ldt_entry entry;
317
318     LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
319
320     entry.base = (DWORD)DOSMEM_MapDosToLinear(base);
321
322     LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
323     return sel;
324 }
325
326
327 /***********************************************************************
328  *           GetSelectorLimit   (KERNEL.188)
329  */
330 DWORD WINAPI GetSelectorLimit( WORD sel )
331 {
332     return GET_SEL_LIMIT(sel);
333 }
334
335
336 /***********************************************************************
337  *           SetSelectorLimit   (KERNEL.189)
338  */
339 WORD WINAPI SetSelectorLimit( WORD sel, DWORD limit )
340 {
341     ldt_entry entry;
342     LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
343     entry.limit_in_pages = (limit >= 0x100000);
344     if (entry.limit_in_pages) entry.limit = limit >> 12;
345     else entry.limit = limit;
346     LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
347     return sel;
348 }
349
350
351 /***********************************************************************
352  *           SelectorAccessRights   (KERNEL.196)
353  */
354 WORD WINAPI SelectorAccessRights( WORD sel, WORD op, WORD val )
355 {
356     ldt_entry entry;
357     LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
358     if (op == 0)  /* get */
359     {
360         return 0x01 | /* accessed */
361                0x10 | /* not system */
362                0x60 | /* DPL 3 */
363                0x80 | /* present */
364                ((entry.read_only == 0) << 1) |
365                (entry.type << 2) |
366                (entry.seg_32bit << 14) |
367                (entry.limit_in_pages << 15);
368     }
369     else  /* set */
370     {
371         entry.read_only = ((val & 2) == 0);
372         entry.type = (val >> 2) & 3;
373         entry.seg_32bit = val & 0x4000;
374         entry.limit_in_pages = val & 0x8000;
375         LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
376         return 0;
377     }
378 }
379
380
381 /***********************************************************************
382  *           IsBadCodePtr16   (KERNEL.336)
383  */
384 BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
385 {
386     WORD sel;
387     ldt_entry entry;
388
389     sel = SELECTOROF(lpfn);
390     if (!sel) return TRUE;
391     if (IS_SELECTOR_FREE(sel)) return TRUE;
392     LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
393     if (entry.type != SEGMENT_CODE) return TRUE;
394     if (OFFSETOF(lpfn) > entry.limit) return TRUE;
395     return FALSE;
396 }
397
398
399 /***********************************************************************
400  *           IsBadStringPtr16   (KERNEL.337)
401  */
402 BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
403 {
404     WORD sel;
405     ldt_entry entry;
406
407     sel = SELECTOROF(ptr);
408     if (!sel) return TRUE;
409     if (IS_SELECTOR_FREE(sel)) return TRUE;
410     LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
411     if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
412     if (strlen(PTR_SEG_TO_LIN(ptr)) < size) size = strlen(PTR_SEG_TO_LIN(ptr));
413     if (OFFSETOF(ptr) + size - 1 > entry.limit) return TRUE;
414     return FALSE;
415 }
416
417
418 /***********************************************************************
419  *           IsBadHugeReadPtr16   (KERNEL.346)
420  */
421 BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
422 {
423     WORD sel;
424     ldt_entry entry;
425
426     sel = SELECTOROF(ptr);
427     if (!sel) return TRUE;
428     if (IS_SELECTOR_FREE(sel)) return TRUE;
429     LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
430     if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
431     if (OFFSETOF(ptr) + size - 1 > entry.limit) return TRUE;
432     return FALSE;
433 }
434
435
436 /***********************************************************************
437  *           IsBadHugeWritePtr16   (KERNEL.347)
438  */
439 BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
440 {
441     WORD sel;
442     ldt_entry entry;
443
444     sel = SELECTOROF(ptr);
445     if (!sel) return TRUE;
446     if (IS_SELECTOR_FREE(sel)) return TRUE;
447     LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
448     if ((entry.type == SEGMENT_CODE) || entry.read_only) return TRUE;
449     if (OFFSETOF(ptr) + size - 1 > entry.limit) return TRUE;
450     return FALSE;
451 }
452
453 /***********************************************************************
454  *           IsBadReadPtr16   (KERNEL.334)
455  */
456 BOOL16 WINAPI IsBadReadPtr16( SEGPTR ptr, UINT16 size )
457 {
458     return IsBadHugeReadPtr16( ptr, size );
459 }
460
461
462 /***********************************************************************
463  *           IsBadWritePtr16   (KERNEL.335)
464  */
465 BOOL16 WINAPI IsBadWritePtr16( SEGPTR ptr, UINT16 size )
466 {
467     return IsBadHugeWritePtr16( ptr, size );
468 }
469
470
471 /***********************************************************************
472  *           MemoryRead   (TOOLHELP.78)
473  */
474 DWORD WINAPI MemoryRead( WORD sel, DWORD offset, void *buffer, DWORD count )
475 {
476     if (IS_SELECTOR_FREE(sel)) return 0;
477     if (offset > GET_SEL_LIMIT(sel)) return 0;
478     if (offset + count > GET_SEL_LIMIT(sel) + 1)
479         count = GET_SEL_LIMIT(sel) + 1 - offset;
480     memcpy( buffer, ((char *)GET_SEL_BASE(sel)) + offset, count );
481     return count;
482 }
483
484
485 /***********************************************************************
486  *           MemoryWrite   (TOOLHELP.79)
487  */
488 DWORD WINAPI MemoryWrite( WORD sel, DWORD offset, void *buffer, DWORD count )
489 {
490     if (IS_SELECTOR_FREE(sel)) return 0;
491     if (offset > GET_SEL_LIMIT(sel)) return 0;
492     if (offset + count > GET_SEL_LIMIT(sel) + 1)
493         count = GET_SEL_LIMIT(sel) + 1 - offset;
494     memcpy( ((char *)GET_SEL_BASE(sel)) + offset, buffer, count );
495     return count;
496 }
497
498 /************************************* Win95 pointer mapping functions *
499  *
500  * NOTE: MapSLFix and UnMapSLFixArray are probably needed to prevent
501  * unexpected linear address change when GlobalCompact() shuffles
502  * moveable blocks.
503  */
504
505 /***********************************************************************
506  *           MapSL   (KERNEL32.662)
507  *
508  * Maps fixed segmented pointer to linear.
509  */
510 LPVOID WINAPI MapSL( SEGPTR sptr )
511 {
512     return (LPVOID)PTR_SEG_TO_LIN(sptr);
513 }
514
515
516 /***********************************************************************
517  *           MapLS   (KERNEL32.679)
518  *
519  * Maps linear pointer to segmented.
520  */
521 SEGPTR WINAPI MapLS( LPVOID ptr )
522 {
523     WORD sel = SELECTOR_AllocBlock( ptr, 0x10000, SEGMENT_DATA, FALSE, FALSE );
524     return PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
525 }
526
527
528 /***********************************************************************
529  *           UnMapLS   (KERNEL32.680)
530  *
531  * Free mapped selector.
532  */
533 void WINAPI UnMapLS( SEGPTR sptr )
534 {
535     if (!__winelib) SELECTOR_FreeBlock( SELECTOROF(sptr), 1 );
536 }
537
538 /***********************************************************************
539  *           GetThreadSelectorEntry   (KERNEL32)
540  * FIXME: add #ifdef i386 for non x86
541  */
542 BOOL32 WINAPI GetThreadSelectorEntry( HANDLE32 hthread, DWORD sel,
543                                       LPLDT_ENTRY ldtent)
544 {
545     ldt_entry   ldtentry;
546
547     LDT_GetEntry(SELECTOR_TO_ENTRY(sel),&ldtentry);
548     ldtent->BaseLow = ldtentry.base & 0x0000ffff;
549     ldtent->HighWord.Bits.BaseMid = (ldtentry.base & 0x00ff0000) >> 16;
550     ldtent->HighWord.Bits.BaseHi = (ldtentry.base & 0xff000000) >> 24;
551     ldtent->LimitLow = ldtentry.limit & 0x0000ffff;
552     ldtent->HighWord.Bits.LimitHi = (ldtentry.limit & 0x00ff0000) >> 16;
553     ldtent->HighWord.Bits.Dpl = 3;
554     ldtent->HighWord.Bits.Sys = 0;
555     ldtent->HighWord.Bits.Pres = 1;
556     ldtent->HighWord.Bits.Type = 0x10|(ldtentry.type << 2);
557     if (ldtentry.read_only)
558         ldtent->HighWord.Bits.Type|=0x2;
559     ldtent->HighWord.Bits.Granularity = ldtentry.limit_in_pages;
560     ldtent->HighWord.Bits.Default_Big = ldtentry.seg_32bit;
561     return TRUE;
562 }
563
564
565 /**********************************************************************
566  *              SMapLS*         (KERNEL32)
567  * These functions map linear pointers at [EBP+xxx] to segmented pointers
568  * and return them.
569  * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
570  * unravel them at SUnMapLS. We just store the segmented pointer there.
571  */
572 static void
573 x_SMapLS_IP_EBP_x(CONTEXT *context,int argoff) {
574     DWORD       val,ptr; 
575
576     val =*(DWORD*)(EBP_reg(context)+argoff);
577     if (val<0x10000) {
578         ptr=val;
579         *(DWORD*)(EBP_reg(context)+argoff) = 0;
580     } else {
581         ptr = MapLS((LPVOID)val);
582         *(DWORD*)(EBP_reg(context)+argoff) = ptr;
583     }
584     EAX_reg(context) = ptr;
585 }
586
587 void WINAPI SMapLS_IP_EBP_8(CONTEXT *context)  {x_SMapLS_IP_EBP_x(context,8);}
588 void WINAPI SMapLS_IP_EBP_12(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,12);}
589 void WINAPI SMapLS_IP_EBP_16(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,16);}
590 void WINAPI SMapLS_IP_EBP_20(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,20);}
591 void WINAPI SMapLS_IP_EBP_24(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,24);}
592 void WINAPI SMapLS_IP_EBP_28(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,28);}
593 void WINAPI SMapLS_IP_EBP_32(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,32);}
594 void WINAPI SMapLS_IP_EBP_36(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,36);}
595 void WINAPI SMapLS_IP_EBP_40(CONTEXT *context) {x_SMapLS_IP_EBP_x(context,40);}
596
597 void WINAPI SMapLS(CONTEXT *context)
598 {
599     if (EAX_reg(context)>=0x10000) {
600         EAX_reg(context) = MapLS((LPVOID)EAX_reg(context));
601         EDX_reg(context) = EAX_reg(context);
602     } else {
603         EDX_reg(context) = 0;
604     }
605 }
606
607 void WINAPI SUnMapLS(CONTEXT *context)
608 {
609     if (EAX_reg(context)>=0x10000)
610         UnMapLS((SEGPTR)EAX_reg(context));
611 }
612
613 static void
614 x_SUnMapLS_IP_EBP_x(CONTEXT *context,int argoff) {
615         if (*(DWORD*)(EBP_reg(context)+argoff))
616                 UnMapLS(*(DWORD*)(EBP_reg(context)+argoff));
617         *(DWORD*)(EBP_reg(context)+argoff)=0;
618 }
619 void WINAPI SUnMapLS_IP_EBP_8(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,12); }
620 void WINAPI SUnMapLS_IP_EBP_12(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,12); }
621 void WINAPI SUnMapLS_IP_EBP_16(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,16); }
622 void WINAPI SUnMapLS_IP_EBP_20(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,20); }
623 void WINAPI SUnMapLS_IP_EBP_24(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,24); }
624 void WINAPI SUnMapLS_IP_EBP_28(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,28); }
625 void WINAPI SUnMapLS_IP_EBP_32(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,32); }
626 void WINAPI SUnMapLS_IP_EBP_36(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,36); }
627 void WINAPI SUnMapLS_IP_EBP_40(CONTEXT *context) { x_SUnMapLS_IP_EBP_x(context,40); }
628
629 /**********************************************************************
630  *           WOWGetVDMPointer   (KERNEL32.55)
631  * Get linear from segmented pointer. (MSDN lib)
632  */
633 LPVOID WINAPI WOWGetVDMPointer(DWORD vp,DWORD nrofbytes,BOOL32 protected)
634 {
635     /* FIXME: add size check too */
636     fprintf(stdnimp,"WOWGetVDMPointer(%08lx,%ld,%d)\n",vp,nrofbytes,protected);
637     if (protected)
638         return PTR_SEG_TO_LIN(vp);
639     else
640         return DOSMEM_MapRealToLinear(vp);
641 }
642
643 /**********************************************************************
644  *           GetVDMPointer32W   (KERNEL.516)
645  */
646 LPVOID WINAPI GetVDMPointer32W(DWORD vp,DWORD mode)
647 {
648     return WOWGetVDMPointer(vp,0,mode);
649 }
650
651 /**********************************************************************
652  *           WOWGetVDMPointerFix (KERNEL32.55)
653  * Dito, but fix heapsegment (MSDN lib)
654  */
655 LPVOID WINAPI WOWGetVDMPointerFix(DWORD vp,DWORD nrofbytes,BOOL32 protected)
656 {
657     /* FIXME: fix heapsegment */
658     fprintf(stdnimp,"WOWGetVDMPointerFix(%08lx,%ld,%d)\n",vp,nrofbytes,protected);
659     return WOWGetVDMPointer(vp,nrofbytes,protected);
660 }
661
662 /**********************************************************************
663  *           WOWGetVDMPointerUnFix (KERNEL32.56)
664  */
665 void WINAPI WOWGetVDMPointerUnfix(DWORD vp)
666 {
667     fprintf(stdnimp,"WOWGetVDMPointerUnfix(%08lx), STUB\n",vp);
668     /* FIXME: unfix heapsegment */
669 }
670
671 /***********************************************************************
672  *           UTSelectorOffsetToLinear       (WIN32S16.48)
673  *
674  * rough guesswork, but seems to work (I had no "reasonable" docu)
675  */
676 LPVOID WINAPI UTSelectorOffsetToLinear(SEGPTR sptr)
677 {
678         return PTR_SEG_TO_LIN(sptr);
679 }
680
681 /***********************************************************************
682  *           UTLinearToSelectorOffset       (WIN32S16.49)
683  *
684  * FIXME: I don't know if that's the right way to do linear -> segmented
685  */
686 SEGPTR WINAPI UTLinearToSelectorOffset(LPVOID lptr)
687 {
688     fprintf( stderr, "UTLinearToSelectorOffset(%p): stub\n", lptr );
689     return (SEGPTR)lptr;
690 }