diff --git a/IOSync/Info.props b/IOSync/Info.props index f8b55f2..8b492b7 100644 --- a/IOSync/Info.props +++ b/IOSync/Info.props @@ -2,7 +2,7 @@ - 1.0.0 + 1.0.1 diff --git a/IOSync/src/application/application.h b/IOSync/src/application/application.h index 182b150..89419d7 100644 --- a/IOSync/src/application/application.h +++ b/IOSync/src/application/application.h @@ -137,6 +137,52 @@ namespace iosync } #ifdef PLATFORM_WINDOWS + static inline bool __winnt__startProcess(LPCTSTR applicationName, const string& commandLine=string(), DWORD flags=CREATE_NO_WINDOW) + { + // Local variable(s): + STARTUPINFO si; + PROCESS_INFORMATION pi; + + // Set the size of the structures: + ZeroMemory(&si, sizeof(si)); + ZeroMemory(&pi, sizeof(pi)); + + si.cb = sizeof(si); + + CHAR cmd[MAX_PATH]; + + memcpy(cmd, commandLine.c_str(), min(commandLine.size(), MAX_PATH)); + cmd[commandLine.length()] = '\0'; + + // Start the specified program: + if + ( + CreateProcess + ( + applicationName, + (LPSTR)cmd, + NULL, + NULL, + FALSE, + flags, + NULL, + NULL, + &si, + &pi + ) == FALSE + ) + { + return false; + } + + // Close the process and thread handles: + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + // Return the default response. + return true; + } + // This command will inject the library specified into the process with the PID specified by 'processID'. // The return-value of this command indicates if injection was successful. static inline bool __winnt__injectLibrary(string library, DWORD processID) @@ -158,6 +204,7 @@ namespace iosync //cout << "Directory: " << buffer << endl; SIZE_T strLength = (SIZE_T)strlen(buffer); + //buffer[strLength] = '\0'; // Open the remote process with specific rights. remoteProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID); @@ -169,24 +216,24 @@ namespace iosync LoadLibraryAddr = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); // Allocate a buffer using the remote process. - remoteLibraryName = (LPVOID)VirtualAllocEx(remoteProc, NULL, strLength, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + remoteLibraryName = (LPVOID)VirtualAllocEx(remoteProc, NULL, strLength, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); // strLength+1 // Write the 'library' string to the newly allocated portion of memory. - BOOL test = WriteProcessMemory(remoteProc, remoteLibraryName, buffer, strLength, NULL); // library.c_str() + BOOL test = WriteProcessMemory(remoteProc, remoteLibraryName, buffer, strLength, NULL); // strLength+1 // Create a remote thread that will immediately load the library specified into the remote process. HANDLE h = CreateRemoteThread(remoteProc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryAddr, remoteLibraryName, NULL, NULL); - // Close the handle to the remote process. - CloseHandle(remoteProc); - // Close our local handle to the remote thread. CloseHandle(h); + // Close the handle to the remote process. + CloseHandle(remoteProc); + // Free the memory we allocated. VirtualFreeEx(remoteProc, remoteLibraryName, 0, MEM_RELEASE | MEM_DECOMMIT); - delete buffer; + delete[] buffer; // Return the default response. return true; diff --git a/IOSync/src/devices/gamepad.cpp b/IOSync/src/devices/gamepad.cpp index 369780c..d640f34 100644 --- a/IOSync/src/devices/gamepad.cpp +++ b/IOSync/src/devices/gamepad.cpp @@ -120,6 +120,15 @@ namespace iosync #ifdef PLATFORM_WINDOWS bool gamepad::__winnt__injectLibrary(DWORD processID, CPUArchitecture process_Architecture) { + // Nested functions/lambdas: + auto injectionStr = [&]() -> string + { + stringstream injectionStream; + injectionStream << "IGNORE " << XINPUT_INJECTION_ARGUMENT << " " << processID; + + return injectionStream.str(); + }; + if (processID == 0) return false; @@ -127,9 +136,17 @@ namespace iosync { #if defined(PLATFORM_X86) || defined(PLATFORM_X64) case x86: - return application::__winnt__injectLibrary(INJECTION_DLL_NAME_X86, processID); + #if defined(PLATFORM_X86) + return application::__winnt__injectLibrary(INJECTION_DLL_NAME_X86, processID); + #else + return application::__winnt__startProcess(TEXT("IOSync_x86.exe"), injectionStr()); + #endif case x64: - return application::__winnt__injectLibrary(INJECTION_DLL_NAME_X64, processID); + #if defined(PLATFORM_X64) + return application::__winnt__injectLibrary(INJECTION_DLL_NAME_X64, processID); + #else + return application::__winnt__startProcess(TEXT("IOSync_x64.exe"), injectionStr()); + #endif #elif defined(PLATFORM_ARM) || defined(PLATFORM_ARM64) case ARM: return application::__winnt__injectLibrary(INJECTION_DLL_NAME_ARM, processID); diff --git a/IOSync/src/devices/gamepad.h b/IOSync/src/devices/gamepad.h index 3cb81cd..e600bed 100644 --- a/IOSync/src/devices/gamepad.h +++ b/IOSync/src/devices/gamepad.h @@ -112,6 +112,9 @@ namespace iosync static const size_t serializedNativeGamepadSize = sizeof(nativeGamepad); // sizeof(nativeGamepad); #ifdef PLATFORM_WINDOWS + const string XINPUT_INJECTION_ARGUMENT = "XI_INJECT"; + const wstring XINPUT_INJECTION_ARGUMENTW = L"XI_INJECT"; + static LPCTSTR SHARED_GAMEPAD_MEMORY_NAME = "IOSYNC_GAMEPAD_BUFFER"; static const size_t SHARED_SIZEOF_PLUGGED_IN_SEGMENT = (sizeof(bool)*MAX_GAMEPADS); diff --git a/IOSync/src/devices/native/winnt/Real_XInput_Wrapper.cpp b/IOSync/src/devices/native/winnt/Real_XInput_Wrapper.cpp index ae7b267..4318776 100644 --- a/IOSync/src/devices/native/winnt/Real_XInput_Wrapper.cpp +++ b/IOSync/src/devices/native/winnt/Real_XInput_Wrapper.cpp @@ -1,7 +1,12 @@ // Preprocessor related: + //#define WIN32_LEAN_AND_MEAN #define _CRT_SECURE_NO_WARNINGS +// This enables console-output when injected XInput commands are executed (Virtual or real). +// This also applies to IOSync's general XInput support. +//#define DEBUG_XINPUT_CALLS + // Includes: // The main interface-header. @@ -11,12 +16,15 @@ #include #include "Real_XInput_Wrapper.h" -#include "../../../native/winnt/processManagement.h" // Standard library: #include //#include +//#ifdef DEBUG_XINPUT_CALLS +#include +//#endif + // Namespace(s): namespace REAL_XINPUT { @@ -39,9 +47,39 @@ namespace REAL_XINPUT _XInputGetAudioDeviceIds_t _XInputGetAudioDeviceIds; _XInputGetStateEx_t _XInputGetStateEx; + // Global variable(s): + jumpMap jumpStates; + // Functions: // Meta: + process::jumpSegment mapRemoteFunction(LPCSTR name, LPCVOID function, HMODULE hDLL) + { + using namespace process; + + #ifdef PROCESS_MANAGER_DEBUG + cout << "{XINPUT}: Attempting to map '" << function << "' to: '" << name << "'" << endl; + #endif + + auto remoteFunction = getRemoteFunction(name, hDLL); + + if (remoteFunction == NULL) + { + #ifdef PROCESS_MANAGER_DEBUG + cout << "Mapping failed; unable to find remote function." + #endif + + // For now, do nothing. + return jumpSegment(); + } + + auto response = writeJump(remoteFunction, function); + + jumpStates[remoteFunction] = response; + + return response; + } + VOID linkTo(HMODULE hDLL) { using namespace process; @@ -130,8 +168,30 @@ namespace REAL_XINPUT // Wrapper / "shim": VOID WINAPI XInputEnable(BOOL enable) { + #ifdef DEBUG_XINPUT_CALLS + cout << "XInputEnable(" << enable << ")" << endl; + #endif + if (_XInputEnable != nullptr) - { + { + if (shouldFixJumps()) + { + auto entryIterator = jumpStates.find((LPVOID)_XInputEnable); + + if (entryIterator != jumpStates.end()) + { + jumpEntry entry = *entryIterator; + + swapJumps(entry); + + _XInputEnable(enable); + + swapJumps(entry); + + return; + } + } + _XInputEnable(enable); return; @@ -142,8 +202,30 @@ namespace REAL_XINPUT DWORD WINAPI XInputSetState(DWORD dwUserIndex, PXINPUT_VIBRATION pVibration) { + #ifdef DEBUG_XINPUT_CALLS + cout << "XInputSetState(" << dwUserIndex << ", " << pVibration << ")" << endl; + #endif + if (_XInputSetState != nullptr) { + if (shouldFixJumps()) + { + auto entryIterator = jumpStates.find((LPVOID)_XInputSetState); + + if (entryIterator != jumpStates.end()) + { + jumpEntry entry = *entryIterator; + + swapJumps(entry); + + auto response = _XInputSetState(dwUserIndex, pVibration); + + swapJumps(entry); + + return response; + } + } + return _XInputSetState(dwUserIndex, pVibration); } @@ -152,8 +234,39 @@ namespace REAL_XINPUT DWORD WINAPI XInputGetState(DWORD dwUserIndex, PXINPUT_STATE pState) { + #ifdef DEBUG_XINPUT_CALLS + cout << "XInputGetState(" << dwUserIndex << ", " << pState << ")" << endl; + cout << "_XInputGetState: " << _XInputGetState << endl; + #endif + if (_XInputGetState != nullptr) { + if (shouldFixJumps()) + { + #ifdef DEBUG_XINPUT_CALLS + cout << "Jump fixing..." << endl; + #endif + + auto entryIterator = jumpStates.find((LPVOID)_XInputGetState); + + if (entryIterator != jumpStates.end()) + { + #ifdef DEBUG_XINPUT_CALLS + cout << "__XInputGetState? - " << entryIterator->first << endl; + #endif + + jumpEntry entry = *entryIterator; + + swapJumps(entry); + + auto response = _XInputGetState(dwUserIndex, pState); + + swapJumps(entry); + + return response; + } + } + return _XInputGetState(dwUserIndex, pState); } @@ -162,10 +275,30 @@ namespace REAL_XINPUT DWORD WINAPI XInputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags, PXINPUT_CAPABILITIES pCapabilities) { - using namespace std; + #ifdef DEBUG_XINPUT_CALLS + cout << "XInputGetCapabilities(" << dwUserIndex << ", " << dwFlags << ", " << pCapabilities << ")" << endl; + #endif if (_XInputGetCapabilities != nullptr) { + if (shouldFixJumps()) + { + auto entryIterator = jumpStates.find((LPVOID)_XInputGetCapabilities); + + if (entryIterator != jumpStates.end()) + { + jumpEntry entry = *entryIterator; + + swapJumps(entry); + + auto response = _XInputGetCapabilities(dwUserIndex, dwFlags, pCapabilities); + + swapJumps(entry); + + return response; + } + } + return _XInputGetCapabilities(dwUserIndex, dwFlags, pCapabilities); } @@ -174,8 +307,30 @@ namespace REAL_XINPUT DWORD WINAPI XInputGetBatteryInformation(DWORD dwUserIndex, BYTE devType, PXINPUT_BATTERY_INFORMATION battery) { + #ifdef DEBUG_XINPUT_CALLS + cout << "XInputGetBatteryInformation(" << dwUserIndex << ", " << devType << ", " << battery << ")" << endl; + #endif + if (_XInputGetBatteryInformation != nullptr) { + if (shouldFixJumps()) + { + auto entryIterator = jumpStates.find((LPVOID)_XInputGetBatteryInformation); + + if (entryIterator != jumpStates.end()) + { + jumpEntry entry = *entryIterator; + + swapJumps(entry); + + auto response = _XInputGetBatteryInformation(dwUserIndex, devType, battery); + + swapJumps(entry); + + return response; + } + } + return _XInputGetBatteryInformation(dwUserIndex, devType, battery); } @@ -184,8 +339,30 @@ namespace REAL_XINPUT DWORD WINAPI XInputGetKeystroke(DWORD dwUserIndex, DWORD dwReserved, PXINPUT_KEYSTROKE pKeyStroke) { + #ifdef DEBUG_XINPUT_CALLS + cout << "XInputGetKeystroke(" << dwUserIndex << ", " << dwReserved << ", " << pKeyStroke << ")" << endl; + #endif + if (_XInputGetKeystroke != nullptr) { + if (shouldFixJumps()) + { + auto entryIterator = jumpStates.find((LPVOID)_XInputGetKeystroke); + + if (entryIterator != jumpStates.end()) + { + jumpEntry entry = *entryIterator; + + swapJumps(entry); + + auto response = _XInputGetKeystroke(dwUserIndex, dwReserved, pKeyStroke); + + swapJumps(entry); + + return response; + } + } + return _XInputGetKeystroke(dwUserIndex, dwReserved, pKeyStroke); } @@ -194,8 +371,30 @@ namespace REAL_XINPUT DWORD WINAPI XInputGetAudioDeviceIds(DWORD dwUserIndex, LPWSTR pRenderDeviceId, PUINT renderCount, LPWSTR captureDeviceId, PUINT captureCount) { + #ifdef DEBUG_XINPUT_CALLS + cout << "XInputGetAudioDeviceIds(" << dwUserIndex << ", " << pRenderDeviceId << ", " << renderCount << ", " << captureDeviceId << ", " << captureCount << ")" << endl; + #endif + if (_XInputGetAudioDeviceIds != nullptr) { + if (shouldFixJumps()) + { + auto entryIterator = jumpStates.find((LPVOID)_XInputGetAudioDeviceIds); + + if (entryIterator != jumpStates.end()) + { + jumpEntry entry = *entryIterator; + + swapJumps(entry); + + auto response = _XInputGetAudioDeviceIds(dwUserIndex, pRenderDeviceId, renderCount, captureDeviceId, captureCount); + + swapJumps(entry); + + return response; + } + } + return _XInputGetAudioDeviceIds(dwUserIndex, pRenderDeviceId, renderCount, captureDeviceId, captureCount); } @@ -204,9 +403,31 @@ namespace REAL_XINPUT DWORD WINAPI XInputGetStateEx(DWORD dwUserIndex, PXINPUT_STATE pState) { - if (_XInputGetState != nullptr) + #ifdef DEBUG_XINPUT_CALLS + cout << "XInputGetStateEx(" << dwUserIndex << ", " << pState << ")" << endl; + #endif + + if (_XInputGetStateEx != nullptr) { - return _XInputGetState(dwUserIndex, pState); + if (shouldFixJumps()) + { + auto entryIterator = jumpStates.find((LPVOID)_XInputGetStateEx); + + if (entryIterator != jumpStates.end()) + { + jumpEntry entry = *entryIterator; + + swapJumps(entry); + + auto response = _XInputGetStateEx(dwUserIndex, pState); + + swapJumps(entry); + + return response; + } + } + + return _XInputGetStateEx(dwUserIndex, pState); } return ERROR_DEVICE_NOT_CONNECTED; diff --git a/IOSync/src/devices/native/winnt/Real_XInput_Wrapper.h b/IOSync/src/devices/native/winnt/Real_XInput_Wrapper.h index 36e1f8a..5fa584c 100644 --- a/IOSync/src/devices/native/winnt/Real_XInput_Wrapper.h +++ b/IOSync/src/devices/native/winnt/Real_XInput_Wrapper.h @@ -1,6 +1,8 @@ #pragma once // Includes: +#include "../../../native/winnt/processManagement.h" + #include #ifdef XINPUT_INJECTOR @@ -9,17 +11,42 @@ #include #endif +// Standard library: +#include + // Namespace(s): namespace REAL_XINPUT { - //#include + // Namespace(s): + using namespace std; + + // Typedefs: + typedef pair jumpEntry; + typedef map jumpMap; + + // Global variable(s): + extern jumpMap jumpStates; // Functions: + inline bool shouldFixJumps() + { + return !jumpStates.empty(); + } + + inline void swapJumps(jumpEntry& entry) + { + entry.second = process::swapJumpInstruction(entry.first, entry.second); + + return; + } + inline LPCSTR XInputGetStateEx_Ordinal() { return (LPCSTR)100; } + process::jumpSegment mapRemoteFunction(LPCSTR name, LPCVOID function, HMODULE hDLL); + VOID linkTo(HMODULE hDLL); // The 'resolveSystemPath' argument specifies if this routine diff --git a/IOSync/src/iosync.cpp b/IOSync/src/iosync.cpp index bc1ae68..1cbec8b 100644 --- a/IOSync/src/iosync.cpp +++ b/IOSync/src/iosync.cpp @@ -1151,7 +1151,12 @@ namespace iosync } } - mode = (applicationMode)stoi(application[APPLICATION_MODE]); + auto modeIterator = application.find(APPLICATION_MODE); + + if (modeIterator != application.end()) + { + mode = (applicationMode)stoi(modeIterator->second); + } } // Devices: @@ -1676,6 +1681,16 @@ namespace iosync // Check if we have arguments to use: if (argCount > 1) { + #ifdef PLATFORM_WINDOWS + if (devices::XINPUT_INJECTION_ARGUMENTW == args[0]) + { + if (!devices::gamepad::__winnt__injectLibrary(stoi(args[1]))) + return -1; + + return 0; + } + #endif + return execute((argCount > 2) ? args[2] : DEFAULT_PLAYER_NAME, wideStringToDefault(args[0]), (addressPort)stoi(args[1])); } else if (argCount > 0) @@ -1688,7 +1703,7 @@ namespace iosync try { // Local variable(s): - applicationConfiguration configuration(mode); + applicationConfiguration configuration; configuration.load(); diff --git a/IOSync/src/main.cpp b/IOSync/src/main.cpp index 4e318cf..a4e1f91 100644 --- a/IOSync/src/main.cpp +++ b/IOSync/src/main.cpp @@ -72,11 +72,7 @@ int runProgram(OSINFO OSInfo, rate updateRate=DEFAULT_UPDATERATE) cout << "Unable to continue operations; exiting..." << endl; cout << "Error code thrown by application: " << responseCode << endl; - #ifdef PLATFORM_WINDOWS - system("PAUSE"); - #else - cin.get(); - #endif + cout << "Press any key to continue..."; cin.get(); // Return the response-code. return responseCode; @@ -97,6 +93,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine int main(int argc, char** argv) #endif { + // Local variable(s): + bool parentConsoleAttached = false; + // Initialize networking functionality. QSocket::initSockets(); @@ -105,7 +104,32 @@ int main(int argc, char** argv) #endif #ifdef PLATFORM_WINDOWS_EXTENSIONS - AllocConsole(); + // Kept in its own scope due to large stack allocation(s): + { + WCHAR pathBuffer[MAX_PATH]; + + GetModuleFileNameW(NULL, (LPWSTR)pathBuffer, MAX_PATH); + + auto tempStr = wstring(pathBuffer); + + string::size_type dividerLocation = tempStr.find_last_of(L"\\/"); + + if (dividerLocation != string::npos) + { + application::path = tempStr.substr(0, dividerLocation); + } + + //application::path = wstring((const wchar_t*)pathBuffer); + } + + if (!AttachConsole(ATTACH_PARENT_PROCESS)) + { + AllocConsole(); + } + else + { + parentConsoleAttached = true; + } freopen("CONOUT$", "w", stdout); freopen("CONIN$", "r", stdin); @@ -118,7 +142,7 @@ int main(int argc, char** argv) std::locale engLocale(locale); setlocale(LC_ALL, locale); - + wcout.imbue(engLocale); //wcin.imbue(engLocale); @@ -135,37 +159,15 @@ int main(int argc, char** argv) //SetStdHandle(STD_INPUT_HANDLE, GetStdHandle(STD_INPUT_HANDLE)); // stdin //SetStdHandle(STD_OUTPUT_HANDLE, GetStdHandle(STD_OUTPUT_HANDLE)); // stdout - - // Kept in its own scope due to large stack allocation(s): - { - WCHAR pathBuffer[MAX_PATH]; - - GetModuleFileNameW(NULL, (LPWSTR)pathBuffer, MAX_PATH); - - auto tempStr = wstring(pathBuffer); - - string::size_type dividerLocation = tempStr.find_last_of(L"\\/"); - - if (dividerLocation != string::npos) - { - application::path = tempStr.substr(0, dividerLocation); - } - - //application::path = wstring((const wchar_t*)pathBuffer); - } #else application::path = defaultStringToWide(argv[0]); #endif - //wcout << "Path: " << "\"" << application::path << "\"" << endl; - cout << "Starting the application..." << endl; - - /* - keyboard test_keyboard(keyboardDeviceFlag::FLAG_TESTMODE); - - if (!test_keyboard.connect()) - return -1; - */ + if (!parentConsoleAttached) + { + //wcout << "Path: " << "\"" << application::path << "\"" << endl; + cout << "Starting the application..." << endl; + } // Allocate the main application using the stack's memory. // This effectively embeds 'program' into 'main'. diff --git a/IOSync/src/native/winnt/processManagement.cpp b/IOSync/src/native/winnt/processManagement.cpp index 9436dcc..1e27de0 100644 --- a/IOSync/src/native/winnt/processManagement.cpp +++ b/IOSync/src/native/winnt/processManagement.cpp @@ -60,20 +60,59 @@ namespace process return s.str(); } - BOOL writeJump(LPVOID writeaddress, LPVOID funcaddress) + void readJumpSegment(jumpSegment& output, LPCVOID address) { - unsigned char data[5]; + ReadProcessMemory(GetCurrentProcess(), address, output.data(), output.size(), NULL); + return; + } + + void writeJumpSegment(const jumpSegment& segment, LPVOID writeaddress) + { + WriteProcessMemory(GetCurrentProcess(), writeaddress, segment.data(), JUMP_SEGMENT_SIZE, NULL); + + return; + } + + jumpSegment swapJumpInstruction(LPVOID writeaddress, const jumpSegment& segment) + { + jumpSegment currentData; + + readJumpSegment(currentData, writeaddress); + + writeJumpSegment(segment, writeaddress); + + return currentData; + } + + jumpSegment writeJump(LPVOID writeaddress, LPCVOID funcaddress) + { + // Local variable(s): + + // This will act as the original segment, before the jump was injected. + jumpSegment currentData; + + // Read the segment of memory safely. + readJumpSegment(currentData, writeaddress); + + // Allocate a temporary buffer for jump-injection. + unsigned char data[JUMP_SEGMENT_SIZE]; + + // Generate the proper instruction: data[0] = 0xE9; // E8; // 9A; *(signed int *)(data + 1) = (unsigned int)funcaddress - ((unsigned int)writeaddress + 5); - return WriteProcessMemory(GetCurrentProcess(), writeaddress, data, 5, NULL); + // Write over the targeted binary with our new instruction. + WriteProcessMemory(GetCurrentProcess(), writeaddress, data, JUMP_SEGMENT_SIZE, NULL); + + // Return the original binary, now that we've replaced it. + return currentData; } LPVOID getRemoteFunction(LPCSTR name, HMODULE hDLL) { - return (LPVOID*)GetProcAddress(hDLL, name); + return (LPVOID)GetProcAddress(hDLL, name); } LPVOID getRemoteFunction(LPCSTR name, LPCSTR DLL) @@ -81,7 +120,7 @@ namespace process return getRemoteFunction(name, GetModuleHandleA(DLL)); } - BOOL mapRemoteFunction(LPCSTR name, LPVOID function, HMODULE hDLL) + jumpSegment mapRemoteFunction(LPCSTR name, LPCVOID function, HMODULE hDLL) { #ifdef PROCESS_MANAGER_DEBUG cout << "Attempting to map '" << function << "' to: '" << name << "'" << endl; @@ -95,13 +134,14 @@ namespace process cout << "Remapping failed; unable to find remote function." #endif - return FALSE; + // For now, do nothing. + return jumpSegment(); } return writeJump(remoteFunction, function); } - BOOL mapRemoteFunction(LPCSTR name, LPVOID function, LPCSTR DLL) + jumpSegment mapRemoteFunction(LPCSTR name, LPCVOID function, LPCSTR DLL) { return writeJump(getRemoteFunction(name, DLL), function); } diff --git a/IOSync/src/native/winnt/processManagement.h b/IOSync/src/native/winnt/processManagement.h index ded0505..eab371e 100644 --- a/IOSync/src/native/winnt/processManagement.h +++ b/IOSync/src/native/winnt/processManagement.h @@ -18,6 +18,7 @@ // Standard library: #include +#include // Namespace(s): namespace process @@ -25,6 +26,14 @@ namespace process // Namespace(s): using namespace std; + // Constant variable(s): + const size_t JUMP_SEGMENT_SIZE = 5; + + // Typedefs: + + // A "segment" of memory dedicated to a jump instruction. + typedef array jumpSegment; + // Functions: DWORD getPID(); @@ -44,13 +53,17 @@ namespace process // This will return the result of 'getName', plus an additional random-number. string getUniqueName(); - BOOL writeJump(LPVOID writeaddress, LPVOID funcaddress); + void readJumpSegment(jumpSegment& output, LPCVOID address); + void writeJumpSegment(const jumpSegment& segment, LPVOID writeaddress); + + jumpSegment swapJumpInstruction(LPVOID writeaddress, const jumpSegment& segment); + jumpSegment writeJump(LPVOID writeaddress, LPCVOID funcaddress); LPVOID getRemoteFunction(LPCSTR name, HMODULE hDLL); LPVOID getRemoteFunction(LPCSTR name, LPCSTR DLL=INJECTOR_XINPUT_DEFAULT_DLL_A); - BOOL mapRemoteFunction(LPCSTR name, LPVOID function, HMODULE hDLL); - BOOL mapRemoteFunction(LPCSTR name, LPVOID function, LPCSTR DLL=INJECTOR_XINPUT_DEFAULT_DLL_A); + jumpSegment mapRemoteFunction(LPCSTR name, LPCVOID function, HMODULE hDLL); + jumpSegment mapRemoteFunction(LPCSTR name, LPCVOID function, LPCSTR DLL=INJECTOR_XINPUT_DEFAULT_DLL_A); // This command requires you to link with "psapi.lib"; use at your own risk. template diff --git a/XInput_Injection_DLL/Source.cpp b/XInput_Injection_DLL/Source.cpp index 9e6cc87..e28961c 100644 --- a/XInput_Injection_DLL/Source.cpp +++ b/XInput_Injection_DLL/Source.cpp @@ -183,7 +183,9 @@ extern "C" if (sharedMemoryResponse == SHARED_MEMORY_ALLOCATED || sharedMemoryResponse == SHARED_MEMORY_ALREADY_ALLOCATED) { - auto PID = getPID(); + #ifdef DLL_DEBUG + auto PID = getPID(); + #endif sharedBuffer = gamepad::__winnt__mapSharedMemory(FILE_MAP_READ); @@ -195,6 +197,7 @@ extern "C" bool injected = false; bool shouldInject = true; + char DLLName[XINPUT_DLL_NAMELENGTH]; for (auto i = XINPUT_MAX_SUBVERSION; i > 0; i--) @@ -237,18 +240,18 @@ extern "C" #ifdef DLL_DEBUG cout << "Injecting functions..." << endl; #endif - - // Remap the active functions in the remote library. - mapRemoteFunction("XInputEnable", (LPVOID)::XInputEnable, hDLL); - mapRemoteFunction("XInputGetState", (LPVOID)::XInputGetState, hDLL); - mapRemoteFunction("XInputSetState", (LPVOID)::XInputSetState, hDLL); - mapRemoteFunction("XInputGetCapabilities", (LPVOID)::XInputGetCapabilities, hDLL); - mapRemoteFunction("XInputGetKeystroke", (LPVOID)::XInputGetKeystroke, hDLL); - mapRemoteFunction("XInputGetBatteryInformation", (LPVOID)::XInputGetBatteryInformation, hDLL); - mapRemoteFunction("XInputGetAudioDeviceIds", (LPVOID)::XInputGetAudioDeviceIds, hDLL); + //jumpSegment + // Remap the active functions in the remote library: + REAL_XINPUT::mapRemoteFunction("XInputEnable", (LPVOID)::XInputEnable, hDLL); + REAL_XINPUT::mapRemoteFunction("XInputGetState", (LPVOID)::XInputGetState, hDLL); + REAL_XINPUT::mapRemoteFunction("XInputSetState", (LPVOID)::XInputSetState, hDLL); + REAL_XINPUT::mapRemoteFunction("XInputGetCapabilities", (LPVOID)::XInputGetCapabilities, hDLL); + REAL_XINPUT::mapRemoteFunction("XInputGetKeystroke", (LPVOID)::XInputGetKeystroke, hDLL); + REAL_XINPUT::mapRemoteFunction("XInputGetBatteryInformation", (LPVOID)::XInputGetBatteryInformation, hDLL); + REAL_XINPUT::mapRemoteFunction("XInputGetAudioDeviceIds", (LPVOID)::XInputGetAudioDeviceIds, hDLL); // Extensions: - mapRemoteFunction(REAL_XINPUT::XInputGetStateEx_Ordinal(), (LPVOID)::XInputGetStateEx, hDLL); // "XInputGetStateEx" + REAL_XINPUT::mapRemoteFunction(REAL_XINPUT::XInputGetStateEx_Ordinal(), (LPVOID)::XInputGetStateEx, hDLL); // "XInputGetStateEx" #ifdef DLL_DEBUG cout << "Functions injected." << endl; @@ -256,12 +259,11 @@ extern "C" cout << "Attempting to link with real 'XInput' module..." << endl; #endif - // Link to this module. + // Safely link to the real module. REAL_XINPUT::linkTo(hDLL); - #ifdef DLL_DEBUG - cout << "Real module linked." << endl; - #endif + // Set the global XInput-module. + XINPUT_MODULE = hDLL; // Set the injection-flag to 'true'. injected = true; @@ -269,7 +271,7 @@ extern "C" else { // Link to an 'XInput' DLL in the system-folder. - XINPUT_MODULE = REAL_XINPUT::linkTo(DLLName, TRUE); + XINPUT_MODULE = REAL_XINPUT::linkTo((PCSTR)DLLName, TRUE); } break; diff --git a/XInput_Injection_DLL/XInput_Injection_DLL.vcxproj b/XInput_Injection_DLL/XInput_Injection_DLL.vcxproj index 8cb9a25..64651ea 100644 --- a/XInput_Injection_DLL/XInput_Injection_DLL.vcxproj +++ b/XInput_Injection_DLL/XInput_Injection_DLL.vcxproj @@ -242,6 +242,7 @@ + diff --git a/XInput_Injection_DLL/XInput_Injection_DLL.vcxproj.filters b/XInput_Injection_DLL/XInput_Injection_DLL.vcxproj.filters index 74428b4..bcfce91 100644 --- a/XInput_Injection_DLL/XInput_Injection_DLL.vcxproj.filters +++ b/XInput_Injection_DLL/XInput_Injection_DLL.vcxproj.filters @@ -32,6 +32,9 @@ Header Files + + Header Files + diff --git a/XInput_Injection_DLL/XInput_Injector.h b/XInput_Injection_DLL/XInput_Injector.h index 3de53ab..a7d80ec 100644 --- a/XInput_Injection_DLL/XInput_Injector.h +++ b/XInput_Injection_DLL/XInput_Injector.h @@ -13,17 +13,8 @@ // Other: //#define DLLExport // __declspec( dllexport ) -//#define DLL_DEBUG -#define DLL_CONFIRMATION_MESSAGE - -/* -#ifdef DLL_DEBUG - #define PROCESS_MANAGER_DEBUG -#endif -*/ - // Includes: -// Nothing so far. +#include "settings.h" // Windows-specific: #include diff --git a/XInput_Injection_DLL/settings.h b/XInput_Injection_DLL/settings.h new file mode 100644 index 0000000..72e90b4 --- /dev/null +++ b/XInput_Injection_DLL/settings.h @@ -0,0 +1,10 @@ +#pragma once + +//#define DLL_DEBUG +#define DLL_CONFIRMATION_MESSAGE + +/* +#ifdef DLL_DEBUG + #define PROCESS_MANAGER_DEBUG +#endif +*/ \ No newline at end of file