diff --git a/lsteamclient/steamclient_main.c b/lsteamclient/steamclient_main.c index 321ef745..7959d0d5 100644 --- a/lsteamclient/steamclient_main.c +++ b/lsteamclient/steamclient_main.c @@ -1,12 +1,14 @@ #include #include #include -#include #include #include #include #include +#define __USE_GNU +#include + #include "windef.h" #include "winbase.h" #include "winnls.h" @@ -42,6 +44,37 @@ static pthread_cond_t callback_queue_callback_event; static pthread_cond_t callback_queue_ready_event; static pthread_cond_t callback_queue_complete_event; +static void * (WINAPI *p_NtCurrentTeb)(void); + +static void init_ntdll_so_funcs(void) +{ + Dl_info info; + UINT64 unix_funcs; + unsigned int status; + void *ntdll; + + status = NtQueryVirtualMemory(GetCurrentProcess(), GetModuleHandleW(L"ntdll.dll"), (MEMORY_INFORMATION_CLASS)1000 /*MemoryWineUnixFuncs*/, + &unix_funcs, sizeof(unix_funcs), NULL); + if (status) + { + fprintf(stderr, "err:lsteamclient:init_ntdll_so_funcs NtQueryVirtualMemory status %#x.\n", status); + return; + } + if (!dladdr((void *)(ULONG_PTR)unix_funcs, &info)) + { + fprintf(stderr, "err:lsteamclient:init_ntdll_so_funcs dladdr failed.\n"); + return; + } + ntdll = dlopen(info.dli_fname, RTLD_NOW); + if (!ntdll) + { + fprintf(stderr, "err:lsteamclient:init_ntdll_so_funcs could not find ntdll.so.\n"); + return; + } + p_NtCurrentTeb = dlsym(ntdll, "NtCurrentTeb"); + dlclose(ntdll); +} + BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) { TRACE("(%p, %u, %p)\n", instance, reason, reserved); @@ -51,6 +84,7 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(instance); steam_overlay_event = CreateEventA(NULL, TRUE, FALSE, "__wine_steamclient_GameOverlayActivated"); + init_ntdll_so_funcs(); break; case DLL_PROCESS_DETACH: if (callback_thread_handle) @@ -76,6 +110,13 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) return TRUE; } +BOOL is_native_thread(void) +{ + if (!p_NtCurrentTeb) + return TRUE; + return !p_NtCurrentTeb(); +} + void sync_environment(void) { static const char *steamapi_envs[] = @@ -743,7 +784,12 @@ static DWORD WINAPI callback_thread(void *dummy) cb_data.steam_api_warning_hook.msg); callback_complete(cookie); break; - + case STEAM_API_CALLBACK_ONE_PARAM: + TRACE("STEAM_API_CALLBACK_ONE_PARAM func %p, param %p.\n", + cb_data.func, cb_data.steam_api_callback_one_param.param); + ((void (WINAPI *)(void *))cb_data.func)(cb_data.steam_api_callback_one_param.param); + callback_complete(cookie); + break; default: ERR("Unexpected callback type %u.\n", cb_data.type); break; diff --git a/lsteamclient/steamclient_manual_common.cpp b/lsteamclient/steamclient_manual_common.cpp index 8368a28d..0ac2a941 100644 --- a/lsteamclient/steamclient_manual_common.cpp +++ b/lsteamclient/steamclient_manual_common.cpp @@ -88,13 +88,25 @@ static void __attribute__((ms_abi)) win_Release(struct winSteamNetworkingMessage static void lin_FreeData(struct SteamNetworkingMessage_t *lin_msg) { struct msg_wrapper *msg = msg_wrapper_from_lin(lin_msg); + struct callback_data cb_data; - TRACE("%p\n", msg); if (!msg) return; - if(msg->win_msg.m_pfnFreeData) + if (!msg->win_msg.m_pfnFreeData) + return; + + if (!is_native_thread()) + { + TRACE("msg %p, callback %p.\n", msg, msg->win_msg.m_pfnFreeData); ((void (__attribute__((ms_abi))*)(struct winSteamNetworkingMessage_t_153a *))msg->win_msg.m_pfnFreeData)(&msg->win_msg); + return; + } + + cb_data.type = STEAM_API_CALLBACK_ONE_PARAM; + cb_data.func = (void *)msg->win_msg.m_pfnFreeData; + cb_data.steam_api_callback_one_param.param = (void *)&msg->win_msg; + execute_callback(&cb_data); } void *network_message_lin_to_win_(void *msg_, unsigned int version) @@ -104,7 +116,7 @@ void *network_message_lin_to_win_(void *msg_, unsigned int version) msg = (struct msg_wrapper *)HeapAlloc(GetProcessHeap(), 0, sizeof(*msg)); - TRACE("lin_msg %p, msg %p.\n", lin_msg, msg); + TRACE("lin_msg %p, msg %p, m_cbSize %d.\n", lin_msg, msg, lin_msg->m_cbSize); msg->lin_msg = lin_msg; diff --git a/lsteamclient/steamclient_private.h b/lsteamclient/steamclient_private.h index e383bfcc..072300ab 100644 --- a/lsteamclient/steamclient_private.h +++ b/lsteamclient/steamclient_private.h @@ -75,6 +75,7 @@ enum callback_type { SOCKET_DEBUG_OUTPUT = 1, STEAM_API_WARNING_HOOK, + STEAM_API_CALLBACK_ONE_PARAM, }; struct callback_data @@ -96,10 +97,16 @@ struct callback_data const char *msg; } steam_api_warning_hook; + struct + { + void *param; + } + steam_api_callback_one_param; }; }; void execute_callback(struct callback_data *cb_data); +BOOL is_native_thread(void); #ifdef __cplusplus }