New debug scheme with explicit debug channels declaration.
[wine.git] / memory / selector.c
blob964c3cccd3cd00310fa73f5740dfe90c62449c70
1 /*
2 * Selector manipulation functions
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <string.h>
8 #include "wine/winbase16.h"
9 #include "ldt.h"
10 #include "miscemu.h"
11 #include "selectors.h"
12 #include "stackframe.h"
13 #include "process.h"
14 #include "debug.h"
16 DEFAULT_DEBUG_CHANNEL(selector)
19 /***********************************************************************
20 * AllocSelectorArray (KERNEL.206)
22 WORD WINAPI AllocSelectorArray16( WORD count )
24 WORD i, sel, size = 0;
25 ldt_entry entry;
27 if (!count) return 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;
34 sel = i - size + 1;
36 entry.base = 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",
63 sel, newsel );
64 if (!newsel) return 0;
65 if (!sel) return newsel; /* nothing to copy */
66 for (i = 0; i < count; i++)
68 ldt_entry entry;
69 LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
70 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel) + i, &entry );
72 return newsel;
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 );
83 return 0;
87 /***********************************************************************
88 * SELECTOR_SetEntries
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,
94 BOOL readonly )
96 ldt_entry entry;
97 WORD i, count;
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;
102 entry.type = type;
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 )
130 WORD sel, count;
132 if (!size) return 0;
133 count = (size + 0xffff) / 0x10000;
134 sel = AllocSelectorArray16( count );
135 if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
136 return sel;
140 /***********************************************************************
141 * SELECTOR_MoveBlock
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++)
151 ldt_entry entry;
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 /***********************************************************************
160 * SELECTOR_FreeBlock
162 * Free a block of selectors.
164 void SELECTOR_FreeBlock( WORD sel, WORD count )
166 WORD i, nextsel;
167 ldt_entry entry;
169 TRACE(selector, "(%04x,%d)\n", sel, count );
170 sel &= ~(__AHINCR - 1); /* clear bottom bits of selector */
171 nextsel = sel + (count << __AHSHIFT);
173 #ifdef __i386__
175 /* Check if we are freeing current %fs or %gs selector */
177 WORD fs, gs;
178 GET_FS(fs);
179 if ((fs >= sel) && (fs < nextsel))
181 WARN(selector, "Freeing %%fs selector (%04x), not good.\n", fs );
182 SET_FS( 0 );
184 GET_GS(gs);
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 )
205 ldt_entry entry;
206 WORD i, oldcount, newcount;
208 if (!size) size = 1;
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;
217 else
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 );
239 return sel;
243 /***********************************************************************
244 * PrestoChangoSelector (KERNEL.177)
246 WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
248 ldt_entry entry;
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 );
252 return selDst;
256 /***********************************************************************
257 * AllocCStoDSAlias (KERNEL.170)
259 WORD WINAPI AllocCStoDSAlias16( WORD sel )
261 WORD newsel;
262 ldt_entry entry;
264 newsel = AllocSelectorArray16( 1 );
265 TRACE(selector, "(%04x): returning %04x\n",
266 sel, newsel );
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 );
271 return newsel;
275 /***********************************************************************
276 * AllocDStoCSAlias (KERNEL.171)
278 WORD WINAPI AllocDStoCSAlias16( WORD sel )
280 WORD newsel;
281 ldt_entry entry;
283 newsel = AllocSelectorArray16( 1 );
284 TRACE(selector, "(%04x): returning %04x\n",
285 sel, newsel );
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 );
290 return newsel;
294 /***********************************************************************
295 * LongPtrAdd (KERNEL.180)
297 void WINAPI LongPtrAdd16( DWORD ptr, DWORD add )
299 ldt_entry entry;
300 LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
301 entry.base += add;
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 ) );
344 return sel;
346 WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
348 ldt_entry entry;
350 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
352 entry.base = (DWORD)DOSMEM_MapDosToLinear(base);
354 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
355 return sel;
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 )
373 ldt_entry entry;
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 );
379 return sel;
383 /***********************************************************************
384 * SelectorAccessRights (KERNEL.196)
386 WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
388 ldt_entry entry;
389 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
390 if (op == 0) /* get */
392 return 0x01 | /* accessed */
393 0x10 | /* not system */
394 0x60 | /* DPL 3 */
395 0x80 | /* present */
396 ((entry.read_only == 0) << 1) |
397 (entry.type << 2) |
398 (entry.seg_32bit << 14) |
399 (entry.limit_in_pages << 15);
401 else /* set */
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 );
408 return 0;
413 /***********************************************************************
414 * IsBadCodePtr16 (KERNEL.336)
416 BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
418 WORD sel;
419 ldt_entry entry;
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;
427 return FALSE;
431 /***********************************************************************
432 * IsBadStringPtr16 (KERNEL.337)
434 BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
436 WORD sel;
437 ldt_entry entry;
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;
446 return FALSE;
450 /***********************************************************************
451 * IsBadHugeReadPtr16 (KERNEL.346)
453 BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
455 WORD sel;
456 ldt_entry entry;
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;
464 return FALSE;
468 /***********************************************************************
469 * IsBadHugeWritePtr16 (KERNEL.347)
471 BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
473 WORD sel;
474 ldt_entry entry;
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;
482 return FALSE;
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 );
513 return 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 );
527 return 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
549 * moveable blocks.
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 )
575 if (!HIWORD(ptr))
576 return (SEGPTR)ptr;
577 else
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,
601 LPLDT_ENTRY ldtent)
603 ldt_entry ldtentry;
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;
619 return TRUE;
623 /**********************************************************************
624 * SMapLS* (KERNEL32)
625 * These functions map linear pointers at [EBP+xxx] to segmented pointers
626 * and return them.
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.
630 static void
631 x_SMapLS_IP_EBP_x(CONTEXT *context,int argoff) {
632 DWORD val,ptr;
634 val =*(DWORD*)(EBP_reg(context)+argoff);
635 if (val<0x10000) {
636 ptr=val;
637 *(DWORD*)(EBP_reg(context)+argoff) = 0;
638 } else {
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);
660 } else {
661 EDX_reg(context) = 0;
665 REGS_ENTRYPOINT(SUnMapLS)
667 if (EAX_reg(context)>=0x10000)
668 UnMapLS((SEGPTR)EAX_reg(context));
671 static void
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:
697 * ...
698 * edi+0 buffer
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);
710 SEGPTR ptr = 0;
712 if (buffer)
713 if (!(ptr = MapLS(buffer + 2)))
715 GlobalUnlock(handle);
716 GlobalFree(handle);
719 if (!ptr)
720 EAX_reg(context) = EDI_reg(context) = 0;
721 else
723 buffer[0] = handle;
724 buffer[1] = ptr;
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;
745 UnMapLS(buffer[1]);
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 */
759 if (protected)
760 return PTR_SEG_TO_LIN(vp);
761 else
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)
808 return (SEGPTR)lptr;