diff --git a/DDrawCompat/CompatD3dDdiAdapterCallbacks.cpp b/DDrawCompat/CompatD3dDdiAdapterCallbacks.cpp new file mode 100644 index 0000000..8ef14c3 --- /dev/null +++ b/DDrawCompat/CompatD3dDdiAdapterCallbacks.cpp @@ -0,0 +1,5 @@ +#include "CompatD3dDdiAdapterCallbacks.h" + +void CompatD3dDdiAdapterCallbacks::setCompatVtable(D3DDDI_ADAPTERCALLBACKS& /*vtable*/) +{ +} diff --git a/DDrawCompat/CompatD3dDdiAdapterCallbacks.h b/DDrawCompat/CompatD3dDdiAdapterCallbacks.h new file mode 100644 index 0000000..4058487 --- /dev/null +++ b/DDrawCompat/CompatD3dDdiAdapterCallbacks.h @@ -0,0 +1,11 @@ +#pragma once + +#include "CompatVtable.h" +#include "D3dDdiAdapterCallbacksVisitor.h" + +class CompatD3dDdiAdapterCallbacks : + public CompatVtable +{ +public: + static void setCompatVtable(D3DDDI_ADAPTERCALLBACKS& vtable); +}; diff --git a/DDrawCompat/CompatD3dDdiAdapterFuncs.cpp b/DDrawCompat/CompatD3dDdiAdapterFuncs.cpp new file mode 100644 index 0000000..eca9288 --- /dev/null +++ b/DDrawCompat/CompatD3dDdiAdapterFuncs.cpp @@ -0,0 +1,22 @@ +#include "CompatD3dDdiAdapterFuncs.h" +#include "CompatD3dDdiDeviceCallbacks.h" +#include "CompatD3dDdiDeviceFuncs.h" + +namespace +{ + HRESULT APIENTRY createDevice(HANDLE hAdapter, D3DDDIARG_CREATEDEVICE* pCreateData) + { + CompatD3dDdiDeviceCallbacks::hookVtable(pCreateData->pCallbacks); + HRESULT result = CompatD3dDdiAdapterFuncs::s_origVtable.pfnCreateDevice(hAdapter, pCreateData); + if (SUCCEEDED(result)) + { + CompatD3dDdiDeviceFuncs::hookVtable(pCreateData->pDeviceFuncs); + } + return result; + } +} + +void CompatD3dDdiAdapterFuncs::setCompatVtable(D3DDDI_ADAPTERFUNCS& vtable) +{ + vtable.pfnCreateDevice = &createDevice; +} diff --git a/DDrawCompat/CompatD3dDdiAdapterFuncs.h b/DDrawCompat/CompatD3dDdiAdapterFuncs.h new file mode 100644 index 0000000..eaa95cd --- /dev/null +++ b/DDrawCompat/CompatD3dDdiAdapterFuncs.h @@ -0,0 +1,10 @@ +#pragma once + +#include "CompatVtable.h" +#include "D3dDdiAdapterFuncsVisitor.h" + +class CompatD3dDdiAdapterFuncs : public CompatVtable +{ +public: + static void setCompatVtable(D3DDDI_ADAPTERFUNCS& vtable); +}; diff --git a/DDrawCompat/CompatD3dDdiDeviceCallbacks.cpp b/DDrawCompat/CompatD3dDdiDeviceCallbacks.cpp new file mode 100644 index 0000000..fdc8746 --- /dev/null +++ b/DDrawCompat/CompatD3dDdiDeviceCallbacks.cpp @@ -0,0 +1,5 @@ +#include "CompatD3dDdiDeviceCallbacks.h" + +void CompatD3dDdiDeviceCallbacks::setCompatVtable(D3DDDI_DEVICECALLBACKS& /*vtable*/) +{ +} diff --git a/DDrawCompat/CompatD3dDdiDeviceCallbacks.h b/DDrawCompat/CompatD3dDdiDeviceCallbacks.h new file mode 100644 index 0000000..81095aa --- /dev/null +++ b/DDrawCompat/CompatD3dDdiDeviceCallbacks.h @@ -0,0 +1,10 @@ +#pragma once + +#include "CompatVtable.h" +#include "D3dDdiDeviceCallbacksVisitor.h" + +class CompatD3dDdiDeviceCallbacks : public CompatVtable +{ +public: + static void setCompatVtable(D3DDDI_DEVICECALLBACKS& vtable); +}; diff --git a/DDrawCompat/CompatD3dDdiDeviceFuncs.cpp b/DDrawCompat/CompatD3dDdiDeviceFuncs.cpp new file mode 100644 index 0000000..736f7cf --- /dev/null +++ b/DDrawCompat/CompatD3dDdiDeviceFuncs.cpp @@ -0,0 +1,5 @@ +#include "CompatD3dDdiDeviceFuncs.h" + +void CompatD3dDdiDeviceFuncs::setCompatVtable(D3DDDI_DEVICEFUNCS& /*vtable*/) +{ +} diff --git a/DDrawCompat/CompatD3dDdiDeviceFuncs.h b/DDrawCompat/CompatD3dDdiDeviceFuncs.h new file mode 100644 index 0000000..b4ee404 --- /dev/null +++ b/DDrawCompat/CompatD3dDdiDeviceFuncs.h @@ -0,0 +1,10 @@ +#pragma once + +#include "CompatVtable.h" +#include "D3dDdiDeviceFuncsVisitor.h" + +class CompatD3dDdiDeviceFuncs : public CompatVtable +{ +public: + static void setCompatVtable(D3DDDI_DEVICEFUNCS& vtable); +}; diff --git a/DDrawCompat/CompatVtable.h b/DDrawCompat/CompatVtable.h index 4c4e740..76ac051 100644 --- a/DDrawCompat/CompatVtable.h +++ b/DDrawCompat/CompatVtable.h @@ -5,6 +5,7 @@ #include #include "DDrawLog.h" +#include "DDrawProcs.h" #include "DDrawVtableVisitor.h" #include "Hook.h" @@ -29,17 +30,14 @@ template class CompatVtable : public CompatVtableBase { public: - static void hookVtable(Interface& intf) + static void hookVtable(const Vtable* vtable) { static bool isInitialized = false; - if (!isInitialized) + if (!isInitialized && vtable) { isInitialized = true; - s_vtablePtr = intf.lpVtbl; - s_origVtable = *intf.lpVtbl; - - InitVisitor visitor; + InitVisitor visitor(*vtable); forEach>(visitor); } } @@ -48,9 +46,13 @@ private: class InitVisitor { public: + InitVisitor(const Vtable& origVtable) : m_origVtable(origVtable) {} + template void visit() { + s_origVtable.*ptr = m_origVtable.*ptr; + if (!(s_compatVtable.*ptr)) { s_threadSafeVtable.*ptr = s_origVtable.*ptr; @@ -66,8 +68,11 @@ private: template void visitDebug(const std::string& vtableTypeName, const std::string& funcName) { + Compat::Log() << "Hooking function: " << vtableTypeName << "::" << funcName; s_funcNames[getKey()] = vtableTypeName + "::" + funcName; + s_origVtable.*ptr = m_origVtable.*ptr; + s_threadSafeVtable.*ptr = getThreadSafeFuncPtr(s_compatVtable.*ptr); Compat::hookFunction(reinterpret_cast(s_origVtable.*ptr), s_threadSafeVtable.*ptr); @@ -95,22 +100,46 @@ private: return &threadSafeFunc; } - template - static Result STDMETHODCALLTYPE threadSafeFunc(IntfPtr This, Params... params) + template + static FuncPtr getThreadSafeFuncPtr(FuncPtr) + { + return &threadSafeFunc; + } + + template + static Result STDMETHODCALLTYPE threadSafeFunc(Params... params) { Compat::origProcs.AcquireDDThreadLock(); #ifdef _DEBUG - Compat::LogEnter(s_funcNames[getKey()].c_str(), This, params...); + Compat::LogEnter(s_funcNames[getKey()].c_str(), params...); #endif - Result result = (s_compatVtable.*ptr)(This, params...); + Result result = (s_compatVtable.*ptr)(params...); #ifdef _DEBUG - Compat::LogLeave(s_funcNames[getKey()].c_str(), This, params...) << result; + Compat::LogLeave(s_funcNames[getKey()].c_str(), params...) << result; #endif Compat::origProcs.ReleaseDDThreadLock(); return result; } + + template + static void STDMETHODCALLTYPE threadSafeFunc(Params... params) + { + Compat::origProcs.AcquireDDThreadLock(); +#ifdef _DEBUG + Compat::LogEnter(s_funcNames[getKey()].c_str(), params...); +#endif + + (s_compatVtable.*ptr)(params...); + +#ifdef _DEBUG + Compat::LogLeave(s_funcNames[getKey()].c_str(), params...); +#endif + Compat::origProcs.ReleaseDDThreadLock(); + } + + const Vtable& m_origVtable; }; static Vtable createCompatVtable() @@ -126,7 +155,6 @@ private: return vtable; } - static Vtable* s_vtablePtr; static Vtable s_compatVtable; static Vtable s_threadSafeVtable; static std::map, std::string> s_funcNames; @@ -136,10 +164,7 @@ template Vtable CompatVtableBase::s_origVtable = {}; template -Vtable* CompatVtable::s_vtablePtr = nullptr; - -template -Vtable CompatVtable::s_compatVtable(CompatInterface::getCompatVtable()); +Vtable CompatVtable::s_compatVtable(getCompatVtable()); template Vtable CompatVtable::s_threadSafeVtable = {}; diff --git a/DDrawCompat/D3dDdiAdapterCallbacksVisitor.h b/DDrawCompat/D3dDdiAdapterCallbacksVisitor.h new file mode 100644 index 0000000..396b5b1 --- /dev/null +++ b/DDrawCompat/D3dDdiAdapterCallbacksVisitor.h @@ -0,0 +1,24 @@ +#pragma once + +#define CINTERFACE + +#include +#include + +#include "DDrawVtableVisitor.h" + +struct D3dDdiAdapterCallbacksIntf +{ + D3DDDI_ADAPTERCALLBACKS* lpVtbl; +}; + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DD_VISIT(pfnQueryAdapterInfoCb); + // DD_VISIT(pfnGetMultisampleMethodListCb); -- not set by ddraw, potentially garbage + } +}; diff --git a/DDrawCompat/D3dDdiAdapterFuncsVisitor.h b/DDrawCompat/D3dDdiAdapterFuncsVisitor.h new file mode 100644 index 0000000..965bd51 --- /dev/null +++ b/DDrawCompat/D3dDdiAdapterFuncsVisitor.h @@ -0,0 +1,25 @@ +#pragma once + +#define CINTERFACE + +#include +#include + +#include "DDrawVtableVisitor.h" + +struct D3dDdiAdapterFuncsIntf +{ + D3DDDI_ADAPTERFUNCS* lpVtbl; +}; + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DD_VISIT(pfnGetCaps); + DD_VISIT(pfnCreateDevice); + DD_VISIT(pfnCloseAdapter); + } +}; diff --git a/DDrawCompat/D3dDdiDeviceCallbacksVisitor.h b/DDrawCompat/D3dDdiDeviceCallbacksVisitor.h new file mode 100644 index 0000000..cd82406 --- /dev/null +++ b/DDrawCompat/D3dDdiDeviceCallbacksVisitor.h @@ -0,0 +1,85 @@ +#pragma once + +#define CINTERFACE + +#include +#include + +#include "D3dDdiHooks.h" +#include "DDrawVtableVisitor.h" + +struct D3dDdiDeviceCallbacksIntf +{ + D3DDDI_DEVICECALLBACKS* lpVtbl; +}; + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DD_VISIT(pfnAllocateCb); + DD_VISIT(pfnDeallocateCb); + DD_VISIT(pfnSetPriorityCb); + DD_VISIT(pfnQueryResidencyCb); + // DD_VISIT(pfnSetDisplayModeCb); -- not set by ddraw + DD_VISIT(pfnPresentCb); + DD_VISIT(pfnRenderCb); + DD_VISIT(pfnLockCb); + DD_VISIT(pfnUnlockCb); + DD_VISIT(pfnEscapeCb); + DD_VISIT(pfnCreateOverlayCb); + DD_VISIT(pfnUpdateOverlayCb); + DD_VISIT(pfnFlipOverlayCb); + DD_VISIT(pfnDestroyOverlayCb); + DD_VISIT(pfnCreateContextCb); + DD_VISIT(pfnDestroyContextCb); + DD_VISIT(pfnCreateSynchronizationObjectCb); + DD_VISIT(pfnDestroySynchronizationObjectCb); + DD_VISIT(pfnWaitForSynchronizationObjectCb); + DD_VISIT(pfnSignalSynchronizationObjectCb); + // DD_VISIT(pfnSetAsyncCallbacksCb); -- not set by ddraw + DD_VISIT(pfnSetDisplayPrivateDriverFormatCb); + + if (D3dDdiHooks::getDdiVersion() >= D3D_UMD_INTERFACE_VERSION_WIN8) + { + DD_VISIT(pfnOfferAllocationsCb); + DD_VISIT(pfnReclaimAllocationsCb); + DD_VISIT(pfnCreateSynchronizationObject2Cb); + DD_VISIT(pfnWaitForSynchronizationObject2Cb); + DD_VISIT(pfnSignalSynchronizationObject2Cb); + // DD_VISIT(pfnPresentMultiPlaneOverlayCb); -- not set by ddraw + } + + if (D3dDdiHooks::getDdiVersion() >= D3D_UMD_INTERFACE_VERSION_WDDM1_3) + { + // DD_VISIT(pfnLogUMDMarkerCb); -- not set by ddraw + } + + if (D3dDdiHooks::getDdiVersion() >= D3D_UMD_INTERFACE_VERSION_WDDM2_0) + { + DD_VISIT(pfnMakeResidentCb); + DD_VISIT(pfnEvictCb); + DD_VISIT(pfnWaitForSynchronizationObjectFromCpuCb); + DD_VISIT(pfnSignalSynchronizationObjectFromCpuCb); + DD_VISIT(pfnWaitForSynchronizationObjectFromGpuCb); + DD_VISIT(pfnSignalSynchronizationObjectFromGpuCb); + DD_VISIT(pfnCreatePagingQueueCb); + DD_VISIT(pfnDestroyPagingQueueCb); + DD_VISIT(pfnLock2Cb); + DD_VISIT(pfnUnlock2Cb); + DD_VISIT(pfnInvalidateCacheCb); + DD_VISIT(pfnReserveGpuVirtualAddressCb); + DD_VISIT(pfnMapGpuVirtualAddressCb); + DD_VISIT(pfnFreeGpuVirtualAddressCb); + DD_VISIT(pfnUpdateGpuVirtualAddressCb); + DD_VISIT(pfnCreateContextVirtualCb); + DD_VISIT(pfnSubmitCommandCb); + DD_VISIT(pfnDeallocate2Cb); + DD_VISIT(pfnSignalSynchronizationObjectFromGpu2Cb); + DD_VISIT(pfnReclaimAllocations2Cb); + DD_VISIT(pfnGetResourcePresentPrivateDriverDataCb); + } + } +}; diff --git a/DDrawCompat/D3dDdiDeviceFuncsVisitor.h b/DDrawCompat/D3dDdiDeviceFuncsVisitor.h new file mode 100644 index 0000000..39df6de --- /dev/null +++ b/DDrawCompat/D3dDdiDeviceFuncsVisitor.h @@ -0,0 +1,181 @@ +#pragma once + +#define CINTERFACE + +#include +#include + +#include "D3dDdiHooks.h" +#include "DDrawVtableVisitor.h" + +struct D3dDdiDeviceFuncsIntf +{ + D3DDDI_DEVICEFUNCS* lpVtbl; +}; + +template <> +struct DDrawVtableForEach +{ + template + static void forEach(Visitor& visitor) + { + DD_VISIT(pfnSetRenderState); + DD_VISIT(pfnUpdateWInfo); + DD_VISIT(pfnValidateDevice); + DD_VISIT(pfnSetTextureStageState); + DD_VISIT(pfnSetTexture); + DD_VISIT(pfnSetPixelShader); + DD_VISIT(pfnSetPixelShaderConst); + DD_VISIT(pfnSetStreamSourceUm); + DD_VISIT(pfnSetIndices); + DD_VISIT(pfnSetIndicesUm); + DD_VISIT(pfnDrawPrimitive); + DD_VISIT(pfnDrawIndexedPrimitive); + DD_VISIT(pfnDrawRectPatch); + DD_VISIT(pfnDrawTriPatch); + DD_VISIT(pfnDrawPrimitive2); + DD_VISIT(pfnDrawIndexedPrimitive2); + DD_VISIT(pfnVolBlt); + DD_VISIT(pfnBufBlt); + DD_VISIT(pfnTexBlt); + DD_VISIT(pfnStateSet); + DD_VISIT(pfnSetPriority); + DD_VISIT(pfnClear); + DD_VISIT(pfnUpdatePalette); + DD_VISIT(pfnSetPalette); + DD_VISIT(pfnSetVertexShaderConst); + DD_VISIT(pfnMultiplyTransform); + DD_VISIT(pfnSetTransform); + DD_VISIT(pfnSetViewport); + DD_VISIT(pfnSetZRange); + DD_VISIT(pfnSetMaterial); + DD_VISIT(pfnSetLight); + DD_VISIT(pfnCreateLight); + DD_VISIT(pfnDestroyLight); + DD_VISIT(pfnSetClipPlane); + DD_VISIT(pfnGetInfo); + DD_VISIT(pfnLock); + DD_VISIT(pfnUnlock); + DD_VISIT(pfnCreateResource); + DD_VISIT(pfnDestroyResource); + DD_VISIT(pfnSetDisplayMode); + DD_VISIT(pfnPresent); + DD_VISIT(pfnFlush); + DD_VISIT(pfnCreateVertexShaderFunc); + DD_VISIT(pfnDeleteVertexShaderFunc); + DD_VISIT(pfnSetVertexShaderFunc); + DD_VISIT(pfnCreateVertexShaderDecl); + DD_VISIT(pfnDeleteVertexShaderDecl); + DD_VISIT(pfnSetVertexShaderDecl); + DD_VISIT(pfnSetVertexShaderConstI); + DD_VISIT(pfnSetVertexShaderConstB); + DD_VISIT(pfnSetScissorRect); + DD_VISIT(pfnSetStreamSource); + DD_VISIT(pfnSetStreamSourceFreq); + DD_VISIT(pfnSetConvolutionKernelMono); + DD_VISIT(pfnComposeRects); + DD_VISIT(pfnBlt); + DD_VISIT(pfnColorFill); + DD_VISIT(pfnDepthFill); + DD_VISIT(pfnCreateQuery); + DD_VISIT(pfnDestroyQuery); + DD_VISIT(pfnIssueQuery); + DD_VISIT(pfnGetQueryData); + DD_VISIT(pfnSetRenderTarget); + DD_VISIT(pfnSetDepthStencil); + DD_VISIT(pfnGenerateMipSubLevels); + DD_VISIT(pfnSetPixelShaderConstI); + DD_VISIT(pfnSetPixelShaderConstB); + DD_VISIT(pfnCreatePixelShader); + DD_VISIT(pfnDeletePixelShader); + DD_VISIT(pfnCreateDecodeDevice); + DD_VISIT(pfnDestroyDecodeDevice); + DD_VISIT(pfnSetDecodeRenderTarget); + DD_VISIT(pfnDecodeBeginFrame); + DD_VISIT(pfnDecodeEndFrame); + DD_VISIT(pfnDecodeExecute); + DD_VISIT(pfnDecodeExtensionExecute); + DD_VISIT(pfnCreateVideoProcessDevice); + DD_VISIT(pfnDestroyVideoProcessDevice); + DD_VISIT(pfnVideoProcessBeginFrame); + DD_VISIT(pfnVideoProcessEndFrame); + DD_VISIT(pfnSetVideoProcessRenderTarget); + DD_VISIT(pfnVideoProcessBlt); + DD_VISIT(pfnCreateExtensionDevice); + DD_VISIT(pfnDestroyExtensionDevice); + DD_VISIT(pfnExtensionExecute); + DD_VISIT(pfnCreateOverlay); + DD_VISIT(pfnUpdateOverlay); + DD_VISIT(pfnFlipOverlay); + DD_VISIT(pfnGetOverlayColorControls); + DD_VISIT(pfnSetOverlayColorControls); + DD_VISIT(pfnDestroyOverlay); + DD_VISIT(pfnDestroyDevice); + DD_VISIT(pfnQueryResourceResidency); + DD_VISIT(pfnOpenResource); + DD_VISIT(pfnGetCaptureAllocationHandle); + DD_VISIT(pfnCaptureToSysMem); + DD_VISIT(pfnLockAsync); + DD_VISIT(pfnUnlockAsync); + DD_VISIT(pfnRename); + + if (D3dDdiHooks::getDdiVersion() >= D3D_UMD_INTERFACE_VERSION_WIN7) + { + DD_VISIT(pfnCreateVideoProcessor); + DD_VISIT(pfnSetVideoProcessBltState); + DD_VISIT(pfnGetVideoProcessBltStatePrivate); + DD_VISIT(pfnSetVideoProcessStreamState); + DD_VISIT(pfnGetVideoProcessStreamStatePrivate); + DD_VISIT(pfnVideoProcessBltHD); + DD_VISIT(pfnDestroyVideoProcessor); + DD_VISIT(pfnCreateAuthenticatedChannel); + DD_VISIT(pfnAuthenticatedChannelKeyExchange); + DD_VISIT(pfnQueryAuthenticatedChannel); + DD_VISIT(pfnConfigureAuthenticatedChannel); + DD_VISIT(pfnDestroyAuthenticatedChannel); + DD_VISIT(pfnCreateCryptoSession); + DD_VISIT(pfnCryptoSessionKeyExchange); + DD_VISIT(pfnDestroyCryptoSession); + DD_VISIT(pfnEncryptionBlt); + DD_VISIT(pfnGetPitch); + DD_VISIT(pfnStartSessionKeyRefresh); + DD_VISIT(pfnFinishSessionKeyRefresh); + DD_VISIT(pfnGetEncryptionBltKey); + DD_VISIT(pfnDecryptionBlt); + DD_VISIT(pfnResolveSharedResource); + } + + if (D3dDdiHooks::getDdiVersion() >= D3D_UMD_INTERFACE_VERSION_WIN8) + { + DD_VISIT(pfnVolBlt1); + DD_VISIT(pfnBufBlt1); + DD_VISIT(pfnTexBlt1); + DD_VISIT(pfnDiscard); + DD_VISIT(pfnOfferResources); + DD_VISIT(pfnReclaimResources); + DD_VISIT(pfnCheckDirectFlipSupport); + DD_VISIT(pfnCreateResource2); + DD_VISIT(pfnCheckMultiPlaneOverlaySupport); + DD_VISIT(pfnPresentMultiPlaneOverlay); + } + + if (D3dDdiHooks::getDdiVersion() >= D3D_UMD_INTERFACE_VERSION_WDDM1_3) + { + // DD_VISIT(pfnReserved1); -- unused + DD_VISIT(pfnFlush1); + DD_VISIT(pfnCheckCounterInfo); + DD_VISIT(pfnCheckCounter); + DD_VISIT(pfnUpdateSubresourceUP); + DD_VISIT(pfnPresent1); + DD_VISIT(pfnCheckPresentDurationSupport); + + DD_VISIT(pfnSetMarker); + DD_VISIT(pfnSetMarkerMode); + } + + if (D3dDdiHooks::getDdiVersion() >= D3D_UMD_INTERFACE_VERSION_WDDM2_0) + { + DD_VISIT(pfnTrimResidencySet); + } + } +}; diff --git a/DDrawCompat/D3dDdiHooks.cpp b/DDrawCompat/D3dDdiHooks.cpp new file mode 100644 index 0000000..f44fab1 --- /dev/null +++ b/DDrawCompat/D3dDdiHooks.cpp @@ -0,0 +1,160 @@ +#define CINTERFACE + +#include +#include +#include +#include <..\km\d3dkmthk.h> + +#include "CompatD3dDdiAdapterCallbacks.h" +#include "CompatD3dDdiAdapterFuncs.h" +#include "DDrawLog.h" +#include "Hook.h" + +HRESULT APIENTRY OpenAdapter(D3DDDIARG_OPENADAPTER*) { return 0; } + +namespace +{ + UINT g_ddiVersion = 0; + HMODULE g_umd = nullptr; + + D3DKMT_HANDLE openAdapterFromHdc(HDC hdc); + + void closeAdapter(D3DKMT_HANDLE adapter) + { + D3DKMT_CLOSEADAPTER closeAdapterData = {}; + closeAdapterData.hAdapter = adapter; + D3DKMTCloseAdapter(&closeAdapterData); + } + + DISPLAY_DEVICE getPrimaryDisplayDevice() + { + DISPLAY_DEVICE dd = {}; + dd.cb = sizeof(dd); + for (DWORD i = 0; + EnumDisplayDevices(nullptr, i, &dd, 0) && !(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE); + ++i) + { + } + + if (!(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)) + { + Compat::Log() << "Failed to find the primary display device"; + ZeroMemory(&dd, sizeof(dd)); + } + + return dd; + } + + D3DKMT_UMDFILENAMEINFO getUmdDriverName(D3DKMT_HANDLE adapter) + { + D3DKMT_UMDFILENAMEINFO umdFileNameInfo = {}; + umdFileNameInfo.Version = KMTUMDVERSION_DX9; + + D3DKMT_QUERYADAPTERINFO queryAdapterInfo = {}; + queryAdapterInfo.hAdapter = adapter; + queryAdapterInfo.Type = KMTQAITYPE_UMDRIVERNAME; + queryAdapterInfo.pPrivateDriverData = &umdFileNameInfo; + queryAdapterInfo.PrivateDriverDataSize = sizeof(umdFileNameInfo); + NTSTATUS result = D3DKMTQueryAdapterInfo(&queryAdapterInfo); + if (FAILED(result)) + { + Compat::Log() << "Failed to query the display driver name: " << result; + ZeroMemory(&umdFileNameInfo, sizeof(umdFileNameInfo)); + } + + return umdFileNameInfo; + } + + D3DKMT_UMDFILENAMEINFO getPrimaryUmdDriverName() + { + D3DKMT_UMDFILENAMEINFO umdFileNameInfo = {}; + + DISPLAY_DEVICE dd = getPrimaryDisplayDevice(); + if (!dd.DeviceName) + { + return umdFileNameInfo; + } + + HDC dc = CreateDC(nullptr, dd.DeviceName, nullptr, nullptr); + if (!dc) + { + Compat::Log() << "Failed to create a DC for the primary display device"; + return umdFileNameInfo; + } + + D3DKMT_HANDLE adapter = openAdapterFromHdc(dc); + DeleteDC(dc); + if (!adapter) + { + return umdFileNameInfo; + } + + umdFileNameInfo = getUmdDriverName(adapter); + closeAdapter(adapter); + if (0 == umdFileNameInfo.UmdFileName[0]) + { + return umdFileNameInfo; + } + + Compat::Log() << "Primary display adapter driver: " << umdFileNameInfo.UmdFileName; + return umdFileNameInfo; + } + + HRESULT APIENTRY openAdapter(D3DDDIARG_OPENADAPTER* pOpenData) + { + Compat::LogEnter("openAdapter", pOpenData); + CompatD3dDdiAdapterCallbacks::hookVtable(pOpenData->pAdapterCallbacks); + HRESULT result = CALL_ORIG_FUNC(OpenAdapter)(pOpenData); + if (SUCCEEDED(result)) + { + g_ddiVersion = min(pOpenData->Version, pOpenData->DriverVersion); + CompatD3dDdiAdapterFuncs::hookVtable(pOpenData->pAdapterFuncs); + } + Compat::LogLeave("openAdapter", pOpenData) << result; + return result; + } + + D3DKMT_HANDLE openAdapterFromHdc(HDC hdc) + { + D3DKMT_OPENADAPTERFROMHDC openAdapterData = {}; + openAdapterData.hDc = hdc; + NTSTATUS result = D3DKMTOpenAdapterFromHdc(&openAdapterData); + if (FAILED(result)) + { + Compat::Log() << "Failed to open the primary display adapter: " << result; + return 0; + } + return openAdapterData.hAdapter; + } +} + +namespace D3dDdiHooks +{ + UINT getDdiVersion() + { + return g_ddiVersion; + } + + void installHooks() + { + D3DKMT_UMDFILENAMEINFO primaryUmd = getPrimaryUmdDriverName(); + g_umd = LoadLibraryW(primaryUmd.UmdFileName); + if (!g_umd) + { + Compat::Log() << "Failed to load the primary display driver library"; + } + + char umdFileName[MAX_PATH] = {}; + wcstombs_s(nullptr, umdFileName, primaryUmd.UmdFileName, _TRUNCATE); + Compat::hookFunction( + umdFileName, "OpenAdapter", &openAdapter); + } + + void uninstallHooks() + { + if (g_umd) + { + FreeLibrary(g_umd); + } + } +} diff --git a/DDrawCompat/D3dDdiHooks.h b/DDrawCompat/D3dDdiHooks.h new file mode 100644 index 0000000..d3cb7ac --- /dev/null +++ b/DDrawCompat/D3dDdiHooks.h @@ -0,0 +1,8 @@ +#pragma once + +namespace D3dDdiHooks +{ + UINT getDdiVersion(); + void installHooks(); + void uninstallHooks(); +} diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 359244c..43b78ba 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -148,6 +148,10 @@ + + + + @@ -172,6 +176,11 @@ + + + + + @@ -197,6 +206,10 @@ + + + + @@ -217,6 +230,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 37a3805..019d911 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -156,6 +156,33 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -257,6 +284,21 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + diff --git a/DDrawCompat/DDrawHooks.cpp b/DDrawCompat/DDrawHooks.cpp index bc5e2f7..70d662e 100644 --- a/DDrawCompat/DDrawHooks.cpp +++ b/DDrawCompat/DDrawHooks.cpp @@ -135,7 +135,7 @@ namespace DDPCAPS_1BIT, paletteEntries, &palette.getRef(), nullptr); if (SUCCEEDED(result)) { - CompatDirectDrawPalette::hookVtable(*palette); + CompatDirectDrawPalette::hookVtable(palette.get()->lpVtbl); } else { @@ -172,7 +172,7 @@ namespace template void hookVtable(const CompatPtr& intf) { - CompatInterface::hookVtable(*intf); + CompatInterface::hookVtable(intf.get()->lpVtbl); } } diff --git a/DDrawCompat/DllMain.cpp b/DDrawCompat/DllMain.cpp index 91c2310..4327783 100644 --- a/DDrawCompat/DllMain.cpp +++ b/DDrawCompat/DllMain.cpp @@ -10,6 +10,7 @@ #include "CompatGdi.h" #include "CompatHooks.h" #include "CompatRegistry.h" +#include "D3dDdiHooks.h" #include "DDrawHooks.h" #include "DDrawProcs.h" #include "Time.h" @@ -26,6 +27,8 @@ namespace static bool isAlreadyInstalled = false; if (!isAlreadyInstalled) { + Compat::Log() << "Installing Direct3D driver hooks"; + D3dDdiHooks::installHooks(); Compat::Log() << "Installing DirectDraw hooks"; DDrawHooks::installHooks(); Compat::Log() << "Installing GDI hooks"; @@ -133,6 +136,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/) { Compat::Log() << "Detaching DDrawCompat"; DDrawHooks::uninstallHooks(); + D3dDdiHooks::uninstallHooks(); CompatGdi::uninstallHooks(); Compat::unhookAllFunctions(); FreeLibrary(g_origDInputModule);