summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Rozenfeld <vrozenfe@redhat.com>2013-12-09 21:55:42 +1100
committerVadim Rozenfeld <vrozenfe@redhat.com>2013-12-09 21:55:42 +1100
commita3f72ee429bac7ff0c402d52cb39a0f9b80a61fc (patch)
tree622c1838b3dcbf5040c04020a846fc844fb47ee6
parentd9c6d518c6110e6aa0c65011d0e223f05d4bffea (diff)
Basic VGA support
-rwxr-xr-xqxldod Package/qxldod Package.vcxproj155
-rwxr-xr-xqxldod Package/qxldod Package.vcxproj.filters9
-rwxr-xr-xqxldod.sln47
-rwxr-xr-xqxldod/BaseObject.cpp80
-rwxr-xr-xqxldod/BaseObject.h70
-rwxr-xr-xqxldod/QxlDod.cpp1074
-rwxr-xr-xqxldod/QxlDod.h236
-rwxr-xr-xqxldod/driver.cpp676
-rwxr-xr-xqxldod/driver.h255
-rwxr-xr-xqxldod/qxldod.infbin0 -> 4142 bytes
-rwxr-xr-xqxldod/qxldod.rcbin0 -> 696 bytes
-rwxr-xr-xqxldod/qxldod.vcxproj288
-rwxr-xr-xqxldod/qxldod.vcxproj.filters56
-rwxr-xr-xqxldod/resource.h14
14 files changed, 2960 insertions, 0 deletions
diff --git a/qxldod Package/qxldod Package.vcxproj b/qxldod Package/qxldod Package.vcxproj
new file mode 100755
index 0000000..d783186
--- /dev/null
+++ b/qxldod Package/qxldod Package.vcxproj
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Win8 Debug|Win32">
+ <Configuration>Win8 Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Release|Win32">
+ <Configuration>Win8 Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win7 Debug|Win32">
+ <Configuration>Win7 Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win7 Release|Win32">
+ <Configuration>Win7 Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Vista Debug|Win32">
+ <Configuration>Vista Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Vista Release|Win32">
+ <Configuration>Vista Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Debug|x64">
+ <Configuration>Win8 Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Release|x64">
+ <Configuration>Win8 Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win7 Debug|x64">
+ <Configuration>Win7 Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win7 Release|x64">
+ <Configuration>Win7 Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Vista Debug|x64">
+ <Configuration>Vista Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Vista Release|x64">
+ <Configuration>Vista Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{B8C04B51-4207-491D-A7DD-C54861E8B528}</ProjectGuid>
+ <TemplateGuid>{4605da2c-74a5-4865-98e1-152ef136825f}</TemplateGuid>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <Configuration>Win8 Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ </PropertyGroup>
+ <PropertyGroup Label="Globals">
+ <RootNamespace>qxldod_Package</RootNamespace>
+ <VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VisualStudioVersion)' == '11.0'">$(VCTargetsPath11)</VCTargetsPath>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets">
+ <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+ <ConfigurationType>Utility</ConfigurationType>
+ <DriverType>Package</DriverType>
+ <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|Win32'" Label="Configuration">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Release|Win32'" Label="Configuration">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Debug|Win32'" Label="Configuration">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Release|Win32'" Label="Configuration">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Release|x64'" Label="Configuration">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Debug|x64'" Label="Configuration">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Release|x64'" Label="Configuration">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <PropertyGroup>
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ <EnableDeployment>False</EnableDeployment>
+ <RemoveDriver>True</RemoveDriver>
+ <HardwareIdString />
+ <CommandLine />
+ <DeployFiles />
+ <EnableVerifier>False</EnableVerifier>
+ <AllDrivers>False</AllDrivers>
+ <VerifyProjectOutput>True</VerifyProjectOutput>
+ <VerifyDrivers />
+ <VerifyFlags>133563</VerifyFlags>
+ <PackageDir>$(OutDir)qxldod Package</PackageDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\qxldod\qxldod.vcxproj">
+ <Project>{a6f48fc7-97e9-48ec-bcdf-1e4f9b43aadd}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/qxldod Package/qxldod Package.vcxproj.filters b/qxldod Package/qxldod Package.vcxproj.filters
new file mode 100755
index 0000000..73af436
--- /dev/null
+++ b/qxldod Package/qxldod Package.vcxproj.filters
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Driver Files">
+ <UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ </Filter>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/qxldod.sln b/qxldod.sln
new file mode 100755
index 0000000..2b74fb7
--- /dev/null
+++ b/qxldod.sln
@@ -0,0 +1,47 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qxldod", "qxldod\qxldod.vcxproj", "{A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qxldod Package", "qxldod Package\qxldod Package.vcxproj", "{B8C04B51-4207-491D-A7DD-C54861E8B528}"
+ ProjectSection(ProjectDependencies) = postProject
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD} = {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Win8 Debug|Win32 = Win8 Debug|Win32
+ Win8 Debug|x64 = Win8 Debug|x64
+ Win8 Release|Win32 = Win8 Release|Win32
+ Win8 Release|x64 = Win8 Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|x64.Build.0 = Win8 Debug|x64
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|Win32.Build.0 = Win8 Release|Win32
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|x64.ActiveCfg = Win8 Release|x64
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|x64.Build.0 = Win8 Release|x64
+ {A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}.Win8 Release|x64.Deploy.0 = Win8 Release|x64
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|x64.Build.0 = Win8 Debug|x64
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|Win32.Build.0 = Win8 Release|Win32
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|x64.ActiveCfg = Win8 Release|x64
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|x64.Build.0 = Win8 Release|x64
+ {B8C04B51-4207-491D-A7DD-C54861E8B528}.Win8 Release|x64.Deploy.0 = Win8 Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/qxldod/BaseObject.cpp b/qxldod/BaseObject.cpp
new file mode 100755
index 0000000..0405541
--- /dev/null
+++ b/qxldod/BaseObject.cpp
@@ -0,0 +1,80 @@
+#include "BaseObject.h"
+
+#pragma code_seg("PAGE")
+
+#define QXLTAG 'LXQd'
+
+//
+// New and delete operators
+//
+_When_((PoolType & NonPagedPoolMustSucceed) != 0,
+ __drv_reportError("Must succeed pool allocations are forbidden. "
+ "Allocation failures cause a system crash"))
+void* __cdecl operator new(size_t Size, POOL_TYPE PoolType)
+{
+ PAGED_CODE();
+
+ Size = (Size != 0) ? Size : 1;
+
+ void* pObject = ExAllocatePoolWithTag(PoolType, Size, QXLTAG);
+
+#if DBG
+ if (pObject != NULL)
+ {
+ RtlFillMemory(pObject, Size, 0xCD);
+ }
+#endif // DBG
+
+ return pObject;
+}
+
+_When_((PoolType & NonPagedPoolMustSucceed) != 0,
+ __drv_reportError("Must succeed pool allocations are forbidden. "
+ "Allocation failures cause a system crash"))
+void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType)
+{
+ PAGED_CODE();
+
+ Size = (Size != 0) ? Size : 1;
+
+ void* pObject = ExAllocatePoolWithTag(PoolType, Size, QXLTAG);
+
+#if DBG
+ if (pObject != NULL)
+ {
+ RtlFillMemory(pObject, Size, 0xCD);
+ }
+#endif // DBG
+
+ return pObject;
+}
+
+void __cdecl operator delete(void* pObject)
+{
+ PAGED_CODE();
+
+ if (pObject != NULL)
+ {
+ ExFreePool(pObject);
+ }
+}
+
+void __cdecl operator delete[](void* pObject)
+{
+ PAGED_CODE();
+
+ if (pObject != NULL)
+ {
+ ExFreePool(pObject);
+ }
+}
+
+
+BaseObject::BaseObject(void)
+{
+}
+
+
+BaseObject::~BaseObject(void)
+{
+}
diff --git a/qxldod/BaseObject.h b/qxldod/BaseObject.h
new file mode 100755
index 0000000..fc4ca59
--- /dev/null
+++ b/qxldod/BaseObject.h
@@ -0,0 +1,70 @@
+#pragma once
+extern "C"
+{
+ #define __CPLUSPLUS
+
+ // Standard C-runtime headers
+ #include <stddef.h>
+ #include <string.h>
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ #include <initguid.h>
+
+ // NTOS headers
+ #include <ntddk.h>
+
+ #ifndef FAR
+ #define FAR
+ #endif
+
+ // Windows headers
+ #include <windef.h>
+ #include <winerror.h>
+
+ // Windows GDI headers
+ #include <wingdi.h>
+
+ // Windows DDI headers
+ #include <winddi.h>
+ #include <ntddvdeo.h>
+
+ #include <d3dkmddi.h>
+ #include <d3dkmthk.h>
+
+ #include <ntstrsafe.h>
+ #include <ntintsafe.h>
+
+ #include <dispmprt.h>
+};
+
+//
+// Memory handling
+//
+
+// Defaulting the value of PoolType means that any call to new Foo()
+// will raise a compiler error for being ambiguous. This is to help keep
+// any calls to allocate memory from accidentally NOT going through
+// these functions.
+_When_((PoolType & NonPagedPoolMustSucceed) != 0,
+ __drv_reportError("Must succeed pool allocations are forbidden. "
+ "Allocation failures cause a system crash"))
+void* __cdecl operator new(size_t Size, POOL_TYPE PoolType = PagedPool);
+_When_((PoolType & NonPagedPoolMustSucceed) != 0,
+ __drv_reportError("Must succeed pool allocations are forbidden. "
+ "Allocation failures cause a system crash"))
+void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType = PagedPool);
+void __cdecl operator delete(void* pObject);
+void __cdecl operator delete[](void* pObject);
+
+// Pool allocation tag for the Sample Display Driver. All allocations use this tag.
+
+
+class BaseObject
+{
+public:
+ BaseObject(void);
+ ~BaseObject(void);
+};
+
diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp
new file mode 100755
index 0000000..9717c7d
--- /dev/null
+++ b/qxldod/QxlDod.cpp
@@ -0,0 +1,1074 @@
+#include "driver.h"
+#include "qxldod.h"
+
+QxlDod::QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pPhysicalDeviceObject),
+ m_MonitorPowerState(PowerDeviceD0),
+ m_AdapterPowerState(PowerDeviceD0)
+{
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+ *((UINT*)&m_Flags) = 0;
+ RtlZeroMemory(&m_DxgkInterface, sizeof(m_DxgkInterface));
+ RtlZeroMemory(&m_DeviceInfo, sizeof(m_DeviceInfo));
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+}
+
+
+QxlDod::~QxlDod(void)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+
+// CleanUp();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+}
+
+
+NTSTATUS QxlDod::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo,
+ _In_ DXGKRNL_INTERFACE* pDxgkInterface,
+ _Out_ ULONG* pNumberOfViews,
+ _Out_ ULONG* pNumberOfChildren)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__));
+ QXL_ASSERT(pDxgkStartInfo != NULL);
+ QXL_ASSERT(pDxgkInterface != NULL);
+ QXL_ASSERT(pNumberOfViews != NULL);
+ QXL_ASSERT(pNumberOfChildren != NULL);
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+
+ DXGK_DISPLAY_INFORMATION DisplayInfo;
+ RtlCopyMemory(&m_DxgkInterface, pDxgkInterface, sizeof(m_DxgkInterface));
+ // Get device information from OS.
+ NTSTATUS Status = m_DxgkInterface.DxgkCbGetDeviceInformation(m_DxgkInterface.DeviceHandle, &m_DeviceInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ QXL_LOG_ASSERTION1("DxgkCbGetDeviceInformation failed with status 0x%X\n",
+ Status);
+ return Status;
+ }
+
+ Status = RegisterHWInfo();
+ if (!NT_SUCCESS(Status))
+ {
+ QXL_LOG_ASSERTION1("RegisterHWInfo failed with status 0x%X\n",
+ Status);
+ return Status;
+ }
+
+// TODO: Uncomment the line below after updating the TODOs in the function CheckHardware
+// Status = CheckHardware();
+// if (!NT_SUCCESS(Status))
+// {
+// return Status;
+// }
+
+
+ Status = VbeGetModeList();
+ if (!NT_SUCCESS(Status))
+ {
+ QXL_LOG_ASSERTION1("RegisterHWInfo failed with status 0x%X\n",
+ Status);
+ return Status;
+ }
+
+
+ // This sample driver only uses the frame buffer of the POST device. DxgkCbAcquirePostDisplayOwnership
+ // gives you the frame buffer address and ensures that no one else is drawing to it. Be sure to give it back!
+ Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &DisplayInfo);
+ if (!NT_SUCCESS(Status) || DisplayInfo.Width == 0)
+ {
+ // The most likely cause of failure is that the driver is simply not running on a POST device, or we are running
+ // after a pre-WDDM 1.2 driver. Since we can't draw anything, we should fail to start.
+ return STATUS_UNSUCCESSFUL;
+ }
+ *pNumberOfViews = MAX_VIEWS;
+ *pNumberOfChildren = MAX_CHILDREN;
+ m_Flags.DriverStarted = TRUE;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS QxlDod::StopDevice(VOID)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__));
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ m_Flags.DriverStarted = FALSE;
+ return STATUS_SUCCESS;
+}
+
+VOID QxlDod::CleanUp(VOID)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+}
+
+
+NTSTATUS QxlDod::DispatchIoRequest(_In_ ULONG VidPnSourceId,
+ _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket)
+{
+ PAGED_CODE();
+ UNREFERENCED_PARAMETER(VidPnSourceId);
+ UNREFERENCED_PARAMETER(pVideoRequestPacket);
+
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS QxlDod::SetPowerState(_In_ ULONG HardwareUid,
+ _In_ DEVICE_POWER_STATE DevicePowerState,
+ _In_ POWER_ACTION ActionType)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__));
+
+ if (HardwareUid == DISPLAY_ADAPTER_HW_ID)
+ {
+
+ if (DevicePowerState == PowerDeviceD0)
+ {
+
+ // When returning from D3 the device visibility defined to be off for all targets
+ if (m_AdapterPowerState == PowerDeviceD3)
+ {
+ DXGKARG_SETVIDPNSOURCEVISIBILITY Visibility;
+ Visibility.VidPnSourceId = D3DDDI_ID_ALL;
+ Visibility.Visible = FALSE;
+ SetVidPnSourceVisibility(&Visibility);
+ }
+ }
+
+
+ // Store new adapter power state
+ m_AdapterPowerState = DevicePowerState;
+ }
+
+ if ((ActionType == PowerActionHibernate) &&
+ (DevicePowerState > PowerDeviceD0))
+ {
+ ActionType = PowerActionHibernate;
+ }
+ else if ((ActionType >= PowerActionShutdown) &&
+ (ActionType < PowerActionWarmEject) &&
+ (DevicePowerState > PowerDeviceD0))
+ {
+ ActionType = PowerActionShutdown;
+ }
+
+ Status = VbeSetPowerState(ActionType);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__));
+
+ return Status;
+}
+
+
+NTSTATUS QxlDod::QueryChildRelations(_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
+ _In_ ULONG ChildRelationsSize)
+{
+ PAGED_CODE();
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+ QXL_ASSERT(pChildRelations != NULL);
+
+ // The last DXGK_CHILD_DESCRIPTOR in the array of pChildRelations must remain zeroed out, so we subtract this from the count
+ ULONG ChildRelationsCount = (ChildRelationsSize / sizeof(DXGK_CHILD_DESCRIPTOR)) - 1;
+ QXL_ASSERT(ChildRelationsCount <= MAX_CHILDREN);
+
+ for (UINT ChildIndex = 0; ChildIndex < ChildRelationsCount; ++ChildIndex)
+ {
+ pChildRelations[ChildIndex].ChildDeviceType = TypeVideoOutput;
+ pChildRelations[ChildIndex].ChildCapabilities.HpdAwareness = HpdAwarenessAlwaysConnected;
+ pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_INTERNAL;
+ pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_NONE;
+ pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.SupportsSdtvModes = FALSE;
+ // TODO: Replace 0 with the actual ACPI ID of the child device, if available
+ pChildRelations[ChildIndex].AcpiUid = 0;
+ pChildRelations[ChildIndex].ChildUid = ChildIndex;
+ }
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS QxlDod::QueryChildStatus(_Inout_ DXGK_CHILD_STATUS* pChildStatus,
+ _In_ BOOLEAN NonDestructiveOnly)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+ UNREFERENCED_PARAMETER(NonDestructiveOnly);
+ QXL_ASSERT(pChildStatus != NULL);
+ QXL_ASSERT(pChildStatus->ChildUid < MAX_CHILDREN);
+
+ switch (pChildStatus->Type)
+ {
+ case StatusConnection:
+ {
+ // HpdAwarenessInterruptible was reported since HpdAwarenessNone is deprecated.
+ // However, BDD has no knowledge of HotPlug events, so just always return connected.
+ pChildStatus->HotPlug.Connected = IsDriverActive();
+ return STATUS_SUCCESS;
+ }
+
+ case StatusRotation:
+ {
+ // D3DKMDT_MOA_NONE was reported, so this should never be called
+ DbgPrint(TRACE_LEVEL_ERROR, ("Child status being queried for StatusRotation even though D3DKMDT_MOA_NONE was reported"));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ default:
+ {
+ DbgPrint(TRACE_LEVEL_WARNING, ("Unknown pChildStatus->Type (0x%I64x) requested.", pChildStatus->Type));
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+}
+
+// EDID retrieval
+NTSTATUS QxlDod::QueryDeviceDescriptor(_In_ ULONG ChildUid,
+ _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+ QXL_ASSERT(pDeviceDescriptor != NULL);
+ QXL_ASSERT(ChildUid < MAX_CHILDREN);
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA;
+}
+
+NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
+{
+ PAGED_CODE();
+
+ QXL_ASSERT(pQueryAdapterInfo != NULL);
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+
+ switch (pQueryAdapterInfo->Type)
+ {
+ case DXGKQAITYPE_DRIVERCAPS:
+ {
+ if (pQueryAdapterInfo->OutputDataSize < sizeof(DXGK_DRIVERCAPS))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("pQueryAdapterInfo->OutputDataSize (0x%I64x) is smaller than sizeof(DXGK_DRIVERCAPS) (0x%I64x)", pQueryAdapterInfo->OutputDataSize, sizeof(DXGK_DRIVERCAPS)));
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ DXGK_DRIVERCAPS* pDriverCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData;
+
+ RtlZeroMemory(pDriverCaps, sizeof(DXGK_DRIVERCAPS));
+
+ pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2;
+ pDriverCaps->HighestAcceptableAddress.QuadPart = -1;
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s 1\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+ }
+
+ default:
+ {
+ // BDD does not need to support any other adapter information types
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+}
+
+NTSTATUS QxlDod::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+
+ QXL_ASSERT(pSetPointerPosition != NULL);
+ QXL_ASSERT(pSetPointerPosition->VidPnSourceId < MAX_VIEWS);
+
+ if (!(pSetPointerPosition->Flags.Visible))
+ {
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s Cursor is not visible\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+ }
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s cursor position X = %d, Y = %d\n", __FUNCTION__, pSetPointerPosition->X, pSetPointerPosition->Y));
+ return STATUS_UNSUCCESSFUL;
+}
+
+// Basic Sample Display Driver does not support hardware cursors, and reports such
+// in QueryAdapterInfo. Therefore this function should never be called.
+NTSTATUS QxlDod::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
+{
+ PAGED_CODE();
+ QXL_ASSERT(pSetPointerShape != NULL);
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Height = %d, Width = %d, XHot= %d, YHot = %d\n", __FUNCTION__, pSetPointerShape->Height, pSetPointerShape->Width, pSetPointerShape->XHot, pSetPointerShape->YHot));
+
+ if (pSetPointerShape->Flags.Color)
+ {
+ }
+ else if (pSetPointerShape->Flags.Monochrome)
+ {
+ }
+ else
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS QxlDod::Escape(_In_ CONST DXGKARG_ESCAPE* pEscape)
+{
+ PAGED_CODE();
+ QXL_ASSERT(pEscape != NULL);
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Flags = %d\n", __FUNCTION__, pEscape->Flags));
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+NTSTATUS QxlDod::PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly)
+{
+ PAGED_CODE();
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+ QXL_ASSERT(pPresentDisplayOnly != NULL);
+ QXL_ASSERT(pPresentDisplayOnly->VidPnSourceId < MAX_VIEWS);
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS QxlDod::QueryInterface(_In_ CONST PQUERY_INTERFACE pQueryInterface)
+{
+ PAGED_CODE();
+ QXL_ASSERT(pQueryInterface != NULL);
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s Version = %d\n", __FUNCTION__, pQueryInterface->Version));
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS QxlDod::StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _Out_ DXGK_DISPLAY_INFORMATION* pDisplayInfo)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(pDisplayInfo);
+ QXL_ASSERT(TargetId < MAX_CHILDREN);
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+ return StopDevice();
+}
+
+NTSTATUS QxlDod::QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+
+ QXL_ASSERT(pVidPnHWCaps != NULL);
+ QXL_ASSERT(pVidPnHWCaps->SourceId < MAX_VIEWS);
+ QXL_ASSERT(pVidPnHWCaps->TargetId < MAX_CHILDREN);
+
+ pVidPnHWCaps->VidPnHWCaps.DriverRotation = 1; // BDD does rotation in software
+ pVidPnHWCaps->VidPnHWCaps.DriverScaling = 0; // BDD does not support scaling
+ pVidPnHWCaps->VidPnHWCaps.DriverCloning = 0; // BDD does not support clone
+ pVidPnHWCaps->VidPnHWCaps.DriverColorConvert = 1; // BDD does color conversions in software
+ pVidPnHWCaps->VidPnHWCaps.DriverLinkedAdapaterOutput = 0; // BDD does not support linked adapters
+ pVidPnHWCaps->VidPnHWCaps.DriverRemoteDisplay = 0; // BDD does not support remote displays
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+}
+
+
+// TODO: Need to also check pinned modes and the path parameters, not just topology
+NTSTATUS QxlDod::IsSupportedVidPn(_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+
+ QXL_ASSERT(pIsSupportedVidPn != NULL);
+
+ if (pIsSupportedVidPn->hDesiredVidPn == 0)
+ {
+ // A null desired VidPn is supported
+ pIsSupportedVidPn->IsVidPnSupported = TRUE;
+ return STATUS_SUCCESS;
+ }
+
+ // Default to not supported, until shown it is supported
+ pIsSupportedVidPn->IsVidPnSupported = FALSE;
+
+ CONST DXGK_VIDPN_INTERFACE* pVidPnInterface;
+ NTSTATUS Status = m_DxgkInterface.DxgkCbQueryVidPnInterface(pIsSupportedVidPn->hDesiredVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbQueryVidPnInterface failed with Status = 0x%X, hDesiredVidPn = 0x%I64x\n", Status, pIsSupportedVidPn->hDesiredVidPn));
+ return Status;
+ }
+
+ D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
+ CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
+ Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPn->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("pfnGetTopology failed with Status = 0x%X, hDesiredVidPn = 0x%I64x\n", Status, pIsSupportedVidPn->hDesiredVidPn));
+ return Status;
+ }
+
+ // For every source in this topology, make sure they don't have more paths than there are targets
+ for (D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId = 0; SourceId < MAX_VIEWS; ++SourceId)
+ {
+ SIZE_T NumPathsFromSource = 0;
+ Status = pVidPnTopologyInterface->pfnGetNumPathsFromSource(hVidPnTopology, SourceId, &NumPathsFromSource);
+ if (Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY)
+ {
+ continue;
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("pfnGetNumPathsFromSource failed with Status = 0x%X hVidPnTopology = 0x%I64x, SourceId = 0x%I64x",
+ Status, hVidPnTopology, SourceId));
+ return Status;
+ }
+ else if (NumPathsFromSource > MAX_CHILDREN)
+ {
+ // This VidPn is not supported, which has already been set as the default
+ return STATUS_SUCCESS;
+ }
+ }
+
+ // All sources succeeded so this VidPn is supported
+ pIsSupportedVidPn->IsVidPnSupported = TRUE;
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS QxlDod::RecommendFunctionalVidPn(_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
+
+ QXL_ASSERT(pRecommendFunctionalVidPn == NULL);
+
+ return STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN;
+}
+
+NTSTATUS QxlDod::RecommendVidPnTopology(_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
+
+ QXL_ASSERT(pRecommendVidPnTopology == NULL);
+
+ return STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN;
+}
+
+NTSTATUS QxlDod::RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes)
+{
+ PAGED_CODE();
+ NTSTATUS Status = STATUS_SUCCESS;
+ D3DKMDT_MONITOR_SOURCE_MODE* pMonitorSourceMode = NULL;
+ PVBE_MODEINFO pVbeModeInfo = NULL;
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+
+ Status = pRecommendMonitorModes->pMonitorSourceModeSetInterface->pfnCreateNewModeInfo(pRecommendMonitorModes->hMonitorSourceModeSet, &pMonitorSourceMode);
+ if (!NT_SUCCESS(Status))
+ {
+ // If failed to create a new mode info, mode doesn't need to be released since it was never created
+ DbgPrint(TRACE_LEVEL_ERROR, ("pfnCreateNewModeInfo failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x", Status, pRecommendMonitorModes->hMonitorSourceModeSet));
+ return Status;
+ }
+
+ pVbeModeInfo = &m_ModeInfo[m_CurrentMode];
+ pMonitorSourceMode->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER;
+ pMonitorSourceMode->VideoSignalInfo.TotalSize.cx = pVbeModeInfo->XResolution;//m_CurrentModes[CorrespondingSourceId].DispInfo.Width;
+ pMonitorSourceMode->VideoSignalInfo.TotalSize.cy = pVbeModeInfo->YResolution;//m_CurrentModes[CorrespondingSourceId].DispInfo.Height;
+ pMonitorSourceMode->VideoSignalInfo.ActiveSize = pMonitorSourceMode->VideoSignalInfo.TotalSize;
+ pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pMonitorSourceMode->VideoSignalInfo.HSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pMonitorSourceMode->VideoSignalInfo.HSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pMonitorSourceMode->VideoSignalInfo.PixelRate = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pMonitorSourceMode->VideoSignalInfo.ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE;
+
+ // We set the preference to PREFERRED since this is the only supported mode
+ pMonitorSourceMode->Origin = D3DKMDT_MCO_DRIVER;
+ pMonitorSourceMode->Preference = D3DKMDT_MP_PREFERRED;
+ pMonitorSourceMode->ColorBasis = D3DKMDT_CB_SRGB;
+ pMonitorSourceMode->ColorCoeffDynamicRanges.FirstChannel = 8;
+ pMonitorSourceMode->ColorCoeffDynamicRanges.SecondChannel = 8;
+ pMonitorSourceMode->ColorCoeffDynamicRanges.ThirdChannel = 8;
+ pMonitorSourceMode->ColorCoeffDynamicRanges.FourthChannel = 8;
+
+ Status = pRecommendMonitorModes->pMonitorSourceModeSetInterface->pfnAddMode(pRecommendMonitorModes->hMonitorSourceModeSet, pMonitorSourceMode);
+ if (!NT_SUCCESS(Status))
+ {
+ if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET)
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("pfnAddMode failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x, pMonitorSourceMode = 0x%I64x",
+ Status, pRecommendMonitorModes->hMonitorSourceModeSet, pMonitorSourceMode));
+ }
+ else
+ {
+ Status = STATUS_SUCCESS;
+ }
+
+ // If adding the mode failed, release the mode, if this doesn't work there is nothing that can be done, some memory will get leaked
+ NTSTATUS TempStatus = pRecommendMonitorModes->pMonitorSourceModeSetInterface->pfnReleaseModeInfo(pRecommendMonitorModes->hMonitorSourceModeSet, pMonitorSourceMode);
+ UNREFERENCED_PARAMETER(TempStatus);
+ NT_ASSERT(NT_SUCCESS(TempStatus));
+ return Status;
+ }
+ // If AddMode succeeded with something other than STATUS_SUCCESS treat it as such anyway when propagating up
+ return STATUS_SUCCESS;
+}
+
+// Tell DMM about all the modes, etc. that are supported
+NTSTATUS QxlDod::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality)
+{
+ PAGED_CODE();
+
+ QXL_ASSERT(pEnumCofuncModality != NULL);
+ DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__));
+
+ D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology = 0;
+ D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet = 0;
+ D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet = 0;
+ CONST DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
+ CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface = NULL;
+ CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface = NULL;
+ CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface = NULL;
+ CONST D3DKMDT_VIDPN_PRESENT_PATH* pVidPnPresentPath = NULL;
+ CONST D3DKMDT_VIDPN_PRESENT_PATH* pVidPnPresentPathTemp = NULL; // Used for AcquireNextPathInfo
+ CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnPinnedSourceModeInfo = NULL;
+ CONST D3DKMDT_VIDPN_TARGET_MODE* pVidPnPinnedTargetModeInfo = NULL;
+
+ // Get the VidPn Interface so we can get the 'Source Mode Set', 'Target Mode Set' and 'VidPn Topology' interfaces
+ NTSTATUS Status = m_DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModality->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("DxgkCbQueryVidPnInterface failed with Status = 0x%X, hFunctionalVidPn = 0x%I64x", Status, pEnumCofuncModality->hConstrainingVidPn));
+ return Status;
+ }
+
+ // Get the VidPn Topology interface so we can enumerate all paths
+ Status = pVidPnInterface->pfnGetTopology(pEnumCofuncModality->hConstrainingVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("pfnGetTopology failed with Status = 0x%X, hFunctionalVidPn = 0x%I64x", Status, pEnumCofuncModality->hConstrainingVidPn));
+ return Status;
+ }
+
+ // Get the first path before we start looping through them
+ Status = pVidPnTopologyInterface->pfnAcquireFirstPathInfo(hVidPnTopology, &pVidPnPresentPath);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("pfnAcquireFirstPathInfo failed with Status =0x%X, hVidPnTopology = 0x%I64x", Status, hVidPnTopology));
+ return Status;
+ }
+
+ // Loop through all available paths.
+ while (Status != STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
+ {
+
+//FIXME
+
+ pVidPnPresentPathTemp = NULL; // Successfully released it
+ }// End: while loop for paths in topology
+
+ // If quit the while loop normally, set the return value to success
+ if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
+ {
+ Status = STATUS_SUCCESS;
+ }
+
+ // Release any resources hanging around because the loop was quit early.
+ // Since in normal execution everything should be released by this point, TempStatus is initialized to a bogus error to be used as an
+ // assertion that if anything had to be released now (TempStatus changing) Status isn't successful.
+ NTSTATUS TempStatus = STATUS_NOT_FOUND;
+
+ if ((pVidPnSourceModeSetInterface != NULL) &&
+ (pVidPnPinnedSourceModeInfo != NULL))
+ {
+ TempStatus = pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hVidPnSourceModeSet, pVidPnPinnedSourceModeInfo);
+ QXL_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ if ((pVidPnTargetModeSetInterface != NULL) &&
+ (pVidPnPinnedTargetModeInfo != NULL))
+ {
+ TempStatus = pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pVidPnPinnedTargetModeInfo);
+ QXL_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ if (pVidPnPresentPath != NULL)
+ {
+ TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPath);
+ QXL_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ if (pVidPnPresentPathTemp != NULL)
+ {
+ TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPathTemp);
+ QXL_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ if (hVidPnSourceModeSet != 0)
+ {
+ TempStatus = pVidPnInterface->pfnReleaseSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet);
+ QXL_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ if (hVidPnTargetModeSet != 0)
+ {
+ TempStatus = pVidPnInterface->pfnReleaseTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet);
+ QXL_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ QXL_ASSERT_CHK(TempStatus == STATUS_NOT_FOUND || Status != STATUS_SUCCESS);
+
+ DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__));
+ return Status;
+}
+
+NTSTATUS QxlDod::SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+ QXL_ASSERT(pSetVidPnSourceVisibility != NULL);
+ QXL_ASSERT((pSetVidPnSourceVisibility->VidPnSourceId < MAX_VIEWS) ||
+ (pSetVidPnSourceVisibility->VidPnSourceId == D3DDDI_ID_ALL));
+
+ UINT StartVidPnSourceId = (pSetVidPnSourceVisibility->VidPnSourceId == D3DDDI_ID_ALL) ? 0 : pSetVidPnSourceVisibility->VidPnSourceId;
+ UINT MaxVidPnSourceId = (pSetVidPnSourceVisibility->VidPnSourceId == D3DDDI_ID_ALL) ? MAX_VIEWS : pSetVidPnSourceVisibility->VidPnSourceId + 1;
+
+ for (UINT SourceId = StartVidPnSourceId; SourceId < MaxVidPnSourceId; ++SourceId)
+ {
+ if (pSetVidPnSourceVisibility->Visible)
+ {
+// m_CurrentModes[SourceId].Flags.FullscreenPresent = TRUE;
+ }
+ else
+ {
+// BlackOutScreen(SourceId);
+ }
+
+ // Store current visibility so it can be dealt with during Present call
+// m_CurrentModes[SourceId].Flags.SourceNotVisible = !(pSetVidPnSourceVisibility->Visible);
+ }
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+}
+
+// NOTE: The value of pCommitVidPn->MonitorConnectivityChecks is ignored, since BDD is unable to recognize whether a monitor is connected or not
+// The value of pCommitVidPn->hPrimaryAllocation is also ignored, since BDD is a display only driver and does not deal with allocations
+NTSTATUS QxlDod::CommitVidPn(_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+ QXL_ASSERT(pCommitVidPn != NULL);
+ QXL_ASSERT(pCommitVidPn->AffectedVidPnSourceId < MAX_VIEWS);
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+
+//FIXME
+
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return Status;
+}
+
+NTSTATUS QxlDod::UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+ QXL_ASSERT(pUpdateActiveVidPnPresentPath != NULL);
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+}
+
+
+
+//
+// Non-Paged Code
+//
+#pragma code_seg(push)
+#pragma code_seg()
+
+VOID QxlDod::DpcRoutine(VOID)
+{
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__));
+ m_DxgkInterface.DxgkCbNotifyDpc((HANDLE)m_DxgkInterface.DeviceHandle);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__));
+}
+
+BOOLEAN QxlDod::InterruptRoutine(_In_ ULONG MessageNumber)
+{
+ UNREFERENCED_PARAMETER(MessageNumber);
+
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("---> 0 %s\n", __FUNCTION__));
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__));
+ return TRUE;
+}
+
+VOID QxlDod::ResetDevice(VOID)
+{
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<---> %s\n", __FUNCTION__));
+}
+
+// Must be Non-Paged, as it sets up the display for a bugcheck
+NTSTATUS QxlDod::SystemDisplayEnable(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
+ _Out_ UINT* pWidth,
+ _Out_ UINT* pHeight,
+ _Out_ D3DDDIFORMAT* pColorFormat)
+{
+ UNREFERENCED_PARAMETER(Flags);
+ UNREFERENCED_PARAMETER(pColorFormat);
+ UNREFERENCED_PARAMETER(pWidth);
+ UNREFERENCED_PARAMETER(pHeight);
+ QXL_ASSERT((TargetId < MAX_CHILDREN) || (TargetId == D3DDDI_ID_UNINITIALIZED));
+
+ return STATUS_SUCCESS;
+}
+
+// Must be Non-Paged, as it is called to display the bugcheck screen
+VOID QxlDod::SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VOID* pSource,
+ _In_ UINT SourceWidth,
+ _In_ UINT SourceHeight,
+ _In_ UINT SourceStride,
+ _In_ INT PositionX,
+ _In_ INT PositionY)
+{
+ UNREFERENCED_PARAMETER(pSource);
+ UNREFERENCED_PARAMETER(SourceStride);
+ // Rect will be Offset by PositionX/Y in the src to reset it back to 0
+ RECT Rect;
+ Rect.left = PositionX;
+ Rect.top = PositionY;
+ Rect.right = Rect.left + SourceWidth;
+ Rect.bottom = Rect.top + SourceHeight;
+
+}
+
+#pragma code_seg(pop) // End Non-Paged Code
+
+
+
+NTSTATUS QxlDod::WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue)
+{
+ PAGED_CODE();
+
+ NTSTATUS Status;
+ ANSI_STRING AnsiStrValue;
+ UNICODE_STRING UnicodeStrValue;
+ UNICODE_STRING UnicodeStrValueName;
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+
+ // ZwSetValueKey wants the ValueName as a UNICODE_STRING
+ RtlInitUnicodeString(&UnicodeStrValueName, pszwValueName);
+
+ // REG_SZ is for WCHARs, there is no equivalent for CHARs
+ // Use the ansi/unicode conversion functions to get from PSTR to PWSTR
+ RtlInitAnsiString(&AnsiStrValue, pszValue);
+ Status = RtlAnsiStringToUnicodeString(&UnicodeStrValue, &AnsiStrValue, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("RtlAnsiStringToUnicodeString failed with Status: 0x%X\n", Status));
+ return Status;
+ }
+
+ // Write the value to the registry
+ Status = ZwSetValueKey(DevInstRegKeyHandle,
+ &UnicodeStrValueName,
+ 0,
+ REG_SZ,
+ UnicodeStrValue.Buffer,
+ UnicodeStrValue.MaximumLength);
+
+ // Free the earlier allocated unicode string
+ RtlFreeUnicodeString(&UnicodeStrValue);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("ZwSetValueKey failed with Status: 0x%X\n", Status));
+ }
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return Status;
+}
+
+NTSTATUS QxlDod::RegisterHWInfo()
+{
+ PAGED_CODE();
+
+ NTSTATUS Status;
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+
+ // TODO: Replace these strings with proper information
+ PCSTR StrHWInfoChipType = "QEMU QXL";
+ PCSTR StrHWInfoDacType = "QXL 1B36";
+ PCSTR StrHWInfoAdapterString = "QXL";
+ PCSTR StrHWInfoBiosString = "SEABIOS QXL";
+
+ HANDLE DevInstRegKeyHandle;
+ Status = IoOpenDeviceRegistryKey(m_pPhysicalDevice, PLUGPLAY_REGKEY_DRIVER, KEY_SET_VALUE, &DevInstRegKeyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("IoOpenDeviceRegistryKey failed for PDO: 0x%I64x, Status: 0x%I64x", m_pPhysicalDevice, Status));
+ return Status;
+ }
+
+ Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.ChipType", StrHWInfoChipType);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.DacType", StrHWInfoDacType);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.AdapterString", StrHWInfoAdapterString);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.BiosString", StrHWInfoBiosString);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ // MemorySize is a ULONG, unlike the others which are all strings
+ UNICODE_STRING ValueNameMemorySize;
+ RtlInitUnicodeString(&ValueNameMemorySize, L"HardwareInformation.MemorySize");
+ DWORD MemorySize = 0; // BDD has no access to video memory
+ Status = ZwSetValueKey(DevInstRegKeyHandle,
+ &ValueNameMemorySize,
+ 0,
+ REG_DWORD,
+ &MemorySize,
+ sizeof(MemorySize));
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("ZwSetValueKey for MemorySize failed with Status: 0x%X\n", Status));
+ return Status;
+ }
+
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return Status;
+}
+
+NTSTATUS QxlDod::VbeGetModeList()
+{
+ PAGED_CODE();
+ USHORT m_Segment;
+ USHORT m_Offset;
+ USHORT ModeCount;
+ ULONG SuitableModeCount;
+ USHORT ModeTemp;
+ USHORT CurrentMode;
+ PVBE_MODEINFO VbeModeInfo;
+ VBE_INFO VbeInfo = {0};
+ ULONG Length;
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+//Get VBE Mode List
+ Length = 0x400;
+ Status = x86BiosAllocateBuffer (&Length, &m_Segment, &m_Offset);
+ if (!NT_SUCCESS (Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosAllocateBuffer failed with Status: 0x%X\n", Status));
+ return Status;
+ }
+ DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosAllocateBuffer 0x%x (%x.%x)\n", VbeInfo.VideoModePtr, m_Segment, m_Offset));
+
+ Status = x86BiosWriteMemory (m_Segment, m_Offset, "VBE2", 4);
+
+ if (!NT_SUCCESS (Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosWriteMemory failed with Status: 0x%X\n", Status));
+ return Status;
+ }
+
+ X86BIOS_REGISTERS regs = {0};
+ regs.SegEs = m_Segment;
+ regs.Edi = m_Offset;
+ regs.Eax = 0x4F00;
+ if (!x86BiosCall (0x10, &regs) /* || (regs.Eax & 0xFF00) != 0x4F00 */)
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = x86BiosReadMemory (m_Segment, m_Offset, &VbeInfo, sizeof (VbeInfo));
+ if (!NT_SUCCESS (Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosReadMemory failed with Status: 0x%X\n", Status));
+ return Status;
+ }
+
+ if (!RtlEqualMemory(VbeInfo.Signature, "VESA", 4))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("No VBE BIOS present\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ DbgPrint(TRACE_LEVEL_ERROR, ("VBE BIOS Present (%d.%d, %8ld Kb)\n", VbeInfo.Version / 0x100, VbeInfo.Version & 0xFF, VbeInfo.TotalMemory * 64));
+ DbgPrint(TRACE_LEVEL_ERROR, ("Capabilities = 0x%x\n", VbeInfo.Capabilities));
+ DbgPrint(TRACE_LEVEL_ERROR, ("VideoModePtr = 0x%x (0x%x.0x%x)\n", VbeInfo.VideoModePtr, HIWORD( VbeInfo.VideoModePtr), LOWORD( VbeInfo.VideoModePtr)));
+
+ for (ModeCount = 0; ; ModeCount++)
+ {
+ /* Read the VBE mode number. */
+ Status = x86BiosReadMemory (
+ HIWORD(VbeInfo.VideoModePtr),
+ LOWORD(VbeInfo.VideoModePtr) + (ModeCount << 1),
+ &ModeTemp,
+ sizeof(ModeTemp));
+
+ if (!NT_SUCCESS (Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosReadMemory failed with Status: 0x%X\n", Status));
+ break;
+ }
+ /* End of list? */
+ if (ModeTemp == 0xFFFF || ModeTemp == 0)
+ {
+ break;
+ }
+ }
+
+ DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount %d\n", ModeCount));
+
+ m_ModeInfo = reinterpret_cast<PVBE_MODEINFO> (new (PagedPool) BYTE[sizeof (VBE_MODEINFO) * ModeCount]);
+ m_ModeNumbers = reinterpret_cast<PUSHORT> (new (PagedPool) BYTE [sizeof (USHORT) * ModeCount]);
+ m_CurrentMode = 0;
+ DbgPrint(TRACE_LEVEL_ERROR, ("m_ModeInfo = 0x%p, m_ModeNumbers = 0x%p\n", m_ModeInfo, m_ModeNumbers));
+ for (CurrentMode = 0, SuitableModeCount = 0;
+ CurrentMode < ModeCount;
+ CurrentMode++)
+ {
+ Status = x86BiosReadMemory (
+ HIWORD(VbeInfo.VideoModePtr),
+ LOWORD(VbeInfo.VideoModePtr) + (CurrentMode << 1),
+ &ModeTemp,
+ sizeof(ModeTemp));
+
+ if (!NT_SUCCESS (Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosReadMemory failed with Status: 0x%X\n", Status));
+ break;
+ }
+
+ DbgPrint(TRACE_LEVEL_ERROR, ("ModeTemp = 0x%X\n", ModeTemp));
+ RtlZeroMemory(&regs, sizeof(regs));
+ regs.Eax = 0x4F01;
+ regs.Ecx = ModeTemp;
+ regs.Edi = m_Offset + sizeof (VbeInfo);
+ regs.SegEs = m_Segment;
+ if (!x86BiosCall (0x10, &regs))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+ Status = x86BiosReadMemory (
+ m_Segment,
+ m_Offset + sizeof (VbeInfo),
+ m_ModeInfo + SuitableModeCount,
+ sizeof(VBE_MODEINFO));
+
+ VbeModeInfo = m_ModeInfo + SuitableModeCount;
+
+ if (VbeModeInfo->XResolution >= 1024 &&
+ VbeModeInfo->YResolution >= 768 &&
+ VbeModeInfo->BitsPerPixel == 32 &&
+ VbeModeInfo->PhysBasePtr != 0)
+ {
+ m_ModeNumbers[SuitableModeCount] = ModeTemp;
+ if (VbeModeInfo->XResolution == 1024 &&
+ VbeModeInfo->YResolution == 768)
+ {
+ m_CurrentMode = (USHORT)SuitableModeCount;
+ }
+ SuitableModeCount++;
+ }
+ }
+
+ if (SuitableModeCount == 0)
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("No video modes supported\n"));
+ Status = STATUS_UNSUCCESSFUL;
+ }
+
+ m_ModeCount = SuitableModeCount;
+ DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount));
+
+ if (m_Segment != 0)
+ {
+ x86BiosFreeBuffer (m_Segment, m_Offset);
+ }
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return Status;
+}
+
+NTSTATUS QxlDod::VbeQueryCurrentMode(PVIDEO_MODE RequestedMode)
+{
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ NTSTATUS Status = STATUS_SUCCESS;
+ PVBE_MODEINFO VBEMode = &m_ModeInfo[m_CurrentMode];
+
+ return Status;
+}
+
+NTSTATUS QxlDod::VbeSetCurrentMode(PVIDEO_MODE RequestedMode)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+ X86BIOS_REGISTERS regs = {0};
+ regs.Eax = 0x4F02;
+ regs.Edx = m_ModeNumbers[RequestedMode->RequestedMode];
+ if (!x86BiosCall (0x10, &regs))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+ m_CurrentMode = (USHORT)RequestedMode->RequestedMode;
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return Status;
+}
+
+NTSTATUS QxlDod::VbeSetPowerState(POWER_ACTION ActionType)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
+
+ X86BIOS_REGISTERS regs = {0};
+ regs.Eax = 0x4F10;
+ regs.Ebx = 1;
+ switch (ActionType)
+ {
+ case PowerActionSleep: regs.Ebx |= 0x100; break;
+ case PowerActionHibernate: regs.Ebx |= 0x200; break;
+ case PowerActionShutdown:
+ case PowerActionShutdownReset:
+ case PowerActionShutdownOff: regs.Ebx |= 0x400; break;
+ }
+ if (!x86BiosCall (0x10, &regs))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("x86BiosCall failed\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+ DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+ return Status;
+}
diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h
new file mode 100755
index 0000000..18ec7b1
--- /dev/null
+++ b/qxldod/QxlDod.h
@@ -0,0 +1,236 @@
+#pragma once
+#include "baseobject.h"
+
+typedef struct _QXL_FLAGS
+{
+ UINT DriverStarted : 1; // ( 1) 1 after StartDevice and 0 after StopDevice
+ UINT Unused : 31;
+} QXL_FLAGS;
+
+#define MAX_CHILDREN 1
+#define MAX_VIEWS 1
+
+#pragma pack(push)
+#pragma pack(1)
+
+typedef struct
+{
+ CHAR Signature[4];
+ USHORT Version;
+ ULONG OemStringPtr;
+ LONG Capabilities;
+ ULONG VideoModePtr;
+ USHORT TotalMemory;
+ USHORT OemSoftwareRevision;
+ ULONG OemVendorNamePtr;
+ ULONG OemProductNamePtr;
+ ULONG OemProductRevPtr;
+ CHAR Reserved[222];
+// CHAR OemData[256];
+} VBE_INFO, *PVBE_INFO;
+
+typedef struct
+{
+/* Mandatory information for all VBE revisions */
+ USHORT ModeAttributes;
+ UCHAR WinAAttributes;
+ UCHAR WinBAttributes;
+ USHORT WinGranularity;
+ USHORT WinSize;
+ USHORT WinASegment;
+ USHORT WinBSegment;
+ ULONG WinFuncPtr;
+ USHORT BytesPerScanLine;
+/* Mandatory information for VBE 1.2 and above */
+ USHORT XResolution;
+ USHORT YResolution;
+ UCHAR XCharSize;
+ UCHAR YCharSize;
+ UCHAR NumberOfPlanes;
+ UCHAR BitsPerPixel;
+ UCHAR NumberOfBanks;
+ UCHAR MemoryModel;
+ UCHAR BankSize;
+ UCHAR NumberOfImagePages;
+ UCHAR Reserved1;
+/* Direct Color fields (required for Direct/6 and YUV/7 memory models) */
+ UCHAR RedMaskSize;
+ UCHAR RedFieldPosition;
+ UCHAR GreenMaskSize;
+ UCHAR GreenFieldPosition;
+ UCHAR BlueMaskSize;
+ UCHAR BlueFieldPosition;
+ UCHAR ReservedMaskSize;
+ UCHAR ReservedFieldPosition;
+ UCHAR DirectColorModeInfo;
+/* Mandatory information for VBE 2.0 and above */
+ ULONG PhysBasePtr;
+ ULONG Reserved2;
+ USHORT Reserved3;
+ /* Mandatory information for VBE 3.0 and above */
+ USHORT LinBytesPerScanLine;
+ UCHAR BnkNumberOfImagePages;
+ UCHAR LinNumberOfImagePages;
+ UCHAR LinRedMaskSize;
+ UCHAR LinRedFieldPosition;
+ UCHAR LinGreenMaskSize;
+ UCHAR LinGreenFieldPosition;
+ UCHAR LinBlueMaskSize;
+ UCHAR LinBlueFieldPosition;
+ UCHAR LinReservedMaskSize;
+ UCHAR LinReservedFieldPosition;
+ ULONG MaxPixelClock;
+ CHAR Reserved4[189];
+} VBE_MODEINFO, *PVBE_MODEINFO;
+
+#pragma pack(pop)
+
+typedef struct _X86BIOS_REGISTERS // invented names
+{
+ ULONG Eax;
+ ULONG Ecx;
+ ULONG Edx;
+ ULONG Ebx;
+ ULONG Ebp;
+ ULONG Esi;
+ ULONG Edi;
+ USHORT SegDs;
+ USHORT SegEs;
+} X86BIOS_REGISTERS, *PX86BIOS_REGISTERS;
+
+/* Undocumented imports from the HAL */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NTHALAPI BOOLEAN x86BiosCall (ULONG, PX86BIOS_REGISTERS);
+
+NTHALAPI NTSTATUS x86BiosAllocateBuffer (ULONG *, USHORT *, USHORT *);
+NTHALAPI NTSTATUS x86BiosFreeBuffer (USHORT, USHORT);
+
+NTHALAPI NTSTATUS x86BiosReadMemory (USHORT, USHORT, PVOID, ULONG);
+NTHALAPI NTSTATUS x86BiosWriteMemory (USHORT, USHORT, PVOID, ULONG);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+class QxlDod :
+ public BaseObject
+{
+private:
+ DEVICE_OBJECT* m_pPhysicalDevice;
+ DXGKRNL_INTERFACE m_DxgkInterface;
+ DXGK_DEVICE_INFO m_DeviceInfo;
+
+ DEVICE_POWER_STATE m_MonitorPowerState;
+ DEVICE_POWER_STATE m_AdapterPowerState;
+ QXL_FLAGS m_Flags;
+ PVBE_MODEINFO m_ModeInfo;
+ ULONG m_ModeCount;
+ PUSHORT m_ModeNumbers;
+ USHORT m_CurrentMode;
+public:
+ QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject);
+ ~QxlDod(void);
+#pragma code_seg(push)
+#pragma code_seg()
+ BOOLEAN IsDriverActive() const
+ {
+ return m_Flags.DriverStarted;
+ }
+#pragma code_seg(pop)
+
+ NTSTATUS StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo,
+ _In_ DXGKRNL_INTERFACE* pDxgkInterface,
+ _Out_ ULONG* pNumberOfViews,
+ _Out_ ULONG* pNumberOfChildren);
+ NTSTATUS StopDevice(VOID);
+ // Must be Non-Paged
+ VOID ResetDevice(VOID);
+
+ NTSTATUS DispatchIoRequest(_In_ ULONG VidPnSourceId,
+ _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket);
+ NTSTATUS SetPowerState(_In_ ULONG HardwareUid,
+ _In_ DEVICE_POWER_STATE DevicePowerState,
+ _In_ POWER_ACTION ActionType);
+ // Report back child capabilities
+ NTSTATUS QueryChildRelations(_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
+ _In_ ULONG ChildRelationsSize);
+
+ NTSTATUS QueryChildStatus(_Inout_ DXGK_CHILD_STATUS* pChildStatus,
+ _In_ BOOLEAN NonDestructiveOnly);
+
+ // Return EDID if previously retrieved
+ NTSTATUS QueryDeviceDescriptor(_In_ ULONG ChildUid,
+ _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor);
+
+ // Must be Non-Paged
+ // BDD doesn't have interrupts, so just returns false
+ BOOLEAN InterruptRoutine(_In_ ULONG MessageNumber);
+
+ VOID DpcRoutine(VOID);
+
+ // Return DriverCaps, doesn't support other queries though
+ NTSTATUS QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo);
+
+ NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition);
+
+ NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape);
+
+ NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscape);
+
+ NTSTATUS PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly);
+
+ NTSTATUS QueryInterface(_In_ CONST PQUERY_INTERFACE QueryInterface);
+
+ NTSTATUS IsSupportedVidPn(_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn);
+
+ NTSTATUS RecommendFunctionalVidPn(_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn);
+
+ NTSTATUS RecommendVidPnTopology(_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology);
+
+ NTSTATUS RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes);
+
+ NTSTATUS EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality);
+
+ NTSTATUS SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility);
+
+ NTSTATUS CommitVidPn(_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn);
+
+ NTSTATUS UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath);
+
+ NTSTATUS QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps);
+
+ // Part of PnPStop (PnP instance only), returns current mode information (which will be passed to fallback instance by dxgkrnl)
+ NTSTATUS StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _Out_ DXGK_DISPLAY_INFORMATION* pDisplayInfo);
+
+ // Must be Non-Paged
+ // Call to initialize as part of bugcheck
+ NTSTATUS SystemDisplayEnable(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
+ _Out_ UINT* pWidth,
+ _Out_ UINT* pHeight,
+ _Out_ D3DDDIFORMAT* pColorFormat);
+
+ // Must be Non-Paged
+ // Write out pixels as part of bugcheck
+ VOID SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VOID* pSource,
+ _In_ UINT SourceWidth,
+ _In_ UINT SourceHeight,
+ _In_ UINT SourceStride,
+ _In_ INT PositionX,
+ _In_ INT PositionY);
+private:
+ VOID CleanUp(VOID);
+ NTSTATUS WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue);
+ NTSTATUS RegisterHWInfo();
+ NTSTATUS VbeGetModeList();
+ NTSTATUS VbeQueryCurrentMode(PVIDEO_MODE RequestedMode);
+ NTSTATUS VbeSetCurrentMode(PVIDEO_MODE RequestedMode);
+ NTSTATUS VbeSetPowerState(POWER_ACTION ActionType);
+};
+
diff --git a/qxldod/driver.cpp b/qxldod/driver.cpp
new file mode 100755
index 0000000..546fc88
--- /dev/null
+++ b/qxldod/driver.cpp
@@ -0,0 +1,676 @@
+#include "driver.h"
+#include "QxlDod.h"
+
+#pragma code_seg(push)
+#pragma code_seg("INIT")
+// BEGIN: Init Code
+
+//
+// Driver Entry point
+//
+
+int nDebugLevel = TRACE_LEVEL_VERBOSE;
+
+
+extern "C"
+NTSTATUS
+DriverEntry(
+ _In_ DRIVER_OBJECT* pDriverObject,
+ _In_ UNICODE_STRING* pRegistryPath)
+{
+ PAGED_CODE();
+
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("---> KMDOD build on on %s %s\n", __DATE__, __TIME__));
+
+#ifdef DBG
+// KdBreakPoint();
+#endif
+ // Initialize DDI function pointers and dxgkrnl
+ KMDDOD_INITIALIZATION_DATA InitialData = {0};
+
+ InitialData.Version = DXGKDDI_INTERFACE_VERSION_WIN8;
+
+ InitialData.DxgkDdiAddDevice = DodAddDevice;
+ InitialData.DxgkDdiStartDevice = DodStartDevice;
+ InitialData.DxgkDdiStopDevice = DodStopDevice;
+ InitialData.DxgkDdiResetDevice = DodResetDevice;
+ InitialData.DxgkDdiRemoveDevice = DodRemoveDevice;
+ InitialData.DxgkDdiDispatchIoRequest = DodDispatchIoRequest;
+ InitialData.DxgkDdiInterruptRoutine = DodInterruptRoutine;
+ InitialData.DxgkDdiDpcRoutine = DodDpcRoutine;
+ InitialData.DxgkDdiQueryChildRelations = DodQueryChildRelations;
+ InitialData.DxgkDdiQueryChildStatus = DodQueryChildStatus;
+ InitialData.DxgkDdiQueryDeviceDescriptor = DodQueryDeviceDescriptor;
+ InitialData.DxgkDdiSetPowerState = DodSetPowerState;
+ InitialData.DxgkDdiUnload = DodUnload;
+ InitialData.DxgkDdiQueryInterface = DodQueryInterface;
+ InitialData.DxgkDdiQueryAdapterInfo = DodQueryAdapterInfo;
+ InitialData.DxgkDdiSetPointerPosition = DodSetPointerPosition;
+ InitialData.DxgkDdiSetPointerShape = DodSetPointerShape;
+ InitialData.DxgkDdiEscape = DodEscape;
+ InitialData.DxgkDdiIsSupportedVidPn = DodIsSupportedVidPn;
+ InitialData.DxgkDdiRecommendFunctionalVidPn = DodRecommendFunctionalVidPn;
+ InitialData.DxgkDdiEnumVidPnCofuncModality = DodEnumVidPnCofuncModality;
+ InitialData.DxgkDdiSetVidPnSourceVisibility = DodSetVidPnSourceVisibility;
+ InitialData.DxgkDdiCommitVidPn = DodCommitVidPn;
+ InitialData.DxgkDdiUpdateActiveVidPnPresentPath = DodUpdateActiveVidPnPresentPath;
+ InitialData.DxgkDdiRecommendMonitorModes = DodRecommendMonitorModes;
+ InitialData.DxgkDdiQueryVidPnHWCapability = DodQueryVidPnHWCapability;
+ InitialData.DxgkDdiPresentDisplayOnly = DodPresentDisplayOnly;
+ InitialData.DxgkDdiStopDeviceAndReleasePostDisplayOwnership = DodStopDeviceAndReleasePostDisplayOwnership;
+ InitialData.DxgkDdiSystemDisplayEnable = DodSystemDisplayEnable;
+ InitialData.DxgkDdiSystemDisplayWrite = DodSystemDisplayWrite;
+
+ NTSTATUS Status = DxgkInitializeDisplayOnlyDriver(pDriverObject, pRegistryPath, &InitialData);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("DxgkInitializeDisplayOnlyDriver failed with Status: 0x%X\n", Status));
+ }
+
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__));
+ return Status;
+}
+// END: Init Code
+#pragma code_seg(pop)
+
+#pragma code_seg(push)
+#pragma code_seg("PAGE")
+
+//
+// PnP DDIs
+//
+
+VOID
+DodUnload(VOID)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<--> %s\n", __FUNCTION__));
+}
+
+NTSTATUS
+DodAddDevice(
+ _In_ DEVICE_OBJECT* pPhysicalDeviceObject,
+ _Outptr_ PVOID* ppDeviceContext)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__));
+
+ if ((pPhysicalDeviceObject == NULL) ||
+ (ppDeviceContext == NULL))
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("One of pPhysicalDeviceObject (0x%I64x), ppDeviceContext (0x%I64x) is NULL",
+ pPhysicalDeviceObject, ppDeviceContext));
+ return STATUS_INVALID_PARAMETER;
+ }
+ *ppDeviceContext = NULL;
+
+ QxlDod* pQxl = new(NonPagedPoolNx) QxlDod(pPhysicalDeviceObject);
+ if (pQxl == NULL)
+ {
+ DbgPrint(TRACE_LEVEL_ERROR, ("pQxl failed to be allocated"));
+ return STATUS_NO_MEMORY;
+ }
+
+ *ppDeviceContext = pQxl;
+
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+DodRemoveDevice(
+ _In_ VOID* pDeviceContext)
+{
+ PAGED_CODE();
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+
+ if (pQxl)
+ {
+ delete pQxl;
+ pQxl = NULL;
+ }
+
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+DodStartDevice(
+ _In_ VOID* pDeviceContext,
+ _In_ DXGK_START_INFO* pDxgkStartInfo,
+ _In_ DXGKRNL_INTERFACE* pDxgkInterface,
+ _Out_ ULONG* pNumberOfViews,
+ _Out_ ULONG* pNumberOfChildren)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ return pQxl->StartDevice(pDxgkStartInfo, pDxgkInterface, pNumberOfViews, pNumberOfChildren);
+}
+
+NTSTATUS
+DodStopDevice(
+ _In_ VOID* pDeviceContext)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ return pQxl->StopDevice();
+}
+
+
+NTSTATUS
+DodDispatchIoRequest(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG VidPnSourceId,
+ _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->DispatchIoRequest(VidPnSourceId, pVideoRequestPacket);
+}
+
+NTSTATUS
+DodSetPowerState(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG HardwareUid,
+ _In_ DEVICE_POWER_STATE DevicePowerState,
+ _In_ POWER_ACTION ActionType)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ if (!pQxl->IsDriverActive())
+ {
+ // If the driver isn't active, SetPowerState can still be called, however in QXL's case
+ // this shouldn't do anything, as it could for instance be called on QXL Fallback after
+ // Fallback has been stopped and QXL PnP is being started. Fallback doesn't have control
+ // of the hardware in this case.
+ return STATUS_SUCCESS;
+ }
+ return pQxl->SetPowerState(HardwareUid, DevicePowerState, ActionType);
+}
+
+NTSTATUS
+DodQueryChildRelations(
+ _In_ VOID* pDeviceContext,
+ _Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
+ _In_ ULONG ChildRelationsSize)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ return pQxl->QueryChildRelations(pChildRelations, ChildRelationsSize);
+}
+
+NTSTATUS
+DodQueryChildStatus(
+ _In_ VOID* pDeviceContext,
+ _Inout_ DXGK_CHILD_STATUS* pChildStatus,
+ _In_ BOOLEAN NonDestructiveOnly)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ return pQxl->QueryChildStatus(pChildStatus, NonDestructiveOnly);
+}
+
+NTSTATUS
+DodQueryDeviceDescriptor(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG ChildUid,
+ _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ if (!pQxl->IsDriverActive())
+ {
+ // During stress testing of PnPStop, it is possible for QXL Fallback to get called to start then stop in quick succession.
+ // The first call queues a worker thread item indicating that it now has a child device, the second queues a worker thread
+ // item that it no longer has any child device. This function gets called based on the first worker thread item, but after
+ // the driver has been stopped. Therefore instead of asserting like other functions, we only warn.
+ DbgPrint(TRACE_LEVEL_WARNING, ("QXL (0x%I64x) is being called when not active!", pQxl));
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->QueryDeviceDescriptor(ChildUid, pDeviceDescriptor);
+}
+
+
+//
+// WDDM Display Only Driver DDIs
+//
+
+NTSTATUS
+APIENTRY
+DodQueryAdapterInfo(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ return pQxl->QueryAdapterInfo(pQueryAdapterInfo);
+}
+
+NTSTATUS
+APIENTRY
+DodSetPointerPosition(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->SetPointerPosition(pSetPointerPosition);
+}
+
+NTSTATUS
+APIENTRY
+DodSetPointerShape(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->SetPointerShape(pSetPointerShape);
+}
+
+NTSTATUS
+APIENTRY
+DodEscape(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_ESCAPE* pEscape
+ )
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ return pQxl->Escape(pEscape);
+}
+
+NTSTATUS
+DodQueryInterface(
+ _In_ CONST PVOID pDeviceContext,
+ _In_ CONST PQUERY_INTERFACE QueryInterface
+ )
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ return pQxl->QueryInterface(QueryInterface);
+}
+
+NTSTATUS
+APIENTRY
+DodPresentDisplayOnly(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+// DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->PresentDisplayOnly(pPresentDisplayOnly);
+}
+
+NTSTATUS
+APIENTRY
+DodStopDeviceAndReleasePostDisplayOwnership(
+ _In_ VOID* pDeviceContext,
+ _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _Out_ DXGK_DISPLAY_INFORMATION* DisplayInfo)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ return pQxl->StopDeviceAndReleasePostDisplayOwnership(TargetId, DisplayInfo);
+}
+
+NTSTATUS
+APIENTRY
+DodIsSupportedVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ // This path might hit because win32k/dxgport doesn't check that an adapter is active when taking the adapter lock.
+ // The adapter lock is the main thing QXL Fallback relies on to not be called while it's inactive. It is still a rare
+ // timing issue around PnpStart/Stop and isn't expected to have any effect on the stability of the system.
+ DbgPrint(TRACE_LEVEL_WARNING, ("QXL (0x%I64x) is being called when not active!", pQxl));
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->IsSupportedVidPn(pIsSupportedVidPn);
+}
+
+NTSTATUS
+APIENTRY
+DodRecommendFunctionalVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->RecommendFunctionalVidPn(pRecommendFunctionalVidPn);
+}
+
+NTSTATUS
+APIENTRY
+DodRecommendVidPnTopology(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->RecommendVidPnTopology(pRecommendVidPnTopology);
+}
+
+NTSTATUS
+APIENTRY
+DodRecommendMonitorModes(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->RecommendMonitorModes(pRecommendMonitorModes);
+}
+
+NTSTATUS
+APIENTRY
+DodEnumVidPnCofuncModality(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->EnumVidPnCofuncModality(pEnumCofuncModality);
+}
+
+NTSTATUS
+APIENTRY
+DodSetVidPnSourceVisibility(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->SetVidPnSourceVisibility(pSetVidPnSourceVisibility);
+}
+
+NTSTATUS
+APIENTRY
+DodCommitVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->CommitVidPn(pCommitVidPn);
+}
+
+NTSTATUS
+APIENTRY
+DodUpdateActiveVidPnPresentPath(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->UpdateActiveVidPnPresentPath(pUpdateActiveVidPnPresentPath);
+}
+
+NTSTATUS
+APIENTRY
+DodQueryVidPnHWCapability(
+ _In_ CONST HANDLE hAdapter,
+ _Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps)
+{
+ PAGED_CODE();
+ QXL_ASSERT_CHK(hAdapter != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(hAdapter);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pQxl->QueryVidPnHWCapability(pVidPnHWCaps);
+}
+
+//END: Paged Code
+#pragma code_seg(pop)
+
+#pragma code_seg(push)
+#pragma code_seg()
+// BEGIN: Non-Paged Code
+
+VOID
+DodDpcRoutine(
+ _In_ VOID* pDeviceContext)
+{
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ if (!pQxl->IsDriverActive())
+ {
+ QXL_LOG_ASSERTION1("QXL (0x%I64x) is being called when not active!", pQxl);
+ return;
+ }
+ pQxl->DpcRoutine();
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__));
+}
+
+BOOLEAN
+DodInterruptRoutine(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG MessageNumber)
+{
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ return pQxl->InterruptRoutine(MessageNumber);
+}
+
+VOID
+DodResetDevice(
+ _In_ VOID* pDeviceContext)
+{
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ pQxl->ResetDevice();
+}
+
+NTSTATUS
+APIENTRY
+DodSystemDisplayEnable(
+ _In_ VOID* pDeviceContext,
+ _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
+ _Out_ UINT* Width,
+ _Out_ UINT* Height,
+ _Out_ D3DDDIFORMAT* ColorFormat)
+{
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ return pQxl->SystemDisplayEnable(TargetId, Flags, Width, Height, ColorFormat);
+}
+
+VOID
+APIENTRY
+DodSystemDisplayWrite(
+ _In_ VOID* pDeviceContext,
+ _In_ VOID* Source,
+ _In_ UINT SourceWidth,
+ _In_ UINT SourceHeight,
+ _In_ UINT SourceStride,
+ _In_ UINT PositionX,
+ _In_ UINT PositionY)
+{
+ QXL_ASSERT_CHK(pDeviceContext != NULL);
+ DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s\n", __FUNCTION__));
+
+ QxlDod* pQxl = reinterpret_cast<QxlDod*>(pDeviceContext);
+ pQxl->SystemDisplayWrite(Source, SourceWidth, SourceHeight, SourceStride, PositionX, PositionY);
+}
+
+#if defined(DBG)
+
+#define RHEL_DEBUG_PORT ((PUCHAR)0x3F8)
+#define TEMP_BUFFER_SIZE 256
+
+void DebugPrintFuncSerial(const char *format, ...)
+{
+ char buf[TEMP_BUFFER_SIZE];
+ NTSTATUS status;
+ size_t len;
+ va_list list;
+ va_start(list, format);
+ status = RtlStringCbVPrintfA(buf, sizeof(buf), format, list);
+ if (status == STATUS_SUCCESS)
+ {
+ len = strlen(buf);
+ }
+ else
+ {
+ len = 2;
+ buf[0] = 'O';
+ buf[1] = '\n';
+ }
+ if (len)
+ {
+ WRITE_PORT_BUFFER_UCHAR(RHEL_DEBUG_PORT, (PUCHAR)buf, len);
+ WRITE_PORT_UCHAR(RHEL_DEBUG_PORT, '\r');
+ }
+}
+
+void DebugPrintFunc(const char *format, ...)
+{
+ va_list list;
+ va_start(list, format);
+ vDbgPrintEx(DPFLTR_DEFAULT_ID, 9 | DPFLTR_MASK, format, list);
+}
+#endif
+
+#pragma code_seg(pop) // End Non-Paged Code
+
diff --git a/qxldod/driver.h b/qxldod/driver.h
new file mode 100755
index 0000000..72a8b46
--- /dev/null
+++ b/qxldod/driver.h
@@ -0,0 +1,255 @@
+#pragma once
+#include "BaseObject.h"
+
+
+extern "C"
+DRIVER_INITIALIZE DriverEntry;
+
+//
+// PnP DDIs
+//
+
+VOID
+DodUnload(VOID);
+
+// If uncommenting ENABLE_DXGK_SAL in the sources file, all the below function prototypes should be updated to use
+// the function typedef's from the header files. Additionally, annotations on the function definitions can be removed
+// as they are inherited from the prototype definition here. As an example the entire 4-line prototype for BddDdiAddDevice
+// is replaced by the single commented line below:
+// DXGKDDI_ADD_DEVICE BddDdiAddDevice;
+NTSTATUS
+DodAddDevice(
+ _In_ DEVICE_OBJECT* pPhysicalDeviceObject,
+ _Outptr_ PVOID* ppDeviceContext);
+
+NTSTATUS
+DodRemoveDevice(
+ _In_ VOID* pDeviceContext);
+
+NTSTATUS
+DodStartDevice(
+ _In_ VOID* pDeviceContext,
+ _In_ DXGK_START_INFO* pDxgkStartInfo,
+ _In_ DXGKRNL_INTERFACE* pDxgkInterface,
+ _Out_ ULONG* pNumberOfViews,
+ _Out_ ULONG* pNumberOfChildren);
+
+NTSTATUS
+DodStopDevice(
+ _In_ VOID* pDeviceContext);
+
+VOID
+DodResetDevice(
+ _In_ VOID* pDeviceContext);
+
+
+NTSTATUS
+DodDispatchIoRequest(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG VidPnSourceId,
+ _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket);
+
+NTSTATUS
+DodSetPowerState(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG HardwareUid,
+ _In_ DEVICE_POWER_STATE DevicePowerState,
+ _In_ POWER_ACTION ActionType);
+
+NTSTATUS
+DodQueryChildRelations(
+ _In_ VOID* pDeviceContext,
+ _Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
+ _In_ ULONG ChildRelationsSize);
+
+NTSTATUS
+DodQueryChildStatus(
+ _In_ VOID* pDeviceContext,
+ _Inout_ DXGK_CHILD_STATUS* pChildStatus,
+ _In_ BOOLEAN NonDestructiveOnly);
+
+NTSTATUS
+DodQueryDeviceDescriptor(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG ChildUid,
+ _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor);
+
+// Must be Non-Paged
+BOOLEAN
+DodInterruptRoutine(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG MessageNumber);
+
+VOID
+DodDpcRoutine(
+ _In_ VOID* pDeviceContext);
+
+//
+// WDDM Display Only Driver DDIs
+//
+
+NTSTATUS
+APIENTRY
+DodQueryAdapterInfo(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo);
+
+NTSTATUS
+APIENTRY
+DodSetPointerPosition(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition);
+
+NTSTATUS
+APIENTRY
+DodSetPointerShape(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape);
+
+NTSTATUS
+APIENTRY
+DodEscape(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_ESCAPE* pEscape);
+
+NTSTATUS
+DodQueryInterface(
+ _In_ CONST PVOID pDeviceContext,
+ _In_ CONST PQUERY_INTERFACE pQueryInterface);
+
+NTSTATUS
+APIENTRY
+DodPresentDisplayOnly(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly);
+
+NTSTATUS
+APIENTRY
+DodIsSupportedVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn);
+
+NTSTATUS
+APIENTRY
+DodRecommendFunctionalVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn);
+
+NTSTATUS
+APIENTRY
+DodRecommendVidPnTopology(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology);
+
+NTSTATUS
+APIENTRY
+DodRecommendMonitorModes(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes);
+
+NTSTATUS
+APIENTRY
+DodEnumVidPnCofuncModality(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality);
+
+NTSTATUS
+APIENTRY
+DodSetVidPnSourceVisibility(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility);
+
+NTSTATUS
+APIENTRY
+DodCommitVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn);
+
+NTSTATUS
+APIENTRY
+DodUpdateActiveVidPnPresentPath(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath);
+
+NTSTATUS
+APIENTRY
+DodQueryVidPnHWCapability(
+ _In_ CONST HANDLE hAdapter,
+ _Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps);
+
+NTSTATUS
+APIENTRY
+DodStopDeviceAndReleasePostDisplayOwnership(
+ _In_ VOID* pDeviceContext,
+ _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _Out_ DXGK_DISPLAY_INFORMATION* DisplayInfo);
+
+// Must be Non-Paged
+NTSTATUS
+APIENTRY
+DodSystemDisplayEnable(
+ _In_ VOID* pDeviceContext,
+ _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
+ _Out_ UINT* Width,
+ _Out_ UINT* Height,
+ _Out_ D3DDDIFORMAT* ColorFormat);
+
+// Must be Non-Paged
+VOID
+APIENTRY
+DodSystemDisplayWrite(
+ _In_ VOID* pDeviceContext,
+ _In_ VOID* Source,
+ _In_ UINT SourceWidth,
+ _In_ UINT SourceHeight,
+ _In_ UINT SourceStride,
+ _In_ UINT PositionX,
+ _In_ UINT PositionY);
+
+
+
+#if DBG
+
+extern int nDebugLevel;
+void DebugPrintFuncSerial(const char *format, ...);
+
+void DebugPrintFunc(const char *format, ...);
+
+#define DbgPrint(level, line) \
+ if (level > nDebugLevel) {} \
+ else DebugPrintFuncSerial line
+#else
+#define DbgPrint(level, line)
+#endif
+
+// else if (0) DebugPrintFuncSerial line \
+
+
+#ifndef TRACE_LEVEL_INFORMATION
+#define TRACE_LEVEL_NONE 0 // Tracing is not on
+#define TRACE_LEVEL_FATAL 1 // Abnormal exit or termination
+#define TRACE_LEVEL_ERROR 2 // Severe errors that need logging
+#define TRACE_LEVEL_WARNING 3 // Warnings such as allocation failure
+#define TRACE_LEVEL_INFORMATION 4 // Includes non-error cases(e.g.,Entry-Exit)
+#define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps
+#define TRACE_LEVEL_RESERVED6 6
+#define TRACE_LEVEL_RESERVED7 7
+#define TRACE_LEVEL_RESERVED8 8
+#define TRACE_LEVEL_RESERVED9 9
+#endif // TRACE_LEVEL_INFORMATION
+
+#define QXL_LOG_ASSERTION0(Msg) NT_ASSERT(FALSE)
+#define QXL_LOG_ASSERTION1(Msg,Param1) NT_ASSERT(FALSE)
+#define QXL_LOG_ASSERTION2(Msg,Param1,Param2) NT_ASSERT(FALSE)
+#define QXL_LOG_ASSERTION3(Msg,Param1,Param2,Param3) NT_ASSERT(FALSE)
+#define QXL_LOG_ASSERTION4(Msg,Param1,Param2,Param3,Param4) NT_ASSERT(FALSE)
+#define QXL_LOG_ASSERTION5(Msg,Param1,Param2,Param3,Param4,Param5) NT_ASSERT(FALSE)
+#define QXL_ASSERT(exp) {if (!(exp)) {QXL_LOG_ASSERTION0(#exp);}}
+
+
+#if DBG
+#define QXL_ASSERT_CHK(exp) QXL_ASSERT(exp)
+#else
+#define QXL_ASSERT_CHK(exp) {}
+#endif
diff --git a/qxldod/qxldod.inf b/qxldod/qxldod.inf
new file mode 100755
index 0000000..28080d4
--- /dev/null
+++ b/qxldod/qxldod.inf
Binary files differ
diff --git a/qxldod/qxldod.rc b/qxldod/qxldod.rc
new file mode 100755
index 0000000..ba45879
--- /dev/null
+++ b/qxldod/qxldod.rc
Binary files differ
diff --git a/qxldod/qxldod.vcxproj b/qxldod/qxldod.vcxproj
new file mode 100755
index 0000000..38cd91a
--- /dev/null
+++ b/qxldod/qxldod.vcxproj
@@ -0,0 +1,288 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Win8 Debug|Win32">
+ <Configuration>Win8 Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Release|Win32">
+ <Configuration>Win8 Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win7 Debug|Win32">
+ <Configuration>Win7 Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win7 Release|Win32">
+ <Configuration>Win7 Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Vista Debug|Win32">
+ <Configuration>Vista Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Vista Release|Win32">
+ <Configuration>Vista Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Debug|x64">
+ <Configuration>Win8 Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Release|x64">
+ <Configuration>Win8 Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win7 Debug|x64">
+ <Configuration>Win7 Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win7 Release|x64">
+ <Configuration>Win7 Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Vista Debug|x64">
+ <Configuration>Vista Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Vista Release|x64">
+ <Configuration>Vista Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{A6F48FC7-97E9-48EC-BCDF-1E4F9B43AADD}</ProjectGuid>
+ <TemplateGuid>{dd38f7fc-d7bd-488b-9242-7d8754cde80d}</TemplateGuid>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <Configuration>Win8 Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ </PropertyGroup>
+ <PropertyGroup Label="Globals">
+ <RootNamespace>qxldod</RootNamespace>
+ <VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VisualStudioVersion)' == '11.0'">$(VCTargetsPath11)</VCTargetsPath>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets">
+ <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>WDM</DriverType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|Win32'" Label="Configuration">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Release|Win32'" Label="Configuration">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Debug|Win32'" Label="Configuration">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Release|Win32'" Label="Configuration">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Release|x64'" Label="Configuration">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Debug|x64'" Label="Configuration">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Release|x64'" Label="Configuration">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <PropertyGroup>
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Vista Debug|Win32'">
+ <Link>
+ <AdditionalDependencies>;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ <WarningLevel>Level3</WarningLevel>
+ <ExceptionHandling />
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Vista Release|Win32'">
+ <Link>
+ <AdditionalDependencies>;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|Win32'">
+ <Link>
+ <AdditionalDependencies>;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Release|Win32'">
+ <Link>
+ <AdditionalDependencies>;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">
+ <Link>
+ <AdditionalDependencies>;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Vista Debug|x64'">
+ <Link>
+ <AdditionalDependencies>;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'">
+ <Link>
+ <AdditionalDependencies>;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Vista Release|x64'">
+ <Link>
+ <AdditionalDependencies>;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|x64'">
+ <Link>
+ <AdditionalDependencies>;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Release|x64'">
+ <Link>
+ <AdditionalDependencies>;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'">
+ <Link>
+ <AdditionalDependencies>;$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Inf Include="qxldod.inf" />
+ </ItemGroup>
+ <ItemGroup>
+ <FilesToPackage Include="$(TargetPath)" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="BaseObject.h" />
+ <ClInclude Include="driver.h" />
+ <ClInclude Include="QxlDod.h" />
+ <ClInclude Include="resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="BaseObject.cpp" />
+ <ClCompile Include="driver.cpp" />
+ <ClCompile Include="QxlDod.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="qxldod.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/qxldod/qxldod.vcxproj.filters b/qxldod/qxldod.vcxproj.filters
new file mode 100755
index 0000000..db5df31
--- /dev/null
+++ b/qxldod/qxldod.vcxproj.filters
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Driver Files">
+ <UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="qxldod.inf">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="BaseObject.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="driver.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QxlDod.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="BaseObject.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="driver.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QxlDod.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="qxldod.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/qxldod/resource.h b/qxldod/resource.h
new file mode 100755
index 0000000..4c0462f
--- /dev/null
+++ b/qxldod/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by qxldod.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif