mirror of
https://github.com/VirtualDrivers/Virtual-Display-Driver.git
synced 2026-10-21 06:09:59 -05:00
Test
This commit is contained in:
1 parent
3a1871fd23
commit
c6b1e893ec
7 files changed
+642
-14
No files matched your search
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <windows.h>
|
||||
|
||||
// Forward declaration for the logging function used throughout the driver
|
||||
void vddlog(const char* type, const char* message);
|
||||
|
||||
// Forward declarations for existing string conversion functions
|
||||
std::string WStringToString(const std::wstring& wstr);
|
||||
std::wstring StringToWString(const std::string& str);
|
||||
@@ -79,6 +79,10 @@ EVT_IDD_CX_MONITOR_QUERY_TARGET_MODES2 VirtualDisplayDriverEvtIddCxMonitorQueryT
|
||||
EVT_IDD_CX_ADAPTER_COMMIT_MODES2 VirtualDisplayDriverEvtIddCxAdapterCommitModes2;
|
||||
|
||||
EVT_IDD_CX_MONITOR_SET_GAMMA_RAMP VirtualDisplayDriverEvtIddCxMonitorSetGammaRamp;
|
||||
EVT_IDD_CX_DEVICE_IO_CONTROL MttVddEvtIoDeviceControl;
|
||||
|
||||
// Forward declaration for IOCTL queue setup function
|
||||
NTSTATUS SetupIoctlQueue(WDFDEVICE Device);
|
||||
|
||||
struct
|
||||
{
|
||||
@@ -152,16 +156,7 @@ const char* XorCursorSupportLevelToString(IDDCX_XOR_CURSOR_SUPPORT level) {
|
||||
|
||||
vector<unsigned char> Microsoft::IndirectDisp::IndirectDeviceContext::s_KnownMonitorEdid; //Changed to support static vector
|
||||
|
||||
struct IndirectDeviceContextWrapper
|
||||
{
|
||||
IndirectDeviceContext* pContext;
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
delete pContext;
|
||||
pContext = nullptr;
|
||||
}
|
||||
};
|
||||
void LogQueries(const char* severity, const std::wstring& xmlName) {
|
||||
if (xmlName.find(L"logging") == std::wstring::npos) {
|
||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, xmlName.c_str(), (int)xmlName.size(), NULL, 0, NULL, NULL);
|
||||
@@ -634,10 +629,6 @@ void InitializeD3DDeviceAndLogGPU() {
|
||||
vddlog("i", logtext.c_str());
|
||||
}
|
||||
|
||||
|
||||
// This macro creates the methods for accessing an IndirectDeviceContextWrapper as a context for a WDF object
|
||||
WDF_DECLARE_CONTEXT_TYPE(IndirectDeviceContextWrapper);
|
||||
|
||||
extern "C" BOOL WINAPI DllMain(
|
||||
_In_ HINSTANCE hInstance,
|
||||
_In_ UINT dwReason,
|
||||
@@ -1783,6 +1774,9 @@ NTSTATUS VirtualDisplayDriverDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT pDevice
|
||||
IddConfig.EvtIddCxMonitorAssignSwapChain = VirtualDisplayDriverMonitorAssignSwapChain;
|
||||
IddConfig.EvtIddCxMonitorUnassignSwapChain = VirtualDisplayDriverMonitorUnassignSwapChain;
|
||||
|
||||
// Enable IOCTL handling
|
||||
IddConfig.EvtIddCxDeviceIoControl = MttVddEvtIoDeviceControl;
|
||||
|
||||
if (IDD_IS_FIELD_AVAILABLE(IDD_CX_CLIENT_CONFIG, EvtIddCxAdapterQueryTargetInfo))
|
||||
{
|
||||
IddConfig.EvtIddCxAdapterQueryTargetInfo = VirtualDisplayDriverEvtIddCxAdapterQueryTargetInfo;
|
||||
|
||||
@@ -16,6 +16,28 @@
|
||||
#include <vector>
|
||||
|
||||
#include "Trace.h"
|
||||
#include "mttvdd-ioctl.h"
|
||||
#include "Common.h"
|
||||
|
||||
// Forward declaration for the IndirectDeviceContext class
|
||||
namespace Microsoft
|
||||
{
|
||||
namespace IndirectDisp
|
||||
{
|
||||
class IndirectDeviceContext;
|
||||
}
|
||||
}
|
||||
|
||||
// Forward declarations for driver-defined context type
|
||||
struct IndirectDeviceContextWrapper
|
||||
{
|
||||
Microsoft::IndirectDisp::IndirectDeviceContext* pContext;
|
||||
|
||||
void Cleanup(); // Just declare it, don't implement
|
||||
};
|
||||
|
||||
// The WDF context access function is defined by WDF_DECLARE_CONTEXT_TYPE macro
|
||||
WDF_DECLARE_CONTEXT_TYPE(IndirectDeviceContextWrapper);
|
||||
|
||||
namespace Microsoft
|
||||
{
|
||||
@@ -85,18 +107,26 @@ namespace Microsoft
|
||||
void FinishInit();
|
||||
|
||||
void CreateMonitor(unsigned int index);
|
||||
NTSTATUS CreateMonitorWithParams(ULONG Width, ULONG Height, ULONG RefreshRate, GUID* MonitorId);
|
||||
NTSTATUS DestroyMonitor(ULONG MonitorIndex);
|
||||
NTSTATUS SetMonitorMode(ULONG MonitorIndex, ULONG Width, ULONG Height, ULONG RefreshRate);
|
||||
NTSTATUS SetPreferredMode(ULONG MonitorIndex, ULONG Width, ULONG Height, ULONG RefreshRate);
|
||||
NTSTATUS SetGpuPreference(LUID AdapterLuid);
|
||||
ULONG GetMonitorCount();
|
||||
|
||||
void AssignSwapChain(IDDCX_MONITOR& Monitor, IDDCX_SWAPCHAIN SwapChain, LUID RenderAdapter, HANDLE NewFrameEvent);
|
||||
void UnassignSwapChain();
|
||||
|
||||
protected:
|
||||
|
||||
WDFDEVICE m_WdfDevice;
|
||||
IDDCX_ADAPTER m_Adapter;
|
||||
IDDCX_MONITOR m_Monitor;
|
||||
IDDCX_MONITOR m_Monitor2;
|
||||
|
||||
std::unique_ptr<SwapChainProcessor> m_ProcessingThread;
|
||||
|
||||
// Store a list of connected monitors and their info
|
||||
std::vector<std::pair<IDDCX_MONITOR, GUID>> m_Monitors;
|
||||
|
||||
public:
|
||||
static const DISPLAYCONFIG_VIDEO_SIGNAL_INFO s_KnownMonitorModes[];
|
||||
|
||||
Binary file not shown.
@@ -36,12 +36,16 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Driver.cpp" />
|
||||
<ClCompile Include="mttioctl.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\..\Downloads\wudfwdm.h">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Driver.h" />
|
||||
<ClInclude Include="mttvdd-ioctl.h" />
|
||||
<ClInclude Include="Trace.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,523 @@
|
||||
#include "Driver.h"
|
||||
#include "Common.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace Microsoft::IndirectDisp;
|
||||
using namespace std;
|
||||
|
||||
// External declaration of the logging function
|
||||
extern void vddlog(const char* type, const char* message);
|
||||
|
||||
// Forward declaration of callback function
|
||||
extern "C" EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL MttVddEvtIoDeviceControl;
|
||||
|
||||
NTSTATUS IndirectDeviceContext::CreateMonitorWithParams(ULONG Width, ULONG Height, ULONG RefreshRate, GUID* MonitorId)
|
||||
{
|
||||
// Log the parameters
|
||||
stringstream logStream;
|
||||
logStream << "Creating monitor with parameters:"
|
||||
<< "\n Width: " << Width
|
||||
<< "\n Height: " << Height
|
||||
<< "\n RefreshRate: " << RefreshRate
|
||||
<< "\n MonitorId: " << (MonitorId ? "Provided" : "Not provided");
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
// If MonitorId is null, generate a new one
|
||||
GUID monitorGuid;
|
||||
if (MonitorId == nullptr || IsEqualGUID(*MonitorId, GUID_NULL))
|
||||
{
|
||||
CoCreateGuid(&monitorGuid);
|
||||
logStream.str("");
|
||||
logStream << "Generated new monitor GUID";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
monitorGuid = *MonitorId;
|
||||
logStream.str("");
|
||||
logStream << "Using provided monitor GUID";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
}
|
||||
|
||||
// TODO: Implement actual monitor creation with the specified parameters
|
||||
// For now, we'll add a placeholder that just uses the existing CreateMonitor function
|
||||
// This would be enhanced to use the width, height, and refresh rate parameters
|
||||
|
||||
// Add the monitor to our list
|
||||
unsigned int index = (unsigned int)m_Monitors.size();
|
||||
CreateMonitor(index);
|
||||
|
||||
// Store the GUID with the monitor for future reference
|
||||
m_Monitors.push_back(std::make_pair(m_Monitor, monitorGuid));
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Monitor created successfully with index: " << index;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS IndirectDeviceContext::DestroyMonitor(ULONG MonitorIndex)
|
||||
{
|
||||
// Log the request
|
||||
stringstream logStream;
|
||||
logStream << "Destroying monitor with index: " << MonitorIndex;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
// Check if the index is valid
|
||||
if (MonitorIndex >= m_Monitors.size())
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Invalid monitor index: " << MonitorIndex << ". Max index: " << (m_Monitors.size() > 0 ? m_Monitors.size() - 1 : 0);
|
||||
vddlog("e", logStream.str().c_str());
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// TODO: Implement actual monitor destruction logic
|
||||
// For now, this is a placeholder that would be enhanced in a real implementation
|
||||
|
||||
// Remove the monitor from our list
|
||||
m_Monitors.erase(m_Monitors.begin() + MonitorIndex);
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Monitor with index " << MonitorIndex << " successfully destroyed";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void IndirectDeviceContextWrapper::Cleanup()
|
||||
{
|
||||
delete pContext;
|
||||
pContext = nullptr;
|
||||
}
|
||||
|
||||
NTSTATUS IndirectDeviceContext::SetMonitorMode(ULONG MonitorIndex, ULONG Width, ULONG Height, ULONG RefreshRate)
|
||||
{
|
||||
// Log the request
|
||||
stringstream logStream;
|
||||
logStream << "Setting monitor mode:"
|
||||
<< "\n MonitorIndex: " << MonitorIndex
|
||||
<< "\n Width: " << Width
|
||||
<< "\n Height: " << Height
|
||||
<< "\n RefreshRate: " << RefreshRate;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
// Check if the index is valid
|
||||
if (MonitorIndex >= m_Monitors.size())
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Invalid monitor index: " << MonitorIndex << ". Max index: " << (m_Monitors.size() > 0 ? m_Monitors.size() - 1 : 0);
|
||||
vddlog("e", logStream.str().c_str());
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// TODO: Implement logic to change the monitor mode
|
||||
// This would need to interact with the IddCx APIs to change the resolution/refresh rate
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Monitor mode set successfully for monitor index " << MonitorIndex;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS IndirectDeviceContext::SetPreferredMode(ULONG MonitorIndex, ULONG Width, ULONG Height, ULONG RefreshRate)
|
||||
{
|
||||
// Log the request
|
||||
stringstream logStream;
|
||||
logStream << "Setting preferred monitor mode:"
|
||||
<< "\n MonitorIndex: " << MonitorIndex
|
||||
<< "\n Width: " << Width
|
||||
<< "\n Height: " << Height
|
||||
<< "\n RefreshRate: " << RefreshRate;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
// Check if the index is valid
|
||||
if (MonitorIndex >= m_Monitors.size())
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Invalid monitor index: " << MonitorIndex << ". Max index: " << (m_Monitors.size() > 0 ? m_Monitors.size() - 1 : 0);
|
||||
vddlog("e", logStream.str().c_str());
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// TODO: Implement logic to set the preferred mode for the monitor
|
||||
// This would update the EDID or other configuration to indicate the preferred mode
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Preferred mode set successfully for monitor index " << MonitorIndex;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS IndirectDeviceContext::SetGpuPreference(LUID AdapterLuid)
|
||||
{
|
||||
// Log the request
|
||||
stringstream logStream;
|
||||
logStream << "Setting GPU preference:"
|
||||
<< "\n AdapterLuid.LowPart: " << AdapterLuid.LowPart
|
||||
<< "\n AdapterLuid.HighPart: " << AdapterLuid.HighPart;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
// TODO: Implement GPU preference setting
|
||||
// This would call IddCxAdapterSetRenderAdapter or similar
|
||||
|
||||
logStream.str("");
|
||||
logStream << "GPU preference set successfully";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ULONG IndirectDeviceContext::GetMonitorCount()
|
||||
{
|
||||
ULONG count = (ULONG)m_Monitors.size();
|
||||
|
||||
// Log the request
|
||||
stringstream logStream;
|
||||
logStream << "Getting monitor count: " << count << " monitor(s)";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// IOCTL handler implementation
|
||||
VOID MttVddEvtIoDeviceControl(
|
||||
_In_ WDFQUEUE Queue,
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ size_t OutputBufferLength,
|
||||
_In_ size_t InputBufferLength,
|
||||
_In_ ULONG IoControlCode
|
||||
)
|
||||
{
|
||||
// Log the IOCTL request
|
||||
stringstream logStream;
|
||||
logStream << "Received IOCTL request:"
|
||||
<< "\n IoControlCode: 0x" << std::hex << IoControlCode << std::dec
|
||||
<< "\n InputBufferLength: " << InputBufferLength
|
||||
<< "\n OutputBufferLength: " << OutputBufferLength;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
WDFDEVICE device = WdfIoQueueGetDevice(Queue);
|
||||
|
||||
// Get the device context
|
||||
IndirectDeviceContextWrapper* pContextWrapper = WdfObjectGet_IndirectDeviceContextWrapper(device);
|
||||
if (!pContextWrapper || !pContextWrapper->pContext)
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Invalid device context - request will be completed with STATUS_INVALID_DEVICE_STATE";
|
||||
vddlog("e", logStream.str().c_str());
|
||||
|
||||
WdfRequestComplete(Request, STATUS_INVALID_DEVICE_STATE);
|
||||
return;
|
||||
}
|
||||
|
||||
Microsoft::IndirectDisp::IndirectDeviceContext* pContext = pContextWrapper->pContext;
|
||||
|
||||
PVOID inputBuffer = nullptr;
|
||||
PVOID outputBuffer = nullptr;
|
||||
size_t bytesReturned = 0;
|
||||
|
||||
// Get input and output buffers if needed
|
||||
if (InputBufferLength > 0)
|
||||
{
|
||||
status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &inputBuffer, nullptr);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Failed to retrieve input buffer with status: 0x" << std::hex << status;
|
||||
vddlog("e", logStream.str().c_str());
|
||||
|
||||
WdfRequestComplete(Request, status);
|
||||
return;
|
||||
}
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Successfully retrieved input buffer";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
}
|
||||
|
||||
if (OutputBufferLength > 0)
|
||||
{
|
||||
status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &outputBuffer, nullptr);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Failed to retrieve output buffer with status: 0x" << std::hex << status;
|
||||
vddlog("e", logStream.str().c_str());
|
||||
|
||||
WdfRequestComplete(Request, status);
|
||||
return;
|
||||
}
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Successfully retrieved output buffer";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
}
|
||||
|
||||
// Process the IOCTL based on the control code
|
||||
logStream.str("");
|
||||
logStream << "Processing IOCTL control code: 0x" << std::hex << IoControlCode << std::dec;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
switch (IoControlCode)
|
||||
{
|
||||
case IOCTL_MTTVDD_GET_VERSION:
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "IOCTL_MTTVDD_GET_VERSION request received";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
if (OutputBufferLength < sizeof(MTTVDD_VERSION_INFO))
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Output buffer too small: " << OutputBufferLength << " bytes (required " << sizeof(MTTVDD_VERSION_INFO) << " bytes)";
|
||||
vddlog("e", logStream.str().c_str());
|
||||
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
PMTTVDD_VERSION_INFO versionInfo = (PMTTVDD_VERSION_INFO)outputBuffer;
|
||||
versionInfo->MajorVersion = 1;
|
||||
versionInfo->MinorVersion = 0;
|
||||
versionInfo->BuildNumber = 1;
|
||||
bytesReturned = sizeof(MTTVDD_VERSION_INFO);
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Version information returned: "
|
||||
<< versionInfo->MajorVersion << "."
|
||||
<< versionInfo->MinorVersion << "."
|
||||
<< versionInfo->BuildNumber;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_MTTVDD_CREATE_MONITOR:
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "IOCTL_MTTVDD_CREATE_MONITOR request received";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
if (InputBufferLength < sizeof(MTTVDD_CREATE_MONITOR))
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Input buffer too small: " << InputBufferLength << " bytes (required " << sizeof(MTTVDD_CREATE_MONITOR) << " bytes)";
|
||||
vddlog("e", logStream.str().c_str());
|
||||
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
PMTTVDD_CREATE_MONITOR createInfo = (PMTTVDD_CREATE_MONITOR)inputBuffer;
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Calling CreateMonitorWithParams with:"
|
||||
<< "\n Width: " << createInfo->Width
|
||||
<< "\n Height: " << createInfo->Height
|
||||
<< "\n RefreshRate: " << createInfo->RefreshRate;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
status = pContext->CreateMonitorWithParams(createInfo->Width, createInfo->Height, createInfo->RefreshRate, &createInfo->MonitorId);
|
||||
|
||||
logStream.str("");
|
||||
logStream << "CreateMonitorWithParams returned status: 0x" << std::hex << status;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_MTTVDD_DESTROY_MONITOR:
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "IOCTL_MTTVDD_DESTROY_MONITOR request received";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
if (InputBufferLength < sizeof(MTTVDD_DESTROY_MONITOR))
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Input buffer too small: " << InputBufferLength << " bytes (required " << sizeof(MTTVDD_DESTROY_MONITOR) << " bytes)";
|
||||
vddlog("e", logStream.str().c_str());
|
||||
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
PMTTVDD_DESTROY_MONITOR destroyInfo = (PMTTVDD_DESTROY_MONITOR)inputBuffer;
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Calling DestroyMonitor with index: " << destroyInfo->MonitorIndex;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
status = pContext->DestroyMonitor(destroyInfo->MonitorIndex);
|
||||
|
||||
logStream.str("");
|
||||
logStream << "DestroyMonitor returned status: 0x" << std::hex << status;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_MTTVDD_SET_MODE:
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "IOCTL_MTTVDD_SET_MODE request received";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
if (InputBufferLength < sizeof(MTTVDD_SET_MODE))
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Input buffer too small: " << InputBufferLength << " bytes (required " << sizeof(MTTVDD_SET_MODE) << " bytes)";
|
||||
vddlog("e", logStream.str().c_str());
|
||||
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
PMTTVDD_SET_MODE modeInfo = (PMTTVDD_SET_MODE)inputBuffer;
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Calling SetMonitorMode with:"
|
||||
<< "\n MonitorIndex: " << modeInfo->MonitorIndex
|
||||
<< "\n Width: " << modeInfo->Width
|
||||
<< "\n Height: " << modeInfo->Height
|
||||
<< "\n RefreshRate: " << modeInfo->RefreshRate;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
status = pContext->SetMonitorMode(modeInfo->MonitorIndex, modeInfo->Width, modeInfo->Height, modeInfo->RefreshRate);
|
||||
|
||||
logStream.str("");
|
||||
logStream << "SetMonitorMode returned status: 0x" << std::hex << status;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_MTTVDD_GET_MONITOR_COUNT:
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "IOCTL_MTTVDD_GET_MONITOR_COUNT request received";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
if (OutputBufferLength < sizeof(ULONG))
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Output buffer too small: " << OutputBufferLength << " bytes (required " << sizeof(ULONG) << " bytes)";
|
||||
vddlog("e", logStream.str().c_str());
|
||||
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
PULONG count = (PULONG)outputBuffer;
|
||||
*count = pContext->GetMonitorCount();
|
||||
bytesReturned = sizeof(ULONG);
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Monitor count returned: " << *count;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_MTTVDD_SET_PREFERRED_MODE:
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "IOCTL_MTTVDD_SET_PREFERRED_MODE request received";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
if (InputBufferLength < sizeof(MTTVDD_SET_PREFERRED_MODE))
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Input buffer too small: " << InputBufferLength << " bytes (required " << sizeof(MTTVDD_SET_PREFERRED_MODE) << " bytes)";
|
||||
vddlog("e", logStream.str().c_str());
|
||||
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
PMTTVDD_SET_PREFERRED_MODE modeInfo = (PMTTVDD_SET_PREFERRED_MODE)inputBuffer;
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Calling SetPreferredMode with:"
|
||||
<< "\n MonitorIndex: " << modeInfo->MonitorIndex
|
||||
<< "\n Width: " << modeInfo->Width
|
||||
<< "\n Height: " << modeInfo->Height
|
||||
<< "\n RefreshRate: " << modeInfo->RefreshRate;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
status = pContext->SetPreferredMode(modeInfo->MonitorIndex, modeInfo->Width, modeInfo->Height, modeInfo->RefreshRate);
|
||||
|
||||
logStream.str("");
|
||||
logStream << "SetPreferredMode returned status: 0x" << std::hex << status;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_MTTVDD_SET_GPU_PREFERENCE:
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "IOCTL_MTTVDD_SET_GPU_PREFERENCE request received";
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
if (InputBufferLength < sizeof(MTTVDD_SET_GPU_PREFERENCE))
|
||||
{
|
||||
logStream.str("");
|
||||
logStream << "Input buffer too small: " << InputBufferLength << " bytes (required " << sizeof(MTTVDD_SET_GPU_PREFERENCE) << " bytes)";
|
||||
vddlog("e", logStream.str().c_str());
|
||||
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
PMTTVDD_SET_GPU_PREFERENCE gpuInfo = (PMTTVDD_SET_GPU_PREFERENCE)inputBuffer;
|
||||
|
||||
logStream.str("");
|
||||
logStream << "Calling SetGpuPreference with:"
|
||||
<< "\n AdapterLuid.LowPart: " << gpuInfo->AdapterLuid.LowPart
|
||||
<< "\n AdapterLuid.HighPart: " << gpuInfo->AdapterLuid.HighPart;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
status = pContext->SetGpuPreference(gpuInfo->AdapterLuid);
|
||||
|
||||
logStream.str("");
|
||||
logStream << "SetGpuPreference returned status: 0x" << std::hex << status;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
logStream.str("");
|
||||
logStream << "Unknown IOCTL code: 0x" << std::hex << IoControlCode;
|
||||
vddlog("e", logStream.str().c_str());
|
||||
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
// Complete the request with the status and bytes returned
|
||||
logStream.str("");
|
||||
logStream << "Completing IOCTL request with:"
|
||||
<< "\n Status: 0x" << std::hex << status
|
||||
<< "\n BytesReturned: " << std::dec << bytesReturned;
|
||||
vddlog("i", logStream.str().c_str());
|
||||
|
||||
WdfRequestCompleteWithInformation(Request, status, bytesReturned);
|
||||
}
|
||||
|
||||
// Function to setup the IOCTL queue
|
||||
NTSTATUS SetupIoctlQueue(WDFDEVICE Device)
|
||||
{
|
||||
WDF_IO_QUEUE_CONFIG queueConfig;
|
||||
WDFQUEUE queue;
|
||||
|
||||
// Initialize the queue configuration
|
||||
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchSequential);
|
||||
|
||||
// Set the callback for device control IOCTLs
|
||||
queueConfig.EvtIoDeviceControl = MttVddEvtIoDeviceControl;
|
||||
|
||||
// Create the queue
|
||||
NTSTATUS status = WdfIoQueueCreate(Device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Define the IOCTL control codes
|
||||
#define FILE_DEVICE_MTTVDD 0x8000
|
||||
|
||||
// Function codes: 0x800 to 0x8FF for custom functions
|
||||
#define IOCTL_MTTVDD_FUNCTION_BASE 0x800
|
||||
|
||||
// IOCTL commands
|
||||
#define IOCTL_MTTVDD_GET_VERSION CTL_CODE(FILE_DEVICE_MTTVDD, IOCTL_MTTVDD_FUNCTION_BASE + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MTTVDD_CREATE_MONITOR CTL_CODE(FILE_DEVICE_MTTVDD, IOCTL_MTTVDD_FUNCTION_BASE + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MTTVDD_DESTROY_MONITOR CTL_CODE(FILE_DEVICE_MTTVDD, IOCTL_MTTVDD_FUNCTION_BASE + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MTTVDD_SET_MODE CTL_CODE(FILE_DEVICE_MTTVDD, IOCTL_MTTVDD_FUNCTION_BASE + 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MTTVDD_GET_MONITOR_COUNT CTL_CODE(FILE_DEVICE_MTTVDD, IOCTL_MTTVDD_FUNCTION_BASE + 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MTTVDD_SET_PREFERRED_MODE CTL_CODE(FILE_DEVICE_MTTVDD, IOCTL_MTTVDD_FUNCTION_BASE + 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MTTVDD_SET_GPU_PREFERENCE CTL_CODE(FILE_DEVICE_MTTVDD, IOCTL_MTTVDD_FUNCTION_BASE + 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
// Driver version information
|
||||
typedef struct _MTTVDD_VERSION_INFO {
|
||||
ULONG MajorVersion;
|
||||
ULONG MinorVersion;
|
||||
ULONG BuildNumber;
|
||||
} MTTVDD_VERSION_INFO, *PMTTVDD_VERSION_INFO;
|
||||
|
||||
// Structure for creating a monitor
|
||||
typedef struct _MTTVDD_CREATE_MONITOR {
|
||||
ULONG Width;
|
||||
ULONG Height;
|
||||
ULONG RefreshRate;
|
||||
GUID MonitorId; // Optional monitor ID, can be zeroed for auto-generation
|
||||
} MTTVDD_CREATE_MONITOR, *PMTTVDD_CREATE_MONITOR;
|
||||
|
||||
// Structure for destroying a monitor
|
||||
typedef struct _MTTVDD_DESTROY_MONITOR {
|
||||
ULONG MonitorIndex;
|
||||
} MTTVDD_DESTROY_MONITOR, *PMTTVDD_DESTROY_MONITOR;
|
||||
|
||||
// Structure for setting a monitor mode
|
||||
typedef struct _MTTVDD_SET_MODE {
|
||||
ULONG MonitorIndex;
|
||||
ULONG Width;
|
||||
ULONG Height;
|
||||
ULONG RefreshRate;
|
||||
} MTTVDD_SET_MODE, *PMTTVDD_SET_MODE;
|
||||
|
||||
// Structure for setting a preferred mode
|
||||
typedef struct _MTTVDD_SET_PREFERRED_MODE {
|
||||
ULONG MonitorIndex;
|
||||
ULONG Width;
|
||||
ULONG Height;
|
||||
ULONG RefreshRate;
|
||||
} MTTVDD_SET_PREFERRED_MODE, *PMTTVDD_SET_PREFERRED_MODE;
|
||||
|
||||
// Structure for setting GPU preference
|
||||
typedef struct _MTTVDD_SET_GPU_PREFERENCE {
|
||||
LUID AdapterLuid;
|
||||
} MTTVDD_SET_GPU_PREFERENCE, *PMTTVDD_SET_GPU_PREFERENCE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in new issue
Block a user