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