// Copyright 2011-2020 Molecular Matters GmbH, all rights reserved. #pragma once #if LC_VERSION == 1 #include "LC_WindowsInternals.h" // BEGIN EPIC MODS #include "LC_Logging.h" // END EPIC MODS namespace WindowsInternals { // Helper class that allows us to call any function in any Windows DLL, as long as it is exported and we know its signature. // Base template. template class Function {}; // Partial specialization for matching any function signature. template class Function { typedef R (NTAPI *PtrToFunction)(Args...); public: inline Function(const char* moduleName, const char* functionName); inline R operator()(Args... args) const; // BEGIN EPIC MODS inline R ExecNoResultCheck(Args... args) const; // END EPIC MODS // Helper for letting us check the result for arbitrary return types. // Base template. template inline void CheckResult(T) const {} // Explicit specialization for NTSTATUS return values. template <> inline void CheckResult(NTSTATUS result) const { if (!NT_SUCCESS(result)) { LC_ERROR_USER("Call to function %s in module %s failed. Error: 0x%X", m_functionName, m_moduleName, result); } } // BEGIN EPIC MODS private: // END EPIC MODS const char* m_moduleName; const char* m_functionName; PtrToFunction m_function; }; } template inline WindowsInternals::Function::Function(const char* moduleName, const char* functionName) : m_moduleName(moduleName) , m_functionName(functionName) , m_function(nullptr) { HMODULE module = ::GetModuleHandleA(moduleName); if (!module) { LC_ERROR_USER("Cannot get handle for module %s", moduleName); return; } m_function = reinterpret_cast(reinterpret_cast(::GetProcAddress(module, functionName))); if (!m_function) { LC_ERROR_USER("Cannot get address of function %s in module %s", functionName, moduleName); } } template inline R WindowsInternals::Function::operator()(Args... args) const { const R result = m_function(args...); CheckResult(result); return result; } // BEGIN EPIC MODS template inline R WindowsInternals::Function::ExecNoResultCheck(Args... args) const { const R result = m_function(args...); return result; } // BEGIN EPIC MODS // These are undocumented functions found in ntdll.dll. // We don't call them directly, but use them for "extracting" their signature using decltype. extern "C" WindowsInternals::NTSTATUS NtSuspendProcess(HANDLE ProcessHandle); extern "C" WindowsInternals::NTSTATUS NtResumeProcess(HANDLE ProcessHandle); extern "C" WindowsInternals::NTSTATUS NtReadVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, ULONG NumberOfBytesToRead, PULONG NumberOfBytesRead); extern "C" WindowsInternals::NTSTATUS NtWriteVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, ULONG NumberOfBytesToWrite, PULONG NumberOfBytesWritten); extern "C" WindowsInternals::NTSTATUS NtQuerySystemInformation(WindowsInternals::NT_SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); extern "C" WindowsInternals::NTSTATUS NtQueryInformationProcess(HANDLE ProcessHandle, WindowsInternals::NT_PROCESS_INFORMATION_CLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength); extern "C" WindowsInternals::NTSTATUS NtContinue(CONTEXT* ThreadContext, BOOLEAN RaiseAlert); // Cache important undocumented functions. namespace WindowsInternals { extern Function NtSuspendProcess; extern Function NtResumeProcess; extern Function NtReadVirtualMemory; extern Function NtWriteVirtualMemory; extern Function NtQuerySystemInformation; extern Function NtQueryInformationProcess; extern Function NtContinue; } #endif // LC_VERSION