2 * Selector manipulation functions
4 * Copyright 1995 Alexandre Julliard
11 #include "selectors.h"
12 #include "stackframe.h"
17 /***********************************************************************
18 * AllocSelectorArray (KERNEL.206)
20 WORD WINAPI
AllocSelectorArray( WORD count
)
22 WORD i
, sel
, size
= 0;
26 for (i
= FIRST_LDT_ENTRY_TO_ALLOC
; i
< LDT_SIZE
; i
++)
28 if (!IS_LDT_ENTRY_FREE(i
)) size
= 0;
29 else if (++size
>= count
) break;
31 if (i
== LDT_SIZE
) return 0;
35 entry
.type
= SEGMENT_DATA
;
36 entry
.seg_32bit
= FALSE
;
37 entry
.read_only
= FALSE
;
38 entry
.limit_in_pages
= FALSE
;
39 entry
.limit
= 1; /* avoid 0 base and limit */
41 for (i
= 0; i
< count
; i
++)
43 /* Mark selector as allocated */
44 ldt_flags_copy
[sel
+ i
] |= LDT_FLAGS_ALLOCATED
;
45 LDT_SetEntry( sel
+ i
, &entry
);
47 return ENTRY_TO_SELECTOR( sel
);
51 /***********************************************************************
52 * AllocSelector (KERNEL.175)
54 WORD WINAPI
AllocSelector( WORD sel
)
56 WORD newsel
, count
, i
;
58 count
= sel
? ((GET_SEL_LIMIT(sel
) >> 16) + 1) : 1;
59 newsel
= AllocSelectorArray( count
);
60 TRACE(selector
, "(%04x): returning %04x\n",
62 if (!newsel
) return 0;
63 if (!sel
) return newsel
; /* nothing to copy */
64 for (i
= 0; i
< count
; i
++)
67 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
68 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
) + i
, &entry
);
74 /***********************************************************************
75 * FreeSelector (KERNEL.176)
77 WORD WINAPI
FreeSelector( WORD sel
)
79 if (IS_SELECTOR_FREE(sel
)) return sel
; /* error */
80 SELECTOR_FreeBlock( sel
, 1 );
85 /***********************************************************************
88 * Set the LDT entries for an array of selectors.
90 static void SELECTOR_SetEntries( WORD sel
, const void *base
, DWORD size
,
91 enum seg_type type
, BOOL32 is32bit
,
97 /* The limit for the first selector is the whole */
98 /* block. The next selectors get a 64k limit. */
99 entry
.base
= (unsigned long)base
;
101 entry
.seg_32bit
= is32bit
;
102 entry
.read_only
= readonly
;
103 entry
.limit_in_pages
= (size
> 0x100000);
104 if (entry
.limit_in_pages
) entry
.limit
= ((size
+ 0xfff) >> 12) - 1;
105 else entry
.limit
= size
- 1;
106 /* Make sure base and limit are not 0 together if the size is not 0 */
107 if (!base
&& !entry
.limit
&& size
) entry
.limit
= 1;
108 count
= (size
+ 0xffff) / 0x10000;
109 for (i
= 0; i
< count
; i
++)
111 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
112 entry
.base
+= 0x10000;
113 /* Apparently the next selectors should *not* get a 64k limit. */
114 /* Can't remember where I read they should... --AJ */
115 entry
.limit
-= entry
.limit_in_pages
? 0x10 : 0x10000;
120 /***********************************************************************
121 * SELECTOR_AllocBlock
123 * Allocate selectors for a block of linear memory.
125 WORD
SELECTOR_AllocBlock( const void *base
, DWORD size
, enum seg_type type
,
126 BOOL32 is32bit
, BOOL32 readonly
)
131 count
= (size
+ 0xffff) / 0x10000;
132 sel
= AllocSelectorArray( count
);
133 if (sel
) SELECTOR_SetEntries( sel
, base
, size
, type
, is32bit
, readonly
);
138 /***********************************************************************
141 * Move a block of selectors in linear memory.
143 void SELECTOR_MoveBlock( WORD sel
, const void *new_base
)
145 WORD i
, count
= (GET_SEL_LIMIT(sel
) >> 16) + 1;
147 for (i
= 0; i
< count
; i
++)
150 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
151 entry
.base
= (unsigned long)new_base
;
152 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
157 /***********************************************************************
160 * Free a block of selectors.
162 void SELECTOR_FreeBlock( WORD sel
, WORD count
)
167 TRACE(selector
, "(%04x,%d)\n", sel
, count
);
168 sel
&= ~(__AHINCR
- 1); /* clear bottom bits of selector */
169 nextsel
= sel
+ (count
<< __AHSHIFT
);
173 /* Check if we are freeing current %fs or %gs selector */
177 if ((fs
>= sel
) && (fs
< nextsel
))
179 WARN(selector
, "Freeing %%fs selector (%04x), not good.\n", fs
);
183 if ((gs
>= sel
) && (gs
< nextsel
)) SET_GS( 0 );
185 #endif /* __i386__ */
187 memset( &entry
, 0, sizeof(entry
) ); /* clear the LDT entries */
188 for (i
= SELECTOR_TO_ENTRY(sel
); count
; i
++, count
--)
190 LDT_SetEntry( i
, &entry
);
191 ldt_flags_copy
[i
] &= ~LDT_FLAGS_ALLOCATED
;
196 /***********************************************************************
197 * SELECTOR_ReallocBlock
199 * Change the size of a block of selectors.
201 WORD
SELECTOR_ReallocBlock( WORD sel
, const void *base
, DWORD size
,
202 enum seg_type type
, BOOL32 is32bit
, BOOL32 readonly
)
204 WORD i
, oldcount
, newcount
;
207 oldcount
= (GET_SEL_LIMIT(sel
) >> 16) + 1;
208 newcount
= (size
+ 0xffff) >> 16;
210 if (oldcount
< newcount
) /* We need to add selectors */
212 /* Check if the next selectors are free */
213 if (SELECTOR_TO_ENTRY(sel
) + newcount
> LDT_SIZE
) i
= oldcount
;
215 for (i
= oldcount
; i
< newcount
; i
++)
216 if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel
)+i
)) break;
218 if (i
< newcount
) /* they are not free */
220 SELECTOR_FreeBlock( sel
, oldcount
);
221 sel
= AllocSelectorArray( newcount
);
223 else /* mark the selectors as allocated */
225 for (i
= oldcount
; i
< newcount
; i
++)
226 ldt_flags_copy
[SELECTOR_TO_ENTRY(sel
)+i
] |=LDT_FLAGS_ALLOCATED
;
229 else if (oldcount
> newcount
) /* We need to remove selectors */
231 SELECTOR_FreeBlock( ENTRY_TO_SELECTOR(SELECTOR_TO_ENTRY(sel
)+newcount
),
232 oldcount
- newcount
);
234 if (sel
) SELECTOR_SetEntries( sel
, base
, size
, type
, is32bit
, readonly
);
239 /***********************************************************************
240 * PrestoChangoSelector (KERNEL.177)
242 WORD WINAPI
PrestoChangoSelector( WORD selSrc
, WORD selDst
)
245 LDT_GetEntry( SELECTOR_TO_ENTRY( selSrc
), &entry
);
246 entry
.type
^= SEGMENT_CODE
; /* toggle the executable bit */
247 LDT_SetEntry( SELECTOR_TO_ENTRY( selDst
), &entry
);
252 /***********************************************************************
253 * AllocCStoDSAlias (KERNEL.170)
255 WORD WINAPI
AllocCStoDSAlias( WORD sel
)
260 newsel
= AllocSelectorArray( 1 );
261 TRACE(selector
, "(%04x): returning %04x\n",
263 if (!newsel
) return 0;
264 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
265 entry
.type
= SEGMENT_DATA
;
266 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
), &entry
);
271 /***********************************************************************
272 * AllocDStoCSAlias (KERNEL.171)
274 WORD WINAPI
AllocDStoCSAlias( WORD sel
)
279 newsel
= AllocSelectorArray( 1 );
280 TRACE(selector
, "(%04x): returning %04x\n",
282 if (!newsel
) return 0;
283 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
284 entry
.type
= SEGMENT_CODE
;
285 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
), &entry
);
290 /***********************************************************************
291 * LongPtrAdd (KERNEL.180)
293 void WINAPI
LongPtrAdd( DWORD ptr
, DWORD add
)
296 LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr
)), &entry
);
298 LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr
)), &entry
);
302 /***********************************************************************
303 * GetSelectorBase (KERNEL.186)
305 DWORD WINAPI
WIN16_GetSelectorBase( WORD sel
)
308 * Note: For Win32s processes, the whole linear address space is
309 * shifted by 0x10000 relative to the OS linear address space.
310 * See the comment in msdos/vxd.c.
313 DWORD base
= GetSelectorBase( sel
);
314 return W32S_WINE2APP( base
, W32S_APPLICATION() ? W32S_OFFSET
: 0 );
316 DWORD WINAPI
GetSelectorBase( WORD sel
)
318 DWORD base
= GET_SEL_BASE(sel
);
320 /* if base points into DOSMEM, assume we have to
321 * return pointer into physical lower 1MB */
323 return DOSMEM_MapLinearToDos( (LPVOID
)base
);
327 /***********************************************************************
328 * SetSelectorBase (KERNEL.187)
330 DWORD WINAPI
WIN16_SetSelectorBase( WORD sel
, DWORD base
)
333 * Note: For Win32s processes, the whole linear address space is
334 * shifted by 0x10000 relative to the OS linear address space.
335 * See the comment in msdos/vxd.c.
338 SetSelectorBase( sel
,
339 W32S_APP2WINE( base
, W32S_APPLICATION() ? W32S_OFFSET
: 0 ) );
342 WORD WINAPI
SetSelectorBase( WORD sel
, DWORD base
)
346 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
348 entry
.base
= (DWORD
)DOSMEM_MapDosToLinear(base
);
350 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
355 /***********************************************************************
356 * GetSelectorLimit (KERNEL.188)
358 DWORD WINAPI
GetSelectorLimit( WORD sel
)
360 return GET_SEL_LIMIT(sel
);
364 /***********************************************************************
365 * SetSelectorLimit (KERNEL.189)
367 WORD WINAPI
SetSelectorLimit( WORD sel
, DWORD limit
)
370 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
371 entry
.limit_in_pages
= (limit
>= 0x100000);
372 if (entry
.limit_in_pages
) entry
.limit
= limit
>> 12;
373 else entry
.limit
= limit
;
374 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
379 /***********************************************************************
380 * SelectorAccessRights (KERNEL.196)
382 WORD WINAPI
SelectorAccessRights( WORD sel
, WORD op
, WORD val
)
385 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
386 if (op
== 0) /* get */
388 return 0x01 | /* accessed */
389 0x10 | /* not system */
392 ((entry
.read_only
== 0) << 1) |
394 (entry
.seg_32bit
<< 14) |
395 (entry
.limit_in_pages
<< 15);
399 entry
.read_only
= ((val
& 2) == 0);
400 entry
.type
= (val
>> 2) & 3;
401 entry
.seg_32bit
= val
& 0x4000;
402 entry
.limit_in_pages
= val
& 0x8000;
403 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
409 /***********************************************************************
410 * IsBadCodePtr16 (KERNEL.336)
412 BOOL16 WINAPI
IsBadCodePtr16( SEGPTR lpfn
)
417 sel
= SELECTOROF(lpfn
);
418 if (!sel
) return TRUE
;
419 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
420 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
421 if (entry
.type
!= SEGMENT_CODE
) return TRUE
;
422 if (OFFSETOF(lpfn
) > GET_SEL_LIMIT(sel
)) return TRUE
;
427 /***********************************************************************
428 * IsBadStringPtr16 (KERNEL.337)
430 BOOL16 WINAPI
IsBadStringPtr16( SEGPTR ptr
, UINT16 size
)
435 sel
= SELECTOROF(ptr
);
436 if (!sel
) return TRUE
;
437 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
438 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
439 if ((entry
.type
== SEGMENT_CODE
) && entry
.read_only
) return TRUE
;
440 if (strlen(PTR_SEG_TO_LIN(ptr
)) < size
) size
= strlen(PTR_SEG_TO_LIN(ptr
));
441 if (OFFSETOF(ptr
) + size
- 1 > GET_SEL_LIMIT(sel
)) return TRUE
;
446 /***********************************************************************
447 * IsBadHugeReadPtr16 (KERNEL.346)
449 BOOL16 WINAPI
IsBadHugeReadPtr16( SEGPTR ptr
, DWORD size
)
454 sel
= SELECTOROF(ptr
);
455 if (!sel
) return TRUE
;
456 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
457 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
458 if ((entry
.type
== SEGMENT_CODE
) && entry
.read_only
) return TRUE
;
459 if (OFFSETOF(ptr
) + size
- 1 > GET_SEL_LIMIT(sel
)) return TRUE
;
464 /***********************************************************************
465 * IsBadHugeWritePtr16 (KERNEL.347)
467 BOOL16 WINAPI
IsBadHugeWritePtr16( SEGPTR ptr
, DWORD size
)
472 sel
= SELECTOROF(ptr
);
473 if (!sel
) return TRUE
;
474 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
475 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
476 if ((entry
.type
== SEGMENT_CODE
) || entry
.read_only
) return TRUE
;
477 if (OFFSETOF(ptr
) + size
- 1 > GET_SEL_LIMIT(sel
)) return TRUE
;
481 /***********************************************************************
482 * IsBadReadPtr16 (KERNEL.334)
484 BOOL16 WINAPI
IsBadReadPtr16( SEGPTR ptr
, UINT16 size
)
486 return IsBadHugeReadPtr16( ptr
, size
);
490 /***********************************************************************
491 * IsBadWritePtr16 (KERNEL.335)
493 BOOL16 WINAPI
IsBadWritePtr16( SEGPTR ptr
, UINT16 size
)
495 return IsBadHugeWritePtr16( ptr
, size
);
499 /***********************************************************************
500 * MemoryRead (TOOLHELP.78)
502 DWORD WINAPI
MemoryRead( WORD sel
, DWORD offset
, void *buffer
, DWORD count
)
504 if (IS_SELECTOR_FREE(sel
)) return 0;
505 if (offset
> GET_SEL_LIMIT(sel
)) return 0;
506 if (offset
+ count
> GET_SEL_LIMIT(sel
) + 1)
507 count
= GET_SEL_LIMIT(sel
) + 1 - offset
;
508 memcpy( buffer
, ((char *)GET_SEL_BASE(sel
)) + offset
, count
);
513 /***********************************************************************
514 * MemoryWrite (TOOLHELP.79)
516 DWORD WINAPI
MemoryWrite( WORD sel
, DWORD offset
, void *buffer
, DWORD count
)
518 if (IS_SELECTOR_FREE(sel
)) return 0;
519 if (offset
> GET_SEL_LIMIT(sel
)) return 0;
520 if (offset
+ count
> GET_SEL_LIMIT(sel
) + 1)
521 count
= GET_SEL_LIMIT(sel
) + 1 - offset
;
522 memcpy( ((char *)GET_SEL_BASE(sel
)) + offset
, buffer
, count
);
526 /************************************* Win95 pointer mapping functions *
530 /***********************************************************************
531 * MapSL (KERNEL32.523)
533 * Maps fixed segmented pointer to linear.
535 LPVOID WINAPI
MapSL( SEGPTR sptr
)
537 return (LPVOID
)PTR_SEG_TO_LIN(sptr
);
540 /***********************************************************************
541 * MapSLFix (KERNEL32.524)
543 * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
544 * unexpected linear address change when GlobalCompact() shuffles
548 LPVOID WINAPI
MapSLFix( SEGPTR sptr
)
550 return (LPVOID
)PTR_SEG_TO_LIN(sptr
);
553 /***********************************************************************
554 * UnMapSLFixArray (KERNEL32.701)
557 void WINAPI
UnMapSLFixArray( SEGPTR sptr
[], INT32 length
)
561 /***********************************************************************
562 * MapLS (KERNEL32.522)
564 * Maps linear pointer to segmented.
566 SEGPTR WINAPI
MapLS( LPVOID ptr
)
572 WORD sel
= SELECTOR_AllocBlock( ptr
, 0x10000, SEGMENT_DATA
, FALSE
, FALSE
);
573 return PTR_SEG_OFF_TO_SEGPTR( sel
, 0 );
578 /***********************************************************************
579 * UnMapLS (KERNEL32.700)
581 * Free mapped selector.
583 void WINAPI
UnMapLS( SEGPTR sptr
)
585 if (SELECTOROF(sptr
))
586 SELECTOR_FreeBlock( SELECTOROF(sptr
), 1 );
589 /***********************************************************************
590 * GetThreadSelectorEntry (KERNEL32)
591 * FIXME: add #ifdef i386 for non x86
593 BOOL32 WINAPI
GetThreadSelectorEntry( HANDLE32 hthread
, DWORD sel
,
598 LDT_GetEntry(SELECTOR_TO_ENTRY(sel
),&ldtentry
);
599 ldtent
->BaseLow
= ldtentry
.base
& 0x0000ffff;
600 ldtent
->HighWord
.Bits
.BaseMid
= (ldtentry
.base
& 0x00ff0000) >> 16;
601 ldtent
->HighWord
.Bits
.BaseHi
= (ldtentry
.base
& 0xff000000) >> 24;
602 ldtent
->LimitLow
= ldtentry
.limit
& 0x0000ffff;
603 ldtent
->HighWord
.Bits
.LimitHi
= (ldtentry
.limit
& 0x00ff0000) >> 16;
604 ldtent
->HighWord
.Bits
.Dpl
= 3;
605 ldtent
->HighWord
.Bits
.Sys
= 0;
606 ldtent
->HighWord
.Bits
.Pres
= 1;
607 ldtent
->HighWord
.Bits
.Type
= 0x10|(ldtentry
.type
<< 2);
608 if (ldtentry
.read_only
)
609 ldtent
->HighWord
.Bits
.Type
|=0x2;
610 ldtent
->HighWord
.Bits
.Granularity
= ldtentry
.limit_in_pages
;
611 ldtent
->HighWord
.Bits
.Default_Big
= ldtentry
.seg_32bit
;
616 /**********************************************************************
618 * These functions map linear pointers at [EBP+xxx] to segmented pointers
620 * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
621 * unravel them at SUnMapLS. We just store the segmented pointer there.
624 x_SMapLS_IP_EBP_x(CONTEXT
*context
,int argoff
) {
627 val
=*(DWORD
*)(EBP_reg(context
)+argoff
);
630 *(DWORD
*)(EBP_reg(context
)+argoff
) = 0;
632 ptr
= MapLS((LPVOID
)val
);
633 *(DWORD
*)(EBP_reg(context
)+argoff
) = ptr
;
635 EAX_reg(context
) = ptr
;
638 REGS_ENTRYPOINT(SMapLS_IP_EBP_8
) {x_SMapLS_IP_EBP_x(context
,8);}
639 REGS_ENTRYPOINT(SMapLS_IP_EBP_12
) {x_SMapLS_IP_EBP_x(context
,12);}
640 REGS_ENTRYPOINT(SMapLS_IP_EBP_16
) {x_SMapLS_IP_EBP_x(context
,16);}
641 REGS_ENTRYPOINT(SMapLS_IP_EBP_20
) {x_SMapLS_IP_EBP_x(context
,20);}
642 REGS_ENTRYPOINT(SMapLS_IP_EBP_24
) {x_SMapLS_IP_EBP_x(context
,24);}
643 REGS_ENTRYPOINT(SMapLS_IP_EBP_28
) {x_SMapLS_IP_EBP_x(context
,28);}
644 REGS_ENTRYPOINT(SMapLS_IP_EBP_32
) {x_SMapLS_IP_EBP_x(context
,32);}
645 REGS_ENTRYPOINT(SMapLS_IP_EBP_36
) {x_SMapLS_IP_EBP_x(context
,36);}
646 REGS_ENTRYPOINT(SMapLS_IP_EBP_40
) {x_SMapLS_IP_EBP_x(context
,40);}
648 REGS_ENTRYPOINT(SMapLS
)
650 if (EAX_reg(context
)>=0x10000) {
651 EAX_reg(context
) = MapLS((LPVOID
)EAX_reg(context
));
652 EDX_reg(context
) = EAX_reg(context
);
654 EDX_reg(context
) = 0;
658 REGS_ENTRYPOINT(SUnMapLS
)
660 if (EAX_reg(context
)>=0x10000)
661 UnMapLS((SEGPTR
)EAX_reg(context
));
665 x_SUnMapLS_IP_EBP_x(CONTEXT
*context
,int argoff
) {
666 if (*(DWORD
*)(EBP_reg(context
)+argoff
))
667 UnMapLS(*(DWORD
*)(EBP_reg(context
)+argoff
));
668 *(DWORD
*)(EBP_reg(context
)+argoff
)=0;
670 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_8
) { x_SUnMapLS_IP_EBP_x(context
,8); }
671 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_12
) { x_SUnMapLS_IP_EBP_x(context
,12); }
672 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_16
) { x_SUnMapLS_IP_EBP_x(context
,16); }
673 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_20
) { x_SUnMapLS_IP_EBP_x(context
,20); }
674 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_24
) { x_SUnMapLS_IP_EBP_x(context
,24); }
675 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_28
) { x_SUnMapLS_IP_EBP_x(context
,28); }
676 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_32
) { x_SUnMapLS_IP_EBP_x(context
,32); }
677 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_36
) { x_SUnMapLS_IP_EBP_x(context
,36); }
678 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_40
) { x_SUnMapLS_IP_EBP_x(context
,40); }
680 /**********************************************************************
681 * AllocMappedBuffer (KERNEL32.38)
683 * This is a undocumented KERNEL32 function that
684 * SMapLS's a GlobalAlloc'ed buffer.
686 * Input: EDI register: size of buffer to allocate
687 * Output: EDI register: pointer to buffer
689 * Note: The buffer is preceeded by 8 bytes:
692 * edi-4 SEGPTR to buffer
693 * edi-8 some magic Win95 needs for SUnMapLS
694 * (we use it for the memory handle)
696 * The SEGPTR is used by the caller!
699 REGS_ENTRYPOINT(AllocMappedBuffer
)
701 HGLOBAL32 handle
= GlobalAlloc32(0, EDI_reg(context
) + 8);
702 DWORD
*buffer
= (DWORD
*)GlobalLock32(handle
);
706 if (!(ptr
= MapLS(buffer
+ 2)))
708 GlobalUnlock32(handle
);
709 GlobalFree32(handle
);
713 EAX_reg(context
) = EDI_reg(context
) = 0;
719 EAX_reg(context
) = (DWORD
) ptr
;
720 EDI_reg(context
) = (DWORD
)(buffer
+ 2);
724 /**********************************************************************
725 * FreeMappedBuffer (KERNEL32.39)
727 * Free a buffer allocated by AllocMappedBuffer
729 * Input: EDI register: pointer to buffer
732 REGS_ENTRYPOINT(FreeMappedBuffer
)
734 if (EDI_reg(context
))
736 DWORD
*buffer
= (DWORD
*)EDI_reg(context
) - 2;
740 GlobalUnlock32(buffer
[0]);
741 GlobalFree32(buffer
[0]);
745 /**********************************************************************
746 * WOWGetVDMPointer (KERNEL32.55)
747 * Get linear from segmented pointer. (MSDN lib)
749 LPVOID WINAPI
WOWGetVDMPointer(DWORD vp
,DWORD nrofbytes
,BOOL32
protected)
751 /* FIXME: add size check too */
753 return PTR_SEG_TO_LIN(vp
);
755 return DOSMEM_MapRealToLinear(vp
);
758 /**********************************************************************
759 * GetVDMPointer32W (KERNEL.516)
761 LPVOID WINAPI
GetVDMPointer32W(DWORD vp
,DWORD mode
)
763 return WOWGetVDMPointer(vp
,0,mode
);
766 /**********************************************************************
767 * WOWGetVDMPointerFix (KERNEL32.55)
768 * Dito, but fix heapsegment (MSDN lib)
770 LPVOID WINAPI
WOWGetVDMPointerFix(DWORD vp
,DWORD nrofbytes
,BOOL32
protected)
772 /* FIXME: fix heapsegment */
773 return WOWGetVDMPointer(vp
,nrofbytes
,protected);
776 /**********************************************************************
777 * WOWGetVDMPointerUnFix (KERNEL32.56)
779 void WINAPI
WOWGetVDMPointerUnfix(DWORD vp
)
781 /* FIXME: unfix heapsegment */
784 /***********************************************************************
785 * UTSelectorOffsetToLinear (WIN32S16.48)
787 * rough guesswork, but seems to work (I had no "reasonable" docu)
789 LPVOID WINAPI
UTSelectorOffsetToLinear(SEGPTR sptr
)
791 return PTR_SEG_TO_LIN(sptr
);
794 /***********************************************************************
795 * UTLinearToSelectorOffset (WIN32S16.49)
797 * FIXME: I don't know if that's the right way to do linear -> segmented
799 SEGPTR WINAPI
UTLinearToSelectorOffset(LPVOID lptr
)