2 * Selector manipulation functions
4 * Copyright 1995 Alexandre Julliard
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.
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.
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
22 #include "wine/port.h"
26 #include "wine/winbase16.h"
27 #include "wine/server.h"
28 #include "wine/debug.h"
29 #include "kernel16_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(selector
);
35 /* get the number of selectors needed to cover up to the selector limit */
36 static inline WORD
get_sel_count( WORD sel
)
38 return (wine_ldt_copy
.limit
[sel
>> __AHSHIFT
] >> 16) + 1;
42 /***********************************************************************
43 * AllocSelectorArray (KERNEL.206)
45 WORD WINAPI
AllocSelectorArray16( WORD count
)
47 WORD i
, sel
= wine_ldt_alloc_entries( count
);
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
++)
57 if (wine_ldt_set_entry( sel
+ (i
<< __AHSHIFT
), &entry
) < 0)
59 wine_ldt_free_entries( sel
, count
);
68 /***********************************************************************
69 * AllocSelector (KERNEL.175)
71 WORD WINAPI
AllocSelector16( WORD sel
)
73 WORD newsel
, count
, i
;
75 count
= sel
? get_sel_count(sel
) : 1;
76 newsel
= wine_ldt_alloc_entries( count
);
77 TRACE("(%04x): returning %04x\n", sel
, newsel
);
78 if (!newsel
) return 0;
79 if (!sel
) return newsel
; /* nothing to copy */
80 for (i
= 0; i
< count
; i
++)
83 wine_ldt_get_entry( sel
+ (i
<< __AHSHIFT
), &entry
);
84 wine_ldt_set_entry( newsel
+ (i
<< __AHSHIFT
), &entry
);
90 /***********************************************************************
91 * FreeSelector (KERNEL.176)
93 WORD WINAPI
FreeSelector16( WORD sel
)
97 wine_ldt_get_entry( sel
, &entry
);
98 if (wine_ldt_is_empty( &entry
)) return sel
; /* error */
99 /* Check if we are freeing current %fs selector */
100 if (!((wine_get_fs() ^ sel
) & ~3))
101 WARN("Freeing %%fs selector (%04x), not good.\n", wine_get_fs() );
102 wine_ldt_free_entries( sel
, 1 );
107 /***********************************************************************
108 * SELECTOR_SetEntries
110 * Set the LDT entries for an array of selectors.
112 static BOOL
SELECTOR_SetEntries( WORD sel
, const void *base
, DWORD size
, unsigned char flags
)
117 wine_ldt_set_base( &entry
, base
);
118 wine_ldt_set_limit( &entry
, size
- 1 );
119 wine_ldt_set_flags( &entry
, flags
);
120 count
= (size
+ 0xffff) / 0x10000;
121 for (i
= 0; i
< count
; i
++)
123 if (wine_ldt_set_entry( sel
+ (i
<< __AHSHIFT
), &entry
) < 0) return FALSE
;
124 wine_ldt_set_base( &entry
, (char*)wine_ldt_get_base(&entry
) + 0x10000);
125 /* yep, Windows sets limit like that, not 64K sel units */
126 wine_ldt_set_limit( &entry
, wine_ldt_get_limit(&entry
) - 0x10000 );
132 /***********************************************************************
133 * SELECTOR_AllocBlock
135 * Allocate selectors for a block of linear memory.
137 WORD
SELECTOR_AllocBlock( const void *base
, DWORD size
, unsigned char flags
)
142 count
= (size
+ 0xffff) / 0x10000;
143 if ((sel
= wine_ldt_alloc_entries( count
)))
145 if (SELECTOR_SetEntries( sel
, base
, size
, flags
)) return sel
;
146 wine_ldt_free_entries( sel
, count
);
153 /***********************************************************************
156 * Free a block of selectors.
158 void SELECTOR_FreeBlock( WORD sel
)
160 WORD i
, count
= get_sel_count( sel
);
162 TRACE("(%04x,%d)\n", sel
, count
);
163 for (i
= 0; i
< count
; i
++) FreeSelector16( sel
+ (i
<< __AHSHIFT
) );
167 /***********************************************************************
168 * SELECTOR_ReallocBlock
170 * Change the size of a block of selectors.
172 WORD
SELECTOR_ReallocBlock( WORD sel
, const void *base
, DWORD size
)
175 int oldcount
, newcount
;
178 wine_ldt_get_entry( sel
, &entry
);
179 oldcount
= (wine_ldt_get_limit(&entry
) >> 16) + 1;
180 newcount
= (size
+ 0xffff) >> 16;
182 sel
= wine_ldt_realloc_entries( sel
, oldcount
, newcount
);
183 if (sel
) SELECTOR_SetEntries( sel
, base
, size
, wine_ldt_get_flags(&entry
) );
188 /***********************************************************************
189 * PrestoChangoSelector (KERNEL.177)
191 WORD WINAPI
PrestoChangoSelector16( WORD selSrc
, WORD selDst
)
194 wine_ldt_get_entry( selSrc
, &entry
);
195 /* toggle the executable bit */
196 entry
.HighWord
.Bits
.Type
^= (WINE_LDT_FLAGS_CODE
^ WINE_LDT_FLAGS_DATA
);
197 wine_ldt_set_entry( selDst
, &entry
);
202 /***********************************************************************
203 * AllocCStoDSAlias (KERNEL.170)
204 * AllocAlias (KERNEL.172)
206 WORD WINAPI
AllocCStoDSAlias16( WORD sel
)
211 newsel
= wine_ldt_alloc_entries( 1 );
212 TRACE("(%04x): returning %04x\n",
214 if (!newsel
) return 0;
215 wine_ldt_get_entry( sel
, &entry
);
216 entry
.HighWord
.Bits
.Type
= WINE_LDT_FLAGS_DATA
;
217 if (wine_ldt_set_entry( newsel
, &entry
) >= 0) return newsel
;
218 wine_ldt_free_entries( newsel
, 1 );
223 /***********************************************************************
224 * AllocDStoCSAlias (KERNEL.171)
226 WORD WINAPI
AllocDStoCSAlias16( WORD sel
)
231 newsel
= wine_ldt_alloc_entries( 1 );
232 TRACE("(%04x): returning %04x\n",
234 if (!newsel
) return 0;
235 wine_ldt_get_entry( sel
, &entry
);
236 entry
.HighWord
.Bits
.Type
= WINE_LDT_FLAGS_CODE
;
237 if (wine_ldt_set_entry( newsel
, &entry
) >= 0) return newsel
;
238 wine_ldt_free_entries( newsel
, 1 );
243 /***********************************************************************
244 * LongPtrAdd (KERNEL.180)
246 void WINAPI
LongPtrAdd16( DWORD ptr
, DWORD add
)
249 wine_ldt_get_entry( SELECTOROF(ptr
), &entry
);
250 wine_ldt_set_base( &entry
, (char *)wine_ldt_get_base(&entry
) + add
);
251 wine_ldt_set_entry( SELECTOROF(ptr
), &entry
);
255 /***********************************************************************
256 * GetSelectorBase (KERNEL.186)
258 DWORD WINAPI
GetSelectorBase( WORD sel
)
260 void *base
= wine_ldt_copy
.base
[sel
>> __AHSHIFT
];
262 /* if base points into DOSMEM, assume we have to
263 * return pointer into physical lower 1MB */
265 return DOSMEM_MapLinearToDos( base
);
269 /***********************************************************************
270 * SetSelectorBase (KERNEL.187)
272 WORD WINAPI
SetSelectorBase( WORD sel
, DWORD base
)
275 wine_ldt_get_entry( sel
, &entry
);
276 wine_ldt_set_base( &entry
, DOSMEM_MapDosToLinear(base
) );
277 if (wine_ldt_set_entry( sel
, &entry
) < 0) sel
= 0;
282 /***********************************************************************
283 * GetSelectorLimit (KERNEL.188)
285 DWORD WINAPI
GetSelectorLimit16( WORD sel
)
287 return wine_ldt_copy
.limit
[sel
>> __AHSHIFT
];
291 /***********************************************************************
292 * SetSelectorLimit (KERNEL.189)
294 WORD WINAPI
SetSelectorLimit16( WORD sel
, DWORD limit
)
297 wine_ldt_get_entry( sel
, &entry
);
298 wine_ldt_set_limit( &entry
, limit
);
299 if (wine_ldt_set_entry( sel
, &entry
) < 0) sel
= 0;
304 /***********************************************************************
305 * SelectorAccessRights (KERNEL.196)
307 WORD WINAPI
SelectorAccessRights16( WORD sel
, WORD op
, WORD val
)
310 wine_ldt_get_entry( sel
, &entry
);
312 if (op
== 0) /* get */
314 return entry
.HighWord
.Bytes
.Flags1
| ((entry
.HighWord
.Bytes
.Flags2
& 0xf0) << 8);
318 entry
.HighWord
.Bytes
.Flags1
= LOBYTE(val
) | 0xf0;
319 entry
.HighWord
.Bytes
.Flags2
= (entry
.HighWord
.Bytes
.Flags2
& 0x0f) | (HIBYTE(val
) & 0xf0);
320 wine_ldt_set_entry( sel
, &entry
);
326 /***********************************************************************
327 * IsBadCodePtr (KERNEL.336)
329 BOOL16 WINAPI
IsBadCodePtr16( SEGPTR lpfn
)
334 sel
= SELECTOROF(lpfn
);
335 if (!sel
) return TRUE
;
336 wine_ldt_get_entry( sel
, &entry
);
337 if (wine_ldt_is_empty( &entry
)) return TRUE
;
338 /* check for code segment, ignoring conforming, read-only and accessed bits */
339 if ((entry
.HighWord
.Bits
.Type
^ WINE_LDT_FLAGS_CODE
) & 0x18) return TRUE
;
340 if (OFFSETOF(lpfn
) > wine_ldt_get_limit(&entry
)) return TRUE
;
345 /***********************************************************************
346 * IsBadStringPtr (KERNEL.337)
348 BOOL16 WINAPI
IsBadStringPtr16( SEGPTR ptr
, UINT16 size
)
353 sel
= SELECTOROF(ptr
);
354 if (!sel
) return TRUE
;
355 wine_ldt_get_entry( sel
, &entry
);
356 if (wine_ldt_is_empty( &entry
)) return TRUE
;
357 /* check for data or readable code segment */
358 if (!(entry
.HighWord
.Bits
.Type
& 0x10)) return TRUE
; /* system descriptor */
359 if ((entry
.HighWord
.Bits
.Type
& 0x0a) == 0x08) return TRUE
; /* non-readable code segment */
360 if (strlen(MapSL(ptr
)) < size
) size
= strlen(MapSL(ptr
)) + 1;
361 if (size
&& (OFFSETOF(ptr
) + size
- 1 > wine_ldt_get_limit(&entry
))) return TRUE
;
366 /***********************************************************************
367 * IsBadHugeReadPtr (KERNEL.346)
369 BOOL16 WINAPI
IsBadHugeReadPtr16( SEGPTR ptr
, DWORD size
)
374 sel
= SELECTOROF(ptr
);
375 if (!sel
) return TRUE
;
376 wine_ldt_get_entry( sel
, &entry
);
377 if (wine_ldt_is_empty( &entry
)) return TRUE
;
378 /* check for data or readable code segment */
379 if (!(entry
.HighWord
.Bits
.Type
& 0x10)) return TRUE
; /* system descriptor */
380 if ((entry
.HighWord
.Bits
.Type
& 0x0a) == 0x08) return TRUE
; /* non-readable code segment */
381 if (size
&& (OFFSETOF(ptr
) + size
- 1 > wine_ldt_get_limit( &entry
))) return TRUE
;
386 /***********************************************************************
387 * IsBadHugeWritePtr (KERNEL.347)
389 BOOL16 WINAPI
IsBadHugeWritePtr16( SEGPTR ptr
, DWORD size
)
394 sel
= SELECTOROF(ptr
);
395 if (!sel
) return TRUE
;
396 wine_ldt_get_entry( sel
, &entry
);
397 if (wine_ldt_is_empty( &entry
)) return TRUE
;
398 /* check for writable data segment, ignoring expand-down and accessed flags */
399 if ((entry
.HighWord
.Bits
.Type
^ WINE_LDT_FLAGS_DATA
) & ~5) return TRUE
;
400 if (size
&& (OFFSETOF(ptr
) + size
- 1 > wine_ldt_get_limit( &entry
))) return TRUE
;
404 /***********************************************************************
405 * IsBadReadPtr (KERNEL.334)
407 BOOL16 WINAPI
IsBadReadPtr16( SEGPTR ptr
, UINT16 size
)
409 return IsBadHugeReadPtr16( ptr
, size
);
413 /***********************************************************************
414 * IsBadWritePtr (KERNEL.335)
416 BOOL16 WINAPI
IsBadWritePtr16( SEGPTR ptr
, UINT16 size
)
418 return IsBadHugeWritePtr16( ptr
, size
);
422 /***********************************************************************
423 * IsBadFlatReadWritePtr (KERNEL.627)
425 BOOL16 WINAPI
IsBadFlatReadWritePtr16( SEGPTR ptr
, DWORD size
, BOOL16 bWrite
)
427 return bWrite
? IsBadHugeWritePtr16( ptr
, size
)
428 : IsBadHugeReadPtr16( ptr
, size
);
432 /************************************* Win95 pointer mapping functions *
438 struct mapls_entry
*next
;
439 void *addr
; /* linear address */
440 int count
; /* ref count */
441 WORD sel
; /* selector */
444 static struct mapls_entry
*first_entry
;
447 /***********************************************************************
451 * Maps linear pointer to segmented.
453 SEGPTR WINAPI
MapLS( LPCVOID ptr
)
455 struct mapls_entry
*entry
, *free
= NULL
;
459 if (!HIWORD(ptr
)) return (SEGPTR
)LOWORD(ptr
);
461 base
= (const char *)ptr
- ((ULONG_PTR
)ptr
& 0x7fff);
462 HeapLock( GetProcessHeap() );
463 for (entry
= first_entry
; entry
; entry
= entry
->next
)
465 if (entry
->addr
== base
) break;
466 if (!entry
->count
) free
= entry
;
471 if (!free
) /* no free entry found, create a new one */
473 if (!(free
= HeapAlloc( GetProcessHeap(), 0, sizeof(*free
) ))) goto done
;
474 if (!(free
->sel
= SELECTOR_AllocBlock( base
, 0x10000, WINE_LDT_FLAGS_DATA
)))
476 HeapFree( GetProcessHeap(), 0, free
);
480 free
->next
= first_entry
;
483 SetSelectorBase( free
->sel
, (DWORD
)base
);
484 free
->addr
= (void*)base
;
488 ret
= MAKESEGPTR( entry
->sel
, (const char *)ptr
- (char *)entry
->addr
);
490 HeapUnlock( GetProcessHeap() );
494 /***********************************************************************
495 * UnMapLS (KERNEL32.@)
496 * UnMapLS (KERNEL.359)
498 * Free mapped selector.
500 void WINAPI
UnMapLS( SEGPTR sptr
)
502 struct mapls_entry
*entry
;
503 WORD sel
= SELECTOROF(sptr
);
507 HeapLock( GetProcessHeap() );
508 for (entry
= first_entry
; entry
; entry
= entry
->next
) if (entry
->sel
== sel
) break;
509 if (entry
&& entry
->count
> 0) entry
->count
--;
510 HeapUnlock( GetProcessHeap() );
514 /***********************************************************************
518 * Maps fixed segmented pointer to linear.
520 LPVOID WINAPI
MapSL( SEGPTR sptr
)
522 return (char *)wine_ldt_copy
.base
[SELECTOROF(sptr
) >> __AHSHIFT
] + OFFSETOF(sptr
);
525 /***********************************************************************
526 * MapSLFix (KERNEL32.@)
528 * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
529 * unexpected linear address change when GlobalCompact() shuffles
533 LPVOID WINAPI
MapSLFix( SEGPTR sptr
)
539 /***********************************************************************
540 * UnMapSLFixArray (KERNEL32.@)
542 * Must not change EAX, hence defined as asm function.
544 __ASM_STDCALL_FUNC( UnMapSLFixArray
, 8, "ret $8" )
546 /***********************************************************************
547 * SMapLS (KERNEL32.@)
549 __ASM_STDCALL_FUNC( SMapLS
, 0,
551 "testl $0xffff0000,%eax\n\t"
554 "call " __ASM_NAME("MapLS") __ASM_STDCALL(4) "\n\t"
558 /***********************************************************************
559 * SUnMapLS (KERNEL32.@)
561 __ASM_STDCALL_FUNC( SUnMapLS
, 0,
562 "pushl %eax\n\t" /* preserve eax */
564 "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t"
568 /***********************************************************************
569 * SMapLS_IP_EBP_8 (KERNEL32.@)
571 * These functions map linear pointers at [EBP+xxx] to segmented pointers
573 * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
574 * unravel them at SUnMapLS. We just store the segmented pointer there.
576 __ASM_STDCALL_FUNC( SMapLS_IP_EBP_8
, 0,
577 "movl 8(%ebp),%eax\n\t"
578 "call " __ASM_NAME("SMapLS") __ASM_STDCALL(4) "\n\t"
579 "movl %edx,8(%ebp)\n\t"
582 /***********************************************************************
583 * SMapLS_IP_EBP_12 (KERNEL32.@)
585 __ASM_STDCALL_FUNC( SMapLS_IP_EBP_12
, 0,
586 "movl 12(%ebp),%eax\n\t"
587 "call " __ASM_NAME("SMapLS") __ASM_STDCALL(4) "\n\t"
588 "movl %edx,12(%ebp)\n\t"
591 /***********************************************************************
592 * SMapLS_IP_EBP_16 (KERNEL32.@)
594 __ASM_STDCALL_FUNC( SMapLS_IP_EBP_16
, 0,
595 "movl 16(%ebp),%eax\n\t"
596 "call " __ASM_NAME("SMapLS") __ASM_STDCALL(4) "\n\t"
597 "movl %edx,16(%ebp)\n\t"
600 /***********************************************************************
601 * SMapLS_IP_EBP_20 (KERNEL32.@)
603 __ASM_STDCALL_FUNC( SMapLS_IP_EBP_20
, 0,
604 "movl 20(%ebp),%eax\n\t"
605 "call " __ASM_NAME("SMapLS") __ASM_STDCALL(4) "\n\t"
606 "movl %edx,20(%ebp)\n\t"
609 /***********************************************************************
610 * SMapLS_IP_EBP_24 (KERNEL32.@)
612 __ASM_STDCALL_FUNC( SMapLS_IP_EBP_24
, 0,
613 "movl 24(%ebp),%eax\n\t"
614 "call " __ASM_NAME("SMapLS") __ASM_STDCALL(4) "\n\t"
615 "movl %edx,24(%ebp)\n\t"
618 /***********************************************************************
619 * SMapLS_IP_EBP_28 (KERNEL32.@)
621 __ASM_STDCALL_FUNC( SMapLS_IP_EBP_28
, 0,
622 "movl 28(%ebp),%eax\n\t"
623 "call " __ASM_NAME("SMapLS") __ASM_STDCALL(4) "\n\t"
624 "movl %edx,28(%ebp)\n\t"
627 /***********************************************************************
628 * SMapLS_IP_EBP_32 (KERNEL32.@)
630 __ASM_STDCALL_FUNC( SMapLS_IP_EBP_32
, 0,
631 "movl 32(%ebp),%eax\n\t"
632 "call " __ASM_NAME("SMapLS") __ASM_STDCALL(4) "\n\t"
633 "movl %edx,32(%ebp)\n\t"
636 /***********************************************************************
637 * SMapLS_IP_EBP_36 (KERNEL32.@)
639 __ASM_STDCALL_FUNC( SMapLS_IP_EBP_36
, 0,
640 "movl 36(%ebp),%eax\n\t"
641 "call " __ASM_NAME("SMapLS") __ASM_STDCALL(4) "\n\t"
642 "movl %edx,36(%ebp)\n\t"
645 /***********************************************************************
646 * SMapLS_IP_EBP_40 (KERNEL32.@)
648 __ASM_STDCALL_FUNC( SMapLS_IP_EBP_40
, 0,
649 "movl 40(%ebp),%eax\n\t"
650 "call " __ASM_NAME("SMapLS") __ASM_STDCALL(4) "\n\t"
651 "movl %edx,40(%ebp)\n\t"
654 /***********************************************************************
655 * SUnMapLS_IP_EBP_8 (KERNEL32.@)
657 __ASM_STDCALL_FUNC( SUnMapLS_IP_EBP_8
, 0,
658 "pushl %eax\n\t" /* preserve eax */
660 "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t"
661 "movl $0,8(%ebp)\n\t"
665 /***********************************************************************
666 * SUnMapLS_IP_EBP_12 (KERNEL32.@)
668 __ASM_STDCALL_FUNC( SUnMapLS_IP_EBP_12
, 0,
669 "pushl %eax\n\t" /* preserve eax */
671 "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t"
672 "movl $0,12(%ebp)\n\t"
676 /***********************************************************************
677 * SUnMapLS_IP_EBP_16 (KERNEL32.@)
679 __ASM_STDCALL_FUNC( SUnMapLS_IP_EBP_16
, 0,
680 "pushl %eax\n\t" /* preserve eax */
682 "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t"
683 "movl $0,16(%ebp)\n\t"
687 /***********************************************************************
688 * SUnMapLS_IP_EBP_20 (KERNEL32.@)
690 __ASM_STDCALL_FUNC( SUnMapLS_IP_EBP_20
, 0,
691 "pushl %eax\n\t" /* preserve eax */
693 "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t"
694 "movl $0,20(%ebp)\n\t"
698 /***********************************************************************
699 * SUnMapLS_IP_EBP_24 (KERNEL32.@)
701 __ASM_STDCALL_FUNC( SUnMapLS_IP_EBP_24
, 0,
702 "pushl %eax\n\t" /* preserve eax */
704 "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t"
705 "movl $0,24(%ebp)\n\t"
709 /***********************************************************************
710 * SUnMapLS_IP_EBP_28 (KERNEL32.@)
712 __ASM_STDCALL_FUNC( SUnMapLS_IP_EBP_28
, 0,
713 "pushl %eax\n\t" /* preserve eax */
715 "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t"
716 "movl $0,28(%ebp)\n\t"
720 /***********************************************************************
721 * SUnMapLS_IP_EBP_32 (KERNEL32.@)
723 __ASM_STDCALL_FUNC( SUnMapLS_IP_EBP_32
, 0,
724 "pushl %eax\n\t" /* preserve eax */
726 "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t"
727 "movl $0,32(%ebp)\n\t"
731 /***********************************************************************
732 * SUnMapLS_IP_EBP_36 (KERNEL32.@)
734 __ASM_STDCALL_FUNC( SUnMapLS_IP_EBP_36
, 0,
735 "pushl %eax\n\t" /* preserve eax */
737 "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t"
738 "movl $0,36(%ebp)\n\t"
742 /***********************************************************************
743 * SUnMapLS_IP_EBP_40 (KERNEL32.@)
745 __ASM_STDCALL_FUNC( SUnMapLS_IP_EBP_40
, 0,
746 "pushl %eax\n\t" /* preserve eax */
748 "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t"
749 "movl $0,40(%ebp)\n\t"