-
-
Notifications
You must be signed in to change notification settings - Fork 502
Fix some small problems with Device Selection Dialog #3851
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Dutchman101
merged 14 commits into
multitheftauto:master
from
forkerer:feature/DeviceSelectionFixes
Nov 21, 2024
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
30f9675
Fix some small problems with Device Selection Dialog
forkerer 8bc4427
Fix file comment
forkerer 0d66ab4
Remove NOMINMAX directive
forkerer ca847bb
Early outs
forkerer 83b210d
RwGlobals and RwDevice stup in Renderware.h
forkerer 148aef6
Pointles static removal, clarification of some addresses
forkerer 406f74c
added missing std::
forkerer 40b4752
Fixed incorrect comment
forkerer c621fc8
Remove windows 7 safety checks
forkerer 486aa59
Instant return from function if possible
forkerer cc90226
use auto* for pointers
forkerer 1a7e9cd
Move every single magic number to the defines at the top of the file
forkerer 479f0f7
Replace std::map with std::unordered_map
forkerer 20a5659
Merge branch 'master' into feature/DeviceSelectionFixes
Dutchman101 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
155 changes: 155 additions & 0 deletions
155
Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| /***************************************************************************** | ||
| * | ||
| * PROJECT: Multi Theft Auto v1.0 | ||
| * LICENSE: See LICENSE in the top level directory | ||
| * FILE: multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp | ||
| * | ||
| * Multi Theft Auto is available from http://www.multitheftauto.com/ | ||
| * | ||
| *****************************************************************************/ | ||
|
|
||
| #include "StdInc.h" | ||
| #define FUNC_rwDeviceSystemRequest 0x7F2AB0 | ||
| #define FUNC_DialogFunc 0x745E50 | ||
| #define FUNC_RwEngineGetSubSystemInfo 0x7F2C30 | ||
| #define CLASS_RwGlobals 0xC97B24 | ||
| #define CLASS_IDirect3D9 0xC97C20 | ||
| #define NUM_DialogFuncStackPushAddress 0x746239 | ||
|
|
||
| // This is copied from SilentPatch: | ||
| // https://github.com/CookiePLMonster/SilentPatch/blob/dev/SilentPatch/FriendlyMonitorNames.cpp | ||
| std::unordered_map<std::string, std::string> GetFriendlyMonitorNamesForDevicePaths() | ||
| { | ||
| std::unordered_map<std::string, std::string> monitorNames; | ||
|
|
||
| HMODULE user32Lib = LoadLibrary(TEXT("user32")); | ||
| if (!user32Lib) | ||
| return monitorNames; | ||
|
|
||
| auto* getDisplayConfigBufferSizes = (decltype(GetDisplayConfigBufferSizes)*)GetProcAddress(user32Lib, "GetDisplayConfigBufferSizes"); | ||
| auto* queryDisplayConfig = (decltype(QueryDisplayConfig)*)GetProcAddress(user32Lib, "QueryDisplayConfig"); | ||
| auto* displayConfigGetDeviceInfo = (decltype(DisplayConfigGetDeviceInfo)*)GetProcAddress(user32Lib, "DisplayConfigGetDeviceInfo"); | ||
| if (!getDisplayConfigBufferSizes || !queryDisplayConfig || !displayConfigGetDeviceInfo) | ||
| { | ||
| FreeLibrary(user32Lib); | ||
| return monitorNames; | ||
| } | ||
|
|
||
| UINT32 pathCount, modeCount; | ||
| std::unique_ptr<DISPLAYCONFIG_PATH_INFO[]> paths; | ||
| std::unique_ptr<DISPLAYCONFIG_MODE_INFO[]> modes; | ||
|
|
||
| LONG result = ERROR_SUCCESS; | ||
| do | ||
| { | ||
| result = getDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount); | ||
| if (result != ERROR_SUCCESS) | ||
| { | ||
| break; | ||
| } | ||
| paths = std::make_unique<DISPLAYCONFIG_PATH_INFO[]>(pathCount); | ||
| modes = std::make_unique<DISPLAYCONFIG_MODE_INFO[]>(modeCount); | ||
| result = queryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths.get(), &modeCount, modes.get(), nullptr); | ||
| } while (result == ERROR_INSUFFICIENT_BUFFER); | ||
|
|
||
| if (result != ERROR_SUCCESS) | ||
| { | ||
| FreeLibrary(user32Lib); | ||
| return monitorNames; | ||
| } | ||
|
|
||
| for (size_t i = 0; i < pathCount; i++) | ||
| { | ||
| DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {}; | ||
| targetName.header.adapterId = paths[i].targetInfo.adapterId; | ||
| targetName.header.id = paths[i].targetInfo.id; | ||
| targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; | ||
| targetName.header.size = sizeof(targetName); | ||
| const LONG targetNameResult = DisplayConfigGetDeviceInfo(&targetName.header); | ||
|
|
||
| DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {}; | ||
| sourceName.header.adapterId = paths[i].sourceInfo.adapterId; | ||
| sourceName.header.id = paths[i].sourceInfo.id; | ||
| sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; | ||
| sourceName.header.size = sizeof(sourceName); | ||
| const LONG sourceNameResult = DisplayConfigGetDeviceInfo(&sourceName.header); | ||
| if (targetNameResult == ERROR_SUCCESS && sourceNameResult == ERROR_SUCCESS && targetName.monitorFriendlyDeviceName[0] != '\0') | ||
| { | ||
| char gdiDeviceName[std::size(sourceName.viewGdiDeviceName)]; | ||
| char monitorFriendlyDeviceName[std::size(targetName.monitorFriendlyDeviceName)]; | ||
| WideCharToMultiByte(CP_ACP, 0, sourceName.viewGdiDeviceName, -1, gdiDeviceName, static_cast<int>(std::size(gdiDeviceName)), nullptr, nullptr); | ||
| WideCharToMultiByte(CP_ACP, 0, targetName.monitorFriendlyDeviceName, -1, monitorFriendlyDeviceName, | ||
| static_cast<int>(std::size(monitorFriendlyDeviceName)), nullptr, nullptr); | ||
|
|
||
| monitorNames.try_emplace(gdiDeviceName, monitorFriendlyDeviceName); | ||
| } | ||
| } | ||
|
|
||
| FreeLibrary(user32Lib); | ||
| return monitorNames; | ||
| } | ||
|
|
||
| struct RwSubSystemInfo | ||
| { | ||
| char name[80]; | ||
| }; | ||
|
|
||
| using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(RwDevice* device, std::int32_t requestId, RwSubSystemInfo* pOut, void* pInOut, std::int32_t numIn); | ||
| static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, std::int32_t subSystemIndex) | ||
| { | ||
| auto* rwGlobals = *(RwGlobals**)CLASS_RwGlobals; | ||
| auto* rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest); | ||
| if (!rwDeviceSystemRequestFunc(&rwGlobals->dOpenDevice, 14, subSystemInfo, nullptr, subSystemIndex)) | ||
| return nullptr; | ||
|
|
||
| auto* pDxDevice = *(IDirect3D9**)CLASS_IDirect3D9; | ||
| if (!pDxDevice) | ||
| return subSystemInfo; | ||
|
|
||
| D3DADAPTER_IDENTIFIER9 identifier; | ||
| if (FAILED(pDxDevice->GetAdapterIdentifier(subSystemIndex, 0, &identifier))) | ||
| return subSystemInfo; | ||
|
|
||
| static const auto friendlyNames = GetFriendlyMonitorNamesForDevicePaths(); | ||
|
|
||
| // If we can't find the friendly name, either because it doesn't exist or we're on an ancient Windows, fall back to the device name | ||
| auto it = friendlyNames.find(identifier.DeviceName); | ||
| if (it != friendlyNames.end()) | ||
| { | ||
| strncpy_s(subSystemInfo->name, it->second.c_str(), _TRUNCATE); | ||
| } | ||
| else | ||
| { | ||
| strncpy_s(subSystemInfo->name, identifier.Description, _TRUNCATE); | ||
| } | ||
|
|
||
| return subSystemInfo; | ||
| } | ||
|
|
||
| INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) | ||
| { | ||
| auto* orgDialogFunc = (DLGPROC)FUNC_DialogFunc; | ||
| if (msg != WM_INITDIALOG) | ||
| return orgDialogFunc(window, msg, wParam, lParam); | ||
|
|
||
| orgDialogFunc(window, msg, wParam, lParam); | ||
|
|
||
| // Set Icon | ||
| HMODULE hGameModule = GetModuleHandle(nullptr); | ||
| SendMessage(window, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(LoadIcon(hGameModule, MAKEINTRESOURCE(100)))); | ||
|
|
||
| // Make the dialog visible in the task bar | ||
| // https://stackoverflow.com/a/1462811 | ||
| SetWindowLongPtr(window, GWL_EXSTYLE, WS_EX_APPWINDOW); | ||
| ShowWindow(window, SW_HIDE); | ||
| ShowWindow(window, SW_SHOW); | ||
| return FALSE; | ||
| } | ||
|
|
||
| void CMultiplayerSA::InitHooks_DeviceSelection() | ||
| { | ||
| // 0x746239 -> Exact address where the original DialogFunc address is being pushed as an argument to DialogBoxParamA(), | ||
| // we're replacing it with out own proxy function | ||
| MemPut<DLGPROC>(NUM_DialogFuncStackPushAddress, (DLGPROC)&CustomDlgProc); | ||
| HookInstall(FUNC_RwEngineGetSubSystemInfo, (DWORD)RwEngineGetSubSystemInfo_Hooked, 6); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.