mirror of
https://github.com/reactos/reactos.git
synced 2026-06-01 08:50:24 +08:00
[VIDEOPRT] Implement support for dynamically choosing V86 vs. X86 emulator on x86 32-bit builds (#8451)
The choice is done by looking for the presence or absence of the `HKLM\System\CurrentControlSet\Control\GraphicsDrivers\DisableEmulator` registry key. For more details, see: https://www.geoffchappell.com/studies/windows/km/hal/api/x86bios/call.htm By default, use V86 in 32-bit Win2k3-compatible builds, otherwise (Vista+) check the presence of the registry key. The X86 emulator routines are exported by the HAL.DLL. They are always exported by the non-x86 HAL. However, they may or may not be exported by the x86 (32-bit) HAL: on NT 5.2 and below they are not exported, while on NT 6.x (Vista+) they are. Therefore: - in our NT <= 5.2 x86 builds, we load the routines at runtime. If they aren't found, we fail emulator support initialization and fall back to VDM V86 support. - in our NT 6.x (x86 or not) builds, we always directly link with the HAL routines, since they are guaranteed to be present there.
This commit is contained in:
@@ -385,10 +385,10 @@ IntVideoPortDispatchOpen(
|
||||
ObReferenceObject(CsrProcess);
|
||||
INFO_(VIDEOPRT, "CsrProcess 0x%p\n", CsrProcess);
|
||||
|
||||
Status = IntInitializeVideoAddressSpace();
|
||||
Status = IntInitializeInt10();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR_(VIDEOPRT, "IntInitializeVideoAddressSpace() failed: 0x%lx\n", Status);
|
||||
ERR_(VIDEOPRT, "IntInitializeInt10() failed: 0x%lx\n", Status);
|
||||
ObDereferenceObject(CsrProcess);
|
||||
CsrProcess = NULL;
|
||||
return Status;
|
||||
|
||||
@@ -22,20 +22,96 @@
|
||||
#include "videoprt.h"
|
||||
|
||||
#include <ndk/kefuncs.h>
|
||||
#include <ndk/halfuncs.h>
|
||||
#include <ndk/mmfuncs.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
/* GLOBAL VARIABLES ***********************************************************/
|
||||
|
||||
#ifdef _M_IX86
|
||||
/* Use the 32-bit x86 emulator by default, on NT 6.x (Vista+), or on NT 5.x
|
||||
* if the HAL has the necessary exports. Otherwise fall back to V86 mode. */
|
||||
BOOLEAN VideoPortDisableX86Emulator = FALSE;
|
||||
#endif
|
||||
|
||||
KMUTEX VideoPortInt10Mutex;
|
||||
|
||||
|
||||
/* X86 EMULATOR & V86 MODE INITIALIZATION *************************************/
|
||||
|
||||
#if (NTDDI_VERSION < NTDDI_VISTA) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
|
||||
/*
|
||||
* x86 Emulator callbacks
|
||||
*/
|
||||
#include <ndk/haltypes.h> // For X86_BIOS_REGISTERS
|
||||
|
||||
static BOOLEAN
|
||||
(NTAPI *x86BiosCall)(
|
||||
_In_ ULONG InterruptNumber,
|
||||
_Inout_ PX86_BIOS_REGISTERS Registers);
|
||||
|
||||
static NTSTATUS
|
||||
(NTAPI *x86BiosAllocateBuffer)(
|
||||
_Inout_ PULONG Size,
|
||||
_Out_ PUSHORT Segment,
|
||||
_Out_ PUSHORT Offset);
|
||||
|
||||
static NTSTATUS
|
||||
(NTAPI *x86BiosFreeBuffer)(
|
||||
_In_ USHORT Segment,
|
||||
_In_ USHORT Offset);
|
||||
|
||||
static NTSTATUS
|
||||
(NTAPI *x86BiosReadMemory)(
|
||||
_In_ USHORT Segment,
|
||||
_In_ USHORT Offset,
|
||||
_Out_writes_bytes_(Size) PVOID Buffer,
|
||||
_In_ ULONG Size);
|
||||
|
||||
static NTSTATUS
|
||||
(NTAPI *x86BiosWriteMemory)(
|
||||
_In_ USHORT Segment,
|
||||
_In_ USHORT Offset,
|
||||
_In_reads_bytes_(Size) PVOID Buffer,
|
||||
_In_ ULONG Size);
|
||||
|
||||
#else // (NTDDI_VERSION >= NTDDI_VISTA) || (DLL_EXPORT_VERSION >= _WIN32_WINNT_VISTA)
|
||||
#include <ndk/halfuncs.h> // For x86Bios*()
|
||||
#endif
|
||||
|
||||
static BOOLEAN
|
||||
IntInitializeX86Emu(VOID)
|
||||
{
|
||||
#if (NTDDI_VERSION < NTDDI_VISTA) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
|
||||
UNICODE_STRING ImportName;
|
||||
#define LOAD_IMPORT(func) \
|
||||
(RtlInitUnicodeString(&ImportName, L ## #func), \
|
||||
(func) = MmGetSystemRoutineAddress(&ImportName))
|
||||
|
||||
if (!LOAD_IMPORT(x86BiosCall)) // Check also HalInitializeBios ?
|
||||
return FALSE; /* No emulator available */
|
||||
if (!LOAD_IMPORT(x86BiosAllocateBuffer))
|
||||
return FALSE;
|
||||
if (!LOAD_IMPORT(x86BiosFreeBuffer))
|
||||
return FALSE;
|
||||
if (!LOAD_IMPORT(x86BiosReadMemory))
|
||||
return FALSE;
|
||||
if (!LOAD_IMPORT(x86BiosWriteMemory))
|
||||
return FALSE;
|
||||
#undef LOAD_IMPORT
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef _M_IX86
|
||||
|
||||
#define IsLowV86Mem(_Seg, _Off) ((((_Seg) << 4) + (_Off)) < (0xa0000))
|
||||
|
||||
/* Those two functions below are there so that CSRSS can't access low mem.
|
||||
* Especially, MAKE IT CRASH ON NULL ACCESS */
|
||||
static
|
||||
VOID
|
||||
static VOID
|
||||
ProtectLowV86Mem(VOID)
|
||||
{
|
||||
/* We pass a non-NULL address so that ZwAllocateVirtualMemory really does it
|
||||
@@ -57,8 +133,7 @@ ProtectLowV86Mem(VOID)
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
static VOID
|
||||
UnprotectLowV86Mem(VOID)
|
||||
{
|
||||
/* We pass a non-NULL address so that ZwAllocateVirtualMemory really does it
|
||||
@@ -80,9 +155,8 @@ UnprotectLowV86Mem(VOID)
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
}
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_AMD64)
|
||||
static inline
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IntInitializeVideoAddressSpace(VOID)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
@@ -92,9 +166,7 @@ IntInitializeVideoAddressSpace(VOID)
|
||||
PVOID BaseAddress;
|
||||
LARGE_INTEGER Offset;
|
||||
SIZE_T ViewSize;
|
||||
#ifdef _M_IX86
|
||||
CHAR IVTAndBda[1024 + 256];
|
||||
#endif // _M_IX86
|
||||
|
||||
/* We should only do that for CSRSS */
|
||||
ASSERT(PsGetCurrentProcess() == (PEPROCESS)CsrProcess);
|
||||
@@ -181,7 +253,6 @@ IntInitializeVideoAddressSpace(VOID)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _M_IX86
|
||||
/* Get the real mode IVT and BDA from the kernel */
|
||||
Status = NtVdmControl(VdmInitialize, IVTAndBda);
|
||||
if (!NT_SUCCESS(Status))
|
||||
@@ -189,7 +260,6 @@ IntInitializeVideoAddressSpace(VOID)
|
||||
DPRINT1("NtVdmControl failed (status %x)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
#endif // _M_IX86
|
||||
|
||||
/* Protect the V86 address space after this */
|
||||
ProtectLowV86Mem();
|
||||
@@ -197,33 +267,62 @@ IntInitializeVideoAddressSpace(VOID)
|
||||
/* Return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
#else
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IntInitializeVideoAddressSpace(VOID)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
NT_ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
VP_STATUS
|
||||
#endif // _M_IX86
|
||||
|
||||
|
||||
/* VideoPortServicesInt10 CALLBACKS *******************************************/
|
||||
|
||||
#ifdef _M_IX86
|
||||
typedef struct _INT10_INTERFACE
|
||||
{
|
||||
PINT10_ALLOCATE_BUFFER Int10AllocateBuffer;
|
||||
PINT10_FREE_BUFFER Int10FreeBuffer;
|
||||
PINT10_READ_MEMORY Int10ReadMemory;
|
||||
PINT10_WRITE_MEMORY Int10WriteMemory;
|
||||
PINT10_CALL_BIOS Int10CallBios;
|
||||
} INT10_INTERFACE;
|
||||
|
||||
// Remark: Instead of `Int10Vtbl->`, one could use: `Int10IFace[VideoPortDisableX86Emulator].`
|
||||
static const INT10_INTERFACE *Int10Vtbl; // Int10IFace[2];
|
||||
#define INT10(func) Int10Vtbl->Int10##func
|
||||
#else
|
||||
#define INT10(func) IntInt10##func##Emu
|
||||
#endif // _M_IX86
|
||||
|
||||
|
||||
static VP_STATUS
|
||||
NTAPI
|
||||
IntInt10AllocateBuffer(
|
||||
IN PVOID Context,
|
||||
OUT PUSHORT Seg,
|
||||
OUT PUSHORT Off,
|
||||
IN OUT PULONG Length)
|
||||
IntInt10AllocateBufferEmu(
|
||||
_In_ PVOID Context,
|
||||
_Out_ PUSHORT Seg,
|
||||
_Out_ PUSHORT Off,
|
||||
_Inout_ PULONG Length)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
Status = x86BiosAllocateBuffer(Length, Seg, Off);
|
||||
return (NT_SUCCESS(Status) ? NO_ERROR : ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
|
||||
#ifdef _M_IX86
|
||||
static VP_STATUS
|
||||
NTAPI
|
||||
IntInt10AllocateBufferV86(
|
||||
_In_ PVOID Context,
|
||||
_Out_ PUSHORT Seg,
|
||||
_Out_ PUSHORT Off,
|
||||
_Inout_ PULONG Length)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PVOID MemoryAddress;
|
||||
PKPROCESS CallingProcess;
|
||||
KAPC_STATE ApcState;
|
||||
SIZE_T Size;
|
||||
|
||||
TRACE_(VIDEOPRT, "IntInt10AllocateBuffer\n");
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
/* Perform the call in the CSRSS context */
|
||||
if (!IntAttachToCSRSS(&CallingProcess, &ApcState))
|
||||
@@ -262,34 +361,63 @@ IntInt10AllocateBuffer(
|
||||
*Seg = (USHORT)((ULONG_PTR)MemoryAddress >> 4);
|
||||
*Off = (USHORT)((ULONG_PTR)MemoryAddress & 0xF);
|
||||
|
||||
INFO_(VIDEOPRT, "- Segment: %x\n", *Seg);
|
||||
INFO_(VIDEOPRT, "- Offset: %x\n", *Off);
|
||||
INFO_(VIDEOPRT, "- Length: %x\n", *Length);
|
||||
|
||||
return NO_ERROR;
|
||||
#else
|
||||
Status = x86BiosAllocateBuffer(Length, Seg, Off);
|
||||
return NT_SUCCESS(Status) ? NO_ERROR : ERROR_NOT_ENOUGH_MEMORY;
|
||||
#endif
|
||||
}
|
||||
#endif // _M_IX86
|
||||
|
||||
VP_STATUS
|
||||
NTAPI
|
||||
IntInt10FreeBuffer(
|
||||
IN PVOID Context,
|
||||
IN USHORT Seg,
|
||||
IN USHORT Off)
|
||||
IntInt10AllocateBuffer(
|
||||
_In_ PVOID Context,
|
||||
_Out_ PUSHORT Seg,
|
||||
_Out_ PUSHORT Off,
|
||||
_Inout_ PULONG Length)
|
||||
{
|
||||
VP_STATUS Status;
|
||||
|
||||
TRACE_(VIDEOPRT, "IntInt10AllocateBuffer\n");
|
||||
|
||||
Status = INT10(AllocateBuffer)(Context, Seg, Off, Length);
|
||||
if (Status == NO_ERROR)
|
||||
{
|
||||
INFO_(VIDEOPRT, "- Segment: 0x%x\n", *Seg);
|
||||
INFO_(VIDEOPRT, "- Offset : 0x%x\n", *Off);
|
||||
INFO_(VIDEOPRT, "- Length : 0x%x\n", *Length);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
static VP_STATUS
|
||||
NTAPI
|
||||
IntInt10FreeBufferEmu(
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
Status = x86BiosFreeBuffer(Seg, Off);
|
||||
return (NT_SUCCESS(Status) ? NO_ERROR : ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
#ifdef _M_IX86
|
||||
static VP_STATUS
|
||||
NTAPI
|
||||
IntInt10FreeBufferV86(
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PVOID MemoryAddress = (PVOID)((ULONG_PTR)(Seg << 4) | Off);
|
||||
PKPROCESS CallingProcess;
|
||||
KAPC_STATE ApcState;
|
||||
SIZE_T Size = 0;
|
||||
|
||||
TRACE_(VIDEOPRT, "IntInt10FreeBuffer\n");
|
||||
INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
|
||||
INFO_(VIDEOPRT, "- Offset: %x\n", Off);
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
/* Perform the call in the CSRSS context */
|
||||
if (!IntAttachToCSRSS(&CallingProcess, &ApcState))
|
||||
@@ -303,30 +431,55 @@ IntInt10FreeBuffer(
|
||||
IntDetachFromCSRSS(CallingProcess, &ApcState);
|
||||
|
||||
return Status;
|
||||
#else
|
||||
Status = x86BiosFreeBuffer(Seg, Off);
|
||||
return NT_SUCCESS(Status) ? NO_ERROR : ERROR_INVALID_PARAMETER;
|
||||
#endif
|
||||
}
|
||||
#endif // _M_IX86
|
||||
|
||||
VP_STATUS
|
||||
NTAPI
|
||||
IntInt10ReadMemory(
|
||||
IN PVOID Context,
|
||||
IN USHORT Seg,
|
||||
IN USHORT Off,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG Length)
|
||||
IntInt10FreeBuffer(
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off)
|
||||
{
|
||||
TRACE_(VIDEOPRT, "IntInt10FreeBuffer\n");
|
||||
INFO_(VIDEOPRT, "- Segment: 0x%x\n", Seg);
|
||||
INFO_(VIDEOPRT, "- Offset : 0x%x\n", Off);
|
||||
|
||||
return INT10(FreeBuffer)(Context, Seg, Off);
|
||||
}
|
||||
|
||||
|
||||
static VP_STATUS
|
||||
NTAPI
|
||||
IntInt10ReadMemoryEmu(
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off,
|
||||
_Out_writes_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
Status = x86BiosReadMemory(Seg, Off, Buffer, Length);
|
||||
return (NT_SUCCESS(Status) ? NO_ERROR : ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
#ifdef _M_IX86
|
||||
static VP_STATUS
|
||||
NTAPI
|
||||
IntInt10ReadMemoryV86(
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off,
|
||||
_Out_writes_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length)
|
||||
{
|
||||
PKPROCESS CallingProcess;
|
||||
KAPC_STATE ApcState;
|
||||
|
||||
TRACE_(VIDEOPRT, "IntInt10ReadMemory\n");
|
||||
INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
|
||||
INFO_(VIDEOPRT, "- Offset: %x\n", Off);
|
||||
INFO_(VIDEOPRT, "- Buffer: %x\n", Buffer);
|
||||
INFO_(VIDEOPRT, "- Length: %x\n", Length);
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
/* Perform the call in the CSRSS context */
|
||||
if (!IntAttachToCSRSS(&CallingProcess, &ApcState))
|
||||
@@ -341,32 +494,59 @@ IntInt10ReadMemory(
|
||||
IntDetachFromCSRSS(CallingProcess, &ApcState);
|
||||
|
||||
return NO_ERROR;
|
||||
#else
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = x86BiosReadMemory(Seg, Off, Buffer, Length);
|
||||
return NT_SUCCESS(Status) ? NO_ERROR : ERROR_INVALID_PARAMETER;
|
||||
#endif
|
||||
}
|
||||
#endif // _M_IX86
|
||||
|
||||
VP_STATUS
|
||||
NTAPI
|
||||
IntInt10WriteMemory(
|
||||
IN PVOID Context,
|
||||
IN USHORT Seg,
|
||||
IN USHORT Off,
|
||||
IN PVOID Buffer,
|
||||
IN ULONG Length)
|
||||
IntInt10ReadMemory(
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off,
|
||||
_Out_writes_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length)
|
||||
{
|
||||
TRACE_(VIDEOPRT, "IntInt10ReadMemory\n");
|
||||
INFO_(VIDEOPRT, "- Segment: 0x%x\n", Seg);
|
||||
INFO_(VIDEOPRT, "- Offset : 0x%x\n", Off);
|
||||
INFO_(VIDEOPRT, "- Buffer : 0x%x\n", Buffer);
|
||||
INFO_(VIDEOPRT, "- Length : 0x%x\n", Length);
|
||||
|
||||
return INT10(ReadMemory)(Context, Seg, Off, Buffer, Length);
|
||||
}
|
||||
|
||||
|
||||
static VP_STATUS
|
||||
NTAPI
|
||||
IntInt10WriteMemoryEmu(
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off,
|
||||
_In_reads_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
Status = x86BiosWriteMemory(Seg, Off, Buffer, Length);
|
||||
return (NT_SUCCESS(Status) ? NO_ERROR : ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
#ifdef _M_IX86
|
||||
static VP_STATUS
|
||||
NTAPI
|
||||
IntInt10WriteMemoryV86(
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off,
|
||||
_In_reads_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length)
|
||||
{
|
||||
PKPROCESS CallingProcess;
|
||||
KAPC_STATE ApcState;
|
||||
|
||||
TRACE_(VIDEOPRT, "IntInt10WriteMemory\n");
|
||||
INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
|
||||
INFO_(VIDEOPRT, "- Offset: %x\n", Off);
|
||||
INFO_(VIDEOPRT, "- Buffer: %x\n", Buffer);
|
||||
INFO_(VIDEOPRT, "- Length: %x\n", Length);
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
/* Perform the call in the CSRSS context */
|
||||
if (!IntAttachToCSRSS(&CallingProcess, &ApcState))
|
||||
@@ -381,29 +561,90 @@ IntInt10WriteMemory(
|
||||
IntDetachFromCSRSS(CallingProcess, &ApcState);
|
||||
|
||||
return NO_ERROR;
|
||||
#else
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = x86BiosWriteMemory(Seg, Off, Buffer, Length);
|
||||
return NT_SUCCESS(Status) ? NO_ERROR : ERROR_INVALID_PARAMETER;
|
||||
#endif
|
||||
}
|
||||
#endif // _M_IX86
|
||||
|
||||
VP_STATUS
|
||||
NTAPI
|
||||
IntInt10CallBios(
|
||||
IN PVOID Context,
|
||||
IN OUT PINT10_BIOS_ARGUMENTS BiosArguments)
|
||||
IntInt10WriteMemory(
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off,
|
||||
_In_reads_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length)
|
||||
{
|
||||
TRACE_(VIDEOPRT, "IntInt10WriteMemory\n");
|
||||
INFO_(VIDEOPRT, "- Segment: 0x%x\n", Seg);
|
||||
INFO_(VIDEOPRT, "- Offset : 0x%x\n", Off);
|
||||
INFO_(VIDEOPRT, "- Buffer : 0x%x\n", Buffer);
|
||||
INFO_(VIDEOPRT, "- Length : 0x%x\n", Length);
|
||||
|
||||
return INT10(WriteMemory)(Context, Seg, Off, Buffer, Length);
|
||||
}
|
||||
|
||||
|
||||
static VP_STATUS
|
||||
NTAPI
|
||||
IntInt10CallBiosEmu(
|
||||
_In_ PVOID Context,
|
||||
_Inout_ PINT10_BIOS_ARGUMENTS BiosArguments)
|
||||
{
|
||||
#ifdef _M_AMD64
|
||||
X86_BIOS_REGISTERS BiosContext;
|
||||
#else
|
||||
BOOLEAN Success;
|
||||
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
/* Clear the context and fill out the BIOS arguments */
|
||||
RtlZeroMemory(&BiosContext, sizeof(BiosContext));
|
||||
BiosContext.Eax = BiosArguments->Eax;
|
||||
BiosContext.Ebx = BiosArguments->Ebx;
|
||||
BiosContext.Ecx = BiosArguments->Ecx;
|
||||
BiosContext.Edx = BiosArguments->Edx;
|
||||
BiosContext.Esi = BiosArguments->Esi;
|
||||
BiosContext.Edi = BiosArguments->Edi;
|
||||
BiosContext.Ebp = BiosArguments->Ebp;
|
||||
BiosContext.SegDs = BiosArguments->SegDs;
|
||||
BiosContext.SegEs = BiosArguments->SegEs;
|
||||
|
||||
/* Do the ROM BIOS call */
|
||||
(void)KeWaitForMutexObject(&VideoPortInt10Mutex,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
Success = x86BiosCall(0x10, &BiosContext);
|
||||
|
||||
KeReleaseMutex(&VideoPortInt10Mutex, FALSE);
|
||||
|
||||
/* Return the arguments */
|
||||
BiosArguments->Eax = BiosContext.Eax;
|
||||
BiosArguments->Ebx = BiosContext.Ebx;
|
||||
BiosArguments->Ecx = BiosContext.Ecx;
|
||||
BiosArguments->Edx = BiosContext.Edx;
|
||||
BiosArguments->Esi = BiosContext.Esi;
|
||||
BiosArguments->Edi = BiosContext.Edi;
|
||||
BiosArguments->Ebp = BiosContext.Ebp;
|
||||
BiosArguments->SegDs = (USHORT)BiosContext.SegDs;
|
||||
BiosArguments->SegEs = (USHORT)BiosContext.SegEs;
|
||||
|
||||
return (Success ? NO_ERROR : ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
#ifdef _M_IX86
|
||||
static VP_STATUS
|
||||
NTAPI
|
||||
IntInt10CallBiosV86(
|
||||
_In_ PVOID Context,
|
||||
_Inout_ PINT10_BIOS_ARGUMENTS BiosArguments)
|
||||
{
|
||||
CONTEXT BiosContext;
|
||||
#endif
|
||||
NTSTATUS Status;
|
||||
PKPROCESS CallingProcess;
|
||||
KAPC_STATE ApcState;
|
||||
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
/* Clear the context and fill out the BIOS arguments */
|
||||
RtlZeroMemory(&BiosContext, sizeof(BiosContext));
|
||||
BiosContext.Eax = BiosArguments->Eax;
|
||||
@@ -429,11 +670,18 @@ IntInt10CallBios(
|
||||
|
||||
/* The kernel needs access here */
|
||||
UnprotectLowV86Mem();
|
||||
#ifdef _M_AMD64
|
||||
Status = x86BiosCall(0x10, &BiosContext) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
||||
#else
|
||||
Status = Ke386CallBios(0x10, &BiosContext);
|
||||
#endif
|
||||
|
||||
/* Invoke the V86 monitor under SEH, as it can raise exceptions */
|
||||
_SEH2_TRY
|
||||
{
|
||||
Status = Ke386CallBios(0x10, &BiosContext);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
ProtectLowV86Mem();
|
||||
|
||||
KeReleaseMutex(&VideoPortInt10Mutex, FALSE);
|
||||
@@ -451,8 +699,67 @@ IntInt10CallBios(
|
||||
BiosArguments->SegDs = (USHORT)BiosContext.SegDs;
|
||||
BiosArguments->SegEs = (USHORT)BiosContext.SegEs;
|
||||
|
||||
return NT_SUCCESS(Status) ? NO_ERROR : ERROR_INVALID_PARAMETER;
|
||||
return (NT_SUCCESS(Status) ? NO_ERROR : ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
#endif // _M_IX86
|
||||
|
||||
VP_STATUS
|
||||
NTAPI
|
||||
IntInt10CallBios(
|
||||
_In_ PVOID Context,
|
||||
_Inout_ PINT10_BIOS_ARGUMENTS BiosArguments)
|
||||
{
|
||||
return INT10(CallBios)(Context, BiosArguments);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _M_IX86
|
||||
static const INT10_INTERFACE Int10IFace[2] =
|
||||
{ { IntInt10AllocateBufferEmu,
|
||||
IntInt10FreeBufferEmu,
|
||||
IntInt10ReadMemoryEmu,
|
||||
IntInt10WriteMemoryEmu,
|
||||
IntInt10CallBiosEmu }
|
||||
,
|
||||
{ IntInt10AllocateBufferV86,
|
||||
IntInt10FreeBufferV86,
|
||||
IntInt10ReadMemoryV86,
|
||||
IntInt10WriteMemoryV86,
|
||||
IntInt10CallBiosV86 }
|
||||
};
|
||||
static const INT10_INTERFACE *Int10Vtbl = &Int10IFace[0];
|
||||
#endif
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
NTSTATUS
|
||||
IntInitializeInt10(VOID)
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
/* We should only do that for CSRSS */
|
||||
ASSERT(PsGetCurrentProcess() == (PEPROCESS)CsrProcess);
|
||||
|
||||
/* Initialize the x86 emulator if necessary, otherwise fall back to V86 mode */
|
||||
if (!VideoPortDisableX86Emulator)
|
||||
{
|
||||
/* Use the emulation routines */
|
||||
//Int10Vtbl = &Int10IFace[0];
|
||||
if (IntInitializeX86Emu())
|
||||
return STATUS_SUCCESS;
|
||||
DPRINT1("Could not initialize the x86 emulator; falling back to V86 mode\n");
|
||||
VideoPortDisableX86Emulator = TRUE;
|
||||
}
|
||||
|
||||
/* Fall back to the V86 routines */
|
||||
Int10Vtbl = &Int10IFace[1];
|
||||
return IntInitializeVideoAddressSpace();
|
||||
#else
|
||||
/* Initialize the x86 emulator */
|
||||
return (IntInitializeX86Emu() ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
@@ -465,13 +772,8 @@ VideoPortInt10(
|
||||
IN PVOID HwDeviceExtension,
|
||||
IN PVIDEO_X86_BIOS_ARGUMENTS BiosArguments)
|
||||
{
|
||||
INT10_BIOS_ARGUMENTS Int10BiosArguments;
|
||||
VP_STATUS Status;
|
||||
|
||||
if (!CsrProcess)
|
||||
{
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
INT10_BIOS_ARGUMENTS Int10BiosArguments;
|
||||
|
||||
/* Copy arguments to other format */
|
||||
RtlCopyMemory(&Int10BiosArguments, BiosArguments, sizeof(*BiosArguments));
|
||||
|
||||
@@ -39,7 +39,7 @@ BOOLEAN VpNoVesa = FALSE;
|
||||
PKPROCESS CsrProcess = NULL;
|
||||
static ULONG VideoPortMaxObjectNumber = -1;
|
||||
BOOLEAN VideoPortUseNewKey = FALSE;
|
||||
KMUTEX VideoPortInt10Mutex;
|
||||
|
||||
KSPIN_LOCK HwResetAdaptersLock;
|
||||
RTL_STATIC_LIST_HEAD(HwResetAdaptersList);
|
||||
|
||||
@@ -628,21 +628,21 @@ IntLoadRegistryParameters(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE KeyHandle;
|
||||
UNICODE_STRING UseNewKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\GraphicsDrivers\\UseNewKey");
|
||||
UNICODE_STRING Path = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
|
||||
UNICODE_STRING KeyPath;
|
||||
UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"SystemStartOptions");
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
|
||||
ULONG Length, NewLength;
|
||||
|
||||
/* Check if we need to use new registry */
|
||||
RtlInitUnicodeString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\GraphicsDrivers\\UseNewKey");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&UseNewKeyPath,
|
||||
&KeyPath,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenKey(&KeyHandle,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
KEY_QUERY_VALUE,
|
||||
&ObjectAttributes);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
@@ -650,9 +650,29 @@ IntLoadRegistryParameters(VOID)
|
||||
ZwClose(KeyHandle);
|
||||
}
|
||||
|
||||
/* Initialize object attributes with the path we want */
|
||||
#ifdef _M_IX86
|
||||
/* Check whether we need to use the 32-bit x86 emulator instead of V86 mode */
|
||||
RtlInitUnicodeString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\GraphicsDrivers\\DisableEmulator");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&Path,
|
||||
&KeyPath,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenKey(&KeyHandle,
|
||||
KEY_QUERY_VALUE,
|
||||
&ObjectAttributes);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
VideoPortDisableX86Emulator = TRUE;
|
||||
ZwClose(KeyHandle);
|
||||
}
|
||||
DPRINT1("Using %s\n", VideoPortDisableX86Emulator ? "V86 mode" : "x86 emulator");
|
||||
#endif // _M_IX86
|
||||
|
||||
/* Initialize object attributes with the path we want */
|
||||
RtlInitUnicodeString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyPath,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
@@ -677,7 +697,7 @@ IntLoadRegistryParameters(VOID)
|
||||
if (Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
VideoPortDebugPrint(Error, "ZwQueryValueKey failed (0x%x)\n", Status);
|
||||
ObCloseHandle(KeyHandle, KernelMode);
|
||||
ZwClose(KeyHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -686,7 +706,7 @@ IntLoadRegistryParameters(VOID)
|
||||
if (!KeyInfo)
|
||||
{
|
||||
VideoPortDebugPrint(Error, "Out of memory\n");
|
||||
ObCloseHandle(KeyHandle, KernelMode);
|
||||
ZwClose(KeyHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -697,7 +717,7 @@ IntLoadRegistryParameters(VOID)
|
||||
KeyInfo,
|
||||
Length,
|
||||
&NewLength);
|
||||
ObCloseHandle(KeyHandle, KernelMode);
|
||||
ZwClose(KeyHandle);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
@@ -733,10 +753,9 @@ IntLoadRegistryParameters(VOID)
|
||||
/* If we are in BASEVIDEO, create the volatile registry key for Win32k */
|
||||
if (VpBaseVideo)
|
||||
{
|
||||
RtlInitUnicodeString(&Path, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\GraphicsDrivers\\BaseVideo");
|
||||
|
||||
RtlInitUnicodeString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\GraphicsDrivers\\BaseVideo");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&Path,
|
||||
&KeyPath,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
@@ -749,7 +768,7 @@ IntLoadRegistryParameters(VOID)
|
||||
REG_OPTION_VOLATILE,
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
ObCloseHandle(KeyHandle, KernelMode);
|
||||
ZwClose(KeyHandle);
|
||||
else
|
||||
ERR_(VIDEOPRT, "Failed to create the BaseVideo key (0x%x)\n", Status);
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ IntVideoPortMapPhysicalMemory(
|
||||
extern PKPROCESS CsrProcess;
|
||||
extern ULONG VideoPortDeviceNumber;
|
||||
extern BOOLEAN VideoPortUseNewKey;
|
||||
extern KMUTEX VideoPortInt10Mutex;
|
||||
|
||||
extern KSPIN_LOCK HwResetAdaptersLock;
|
||||
extern LIST_ENTRY HwResetAdaptersList;
|
||||
|
||||
@@ -298,43 +298,52 @@ IntVideoPortEnumerateChildren(
|
||||
|
||||
/* int10.c */
|
||||
|
||||
#ifdef _M_IX86
|
||||
extern BOOLEAN VideoPortDisableX86Emulator;
|
||||
#endif
|
||||
extern KMUTEX VideoPortInt10Mutex;
|
||||
|
||||
NTSTATUS
|
||||
IntInitializeInt10(VOID);
|
||||
|
||||
VP_STATUS
|
||||
NTAPI
|
||||
IntInitializeVideoAddressSpace(VOID);
|
||||
|
||||
VP_STATUS NTAPI
|
||||
IntInt10AllocateBuffer(
|
||||
IN PVOID Context,
|
||||
OUT PUSHORT Seg,
|
||||
OUT PUSHORT Off,
|
||||
IN OUT PULONG Length);
|
||||
_In_ PVOID Context,
|
||||
_Out_ PUSHORT Seg,
|
||||
_Out_ PUSHORT Off,
|
||||
_Inout_ PULONG Length);
|
||||
|
||||
VP_STATUS NTAPI
|
||||
VP_STATUS
|
||||
NTAPI
|
||||
IntInt10FreeBuffer(
|
||||
IN PVOID Context,
|
||||
IN USHORT Seg,
|
||||
IN USHORT Off);
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off);
|
||||
|
||||
VP_STATUS NTAPI
|
||||
VP_STATUS
|
||||
NTAPI
|
||||
IntInt10ReadMemory(
|
||||
IN PVOID Context,
|
||||
IN USHORT Seg,
|
||||
IN USHORT Off,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG Length);
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off,
|
||||
_Out_writes_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length);
|
||||
|
||||
VP_STATUS NTAPI
|
||||
VP_STATUS
|
||||
NTAPI
|
||||
IntInt10WriteMemory(
|
||||
IN PVOID Context,
|
||||
IN USHORT Seg,
|
||||
IN USHORT Off,
|
||||
IN PVOID Buffer,
|
||||
IN ULONG Length);
|
||||
_In_ PVOID Context,
|
||||
_In_ USHORT Seg,
|
||||
_In_ USHORT Off,
|
||||
_In_reads_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length);
|
||||
|
||||
VP_STATUS NTAPI
|
||||
VP_STATUS
|
||||
NTAPI
|
||||
IntInt10CallBios(
|
||||
IN PVOID Context,
|
||||
IN OUT PINT10_BIOS_ARGUMENTS BiosArguments);
|
||||
_In_ PVOID Context,
|
||||
_Inout_ PINT10_BIOS_ARGUMENTS BiosArguments);
|
||||
|
||||
/* registry.c */
|
||||
|
||||
@@ -368,5 +377,4 @@ IntCreateRegistryPath(
|
||||
IN ULONG DeviceNumber,
|
||||
OUT PUNICODE_STRING DeviceRegistryPath);
|
||||
|
||||
|
||||
#endif /* VIDEOPRT_H */
|
||||
|
||||
Reference in New Issue
Block a user