wine/memory/selector.c
Alexandre Julliard d30dfd24d6 Release 980927
Sun Sep 27 14:25:38 1998  Petter Reinholdtsen <pere@td.org.uit.no>

	* [files/drive.c]
	Make sure GetDriveType32A() handles param NULL.  Added some
	doc on function.

Sun Sep 27 14:07:26 1998  Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>

	* [controls/edit.c] [windows/win.c]
	Don't call SetWindowLong() in EDIT_WM_NCREATE.
	Fix SetWindowLong(GWL_[EX]STYLE) to work for 16bit windows. Remove
	UpdateWindow() call. 

Sun Sep 27 13:41:22 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [scheduler/*.c] [server/event.c] [server/mutex.c]
	  [server/semaphore.c]
	Implemented server-side synchronisation objects.

Sun Sep 27 01:13:35 1998  Alex Priem <alexp@sci.kun.nl>

	* [dlls/comctl32/treeview.c] [include/treeview.h] [include/comctl.h]
	Treeview implementation.

	* [dlls/comctl32/trackbar.c] [include/trackbar.h] 
	Trackbar implementation.

Sat Sep 26 20:49:13 1998  Ulrich Weigand <weigand@informatik.uni-erlangen.de>

	* [if1632/thunk.c] [tools/build.c] [win32/kernel32.c]
	Bugfix: several problems with flat thunks fixed.

	* [memory/selector.c]
	Bugfix: IsBad...Ptr16 didn't work for limit_in_pages segments.

	* [scheduler/thread.c]
	Bugfix: CreateThread: Allow id parameter == NULL.

	* [objects/gdiobj.c]
	Bugfix: IsGDIObject: Return correct object type for stock objects.

	* [msdos/dpmi.c]
	Bugfix: fixed typo in INT_DoRealModeInt.

	* [msdos/int21.c]
	Bugfix: int21 READ *must* use WIN16_hread, not _hread16.

	* [if1632/kernel.spec] [if1632/dummy.c] [if1632/thunk.c]
	  [loader/ne/module.c] [scheduler/event.c] [scheduler/synchro.c]
	  [scheduler/thread.c] [win32/kernel32.c] [win32/ordinals.c]
	Added names/stubs for all undocumented KERNEL routines (Win95).
	Added the following undoc. 16-bit equivalents to Win32 routines:
	KERNEL.441-443,449-453,456-462,471-476,479-486,488.
	Added stubs for some other KERNEL routines.

	* [memory/heap.c] [memory/global.c] [include/global.h]
	Implemented Local32... 32-bit local heap routines (KERNEL.208-215, 229).

	* [miscemu/instr.c] [loader/module.c] [include/module.h]
	Implemented __GP fault handling and HasGPHandler (KERNEL.338).

	* [misc/error.c]
	Implemented LogParamErrorRegs (KERNEL.327).

	* [loader/task.c] [include/windows.h]
	Implemented GetCodeInfo (KERNEL.104).

	* [loader/task.c] [scheduler/thread.c] [include/thread.h]
	Implemented [GS]etThreadQueue and [GS]etFastQueue (KERNEL.463/4, 624/5).

	* [if1632/gdi.spec] [objects/dc.c] [objects/dib.c]
	  [objects/bitmap.c] [include/windows.h]
	Bugfix: fixed wrong parameter for CreateDIBSection16.
	Added [GS]etDIBColorTable16, stub for GetBoundsRect16.
	Partially implemented BITMAP_GetObject16 for DIBs.

	* [if1632/gdi.spec] [relay32/gdi32.spec] [objects/palette.c]
	Added some GDI stubs.

	* [if1632/Makefile.in] [if1632/display.spec] [if1632/mouse.spec]
	  [if1632/keyboard.spec] [if1632/builtin.c] [windows/keyboard.c]
	Added some stubs for Win16 drivers: KEYBOARD, MOUSE, DISPLAY.

	* [if1632/wprocs.spec] [msdos/vxd.c]
	Added some stubs for VxDs: VMM, ConfigMG, TimerAPI.

	* [msdos/int2f.c]
	Added some stubs for real-mode network drivers.

Sat Sep 26 18:18:18 1998  Marcus Meissner <marcus@jet.franken.de>

	* [configure.in]
	Merged in some more of the FreeBSD ports/emulators/wine patches. 
	(Maintainer(s) of this port: You can just submit these
	patches to Alexandre directly.)

	 * [loader/pe_image.c]
	Check filesize of image against size derived from header
	to spot truncated executeables without crashing.

	* [files/directory.c]
	Set envvar "COMSPEC". One win32(!!) program crashes without it.

	* [multimedia/mmio.c]
	Added mmioSetInfo32.

	* [include/file.h]
	Return STD_ERROR_HANDLE for AUX and PRT dos handles.

	* [loader/module.c]
	Handle executeables with spaces in their names a bit better in
	CreateProcess.

	* [relay32/msvfw32.spec][if1632/msvideo.spec][multimedia/msvideo.c][include/vfw.h]
	Started on MS Video support (can load Win32 ICMs).

	* [tools/testrun]
	A bit smarter use of ps.

	* [memory/virtual.c]
	Report PAGE_GUARDed pages as PAGE_PROTECTED (AutoCAD LT R17 fails
	without that check (since Win95 doesn't know about PAGE_GUARD)).

Sat Sep 26 15:04:05 1998  Ove Kaaven <ovek@arcticnet.no>

	* [include/miscemu.h] [if1632/builtin.c] [loader/task.c]
	  [miscemu/instr.c] [msdos/dpmi.c] [msdos/int21.c]
	  [msdos/interrupts.c] [windows/user.c]
	INT_[S|G]etHandler was renamed to INT_[S|G]etPMHandler.
	Added handlers to deal with real-mode interrupts; DOS
	programs are now able to hook real-mode interrupts.

	* [loader/dos/module.c] [msdos/dosmem.c] [msdos/int21.c]
	Moved real-mode interrupt table initialization to
	msdos/dosmem.c, and made new V86 tasks get a full copy
	of the existing "system memory" instead of almost empty
	space. Misc fixes.

	* [include/dosexe.h] [loader/dos/module.c] [msdos/dpmi.c]
	  [msdos/int2f.c]
	First shot at letting DOS programs start up DPMI (but DPMI
	is still disabled for DOS programs, for pkunzip's sake).

	* [include/debugger.h] [debugger/break.c] [debugger/dbg.y]
	  [debugger/registers.c] [debugger/memory.c] [debugger/info.c]
	  [loader/dos/dosvm.c]
	First shot at making Wine's debugger work for DOS programs.
	The -debug flag works, as do "nexti" and "stepi".

Sat Sep 26 13:13:13 1998  Juergen Schmied <juergen.schmied@metronet.de>

	* [dlls/shell32/dataobject.c]
	New classes IEnumFORMATETC implemented, IDataObject stubs.
	
	* [dlls/shell32/*.*][relay32/shell32.spec]
	Bugfixes.
	New: ICM_InsertItem(), ILCreateFromPath().
	Implemented: ILCloneFirst().
	Stubs: ILIsEqual(), ILFindChild(), SHLogILFromFSIL(),
	  PathMatchSpec(), PathIsExe().
	Changed: ILGetSize(), _ILIsDesktop(), PathCombine().

	* [include/shlobj.h]
	New SHLGUID's
	New structures: DVTARGETDEVICE32, STGMEDIUM32, FORMATETC32,
	CLIPFORMAT32.
	New interfaces: IEnumFORMATETC, IDataObject, ICommDlgBrowser
	IDockingWindowFrame, IServiceProvider.

	* [dlls/shell32/folders.c]
	Stubs for IShellLink.

	* [loader/resource.c]
	Small fixes.

	* [misc/crtdll.c][relay32/crtdll.spec]
	New __dllonexit().

	* [windows/message.c]
	SendNotifyMessageA, SendMessageCallBack32A half implemented.

	* [controls/edit.c]
	EDIT_WM_SetText set EF_UPDATE flag not for ES_MULTILINE.

	* [files/file.c]
	Handling of fileposition fixed.

Fri Sep 25 18:13:30 1998  Patrik Stridvall <ps@leissner.se>

	* [include/windows.h] [include/wintypes.h]
	  [ole/ole2nls.h] [relay32/kernel32.spec]
	Implemented EnumDateFormats and EnumTimeFormats.
	Only adds US English support.

	* [Makefile.in] [configure.in] 
	  [dlls/Makefile.in] [dlls/psapi/Makefile.in] 
	  [dlls/psapi/psapi_main.c] 
	New files to implement stubs for PSAPI.DLL (NT only).

	* [relay32/Makefile.in] [relay32/builtin32.c] 
	  [relay32/psapi.spec]
	New spec file for PSAPI.DLL (NT only).

	* [scheduler/handle.c]
	HANDLE_GetObjPtr should only interpret the pseudo handles as the
	current thread or the current process if a thread or a process is
	requested.

	* [include/winversion.h] [misc/version.c]
	Adds the global function VERSION_GetVersion() so functions can
	have different behavior depending on the -winver flag.

	* [include/oledlg.h] [ole/oledlg.c]
	Minor fixes. 

	* [windows/winproc.c]
	Minor changes.

	* [include/imm.h] [misc/imm.c]
	Now returns correct values under both Windows 95 and NT 4.0.

Thu Sep 24 22:11:44 1998  Kristian Nielsen  <kristian.nielsen@risoe.dk>

	* [configure.in] [include/acconfig.h] [include/thread.h]
	  [scheduler/sysdeps.c]
	Autoconfig test for non-reentrant libc.

Wed Sep 23 19:52:12 1998  Matthew Becker <mbecker@glasscity.net>

	* [*/*.c]
	Miscellaneous documentation updates and debugging output 
	standardizations.

	* [objects/clipping.c]
	Added ExtSelectClipRgn.

Wed Sep 23 00:03:28 EDT 1998  Pete Ratzlaff <pratzlaff@cfa.harvard.edu>

	* [include/windows.h] [if1632/user.spec] [relay32/user32.spec]
	  [windows/keyboard.c]
	Added, marginally implemented, GetKeyboardLayoutName().
	Only returns US English keyboard name.

Tue Sep 22 16:32:41 1998  Marcel Baur <mbaur@iiic.ethz.ch>

	* [programs/control/*]
	New Winelib application.

Mon Sep 21 00:29:18 1998  Peter Hunnisett <hunnise@nortel.ca>

	* [include/dplay.h][multimedia/dplay.c][ole/compobj.c]
	Added all DirectPlayLobby interfaces and enhanced DirectPlay
	and DirectPlayLobby support. Still not all that much. Useful
	enough if you just need to start a program, don't try any
	real dplay/lobby stuff.

	* [documentation/status/directplay]
	Added a very little bit.

	* [graphics/ddraw.c]
	- Call to SetWindowLong32A wasn't working because there was no
	  memory set aside when the window class was registered.
	- Fixed some xlib reference counting and change the behaviour
	  of DirectDrawSurface3_SetPalette to mimic observed behaviour
	  (palette is associated will all backbuffers)
	- Also stored all palette colour fields and spit back our saved
	  colour fields rather than query X for them.
	- Added plenty of AddRef and Release traces.
	- Added Xlib support for using -desktop option.
	- Fixed Xlib message handling. Messages weren't being passed to
	  the application. Fixes mouse movements in some xlib DDraw games.
	- Added a few stubs.

	* [windows/win.c][include/winerror.h]
	Fixed up some error handling in WIN_SetWindowLong. SetLastError
	wasn't being used. Could cause problems with 0 return codes.
	Added new error in winerror (1400).

	* [AUTHORS] [include/authors.h]
	Added myself as a Wine author.

Sun Sep 20 21:22:44 1998  Alexander Larsson  <alla@lysator.liu.se>

	* [loader/module.c]
	Changed GetModuleFileName32A so that is returns the
	long version of the filename. Note that just the name
	is long, not the directories.

Sat Sep 19 20:05:30 1998 Per Ångström <pang@mind.nu> 

	* [controls/menu.c]
	Made a couple of fixes to make life easier for applications that alter
	their menus at runtime.

	* [windows/defdlg.c]
	Removed the cast of the return value from dialog procedures to a 16-bit
	bool. The return value needs to retain all its 32 bits, since it is not 
	always a bool, such as when responding to the WM_NCHITTEST message.

Fri Sep 18 11:30:38 1998  Sergey Turchanov <turchanov@usa.net>

	* [loader/resource.c]
	Fixed very funny bug (though gravely affecting further excecution)
	with FindResource[Ex]32 functions.

	* [include/multimon.h] [windows/multimon.c] [relay32/user32.spec]
	  [include/windows.h] [windows/sysmetrics.c]
	Default implementation for Multimonitor API.

	* [include/windows.h] [windows/winpos.c]
	Fixed incorrect declaration (and behaviour) of GetWindowRect32.

Wed Sep 16 10:21:15 1998  Gerard Patel <G.Patel@Wanadoo.fr>

	* [controls/edit.c]
	Fixed EDIT_EM_GetLine to use correctly length of lines.

Tue Sep 15 20:40:16 1998  Eric Kohl <ekohl@abo.rhein-zeitung.de>

	* [misc/tweak.c][include/tweak.h][controls/menu.c]
	Replaced the tweak graphic routines by calls to DrawEdge32().

	* [misc/tweak.c][include/tweak.h][documentation/win95look]
	  [wine.ini][*/*]
	Changed "look and feel" selection. Allows Win3.1, Win95 and
	Win98 (no GUI code implemented) look and feel.

	* [dlls/comctl32/header.c][include/header.h][include/commctrl.h]
	Started callback item support and did some minor improvements.

	* [dlls/comctl32/imagelist.c]
	Fixed bug in transparent image display.
	ImageList_GetIcon is still buggy :-(

	* [dlls/comctl32/toolbar.c]
	Fixed button drawing (partial hack).

	* [dlls/comctl32/commctrl.c]
	Fixed MenuHelp().

	* [controls/button.c]
	Added 3d effect for groupbox.

	* [windows/msgbox.c]
	Added font support for message boxes.

	* [windows/nonclient.c]
	Fixed window moving bug.

	* [dlls/comctl32/*.c]
	Various improvements.

	* [dlls/comctl32/listview.c][dlls/comctl32/rebar.c]
	  [include/commctrl.h]
	More messages.

	* [windows/syscolor.c][include/windows.h]
	Introduced new Win98 system colors.

Tue Sep 15 18:29:45 1998 Wesley Filardo <eightknots@aol.com>

	* [files/profile.c]
	Added support in PROFILE_LoadWineIni for -config option

	* [misc/main.c] [include/options.h]
	Added -config option.

Tue Sep 15 18:22:26 1998  Petter Reinholdtsen <pere@td.org.uit.no>

	* [documentation/Makefile.in]
	Make sure directory exists before installing into it.

Tue Sep 15 01:47:33 1998  Pablo Saratxaga <pablo.sarachaga@ping.be>

	* [ole/nls/*] [ole/ole2nls.c] [include/winnls.h]
	Fixed a few errors and completed some NLS files.

Mon Sep 14 01:23:45 1998  Joseph Pranevich <knight@baltimore.wwaves.com>

	* [include/miscemu.h] [msdos/interrupts.c]
	Removed a compilation warning, added INT 25 to the list of interrupts
	callable from DOS applications, added a debug message when unsupported
	interrupts are used.

Sun Sep 13 19:55:22 1998  Lawson Whitney <lawson_whitney@juno.com>

	* [if1632/relay.c]
	CallProcEx32W should not reverse arguments.

Sun Aug 17 21:18:12 1998  Eric Pouech  <eric.pouech@lemel.fr>

	* [multimedia/midi.c] [multimedia/init.c] [multimedia/mmsys.c] 
	  [include/multimedia.h] [include/mmsystem.h] 
	  [multimedia/Makefile.in] [multimedia/midipatch.c]
	  [if1632/multimedia.spec]
	Made MIDI input and output functional on OSS capable systems.

	* [multimedia/timer.c]
	Changes to trigger callbacks at the accurate pace even when
	fake timers are used.
1998-09-27 18:28:36 +00:00

789 lines
23 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 "debug.h"
/***********************************************************************
* AllocSelectorArray (KERNEL.206)
*/
WORD WINAPI AllocSelectorArray( WORD count )
{
WORD i, sel, size = 0;
ldt_entry entry;
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;
sel = i - size + 1;
entry.base = 0;
entry.type = SEGMENT_DATA;
entry.seg_32bit = FALSE;
entry.read_only = FALSE;
entry.limit_in_pages = FALSE;
entry.limit = 1; /* avoid 0 base and limit */
for (i = 0; i < count; i++)
{
/* Mark selector as allocated */
ldt_flags_copy[sel + i] |= LDT_FLAGS_ALLOCATED;
LDT_SetEntry( sel + i, &entry );
}
return ENTRY_TO_SELECTOR( sel );
}
/***********************************************************************
* AllocSelector (KERNEL.175)
*/
WORD WINAPI AllocSelector( WORD sel )
{
WORD newsel, count, i;
count = sel ? ((GET_SEL_LIMIT(sel) >> 16) + 1) : 1;
newsel = AllocSelectorArray( count );
TRACE(selector, "(%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 WINAPI 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_MoveBlock
*
* Move a block of selectors in linear memory.
*/
void SELECTOR_MoveBlock( WORD sel, const void *new_base )
{
WORD i, count = (GET_SEL_LIMIT(sel) >> 16) + 1;
for (i = 0; i < count; i++)
{
ldt_entry entry;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
entry.base = (unsigned long)new_base;
LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
}
}
/***********************************************************************
* SELECTOR_FreeBlock
*
* Free a block of selectors.
*/
void SELECTOR_FreeBlock( WORD sel, WORD count )
{
WORD i, nextsel;
ldt_entry entry;
STACK16FRAME *frame;
TRACE(selector, "(%04x,%d)\n", sel, count );
sel &= ~(__AHINCR - 1); /* clear bottom bits of selector */
nextsel = sel + (count << __AHSHIFT);
#ifdef __i386__
{
/* Check if we are freeing current %fs or %gs selector */
WORD fs, gs;
GET_FS(fs);
if ((fs >= sel) && (fs < nextsel))
{
WARN(selector, "Freeing %%fs selector (%04x), not good.\n", fs );
SET_FS( 0 );
}
GET_GS(gs);
if ((gs >= sel) && (gs < nextsel)) SET_GS( 0 );
}
#endif /* __i386__ */
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 && frame->frame32)
{
if ((frame->ds >= sel) && (frame->ds < nextsel)) frame->ds = 0;
if ((frame->es >= sel) && (frame->es < nextsel)) frame->es = 0;
if ((frame->fs >= sel) && (frame->fs < nextsel)) frame->fs = 0;
frame = PTR_SEG_TO_LIN( frame->frame32->frame16 );
}
}
/***********************************************************************
* 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 WINAPI 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 WINAPI AllocCStoDSAlias( WORD sel )
{
WORD newsel;
ldt_entry entry;
newsel = AllocSelectorArray( 1 );
TRACE(selector, "(%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 WINAPI AllocDStoCSAlias( WORD sel )
{
WORD newsel;
ldt_entry entry;
newsel = AllocSelectorArray( 1 );
TRACE(selector, "(%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 WINAPI 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 WINAPI 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 WINAPI 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 WINAPI GetSelectorLimit( WORD sel )
{
return GET_SEL_LIMIT(sel);
}
/***********************************************************************
* SetSelectorLimit (KERNEL.189)
*/
WORD WINAPI 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 WINAPI 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 WINAPI 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) > GET_SEL_LIMIT(sel)) return TRUE;
return FALSE;
}
/***********************************************************************
* IsBadStringPtr16 (KERNEL.337)
*/
BOOL16 WINAPI 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 > GET_SEL_LIMIT(sel)) return TRUE;
return FALSE;
}
/***********************************************************************
* IsBadHugeReadPtr16 (KERNEL.346)
*/
BOOL16 WINAPI 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 > GET_SEL_LIMIT(sel)) return TRUE;
return FALSE;
}
/***********************************************************************
* IsBadHugeWritePtr16 (KERNEL.347)
*/
BOOL16 WINAPI 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 > GET_SEL_LIMIT(sel)) return TRUE;
return FALSE;
}
/***********************************************************************
* IsBadReadPtr16 (KERNEL.334)
*/
BOOL16 WINAPI IsBadReadPtr16( SEGPTR ptr, UINT16 size )
{
return IsBadHugeReadPtr16( ptr, size );
}
/***********************************************************************
* IsBadWritePtr16 (KERNEL.335)
*/
BOOL16 WINAPI IsBadWritePtr16( SEGPTR ptr, UINT16 size )
{
return IsBadHugeWritePtr16( ptr, size );
}
/***********************************************************************
* MemoryRead (TOOLHELP.78)
*/
DWORD WINAPI 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 WINAPI 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 *
*
*/
/***********************************************************************
* MapSL (KERNEL32.523)
*
* Maps fixed segmented pointer to linear.
*/
LPVOID WINAPI MapSL( SEGPTR sptr )
{
return (LPVOID)PTR_SEG_TO_LIN(sptr);
}
/***********************************************************************
* MapSLFix (KERNEL32.524)
*
* FIXME: MapSLFix and UnMapSLFixArray should probably prevent
* unexpected linear address change when GlobalCompact() shuffles
* moveable blocks.
*/
LPVOID WINAPI MapSLFix( SEGPTR sptr )
{
return (LPVOID)PTR_SEG_TO_LIN(sptr);
}
/***********************************************************************
* UnMapSLFixArray (KERNEL32.701)
*/
void WINAPI UnMapSLFixArray( SEGPTR sptr[], INT32 length )
{
}
/***********************************************************************
* MapLS (KERNEL32.522)
*
* Maps linear pointer to segmented.
*/
SEGPTR WINAPI MapLS( LPVOID ptr )
{
if (!HIWORD(ptr))
return (SEGPTR)ptr;
else
{
WORD sel = SELECTOR_AllocBlock( ptr, 0x10000, SEGMENT_DATA, FALSE, FALSE );
return PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
}
}
/***********************************************************************
* UnMapLS (KERNEL32.700)
*
* Free mapped selector.
*/
void WINAPI UnMapLS( SEGPTR sptr )
{
if (SELECTOROF(sptr))
SELECTOR_FreeBlock( SELECTOROF(sptr), 1 );
}
/***********************************************************************
* GetThreadSelectorEntry (KERNEL32)
* FIXME: add #ifdef i386 for non x86
*/
BOOL32 WINAPI GetThreadSelectorEntry( HANDLE32 hthread, DWORD sel,
LPLDT_ENTRY ldtent)
{
ldt_entry ldtentry;
LDT_GetEntry(SELECTOR_TO_ENTRY(sel),&ldtentry);
ldtent->BaseLow = ldtentry.base & 0x0000ffff;
ldtent->HighWord.Bits.BaseMid = (ldtentry.base & 0x00ff0000) >> 16;
ldtent->HighWord.Bits.BaseHi = (ldtentry.base & 0xff000000) >> 24;
ldtent->LimitLow = ldtentry.limit & 0x0000ffff;
ldtent->HighWord.Bits.LimitHi = (ldtentry.limit & 0x00ff0000) >> 16;
ldtent->HighWord.Bits.Dpl = 3;
ldtent->HighWord.Bits.Sys = 0;
ldtent->HighWord.Bits.Pres = 1;
ldtent->HighWord.Bits.Type = 0x10|(ldtentry.type << 2);
if (ldtentry.read_only)
ldtent->HighWord.Bits.Type|=0x2;
ldtent->HighWord.Bits.Granularity = ldtentry.limit_in_pages;
ldtent->HighWord.Bits.Default_Big = ldtentry.seg_32bit;
return TRUE;
}
/**********************************************************************
* SMapLS* (KERNEL32)
* These functions map linear pointers at [EBP+xxx] to segmented pointers
* and return them.
* Win95 uses some kind of alias structs, which it stores in [EBP+x] to
* unravel them at SUnMapLS. We just store the segmented pointer there.
*/
static void
x_SMapLS_IP_EBP_x(CONTEXT *context,int argoff) {
DWORD val,ptr;
val =*(DWORD*)(EBP_reg(context)+argoff);
if (val<0x10000) {
ptr=val;
*(DWORD*)(EBP_reg(context)+argoff) = 0;
} else {
ptr = MapLS((LPVOID)val);
*(DWORD*)(EBP_reg(context)+argoff) = ptr;
}
EAX_reg(context) = ptr;
}
REGS_ENTRYPOINT(SMapLS_IP_EBP_8) {x_SMapLS_IP_EBP_x(context,8);}
REGS_ENTRYPOINT(SMapLS_IP_EBP_12) {x_SMapLS_IP_EBP_x(context,12);}
REGS_ENTRYPOINT(SMapLS_IP_EBP_16) {x_SMapLS_IP_EBP_x(context,16);}
REGS_ENTRYPOINT(SMapLS_IP_EBP_20) {x_SMapLS_IP_EBP_x(context,20);}
REGS_ENTRYPOINT(SMapLS_IP_EBP_24) {x_SMapLS_IP_EBP_x(context,24);}
REGS_ENTRYPOINT(SMapLS_IP_EBP_28) {x_SMapLS_IP_EBP_x(context,28);}
REGS_ENTRYPOINT(SMapLS_IP_EBP_32) {x_SMapLS_IP_EBP_x(context,32);}
REGS_ENTRYPOINT(SMapLS_IP_EBP_36) {x_SMapLS_IP_EBP_x(context,36);}
REGS_ENTRYPOINT(SMapLS_IP_EBP_40) {x_SMapLS_IP_EBP_x(context,40);}
REGS_ENTRYPOINT(SMapLS)
{
if (EAX_reg(context)>=0x10000) {
EAX_reg(context) = MapLS((LPVOID)EAX_reg(context));
EDX_reg(context) = EAX_reg(context);
} else {
EDX_reg(context) = 0;
}
}
REGS_ENTRYPOINT(SUnMapLS)
{
if (EAX_reg(context)>=0x10000)
UnMapLS((SEGPTR)EAX_reg(context));
}
static void
x_SUnMapLS_IP_EBP_x(CONTEXT *context,int argoff) {
if (*(DWORD*)(EBP_reg(context)+argoff))
UnMapLS(*(DWORD*)(EBP_reg(context)+argoff));
*(DWORD*)(EBP_reg(context)+argoff)=0;
}
REGS_ENTRYPOINT(SUnMapLS_IP_EBP_8) { x_SUnMapLS_IP_EBP_x(context,12); }
REGS_ENTRYPOINT(SUnMapLS_IP_EBP_12) { x_SUnMapLS_IP_EBP_x(context,12); }
REGS_ENTRYPOINT(SUnMapLS_IP_EBP_16) { x_SUnMapLS_IP_EBP_x(context,16); }
REGS_ENTRYPOINT(SUnMapLS_IP_EBP_20) { x_SUnMapLS_IP_EBP_x(context,20); }
REGS_ENTRYPOINT(SUnMapLS_IP_EBP_24) { x_SUnMapLS_IP_EBP_x(context,24); }
REGS_ENTRYPOINT(SUnMapLS_IP_EBP_28) { x_SUnMapLS_IP_EBP_x(context,28); }
REGS_ENTRYPOINT(SUnMapLS_IP_EBP_32) { x_SUnMapLS_IP_EBP_x(context,32); }
REGS_ENTRYPOINT(SUnMapLS_IP_EBP_36) { x_SUnMapLS_IP_EBP_x(context,36); }
REGS_ENTRYPOINT(SUnMapLS_IP_EBP_40) { x_SUnMapLS_IP_EBP_x(context,40); }
/**********************************************************************
* AllocMappedBuffer (KERNEL32.38)
*
* This is a undocumented KERNEL32 function that
* SMapLS's a GlobalAlloc'ed buffer.
*
* Input: EDI register: size of buffer to allocate
* Output: EDI register: pointer to buffer
*
* Note: The buffer is preceeded by 8 bytes:
* ...
* edi+0 buffer
* edi-4 SEGPTR to buffer
* edi-8 some magic Win95 needs for SUnMapLS
* (we use it for the memory handle)
*
* The SEGPTR is used by the caller!
*/
REGS_ENTRYPOINT(AllocMappedBuffer)
{
HGLOBAL32 handle = GlobalAlloc32(0, EDI_reg(context) + 8);
DWORD *buffer = (DWORD *)GlobalLock32(handle);
SEGPTR ptr = 0;
if (buffer)
if (!(ptr = MapLS(buffer + 2)))
{
GlobalUnlock32(handle);
GlobalFree32(handle);
}
if (!ptr)
EAX_reg(context) = EDI_reg(context) = 0;
else
{
buffer[0] = handle;
buffer[1] = ptr;
EAX_reg(context) = (DWORD) ptr;
EDI_reg(context) = (DWORD)(buffer + 2);
}
}
/**********************************************************************
* FreeMappedBuffer (KERNEL32.39)
*
* Free a buffer allocated by AllocMappedBuffer
*
* Input: EDI register: pointer to buffer
*/
REGS_ENTRYPOINT(FreeMappedBuffer)
{
if (EDI_reg(context))
{
DWORD *buffer = (DWORD *)EDI_reg(context) - 2;
UnMapLS(buffer[1]);
GlobalUnlock32(buffer[0]);
GlobalFree32(buffer[0]);
}
}
/**********************************************************************
* WOWGetVDMPointer (KERNEL32.55)
* Get linear from segmented pointer. (MSDN lib)
*/
LPVOID WINAPI WOWGetVDMPointer(DWORD vp,DWORD nrofbytes,BOOL32 protected)
{
/* FIXME: add size check too */
if (protected)
return PTR_SEG_TO_LIN(vp);
else
return DOSMEM_MapRealToLinear(vp);
}
/**********************************************************************
* GetVDMPointer32W (KERNEL.516)
*/
LPVOID WINAPI GetVDMPointer32W(DWORD vp,DWORD mode)
{
return WOWGetVDMPointer(vp,0,mode);
}
/**********************************************************************
* WOWGetVDMPointerFix (KERNEL32.55)
* Dito, but fix heapsegment (MSDN lib)
*/
LPVOID WINAPI WOWGetVDMPointerFix(DWORD vp,DWORD nrofbytes,BOOL32 protected)
{
/* FIXME: fix heapsegment */
return WOWGetVDMPointer(vp,nrofbytes,protected);
}
/**********************************************************************
* WOWGetVDMPointerUnFix (KERNEL32.56)
*/
void WINAPI WOWGetVDMPointerUnfix(DWORD vp)
{
/* FIXME: unfix heapsegment */
}
/***********************************************************************
* UTSelectorOffsetToLinear (WIN32S16.48)
*
* rough guesswork, but seems to work (I had no "reasonable" docu)
*/
LPVOID WINAPI UTSelectorOffsetToLinear(SEGPTR sptr)
{
return PTR_SEG_TO_LIN(sptr);
}
/***********************************************************************
* UTLinearToSelectorOffset (WIN32S16.49)
*
* FIXME: I don't know if that's the right way to do linear -> segmented
*/
SEGPTR WINAPI UTLinearToSelectorOffset(LPVOID lptr)
{
return (SEGPTR)lptr;
}