diff --git a/.gitignore b/.gitignore
index d4fb281..b92f67a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,11 @@
+x64/
+powrprof/
+.vscode/
+.vs/
+
+*.vcxproj.filters
+*.vcxproj.user
+
# Prerequisites
*.d
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..ad2be12
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,19 @@
+# SWEaW Hooks
+
+## Project Overview
+
+This project is a hook API for Star Wars: Empire at War: Forces of Corruption to expose custom Lua functions available for scripting.
+
+## Client and Debug Kits
+
+- StarWarsG.exe -- the binary shipped with the game for all clients. PDB unavailable.
+- StarWarsI.exe -- the debug kit binary which comes with debug functionality but is too slow to run normally. PDB available.
+
+## DLL Hook
+
+- Uses MinHook to create the DLL hook into the game via powerprof.dll
+- Using IDA Free to find addresses of function calls.
+
+## Empire at War Lua Scripting Engine
+
+The source code for the Lua scripting engine in Empire at War was leaked at: https://github.com/PetroglyphGames/GlyphX-Reference. Use this as a guide for what Lua functions and variables are already available, and how the engine hooks Lua scripting into the rest of the game. No other engine source code is available.
\ No newline at end of file
diff --git a/README.md b/README.md
index 8873b1a..b41b7fd 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,12 @@
-# SWEAW Hooks
\ No newline at end of file
+# SWEaW Hooks
+
+A powrprof.dll hook which adds custom Lua functions to Forces of Corruption.
+
+## Usage
+
+Drop powrprof.dll and MinHooks.x64.dll into the `/corruption/` folder of your Empire at War installation.
+Currently only works with the debug kit `StarWarsI.exe`; `StarWarsG.exe` support is coming soon.
+
+## Functions
+
+- Global `WriteToFile(str a, str b)` - Appends a line of text `b` to the file name `a` in the game directory.
\ No newline at end of file
diff --git a/SWEAW Hooks.sln b/SWEAW Hooks.sln
new file mode 100644
index 0000000..56a994c
--- /dev/null
+++ b/SWEAW Hooks.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36127.28 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SWEAW Hooks", "SWEAW Hooks.vcxproj", "{F2C4477F-C9F1-4AF0-A04C-9D6ADD14E783}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F2C4477F-C9F1-4AF0-A04C-9D6ADD14E783}.Debug|x64.ActiveCfg = Debug|x64
+ {F2C4477F-C9F1-4AF0-A04C-9D6ADD14E783}.Debug|x64.Build.0 = Debug|x64
+ {F2C4477F-C9F1-4AF0-A04C-9D6ADD14E783}.Debug|x86.ActiveCfg = Debug|Win32
+ {F2C4477F-C9F1-4AF0-A04C-9D6ADD14E783}.Debug|x86.Build.0 = Debug|Win32
+ {F2C4477F-C9F1-4AF0-A04C-9D6ADD14E783}.Release|x64.ActiveCfg = Release|x64
+ {F2C4477F-C9F1-4AF0-A04C-9D6ADD14E783}.Release|x64.Build.0 = Release|x64
+ {F2C4477F-C9F1-4AF0-A04C-9D6ADD14E783}.Release|x86.ActiveCfg = Release|Win32
+ {F2C4477F-C9F1-4AF0-A04C-9D6ADD14E783}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {A512788C-5D26-42E2-BCB7-1459395B6B39}
+ EndGlobalSection
+EndGlobal
diff --git a/SWEAW Hooks.vcxproj b/SWEAW Hooks.vcxproj
new file mode 100644
index 0000000..144e66e
--- /dev/null
+++ b/SWEAW Hooks.vcxproj
@@ -0,0 +1,165 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 17.0
+ Win32Proj
+ {f2c4477f-c9f1-4af0-a04c-9d6add14e783}
+ SWEAWHooks
+ 10.0
+ powrprof
+
+
+
+ DynamicLibrary
+ true
+ v145
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v145
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ v145
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v145
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;$(IncludePath)
+ C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\ucrt\x64;$(LibraryPath)
+
+
+ C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;$(IncludePath)
+ C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\ucrt\x64;$(LibraryPath)
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;SWEAWHOOKS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;SWEAWHOOKS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ _DEBUG;SWEAWHOOKS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ NotUsing
+ pch.h
+
+
+ Windows
+ true
+ false
+ minhook\bin\;%(AdditionalLibraryDirectories)
+ powrprof.def
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;SWEAWHOOKS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ NotUsing
+ pch.h
+
+
+ Windows
+ true
+ false
+ minhook\bin\;%(AdditionalLibraryDirectories)
+ powrprof.def
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dllmain.cpp b/dllmain.cpp
new file mode 100644
index 0000000..2af5a1a
--- /dev/null
+++ b/dllmain.cpp
@@ -0,0 +1,26 @@
+#include "proxy.h"
+#include "lua_hook.h"
+#include
+
+BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) {
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hinstDll);
+
+ if (!Proxy_Init()) {
+ return FALSE;
+ }
+
+ if (!LuaHook_Init()) {
+ OutputDebugStringA("[SWEAW Hooks] WARNING: LuaHook_Init() failed - Lua hooks are not active.\n");
+ }
+ break;
+
+ case DLL_PROCESS_DETACH:
+ LuaHook_Shutdown();
+ Proxy_Shutdown();
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/lua_hook.cpp b/lua_hook.cpp
new file mode 100644
index 0000000..3e41295
--- /dev/null
+++ b/lua_hook.cpp
@@ -0,0 +1,116 @@
+#include "lua_hook.h"
+#include "minhook/include/MinHook.h"
+#include
+
+#if defined _M_X64
+#pragma comment(lib, "MinHook.x64.lib")
+#elif defined _M_IX86
+#pragma comment(lib, "MinHook.x86.lib")
+#endif
+
+// Opaque Lua state - never dereferenced, just passed around
+struct lua_State;
+typedef int (*lua_CFunction)(lua_State*);
+
+// Function pointer types
+typedef lua_State* (*fn_lua_open)();
+typedef void (*fn_lua_pushstring)(lua_State*, const char*);
+typedef void (*fn_lua_pushcclosure)(lua_State*, lua_CFunction, int);
+typedef void (*fn_lua_settable)(lua_State*, int);
+typedef const char* (*fn_lua_tostring)(lua_State*, int);
+
+// Resolved function pointers
+static fn_lua_open real_lua_open = nullptr;
+static fn_lua_pushstring pfn_pushstring = nullptr;
+static fn_lua_pushcclosure pfn_pushcclosure = nullptr;
+static fn_lua_settable pfn_settable = nullptr;
+static fn_lua_tostring pfn_tostring = nullptr;
+
+// Helper, equivalent of lua_setglobal
+static void register_global(lua_State* L, const char* name, lua_CFunction fn) {
+ pfn_pushstring(L, name);
+ pfn_pushcclosure(L, fn, 0);
+ pfn_settable(L, LUA_GLOBALSINDEX);
+}
+
+// =========================
+// Custom Lua file functions
+// =========================
+
+// WriteToFile(path, text) - appends text to a file
+static int L_WriteToFile(lua_State* L) {
+ const char* path = pfn_tostring(L, 1);
+ const char* text = pfn_tostring(L, 2);
+
+ if (!path || !text) {
+ return 0;
+ }
+
+ HANDLE hFile = CreateFileA(
+ path,
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile != INVALID_HANDLE_VALUE) {
+ DWORD written;
+
+ SetFilePointer(hFile, 0, NULL, FILE_END);
+ WriteFile(hFile, text, lstrlenA(text), &written, NULL);
+ WriteFile(hFile, "\n", 1, &written, NULL);
+ CloseHandle(hFile);
+ }
+
+ return 0;
+}
+
+// =========================
+// Hooks
+// =========================
+
+// Fired every time the game creates a new Lua state
+static lua_State* Hook_lua_open() {
+ lua_State* L = real_lua_open();
+
+ if (!L) {
+ return L;
+ }
+
+ // Register custom Lua functions
+ register_global(L, "WriteToFile", L_WriteToFile);
+
+ return L;
+}
+
+bool LuaHook_Init() {
+ uintptr_t base = (uintptr_t)GetModuleHandleA(nullptr);
+
+ pfn_pushstring = (fn_lua_pushstring)(base + RVA_lua_pushstring);
+ pfn_pushcclosure = (fn_lua_pushcclosure)(base + RVA_lua_pushcclosure);
+ pfn_settable = (fn_lua_settable)(base + RVA_lua_settable);
+ pfn_tostring = (fn_lua_tostring)(base + RVA_lua_tostring);
+
+ void* const target = (void*)(base + RVA_lua_open);
+
+ if (MH_Initialize() != MH_OK) {
+ return false;
+ }
+
+ if (MH_CreateHook(target, &Hook_lua_open, (void**)&real_lua_open) != MH_OK) {
+ return false;
+ }
+
+ if (MH_EnableHook(target) != MH_OK) {
+ return false;
+ }
+
+ return true;
+}
+
+void LuaHook_Shutdown() {
+ MH_DisableHook(MH_ALL_HOOKS);
+ MH_Uninitialize();
+}
\ No newline at end of file
diff --git a/lua_hook.h b/lua_hook.h
new file mode 100644
index 0000000..7628a6c
--- /dev/null
+++ b/lua_hook.h
@@ -0,0 +1,13 @@
+#pragma once
+#include
+
+constexpr uintptr_t RVA_lua_open = 0x12AB790;
+constexpr uintptr_t RVA_lua_pushstring = 0x12AC930;
+constexpr uintptr_t RVA_lua_pushcclosure = 0x12AC6E0;
+constexpr uintptr_t RVA_lua_settable = 0x12AD020;
+constexpr uintptr_t RVA_lua_tostring = 0x12AD430;
+
+constexpr int LUA_GLOBALSINDEX = -10001;
+
+bool LuaHook_Init();
+void LuaHook_Shutdown();
\ No newline at end of file
diff --git a/minhook/bin/MinHook.x64.exp b/minhook/bin/MinHook.x64.exp
new file mode 100644
index 0000000..ad66dd6
Binary files /dev/null and b/minhook/bin/MinHook.x64.exp differ
diff --git a/minhook/bin/MinHook.x86.exp b/minhook/bin/MinHook.x86.exp
new file mode 100644
index 0000000..20ed634
Binary files /dev/null and b/minhook/bin/MinHook.x86.exp differ
diff --git a/minhook/include/MinHook.h b/minhook/include/MinHook.h
new file mode 100644
index 0000000..492d83f
--- /dev/null
+++ b/minhook/include/MinHook.h
@@ -0,0 +1,185 @@
+/*
+ * MinHook - The Minimalistic API Hooking Library for x64/x86
+ * Copyright (C) 2009-2017 Tsuda Kageyu.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__)
+ #error MinHook supports only x86 and x64 systems.
+#endif
+
+#include
+
+// MinHook Error Codes.
+typedef enum MH_STATUS
+{
+ // Unknown error. Should not be returned.
+ MH_UNKNOWN = -1,
+
+ // Successful.
+ MH_OK = 0,
+
+ // MinHook is already initialized.
+ MH_ERROR_ALREADY_INITIALIZED,
+
+ // MinHook is not initialized yet, or already uninitialized.
+ MH_ERROR_NOT_INITIALIZED,
+
+ // The hook for the specified target function is already created.
+ MH_ERROR_ALREADY_CREATED,
+
+ // The hook for the specified target function is not created yet.
+ MH_ERROR_NOT_CREATED,
+
+ // The hook for the specified target function is already enabled.
+ MH_ERROR_ENABLED,
+
+ // The hook for the specified target function is not enabled yet, or already
+ // disabled.
+ MH_ERROR_DISABLED,
+
+ // The specified pointer is invalid. It points the address of non-allocated
+ // and/or non-executable region.
+ MH_ERROR_NOT_EXECUTABLE,
+
+ // The specified target function cannot be hooked.
+ MH_ERROR_UNSUPPORTED_FUNCTION,
+
+ // Failed to allocate memory.
+ MH_ERROR_MEMORY_ALLOC,
+
+ // Failed to change the memory protection.
+ MH_ERROR_MEMORY_PROTECT,
+
+ // The specified module is not loaded.
+ MH_ERROR_MODULE_NOT_FOUND,
+
+ // The specified function is not found.
+ MH_ERROR_FUNCTION_NOT_FOUND
+}
+MH_STATUS;
+
+// Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
+// MH_QueueEnableHook or MH_QueueDisableHook.
+#define MH_ALL_HOOKS NULL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ // Initialize the MinHook library. You must call this function EXACTLY ONCE
+ // at the beginning of your program.
+ MH_STATUS WINAPI MH_Initialize(VOID);
+
+ // Uninitialize the MinHook library. You must call this function EXACTLY
+ // ONCE at the end of your program.
+ MH_STATUS WINAPI MH_Uninitialize(VOID);
+
+ // Creates a hook for the specified target function, in disabled state.
+ // Parameters:
+ // pTarget [in] A pointer to the target function, which will be
+ // overridden by the detour function.
+ // pDetour [in] A pointer to the detour function, which will override
+ // the target function.
+ // ppOriginal [out] A pointer to the trampoline function, which will be
+ // used to call the original target function.
+ // This parameter can be NULL.
+ MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal);
+
+ // Creates a hook for the specified API function, in disabled state.
+ // Parameters:
+ // pszModule [in] A pointer to the loaded module name which contains the
+ // target function.
+ // pszProcName [in] A pointer to the target function name, which will be
+ // overridden by the detour function.
+ // pDetour [in] A pointer to the detour function, which will override
+ // the target function.
+ // ppOriginal [out] A pointer to the trampoline function, which will be
+ // used to call the original target function.
+ // This parameter can be NULL.
+ MH_STATUS WINAPI MH_CreateHookApi(
+ LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal);
+
+ // Creates a hook for the specified API function, in disabled state.
+ // Parameters:
+ // pszModule [in] A pointer to the loaded module name which contains the
+ // target function.
+ // pszProcName [in] A pointer to the target function name, which will be
+ // overridden by the detour function.
+ // pDetour [in] A pointer to the detour function, which will override
+ // the target function.
+ // ppOriginal [out] A pointer to the trampoline function, which will be
+ // used to call the original target function.
+ // This parameter can be NULL.
+ // ppTarget [out] A pointer to the target function, which will be used
+ // with other functions.
+ // This parameter can be NULL.
+ MH_STATUS WINAPI MH_CreateHookApiEx(
+ LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget);
+
+ // Removes an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
+
+ // Enables an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // enabled in one go.
+ MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
+
+ // Disables an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // disabled in one go.
+ MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
+
+ // Queues to enable an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // queued to be enabled.
+ MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
+
+ // Queues to disable an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // queued to be disabled.
+ MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
+
+ // Applies all queued changes in one go.
+ MH_STATUS WINAPI MH_ApplyQueued(VOID);
+
+ // Translates the MH_STATUS to its name as a string.
+ const char * WINAPI MH_StatusToString(MH_STATUS status);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/powrprof.def b/powrprof.def
new file mode 100644
index 0000000..8ea05c6
--- /dev/null
+++ b/powrprof.def
@@ -0,0 +1,8 @@
+LIBRARY powrprof
+EXPORTS
+ CallNtPowerInformation
+ PowerReadACValueIndex
+ PowerReadDCValueIndex
+ PowerGetActiveScheme
+ PowerSettingRegisterNotification
+ PowerSettingUnregisterNotification
diff --git a/proxy.cpp b/proxy.cpp
new file mode 100644
index 0000000..2b490ef
--- /dev/null
+++ b/proxy.cpp
@@ -0,0 +1,100 @@
+#include "proxy.h"
+
+HMODULE g_hRealPowrprof = nullptr;
+
+// NTSTATUS = LONG, POWER_INFORMATION_LEVEL = int; using primitive types
+// avoids pulling in powerbase.h / ntstatus.h for a simple passthrough.
+typedef LONG (WINAPI* fn_CallNtPowerInformation)(int, PVOID, ULONG, PVOID, ULONG);
+typedef DWORD (WINAPI* fn_PowerReadACValueIndex)(HKEY, const GUID*, const GUID*, const GUID*, LPDWORD);
+typedef DWORD (WINAPI* fn_PowerGetActiveScheme)(HKEY, GUID**);
+typedef DWORD (WINAPI* fn_PowerSettingRegisterNotification)(LPCGUID, DWORD, HANDLE, HANDLE*);
+typedef DWORD (WINAPI* fn_PowerSettingUnregisterNotification)(HANDLE);
+
+static fn_CallNtPowerInformation real_CallNtPowerInformation = nullptr;
+static fn_PowerReadACValueIndex real_PowerReadACValueIndex = nullptr;
+static fn_PowerReadACValueIndex real_PowerReadDCValueIndex = nullptr;
+static fn_PowerGetActiveScheme real_PowerGetActiveScheme = nullptr;
+static fn_PowerSettingRegisterNotification real_PowerSettingRegisterNotification = nullptr;
+static fn_PowerSettingUnregisterNotification real_PowerSettingUnregisterNotification = nullptr;
+
+bool Proxy_Init() {
+ char path[MAX_PATH];
+
+ GetSystemDirectoryA(path, MAX_PATH);
+ lstrcatA(path, "\\powrprof.dll");
+ g_hRealPowrprof = LoadLibraryA(path);
+
+ if (!g_hRealPowrprof) {
+ return false;
+ }
+
+ real_CallNtPowerInformation = (fn_CallNtPowerInformation)
+ GetProcAddress(g_hRealPowrprof, "CallNtPowerInformation");
+ real_PowerReadACValueIndex = (fn_PowerReadACValueIndex)
+ GetProcAddress(g_hRealPowrprof, "PowerReadACValueIndex");
+ real_PowerReadDCValueIndex = (fn_PowerReadACValueIndex)
+ GetProcAddress(g_hRealPowrprof, "PowerReadDCValueIndex");
+ real_PowerGetActiveScheme = (fn_PowerGetActiveScheme)
+ GetProcAddress(g_hRealPowrprof, "PowerGetActiveScheme");
+ real_PowerSettingRegisterNotification = (fn_PowerSettingRegisterNotification)
+ GetProcAddress(g_hRealPowrprof, "PowerSettingRegisterNotification");
+ real_PowerSettingUnregisterNotification = (fn_PowerSettingUnregisterNotification)
+ GetProcAddress(g_hRealPowrprof, "PowerSettingUnregisterNotification");
+
+ return real_CallNtPowerInformation != nullptr;
+}
+
+void Proxy_Shutdown() {
+ if (g_hRealPowrprof) {
+ FreeLibrary(g_hRealPowrprof);
+ g_hRealPowrprof = nullptr;
+ }
+}
+
+extern "C" {
+ __declspec(dllexport) LONG WINAPI CallNtPowerInformation(
+ int level, PVOID inBuf, ULONG inSize, PVOID outBuf, ULONG outSize)
+ {
+ return real_CallNtPowerInformation(level, inBuf, inSize, outBuf, outSize);
+ }
+
+ __declspec(dllexport) DWORD WINAPI PowerReadACValueIndex(
+ HKEY rootKey, const GUID* scheme, const GUID* subgroup, const GUID* setting, LPDWORD index)
+ {
+ if (real_PowerReadACValueIndex)
+ return real_PowerReadACValueIndex(rootKey, scheme, subgroup, setting, index);
+ return ERROR_NOT_SUPPORTED;
+ }
+
+ __declspec(dllexport) DWORD WINAPI PowerReadDCValueIndex(
+ HKEY rootKey, const GUID* scheme, const GUID* subgroup, const GUID* setting, LPDWORD index)
+ {
+ if (real_PowerReadDCValueIndex)
+ return real_PowerReadDCValueIndex(rootKey, scheme, subgroup, setting, index);
+ return ERROR_NOT_SUPPORTED;
+ }
+
+ __declspec(dllexport) DWORD WINAPI PowerGetActiveScheme(
+ HKEY userRootPowerKey, GUID** activePolicyGuid)
+ {
+ if (real_PowerGetActiveScheme)
+ return real_PowerGetActiveScheme(userRootPowerKey, activePolicyGuid);
+ return ERROR_NOT_SUPPORTED;
+ }
+
+ __declspec(dllexport) DWORD WINAPI PowerSettingRegisterNotification(
+ LPCGUID settingGuid, DWORD flags, HANDLE recipient, HANDLE* registrationHandle)
+ {
+ if (real_PowerSettingRegisterNotification)
+ return real_PowerSettingRegisterNotification(settingGuid, flags, recipient, registrationHandle);
+ return ERROR_NOT_SUPPORTED;
+ }
+
+ __declspec(dllexport) DWORD WINAPI PowerSettingUnregisterNotification(
+ HANDLE registrationHandle)
+ {
+ if (real_PowerSettingUnregisterNotification)
+ return real_PowerSettingUnregisterNotification(registrationHandle);
+ return ERROR_NOT_SUPPORTED;
+ }
+}
diff --git a/proxy.h b/proxy.h
new file mode 100644
index 0000000..f733844
--- /dev/null
+++ b/proxy.h
@@ -0,0 +1,7 @@
+#pragma once
+#define WIN32_LEAN_AND_MEAN
+#include
+
+extern HMODULE g_hRealPowrprof;
+bool Proxy_Init();
+void Proxy_Shutdown();
\ No newline at end of file