Changes in X11DRV_KEYBOARD_DetectLayout in order to implement Russian
[wine/multimedia.git] / memory / selector.c
blob250a1ed33691931c757b54a040ddf88fab008e15
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"
17 /***********************************************************************
18 * AllocSelectorArray (KERNEL.206)
20 WORD WINAPI AllocSelectorArray16( WORD count )
22 WORD i, sel, size = 0;
23 ldt_entry entry;
25 if (!count) return 0;
26 for (i = FIRST_LDT_ENTRY_TO_ALLOC; i < LDT_SIZE; i++)
28 if (!IS_LDT_ENTRY_FREE(i)) size = 0;
29 else if (++size >= count) break;
31 if (i == LDT_SIZE) return 0;
32 sel = i - size + 1;
34 entry.base = 0;
35 entry.type = SEGMENT_DATA;
36 entry.seg_32bit = FALSE;
37 entry.read_only = FALSE;
38 entry.limit_in_pages = FALSE;
39 entry.limit = 1; /* avoid 0 base and limit */
41 for (i = 0; i < count; i++)
43 /* Mark selector as allocated */
44 ldt_flags_copy[sel + i] |= LDT_FLAGS_ALLOCATED;
45 LDT_SetEntry( sel + i, &entry );
47 return ENTRY_TO_SELECTOR( sel );
51 /***********************************************************************
52 * AllocSelector (KERNEL.175)
54 WORD WINAPI AllocSelector16( WORD sel )
56 WORD newsel, count, i;
58 count = sel ? ((GET_SEL_LIMIT(sel) >> 16) + 1) : 1;
59 newsel = AllocSelectorArray16( count );
60 TRACE(selector, "(%04x): returning %04x\n",
61 sel, newsel );
62 if (!newsel) return 0;
63 if (!sel) return newsel; /* nothing to copy */
64 for (i = 0; i < count; i++)
66 ldt_entry entry;
67 LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
68 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel) + i, &entry );
70 return newsel;
74 /***********************************************************************
75 * FreeSelector (KERNEL.176)
77 WORD WINAPI FreeSelector16( WORD sel )
79 if (IS_SELECTOR_FREE(sel)) return sel; /* error */
80 SELECTOR_FreeBlock( sel, 1 );
81 return 0;
85 /***********************************************************************
86 * SELECTOR_SetEntries
88 * Set the LDT entries for an array of selectors.
90 static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size,
91 enum seg_type type, BOOL is32bit,
92 BOOL readonly )
94 ldt_entry entry;
95 WORD i, count;
97 /* The limit for the first selector is the whole */
98 /* block. The next selectors get a 64k limit. */
99 entry.base = (unsigned long)base;
100 entry.type = type;
101 entry.seg_32bit = is32bit;
102 entry.read_only = readonly;
103 entry.limit_in_pages = (size > 0x100000);
104 if (entry.limit_in_pages) entry.limit = ((size + 0xfff) >> 12) - 1;
105 else entry.limit = size - 1;
106 /* Make sure base and limit are not 0 together if the size is not 0 */
107 if (!base && !entry.limit && size) entry.limit = 1;
108 count = (size + 0xffff) / 0x10000;
109 for (i = 0; i < count; i++)
111 LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
112 entry.base += 0x10000;
113 /* Apparently the next selectors should *not* get a 64k limit. */
114 /* Can't remember where I read they should... --AJ */
115 entry.limit -= entry.limit_in_pages ? 0x10 : 0x10000;
120 /***********************************************************************
121 * SELECTOR_AllocBlock
123 * Allocate selectors for a block of linear memory.
125 WORD SELECTOR_AllocBlock( const void *base, DWORD size, enum seg_type type,
126 BOOL is32bit, BOOL readonly )
128 WORD sel, count;
130 if (!size) return 0;
131 count = (size + 0xffff) / 0x10000;
132 sel = AllocSelectorArray16( count );
133 if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
134 return sel;
138 /***********************************************************************
139 * SELECTOR_MoveBlock
141 * Move a block of selectors in linear memory.
143 void SELECTOR_MoveBlock( WORD sel, const void *new_base )
145 WORD i, count = (GET_SEL_LIMIT(sel) >> 16) + 1;
147 for (i = 0; i < count; i++)
149 ldt_entry entry;
150 LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
151 entry.base = (unsigned long)new_base;
152 LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
157 /***********************************************************************
158 * SELECTOR_FreeBlock
160 * Free a block of selectors.
162 void SELECTOR_FreeBlock( WORD sel, WORD count )
164 WORD i, nextsel;
165 ldt_entry entry;
167 TRACE(selector, "(%04x,%d)\n", sel, count );
168 sel &= ~(__AHINCR - 1); /* clear bottom bits of selector */
169 nextsel = sel + (count << __AHSHIFT);
171 #ifdef __i386__
173 /* Check if we are freeing current %fs or %gs selector */
175 WORD fs, gs;
176 GET_FS(fs);
177 if ((fs >= sel) && (fs < nextsel))
179 WARN(selector, "Freeing %%fs selector (%04x), not good.\n", fs );
180 SET_FS( 0 );
182 GET_GS(gs);
183 if ((gs >= sel) && (gs < nextsel)) SET_GS( 0 );
185 #endif /* __i386__ */
187 memset( &entry, 0, sizeof(entry) ); /* clear the LDT entries */
188 for (i = SELECTOR_TO_ENTRY(sel); count; i++, count--)
190 LDT_SetEntry( i, &entry );
191 ldt_flags_copy[i] &= ~LDT_FLAGS_ALLOCATED;
196 /***********************************************************************
197 * SELECTOR_ReallocBlock
199 * Change the size of a block of selectors.
201 WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size,
202 enum seg_type type, BOOL is32bit, BOOL readonly)
204 WORD i, oldcount, newcount;
206 if (!size) size = 1;
207 oldcount = (GET_SEL_LIMIT(sel) >> 16) + 1;
208 newcount = (size + 0xffff) >> 16;
210 if (oldcount < newcount) /* We need to add selectors */
212 /* Check if the next selectors are free */
213 if (SELECTOR_TO_ENTRY(sel) + newcount > LDT_SIZE) i = oldcount;
214 else
215 for (i = oldcount; i < newcount; i++)
216 if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel)+i)) break;
218 if (i < newcount) /* they are not free */
220 SELECTOR_FreeBlock( sel, oldcount );
221 sel = AllocSelectorArray16( newcount );
223 else /* mark the selectors as allocated */
225 for (i = oldcount; i < newcount; i++)
226 ldt_flags_copy[SELECTOR_TO_ENTRY(sel)+i] |=LDT_FLAGS_ALLOCATED;
229 else if (oldcount > newcount) /* We need to remove selectors */
231 SELECTOR_FreeBlock( ENTRY_TO_SELECTOR(SELECTOR_TO_ENTRY(sel)+newcount),
232 oldcount - newcount );
234 if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
235 return sel;
239 /***********************************************************************
240 * PrestoChangoSelector (KERNEL.177)
242 WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
244 ldt_entry entry;
245 LDT_GetEntry( SELECTOR_TO_ENTRY( selSrc ), &entry );
246 entry.type ^= SEGMENT_CODE; /* toggle the executable bit */
247 LDT_SetEntry( SELECTOR_TO_ENTRY( selDst ), &entry );
248 return selDst;
252 /***********************************************************************
253 * AllocCStoDSAlias (KERNEL.170)
255 WORD WINAPI AllocCStoDSAlias16( WORD sel )
257 WORD newsel;
258 ldt_entry entry;
260 newsel = AllocSelectorArray16( 1 );
261 TRACE(selector, "(%04x): returning %04x\n",
262 sel, newsel );
263 if (!newsel) return 0;
264 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
265 entry.type = SEGMENT_DATA;
266 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
267 return newsel;
271 /***********************************************************************
272 * AllocDStoCSAlias (KERNEL.171)
274 WORD WINAPI AllocDStoCSAlias16( WORD sel )
276 WORD newsel;
277 ldt_entry entry;
279 newsel = AllocSelectorArray16( 1 );
280 TRACE(selector, "(%04x): returning %04x\n",
281 sel, newsel );
282 if (!newsel) return 0;
283 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
284 entry.type = SEGMENT_CODE;
285 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
286 return newsel;
290 /***********************************************************************
291 * LongPtrAdd (KERNEL.180)
293 void WINAPI LongPtrAdd16( DWORD ptr, DWORD add )
295 ldt_entry entry;
296 LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
297 entry.base += add;
298 LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
302 /***********************************************************************
303 * GetSelectorBase (KERNEL.186)
305 DWORD WINAPI WIN16_GetSelectorBase( WORD sel )
308 * Note: For Win32s processes, the whole linear address space is
309 * shifted by 0x10000 relative to the OS linear address space.
310 * See the comment in msdos/vxd.c.
313 DWORD base = GetSelectorBase( sel );
314 return W32S_WINE2APP( base, W32S_APPLICATION() ? W32S_OFFSET : 0 );
316 DWORD WINAPI GetSelectorBase( WORD sel )
318 DWORD base = GET_SEL_BASE(sel);
320 /* if base points into DOSMEM, assume we have to
321 * return pointer into physical lower 1MB */
323 return DOSMEM_MapLinearToDos( (LPVOID)base );
327 /***********************************************************************
328 * SetSelectorBase (KERNEL.187)
330 DWORD WINAPI WIN16_SetSelectorBase( WORD sel, DWORD base )
333 * Note: For Win32s processes, the whole linear address space is
334 * shifted by 0x10000 relative to the OS linear address space.
335 * See the comment in msdos/vxd.c.
338 SetSelectorBase( sel,
339 W32S_APP2WINE( base, W32S_APPLICATION() ? W32S_OFFSET : 0 ) );
340 return sel;
342 WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
344 ldt_entry entry;
346 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
348 entry.base = (DWORD)DOSMEM_MapDosToLinear(base);
350 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
351 return sel;
355 /***********************************************************************
356 * GetSelectorLimit (KERNEL.188)
358 DWORD WINAPI GetSelectorLimit16( WORD sel )
360 return GET_SEL_LIMIT(sel);
364 /***********************************************************************
365 * SetSelectorLimit (KERNEL.189)
367 WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
369 ldt_entry entry;
370 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
371 entry.limit_in_pages = (limit >= 0x100000);
372 if (entry.limit_in_pages) entry.limit = limit >> 12;
373 else entry.limit = limit;
374 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
375 return sel;
379 /***********************************************************************
380 * SelectorAccessRights (KERNEL.196)
382 WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
384 ldt_entry entry;
385 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
386 if (op == 0) /* get */
388 return 0x01 | /* accessed */
389 0x10 | /* not system */
390 0x60 | /* DPL 3 */
391 0x80 | /* present */
392 ((entry.read_only == 0) << 1) |
393 (entry.type << 2) |
394 (entry.seg_32bit << 14) |
395 (entry.limit_in_pages << 15);
397 else /* set */
399 entry.read_only = ((val & 2) == 0);
400 entry.type = (val >> 2) & 3;
401 entry.seg_32bit = val & 0x4000;
402 entry.limit_in_pages = val & 0x8000;
403 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
404 return 0;
409 /***********************************************************************
410 * IsBadCodePtr16 (KERNEL.336)
412 BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
414 WORD sel;
415 ldt_entry entry;
417 sel = SELECTOROF(lpfn);
418 if (!sel) return TRUE;
419 if (IS_SELECTOR_FREE(sel)) return TRUE;
420 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
421 if (entry.type != SEGMENT_CODE) return TRUE;
422 if (OFFSETOF(lpfn) > GET_SEL_LIMIT(sel)) return TRUE;
423 return FALSE;
427 /***********************************************************************
428 * IsBadStringPtr16 (KERNEL.337)
430 BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
432 WORD sel;
433 ldt_entry entry;
435 sel = SELECTOROF(ptr);
436 if (!sel) return TRUE;
437 if (IS_SELECTOR_FREE(sel)) return TRUE;
438 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
439 if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
440 if (strlen(PTR_SEG_TO_LIN(ptr)) < size) size = strlen(PTR_SEG_TO_LIN(ptr));
441 if (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel)) return TRUE;
442 return FALSE;
446 /***********************************************************************
447 * IsBadHugeReadPtr16 (KERNEL.346)
449 BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
451 WORD sel;
452 ldt_entry entry;
454 sel = SELECTOROF(ptr);
455 if (!sel) return TRUE;
456 if (IS_SELECTOR_FREE(sel)) return TRUE;
457 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
458 if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
459 if (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel)) return TRUE;
460 return FALSE;
464 /***********************************************************************
465 * IsBadHugeWritePtr16 (KERNEL.347)
467 BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
469 WORD sel;
470 ldt_entry entry;
472 sel = SELECTOROF(ptr);
473 if (!sel) return TRUE;
474 if (IS_SELECTOR_FREE(sel)) return TRUE;
475 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
476 if ((entry.type == SEGMENT_CODE) || entry.read_only) return TRUE;
477 if (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel)) return TRUE;
478 return FALSE;
481 /***********************************************************************
482 * IsBadReadPtr16 (KERNEL.334)
484 BOOL16 WINAPI IsBadReadPtr16( SEGPTR ptr, UINT16 size )
486 return IsBadHugeReadPtr16( ptr, size );
490 /***********************************************************************
491 * IsBadWritePtr16 (KERNEL.335)
493 BOOL16 WINAPI IsBadWritePtr16( SEGPTR ptr, UINT16 size )
495 return IsBadHugeWritePtr16( ptr, size );
499 /***********************************************************************
500 * MemoryRead (TOOLHELP.78)
502 DWORD WINAPI MemoryRead16( WORD sel, DWORD offset, void *buffer, DWORD count )
504 if (IS_SELECTOR_FREE(sel)) return 0;
505 if (offset > GET_SEL_LIMIT(sel)) return 0;
506 if (offset + count > GET_SEL_LIMIT(sel) + 1)
507 count = GET_SEL_LIMIT(sel) + 1 - offset;
508 memcpy( buffer, ((char *)GET_SEL_BASE(sel)) + offset, count );
509 return count;
513 /***********************************************************************
514 * MemoryWrite (TOOLHELP.79)
516 DWORD WINAPI MemoryWrite16( WORD sel, DWORD offset, void *buffer, DWORD count )
518 if (IS_SELECTOR_FREE(sel)) return 0;
519 if (offset > GET_SEL_LIMIT(sel)) return 0;
520 if (offset + count > GET_SEL_LIMIT(sel) + 1)
521 count = GET_SEL_LIMIT(sel) + 1 - offset;
522 memcpy( ((char *)GET_SEL_BASE(sel)) + offset, buffer, count );
523 return count;
526 /************************************* Win95 pointer mapping functions *
530 /***********************************************************************
531 * MapSL (KERNEL32.523)
533 * Maps fixed segmented pointer to linear.
535 LPVOID WINAPI MapSL( SEGPTR sptr )
537 return (LPVOID)PTR_SEG_TO_LIN(sptr);
540 /***********************************************************************
541 * MapSLFix (KERNEL32.524)
543 * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
544 * unexpected linear address change when GlobalCompact() shuffles
545 * moveable blocks.
548 LPVOID WINAPI MapSLFix( SEGPTR sptr )
550 return (LPVOID)PTR_SEG_TO_LIN(sptr);
553 /***********************************************************************
554 * UnMapSLFixArray (KERNEL32.701)
557 REGS_ENTRYPOINT(UnMapSLFixArray) /* SEGPTR sptr[], INT32 length */
559 /* Must not change EAX, hence defined as 'register' function */
560 /* We need to remove the arguments ourselves */
561 ESP_reg( context ) += 8;
564 /***********************************************************************
565 * MapLS (KERNEL32.522)
567 * Maps linear pointer to segmented.
569 SEGPTR WINAPI MapLS( LPVOID ptr )
571 if (!HIWORD(ptr))
572 return (SEGPTR)ptr;
573 else
575 WORD sel = SELECTOR_AllocBlock( ptr, 0x10000, SEGMENT_DATA, FALSE, FALSE );
576 return PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
581 /***********************************************************************
582 * UnMapLS (KERNEL32.700)
584 * Free mapped selector.
586 void WINAPI UnMapLS( SEGPTR sptr )
588 if (SELECTOROF(sptr))
589 SELECTOR_FreeBlock( SELECTOROF(sptr), 1 );
592 /***********************************************************************
593 * GetThreadSelectorEntry (KERNEL32)
594 * FIXME: add #ifdef i386 for non x86
596 BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel,
597 LPLDT_ENTRY ldtent)
599 ldt_entry ldtentry;
601 LDT_GetEntry(SELECTOR_TO_ENTRY(sel),&ldtentry);
602 ldtent->BaseLow = ldtentry.base & 0x0000ffff;
603 ldtent->HighWord.Bits.BaseMid = (ldtentry.base & 0x00ff0000) >> 16;
604 ldtent->HighWord.Bits.BaseHi = (ldtentry.base & 0xff000000) >> 24;
605 ldtent->LimitLow = ldtentry.limit & 0x0000ffff;
606 ldtent->HighWord.Bits.LimitHi = (ldtentry.limit & 0x00ff0000) >> 16;
607 ldtent->HighWord.Bits.Dpl = 3;
608 ldtent->HighWord.Bits.Sys = 0;
609 ldtent->HighWord.Bits.Pres = 1;
610 ldtent->HighWord.Bits.Type = 0x10|(ldtentry.type << 2);
611 if (ldtentry.read_only)
612 ldtent->HighWord.Bits.Type|=0x2;
613 ldtent->HighWord.Bits.Granularity = ldtentry.limit_in_pages;
614 ldtent->HighWord.Bits.Default_Big = ldtentry.seg_32bit;
615 return TRUE;
619 /**********************************************************************
620 * SMapLS* (KERNEL32)
621 * These functions map linear pointers at [EBP+xxx] to segmented pointers
622 * and return them.
623 * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
624 * unravel them at SUnMapLS. We just store the segmented pointer there.
626 static void
627 x_SMapLS_IP_EBP_x(CONTEXT *context,int argoff) {
628 DWORD val,ptr;
630 val =*(DWORD*)(EBP_reg(context)+argoff);
631 if (val<0x10000) {
632 ptr=val;
633 *(DWORD*)(EBP_reg(context)+argoff) = 0;
634 } else {
635 ptr = MapLS((LPVOID)val);
636 *(DWORD*)(EBP_reg(context)+argoff) = ptr;
638 EAX_reg(context) = ptr;
641 REGS_ENTRYPOINT(SMapLS_IP_EBP_8) {x_SMapLS_IP_EBP_x(context,8);}
642 REGS_ENTRYPOINT(SMapLS_IP_EBP_12) {x_SMapLS_IP_EBP_x(context,12);}
643 REGS_ENTRYPOINT(SMapLS_IP_EBP_16) {x_SMapLS_IP_EBP_x(context,16);}
644 REGS_ENTRYPOINT(SMapLS_IP_EBP_20) {x_SMapLS_IP_EBP_x(context,20);}
645 REGS_ENTRYPOINT(SMapLS_IP_EBP_24) {x_SMapLS_IP_EBP_x(context,24);}
646 REGS_ENTRYPOINT(SMapLS_IP_EBP_28) {x_SMapLS_IP_EBP_x(context,28);}
647 REGS_ENTRYPOINT(SMapLS_IP_EBP_32) {x_SMapLS_IP_EBP_x(context,32);}
648 REGS_ENTRYPOINT(SMapLS_IP_EBP_36) {x_SMapLS_IP_EBP_x(context,36);}
649 REGS_ENTRYPOINT(SMapLS_IP_EBP_40) {x_SMapLS_IP_EBP_x(context,40);}
651 REGS_ENTRYPOINT(SMapLS)
653 if (EAX_reg(context)>=0x10000) {
654 EAX_reg(context) = MapLS((LPVOID)EAX_reg(context));
655 EDX_reg(context) = EAX_reg(context);
656 } else {
657 EDX_reg(context) = 0;
661 REGS_ENTRYPOINT(SUnMapLS)
663 if (EAX_reg(context)>=0x10000)
664 UnMapLS((SEGPTR)EAX_reg(context));
667 static void
668 x_SUnMapLS_IP_EBP_x(CONTEXT *context,int argoff) {
669 if (*(DWORD*)(EBP_reg(context)+argoff))
670 UnMapLS(*(DWORD*)(EBP_reg(context)+argoff));
671 *(DWORD*)(EBP_reg(context)+argoff)=0;
673 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_8) { x_SUnMapLS_IP_EBP_x(context,8); }
674 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_12) { x_SUnMapLS_IP_EBP_x(context,12); }
675 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_16) { x_SUnMapLS_IP_EBP_x(context,16); }
676 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_20) { x_SUnMapLS_IP_EBP_x(context,20); }
677 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_24) { x_SUnMapLS_IP_EBP_x(context,24); }
678 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_28) { x_SUnMapLS_IP_EBP_x(context,28); }
679 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_32) { x_SUnMapLS_IP_EBP_x(context,32); }
680 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_36) { x_SUnMapLS_IP_EBP_x(context,36); }
681 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_40) { x_SUnMapLS_IP_EBP_x(context,40); }
683 /**********************************************************************
684 * AllocMappedBuffer (KERNEL32.38)
686 * This is a undocumented KERNEL32 function that
687 * SMapLS's a GlobalAlloc'ed buffer.
689 * Input: EDI register: size of buffer to allocate
690 * Output: EDI register: pointer to buffer
692 * Note: The buffer is preceeded by 8 bytes:
693 * ...
694 * edi+0 buffer
695 * edi-4 SEGPTR to buffer
696 * edi-8 some magic Win95 needs for SUnMapLS
697 * (we use it for the memory handle)
699 * The SEGPTR is used by the caller!
702 REGS_ENTRYPOINT(AllocMappedBuffer)
704 HGLOBAL handle = GlobalAlloc(0, EDI_reg(context) + 8);
705 DWORD *buffer = (DWORD *)GlobalLock(handle);
706 SEGPTR ptr = 0;
708 if (buffer)
709 if (!(ptr = MapLS(buffer + 2)))
711 GlobalUnlock(handle);
712 GlobalFree(handle);
715 if (!ptr)
716 EAX_reg(context) = EDI_reg(context) = 0;
717 else
719 buffer[0] = handle;
720 buffer[1] = ptr;
722 EAX_reg(context) = (DWORD) ptr;
723 EDI_reg(context) = (DWORD)(buffer + 2);
727 /**********************************************************************
728 * FreeMappedBuffer (KERNEL32.39)
730 * Free a buffer allocated by AllocMappedBuffer
732 * Input: EDI register: pointer to buffer
735 REGS_ENTRYPOINT(FreeMappedBuffer)
737 if (EDI_reg(context))
739 DWORD *buffer = (DWORD *)EDI_reg(context) - 2;
741 UnMapLS(buffer[1]);
743 GlobalUnlock(buffer[0]);
744 GlobalFree(buffer[0]);
748 /**********************************************************************
749 * WOWGetVDMPointer (KERNEL32.55)
750 * Get linear from segmented pointer. (MSDN lib)
752 LPVOID WINAPI WOWGetVDMPointer(DWORD vp,DWORD nrofbytes,BOOL protected)
754 /* FIXME: add size check too */
755 if (protected)
756 return PTR_SEG_TO_LIN(vp);
757 else
758 return DOSMEM_MapRealToLinear(vp);
761 /**********************************************************************
762 * GetVDMPointer32W (KERNEL.516)
764 LPVOID WINAPI GetVDMPointer32W(DWORD vp,WORD mode)
766 return WOWGetVDMPointer(vp,0,(DWORD)mode);
769 /**********************************************************************
770 * WOWGetVDMPointerFix (KERNEL32.55)
771 * Dito, but fix heapsegment (MSDN lib)
773 LPVOID WINAPI WOWGetVDMPointerFix(DWORD vp,DWORD nrofbytes,BOOL protected)
775 /* FIXME: fix heapsegment */
776 return WOWGetVDMPointer(vp,nrofbytes,protected);
779 /**********************************************************************
780 * WOWGetVDMPointerUnFix (KERNEL32.56)
782 void WINAPI WOWGetVDMPointerUnfix(DWORD vp)
784 /* FIXME: unfix heapsegment */
787 /***********************************************************************
788 * UTSelectorOffsetToLinear (WIN32S16.48)
790 * rough guesswork, but seems to work (I had no "reasonable" docu)
792 LPVOID WINAPI UTSelectorOffsetToLinear16(SEGPTR sptr)
794 return PTR_SEG_TO_LIN(sptr);
797 /***********************************************************************
798 * UTLinearToSelectorOffset (WIN32S16.49)
800 * FIXME: I don't know if that's the right way to do linear -> segmented
802 SEGPTR WINAPI UTLinearToSelectorOffset16(LPVOID lptr)
804 return (SEGPTR)lptr;