mirror of
https://github.com/ValveSoftware/Proton.git
synced 2025-05-17 17:08:11 +03:00
lsteamclient: Add a new export to initialize registry.
CW-Bug-Id: #24510
This commit is contained in:
parent
3a4858bd6b
commit
2a69a32cf8
@ -209,6 +209,7 @@ MANUAL_STRUCTS = [
|
||||
|
||||
UNIX_FUNCS = [
|
||||
'steamclient_init',
|
||||
'steamclient_init_registry',
|
||||
'steamclient_next_callback',
|
||||
'steamclient_CreateInterface',
|
||||
'steamclient_Steam_GetAPICallResult',
|
||||
|
@ -74,3 +74,5 @@
|
||||
@ stub VulkanSteamOverlayGetScaleFactors
|
||||
@ stub VulkanSteamOverlayPresent
|
||||
@ stub VulkanSteamOverlayProcessCapturedFrame
|
||||
|
||||
@ cdecl -private steamclient_init_registry()
|
||||
|
@ -601,3 +601,10 @@ void CDECL Steam_NotifyMissingInterface( int32_t hSteamPipe, const char *pchVers
|
||||
load_steamclient();
|
||||
STEAMCLIENT_CALL( steamclient_Steam_NotifyMissingInterface, ¶ms );
|
||||
}
|
||||
|
||||
BOOL CDECL steamclient_init_registry(void)
|
||||
{
|
||||
load_steamclient();
|
||||
if (STEAMCLIENT_CALL( steamclient_init_registry, NULL )) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ void *alloc_callback_wtou( int id, void *callback, int *callback_len );
|
||||
void convert_callback_utow( int id, void *u_callback, int u_callback_len, void *w_callback, int w_callback_len );
|
||||
|
||||
extern NTSTATUS steamclient_init( void * );
|
||||
extern NTSTATUS steamclient_init_registry( void * );
|
||||
extern NTSTATUS steamclient_next_callback( void * );
|
||||
extern NTSTATUS steamclient_CreateInterface( void * );
|
||||
extern NTSTATUS steamclient_Steam_GetAPICallResult( void * );
|
||||
|
@ -379,6 +379,248 @@ NTSTATUS steamclient_Steam_GetAPICallResult( void *args )
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UINT asciiz_to_unicode( WCHAR *dst, const char *src )
|
||||
{
|
||||
WCHAR *p = dst;
|
||||
while ((*p++ = *src++));
|
||||
return (p - dst) * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
static BOOL set_reg_value( HANDLE hkey, const WCHAR *name, UINT type, const void *value, DWORD count )
|
||||
{
|
||||
unsigned short name_size = name ? lstrlenW( name ) * sizeof(WCHAR) : 0;
|
||||
UNICODE_STRING nameW = { name_size, name_size, (WCHAR *)name };
|
||||
return !NtSetValueKey( hkey, &nameW, 0, type, value, count );
|
||||
}
|
||||
|
||||
static void set_reg_ascii_dword( HANDLE hkey, const char *name, DWORD value )
|
||||
{
|
||||
WCHAR nameW[64], valueW[128];
|
||||
asciiz_to_unicode( nameW, name );
|
||||
set_reg_value( hkey, nameW, REG_DWORD, &value, sizeof(value) );
|
||||
}
|
||||
|
||||
static void set_reg_ascii_str( HANDLE hkey, const char *name, const char *value )
|
||||
{
|
||||
size_t len = strlen( value ) + 1;
|
||||
WCHAR nameW[64], *valueW;
|
||||
|
||||
if (!(valueW = (WCHAR *)malloc( len * sizeof(*valueW) ))) return;
|
||||
asciiz_to_unicode( valueW, value );
|
||||
asciiz_to_unicode( nameW, name );
|
||||
set_reg_value( hkey, nameW, REG_SZ, valueW, len * sizeof(*valueW) );
|
||||
free( valueW );
|
||||
}
|
||||
|
||||
static inline void init_unicode_string( UNICODE_STRING *str, const WCHAR *data )
|
||||
{
|
||||
str->Length = wcslen( data ) * sizeof(WCHAR);
|
||||
str->MaximumLength = str->Length + sizeof(WCHAR);
|
||||
str->Buffer = (WCHAR *)data;
|
||||
}
|
||||
|
||||
static NTSTATUS open_hkcu_key( const char *path, HANDLE *key )
|
||||
{
|
||||
NTSTATUS status;
|
||||
char buffer[256];
|
||||
WCHAR bufferW[256];
|
||||
DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)];
|
||||
DWORD i, len = sizeof(sid_data);
|
||||
SID *sid;
|
||||
UNICODE_STRING name;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
|
||||
status = NtQueryInformationToken( GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len );
|
||||
if (status) return status;
|
||||
|
||||
sid = (SID *)((TOKEN_USER *)sid_data)->User.Sid;
|
||||
len = snprintf( buffer, sizeof(buffer), "\\Registry\\User\\S-%u-%u", sid->Revision,
|
||||
(int)MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5], sid->IdentifierAuthority.Value[4] ),
|
||||
MAKEWORD( sid->IdentifierAuthority.Value[3], sid->IdentifierAuthority.Value[2] )));
|
||||
for (i = 0; i < sid->SubAuthorityCount; i++)
|
||||
len += snprintf( buffer + len, sizeof(buffer) - len, "-%u", (int)sid->SubAuthority[i] );
|
||||
len += snprintf( buffer + len, sizeof(buffer) - len, "\\%s", path );
|
||||
|
||||
asciiz_to_unicode( bufferW, buffer );
|
||||
init_unicode_string( &name, bufferW );
|
||||
InitializeObjectAttributes( &attr, &name, OBJ_CASE_INSENSITIVE, 0, NULL );
|
||||
return NtCreateKey( key, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL );
|
||||
}
|
||||
|
||||
/* requires steam API to be initialized */
|
||||
static void setup_steam_registry( u_ISteamClient_SteamClient017 *client, int pipe, int user )
|
||||
{
|
||||
static const int system_locale_appids[] =
|
||||
{
|
||||
1284210 /* Guild Wars 2 */
|
||||
};
|
||||
|
||||
const char *ui_lang, *language, *languages, *locale = NULL;
|
||||
u_ISteamApps_STEAMAPPS_INTERFACE_VERSION008 *apps;
|
||||
u_ISteamUtils_SteamUtils009 *utils;
|
||||
unsigned int appid, status;
|
||||
char buf[256];
|
||||
HANDLE key;
|
||||
int i;
|
||||
|
||||
utils = (u_ISteamUtils_SteamUtils009 *)client->GetISteamUtils( pipe, "SteamUtils009" );
|
||||
ui_lang = utils->GetSteamUILanguage();
|
||||
TRACE( "UI language: %s\n", debugstr_a(ui_lang) );
|
||||
|
||||
if ((status = open_hkcu_key( "Software\\Valve\\Steam", &key )))
|
||||
ERR( "Could not create key, status %#x\n", status );
|
||||
else
|
||||
{
|
||||
set_reg_ascii_str( key, "language", ui_lang );
|
||||
NtClose( key );
|
||||
}
|
||||
|
||||
appid = utils->GetAppID();
|
||||
TRACE( "appid: %u\n", appid );
|
||||
|
||||
if ((status = open_hkcu_key( "Software\\Valve\\Steam\\Apps", &key )))
|
||||
ERR( "Could not create key, status %#x\n", status );
|
||||
else
|
||||
NtClose( key );
|
||||
|
||||
sprintf( buf, "Software\\Valve\\Steam\\Apps\\%u", appid );
|
||||
if ((status = open_hkcu_key( buf, &key ))) ERR( "Could not create key, status %#x\n", status );
|
||||
else
|
||||
{
|
||||
DWORD value;
|
||||
value = 1;
|
||||
set_reg_ascii_dword( key, "Installed", value );
|
||||
set_reg_ascii_dword( key, "Running", value );
|
||||
value = 0;
|
||||
set_reg_ascii_dword( key, "Updating", value );
|
||||
NtClose( key );
|
||||
}
|
||||
|
||||
apps = (u_ISteamApps_STEAMAPPS_INTERFACE_VERSION008 *)client->GetISteamApps( user, pipe, "STEAMAPPS_INTERFACE_VERSION008" );
|
||||
language = apps->GetCurrentGameLanguage();
|
||||
languages = apps->GetAvailableGameLanguages();
|
||||
TRACE( "Game language %s, available %s\n", debugstr_a(language), debugstr_a(languages) );
|
||||
|
||||
if (!strchr( languages, ',' )) /* If there is a list of languages then respect that */
|
||||
{
|
||||
for (i = 0; language && i < ARRAY_SIZE(system_locale_appids); i++)
|
||||
{
|
||||
if (system_locale_appids[i] == appid)
|
||||
{
|
||||
TRACE( "Not changing system locale for application %i\n", appid );
|
||||
language = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!language) locale = NULL;
|
||||
else if (!strcmp( language, "arabic" )) locale = "ar_001.UTF-8";
|
||||
else if (!strcmp( language, "bulgarian" )) locale = "bg_BG.UTF-8";
|
||||
else if (!strcmp( language, "schinese" )) locale = "zh_CN.UTF-8";
|
||||
else if (!strcmp( language, "tchinese" )) locale = "zh_TW.UTF-8";
|
||||
else if (!strcmp( language, "czech" )) locale = "cs_CZ.UTF-8";
|
||||
else if (!strcmp( language, "danish" )) locale = "da_DK.UTF-8";
|
||||
else if (!strcmp( language, "dutch" )) locale = "nl_NL.UTF-8";
|
||||
else if (!strcmp( language, "english" )) locale = "en_US.UTF-8";
|
||||
else if (!strcmp( language, "finnish" )) locale = "fi_FI.UTF-8";
|
||||
else if (!strcmp( language, "french" )) locale = "fr_FR.UTF-8";
|
||||
else if (!strcmp( language, "german" )) locale = "de_DE.UTF-8";
|
||||
else if (!strcmp( language, "greek" )) locale = "el_GR.UTF-8";
|
||||
else if (!strcmp( language, "hungarian" )) locale = "hu_HU.UTF-8";
|
||||
else if (!strcmp( language, "italian" )) locale = "it_IT.UTF-8";
|
||||
else if (!strcmp( language, "japanese" )) locale = "ja_JP.UTF-8";
|
||||
else if (!strcmp( language, "koreana" )) locale = "ko_KR.UTF-8";
|
||||
else if (!strcmp( language, "norwegian" )) locale = "nb_NO.UTF-8";
|
||||
else if (!strcmp( language, "polish" )) locale = "pl_PL.UTF-8";
|
||||
else if (!strcmp( language, "portuguese" )) locale = "pt_PT.UTF-8";
|
||||
else if (!strcmp( language, "brazilian" )) locale = "pt_BR.UTF-8";
|
||||
else if (!strcmp( language, "romanian" )) locale = "ro_RO.UTF-8";
|
||||
else if (!strcmp( language, "russian" )) locale = "ru_RU.UTF-8";
|
||||
else if (!strcmp( language, "spanish" )) locale = "es_ES.UTF-8";
|
||||
else if (!strcmp( language, "latam" )) locale = "es_419.UTF-8";
|
||||
else if (!strcmp( language, "swedish" )) locale = "sv_SE.UTF-8";
|
||||
else if (!strcmp( language, "thai" )) locale = "th_TH.UTF-8";
|
||||
else if (!strcmp( language, "turkish" )) locale = "tr_TR.UTF-8";
|
||||
else if (!strcmp( language, "ukrainian" )) locale = "uk_UA.UTF-8";
|
||||
else if (!strcmp( language, "vietnamese" )) locale = "vi_VN.UTF-8";
|
||||
else FIXME( "Unsupported game language %s\n", debugstr_a(language) );
|
||||
|
||||
/* HACK: Bug 23597 Granado Espada Japan (1219160) launcher needs Japanese locale to display correctly */
|
||||
if (appid == 1219160) locale = "ja_JP.UTF-8";
|
||||
|
||||
if (locale)
|
||||
{
|
||||
FIXME( "Game language %s, defaulting LC_CTYPE / LC_MESSAGES to %s.\n", debugstr_a(language), locale );
|
||||
setenv( "LC_CTYPE", locale, FALSE );
|
||||
setenv( "LC_MESSAGES", locale, FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
/* requires steam API to be initialized */
|
||||
static void setup_battleye_bridge( u_ISteamClient_SteamClient017 *client, int pipe, int user )
|
||||
{
|
||||
u_ISteamApps_STEAMAPPS_INTERFACE_VERSION008 *apps;
|
||||
const unsigned int be_runtime_appid = 1161040;
|
||||
char path[2048];
|
||||
int error;
|
||||
|
||||
apps = (u_ISteamApps_STEAMAPPS_INTERFACE_VERSION008 *)client->GetISteamApps( user, pipe, "STEAMAPPS_INTERFACE_VERSION008" );
|
||||
if (!apps->BIsAppInstalled( be_runtime_appid )) return;
|
||||
if (!apps->GetAppInstallDir( be_runtime_appid, path, sizeof(path) )) return;
|
||||
TRACE( "Found battleye runtime at %s\n", path );
|
||||
setenv( "PROTON_BATTLEYE_RUNTIME", path, 1 );
|
||||
}
|
||||
|
||||
static void setup_eac_bridge( u_ISteamClient_SteamClient017 *client, int pipe, int user )
|
||||
{
|
||||
u_ISteamApps_STEAMAPPS_INTERFACE_VERSION008 *apps;
|
||||
const unsigned int eac_runtime_appid = 1826330;
|
||||
char path[2048];
|
||||
int error;
|
||||
|
||||
apps = (u_ISteamApps_STEAMAPPS_INTERFACE_VERSION008 *)client->GetISteamApps( user, pipe, "STEAMAPPS_INTERFACE_VERSION008" );
|
||||
if (!apps->BIsAppInstalled( eac_runtime_appid )) return;
|
||||
if (!apps->GetAppInstallDir( eac_runtime_appid, path, sizeof(path) )) return;
|
||||
TRACE( "Found easyanticheat runtime at %s\n", path );
|
||||
setenv( "PROTON_EAC_RUNTIME", path, 1 );
|
||||
}
|
||||
|
||||
static void setup_proton_voice_files( u_ISteamClient_SteamClient017 *client, int pipe, int user )
|
||||
{
|
||||
u_ISteamApps_STEAMAPPS_INTERFACE_VERSION008 *apps;
|
||||
const unsigned int eac_runtime_appid = 3086180;
|
||||
char path[2048];
|
||||
int error;
|
||||
|
||||
apps = (u_ISteamApps_STEAMAPPS_INTERFACE_VERSION008 *)client->GetISteamApps( user, pipe, "STEAMAPPS_INTERFACE_VERSION008" );
|
||||
if (!apps->BIsAppInstalled( eac_runtime_appid )) return;
|
||||
if (!apps->GetAppInstallDir( eac_runtime_appid, path, sizeof(path) )) return;
|
||||
TRACE( "Found proton voice files at %s\n", path );
|
||||
setenv( "PROTON_VOICE_FILES", path, 1 );
|
||||
}
|
||||
|
||||
NTSTATUS steamclient_init_registry( void *args )
|
||||
{
|
||||
u_ISteamClient_SteamClient017 *client;
|
||||
int pipe, user, error;
|
||||
|
||||
client = (u_ISteamClient_SteamClient017 *)p_CreateInterface( "SteamClient017", &error );
|
||||
if (!(pipe = client->CreateSteamPipe()) || !(user = client->ConnectToGlobalUser( pipe )))
|
||||
{
|
||||
ERR( "Failed to connect to Steam\n" );
|
||||
if (pipe) client->BReleaseSteamPipe( pipe );
|
||||
return -1;
|
||||
}
|
||||
|
||||
setup_steam_registry( client, pipe, user );
|
||||
setup_battleye_bridge( client, pipe, user );
|
||||
setup_eac_bridge( client, pipe, user );
|
||||
setup_proton_voice_files( client, pipe, user );
|
||||
|
||||
client->BReleaseSteamPipe( pipe );
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS steamclient_init( void *args )
|
||||
{
|
||||
struct steamclient_init_params *params = (struct steamclient_init_params *)args;
|
||||
|
@ -9,6 +9,7 @@
|
||||
extern "C" const unixlib_entry_t __wine_unix_call_funcs[] =
|
||||
{
|
||||
steamclient_init,
|
||||
steamclient_init_registry,
|
||||
steamclient_next_callback,
|
||||
steamclient_CreateInterface,
|
||||
steamclient_Steam_GetAPICallResult,
|
||||
|
@ -48757,6 +48757,7 @@ struct ISteamUtils_SteamUtils010_DismissGamepadTextInput_params
|
||||
enum unix_funcs
|
||||
{
|
||||
unix_steamclient_init,
|
||||
unix_steamclient_init_registry,
|
||||
unix_steamclient_next_callback,
|
||||
unix_steamclient_CreateInterface,
|
||||
unix_steamclient_Steam_GetAPICallResult,
|
||||
|
Loading…
x
Reference in New Issue
Block a user