Initial revision
[wine/multimedia.git] / memory / selector.c
blob16bddc6ff27fc7e199cccb0ef97eb9f790b60f1c
1 /*
2 * Selector manipulation functions
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <string.h>
8 #include "windows.h"
9 #include "ldt.h"
10 #include "miscemu.h"
11 #include "selectors.h"
12 #include "stackframe.h"
13 #include "debug.h"
16 /***********************************************************************
17 * AllocSelectorArray (KERNEL.206)
19 WORD WINAPI AllocSelectorArray( WORD count )
21 WORD i, sel, size = 0;
22 ldt_entry entry;
24 if (!count) return 0;
25 for (i = FIRST_LDT_ENTRY_TO_ALLOC; i < LDT_SIZE; i++)
27 if (!IS_LDT_ENTRY_FREE(i)) size = 0;
28 else if (++size >= count) break;
30 if (i == LDT_SIZE) return 0;
31 sel = i - size + 1;
33 entry.base = 0;
34 entry.type = SEGMENT_DATA;
35 entry.seg_32bit = FALSE;
36 entry.read_only = FALSE;
37 entry.limit_in_pages = FALSE;
38 entry.limit = 1; /* avoid 0 base and limit */
40 for (i = 0; i < count; i++)
42 /* Mark selector as allocated */
43 ldt_flags_copy[sel + i] |= LDT_FLAGS_ALLOCATED;
44 LDT_SetEntry( sel + i, &entry );
46 return ENTRY_TO_SELECTOR( sel );
50 /***********************************************************************
51 * AllocSelector (KERNEL.175)
53 WORD WINAPI AllocSelector( WORD sel )
55 WORD newsel, count, i;
57 count = sel ? ((GET_SEL_LIMIT(sel) >> 16) + 1) : 1;
58 newsel = AllocSelectorArray( count );
59 TRACE(selector, "(%04x): returning %04x\n",
60 sel, newsel );
61 if (!newsel) return 0;
62 if (!sel) return newsel; /* nothing to copy */
63 for (i = 0; i < count; i++)
65 ldt_entry entry;
66 LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
67 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel) + i, &entry );
69 return newsel;
73 /***********************************************************************
74 * FreeSelector (KERNEL.176)
76 WORD WINAPI FreeSelector( WORD sel )
78 if (IS_SELECTOR_FREE(sel)) return sel; /* error */
79 SELECTOR_FreeBlock( sel, 1 );
80 return 0;
84 /***********************************************************************
85 * SELECTOR_SetEntries
87 * Set the LDT entries for an array of selectors.
89 static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size,
90 enum seg_type type, BOOL32 is32bit,
91 BOOL32 readonly )
93 ldt_entry entry;
94 WORD i, count;
96 /* The limit for the first selector is the whole */
97 /* block. The next selectors get a 64k limit. */
98 entry.base = (unsigned long)base;
99 entry.type = type;
100 entry.seg_32bit = is32bit;
101 entry.read_only = readonly;
102 entry.limit_in_pages = (size > 0x100000);
103 if (entry.limit_in_pages) entry.limit = ((size + 0xfff) >> 12) - 1;
104 else entry.limit = size - 1;
105 /* Make sure base and limit are not 0 together if the size is not 0 */
106 if (!base && !entry.limit && size) entry.limit = 1;
107 count = (size + 0xffff) / 0x10000;
108 for (i = 0; i < count; i++)
110 LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
111 entry.base += 0x10000;
112 /* Apparently the next selectors should *not* get a 64k limit. */
113 /* Can't remember where I read they should... --AJ */
114 entry.limit -= entry.limit_in_pages ? 0x10 : 0x10000;
119 /***********************************************************************
120 * SELECTOR_AllocBlock
122 * Allocate selectors for a block of linear memory.
124 WORD SELECTOR_AllocBlock( const void *base, DWORD size, enum seg_type type,
125 BOOL32 is32bit, BOOL32 readonly )
127 WORD sel, count;
129 if (!size) return 0;
130 count = (size + 0xffff) / 0x10000;
131 sel = AllocSelectorArray( count );
132 if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
133 return sel;
137 /***********************************************************************
138 * SELECTOR_MoveBlock
140 * Move a block of selectors in linear memory.
142 void SELECTOR_MoveBlock( WORD sel, const void *new_base )
144 WORD i, count = (GET_SEL_LIMIT(sel) >> 16) + 1;
146 for (i = 0; i < count; i++)
148 ldt_entry entry;
149 LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
150 entry.base = (unsigned long)new_base;
151 LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
156 /***********************************************************************
157 * SELECTOR_FreeBlock
159 * Free a block of selectors.
161 void SELECTOR_FreeBlock( WORD sel, WORD count )
163 WORD i, nextsel;
164 ldt_entry entry;
165 STACK16FRAME *frame;
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;
194 /* Clear the saved 16-bit selector */
195 frame = CURRENT_STACK16;
196 while (frame && frame->frame32)
198 if ((frame->ds >= sel) && (frame->ds < nextsel)) frame->ds = 0;
199 if ((frame->es >= sel) && (frame->es < nextsel)) frame->es = 0;
200 if ((frame->fs >= sel) && (frame->fs < nextsel)) frame->fs = 0;
201 frame = PTR_SEG_TO_LIN( frame->frame32->frame16 );
206 /***********************************************************************
207 * SELECTOR_ReallocBlock
209 * Change the size of a block of selectors.
211 WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size,
212 enum seg_type type, BOOL32 is32bit, BOOL32 readonly)
214 WORD i, oldcount, newcount;
216 if (!size) size = 1;
217 oldcount = (GET_SEL_LIMIT(sel) >> 16) + 1;
218 newcount = (size + 0xffff) >> 16;
220 if (oldcount < newcount) /* We need to add selectors */
222 /* Check if the next selectors are free */
223 if (SELECTOR_TO_ENTRY(sel) + newcount > LDT_SIZE) i = oldcount;
224 else
225 for (i = oldcount; i < newcount; i++)
226 if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel)+i)) break;
228 if (i < newcount) /* they are not free */
230 SELECTOR_FreeBlock( sel, oldcount );
231 sel = AllocSelectorArray( newcount );
233 else /* mark the selectors as allocated */
235 for (i = oldcount; i < newcount; i++)
236 ldt_flags_copy[SELECTOR_TO_ENTRY(sel)+i] |=LDT_FLAGS_ALLOCATED;
239 else if (oldcount > newcount) /* We need to remove selectors */
241 SELECTOR_FreeBlock( ENTRY_TO_SELECTOR(SELECTOR_TO_ENTRY(sel)+newcount),
242 oldcount - newcount );
244 if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
245 return sel;
249 /***********************************************************************
250 * PrestoChangoSelector (KERNEL.177)
252 WORD WINAPI PrestoChangoSelector( WORD selSrc, WORD selDst )
254 ldt_entry entry;
255 LDT_GetEntry( SELECTOR_TO_ENTRY( selSrc ), &entry );
256 entry.type ^= SEGMENT_CODE; /* toggle the executable bit */
257 LDT_SetEntry( SELECTOR_TO_ENTRY( selDst ), &entry );
258 return selDst;
262 /***********************************************************************
263 * AllocCStoDSAlias (KERNEL.170)
265 WORD WINAPI AllocCStoDSAlias( WORD sel )
267 WORD newsel;
268 ldt_entry entry;
270 newsel = AllocSelectorArray( 1 );
271 TRACE(selector, "(%04x): returning %04x\n",
272 sel, newsel );
273 if (!newsel) return 0;
274 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
275 entry.type = SEGMENT_DATA;
276 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
277 return newsel;
281 /***********************************************************************
282 * AllocDStoCSAlias (KERNEL.171)
284 WORD WINAPI AllocDStoCSAlias( WORD sel )
286 WORD newsel;
287 ldt_entry entry;
289 newsel = AllocSelectorArray( 1 );
290 TRACE(selector, "(%04x): returning %04x\n",
291 sel, newsel );
292 if (!newsel) return 0;
293 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
294 entry.type = SEGMENT_CODE;
295 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
296 return newsel;
300 /***********************************************************************
301 * LongPtrAdd (KERNEL.180)
303 void WINAPI LongPtrAdd( DWORD ptr, DWORD add )
305 ldt_entry entry;
306 LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
307 entry.base += add;
308 LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
312 /***********************************************************************
313 * GetSelectorBase (KERNEL.186)
315 DWORD WINAPI GetSelectorBase( WORD sel )
317 DWORD base = GET_SEL_BASE(sel);
319 /* if base points into DOSMEM, assume we have to
320 * return pointer into physical lower 1MB */
322 return DOSMEM_MapLinearToDos( (LPVOID)base );
326 /***********************************************************************
327 * SetSelectorBase (KERNEL.187)
329 WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
331 ldt_entry entry;
333 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
335 entry.base = (DWORD)DOSMEM_MapDosToLinear(base);
337 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
338 return sel;
342 /***********************************************************************
343 * GetSelectorLimit (KERNEL.188)
345 DWORD WINAPI GetSelectorLimit( WORD sel )
347 return GET_SEL_LIMIT(sel);
351 /***********************************************************************
352 * SetSelectorLimit (KERNEL.189)
354 WORD WINAPI SetSelectorLimit( WORD sel, DWORD limit )
356 ldt_entry entry;
357 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
358 entry.limit_in_pages = (limit >= 0x100000);
359 if (entry.limit_in_pages) entry.limit = limit >> 12;
360 else entry.limit = limit;
361 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
362 return sel;
366 /***********************************************************************
367 * SelectorAccessRights (KERNEL.196)
369 WORD WINAPI SelectorAccessRights( WORD sel, WORD op, WORD val )
371 ldt_entry entry;
372 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
373 if (op == 0) /* get */
375 return 0x01 | /* accessed */
376 0x10 | /* not system */
377 0x60 | /* DPL 3 */
378 0x80 | /* present */
379 ((entry.read_only == 0) << 1) |
380 (entry.type << 2) |
381 (entry.seg_32bit << 14) |
382 (entry.limit_in_pages << 15);
384 else /* set */
386 entry.read_only = ((val & 2) == 0);
387 entry.type = (val >> 2) & 3;
388 entry.seg_32bit = val & 0x4000;
389 entry.limit_in_pages = val & 0x8000;
390 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
391 return 0;
396 /***********************************************************************
397 * IsBadCodePtr16 (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 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
408 if (entry.type != SEGMENT_CODE) return TRUE;
409 if (OFFSETOF(lpfn) > GET_SEL_LIMIT(sel)) return TRUE;
410 return FALSE;
414 /***********************************************************************
415 * IsBadStringPtr16 (KERNEL.337)
417 BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
419 WORD sel;
420 ldt_entry entry;
422 sel = SELECTOROF(ptr);
423 if (!sel) return TRUE;
424 if (IS_SELECTOR_FREE(sel)) return TRUE;
425 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
426 if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
427 if (strlen(PTR_SEG_TO_LIN(ptr)) < size) size = strlen(PTR_SEG_TO_LIN(ptr));
428 if (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel)) return TRUE;
429 return FALSE;
433 /***********************************************************************
434 * IsBadHugeReadPtr16 (KERNEL.346)
436 BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
438 WORD sel;
439 ldt_entry entry;
441 sel = SELECTOROF(ptr);
442 if (!sel) return TRUE;
443 if (IS_SELECTOR_FREE(sel)) return TRUE;
444 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
445 if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
446 if (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel)) return TRUE;
447 return FALSE;
451 /***********************************************************************
452 * IsBadHugeWritePtr16 (KERNEL.347)
454 BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
456 WORD sel;
457 ldt_entry entry;
459 sel = SELECTOROF(ptr);
460 if (!sel) return TRUE;
461 if (IS_SELECTOR_FREE(sel)) return TRUE;
462 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
463 if ((entry.type == SEGMENT_CODE) || entry.read_only) return TRUE;
464 if (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel)) return TRUE;
465 return FALSE;
468 /***********************************************************************
469 * IsBadReadPtr16 (KERNEL.334)
471 BOOL16 WINAPI IsBadReadPtr16( SEGPTR ptr, UINT16 size )
473 return IsBadHugeReadPtr16( ptr, size );
477 /***********************************************************************
478 * IsBadWritePtr16 (KERNEL.335)
480 BOOL16 WINAPI IsBadWritePtr16( SEGPTR ptr, UINT16 size )
482 return IsBadHugeWritePtr16( ptr, size );
486 /***********************************************************************
487 * MemoryRead (TOOLHELP.78)
489 DWORD WINAPI MemoryRead( WORD sel, DWORD offset, void *buffer, DWORD count )
491 if (IS_SELECTOR_FREE(sel)) return 0;
492 if (offset > GET_SEL_LIMIT(sel)) return 0;
493 if (offset + count > GET_SEL_LIMIT(sel) + 1)
494 count = GET_SEL_LIMIT(sel) + 1 - offset;
495 memcpy( buffer, ((char *)GET_SEL_BASE(sel)) + offset, count );
496 return count;
500 /***********************************************************************
501 * MemoryWrite (TOOLHELP.79)
503 DWORD WINAPI MemoryWrite( WORD sel, DWORD offset, void *buffer, DWORD count )
505 if (IS_SELECTOR_FREE(sel)) return 0;
506 if (offset > GET_SEL_LIMIT(sel)) return 0;
507 if (offset + count > GET_SEL_LIMIT(sel) + 1)
508 count = GET_SEL_LIMIT(sel) + 1 - offset;
509 memcpy( ((char *)GET_SEL_BASE(sel)) + offset, buffer, count );
510 return count;
513 /************************************* Win95 pointer mapping functions *
517 /***********************************************************************
518 * MapSL (KERNEL32.523)
520 * Maps fixed segmented pointer to linear.
522 LPVOID WINAPI MapSL( SEGPTR sptr )
524 return (LPVOID)PTR_SEG_TO_LIN(sptr);
527 /***********************************************************************
528 * MapSLFix (KERNEL32.524)
530 * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
531 * unexpected linear address change when GlobalCompact() shuffles
532 * moveable blocks.
535 LPVOID WINAPI MapSLFix( SEGPTR sptr )
537 return (LPVOID)PTR_SEG_TO_LIN(sptr);
540 /***********************************************************************
541 * UnMapSLFixArray (KERNEL32.701)
544 void WINAPI UnMapSLFixArray( SEGPTR sptr[], INT32 length )
548 /***********************************************************************
549 * MapLS (KERNEL32.522)
551 * Maps linear pointer to segmented.
553 SEGPTR WINAPI MapLS( LPVOID ptr )
555 if (!HIWORD(ptr))
556 return (SEGPTR)ptr;
557 else
559 WORD sel = SELECTOR_AllocBlock( ptr, 0x10000, SEGMENT_DATA, FALSE, FALSE );
560 return PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
565 /***********************************************************************
566 * UnMapLS (KERNEL32.700)
568 * Free mapped selector.
570 void WINAPI UnMapLS( SEGPTR sptr )
572 if (SELECTOROF(sptr))
573 SELECTOR_FreeBlock( SELECTOROF(sptr), 1 );
576 /***********************************************************************
577 * GetThreadSelectorEntry (KERNEL32)
578 * FIXME: add #ifdef i386 for non x86
580 BOOL32 WINAPI GetThreadSelectorEntry( HANDLE32 hthread, DWORD sel,
581 LPLDT_ENTRY ldtent)
583 ldt_entry ldtentry;
585 LDT_GetEntry(SELECTOR_TO_ENTRY(sel),&ldtentry);
586 ldtent->BaseLow = ldtentry.base & 0x0000ffff;
587 ldtent->HighWord.Bits.BaseMid = (ldtentry.base & 0x00ff0000) >> 16;
588 ldtent->HighWord.Bits.BaseHi = (ldtentry.base & 0xff000000) >> 24;
589 ldtent->LimitLow = ldtentry.limit & 0x0000ffff;
590 ldtent->HighWord.Bits.LimitHi = (ldtentry.limit & 0x00ff0000) >> 16;
591 ldtent->HighWord.Bits.Dpl = 3;
592 ldtent->HighWord.Bits.Sys = 0;
593 ldtent->HighWord.Bits.Pres = 1;
594 ldtent->HighWord.Bits.Type = 0x10|(ldtentry.type << 2);
595 if (ldtentry.read_only)
596 ldtent->HighWord.Bits.Type|=0x2;
597 ldtent->HighWord.Bits.Granularity = ldtentry.limit_in_pages;
598 ldtent->HighWord.Bits.Default_Big = ldtentry.seg_32bit;
599 return TRUE;
603 /**********************************************************************
604 * SMapLS* (KERNEL32)
605 * These functions map linear pointers at [EBP+xxx] to segmented pointers
606 * and return them.
607 * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
608 * unravel them at SUnMapLS. We just store the segmented pointer there.
610 static void
611 x_SMapLS_IP_EBP_x(CONTEXT *context,int argoff) {
612 DWORD val,ptr;
614 val =*(DWORD*)(EBP_reg(context)+argoff);
615 if (val<0x10000) {
616 ptr=val;
617 *(DWORD*)(EBP_reg(context)+argoff) = 0;
618 } else {
619 ptr = MapLS((LPVOID)val);
620 *(DWORD*)(EBP_reg(context)+argoff) = ptr;
622 EAX_reg(context) = ptr;
625 REGS_ENTRYPOINT(SMapLS_IP_EBP_8) {x_SMapLS_IP_EBP_x(context,8);}
626 REGS_ENTRYPOINT(SMapLS_IP_EBP_12) {x_SMapLS_IP_EBP_x(context,12);}
627 REGS_ENTRYPOINT(SMapLS_IP_EBP_16) {x_SMapLS_IP_EBP_x(context,16);}
628 REGS_ENTRYPOINT(SMapLS_IP_EBP_20) {x_SMapLS_IP_EBP_x(context,20);}
629 REGS_ENTRYPOINT(SMapLS_IP_EBP_24) {x_SMapLS_IP_EBP_x(context,24);}
630 REGS_ENTRYPOINT(SMapLS_IP_EBP_28) {x_SMapLS_IP_EBP_x(context,28);}
631 REGS_ENTRYPOINT(SMapLS_IP_EBP_32) {x_SMapLS_IP_EBP_x(context,32);}
632 REGS_ENTRYPOINT(SMapLS_IP_EBP_36) {x_SMapLS_IP_EBP_x(context,36);}
633 REGS_ENTRYPOINT(SMapLS_IP_EBP_40) {x_SMapLS_IP_EBP_x(context,40);}
635 REGS_ENTRYPOINT(SMapLS)
637 if (EAX_reg(context)>=0x10000) {
638 EAX_reg(context) = MapLS((LPVOID)EAX_reg(context));
639 EDX_reg(context) = EAX_reg(context);
640 } else {
641 EDX_reg(context) = 0;
645 REGS_ENTRYPOINT(SUnMapLS)
647 if (EAX_reg(context)>=0x10000)
648 UnMapLS((SEGPTR)EAX_reg(context));
651 static void
652 x_SUnMapLS_IP_EBP_x(CONTEXT *context,int argoff) {
653 if (*(DWORD*)(EBP_reg(context)+argoff))
654 UnMapLS(*(DWORD*)(EBP_reg(context)+argoff));
655 *(DWORD*)(EBP_reg(context)+argoff)=0;
657 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_8) { x_SUnMapLS_IP_EBP_x(context,12); }
658 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_12) { x_SUnMapLS_IP_EBP_x(context,12); }
659 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_16) { x_SUnMapLS_IP_EBP_x(context,16); }
660 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_20) { x_SUnMapLS_IP_EBP_x(context,20); }
661 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_24) { x_SUnMapLS_IP_EBP_x(context,24); }
662 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_28) { x_SUnMapLS_IP_EBP_x(context,28); }
663 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_32) { x_SUnMapLS_IP_EBP_x(context,32); }
664 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_36) { x_SUnMapLS_IP_EBP_x(context,36); }
665 REGS_ENTRYPOINT(SUnMapLS_IP_EBP_40) { x_SUnMapLS_IP_EBP_x(context,40); }
667 /**********************************************************************
668 * AllocMappedBuffer (KERNEL32.38)
670 * This is a undocumented KERNEL32 function that
671 * SMapLS's a GlobalAlloc'ed buffer.
673 * Input: EDI register: size of buffer to allocate
674 * Output: EDI register: pointer to buffer
676 * Note: The buffer is preceeded by 8 bytes:
677 * ...
678 * edi+0 buffer
679 * edi-4 SEGPTR to buffer
680 * edi-8 some magic Win95 needs for SUnMapLS
681 * (we use it for the memory handle)
683 * The SEGPTR is used by the caller!
686 REGS_ENTRYPOINT(AllocMappedBuffer)
688 HGLOBAL32 handle = GlobalAlloc32(0, EDI_reg(context) + 8);
689 DWORD *buffer = (DWORD *)GlobalLock32(handle);
690 SEGPTR ptr = 0;
692 if (buffer)
693 if (!(ptr = MapLS(buffer + 2)))
695 GlobalUnlock32(handle);
696 GlobalFree32(handle);
699 if (!ptr)
700 EAX_reg(context) = EDI_reg(context) = 0;
701 else
703 buffer[0] = handle;
704 buffer[1] = ptr;
706 EAX_reg(context) = (DWORD) ptr;
707 EDI_reg(context) = (DWORD)(buffer + 2);
711 /**********************************************************************
712 * FreeMappedBuffer (KERNEL32.39)
714 * Free a buffer allocated by AllocMappedBuffer
716 * Input: EDI register: pointer to buffer
719 REGS_ENTRYPOINT(FreeMappedBuffer)
721 if (EDI_reg(context))
723 DWORD *buffer = (DWORD *)EDI_reg(context) - 2;
725 UnMapLS(buffer[1]);
727 GlobalUnlock32(buffer[0]);
728 GlobalFree32(buffer[0]);
732 /**********************************************************************
733 * WOWGetVDMPointer (KERNEL32.55)
734 * Get linear from segmented pointer. (MSDN lib)
736 LPVOID WINAPI WOWGetVDMPointer(DWORD vp,DWORD nrofbytes,BOOL32 protected)
738 /* FIXME: add size check too */
739 if (protected)
740 return PTR_SEG_TO_LIN(vp);
741 else
742 return DOSMEM_MapRealToLinear(vp);
745 /**********************************************************************
746 * GetVDMPointer32W (KERNEL.516)
748 LPVOID WINAPI GetVDMPointer32W(DWORD vp,DWORD mode)
750 return WOWGetVDMPointer(vp,0,mode);
753 /**********************************************************************
754 * WOWGetVDMPointerFix (KERNEL32.55)
755 * Dito, but fix heapsegment (MSDN lib)
757 LPVOID WINAPI WOWGetVDMPointerFix(DWORD vp,DWORD nrofbytes,BOOL32 protected)
759 /* FIXME: fix heapsegment */
760 return WOWGetVDMPointer(vp,nrofbytes,protected);
763 /**********************************************************************
764 * WOWGetVDMPointerUnFix (KERNEL32.56)
766 void WINAPI WOWGetVDMPointerUnfix(DWORD vp)
768 /* FIXME: unfix heapsegment */
771 /***********************************************************************
772 * UTSelectorOffsetToLinear (WIN32S16.48)
774 * rough guesswork, but seems to work (I had no "reasonable" docu)
776 LPVOID WINAPI UTSelectorOffsetToLinear(SEGPTR sptr)
778 return PTR_SEG_TO_LIN(sptr);
781 /***********************************************************************
782 * UTLinearToSelectorOffset (WIN32S16.49)
784 * FIXME: I don't know if that's the right way to do linear -> segmented
786 SEGPTR WINAPI UTLinearToSelectorOffset(LPVOID lptr)
788 return (SEGPTR)lptr;