From 40a627a4fb71e121fceec4890927bad54bd9463d Mon Sep 17 00:00:00 2001 From: OpenSteam001 <248184252+OpenSteam001@users.noreply.github.com> Date: Sat, 30 May 2026 22:52:13 +0800 Subject: [PATCH] Fix Lua library refresh on startup and bulk deletion --- src/Hook/Hooks_Package.cpp | 85 +++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/src/Hook/Hooks_Package.cpp b/src/Hook/Hooks_Package.cpp index 8bfde27..1e265d2 100644 --- a/src/Hook/Hooks_Package.cpp +++ b/src/Hook/Hooks_Package.cpp @@ -2,19 +2,23 @@ #include "HookMacros.h" #include "Hooks_SteamUI.h" #include "dllmain.h" +#include "Utils/VehCommon.h" +#include namespace { RESOLVE_FUNC(CUtlMemoryGrow, void*, CUtlVector*, int); RESOLVE_FUNC(MarkLicenseAsChanged, int64, void*, uint32, bool); RESOLVE_FUNC(ProcessPendingLicenseUpdates, bool, void*); + CAPTURE_THIS_FUNC(GetPackageInfo, PackageInfo*,g_pCPackageInfo,void* pThis, uint32 packageId, uint64 accessToken); + void* g_pCUser = nullptr; - void* g_pCPackageInfo = nullptr; PackageInfo* g_pInjectedPackageInfo = nullptr; bool g_licenseInitialized = false; bool g_licenseRefreshPending = false; constexpr PackageId_t kInjectedPackageId = 0; + constexpr uint64_t kInjectedPkgAccessToken = 10660652434190618804ull; bool MarkLicenseAsChangedAndProcessUpdates() { if (!g_pCUser || !oMarkLicenseAsChanged || !oProcessPendingLicenseUpdates) { @@ -43,10 +47,12 @@ namespace { } bool InitFakeLicenseOnce(PackageInfo* pPkg) { - if (!pPkg) { - LOG_PACKAGE_WARN("InitFakeLicense: null PackageInfo pointer"); + // check package status before injecting + if (pPkg->Status != EPackageStatus::Available) { + LOG_PACKAGE_WARN("InitFakeLicenseOnce: package status is not Available ({}), skipping injection", static_cast(pPkg->Status)); return false; } + // Inject all depots from config into the fake license. std::vector appIds = LuaConfig::GetAllDepotIds(); if (!appIds.empty()) { @@ -67,46 +73,21 @@ namespace { return true; } - HOOK_FUNC(LoadPackage, bool, PackageInfo* pInfo, uint8* sha1, int32 cn, void* p4) { - bool result = oLoadPackage(pInfo, sha1, cn, p4); - - if (pInfo->PackageId == 0) { - std::vector appIds = LuaConfig::GetAllDepotIds(); - if (!appIds.empty()) { - uint32 oldSize = pInfo->AppIdVec.m_Size; - uint32 numToAdd = static_cast(appIds.size()); - LOG_PACKAGE_INFO("LoadPackage(PackageId={}): adding {} apps, oldSize={}", kInjectedPackageId, numToAdd, oldSize); - if (!CUtlMemoryGrowWrap(&pInfo->AppIdVec, numToAdd)) { - LOG_PACKAGE_WARN("LoadPackage(PackageId={}): failed to grow AppId vector", kInjectedPackageId); - return result; - } - for (uint32 i = 0; i < numToAdd; i++) - pInfo->AppIdVec.m_Memory.m_pMemory[oldSize + i] = appIds[i]; - } - } - - return result; - } - - HOOK_FUNC(GetPackageInfo, PackageInfo*, void* pPackageInfoCache, uint32 packageId, uint64 accessToken) { - if (!g_pCPackageInfo) { - g_pCPackageInfo = pPackageInfoCache; - LOG_PACKAGE_DEBUG("GetPackageInfo: captured CPackageInfo {}", g_pCPackageInfo); - } - // LOG_PACKAGE_TRACE("GetPackageInfo: package cache {}, packageId {}, accessToken {}", pPackageInfoCache, packageId, accessToken); - PackageInfo* pPkg = oGetPackageInfo(pPackageInfoCache, packageId, accessToken); - if (packageId == 0 && pPkg) { - if(!g_pInjectedPackageInfo) { - g_pInjectedPackageInfo = pPkg; - LOG_PACKAGE_INFO("GetPackageInfo: g_pInjectedPackageInfo set to {}", (void*)g_pInjectedPackageInfo); - } - if(!g_licenseInitialized) { - InitFakeLicenseOnce(pPkg); + bool TryInitFakeLicenseOnce() { + if (g_licenseInitialized) return true; + if(CAPTURE_READY(GetPackageInfo)){ + PackageInfo* pPkg = oGetPackageInfo(g_pCPackageInfo, kInjectedPackageId, kInjectedPkgAccessToken); + if(!pPkg) { + LOG_PACKAGE_WARN("TryInitFakeLicenseOnce: GetPackageInfo returned null for injected package"); + return false; } + if(!g_pInjectedPackageInfo) g_pInjectedPackageInfo = pPkg; + return InitFakeLicenseOnce(pPkg); } - return pPkg; + return false; } + HOOK_FUNC(CheckAppOwnership, bool, void* pObj, AppId_t appId, AppOwnership* pOwn) { if (!g_pCUser) { g_pCUser = pObj; @@ -114,7 +95,7 @@ namespace { } bool result = oCheckAppOwnership(pObj, appId, pOwn); - TryProcessPendingLicenseRefresh(); + TryInitFakeLicenseOnce(); // LOG_PACKAGE_TRACE("CheckAppOwnership: AppId={} result={} {}", appId, result, pOwn->DebugString()); if (LuaConfig::HasDepot(appId,false)) { @@ -140,21 +121,22 @@ namespace Hooks_Package { RESOLVE_C(MarkLicenseAsChanged); RESOLVE_C(ProcessPendingLicenseUpdates); + ARM_CAPTURE_C(GetPackageInfo); + HOOK_BEGIN(); - // INSTALL_HOOK_C(LoadPackage); - INSTALL_HOOK_C(GetPackageInfo); INSTALL_HOOK_C(CheckAppOwnership); HOOK_END(); } void Uninstall() { UNHOOK_BEGIN(); - // UNINSTALL_HOOK_C(LoadPackage); - UNINSTALL_HOOK_C(GetPackageInfo); UNINSTALL_HOOK_C(CheckAppOwnership); UNHOOK_END(); } + constexpr size_t kBatchSize = 50; + constexpr DWORD kBatchSleepMs = 20; + void NotifyLicenseChanged() { PackageInfo* pPkg = g_pInjectedPackageInfo; if (!pPkg) { @@ -164,16 +146,20 @@ namespace Hooks_Package { // ── Remove depots that were unloaded ── std::vector removals = LuaConfig::TakePendingRemovals(); + LOG_PACKAGE_DEBUG("NotifyLicenseChanged: processing {} removals", removals.size()); uint32_t removedCount = 0; for (AppId_t id : removals) { if (pPkg->AppIdVec.FindAndFastRemove(id)) { ++removedCount; LOG_PACKAGE_DEBUG("NotifyLicenseChanged: removed AppId {}", id); + }else { + LOG_PACKAGE_WARN("NotifyLicenseChanged: AppId {} not found in package AppIdVec during removal", id); } } // ── Add depots that are newly loaded ── std::vector additions = LuaConfig::TakePendingAdditions(); + LOG_PACKAGE_DEBUG("NotifyLicenseChanged: processing {} additions", additions.size()); if (!additions.empty()) { uint32_t oldSize = pPkg->AppIdVec.m_Size; if (CUtlMemoryGrowWrap(&pPkg->AppIdVec, additions.size())) { @@ -181,6 +167,8 @@ namespace Hooks_Package { pPkg->AppIdVec.m_Memory.m_pMemory[oldSize + i] = additions[i]; LOG_PACKAGE_DEBUG("NotifyLicenseChanged: inserted AppId {} at [{}]", additions[i], oldSize + i); } + }else { + LOG_PACKAGE_WARN("NotifyLicenseChanged: failed to grow AppId vector for additions"); } } @@ -196,10 +184,13 @@ namespace Hooks_Package { } LOG_PACKAGE_INFO("NotifyLicenseChanged: {} added, {} removed", additions.size(), removedCount); - // CSteamUIAppController caches its own AppOverview entries and doesn't - // re-query subscription state on package mutation; remove them - // explicitly so the library UI reflects the dropped license. + // every kBatchSize ids changed, sleep kBatchSleepMs milliseconds + size_t i = 0; for (AppId_t id : removals) { + if (++i % kBatchSize == 0) { + LOG_PACKAGE_DEBUG("NotifyLicenseChanged: processed {} removals, sleeping for {} ms...", i, kBatchSleepMs); + std::this_thread::sleep_for(std::chrono::milliseconds(kBatchSleepMs)); + } Hooks_SteamUI::RemoveAppAndSendChange(id); } }