[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:
Hermès Bélusca-Maïto
2023-07-26 22:05:53 +02:00
parent 6313ef9d69
commit 89d5a3dbb8
4 changed files with 473 additions and 144 deletions

View File

@@ -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;

View File

@@ -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));

View File

@@ -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);
}

View File

@@ -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 */