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系统

2019/07/03

英文學習: 關於 include 三種用法,一次滿足!

動詞 include 放在句子後方作補充說明用法時,有幾個常見的型態--including、included,它們因為太相像而讓許多人總是搞錯它們的用法,像是:

Some people are trapped in the burning building, _____ two men and five women.
請問老師,我應該要用 including 還是 included 呢?


2018-03-07
老師救救我考試英文include用法
出處: 希平方


1) include 怎麼用?

Include 就是一般動詞「包括、包含」的意思,需要搭配主詞、受詞,例如:
The meal includes dessert and beverage.
(餐點包含甜點以及飲料。)

2) including 怎麼用?

Including 是用來帶出包含的事物,在主要句子後面先加上逗號之後,由 including 引導含括的事物,例如剛剛的例句中包含的事物在後面,所以前方的空格應該使用 including:
Some people are trapped in the burning building, including two men and five women.
(有些人被困在那棟著火的建築物裡,包含兩名男性及五名女性。)
再舉個例子:
My grandparents own a farm, and they grow a lot of vegetables there, including cabbage and peppers.
(我的祖父母有一座農場,他們在那裡種許多蔬菜,包含高麗菜跟椒類。)

3) included 怎麼用?

Included 也是在主要句子後加上逗號,再作補充說明,不過它放置的位子跟 including 相反,會先講出所包含的事物,再加上 included 於後方位置。例如剛剛那句可以這樣改:
Some people are trapped in the burning building, two men and five women included.
(有些人被困在那棟著火的建築物裡,包含兩名男性及五名女性。)
或是:
They’re having a big sale, all electric appliances included.
(他們在舉辦一場大拍賣,所有電器產品都有包含在內。)

2019/06/13

英語學習 - 正確使用 時間介係詞 in, on, at 範例很多

作者: Derrick Chen
【時間介係詞】2 分鐘搞懂 In, On, At!讓你再也不怕用錯!

in, on, at 用法的差別就在於:

at:一個準確、特定的時刻
in:月份、季節、年、世紀、一段長而非特定的時間
on:特定日期、星期
邏輯就只是這樣而已!下面幫大家統整常用的時間用法,一起練習看看吧!

in + (months, years, centuries, long periods)

in the morning
in the afternoon
in the evening
in January
in February
in March, 2015
in the spring
in the summer
in the fall
in the winter
in 2015
in the past year
in the 18th century
in the week
in the past
in the future

on + (days and dates)

on Monday
on Tuesday morning
on Wednesday afternoon
on Thursday evening
on Friday night
on 28, April
on New Year’s Day
on Christmas Day
on the weekend

at + (precise time)

at 07:11
at 10 o’clock
at noon
at noon yesterday
at night
at midnight
at the same time