diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
commit | f215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch) | |
tree | 6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Additions/3D/win/VBoxWddmUmHlp | |
parent | Initial commit. (diff) | |
download | virtualbox-c31cb7e733ae8e33d73383e04db264d4293f0b1a.tar.xz virtualbox-c31cb7e733ae8e33d73383e04db264d4293f0b1a.zip |
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Additions/3D/win/VBoxWddmUmHlp')
-rw-r--r-- | src/VBox/Additions/3D/win/VBoxWddmUmHlp/D3DKMT.cpp | 260 | ||||
-rw-r--r-- | src/VBox/Additions/3D/win/VBoxWddmUmHlp/Makefile.kmk | 54 | ||||
-rw-r--r-- | src/VBox/Additions/3D/win/VBoxWddmUmHlp/UmHlpInternal.h | 36 | ||||
-rw-r--r-- | src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp | 167 | ||||
-rw-r--r-- | src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxWddmUmHlp.h | 116 |
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 */ |