Code:
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
/////// Name: Worms: Reloaded Windowed Loader b12395
/////// Description: Allows you to run the game in windowed mode flawlessly
/////// Author: *snip*
/////// Email: *snip*
/////// URL: http://forums.steampowered.com/forums/showthread.php?p=16796532
/////// License: GPLv3 (or later)
///////
/////// This program is free software: you can redistribute it and/or modify
/////// it under the terms of the GNU General Public License as published by
/////// the Free Software Foundation, either version 3 of the License, or
/////// (at your option) any later version.
///////
/////// This program is distributed in the hope that it will be useful,
/////// but WITHOUT ANY WARRANTY; without even the implied warranty of
/////// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/////// GNU General Public License for more details.
///////
/////// You should have received a copy of the GNU General Public License
/////// along with this program. If not, see <http://www.gnu.org/licenses/>.
///////
//////// Contributors (see changelog in readme.txt for exact details):
//////// Name: CyberShadow
//////// Email: vladimir@thecybershadow.net
//////// Website: http://thecybershadow.net/
//////// Profile: http://forums.steampowered.com/forums/member.php?u=595488
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// Dependencies
#pragma comment(lib,"advapi32")
#pragma comment(lib,"shell32")
#pragma comment(lib,"user32")
// Library inclusion
#include <direct.h>
#include <tchar.h>
#include <windows.h>
#include <tlhelp32.h>
// General project properties
const wchar_t gameName[] = _T("Worms: Reloaded");
const wchar_t gameExecutable[MAX_PATH] = _T("steam://rungameid/22600"); // The initial executable can sometimes differ from the actual game process
const wchar_t gameProcess[MAX_PATH] = _T("WormsReloaded.exe");
const char dllFileName[MAX_PATH] = "WormsReloadedWindowedDll.dll";
const unsigned int injectTimeout = 10000; // Amount of time in miliseconds before the loader will stop looking for the process to inject
// Retrieve process handle by its name
HANDLE GetProcessHandle(LPCTSTR szExeName);
// The function that injects the dynamic link library
bool DllInject(HANDLE hProcess, LPSTR lpszDllPath);
// Main entry point of the loader
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Open the game
ShellExecute(0, _T("open"), gameExecutable, 0, 0, SW_SHOWNORMAL);
// Look for the game process
HANDLE hProcess;
do
{
hProcess = GetProcessHandle(gameProcess);
Sleep(1);
}while(hProcess == 0);
// Obtain the full path of the dynamic link library to pass on
char location[MAX_PATH] = "";
_getcwd(location, MAX_PATH);
strcat_s(location, "\\");
strcat_s(location, dllFileName);
// Error message
wchar_t errorMessage[300] = _T("");
_tcscat_s(errorMessage, _T("Failed to inject the dynamic link library into "));
_tcscat_s(errorMessage, gameName);
_tcscat_s(errorMessage, _T(". Do you wish to start the game normally?"));
if(!DllInject(hProcess, location))
{
// Injection failure, stop the game and ask the user whether to run the game normally
TerminateProcess(hProcess, 0);
if(IDYES == MessageBox(0, errorMessage, _T("Loader Injection Failure"), MB_YESNO | MB_ICONERROR))
{
ShellExecute(0, _T("open"), gameExecutable, 0, 0, SW_SHOWNORMAL);
}
}
return 0;
}
// Injection process
bool DllInject(HANDLE hProcess, LPSTR lpszDllPath)
{
HMODULE hmKernel = GetModuleHandle(_T("kernel32"));
if(hmKernel == 0 || hProcess == 0)
{
// Unable to proceed with injection due to lack of necessary information
return false;
}
int nPathLength = strlen(lpszDllPath) + 1;
LPVOID lpvMemory = VirtualAllocEx(hProcess, 0, nPathLength, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, lpvMemory, lpszDllPath, nPathLength, 0);
DWORD dwWaitResult, dwExitResult = 0;
HANDLE hThread = CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(hmKernel, "LoadLibraryA"), lpvMemory, 0, 0);
if(hThread != 0)
{
dwWaitResult = WaitForSingleObject(hThread, injectTimeout);
GetExitCodeThread(hThread, &dwExitResult);
CloseHandle(hThread);
}
VirtualFreeEx(hProcess, lpvMemory, 0, MEM_RELEASE);
return ((dwWaitResult != WAIT_TIMEOUT) && (dwExitResult > 0));
}
// Retrieving the process handle
HANDLE GetProcessHandle(LPCTSTR szExeName)
{
PROCESSENTRY32 pEntry = { sizeof(PROCESSENTRY32) };
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
HANDLE hProcess = 0;
if(Process32First(hSnapshot, &pEntry))
{
do
{
if(!lstrcmp(pEntry.szExeFile, szExeName))
{
HANDLE hToken;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
{
LUID luidProcess;
if(LookupPrivilegeValue(0, SE_DEBUG_NAME, &luidProcess))
{
TOKEN_PRIVILEGES tpProcess;
tpProcess.PrivilegeCount = 1;
tpProcess.Privileges[0].Luid = luidProcess;
tpProcess.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(AdjustTokenPrivileges(hToken, FALSE, &tpProcess, sizeof(TOKEN_PRIVILEGES), 0, 0))
{
hProcess = OpenProcess(PROCESS_ALL_ACCESS, true, pEntry.th32ProcessID);
}
}
}
if(hProcess == 0)
{
DWORD dwError = GetLastError();
dwError = 0;
}
}
}while(Process32Next(hSnapshot, &pEntry));
}
return hProcess;
}
Code:
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
/////// Name: Worms: Reloaded Windowed Dll b12395
/////// Description: Allows you to run the game in windowed mode flawlessly
/////// Author: *snip*
/////// Email: *snip*
/////// URL: http://forums.steampowered.com/forums/showthread.php?p=16796532
/////// License: GPLv3 (or later)
///////
/////// This program is free software: you can redistribute it and/or modify
/////// it under the terms of the GNU General Public License as published by
/////// the Free Software Foundation, either version 3 of the License, or
/////// (at your option) any later version.
///////
/////// This program is distributed in the hope that it will be useful,
/////// but WITHOUT ANY WARRANTY; without even the implied warranty of
/////// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/////// GNU General Public License for more details.
///////
/////// You should have received a copy of the GNU General Public License
/////// along with this program. If not, see <http://www.gnu.org/licenses/>.
///////
//////// Contributors (see changelog in readme.txt for exact details):
//////// Name: CyberShadow
//////// Email: vladimir@thecybershadow.net
//////// Website: http://thecybershadow.net/
//////// Profile: http://forums.steampowered.com/forums/member.php?u=595488
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// Dependencies
#pragma comment(lib,"dwmapi")
#pragma comment(lib,"shell32")
#pragma comment(lib,"user32")
// Library inclusion
#include <dwmapi.h>
#include <tchar.h>
#include <windows.h>
// Definition of function that will hook the code
DWORD HookIt(const wchar_t *dllFile, const char *hookedAPI, void *redirectAPI, wchar_t *originalCodeBackup);
// Definintion of function that will check for keyboard input
DWORD WINAPI KeyboardCheckThread(LPVOID args);
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam );
// Definitions of functions that will be hooked
HWND WINAPI hkCreateWindowEx(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
long WINAPI hkChangeDisplaySettings(DEVMODE *lpDevMode, DWORD dwflags);
bool WINAPI hkCloseWindow(HWND hWnd);
// General project properties
const wchar_t targetFileName[MAX_PATH] = _T("WormsReloaded.exe"); // File name of target
// Addresses of the hook functions
DWORD dwCreateWindowExAddress = 0;
DWORD dwChangeDisplaySettingsAddress = 0;
DWORD dwCloseWindowAddress = 0;
// Original function addresses for restoration purposes
byte backupCreateWindowEx[6];
byte backupChangeDisplaySettings[6];
byte backupCloseWindow[6];
// Size properties of the game itself
int gameScreenWidth = 0;
int gameScreenHeight = 0;
// Takes care of hooking and unhooking the functions
bool WINAPI DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
DWORD dwKeyboardCheckThread;
HANDLE hKeyboardCheck = CreateThread(0, 0, KeyboardCheckThread, 0, 0, &dwKeyboardCheckThread);
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
dwCreateWindowExAddress = HookIt(_T("user32.dll"), "CreateWindowExW", hkCreateWindowEx, (_TUCHAR*)backupCreateWindowEx);
dwChangeDisplaySettingsAddress = HookIt(_T("user32.dll"), "ChangeDisplaySettingsW", hkChangeDisplaySettings, (_TUCHAR*)backupChangeDisplaySettings);
dwCloseWindowAddress = HookIt(_T("user32.dll"), "CloseWindow", hkCloseWindow, (_TUCHAR*)backupCloseWindow);
break;
case DLL_PROCESS_DETACH:
if(dwCreateWindowExAddress)
WriteProcessMemory((HANDLE) -1, (void*)dwCreateWindowExAddress, backupCreateWindowEx, 6, 0);
if(dwChangeDisplaySettingsAddress)
WriteProcessMemory((HANDLE) -1, (void*)dwChangeDisplaySettingsAddress, backupChangeDisplaySettings, 6, 0);
if(dwCloseWindowAddress)
WriteProcessMemory((HANDLE) -1, (void*)dwCloseWindowAddress, backupCloseWindow, 6, 0);
break;
}
return true;
}
// Hook the process and its modules by writing to the kernel memory area
DWORD HookIt(const wchar_t *dllFile, const char *hookedAPI, void *redirectAPI, wchar_t *originalCodeBackup)
{
DWORD dwAddress = (DWORD)GetProcAddress(GetModuleHandle(dllFile), hookedAPI); // Obtain the address of the API
BYTE jump[6] = {0xE9, 0x00, 0x00, 0x00, 0x00, 0xC3}; // 0xE9 = jump, 0x00, 0x00, 0x00, 0x00 = address, 0xC3 = return
ReadProcessMemory((HANDLE)-1, (void*)dwAddress, originalCodeBackup, 6, 0); // Obtain first six bytes of the API
DWORD dwJumpCalculation = ((DWORD)redirectAPI - dwAddress - 5); // Calculate the jump
memcpy(&jump[1], &dwJumpCalculation, 4); // Build the jump
WriteProcessMemory((HANDLE) -1, (void*)dwAddress, jump, 6, 0); // Overwrite first six bytes of the API with a jump to the hook function
return dwAddress; // Return the API address so restoring to the original address is possible
}
DWORD WINAPI KeyboardCheckThread(LPVOID args)
{
// Obtain application instance
HINSTANCE applicationInstance = GetModuleHandle(0);
// Global Windows hook to capture keyboard strokes
SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, applicationInstance, 0);
MSG message;
while(GetMessage(&message, 0, 0, 0) > 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return 0;
}
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam )
{
MessageBox(0, _T("Test"), _T("Test"), 0);
// Declare our pointer to the KBDLLHOOKSTRUCT
KBDLLHOOKSTRUCT *pKeyBoard = (KBDLLHOOKSTRUCT *)lParam;
switch( wParam )
{
case WM_KEYDOWN:
// When the key has been pressed and released
{
switch( pKeyBoard->vkCode )
// Check to see what key has been pushed
{
case VK_LWIN:
MessageBox(0, _T("test"), _T("test"), 0);
keybd_event(VK_LWIN, 0xb8, 0, 0);
keybd_event(VK_LWIN, 0x8f, KEYEVENTF_KEYUP, 0);
break;
case VK_RWIN:
keybd_event(VK_RWIN, 0xb8, 0, 0);
keybd_event(VK_RWIN, 0x8f, KEYEVENTF_KEYUP, 0);
break;
}
}
default:
return CallNextHookEx( NULL, nCode, wParam, lParam );
}
return 0;
}
// Window property definitions and creation of the window
HWND WINAPI hkCreateWindowEx(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
// Set game resolution height and width so the window size can be adjusted to it
nWidth = gameScreenWidth;
nHeight = gameScreenHeight;
// If the game resolution equals the desktop resolution it will create a borderless window
if(!(nWidth == GetSystemMetrics(SM_CXSCREEN) && nHeight == GetSystemMetrics(SM_CYSCREEN)))
{
// Window style properties
dwStyle = WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX) | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
// Ensure the game is fully displayed and nothing gets cut off
RECT windowSizeProperties;
windowSizeProperties.right = nWidth;
windowSizeProperties.bottom = nHeight;
AdjustWindowRect(&windowSizeProperties, WS_OVERLAPPEDWINDOW, FALSE);
// Included minor adjustment size values for perfect fitting
nWidth = windowSizeProperties.right - 2;
nHeight = windowSizeProperties.bottom + 20;
// Center the window when the game starts
x = (GetSystemMetrics(SM_CXSCREEN) / 2) - (nWidth / 2);
y = (GetSystemMetrics(SM_CYSCREEN) / 2) - (nHeight / 2);
}
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
// Unhook the API, create the new window and setup the hook again
WriteProcessMemory((HANDLE) -1, (void*)dwCreateWindowExAddress, backupCreateWindowEx, 6, 0);
HWND hWindow = CreateWindowExW(WS_EX_APPWINDOW | dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
dwCreateWindowExAddress = HookIt(L"user32.dll", "CreateWindowExW", hkCreateWindowEx, (_TUCHAR*)backupCreateWindowEx);
// Set the window icon
SendMessage(hWindow, WM_SETICON, ICON_BIG, (LPARAM)ExtractIcon(0, targetFileName, 0));
// Confine the cursor to the game as long as it has focus
RECT cursorArea;
GetWindowRect(GetForegroundWindow(), &cursorArea);
// Make the title bar inaccessible so it can't be accidently moved, minimized or closed while in-game
cursorArea.top += 25;
ClipCursor(&cursorArea);
// Make sure desktop composition does not get disabled
DwmEnableComposition(DWM_EC_ENABLECOMPOSITION);
return hWindow;
}
// Obtain the game resolution height and width
long WINAPI hkChangeDisplaySettings(DEVMODE *lpDevMode, DWORD dwflags)
{
DEVMODEW dmGameScreenSettings = *lpDevMode;
gameScreenWidth = dmGameScreenSettings.dmPelsWidth;
gameScreenHeight = dmGameScreenSettings.dmPelsHeight;
return 0;
}
// Ensures the window does not minimize when it loses focus
bool WINAPI hkCloseWindow(HWND hWnd)
{
return 0;
}