Removed some flicker by detecting if we set the same value again.
[wine/multimedia.git] / memory / selector.c
blobc12b6205eeddf9c99b161a362da7bbd05a08ff55
1 /*
2 * Selector manipulation functions
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <string.h>
8 #include "winerror.h"
9 #include "wine/winbase16.h"
10 #include "ldt.h"
11 #include "miscemu.h"
12 #include "selectors.h"
13 #include "stackframe.h"
14 #include "process.h"
15 #include "server.h"
16 #include "debugtools.h"
17 #include "toolhelp.h"
19 DEFAULT_DEBUG_CHANNEL(selector);
22 /***********************************************************************
23 * AllocSelectorArray (KERNEL.206)
25 WORD WINAPI AllocSelectorArray16( WORD count )
27 WORD i, sel, size = 0;
28 ldt_entry entry;
30 if (!count) return 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;
37 sel = i - size + 1;
39 entry.base = 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",
66 sel, newsel );
67 if (!newsel) return 0;
68 if (!sel) return newsel; /* nothing to copy */
69 for (i = 0; i < count; i++)
71 ldt_entry entry;
72 LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
73 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel) + i, &entry );
75 return newsel;
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 );
86 return 0;
90 /***********************************************************************
91 * SELECTOR_SetEntries
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,
97 BOOL readonly )
99 ldt_entry entry;
100 WORD i, count;
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;
105 entry.type = type;
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 )
133 WORD sel, count;
135 if (!size) return 0;
136 count = (size + 0xffff) / 0x10000;
137 sel = AllocSelectorArray16( count );
138 if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
139 return sel;
143 /***********************************************************************
144 * SELECTOR_MoveBlock
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++)
154 ldt_entry entry;
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 /***********************************************************************
163 * SELECTOR_FreeBlock
165 * Free a block of selectors.
167 void SELECTOR_FreeBlock( WORD sel, WORD count )
169 WORD i, nextsel;
170 ldt_entry entry;
172 TRACE("(%04x,%d)\n", sel, count );
173 sel &= ~(__AHINCR - 1); /* clear bottom bits of selector */
174 nextsel = sel + (count << __AHSHIFT);
176 #ifdef __i386__
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() );
182 __set_fs( 0 );
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 )
204 ldt_entry entry;
205 WORD i, oldcount, newcount;
207 if (!size) size = 1;
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;
216 else
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 );
238 return sel;
242 /***********************************************************************
243 * PrestoChangoSelector (KERNEL.177)
245 WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
247 ldt_entry entry;
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 );
251 return selDst;
255 /***********************************************************************
256 * AllocCStoDSAlias (KERNEL.170)
258 WORD WINAPI AllocCStoDSAlias16( WORD sel )
260 WORD newsel;
261 ldt_entry entry;
263 newsel = AllocSelectorArray16( 1 );
264 TRACE("(%04x): returning %04x\n",
265 sel, newsel );
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 );
270 return newsel;
274 /***********************************************************************
275 * AllocDStoCSAlias (KERNEL.171)
277 WORD WINAPI AllocDStoCSAlias16( WORD sel )
279 WORD newsel;
280 ldt_entry entry;
282 newsel = AllocSelectorArray16( 1 );
283 TRACE("(%04x): returning %04x\n",
284 sel, newsel );
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 );
289 return newsel;
293 /***********************************************************************
294 * LongPtrAdd (KERNEL.180)
296 void WINAPI LongPtrAdd16( DWORD ptr, DWORD add )
298 ldt_entry entry;
299 LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
300 entry.base += add;
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 ) );
343 return sel;
345 WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
347 ldt_entry entry;
349 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
351 entry.base = (DWORD)DOSMEM_MapDosToLinear(base);
353 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
354 return sel;
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 )
372 ldt_entry entry;
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 );
378 return sel;
382 /***********************************************************************
383 * SelectorAccessRights (KERNEL.196)
385 WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
387 ldt_entry entry;
388 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
389 if (op == 0) /* get */
391 return 0x01 | /* accessed */
392 0x10 | /* not system */
393 0x60 | /* DPL 3 */
394 0x80 | /* present */
395 ((entry.read_only == 0) << 1) |
396 (entry.type << 2) |
397 (entry.seg_32bit << 14) |
398 (entry.limit_in_pages << 15);
400 else /* set */
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 );
407 return 0;
412 /***********************************************************************
413 * IsBadCodePtr16 (KERNEL.336)
415 BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
417 WORD sel;
418 ldt_entry entry;
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;
426 return FALSE;
430 /***********************************************************************
431 * IsBadStringPtr16 (KERNEL.337)
433 BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
435 WORD sel;
436 ldt_entry entry;
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;
445 return FALSE;
449 /***********************************************************************
450 * IsBadHugeReadPtr16 (KERNEL.346)
452 BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
454 WORD sel;
455 ldt_entry entry;
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;
463 return FALSE;
467 /***********************************************************************
468 * IsBadHugeWritePtr16 (KERNEL.347)
470 BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
472 WORD sel;
473 ldt_entry entry;
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;
481 return FALSE;
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 );
522 return 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 );
536 return 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
558 * moveable blocks.
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 )
582 if (!HIWORD(ptr))
583 return (SEGPTR)ptr;
584 else
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)
608 #ifdef __i386__
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) );
617 return TRUE;
619 ldtent->BaseLow = 0;
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 */
636 return TRUE;
638 SetLastError( ERROR_NOACCESS );
639 return FALSE;
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 */
649 return FALSE;
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;
664 return TRUE;
665 #else
666 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
667 return FALSE;
668 #endif
672 /**********************************************************************
673 * SMapLS* (KERNEL32)
674 * These functions map linear pointers at [EBP+xxx] to segmented pointers
675 * and return them.
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.
679 static void
680 x_SMapLS_IP_EBP_x(CONTEXT86 *context,int argoff) {
681 DWORD val,ptr;
683 val =*(DWORD*)(EBP_reg(context)+argoff);
684 if (val<0x10000) {
685 ptr=val;
686 *(DWORD*)(EBP_reg(context)+argoff) = 0;
687 } else {
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);
747 } else {
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));
762 static void
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:
824 * ...
825 * edi+0 buffer
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);
837 SEGPTR ptr = 0;
839 if (buffer)
840 if (!(ptr = MapLS(buffer + 2)))
842 GlobalUnlock(handle);
843 GlobalFree(handle);
846 if (!ptr)
847 EAX_reg(context) = EDI_reg(context) = 0;
848 else
850 buffer[0] = handle;
851 buffer[1] = ptr;
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;
872 UnMapLS(buffer[1]);
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)
897 return (SEGPTR)lptr;
900 #ifdef __i386__
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" )
909 #endif