From 371d50b62e61a05a39f12795652bb7f2f42c8492 Mon Sep 17 00:00:00 2001 From: otavepto <153766569+otavepto@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:01:29 +0200 Subject: [PATCH] make sure buffer is nulled in ugc::GetItemInstallInfo() + a bunch of params check & stub code --- dll/dll/steam_remote_storage.h | 86 +++++++++------ dll/dll/steam_ugc.h | 189 +++++++++++++++++++++++++++++---- 2 files changed, 221 insertions(+), 54 deletions(-) diff --git a/dll/dll/steam_remote_storage.h b/dll/dll/steam_remote_storage.h index 3278adf4..15c7589c 100644 --- a/dll/dll/steam_remote_storage.h +++ b/dll/dll/steam_remote_storage.h @@ -36,7 +36,7 @@ struct Downloaded_File { enum DownloadSource { AfterFileShare, // attempted download after a call to Steam_Remote_Storage::FileShare() AfterSendQueryUGCRequest, // attempted download after a call to Steam_UGC::SendQueryUGCRequest() - AfterUGCDownloadToLocation, // attempted download after a call to Steam_Remote_Storage::UGCDownloadToLocation() + FromUGCDownloadToLocation, // attempted download via Steam_Remote_Storage::UGCDownloadToLocation() } source; // *** used in any case @@ -48,7 +48,7 @@ struct Downloaded_File { // *** used when source = SendQueryUGCRequest only Ugc_Remote_Storage_Bridge::QueryInfo mod_query_info; - // *** used when source = AfterUGCDownloadToLocation only + // *** used when source = FromUGCDownloadToLocation only std::string download_to_location_fullpath; }; @@ -117,7 +117,7 @@ bool FileWrite( const char *pchFile, const void *pvData, int32 cubData ) PRINT_DEBUG("Steam_Remote_Storage::FileWrite '%s' %p %u\n", pchFile, pvData, cubData); std::lock_guard lock(global_mutex); - if (!pchFile || cubData <= 0 || cubData > k_unMaxCloudFileChunkSize || !pvData) { + if (!pchFile || !pchFile[0] || cubData <= 0 || cubData > k_unMaxCloudFileChunkSize || !pvData) { return false; } @@ -131,7 +131,7 @@ int32 FileRead( const char *pchFile, void *pvData, int32 cubDataToRead ) PRINT_DEBUG("Steam_Remote_Storage::FileRead '%s' %p %i\n", pchFile, pvData, cubDataToRead); std::lock_guard lock(global_mutex); - if (!pchFile || !pvData || !cubDataToRead) return 0; + if (!pchFile || !pchFile[0] || !pvData || !cubDataToRead) return 0; int read_data = local_storage->get_data(Local_Storage::remote_storage_folder, pchFile, (char* )pvData, cubDataToRead); if (read_data < 0) read_data = 0; PRINT_DEBUG(" Read %i\n", read_data); @@ -143,7 +143,8 @@ SteamAPICall_t FileWriteAsync( const char *pchFile, const void *pvData, uint32 c { PRINT_DEBUG("Steam_Remote_Storage::FileWriteAsync '%s' %p %u\n", pchFile, pvData, cubData); std::lock_guard lock(global_mutex); - if (!pchFile || cubData > k_unMaxCloudFileChunkSize || cubData == 0 || !pvData) { + + if (!pchFile || !pchFile[0] || cubData > k_unMaxCloudFileChunkSize || cubData == 0 || !pvData) { return k_uAPICallInvalid; } @@ -161,7 +162,7 @@ SteamAPICall_t FileReadAsync( const char *pchFile, uint32 nOffset, uint32 cubToR PRINT_DEBUG("Steam_Remote_Storage::FileReadAsync '%s' %u %u\n", pchFile, nOffset, cubToRead); std::lock_guard lock(global_mutex); - if (!pchFile) return k_uAPICallInvalid; + if (!pchFile || !pchFile[0]) return k_uAPICallInvalid; unsigned int size = local_storage->file_size(Local_Storage::remote_storage_folder, pchFile); RemoteStorageFileReadAsyncComplete_t data; @@ -215,6 +216,7 @@ bool FileForget( const char *pchFile ) { PRINT_DEBUG("Steam_Remote_Storage::FileForget\n"); std::lock_guard lock(global_mutex); + if (!pchFile || !pchFile[0]) return false; return true; } @@ -223,6 +225,7 @@ bool FileDelete( const char *pchFile ) { PRINT_DEBUG("Steam_Remote_Storage::FileDelete\n"); std::lock_guard lock(global_mutex); + if (!pchFile || !pchFile[0]) return false; return local_storage->file_delete(Local_Storage::remote_storage_folder, pchFile); } @@ -232,7 +235,8 @@ SteamAPICall_t FileShare( const char *pchFile ) { PRINT_DEBUG("Steam_Remote_Storage::FileShare\n"); std::lock_guard lock(global_mutex); - if (!pchFile) return k_uAPICallInvalid; + if (!pchFile || !pchFile[0]) return k_uAPICallInvalid; + RemoteStorageFileShareResult_t data = {}; if (local_storage->file_exists(Local_Storage::remote_storage_folder, pchFile)) { data.m_eResult = k_EResultOK; @@ -250,6 +254,7 @@ bool SetSyncPlatforms( const char *pchFile, ERemoteStoragePlatform eRemoteStorag { PRINT_DEBUG("Steam_Remote_Storage::SetSyncPlatforms\n"); std::lock_guard lock(global_mutex); + if (!pchFile || !pchFile[0]) return false; return true; } @@ -260,6 +265,8 @@ UGCFileWriteStreamHandle_t FileWriteStreamOpen( const char *pchFile ) { PRINT_DEBUG("Steam_Remote_Storage::FileWriteStreamOpen\n"); std::lock_guard lock(global_mutex); + if (!pchFile || !pchFile[0]) return k_UGCFileStreamHandleInvalid; + static UGCFileWriteStreamHandle_t handle; ++handle; struct Stream_Write stream_write; @@ -273,6 +280,8 @@ bool FileWriteStreamWriteChunk( UGCFileWriteStreamHandle_t writeHandle, const vo { PRINT_DEBUG("Steam_Remote_Storage::FileWriteStreamWriteChunk\n"); std::lock_guard lock(global_mutex); + if (!pvData || cubData < 0) return false; + auto request = std::find_if(stream_writes.begin(), stream_writes.end(), [&writeHandle](struct Stream_Write const& item) { return item.write_stream_handle == writeHandle; }); if (stream_writes.end() == request) return false; @@ -311,6 +320,7 @@ bool FileExists( const char *pchFile ) { PRINT_DEBUG("Steam_Remote_Storage::FileExists %s\n", pchFile); std::lock_guard lock(global_mutex); + if (!pchFile || !pchFile[0]) return false; return local_storage->file_exists(Local_Storage::remote_storage_folder, pchFile); } @@ -319,6 +329,7 @@ bool FilePersisted( const char *pchFile ) { PRINT_DEBUG("Steam_Remote_Storage::FilePersisted\n"); std::lock_guard lock(global_mutex); + if (!pchFile || !pchFile[0]) return false; return local_storage->file_exists(Local_Storage::remote_storage_folder, pchFile); } @@ -327,6 +338,7 @@ int32 GetFileSize( const char *pchFile ) { PRINT_DEBUG("Steam_Remote_Storage::GetFileSize %s\n", pchFile); std::lock_guard lock(global_mutex); + if (!pchFile || !pchFile[0]) return 0; return local_storage->file_size(Local_Storage::remote_storage_folder, pchFile); } @@ -335,6 +347,7 @@ int64 GetFileTimestamp( const char *pchFile ) { PRINT_DEBUG("Steam_Remote_Storage::GetFileTimestamp\n"); std::lock_guard lock(global_mutex); + if (!pchFile || !pchFile[0]) return 0; return local_storage->file_timestamp(Local_Storage::remote_storage_folder, pchFile); } @@ -381,8 +394,8 @@ bool GetQuota( uint64 *pnTotalBytes, uint64 *puAvailableBytes ) std::lock_guard lock(global_mutex); uint64 quota = 2 << 26; - *pnTotalBytes = quota; - *puAvailableBytes = (quota); + if (pnTotalBytes) *pnTotalBytes = quota; + if (puAvailableBytes) *puAvailableBytes = (quota); return true; } @@ -392,8 +405,8 @@ bool GetQuota( int32 *pnTotalBytes, int32 *puAvailableBytes ) std::lock_guard lock(global_mutex); uint64 quota = 2 << 26; - *pnTotalBytes = quota; - *puAvailableBytes = (quota); + if (pnTotalBytes) *pnTotalBytes = quota; + if (puAvailableBytes) *puAvailableBytes = (quota); return true; } @@ -550,6 +563,7 @@ int32 UGCRead( UGCHandle_t hContent, void *pvData, int32 cubDataToRead, uint32 c uint64 total_size = 0; Downloaded_File f = downloaded_files[hContent]; + // depending on the download source, we have to decide where to grab the content/data switch (f.source) { case Downloaded_File::DownloadSource::AfterFileShare: @@ -561,9 +575,9 @@ int32 UGCRead( UGCHandle_t hContent, void *pvData, int32 cubDataToRead, uint32 c break; case Downloaded_File::DownloadSource::AfterSendQueryUGCRequest: - case Downloaded_File::DownloadSource::AfterUGCDownloadToLocation: + case Downloaded_File::DownloadSource::FromUGCDownloadToLocation: { - PRINT_DEBUG(" Steam_Remote_Storage::UGCRead source = AfterSendQueryUGCRequest || AfterUGCDownloadToLocation [%i]\n", (int)f.source); + PRINT_DEBUG(" Steam_Remote_Storage::UGCRead source = AfterSendQueryUGCRequest || FromUGCDownloadToLocation [%i]\n", (int)f.source); auto mod = settings->getMod(f.mod_query_info.mod_id); auto &mod_name = f.mod_query_info.is_primary_file ? mod.primaryFileName @@ -576,7 +590,7 @@ int32 UGCRead( UGCHandle_t hContent, void *pvData, int32 cubDataToRead, uint32 c : Local_Storage::get_game_settings_path() + "mod_images" + PATH_SEPARATOR + std::to_string(mod.id); mod_fullpath = common_helpers::to_absolute(mod_name, mod_base_path); - } else { // Downloaded_File::DownloadSource::AfterUGCDownloadToLocation + } else { // Downloaded_File::DownloadSource::FromUGCDownloadToLocation mod_fullpath = f.download_to_location_fullpath; } @@ -700,7 +714,7 @@ SteamAPICall_t PublishWorkshopFile( const char *pchFile, const char *pchPreviewF PRINT_DEBUG("TODO Steam_Remote_Storage::PublishWorkshopFile\n"); std::lock_guard lock(global_mutex); - return 0; + return k_uAPICallInvalid; } PublishedFileUpdateHandle_t CreatePublishedFileUpdateRequest( PublishedFileId_t unPublishedFileId ) @@ -708,7 +722,7 @@ PublishedFileUpdateHandle_t CreatePublishedFileUpdateRequest( PublishedFileId_t PRINT_DEBUG("TODO Steam_Remote_Storage::CreatePublishedFileUpdateRequest\n"); std::lock_guard lock(global_mutex); - return 0; + return k_PublishedFileUpdateHandleInvalid; } bool UpdatePublishedFileFile( PublishedFileUpdateHandle_t updateHandle, const char *pchFile ) @@ -724,7 +738,7 @@ SteamAPICall_t PublishFile( const char *pchFile, const char *pchPreviewFile, App PRINT_DEBUG("TODO Steam_Remote_Storage::PublishFile\n"); std::lock_guard lock(global_mutex); - return 0; + return k_uAPICallInvalid; } SteamAPICall_t PublishWorkshopFile( const char *pchFile, const char *pchPreviewFile, AppId_t nConsumerAppId, const char *pchTitle, const char *pchDescription, SteamParamStringArray_t *pTags ) @@ -732,7 +746,7 @@ SteamAPICall_t PublishWorkshopFile( const char *pchFile, const char *pchPreviewF PRINT_DEBUG("TODO Steam_Remote_Storage::PublishWorkshopFile old\n"); std::lock_guard lock(global_mutex); - return 0; + return k_uAPICallInvalid; } SteamAPICall_t UpdatePublishedFile( RemoteStorageUpdatePublishedFileRequest_t updatePublishedFileRequest ) @@ -740,7 +754,7 @@ SteamAPICall_t UpdatePublishedFile( RemoteStorageUpdatePublishedFileRequest_t up PRINT_DEBUG("TODO Steam_Remote_Storage::UpdatePublishedFile\n"); std::lock_guard lock(global_mutex); - return 0; + return k_uAPICallInvalid; } bool UpdatePublishedFilePreviewFile( PublishedFileUpdateHandle_t updateHandle, const char *pchPreviewFile ) @@ -789,7 +803,7 @@ SteamAPICall_t CommitPublishedFileUpdate( PublishedFileUpdateHandle_t updateHand PRINT_DEBUG("TODO Steam_Remote_Storage::CommitPublishedFileUpdate %llu\n", updateHandle); std::lock_guard lock(global_mutex); - return 0; + return k_uAPICallInvalid; } // Gets published file details for the given publishedfileid. If unMaxSecondsOld is greater than 0, @@ -802,6 +816,7 @@ SteamAPICall_t GetPublishedFileDetails( PublishedFileId_t unPublishedFileId, uin //TODO: check what this function really returns // TODO is this implementation correct? std::lock_guard lock(global_mutex); + if (unPublishedFileId == k_PublishedFileIdInvalid) return k_uAPICallInvalid; RemoteStorageGetPublishedFileDetailsResult_t data{}; data.m_nPublishedFileId = unPublishedFileId; @@ -859,7 +874,7 @@ SteamAPICall_t DeletePublishedFile( PublishedFileId_t unPublishedFileId ) PRINT_DEBUG("TODO Steam_Remote_Storage::DeletePublishedFile %llu\n", unPublishedFileId); std::lock_guard lock(global_mutex); - return 0; + return k_uAPICallInvalid; } // enumerate the files that the current user published with this app @@ -908,6 +923,8 @@ SteamAPICall_t SubscribePublishedFile( PublishedFileId_t unPublishedFileId ) { PRINT_DEBUG("TODO Steam_Remote_Storage::SubscribePublishedFile %llu\n", unPublishedFileId); std::lock_guard lock(global_mutex); + if (unPublishedFileId == k_PublishedFileIdInvalid) return k_uAPICallInvalid; + // TODO is this implementation correct? RemoteStorageSubscribePublishedFileResult_t data{}; data.m_nPublishedFileId = unPublishedFileId; @@ -959,6 +976,8 @@ SteamAPICall_t UnsubscribePublishedFile( PublishedFileId_t unPublishedFileId ) { PRINT_DEBUG("TODO Steam_Remote_Storage::UnsubscribePublishedFile %llu\n", unPublishedFileId); std::lock_guard lock(global_mutex); + if (unPublishedFileId == k_PublishedFileIdInvalid) return k_uAPICallInvalid; + // TODO is this implementation correct? RemoteStorageUnsubscribePublishedFileResult_t data{}; data.m_nPublishedFileId = unPublishedFileId; @@ -987,6 +1006,8 @@ SteamAPICall_t GetPublishedItemVoteDetails( PublishedFileId_t unPublishedFileId PRINT_DEBUG("TODO Steam_Remote_Storage::GetPublishedItemVoteDetails\n"); // TODO s this implementation correct? std::lock_guard lock(global_mutex); + if (unPublishedFileId == k_PublishedFileIdInvalid) return k_uAPICallInvalid; + RemoteStorageGetPublishedItemVoteDetailsResult_t data{}; data.m_unPublishedFileId = unPublishedFileId; if (settings->isModInstalled(unPublishedFileId)) { @@ -1011,6 +1032,8 @@ SteamAPICall_t UpdateUserPublishedItemVote( PublishedFileId_t unPublishedFileId, PRINT_DEBUG("TODO Steam_Remote_Storage::UpdateUserPublishedItemVote\n"); // TODO is this implementation correct? std::lock_guard lock(global_mutex); + if (unPublishedFileId == k_PublishedFileIdInvalid) return k_uAPICallInvalid; + RemoteStorageUpdateUserPublishedItemVoteResult_t data{}; data.m_nPublishedFileId = unPublishedFileId; if (settings->isModInstalled(unPublishedFileId)) { @@ -1034,6 +1057,8 @@ SteamAPICall_t GetUserPublishedItemVoteDetails( PublishedFileId_t unPublishedFil // TODO is this implementation correct? std::lock_guard lock(global_mutex); + if (unPublishedFileId == k_PublishedFileIdInvalid) return k_uAPICallInvalid; + RemoteStorageGetPublishedItemVoteDetailsResult_t data{}; data.m_unPublishedFileId = unPublishedFileId; if (settings->isModInstalled(unPublishedFileId)) { @@ -1081,7 +1106,7 @@ SteamAPICall_t PublishVideo( EWorkshopVideoProvider eVideoProvider, const char * { PRINT_DEBUG("TODO Steam_Remote_Storage::PublishVideo\n"); std::lock_guard lock(global_mutex); - return 0; + return k_uAPICallInvalid; } STEAM_CALL_RESULT( RemoteStoragePublishFileProgress_t ) @@ -1089,7 +1114,7 @@ SteamAPICall_t PublishVideo(const char *pchFileName, const char *pchPreviewFile, { PRINT_DEBUG("TODO Steam_Remote_Storage::PublishVideo old\n"); std::lock_guard lock(global_mutex); - return 0; + return k_uAPICallInvalid; } STEAM_CALL_RESULT( RemoteStorageSetUserPublishedFileActionResult_t ) @@ -1097,7 +1122,7 @@ SteamAPICall_t SetUserPublishedFileAction( PublishedFileId_t unPublishedFileId, { PRINT_DEBUG("TODO Steam_Remote_Storage::SetUserPublishedFileAction\n"); std::lock_guard lock(global_mutex); - return 0; + return k_uAPICallInvalid; } STEAM_CALL_RESULT( RemoteStorageEnumeratePublishedFilesByUserActionResult_t ) @@ -1105,7 +1130,7 @@ SteamAPICall_t EnumeratePublishedFilesByUserAction( EWorkshopFileAction eAction, { PRINT_DEBUG("TODO Steam_Remote_Storage::EnumeratePublishedFilesByUserAction\n"); std::lock_guard lock(global_mutex); - return 0; + return k_uAPICallInvalid; } // this method enumerates the public view of workshop files @@ -1130,16 +1155,15 @@ SteamAPICall_t UGCDownloadToLocation( UGCHandle_t hContent, const char *pchLocat PRINT_DEBUG("TODO Steam_Remote_Storage::UGCDownloadToLocation %llu %s\n", hContent, pchLocation); // TODO is this implementation correct? std::lock_guard lock(global_mutex); - if (hContent == k_UGCHandleInvalid) return k_uAPICallInvalid; + //TODO: not sure if this is the right result + if (hContent == k_UGCHandleInvalid || !pchLocation || !pchLocation[0]) return k_uAPICallInvalid; RemoteStorageDownloadUGCResult_t data{}; data.m_hFile = hContent; data.m_nAppID = settings->get_local_game_id().AppID(); - if (!pchLocation || !pchLocation[0]) { - data.m_eResult = EResult::k_EResultInvalidParam; //TODO: not sure if this is the right result - data.m_nSizeInBytes = 0; - } else if (auto query_res = ugc_bridge->get_ugc_query_result(hContent)) { + auto query_res = ugc_bridge->get_ugc_query_result(hContent); + if (query_res) { auto mod = settings->getMod(query_res.value().mod_id); auto &mod_name = query_res.value().is_primary_file ? mod.primaryFileName @@ -1164,7 +1188,7 @@ SteamAPICall_t UGCDownloadToLocation( UGCHandle_t hContent, const char *pchLocat copy_file(mod_fullpath, pchLocation); // TODO not sure about this though - downloaded_files[hContent].source = Downloaded_File::DownloadSource::AfterUGCDownloadToLocation; + downloaded_files[hContent].source = Downloaded_File::DownloadSource::FromUGCDownloadToLocation; downloaded_files[hContent].file = mod_name; downloaded_files[hContent].total_size = mod_size; diff --git a/dll/dll/steam_ugc.h b/dll/dll/steam_ugc.h index f1885768..c0b8db17 100644 --- a/dll/dll/steam_ugc.h +++ b/dll/dll/steam_ugc.h @@ -77,12 +77,15 @@ UGCQueryHandle_t new_ugc_query( void set_details(PublishedFileId_t id, SteamUGCDetails_t *pDetails) { if (pDetails) { + memset(pDetails, 0, sizeof(SteamUGCDetails_t)); + pDetails->m_nPublishedFileId = id; if (settings->isModInstalled(id)) { PRINT_DEBUG(" mod is installed, setting details\n"); - auto mod = settings->getMod(id); pDetails->m_eResult = k_EResultOK; + + auto mod = settings->getMod(id); pDetails->m_bAcceptedForUse = mod.acceptedForUse; pDetails->m_bBanned = mod.banned; pDetails->m_bTagsTruncated = mod.tagsTruncated; @@ -283,11 +286,6 @@ bool GetQueryUGCResult( UGCQueryHandle_t handle, uint32 index, SteamUGCDetails_t return false; } - if (pDetails) { - memset(pDetails, 0, sizeof(SteamUGCDetails_t)); - pDetails->m_eResult = k_EResultFail; - } - auto it = request->results.begin(); std::advance(it, index); PublishedFileId_t file_id = *it; @@ -342,6 +340,7 @@ uint32 GetQueryUGCNumTags( UGCQueryHandle_t handle, uint32 index ) PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCNumTags\n"); // TODO is this correct? std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return 0; auto res = get_query_ugc_tags(handle, index); return res.has_value() ? res.value().size() : 0; @@ -352,6 +351,7 @@ bool GetQueryUGCTag( UGCQueryHandle_t handle, uint32 index, uint32 indexTag, STE PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCTag\n"); // TODO is this correct? std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; if (!pchValue || !cchValueSize) return false; auto res = get_query_ugc_tag(handle, index, indexTag); @@ -367,6 +367,7 @@ bool GetQueryUGCTagDisplayName( UGCQueryHandle_t handle, uint32 index, uint32 in PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCTagDisplayName\n"); // TODO is this correct? std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; if (!pchValue || !cchValueSize) return false; auto res = get_query_ugc_tag(handle, index, indexTag); @@ -382,14 +383,14 @@ bool GetQueryUGCPreviewURL( UGCQueryHandle_t handle, uint32 index, STEAM_OUT_STR PRINT_DEBUG("Steam_UGC::GetQueryUGCPreviewURL\n"); std::lock_guard lock(global_mutex); //TODO: escape simulator tries downloading this url and unsubscribes if it fails - + if (handle == k_UGCQueryHandleInvalid) return false; if (!pchURL || !cchURLSize) return false; auto res = get_query_ugc(handle, index); if (!res.has_value()) return false; auto mod = res.value(); - PRINT_DEBUG("Steam_UGC:GetQueryUGCPreviewURL: %s\n", mod.previewURL.c_str()); + PRINT_DEBUG("Steam_UGC:GetQueryUGCPreviewURL: '%s'\n", mod.previewURL.c_str()); mod.previewURL.copy(pchURL, cchURLSize - 1); return true; } @@ -399,6 +400,10 @@ bool GetQueryUGCMetadata( UGCQueryHandle_t handle, uint32 index, STEAM_OUT_STRIN { PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCMetadata\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return false; } @@ -408,6 +413,10 @@ bool GetQueryUGCChildren( UGCQueryHandle_t handle, uint32 index, PublishedFileId { PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCChildren\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return false; } @@ -417,6 +426,10 @@ bool GetQueryUGCStatistic( UGCQueryHandle_t handle, uint32 index, EItemStatistic { PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCStatistic\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return false; } @@ -425,6 +438,10 @@ bool GetQueryUGCStatistic( UGCQueryHandle_t handle, uint32 index, EItemStatistic { PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCStatistic old\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return false; } @@ -433,6 +450,10 @@ uint32 GetQueryUGCNumAdditionalPreviews( UGCQueryHandle_t handle, uint32 index ) { PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCNumAdditionalPreviews\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return 0; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return 0; return 0; } @@ -442,6 +463,10 @@ bool GetQueryUGCAdditionalPreview( UGCQueryHandle_t handle, uint32 index, uint32 { PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCAdditionalPreview\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return false; } @@ -450,6 +475,10 @@ bool GetQueryUGCAdditionalPreview( UGCQueryHandle_t handle, uint32 index, uint32 { PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCAdditionalPreview old\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return false; } @@ -458,6 +487,10 @@ uint32 GetQueryUGCNumKeyValueTags( UGCQueryHandle_t handle, uint32 index ) { PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCNumKeyValueTags\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return 0; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return 0; return 0; } @@ -467,6 +500,10 @@ bool GetQueryUGCKeyValueTag( UGCQueryHandle_t handle, uint32 index, uint32 keyVa { PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCKeyValueTag\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return false; } @@ -475,6 +512,10 @@ bool GetQueryUGCKeyValueTag( UGCQueryHandle_t handle, uint32 index, const char * { PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCKeyValueTag2\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return false; } @@ -483,6 +524,10 @@ uint32 GetQueryUGCContentDescriptors( UGCQueryHandle_t handle, uint32 index, EUG { PRINT_DEBUG("TODO Steam_UGC::GetQueryUGCContentDescriptors\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return 0; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return 0; return 0; } @@ -492,9 +537,10 @@ bool ReleaseQueryUGCRequest( UGCQueryHandle_t handle ) { PRINT_DEBUG("Steam_UGC::ReleaseQueryUGCRequest %llu\n", handle); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); - if (ugc_queries.end() == request) - return false; + if (ugc_queries.end() == request) return false; ugc_queries.erase(request); return true; @@ -506,6 +552,10 @@ bool AddRequiredTag( UGCQueryHandle_t handle, const char *pTagName ) { PRINT_DEBUG("TODO Steam_UGC::AddRequiredTag\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -514,6 +564,10 @@ bool AddRequiredTagGroup( UGCQueryHandle_t handle, const SteamParamStringArray_t { PRINT_DEBUG("TODO Steam_UGC::AddRequiredTagGroup\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -522,6 +576,10 @@ bool AddExcludedTag( UGCQueryHandle_t handle, const char *pTagName ) { PRINT_DEBUG("TODO Steam_UGC::AddExcludedTag\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -531,6 +589,10 @@ bool SetReturnOnlyIDs( UGCQueryHandle_t handle, bool bReturnOnlyIDs ) { PRINT_DEBUG("TODO Steam_UGC::SetReturnOnlyIDs\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -539,7 +601,10 @@ bool SetReturnOnlyIDs( UGCQueryHandle_t handle, bool bReturnOnlyIDs ) bool SetReturnKeyValueTags( UGCQueryHandle_t handle, bool bReturnKeyValueTags ) { PRINT_DEBUG("TODO Steam_UGC::SetReturnKeyValueTags\n"); - std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -548,7 +613,10 @@ bool SetReturnKeyValueTags( UGCQueryHandle_t handle, bool bReturnKeyValueTags ) bool SetReturnLongDescription( UGCQueryHandle_t handle, bool bReturnLongDescription ) { PRINT_DEBUG("TODO Steam_UGC::SetReturnLongDescription\n"); - std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -558,8 +626,10 @@ bool SetReturnMetadata( UGCQueryHandle_t handle, bool bReturnMetadata ) { PRINT_DEBUG("TODO Steam_UGC::SetReturnMetadata %i\n", (int)bReturnMetadata); std::lock_guard lock(global_mutex); - if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -569,6 +639,10 @@ bool SetReturnChildren( UGCQueryHandle_t handle, bool bReturnChildren ) { PRINT_DEBUG("TODO Steam_UGC::SetReturnChildren\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -578,6 +652,10 @@ bool SetReturnAdditionalPreviews( UGCQueryHandle_t handle, bool bReturnAdditiona { PRINT_DEBUG("TODO Steam_UGC::SetReturnAdditionalPreviews\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -587,6 +665,10 @@ bool SetReturnTotalOnly( UGCQueryHandle_t handle, bool bReturnTotalOnly ) { PRINT_DEBUG("TODO Steam_UGC::SetReturnTotalOnly\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -596,6 +678,10 @@ bool SetReturnPlaytimeStats( UGCQueryHandle_t handle, uint32 unDays ) { PRINT_DEBUG("TODO Steam_UGC::SetReturnPlaytimeStats\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -605,6 +691,10 @@ bool SetLanguage( UGCQueryHandle_t handle, const char *pchLanguage ) { PRINT_DEBUG("TODO Steam_UGC::SetLanguage\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -614,6 +704,10 @@ bool SetAllowCachedResponse( UGCQueryHandle_t handle, uint32 unMaxAgeSeconds ) { PRINT_DEBUG("TODO Steam_UGC::SetAllowCachedResponse\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -624,6 +718,10 @@ bool SetCloudFileNameFilter( UGCQueryHandle_t handle, const char *pMatchCloudFil { PRINT_DEBUG("TODO Steam_UGC::SetCloudFileNameFilter\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -634,6 +732,10 @@ bool SetMatchAnyTag( UGCQueryHandle_t handle, bool bMatchAnyTag ) { PRINT_DEBUG("TODO Steam_UGC::SetMatchAnyTag\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -643,6 +745,10 @@ bool SetSearchText( UGCQueryHandle_t handle, const char *pSearchText ) { PRINT_DEBUG("TODO Steam_UGC::SetSearchText\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -652,6 +758,10 @@ bool SetRankedByTrendDays( UGCQueryHandle_t handle, uint32 unDays ) { PRINT_DEBUG("TODO Steam_UGC::SetRankedByTrendDays\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -661,6 +771,10 @@ bool AddRequiredKeyValueTag( UGCQueryHandle_t handle, const char *pKey, const ch { PRINT_DEBUG("TODO Steam_UGC::AddRequiredKeyValueTag\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -669,6 +783,10 @@ bool SetTimeCreatedDateRange( UGCQueryHandle_t handle, RTime32 rtStart, RTime32 { PRINT_DEBUG("TODO Steam_UGC::SetTimeCreatedDateRange\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -677,6 +795,10 @@ bool SetTimeUpdatedDateRange( UGCQueryHandle_t handle, RTime32 rtStart, RTime32 { PRINT_DEBUG("TODO Steam_UGC::SetTimeUpdatedDateRange\n"); std::lock_guard lock(global_mutex); + if (handle == k_UGCQueryHandleInvalid) return false; + + auto request = std::find_if(ugc_queries.begin(), ugc_queries.end(), [&handle](struct UGC_query const& item) { return item.handle == handle; }); + if (ugc_queries.end() == request) return false; return true; } @@ -687,7 +809,7 @@ SteamAPICall_t RequestUGCDetails( PublishedFileId_t nPublishedFileID, uint32 unM PRINT_DEBUG("Steam_UGC::RequestUGCDetails %llu\n", nPublishedFileID); std::lock_guard lock(global_mutex); - SteamUGCRequestUGCDetailsResult_t data = {}; + SteamUGCRequestUGCDetailsResult_t data{}; data.m_bCachedData = false; set_details(nPublishedFileID, &(data.m_details)); return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); @@ -1044,6 +1166,7 @@ SteamAPICall_t UnsubscribeItem( PublishedFileId_t nPublishedFileID ) { PRINT_DEBUG("Steam_UGC::UnsubscribeItem %llu\n", nPublishedFileID); std::lock_guard lock(global_mutex); + RemoteStorageUnsubscribePublishedFileResult_t data; data.m_nPublishedFileId = nPublishedFileID; if (!ugc_bridge->has_subbed_mod(nPublishedFileID)) { @@ -1104,18 +1227,26 @@ uint32 GetItemState( PublishedFileId_t nPublishedFileID ) // if k_EItemStateLegacyItem is set, pchFolder contains the path to the legacy file itself (not a folder) bool GetItemInstallInfo( PublishedFileId_t nPublishedFileID, uint64 *punSizeOnDisk, STEAM_OUT_STRING_COUNT( cchFolderSize ) char *pchFolder, uint32 cchFolderSize, uint32 *punTimeStamp ) { - PRINT_DEBUG("Steam_UGC::GetItemInstallInfo %llu %p %p %u %p\n", nPublishedFileID, punSizeOnDisk, pchFolder, cchFolderSize, punTimeStamp); + PRINT_DEBUG("Steam_UGC::GetItemInstallInfo %llu %p %p [%u] %p\n", nPublishedFileID, punSizeOnDisk, pchFolder, cchFolderSize, punTimeStamp); std::lock_guard lock(global_mutex); if (!cchFolderSize) return false; if (!settings->isModInstalled(nPublishedFileID)) return false; auto mod = settings->getMod(nPublishedFileID); + + // I don't know if this is accurate behavior, but to avoid returning true with invalid data + if ((cchFolderSize - 1) < mod.path.size()) { // -1 because the last char is reserved for null terminator + PRINT_DEBUG(" ERROR mod path: '%s' [%zu bytes] cannot fit into the given buffer\n", mod.path.c_str(), mod.path.size()); + return false; + } + if (punSizeOnDisk) *punSizeOnDisk = mod.primaryFileSize; if (punTimeStamp) *punTimeStamp = mod.timeUpdated; if (pchFolder && cchFolderSize) { - PRINT_DEBUG(" mod path: '%s'\n", mod.path.c_str()); + // human fall flat doesn't send a nulled buffer, and won't recognize the proper mod path because of that memset(pchFolder, 0, cchFolderSize); mod.path.copy(pchFolder, cchFolderSize - 1); + PRINT_DEBUG(" copied mod path: '%s'\n", pchFolder); } return true; @@ -1231,7 +1362,9 @@ SteamAPICall_t AddDependency( PublishedFileId_t nParentPublishedFileID, Publishe PRINT_DEBUG("Steam_UGC::AddDependency\n"); std::lock_guard lock(global_mutex); - return 0; + if (nParentPublishedFileID == k_PublishedFileIdInvalid) return k_uAPICallInvalid; + + return k_uAPICallInvalid; } STEAM_CALL_RESULT( RemoveUGCDependencyResult_t ) @@ -1240,7 +1373,9 @@ SteamAPICall_t RemoveDependency( PublishedFileId_t nParentPublishedFileID, Publi PRINT_DEBUG("Steam_UGC::RemoveDependency\n"); std::lock_guard lock(global_mutex); - return 0; + if (nParentPublishedFileID == k_PublishedFileIdInvalid) return k_uAPICallInvalid; + + return k_uAPICallInvalid; } @@ -1251,7 +1386,9 @@ SteamAPICall_t AddAppDependency( PublishedFileId_t nPublishedFileID, AppId_t nAp PRINT_DEBUG("Steam_UGC::AddAppDependency\n"); std::lock_guard lock(global_mutex); - return 0; + if (nPublishedFileID == k_PublishedFileIdInvalid) return k_uAPICallInvalid; + + return k_uAPICallInvalid; } STEAM_CALL_RESULT( RemoveAppDependencyResult_t ) @@ -1260,7 +1397,9 @@ SteamAPICall_t RemoveAppDependency( PublishedFileId_t nPublishedFileID, AppId_t PRINT_DEBUG("Steam_UGC::RemoveAppDependency\n"); std::lock_guard lock(global_mutex); - return 0; + if (nPublishedFileID == k_PublishedFileIdInvalid) return k_uAPICallInvalid; + + return k_uAPICallInvalid; } // request app dependencies. note that whatever callback you register for GetAppDependenciesResult_t may be called multiple times @@ -1271,7 +1410,9 @@ SteamAPICall_t GetAppDependencies( PublishedFileId_t nPublishedFileID ) PRINT_DEBUG("Steam_UGC::GetAppDependencies\n"); std::lock_guard lock(global_mutex); - return 0; + if (nPublishedFileID == k_PublishedFileIdInvalid) return k_uAPICallInvalid; + + return k_uAPICallInvalid; } @@ -1282,7 +1423,9 @@ SteamAPICall_t DeleteItem( PublishedFileId_t nPublishedFileID ) PRINT_DEBUG("Steam_UGC::DeleteItem\n"); std::lock_guard lock(global_mutex); - return 0; + if (nPublishedFileID == k_PublishedFileIdInvalid) return k_uAPICallInvalid; + + return k_uAPICallInvalid; } // Show the app's latest Workshop EULA to the user in an overlay window, where they can accept it or not @@ -1301,7 +1444,7 @@ SteamAPICall_t GetWorkshopEULAStatus() PRINT_DEBUG("GetWorkshopEULAStatus\n"); std::lock_guard lock(global_mutex); - return 0; + return k_uAPICallInvalid; } // Return the user's community content descriptor preferences