From e11162ecff02e97e1517781712c1f0262ab7c792 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Thu, 10 Jul 2025 20:00:04 +0300 Subject: [PATCH] Implemented steamclient.dll C exports --- dll/auth.cpp | 10 +- dll/dll.cpp | 213 ++++++++++++++++++++++----------------- dll/dll/auth.h | 5 + dll/steam_gameserver.cpp | 10 +- dll/steam_user.cpp | 27 +++-- 5 files changed, 151 insertions(+), 114 deletions(-) diff --git a/dll/auth.cpp b/dll/auth.cpp index 9737950f..03fac712 100644 --- a/dll/auth.cpp +++ b/dll/auth.cpp @@ -1,16 +1,8 @@ #include "dll/auth.h" #define STEAM_ID_OFFSET_TICKET (4 + 8) -#define STEAM_TICKET_MIN_SIZE (4 + 8 + 8) -#define STEAM_TICKET_MIN_SIZE_NEW 170 - #define STEAM_TICKET_PROCESS_TIME 0.03 -//Conan Exiles doesn't work with 512 or 128, 256 seems to be the good size -// Usually steam send as 1024 (or recommend sending as that) -//Steam returns 234 -#define STEAM_AUTH_TICKET_SIZE 256 //234 - static inline int generate_random_int() { int a; @@ -739,7 +731,7 @@ Auth_Data Auth_Manager::getTicketData( void *pTicket, int cbMaxTicket, uint32 *p ((char *)pTicket)[3] = 0; uint64 steam_id_buff = steam_id.ConvertToUint64(); memcpy((char *)pTicket + STEAM_ID_OFFSET_TICKET, &steam_id_buff, sizeof(steam_id_buff)); - *pcbTicket = cbMaxTicket; + *pcbTicket = STEAM_TICKET_MIN_SIZE; uint32 ttt = generate_steam_ticket_id(); ticket_data.id = steam_id; ticket_data.number = ttt; diff --git a/dll/dll.cpp b/dll/dll.cpp index 9e0b77ee..6aed34c5 100644 --- a/dll/dll.cpp +++ b/dll/dll.cpp @@ -1379,169 +1379,186 @@ STEAMCLIENT_API void Breakpad_SteamWriteMiniDumpUsingExceptionInfoWithBuildId( i STEAMCLIENT_API steam_bool Steam_BConnected( HSteamUser hUser, HSteamPipe hSteamPipe ) { PRINT_DEBUG_ENTRY(); - return true; + ISteamUser004 *su = reinterpret_cast(get_steam_client()->GetISteamUser(hUser, hSteamPipe, "SteamUser004")); + return su->BConnected(); } STEAMCLIENT_API steam_bool Steam_BLoggedOn( HSteamUser hUser, HSteamPipe hSteamPipe ) { - PRINT_DEBUG("%i %i", hUser, hSteamPipe); - Steam_Client *steam_client = get_steam_client(); - - auto pipe_it = steam_client->steam_pipes.find(hSteamPipe); - if (steam_client->steam_pipes.end() == pipe_it) { - return false; - } - - class Settings *settings_tmp{}; - if (pipe_it->second == Steam_Pipe::SERVER) { - settings_tmp = steam_client->settings_server; - } else if (pipe_it->second == Steam_Pipe::CLIENT) { - settings_tmp = steam_client->settings_client; - } else { - return false; - } - - return !settings_tmp->is_offline(); + PRINT_DEBUG_ENTRY(); + ISteamUser004 *su = reinterpret_cast(get_steam_client()->GetISteamUser(hUser, hSteamPipe, "SteamUser004")); + return su->BLoggedOn(); } STEAMCLIENT_API steam_bool Steam_BReleaseSteamPipe( HSteamPipe hSteamPipe ) { - PRINT_DEBUG_TODO(); - return false; + PRINT_DEBUG_ENTRY(); + return get_steam_client()->BReleaseSteamPipe(hSteamPipe); } STEAMCLIENT_API HSteamUser Steam_ConnectToGlobalUser( HSteamPipe hSteamPipe ) { - PRINT_DEBUG_TODO(); - return 0; + PRINT_DEBUG_ENTRY(); + return get_steam_client()->ConnectToGlobalUser(hSteamPipe); } STEAMCLIENT_API HSteamUser Steam_CreateGlobalUser( HSteamPipe *phSteamPipe ) { - PRINT_DEBUG_TODO(); - return 0; + PRINT_DEBUG_ENTRY(); + return get_steam_client()->CreateGlobalUser(phSteamPipe); } STEAMCLIENT_API HSteamUser Steam_CreateLocalUser( HSteamPipe *phSteamPipe, EAccountType eAccountType ) { - PRINT_DEBUG_TODO(); - return 0; + PRINT_DEBUG_ENTRY(); + return get_steam_client()->CreateLocalUser(phSteamPipe, eAccountType); } STEAMCLIENT_API HSteamPipe Steam_CreateSteamPipe() { - PRINT_DEBUG_TODO(); - return 0; + PRINT_DEBUG_ENTRY(); + return get_steam_client()->CreateSteamPipe(); +} + +STEAMCLIENT_API void *Steam_GetGSHandle(HSteamUser hUser, HSteamPipe hSteamPipe) +{ + PRINT_DEBUG_ENTRY(); + return get_steam_client()->GetISteamGameServer(hUser, hSteamPipe, "SteamGameServer002"); } STEAMCLIENT_API steam_bool Steam_GSBLoggedOn( void *phSteamHandle ) { - PRINT_DEBUG_TODO(); - return false; + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->BLoggedOn(); } -STEAMCLIENT_API steam_bool Steam_GSBSecure( void *phSteamHandle) +STEAMCLIENT_API steam_bool Steam_GSBSecure( void *phSteamHandle ) { - PRINT_DEBUG_TODO(); - return false; + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->BSecure(); } -// latest steamclient -STEAMCLIENT_API steam_bool Steam_GSGetSteam2GetEncryptionKeyToSendToNewClient(void* phSteamHandle) -//STEAMCLIENT_API steam_bool Steam_GSGetSteam2GetEncryptionKeyToSendToNewClient( void *phSteamHandle, void *pvEncryptionKey, uint32 *pcbEncryptionKey, uint32 cbMaxEncryptionKey ) +STEAMCLIENT_API steam_bool Steam_GSGetSteam2GetEncryptionKeyToSendToNewClient( void *phSteamHandle, void *pvEncryptionKey, uint32 *pcbEncryptionKey, uint32 cbMaxEncryptionKey ) { - PRINT_DEBUG_TODO(); - return false; + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->GSGetSteam2GetEncryptionKeyToSendToNewClient(pvEncryptionKey, pcbEncryptionKey, cbMaxEncryptionKey); } -STEAMCLIENT_API uint64 Steam_GSGetSteamID() +STEAMCLIENT_API int Steam_GSGetSteamGameConnectToken(HSteamUser hUser, HSteamPipe hSteamPipe, void *pBlob, int cbMaxBlob) { - PRINT_DEBUG_TODO(); - return 0; + PRINT_DEBUG_ENTRY(); + ISteamUser004 *su = reinterpret_cast(get_steam_client()->GetISteamUser(hUser, hSteamPipe, "SteamUser004")); + return su->GetSteamGameConnectToken(pBlob, cbMaxBlob); +} + +STEAMCLIENT_API uint64 Steam_GSGetSteamID( void *phSteamHandle ) +{ + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->GetSteamID().ConvertToUint64(); } STEAMCLIENT_API void Steam_GSLogOff( void *phSteamHandle ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + gs->LogOff(); } STEAMCLIENT_API void Steam_GSLogOn( void *phSteamHandle ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + gs->LogOn(); } -STEAMCLIENT_API steam_bool Steam_GSRemoveUserConnect(void* phSteamHandle) -//STEAMCLIENT_API steam_bool Steam_GSRemoveUserConnect( void *phSteamHandle, uint32 unUserID ) +STEAMCLIENT_API steam_bool Steam_GSRemoveUserConnect( void *phSteamHandle, uint32 unUserID ) { - PRINT_DEBUG_TODO(); - return false; + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->GSRemoveUserConnect(unUserID); } -STEAMCLIENT_API steam_bool Steam_GSSendSteam2UserConnect(void* phSteamHandle) -//STEAMCLIENT_API steam_bool Steam_GSSendSteam2UserConnect( void *phSteamHandle, uint32 unUserID, const void *pvRawKey, uint32 unKeyLen, uint32 unIPPublic, uint16 usPort, const void *pvCookie, uint32 cubCookie ) +STEAMCLIENT_API steam_bool Steam_GSSendSteam2UserConnect( void *phSteamHandle, uint32 unUserID, const void *pvRawKey, uint32 unKeyLen, uint32 unIPPublic, uint16 usPort, const void *pvCookie, uint32 cubCookie ) { - PRINT_DEBUG_TODO(); - return false; + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->GSSendSteam2UserConnect(unUserID, pvRawKey, unKeyLen, unIPPublic, usPort, pvCookie, cubCookie); } -STEAMCLIENT_API steam_bool Steam_GSSendSteam3UserConnect(void* phSteamHandle) -//STEAMCLIENT_API steam_bool Steam_GSSendSteam3UserConnect( void *phSteamHandle, uint64 steamID, uint32 unIPPublic, const void *pvCookie, uint32 cubCookie ) +STEAMCLIENT_API steam_bool Steam_GSSendSteam3UserConnect( void *phSteamHandle, uint64 steamID, uint32 unIPPublic, const void *pvCookie, uint32 cubCookie ) { - PRINT_DEBUG_TODO(); - return false; + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->GSSendSteam3UserConnect(steamID, unIPPublic, pvCookie, cubCookie); } -STEAMCLIENT_API steam_bool Steam_GSSendUserDisconnect(void* phSteamHandle) -//STEAMCLIENT_API steam_bool Steam_GSSendUserDisconnect( void *phSteamHandle, uint64 ulSteamID, uint32 unUserID ) +STEAMCLIENT_API steam_bool Steam_GSSendUserDisconnect( void *phSteamHandle, uint64 ulSteamID, uint32 unUserID ) { - PRINT_DEBUG_TODO(); - return false; + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->GSSendUserDisconnect(ulSteamID, unUserID); } -STEAMCLIENT_API steam_bool Steam_GSSendUserStatusResponse() -//STEAMCLIENT_API steam_bool Steam_GSSendUserStatusResponse( void *phSteamHandle, uint64 ulSteamID, int nSecondsConnected, int nSecondsSinceLast ) +STEAMCLIENT_API steam_bool Steam_GSSendUserStatusResponse( void *phSteamHandle, uint64 ulSteamID, int nSecondsConnected, int nSecondsSinceLast ) { - PRINT_DEBUG_TODO(); - return false; + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->GSSendUserStatusResponse(ulSteamID, nSecondsConnected, nSecondsSinceLast); } // Changed later, idk when. -STEAMCLIENT_API steam_bool Steam_GSSetServerType(void* phSteamHandle, int32 a2) -//STEAMCLIENT_API steam_bool Steam_GSSetServerType( void *phSteamHandle, int32 nAppIdServed, uint32 unServerFlags, uint32 unGameIP, uint32 unGamePort, const char *pchGameDir, const char *pchVersion ) +STEAMCLIENT_API steam_bool Steam_GSSetServerType( void *phSteamHandle, int32 nAppIdServed, uint32 unServerFlags, uint32 unGameIP, uint32 unGamePort, const char *pchGameDir, const char *pchVersion ) { - PRINT_DEBUG_TODO(); - return false; + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->GSSetServerType(nAppIdServed, unServerFlags, unGameIP, unGamePort, pchGameDir, pchVersion); } -STEAMCLIENT_API int64 Steam_GSSetSpawnCount(void* phSteamHandle) -{ - PRINT_DEBUG_TODO(); - return 0; -} - -/* STEAMCLIENT_API void Steam_GSSetSpawnCount( void *phSteamHandle, uint32 ucSpawn ) { - PRINT_DEBUG_TODO(); -} -*/ -STEAMCLIENT_API steam_bool Steam_GSUpdateStatus(void* phSteamHandle) -//STEAMCLIENT_API steam_bool Steam_GSUpdateStatus( void *phSteamHandle, int cPlayers, int cPlayersMax, int cBotPlayers, const char *pchServerName, const char *pchMapName ) -{ - PRINT_DEBUG_TODO(); - return false; + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + gs->GSSetSpawnCount(ucSpawn); } -STEAMCLIENT_API void* Steam_GetGSHandle( HSteamUser hUser, HSteamPipe hSteamPipe ) +STEAMCLIENT_API steam_bool Steam_GSSetStatus(void *phSteamHandle, int32 nAppIdServed, uint32 unServerFlags, int cPlayers, int cPlayersMax, int cBotPlayers, int unGamePort, const char *pchServerName, const char *pchGameDir, const char *pchMapName, const char *pchVersion) { - PRINT_DEBUG_TODO(); - return nullptr; + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->Obsolete_GSSetStatus(nAppIdServed, unServerFlags, cPlayers, cPlayersMax, cBotPlayers, unGamePort, pchServerName, pchGameDir, pchMapName, pchVersion); +} + +STEAMCLIENT_API steam_bool Steam_GSUpdateStatus( void *phSteamHandle, int cPlayers, int cPlayersMax, int cBotPlayers, const char *pchServerName, const char *pchMapName ) +{ + PRINT_DEBUG_ENTRY(); + if (!phSteamHandle) return 0; + ISteamGameServer002 *gs = reinterpret_cast(phSteamHandle); + return gs->GSUpdateStatus(cPlayers, cPlayersMax, cBotPlayers, pchServerName, pchMapName); } STEAMCLIENT_API int Steam_InitiateGameConnection( HSteamUser hUser, HSteamPipe hSteamPipe, void *pBlob, int cbMaxBlob, uint64 steamID, int nGameAppID, uint32 unIPServer, uint16 usPortServer, bool bSecure ) { - PRINT_DEBUG_TODO(); - return 0; + PRINT_DEBUG_ENTRY(); + ISteamUser004 *su = reinterpret_cast(get_steam_client()->GetISteamUser(hUser, hSteamPipe, "SteamUser004")); + return su->InitiateGameConnection(pBlob, cbMaxBlob, steamID, nGameAppID, unIPServer, usPortServer, bSecure); } // https://github.com/ValveSoftware/Proton/blob/962bbc4e74dde0643a6edab7c845bc628601f23f/lsteamclient/steamclient_main.c#L579-L586 @@ -1564,12 +1581,16 @@ STEAMCLIENT_API steam_bool Steam_IsKnownInterface( const char *pchVersion ) STEAMCLIENT_API void Steam_LogOff( HSteamUser hUser, HSteamPipe hSteamPipe ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); + ISteamUser004 *su = reinterpret_cast(get_steam_client()->GetISteamUser(hUser, hSteamPipe, "SteamUser004")); + su->LogOff(); } STEAMCLIENT_API void Steam_LogOn( HSteamUser hUser, HSteamPipe hSteamPipe, uint64 ulSteamID ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); + ISteamUser004 *su = reinterpret_cast(get_steam_client()->GetISteamUser(hUser, hSteamPipe, "SteamUser004")); + su->LogOn(ulSteamID); } // https://github.com/ValveSoftware/Proton/blob/962bbc4e74dde0643a6edab7c845bc628601f23f/lsteamclient/steamclient_main.c#L588-L594 @@ -1579,22 +1600,26 @@ STEAMCLIENT_API void Steam_NotifyMissingInterface(HSteamPipe hSteamPipe, const c get_steam_client()->report_missing_impl(pchVersion, EMU_FUNC_NAME); } -STEAMCLIENT_API void Steam_ReleaseThreadLocalMemory(bool thread_exit) +STEAMCLIENT_API void Steam_ReleaseThreadLocalMemory( bool thread_exit ) { PRINT_DEBUG_TODO(); } STEAMCLIENT_API void Steam_ReleaseUser( HSteamPipe hSteamPipe, HSteamUser hUser ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); + get_steam_client()->ReleaseUser(hSteamPipe, hUser); } STEAMCLIENT_API void Steam_SetLocalIPBinding( uint32 unIP, uint16 usLocalPort ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); + get_steam_client()->SetLocalIPBinding(unIP, usLocalPort); } STEAMCLIENT_API void Steam_TerminateGameConnection( HSteamUser hUser, HSteamPipe hSteamPipe, uint32 unIPServer, uint16 usPortServer ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); + ISteamUser004 *su = reinterpret_cast(get_steam_client()->GetISteamUser(hUser, hSteamPipe, "SteamUser004")); + su->TerminateGameConnection(unIPServer, usPortServer); } diff --git a/dll/dll/auth.h b/dll/dll/auth.h index 79e80b6a..ad2e6229 100644 --- a/dll/dll/auth.h +++ b/dll/dll/auth.h @@ -7,6 +7,11 @@ #include "base.h" #include "include.wrap.mbedtls.h" +#define STEAM_TICKET_MIN_SIZE (4 + 8 + 8) +#define STEAM_TICKET_MIN_SIZE_NEW 170 + +// Steam recommends sending 1024 byte buffer. It returns 234 byte ticket. +#define STEAM_AUTH_TICKET_SIZE 1024 // the data type is important, we depend on sizeof() for each one of them constexpr const static uint32_t STEAM_APPTICKET_SIGLEN = 128; diff --git a/dll/steam_gameserver.cpp b/dll/steam_gameserver.cpp index f3ae5b52..7a4c0212 100644 --- a/dll/steam_gameserver.cpp +++ b/dll/steam_gameserver.cpp @@ -201,6 +201,7 @@ void Steam_GameServer::LogOff() call_servers_disconnected = true; } + policy_response_called = false; logged_in = false; } @@ -960,10 +961,15 @@ bool Steam_GameServer::GSSendUserStatusResponse( CSteamID steamID, int nSecondsC bool Steam_GameServer::Obsolete_GSSetStatus( int32 nAppIdServed, uint32 unServerFlags, int cPlayers, int cPlayersMax, int cBotPlayers, int unGamePort, const char *pchServerName, const char *pchGameDir, const char *pchMapName, const char *pchVersion ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - return false; + set_version(pchVersion); + server_data.set_game_dir(pchGameDir); + flags = unServerFlags; + + UpdateServerStatus(cPlayers, cPlayersMax, cBotPlayers, pchServerName, "", pchMapName); + return true; } bool Steam_GameServer::GSUpdateStatus( int cPlayers, int cPlayersMax, int cBotPlayers, const char *pchServerName, const char *pchMapName ) diff --git a/dll/steam_user.cpp b/dll/steam_user.cpp index 0d942e4c..263040ac 100644 --- a/dll/steam_user.cpp +++ b/dll/steam_user.cpp @@ -144,7 +144,17 @@ bool Steam_User::SetEmail( const char *pchEmail ) int Steam_User::GetSteamGameConnectToken( void *pBlob, int cbMaxBlob ) { PRINT_DEBUG_ENTRY(); - return 0; + std::lock_guard lock(global_mutex); + + if (cbMaxBlob < STEAM_TICKET_MIN_SIZE) return 0; + if (!pBlob) return 0; + + uint32 out_size = STEAM_AUTH_TICKET_SIZE; + auth_manager->getTicketData(pBlob, cbMaxBlob, &out_size); + + if (out_size > STEAM_AUTH_TICKET_SIZE) + return 0; + return out_size; } bool Steam_User::SetRegistryString( EConfigSubTree eRegistrySubTree, const char *pchKey, const char *pchValue ) @@ -259,19 +269,18 @@ bool Steam_User::GetRegistryInt( EConfigSubTree eRegistrySubTree, const char *pc // // return value - returns the number of bytes written to pBlob. If the return is 0, then the buffer passed in was too small, and the call has failed // The contents of pBlob should then be sent to the game server, for it to use to complete the authentication process. - -//steam returns 206 bytes -#define INITIATE_GAME_CONNECTION_TICKET_SIZE 206 - int Steam_User::InitiateGameConnection( void *pAuthBlob, int cbMaxAuthBlob, CSteamID steamIDGameServer, uint32 unIPServer, uint16 usPortServer, bool bSecure ) { PRINT_DEBUG("%i %llu %u %u %u %p", cbMaxAuthBlob, steamIDGameServer.ConvertToUint64(), unIPServer, usPortServer, bSecure, pAuthBlob); std::lock_guard lock(global_mutex); - if (cbMaxAuthBlob < INITIATE_GAME_CONNECTION_TICKET_SIZE) return 0; + + if (cbMaxAuthBlob < STEAM_TICKET_MIN_SIZE) return 0; if (!pAuthBlob) return 0; - uint32 out_size = INITIATE_GAME_CONNECTION_TICKET_SIZE; - auth_manager->getTicketData(pAuthBlob, INITIATE_GAME_CONNECTION_TICKET_SIZE, &out_size); - if (out_size > INITIATE_GAME_CONNECTION_TICKET_SIZE) + + uint32 out_size = STEAM_AUTH_TICKET_SIZE; + auth_manager->getTicketData(pAuthBlob, cbMaxAuthBlob, &out_size); + + if (out_size > STEAM_AUTH_TICKET_SIZE) return 0; return out_size; }