Corel merge:
[wine/dcerpc.git] / memory / selector.c
blobe52c3980d33cfda5de64caec4e97b71fc9078143
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 */
180 WORD fs, gs;
181 GET_FS(fs);
182 if ((fs >= sel) && (fs < nextsel))
184 WARN("Freeing %%fs selector (%04x), not good.\n", fs );
185 SET_FS( 0 );
187 GET_GS(gs);
188 if ((gs >= sel) && (gs < nextsel)) SET_GS( 0 );
190 #endif /* __i386__ */
192 memset( &entry, 0, sizeof(entry) ); /* clear the LDT entries */
193 for (i = SELECTOR_TO_ENTRY(sel); count; i++, count--)
195 LDT_SetEntry( i, &entry );
196 ldt_flags_copy[i] &= ~LDT_FLAGS_ALLOCATED;
201 /***********************************************************************
202 * SELECTOR_ReallocBlock
204 * Change the size of a block of selectors.
206 WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size )
208 ldt_entry entry;
209 WORD i, oldcount, newcount;
211 if (!size) size = 1;
212 oldcount = (GET_SEL_LIMIT(sel) >> 16) + 1;
213 newcount = (size + 0xffff) >> 16;
214 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
216 if (oldcount < newcount) /* We need to add selectors */
218 /* Check if the next selectors are free */
219 if (SELECTOR_TO_ENTRY(sel) + newcount > LDT_SIZE) i = oldcount;
220 else
221 for (i = oldcount; i < newcount; i++)
222 if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel)+i)) break;
224 if (i < newcount) /* they are not free */
226 SELECTOR_FreeBlock( sel, oldcount );
227 sel = AllocSelectorArray16( newcount );
229 else /* mark the selectors as allocated */
231 for (i = oldcount; i < newcount; i++)
232 ldt_flags_copy[SELECTOR_TO_ENTRY(sel)+i] |=LDT_FLAGS_ALLOCATED;
235 else if (oldcount > newcount) /* We need to remove selectors */
237 SELECTOR_FreeBlock( ENTRY_TO_SELECTOR(SELECTOR_TO_ENTRY(sel)+newcount),
238 oldcount - newcount );
240 if (sel) SELECTOR_SetEntries( sel, base, size, entry.type,
241 entry.seg_32bit, entry.read_only );
242 return sel;
246 /***********************************************************************
247 * PrestoChangoSelector (KERNEL.177)
249 WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
251 ldt_entry entry;
252 LDT_GetEntry( SELECTOR_TO_ENTRY( selSrc ), &entry );
253 entry.type ^= SEGMENT_CODE; /* toggle the executable bit */
254 LDT_SetEntry( SELECTOR_TO_ENTRY( selDst ), &entry );
255 return selDst;
259 /***********************************************************************
260 * AllocCStoDSAlias (KERNEL.170)
262 WORD WINAPI AllocCStoDSAlias16( WORD sel )
264 WORD newsel;
265 ldt_entry entry;
267 newsel = AllocSelectorArray16( 1 );
268 TRACE("(%04x): returning %04x\n",
269 sel, newsel );
270 if (!newsel) return 0;
271 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
272 entry.type = SEGMENT_DATA;
273 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
274 return newsel;
278 /***********************************************************************
279 * AllocDStoCSAlias (KERNEL.171)
281 WORD WINAPI AllocDStoCSAlias16( WORD sel )
283 WORD newsel;
284 ldt_entry entry;
286 newsel = AllocSelectorArray16( 1 );
287 TRACE("(%04x): returning %04x\n",
288 sel, newsel );
289 if (!newsel) return 0;
290 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
291 entry.type = SEGMENT_CODE;
292 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
293 return newsel;
297 /***********************************************************************
298 * LongPtrAdd (KERNEL.180)
300 void WINAPI LongPtrAdd16( DWORD ptr, DWORD add )
302 ldt_entry entry;
303 LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
304 entry.base += add;
305 LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
309 /***********************************************************************
310 * GetSelectorBase (KERNEL.186)
312 DWORD WINAPI WIN16_GetSelectorBase( WORD sel )
315 * Note: For Win32s processes, the whole linear address space is
316 * shifted by 0x10000 relative to the OS linear address space.
317 * See the comment in msdos/vxd.c.
320 DWORD base = GetSelectorBase( sel );
321 return W32S_WINE2APP( base, W32S_APPLICATION() ? W32S_OFFSET : 0 );
323 DWORD WINAPI GetSelectorBase( WORD sel )
325 DWORD base = GET_SEL_BASE(sel);
327 /* if base points into DOSMEM, assume we have to
328 * return pointer into physical lower 1MB */
330 return DOSMEM_MapLinearToDos( (LPVOID)base );
334 /***********************************************************************
335 * SetSelectorBase (KERNEL.187)
337 DWORD WINAPI WIN16_SetSelectorBase( WORD sel, DWORD base )
340 * Note: For Win32s processes, the whole linear address space is
341 * shifted by 0x10000 relative to the OS linear address space.
342 * See the comment in msdos/vxd.c.
345 SetSelectorBase( sel,
346 W32S_APP2WINE( base, W32S_APPLICATION() ? W32S_OFFSET : 0 ) );
347 return sel;
349 WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
351 ldt_entry entry;
353 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
355 entry.base = (DWORD)DOSMEM_MapDosToLinear(base);
357 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
358 return sel;
362 /***********************************************************************
363 * GetSelectorLimit (KERNEL.188)
365 DWORD WINAPI GetSelectorLimit16( WORD sel )
367 return GET_SEL_LIMIT(sel);
371 /***********************************************************************
372 * SetSelectorLimit (KERNEL.189)
374 WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
376 ldt_entry entry;
377 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
378 entry.limit_in_pages = (limit >= 0x100000);
379 if (entry.limit_in_pages) entry.limit = limit >> 12;
380 else entry.limit = limit;
381 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
382 return sel;
386 /***********************************************************************
387 * SelectorAccessRights (KERNEL.196)
389 WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
391 ldt_entry entry;
392 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
393 if (op == 0) /* get */
395 return 0x01 | /* accessed */
396 0x10 | /* not system */
397 0x60 | /* DPL 3 */
398 0x80 | /* present */
399 ((entry.read_only == 0) << 1) |
400 (entry.type << 2) |
401 (entry.seg_32bit << 14) |
402 (entry.limit_in_pages << 15);
404 else /* set */
406 entry.read_only = ((val & 2) == 0);
407 entry.type = (val >> 2) & 3;
408 entry.seg_32bit = val & 0x4000;
409 entry.limit_in_pages = val & 0x8000;
410 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
411 return 0;
416 /***********************************************************************
417 * IsBadCodePtr16 (KERNEL.336)
419 BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
421 WORD sel;
422 ldt_entry entry;
424 sel = SELECTOROF(lpfn);
425 if (!sel) return TRUE;
426 if (IS_SELECTOR_FREE(sel)) return TRUE;
427 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
428 if (entry.type != SEGMENT_CODE) return TRUE;
429 if (OFFSETOF(lpfn) > GET_SEL_LIMIT(sel)) return TRUE;
430 return FALSE;
434 /***********************************************************************
435 * IsBadStringPtr16 (KERNEL.337)
437 BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
439 WORD sel;
440 ldt_entry entry;
442 sel = SELECTOROF(ptr);
443 if (!sel) return TRUE;
444 if (IS_SELECTOR_FREE(sel)) return TRUE;
445 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
446 if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
447 if (strlen(PTR_SEG_TO_LIN(ptr)) < size) size = strlen(PTR_SEG_TO_LIN(ptr)) + 1;
448 if (size && (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel))) return TRUE;
449 return FALSE;
453 /***********************************************************************
454 * IsBadHugeReadPtr16 (KERNEL.346)
456 BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
458 WORD sel;
459 ldt_entry entry;
461 sel = SELECTOROF(ptr);
462 if (!sel) return TRUE;
463 if (IS_SELECTOR_FREE(sel)) return TRUE;
464 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
465 if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
466 if (size && (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel))) return TRUE;
467 return FALSE;
471 /***********************************************************************
472 * IsBadHugeWritePtr16 (KERNEL.347)
474 BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
476 WORD sel;
477 ldt_entry entry;
479 sel = SELECTOROF(ptr);
480 if (!sel) return TRUE;
481 if (IS_SELECTOR_FREE(sel)) return TRUE;
482 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
483 if ((entry.type == SEGMENT_CODE) || entry.read_only) return TRUE;
484 if (size && (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel))) return TRUE;
485 return FALSE;
488 /***********************************************************************
489 * IsBadReadPtr16 (KERNEL.334)
491 BOOL16 WINAPI IsBadReadPtr16( SEGPTR ptr, UINT16 size )
493 return IsBadHugeReadPtr16( ptr, size );
497 /***********************************************************************
498 * IsBadWritePtr16 (KERNEL.335)
500 BOOL16 WINAPI IsBadWritePtr16( SEGPTR ptr, UINT16 size )
502 return IsBadHugeWritePtr16( ptr, size );
506 /***********************************************************************
507 * IsBadFlatReadWritePtr16 (KERNEL.627)
509 BOOL16 WINAPI IsBadFlatReadWritePtr16( SEGPTR ptr, DWORD size, BOOL16 bWrite )
511 return bWrite? IsBadHugeWritePtr16( ptr, size )
512 : IsBadHugeReadPtr16( ptr, size );
516 /***********************************************************************
517 * MemoryRead (TOOLHELP.78)
519 DWORD WINAPI MemoryRead16( WORD sel, DWORD offset, void *buffer, DWORD count )
521 if (IS_SELECTOR_FREE(sel)) return 0;
522 if (offset > GET_SEL_LIMIT(sel)) return 0;
523 if (offset + count > GET_SEL_LIMIT(sel) + 1)
524 count = GET_SEL_LIMIT(sel) + 1 - offset;
525 memcpy( buffer, ((char *)GET_SEL_BASE(sel)) + offset, count );
526 return count;
530 /***********************************************************************
531 * MemoryWrite (TOOLHELP.79)
533 DWORD WINAPI MemoryWrite16( WORD sel, DWORD offset, void *buffer, DWORD count )
535 if (IS_SELECTOR_FREE(sel)) return 0;
536 if (offset > GET_SEL_LIMIT(sel)) return 0;
537 if (offset + count > GET_SEL_LIMIT(sel) + 1)
538 count = GET_SEL_LIMIT(sel) + 1 - offset;
539 memcpy( ((char *)GET_SEL_BASE(sel)) + offset, buffer, count );
540 return count;
543 /************************************* Win95 pointer mapping functions *
547 /***********************************************************************
548 * MapSL (KERNEL32.523)
550 * Maps fixed segmented pointer to linear.
552 LPVOID WINAPI MapSL( SEGPTR sptr )
554 return (LPVOID)PTR_SEG_TO_LIN(sptr);
557 /***********************************************************************
558 * MapSLFix (KERNEL32.524)
560 * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
561 * unexpected linear address change when GlobalCompact() shuffles
562 * moveable blocks.
565 LPVOID WINAPI MapSLFix( SEGPTR sptr )
567 return (LPVOID)PTR_SEG_TO_LIN(sptr);
570 /***********************************************************************
571 * UnMapSLFixArray (KERNEL32.701)
574 void WINAPI UnMapSLFixArray( SEGPTR sptr[], INT length, CONTEXT86 *context )
576 /* Must not change EAX, hence defined as 'register' function */
579 /***********************************************************************
580 * MapLS (KERNEL32.522)
582 * Maps linear pointer to segmented.
584 SEGPTR WINAPI MapLS( LPVOID ptr )
586 if (!HIWORD(ptr))
587 return (SEGPTR)ptr;
588 else
590 WORD sel = SELECTOR_AllocBlock( ptr, 0x10000, SEGMENT_DATA, FALSE, FALSE );
591 return PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
596 /***********************************************************************
597 * UnMapLS (KERNEL32.700)
599 * Free mapped selector.
601 void WINAPI UnMapLS( SEGPTR sptr )
603 if (SELECTOROF(sptr))
604 SELECTOR_FreeBlock( SELECTOROF(sptr), 1 );
607 /***********************************************************************
608 * GetThreadSelectorEntry (KERNEL32)
610 BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldtent)
612 #ifdef __i386__
613 struct get_selector_entry_request *req = get_req_buffer();
615 if (!(sel & 4)) /* GDT selector */
617 WORD seg;
618 sel &= ~3; /* ignore RPL */
619 if (!sel) /* null selector */
621 memset( ldtent, 0, sizeof(*ldtent) );
622 return TRUE;
624 ldtent->BaseLow = 0;
625 ldtent->HighWord.Bits.BaseMid = 0;
626 ldtent->HighWord.Bits.BaseHi = 0;
627 ldtent->LimitLow = 0xffff;
628 ldtent->HighWord.Bits.LimitHi = 0xf;
629 ldtent->HighWord.Bits.Dpl = 3;
630 ldtent->HighWord.Bits.Sys = 0;
631 ldtent->HighWord.Bits.Pres = 1;
632 ldtent->HighWord.Bits.Granularity = 1;
633 ldtent->HighWord.Bits.Default_Big = 1;
634 ldtent->HighWord.Bits.Type = 0x12;
635 /* it has to be one of the system GDT selectors */
636 GET_DS(seg);
637 if (sel == (seg & ~3)) return TRUE;
638 GET_SS(seg);
639 if (sel == (seg & ~3)) return TRUE;
640 GET_CS(seg);
641 if (sel == (seg & ~3))
643 ldtent->HighWord.Bits.Type |= 8; /* code segment */
644 return TRUE;
646 SetLastError( ERROR_NOACCESS );
647 return FALSE;
650 req->handle = hthread;
651 req->entry = sel >> __AHSHIFT;
652 if (server_call( REQ_GET_SELECTOR_ENTRY )) return FALSE;
654 if (!(req->flags & LDT_FLAGS_ALLOCATED))
656 SetLastError( ERROR_MR_MID_NOT_FOUND ); /* sic */
657 return FALSE;
659 if (req->flags & LDT_FLAGS_BIG) req->limit >>= 12;
660 ldtent->BaseLow = req->base & 0x0000ffff;
661 ldtent->HighWord.Bits.BaseMid = (req->base & 0x00ff0000) >> 16;
662 ldtent->HighWord.Bits.BaseHi = (req->base & 0xff000000) >> 24;
663 ldtent->LimitLow = req->limit & 0x0000ffff;
664 ldtent->HighWord.Bits.LimitHi = (req->limit & 0x000f0000) >> 16;
665 ldtent->HighWord.Bits.Dpl = 3;
666 ldtent->HighWord.Bits.Sys = 0;
667 ldtent->HighWord.Bits.Pres = 1;
668 ldtent->HighWord.Bits.Granularity = (req->flags & LDT_FLAGS_BIG) !=0;
669 ldtent->HighWord.Bits.Default_Big = (req->flags & LDT_FLAGS_32BIT) != 0;
670 ldtent->HighWord.Bits.Type = ((req->flags & LDT_FLAGS_TYPE) << 2) | 0x10;
671 if (!(req->flags & LDT_FLAGS_READONLY)) ldtent->HighWord.Bits.Type |= 0x2;
672 return TRUE;
673 #else
674 SetLastError( ERROR_NOT_IMPLEMENTED );
675 return FALSE;
676 #endif
680 /**********************************************************************
681 * SMapLS* (KERNEL32)
682 * These functions map linear pointers at [EBP+xxx] to segmented pointers
683 * and return them.
684 * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
685 * unravel them at SUnMapLS. We just store the segmented pointer there.
687 static void
688 x_SMapLS_IP_EBP_x(CONTEXT86 *context,int argoff) {
689 DWORD val,ptr;
691 val =*(DWORD*)(EBP_reg(context)+argoff);
692 if (val<0x10000) {
693 ptr=val;
694 *(DWORD*)(EBP_reg(context)+argoff) = 0;
695 } else {
696 ptr = MapLS((LPVOID)val);
697 *(DWORD*)(EBP_reg(context)+argoff) = ptr;
699 EAX_reg(context) = ptr;
702 void WINAPI SMapLS_IP_EBP_8 (CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context, 8);}
703 void WINAPI SMapLS_IP_EBP_12(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,12);}
704 void WINAPI SMapLS_IP_EBP_16(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,16);}
705 void WINAPI SMapLS_IP_EBP_20(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,20);}
706 void WINAPI SMapLS_IP_EBP_24(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,24);}
707 void WINAPI SMapLS_IP_EBP_28(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,28);}
708 void WINAPI SMapLS_IP_EBP_32(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,32);}
709 void WINAPI SMapLS_IP_EBP_36(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,36);}
710 void WINAPI SMapLS_IP_EBP_40(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,40);}
712 void WINAPI SMapLS( CONTEXT86 *context )
714 if (EAX_reg(context)>=0x10000) {
715 EAX_reg(context) = MapLS((LPVOID)EAX_reg(context));
716 EDX_reg(context) = EAX_reg(context);
717 } else {
718 EDX_reg(context) = 0;
722 void WINAPI SUnMapLS( CONTEXT86 *context )
724 if (EAX_reg(context)>=0x10000)
725 UnMapLS((SEGPTR)EAX_reg(context));
728 static void
729 x_SUnMapLS_IP_EBP_x(CONTEXT86 *context,int argoff) {
730 if (*(DWORD*)(EBP_reg(context)+argoff))
731 UnMapLS(*(DWORD*)(EBP_reg(context)+argoff));
732 *(DWORD*)(EBP_reg(context)+argoff)=0;
734 void WINAPI SUnMapLS_IP_EBP_8 (CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context, 8); }
735 void WINAPI SUnMapLS_IP_EBP_12(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,12); }
736 void WINAPI SUnMapLS_IP_EBP_16(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,16); }
737 void WINAPI SUnMapLS_IP_EBP_20(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,20); }
738 void WINAPI SUnMapLS_IP_EBP_24(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,24); }
739 void WINAPI SUnMapLS_IP_EBP_28(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,28); }
740 void WINAPI SUnMapLS_IP_EBP_32(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,32); }
741 void WINAPI SUnMapLS_IP_EBP_36(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,36); }
742 void WINAPI SUnMapLS_IP_EBP_40(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,40); }
744 /**********************************************************************
745 * AllocMappedBuffer (KERNEL32.38)
747 * This is a undocumented KERNEL32 function that
748 * SMapLS's a GlobalAlloc'ed buffer.
750 * Input: EDI register: size of buffer to allocate
751 * Output: EDI register: pointer to buffer
753 * Note: The buffer is preceeded by 8 bytes:
754 * ...
755 * edi+0 buffer
756 * edi-4 SEGPTR to buffer
757 * edi-8 some magic Win95 needs for SUnMapLS
758 * (we use it for the memory handle)
760 * The SEGPTR is used by the caller!
763 void WINAPI AllocMappedBuffer( CONTEXT86 *context )
765 HGLOBAL handle = GlobalAlloc(0, EDI_reg(context) + 8);
766 DWORD *buffer = (DWORD *)GlobalLock(handle);
767 SEGPTR ptr = 0;
769 if (buffer)
770 if (!(ptr = MapLS(buffer + 2)))
772 GlobalUnlock(handle);
773 GlobalFree(handle);
776 if (!ptr)
777 EAX_reg(context) = EDI_reg(context) = 0;
778 else
780 buffer[0] = handle;
781 buffer[1] = ptr;
783 EAX_reg(context) = (DWORD) ptr;
784 EDI_reg(context) = (DWORD)(buffer + 2);
788 /**********************************************************************
789 * FreeMappedBuffer (KERNEL32.39)
791 * Free a buffer allocated by AllocMappedBuffer
793 * Input: EDI register: pointer to buffer
796 void WINAPI FreeMappedBuffer( CONTEXT86 *context )
798 if (EDI_reg(context))
800 DWORD *buffer = (DWORD *)EDI_reg(context) - 2;
802 UnMapLS(buffer[1]);
804 GlobalUnlock(buffer[0]);
805 GlobalFree(buffer[0]);
810 /***********************************************************************
811 * UTSelectorOffsetToLinear (WIN32S16.48)
813 * rough guesswork, but seems to work (I had no "reasonable" docu)
815 LPVOID WINAPI UTSelectorOffsetToLinear16(SEGPTR sptr)
817 return PTR_SEG_TO_LIN(sptr);
820 /***********************************************************************
821 * UTLinearToSelectorOffset (WIN32S16.49)
823 * FIXME: I don't know if that's the right way to do linear -> segmented
825 SEGPTR WINAPI UTLinearToSelectorOffset16(LPVOID lptr)
827 return (SEGPTR)lptr;