2 * Selector manipulation functions
4 * Copyright 1995 Alexandre Julliard
8 #include "wine/winbase16.h"
11 #include "selectors.h"
12 #include "stackframe.h"
16 DEFAULT_DEBUG_CHANNEL(selector
)
19 /***********************************************************************
20 * AllocSelectorArray (KERNEL.206)
22 WORD WINAPI
AllocSelectorArray16( WORD count
)
24 WORD i
, sel
, size
= 0;
28 for (i
= FIRST_LDT_ENTRY_TO_ALLOC
; i
< LDT_SIZE
; i
++)
30 if (!IS_LDT_ENTRY_FREE(i
)) size
= 0;
31 else if (++size
>= count
) break;
33 if (i
== LDT_SIZE
) return 0;
37 entry
.type
= SEGMENT_DATA
;
38 entry
.seg_32bit
= FALSE
;
39 entry
.read_only
= FALSE
;
40 entry
.limit_in_pages
= FALSE
;
41 entry
.limit
= 1; /* avoid 0 base and limit */
43 for (i
= 0; i
< count
; i
++)
45 /* Mark selector as allocated */
46 ldt_flags_copy
[sel
+ i
] |= LDT_FLAGS_ALLOCATED
;
47 LDT_SetEntry( sel
+ i
, &entry
);
49 return ENTRY_TO_SELECTOR( sel
);
53 /***********************************************************************
54 * AllocSelector (KERNEL.175)
56 WORD WINAPI
AllocSelector16( WORD sel
)
58 WORD newsel
, count
, i
;
60 count
= sel
? ((GET_SEL_LIMIT(sel
) >> 16) + 1) : 1;
61 newsel
= AllocSelectorArray16( count
);
62 TRACE(selector
, "(%04x): returning %04x\n",
64 if (!newsel
) return 0;
65 if (!sel
) return newsel
; /* nothing to copy */
66 for (i
= 0; i
< count
; i
++)
69 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
70 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
) + i
, &entry
);
76 /***********************************************************************
77 * FreeSelector (KERNEL.176)
79 WORD WINAPI
FreeSelector16( WORD sel
)
81 if (IS_SELECTOR_FREE(sel
)) return sel
; /* error */
82 SELECTOR_FreeBlock( sel
, 1 );
87 /***********************************************************************
90 * Set the LDT entries for an array of selectors.
92 static void SELECTOR_SetEntries( WORD sel
, const void *base
, DWORD size
,
93 enum seg_type type
, BOOL is32bit
,
99 /* The limit for the first selector is the whole */
100 /* block. The next selectors get a 64k limit. */
101 entry
.base
= (unsigned long)base
;
103 entry
.seg_32bit
= is32bit
;
104 entry
.read_only
= readonly
;
105 entry
.limit_in_pages
= (size
> 0x100000);
106 if (entry
.limit_in_pages
) entry
.limit
= ((size
+ 0xfff) >> 12) - 1;
107 else entry
.limit
= size
- 1;
108 /* Make sure base and limit are not 0 together if the size is not 0 */
109 if (!base
&& !entry
.limit
&& size
) entry
.limit
= 1;
110 count
= (size
+ 0xffff) / 0x10000;
111 for (i
= 0; i
< count
; i
++)
113 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
114 entry
.base
+= 0x10000;
115 /* Apparently the next selectors should *not* get a 64k limit. */
116 /* Can't remember where I read they should... --AJ */
117 entry
.limit
-= entry
.limit_in_pages
? 0x10 : 0x10000;
122 /***********************************************************************
123 * SELECTOR_AllocBlock
125 * Allocate selectors for a block of linear memory.
127 WORD
SELECTOR_AllocBlock( const void *base
, DWORD size
, enum seg_type type
,
128 BOOL is32bit
, BOOL readonly
)
133 count
= (size
+ 0xffff) / 0x10000;
134 sel
= AllocSelectorArray16( count
);
135 if (sel
) SELECTOR_SetEntries( sel
, base
, size
, type
, is32bit
, readonly
);
140 /***********************************************************************
143 * Move a block of selectors in linear memory.
145 void SELECTOR_MoveBlock( WORD sel
, const void *new_base
)
147 WORD i
, count
= (GET_SEL_LIMIT(sel
) >> 16) + 1;
149 for (i
= 0; i
< count
; i
++)
152 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
153 entry
.base
= (unsigned long)new_base
;
154 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
159 /***********************************************************************
162 * Free a block of selectors.
164 void SELECTOR_FreeBlock( WORD sel
, WORD count
)
169 TRACE(selector
, "(%04x,%d)\n", sel
, count
);
170 sel
&= ~(__AHINCR
- 1); /* clear bottom bits of selector */
171 nextsel
= sel
+ (count
<< __AHSHIFT
);
175 /* Check if we are freeing current %fs or %gs selector */
179 if ((fs
>= sel
) && (fs
< nextsel
))
181 WARN(selector
, "Freeing %%fs selector (%04x), not good.\n", fs
);
185 if ((gs
>= sel
) && (gs
< nextsel
)) SET_GS( 0 );
187 #endif /* __i386__ */
189 memset( &entry
, 0, sizeof(entry
) ); /* clear the LDT entries */
190 for (i
= SELECTOR_TO_ENTRY(sel
); count
; i
++, count
--)
192 LDT_SetEntry( i
, &entry
);
193 ldt_flags_copy
[i
] &= ~LDT_FLAGS_ALLOCATED
;
198 /***********************************************************************
199 * SELECTOR_ReallocBlock
201 * Change the size of a block of selectors.
203 WORD
SELECTOR_ReallocBlock( WORD sel
, const void *base
, DWORD size
)
206 WORD i
, oldcount
, newcount
;
209 oldcount
= (GET_SEL_LIMIT(sel
) >> 16) + 1;
210 newcount
= (size
+ 0xffff) >> 16;
211 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
213 if (oldcount
< newcount
) /* We need to add selectors */
215 /* Check if the next selectors are free */
216 if (SELECTOR_TO_ENTRY(sel
) + newcount
> LDT_SIZE
) i
= oldcount
;
218 for (i
= oldcount
; i
< newcount
; i
++)
219 if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel
)+i
)) break;
221 if (i
< newcount
) /* they are not free */
223 SELECTOR_FreeBlock( sel
, oldcount
);
224 sel
= AllocSelectorArray16( newcount
);
226 else /* mark the selectors as allocated */
228 for (i
= oldcount
; i
< newcount
; i
++)
229 ldt_flags_copy
[SELECTOR_TO_ENTRY(sel
)+i
] |=LDT_FLAGS_ALLOCATED
;
232 else if (oldcount
> newcount
) /* We need to remove selectors */
234 SELECTOR_FreeBlock( ENTRY_TO_SELECTOR(SELECTOR_TO_ENTRY(sel
)+newcount
),
235 oldcount
- newcount
);
237 if (sel
) SELECTOR_SetEntries( sel
, base
, size
, entry
.type
,
238 entry
.seg_32bit
, entry
.read_only
);
243 /***********************************************************************
244 * PrestoChangoSelector (KERNEL.177)
246 WORD WINAPI
PrestoChangoSelector16( WORD selSrc
, WORD selDst
)
249 LDT_GetEntry( SELECTOR_TO_ENTRY( selSrc
), &entry
);
250 entry
.type
^= SEGMENT_CODE
; /* toggle the executable bit */
251 LDT_SetEntry( SELECTOR_TO_ENTRY( selDst
), &entry
);
256 /***********************************************************************
257 * AllocCStoDSAlias (KERNEL.170)
259 WORD WINAPI
AllocCStoDSAlias16( WORD sel
)
264 newsel
= AllocSelectorArray16( 1 );
265 TRACE(selector
, "(%04x): returning %04x\n",
267 if (!newsel
) return 0;
268 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
269 entry
.type
= SEGMENT_DATA
;
270 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
), &entry
);
275 /***********************************************************************
276 * AllocDStoCSAlias (KERNEL.171)
278 WORD WINAPI
AllocDStoCSAlias16( WORD sel
)
283 newsel
= AllocSelectorArray16( 1 );
284 TRACE(selector
, "(%04x): returning %04x\n",
286 if (!newsel
) return 0;
287 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
288 entry
.type
= SEGMENT_CODE
;
289 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
), &entry
);
294 /***********************************************************************
295 * LongPtrAdd (KERNEL.180)
297 void WINAPI
LongPtrAdd16( DWORD ptr
, DWORD add
)
300 LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr
)), &entry
);
302 LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr
)), &entry
);
306 /***********************************************************************
307 * GetSelectorBase (KERNEL.186)
309 DWORD WINAPI
WIN16_GetSelectorBase( WORD sel
)
312 * Note: For Win32s processes, the whole linear address space is
313 * shifted by 0x10000 relative to the OS linear address space.
314 * See the comment in msdos/vxd.c.
317 DWORD base
= GetSelectorBase( sel
);
318 return W32S_WINE2APP( base
, W32S_APPLICATION() ? W32S_OFFSET
: 0 );
320 DWORD WINAPI
GetSelectorBase( WORD sel
)
322 DWORD base
= GET_SEL_BASE(sel
);
324 /* if base points into DOSMEM, assume we have to
325 * return pointer into physical lower 1MB */
327 return DOSMEM_MapLinearToDos( (LPVOID
)base
);
331 /***********************************************************************
332 * SetSelectorBase (KERNEL.187)
334 DWORD WINAPI
WIN16_SetSelectorBase( WORD sel
, DWORD base
)
337 * Note: For Win32s processes, the whole linear address space is
338 * shifted by 0x10000 relative to the OS linear address space.
339 * See the comment in msdos/vxd.c.
342 SetSelectorBase( sel
,
343 W32S_APP2WINE( base
, W32S_APPLICATION() ? W32S_OFFSET
: 0 ) );
346 WORD WINAPI
SetSelectorBase( WORD sel
, DWORD base
)
350 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
352 entry
.base
= (DWORD
)DOSMEM_MapDosToLinear(base
);
354 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
359 /***********************************************************************
360 * GetSelectorLimit (KERNEL.188)
362 DWORD WINAPI
GetSelectorLimit16( WORD sel
)
364 return GET_SEL_LIMIT(sel
);
368 /***********************************************************************
369 * SetSelectorLimit (KERNEL.189)
371 WORD WINAPI
SetSelectorLimit16( WORD sel
, DWORD limit
)
374 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
375 entry
.limit_in_pages
= (limit
>= 0x100000);
376 if (entry
.limit_in_pages
) entry
.limit
= limit
>> 12;
377 else entry
.limit
= limit
;
378 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
383 /***********************************************************************
384 * SelectorAccessRights (KERNEL.196)
386 WORD WINAPI
SelectorAccessRights16( WORD sel
, WORD op
, WORD val
)
389 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
390 if (op
== 0) /* get */
392 return 0x01 | /* accessed */
393 0x10 | /* not system */
396 ((entry
.read_only
== 0) << 1) |
398 (entry
.seg_32bit
<< 14) |
399 (entry
.limit_in_pages
<< 15);
403 entry
.read_only
= ((val
& 2) == 0);
404 entry
.type
= (val
>> 2) & 3;
405 entry
.seg_32bit
= val
& 0x4000;
406 entry
.limit_in_pages
= val
& 0x8000;
407 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
413 /***********************************************************************
414 * IsBadCodePtr16 (KERNEL.336)
416 BOOL16 WINAPI
IsBadCodePtr16( SEGPTR lpfn
)
421 sel
= SELECTOROF(lpfn
);
422 if (!sel
) return TRUE
;
423 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
424 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
425 if (entry
.type
!= SEGMENT_CODE
) return TRUE
;
426 if (OFFSETOF(lpfn
) > GET_SEL_LIMIT(sel
)) return TRUE
;
431 /***********************************************************************
432 * IsBadStringPtr16 (KERNEL.337)
434 BOOL16 WINAPI
IsBadStringPtr16( SEGPTR ptr
, UINT16 size
)
439 sel
= SELECTOROF(ptr
);
440 if (!sel
) return TRUE
;
441 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
442 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
443 if ((entry
.type
== SEGMENT_CODE
) && entry
.read_only
) return TRUE
;
444 if (strlen(PTR_SEG_TO_LIN(ptr
)) < size
) size
= strlen(PTR_SEG_TO_LIN(ptr
));
445 if (OFFSETOF(ptr
) + size
- 1 > GET_SEL_LIMIT(sel
)) return TRUE
;
450 /***********************************************************************
451 * IsBadHugeReadPtr16 (KERNEL.346)
453 BOOL16 WINAPI
IsBadHugeReadPtr16( SEGPTR ptr
, DWORD size
)
458 sel
= SELECTOROF(ptr
);
459 if (!sel
) return TRUE
;
460 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
461 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
462 if ((entry
.type
== SEGMENT_CODE
) && entry
.read_only
) return TRUE
;
463 if (OFFSETOF(ptr
) + size
- 1 > GET_SEL_LIMIT(sel
)) return TRUE
;
468 /***********************************************************************
469 * IsBadHugeWritePtr16 (KERNEL.347)
471 BOOL16 WINAPI
IsBadHugeWritePtr16( SEGPTR ptr
, DWORD size
)
476 sel
= SELECTOROF(ptr
);
477 if (!sel
) return TRUE
;
478 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
479 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
480 if ((entry
.type
== SEGMENT_CODE
) || entry
.read_only
) return TRUE
;
481 if (OFFSETOF(ptr
) + size
- 1 > GET_SEL_LIMIT(sel
)) return TRUE
;
485 /***********************************************************************
486 * IsBadReadPtr16 (KERNEL.334)
488 BOOL16 WINAPI
IsBadReadPtr16( SEGPTR ptr
, UINT16 size
)
490 return IsBadHugeReadPtr16( ptr
, size
);
494 /***********************************************************************
495 * IsBadWritePtr16 (KERNEL.335)
497 BOOL16 WINAPI
IsBadWritePtr16( SEGPTR ptr
, UINT16 size
)
499 return IsBadHugeWritePtr16( ptr
, size
);
503 /***********************************************************************
504 * MemoryRead (TOOLHELP.78)
506 DWORD WINAPI
MemoryRead16( WORD sel
, DWORD offset
, void *buffer
, DWORD count
)
508 if (IS_SELECTOR_FREE(sel
)) return 0;
509 if (offset
> GET_SEL_LIMIT(sel
)) return 0;
510 if (offset
+ count
> GET_SEL_LIMIT(sel
) + 1)
511 count
= GET_SEL_LIMIT(sel
) + 1 - offset
;
512 memcpy( buffer
, ((char *)GET_SEL_BASE(sel
)) + offset
, count
);
517 /***********************************************************************
518 * MemoryWrite (TOOLHELP.79)
520 DWORD WINAPI
MemoryWrite16( WORD sel
, DWORD offset
, void *buffer
, DWORD count
)
522 if (IS_SELECTOR_FREE(sel
)) return 0;
523 if (offset
> GET_SEL_LIMIT(sel
)) return 0;
524 if (offset
+ count
> GET_SEL_LIMIT(sel
) + 1)
525 count
= GET_SEL_LIMIT(sel
) + 1 - offset
;
526 memcpy( ((char *)GET_SEL_BASE(sel
)) + offset
, buffer
, count
);
530 /************************************* Win95 pointer mapping functions *
534 /***********************************************************************
535 * MapSL (KERNEL32.523)
537 * Maps fixed segmented pointer to linear.
539 LPVOID WINAPI
MapSL( SEGPTR sptr
)
541 return (LPVOID
)PTR_SEG_TO_LIN(sptr
);
544 /***********************************************************************
545 * MapSLFix (KERNEL32.524)
547 * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
548 * unexpected linear address change when GlobalCompact() shuffles
552 LPVOID WINAPI
MapSLFix( SEGPTR sptr
)
554 return (LPVOID
)PTR_SEG_TO_LIN(sptr
);
557 /***********************************************************************
558 * UnMapSLFixArray (KERNEL32.701)
561 REGS_ENTRYPOINT(UnMapSLFixArray
) /* SEGPTR sptr[], INT32 length */
563 /* Must not change EAX, hence defined as 'register' function */
564 /* We need to remove the arguments ourselves */
565 ESP_reg( context
) += 8;
568 /***********************************************************************
569 * MapLS (KERNEL32.522)
571 * Maps linear pointer to segmented.
573 SEGPTR WINAPI
MapLS( LPVOID ptr
)
579 WORD sel
= SELECTOR_AllocBlock( ptr
, 0x10000, SEGMENT_DATA
, FALSE
, FALSE
);
580 return PTR_SEG_OFF_TO_SEGPTR( sel
, 0 );
585 /***********************************************************************
586 * UnMapLS (KERNEL32.700)
588 * Free mapped selector.
590 void WINAPI
UnMapLS( SEGPTR sptr
)
592 if (SELECTOROF(sptr
))
593 SELECTOR_FreeBlock( SELECTOROF(sptr
), 1 );
596 /***********************************************************************
597 * GetThreadSelectorEntry (KERNEL32)
598 * FIXME: add #ifdef i386 for non x86
600 BOOL WINAPI
GetThreadSelectorEntry( HANDLE hthread
, DWORD sel
,
605 LDT_GetEntry(SELECTOR_TO_ENTRY(sel
),&ldtentry
);
606 ldtent
->BaseLow
= ldtentry
.base
& 0x0000ffff;
607 ldtent
->HighWord
.Bits
.BaseMid
= (ldtentry
.base
& 0x00ff0000) >> 16;
608 ldtent
->HighWord
.Bits
.BaseHi
= (ldtentry
.base
& 0xff000000) >> 24;
609 ldtent
->LimitLow
= ldtentry
.limit
& 0x0000ffff;
610 ldtent
->HighWord
.Bits
.LimitHi
= (ldtentry
.limit
& 0x00ff0000) >> 16;
611 ldtent
->HighWord
.Bits
.Dpl
= 3;
612 ldtent
->HighWord
.Bits
.Sys
= 0;
613 ldtent
->HighWord
.Bits
.Pres
= 1;
614 ldtent
->HighWord
.Bits
.Type
= 0x10|(ldtentry
.type
<< 2);
615 if (ldtentry
.read_only
)
616 ldtent
->HighWord
.Bits
.Type
|=0x2;
617 ldtent
->HighWord
.Bits
.Granularity
= ldtentry
.limit_in_pages
;
618 ldtent
->HighWord
.Bits
.Default_Big
= ldtentry
.seg_32bit
;
623 /**********************************************************************
625 * These functions map linear pointers at [EBP+xxx] to segmented pointers
627 * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
628 * unravel them at SUnMapLS. We just store the segmented pointer there.
631 x_SMapLS_IP_EBP_x(CONTEXT
*context
,int argoff
) {
634 val
=*(DWORD
*)(EBP_reg(context
)+argoff
);
637 *(DWORD
*)(EBP_reg(context
)+argoff
) = 0;
639 ptr
= MapLS((LPVOID
)val
);
640 *(DWORD
*)(EBP_reg(context
)+argoff
) = ptr
;
642 EAX_reg(context
) = ptr
;
645 REGS_ENTRYPOINT(SMapLS_IP_EBP_8
) {x_SMapLS_IP_EBP_x(context
,8);}
646 REGS_ENTRYPOINT(SMapLS_IP_EBP_12
) {x_SMapLS_IP_EBP_x(context
,12);}
647 REGS_ENTRYPOINT(SMapLS_IP_EBP_16
) {x_SMapLS_IP_EBP_x(context
,16);}
648 REGS_ENTRYPOINT(SMapLS_IP_EBP_20
) {x_SMapLS_IP_EBP_x(context
,20);}
649 REGS_ENTRYPOINT(SMapLS_IP_EBP_24
) {x_SMapLS_IP_EBP_x(context
,24);}
650 REGS_ENTRYPOINT(SMapLS_IP_EBP_28
) {x_SMapLS_IP_EBP_x(context
,28);}
651 REGS_ENTRYPOINT(SMapLS_IP_EBP_32
) {x_SMapLS_IP_EBP_x(context
,32);}
652 REGS_ENTRYPOINT(SMapLS_IP_EBP_36
) {x_SMapLS_IP_EBP_x(context
,36);}
653 REGS_ENTRYPOINT(SMapLS_IP_EBP_40
) {x_SMapLS_IP_EBP_x(context
,40);}
655 REGS_ENTRYPOINT(SMapLS
)
657 if (EAX_reg(context
)>=0x10000) {
658 EAX_reg(context
) = MapLS((LPVOID
)EAX_reg(context
));
659 EDX_reg(context
) = EAX_reg(context
);
661 EDX_reg(context
) = 0;
665 REGS_ENTRYPOINT(SUnMapLS
)
667 if (EAX_reg(context
)>=0x10000)
668 UnMapLS((SEGPTR
)EAX_reg(context
));
672 x_SUnMapLS_IP_EBP_x(CONTEXT
*context
,int argoff
) {
673 if (*(DWORD
*)(EBP_reg(context
)+argoff
))
674 UnMapLS(*(DWORD
*)(EBP_reg(context
)+argoff
));
675 *(DWORD
*)(EBP_reg(context
)+argoff
)=0;
677 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_8
) { x_SUnMapLS_IP_EBP_x(context
,8); }
678 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_12
) { x_SUnMapLS_IP_EBP_x(context
,12); }
679 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_16
) { x_SUnMapLS_IP_EBP_x(context
,16); }
680 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_20
) { x_SUnMapLS_IP_EBP_x(context
,20); }
681 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_24
) { x_SUnMapLS_IP_EBP_x(context
,24); }
682 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_28
) { x_SUnMapLS_IP_EBP_x(context
,28); }
683 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_32
) { x_SUnMapLS_IP_EBP_x(context
,32); }
684 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_36
) { x_SUnMapLS_IP_EBP_x(context
,36); }
685 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_40
) { x_SUnMapLS_IP_EBP_x(context
,40); }
687 /**********************************************************************
688 * AllocMappedBuffer (KERNEL32.38)
690 * This is a undocumented KERNEL32 function that
691 * SMapLS's a GlobalAlloc'ed buffer.
693 * Input: EDI register: size of buffer to allocate
694 * Output: EDI register: pointer to buffer
696 * Note: The buffer is preceeded by 8 bytes:
699 * edi-4 SEGPTR to buffer
700 * edi-8 some magic Win95 needs for SUnMapLS
701 * (we use it for the memory handle)
703 * The SEGPTR is used by the caller!
706 REGS_ENTRYPOINT(AllocMappedBuffer
)
708 HGLOBAL handle
= GlobalAlloc(0, EDI_reg(context
) + 8);
709 DWORD
*buffer
= (DWORD
*)GlobalLock(handle
);
713 if (!(ptr
= MapLS(buffer
+ 2)))
715 GlobalUnlock(handle
);
720 EAX_reg(context
) = EDI_reg(context
) = 0;
726 EAX_reg(context
) = (DWORD
) ptr
;
727 EDI_reg(context
) = (DWORD
)(buffer
+ 2);
731 /**********************************************************************
732 * FreeMappedBuffer (KERNEL32.39)
734 * Free a buffer allocated by AllocMappedBuffer
736 * Input: EDI register: pointer to buffer
739 REGS_ENTRYPOINT(FreeMappedBuffer
)
741 if (EDI_reg(context
))
743 DWORD
*buffer
= (DWORD
*)EDI_reg(context
) - 2;
747 GlobalUnlock(buffer
[0]);
748 GlobalFree(buffer
[0]);
752 /**********************************************************************
753 * WOWGetVDMPointer (KERNEL32.55)
754 * Get linear from segmented pointer. (MSDN lib)
756 LPVOID WINAPI
WOWGetVDMPointer(DWORD vp
,DWORD nrofbytes
,BOOL
protected)
758 /* FIXME: add size check too */
760 return PTR_SEG_TO_LIN(vp
);
762 return DOSMEM_MapRealToLinear(vp
);
765 /**********************************************************************
766 * GetVDMPointer32W (KERNEL.516)
768 LPVOID WINAPI
GetVDMPointer32W(DWORD vp
,WORD mode
)
770 return WOWGetVDMPointer(vp
,0,(DWORD
)mode
);
773 /**********************************************************************
774 * WOWGetVDMPointerFix (KERNEL32.55)
775 * Dito, but fix heapsegment (MSDN lib)
777 LPVOID WINAPI
WOWGetVDMPointerFix(DWORD vp
,DWORD nrofbytes
,BOOL
protected)
779 /* FIXME: fix heapsegment */
780 return WOWGetVDMPointer(vp
,nrofbytes
,protected);
783 /**********************************************************************
784 * WOWGetVDMPointerUnFix (KERNEL32.56)
786 void WINAPI
WOWGetVDMPointerUnfix(DWORD vp
)
788 /* FIXME: unfix heapsegment */
791 /***********************************************************************
792 * UTSelectorOffsetToLinear (WIN32S16.48)
794 * rough guesswork, but seems to work (I had no "reasonable" docu)
796 LPVOID WINAPI
UTSelectorOffsetToLinear16(SEGPTR sptr
)
798 return PTR_SEG_TO_LIN(sptr
);
801 /***********************************************************************
802 * UTLinearToSelectorOffset (WIN32S16.49)
804 * FIXME: I don't know if that's the right way to do linear -> segmented
806 SEGPTR WINAPI
UTLinearToSelectorOffset16(LPVOID lptr
)