Files

580 lines
18 KiB
C++

/******************************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"
NTSTATUS
DriverEntry(
_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
//
VOID
BddDdiUnload(VOID)
{
PAGED_CODE();
}
NTSTATUS
BddDdiAddDevice(
_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;
}
NTSTATUS
BddDdiRemoveDevice(
_In_ VOID* pDeviceContext)
{
PAGED_CODE();
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
if (pBDD)
{
delete pBDD;
pBDD = NULL;
}
return STATUS_SUCCESS;
}
NTSTATUS
BddDdiStartDevice(
_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<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
return pBDD->StartDevice(pDxgkStartInfo, pDxgkInterface, pNumberOfViews, pNumberOfChildren);
}
NTSTATUS
BddDdiStopDevice(
_In_ VOID* pDeviceContext)
{
PAGED_CODE();
BDD_ASSERT_CHK(pDeviceContext != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
return pBDD->StopDevice();
}
NTSTATUS
BddDdiDispatchIoRequest(
_In_ VOID* pDeviceContext,
_In_ ULONG VidPnSourceId,
_In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket)
{
PAGED_CODE();
BDD_ASSERT_CHK(pDeviceContext != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(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);
}
NTSTATUS
BddDdiSetPowerState(
_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<BASIC_DISPLAY_DRIVER*>(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);
}
NTSTATUS
BddDdiQueryChildRelations(
_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<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
return pBDD->QueryChildRelations(pChildRelations, ChildRelationsSize);
}
NTSTATUS
BddDdiQueryChildStatus(
_In_ VOID* pDeviceContext,
_Inout_ DXGK_CHILD_STATUS* pChildStatus,
_In_ BOOLEAN NonDestructiveOnly)
{
PAGED_CODE();
BDD_ASSERT_CHK(pDeviceContext != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
return pBDD->QueryChildStatus(pChildStatus, NonDestructiveOnly);
}
NTSTATUS
BddDdiQueryDeviceDescriptor(
_In_ VOID* pDeviceContext,
_In_ ULONG ChildUid,
_Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor)
{
PAGED_CODE();
BDD_ASSERT_CHK(pDeviceContext != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(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
//
NTSTATUS
APIENTRY
BddDdiQueryAdapterInfo(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
return pBDD->QueryAdapterInfo(pQueryAdapterInfo);
}
NTSTATUS
APIENTRY
BddDdiSetPointerPosition(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
if (!pBDD->IsDriverActive())
{
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
return STATUS_UNSUCCESSFUL;
}
return pBDD->SetPointerPosition(pSetPointerPosition);
}
NTSTATUS
APIENTRY
BddDdiSetPointerShape(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
if (!pBDD->IsDriverActive())
{
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
return STATUS_UNSUCCESSFUL;
}
return pBDD->SetPointerShape(pSetPointerShape);
}
NTSTATUS
APIENTRY
BddDdiPresentDisplayOnly(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
if (!pBDD->IsDriverActive())
{
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
return STATUS_UNSUCCESSFUL;
}
return pBDD->PresentDisplayOnly(pPresentDisplayOnly);
}
NTSTATUS
APIENTRY
BddDdiStopDeviceAndReleasePostDisplayOwnership(
_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<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
return pBDD->StopDeviceAndReleasePostDisplayOwnership(TargetId, DisplayInfo);
}
NTSTATUS
APIENTRY
BddDdiIsSupportedVidPn(
_In_ CONST HANDLE hAdapter,
_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(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);
}
NTSTATUS
APIENTRY
BddDdiRecommendFunctionalVidPn(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
if (!pBDD->IsDriverActive())
{
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
return STATUS_UNSUCCESSFUL;
}
return pBDD->RecommendFunctionalVidPn(pRecommendFunctionalVidPn);
}
NTSTATUS
APIENTRY
BddDdiRecommendVidPnTopology(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
if (!pBDD->IsDriverActive())
{
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
return STATUS_UNSUCCESSFUL;
}
return pBDD->RecommendVidPnTopology(pRecommendVidPnTopology);
}
NTSTATUS
APIENTRY
BddDdiRecommendMonitorModes(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
if (!pBDD->IsDriverActive())
{
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
return STATUS_UNSUCCESSFUL;
}
return pBDD->RecommendMonitorModes(pRecommendMonitorModes);
}
NTSTATUS
APIENTRY
BddDdiEnumVidPnCofuncModality(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
if (!pBDD->IsDriverActive())
{
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
return STATUS_UNSUCCESSFUL;
}
return pBDD->EnumVidPnCofuncModality(pEnumCofuncModality);
}
NTSTATUS
APIENTRY
BddDdiSetVidPnSourceVisibility(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
if (!pBDD->IsDriverActive())
{
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
return STATUS_UNSUCCESSFUL;
}
return pBDD->SetVidPnSourceVisibility(pSetVidPnSourceVisibility);
}
NTSTATUS
APIENTRY
BddDdiCommitVidPn(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
if (!pBDD->IsDriverActive())
{
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
return STATUS_UNSUCCESSFUL;
}
return pBDD->CommitVidPn(pCommitVidPn);
}
NTSTATUS
APIENTRY
BddDdiUpdateActiveVidPnPresentPath(
_In_ CONST HANDLE hAdapter,
_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
if (!pBDD->IsDriverActive())
{
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
return STATUS_UNSUCCESSFUL;
}
return pBDD->UpdateActiveVidPnPresentPath(pUpdateActiveVidPnPresentPath);
}
NTSTATUS
APIENTRY
BddDdiQueryVidPnHWCapability(
_In_ CONST HANDLE hAdapter,
_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps)
{
PAGED_CODE();
BDD_ASSERT_CHK(hAdapter != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(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 Code
VOID
BddDdiDpcRoutine(
_In_ VOID* pDeviceContext)
{
BDD_ASSERT_CHK(pDeviceContext != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
if (!pBDD->IsDriverActive())
{
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
return;
}
pBDD->DpcRoutine();
}
BOOLEAN
BddDdiInterruptRoutine(
_In_ VOID* pDeviceContext,
_In_ ULONG MessageNumber)
{
BDD_ASSERT_CHK(pDeviceContext != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
return pBDD->InterruptRoutine(MessageNumber);
}
VOID
BddDdiResetDevice(
_In_ VOID* pDeviceContext)
{
BDD_ASSERT_CHK(pDeviceContext != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
pBDD->ResetDevice();
}
NTSTATUS
APIENTRY
BddDdiSystemDisplayEnable(
_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<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
return pBDD->SystemDisplayEnable(TargetId, Flags, Width, Height, ColorFormat);
}
VOID
APIENTRY
BddDdiSystemDisplayWrite(
_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<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
pBDD->SystemDisplayWrite(Source, SourceWidth, SourceHeight, SourceStride, PositionX, PositionY);
}
// END: Non-Paged Code
#pragma code_seg(pop)