summaryrefslogtreecommitdiffstats
path: root/src/VBox/Additions/3D/win/VBoxWddmUmHlp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Additions/3D/win/VBoxWddmUmHlp')
-rw-r--r--src/VBox/Additions/3D/win/VBoxWddmUmHlp/D3DKMT.cpp260
-rw-r--r--src/VBox/Additions/3D/win/VBoxWddmUmHlp/Makefile.kmk54
-rw-r--r--src/VBox/Additions/3D/win/VBoxWddmUmHlp/UmHlpInternal.h36
-rw-r--r--src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp167
-rw-r--r--src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxWddmUmHlp.h116
5 files changed, 633 insertions, 0 deletions
diff --git a/src/VBox/Additions/3D/win/VBoxWddmUmHlp/D3DKMT.cpp b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/D3DKMT.cpp
new file mode 100644
index 00000000..b30698a5
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/D3DKMT.cpp
@@ -0,0 +1,260 @@
+/* $Id: D3DKMT.cpp $ */
+/** @file
+ * WDDM Kernel Mode Thunks helpers.
+ */
+
+/*
+ * Copyright (C) 2018-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+/* We're unable to use standard r3 vbgl-based backdoor logging API because win8 Metro apps
+ * can not do CreateFile/Read/Write by default.
+ * This is why we use miniport escape functionality to issue backdoor log string to the miniport
+ * and submit it to host via standard r0 backdoor logging api accordingly
+ */
+
+#include "UmHlpInternal.h"
+
+
+/** Loads a system DLL.
+ *
+ * @returns Module handle or NULL
+ * @param pszName The DLL name.
+ */
+DECLCALLBACK(HMODULE) VBoxWddmLoadSystemDll(const char *pszName)
+{
+ char szPath[MAX_PATH];
+ UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
+ size_t cbName = strlen(pszName) + 1;
+ if (cchPath + 1 + cbName > sizeof(szPath))
+ {
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ return NULL;
+ }
+ szPath[cchPath] = '\\';
+ memcpy(&szPath[cchPath + 1], pszName, cbName);
+ return LoadLibraryA(szPath);
+}
+
+DECLCALLBACK(void) VBoxWddmLoadAdresses(HMODULE hmod, VBOXWDDMDLLPROC *paProcs)
+{
+ struct VBOXWDDMDLLPROC *pIter = paProcs;
+ while (pIter->pszName)
+ {
+ FARPROC pfn = GetProcAddress(hmod, pIter->pszName);
+ *pIter->ppfn = pfn;
+ ++pIter;
+ }
+}
+
+/*
+ * Kernel Mode Thunks (KMT) initialization.
+ */
+
+#define D3DKMT_LOAD_ENTRY(a) { #a, (FARPROC *)&g_D3DKMT.pfn##a }
+
+static D3DKMTFUNCTIONS g_D3DKMT = { 0 };
+static VBOXWDDMDLLPROC g_D3DKMTLoadTable[] =
+{
+ D3DKMT_LOAD_ENTRY(D3DKMTOpenAdapterFromHdc),
+ D3DKMT_LOAD_ENTRY(D3DKMTOpenAdapterFromDeviceName),
+ D3DKMT_LOAD_ENTRY(D3DKMTCloseAdapter),
+ D3DKMT_LOAD_ENTRY(D3DKMTQueryAdapterInfo),
+ D3DKMT_LOAD_ENTRY(D3DKMTEscape),
+ D3DKMT_LOAD_ENTRY(D3DKMTCreateDevice),
+ D3DKMT_LOAD_ENTRY(D3DKMTDestroyDevice),
+ D3DKMT_LOAD_ENTRY(D3DKMTCreateContext),
+ D3DKMT_LOAD_ENTRY(D3DKMTDestroyContext),
+ D3DKMT_LOAD_ENTRY(D3DKMTCreateAllocation),
+ D3DKMT_LOAD_ENTRY(D3DKMTDestroyAllocation),
+ D3DKMT_LOAD_ENTRY(D3DKMTRender),
+ D3DKMT_LOAD_ENTRY(D3DKMTPresent),
+ D3DKMT_LOAD_ENTRY(D3DKMTGetSharedPrimaryHandle),
+ D3DKMT_LOAD_ENTRY(D3DKMTQueryResourceInfo),
+ D3DKMT_LOAD_ENTRY(D3DKMTOpenResource),
+ D3DKMT_LOAD_ENTRY(D3DKMTEnumAdapters),
+ D3DKMT_LOAD_ENTRY(D3DKMTOpenAdapterFromLuid),
+ {NULL, NULL},
+};
+
+#undef D3DKMT_LOAD_ENTRY
+
+/** Initialize Kernel Mode Thunks (KMT) pointers in the g_D3DKMT structure.
+ *
+ * @returns True if successful.
+ */
+DECLCALLBACK(int) D3DKMTLoad(void)
+{
+ /* Modules which use D3DKMT must link with gdi32. */
+ HMODULE hmod = GetModuleHandleA("gdi32.dll");
+ Assert(hmod);
+ if (hmod)
+ {
+ VBoxWddmLoadAdresses(hmod, g_D3DKMTLoadTable);
+ }
+ return hmod != NULL;
+}
+
+DECLCALLBACK(D3DKMTFUNCTIONS const *) D3DKMTFunctions(void)
+{
+ return &g_D3DKMT;
+}
+
+
+/*
+ * Getting VirtualBox Graphics Adapter handle.
+ */
+
+static NTSTATUS vboxDispKmtOpenAdapterFromHdc(D3DKMT_HANDLE *phAdapter, LUID *pLuid)
+{
+ *phAdapter = 0;
+
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+ if (d3dkmt->pfnD3DKMTOpenAdapterFromHdc == NULL)
+ return STATUS_NOT_SUPPORTED;
+
+ D3DKMT_OPENADAPTERFROMHDC OpenAdapterData;
+ memset(&OpenAdapterData, 0, sizeof(OpenAdapterData));
+
+ for (int i = 0; ; ++i)
+ {
+ DISPLAY_DEVICEA dd;
+ memset(&dd, 0, sizeof(dd));
+ dd.cb = sizeof(dd);
+
+ if (!EnumDisplayDevicesA(NULL, i, &dd, 0))
+ break;
+
+ if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
+ {
+ OpenAdapterData.hDc = CreateDCA(NULL, dd.DeviceName, NULL, NULL);
+ break;
+ }
+ }
+
+ Assert(OpenAdapterData.hDc);
+
+ NTSTATUS Status;
+ if (OpenAdapterData.hDc)
+ {
+ Status = d3dkmt->pfnD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
+ Assert(Status == STATUS_SUCCESS);
+ if (Status == STATUS_SUCCESS)
+ {
+ *phAdapter = OpenAdapterData.hAdapter;
+ if (pLuid)
+ {
+ *pLuid = OpenAdapterData.AdapterLuid;
+ }
+ }
+
+ DeleteDC(OpenAdapterData.hDc);
+ }
+ else
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ }
+
+ return Status;
+}
+
+static NTSTATUS vboxDispKmtOpenAdapterFromLuid(D3DKMT_HANDLE *phAdapter, LUID *pLuid)
+{
+ *phAdapter = 0;
+
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+ if ( d3dkmt->pfnD3DKMTOpenAdapterFromLuid == NULL
+ || d3dkmt->pfnD3DKMTEnumAdapters == NULL)
+ return STATUS_NOT_SUPPORTED;
+
+ D3DKMT_ENUMADAPTERS EnumAdaptersData;
+ memset(&EnumAdaptersData, 0, sizeof(EnumAdaptersData));
+ EnumAdaptersData.NumAdapters = RT_ELEMENTS(EnumAdaptersData.Adapters);
+
+ NTSTATUS Status = d3dkmt->pfnD3DKMTEnumAdapters(&EnumAdaptersData);
+ Assert(Status == STATUS_SUCCESS);
+ if (Status == STATUS_SUCCESS)
+ {
+ Assert(EnumAdaptersData.NumAdapters);
+
+ /* Try the same twice: if we fail to open the adapter containing present sources,
+ * then try to open any adapter.
+ */
+ for (int iPass = 0; iPass < 2 && *phAdapter == 0; ++iPass)
+ {
+ for (ULONG i = 0; i < EnumAdaptersData.NumAdapters; ++i)
+ {
+ if (iPass > 0 || EnumAdaptersData.Adapters[i].NumOfSources)
+ {
+ D3DKMT_OPENADAPTERFROMLUID OpenAdapterData;
+ memset(&OpenAdapterData, 0, sizeof(OpenAdapterData));
+ OpenAdapterData.AdapterLuid = EnumAdaptersData.Adapters[i].AdapterLuid;
+
+ Status = d3dkmt->pfnD3DKMTOpenAdapterFromLuid(&OpenAdapterData);
+ Assert(Status == STATUS_SUCCESS);
+ if (Status == STATUS_SUCCESS)
+ {
+ *phAdapter = OpenAdapterData.hAdapter;
+ if (pLuid)
+ {
+ *pLuid = EnumAdaptersData.Adapters[i].AdapterLuid;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS vboxDispKmtOpenAdapter2(D3DKMT_HANDLE *phAdapter, LUID *pLuid)
+{
+ NTSTATUS Status = vboxDispKmtOpenAdapterFromLuid(phAdapter, pLuid);
+ if (Status != STATUS_SUCCESS)
+ {
+ /* Fallback for pre-Windows8 */
+ Status = vboxDispKmtOpenAdapterFromHdc(phAdapter, pLuid);
+ }
+
+ return Status;
+}
+
+NTSTATUS vboxDispKmtOpenAdapter(D3DKMT_HANDLE *phAdapter)
+{
+ return vboxDispKmtOpenAdapter2(phAdapter, NULL);
+}
+
+NTSTATUS vboxDispKmtCloseAdapter(D3DKMT_HANDLE hAdapter)
+{
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+ if (d3dkmt->pfnD3DKMTCloseAdapter == NULL)
+ return STATUS_NOT_SUPPORTED;
+
+ D3DKMT_CLOSEADAPTER CloseAdapterData;
+ CloseAdapterData.hAdapter = hAdapter;
+
+ NTSTATUS Status = d3dkmt->pfnD3DKMTCloseAdapter(&CloseAdapterData);
+ Assert(Status == STATUS_SUCCESS);
+
+ return Status;
+}
diff --git a/src/VBox/Additions/3D/win/VBoxWddmUmHlp/Makefile.kmk b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/Makefile.kmk
new file mode 100644
index 00000000..80f6a078
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/Makefile.kmk
@@ -0,0 +1,54 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for the VirtualBox WDDM user mode driver
+#
+
+#
+# Copyright (C) 2018-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+LIBRARIES += VBoxWddmUmHlp
+LIBRARIES.amd64 += VBoxWddmUmHlp-x86
+
+#
+# VBoxWddmUmHlp - logger and other helpers for user mode driver
+#
+VBoxWddmUmHlp_TEMPLATE = NewerVccVBoxGuestR3Dll
+VBoxWddmUmHlp_INST = $(INST_ADDITIONS_LIB)
+VBoxWddmUmHlp_DEFS = VBOX_WITH_WDDM
+VBoxWddmUmHlp_INCS = \
+ $(PATH_ROOT)/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/shared \
+ $(VBOX_GRAPHICS_INCS)
+VBoxWddmUmHlp_SOURCES = \
+ D3DKMT.cpp \
+ VBoxMpLogger.cpp
+
+#
+# 64-bit version for 32-bit build.
+#
+VBoxWddmUmHlp-x86_EXTENDS = VBoxWddmUmHlp
+VBoxWddmUmHlp-x86_BLD_TRG_ARCH = x86
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Additions/3D/win/VBoxWddmUmHlp/UmHlpInternal.h b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/UmHlpInternal.h
new file mode 100644
index 00000000..5a7bafdb
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/UmHlpInternal.h
@@ -0,0 +1,36 @@
+/* $Id: UmHlpInternal.h $ */
+/** @file
+ * VBox WDDM User Mode Driver Helpers
+ */
+
+/*
+ * Copyright (C) 2018-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_UmHlpInternal_h
+#define GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_UmHlpInternal_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "VBoxWddmUmHlp.h"
+
+#endif /* !GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_UmHlpInternal_h */
diff --git a/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp
new file mode 100644
index 00000000..702e1558
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp
@@ -0,0 +1,167 @@
+/* $Id: VBoxMpLogger.cpp $ */
+/** @file
+ * VBox WDDM Display logger implementation
+ *
+ * We're unable to use standard r3 vbgl-based backdoor logging API because
+ * win8 Metro apps can not do CreateFile/Read/Write by default. This is why
+ * we use miniport escape functionality to issue backdoor log string to the
+ * miniport and submit it to host via standard r0 backdoor logging api
+ * accordingly
+ */
+
+/*
+ * Copyright (C) 2018-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#define IPRT_NO_CRT_FOR_3RD_PARTY /* To get malloc and free wrappers in IPRT_NO_CRT mode. Doesn't link with IPRT in non-no-CRT mode. */
+#include "UmHlpInternal.h"
+
+#include <../../../common/wddm/VBoxMPIf.h>
+#include <stdlib.h>
+#ifdef IPRT_NO_CRT
+# include <iprt/process.h>
+# include <iprt/string.h>
+#else
+# include <stdio.h>
+#endif
+#include <VBox/VBoxGuestLib.h>
+
+
+static void VBoxDispMpLoggerLogN(const char *pchString, size_t cchString)
+{
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+ if (d3dkmt->pfnD3DKMTEscape == NULL)
+ return;
+
+ D3DKMT_HANDLE hAdapter;
+ NTSTATUS Status = vboxDispKmtOpenAdapter(&hAdapter);
+ Assert(Status == STATUS_SUCCESS);
+ if (Status == 0)
+ {
+ uint32_t cchString2 = (uint32_t)RT_MIN(cchString, _64K - 1U);
+ uint32_t cbCmd = RT_UOFFSETOF_DYN(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[cchString2 + 1]);
+ PVBOXDISPIFESCAPE_DBGPRINT pCmd = (PVBOXDISPIFESCAPE_DBGPRINT)malloc(cbCmd);
+ Assert(pCmd);
+ if (pCmd)
+ {
+ pCmd->EscapeHdr.escapeCode = VBOXESC_DBGPRINT;
+ pCmd->EscapeHdr.u32CmdSpecific = 0;
+ memcpy(pCmd->aStringBuf, pchString, cchString2);
+ pCmd->aStringBuf[cchString2] = '\0';
+
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = hAdapter;
+ // EscapeData.hDevice = NULL;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ // EscapeData.Flags.HardwareAccess = 0;
+ EscapeData.pPrivateDriverData = pCmd;
+ EscapeData.PrivateDriverDataSize = cbCmd;
+ // EscapeData.hContext = NULL;
+
+ Status = d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ Assert(Status == STATUS_SUCCESS);
+
+ free(pCmd);
+ }
+
+ Status = vboxDispKmtCloseAdapter(hAdapter);
+ Assert(Status == STATUS_SUCCESS);
+ }
+}
+
+
+DECLCALLBACK(void) VBoxDispMpLoggerLog(const char *pszString)
+{
+ VBoxDispMpLoggerLogN(pszString, strlen(pszString));
+}
+
+
+DECLCALLBACK(void) VBoxDispMpLoggerLogF(const char *pszFormat, ...)
+{
+ /** @todo would make a whole lot more sense to just allocate
+ * VBOXDISPIFESCAPE_DBGPRINT here and printf into it's buffer than
+ * double buffering it like this */
+ char szBuffer[4096];
+ va_list va;
+ va_start(va, pszFormat);
+#ifdef IPRT_NO_CRT
+ RTStrPrintfV(szBuffer, sizeof(szBuffer), pszFormat, va);
+#else
+ _vsnprintf(szBuffer, sizeof(szBuffer), pszFormat, va);
+ szBuffer[sizeof(szBuffer) - 1] = '\0'; /* Don't trust the _vsnprintf function terminate the string! */
+#endif
+ va_end(va);
+
+ VBoxDispMpLoggerLog(szBuffer);
+}
+
+
+/* Interface used for backdoor logging. In no-CRT mode we will drag in IPRT
+ logging and it will be used on assertion in the no-CRT and IPRT code. */
+VBGLR3DECL(int) VbglR3WriteLog(const char *pch, size_t cch)
+{
+ VBoxDispMpLoggerLogN(pch, cch);
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Prefix the output string with exe name and pid/tid.
+ */
+#ifndef IPRT_NO_CRT
+static const char *vboxUmLogGetExeName(void)
+{
+ static int s_fModuleNameInited = 0;
+ static char s_szModuleName[MAX_PATH];
+
+ if (!s_fModuleNameInited)
+ {
+ const DWORD cchName = GetModuleFileNameA(NULL, s_szModuleName, RT_ELEMENTS(s_szModuleName));
+ if (cchName == 0)
+ return "<no module>";
+ s_fModuleNameInited = 1;
+ }
+ return &s_szModuleName[0];
+}
+#endif
+
+DECLCALLBACK(void) VBoxWddmUmLog(const char *pszString)
+{
+ /** @todo Allocate VBOXDISPIFESCAPE_DBGPRINT here and format right into it
+ * instead? That would be a lot more flexible and a little faster. */
+ char szBuffer[4096];
+#ifdef IPRT_NO_CRT
+ /** @todo use RTProcShortName instead of RTProcExecutablePath? Will avoid
+ * chopping off log text if the executable path is too long. */
+ RTStrPrintf(szBuffer, sizeof(szBuffer), "['%s' 0x%lx.0x%lx]: %s",
+ RTProcExecutablePath() /* should've been initialized by nocrt-startup-dll-win.cpp already */,
+ GetCurrentProcessId(), GetCurrentThreadId(), pszString);
+#else
+ int cch = _snprintf(szBuffer, sizeof(szBuffer), "['%s' 0x%lx.0x%lx]: %s",
+ vboxUmLogGetExeName(), GetCurrentProcessId(), GetCurrentThreadId(), pszString);
+ AssertReturnVoid(cch > 0); /* unlikely that we'll have string encoding problems, but just in case. */
+ szBuffer[sizeof(szBuffer) - 1] = '\0'; /* the function doesn't necessarily terminate the buffer on overflow. */
+#endif
+
+ VBoxDispMpLoggerLog(szBuffer);
+}
+
diff --git a/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxWddmUmHlp.h b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxWddmUmHlp.h
new file mode 100644
index 00000000..ffc10c79
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxWddmUmHlp.h
@@ -0,0 +1,116 @@
+/* $Id: VBoxWddmUmHlp.h $ */
+/** @file
+ * VBox WDDM User Mode Driver Helpers
+ */
+
+/*
+ * Copyright (C) 2018-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_VBoxWddmUmHlp_h
+#define GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_VBoxWddmUmHlp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/win/d3d9.h>
+#include <d3dumddi.h>
+#include <iprt/win/d3dkmthk.h>
+
+#include <iprt/asm.h>
+#include <iprt/cdefs.h>
+
+/* Do not require IPRT library. */
+/** @todo r=bird: It is *NOT* okay to redefine Assert* (or Log*) macros! It
+ * causes confusing as the code no longer behaves in the way one expect. Thus,
+ * it is strictly forbidden. */
+#ifndef IPRT_NO_CRT
+# undef Assert
+# undef AssertReturnVoid
+# ifdef RT_STRICT
+# define Assert(_e) (void)( (!!(_e)) || (ASMBreakpoint(), 0) )
+# define AssertReturnVoid(a_Expr) do { if (RT_LIKELY(a_Expr)) {} else { ASMBreakpoint(); return; } } while (0)
+# else
+# define Assert(_e) (void)( 0 )
+# define AssertReturnVoid(a_Expr) do { if (RT_LIKELY(a_Expr)) {} else return; } while (0)
+# endif
+#endif
+
+/* Do not require ntstatus.h.
+ * D3DKMT functions return NTSTATUS, but the driver code uses it only as a success/failure indicator.
+ * Therefore define the success and a failure status here.
+ */
+#ifndef STATUS_SUCCESS
+#define STATUS_SUCCESS 0
+#endif
+#ifndef STATUS_NOT_SUPPORTED
+#define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BBL)
+#endif
+
+RT_C_DECLS_BEGIN
+
+typedef struct VBOXWDDMDLLPROC
+{
+ char const *pszName;
+ FARPROC *ppfn;
+} VBOXWDDMDLLPROC;
+
+typedef struct D3DKMTFUNCTIONS
+{
+ PFND3DKMT_OPENADAPTERFROMHDC pfnD3DKMTOpenAdapterFromHdc;
+ PFND3DKMT_OPENADAPTERFROMDEVICENAME pfnD3DKMTOpenAdapterFromDeviceName;
+ PFND3DKMT_CLOSEADAPTER pfnD3DKMTCloseAdapter;
+ PFND3DKMT_QUERYADAPTERINFO pfnD3DKMTQueryAdapterInfo;
+ PFND3DKMT_ESCAPE pfnD3DKMTEscape;
+ PFND3DKMT_CREATEDEVICE pfnD3DKMTCreateDevice;
+ PFND3DKMT_DESTROYDEVICE pfnD3DKMTDestroyDevice;
+ PFND3DKMT_CREATECONTEXT pfnD3DKMTCreateContext;
+ PFND3DKMT_DESTROYCONTEXT pfnD3DKMTDestroyContext;
+ PFND3DKMT_CREATEALLOCATION pfnD3DKMTCreateAllocation;
+ PFND3DKMT_DESTROYALLOCATION pfnD3DKMTDestroyAllocation;
+ PFND3DKMT_RENDER pfnD3DKMTRender;
+ PFND3DKMT_PRESENT pfnD3DKMTPresent;
+ PFND3DKMT_GETSHAREDPRIMARYHANDLE pfnD3DKMTGetSharedPrimaryHandle;
+ PFND3DKMT_QUERYRESOURCEINFO pfnD3DKMTQueryResourceInfo;
+ PFND3DKMT_OPENRESOURCE pfnD3DKMTOpenResource;
+
+ /* Win 8+ */
+ PFND3DKMT_ENUMADAPTERS pfnD3DKMTEnumAdapters;
+ PFND3DKMT_OPENADAPTERFROMLUID pfnD3DKMTOpenAdapterFromLuid;
+} D3DKMTFUNCTIONS;
+
+DECLCALLBACK(HMODULE) VBoxWddmLoadSystemDll(const char *pszName);
+DECLCALLBACK(void) VBoxWddmLoadAdresses(HMODULE hmod, VBOXWDDMDLLPROC *paProcs);
+
+DECLCALLBACK(int) D3DKMTLoad(void);
+DECLCALLBACK(D3DKMTFUNCTIONS const *) D3DKMTFunctions(void);
+
+DECLCALLBACK(void) VBoxDispMpLoggerLogF(const char *pszFormat, ...);
+DECLCALLBACK(void) VBoxWddmUmLog(const char *pszString);
+
+/** @todo Rename to VBoxWddm* */
+NTSTATUS vboxDispKmtOpenAdapter2(D3DKMT_HANDLE *phAdapter, LUID *pLuid);
+NTSTATUS vboxDispKmtOpenAdapter(D3DKMT_HANDLE *phAdapter);
+NTSTATUS vboxDispKmtCloseAdapter(D3DKMT_HANDLE hAdapter);
+
+RT_C_DECLS_END
+
+#endif /* !GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_VBoxWddmUmHlp_h */