2 * Selector manipulation functions
4 * Copyright 1995 Alexandre Julliard
9 #include "wine/winbase16.h"
12 #include "selectors.h"
13 #include "stackframe.h"
16 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(selector
);
22 /***********************************************************************
23 * AllocSelectorArray (KERNEL.206)
25 WORD WINAPI
AllocSelectorArray16( WORD count
)
27 WORD i
, sel
, size
= 0;
31 for (i
= FIRST_LDT_ENTRY_TO_ALLOC
; i
< LDT_SIZE
; i
++)
33 if (!IS_LDT_ENTRY_FREE(i
)) size
= 0;
34 else if (++size
>= count
) break;
36 if (i
== LDT_SIZE
) return 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 */
46 for (i
= 0; i
< count
; i
++)
48 /* Mark selector as allocated */
49 ldt_flags_copy
[sel
+ i
] |= LDT_FLAGS_ALLOCATED
;
50 LDT_SetEntry( sel
+ i
, &entry
);
52 return ENTRY_TO_SELECTOR( sel
);
56 /***********************************************************************
57 * AllocSelector (KERNEL.175)
59 WORD WINAPI
AllocSelector16( WORD sel
)
61 WORD newsel
, count
, i
;
63 count
= sel
? ((GET_SEL_LIMIT(sel
) >> 16) + 1) : 1;
64 newsel
= AllocSelectorArray16( count
);
65 TRACE("(%04x): returning %04x\n",
67 if (!newsel
) return 0;
68 if (!sel
) return newsel
; /* nothing to copy */
69 for (i
= 0; i
< count
; i
++)
72 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
73 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
) + i
, &entry
);
79 /***********************************************************************
80 * FreeSelector (KERNEL.176)
82 WORD WINAPI
FreeSelector16( WORD sel
)
84 if (IS_SELECTOR_FREE(sel
)) return sel
; /* error */
85 SELECTOR_FreeBlock( sel
, 1 );
90 /***********************************************************************
93 * Set the LDT entries for an array of selectors.
95 static void SELECTOR_SetEntries( WORD sel
, const void *base
, DWORD size
,
96 enum seg_type type
, BOOL is32bit
,
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
;
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
++)
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;
125 /***********************************************************************
126 * SELECTOR_AllocBlock
128 * Allocate selectors for a block of linear memory.
130 WORD
SELECTOR_AllocBlock( const void *base
, DWORD size
, enum seg_type type
,
131 BOOL is32bit
, BOOL readonly
)
136 count
= (size
+ 0xffff) / 0x10000;
137 sel
= AllocSelectorArray16( count
);
138 if (sel
) SELECTOR_SetEntries( sel
, base
, size
, type
, is32bit
, readonly
);
143 /***********************************************************************
146 * Move a block of selectors in linear memory.
148 void SELECTOR_MoveBlock( WORD sel
, const void *new_base
)
150 WORD i
, count
= (GET_SEL_LIMIT(sel
) >> 16) + 1;
152 for (i
= 0; i
< count
; i
++)
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
);
162 /***********************************************************************
165 * Free a block of selectors.
167 void SELECTOR_FreeBlock( WORD sel
, WORD count
)
172 TRACE("(%04x,%d)\n", sel
, count
);
173 sel
&= ~(__AHINCR
- 1); /* clear bottom bits of selector */
174 nextsel
= sel
+ (count
<< __AHSHIFT
);
178 /* Check if we are freeing current %fs or %gs selector */
179 if ((__get_fs() >= sel
) && (__get_fs() < nextsel
))
181 WARN("Freeing %%fs selector (%04x), not good.\n", __get_fs() );
184 if ((__get_gs() >= sel
) && (__get_gs() < nextsel
)) __set_gs( 0 );
186 #endif /* __i386__ */
188 memset( &entry
, 0, sizeof(entry
) ); /* clear the LDT entries */
189 for (i
= SELECTOR_TO_ENTRY(sel
); count
; i
++, count
--)
191 LDT_SetEntry( i
, &entry
);
192 ldt_flags_copy
[i
] &= ~LDT_FLAGS_ALLOCATED
;
197 /***********************************************************************
198 * SELECTOR_ReallocBlock
200 * Change the size of a block of selectors.
202 WORD
SELECTOR_ReallocBlock( WORD sel
, const void *base
, DWORD size
)
205 WORD i
, oldcount
, newcount
;
208 oldcount
= (GET_SEL_LIMIT(sel
) >> 16) + 1;
209 newcount
= (size
+ 0xffff) >> 16;
210 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
212 if (oldcount
< newcount
) /* We need to add selectors */
214 /* Check if the next selectors are free */
215 if (SELECTOR_TO_ENTRY(sel
) + newcount
> LDT_SIZE
) i
= oldcount
;
217 for (i
= oldcount
; i
< newcount
; i
++)
218 if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel
)+i
)) break;
220 if (i
< newcount
) /* they are not free */
222 SELECTOR_FreeBlock( sel
, oldcount
);
223 sel
= AllocSelectorArray16( newcount
);
225 else /* mark the selectors as allocated */
227 for (i
= oldcount
; i
< newcount
; i
++)
228 ldt_flags_copy
[SELECTOR_TO_ENTRY(sel
)+i
] |=LDT_FLAGS_ALLOCATED
;
231 else if (oldcount
> newcount
) /* We need to remove selectors */
233 SELECTOR_FreeBlock( ENTRY_TO_SELECTOR(SELECTOR_TO_ENTRY(sel
)+newcount
),
234 oldcount
- newcount
);
236 if (sel
) SELECTOR_SetEntries( sel
, base
, size
, entry
.type
,
237 entry
.seg_32bit
, entry
.read_only
);
242 /***********************************************************************
243 * PrestoChangoSelector (KERNEL.177)
245 WORD WINAPI
PrestoChangoSelector16( WORD selSrc
, WORD selDst
)
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
);
255 /***********************************************************************
256 * AllocCStoDSAlias (KERNEL.170)
258 WORD WINAPI
AllocCStoDSAlias16( WORD sel
)
263 newsel
= AllocSelectorArray16( 1 );
264 TRACE("(%04x): returning %04x\n",
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
);
274 /***********************************************************************
275 * AllocDStoCSAlias (KERNEL.171)
277 WORD WINAPI
AllocDStoCSAlias16( WORD sel
)
282 newsel
= AllocSelectorArray16( 1 );
283 TRACE("(%04x): returning %04x\n",
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
);
293 /***********************************************************************
294 * LongPtrAdd (KERNEL.180)
296 void WINAPI
LongPtrAdd16( DWORD ptr
, DWORD add
)
299 LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr
)), &entry
);
301 LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr
)), &entry
);
305 /***********************************************************************
306 * GetSelectorBase (KERNEL.186)
308 DWORD WINAPI
WIN16_GetSelectorBase( WORD sel
)
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.
316 DWORD base
= GetSelectorBase( sel
);
317 return W32S_WINE2APP( base
, W32S_APPLICATION() ? W32S_OFFSET
: 0 );
319 DWORD WINAPI
GetSelectorBase( WORD sel
)
321 DWORD base
= GET_SEL_BASE(sel
);
323 /* if base points into DOSMEM, assume we have to
324 * return pointer into physical lower 1MB */
326 return DOSMEM_MapLinearToDos( (LPVOID
)base
);
330 /***********************************************************************
331 * SetSelectorBase (KERNEL.187)
333 DWORD WINAPI
WIN16_SetSelectorBase( WORD sel
, DWORD base
)
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.
341 SetSelectorBase( sel
,
342 W32S_APP2WINE( base
, W32S_APPLICATION() ? W32S_OFFSET
: 0 ) );
345 WORD WINAPI
SetSelectorBase( WORD sel
, DWORD base
)
349 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
351 entry
.base
= (DWORD
)DOSMEM_MapDosToLinear(base
);
353 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
358 /***********************************************************************
359 * GetSelectorLimit (KERNEL.188)
361 DWORD WINAPI
GetSelectorLimit16( WORD sel
)
363 return GET_SEL_LIMIT(sel
);
367 /***********************************************************************
368 * SetSelectorLimit (KERNEL.189)
370 WORD WINAPI
SetSelectorLimit16( WORD sel
, DWORD limit
)
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
);
382 /***********************************************************************
383 * SelectorAccessRights (KERNEL.196)
385 WORD WINAPI
SelectorAccessRights16( WORD sel
, WORD op
, WORD val
)
388 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
389 if (op
== 0) /* get */
391 return 0x01 | /* accessed */
392 0x10 | /* not system */
395 ((entry
.read_only
== 0) << 1) |
397 (entry
.seg_32bit
<< 14) |
398 (entry
.limit_in_pages
<< 15);
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
);
412 /***********************************************************************
413 * IsBadCodePtr16 (KERNEL.336)
415 BOOL16 WINAPI
IsBadCodePtr16( SEGPTR lpfn
)
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
;
430 /***********************************************************************
431 * IsBadStringPtr16 (KERNEL.337)
433 BOOL16 WINAPI
IsBadStringPtr16( SEGPTR ptr
, UINT16 size
)
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
;
449 /***********************************************************************
450 * IsBadHugeReadPtr16 (KERNEL.346)
452 BOOL16 WINAPI
IsBadHugeReadPtr16( SEGPTR ptr
, DWORD size
)
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
;
467 /***********************************************************************
468 * IsBadHugeWritePtr16 (KERNEL.347)
470 BOOL16 WINAPI
IsBadHugeWritePtr16( SEGPTR ptr
, DWORD size
)
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
;
484 /***********************************************************************
485 * IsBadReadPtr16 (KERNEL.334)
487 BOOL16 WINAPI
IsBadReadPtr16( SEGPTR ptr
, UINT16 size
)
489 return IsBadHugeReadPtr16( ptr
, size
);
493 /***********************************************************************
494 * IsBadWritePtr16 (KERNEL.335)
496 BOOL16 WINAPI
IsBadWritePtr16( SEGPTR ptr
, UINT16 size
)
498 return IsBadHugeWritePtr16( ptr
, size
);
502 /***********************************************************************
503 * IsBadFlatReadWritePtr16 (KERNEL.627)
505 BOOL16 WINAPI
IsBadFlatReadWritePtr16( SEGPTR ptr
, DWORD size
, BOOL16 bWrite
)
507 return bWrite
? IsBadHugeWritePtr16( ptr
, size
)
508 : IsBadHugeReadPtr16( ptr
, size
);
512 /***********************************************************************
513 * MemoryRead (TOOLHELP.78)
515 DWORD WINAPI
MemoryRead16( WORD sel
, DWORD offset
, void *buffer
, DWORD count
)
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
);
526 /***********************************************************************
527 * MemoryWrite (TOOLHELP.79)
529 DWORD WINAPI
MemoryWrite16( WORD sel
, DWORD offset
, void *buffer
, DWORD count
)
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
);
539 /************************************* Win95 pointer mapping functions *
543 /***********************************************************************
544 * MapSL (KERNEL32.523)
546 * Maps fixed segmented pointer to linear.
548 LPVOID WINAPI
MapSL( SEGPTR sptr
)
550 return (LPVOID
)PTR_SEG_TO_LIN(sptr
);
553 /***********************************************************************
554 * MapSLFix (KERNEL32.524)
556 * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
557 * unexpected linear address change when GlobalCompact() shuffles
561 LPVOID WINAPI
MapSLFix( SEGPTR sptr
)
563 return (LPVOID
)PTR_SEG_TO_LIN(sptr
);
566 /***********************************************************************
567 * UnMapSLFixArray (KERNEL32.701)
570 void WINAPI
UnMapSLFixArray( SEGPTR sptr
[], INT length
, CONTEXT86
*context
)
572 /* Must not change EAX, hence defined as 'register' function */
575 /***********************************************************************
576 * MapLS (KERNEL32.522)
578 * Maps linear pointer to segmented.
580 SEGPTR WINAPI
MapLS( LPVOID ptr
)
586 WORD sel
= SELECTOR_AllocBlock( ptr
, 0x10000, SEGMENT_DATA
, FALSE
, FALSE
);
587 return PTR_SEG_OFF_TO_SEGPTR( sel
, 0 );
592 /***********************************************************************
593 * UnMapLS (KERNEL32.700)
595 * Free mapped selector.
597 void WINAPI
UnMapLS( SEGPTR sptr
)
599 if (SELECTOROF(sptr
))
600 SELECTOR_FreeBlock( SELECTOROF(sptr
), 1 );
603 /***********************************************************************
604 * GetThreadSelectorEntry (KERNEL32)
606 BOOL WINAPI
GetThreadSelectorEntry( HANDLE hthread
, DWORD sel
, LPLDT_ENTRY ldtent
)
609 struct get_selector_entry_request
*req
= get_req_buffer();
611 if (!(sel
& 4)) /* GDT selector */
613 sel
&= ~3; /* ignore RPL */
614 if (!sel
) /* null selector */
616 memset( ldtent
, 0, sizeof(*ldtent
) );
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))
635 ldtent
->HighWord
.Bits
.Type
|= 8; /* code segment */
638 SetLastError( ERROR_NOACCESS
);
642 req
->handle
= hthread
;
643 req
->entry
= sel
>> __AHSHIFT
;
644 if (server_call( REQ_GET_SELECTOR_ENTRY
)) return FALSE
;
646 if (!(req
->flags
& LDT_FLAGS_ALLOCATED
))
648 SetLastError( ERROR_MR_MID_NOT_FOUND
); /* sic */
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;
666 SetLastError( ERROR_NOT_IMPLEMENTED
);
672 /**********************************************************************
674 * These functions map linear pointers at [EBP+xxx] to segmented pointers
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.
680 x_SMapLS_IP_EBP_x(CONTEXT86
*context
,int argoff
) {
683 val
=*(DWORD
*)(EBP_reg(context
)+argoff
);
686 *(DWORD
*)(EBP_reg(context
)+argoff
) = 0;
688 ptr
= MapLS((LPVOID
)val
);
689 *(DWORD
*)(EBP_reg(context
)+argoff
) = ptr
;
691 EAX_reg(context
) = ptr
;
694 /***********************************************************************
695 * SMapLS_IP_EBP_8 (KERNEL32.601)
697 void WINAPI
SMapLS_IP_EBP_8 (CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
, 8);}
699 /***********************************************************************
700 * SMapLS_IP_EBP_12 (KERNEL32.593)
702 void WINAPI
SMapLS_IP_EBP_12(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,12);}
704 /***********************************************************************
705 * SMapLS_IP_EBP_16 (KERNEL32.594)
707 void WINAPI
SMapLS_IP_EBP_16(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,16);}
709 /***********************************************************************
710 * SMapLS_IP_EBP_20 (KERNEL32.595)
712 void WINAPI
SMapLS_IP_EBP_20(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,20);}
714 /***********************************************************************
715 * SMapLS_IP_EBP_24 (KERNEL32.596)
717 void WINAPI
SMapLS_IP_EBP_24(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,24);}
719 /***********************************************************************
720 * SMapLS_IP_EBP_28 (KERNEL32.597)
722 void WINAPI
SMapLS_IP_EBP_28(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,28);}
724 /***********************************************************************
725 * SMapLS_IP_EBP_32 (KERNEL32.598)
727 void WINAPI
SMapLS_IP_EBP_32(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,32);}
729 /***********************************************************************
730 * SMapLS_IP_EBP_36 (KERNEL32.599)
732 void WINAPI
SMapLS_IP_EBP_36(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,36);}
734 /***********************************************************************
735 * SMapLS_IP_EBP_40 (KERNEL32.600)
737 void WINAPI
SMapLS_IP_EBP_40(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,40);}
739 /***********************************************************************
740 * SMapLS (KERNEL32.592)
742 void WINAPI
SMapLS( CONTEXT86
*context
)
744 if (EAX_reg(context
)>=0x10000) {
745 EAX_reg(context
) = MapLS((LPVOID
)EAX_reg(context
));
746 EDX_reg(context
) = EAX_reg(context
);
748 EDX_reg(context
) = 0;
752 /***********************************************************************
753 * SUnMapLS (KERNEL32.602)
756 void WINAPI
SUnMapLS( CONTEXT86
*context
)
758 if (EAX_reg(context
)>=0x10000)
759 UnMapLS((SEGPTR
)EAX_reg(context
));
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;
769 /***********************************************************************
770 * SUnMapLS_IP_EBP_8 (KERNEL32.611)
772 void WINAPI
SUnMapLS_IP_EBP_8 (CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
, 8); }
774 /***********************************************************************
775 * SUnMapLS_IP_EBP_12 (KERNEL32.603)
777 void WINAPI
SUnMapLS_IP_EBP_12(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,12); }
779 /***********************************************************************
780 * SUnMapLS_IP_EBP_16 (KERNEL32.604)
782 void WINAPI
SUnMapLS_IP_EBP_16(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,16); }
784 /***********************************************************************
785 * SUnMapLS_IP_EBP_20 (KERNEL32.605)
787 void WINAPI
SUnMapLS_IP_EBP_20(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,20); }
789 /***********************************************************************
790 * SUnMapLS_IP_EBP_24 (KERNEL32.606)
792 void WINAPI
SUnMapLS_IP_EBP_24(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,24); }
794 /***********************************************************************
795 * SUnMapLS_IP_EBP_28 (KERNEL32.607)
797 void WINAPI
SUnMapLS_IP_EBP_28(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,28); }
799 /***********************************************************************
800 * SUnMapLS_IP_EBP_32 (KERNEL32.608)
802 void WINAPI
SUnMapLS_IP_EBP_32(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,32); }
804 /***********************************************************************
805 * SUnMapLS_IP_EBP_36 (KERNEL32.609)
807 void WINAPI
SUnMapLS_IP_EBP_36(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,36); }
809 /***********************************************************************
810 * SUnMapLS_IP_EBP_40 (KERNEL32.610)
812 void WINAPI
SUnMapLS_IP_EBP_40(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,40); }
814 /**********************************************************************
815 * AllocMappedBuffer (KERNEL32.38)
817 * This is a undocumented KERNEL32 function that
818 * SMapLS's a GlobalAlloc'ed buffer.
820 * Input: EDI register: size of buffer to allocate
821 * Output: EDI register: pointer to buffer
823 * Note: The buffer is preceeded by 8 bytes:
826 * edi-4 SEGPTR to buffer
827 * edi-8 some magic Win95 needs for SUnMapLS
828 * (we use it for the memory handle)
830 * The SEGPTR is used by the caller!
833 void WINAPI
AllocMappedBuffer( CONTEXT86
*context
)
835 HGLOBAL handle
= GlobalAlloc(0, EDI_reg(context
) + 8);
836 DWORD
*buffer
= (DWORD
*)GlobalLock(handle
);
840 if (!(ptr
= MapLS(buffer
+ 2)))
842 GlobalUnlock(handle
);
847 EAX_reg(context
) = EDI_reg(context
) = 0;
853 EAX_reg(context
) = (DWORD
) ptr
;
854 EDI_reg(context
) = (DWORD
)(buffer
+ 2);
858 /**********************************************************************
859 * FreeMappedBuffer (KERNEL32.39)
861 * Free a buffer allocated by AllocMappedBuffer
863 * Input: EDI register: pointer to buffer
866 void WINAPI
FreeMappedBuffer( CONTEXT86
*context
)
868 if (EDI_reg(context
))
870 DWORD
*buffer
= (DWORD
*)EDI_reg(context
) - 2;
874 GlobalUnlock(buffer
[0]);
875 GlobalFree(buffer
[0]);
880 /***********************************************************************
881 * UTSelectorOffsetToLinear (WIN32S16.48)
883 * rough guesswork, but seems to work (I had no "reasonable" docu)
885 LPVOID WINAPI
UTSelectorOffsetToLinear16(SEGPTR sptr
)
887 return PTR_SEG_TO_LIN(sptr
);
890 /***********************************************************************
891 * UTLinearToSelectorOffset (WIN32S16.49)
893 * FIXME: I don't know if that's the right way to do linear -> segmented
895 SEGPTR WINAPI
UTLinearToSelectorOffset16(LPVOID lptr
)
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" )