MCPcopy Create free account
hub / github.com/Selectively11/CloudRedirect / ServiceMethodHook

Function ServiceMethodHook

src/platform/win/cloud_intercept.cpp:1944–2282  ·  view source on GitHub ↗

The actual vtable hook function - replaces CClientUnifiedServiceTransport::vtable[5]

Source from the content-addressed store, hash-verified

1942
1943// The actual vtable hook function - replaces CClientUnifiedServiceTransport::vtable[5]
1944static bool __fastcall ServiceMethodHook(void* thisptr, const char* methodName,
1945 void* request, void* response, int64_t* flags) {
1946 HookGuard guard;
1947 if (g_shuttingDown.load(std::memory_order_acquire))
1948 return g_originalSlot5(thisptr, methodName, request, response, flags);
1949 if (!methodName) {
1950 return g_originalSlot5(thisptr, methodName, request, response, flags);
1951 }
1952
1953 if (g_parentalBypassPlaytime.load() &&
1954 strcmp(methodName, "Parental.GetSignedParentalSettings#1") == 0) {
1955 bool result = g_originalSlot5(thisptr, methodName, request, response, flags);
1956 if (result && response) {
1957 void* respBody = *(void**)((uintptr_t)response + 48);
1958 if (respBody) {
1959 auto respBytes = SerializeBodyToBytes(respBody);
1960 auto respFields = PB::Parse(respBytes.data(), respBytes.size());
1961 const PB::Field* sf = PB::FindField(respFields, 1);
1962 if (sf && sf->wireType == PB::LengthDelimited && sf->data) {
1963 auto stripped = ParentalBypass::StripPlaytimeRestrictions(sf->data, sf->dataLen);
1964 PB::Writer newResp;
1965 newResp.WriteBytes(1, stripped.data(), stripped.size());
1966 for (const auto& f : respFields) {
1967 if (f.fieldNum == 1) continue;
1968 if (f.wireType == PB::Varint) newResp.WriteVarint(f.fieldNum, f.varintVal);
1969 else if (f.wireType == PB::Fixed64) newResp.WriteFixed64(f.fieldNum, f.varintVal);
1970 else if (f.wireType == PB::LengthDelimited) newResp.WriteBytes(f.fieldNum, f.data, f.dataLen);
1971 }
1972 if (ParseBytesToBody(respBody, newResp.Data().data(), newResp.Size()))
1973 LOG("[Parental] Stripped restrictions from GetSignedParentalSettings (slot5)");
1974 }
1975 }
1976 }
1977 return result;
1978 }
1979
1980 // ---- Native stats / playtime service RPCs --------------------------------
1981 // Player.GetUserStats#1: answer namespace apps from our store for the achievement page.
1982 if (strcmp(methodName, StatsHandlers::RPC_GET_USER_STATS) == 0
1983 && (g_cloudSaveOnly.load(std::memory_order_relaxed)
1984 ? MetadataSync::schemaFetch.load(std::memory_order_relaxed)
1985 : MetadataSync::SchemaFetchEnabled())) {
1986 if (request && response) {
1987 void* reqBody = *(void**)((uintptr_t)request + 48);
1988 if (reqBody) {
1989 auto reqBytes = SerializeBodyToBytes(reqBody);
1990 auto reqFields = PB::Parse(reqBytes.data(), reqBytes.size());
1991 // appid = field 2 in CPlayer_GetUserStats_Request
1992 uint32_t appId = 0;
1993 if (auto* f = PB::FindField(reqFields, 2)) appId = (uint32_t)f->varintVal;
1994 LOG("[Stats] slot5 GetUserStats seen: app=%u namespace=%d", appId, IsNamespaceApp(appId) ? 1 : 0);
1995 if (appId != 0 && IsNamespaceApp(appId)) {
1996 auto res = StatsHandlers::HandleGetUserStats(appId, reqFields);
1997 void* respBody = *(void**)((uintptr_t)response + 48);
1998 if (respBody && res.body.Size() > 0 &&
1999 ParseBytesToBody(respBody, res.body.Data().data(), res.body.Size())) {
2000 if (flags) *flags = 0;
2001 LOG("[Stats] GetUserStats app=%u handled locally (%zu bytes)",

Callers

nothing calls this directly

Calls 15

SerializeBodyToBytesFunction · 0.85
FindFieldFunction · 0.85
ParseBytesToBodyFunction · 0.85
SchemaFetchEnabledFunction · 0.85
HandleGetUserStatsFunction · 0.85
PlaytimeEnabledFunction · 0.85
HandleGetLastPlayedTimesFunction · 0.85
ExtractAppIdFunction · 0.85
SpyLogFieldsFunction · 0.85
SpyLogChangelistResponseFunction · 0.85

Tested by

no test coverage detected