2 * Selector manipulation functions
4 * Copyright 1995 Alexandre Julliard
8 #include "wine/winbase16.h"
11 #include "selectors.h"
12 #include "stackframe.h"
14 #include "debugtools.h"
17 DEFAULT_DEBUG_CHANNEL(selector
)
20 /***********************************************************************
21 * AllocSelectorArray (KERNEL.206)
23 WORD WINAPI
AllocSelectorArray16( WORD count
)
25 WORD i
, sel
, size
= 0;
29 for (i
= FIRST_LDT_ENTRY_TO_ALLOC
; i
< LDT_SIZE
; i
++)
31 if (!IS_LDT_ENTRY_FREE(i
)) size
= 0;
32 else if (++size
>= count
) break;
34 if (i
== LDT_SIZE
) return 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 */
44 for (i
= 0; i
< count
; i
++)
46 /* Mark selector as allocated */
47 ldt_flags_copy
[sel
+ i
] |= LDT_FLAGS_ALLOCATED
;
48 LDT_SetEntry( sel
+ i
, &entry
);
50 return ENTRY_TO_SELECTOR( sel
);
54 /***********************************************************************
55 * AllocSelector (KERNEL.175)
57 WORD WINAPI
AllocSelector16( WORD sel
)
59 WORD newsel
, count
, i
;
61 count
= sel
? ((GET_SEL_LIMIT(sel
) >> 16) + 1) : 1;
62 newsel
= AllocSelectorArray16( count
);
63 TRACE("(%04x): returning %04x\n",
65 if (!newsel
) return 0;
66 if (!sel
) return newsel
; /* nothing to copy */
67 for (i
= 0; i
< count
; i
++)
70 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
71 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
) + i
, &entry
);
77 /***********************************************************************
78 * FreeSelector (KERNEL.176)
80 WORD WINAPI
FreeSelector16( WORD sel
)
82 if (IS_SELECTOR_FREE(sel
)) return sel
; /* error */
83 SELECTOR_FreeBlock( sel
, 1 );
88 /***********************************************************************
91 * Set the LDT entries for an array of selectors.
93 static void SELECTOR_SetEntries( WORD sel
, const void *base
, DWORD size
,
94 enum seg_type type
, BOOL is32bit
,
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
;
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
++)
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;
123 /***********************************************************************
124 * SELECTOR_AllocBlock
126 * Allocate selectors for a block of linear memory.
128 WORD
SELECTOR_AllocBlock( const void *base
, DWORD size
, enum seg_type type
,
129 BOOL is32bit
, BOOL readonly
)
134 count
= (size
+ 0xffff) / 0x10000;
135 sel
= AllocSelectorArray16( count
);
136 if (sel
) SELECTOR_SetEntries( sel
, base
, size
, type
, is32bit
, readonly
);
141 /***********************************************************************
144 * Move a block of selectors in linear memory.
146 void SELECTOR_MoveBlock( WORD sel
, const void *new_base
)
148 WORD i
, count
= (GET_SEL_LIMIT(sel
) >> 16) + 1;
150 for (i
= 0; i
< count
; i
++)
153 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
154 entry
.base
= (unsigned long)new_base
;
155 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
160 /***********************************************************************
163 * Free a block of selectors.
165 void SELECTOR_FreeBlock( WORD sel
, WORD count
)
170 TRACE("(%04x,%d)\n", sel
, count
);
171 sel
&= ~(__AHINCR
- 1); /* clear bottom bits of selector */
172 nextsel
= sel
+ (count
<< __AHSHIFT
);
176 /* Check if we are freeing current %fs or %gs selector */
180 if ((fs
>= sel
) && (fs
< nextsel
))
182 WARN("Freeing %%fs selector (%04x), not good.\n", fs
);
186 if ((gs
>= sel
) && (gs
< nextsel
)) SET_GS( 0 );
188 #endif /* __i386__ */
190 memset( &entry
, 0, sizeof(entry
) ); /* clear the LDT entries */
191 for (i
= SELECTOR_TO_ENTRY(sel
); count
; i
++, count
--)
193 LDT_SetEntry( i
, &entry
);
194 ldt_flags_copy
[i
] &= ~LDT_FLAGS_ALLOCATED
;
199 /***********************************************************************
200 * SELECTOR_ReallocBlock
202 * Change the size of a block of selectors.
204 WORD
SELECTOR_ReallocBlock( WORD sel
, const void *base
, DWORD size
)
207 WORD i
, oldcount
, newcount
;
210 oldcount
= (GET_SEL_LIMIT(sel
) >> 16) + 1;
211 newcount
= (size
+ 0xffff) >> 16;
212 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
214 if (oldcount
< newcount
) /* We need to add selectors */
216 /* Check if the next selectors are free */
217 if (SELECTOR_TO_ENTRY(sel
) + newcount
> LDT_SIZE
) i
= oldcount
;
219 for (i
= oldcount
; i
< newcount
; i
++)
220 if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel
)+i
)) break;
222 if (i
< newcount
) /* they are not free */
224 SELECTOR_FreeBlock( sel
, oldcount
);
225 sel
= AllocSelectorArray16( newcount
);
227 else /* mark the selectors as allocated */
229 for (i
= oldcount
; i
< newcount
; i
++)
230 ldt_flags_copy
[SELECTOR_TO_ENTRY(sel
)+i
] |=LDT_FLAGS_ALLOCATED
;
233 else if (oldcount
> newcount
) /* We need to remove selectors */
235 SELECTOR_FreeBlock( ENTRY_TO_SELECTOR(SELECTOR_TO_ENTRY(sel
)+newcount
),
236 oldcount
- newcount
);
238 if (sel
) SELECTOR_SetEntries( sel
, base
, size
, entry
.type
,
239 entry
.seg_32bit
, entry
.read_only
);
244 /***********************************************************************
245 * PrestoChangoSelector (KERNEL.177)
247 WORD WINAPI
PrestoChangoSelector16( WORD selSrc
, WORD selDst
)
250 LDT_GetEntry( SELECTOR_TO_ENTRY( selSrc
), &entry
);
251 entry
.type
^= SEGMENT_CODE
; /* toggle the executable bit */
252 LDT_SetEntry( SELECTOR_TO_ENTRY( selDst
), &entry
);
257 /***********************************************************************
258 * AllocCStoDSAlias (KERNEL.170)
260 WORD WINAPI
AllocCStoDSAlias16( WORD sel
)
265 newsel
= AllocSelectorArray16( 1 );
266 TRACE("(%04x): returning %04x\n",
268 if (!newsel
) return 0;
269 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
270 entry
.type
= SEGMENT_DATA
;
271 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
), &entry
);
276 /***********************************************************************
277 * AllocDStoCSAlias (KERNEL.171)
279 WORD WINAPI
AllocDStoCSAlias16( WORD sel
)
284 newsel
= AllocSelectorArray16( 1 );
285 TRACE("(%04x): returning %04x\n",
287 if (!newsel
) return 0;
288 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
289 entry
.type
= SEGMENT_CODE
;
290 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
), &entry
);
295 /***********************************************************************
296 * LongPtrAdd (KERNEL.180)
298 void WINAPI
LongPtrAdd16( DWORD ptr
, DWORD add
)
301 LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr
)), &entry
);
303 LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr
)), &entry
);
307 /***********************************************************************
308 * GetSelectorBase (KERNEL.186)
310 DWORD WINAPI
WIN16_GetSelectorBase( WORD sel
)
313 * Note: For Win32s processes, the whole linear address space is
314 * shifted by 0x10000 relative to the OS linear address space.
315 * See the comment in msdos/vxd.c.
318 DWORD base
= GetSelectorBase( sel
);
319 return W32S_WINE2APP( base
, W32S_APPLICATION() ? W32S_OFFSET
: 0 );
321 DWORD WINAPI
GetSelectorBase( WORD sel
)
323 DWORD base
= GET_SEL_BASE(sel
);
325 /* if base points into DOSMEM, assume we have to
326 * return pointer into physical lower 1MB */
328 return DOSMEM_MapLinearToDos( (LPVOID
)base
);
332 /***********************************************************************
333 * SetSelectorBase (KERNEL.187)
335 DWORD WINAPI
WIN16_SetSelectorBase( WORD sel
, DWORD base
)
338 * Note: For Win32s processes, the whole linear address space is
339 * shifted by 0x10000 relative to the OS linear address space.
340 * See the comment in msdos/vxd.c.
343 SetSelectorBase( sel
,
344 W32S_APP2WINE( base
, W32S_APPLICATION() ? W32S_OFFSET
: 0 ) );
347 WORD WINAPI
SetSelectorBase( WORD sel
, DWORD base
)
351 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
353 entry
.base
= (DWORD
)DOSMEM_MapDosToLinear(base
);
355 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
360 /***********************************************************************
361 * GetSelectorLimit (KERNEL.188)
363 DWORD WINAPI
GetSelectorLimit16( WORD sel
)
365 return GET_SEL_LIMIT(sel
);
369 /***********************************************************************
370 * SetSelectorLimit (KERNEL.189)
372 WORD WINAPI
SetSelectorLimit16( WORD sel
, DWORD limit
)
375 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
376 entry
.limit_in_pages
= (limit
>= 0x100000);
377 if (entry
.limit_in_pages
) entry
.limit
= limit
>> 12;
378 else entry
.limit
= limit
;
379 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
384 /***********************************************************************
385 * SelectorAccessRights (KERNEL.196)
387 WORD WINAPI
SelectorAccessRights16( WORD sel
, WORD op
, WORD val
)
390 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
391 if (op
== 0) /* get */
393 return 0x01 | /* accessed */
394 0x10 | /* not system */
397 ((entry
.read_only
== 0) << 1) |
399 (entry
.seg_32bit
<< 14) |
400 (entry
.limit_in_pages
<< 15);
404 entry
.read_only
= ((val
& 2) == 0);
405 entry
.type
= (val
>> 2) & 3;
406 entry
.seg_32bit
= val
& 0x4000;
407 entry
.limit_in_pages
= val
& 0x8000;
408 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
414 /***********************************************************************
415 * IsBadCodePtr16 (KERNEL.336)
417 BOOL16 WINAPI
IsBadCodePtr16( SEGPTR lpfn
)
422 sel
= SELECTOROF(lpfn
);
423 if (!sel
) return TRUE
;
424 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
425 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
426 if (entry
.type
!= SEGMENT_CODE
) return TRUE
;
427 if (OFFSETOF(lpfn
) > GET_SEL_LIMIT(sel
)) return TRUE
;
432 /***********************************************************************
433 * IsBadStringPtr16 (KERNEL.337)
435 BOOL16 WINAPI
IsBadStringPtr16( SEGPTR ptr
, UINT16 size
)
440 sel
= SELECTOROF(ptr
);
441 if (!sel
) return TRUE
;
442 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
443 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
444 if ((entry
.type
== SEGMENT_CODE
) && entry
.read_only
) return TRUE
;
445 if (strlen(PTR_SEG_TO_LIN(ptr
)) < size
) size
= strlen(PTR_SEG_TO_LIN(ptr
)) + 1;
446 if (size
&& (OFFSETOF(ptr
) + size
- 1 > GET_SEL_LIMIT(sel
))) return TRUE
;
451 /***********************************************************************
452 * IsBadHugeReadPtr16 (KERNEL.346)
454 BOOL16 WINAPI
IsBadHugeReadPtr16( SEGPTR ptr
, DWORD size
)
459 sel
= SELECTOROF(ptr
);
460 if (!sel
) return TRUE
;
461 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
462 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
463 if ((entry
.type
== SEGMENT_CODE
) && entry
.read_only
) return TRUE
;
464 if (size
&& (OFFSETOF(ptr
) + size
- 1 > GET_SEL_LIMIT(sel
))) return TRUE
;
469 /***********************************************************************
470 * IsBadHugeWritePtr16 (KERNEL.347)
472 BOOL16 WINAPI
IsBadHugeWritePtr16( SEGPTR ptr
, DWORD size
)
477 sel
= SELECTOROF(ptr
);
478 if (!sel
) return TRUE
;
479 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
480 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
481 if ((entry
.type
== SEGMENT_CODE
) || entry
.read_only
) return TRUE
;
482 if (size
&& (OFFSETOF(ptr
) + size
- 1 > GET_SEL_LIMIT(sel
))) return TRUE
;
486 /***********************************************************************
487 * IsBadReadPtr16 (KERNEL.334)
489 BOOL16 WINAPI
IsBadReadPtr16( SEGPTR ptr
, UINT16 size
)
491 return IsBadHugeReadPtr16( ptr
, size
);
495 /***********************************************************************
496 * IsBadWritePtr16 (KERNEL.335)
498 BOOL16 WINAPI
IsBadWritePtr16( SEGPTR ptr
, UINT16 size
)
500 return IsBadHugeWritePtr16( ptr
, size
);
504 /***********************************************************************
505 * IsBadFlatReadWritePtr16 (KERNEL.627)
507 BOOL16 WINAPI
IsBadFlatReadWritePtr16( SEGPTR ptr
, DWORD size
, BOOL16 bWrite
)
509 return bWrite
? IsBadHugeWritePtr16( ptr
, size
)
510 : IsBadHugeReadPtr16( ptr
, size
);
514 /***********************************************************************
515 * MemoryRead (TOOLHELP.78)
517 DWORD WINAPI
MemoryRead16( WORD sel
, DWORD offset
, void *buffer
, DWORD count
)
519 if (IS_SELECTOR_FREE(sel
)) return 0;
520 if (offset
> GET_SEL_LIMIT(sel
)) return 0;
521 if (offset
+ count
> GET_SEL_LIMIT(sel
) + 1)
522 count
= GET_SEL_LIMIT(sel
) + 1 - offset
;
523 memcpy( buffer
, ((char *)GET_SEL_BASE(sel
)) + offset
, count
);
528 /***********************************************************************
529 * MemoryWrite (TOOLHELP.79)
531 DWORD WINAPI
MemoryWrite16( WORD sel
, DWORD offset
, void *buffer
, DWORD count
)
533 if (IS_SELECTOR_FREE(sel
)) return 0;
534 if (offset
> GET_SEL_LIMIT(sel
)) return 0;
535 if (offset
+ count
> GET_SEL_LIMIT(sel
) + 1)
536 count
= GET_SEL_LIMIT(sel
) + 1 - offset
;
537 memcpy( ((char *)GET_SEL_BASE(sel
)) + offset
, buffer
, count
);
541 /************************************* Win95 pointer mapping functions *
545 /***********************************************************************
546 * MapSL (KERNEL32.523)
548 * Maps fixed segmented pointer to linear.
550 LPVOID WINAPI
MapSL( SEGPTR sptr
)
552 return (LPVOID
)PTR_SEG_TO_LIN(sptr
);
555 /***********************************************************************
556 * MapSLFix (KERNEL32.524)
558 * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
559 * unexpected linear address change when GlobalCompact() shuffles
563 LPVOID WINAPI
MapSLFix( SEGPTR sptr
)
565 return (LPVOID
)PTR_SEG_TO_LIN(sptr
);
568 /***********************************************************************
569 * UnMapSLFixArray (KERNEL32.701)
572 void WINAPI
UnMapSLFixArray( SEGPTR sptr
[], INT length
, CONTEXT86
*context
)
574 /* Must not change EAX, hence defined as 'register' function */
577 /***********************************************************************
578 * MapLS (KERNEL32.522)
580 * Maps linear pointer to segmented.
582 SEGPTR WINAPI
MapLS( LPVOID ptr
)
588 WORD sel
= SELECTOR_AllocBlock( ptr
, 0x10000, SEGMENT_DATA
, FALSE
, FALSE
);
589 return PTR_SEG_OFF_TO_SEGPTR( sel
, 0 );
594 /***********************************************************************
595 * UnMapLS (KERNEL32.700)
597 * Free mapped selector.
599 void WINAPI
UnMapLS( SEGPTR sptr
)
601 if (SELECTOROF(sptr
))
602 SELECTOR_FreeBlock( SELECTOROF(sptr
), 1 );
605 /***********************************************************************
606 * GetThreadSelectorEntry (KERNEL32)
607 * FIXME: add #ifdef i386 for non x86
609 BOOL WINAPI
GetThreadSelectorEntry( HANDLE hthread
, DWORD sel
,
614 LDT_GetEntry(SELECTOR_TO_ENTRY(sel
),&ldtentry
);
615 ldtent
->BaseLow
= ldtentry
.base
& 0x0000ffff;
616 ldtent
->HighWord
.Bits
.BaseMid
= (ldtentry
.base
& 0x00ff0000) >> 16;
617 ldtent
->HighWord
.Bits
.BaseHi
= (ldtentry
.base
& 0xff000000) >> 24;
618 ldtent
->LimitLow
= ldtentry
.limit
& 0x0000ffff;
619 ldtent
->HighWord
.Bits
.LimitHi
= (ldtentry
.limit
& 0x00ff0000) >> 16;
620 ldtent
->HighWord
.Bits
.Dpl
= 3;
621 ldtent
->HighWord
.Bits
.Sys
= 0;
622 ldtent
->HighWord
.Bits
.Pres
= 1;
623 ldtent
->HighWord
.Bits
.Type
= 0x10|(ldtentry
.type
<< 2);
624 if (!ldtentry
.read_only
)
625 ldtent
->HighWord
.Bits
.Type
|=0x2;
626 ldtent
->HighWord
.Bits
.Granularity
= ldtentry
.limit_in_pages
;
627 ldtent
->HighWord
.Bits
.Default_Big
= ldtentry
.seg_32bit
;
632 /**********************************************************************
634 * These functions map linear pointers at [EBP+xxx] to segmented pointers
636 * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
637 * unravel them at SUnMapLS. We just store the segmented pointer there.
640 x_SMapLS_IP_EBP_x(CONTEXT86
*context
,int argoff
) {
643 val
=*(DWORD
*)(EBP_reg(context
)+argoff
);
646 *(DWORD
*)(EBP_reg(context
)+argoff
) = 0;
648 ptr
= MapLS((LPVOID
)val
);
649 *(DWORD
*)(EBP_reg(context
)+argoff
) = ptr
;
651 EAX_reg(context
) = ptr
;
654 void WINAPI
SMapLS_IP_EBP_8 (CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
, 8);}
655 void WINAPI
SMapLS_IP_EBP_12(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,12);}
656 void WINAPI
SMapLS_IP_EBP_16(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,16);}
657 void WINAPI
SMapLS_IP_EBP_20(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,20);}
658 void WINAPI
SMapLS_IP_EBP_24(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,24);}
659 void WINAPI
SMapLS_IP_EBP_28(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,28);}
660 void WINAPI
SMapLS_IP_EBP_32(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,32);}
661 void WINAPI
SMapLS_IP_EBP_36(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,36);}
662 void WINAPI
SMapLS_IP_EBP_40(CONTEXT86
*context
) {x_SMapLS_IP_EBP_x(context
,40);}
664 void WINAPI
SMapLS( CONTEXT86
*context
)
666 if (EAX_reg(context
)>=0x10000) {
667 EAX_reg(context
) = MapLS((LPVOID
)EAX_reg(context
));
668 EDX_reg(context
) = EAX_reg(context
);
670 EDX_reg(context
) = 0;
674 void WINAPI
SUnMapLS( CONTEXT86
*context
)
676 if (EAX_reg(context
)>=0x10000)
677 UnMapLS((SEGPTR
)EAX_reg(context
));
681 x_SUnMapLS_IP_EBP_x(CONTEXT86
*context
,int argoff
) {
682 if (*(DWORD
*)(EBP_reg(context
)+argoff
))
683 UnMapLS(*(DWORD
*)(EBP_reg(context
)+argoff
));
684 *(DWORD
*)(EBP_reg(context
)+argoff
)=0;
686 void WINAPI
SUnMapLS_IP_EBP_8 (CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
, 8); }
687 void WINAPI
SUnMapLS_IP_EBP_12(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,12); }
688 void WINAPI
SUnMapLS_IP_EBP_16(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,16); }
689 void WINAPI
SUnMapLS_IP_EBP_20(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,20); }
690 void WINAPI
SUnMapLS_IP_EBP_24(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,24); }
691 void WINAPI
SUnMapLS_IP_EBP_28(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,28); }
692 void WINAPI
SUnMapLS_IP_EBP_32(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,32); }
693 void WINAPI
SUnMapLS_IP_EBP_36(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,36); }
694 void WINAPI
SUnMapLS_IP_EBP_40(CONTEXT86
*context
) { x_SUnMapLS_IP_EBP_x(context
,40); }
696 /**********************************************************************
697 * AllocMappedBuffer (KERNEL32.38)
699 * This is a undocumented KERNEL32 function that
700 * SMapLS's a GlobalAlloc'ed buffer.
702 * Input: EDI register: size of buffer to allocate
703 * Output: EDI register: pointer to buffer
705 * Note: The buffer is preceeded by 8 bytes:
708 * edi-4 SEGPTR to buffer
709 * edi-8 some magic Win95 needs for SUnMapLS
710 * (we use it for the memory handle)
712 * The SEGPTR is used by the caller!
715 void WINAPI
AllocMappedBuffer( CONTEXT86
*context
)
717 HGLOBAL handle
= GlobalAlloc(0, EDI_reg(context
) + 8);
718 DWORD
*buffer
= (DWORD
*)GlobalLock(handle
);
722 if (!(ptr
= MapLS(buffer
+ 2)))
724 GlobalUnlock(handle
);
729 EAX_reg(context
) = EDI_reg(context
) = 0;
735 EAX_reg(context
) = (DWORD
) ptr
;
736 EDI_reg(context
) = (DWORD
)(buffer
+ 2);
740 /**********************************************************************
741 * FreeMappedBuffer (KERNEL32.39)
743 * Free a buffer allocated by AllocMappedBuffer
745 * Input: EDI register: pointer to buffer
748 void WINAPI
FreeMappedBuffer( CONTEXT86
*context
)
750 if (EDI_reg(context
))
752 DWORD
*buffer
= (DWORD
*)EDI_reg(context
) - 2;
756 GlobalUnlock(buffer
[0]);
757 GlobalFree(buffer
[0]);
762 /***********************************************************************
763 * UTSelectorOffsetToLinear (WIN32S16.48)
765 * rough guesswork, but seems to work (I had no "reasonable" docu)
767 LPVOID WINAPI
UTSelectorOffsetToLinear16(SEGPTR sptr
)
769 return PTR_SEG_TO_LIN(sptr
);
772 /***********************************************************************
773 * UTLinearToSelectorOffset (WIN32S16.49)
775 * FIXME: I don't know if that's the right way to do linear -> segmented
777 SEGPTR WINAPI
UTLinearToSelectorOffset16(LPVOID lptr
)