#include <iostream>
using namespace std;

#define WINAPI
using LPCSTR = const char*;
using BOOL = int;
using DWORD = unsigned int;
using LPVOID = void*;
constexpr BOOL TRUE = 1;
constexpr BOOL FALSE = 0;

BOOL WINAPI GetFileVersionInfo_dummy(LPCSTR, DWORD, DWORD, LPVOID) { return TRUE; }

void* WINAPI LoadLibraryA(LPCSTR) { return reinterpret_cast<void*>(1); }
void* WINAPI GetProcAddress(void*, LPCSTR) { return (void*) &GetFileVersionInfo_dummy; }

template <typename RetType, typename... ArgTypes>
struct proxyTraits
{
    using funcType = RetType (WINAPI *)(ArgTypes...);
    using proxyType = RetType (*)(ArgTypes...);
};

template <typename RetType, typename... ArgTypes>
auto proxyFunction(
	LPCSTR dllPath,
	LPCSTR functionName,
    RetType (*proxy)(ArgTypes...))
{
    using funcType = typename proxyTraits<RetType, ArgTypes...>::funcType;
    funcType funcPtr = (funcType) GetProcAddress(LoadLibraryA(dllPath), functionName);

    if (funcPtr)
        std::cout << "Proxy success" << std::endl;
    else
        std::cout << "Proxy fail" << std::endl;
    
    return funcPtr;
}

BOOL GetFileVersionInfoProxy(LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData)
{
    auto getFileVersion = proxyFunction("C:\\Windows\\System32\\Version.dll", "GetFileVersionInfoA", &GetFileVersionInfoProxy);
    if (getFileVersion)
        return getFileVersion(lptstrFilename, dwHandle, dwLen, lpData);

    return FALSE;
}

int main()
{
    GetFileVersionInfoProxy("filename", 0, 0, nullptr);
	return 0;
}