diff --git a/Virtual Display Driver (HDR)/MttVDD/Common.h b/Virtual Display Driver (HDR)/MttVDD/Common.h new file mode 100644 index 0000000..d308081 --- /dev/null +++ b/Virtual Display Driver (HDR)/MttVDD/Common.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include + +// 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); \ No newline at end of file diff --git a/Virtual Display Driver (HDR)/MttVDD/Driver.cpp b/Virtual Display Driver (HDR)/MttVDD/Driver.cpp index 3012b56..ef95037 100644 --- a/Virtual Display Driver (HDR)/MttVDD/Driver.cpp +++ b/Virtual Display Driver (HDR)/MttVDD/Driver.cpp @@ -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 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; diff --git a/Virtual Display Driver (HDR)/MttVDD/Driver.h b/Virtual Display Driver (HDR)/MttVDD/Driver.h index 17be5b3..5bf6150 100644 --- a/Virtual Display Driver (HDR)/MttVDD/Driver.h +++ b/Virtual Display Driver (HDR)/MttVDD/Driver.h @@ -16,6 +16,28 @@ #include #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 m_ProcessingThread; + + // Store a list of connected monitors and their info + std::vector> m_Monitors; public: static const DISPLAYCONFIG_VIDEO_SIGNAL_INFO s_KnownMonitorModes[]; diff --git a/Virtual Display Driver (HDR)/MttVDD/MttVDD.inf b/Virtual Display Driver (HDR)/MttVDD/MttVDD.inf index e6ba858..a1c5330 100644 Binary files a/Virtual Display Driver (HDR)/MttVDD/MttVDD.inf and b/Virtual Display Driver (HDR)/MttVDD/MttVDD.inf differ diff --git a/Virtual Display Driver (HDR)/MttVDD/MttVDD.vcxproj b/Virtual Display Driver (HDR)/MttVDD/MttVDD.vcxproj index ea85878..37d1c34 100644 --- a/Virtual Display Driver (HDR)/MttVDD/MttVDD.vcxproj +++ b/Virtual Display Driver (HDR)/MttVDD/MttVDD.vcxproj @@ -36,12 +36,16 @@ + + false + true + diff --git a/Virtual Display Driver (HDR)/MttVDD/mttioctl.cpp b/Virtual Display Driver (HDR)/MttVDD/mttioctl.cpp new file mode 100644 index 0000000..f2afa26 --- /dev/null +++ b/Virtual Display Driver (HDR)/MttVDD/mttioctl.cpp @@ -0,0 +1,523 @@ +#include "Driver.h" +#include "Common.h" +#include + +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; +} \ No newline at end of file diff --git a/Virtual Display Driver (HDR)/MttVDD/mttvdd-ioctl.h b/Virtual Display Driver (HDR)/MttVDD/mttvdd-ioctl.h new file mode 100644 index 0000000..4b07893 --- /dev/null +++ b/Virtual Display Driver (HDR)/MttVDD/mttvdd-ioctl.h @@ -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 \ No newline at end of file