mirror of
https://github.com/ValveSoftware/Proton.git
synced 2025-05-17 08:58:06 +03:00
steamclient: Call Windows vtable callbacks with the correct arg count
The x86 Windows ABI pushes all arguments onto the stack in the caller and expects the callee to clean them up. The mismatch in parameter counts thus causes the stack to be offset after calling these callbacks leading to a crash.
This commit is contained in:
parent
454533f7e3
commit
42f2d563a4
@ -401,25 +401,28 @@ void execute_pending_callbacks(void)
|
|||||||
TRACE( "CALL_CDECL_FUNC_DATA func %p, data %p.\n", params.callback->call_cdecl_func_data.pFunc, params.callback->call_cdecl_func_data.data );
|
TRACE( "CALL_CDECL_FUNC_DATA func %p, data %p.\n", params.callback->call_cdecl_func_data.pFunc, params.callback->call_cdecl_func_data.data );
|
||||||
params.callback->call_cdecl_func_data.pFunc( params.callback->call_cdecl_func_data.data );
|
params.callback->call_cdecl_func_data.pFunc( params.callback->call_cdecl_func_data.data );
|
||||||
break;
|
break;
|
||||||
case CALL_IFACE_VTABLE_0:
|
#define CALL_VTABLE_CASES(method) \
|
||||||
TRACE( "CALL_IFACE_VTABLE_0 iface %p, arg0 %#I64x, arg1 %#I64x, arg2 %#I64x.\n", params.callback->call_iface_vtable.iface,
|
case CALL_IFACE_VTABLE_ ## method ## _0: \
|
||||||
params.callback->call_iface_vtable.arg0, params.callback->call_iface_vtable.arg1, params.callback->call_iface_vtable.arg2 );
|
TRACE( "CALL_IFACE_VTABLE_" #method "_0 iface %p.\n", params.callback->call_iface_vtable.iface ); \
|
||||||
CALL_VTBL_FUNC( params.callback->call_iface_vtable.iface, 0, void, (void *, intptr_t, intptr_t, intptr_t), (params.callback->call_iface_vtable.iface,
|
CALL_VTBL_FUNC( params.callback->call_iface_vtable.iface, method * 4, void, (void *), (params.callback->call_iface_vtable.iface) ); \
|
||||||
params.callback->call_iface_vtable.arg0, params.callback->call_iface_vtable.arg1, params.callback->call_iface_vtable.arg2) );
|
break; \
|
||||||
break;
|
case CALL_IFACE_VTABLE_ ## method ## _1: \
|
||||||
case CALL_IFACE_VTABLE_1:
|
TRACE( "CALL_IFACE_VTABLE_" #method "_1 iface %p, arg0 %#I64x.\n", params.callback->call_iface_vtable.iface, \
|
||||||
TRACE( "CALL_IFACE_VTABLE_1 iface %p, arg0 %#I64x, arg1 %#I64x, arg2 %#I64x.\n", params.callback->call_iface_vtable.iface,
|
params.callback->call_iface_vtable.arg0 ); \
|
||||||
params.callback->call_iface_vtable.arg0, params.callback->call_iface_vtable.arg1, params.callback->call_iface_vtable.arg2 );
|
CALL_VTBL_FUNC( params.callback->call_iface_vtable.iface, method * 4, void, (void *, intptr_t), (params.callback->call_iface_vtable.iface, \
|
||||||
CALL_VTBL_FUNC( params.callback->call_iface_vtable.iface, 4, void, (void *, intptr_t, intptr_t, intptr_t), (params.callback->call_iface_vtable.iface,
|
params.callback->call_iface_vtable.arg0) ); \
|
||||||
params.callback->call_iface_vtable.arg0, params.callback->call_iface_vtable.arg1, params.callback->call_iface_vtable.arg2) );
|
break; \
|
||||||
break;
|
case CALL_IFACE_VTABLE_ ## method ## _2: \
|
||||||
case CALL_IFACE_VTABLE_2:
|
TRACE( "CALL_IFACE_VTABLE_" #method "_2 iface %p, arg0 %#I64x, arg1 %#I64x.\n", params.callback->call_iface_vtable.iface, \
|
||||||
TRACE( "CALL_IFACE_VTABLE_2 iface %p, arg0 %#I64x, arg1 %#I64x, arg2 %#I64x.\n", params.callback->call_iface_vtable.iface,
|
params.callback->call_iface_vtable.arg0, params.callback->call_iface_vtable.arg1 ); \
|
||||||
params.callback->call_iface_vtable.arg0, params.callback->call_iface_vtable.arg1, params.callback->call_iface_vtable.arg2 );
|
CALL_VTBL_FUNC( params.callback->call_iface_vtable.iface, method * 4, void, (void *, intptr_t, intptr_t), (params.callback->call_iface_vtable.iface, \
|
||||||
CALL_VTBL_FUNC( params.callback->call_iface_vtable.iface, 8, void, (void *, intptr_t, intptr_t, intptr_t), (params.callback->call_iface_vtable.iface,
|
params.callback->call_iface_vtable.arg0, params.callback->call_iface_vtable.arg1) ); \
|
||||||
params.callback->call_iface_vtable.arg0, params.callback->call_iface_vtable.arg1, params.callback->call_iface_vtable.arg2) );
|
break
|
||||||
break;
|
|
||||||
|
|
||||||
|
CALL_VTABLE_CASES(0);
|
||||||
|
CALL_VTABLE_CASES(1);
|
||||||
|
CALL_VTABLE_CASES(2);
|
||||||
|
#undef CALL_VTABLE_CASES
|
||||||
case CALL_IFACE_VTABLE_0_SERVER_RESPONDED:
|
case CALL_IFACE_VTABLE_0_SERVER_RESPONDED:
|
||||||
TRACE( "CALL_IFACE_VTABLE_0_SERVER_RESPONDED iface %p, server %p.\n", params.callback->server_responded.iface,
|
TRACE( "CALL_IFACE_VTABLE_0_SERVER_RESPONDED iface %p, server %p.\n", params.callback->server_responded.iface,
|
||||||
params.callback->server_responded.server );
|
params.callback->server_responded.server );
|
||||||
|
@ -647,17 +647,17 @@ struct SteamMatchmakingServerListResponse_099u : u_ISteamMatchmakingServerListRe
|
|||||||
|
|
||||||
void SteamMatchmakingServerListResponse_099u::ServerResponded( int32_t iServer )
|
void SteamMatchmakingServerListResponse_099u::ServerResponded( int32_t iServer )
|
||||||
{
|
{
|
||||||
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_0, (intptr_t)iServer, 0, 0 );
|
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_0_1, (intptr_t)iServer, 0, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamMatchmakingServerListResponse_099u::ServerFailedToRespond( int32_t iServer )
|
void SteamMatchmakingServerListResponse_099u::ServerFailedToRespond( int32_t iServer )
|
||||||
{
|
{
|
||||||
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_1, (intptr_t)iServer, 0, 0 );
|
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_1_1, (intptr_t)iServer, 0, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamMatchmakingServerListResponse_099u::RefreshComplete( uint32_t response )
|
void SteamMatchmakingServerListResponse_099u::RefreshComplete( uint32_t response )
|
||||||
{
|
{
|
||||||
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_2, (intptr_t)response, 0, 0 );
|
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_2_1, (intptr_t)response, 0, 0 );
|
||||||
TRACE( "RefreshComplete this %p, w_iface %p.\n", this, this->w_iface );
|
TRACE( "RefreshComplete this %p, w_iface %p.\n", this, this->w_iface );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -701,17 +701,17 @@ class callback_obj_tracker<SteamMatchmakingServerListResponse_106> SteamMatchmak
|
|||||||
|
|
||||||
void SteamMatchmakingServerListResponse_106::ServerResponded( void *hRequest, int32_t iServer )
|
void SteamMatchmakingServerListResponse_106::ServerResponded( void *hRequest, int32_t iServer )
|
||||||
{
|
{
|
||||||
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_0, (intptr_t)hRequest, (intptr_t)iServer, 0 );
|
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_0_2, (intptr_t)hRequest, (intptr_t)iServer, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamMatchmakingServerListResponse_106::ServerFailedToRespond( void *hRequest, int32_t iServer )
|
void SteamMatchmakingServerListResponse_106::ServerFailedToRespond( void *hRequest, int32_t iServer )
|
||||||
{
|
{
|
||||||
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_1, (intptr_t)hRequest, (intptr_t)iServer, 0 );
|
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_1_2, (intptr_t)hRequest, (intptr_t)iServer, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamMatchmakingServerListResponse_106::RefreshComplete( void *hRequest, uint32_t response )
|
void SteamMatchmakingServerListResponse_106::RefreshComplete( void *hRequest, uint32_t response )
|
||||||
{
|
{
|
||||||
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_2, (intptr_t)hRequest, (intptr_t)response, 0 );
|
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_2_2, (intptr_t)hRequest, (intptr_t)response, 0 );
|
||||||
TRACE( "RefreshComplete this %p, w_iface %p.\n", this, this->w_iface );
|
TRACE( "RefreshComplete this %p, w_iface %p.\n", this, this->w_iface );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,7 +744,7 @@ void SteamMatchmakingPingResponse::ServerResponded( gameserveritem_t_105 *server
|
|||||||
|
|
||||||
void SteamMatchmakingPingResponse::ServerFailedToRespond(void)
|
void SteamMatchmakingPingResponse::ServerFailedToRespond(void)
|
||||||
{
|
{
|
||||||
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_1, 0, 0, 0 );
|
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_1_0, 0, 0, 0 );
|
||||||
TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
|
TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
|
||||||
free_callback_obj(this);
|
free_callback_obj(this);
|
||||||
}
|
}
|
||||||
@ -776,14 +776,14 @@ void SteamMatchmakingPlayersResponse::AddPlayerToList(const char *pchName, int n
|
|||||||
|
|
||||||
void SteamMatchmakingPlayersResponse::PlayersFailedToRespond(void)
|
void SteamMatchmakingPlayersResponse::PlayersFailedToRespond(void)
|
||||||
{
|
{
|
||||||
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_1, 0, 0, 0 );
|
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_1_0, 0, 0, 0 );
|
||||||
TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
|
TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
|
||||||
free_callback_obj(this);
|
free_callback_obj(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamMatchmakingPlayersResponse::PlayersRefreshComplete(void)
|
void SteamMatchmakingPlayersResponse::PlayersRefreshComplete(void)
|
||||||
{
|
{
|
||||||
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_2, 0, 0, 0 );
|
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_2_0, 0, 0, 0 );
|
||||||
TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
|
TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
|
||||||
free_callback_obj(this);
|
free_callback_obj(this);
|
||||||
}
|
}
|
||||||
@ -815,14 +815,14 @@ void SteamMatchmakingRulesResponse::RulesResponded(const char *pchRule, const ch
|
|||||||
|
|
||||||
void SteamMatchmakingRulesResponse::RulesFailedToRespond(void)
|
void SteamMatchmakingRulesResponse::RulesFailedToRespond(void)
|
||||||
{
|
{
|
||||||
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_1, 0, 0, 0 );
|
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_1_0, 0, 0, 0 );
|
||||||
TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
|
TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
|
||||||
free_callback_obj(this);
|
free_callback_obj(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamMatchmakingRulesResponse::RulesRefreshComplete(void)
|
void SteamMatchmakingRulesResponse::RulesRefreshComplete(void)
|
||||||
{
|
{
|
||||||
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_2, 0, 0, 0 );
|
queue_vtable_callback( this->w_iface, CALL_IFACE_VTABLE_2_0, 0, 0, 0 );
|
||||||
TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
|
TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
|
||||||
free_callback_obj(this);
|
free_callback_obj(this);
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,15 @@ enum callback_type
|
|||||||
SOCKETS_DEBUG_OUTPUT = 1,
|
SOCKETS_DEBUG_OUTPUT = 1,
|
||||||
WARNING_MESSAGE_HOOK,
|
WARNING_MESSAGE_HOOK,
|
||||||
CALL_CDECL_FUNC_DATA,
|
CALL_CDECL_FUNC_DATA,
|
||||||
CALL_IFACE_VTABLE_0,
|
CALL_IFACE_VTABLE_0_0,
|
||||||
CALL_IFACE_VTABLE_1,
|
CALL_IFACE_VTABLE_0_1,
|
||||||
CALL_IFACE_VTABLE_2,
|
CALL_IFACE_VTABLE_0_2,
|
||||||
|
CALL_IFACE_VTABLE_1_0,
|
||||||
|
CALL_IFACE_VTABLE_1_1,
|
||||||
|
CALL_IFACE_VTABLE_1_2,
|
||||||
|
CALL_IFACE_VTABLE_2_0,
|
||||||
|
CALL_IFACE_VTABLE_2_1,
|
||||||
|
CALL_IFACE_VTABLE_2_2,
|
||||||
CALL_IFACE_VTABLE_0_SERVER_RESPONDED,
|
CALL_IFACE_VTABLE_0_SERVER_RESPONDED,
|
||||||
CALL_IFACE_VTABLE_0_ADD_PLAYER_TO_LIST,
|
CALL_IFACE_VTABLE_0_ADD_PLAYER_TO_LIST,
|
||||||
CALL_IFACE_VTABLE_0_RULES_RESPONDED,
|
CALL_IFACE_VTABLE_0_RULES_RESPONDED,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user