From e0b2b50fb1ddf171a7edf0c3128948b0dad816e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Thu, 19 Oct 2023 11:07:32 +0200 Subject: [PATCH] lsteamclient: Move unix library loading to the unix side. CW-Bug-Id: #22729 --- lsteamclient/steamclient_main.c | 141 ++++---------------------------- lsteamclient/unixlib.cpp | 93 ++++++++++++++++++++- lsteamclient/unixlib.h | 19 +++-- 3 files changed, 121 insertions(+), 132 deletions(-) diff --git a/lsteamclient/steamclient_main.c b/lsteamclient/steamclient_main.c index f7465cfb..241e4219 100644 --- a/lsteamclient/steamclient_main.c +++ b/lsteamclient/steamclient_main.c @@ -5,9 +5,6 @@ #include #include -#define __USE_GNU -#include - #include "windef.h" #include "winbase.h" #include "winnls.h" @@ -45,33 +42,6 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) return TRUE; } -void sync_environment(void) -{ - static const char *steamapi_envs[] = - { - "SteamAppId", - "IgnoreChildProcesses", - }; - - char value[32767]; - - for (unsigned int i = 0; i < ARRAY_SIZE(steamapi_envs); i++) - { - if (!GetEnvironmentVariableA(steamapi_envs[i], value, ARRAY_SIZE(value))) - { - if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) - { - TRACE("unsetenv(\"%s\")\n", steamapi_envs[i]); - unsetenv(steamapi_envs[i]); - } - continue; - } - - TRACE("setenv(\"%s\", \"%s\", 1)\n", steamapi_envs[i], value); - setenv(steamapi_envs[i], value, 1); - } -} - /* Returns: * - if successful, the number of bytes written to dst, including the NULL terminator; * - 0 if failed; @@ -676,101 +646,30 @@ done: return ret; } -static void *steamclient_lib; -static void *(*steamclient_CreateInterface)(const char *name, int *return_code); -bool (*steamclient_BGetCallback)( int32_t a, u_CallbackMsg_t *b, int32_t *c ); -bool (*steamclient_GetAPICallResult)( int32_t, uint64_t, void *, int, int, bool * ); -bool (*steamclient_FreeLastCallback)( int32_t ); -static void (*steamclient_ReleaseThreadLocalMemory)(int); -static bool (*steamclient_IsKnownInterface)( const char *pchVersion ); -static void (*steamclient_NotifyMissingInterface)( int32_t hSteamPipe, const char *pchVersion ); - static int load_steamclient(void) { - char path[PATH_MAX], resolved_path[PATH_MAX]; + char steam_app_id[4096], ignore_child_processes[4096]; + struct steamclient_init_params params = {0}; - if(steamclient_lib) - return 1; + if (!GetEnvironmentVariableA("SteamAppId", steam_app_id, ARRAY_SIZE(steam_app_id))) + params.steam_app_id_unset = GetLastError() == ERROR_ENVVAR_NOT_FOUND; + else + params.steam_app_id = steam_app_id; - sync_environment(); - -#ifdef __APPLE__ - if(getenv("STEAM_COMPAT_CLIENT_INSTALL_PATH")){ - snprintf(path, PATH_MAX, "%s/steamclient.dylib", getenv("STEAM_COMPAT_CLIENT_INSTALL_PATH")); - }else{ - WARN("Old Steam client, falling back to DYLD environment to locate native steamclient library\n"); - strcpy(path, "steamclient.dylib"); - } -#else -#ifdef _WIN64 - snprintf(path, PATH_MAX, "%s/.steam/sdk64/steamclient.so", getenv("HOME")); -#else - snprintf(path, PATH_MAX, "%s/.steam/sdk32/steamclient.so", getenv("HOME")); -#endif - if (realpath(path, resolved_path)){ - lstrcpynA(path, resolved_path, PATH_MAX); - path[PATH_MAX - 1] = 0; - } -#endif - steamclient_lib = dlopen(path, RTLD_NOW); - if(!steamclient_lib){ - ERR("unable to load native steamclient library\n"); - return 0; - } - - steamclient_CreateInterface = dlsym(steamclient_lib, "CreateInterface"); - if(!steamclient_CreateInterface){ - ERR("unable to load CreateInterface method\n"); - return 0; - } - - steamclient_BGetCallback = dlsym(steamclient_lib, "Steam_BGetCallback"); - if(!steamclient_BGetCallback){ - ERR("unable to load BGetCallback method\n"); - return 0; - } - - steamclient_GetAPICallResult = dlsym(steamclient_lib, "Steam_GetAPICallResult"); - if(!steamclient_GetAPICallResult){ - ERR("unable to load GetAPICallResult method\n"); - return 0; - } - - steamclient_FreeLastCallback = dlsym(steamclient_lib, "Steam_FreeLastCallback"); - if(!steamclient_FreeLastCallback){ - ERR("unable to load FreeLastCallback method\n"); - return 0; - } - - steamclient_ReleaseThreadLocalMemory = dlsym(steamclient_lib, "Steam_ReleaseThreadLocalMemory"); - if(!steamclient_ReleaseThreadLocalMemory){ - ERR("unable to load ReleaseThreadLocalMemory method\n"); - return 0; - } - - steamclient_IsKnownInterface = dlsym(steamclient_lib, "Steam_IsKnownInterface"); - if(!steamclient_IsKnownInterface){ - ERR("unable to load IsKnownInterface method\n"); - return 0; - } - - steamclient_NotifyMissingInterface = dlsym(steamclient_lib, "Steam_NotifyMissingInterface"); - if(!steamclient_NotifyMissingInterface){ - ERR("unable to load NotifyMissingInterface method\n"); - return 0; - } + if (!GetEnvironmentVariableA("IgnoreChildProcesses", ignore_child_processes, ARRAY_SIZE(ignore_child_processes))) + params.ignore_child_processes_unset = GetLastError() == ERROR_ENVVAR_NOT_FOUND; + else + params.ignore_child_processes = ignore_child_processes; + if (!unix_steamclient_init( ¶ms )) return 0; return 1; } void *CDECL CreateInterface(const char *name, int *return_code) { TRACE("name: %s, return_code: %p\n", name, return_code); - - if(!load_steamclient()) - return NULL; - - return create_win_interface(name, steamclient_CreateInterface(name, return_code)); + if (!load_steamclient()) return NULL; + return create_win_interface( name, unix_CreateInterface( name, return_code ) ); } static void execute_pending_callbacks(void) @@ -821,8 +720,7 @@ bool CDECL Steam_BGetCallback( int32_t pipe, w_CallbackMsg_t *win_msg, int32_t * TRACE("%u, %p, %p\n", pipe, win_msg, ignored); - if(!load_steamclient()) - return 0; + if (!load_steamclient()) return 0; execute_pending_callbacks(); @@ -867,7 +765,6 @@ bool CDECL Steam_GetAPICallResult( int32_t pipe, uint64_t call, void *w_callback TRACE( "%u, x, %p, %u, %u, %p\n", pipe, w_callback, w_callback_len, id, failed ); if (!load_steamclient()) return FALSE; - return unix_Steam_GetAPICallResult( pipe, call, w_callback, w_callback_len, id, failed ); } @@ -875,10 +772,8 @@ void CDECL Steam_ReleaseThreadLocalMemory(int bThreadExit) { TRACE("%d\n", bThreadExit); - if(!load_steamclient()) - return; - - steamclient_ReleaseThreadLocalMemory(bThreadExit); + if (!load_steamclient()) return; + unix_Steam_ReleaseThreadLocalMemory( bThreadExit ); } void CDECL Breakpad_SteamMiniDumpInit( uint32_t a, const char *b, const char *c ) @@ -912,12 +807,12 @@ bool CDECL Steam_IsKnownInterface( const char *pchVersion ) { TRACE("%s\n", pchVersion); load_steamclient(); - return steamclient_IsKnownInterface( pchVersion ); + return unix_Steam_IsKnownInterface( pchVersion ); } void CDECL Steam_NotifyMissingInterface( int32_t hSteamPipe, const char *pchVersion ) { TRACE("%u %s\n", hSteamPipe, pchVersion); load_steamclient(); - steamclient_NotifyMissingInterface( hSteamPipe, pchVersion ); + unix_Steam_NotifyMissingInterface( hSteamPipe, pchVersion ); } diff --git a/lsteamclient/unixlib.cpp b/lsteamclient/unixlib.cpp index a30ba5c1..a9c1b2be 100644 --- a/lsteamclient/unixlib.cpp +++ b/lsteamclient/unixlib.cpp @@ -2,6 +2,7 @@ #include #include +#include WINE_DEFAULT_DEBUG_CHANNEL(steamclient); @@ -79,9 +80,17 @@ bool unix_steamclient_next_callback( struct callback *callback, uint32_t *size ) return !!ptr; } +static void *(*p_CreateInterface)( const char *name, int *return_code ); +static bool (*p_Steam_BGetCallback)( int32_t a, u_CallbackMsg_t *b, int32_t *c ); +static bool (*p_Steam_GetAPICallResult)( int32_t, uint64_t, void *, int, int, bool * ); +static bool (*p_Steam_FreeLastCallback)( int32_t ); +static void (*p_Steam_ReleaseThreadLocalMemory)( int ); +static bool (*p_Steam_IsKnownInterface)( const char * ); +static void (*p_Steam_NotifyMissingInterface)( int32_t, const char * ); + bool unix_Steam_BGetCallback( uint32_t pipe, w_CallbackMsg_t *w_msg, int32_t *ignored, u_CallbackMsg_t *u_msg ) { - if (!steamclient_BGetCallback( pipe, u_msg, ignored )) return false; + if (!p_Steam_BGetCallback( pipe, u_msg, ignored )) return false; callback_message_utow( u_msg, w_msg ); return true; } @@ -94,7 +103,7 @@ void unix_callback_message_receive( u_CallbackMsg_t *u_msg, w_CallbackMsg_t *w_m bool unix_Steam_FreeLastCallback( uint32_t pipe ) { - return steamclient_FreeLastCallback( pipe ); + return p_Steam_FreeLastCallback( pipe ); } bool unix_Steam_GetAPICallResult( int32_t pipe, uint64_t call, void *w_callback, int w_callback_len, @@ -106,7 +115,7 @@ bool unix_Steam_GetAPICallResult( int32_t pipe, uint64_t call, void *w_callback, if (!(u_callback = alloc_callback_wtou( id, w_callback, &u_callback_len ))) return false; - ret = steamclient_GetAPICallResult( pipe, call, u_callback, u_callback_len, id, failed ); + ret = p_Steam_GetAPICallResult( pipe, call, u_callback, u_callback_len, id, failed ); if (ret && u_callback != w_callback) { @@ -116,3 +125,81 @@ bool unix_Steam_GetAPICallResult( int32_t pipe, uint64_t call, void *w_callback, return ret; } + +bool unix_steamclient_init( struct steamclient_init_params *params ) +{ + char path[PATH_MAX], resolved_path[PATH_MAX]; + static void *steamclient; + + if (params->steam_app_id_unset) unsetenv( "SteamAppId" ); + else if (params->steam_app_id) setenv( "SteamAppId", params->steam_app_id, TRUE ); + if (params->ignore_child_processes_unset) unsetenv( "IgnoreChildProcesses" ); + else if (params->ignore_child_processes) setenv( "IgnoreChildProcesses", params->ignore_child_processes, TRUE ); + + if (steamclient) return true; + +#ifdef __APPLE__ + if (getenv( "STEAM_COMPAT_CLIENT_INSTALL_PATH" )) + snprintf( path, PATH_MAX, "%s/steamclient.dylib", getenv( "STEAM_COMPAT_CLIENT_INSTALL_PATH" ) ); + else + { + WARN( "Old Steam client, falling back to DYLD environment to locate native steamclient " + "library\n" ); + strcpy( path, "steamclient.dylib" ); + } +#else /* __APPLE__ */ +#ifdef __x86_64__ + snprintf( path, PATH_MAX, "%s/.steam/sdk64/steamclient.so", getenv( "HOME" ) ); +#else + snprintf( path, PATH_MAX, "%s/.steam/sdk32/steamclient.so", getenv( "HOME" ) ); +#endif + if (realpath( path, resolved_path )) + { + strcpy( path, resolved_path ); + path[PATH_MAX - 1] = 0; + } +#endif /* __APPLE__ */ + + if (!(steamclient = dlopen( path, RTLD_NOW ))) + { + ERR( "unable to load native steamclient library\n" ); + return false; + } + +#define LOAD_FUNC( x ) \ + if (!(p_##x = (decltype(p_##x))dlsym( steamclient, #x ))) \ + { \ + ERR( "unable to load " #x "\n" ); \ + return false; \ + } + + LOAD_FUNC( CreateInterface ); + LOAD_FUNC( Steam_BGetCallback ); + LOAD_FUNC( Steam_GetAPICallResult ); + LOAD_FUNC( Steam_FreeLastCallback ); + LOAD_FUNC( Steam_ReleaseThreadLocalMemory ); + LOAD_FUNC( Steam_IsKnownInterface ); + LOAD_FUNC( Steam_NotifyMissingInterface ); + + return true; +} + +void *unix_CreateInterface( const char *name, int *return_code ) +{ + return p_CreateInterface( name, return_code ); +} + +void unix_Steam_ReleaseThreadLocalMemory( int thread_exit ) +{ + p_Steam_ReleaseThreadLocalMemory( thread_exit ); +} + +bool unix_Steam_IsKnownInterface( const char *version ) +{ + return p_Steam_IsKnownInterface( version ); +} + +void unix_Steam_NotifyMissingInterface( int32_t pipe, const char *version ) +{ + p_Steam_NotifyMissingInterface( pipe, version ); +} diff --git a/lsteamclient/unixlib.h b/lsteamclient/unixlib.h index bb3fcc0d..fc19590a 100644 --- a/lsteamclient/unixlib.h +++ b/lsteamclient/unixlib.h @@ -27,6 +27,14 @@ extern void steamclient_free_path_array( const char **path_array ); #define PATH_MAX 4096 extern char g_tmppath[PATH_MAX]; +struct steamclient_init_params +{ + const char *steam_app_id; + bool steam_app_id_unset; + const char *ignore_child_processes; + bool ignore_child_processes_unset; +}; + enum callback_type { SOCKETS_DEBUG_OUTPUT = 1, @@ -56,18 +64,17 @@ struct callback }; }; +extern bool unix_steamclient_init( struct steamclient_init_params *params ); extern bool unix_steamclient_next_callback( struct callback *callback, uint32_t *length ); - -extern bool (*steamclient_GetAPICallResult)( int32_t, uint64_t, void *, int, int, bool * ); +extern void *unix_CreateInterface( const char *name, int *return_code ); extern bool unix_Steam_GetAPICallResult( int32_t pipe, uint64_t call, void *w_callback, int w_callback_len, int id, bool *failed ); - -extern bool (*steamclient_BGetCallback)( int32_t a, u_CallbackMsg_t *b, int32_t *c ); extern bool unix_Steam_BGetCallback( uint32_t pipe, w_CallbackMsg_t *w_msg, int32_t *ignored, u_CallbackMsg_t *u_msg ); extern void unix_callback_message_receive( u_CallbackMsg_t *u_msg, w_CallbackMsg_t *w_msg ); - -extern bool (*steamclient_FreeLastCallback)( int32_t ); extern bool unix_Steam_FreeLastCallback( uint32_t pipe ); +extern void unix_Steam_ReleaseThreadLocalMemory( int thread_exit ); +extern bool unix_Steam_IsKnownInterface( const char *version ); +extern void unix_Steam_NotifyMissingInterface( int32_t pipe, const char *version ); struct networking_message_pool; struct networking_message