Try to find CCMInterface if not yet found. Called from OnSendPkt on each invocation until successful. Once found, g_cmInterface is stable for the session.
| 1033 | // Try to find CCMInterface if not yet found. Called from OnSendPkt on each invocation |
| 1034 | // until successful. Once found, g_cmInterface is stable for the session. |
| 1035 | static void TryFindCCMInterface() { |
| 1036 | if (g_cmInterfaceFound.load(std::memory_order_acquire)) return; |
| 1037 | |
| 1038 | void* ccm = FindCCMInterface(); |
| 1039 | if (!ccm) return; |
| 1040 | |
| 1041 | // Claim first-finder atomically. Write pointer before flag (release ordering). |
| 1042 | bool expected = false; |
| 1043 | g_cmInterface.store(ccm, std::memory_order_release); |
| 1044 | if (!g_cmInterfaceFound.compare_exchange_strong(expected, true, |
| 1045 | std::memory_order_acq_rel, std::memory_order_acquire)) { |
| 1046 | return; // another thread already found it |
| 1047 | } |
| 1048 | |
| 1049 | LOG("[CCM] Found real CCMInterface: %p", ccm); |
| 1050 | |
| 1051 | // Log details for debugging (wrapped in SEH - raw pointer dereferences for diagnostics only) |
| 1052 | __try { |
| 1053 | uintptr_t* pEngineGlobal = (uintptr_t*)SC_RESOLVE(globalEngine); |
| 1054 | uintptr_t engine = *pEngineGlobal; |
| 1055 | uint32_t handle = *(uint32_t*)(engine + ENGINE_OFF_GLOBAL_HANDLE); |
| 1056 | |
| 1057 | LOG("[CCM] CSteamEngine: %p (global at sc+0x%X)", (void*)engine, SC_RVA_GLOBAL_ENGINE); |
| 1058 | LOG("[CCM] Global user handle: %u", handle); |
| 1059 | LOG("[CCM] Vtable: %p (RVA=0x%llX) -- MATCHES CCMInterface::vftable", |
| 1060 | (void*)(*(uintptr_t*)ccm), (uint64_t)SC_RVA_CCMINTERFACE_VT); |
| 1061 | } __except(EXCEPTION_EXECUTE_HANDLER) { |
| 1062 | LOG("[CCM] WARNING: exception reading engine globals (code=0x%lX)", GetExceptionCode()); |
| 1063 | } |
| 1064 | |
| 1065 | // Resolve BRouteMsgToJob bypass function pointers (computed from base + RVA, no dereferences) |
| 1066 | g_wrapPacket = (WrapPacketFn)SC_RESOLVE(wrapPacket); |
| 1067 | g_bRouteMsgToJob = (BRouteMsgToJobFn)SC_RESOLVE(bRouteMsgToJob); |
| 1068 | g_releaseWrapped = (ReleaseWrappedFn)SC_RESOLVE(releaseWrapped); |
| 1069 | g_refCountHelper = (RefCountHelperFn)SC_RESOLVE(refCountHelper); |
| 1070 | g_refCountGlobalPtr = (volatile int64_t**)SC_RESOLVE(refCountGlobal); |
| 1071 | LOG("[CCM] WrapPacket=%p BRouteMsgToJob=%p ReleaseWrapped=%p", |
| 1072 | g_wrapPacket, g_bRouteMsgToJob, g_releaseWrapped); |
| 1073 | |
| 1074 | // Additional diagnostic logging (dereferences pointers, wrap in SEH) |
| 1075 | __try { |
| 1076 | LOG("[CCM] RefCountHelper=%p RefCountGlobal=%p (*=%p)", |
| 1077 | g_refCountHelper, g_refCountGlobalPtr, |
| 1078 | g_refCountGlobalPtr ? (void*)*g_refCountGlobalPtr : nullptr); |
| 1079 | uintptr_t engine = *(uintptr_t*)SC_RESOLVE(globalEngine); |
| 1080 | LOG("[CCM] CJobMgr (engine+%u)=%p ConnCtx (ccm+%u)=%p", |
| 1081 | ENGINE_OFF_JOBMGR, (void*)(engine + ENGINE_OFF_JOBMGR), |
| 1082 | CCM_OFF_CONN_CONTEXT, *(void**)((uintptr_t)ccm + CCM_OFF_CONN_CONTEXT)); |
| 1083 | } __except(EXCEPTION_EXECUTE_HANDLER) { |
| 1084 | LOG("[CCM] WARNING: exception during extended diagnostics (code=0x%lX)", GetExceptionCode()); |
| 1085 | } |
| 1086 | |
| 1087 | // Install service-method vtable hook (Approach E) now that we have steamclient base |
| 1088 | if (!g_vtableHookInstalled.load(std::memory_order_acquire) && HasNamespaceApps()) { |
| 1089 | InstallServiceMethodHook(); |
| 1090 | } |
| 1091 | } |
| 1092 |
no test coverage detected