- Introduce a significant design decision.
[wine/wine-kai.git] / memory / selector.c
blob57af3ff4f07227f02041c707f501d4ae14e758b0
1 /*
2 * Selector manipulation functions
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <string.h>
11 #include "winerror.h"
12 #include "wine/winbase16.h"
13 #include "miscemu.h"
14 #include "selectors.h"
15 #include "stackframe.h"
16 #include "wine/server.h"
17 #include "debugtools.h"
18 #include "toolhelp.h"
20 DEFAULT_DEBUG_CHANNEL(selector);
22 #define LDT_SIZE 8192
24 /* get the number of selectors needed to cover up to the selector limit */
25 inline static WORD get_sel_count( WORD sel )
27 return (wine_ldt_copy.limit[sel >> __AHSHIFT] >> 16) + 1;
30 static const LDT_ENTRY null_entry; /* all-zeros, used to clear LDT entries */
32 /***********************************************************************
33 * SELECTOR_AllocArray
35 * Allocate a selector array without setting the LDT entries
37 static WORD SELECTOR_AllocArray( WORD count )
39 WORD i, sel, size = 0;
41 if (!count) return 0;
42 for (i = FIRST_LDT_ENTRY_TO_ALLOC; i < LDT_SIZE; i++)
44 if (wine_ldt_copy.flags[i] & WINE_LDT_FLAGS_ALLOCATED) size = 0;
45 else if (++size >= count) break;
47 if (i == LDT_SIZE) return 0;
48 sel = i - size + 1;
50 /* mark selectors as allocated */
51 for (i = 0; i < count; i++) wine_ldt_copy.flags[sel + i] |= WINE_LDT_FLAGS_ALLOCATED;
53 return (sel << __AHSHIFT) | 7;
57 /***********************************************************************
58 * AllocSelectorArray (KERNEL.206)
60 WORD WINAPI AllocSelectorArray16( WORD count )
62 WORD i, sel = SELECTOR_AllocArray( count );
64 if (sel)
66 LDT_ENTRY entry;
67 wine_ldt_set_base( &entry, 0 );
68 wine_ldt_set_limit( &entry, 1 ); /* avoid 0 base and limit */
69 wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_DATA );
70 for (i = 0; i < count; i++) wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
72 return sel;
76 /***********************************************************************
77 * AllocSelector (KERNEL.175)
79 WORD WINAPI AllocSelector16( WORD sel )
81 WORD newsel, count, i;
83 count = sel ? get_sel_count(sel) : 1;
84 newsel = SELECTOR_AllocArray( count );
85 TRACE("(%04x): returning %04x\n", sel, newsel );
86 if (!newsel) return 0;
87 if (!sel) return newsel; /* nothing to copy */
88 for (i = 0; i < count; i++)
90 LDT_ENTRY entry;
91 wine_ldt_get_entry( sel + (i << __AHSHIFT), &entry );
92 wine_ldt_set_entry( newsel + (i << __AHSHIFT), &entry );
94 return newsel;
98 /***********************************************************************
99 * FreeSelector (KERNEL.176)
101 WORD WINAPI FreeSelector16( WORD sel )
103 if (IS_SELECTOR_FREE(sel)) return sel; /* error */
105 #ifdef __i386__
106 /* Check if we are freeing current %fs or %gs selector */
107 if (!((__get_fs() ^ sel) & ~7))
109 WARN("Freeing %%fs selector (%04x), not good.\n", __get_fs() );
110 __set_fs( 0 );
112 if (!((__get_gs() ^ sel) & ~7)) __set_gs( 0 );
113 #endif /* __i386__ */
115 wine_ldt_set_entry( sel, &null_entry );
116 wine_ldt_copy.flags[sel >> __AHSHIFT] &= ~WINE_LDT_FLAGS_ALLOCATED;
117 return 0;
121 /***********************************************************************
122 * SELECTOR_FreeFs
124 * Free the current %fs selector.
126 void SELECTOR_FreeFs(void)
128 WORD fs = __get_fs();
129 if (fs)
131 wine_ldt_copy.flags[fs >> __AHSHIFT] &= ~WINE_LDT_FLAGS_ALLOCATED;
132 __set_fs(0);
133 wine_ldt_set_entry( fs, &null_entry );
138 /***********************************************************************
139 * SELECTOR_SetEntries
141 * Set the LDT entries for an array of selectors.
143 static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size, unsigned char flags )
145 LDT_ENTRY entry;
146 WORD i, count;
148 wine_ldt_set_base( &entry, base );
149 wine_ldt_set_limit( &entry, size - 1 );
150 wine_ldt_set_flags( &entry, flags );
151 /* Make sure base and limit are not 0 together if the size is not 0 */
152 if (!base && size == 1) wine_ldt_set_limit( &entry, 1 );
153 count = (size + 0xffff) / 0x10000;
154 for (i = 0; i < count; i++)
156 wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
157 wine_ldt_set_base( &entry, wine_ldt_get_base(&entry) + 0x10000 );
158 wine_ldt_set_limit( &entry, wine_ldt_get_limit(&entry) - 0x10000 );
163 /***********************************************************************
164 * SELECTOR_AllocBlock
166 * Allocate selectors for a block of linear memory.
168 WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags )
170 WORD sel, count;
172 if (!size) return 0;
173 count = (size + 0xffff) / 0x10000;
174 sel = SELECTOR_AllocArray( count );
175 if (sel) SELECTOR_SetEntries( sel, base, size, flags );
176 return sel;
180 /***********************************************************************
181 * SELECTOR_FreeBlock
183 * Free a block of selectors.
185 void SELECTOR_FreeBlock( WORD sel )
187 WORD i, count = get_sel_count( sel );
189 TRACE("(%04x,%d)\n", sel, count );
190 for (i = 0; i < count; i++) FreeSelector16( sel + (i << __AHSHIFT) );
194 /***********************************************************************
195 * SELECTOR_ReallocBlock
197 * Change the size of a block of selectors.
199 WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size )
201 LDT_ENTRY entry;
202 WORD i, oldcount, newcount;
204 if (!size) size = 1;
205 oldcount = get_sel_count( sel );
206 newcount = (size + 0xffff) >> 16;
207 wine_ldt_get_entry( sel, &entry );
209 if (oldcount < newcount) /* We need to add selectors */
211 WORD index = sel >> __AHSHIFT;
212 /* Check if the next selectors are free */
213 if (index + newcount > LDT_SIZE) i = oldcount;
214 else
215 for (i = oldcount; i < newcount; i++)
216 if (wine_ldt_copy.flags[index+i] & WINE_LDT_FLAGS_ALLOCATED) break;
218 if (i < newcount) /* they are not free */
220 SELECTOR_FreeBlock( sel );
221 sel = SELECTOR_AllocArray( newcount );
223 else /* mark the selectors as allocated */
225 for (i = oldcount; i < newcount; i++)
226 wine_ldt_copy.flags[index+i] |= WINE_LDT_FLAGS_ALLOCATED;
229 else if (oldcount > newcount) /* We need to remove selectors */
231 SELECTOR_FreeBlock( sel + (newcount << __AHSHIFT) );
233 if (sel) SELECTOR_SetEntries( sel, base, size, wine_ldt_get_flags(&entry) );
234 return sel;
238 /***********************************************************************
239 * PrestoChangoSelector (KERNEL.177)
241 WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
243 LDT_ENTRY entry;
244 wine_ldt_get_entry( selSrc, &entry );
245 /* toggle the executable bit */
246 entry.HighWord.Bits.Type ^= (WINE_LDT_FLAGS_CODE ^ WINE_LDT_FLAGS_DATA);
247 wine_ldt_set_entry( selDst, &entry );
248 return selDst;
252 /***********************************************************************
253 * AllocCStoDSAlias (KERNEL.170)
254 * AllocAlias (KERNEL.172)
256 WORD WINAPI AllocCStoDSAlias16( WORD sel )
258 WORD newsel;
259 LDT_ENTRY entry;
261 newsel = SELECTOR_AllocArray( 1 );
262 TRACE("(%04x): returning %04x\n",
263 sel, newsel );
264 if (!newsel) return 0;
265 wine_ldt_get_entry( sel, &entry );
266 entry.HighWord.Bits.Type = WINE_LDT_FLAGS_DATA;
267 wine_ldt_set_entry( newsel, &entry );
268 return newsel;
272 /***********************************************************************
273 * AllocDStoCSAlias (KERNEL.171)
275 WORD WINAPI AllocDStoCSAlias16( WORD sel )
277 WORD newsel;
278 LDT_ENTRY entry;
280 newsel = SELECTOR_AllocArray( 1 );
281 TRACE("(%04x): returning %04x\n",
282 sel, newsel );
283 if (!newsel) return 0;
284 wine_ldt_get_entry( sel, &entry );
285 entry.HighWord.Bits.Type = WINE_LDT_FLAGS_CODE;
286 wine_ldt_set_entry( newsel, &entry );
287 return newsel;
291 /***********************************************************************
292 * LongPtrAdd (KERNEL.180)
294 void WINAPI LongPtrAdd16( DWORD ptr, DWORD add )
296 LDT_ENTRY entry;
297 wine_ldt_get_entry( SELECTOROF(ptr), &entry );
298 wine_ldt_set_base( &entry, (char *)wine_ldt_get_base(&entry) + add );
299 wine_ldt_set_entry( SELECTOROF(ptr), &entry );
303 /***********************************************************************
304 * GetSelectorBase (KERNEL.186)
306 DWORD WINAPI WIN16_GetSelectorBase( WORD sel )
309 * Note: For Win32s processes, the whole linear address space is
310 * shifted by 0x10000 relative to the OS linear address space.
311 * See the comment in msdos/vxd.c.
314 DWORD base = GetSelectorBase( sel );
315 return W32S_WINE2APP( base );
317 DWORD WINAPI GetSelectorBase( WORD sel )
319 void *base = wine_ldt_copy.base[sel >> __AHSHIFT];
321 /* if base points into DOSMEM, assume we have to
322 * return pointer into physical lower 1MB */
324 return DOSMEM_MapLinearToDos( base );
328 /***********************************************************************
329 * SetSelectorBase (KERNEL.187)
331 DWORD WINAPI WIN16_SetSelectorBase( WORD sel, DWORD base )
334 * Note: For Win32s processes, the whole linear address space is
335 * shifted by 0x10000 relative to the OS linear address space.
336 * See the comment in msdos/vxd.c.
339 SetSelectorBase( sel, W32S_APP2WINE( base ) );
340 return sel;
342 WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
344 LDT_ENTRY entry;
345 wine_ldt_get_entry( sel, &entry );
346 wine_ldt_set_base( &entry, DOSMEM_MapDosToLinear(base) );
347 wine_ldt_set_entry( sel, &entry );
348 return sel;
352 /***********************************************************************
353 * GetSelectorLimit (KERNEL.188)
355 DWORD WINAPI GetSelectorLimit16( WORD sel )
357 return wine_ldt_copy.limit[sel >> __AHSHIFT];
361 /***********************************************************************
362 * SetSelectorLimit (KERNEL.189)
364 WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
366 LDT_ENTRY entry;
367 wine_ldt_get_entry( sel, &entry );
368 wine_ldt_set_limit( &entry, limit );
369 wine_ldt_set_entry( sel, &entry );
370 return sel;
374 /***********************************************************************
375 * SelectorAccessRights (KERNEL.196)
377 WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
379 LDT_ENTRY entry;
380 wine_ldt_get_entry( sel, &entry );
382 if (op == 0) /* get */
384 return entry.HighWord.Bytes.Flags1 | ((entry.HighWord.Bytes.Flags2 << 8) & 0xf0);
386 else /* set */
388 entry.HighWord.Bytes.Flags1 = LOBYTE(val) | 0xf0;
389 entry.HighWord.Bytes.Flags2 = (entry.HighWord.Bytes.Flags2 & 0x0f) | (HIBYTE(val) & 0xf0);
390 wine_ldt_set_entry( sel, &entry );
391 return 0;
396 /***********************************************************************
397 * IsBadCodePtr (KERNEL.336)
399 BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
401 WORD sel;
402 LDT_ENTRY entry;
404 sel = SELECTOROF(lpfn);
405 if (!sel) return TRUE;
406 if (IS_SELECTOR_FREE(sel)) return TRUE;
407 wine_ldt_get_entry( sel, &entry );
408 /* check for code segment, ignoring conforming, read-only and accessed bits */
409 if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_CODE) & 0x18) return TRUE;
410 if (OFFSETOF(lpfn) > wine_ldt_get_limit(&entry)) return TRUE;
411 return FALSE;
415 /***********************************************************************
416 * IsBadStringPtr (KERNEL.337)
418 BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
420 WORD sel;
421 LDT_ENTRY entry;
423 sel = SELECTOROF(ptr);
424 if (!sel) return TRUE;
425 if (IS_SELECTOR_FREE(sel)) return TRUE;
426 wine_ldt_get_entry( sel, &entry );
427 /* check for data or readable code segment */
428 if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE; /* system descriptor */
429 if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE; /* non-readable code segment */
430 if (strlen(MapSL(ptr)) < size) size = strlen(MapSL(ptr)) + 1;
431 if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit(&entry))) return TRUE;
432 return FALSE;
436 /***********************************************************************
437 * IsBadHugeReadPtr (KERNEL.346)
439 BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
441 WORD sel;
442 LDT_ENTRY entry;
444 sel = SELECTOROF(ptr);
445 if (!sel) return TRUE;
446 if (IS_SELECTOR_FREE(sel)) return TRUE;
447 wine_ldt_get_entry( sel, &entry );
448 /* check for data or readable code segment */
449 if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE; /* system descriptor */
450 if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE; /* non-readable code segment */
451 if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
452 return FALSE;
456 /***********************************************************************
457 * IsBadHugeWritePtr (KERNEL.347)
459 BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
461 WORD sel;
462 LDT_ENTRY entry;
464 sel = SELECTOROF(ptr);
465 if (!sel) return TRUE;
466 if (IS_SELECTOR_FREE(sel)) return TRUE;
467 wine_ldt_get_entry( sel, &entry );
468 /* check for writeable data segment, ignoring expand-down and accessed flags */
469 if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_DATA) & ~5) return TRUE;
470 if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
471 return FALSE;
474 /***********************************************************************
475 * IsBadReadPtr (KERNEL.334)
477 BOOL16 WINAPI IsBadReadPtr16( SEGPTR ptr, UINT16 size )
479 return IsBadHugeReadPtr16( ptr, size );
483 /***********************************************************************
484 * IsBadWritePtr (KERNEL.335)
486 BOOL16 WINAPI IsBadWritePtr16( SEGPTR ptr, UINT16 size )
488 return IsBadHugeWritePtr16( ptr, size );
492 /***********************************************************************
493 * IsBadFlatReadWritePtr (KERNEL.627)
495 BOOL16 WINAPI IsBadFlatReadWritePtr16( SEGPTR ptr, DWORD size, BOOL16 bWrite )
497 return bWrite? IsBadHugeWritePtr16( ptr, size )
498 : IsBadHugeReadPtr16( ptr, size );
502 /***********************************************************************
503 * MemoryRead (TOOLHELP.78)
505 DWORD WINAPI MemoryRead16( WORD sel, DWORD offset, void *buffer, DWORD count )
507 WORD index = sel >> __AHSHIFT;
509 if (!(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED)) return 0;
510 if (offset > wine_ldt_copy.limit[index]) return 0;
511 if (offset + count > wine_ldt_copy.limit[index] + 1)
512 count = wine_ldt_copy.limit[index] + 1 - offset;
513 memcpy( buffer, (char *)wine_ldt_copy.base[index] + offset, count );
514 return count;
518 /***********************************************************************
519 * MemoryWrite (TOOLHELP.79)
521 DWORD WINAPI MemoryWrite16( WORD sel, DWORD offset, void *buffer, DWORD count )
523 WORD index = sel >> __AHSHIFT;
525 if (!(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED)) return 0;
526 if (offset > wine_ldt_copy.limit[index]) return 0;
527 if (offset + count > wine_ldt_copy.limit[index] + 1)
528 count = wine_ldt_copy.limit[index] + 1 - offset;
529 memcpy( (char *)wine_ldt_copy.base[index] + offset, buffer, count );
530 return count;
533 /************************************* Win95 pointer mapping functions *
537 struct mapls_entry
539 struct mapls_entry *next;
540 void *addr; /* linear address */
541 int count; /* ref count */
542 WORD sel; /* selector */
545 static struct mapls_entry *first_entry;
548 /***********************************************************************
549 * MapLS (KERNEL32.@)
550 * MapLS (KERNEL.358)
552 * Maps linear pointer to segmented.
554 SEGPTR WINAPI MapLS( LPCVOID ptr )
556 struct mapls_entry *entry, *free = NULL;
557 void *base;
558 SEGPTR ret = 0;
560 if (!HIWORD(ptr)) return (SEGPTR)ptr;
562 base = (char *)ptr - ((unsigned int)ptr & 0x7fff);
563 HeapLock( GetProcessHeap() );
564 for (entry = first_entry; entry; entry = entry->next)
566 if (entry->addr == base) break;
567 if (!entry->count) free = entry;
570 if (!entry)
572 if (!free) /* no free entry found, create a new one */
574 if (!(free = HeapAlloc( GetProcessHeap(), 0, sizeof(*free) ))) goto done;
575 if (!(free->sel = SELECTOR_AllocBlock( base, 0x10000, WINE_LDT_FLAGS_DATA )))
577 HeapFree( GetProcessHeap(), 0, free );
578 goto done;
580 free->count = 0;
581 free->next = first_entry;
582 first_entry = free;
584 SetSelectorBase( free->sel, (DWORD)base );
585 free->addr = base;
586 entry = free;
588 entry->count++;
589 ret = MAKESEGPTR( entry->sel, (char *)ptr - (char *)entry->addr );
590 done:
591 HeapUnlock( GetProcessHeap() );
592 return ret;
595 /***********************************************************************
596 * UnMapLS (KERNEL32.@)
597 * UnMapLS (KERNEL.359)
599 * Free mapped selector.
601 void WINAPI UnMapLS( SEGPTR sptr )
603 struct mapls_entry *entry;
604 WORD sel = SELECTOROF(sptr);
606 if (sel)
608 HeapLock( GetProcessHeap() );
609 for (entry = first_entry; entry; entry = entry->next) if (entry->sel == sel) break;
610 if (entry && entry->count > 0) entry->count--;
611 HeapUnlock( GetProcessHeap() );
615 /***********************************************************************
616 * MapSL (KERNEL32.@)
617 * MapSL (KERNEL.357)
619 * Maps fixed segmented pointer to linear.
621 LPVOID WINAPI MapSL( SEGPTR sptr )
623 return (char *)wine_ldt_copy.base[SELECTOROF(sptr) >> __AHSHIFT] + OFFSETOF(sptr);
626 /***********************************************************************
627 * MapSLFix (KERNEL32.@)
629 * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
630 * unexpected linear address change when GlobalCompact() shuffles
631 * moveable blocks.
634 LPVOID WINAPI MapSLFix( SEGPTR sptr )
636 return MapSL(sptr);
639 /***********************************************************************
640 * UnMapSLFixArray (KERNEL32.@)
643 void WINAPI UnMapSLFixArray( SEGPTR sptr[], INT length, CONTEXT86 *context )
645 /* Must not change EAX, hence defined as 'register' function */
648 /***********************************************************************
649 * GetThreadSelectorEntry (KERNEL32.@)
651 BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldtent)
653 #ifdef __i386__
654 BOOL ret;
656 if (!(sel & 4)) /* GDT selector */
658 sel &= ~3; /* ignore RPL */
659 if (!sel) /* null selector */
661 memset( ldtent, 0, sizeof(*ldtent) );
662 return TRUE;
664 ldtent->BaseLow = 0;
665 ldtent->HighWord.Bits.BaseMid = 0;
666 ldtent->HighWord.Bits.BaseHi = 0;
667 ldtent->LimitLow = 0xffff;
668 ldtent->HighWord.Bits.LimitHi = 0xf;
669 ldtent->HighWord.Bits.Dpl = 3;
670 ldtent->HighWord.Bits.Sys = 0;
671 ldtent->HighWord.Bits.Pres = 1;
672 ldtent->HighWord.Bits.Granularity = 1;
673 ldtent->HighWord.Bits.Default_Big = 1;
674 ldtent->HighWord.Bits.Type = 0x12;
675 /* it has to be one of the system GDT selectors */
676 if (sel == (__get_ds() & ~3)) return TRUE;
677 if (sel == (__get_ss() & ~3)) return TRUE;
678 if (sel == (__get_cs() & ~3))
680 ldtent->HighWord.Bits.Type |= 8; /* code segment */
681 return TRUE;
683 SetLastError( ERROR_NOACCESS );
684 return FALSE;
687 SERVER_START_REQ( get_selector_entry )
689 req->handle = hthread;
690 req->entry = sel >> __AHSHIFT;
691 if ((ret = !wine_server_call_err( req )))
693 if (!(reply->flags & WINE_LDT_FLAGS_ALLOCATED))
695 SetLastError( ERROR_MR_MID_NOT_FOUND ); /* sic */
696 ret = FALSE;
698 else
700 wine_ldt_set_base( ldtent, (void *)reply->base );
701 wine_ldt_set_limit( ldtent, reply->limit );
702 wine_ldt_set_flags( ldtent, reply->flags );
706 SERVER_END_REQ;
707 return ret;
708 #else
709 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
710 return FALSE;
711 #endif
715 /**********************************************************************
716 * SMapLS* (KERNEL32)
717 * These functions map linear pointers at [EBP+xxx] to segmented pointers
718 * and return them.
719 * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
720 * unravel them at SUnMapLS. We just store the segmented pointer there.
722 static void
723 x_SMapLS_IP_EBP_x(CONTEXT86 *context,int argoff) {
724 DWORD val,ptr;
726 val =*(DWORD*)(context->Ebp + argoff);
727 if (val<0x10000) {
728 ptr=val;
729 *(DWORD*)(context->Ebp + argoff) = 0;
730 } else {
731 ptr = MapLS((LPVOID)val);
732 *(DWORD*)(context->Ebp + argoff) = ptr;
734 context->Eax = ptr;
737 /***********************************************************************
738 * SMapLS_IP_EBP_8 (KERNEL32.@)
740 void WINAPI SMapLS_IP_EBP_8 (CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context, 8);}
742 /***********************************************************************
743 * SMapLS_IP_EBP_12 (KERNEL32.@)
745 void WINAPI SMapLS_IP_EBP_12(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,12);}
747 /***********************************************************************
748 * SMapLS_IP_EBP_16 (KERNEL32.@)
750 void WINAPI SMapLS_IP_EBP_16(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,16);}
752 /***********************************************************************
753 * SMapLS_IP_EBP_20 (KERNEL32.@)
755 void WINAPI SMapLS_IP_EBP_20(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,20);}
757 /***********************************************************************
758 * SMapLS_IP_EBP_24 (KERNEL32.@)
760 void WINAPI SMapLS_IP_EBP_24(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,24);}
762 /***********************************************************************
763 * SMapLS_IP_EBP_28 (KERNEL32.@)
765 void WINAPI SMapLS_IP_EBP_28(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,28);}
767 /***********************************************************************
768 * SMapLS_IP_EBP_32 (KERNEL32.@)
770 void WINAPI SMapLS_IP_EBP_32(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,32);}
772 /***********************************************************************
773 * SMapLS_IP_EBP_36 (KERNEL32.@)
775 void WINAPI SMapLS_IP_EBP_36(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,36);}
777 /***********************************************************************
778 * SMapLS_IP_EBP_40 (KERNEL32.@)
780 void WINAPI SMapLS_IP_EBP_40(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,40);}
782 /***********************************************************************
783 * SMapLS (KERNEL32.@)
785 void WINAPI SMapLS( CONTEXT86 *context )
787 if (HIWORD(context->Eax))
789 context->Eax = MapLS( (LPVOID)context->Eax );
790 context->Edx = context->Eax;
791 } else {
792 context->Edx = 0;
796 /***********************************************************************
797 * SUnMapLS (KERNEL32.@)
800 void WINAPI SUnMapLS( CONTEXT86 *context )
802 if (HIWORD(context->Eax)) UnMapLS( (SEGPTR)context->Eax );
805 inline static void x_SUnMapLS_IP_EBP_x(CONTEXT86 *context,int argoff)
807 SEGPTR *ptr = (SEGPTR *)(context->Ebp + argoff);
808 if (*ptr)
810 UnMapLS( *ptr );
811 *ptr = 0;
815 /***********************************************************************
816 * SUnMapLS_IP_EBP_8 (KERNEL32.@)
818 void WINAPI SUnMapLS_IP_EBP_8 (CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context, 8); }
820 /***********************************************************************
821 * SUnMapLS_IP_EBP_12 (KERNEL32.@)
823 void WINAPI SUnMapLS_IP_EBP_12(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,12); }
825 /***********************************************************************
826 * SUnMapLS_IP_EBP_16 (KERNEL32.@)
828 void WINAPI SUnMapLS_IP_EBP_16(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,16); }
830 /***********************************************************************
831 * SUnMapLS_IP_EBP_20 (KERNEL32.@)
833 void WINAPI SUnMapLS_IP_EBP_20(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,20); }
835 /***********************************************************************
836 * SUnMapLS_IP_EBP_24 (KERNEL32.@)
838 void WINAPI SUnMapLS_IP_EBP_24(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,24); }
840 /***********************************************************************
841 * SUnMapLS_IP_EBP_28 (KERNEL32.@)
843 void WINAPI SUnMapLS_IP_EBP_28(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,28); }
845 /***********************************************************************
846 * SUnMapLS_IP_EBP_32 (KERNEL32.@)
848 void WINAPI SUnMapLS_IP_EBP_32(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,32); }
850 /***********************************************************************
851 * SUnMapLS_IP_EBP_36 (KERNEL32.@)
853 void WINAPI SUnMapLS_IP_EBP_36(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,36); }
855 /***********************************************************************
856 * SUnMapLS_IP_EBP_40 (KERNEL32.@)
858 void WINAPI SUnMapLS_IP_EBP_40(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,40); }
860 /**********************************************************************
861 * AllocMappedBuffer (KERNEL32.38)
863 * This is a undocumented KERNEL32 function that
864 * SMapLS's a GlobalAlloc'ed buffer.
866 * Input: EDI register: size of buffer to allocate
867 * Output: EDI register: pointer to buffer
869 * Note: The buffer is preceded by 8 bytes:
870 * ...
871 * edi+0 buffer
872 * edi-4 SEGPTR to buffer
873 * edi-8 some magic Win95 needs for SUnMapLS
874 * (we use it for the memory handle)
876 * The SEGPTR is used by the caller!
879 void WINAPI AllocMappedBuffer( CONTEXT86 *context )
881 HGLOBAL handle = GlobalAlloc(0, context->Edi + 8);
882 DWORD *buffer = (DWORD *)GlobalLock(handle);
883 SEGPTR ptr = 0;
885 if (buffer)
886 if (!(ptr = MapLS(buffer + 2)))
888 GlobalUnlock(handle);
889 GlobalFree(handle);
892 if (!ptr)
893 context->Eax = context->Edi = 0;
894 else
896 buffer[0] = handle;
897 buffer[1] = ptr;
899 context->Eax = (DWORD) ptr;
900 context->Edi = (DWORD)(buffer + 2);
904 /**********************************************************************
905 * FreeMappedBuffer (KERNEL32.39)
907 * Free a buffer allocated by AllocMappedBuffer
909 * Input: EDI register: pointer to buffer
912 void WINAPI FreeMappedBuffer( CONTEXT86 *context )
914 if (context->Edi)
916 DWORD *buffer = (DWORD *)context->Edi - 2;
918 UnMapLS(buffer[1]);
920 GlobalUnlock(buffer[0]);
921 GlobalFree(buffer[0]);
925 #ifdef __i386__
926 __ASM_GLOBAL_FUNC( __get_cs, "movw %cs,%ax\n\tret" )
927 __ASM_GLOBAL_FUNC( __get_ds, "movw %ds,%ax\n\tret" )
928 __ASM_GLOBAL_FUNC( __get_es, "movw %es,%ax\n\tret" )
929 __ASM_GLOBAL_FUNC( __get_fs, "movw %fs,%ax\n\tret" )
930 __ASM_GLOBAL_FUNC( __get_gs, "movw %gs,%ax\n\tret" )
931 __ASM_GLOBAL_FUNC( __get_ss, "movw %ss,%ax\n\tret" )
932 __ASM_GLOBAL_FUNC( __set_fs, "movl 4(%esp),%eax\n\tmovw %ax,%fs\n\tret" )
933 __ASM_GLOBAL_FUNC( __set_gs, "movl 4(%esp),%eax\n\tmovw %ax,%gs\n\tret" )
934 #endif