Skip to content
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

Fix some small problems with Device Selection Dialog #3851

Merged
Merged
1 change: 1 addition & 0 deletions Client/multiplayer_sa/CMultiplayerSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,7 @@ void CMultiplayerSA::InitHooks()
MemSet((void*)0x6C4453, 0x90, 0x68);

InitHooks_CrashFixHacks();
InitHooks_DeviceSelection();

// Init our 1.3 hooks.
Init_13();
Expand Down
1 change: 1 addition & 0 deletions Client/multiplayer_sa/CMultiplayerSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class CMultiplayerSA : public CMultiplayer
void InitHooks_ProjectileCollisionFix();
void InitHooks_ObjectStreamerOptimization();
void InitHooks_Postprocess();
void InitHooks_DeviceSelection();
CRemoteDataStorage* CreateRemoteDataStorage();
void DestroyRemoteDataStorage(CRemoteDataStorage* pData);
void AddRemoteDataStorage(CPlayerPed* pPed, CRemoteDataStorage* pData);
Expand Down
157 changes: 157 additions & 0 deletions Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*****************************************************************************
*
* 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"

#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX
#endif
#endif
forkerer marked this conversation as resolved.
Show resolved Hide resolved

// This is copied from SilentPatch:
// https://github.com/CookiePLMonster/SilentPatch/blob/dev/SilentPatch/FriendlyMonitorNames.cpp
std::map<std::string, std::string, std::less<>> GetFriendlyMonitorNamesForDevicePaths()
{
std::map<std::string, std::string, std::less<>> monitorNames;
forkerer marked this conversation as resolved.
Show resolved Hide resolved

#if WINVER < _WIN32_WINNT_WIN7
return monitorNames;
#else
forkerer marked this conversation as resolved.
Show resolved Hide resolved
HMODULE user32Lib = LoadLibrary(TEXT("user32"));
if (user32Lib != nullptr)
forkerer marked this conversation as resolved.
Show resolved Hide resolved
{
auto getDisplayConfigBufferSizes = (decltype(GetDisplayConfigBufferSizes)*)GetProcAddress(user32Lib, "GetDisplayConfigBufferSizes");
auto queryDisplayConfig = (decltype(QueryDisplayConfig)*)GetProcAddress(user32Lib, "QueryDisplayConfig");
auto displayConfigGetDeviceInfo = (decltype(DisplayConfigGetDeviceInfo)*)GetProcAddress(user32Lib, "DisplayConfigGetDeviceInfo");
if (getDisplayConfigBufferSizes != nullptr && queryDisplayConfig != nullptr && displayConfigGetDeviceInfo != nullptr)
forkerer marked this conversation as resolved.
Show resolved Hide resolved
{
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)
{
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;
forkerer marked this conversation as resolved.
Show resolved Hide resolved
#endif
}

struct RwSubSystemInfo
{
char name[80];
};

#define FUNC_rwDeviceSystemRequest 0x7F2AB0
using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(void* device, uint32_t requestId, RwSubSystemInfo* pOut, void* pInOut, uint32_t numIn);
forkerer marked this conversation as resolved.
Show resolved Hide resolved
static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, int32_t subSystemIndex)
forkerer marked this conversation as resolved.
Show resolved Hide resolved
{
static auto rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest);
auto devicePointer = *(uint32_t*)(0xC97B24);
forkerer marked this conversation as resolved.
Show resolved Hide resolved
auto result = rwDeviceSystemRequestFunc((void*)(devicePointer + 0x10), 14, subSystemInfo, nullptr, subSystemIndex);
forkerer marked this conversation as resolved.
Show resolved Hide resolved
if (result == nullptr)
forkerer marked this conversation as resolved.
Show resolved Hide resolved
return nullptr;

auto pDxDevice = *(IDirect3D9**)0xC97C20;
forkerer marked this conversation as resolved.
Show resolved Hide resolved
if (pDxDevice == nullptr)
forkerer marked this conversation as resolved.
Show resolved Hide resolved
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);
}
forkerer marked this conversation as resolved.
Show resolved Hide resolved

return subSystemInfo;
}

#define FUNC_DialogFunc 0x745E50
static INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
forkerer marked this conversation as resolved.
Show resolved Hide resolved
{
auto orgDialogFunc = (DLGPROC)FUNC_DialogFunc;
if (msg == WM_INITDIALOG)
{
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;
}
forkerer marked this conversation as resolved.
Show resolved Hide resolved

return orgDialogFunc(window, msg, wParam, lParam);
}

void CMultiplayerSA::InitHooks_DeviceSelection()
{
MemPut<DLGPROC>(0x746239, (DLGPROC)&CustomDlgProc);
forkerer marked this conversation as resolved.
Show resolved Hide resolved
HookInstall(0x7F2C30, (DWORD)RwEngineGetSubSystemInfo_Hooked, 6);
forkerer marked this conversation as resolved.
Show resolved Hide resolved
}
Loading