Sat Jul 19 13:03:01 1997 Alexandre Julliard <julliard@lrc.epfl.ch> * [tools/build.c] [include/stackframe.h] Save the complete %ebp register in CallFrom16; fixes a crash with LabView reported by Andreas Mohr. * [loader/main.c] Avoid executing a built-in DLL. * [controls/static.c] Converted static window procedure to Win32. * [windows/message.c] [windows/queue.c] [include/queue.h] Hacked SendMessage functions to support inter-task messages with SendMessage32A/W. Sun Jul 13 16:55:35 1997 Bernhard Rosenkraenzer <bero@bero-online.ml.org> * [ipc/bit_array.c] Don't use bitops.h in Linux 2.1.x (these versions do not return the previous state for clear_bit and set_bit) * [ipc/shm_main_blk.c] Adapt to GLIBC's ipc_perm structure. * [memory/ldt.c] Include <asm/unistd.h> on Linux/GLIBC systems (required for _syscall3). Wed Jul 9 23:53:19 1997 David A. Cuthbert <dacut@henry.ece.cmu.edu> * [include/options.h] [files/profile.c] Added PROFILE_GetWineIniBool and PROFILE_EnumerateWineIniSection. * [include/sysmetrics.h] [include/windows.h] [windows/sysmetrics.c] All sysmetrics moved to array (no more constant macros). Added MOUSEWHEELPRESENT metric. * [include/bitmap.h] [objects/oembitmap.c] Added OBM_Init() (see also loader/main.c) and more support for Win95 bitmaps; added size info to OEM bitmaps. * [include/graphics.h] [windows/graphics.h] Added GRAPH_DrawGenericReliefRect. * [loader/main.c] Added TWEAK_Init() and TWEAK_CheckConfiguration() calls (the latter checks for invalid entries in wine.conf). * [include/debug.h] [include/stddebug.h] [include/nonclient.h] [include/tweak.h] [controls/menu.c] [misc/tweak.c] [objects/gdiobj.c] [windows/syscolor.c] [windows/nonclient.c] [BUGS] [documentation/win95look] Added tweaks for Windows 95 interface support. See documentation/win95look for more information. * [controls/edit.c] Fixed EDIT_MoveHome bug. * [misc/ver.c] Changed name of dprintf_ver_string to ver_dstring to fix problem with tools/make_debug utility. Wed Jul 9 21:31:54 1997 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de> * [objects/dib.c] Don't use palettes with dibs with biBitCount > 8. * [misc/ole2nls.c][misc/ver.c] IsValidLocale, EnumSystemLocales fixed (winhlp32.exe works) Some VerLanguage coded moved to ole2nls.c, some cleanups. * [multimedia/mcistring.c] Fixed "capabilities <dev> device type" crash (cool.exe). * [misc/main.c] SystemParametersInfo*: added stub option 41 (GETNONCLIENTMETRICS), duplicated some stuff away from SPI16 that writes 32bit vars.(one COMCTL32.DLL crash, freecell.exe) Tue Jul 8 22:40:53 1997 Morten Welinder <terra@diku.dk> * [if1632/shell32.spec] Use Windows 95's ordinals. Help wanted, inquire within. Mon Jul 7 11:20:36 1997 Philippe De Muyter <phdm@info.ucl.ac.be> * [if1632/relay.c] [if1632/user.spec] [if1632/kernel.spec] [tools/build-spec.txt] [tools/build.c] Added type 'segstr' (segmented pointer to null-terminated string) to .spec files. * [windows/user.c] [if1632/user.spec] ExitWindowsExec stub function added. Mon Jul 7 01:18:25 1997 U. Bonnes <bon@elektron.ikp.physik.th-darmstadt.de> * [files/file.c] [include/winbase.h] [if1632/kernel32.spec] Implement MoveFileEx32, some enhancement for Movefile32. Sat Jul 5 18:13:48 1997 Bruce Milner <Bruce.Milner@genetics.utah.edu. * [files/file.c] [if1632/kernel32.spec] [include/winerror.h] [msdos/int21.c] [win32/file.c] Add LockFile/UnlockFile implementation. Add back in int21 func(0x5c) Record locking functions. * [files/file.c] Fixed bug with OF_REOPEN in FILE_DoOpenFile. Fri Jul 4 12:00:00 1997 Henrik Olsen <Henrik.Olsen@iaeste.dk> * [misc/ole2nls.c] [programs/progman/Da.rc] [programs/winhelp/Da.rc] [resources/sysres_Da.rc] Added/updated Danish language support. Thu Jul 3 13:04:20 1997 Claus Fischer <fischer@iue.tuwien.ac.at> * [files/dos_fs.c] Properly implemented DOSFS_UnixTimeToFileTime and DOSFS_FileTimeToUnixTime. * [documentation/wine.texinfo] First version of texinfo documentation.
504 lines
14 KiB
C
504 lines
14 KiB
C
/*
|
|
* Selector manipulation functions
|
|
*
|
|
* Copyright 1995 Alexandre Julliard
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "windows.h"
|
|
#include "ldt.h"
|
|
#include "miscemu.h"
|
|
#include "selectors.h"
|
|
#include "stackframe.h"
|
|
#include "stddebug.h"
|
|
#include "debug.h"
|
|
|
|
|
|
#define FIRST_LDT_ENTRY_TO_ALLOC 17
|
|
|
|
|
|
/***********************************************************************
|
|
* AllocSelectorArray (KERNEL.206)
|
|
*/
|
|
WORD AllocSelectorArray( WORD count )
|
|
{
|
|
WORD i, size = 0;
|
|
|
|
if (!count) return 0;
|
|
for (i = FIRST_LDT_ENTRY_TO_ALLOC; i < LDT_SIZE; i++)
|
|
{
|
|
if (!IS_LDT_ENTRY_FREE(i)) size = 0;
|
|
else if (++size >= count) break;
|
|
}
|
|
if (i == LDT_SIZE) return 0;
|
|
/* Mark selector as allocated */
|
|
while (size--) ldt_flags_copy[i--] |= LDT_FLAGS_ALLOCATED;
|
|
return ENTRY_TO_SELECTOR( i + 1 );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* AllocSelector (KERNEL.175)
|
|
*/
|
|
WORD AllocSelector( WORD sel )
|
|
{
|
|
WORD newsel, count, i;
|
|
|
|
count = sel ? ((GET_SEL_LIMIT(sel) >> 16) + 1) : 1;
|
|
newsel = AllocSelectorArray( count );
|
|
dprintf_selector( stddeb, "AllocSelector(%04x): returning %04x\n",
|
|
sel, newsel );
|
|
if (!newsel) return 0;
|
|
if (!sel) return newsel; /* nothing to copy */
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
ldt_entry entry;
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
|
|
LDT_SetEntry( SELECTOR_TO_ENTRY(newsel) + i, &entry );
|
|
}
|
|
return newsel;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* FreeSelector (KERNEL.176)
|
|
*/
|
|
WORD FreeSelector( WORD sel )
|
|
{
|
|
if (IS_SELECTOR_FREE(sel)) return sel; /* error */
|
|
SELECTOR_FreeBlock( sel, 1 );
|
|
return 0;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SELECTOR_SetEntries
|
|
*
|
|
* Set the LDT entries for an array of selectors.
|
|
*/
|
|
static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size,
|
|
enum seg_type type, BOOL32 is32bit,
|
|
BOOL32 readonly )
|
|
{
|
|
ldt_entry entry;
|
|
WORD i, count;
|
|
|
|
/* The limit for the first selector is the whole */
|
|
/* block. The next selectors get a 64k limit. */
|
|
entry.base = (unsigned long)base;
|
|
entry.type = type;
|
|
entry.seg_32bit = is32bit;
|
|
entry.read_only = readonly;
|
|
entry.limit_in_pages = (size > 0x100000);
|
|
if (entry.limit_in_pages) entry.limit = ((size + 0xfff) >> 12) - 1;
|
|
else entry.limit = size - 1;
|
|
/* Make sure base and limit are not 0 together if the size is not 0 */
|
|
if (!base && !entry.limit && size) entry.limit = 1;
|
|
count = (size + 0xffff) / 0x10000;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
|
|
entry.base += 0x10000;
|
|
/* Apparently the next selectors should *not* get a 64k limit. */
|
|
/* Can't remember where I read they should... --AJ */
|
|
entry.limit -= entry.limit_in_pages ? 0x10 : 0x10000;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SELECTOR_AllocBlock
|
|
*
|
|
* Allocate selectors for a block of linear memory.
|
|
*/
|
|
WORD SELECTOR_AllocBlock( const void *base, DWORD size, enum seg_type type,
|
|
BOOL32 is32bit, BOOL32 readonly )
|
|
{
|
|
WORD sel, count;
|
|
|
|
if (!size) return 0;
|
|
count = (size + 0xffff) / 0x10000;
|
|
sel = AllocSelectorArray( count );
|
|
if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
|
|
return sel;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SELECTOR_FreeBlock
|
|
*
|
|
* Free a block of selectors.
|
|
*/
|
|
void SELECTOR_FreeBlock( WORD sel, WORD count )
|
|
{
|
|
WORD i, nextsel;
|
|
ldt_entry entry;
|
|
STACK16FRAME *frame;
|
|
|
|
dprintf_selector( stddeb, "SELECTOR_FreeBlock(%04x,%d)\n", sel, count );
|
|
sel &= ~(__AHINCR - 1); /* clear bottom bits of selector */
|
|
nextsel = sel + (count << __AHSHIFT);
|
|
memset( &entry, 0, sizeof(entry) ); /* clear the LDT entries */
|
|
for (i = SELECTOR_TO_ENTRY(sel); count; i++, count--)
|
|
{
|
|
LDT_SetEntry( i, &entry );
|
|
ldt_flags_copy[i] &= ~LDT_FLAGS_ALLOCATED;
|
|
}
|
|
|
|
/* Clear the saved 16-bit selector */
|
|
frame = CURRENT_STACK16;
|
|
while (frame)
|
|
{
|
|
if ((frame->ds >= sel) && (frame->ds < nextsel)) frame->ds = 0;
|
|
if ((frame->es >= sel) && (frame->es < nextsel)) frame->es = 0;
|
|
frame = PTR_SEG_TO_LIN( frame->saved_ss_sp );
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SELECTOR_ReallocBlock
|
|
*
|
|
* Change the size of a block of selectors.
|
|
*/
|
|
WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size,
|
|
enum seg_type type, BOOL32 is32bit, BOOL32 readonly)
|
|
{
|
|
WORD i, oldcount, newcount;
|
|
|
|
if (!size) size = 1;
|
|
oldcount = (GET_SEL_LIMIT(sel) >> 16) + 1;
|
|
newcount = (size + 0xffff) >> 16;
|
|
|
|
if (oldcount < newcount) /* We need to add selectors */
|
|
{
|
|
/* Check if the next selectors are free */
|
|
if (SELECTOR_TO_ENTRY(sel) + newcount > LDT_SIZE) i = oldcount;
|
|
else
|
|
for (i = oldcount; i < newcount; i++)
|
|
if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel)+i)) break;
|
|
|
|
if (i < newcount) /* they are not free */
|
|
{
|
|
SELECTOR_FreeBlock( sel, oldcount );
|
|
sel = AllocSelectorArray( newcount );
|
|
}
|
|
else /* mark the selectors as allocated */
|
|
{
|
|
for (i = oldcount; i < newcount; i++)
|
|
ldt_flags_copy[SELECTOR_TO_ENTRY(sel)+i] |=LDT_FLAGS_ALLOCATED;
|
|
}
|
|
}
|
|
else if (oldcount > newcount) /* We need to remove selectors */
|
|
{
|
|
SELECTOR_FreeBlock( ENTRY_TO_SELECTOR(SELECTOR_TO_ENTRY(sel)+newcount),
|
|
oldcount - newcount );
|
|
}
|
|
if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
|
|
return sel;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* PrestoChangoSelector (KERNEL.177)
|
|
*/
|
|
WORD PrestoChangoSelector( WORD selSrc, WORD selDst )
|
|
{
|
|
ldt_entry entry;
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY( selSrc ), &entry );
|
|
entry.type ^= SEGMENT_CODE; /* toggle the executable bit */
|
|
LDT_SetEntry( SELECTOR_TO_ENTRY( selDst ), &entry );
|
|
return selDst;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* AllocCStoDSAlias (KERNEL.170)
|
|
*/
|
|
WORD AllocCStoDSAlias( WORD sel )
|
|
{
|
|
WORD newsel;
|
|
ldt_entry entry;
|
|
|
|
newsel = AllocSelectorArray( 1 );
|
|
dprintf_selector( stddeb, "AllocCStoDSAlias(%04x): returning %04x\n",
|
|
sel, newsel );
|
|
if (!newsel) return 0;
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
entry.type = SEGMENT_DATA;
|
|
LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
|
|
return newsel;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* AllocDStoCSAlias (KERNEL.171)
|
|
*/
|
|
WORD AllocDStoCSAlias( WORD sel )
|
|
{
|
|
WORD newsel;
|
|
ldt_entry entry;
|
|
|
|
newsel = AllocSelectorArray( 1 );
|
|
dprintf_selector( stddeb, "AllocDStoCSAlias(%04x): returning %04x\n",
|
|
sel, newsel );
|
|
if (!newsel) return 0;
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
entry.type = SEGMENT_CODE;
|
|
LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
|
|
return newsel;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* LongPtrAdd (KERNEL.180)
|
|
*/
|
|
void LongPtrAdd( DWORD ptr, DWORD add )
|
|
{
|
|
ldt_entry entry;
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
|
|
entry.base += add;
|
|
LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* GetSelectorBase (KERNEL.186)
|
|
*/
|
|
DWORD GetSelectorBase( WORD sel )
|
|
{
|
|
DWORD base = GET_SEL_BASE(sel);
|
|
|
|
/* if base points into DOSMEM, assume we have to
|
|
* return pointer into physical lower 1MB */
|
|
|
|
return DOSMEM_MapLinearToDos( (LPVOID)base );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SetSelectorBase (KERNEL.187)
|
|
*/
|
|
WORD SetSelectorBase( WORD sel, DWORD base )
|
|
{
|
|
ldt_entry entry;
|
|
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
|
|
entry.base = (DWORD)DOSMEM_MapDosToLinear(base);
|
|
|
|
LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
return sel;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* GetSelectorLimit (KERNEL.188)
|
|
*/
|
|
DWORD GetSelectorLimit( WORD sel )
|
|
{
|
|
return GET_SEL_LIMIT(sel);
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SetSelectorLimit (KERNEL.189)
|
|
*/
|
|
WORD SetSelectorLimit( WORD sel, DWORD limit )
|
|
{
|
|
ldt_entry entry;
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
entry.limit_in_pages = (limit >= 0x100000);
|
|
if (entry.limit_in_pages) entry.limit = limit >> 12;
|
|
else entry.limit = limit;
|
|
LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
return sel;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SelectorAccessRights (KERNEL.196)
|
|
*/
|
|
WORD SelectorAccessRights( WORD sel, WORD op, WORD val )
|
|
{
|
|
ldt_entry entry;
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
if (op == 0) /* get */
|
|
{
|
|
return 0x01 | /* accessed */
|
|
0x10 | /* not system */
|
|
0x60 | /* DPL 3 */
|
|
0x80 | /* present */
|
|
((entry.read_only == 0) << 1) |
|
|
(entry.type << 2) |
|
|
(entry.seg_32bit << 14) |
|
|
(entry.limit_in_pages << 15);
|
|
}
|
|
else /* set */
|
|
{
|
|
entry.read_only = ((val & 2) == 0);
|
|
entry.type = (val >> 2) & 3;
|
|
entry.seg_32bit = val & 0x4000;
|
|
entry.limit_in_pages = val & 0x8000;
|
|
LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* IsBadCodePtr16 (KERNEL.336)
|
|
*/
|
|
BOOL16 IsBadCodePtr16( SEGPTR lpfn )
|
|
{
|
|
WORD sel;
|
|
ldt_entry entry;
|
|
|
|
sel = SELECTOROF(lpfn);
|
|
if (!sel) return TRUE;
|
|
if (IS_SELECTOR_FREE(sel)) return TRUE;
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
if (entry.type != SEGMENT_CODE) return TRUE;
|
|
if (OFFSETOF(lpfn) > entry.limit) return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* IsBadStringPtr16 (KERNEL.337)
|
|
*/
|
|
BOOL16 IsBadStringPtr16( SEGPTR ptr, UINT16 size )
|
|
{
|
|
WORD sel;
|
|
ldt_entry entry;
|
|
|
|
sel = SELECTOROF(ptr);
|
|
if (!sel) return TRUE;
|
|
if (IS_SELECTOR_FREE(sel)) return TRUE;
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
|
|
if (strlen(PTR_SEG_TO_LIN(ptr)) < size) size = strlen(PTR_SEG_TO_LIN(ptr));
|
|
if (OFFSETOF(ptr) + size - 1 > entry.limit) return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* IsBadHugeReadPtr16 (KERNEL.346)
|
|
*/
|
|
BOOL16 IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
|
|
{
|
|
WORD sel;
|
|
ldt_entry entry;
|
|
|
|
sel = SELECTOROF(ptr);
|
|
if (!sel) return TRUE;
|
|
if (IS_SELECTOR_FREE(sel)) return TRUE;
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
|
|
if (OFFSETOF(ptr) + size - 1 > entry.limit) return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* IsBadHugeWritePtr16 (KERNEL.347)
|
|
*/
|
|
BOOL16 IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
|
|
{
|
|
WORD sel;
|
|
ldt_entry entry;
|
|
|
|
sel = SELECTOROF(ptr);
|
|
if (!sel) return TRUE;
|
|
if (IS_SELECTOR_FREE(sel)) return TRUE;
|
|
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
|
|
if ((entry.type == SEGMENT_CODE) || entry.read_only) return TRUE;
|
|
if (OFFSETOF(ptr) + size - 1 > entry.limit) return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* IsBadReadPtr16 (KERNEL.334)
|
|
*/
|
|
BOOL16 IsBadReadPtr16( SEGPTR ptr, UINT16 size )
|
|
{
|
|
return IsBadHugeReadPtr16( ptr, size );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* IsBadWritePtr16 (KERNEL.335)
|
|
*/
|
|
BOOL16 IsBadWritePtr16( SEGPTR ptr, UINT16 size )
|
|
{
|
|
return IsBadHugeWritePtr16( ptr, size );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* MemoryRead (TOOLHELP.78)
|
|
*/
|
|
DWORD MemoryRead( WORD sel, DWORD offset, void *buffer, DWORD count )
|
|
{
|
|
if (IS_SELECTOR_FREE(sel)) return 0;
|
|
if (offset > GET_SEL_LIMIT(sel)) return 0;
|
|
if (offset + count > GET_SEL_LIMIT(sel) + 1)
|
|
count = GET_SEL_LIMIT(sel) + 1 - offset;
|
|
memcpy( buffer, ((char *)GET_SEL_BASE(sel)) + offset, count );
|
|
return count;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* MemoryWrite (TOOLHELP.79)
|
|
*/
|
|
DWORD MemoryWrite( WORD sel, DWORD offset, void *buffer, DWORD count )
|
|
{
|
|
if (IS_SELECTOR_FREE(sel)) return 0;
|
|
if (offset > GET_SEL_LIMIT(sel)) return 0;
|
|
if (offset + count > GET_SEL_LIMIT(sel) + 1)
|
|
count = GET_SEL_LIMIT(sel) + 1 - offset;
|
|
memcpy( ((char *)GET_SEL_BASE(sel)) + offset, buffer, count );
|
|
return count;
|
|
}
|
|
|
|
/************************************* Win95 pointer mapping functions *
|
|
*
|
|
* NOTE: MapSLFix and UnMapSLFixArray are probably needed to prevent
|
|
* unexpected linear address change when GlobalCompact() shuffles
|
|
* moveable blocks.
|
|
*/
|
|
|
|
/***********************************************************************
|
|
* MapSL (KERNEL32.662)
|
|
*
|
|
* Maps fixed segmented pointer to linear.
|
|
*/
|
|
LPVOID MapSL( SEGPTR sptr )
|
|
{
|
|
return (LPVOID)PTR_SEG_TO_LIN(sptr);
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* MapLS (KERNEL32.679)
|
|
*
|
|
* Maps linear pointer to segmented.
|
|
*/
|
|
SEGPTR MapLS( LPVOID ptr )
|
|
{
|
|
WORD sel = SELECTOR_AllocBlock( ptr, 0x10000, SEGMENT_DATA, FALSE, FALSE );
|
|
return PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* UnMapLS (KERNEL32.680)
|
|
*
|
|
* Free mapped selector.
|
|
*/
|
|
void UnMapLS( SEGPTR sptr )
|
|
{
|
|
if (!__winelib) SELECTOR_FreeBlock( SELECTOROF(sptr), 1 );
|
|
}
|