diff --git a/README.md b/README.md index 4c21cf5..868dd44 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # UnrealModUnlocker-Public 1.0.4 - ## General Information: UnrealModUnlocker Public and UnrealModUnlocker Basic are NOT from the same codebase. UnrealModUnlocker Public ONLY contains code for the loose file loading part of the UMU Project. diff --git a/plugin_example/ExampleModMenuLoader.dll b/plugin_example/ExampleModMenuLoader.dll new file mode 100644 index 0000000..2ab62e1 Binary files /dev/null and b/plugin_example/ExampleModMenuLoader.dll differ diff --git a/plugin_example/LoadThatModMenu.cpp b/plugin_example/LoadThatModMenu.cpp new file mode 100644 index 0000000..5827ffe --- /dev/null +++ b/plugin_example/LoadThatModMenu.cpp @@ -0,0 +1,43 @@ +#include +#include + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + static bool initialized = false; + + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + if (!initialized) + { + initialized = true; + + HANDLE hMutex = CreateMutexW(NULL, TRUE, L"PluginLoaderW"); + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + CloseHandle(hMutex); + return FALSE; + } + + Sleep(2000); + wchar_t dllPath[MAX_PATH]; + GetModuleFileNameW(hModule, dllPath, MAX_PATH); + + wcsrchr(dllPath, L'\\')[1] = L'\0'; + + wchar_t batchFilePath[MAX_PATH]; + wcscpy_s(batchFilePath, dllPath); + wcscat_s(batchFilePath, L"ModMenuExample.exe"); + + _wsystem((L"cmd.exe /C start \"\" \"" + std::wstring(batchFilePath) + L"\"").c_str()); + + CloseHandle(hMutex); + return FALSE; + } + break; + case DLL_PROCESS_DETACH: + return FALSE; + } + + return FALSE; +} diff --git a/plugin_example/ModMenuExample.zip b/plugin_example/ModMenuExample.zip new file mode 100644 index 0000000..f81f8a0 Binary files /dev/null and b/plugin_example/ModMenuExample.zip differ diff --git a/plugin_example/exe_example/ModMenuExample.exe b/plugin_example/exe_example/ModMenuExample.exe new file mode 100644 index 0000000..c973b88 Binary files /dev/null and b/plugin_example/exe_example/ModMenuExample.exe differ diff --git a/plugin_example/exe_example/ModMenuLoader.cpp b/plugin_example/exe_example/ModMenuLoader.cpp new file mode 100644 index 0000000..7b88d4c --- /dev/null +++ b/plugin_example/exe_example/ModMenuLoader.cpp @@ -0,0 +1,86 @@ +#include +#include + +extern "C" // Allows 'printf' without need for standard lib include +{ +int printf(const char *format, ...); +} + +bool TerminateSecondInstance(const wchar_t* processName) { + bool foundFirstInstance = false; + + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + + if (hSnapshot == INVALID_HANDLE_VALUE) { + return false; + } + + PROCESSENTRY32 pe32; + pe32.dwSize = sizeof(PROCESSENTRY32); + + if (Process32First(hSnapshot, &pe32)) { + do { + // Converts the process name to wide char string + wchar_t wProcessName[MAX_PATH]; + if (MultiByteToWideChar(CP_ACP, 0, pe32.szExeFile, -1, wProcessName, MAX_PATH) > 0) { + if (wcscmp(wProcessName, processName) == 0) { + if (foundFirstInstance) { + // Terminate the second instance + HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe32.th32ProcessID); + if (hProcess != nullptr) { + TerminateProcess(hProcess, 0); + CloseHandle(hProcess); + CloseHandle(hSnapshot); + return true; // Terminated the second instance (successful termanation) + } + } + foundFirstInstance = true; + } + } + } while (Process32Next(hSnapshot, &pe32)); + } + + CloseHandle(hSnapshot); + return false; // Second instance not found or couldn't be terminated +} + +bool IsProcessRunning(const wchar_t* gameName) { // Could be used in a continuous loop (check if game is opened.) + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + + if (hSnapshot == INVALID_HANDLE_VALUE) { + return false; + } + + PROCESSENTRY32 pe32; + pe32.dwSize = sizeof(PROCESSENTRY32); + + if (Process32First(hSnapshot, &pe32)) { + do { + // Convert pe32.szExeFile to a wchar_t* and then compare + wchar_t wideName[MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, pe32.szExeFile, -1, wideName, MAX_PATH); + + if (wcscmp(wideName, gameName) == 0) { + CloseHandle(hSnapshot); + return true; + } + } while (Process32Next(hSnapshot, &pe32)); + } + + CloseHandle(hSnapshot); + return false; +} + +int main() { + const wchar_t* processName = L"PluginLoader.exe"; // Defines Executable ModMenu/Plugin Name + const wchar_t* gameName = L"ISZ-Win64-Shipping.exe"; // Obv. can be changed to specific Game Name + TerminateSecondInstance(processName); + Sleep(100); + if (IsProcessRunning(processName)) { + MessageBoxW(NULL, L"The ModMenu/Plugin/Cheat was Loaded Successfully.", L"Cracko298's Super Secret ModMenu", MB_OK | MB_ICONINFORMATION); // Passes check, opens Message Diag + } + else { + MessageBoxW(NULL, L"The ModMenu/Plugin/Cheat was **NOT** Loaded (Game Not Present).", L"Cracko298's Super Sad ModMenu", MB_OK | MB_ICONINFORMATION); // Does NOT pass check, opens Message Diag error + } + return 0; +}