源代码:
filter.cpp 源文件:
#include "filter.h"
#include "ioctl.h"
///global var
wddm_filter_t __gbl_wddm_filter;
#define DEV_NAME L"\\Device\\WddmFilterCtrlDevice"
#define DOS_NAME L"\\DosDevices\\WddmFilterCtrlDevice"
/////
static NTSTATUS create_ctrl_device()
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT devObj;
UNICODE_STRING dev_name;
UNICODE_STRING dos_name;
RtlInitUnicodeString(&dev_name, DEV_NAME);
RtlInitUnicodeString(&dos_name, DOS_NAME);
status = IoCreateDevice(
wf->driver_object,
0,
&dev_name, //dev name
FILE_DEVICE_VIDEO,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&devObj);
if (!NT_SUCCESS(status)) {
DPT("IoCreateDevice err=0x%X\n", status );
return status;
}
status = IoCreateSymbolicLink(&dos_name, &dev_name);
if (!NT_SUCCESS(status)) {
DPT("IoCreateSymbolicLink err=0x%X\n", status );
IoDeleteDevice(devObj);
return status;
}
// attach
wf->dxgkrnl_nextDevice = IoAttachDeviceToDeviceStack(devObj, wf->dxgkrnl_pdoDevice);
if (!wf->dxgkrnl_nextDevice) {
DPT("IoAttachDeviceToDeviceStack error.\n");
IoDeleteDevice(devObj);
IoDeleteSymbolicLink(&dos_name);
return STATUS_NOT_FOUND;
}
devObj->Flags |= DO_POWER_PAGABLE | DO_BUFFERED_IO | DO_DIRECT_IO;
wf->ctrl_devobj = devObj;
/////
return status;
}
NTSTATUS create_wddm_filter_ctrl_device(PDRIVER_OBJECT drvObj )
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING drvPath;
UNICODE_STRING drvName;
RtlInitUnicodeString(&drvPath, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\SERVICES\\DXGKrnl");
RtlInitUnicodeString(&drvName, L"\\Device\\Dxgkrnl");
//
RtlZeroMemory(wf, sizeof(wddm_filter_t));
wf->driver_object = drvObj;
KeInitializeSpinLock(&wf->spin_lock);
InitializeListHead(&wf->vidpn_if_head);
InitializeListHead(&wf->topology_if_head);
//����dxgkrnl.sys����
status = ZwLoadDriver(&drvPath);
if (!NT_SUCCESS(status)) {
if (status != STATUS_IMAGE_ALREADY_LOADED) {
DPT("ZwLoadDriver error st=0x%X\n", status );
return status;
}
}
status = IoGetDeviceObjectPointer(&drvName, FILE_ALL_ACCESS, &wf->dxgkrnl_fileobj, &wf->dxgkrnl_pdoDevice);
if (!NT_SUCCESS(status)) {
DPT("IoGetDeviceObjectPointer Get DxGkrnl err=0x%X\n", status );
return status;
}
KEVENT evt;
IO_STATUS_BLOCK ioStatus;
KeInitializeEvent(&evt, NotificationEvent, FALSE);
PIRP pIrp = IoBuildDeviceIoControlRequest(
IOCTL_VIDEO_DDI_FUNC_REGISTER, //0x23003F , dxgkrnl.sys ����ע�ắ��
wf->dxgkrnl_pdoDevice,
NULL,
0,
&wf->dxgkrnl_dpiInit,
sizeof(PDXGKRNL_DPIINITIALIZE),
TRUE, // IRP_MJ_INTERNAL_DEVICE_CONTROL
&evt,
&ioStatus);
if (!pIrp) {
DPT("IoBuildDeviceIoControlRequest return NULL.\n");
ObDereferenceObject(wf->dxgkrnl_fileobj);
return STATUS_NO_MEMORY;
}
status = IoCallDriver(wf->dxgkrnl_pdoDevice, pIrp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&evt, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
if (!wf->dxgkrnl_dpiInit) {//
DPT("Can not Load PDXGKRNL_DPIINITIALIZE function address. st=0x%X\n", status );
ObDereferenceObject(wf->dxgkrnl_fileobj);
return STATUS_NOT_FOUND;
}
///create filter device
status = create_ctrl_device();
if (!NT_SUCCESS(status)) {
ObDereferenceObject(wf->dxgkrnl_fileobj);
return status;
}
////
return status;
}
NTSTATUS log_event(PUNICODE_STRING str)
{
NTSTATUS status = STATUS_SUCCESS;
return status;
}
filter.h 源文件:
#pragma once
#include <ntddk.h>
#include <wdm.h>
#include <ntstrsafe.h>
#include <ntddvdeo.h>
#include <initguid.h>
#include <Dispmprt.h>
#include <d3dkmdt.h>
////////////////////////////////////////////////////////////
#ifdef DBG
#define DPT DbgPrint
#else
#define DPT //
#endif
///����VIDPN�����豸ID��
#define VIDPN_CHILD_UDID 0x667b0099
/////////
///0x23003F , dxgkrnl.sys ����ע�ắ�� DXGKRNL_DPIINITIALIZE
#define IOCTL_VIDEO_DDI_FUNC_REGISTER \
CTL_CODE( FILE_DEVICE_VIDEO, 0xF, METHOD_NEITHER, FILE_ANY_ACCESS )
typedef __checkReturn NTSTATUS
DXGKRNL_DPIINITIALIZE(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath,
DRIVER_INITIALIZATION_DATA* DriverInitData
);
typedef DXGKRNL_DPIINITIALIZE* PDXGKRNL_DPIINITIALIZE;
///////
struct vidpn_target_id
{
LONG num;
D3DDDI_VIDEO_PRESENT_TARGET_ID ids[1];
};
struct vidpn_paths_t
{
LONG num_paths;
vidpn_target_id* target_paths[1];
};
struct vidpn_intf_t
{
LIST_ENTRY list;
///
D3DKMDT_HVIDPN hVidPn;
DXGK_VIDPN_INTERFACE vidpn_if, mod_vidpn_if;
////
D3DKMDT_HVIDPNTOPOLOGY hTopology;
DXGK_VIDPNTOPOLOGY_INTERFACE topology_if, mod_topology_if;
vidpn_paths_t* paths; ////
};
struct wddm_filter_t
{
PDRIVER_OBJECT driver_object;
////
PDEVICE_OBJECT ctrl_devobj;
////
PFILE_OBJECT dxgkrnl_fileobj;
PDEVICE_OBJECT dxgkrnl_pdoDevice;
PDEVICE_OBJECT dxgkrnl_nextDevice; ///
PDXGKRNL_DPIINITIALIZE dxgkrnl_dpiInit;
///
KSPIN_LOCK spin_lock;
KIRQL kirql;
LIST_ENTRY vidpn_if_head;
LIST_ENTRY topology_if_head;
////
DRIVER_INITIALIZATION_DATA orgDpiFunc; //ԭʼ��DRIVER_INITIALIZATION_DATA
ULONG vidpn_source_count;
ULONG vidpn_target_count;
DXGKRNL_INTERFACE DxgkInterface;
};
extern wddm_filter_t __gbl_wddm_filter;
#define wf (&(__gbl_wddm_filter))
#define wf_lock() KeAcquireSpinLock(&wf->spin_lock, &wf->kirql);
#define wf_unlock() KeReleaseSpinLock(&wf->spin_lock, wf->kirql);
////////////////function
NTSTATUS create_wddm_filter_ctrl_device(PDRIVER_OBJECT drvObj);
inline NTSTATUS call_lower_driver(PIRP irp)
{
IoSkipCurrentIrpStackLocation(irp);
return IoCallDriver(wf->dxgkrnl_nextDevice, irp);
}
NTSTATUS DpiInitialize(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath,
DRIVER_INITIALIZATION_DATA* DriverInitData);
NTSTATUS DxgkDdiEnumVidPnCofuncModality(CONST HANDLE hAdapter,
CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg);
NTSTATUS DxgkDdiIsSupportedVidPn(
IN_CONST_HANDLE hAdapter,
INOUT_PDXGKARG_ISSUPPORTEDVIDPN pIsSupportedVidPn);
NTSTATUS DxgkDdiCommitVidPn(
IN_CONST_HANDLE hAdapter,
IN_CONST_PDXGKARG_COMMITVIDPN_CONST pCommitVidPn);
NTSTATUS DxgkDdiSetVidPnSourceVisibility(
IN_CONST_HANDLE hAdapter,
IN_CONST_PDXGKARG_SETVIDPNSOURCEVISIBILITY pSetVidPnSourceVisibility);
NTSTATUS APIENTRY DxgkDdiSetVidPnSourceAddress(
const HANDLE hAdapter,
const DXGKARG_SETVIDPNSOURCEADDRESS *pSetVidPnSourceAddress);
main.cpp: /// by fanxiushu 2018-08-29
#include "filter.h"
static NTSTATUS commonDispatch(PDEVICE_OBJECT devObj, PIRP irp)
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(irp);
switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
break;
case IRP_MJ_CLEANUP:
break;
case IRP_MJ_CLOSE:
break;
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_VIDEO_DDI_FUNC_REGISTER) {
///////�Կ�������DxgkInitialize�����е��� IOCTL��ȡdxgkrnl.sys��ע��ص�����������hook�˴�����ȡ���Կ������ṩ������DDI����
irp->IoStatus.Information = 0;
irp->IoStatus.Status = STATUS_SUCCESS;
///�����ǵĻص��������ظ��Կ�����.
if (irp->UserBuffer) {
///
irp->IoStatus.Information = sizeof(PDXGKRNL_DPIINITIALIZE);
*((PDXGKRNL_DPIINITIALIZE*)irp->UserBuffer) = DpiInitialize;
}
/////
IoCompleteRequest(irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
///
}
break;
}
////
return call_lower_driver(irp);
}
extern "C" NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
for (UCHAR i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i) {
DriverObject->MajorFunction[i] = commonDispatch;
}
status = create_wddm_filter_ctrl_device(DriverObject);
///
DriverObject->DriverUnload = NULL; ///�������
return status;
}
miniport.cpp 源文件:
#include "filter.h"
static NTSTATUS DxgkDdiAddDevice(
IN_CONST_PDEVICE_OBJECT PhysicalDeviceObject,
OUT PVOID *MiniportDeviceContext)
{
DPT("Hook: DxgkDdiAddDevice. \n");
return wf->orgDpiFunc.DxgkDdiAddDevice(PhysicalDeviceObject, MiniportDeviceContext);
}
static NTSTATUS DxgkDdiRemoveDevice(IN PVOID MiniportDeviceContext)
{
DPT("Hook: DxgkDdiRemoveDevice\n");
return wf->orgDpiFunc.DxgkDdiRemoveDevice(MiniportDeviceContext);
}
////HOOK DxgkCbQueryVidPnInterface, �ҹ�DxgkCbQueryVidPnInterface��ص����лص�������������ƭԭʼ������Target Source �� Path ��ѯ.
//��ѯ����·�������Ұ���SourceId����
static vidpn_paths_t* enum_all_paths(IN_CONST_D3DKMDT_HVIDPNTOPOLOGY topology_handle,
const DXGK_VIDPNTOPOLOGY_INTERFACE* topology_if )
{
NTSTATUS status = STATUS_SUCCESS;
SIZE_T num = 0;
status = topology_if->pfnGetNumPaths(topology_handle, &num);
if (num <= 0) {
return NULL;
}
LONG sz = sizeof(vidpn_paths_t) + sizeof(vidpn_target_id*)*wf->vidpn_source_count +
wf->vidpn_source_count*( sizeof(vidpn_target_id) + num* sizeof(D3DDDI_VIDEO_PRESENT_TARGET_ID) );
vidpn_paths_t* p = (vidpn_paths_t*)ExAllocatePoolWithTag(NonPagedPool, sz, 'FXSD');
if (!p)return NULL;
///
RtlZeroMemory(p, sz);
////
p->num_paths = num;
CHAR* ptr = (CHAR*)p + sizeof(vidpn_paths_t) + sizeof(vidpn_target_id*)*wf->vidpn_source_count;
for (INT i = 0; i < wf->vidpn_source_count; ++i) {
p->target_paths[i] = (vidpn_target_id*)( ptr + i* ( sizeof(vidpn_target_id) + num * sizeof(D3DDDI_VIDEO_PRESENT_TARGET_ID) ) );
}
//////
CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info;
CONST D3DKMDT_VIDPN_PRESENT_PATH *next_path_info;
status = topology_if->pfnAcquireFirstPathInfo(topology_handle, &curr_path_info);
if (status == STATUS_GRAPHICS_DATASET_IS_EMPTY) {
ExFreePool(p);
return NULL;
}
else if (!NT_SUCCESS(status)) {
ExFreePool(p);
return NULL;
}
/////
INT t_num = 0;
do {
///
UINT sid = curr_path_info->VidPnSourceId;
UINT did = curr_path_info->VidPnTargetId;
if ( sid < (UINT)wf->vidpn_source_count) {
///
if (did != VIDPN_CHILD_UDID) {// skip my target path
///
LONG n = p->target_paths[sid]->num;
p->target_paths[sid]->num++;
p->target_paths[sid]->ids[n] = did;
///
t_num++;
}
///
}
///next
status = topology_if->pfnAcquireNextPathInfo(topology_handle, curr_path_info, &next_path_info);
topology_if->pfnReleasePathInfo(topology_handle, curr_path_info);
curr_path_info = next_path_info;
if (status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) { /// end
curr_path_info = NULL;
// DPT("pfnAcquireNextPathInfo no more data.\n");
break;
}
else if (!NT_SUCCESS(status)) {
curr_path_info = NULL;
DPT("pfnAcquireNextPathInfo err=0x%X\n", status);
break;
}
////
} while (TRUE);
p->num_paths = t_num;
///
return p;
}
NTSTATUS pfnGetNumPaths(
IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology,
OUT_PSIZE_T pNumPaths)
{
NTSTATUS status = STATUS_INVALID_PARAMETER;
DXGKDDI_VIDPNTOPOLOGY_GETNUMPATHS ptr_pfnGetNumPaths = NULL;
wf_lock();
for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) {
vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list);
if (intf->hTopology == hVidPnTopology) {
ptr_pfnGetNumPaths = intf->topology_if.pfnGetNumPaths;
if (intf->paths && pNumPaths) {
*pNumPaths = intf->paths->num_paths;
wf_unlock();
DPT("pfnGetNumPaths Cache called num=%d\n", *pNumPaths);
return STATUS_SUCCESS;
}
break;
}
}
wf_unlock();
/////
if (!ptr_pfnGetNumPaths) {
return STATUS_INVALID_PARAMETER;
}
status = ptr_pfnGetNumPaths(hVidPnTopology, pNumPaths);
DPT("pfnGetNumPaths called num=%d\n", *pNumPaths );
return status;
}
NTSTATUS pfnGetNumPathsFromSource(
IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology,
IN_CONST_D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
OUT_PSIZE_T pNumPathsFromSource)
{
NTSTATUS status = STATUS_SUCCESS;
DXGKDDI_VIDPNTOPOLOGY_GETNUMPATHSFROMSOURCE ptr_pfnGetNumPathsFromSource = NULL;
wf_lock();
for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) {
vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list);
if (intf->hTopology == hVidPnTopology) {
ptr_pfnGetNumPathsFromSource = intf->topology_if.pfnGetNumPathsFromSource;
if (intf->paths && pNumPathsFromSource && VidPnSourceId < wf->vidpn_source_count ) {
*pNumPathsFromSource = intf->paths->target_paths[VidPnSourceId]->num;
wf_unlock();
DPT("pfnGetNumPathsFromSource Cache called. num=%d\n", *pNumPathsFromSource);
return STATUS_SUCCESS;
}
break;
}
}
wf_unlock();
////
if (!ptr_pfnGetNumPathsFromSource) {
return STATUS_INVALID_PARAMETER;
}
status = ptr_pfnGetNumPathsFromSource(hVidPnTopology, VidPnSourceId, pNumPathsFromSource);
DPT("pfnGetNumPathsFromSource called. num=%d\n", *pNumPathsFromSource);
return status;
}
NTSTATUS pfnEnumPathTargetsFromSource(
IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology,
IN_CONST_D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
IN_CONST_D3DKMDT_VIDPN_PRESENT_PATH_INDEX VidPnPresentPathIndex,
OUT_PD3DDDI_VIDEO_PRESENT_TARGET_ID pVidPnTargetId)
{
NTSTATUS status = STATUS_SUCCESS;
DXGKDDI_VIDPNTOPOLOGY_ENUMPATHTARGETSFROMSOURCE ptr_pfnEnumPathTargetsFromSource = NULL;
wf_lock();
for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) {
vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list);
if (intf->hTopology == hVidPnTopology) {
ptr_pfnEnumPathTargetsFromSource = intf->topology_if.pfnEnumPathTargetsFromSource;
if (intf->paths && VidPnSourceId < wf->vidpn_source_count && pVidPnTargetId ) {
if (VidPnPresentPathIndex >= intf->paths->target_paths[VidPnSourceId]->num) {
wf_unlock();
DPT("VidPnPresentPathIndex >= intf->paths->target_path_num[VidPnSourceId]\n");
return STATUS_INVALID_PARAMETER;
}
*pVidPnTargetId = intf->paths->target_paths[VidPnSourceId]->ids[VidPnPresentPathIndex]; ////
wf_unlock();
DPT("pfnEnumPathTargetsFromSource Cache called sourceId=%d, index=%d, targetid=%d, st=0x%X\n", VidPnSourceId, VidPnPresentPathIndex, *pVidPnTargetId, status);
return STATUS_SUCCESS;
}
break;
}
}
wf_unlock();
/////
if (!ptr_pfnEnumPathTargetsFromSource) {
return STATUS_INVALID_PARAMETER;
}
status = ptr_pfnEnumPathTargetsFromSource(hVidPnTopology, VidPnSourceId, VidPnPresentPathIndex, pVidPnTargetId);
DPT("pfnEnumPathTargetsFromSource called sourceId=%d, index=%d, targetid=%d, st=0x%X\n", VidPnSourceId, VidPnPresentPathIndex, *pVidPnTargetId, status );
return status;
}
static NTSTATUS skip_my_target_path(
IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology,
IN_CONST_PD3DKMDT_VIDPN_PRESENT_PATH_CONST pVidPnPresentPathInfo,
DEREF_OUT_CONST_PPD3DKMDT_VIDPN_PRESENT_PATH ppNextVidPnPresentPathInfo,
DXGKDDI_VIDPNTOPOLOGY_ACQUIRENEXTPATHINFO ptr_pfnAcquireNextPathInfo,
DXGKDDI_VIDPNTOPOLOGY_RELEASEPATHINFO ptr_pfnReleasePathInfo)
{
NTSTATUS status = STATUS_SUCCESS;
CONST D3DKMDT_VIDPN_PRESENT_PATH* curr_path = pVidPnPresentPathInfo;
do {
if (curr_path->VidPnTargetId != VIDPN_CHILD_UDID) {//����Ƿ����ǵ�target ID
break;
}
/////skip my target id
status = ptr_pfnAcquireNextPathInfo(hVidPnTopology, curr_path, ppNextVidPnPresentPathInfo );
ptr_pfnReleasePathInfo(hVidPnTopology, curr_path); /// release pathinfo
///
if (status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) {
break;
}
else if (!NT_SUCCESS(status)) {
break;
}
curr_path = *ppNextVidPnPresentPathInfo; ////
/////
} while (TRUE);
///
return status;
}
static NTSTATUS pfnAcquireFirstPathInfo(
IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology,
DEREF_OUT_CONST_PPD3DKMDT_VIDPN_PRESENT_PATH ppFirstVidPnPresentPathInfo)
{
NTSTATUS status = STATUS_SUCCESS;
DXGKDDI_VIDPNTOPOLOGY_ACQUIREFIRSTPATHINFO ptr_pfnAcquireFirstPathInfo = NULL;
DXGKDDI_VIDPNTOPOLOGY_ACQUIRENEXTPATHINFO ptr_pfnAcquireNextPathInfo = NULL;
DXGKDDI_VIDPNTOPOLOGY_RELEASEPATHINFO ptr_pfnReleasePathInfo = NULL;
wf_lock();
for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) {
vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list);
if (intf->hTopology == hVidPnTopology) {
ptr_pfnAcquireFirstPathInfo = intf->topology_if.pfnAcquireFirstPathInfo;
ptr_pfnAcquireNextPathInfo = intf->topology_if.pfnAcquireNextPathInfo;
ptr_pfnReleasePathInfo = intf->topology_if.pfnReleasePathInfo;
break;
}
}
wf_unlock();
///
if (!ptr_pfnAcquireFirstPathInfo) {
DPT("** pfnAcquireFirstPathInfo NULL.\n");
return STATUS_INVALID_PARAMETER;
}
status = ptr_pfnAcquireFirstPathInfo(hVidPnTopology, ppFirstVidPnPresentPathInfo);
if ( NT_SUCCESS(status) && status != STATUS_GRAPHICS_DATASET_IS_EMPTY ) {
CONST D3DKMDT_VIDPN_PRESENT_PATH* curr_path = *ppFirstVidPnPresentPathInfo;
status = skip_my_target_path(hVidPnTopology, curr_path, ppFirstVidPnPresentPathInfo, ptr_pfnAcquireNextPathInfo, ptr_pfnReleasePathInfo); ////
}
// DPT("ppFirstVidPnPresentPathInfo called. st=0x%X\n", status );
/////
return status;
}
static NTSTATUS pfnAcquireNextPathInfo(
IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology,
IN_CONST_PD3DKMDT_VIDPN_PRESENT_PATH_CONST pVidPnPresentPathInfo,
DEREF_OUT_CONST_PPD3DKMDT_VIDPN_PRESENT_PATH ppNextVidPnPresentPathInfo)
{
NTSTATUS status = STATUS_SUCCESS;
DXGKDDI_VIDPNTOPOLOGY_ACQUIRENEXTPATHINFO ptr_pfnAcquireNextPathInfo = NULL;
DXGKDDI_VIDPNTOPOLOGY_RELEASEPATHINFO ptr_pfnReleasePathInfo = NULL;
wf_lock();
for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) {
vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list);
if (intf->hTopology == hVidPnTopology) {
ptr_pfnAcquireNextPathInfo = intf->topology_if.pfnAcquireNextPathInfo;
ptr_pfnReleasePathInfo = intf->topology_if.pfnReleasePathInfo;
break;
}
}
wf_unlock();
/////
if (!ptr_pfnAcquireNextPathInfo) {
DPT("** pfnAcquireNextPathInfo NULL.\n");
return STATUS_INVALID_PARAMETER;
}
status = ptr_pfnAcquireNextPathInfo(hVidPnTopology, pVidPnPresentPathInfo, ppNextVidPnPresentPathInfo );
if (NT_SUCCESS(status) && status != STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET ) {
CONST D3DKMDT_VIDPN_PRESENT_PATH* curr_path = *ppNextVidPnPresentPathInfo;
status = skip_my_target_path(hVidPnTopology, curr_path, ppNextVidPnPresentPathInfo, ptr_pfnAcquireNextPathInfo, ptr_pfnReleasePathInfo); ////
}
// DPT("pfnAcquireNextPathInfo called. st=0x%X\n", status );
return status;
}
static NTSTATUS pfnGetTopology(
IN_CONST_D3DKMDT_HVIDPN hVidPn,
OUT_PD3DKMDT_HVIDPNTOPOLOGY phVidPnTopology,
DEREF_OUT_CONST_PPDXGK_VIDPNTOPOLOGY_INTERFACE ppVidPnTopologyInterface)
{
NTSTATUS status = STATUS_SUCCESS;
DXGKDDI_VIDPN_GETTOPOLOGY ptr_pfnGetTopology = NULL;
wf_lock();
for (PLIST_ENTRY entry = wf->vidpn_if_head.Flink; entry != &wf->vidpn_if_head; entry = entry->Flink) {
vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list);
if (hVidPn == intf->hVidPn) {
ptr_pfnGetTopology = intf->vidpn_if.pfnGetTopology;
break;
}
}
wf_unlock();
if (!ptr_pfnGetTopology) {
DPT("pfnGetTopology==NULL.\n");
return STATUS_INVALID_PARAMETER;
}
status = ptr_pfnGetTopology(hVidPn, phVidPnTopology, ppVidPnTopologyInterface);
// DPT("pfnGetTopology called.\n");
if (NT_SUCCESS(status) && ppVidPnTopologyInterface && *ppVidPnTopologyInterface && phVidPnTopology ) {
///���¼��㲻���������Լ���target path��·��
vidpn_paths_t* p = enum_all_paths(*phVidPnTopology, *ppVidPnTopologyInterface); ///
////
wf_lock();
///
PLIST_ENTRY entry; BOOLEAN find = FALSE;
vidpn_intf_t* intf = NULL;
for (entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) {
vidpn_intf_t* it = CONTAINING_RECORD(entry, vidpn_intf_t, list);
if (it->hTopology == *phVidPnTopology) {
intf = it;
if (intf->paths) { ExFreePool(intf->paths); intf->paths = NULL; }///
break;
}
}
if (!intf) {
intf = (vidpn_intf_t*)ExAllocatePoolWithTag(NonPagedPool, sizeof(vidpn_intf_t), 'FXSD');
if (intf) {
InsertTailList(&wf->topology_if_head, &intf->list);
intf->hTopology = *phVidPnTopology;
intf->paths = NULL;
/////
}
}
if (intf) {
intf->paths = p;
///
intf->topology_if = **ppVidPnTopologyInterface;
intf->mod_topology_if = intf->topology_if;
*ppVidPnTopologyInterface = &intf->mod_topology_if; ///
///�滻����
intf->mod_topology_if.pfnGetNumPaths = pfnGetNumPaths;
intf->mod_topology_if.pfnGetNumPathsFromSource = pfnGetNumPathsFromSource;
intf->mod_topology_if.pfnEnumPathTargetsFromSource = pfnEnumPathTargetsFromSource;
intf->mod_topology_if.pfnAcquireFirstPathInfo = pfnAcquireFirstPathInfo;
intf->mod_topology_if.pfnAcquireNextPathInfo = pfnAcquireNextPathInfo;
/////
}
////
wf_unlock();
}
///
return status;
}
static NTSTATUS DxgkCbQueryVidPnInterface(
IN_CONST_D3DKMDT_HVIDPN hVidPn,
IN_CONST_DXGK_VIDPN_INTERFACE_VERSION VidPnInterfaceVersion,
DEREF_OUT_CONST_PPDXGK_VIDPN_INTERFACE ppVidPnInterface)
{
NTSTATUS status = STATUS_SUCCESS;
status = wf->DxgkInterface.DxgkCbQueryVidPnInterface(hVidPn, VidPnInterfaceVersion, ppVidPnInterface);
/// �滻���Լ��Ļص���������������������Hook Driver��ߵ� Target .
if (NT_SUCCESS(status) && ppVidPnInterface && *ppVidPnInterface ) {
///
PLIST_ENTRY entry; BOOLEAN find = FALSE; ///
wf_lock();
for (entry = wf->vidpn_if_head.Flink; entry != &wf->vidpn_if_head; entry = entry->Flink) {
vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list);
if (intf->hVidPn == hVidPn) {
intf->vidpn_if = *(*ppVidPnInterface);
intf->mod_vidpn_if = intf->vidpn_if;
intf->mod_vidpn_if.pfnGetTopology = pfnGetTopology;
////
*ppVidPnInterface = &intf->mod_vidpn_if;
find = TRUE;
break;
}
}
if (!find) {
vidpn_intf_t* intf = (vidpn_intf_t*)ExAllocatePoolWithTag(NonPagedPool, sizeof(vidpn_intf_t), 'Fxsd');
if (intf) {
intf->hVidPn = hVidPn;
intf->vidpn_if = *(*ppVidPnInterface);
intf->mod_vidpn_if = intf->vidpn_if;
intf->mod_vidpn_if.pfnGetTopology = pfnGetTopology;
///
*ppVidPnInterface = &intf->mod_vidpn_if;
InsertTailList(&wf->vidpn_if_head, &intf->list); ////
////
}
}
wf_unlock();
////
}
////
return status;
}
///////
static NTSTATUS DxgkDdiStartDevice(
IN PVOID MiniportDeviceContext,
IN PDXGK_START_INFO DxgkStartInfo,
IN PDXGKRNL_INTERFACE DxgkInterface,
OUT PULONG NumberOfVideoPresentSources,
OUT PULONG NumberOfChildren)
{
NTSTATUS status = STATUS_SUCCESS;
////WDDM1.1 �� WDDM2.3 ÿ�������в�ͬ���壬������WDK7�±��룬���ֻcopy WDDM1.1�IJ��֡�
wf->DxgkInterface = *DxgkInterface; /// save interface function,����VIDPN����
///////�滻ԭ���Ľӿ�
DxgkInterface->DxgkCbQueryVidPnInterface = DxgkCbQueryVidPnInterface;
//////
status = wf->orgDpiFunc.DxgkDdiStartDevice(MiniportDeviceContext, DxgkStartInfo, DxgkInterface, NumberOfVideoPresentSources, NumberOfChildren);
////
DxgkInterface->DxgkCbQueryVidPnInterface = wf->DxgkInterface.DxgkCbQueryVidPnInterface;
///
DPT("Hook: DxgkDdiStartDevice status=0x%X.\n", status ); ///
if (NT_SUCCESS(status)) {
DPT("org: DxgkDdiStartDevice, NumberOfVideoPresentSources=%d, NumberOfChildren=%d\n", *NumberOfVideoPresentSources, *NumberOfChildren);
//// �ֱ����� 1������ source �� target
wf->vidpn_source_count = *NumberOfVideoPresentSources; // +1;
wf->vidpn_target_count = *NumberOfChildren + 1;
//////
*NumberOfVideoPresentSources = wf->vidpn_source_count;
*NumberOfChildren = wf->vidpn_target_count;
////
}
////
return status;
}
static NTSTATUS DxgkDdiStopDevice(IN PVOID MiniportDeviceContext)
{
DPT("Hook: DxgkDdiStopDevice.\n");
return wf->orgDpiFunc.DxgkDdiStopDevice(MiniportDeviceContext);
}
static NTSTATUS DxgkDdiQueryChildRelations(IN PVOID pvMiniportDeviceContext,
IN OUT PDXGK_CHILD_DESCRIPTOR pChildRelations,
IN ULONG ChildRelationsSize)
{
NTSTATUS status;
status = wf->orgDpiFunc.DxgkDdiQueryChildRelations(pvMiniportDeviceContext, pChildRelations, ChildRelationsSize);
DPT("Hook: DxgkDdiQueryChildRelations status=0x%X\n", status);
////
if (NT_SUCCESS(status)) {
////
LONG reqSize = sizeof(DXGK_CHILD_DESCRIPTOR)*wf->vidpn_target_count;
if (reqSize > ChildRelationsSize) {
return STATUS_BUFFER_TOO_SMALL;
}
/////
pChildRelations[wf->vidpn_target_count - 1] = pChildRelations[0]; ///�ѵ�һ�����Ƹ����ǵ�target
pChildRelations[wf->vidpn_target_count - 1].ChildUid = VIDPN_CHILD_UDID; //�������ǵ�target vidpn��ID
pChildRelations[wf->vidpn_target_count - 1].AcpiUid = VIDPN_CHILD_UDID;
////
}
return status;
}
static NTSTATUS DxgkDdiQueryChildStatus(IN PVOID MiniportDeviceContext, IN PDXGK_CHILD_STATUS ChildStatus, IN BOOLEAN NonDestructiveOnly)
{
DPT("Hook: DxgkDdiQueryChildStatus Uid=0x%X\n", ChildStatus->ChildUid);
if (ChildStatus->ChildUid == VIDPN_CHILD_UDID) {
ChildStatus->HotPlug.Connected = TRUE; ///
///
return STATUS_SUCCESS;
}
////
return wf->orgDpiFunc.DxgkDdiQueryChildStatus(MiniportDeviceContext, ChildStatus, NonDestructiveOnly);
}
static NTSTATUS DxgkDdiQueryDeviceDescriptor(IN_CONST_PVOID MiniportDeviceContext, IN_ULONG ChildUid, INOUT_PDXGK_DEVICE_DESCRIPTOR DeviceDescriptor)
{
DPT("Hook: DxgkDdiQueryDeviceDescriptor Uid=0x%X\n", ChildUid);
if (ChildUid == VIDPN_CHILD_UDID) {
///
return STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA;
}
////
return wf->orgDpiFunc.DxgkDdiQueryDeviceDescriptor(MiniportDeviceContext, ChildUid, DeviceDescriptor);
}
/////
NTSTATUS DpiInitialize(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath,
DRIVER_INITIALIZATION_DATA* DriverInitData)
{
NTSTATUS status = STATUS_SUCCESS;
static BOOLEAN is_hooked = FALSE;
////
UNICODE_STRING vm_str; RtlInitUnicodeString(&vm_str, L"\\Driver\\vm3dmp_loader"); // Vmware 3D
UNICODE_STRING igfx_str; RtlInitUnicodeString(&igfx_str, L"\\Driver\\igfx"); // Intel Graphics
UNICODE_STRING nv_str; RtlInitUnicodeString(&nv_str, L"\\Driver\\nvlddmkm"); // nvidia Graphics
if ( !is_hooked && (
RtlEqualUnicodeString(&vm_str, &DriverObject->DriverName, TRUE) ||
RtlEqualUnicodeString(&nv_str, &DriverObject->DriverName, TRUE) //vmware��������Կ�����Intel�Կ�
) )
{
//����ֻHOOK��һ���Կ�
is_hooked = TRUE;
///
//���︴����Ҫע�⣺
// DRIVER_INITIALIZATION_DATA�ṹ���壬WDDM1.1 �� WDDM2.3 ÿ�������в�ͬ���壬������WDK7�±��룬���ֻcopy WDDM1.1�IJ��֡�
RtlCopyMemory(&wf->orgDpiFunc, DriverInitData, sizeof(DRIVER_INITIALIZATION_DATA));
////replace some function
DriverInitData->DxgkDdiAddDevice = DxgkDdiAddDevice;
DriverInitData->DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
DriverInitData->DxgkDdiStartDevice = DxgkDdiStartDevice;
DriverInitData->DxgkDdiStopDevice = DxgkDdiStopDevice;
DriverInitData->DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
DriverInitData->DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
DriverInitData->DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
DriverInitData->DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality; ////
DriverInitData->DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
DriverInitData->DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
DriverInitData->DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
DriverInitData->DxgkDdiSetVidPnSourceAddress = DxgkDdiSetVidPnSourceAddress;
// DriverInitData->DxgkDdiPresent = DxgkDdiPresent;
/////
}
///�滻��ijЩ�������ŵ��� dxgkrnl.sys �ص�����ע��
return wf->dxgkrnl_dpiInit(DriverObject, RegistryPath, DriverInitData);
}
vidpn.cpp 源文件:
#include "filter.h"
static D3DKMDT_2DREGION Modes[]=
{
{1024, 768},
{1366, 768},
{1920, 1080},
// {6000, 4000}
};
static NTSTATUS
add_source_mode(D3DKMDT_HVIDPNSOURCEMODESET source_mode_set_hdl,
CONST DXGK_VIDPNSOURCEMODESET_INTERFACE *source_mode_set_if,
D3DKMDT_2DREGION* mode)
{
NTSTATUS status = STATUS_SUCCESS;
D3DKMDT_VIDPN_SOURCE_MODE *source_mode;
D3DKMDT_GRAPHICS_RENDERING_FORMAT *fmt;
status = source_mode_set_if->pfnCreateNewModeInfo(source_mode_set_hdl,
&source_mode);
if (!NT_SUCCESS(status)) {
DPT("** pfnCreateNewModeInfo(Source) err=0x%X\n", status );
return status;
}
/* Let OS assign the ID, set the type.*/
source_mode->Type = D3DKMDT_RMT_GRAPHICS;
/* Initialize the rendering format per our constraints and the current mode. */
fmt = &source_mode->Format.Graphics;
fmt->PrimSurfSize.cx = mode->cx;
fmt->PrimSurfSize.cy = mode->cy;
fmt->VisibleRegionSize.cx = mode->cx;
fmt->VisibleRegionSize.cy = mode->cy;
fmt->Stride = mode->cx*4 ; // RGBA
fmt->PixelFormat = D3DDDIFMT_A8R8G8B8;
fmt->ColorBasis = D3DKMDT_CB_SRGB;
fmt->PixelValueAccessMode = D3DKMDT_PVAM_DIRECT;
status = source_mode_set_if->pfnAddMode(source_mode_set_hdl, source_mode);
if (!NT_SUCCESS(status)) {
DPT("** pfnAddMode(Source) err=0x%X\n", status );
source_mode_set_if->pfnReleaseModeInfo(source_mode_set_hdl, source_mode);
}
///
return status;
}
static NTSTATUS update_source_modes(
CONST D3DKMDT_HVIDPN vidpn_hdl,
CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info,
CONST DXGK_VIDPN_INTERFACE* vidpn_if)
{
NTSTATUS status = STATUS_SUCCESS;
D3DKMDT_HVIDPNSOURCEMODESET source_mode_set_hdl = NULL;
CONST DXGK_VIDPNSOURCEMODESET_INTERFACE *source_mode_set_if;
CONST D3DKMDT_VIDPN_SOURCE_MODE *src_mode_info = NULL;
status = vidpn_if->pfnAcquireSourceModeSet(vidpn_hdl,
curr_path_info->VidPnSourceId,
&source_mode_set_hdl,
&source_mode_set_if);
if (!NT_SUCCESS(status)) {
DPT("** not pfnAcquireSourceModeSet st=0x%X\n", status );
return status;
}
////
status = source_mode_set_if->pfnAcquirePinnedModeInfo(source_mode_set_hdl,
&src_mode_info);
if (!NT_SUCCESS(status)) {
vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl);
DPT("pfnAcquirePinnedModeInfo(Source) err=0x%X\n", status );
return status;
}
////
if (src_mode_info != NULL) {
source_mode_set_if->pfnReleaseModeInfo(source_mode_set_hdl, src_mode_info);
}
vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl);
source_mode_set_hdl = NULL; ///
///
if (status == STATUS_SUCCESS && src_mode_info != NULL) { // pinned mode .
///
DPT("Source Mode Pinned Mode: 0x%X -> 0x%X\n", curr_path_info->VidPnSourceId, curr_path_info->VidPnTargetId);
return STATUS_SUCCESS;///�Ѿ����ˣ�������
}
////
status = vidpn_if->pfnCreateNewSourceModeSet(vidpn_hdl,
curr_path_info->VidPnSourceId,
&source_mode_set_hdl,
&source_mode_set_if);
if (!NT_SUCCESS(status)) {
DPT("** pfnCreateNewSourceModeSet err=0x%X\n", status);
return status;
}
////
for (INT i = 0; i < sizeof(Modes) / sizeof(Modes[0]); ++i) {
////
status = add_source_mode(source_mode_set_hdl, source_mode_set_if, &Modes[i]);
if (!NT_SUCCESS(status)) {
///
vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl);
DPT("add_source_mode err=0x%X\n", status);
return status;
}
////
}
//////
status = vidpn_if->pfnAssignSourceModeSet(vidpn_hdl,
curr_path_info->VidPnSourceId,
source_mode_set_hdl);
if (!NT_SUCCESS(status)) {
DPT("** pfnAssignSourceModeSet err=0x%X\n", status);
vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl);
}
////
return status;
}
//// target
static NTSTATUS
add_target_mode(D3DKMDT_HVIDPNTARGETMODESET tgt_mode_set_hdl,
CONST DXGK_VIDPNTARGETMODESET_INTERFACE *target_mode_set_if,
D3DKMDT_2DREGION* mode)
{
D3DKMDT_VIDPN_TARGET_MODE *target_mode;
D3DKMDT_VIDEO_SIGNAL_INFO *signal_info;
NTSTATUS status;
status = target_mode_set_if->pfnCreateNewModeInfo(tgt_mode_set_hdl,
&target_mode);
if (!NT_SUCCESS(status)) {
DPT("** pfnCreateNewModeInfo(Target) err=0x%X\n", status );
return status;
}
////
/* Let OS assign the ID, set the preferred mode field.*/
target_mode->Preference = D3DKMDT_MP_PREFERRED;
////
#define REFRESH_RATE 60
signal_info = &target_mode->VideoSignalInfo;
signal_info->VideoStandard = D3DKMDT_VSS_VESA_DMT;// D3DKMDT_VSS_OTHER;
signal_info->TotalSize.cx = mode->cx;
signal_info->TotalSize.cy = mode->cy;
signal_info->ActiveSize.cx = mode->cx;
signal_info->ActiveSize.cy = mode->cy;
signal_info->PixelRate = mode->cx * mode->cy * REFRESH_RATE;
signal_info->VSyncFreq.Numerator = REFRESH_RATE * 1000;
signal_info->VSyncFreq.Denominator = 1000;
signal_info->HSyncFreq.Numerator = (UINT)((signal_info->PixelRate / signal_info->TotalSize.cy) * 1000);
signal_info->HSyncFreq.Denominator = 1000;
signal_info->ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE;
status = target_mode_set_if->pfnAddMode(tgt_mode_set_hdl, target_mode);
if (!NT_SUCCESS(status)) {
DPT("pfnAddMode failed: 0x%x", status);
target_mode_set_if->pfnReleaseModeInfo(tgt_mode_set_hdl, target_mode);
return status;
}
return status;
}
static NTSTATUS
update_target_modes(
CONST D3DKMDT_HVIDPN vidpn_hdl,
CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info,
CONST DXGK_VIDPN_INTERFACE* vidpn_if)
{
NTSTATUS status = STATUS_SUCCESS;
D3DKMDT_HVIDPNTARGETMODESET tgt_mode_set_hdl = NULL;
CONST DXGK_VIDPNTARGETMODESET_INTERFACE *target_mode_set_if;
CONST D3DKMDT_VIDPN_TARGET_MODE *tgt_mode_info = NULL;
status = vidpn_if->pfnAcquireTargetModeSet(vidpn_hdl,
curr_path_info->VidPnTargetId,
&tgt_mode_set_hdl,
&target_mode_set_if);
if (!NT_SUCCESS(status)) {
DPT("** pfnAcquireTargetModeSet err=0x%X\n", status );
return status;
}
status = target_mode_set_if->pfnAcquirePinnedModeInfo(tgt_mode_set_hdl, &tgt_mode_info);
if (!NT_SUCCESS(status)) {
vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl);
DPT("** pfnAcquirePinnedModeInfo(Source) err=0x%X\n", status );
return status;
}
////
if (tgt_mode_info) {
target_mode_set_if->pfnReleaseModeInfo(tgt_mode_set_hdl, tgt_mode_info);
}
vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl);
tgt_mode_set_hdl = NULL;
if (status == STATUS_SUCCESS && tgt_mode_info != NULL) {
DPT("Target Mode Pinned Mode: 0x%X -> 0x%X\n", curr_path_info->VidPnSourceId, curr_path_info->VidPnTargetId);
return STATUS_SUCCESS;///�Ѿ����ˣ�������
///
}
/////
status = vidpn_if->pfnCreateNewTargetModeSet(vidpn_hdl,
curr_path_info->VidPnTargetId,
&tgt_mode_set_hdl,
&target_mode_set_if);
if (!NT_SUCCESS(status)) {
DPT("** pfnCreateNewTargetModeSet err=0x%X\n", status );
return status;
}
///add target
for (INT i = 0; i < sizeof(Modes) / sizeof(Modes[0]); ++i) {
status = add_target_mode(tgt_mode_set_hdl, target_mode_set_if, &Modes[i]);
if (!NT_SUCCESS(status)) {
///
vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl);
DPT("add_target_mode err=0x%X\n", status);
return status;
}
///
}
//////
status = vidpn_if->pfnAssignTargetModeSet(vidpn_hdl,
curr_path_info->VidPnTargetId,
tgt_mode_set_hdl);
if (!NT_SUCCESS(status)) {
DPT("** pfnAssignTargetModeSet err=0x%x\n", status );
vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl);
return status;
}
return status;
}
static NTSTATUS DxgkDdiEnumVidPnCofuncModality_modify(CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST arg)
{
NTSTATUS status = STATUS_SUCCESS;
D3DKMDT_HVIDPN hConstrainingVidPn = arg->hConstrainingVidPn;
CONST DXGK_VIDPN_INTERFACE* vidpn_if;
status = wf->DxgkInterface.DxgkCbQueryVidPnInterface(
hConstrainingVidPn,
DXGK_VIDPN_INTERFACE_VERSION_V1,
&vidpn_if);
if (!NT_SUCCESS(status)) {
return status;
}
////
D3DKMDT_HVIDPNTOPOLOGY topology_handle = NULL;
CONST DXGK_VIDPNTOPOLOGY_INTERFACE* topology_if = NULL;
CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info;
CONST D3DKMDT_VIDPN_PRESENT_PATH *next_path_info;
status = vidpn_if->pfnGetTopology(hConstrainingVidPn,
&topology_handle, &topology_if);
if (!NT_SUCCESS(status)) {
return status;
}
////
status = topology_if->pfnAcquireFirstPathInfo(topology_handle, &curr_path_info);
if (status == STATUS_GRAPHICS_DATASET_IS_EMPTY) {
// Empty topology, nothing to do.
DPT("pfnAcquireFirstPathInfo: Empty topology.\n");
return STATUS_SUCCESS;
}
else if (!NT_SUCCESS(status)) {
DPT("pfnAcquireFirstPathInfo failed: 0x%x", status);
return STATUS_NO_MEMORY; ////
}
////
do {
////����ÿ��·��
DPT("0x%X --> 0x%X\n", curr_path_info->VidPnSourceId, curr_path_info->VidPnTargetId);
if (curr_path_info->VidPnTargetId == VIDPN_CHILD_UDID) {//·��Ŀ���������Լ���
///
if ((arg->EnumPivotType != D3DKMDT_EPT_VIDPNSOURCE) ||
(arg->EnumPivot.VidPnSourceId != curr_path_info->VidPnSourceId))
{
/////
status = update_source_modes(arg->hConstrainingVidPn, curr_path_info, vidpn_if); DPT("update_source_modes st=0x%X\n",status );
if (!NT_SUCCESS(status)) {
DPT("** update_source_modes err=0x%X\n", status );
}
//////
}
/////
if ((arg->EnumPivotType != D3DKMDT_EPT_VIDPNTARGET) ||
(arg->EnumPivot.VidPnTargetId != curr_path_info->VidPnTargetId))
{
status = update_target_modes(arg->hConstrainingVidPn, curr_path_info, vidpn_if); DPT("update_target_modes st=0x%X\n", status);
if (!NT_SUCCESS(status)) {
DPT("** update_target_modes err=0x%X\n", status);
}
}
////////
}
///next
status = topology_if->pfnAcquireNextPathInfo(topology_handle, curr_path_info, &next_path_info);
topology_if->pfnReleasePathInfo(topology_handle, curr_path_info);
curr_path_info = next_path_info;
if (status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) { /// end
curr_path_info = NULL;
// DPT("pfnAcquireNextPathInfo no more data.\n");
break;
}
else if (!NT_SUCCESS(status)) {
curr_path_info = NULL;
DPT("pfnAcquireNextPathInfo err=0x%X\n", status );
break;
}
/////
} while (TRUE);
return status;
}
NTSTATUS DxgkDdiEnumVidPnCofuncModality(CONST HANDLE hAdapter,
CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg)
{
NTSTATUS status = STATUS_SUCCESS;
DPT("DxgkDdiEnumVidPnCofuncModality: type=%d, 0x%X -> 0x%X, [%d, %d]\n",
pEnumCofuncModalityArg->EnumPivotType, pEnumCofuncModalityArg->EnumPivot.VidPnSourceId,
pEnumCofuncModalityArg->EnumPivot.VidPnTargetId, wf->vidpn_source_count, wf->vidpn_target_count );
///
DxgkDdiEnumVidPnCofuncModality_modify(pEnumCofuncModalityArg); ////
////
status = wf->orgDpiFunc.DxgkDdiEnumVidPnCofuncModality(hAdapter, pEnumCofuncModalityArg);
if (!NT_SUCCESS(status)) {
DPT("** DxgkDdiEnumVidPnCofuncModality err=0x%X\n", status );
}
return status;
}
NTSTATUS DxgkDdiIsSupportedVidPn(
IN_CONST_HANDLE hAdapter,
INOUT_PDXGKARG_ISSUPPORTEDVIDPN pIsSupportedVidPn)
{
NTSTATUS status;
status = wf->orgDpiFunc.DxgkDdiIsSupportedVidPn(hAdapter, pIsSupportedVidPn);
if (NT_SUCCESS(status)) {
DPT("DxgkDdiIsSupportedVidPn handle=%p, supported=%d, \n", pIsSupportedVidPn->hDesiredVidPn, pIsSupportedVidPn->IsVidPnSupported );
}
else {
DPT("** DxgkDdiIsSupportedVidPn err=0x%X, handle=%p, supported=%d\n", status , pIsSupportedVidPn->hDesiredVidPn, pIsSupportedVidPn->IsVidPnSupported );
}
return status;
}
NTSTATUS DxgkDdiCommitVidPn(
IN_CONST_HANDLE hAdapter,
IN_CONST_PDXGKARG_COMMITVIDPN_CONST pCommitVidPn)
{
NTSTATUS status;
status = wf->orgDpiFunc.DxgkDdiCommitVidPn(hAdapter, pCommitVidPn );
// if (!NT_SUCCESS(status)) {
///
DPT(" DxgkDdiCommitVidPn st=0x%X\n", status );
// }
////
return status;
}
NTSTATUS DxgkDdiSetVidPnSourceVisibility(
IN_CONST_HANDLE hAdapter,
IN_CONST_PDXGKARG_SETVIDPNSOURCEVISIBILITY pSetVidPnSourceVisibility)
{
NTSTATUS status;
status = wf->orgDpiFunc.DxgkDdiSetVidPnSourceVisibility(hAdapter, pSetVidPnSourceVisibility);
DPT(" DxgkDdiSetVidPnSourceVisibility sourceId=0x%X, visible=0x%X, st=0x%X\n", pSetVidPnSourceVisibility->VidPnSourceId, pSetVidPnSourceVisibility->Visible ,status );
return status;
}
NTSTATUS APIENTRY DxgkDdiSetVidPnSourceAddress(
const HANDLE hAdapter,
const DXGKARG_SETVIDPNSOURCEADDRESS *pSetVidPnSourceAddress)
{
NTSTATUS status;
status = wf->orgDpiFunc.DxgkDdiSetVidPnSourceAddress(hAdapter, pSetVidPnSourceAddress );
DPT("DxgkDdiSetVidPnSourceAddress sourceId=0x%X, paddr=%llu, st=0x%X\n", pSetVidPnSourceAddress->VidPnSourceId, pSetVidPnSourceAddress->PrimaryAddress.QuadPart, status );
return status;
}
修改以上代码,添加虚拟显示器管理代码
最新发布