summaryrefslogtreecommitdiffstats
path: root/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp')
-rw-r--r--src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp167
1 files changed, 167 insertions, 0 deletions
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);
+}
+