2019/07/25

Video and Graphic windows driver 驅動程式開發筆記

* 前情提要之本文另一篇: Windows Driver 開發學習筆記
* Graphic driver要了解一下
* Umd kmd 基本概念要懂
* 會寫程式 XD

關於 WDF 、WDK、WDM、DDK 介紹

(轉自: DDK與WDK的區別與聯繫)
最近嘗試去了解WINDOWS下的驅動開發,現在總結一下最近看到的資料。

1. 專門的開發包

首先,先從基礎的東西說起,開發WINDOWS下的驅動程序,需要一個專門的開發包
如:

  • 開發 JAVA 程序,我們可能需要一個JDK
  • 開發 WINDOWS 應用程式(Applications),我們需要WINDOWS的SDK
  • 開發 WINDOWS 下的驅動程序(Drivers),我們需要一個DDK/WDK。

2. DDK(Driver Developer Kit)和 WDK(Windows Driver Kit)的區別:

這個要說說驅動相關的一些歷史:

  • (1). 95/98/ME下,驅動模型為:Vxd, 相關資料可以看《編程高手箴言》的前幾個章節,裡面有很詳細的介紹,雖然這個東西已經過時,但大概看看還是會增長見識的。
  • (2). 2000/XP/2003下,Windows採用WDM驅動模型(Windows Driver Model),開發2000/XP/2003的驅動開發包為:DDK。
  • (3). Vista及以後版本,採用了WDF驅動模型(Windows Driver Foudation),對應的開發包:WDK。

其實WDK可以看做是DDK的升級版本,現在一般的WDK是包含以前DDK相關的功能,現在XP下也可以用WDK開發驅動,WDK能編譯出2000-2008的各種驅動。

3. 副檔名的區別

  • Vxd驅動文件擴展名為:.vxd。
  • WDM和WDF驅動文件擴展名為:.sys。

4. 相關的名詞解釋

  • DDK——Driver Developer Kit,設備驅動程序開發包。
  • WDK——Windows Driver Kit,Windows驅動程序開發包,就是DDK升級改名了。
  • VxD——Virtual Device Driver,虛擬設備驅動程序,9X中的一種驅動程序。
  • WDM——Windows Driver Model,Windows驅動程序模型,98以上版本的一種驅動程序。
  • WDF——Windows Driver Frameworks, 驅動程序包括兩個類型,一個是內核級的,稱為KMDF(Kernel-Mode Driver Framework),為SYS文件;另一個是用戶級的,稱為UMDF(User-Mode Driver Framework),為DLL文件。
  • 驅動程序的文件格式都是PE格式。

windows驅動開發: 比較 WDM 與 WDF

(轉載自 yinaiyun52)

如所周知,自Windows 2000開始,開發驅動程序必以WDM為基礎的,但其開發難度之大,根本不能奢望像用戶模式應用程序開發那樣容易。為改善這種局面,微軟推出了新的驅動程序開發環境 – WDF驅動模型。

WDF驅動框架對WDM進行了一次封裝
WDF框架就好像C++中的基類一樣,且這個基類中的model, IO model ,pnp和電源管理模型;且提供了一些與操作系統相關的處理函數,這些函數好像C++中的虛函數一樣,WDF驅動中能夠對這些函數進行override;特別是Pnp管理和電源管理!基本上都由WDF框架做了,而WDF的功能驅動幾乎不要對它進行特殊的處理;

要預先指出的是,WDF這不是另起爐灶改弦更張,而是以WDM為基礎進行了建模和封裝,顯著特點是降低了開發難度。
因為:
1、 將原來普通程序設計中基於對象的技術應用到了驅動開發中。 WDM中雖也有對像模型,但與真正的基於對象技術根本就不是一回事。為了實現基於對象的技術,微軟精心設計了對像模型並進行了封裝。屬性、方法、事件等等“一個都不能少”。

2、 無論內核模式的驅動程序或者用戶模式的驅動程序,都採用同一套對像模型構建,採用同一個基礎承載。這個基礎就是WDF。 WDF雖然已經是經過封裝和定義的對像模型,但對內核模式和用戶模式對象來說,WDF又是兩者的父對象。換言之兩者都是繼承了WDF才得到的,或者都是從WDF派生而來的。相對於內核模式,派生出的對象稱為“KMD框架”即KMDF;相對於用戶模式,派生出的模型稱為“UMD框架”即UMDF。無論何種模式的框架,其內部封裝的方法、執行的行為其實還是用WDM完成的。

3、 更重要的,也是微軟反复炫耀的是封裝了驅動程序中的某些共同行為:例如即插即用和電源管理就屬於這種共同行為。因為大多數驅動程序中都需要處理即插即用和電源管理問題,據說這大概要上千行的代碼,況且,沒有相當水平還不一定能處理好。為了一勞永逸,WDF乾脆將即插即用和電源管理封裝了進了對象之內,一舉成了對象的缺省(默認)行為。

4、 改變了操作系統內核與驅動程序之間的關係,WDM驅動程序中,一方面要處理硬件,另一方面要處理驅動程序與操作系統內核的交互。現在WDF則將驅動程序與操作系統內核之間進行了分離,驅動程序與操作系統交互工作交給框架內封裝的方法(函數)完成,這樣驅動開發者只需專注處理硬件的行為即可。這不僅避免了顧此失彼兩面不周的弊端,也由於雙方的分離,對操作系統內的某些改動,硬件製造商配套驅動程序的開發都有莫大的好處。

5、 兩種模式的驅動程序(KMDF、UMDF)都使用同一環境進行構建,這一環境稱為WDK。
即KMDF,UMDF的開發環境為WDK。
Windows Device Kit (WDK): 把測試套件(test suites)集成進來,DDK 就成了WDK。 WDK是針對微軟操作系統系列的驅動器集成開發系統。它組合了Windows DDK和Hardware Compatibility Test (HCT) kits(硬件兼容性測試工具),同時提供了微軟內部用來測試Windows操作系統穩定性和可靠性的測試套件。

6、 雖然經過封裝並引入基於對象的技術,所開發的驅動程序在執行效率上並不比原來遜色。
WDF和WDM的關係有點類似於MFC和Windows SDK的關係。 WDF只是在WDM上面加了一層,來簡化driver的開發,特別是PNP,power和IO cancellation 等幾個方面有很大改進。

現在學習WDF最好的資料還是DDK帶的sample code。 WHDC有一些資料:
http://www.microsoft.com/whdc/driver/wdf/default.mspx

再繼續說新舊時代

關鍵的visual studio 2012, 新時代忽然就來了, VS2012是Win8發布之後才出來的,有很多針對Win8的特性,但也能在Win7/Vista系統上運行。

舊時代

近期的win8與win10的系統出現以前, 也就是含win7之前的系統, 如果要開發kernel/driver的驅動程式, 環境的準備比較繁瑣, 首先需要手動下載WDK並安裝, 因為開發環境是在安裝好的WDK當中。WDK是Windows Driver Kit縮寫,即Windows驅動開發包。它提供的開發環境非常簡陋,不是一個便於開發的IDE環境,而僅僅是一些散裝的編譯工具包。

新時代

基本上必須要安裝三個軟體:
1. 我這裡使用 visual studio 2015版本 (或2012之後的版本)
2. WDK 10 (或Win8之後的版本)
3. Win10 SDK

請您先下載安裝 VS2015, 再安裝 Win10 的 WDK, 然後WDK的編譯環境就會自動整合進去 VS2015裡面, 所以重新開啟VS2015的時候, 在new project 新項目嚮導裡面, 就能夠找到driver(內核驅動)項目了。

開啟 Visual Studio 2015,選擇 New Project 建立新專案:
選擇 Visual C++ > Windows Driver > WDF

跳出的分別是有自動生成代碼的KMDF和沒有自動代碼的KMDF(empty),以及UMDF
我們選擇 Kernel Mode Driver (KMDF),直接按 OK 用預設值建立一個簡單的 driver 專案

測試安裝好的 Visual Studio 2015 + Windows SDK 10 + Windows Driver Kit 10
正常的話, 可以編譯通過successfully!

微軟釋出的 Driver samples for Windows 10 – 擷取video 部分

網址: https://github.com/microsoft/Windows-driver-samples/tree/master/video/KMDOD
目前我使用的為visual studio 2015 + (WinSDK)Windows Software Development kit 10.0.14393.33 + (WDK)Windows Driver kit 10.0.14393.0

資源指令碼檔案 .rc
包含目前專案中的資源所適用之指令碼的資源指令碼檔。 .aps 檔會在您每次存檔時覆寫此檔案。
原始檔控制中包含此檔案。

/*++Copyright (c) 2011 Microsoft CorporationModule Name:    SampleDisplay.rcAbstract:    This modules contains the version information for the Sample Display DriverEnvironment:    Kernel mode only--*/#include #include #define VER_FILETYPE                VFT_DRV#define VER_FILESUBTYPE             VFT2_DRV_DISPLAY#define VER_FILEDESCRIPTION_STR     "Microsoft Sample Display Driver"#define VER_INTERNALNAME_STR        "SampleDisplay.sys"#define VER_ORIGINALFILENAME_STR    "SampleDisplay.sys"#define VER_LANGNEUTRAL#include "common.ver"

驅動程式檔案 .inf
.INF是 Device Information File 的縮寫,是微軟為供硬體製造商散佈其設備驅動程式而發展, .INF 檔是一種具有特定格式的純文字檔,我們可說它是種安裝腳本檔(Setup Script)。為甚麼當我們在檔案總管對 .INF 檔按右鍵後,快顯功能表會出現「安裝」指令呢? 這是因為微軟已在其作業系統 Windows 中提供了 Setup API(註一),程式設計師只需用任何文書編輯軟體撰寫 .INF 檔,便可完成大部份的安裝工作。

;++;; Copyright (c) 2011 Microsoft Corporation;; Module Name:;;    SampleDisplay.inf;; Abstract:;;    Inf file for Kernel mode display only sample driver;;--[Version]Signature = "$Windows NT$"Class=DisplayClassGUID={4d36e968-e325-11ce-bfc1-08002be10318}Provider=%ProviderString%DriverVer= 03/15/2011, 0.03.15.0011CatalogFile=SampleDisplay.cat[DestinationDirs]KDODSamp.Files = 12[SourceDisksNames]0=%SampleDisk%[SourceDisksFiles]SampleDisplay.sys=0[Manufacturer]%ManufacturerName%=Standard,NTx86,NTamd64,NTarm,NTarm64;;    Allow the driver to be loaded on VGA and XGA exposed by PCI bus and ACPI;[Standard.NTx86]%SampleDeviceName% = KDODSamp_Inst, PCI\CC_0300%SampleDeviceName% = KDODSamp_Inst, PCI\CC_0301%SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0000%SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0001[Standard.NTamd64]%SampleDeviceName% = KDODSamp_Inst, PCI\CC_0300%SampleDeviceName% = KDODSamp_Inst, PCI\CC_0301%SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0000%SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0001[Standard.NTarm]%SampleDeviceName% = KDODSamp_Inst, PCI\CC_0300%SampleDeviceName% = KDODSamp_Inst, PCI\CC_0301%SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0000%SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0001[Standard.NTarm64]%SampleDeviceName% = KDODSamp_Inst, PCI\CC_0300%SampleDeviceName% = KDODSamp_Inst, PCI\CC_0301%SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0000%SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0001[KDODSamp_Inst]FeatureScore=F9CopyFiles = KDODSamp.Files;;   Install driver service;[KDODSamp_Inst.Services]AddService = KDODSamp,0x00000002,KDODSamp_Service_Inst,KDODSamp_EventLog_Inst[KDODSamp_Service_Inst]ServiceType = %SERVICE_KERNEL_DRIVER%StartType = %SERVICE_DEMAND_START%ErrorControl = %SERVICE_ERROR_IGNORE%ServiceBinary = %12%\SampleDisplay.sys;;   Display Adapter Specific Settings;[KDODSamp.Files]SampleDisplay.sys[KDODSamp_EventLog_Inst]AddReg = KDODSamp_EventLog_Inst.AddReg[KDODSamp_EventLog_Inst.AddReg]HKR,,EventMessageFile,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll"HKR,,TypesSupported,%REG_DWORD%,7[Strings];  *******Localizable Strings*******ProviderString="TODO-Set-Provider"ManufacturerName="TODO-Set-Manufacturer"SampleDisk = "Sample Disk"SampleDeviceName = "Kernel mode display only sample driver";  *******Non Localizable Strings*******SERVICE_BOOT_START = 0x0SERVICE_SYSTEM_START = 0x1SERVICE_AUTO_START = 0x2SERVICE_DEMAND_START = 0x3SERVICE_DISABLED = 0x4SERVICE_KERNEL_DRIVER = 0x1SERVICE_ERROR_IGNORE = 0x0SERVICE_ERROR_NORMAL = 0x1SERVICE_ERROR_SEVERE = 0x2SERVICE_ERROR_CRITICAL = 0x3REG_MULTI_SZ   = 0x00010000REG_EXPAND_SZ = 0x00020000REG_DWORD = 0x00010001

C++程式標頭檔案 bdd.hxx

/******************************Module*Header*******************************\* Module Name: BDD.hxx** Basic Display Driver header file*** Copyright (c) 2010 Microsoft Corporation\**************************************************************************/#ifndef _BDD_HXX_#define _BDD_HXX_extern "C"{    #define __CPLUSPLUS    // Standard C-runtime headers    #include     #include     #include     #include     #include     #include     // NTOS headers    #include     #ifndef FAR    #define FAR    #endif    // Windows headers    #include     #include     // Windows GDI headers    #include     // Windows DDI headers    #include     #include     #include     #include     #include     #include     #include };#define EDID_V1_BLOCK_SIZE 128#include "BDD_ErrorLog.hxx"#define MIN_WIDTH                    640#define MIN_HEIGHT                   480#define MIN_BITS_PER_PIXEL_ALLOWED     8#define MIN_BYTES_PER_PIXEL_REPORTED   4#define DEFAULT_WIDTH               1024#define DEFAULT_HEIGHT               768#define MAX_INVALID_INHERITED_WIDTH 1024#define MAX_INVALID_INHERITED_HEIGHT 768#define BITS_PER_BYTE                  8typedef struct _BLT_INFO{    PVOID pBits;    UINT Pitch;    UINT BitsPerPel;    POINT Offset; // To unrotated top-left of dirty rects    D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation;    UINT Width; // For the unrotated image    UINT Height; // For the unrotated image} BLT_INFO;#define MAX_CHILDREN                   1#define MAX_VIEWS                      1typedef struct _BDD_FLAGS{    UINT DriverStarted           : 1; // ( 1) 1 after StartDevice and 0 after StopDevice    UINT EDID_Retrieved          : 1; // ( 2) EDID was successfully retrieved    UINT EDID_ValidChecksum      : 1; // ( 3) Retrieved EDID has a valid checksum    UINT EDID_ValidHeader        : 1; // ( 4) Retrieved EDID has a valid header    UINT EDID_Attempted          : 1; // ( 5) 1 if an attempt was made to retrieve the EDID, successful or not    // IMPORTANT: All new flags must be added to just before _LastFlag (i.e. right above this comment), this allows different versions of diagnostics to still be useful.    UINT _LastFlag               : 1; // ( 6) Always set to 1, is used to ensure that diagnostic version matches binary version    UINT Unused                  : 26;} BDD_FLAGS;// Represents the current mode, may not always be set (i.e. frame buffer mapped) if representing the mode passed in on single mode setups.typedef struct _CURRENT_BDD_MODE{    // The source mode currently set for HW Framebuffer    // For sample driver this info filled in StartDevice by the OS and never changed.    DXGK_DISPLAY_INFORMATION             DispInfo;    // The rotation of the current mode. Rotation is performed in software during Present call    D3DKMDT_VIDPN_PRESENT_PATH_ROTATION  Rotation;    D3DKMDT_VIDPN_PRESENT_PATH_SCALING Scaling;    // This mode might be different from one which are supported for HW frame buffer    // Scaling/displasment might be needed (if supported)    UINT SrcModeWidth;    UINT SrcModeHeight;    // Various boolean flags the struct uses    struct _CURRENT_BDD_MODE_FLAGS    {        UINT SourceNotVisible     : 1; // 0 if source is visible        UINT FullscreenPresent    : 1; // 0 if should use dirty rects for present        UINT FrameBufferIsActive  : 1; // 0 if not currently active (i.e. target not connected to source)        UINT DoNotMapOrUnmap      : 1; // 1 if the FrameBuffer should not be (un)mapped during normal execution        UINT IsInternal           : 1; // 1 if it was determined (i.e. through ACPI) that an internal panel is being driven        UINT Unused               : 27;    } Flags;    // The start and end of physical memory known to be all zeroes. Used to optimize the BlackOutScreen function to not write    // zeroes to memory already known to be zero. (Physical address is located in DispInfo)    PHYSICAL_ADDRESS ZeroedOutStart;    PHYSICAL_ADDRESS ZeroedOutEnd;    // Linear frame buffer pointer    // A union with a ULONG64 is used here to ensure this struct looks the same on 32bit and 64bit builds    // since the size of a VOID* changes depending on the build.    union    {        VOID*                            Ptr;        ULONG64                          Force8Bytes;    } FrameBuffer;} CURRENT_BDD_MODE;class BASIC_DISPLAY_DRIVER;class BDD_HWBLT{public:    D3DDDI_VIDEO_PRESENT_SOURCE_ID  m_SourceId;    BASIC_DISPLAY_DRIVER*           m_DevExt;    BOOLEAN                         m_SynchExecution;    HANDLE                          m_hPresentWorkerThread;    PVOID                           m_pPresentWorkerThread;    //  Events to contol thread execution    KEVENT                          m_hThreadStartupEvent;    KEVENT                          m_hThreadSuspendEvent;    BDD_HWBLT();    ~BDD_HWBLT();    void Initialize(_In_ BASIC_DISPLAY_DRIVER* DevExt, _In_ UINT IdSrc) { m_DevExt = DevExt; m_SourceId = IdSrc; }    void SetPresentWorkerThreadInfo(HANDLE hWorkerThread);    NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE*             DstAddr,                                       _In_ UINT              DstBitPerPixel,                                       _In_ BYTE*             SrcAddr,                                       _In_ UINT              SrcBytesPerPixel,                                       _In_ LONG              SrcPitch,                                       _In_ ULONG             NumMoves,                                       _In_ D3DKMT_MOVE_RECT* pMoves,                                       _In_ ULONG             NumDirtyRects,                                       _In_ RECT*             pDirtyRect,                                       _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation);};class BASIC_DISPLAY_DRIVER{private:    DEVICE_OBJECT* m_pPhysicalDevice;    DXGKRNL_INTERFACE m_DxgkInterface;    // Information passed in by StartDevice DDI    DXGK_START_INFO m_StartInfo;    // Array of EDIDs, currently only supporting base block, hence EDID_V1_BLOCK_SIZE for size of each EDID    BYTE m_EDIDs[MAX_CHILDREN][EDID_V1_BLOCK_SIZE];    CURRENT_BDD_MODE m_CurrentModes[MAX_VIEWS];    BDD_HWBLT        m_HardwareBlt[MAX_VIEWS];    // Current monitorpower state (this needs to be changed if MAX_CHILDREN != 1)    DEVICE_POWER_STATE m_MonitorPowerState;    // Current adapter power state    DEVICE_POWER_STATE m_AdapterPowerState;    // Source ID to be used by SystemDisplay functions    D3DDDI_VIDEO_PRESENT_SOURCE_ID m_SystemDisplaySourceId;    // Various boolean flags the class uses    BDD_FLAGS m_Flags;    // Device information    DXGK_DEVICE_INFO m_DeviceInfo;public:    BASIC_DISPLAY_DRIVER(_In_ DEVICE_OBJECT* pPhysicalDeviceObject);    ~BASIC_DISPLAY_DRIVER();#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);    const CURRENT_BDD_MODE* GetCurrentMode(UINT SourceId) const    {        return (SourceId < MAX_VIEWS)?&m_CurrentModes[SourceId]:NULL;    }    const DXGKRNL_INTERFACE* GetDxgkInterface() const { return &m_DxgkInterface;}    // Not implemented since no IOCTLs currently handled.    NTSTATUS DispatchIoRequest(_In_  ULONG                 VidPnSourceId,                               _In_  VIDEO_REQUEST_PACKET* pVideoRequestPacket);    // Used to either turn off/on monitor (if possible), or mark that system is going into hibernate    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 PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly);    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();    NTSTATUS CommonStart();    NTSTATUS GetEdid(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId);    // Given pixel format, give back the bits per pixel. Only supports pixel formats expected by BDD    // (i.e. the ones found below in PixelFormatFromBPP or that may come in from FallbackStart)    // This is because these two functions combine to allow BDD to store the bpp of a VBE mode in the    // ColorFormat field of a DispInfo    UINT BPPFromPixelFormat(D3DDDIFORMAT Format) const    {        switch (Format)        {            case D3DDDIFMT_UNKNOWN: return 0;            case D3DDDIFMT_P8: return 8;            case D3DDDIFMT_R5G6B5: return 16;            case D3DDDIFMT_R8G8B8: return 24;            case D3DDDIFMT_X8R8G8B8: // fall through            case D3DDDIFMT_A8R8G8B8: return 32;            default: BDD_LOG_ASSERTION1("Unknown D3DDDIFORMAT 0x%I64x", Format); return 0;        }    }    // Given bits per pixel, return the pixel format at the same bpp    D3DDDIFORMAT PixelFormatFromBPP(UINT BPP) const    {        switch (BPP)        {            case  8: return D3DDDIFMT_P8;            case 16: return D3DDDIFMT_R5G6B5;            case 24: return D3DDDIFMT_R8G8B8;            case 32: return D3DDDIFMT_X8R8G8B8;            default: BDD_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not supported.", BPP); return D3DDDIFMT_UNKNOWN;        }    }    // These two functions make checks on the values of some of the fields of their respective structures to ensure    // that the specified fields are supported by BDD, i.e. gamma ramp must be D3DDDI_GAMMARAMP_DEFAULT    NTSTATUS IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) const;    NTSTATUS IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const;    VOID BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId);    // Returns the index into gBddBiosData.BddModes of the VBE mode that matches the given VidPnSourceMode.    // If such a mode cannot be found, returns a number outside of [0, gBddBiosData.CountBddModes)    UINT FindMatchingVBEMode(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const;    // Must be Non-Paged    // Returns the SourceId that has TargetId as a valid frame buffer or D3DDDI_ID_UNINITIALIZED if no such SourceId exists    D3DDDI_VIDEO_PRESENT_SOURCE_ID FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero);    // Set the given source mode on the given path    NTSTATUS SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode,                                  CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath);    // Add the current mode to the given monitor source mode set    NTSTATUS AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes);    // Add the current mode to the given VidPn source mode set    NTSTATUS AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface,                                 D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet,                                 D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId);    // Add the current mode (or the matching to pinned source mode) to the give VidPn target mode set    NTSTATUS AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface,                                 D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet,                                 _In_opt_ CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnPinnedSourceModeInfo,                                 D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId);    // Check that the hardware the driver is running on is hardware it is capable of driving.    NTSTATUS CheckHardware();    // Helper function for RegisterHWInfo    NTSTATUS WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue);    // Set the information in the registry as described here: http://msdn.microsoft.com/en-us/library/windows/hardware/ff569240(v=vs.85).aspx    NTSTATUS RegisterHWInfo();};//// Blt functions//// Must be Non-PagedVOID BltBits(    BLT_INFO* pDst,    CONST BLT_INFO* pSrc,    UINT  NumRects,    _In_reads_(NumRects) CONST RECT *pRects);//// Driver Entry point//extern "C"DRIVER_INITIALIZE DriverEntry;//// PnP DDIs//VOIDBddDdiUnload(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;NTSTATUSBddDdiAddDevice(    _In_ DEVICE_OBJECT* pPhysicalDeviceObject,    _Outptr_ PVOID*  ppDeviceContext);NTSTATUSBddDdiRemoveDevice(    _In_  VOID* pDeviceContext);NTSTATUSBddDdiStartDevice(    _In_  VOID*              pDeviceContext,    _In_  DXGK_START_INFO*   pDxgkStartInfo,    _In_  DXGKRNL_INTERFACE* pDxgkInterface,    _Out_ ULONG*             pNumberOfViews,    _Out_ ULONG*             pNumberOfChildren);NTSTATUSBddDdiStopDevice(    _In_  VOID* pDeviceContext);VOIDBddDdiResetDevice(    _In_  VOID* pDeviceContext);NTSTATUSBddDdiDispatchIoRequest(    _In_  VOID*                 pDeviceContext,    _In_  ULONG                 VidPnSourceId,    _In_  VIDEO_REQUEST_PACKET* pVideoRequestPacket);NTSTATUSBddDdiSetPowerState(    _In_  VOID*              pDeviceContext,    _In_  ULONG              HardwareUid,    _In_  DEVICE_POWER_STATE DevicePowerState,    _In_  POWER_ACTION       ActionType);NTSTATUSBddDdiQueryChildRelations(    _In_                             VOID*                  pDeviceContext,    _Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,    _In_                             ULONG                  ChildRelationsSize);NTSTATUSBddDdiQueryChildStatus(    _In_    VOID*              pDeviceContext,    _Inout_ DXGK_CHILD_STATUS* pChildStatus,    _In_    BOOLEAN            NonDestructiveOnly);NTSTATUSBddDdiQueryDeviceDescriptor(    _In_  VOID*                     pDeviceContext,    _In_  ULONG                     ChildUid,    _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor);// Must be Non-PagedBOOLEANBddDdiInterruptRoutine(    _In_  VOID* pDeviceContext,    _In_  ULONG MessageNumber);VOIDBddDdiDpcRoutine(    _In_  VOID* pDeviceContext);//// WDDM Display Only Driver DDIs//NTSTATUSAPIENTRYBddDdiQueryAdapterInfo(    _In_ CONST HANDLE                         hAdapter,    _In_ CONST DXGKARG_QUERYADAPTERINFO*      pQueryAdapterInfo);NTSTATUSAPIENTRYBddDdiSetPointerPosition(    _In_ CONST HANDLE                         hAdapter,    _In_ CONST DXGKARG_SETPOINTERPOSITION*    pSetPointerPosition);NTSTATUSAPIENTRYBddDdiSetPointerShape(    _In_ CONST HANDLE                         hAdapter,    _In_ CONST DXGKARG_SETPOINTERSHAPE*       pSetPointerShape);NTSTATUSAPIENTRYBddDdiPresentDisplayOnly(    _In_ CONST HANDLE                         hAdapter,    _In_ CONST DXGKARG_PRESENT_DISPLAYONLY*   pPresentDisplayOnly);NTSTATUSAPIENTRYBddDdiIsSupportedVidPn(    _In_ CONST HANDLE                         hAdapter,    _Inout_ DXGKARG_ISSUPPORTEDVIDPN*         pIsSupportedVidPn);NTSTATUSAPIENTRYBddDdiRecommendFunctionalVidPn(    _In_ CONST HANDLE                                   hAdapter,    _In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST  pRecommendFunctionalVidPn);NTSTATUSAPIENTRYBddDdiRecommendVidPnTopology(    _In_ CONST HANDLE                                 hAdapter,    _In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST  pRecommendVidPnTopology);NTSTATUSAPIENTRYBddDdiRecommendMonitorModes(    _In_ CONST HANDLE                                hAdapter,    _In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST  pRecommendMonitorModes);NTSTATUSAPIENTRYBddDdiEnumVidPnCofuncModality(    _In_ CONST HANDLE                                  hAdapter,    _In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST  pEnumCofuncModality);NTSTATUSAPIENTRYBddDdiSetVidPnSourceVisibility(    _In_ CONST HANDLE                             hAdapter,    _In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY*  pSetVidPnSourceVisibility);NTSTATUSAPIENTRYBddDdiCommitVidPn(    _In_ CONST HANDLE                         hAdapter,    _In_ CONST DXGKARG_COMMITVIDPN* CONST     pCommitVidPn);NTSTATUSAPIENTRYBddDdiUpdateActiveVidPnPresentPath(    _In_ CONST HANDLE                                       hAdapter,    _In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST  pUpdateActiveVidPnPresentPath);NTSTATUSAPIENTRYBddDdiQueryVidPnHWCapability(    _In_ CONST HANDLE                         hAdapter,    _Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY*   pVidPnHWCaps);NTSTATUSAPIENTRYBddDdiStopDeviceAndReleasePostDisplayOwnership(    _In_  VOID*                          pDeviceContext,    _In_  D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,    _Out_ DXGK_DISPLAY_INFORMATION*      DisplayInfo);// Must be Non-PagedNTSTATUSAPIENTRYBddDdiSystemDisplayEnable(    _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-PagedVOIDAPIENTRYBddDdiSystemDisplayWrite(    _In_  VOID* pDeviceContext,    _In_  VOID* Source,    _In_  UINT  SourceWidth,    _In_  UINT  SourceHeight,    _In_  UINT  SourceStride,    _In_  UINT  PositionX,    _In_  UINT  PositionY);//// Frame buffer map/unmap//NTSTATUSMapFrameBuffer(    _In_                       PHYSICAL_ADDRESS    PhysicalAddress,    _In_                       ULONG               Length,    _Outptr_result_bytebuffer_(Length) VOID**              VirtualAddress);NTSTATUSUnmapFrameBuffer(    _In_reads_bytes_(Length) VOID* VirtualAddress,    _In_                ULONG Length);BOOLEANIsEdidHeaderValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid);BOOLEANIsEdidChecksumValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid);//// 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, size_t s);void  __cdecl operator delete[](void* pObject);// Pool allocation tag for the Sample Display Driver. All allocations use this tag.#define BDDTAG 'DDBS'#endif // _BDD_HXX_

C++程式檔案 bdd.cxx

/******************************Module*Header*******************************\* Module Name: bdd.cxx** Basic Display Driver functions implementation*** Copyright (c) 2010 Microsoft Corporation\**************************************************************************/#include "BDD.hxx"#pragma code_seg("PAGE")BASIC_DISPLAY_DRIVER::BASIC_DISPLAY_DRIVER(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pPhysicalDeviceObject),                                                                                        m_MonitorPowerState(PowerDeviceD0),                                                                                        m_AdapterPowerState(PowerDeviceD0){    PAGED_CODE();    *((UINT*)&m_Flags) = 0;    m_Flags._LastFlag = TRUE;    RtlZeroMemory(&m_DxgkInterface, sizeof(m_DxgkInterface));    RtlZeroMemory(&m_StartInfo, sizeof(m_StartInfo));    RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes));    RtlZeroMemory(&m_DeviceInfo, sizeof(m_DeviceInfo));    for (UINT i=0;iChildUid < 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            BDD_LOG_ERROR0("Child status being queried for StatusRotation even though D3DKMDT_MOA_NONE was reported");            return STATUS_INVALID_PARAMETER;        }        default:        {            BDD_LOG_WARNING1("Unknown pChildStatus->Type (0x%I64x) requested.", pChildStatus->Type);            return STATUS_NOT_SUPPORTED;        }    }}// EDID retrievalNTSTATUS BASIC_DISPLAY_DRIVER::QueryDeviceDescriptor(_In_    ULONG                   ChildUid,                                                     _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor){    PAGED_CODE();    BDD_ASSERT(pDeviceDescriptor != NULL);    BDD_ASSERT(ChildUid < MAX_CHILDREN);    // If we haven't successfully retrieved an EDID yet (invalid ones are ok, so long as it was retrieved)    if (!m_Flags.EDID_Attempted)    {        GetEdid(ChildUid);    }    if (!m_Flags.EDID_Retrieved || !m_Flags.EDID_ValidHeader || !m_Flags.EDID_ValidChecksum)    {        // Report no EDID if a valid one wasn't retrieved        return STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED;    }    else if (pDeviceDescriptor->DescriptorOffset == 0)    {        // Only the base block is supported        RtlCopyMemory(pDeviceDescriptor->DescriptorBuffer,                      m_EDIDs[ChildUid],                      min(pDeviceDescriptor->DescriptorLength, EDID_V1_BLOCK_SIZE));        return STATUS_SUCCESS;    }    else    {        return STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA;    }}NTSTATUS BASIC_DISPLAY_DRIVER::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo){    PAGED_CODE();    BDD_ASSERT(pQueryAdapterInfo != NULL);    switch (pQueryAdapterInfo->Type)    {        case DXGKQAITYPE_DRIVERCAPS:        {            if (pQueryAdapterInfo->OutputDataSize < sizeof(DXGK_DRIVERCAPS))            {                BDD_LOG_ERROR2("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;            // Nearly all fields must be initialized to zero, so zero out to start and then change those that are non-zero.            // Fields are zero since BDD is Display-Only and therefore does not support any of the render related fields.            // It also doesn't support hardware interrupts, gamma ramps, etc.            RtlZeroMemory(pDriverCaps, sizeof(DXGK_DRIVERCAPS));            pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2;            pDriverCaps->HighestAcceptableAddress.QuadPart = -1;            pDriverCaps->SupportNonVGA = TRUE;            pDriverCaps->SupportSmoothRotation = TRUE;            return STATUS_SUCCESS;        }        case DXGKQAITYPE_DISPLAY_DRIVERCAPS_EXTENSION:        {            DXGK_DISPLAY_DRIVERCAPS_EXTENSION* pDriverDisplayCaps;            if (pQueryAdapterInfo->OutputDataSize < sizeof(*pDriverDisplayCaps))            {                BDD_LOG_ERROR2("pQueryAdapterInfo->OutputDataSize (0x%I64x) is smaller than sizeof(DXGK_DISPLAY_DRIVERCAPS_EXTENSION) (0x%I64x)",                               pQueryAdapterInfo->OutputDataSize,                               sizeof(DXGK_DISPLAY_DRIVERCAPS_EXTENSION));                return STATUS_INVALID_PARAMETER;            }            pDriverDisplayCaps = (DXGK_DISPLAY_DRIVERCAPS_EXTENSION*)pQueryAdapterInfo->pOutputData;            // Reset all caps values            RtlZeroMemory(pDriverDisplayCaps, pQueryAdapterInfo->OutputDataSize);            // We claim to support virtual display mode.            pDriverDisplayCaps->VirtualModeSupport = 1;            return STATUS_SUCCESS;        }        default:        {            // BDD does not need to support any other adapter information types            BDD_LOG_WARNING1("Unknown QueryAdapterInfo Type (0x%I64x) requested", pQueryAdapterInfo->Type);            return STATUS_NOT_SUPPORTED;        }    }}NTSTATUS BASIC_DISPLAY_DRIVER::CheckHardware(){    PAGED_CODE();    NTSTATUS Status;    ULONG VendorID;    ULONG DeviceID;// TODO: If developing a driver for PCI based hardware, then use the second method to retrieve Vendor/Device IDs.// If developing for non-PCI based hardware (i.e. ACPI based hardware), use the first method to retrieve the IDs.#if 1 // ACPI-based device    // Get the Vendor & Device IDs on non-PCI system    ACPI_EVAL_INPUT_BUFFER_COMPLEX AcpiInputBuffer = {0};    AcpiInputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;    AcpiInputBuffer.MethodNameAsUlong = ACPI_METHOD_HARDWARE_ID;    AcpiInputBuffer.Size = 0;    AcpiInputBuffer.ArgumentCount = 0;    BYTE OutputBuffer[sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 0x10];    RtlZeroMemory(OutputBuffer, sizeof(OutputBuffer));    ACPI_EVAL_OUTPUT_BUFFER* pAcpiOutputBuffer = reinterpret_cast(&OutputBuffer);    Status = m_DxgkInterface.DxgkCbEvalAcpiMethod(m_DxgkInterface.DeviceHandle,                                                  DISPLAY_ADAPTER_HW_ID,                                                  &AcpiInputBuffer,                                                  sizeof(AcpiInputBuffer),                                                  pAcpiOutputBuffer,                                                  sizeof(OutputBuffer));    if (!NT_SUCCESS(Status))    {        BDD_LOG_ERROR1("DxgkCbReadDeviceSpace failed to get hardware IDs with status 0x%I64x", Status);        return Status;    }    VendorID = ((ULONG*)(pAcpiOutputBuffer->Argument[0].Data))[0];    DeviceID = ((ULONG*)(pAcpiOutputBuffer->Argument[0].Data))[1];#else // PCI-based device    // Get the Vendor & Device IDs on PCI system    PCI_COMMON_HEADER Header = {0};    ULONG BytesRead;    Status = m_DxgkInterface.DxgkCbReadDeviceSpace(m_DxgkInterface.DeviceHandle,                                                   DXGK_WHICHSPACE_CONFIG,                                                   &Header,                                                   0,                                                   sizeof(Header),                                                   &BytesRead);    if (!NT_SUCCESS(Status))    {        BDD_LOG_ERROR1("DxgkCbReadDeviceSpace failed with status 0x%I64x", Status);        return Status;    }    VendorID = Header.VendorID;    DeviceID = Header.DeviceID;#endif    // TODO: Replace 0x1414 with your Vendor ID    if (VendorID == 0x1414)    {        switch (DeviceID)        {            // TODO: Replace the case statements below with the Device IDs supported by this driver            case 0x0000:            case 0xFFFF: return STATUS_SUCCESS;        }    }    return STATUS_GRAPHICS_DRIVER_MISMATCH;}// Even though Sample Basic Display Driver does not support hardware cursors, and reports such// in QueryAdapterInfo. This function can still be called to set the pointer to not visibleNTSTATUS BASIC_DISPLAY_DRIVER::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition){    PAGED_CODE();    BDD_ASSERT(pSetPointerPosition != NULL);    BDD_ASSERT(pSetPointerPosition->VidPnSourceId < MAX_VIEWS);    if (!(pSetPointerPosition->Flags.Visible))    {        return STATUS_SUCCESS;    }    else    {        BDD_LOG_ASSERTION0("SetPointerPosition should never be called to set the pointer to visible since BDD doesn't support hardware cursors.");        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 BASIC_DISPLAY_DRIVER::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape){    PAGED_CODE();    BDD_ASSERT(pSetPointerShape != NULL);    BDD_LOG_ASSERTION0("SetPointerShape should never be called since BDD doesn't support hardware cursors.");    return STATUS_NOT_IMPLEMENTED;}NTSTATUS BASIC_DISPLAY_DRIVER::PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly){    PAGED_CODE();    BDD_ASSERT(pPresentDisplayOnly != NULL);    BDD_ASSERT(pPresentDisplayOnly->VidPnSourceId < MAX_VIEWS);    if (pPresentDisplayOnly->BytesPerPixel < MIN_BYTES_PER_PIXEL_REPORTED)    {        // Only >=32bpp modes are reported, therefore this Present should never pass anything less than 4 bytes per pixel        BDD_LOG_ERROR1("pPresentDisplayOnly->BytesPerPixel is 0x%I64x, which is lower than the allowed.", pPresentDisplayOnly->BytesPerPixel);        return STATUS_INVALID_PARAMETER;    }    // If it is in monitor off state or source is not supposed to be visible, don't present anything to the screen    if ((m_MonitorPowerState > PowerDeviceD0) ||        (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Flags.SourceNotVisible))    {        return STATUS_SUCCESS;    }    // Present is only valid if the target is actively connected to this source    if (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Flags.FrameBufferIsActive)    {        // If actual pixels are coming through, will need to completely zero out physical address next time in BlackOutScreen        m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].ZeroedOutStart.QuadPart = 0;        m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].ZeroedOutEnd.QuadPart = 0;        D3DKMDT_VIDPN_PRESENT_PATH_ROTATION RotationNeededByFb = pPresentDisplayOnly->Flags.Rotate ?                                                                 m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Rotation :                                                                 D3DKMDT_VPPR_IDENTITY;            BYTE* pDst = (BYTE*)m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].FrameBuffer.Ptr;            UINT DstBitPerPixel = BPPFromPixelFormat(m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.ColorFormat);            if (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Scaling == D3DKMDT_VPPS_CENTERED)            {                UINT CenterShift = (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.Height -                    m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].SrcModeHeight)*m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.Pitch;                CenterShift += (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.Width -                    m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].SrcModeWidth)*DstBitPerPixel/8;                pDst += (int)CenterShift/2;            }            return m_HardwareBlt[pPresentDisplayOnly->VidPnSourceId].ExecutePresentDisplayOnly(pDst,                                                                    DstBitPerPixel,                                                                    (BYTE*)pPresentDisplayOnly->pSource,                                                                    pPresentDisplayOnly->BytesPerPixel,                                                                    pPresentDisplayOnly->Pitch,                                                                    pPresentDisplayOnly->NumMoves,                                                                    pPresentDisplayOnly->pMoves,                                                                    pPresentDisplayOnly->NumDirtyRects,                                                                    pPresentDisplayOnly->pDirtyRect,                                                                    RotationNeededByFb);    }    return STATUS_SUCCESS;}NTSTATUS BASIC_DISPLAY_DRIVER::StopDeviceAndReleasePostDisplayOwnership(_In_  D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,                                                                        _Out_ DXGK_DISPLAY_INFORMATION*      pDisplayInfo){    PAGED_CODE();    BDD_ASSERT(TargetId < MAX_CHILDREN);    D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId = FindSourceForTarget(TargetId, TRUE);    // In case BDD is the next driver to run, the monitor should not be off, since    // this could cause the BIOS to hang when the EDID is retrieved on Start.    if (m_MonitorPowerState > PowerDeviceD0)    {        SetPowerState(TargetId, PowerDeviceD0, PowerActionNone);    }    // The driver has to black out the display and ensure it is visible when releasing ownership    BlackOutScreen(SourceId);    *pDisplayInfo = m_CurrentModes[SourceId].DispInfo;    return StopDevice();}NTSTATUS BASIC_DISPLAY_DRIVER::QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps){    PAGED_CODE();    BDD_ASSERT(pVidPnHWCaps != NULL);    BDD_ASSERT(pVidPnHWCaps->SourceId < MAX_VIEWS);    BDD_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    return STATUS_SUCCESS;}NTSTATUS BASIC_DISPLAY_DRIVER::GetEdid(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId){    PAGED_CODE();    BDD_ASSERT_CHK(!m_Flags.EDID_Attempted);    NTSTATUS Status = STATUS_SUCCESS;    RtlZeroMemory(m_EDIDs[TargetId], sizeof(m_EDIDs[TargetId]));    m_Flags.EDID_Attempted = TRUE;    return Status;}VOID BASIC_DISPLAY_DRIVER::BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId){    PAGED_CODE();    UINT ScreenHeight = m_CurrentModes[SourceId].DispInfo.Height;    UINT ScreenPitch = m_CurrentModes[SourceId].DispInfo.Pitch;    PHYSICAL_ADDRESS NewPhysAddrStart = m_CurrentModes[SourceId].DispInfo.PhysicAddress;    PHYSICAL_ADDRESS NewPhysAddrEnd;    NewPhysAddrEnd.QuadPart = NewPhysAddrStart.QuadPart + (ScreenHeight * ScreenPitch);    if (m_CurrentModes[SourceId].Flags.FrameBufferIsActive)    {        BYTE* MappedAddr = reinterpret_cast(m_CurrentModes[SourceId].FrameBuffer.Ptr);        // Zero any memory at the start that hasn't been zeroed recently        if (NewPhysAddrStart.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart)        {            if (NewPhysAddrEnd.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart)            {                // No overlap                RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch);            }            else            {                RtlZeroMemory(MappedAddr, (UINT)(m_CurrentModes[SourceId].ZeroedOutStart.QuadPart - NewPhysAddrStart.QuadPart));            }        }        // Zero any memory at the end that hasn't been zeroed recently        if (NewPhysAddrEnd.QuadPart > m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart)        {            if (NewPhysAddrStart.QuadPart > m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart)            {                // No overlap                // NOTE: When actual pixels were the most recent thing drawn, ZeroedOutStart & ZeroedOutEnd will both be 0                // and this is the path that will be used to black out the current screen.                RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch);            }            else            {                RtlZeroMemory(MappedAddr, (UINT)(NewPhysAddrEnd.QuadPart - m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart));            }        }    }    m_CurrentModes[SourceId].ZeroedOutStart.QuadPart = NewPhysAddrStart.QuadPart;    m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart = NewPhysAddrEnd.QuadPart;}NTSTATUS BASIC_DISPLAY_DRIVER::WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue){    PAGED_CODE();    NTSTATUS Status;    ANSI_STRING AnsiStrValue;    UNICODE_STRING UnicodeStrValue;    UNICODE_STRING UnicodeStrValueName;    // 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))    {        BDD_LOG_ERROR1("RtlAnsiStringToUnicodeString failed with Status: 0x%I64x", 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))    {        BDD_LOG_ERROR1("ZwSetValueKey failed with Status: 0x%I64x", Status);    }    return Status;}NTSTATUS BASIC_DISPLAY_DRIVER::RegisterHWInfo(){    PAGED_CODE();    NTSTATUS Status;    // TODO: Replace these strings with proper information    PCSTR StrHWInfoChipType = "Replace with the chip name";    PCSTR StrHWInfoDacType = "Replace with the DAC name or identifier (ID)";    PCSTR StrHWInfoAdapterString = "Replace with the name of the adapter";    PCSTR StrHWInfoBiosString = "Replace with information about the BIOS";    HANDLE DevInstRegKeyHandle;    Status = IoOpenDeviceRegistryKey(m_pPhysicalDevice, PLUGPLAY_REGKEY_DRIVER, KEY_SET_VALUE, &DevInstRegKeyHandle);    if (!NT_SUCCESS(Status))    {        BDD_LOG_ERROR2("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))    {        BDD_LOG_ERROR1("ZwSetValueKey for MemorySize failed with Status: 0x%I64x", Status);        return Status;    }    return Status;}//// Non-Paged Code//#pragma code_seg(push)#pragma code_seg()D3DDDI_VIDEO_PRESENT_SOURCE_ID BASIC_DISPLAY_DRIVER::FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero){    UNREFERENCED_PARAMETER(TargetId);    BDD_ASSERT_CHK(TargetId < MAX_CHILDREN);    for (UINT SourceId = 0; SourceId < MAX_VIEWS; ++SourceId)    {        if (m_CurrentModes[SourceId].FrameBuffer.Ptr != NULL)        {            return SourceId;        }    }    return DefaultToZero ? 0 : D3DDDI_ID_UNINITIALIZED;}VOID BASIC_DISPLAY_DRIVER::DpcRoutine(VOID){    m_DxgkInterface.DxgkCbNotifyDpc((HANDLE)m_DxgkInterface.DeviceHandle);}BOOLEAN BASIC_DISPLAY_DRIVER::InterruptRoutine(_In_  ULONG MessageNumber){    UNREFERENCED_PARAMETER(MessageNumber);    // BDD cannot handle interrupts    return FALSE;}VOID BASIC_DISPLAY_DRIVER::ResetDevice(VOID){}// Must be Non-Paged, as it sets up the display for a bugcheckNTSTATUS BASIC_DISPLAY_DRIVER::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);    m_SystemDisplaySourceId = D3DDDI_ID_UNINITIALIZED;    BDD_ASSERT((TargetId < MAX_CHILDREN) || (TargetId == D3DDDI_ID_UNINITIALIZED));    // Find the frame buffer for displaying the bugcheck, if it was successfully mapped    if (TargetId == D3DDDI_ID_UNINITIALIZED)    {        for (UINT SourceIdx = 0; SourceIdx < MAX_VIEWS; ++SourceIdx)        {            if (m_CurrentModes[SourceIdx].FrameBuffer.Ptr != NULL)            {                m_SystemDisplaySourceId = SourceIdx;                break;            }        }    }    else    {        m_SystemDisplaySourceId = FindSourceForTarget(TargetId, FALSE);    }    if (m_SystemDisplaySourceId == D3DDDI_ID_UNINITIALIZED)    {        {            return STATUS_UNSUCCESSFUL;        }    }    if ((m_CurrentModes[m_SystemDisplaySourceId].Rotation == D3DKMDT_VPPR_ROTATE90) ||        (m_CurrentModes[m_SystemDisplaySourceId].Rotation == D3DKMDT_VPPR_ROTATE270))    {        *pHeight = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Width;        *pWidth = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Height;    }    else    {        *pWidth = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Width;        *pHeight = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Height;    }    *pColorFormat = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.ColorFormat;    return STATUS_SUCCESS;}// Must be Non-Paged, as it is called to display the bugcheck screenVOID BASIC_DISPLAY_DRIVER::SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VOID* pSource,                                              _In_ UINT SourceWidth,                                              _In_ UINT SourceHeight,                                              _In_ UINT SourceStride,                                              _In_ INT PositionX,                                              _In_ INT PositionY){    // 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;    // Set up destination blt info    BLT_INFO DstBltInfo;    DstBltInfo.pBits = m_CurrentModes[m_SystemDisplaySourceId].FrameBuffer.Ptr;    DstBltInfo.Pitch = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Pitch;    DstBltInfo.BitsPerPel = BPPFromPixelFormat(m_CurrentModes[m_SystemDisplaySourceId].DispInfo.ColorFormat);    DstBltInfo.Offset.x = 0;    DstBltInfo.Offset.y = 0;    DstBltInfo.Rotation = m_CurrentModes[m_SystemDisplaySourceId].Rotation;    DstBltInfo.Width = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Width;    DstBltInfo.Height = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Height;    // Set up source blt info    BLT_INFO SrcBltInfo;    SrcBltInfo.pBits = pSource;    SrcBltInfo.Pitch = SourceStride;    SrcBltInfo.BitsPerPel = 32;    SrcBltInfo.Offset.x = -PositionX;    SrcBltInfo.Offset.y = -PositionY;    SrcBltInfo.Rotation = D3DKMDT_VPPR_IDENTITY;    SrcBltInfo.Width = SourceWidth;    SrcBltInfo.Height = SourceHeight;    BltBits(&DstBltInfo,            &SrcBltInfo,            1, // NumRects            &Rect);}#pragma code_seg(pop) // End Non-Paged Code

C++程式檔案 bdd_ddi.cxx

/******************************Module*Header*******************************\* Module Name: BDD_DDI.cxx** Basic Display Driver DDI entry points redirects*** Copyright (c) 2010 Microsoft Corporation\**************************************************************************/#include "BDD.hxx"#pragma code_seg(push)#pragma code_seg("INIT")// BEGIN: Init Code//// Driver Entry point//extern "C"NTSTATUSDriverEntry(    _In_  DRIVER_OBJECT*  pDriverObject,    _In_  UNICODE_STRING* pRegistryPath){    PAGED_CODE();    // Initialize DDI function pointers and dxgkrnl    KMDDOD_INITIALIZATION_DATA InitialData = {0};    InitialData.Version = DXGKDDI_INTERFACE_VERSION;    InitialData.DxgkDdiAddDevice                    = BddDdiAddDevice;    InitialData.DxgkDdiStartDevice                  = BddDdiStartDevice;    InitialData.DxgkDdiStopDevice                   = BddDdiStopDevice;    InitialData.DxgkDdiResetDevice                  = BddDdiResetDevice;    InitialData.DxgkDdiRemoveDevice                 = BddDdiRemoveDevice;    InitialData.DxgkDdiDispatchIoRequest            = BddDdiDispatchIoRequest;    InitialData.DxgkDdiInterruptRoutine             = BddDdiInterruptRoutine;    InitialData.DxgkDdiDpcRoutine                   = BddDdiDpcRoutine;    InitialData.DxgkDdiQueryChildRelations          = BddDdiQueryChildRelations;    InitialData.DxgkDdiQueryChildStatus             = BddDdiQueryChildStatus;    InitialData.DxgkDdiQueryDeviceDescriptor        = BddDdiQueryDeviceDescriptor;    InitialData.DxgkDdiSetPowerState                = BddDdiSetPowerState;    InitialData.DxgkDdiUnload                       = BddDdiUnload;    InitialData.DxgkDdiQueryAdapterInfo             = BddDdiQueryAdapterInfo;    InitialData.DxgkDdiSetPointerPosition           = BddDdiSetPointerPosition;    InitialData.DxgkDdiSetPointerShape              = BddDdiSetPointerShape;    InitialData.DxgkDdiIsSupportedVidPn             = BddDdiIsSupportedVidPn;    InitialData.DxgkDdiRecommendFunctionalVidPn     = BddDdiRecommendFunctionalVidPn;    InitialData.DxgkDdiEnumVidPnCofuncModality      = BddDdiEnumVidPnCofuncModality;    InitialData.DxgkDdiSetVidPnSourceVisibility     = BddDdiSetVidPnSourceVisibility;    InitialData.DxgkDdiCommitVidPn                  = BddDdiCommitVidPn;    InitialData.DxgkDdiUpdateActiveVidPnPresentPath = BddDdiUpdateActiveVidPnPresentPath;    InitialData.DxgkDdiRecommendMonitorModes        = BddDdiRecommendMonitorModes;    InitialData.DxgkDdiQueryVidPnHWCapability       = BddDdiQueryVidPnHWCapability;    InitialData.DxgkDdiPresentDisplayOnly           = BddDdiPresentDisplayOnly;    InitialData.DxgkDdiStopDeviceAndReleasePostDisplayOwnership = BddDdiStopDeviceAndReleasePostDisplayOwnership;    InitialData.DxgkDdiSystemDisplayEnable          = BddDdiSystemDisplayEnable;    InitialData.DxgkDdiSystemDisplayWrite           = BddDdiSystemDisplayWrite;    NTSTATUS Status = DxgkInitializeDisplayOnlyDriver(pDriverObject, pRegistryPath, &InitialData);    if (!NT_SUCCESS(Status))    {        BDD_LOG_ERROR1("DxgkInitializeDisplayOnlyDriver failed with Status: 0x%I64x", Status);        return Status;    }    return Status;}// END: Init Code#pragma code_seg(pop)#pragma code_seg(push)#pragma code_seg("PAGE")//// PnP DDIs//VOIDBddDdiUnload(VOID){    PAGED_CODE();}NTSTATUSBddDdiAddDevice(    _In_ DEVICE_OBJECT* pPhysicalDeviceObject,    _Outptr_ PVOID*  ppDeviceContext){    PAGED_CODE();    if ((pPhysicalDeviceObject == NULL) ||        (ppDeviceContext == NULL))    {        BDD_LOG_ERROR2("One of pPhysicalDeviceObject (0x%I64x), ppDeviceContext (0x%I64x) is NULL",                        pPhysicalDeviceObject, ppDeviceContext);        return STATUS_INVALID_PARAMETER;    }    *ppDeviceContext = NULL;    BASIC_DISPLAY_DRIVER* pBDD = new(NonPagedPoolNx) BASIC_DISPLAY_DRIVER(pPhysicalDeviceObject);    if (pBDD == NULL)    {        BDD_LOG_LOW_RESOURCE0("pBDD failed to be allocated");        return STATUS_NO_MEMORY;    }    *ppDeviceContext = pBDD;    return STATUS_SUCCESS;}NTSTATUSBddDdiRemoveDevice(    _In_  VOID* pDeviceContext){    PAGED_CODE();    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    if (pBDD)    {        delete pBDD;        pBDD = NULL;    }    return STATUS_SUCCESS;}NTSTATUSBddDdiStartDevice(    _In_  VOID*              pDeviceContext,    _In_  DXGK_START_INFO*   pDxgkStartInfo,    _In_  DXGKRNL_INTERFACE* pDxgkInterface,    _Out_ ULONG*             pNumberOfViews,    _Out_ ULONG*             pNumberOfChildren){    PAGED_CODE();    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    return pBDD->StartDevice(pDxgkStartInfo, pDxgkInterface, pNumberOfViews, pNumberOfChildren);}NTSTATUSBddDdiStopDevice(    _In_  VOID* pDeviceContext){    PAGED_CODE();    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    return pBDD->StopDevice();}NTSTATUSBddDdiDispatchIoRequest(    _In_  VOID*                 pDeviceContext,    _In_  ULONG                 VidPnSourceId,    _In_  VIDEO_REQUEST_PACKET* pVideoRequestPacket){    PAGED_CODE();    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->DispatchIoRequest(VidPnSourceId, pVideoRequestPacket);}NTSTATUSBddDdiSetPowerState(    _In_  VOID*              pDeviceContext,    _In_  ULONG              HardwareUid,    _In_  DEVICE_POWER_STATE DevicePowerState,    _In_  POWER_ACTION       ActionType){    PAGED_CODE();    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    if (!pBDD->IsDriverActive())    {        // If the driver isn't active, SetPowerState can still be called, however in BDD's case        // this shouldn't do anything, as it could for instance be called on BDD Fallback after        // Fallback has been stopped and BDD PnP is being started. Fallback doesn't have control        // of the hardware in this case.        return STATUS_SUCCESS;    }    return pBDD->SetPowerState(HardwareUid, DevicePowerState, ActionType);}NTSTATUSBddDdiQueryChildRelations(    _In_                             VOID*                  pDeviceContext,    _Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,    _In_                             ULONG                  ChildRelationsSize){    PAGED_CODE();    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    return pBDD->QueryChildRelations(pChildRelations, ChildRelationsSize);}NTSTATUSBddDdiQueryChildStatus(    _In_    VOID*              pDeviceContext,    _Inout_ DXGK_CHILD_STATUS* pChildStatus,    _In_    BOOLEAN            NonDestructiveOnly){    PAGED_CODE();    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    return pBDD->QueryChildStatus(pChildStatus, NonDestructiveOnly);}NTSTATUSBddDdiQueryDeviceDescriptor(    _In_  VOID*                     pDeviceContext,    _In_  ULONG                     ChildUid,    _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor){    PAGED_CODE();    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    if (!pBDD->IsDriverActive())    {        // During stress testing of PnPStop, it is possible for BDD 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.        BDD_LOG_WARNING1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->QueryDeviceDescriptor(ChildUid, pDeviceDescriptor);}//// WDDM Display Only Driver DDIs//NTSTATUSAPIENTRYBddDdiQueryAdapterInfo(    _In_ CONST HANDLE                    hAdapter,    _In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    return pBDD->QueryAdapterInfo(pQueryAdapterInfo);}NTSTATUSAPIENTRYBddDdiSetPointerPosition(    _In_ CONST HANDLE                      hAdapter,    _In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->SetPointerPosition(pSetPointerPosition);}NTSTATUSAPIENTRYBddDdiSetPointerShape(    _In_ CONST HANDLE                   hAdapter,    _In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->SetPointerShape(pSetPointerShape);}NTSTATUSAPIENTRYBddDdiPresentDisplayOnly(    _In_ CONST HANDLE                       hAdapter,    _In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->PresentDisplayOnly(pPresentDisplayOnly);}NTSTATUSAPIENTRYBddDdiStopDeviceAndReleasePostDisplayOwnership(    _In_  VOID*                          pDeviceContext,    _In_  D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,    _Out_ DXGK_DISPLAY_INFORMATION*      DisplayInfo){    PAGED_CODE();    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    return pBDD->StopDeviceAndReleasePostDisplayOwnership(TargetId, DisplayInfo);}NTSTATUSAPIENTRYBddDdiIsSupportedVidPn(    _In_ CONST HANDLE                 hAdapter,    _Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->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 BDD 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.        BDD_LOG_WARNING1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->IsSupportedVidPn(pIsSupportedVidPn);}NTSTATUSAPIENTRYBddDdiRecommendFunctionalVidPn(    _In_ CONST HANDLE                                  hAdapter,    _In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->RecommendFunctionalVidPn(pRecommendFunctionalVidPn);}NTSTATUSAPIENTRYBddDdiRecommendVidPnTopology(    _In_ CONST HANDLE                                 hAdapter,    _In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST  pRecommendVidPnTopology){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->RecommendVidPnTopology(pRecommendVidPnTopology);}NTSTATUSAPIENTRYBddDdiRecommendMonitorModes(    _In_ CONST HANDLE                                hAdapter,    _In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST  pRecommendMonitorModes){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->RecommendMonitorModes(pRecommendMonitorModes);}NTSTATUSAPIENTRYBddDdiEnumVidPnCofuncModality(    _In_ CONST HANDLE                                 hAdapter,    _In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->EnumVidPnCofuncModality(pEnumCofuncModality);}NTSTATUSAPIENTRYBddDdiSetVidPnSourceVisibility(    _In_ CONST HANDLE                            hAdapter,    _In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->SetVidPnSourceVisibility(pSetVidPnSourceVisibility);}NTSTATUSAPIENTRYBddDdiCommitVidPn(    _In_ CONST HANDLE                     hAdapter,    _In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->CommitVidPn(pCommitVidPn);}NTSTATUSAPIENTRYBddDdiUpdateActiveVidPnPresentPath(    _In_ CONST HANDLE                                      hAdapter,    _In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->UpdateActiveVidPnPresentPath(pUpdateActiveVidPnPresentPath);}NTSTATUSAPIENTRYBddDdiQueryVidPnHWCapability(    _In_ CONST HANDLE                       hAdapter,    _Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps){    PAGED_CODE();    BDD_ASSERT_CHK(hAdapter != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(hAdapter);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return STATUS_UNSUCCESSFUL;    }    return pBDD->QueryVidPnHWCapability(pVidPnHWCaps);}//END: Paged Code#pragma code_seg(pop)#pragma code_seg(push)#pragma code_seg()// BEGIN: Non-Paged CodeVOIDBddDdiDpcRoutine(    _In_  VOID* pDeviceContext){    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    if (!pBDD->IsDriverActive())    {        BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);        return;    }    pBDD->DpcRoutine();}BOOLEANBddDdiInterruptRoutine(    _In_  VOID* pDeviceContext,    _In_  ULONG MessageNumber){    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    return pBDD->InterruptRoutine(MessageNumber);}VOIDBddDdiResetDevice(    _In_  VOID* pDeviceContext){    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    pBDD->ResetDevice();}NTSTATUSAPIENTRYBddDdiSystemDisplayEnable(    _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){    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    return pBDD->SystemDisplayEnable(TargetId, Flags, Width, Height, ColorFormat);}VOIDAPIENTRYBddDdiSystemDisplayWrite(    _In_  VOID* pDeviceContext,    _In_  VOID* Source,    _In_  UINT  SourceWidth,    _In_  UINT  SourceHeight,    _In_  UINT  SourceStride,    _In_  UINT  PositionX,    _In_  UINT  PositionY){    BDD_ASSERT_CHK(pDeviceContext != NULL);    BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast(pDeviceContext);    pBDD->SystemDisplayWrite(Source, SourceWidth, SourceHeight, SourceStride, PositionX, PositionY);}// END: Non-Paged Code#pragma code_seg(pop)

C++程式檔案 bdd_dmm.cxx

/******************************Module*Header*******************************\* Module Name: bdd_dmm.hxx** Basic Display Driver display-mode management (DMM) function implementations*** Copyright (c) 2010 Microsoft Corporation\**************************************************************************/#include "BDD.hxx"#pragma code_seg("PAGE")// Display-Only Devices can only return display modes of D3DDDIFMT_A8R8G8B8.// Color conversion takes place if the app's fullscreen backbuffer has different format.// Full display drivers can add more if the hardware supports them.D3DDDIFORMAT gBddPixelFormats[] = {    D3DDDIFMT_A8R8G8B8};// TODO: Need to also check pinned modes and the path parameters, not just topologyNTSTATUS BASIC_DISPLAY_DRIVER::IsSupportedVidPn(_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn){    PAGED_CODE();    BDD_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))    {        BDD_LOG_ERROR2("DxgkCbQueryVidPnInterface failed with Status = 0x%I64x, hDesiredVidPn = 0x%I64x", Status, pIsSupportedVidPn->hDesiredVidPn);        return Status;    }    D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;    CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;    Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPn->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);    if (!NT_SUCCESS(Status))    {        BDD_LOG_ERROR2("pfnGetTopology failed with Status = 0x%I64x, hDesiredVidPn = 0x%I64x", 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))        {            BDD_LOG_ERROR3("pfnGetNumPathsFromSource failed with Status = 0x%I64x. 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;    return STATUS_SUCCESS;}NTSTATUS BASIC_DISPLAY_DRIVER::RecommendFunctionalVidPn(_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn){    PAGED_CODE();    BDD_ASSERT(pRecommendFunctionalVidPn == NULL);    return STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN;}NTSTATUS BASIC_DISPLAY_DRIVER::RecommendVidPnTopology(_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology){    PAGED_CODE();    BDD_ASSERT(pRecommendVidPnTopology == NULL);    return STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN;}NTSTATUS BASIC_DISPLAY_DRIVER::RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes){    PAGED_CODE();    // This is always called to recommend modes for the monitor. The sample driver doesn't provide EDID for a monitor, so     // the OS prefills the list with default monitor modes. Since the required mode might not be in the list, it should     // be provided as a recommended mode.    return AddSingleMonitorMode(pRecommendMonitorModes);}// Tell DMM about all the modes, etc. that are supportedNTSTATUS BASIC_DISPLAY_DRIVER::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality){    PAGED_CODE();    BDD_ASSERT(pEnumCofuncModality != NULL);    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))    {        BDD_LOG_ERROR2("DxgkCbQueryVidPnInterface failed with Status = 0x%I64x, 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))    {        BDD_LOG_ERROR2("pfnGetTopology failed with Status = 0x%I64x, 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))    {        BDD_LOG_ERROR2("pfnAcquireFirstPathInfo failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x", Status, hVidPnTopology);        return Status;    }    // Loop through all available paths.    while (Status != STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)    {        // Get the Source Mode Set interface so the pinned mode can be retrieved        Status = pVidPnInterface->pfnAcquireSourceModeSet(pEnumCofuncModality->hConstrainingVidPn,                                                          pVidPnPresentPath->VidPnSourceId,                                                          &hVidPnSourceModeSet,                                                          &pVidPnSourceModeSetInterface);        if (!NT_SUCCESS(Status))        {            BDD_LOG_ERROR3("pfnAcquireSourceModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, SourceId = 0x%I64x",                           Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnSourceId);            break;        }        // Get the pinned mode, needed when VidPnSource isn't pivot, and when VidPnTarget isn't pivot        Status = pVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(hVidPnSourceModeSet, &pVidPnPinnedSourceModeInfo);        if (!NT_SUCCESS(Status))        {            BDD_LOG_ERROR2("pfnAcquirePinnedModeInfo failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x", Status, hVidPnSourceModeSet);            break;        }        // SOURCE MODES: If this source mode isn't the pivot point, do work on the source mode set        if (!((pEnumCofuncModality->EnumPivotType == D3DKMDT_EPT_VIDPNSOURCE) &&              (pEnumCofuncModality->EnumPivot.VidPnSourceId == pVidPnPresentPath->VidPnSourceId)))        {            // If there's no pinned source add possible modes (otherwise they've already been added)            if (pVidPnPinnedSourceModeInfo == NULL)            {                // Release the acquired source mode set, since going to create a new one to put all modes in                Status = pVidPnInterface->pfnReleaseSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet);                if (!NT_SUCCESS(Status))                {                    BDD_LOG_ERROR3("pfnReleaseSourceModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, hVidPnSourceModeSet = 0x%I64x",                                   Status, pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet);                    break;                }                hVidPnSourceModeSet = 0; // Successfully released it                // Create a new source mode set which will be added to the constraining VidPn with all the possible modes                Status = pVidPnInterface->pfnCreateNewSourceModeSet(pEnumCofuncModality->hConstrainingVidPn,                                                                    pVidPnPresentPath->VidPnSourceId,                                                                    &hVidPnSourceModeSet,                                                                    &pVidPnSourceModeSetInterface);                if (!NT_SUCCESS(Status))                {                    BDD_LOG_ERROR3("pfnCreateNewSourceModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, SourceId = 0x%I64x",                                   Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnSourceId);                    break;                }                // Add the appropriate modes to the source mode set                {                    Status = AddSingleSourceMode(pVidPnSourceModeSetInterface, hVidPnSourceModeSet, pVidPnPresentPath->VidPnSourceId);                }                if (!NT_SUCCESS(Status))                {                    break;                }                // Give DMM back the source modes just populated                Status = pVidPnInterface->pfnAssignSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnSourceId, hVidPnSourceModeSet);                if (!NT_SUCCESS(Status))                {                    BDD_LOG_ERROR4("pfnAssignSourceModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, SourceId = 0x%I64x, hVidPnSourceModeSet = 0x%I64x",                                   Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnSourceId, hVidPnSourceModeSet);                    break;                }                hVidPnSourceModeSet = 0; // Successfully assigned it (equivalent to releasing it)            }        }// End: SOURCE MODES        // TARGET MODES: If this target mode isn't the pivot point, do work on the target mode set        if (!((pEnumCofuncModality->EnumPivotType == D3DKMDT_EPT_VIDPNTARGET) &&              (pEnumCofuncModality->EnumPivot.VidPnTargetId == pVidPnPresentPath->VidPnTargetId)))        {            // Get the Target Mode Set interface so modes can be added if necessary            Status = pVidPnInterface->pfnAcquireTargetModeSet(pEnumCofuncModality->hConstrainingVidPn,                                                              pVidPnPresentPath->VidPnTargetId,                                                              &hVidPnTargetModeSet,                                                              &pVidPnTargetModeSetInterface);            if (!NT_SUCCESS(Status))            {                BDD_LOG_ERROR3("pfnAcquireTargetModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, TargetId = 0x%I64x",                               Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnTargetId);                break;            }            Status = pVidPnTargetModeSetInterface->pfnAcquirePinnedModeInfo(hVidPnTargetModeSet, &pVidPnPinnedTargetModeInfo);            if (!NT_SUCCESS(Status))            {                BDD_LOG_ERROR2("pfnAcquirePinnedModeInfo failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x", Status, hVidPnTargetModeSet);                break;            }            // If there's no pinned target add possible modes (otherwise they've already been added)            if (pVidPnPinnedTargetModeInfo == NULL)            {                // Release the acquired target mode set, since going to create a new one to put all modes in                Status = pVidPnInterface->pfnReleaseTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet);                if (!NT_SUCCESS(Status))                {                    BDD_LOG_ASSERTION3("pfnReleaseTargetModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, hVidPnTargetModeSet = 0x%I64x",                                       Status, pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet);                    break;                }                hVidPnTargetModeSet = 0; // Successfully released it                // Create a new target mode set which will be added to the constraining VidPn with all the possible modes                Status = pVidPnInterface->pfnCreateNewTargetModeSet(pEnumCofuncModality->hConstrainingVidPn,                                                                    pVidPnPresentPath->VidPnTargetId,                                                                    &hVidPnTargetModeSet,                                                                    &pVidPnTargetModeSetInterface);                if (!NT_SUCCESS(Status))                {                    BDD_LOG_ERROR3("pfnCreateNewTargetModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, TargetId = 0x%I64x",                                   Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnTargetId);                    break;                }                Status = AddSingleTargetMode(pVidPnTargetModeSetInterface, hVidPnTargetModeSet, pVidPnPinnedSourceModeInfo, pVidPnPresentPath->VidPnSourceId);                if (!NT_SUCCESS(Status))                {                    break;                }                // Give DMM back the source modes just populated                Status = pVidPnInterface->pfnAssignTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnTargetId, hVidPnTargetModeSet);                if (!NT_SUCCESS(Status))                {                    BDD_LOG_ERROR4("pfnAssignTargetModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, TargetId = 0x%I64x, hVidPnTargetModeSet = 0x%I64x",                                   Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnTargetId, hVidPnTargetModeSet);                    break;                }                hVidPnTargetModeSet = 0; // Successfully assigned it (equivalent to releasing it)            }            else            {                // Release the pinned target as there's no other work to do                Status = pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pVidPnPinnedTargetModeInfo);                if (!NT_SUCCESS(Status))                {                    BDD_LOG_ASSERTION3("pfnReleaseModeInfo failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x, pVidPnPinnedTargetModeInfo = 0x%I64x",                                        Status, hVidPnTargetModeSet, pVidPnPinnedTargetModeInfo);                    break;                }                pVidPnPinnedTargetModeInfo = NULL; // Successfully released it                // Release the acquired target mode set, since it is no longer needed                Status = pVidPnInterface->pfnReleaseTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet);                if (!NT_SUCCESS(Status))                {                    BDD_LOG_ASSERTION3("pfnReleaseTargetModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, hVidPnTargetModeSet = 0x%I64x",                                       Status, pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet);                    break;                }                hVidPnTargetModeSet = 0; // Successfully released it            }        }// End: TARGET MODES        // Nothing else needs the pinned source mode so release it        if (pVidPnPinnedSourceModeInfo != NULL)        {            Status = pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hVidPnSourceModeSet, pVidPnPinnedSourceModeInfo);            if (!NT_SUCCESS(Status))            {                BDD_LOG_ASSERTION3("pfnReleaseModeInfo failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x, pVidPnPinnedSourceModeInfo = 0x%I64x",                                    Status, hVidPnSourceModeSet, pVidPnPinnedSourceModeInfo);                break;            }            pVidPnPinnedSourceModeInfo = NULL; // Successfully released it        }        // With the pinned source mode now released, if the source mode set hasn't been released, release that as well        if (hVidPnSourceModeSet != 0)        {            Status = pVidPnInterface->pfnReleaseSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet);            if (!NT_SUCCESS(Status))            {                BDD_LOG_ERROR3("pfnReleaseSourceModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, hVidPnSourceModeSet = 0x%I64x",                               Status, pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet);                break;            }            hVidPnSourceModeSet = 0; // Successfully released it        }        // If modifying support fields, need to modify a local version of a path structure since the retrieved one is const        D3DKMDT_VIDPN_PRESENT_PATH LocalVidPnPresentPath = *pVidPnPresentPath;        BOOLEAN SupportFieldsModified = FALSE;        // SCALING: If this path's scaling isn't the pivot point, do work on the scaling support        if (!((pEnumCofuncModality->EnumPivotType == D3DKMDT_EPT_SCALING) &&              (pEnumCofuncModality->EnumPivot.VidPnSourceId == pVidPnPresentPath->VidPnSourceId) &&              (pEnumCofuncModality->EnumPivot.VidPnTargetId == pVidPnPresentPath->VidPnTargetId)))        {            // If the scaling is unpinned, then modify the scaling support field            if (pVidPnPresentPath->ContentTransformation.Scaling == D3DKMDT_VPPS_UNPINNED)            {                // Identity and centered scaling are supported, but not any stretch modes                RtlZeroMemory(&(LocalVidPnPresentPath.ContentTransformation.ScalingSupport), sizeof(D3DKMDT_VIDPN_PRESENT_PATH_SCALING_SUPPORT));                LocalVidPnPresentPath.ContentTransformation.ScalingSupport.Identity = 1;                LocalVidPnPresentPath.ContentTransformation.ScalingSupport.Centered = 1;                SupportFieldsModified = TRUE;            }        } // End: SCALING        // ROTATION: If this path's rotation isn't the pivot point, do work on the rotation support        if (!((pEnumCofuncModality->EnumPivotType != D3DKMDT_EPT_ROTATION) &&              (pEnumCofuncModality->EnumPivot.VidPnSourceId == pVidPnPresentPath->VidPnSourceId) &&              (pEnumCofuncModality->EnumPivot.VidPnTargetId == pVidPnPresentPath->VidPnTargetId)))        {            // If the rotation is unpinned, then modify the rotation support field            if (pVidPnPresentPath->ContentTransformation.Rotation == D3DKMDT_VPPR_UNPINNED)            {                LocalVidPnPresentPath.ContentTransformation.RotationSupport.Identity = 1;                // Sample supports only Rotate90                LocalVidPnPresentPath.ContentTransformation.RotationSupport.Rotate90 = 1;                LocalVidPnPresentPath.ContentTransformation.RotationSupport.Rotate180 = 0;                LocalVidPnPresentPath.ContentTransformation.RotationSupport.Rotate270 = 0;                // Since clone is not supported, should not support path-independent rotations                LocalVidPnPresentPath.ContentTransformation.RotationSupport.Offset0 = 1;                SupportFieldsModified = TRUE;            }        } // End: ROTATION        if (SupportFieldsModified)        {            // The correct path will be found by this function and the appropriate fields updated            Status = pVidPnTopologyInterface->pfnUpdatePathSupportInfo(hVidPnTopology, &LocalVidPnPresentPath);            if (!NT_SUCCESS(Status))            {                BDD_LOG_ERROR2("pfnUpdatePathSupportInfo failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x", Status, hVidPnTopology);                break;            }        }        // Get the next path...        // (NOTE: This is the value of Status that will return STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET when it's time to quit the loop)        pVidPnPresentPathTemp = pVidPnPresentPath;        Status = pVidPnTopologyInterface->pfnAcquireNextPathInfo(hVidPnTopology, pVidPnPresentPathTemp, &pVidPnPresentPath);        if (!NT_SUCCESS(Status))        {            BDD_LOG_ERROR3("pfnAcquireNextPathInfo failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x, pVidPnPresentPathTemp = 0x%I64x", Status, hVidPnTopology, pVidPnPresentPathTemp);            break;        }        // ...and release the last path        NTSTATUS TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPathTemp);        if (!NT_SUCCESS(TempStatus))        {            BDD_LOG_ERROR3("pfnReleasePathInfo failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x, pVidPnPresentPathTemp = 0x%I64x", TempStatus, hVidPnTopology, pVidPnPresentPathTemp);            Status = TempStatus;            break;        }        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);        BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));    }    if ((pVidPnTargetModeSetInterface != NULL) &&        (pVidPnPinnedTargetModeInfo != NULL))    {        TempStatus = pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pVidPnPinnedTargetModeInfo);        BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));    }    if (pVidPnPresentPath != NULL)    {        TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPath);        BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));    }    if (pVidPnPresentPathTemp != NULL)    {        TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPathTemp);        BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));    }    if (hVidPnSourceModeSet != 0)    {        TempStatus = pVidPnInterface->pfnReleaseSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet);        BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));    }    if (hVidPnTargetModeSet != 0)    {        TempStatus = pVidPnInterface->pfnReleaseTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet);        BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));    }    BDD_ASSERT_CHK(TempStatus == STATUS_NOT_FOUND || Status != STATUS_SUCCESS);    return Status;}NTSTATUS BASIC_DISPLAY_DRIVER::SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility){    PAGED_CODE();    BDD_ASSERT(pSetVidPnSourceVisibility != NULL);    BDD_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);    }    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 allocationsNTSTATUS BASIC_DISPLAY_DRIVER::CommitVidPn(_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn){    PAGED_CODE();    BDD_ASSERT(pCommitVidPn != NULL);    BDD_ASSERT(pCommitVidPn->AffectedVidPnSourceId < MAX_VIEWS);    NTSTATUS                                 Status;    SIZE_T                                   NumPaths = 0;    D3DKMDT_HVIDPNTOPOLOGY                   hVidPnTopology = 0;    D3DKMDT_HVIDPNSOURCEMODESET              hVidPnSourceModeSet = 0;    CONST DXGK_VIDPN_INTERFACE*              pVidPnInterface = NULL;    CONST DXGK_VIDPNTOPOLOGY_INTERFACE*      pVidPnTopologyInterface = NULL;    CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface = NULL;    CONST D3DKMDT_VIDPN_PRESENT_PATH*        pVidPnPresentPath = NULL;    CONST D3DKMDT_VIDPN_SOURCE_MODE*         pPinnedVidPnSourceModeInfo = NULL;    // Check this CommitVidPn is for the mode change notification when monitor is in power off state.    if (pCommitVidPn->Flags.PathPoweredOff)    {        // Ignore the commitVidPn call for the mode change notification when monitor is in power off state.        Status = STATUS_SUCCESS;        goto CommitVidPnExit;    }    // Get the VidPn Interface so we can get the 'Source Mode Set' and 'VidPn Topology' interfaces    Status = m_DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPn->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);    if (!NT_SUCCESS(Status))    {        BDD_LOG_ERROR2("DxgkCbQueryVidPnInterface failed with Status = 0x%I64x, hFunctionalVidPn = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn);        goto CommitVidPnExit;    }    // Get the VidPn Topology interface so can enumerate paths from source    Status = pVidPnInterface->pfnGetTopology(pCommitVidPn->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface);    if (!NT_SUCCESS(Status))    {        BDD_LOG_ERROR2("pfnGetTopology failed with Status = 0x%I64x, hFunctionalVidPn = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn);        goto CommitVidPnExit;    }    // Find out the number of paths now, if it's 0 don't bother with source mode set and pinned mode, just clear current and then quit    Status = pVidPnTopologyInterface->pfnGetNumPaths(hVidPnTopology, &NumPaths);    if (!NT_SUCCESS(Status))    {        BDD_LOG_ERROR2("pfnGetNumPaths failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x", Status, hVidPnTopology);        goto CommitVidPnExit;    }    if (NumPaths != 0)    {        // Get the Source Mode Set interface so we can get the pinned mode        Status = pVidPnInterface->pfnAcquireSourceModeSet(pCommitVidPn->hFunctionalVidPn,                                                          pCommitVidPn->AffectedVidPnSourceId,                                                          &hVidPnSourceModeSet,                                                          &pVidPnSourceModeSetInterface);        if (!NT_SUCCESS(Status))        {            BDD_LOG_ERROR3("pfnAcquireSourceModeSet failed with Status = 0x%I64x, hFunctionalVidPn = 0x%I64x, SourceId = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn, pCommitVidPn->AffectedVidPnSourceId);            goto CommitVidPnExit;        }        // Get the mode that is being pinned        Status = pVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(hVidPnSourceModeSet, &pPinnedVidPnSourceModeInfo);        if (!NT_SUCCESS(Status))        {            BDD_LOG_ERROR2("pfnAcquirePinnedModeInfo failed with Status = 0x%I64x, hFunctionalVidPn = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn);            goto CommitVidPnExit;        }    }    else    {        // This will cause the successful quit below        pPinnedVidPnSourceModeInfo = NULL;    }    if (m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].FrameBuffer.Ptr &&        !m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].Flags.DoNotMapOrUnmap)    {        Status = UnmapFrameBuffer(m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].FrameBuffer.Ptr,                                  m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].DispInfo.Pitch * m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].DispInfo.Height);        m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].FrameBuffer.Ptr = NULL;        m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].Flags.FrameBufferIsActive = FALSE;        if (!NT_SUCCESS(Status))        {            goto CommitVidPnExit;        }    }    if (pPinnedVidPnSourceModeInfo == NULL)    {        // There is no mode to pin on this source, any old paths here have already been cleared        Status = STATUS_SUCCESS;        goto CommitVidPnExit;    }    Status = IsVidPnSourceModeFieldsValid(pPinnedVidPnSourceModeInfo);    if (!NT_SUCCESS(Status))    {        goto CommitVidPnExit;    }    // Get the number of paths from this source so we can loop through all paths    SIZE_T NumPathsFromSource = 0;    Status = pVidPnTopologyInterface->pfnGetNumPathsFromSource(hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, &NumPathsFromSource);    if (!NT_SUCCESS(Status))    {        BDD_LOG_ERROR2("pfnGetNumPathsFromSource failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x", Status, hVidPnTopology);        goto CommitVidPnExit;    }    // Loop through all paths to set this mode    for (SIZE_T PathIndex = 0; PathIndex < NumPathsFromSource; ++PathIndex)    {        // Get the target id for this path        D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId = D3DDDI_ID_UNINITIALIZED;        Status = pVidPnTopologyInterface->pfnEnumPathTargetsFromSource(hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, PathIndex, &TargetId);        if (!NT_SUCCESS(Status))        {            BDD_LOG_ERROR4("pfnEnumPathTargetsFromSource failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x, SourceId = 0x%I64x, PathIndex = 0x%I64x",                            Status, hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, PathIndex);            goto CommitVidPnExit;        }        // Get the actual path info        Status = pVidPnTopologyInterface->pfnAcquirePathInfo(hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, TargetId, &pVidPnPresentPath);        if (!NT_SUCCESS(Status))        {            BDD_LOG_ERROR4("pfnAcquirePathInfo failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x, SourceId = 0x%I64x, TargetId = 0x%I64x",                            Status, hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, TargetId);            goto CommitVidPnExit;        }        Status = IsVidPnPathFieldsValid(pVidPnPresentPath);        if (!NT_SUCCESS(Status))        {            goto CommitVidPnExit;        }        Status = SetSourceModeAndPath(pPinnedVidPnSourceModeInfo, pVidPnPresentPath);        if (!NT_SUCCESS(Status))        {            goto CommitVidPnExit;        }        Status = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPath);        if (!NT_SUCCESS(Status))        {            BDD_LOG_ERROR3("pfnReleasePathInfo failed with Status = 0x%I64x, hVidPnTopoogy = 0x%I64x, pVidPnPresentPath = 0x%I64x",                            Status, hVidPnTopology, pVidPnPresentPath);            goto CommitVidPnExit;        }        pVidPnPresentPath = NULL; // Successfully released it    }CommitVidPnExit:    NTSTATUS TempStatus;    if ((pVidPnSourceModeSetInterface != NULL) &&        (hVidPnSourceModeSet != 0) &&        (pPinnedVidPnSourceModeInfo != NULL))    {        TempStatus = pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hVidPnSourceModeSet, pPinnedVidPnSourceModeInfo);        NT_ASSERT(NT_SUCCESS(TempStatus));    }    if ((pVidPnInterface != NULL) &&        (pCommitVidPn->hFunctionalVidPn != 0) &&        (hVidPnSourceModeSet != 0))    {        TempStatus = pVidPnInterface->pfnReleaseSourceModeSet(pCommitVidPn->hFunctionalVidPn, hVidPnSourceModeSet);        NT_ASSERT(NT_SUCCESS(TempStatus));    }    if ((pVidPnTopologyInterface != NULL) &&        (hVidPnTopology != 0) &&        (pVidPnPresentPath != NULL))    {        TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPath);        NT_ASSERT(NT_SUCCESS(TempStatus));    }    return Status;}NTSTATUS BASIC_DISPLAY_DRIVER::UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath){    PAGED_CODE();    BDD_ASSERT(pUpdateActiveVidPnPresentPath != NULL);    NTSTATUS Status = IsVidPnPathFieldsValid(&(pUpdateActiveVidPnPresentPath->VidPnPresentPathInfo));    if (!NT_SUCCESS(Status))    {        return Status;    }    // Mark the next present as fullscreen to make sure the full rotation comes through    m_CurrentModes[pUpdateActiveVidPnPresentPath->VidPnPresentPathInfo.VidPnSourceId].Flags.FullscreenPresent = TRUE;    m_CurrentModes[pUpdateActiveVidPnPresentPath->VidPnPresentPathInfo.VidPnSourceId].Rotation = pUpdateActiveVidPnPresentPath->VidPnPresentPathInfo.ContentTransformation.Rotation;    return STATUS_SUCCESS;}//// Private BDD DMM functions//NTSTATUS BASIC_DISPLAY_DRIVER::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode,                                                    CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath){    PAGED_CODE();    CURRENT_BDD_MODE* pCurrentBddMode = &m_CurrentModes[pPath->VidPnSourceId];    NTSTATUS Status = STATUS_SUCCESS;    pCurrentBddMode->Scaling = pPath->ContentTransformation.Scaling;    pCurrentBddMode->SrcModeWidth = pSourceMode->Format.Graphics.PrimSurfSize.cx;    pCurrentBddMode->SrcModeHeight = pSourceMode->Format.Graphics.PrimSurfSize.cy;    pCurrentBddMode->Rotation = pPath->ContentTransformation.Rotation;    if (!pCurrentBddMode->Flags.DoNotMapOrUnmap)    {        // Map the new frame buffer        BDD_ASSERT(pCurrentBddMode->FrameBuffer.Ptr == NULL);        Status = MapFrameBuffer(pCurrentBddMode->DispInfo.PhysicAddress,                                pCurrentBddMode->DispInfo.Pitch * pCurrentBddMode->DispInfo.Height,                                &(pCurrentBddMode->FrameBuffer.Ptr));    }    if (NT_SUCCESS(Status))    {        pCurrentBddMode->Flags.FrameBufferIsActive = TRUE;        BlackOutScreen(pPath->VidPnSourceId);        // Mark that the next present should be fullscreen so the screen doesn't go from black to actual pixels one dirty rect at a time.        pCurrentBddMode->Flags.FullscreenPresent = TRUE;    }    return Status;}NTSTATUS BASIC_DISPLAY_DRIVER::IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) const{    PAGED_CODE();    if (pPath->VidPnSourceId >= MAX_VIEWS)    {        BDD_LOG_ERROR2("VidPnSourceId is 0x%I64x is too high (MAX_VIEWS is 0x%I64x)",                        pPath->VidPnSourceId, MAX_VIEWS);        return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE;    }    else if (pPath->VidPnTargetId >= MAX_CHILDREN)    {        BDD_LOG_ERROR2("VidPnTargetId is 0x%I64x is too high (MAX_CHILDREN is 0x%I64x)",                        pPath->VidPnTargetId, MAX_CHILDREN);        return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET;    }    else if (pPath->GammaRamp.Type != D3DDDI_GAMMARAMP_DEFAULT)    {        BDD_LOG_ERROR1("pPath contains a gamma ramp (0x%I64x)", pPath->GammaRamp.Type);        return STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED;    }    else if ((pPath->ContentTransformation.Scaling != D3DKMDT_VPPS_IDENTITY) &&             (pPath->ContentTransformation.Scaling != D3DKMDT_VPPS_CENTERED) &&             (pPath->ContentTransformation.Scaling != D3DKMDT_VPPS_NOTSPECIFIED) &&             (pPath->ContentTransformation.Scaling != D3DKMDT_VPPS_UNINITIALIZED))    {        BDD_LOG_ERROR1("pPath contains a non-identity scaling (0x%I64x)", pPath->ContentTransformation.Scaling);        return STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED;    }    else if ((pPath->ContentTransformation.Rotation != D3DKMDT_VPPR_IDENTITY) &&             (pPath->ContentTransformation.Rotation != D3DKMDT_VPPR_ROTATE90) &&             (pPath->ContentTransformation.Rotation != D3DKMDT_VPPR_NOTSPECIFIED) &&             (pPath->ContentTransformation.Rotation != D3DKMDT_VPPR_UNINITIALIZED))    {        BDD_LOG_ERROR1("pPath contains a not-supported rotation (0x%I64x)", pPath->ContentTransformation.Rotation);        return STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED;    }    else if ((pPath->VidPnTargetColorBasis != D3DKMDT_CB_SCRGB) &&             (pPath->VidPnTargetColorBasis != D3DKMDT_CB_UNINITIALIZED))    {        BDD_LOG_ERROR1("pPath has a non-linear RGB color basis (0x%I64x)", pPath->VidPnTargetColorBasis);        return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE;    }    else    {        return STATUS_SUCCESS;    }}NTSTATUS BASIC_DISPLAY_DRIVER::IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const{    PAGED_CODE();    if (pSourceMode->Type != D3DKMDT_RMT_GRAPHICS)    {        BDD_LOG_ERROR1("pSourceMode is a non-graphics mode (0x%I64x)", pSourceMode->Type);        return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE;    }    else if ((pSourceMode->Format.Graphics.ColorBasis != D3DKMDT_CB_SCRGB) &&             (pSourceMode->Format.Graphics.ColorBasis != D3DKMDT_CB_UNINITIALIZED))    {        BDD_LOG_ERROR1("pSourceMode has a non-linear RGB color basis (0x%I64x)", pSourceMode->Format.Graphics.ColorBasis);        return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE;    }    else if (pSourceMode->Format.Graphics.PixelValueAccessMode != D3DKMDT_PVAM_DIRECT)    {        BDD_LOG_ERROR1("pSourceMode has a palettized access mode (0x%I64x)", pSourceMode->Format.Graphics.PixelValueAccessMode);        return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE;    }    else    {        for (UINT PelFmtIdx = 0; PelFmtIdx < ARRAYSIZE(gBddPixelFormats); ++PelFmtIdx)        {            if (pSourceMode->Format.Graphics.PixelFormat == gBddPixelFormats[PelFmtIdx])            {                return STATUS_SUCCESS;            }        }        BDD_LOG_ERROR1("pSourceMode has an unknown pixel format (0x%I64x)", pSourceMode->Format.Graphics.PixelFormat);        return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE;    }}// Add more mode from the table.struct SampleSourceMode{    UINT ModeWidth;    UINT ModeHeight;};// The driver will advertise all modes that fit within the actual required mode (see AddSingleSourceMode below)const static SampleSourceMode C_SampleSourceMode[] = {{800,600},{1024,768},{1152,864},{1280,800},{1280,1024},{1400,1050},{1600,1200},{1680,1050},{1920,1200}};const static UINT C_SampleSourceModeMax = sizeof(C_SampleSourceMode)/sizeof(C_SampleSourceMode[0]);NTSTATUS BASIC_DISPLAY_DRIVER::AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface,                                                   D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet,                                                   D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId){    PAGED_CODE();    // There is only one source format supported by display-only drivers, but more can be added in a     // full WDDM driver if the hardware supports them    for (UINT PelFmtIdx = 0; PelFmtIdx < ARRAYSIZE(gBddPixelFormats); ++PelFmtIdx)    {        // Create new mode info that will be populated        D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo = NULL;        NTSTATUS Status = pVidPnSourceModeSetInterface->pfnCreateNewModeInfo(hVidPnSourceModeSet, &pVidPnSourceModeInfo);        if (!NT_SUCCESS(Status))        {            // If failed to create a new mode info, mode doesn't need to be released since it was never created            BDD_LOG_ERROR2("pfnCreateNewModeInfo failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x", Status, hVidPnSourceModeSet);            return Status;        }        // Populate mode info with values from current mode and hard-coded values        // Always report 32 bpp format, this will be color converted during the present if the mode is < 32bpp        pVidPnSourceModeInfo->Type = D3DKMDT_RMT_GRAPHICS;        pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx = m_CurrentModes[SourceId].DispInfo.Width;        pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy = m_CurrentModes[SourceId].DispInfo.Height;        pVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize;        pVidPnSourceModeInfo->Format.Graphics.Stride = m_CurrentModes[SourceId].DispInfo.Pitch;        pVidPnSourceModeInfo->Format.Graphics.PixelFormat = gBddPixelFormats[PelFmtIdx];        pVidPnSourceModeInfo->Format.Graphics.ColorBasis = D3DKMDT_CB_SCRGB;        pVidPnSourceModeInfo->Format.Graphics.PixelValueAccessMode = D3DKMDT_PVAM_DIRECT;        // Add the mode to the source mode set        Status = pVidPnSourceModeSetInterface->pfnAddMode(hVidPnSourceModeSet, pVidPnSourceModeInfo);        if (!NT_SUCCESS(Status))        {            // 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 = pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hVidPnSourceModeSet, pVidPnSourceModeInfo);            UNREFERENCED_PARAMETER(TempStatus);            NT_ASSERT(NT_SUCCESS(TempStatus));            if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET)            {                BDD_LOG_ERROR3("pfnAddMode failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x, pVidPnSourceModeInfo = 0x%I64x", Status, hVidPnSourceModeSet, pVidPnSourceModeInfo);                return Status;            }        }    }    UINT WidthMax = m_CurrentModes[SourceId].DispInfo.Width;    UINT HeightMax = m_CurrentModes[SourceId].DispInfo.Height;    // Add all predefined modes that fit within the bounds of the required (POST) mode    for (UINT ModeIndex = 0; ModeIndex < C_SampleSourceModeMax; ++ModeIndex)    {        if (C_SampleSourceMode[ModeIndex].ModeWidth > WidthMax)        {            break;        }        else if (C_SampleSourceMode[ModeIndex].ModeWidth == WidthMax)        {            if(C_SampleSourceMode[ModeIndex].ModeHeight >= HeightMax)            {                break;            }        }        else        {            if(C_SampleSourceMode[ModeIndex].ModeHeight > HeightMax)            {                continue;            }        }        // There is only one source format supported by display-only drivers, but more can be added in a         // full WDDM driver if the hardware supports them        for (UINT PelFmtIdx = 0; PelFmtIdx < ARRAYSIZE(gBddPixelFormats); ++PelFmtIdx)        {            // Create new mode info that will be populated            D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo = NULL;            NTSTATUS Status = pVidPnSourceModeSetInterface->pfnCreateNewModeInfo(hVidPnSourceModeSet, &pVidPnSourceModeInfo);            if (!NT_SUCCESS(Status))            {                // If failed to create a new mode info, continuing to the next mode and trying again isn't going to be at all helpful, so return                // Also, mode doesn't need to be released since it was never created                BDD_LOG_ERROR2("pfnCreateNewModeInfo failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x", Status, hVidPnSourceModeSet);                return Status;            }            // Populate mode info with values from mode at ModeIndex and hard-coded values            // Always report 32 bpp format, this will be color converted during the present if the mode at ModeIndex was < 32bpp            pVidPnSourceModeInfo->Type = D3DKMDT_RMT_GRAPHICS;            pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx = C_SampleSourceMode[ModeIndex].ModeWidth;            pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy = C_SampleSourceMode[ModeIndex].ModeHeight;            pVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize;            pVidPnSourceModeInfo->Format.Graphics.Stride = 4*C_SampleSourceMode[ModeIndex].ModeWidth;            pVidPnSourceModeInfo->Format.Graphics.PixelFormat = gBddPixelFormats[PelFmtIdx];            pVidPnSourceModeInfo->Format.Graphics.ColorBasis = D3DKMDT_CB_SCRGB;            pVidPnSourceModeInfo->Format.Graphics.PixelValueAccessMode = D3DKMDT_PVAM_DIRECT;            // Add the mode to the source mode set            Status = pVidPnSourceModeSetInterface->pfnAddMode(hVidPnSourceModeSet, pVidPnSourceModeInfo);            if (!NT_SUCCESS(Status))            {                if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET)                {                    BDD_LOG_ERROR3("pfnAddMode failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x, pVidPnSourceModeInfo = 0x%I64x", Status, hVidPnSourceModeSet, pVidPnSourceModeInfo);                }                // 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, continue to next mode anyway                Status = pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hVidPnSourceModeSet, pVidPnSourceModeInfo);                BDD_ASSERT_CHK(NT_SUCCESS(Status));            }        }    }    return STATUS_SUCCESS;}// Add the current mode information (acquired from the POST frame buffer) as the target mode.NTSTATUS BASIC_DISPLAY_DRIVER::AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface,                                                   D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet,                                                   _In_opt_ CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnPinnedSourceModeInfo,                                                   D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId){    PAGED_CODE();    D3DKMDT_VIDPN_TARGET_MODE* pVidPnTargetModeInfo = NULL;    NTSTATUS Status = pVidPnTargetModeSetInterface->pfnCreateNewModeInfo(hVidPnTargetModeSet, &pVidPnTargetModeInfo);    if (!NT_SUCCESS(Status))    {        // If failed to create a new mode info, mode doesn't need to be released since it was never created        BDD_LOG_ERROR2("pfnCreateNewModeInfo failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x", Status, hVidPnTargetModeSet);        return Status;    }    pVidPnTargetModeInfo->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER;    UNREFERENCED_PARAMETER(pVidPnPinnedSourceModeInfo);    pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cx = m_CurrentModes[SourceId].DispInfo.Width;    pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cy = m_CurrentModes[SourceId].DispInfo.Height;    pVidPnTargetModeInfo->VideoSignalInfo.ActiveSize = pVidPnTargetModeInfo->VideoSignalInfo.TotalSize;    pVidPnTargetModeInfo->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;    pVidPnTargetModeInfo->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;    pVidPnTargetModeInfo->VideoSignalInfo.HSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;    pVidPnTargetModeInfo->VideoSignalInfo.HSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;    pVidPnTargetModeInfo->VideoSignalInfo.PixelRate = D3DKMDT_FREQUENCY_NOTSPECIFIED;    pVidPnTargetModeInfo->VideoSignalInfo.ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE;    // We add this as PREFERRED since it is the only supported target    pVidPnTargetModeInfo->Preference = D3DKMDT_MP_PREFERRED;    Status = pVidPnTargetModeSetInterface->pfnAddMode(hVidPnTargetModeSet, pVidPnTargetModeInfo);    if (!NT_SUCCESS(Status))    {        if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET)        {            BDD_LOG_ERROR3("pfnAddMode failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x, pVidPnTargetModeInfo = 0x%I64x", Status, hVidPnTargetModeSet, pVidPnTargetModeInfo);        }        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 = pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pVidPnTargetModeInfo);        UNREFERENCED_PARAMETER(TempStatus);        NT_ASSERT(NT_SUCCESS(TempStatus));        return Status;    }    else    {        // If AddMode succeeded with something other than STATUS_SUCCESS treat it as such anyway when propagating up        return STATUS_SUCCESS;    }}NTSTATUS BASIC_DISPLAY_DRIVER::AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes){    PAGED_CODE();    D3DKMDT_MONITOR_SOURCE_MODE* pMonitorSourceMode = NULL;    NTSTATUS 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        BDD_LOG_ERROR2("pfnCreateNewModeInfo failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x", Status, pRecommendMonitorModes->hMonitorSourceModeSet);        return Status;    }    D3DDDI_VIDEO_PRESENT_SOURCE_ID CorrespondingSourceId = FindSourceForTarget(pRecommendMonitorModes->VideoPresentTargetId, TRUE);    // Since we don't know the real monitor timing information, just use the current display mode (from the POST device) with unknown frequencies    pMonitorSourceMode->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER;    pMonitorSourceMode->VideoSignalInfo.TotalSize.cx = m_CurrentModes[CorrespondingSourceId].DispInfo.Width;    pMonitorSourceMode->VideoSignalInfo.TotalSize.cy = 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)        {            BDD_LOG_ERROR3("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;    }    else    {        // If AddMode succeeded with something other than STATUS_SUCCESS treat it as such anyway when propagating up        return STATUS_SUCCESS;    }}

C++程式檔案 bdd_util.cxx

/******************************Module*Header*******************************\* Module Name: bdd_util.cxx** Basic Display Driver utility functions** Created: 29-Mar-2011* Author: Amos Eshel [amosesh]** Copyright (c) 2011 Microsoft Corporation\**************************************************************************/#include "BDD.hxx"#pragma code_seg("PAGE")//// EDID validation//BOOLEAN IsEdidHeaderValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid){    PAGED_CODE();    static const UCHAR EDID1Header[8] = {0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0};    return memcmp(pEdid, EDID1Header, sizeof(EDID1Header)) == 0;}BOOLEAN IsEdidChecksumValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid){    PAGED_CODE();    BYTE CheckSum = 0;    for (const BYTE* pEdidStart = pEdid; pEdidStart < (pEdid + EDID_V1_BLOCK_SIZE); ++pEdidStart)    {        CheckSum += *pEdidStart;    }    return CheckSum == 0;}//// Frame buffer map/unmap//NTSTATUSMapFrameBuffer(    _In_                       PHYSICAL_ADDRESS    PhysicalAddress,    _In_                       ULONG               Length,    _Outptr_result_bytebuffer_(Length) VOID**              VirtualAddress){    PAGED_CODE();    //    // Check for parameters    //    if ((PhysicalAddress.QuadPart == (ULONGLONG)0) ||        (Length == 0) ||        (VirtualAddress == NULL))    {        BDD_LOG_ERROR3("One of PhysicalAddress.QuadPart (0x%I64x), Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0",                        PhysicalAddress.QuadPart, Length, VirtualAddress);        return STATUS_INVALID_PARAMETER;    }    *VirtualAddress = MmMapIoSpaceEx(PhysicalAddress,                                   Length,                                   PAGE_READWRITE | PAGE_WRITECOMBINE);    if (*VirtualAddress == NULL)    {        // The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined        // isn't supported, so try again with MmNonCached        *VirtualAddress = MmMapIoSpaceEx(PhysicalAddress,                                       Length,                                       PAGE_READWRITE | PAGE_NOCACHE);        if (*VirtualAddress == NULL)        {            BDD_LOG_LOW_RESOURCE1("MmMapIoSpace returned a NULL buffer when trying to allocate 0x%I64x bytes", Length);            return STATUS_NO_MEMORY;        }    }    return STATUS_SUCCESS;}NTSTATUSUnmapFrameBuffer(    _In_reads_bytes_(Length) VOID* VirtualAddress,    _In_                ULONG Length){    PAGED_CODE();    //    // Check for parameters    //    if ((VirtualAddress == NULL) && (Length == 0))    {        // Allow this function to be called when there's no work to do, and treat as successful        return STATUS_SUCCESS;    }    else if ((VirtualAddress == NULL) || (Length == 0))    {        BDD_LOG_ERROR2("Only one of Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0",                        Length, VirtualAddress);        return STATUS_INVALID_PARAMETER;    }    MmUnmapIoSpace(VirtualAddress,                   Length);    return STATUS_SUCCESS;}

最後找出diagnostic tool關於 video & graphic card部分的測試

參考文章:

微軟 Getting started with Windows drivers
Steward
小z说:内核驱动的编译环境
VS2012开发驱动小Tip之:更改KMDF版本以支持XP系统