static ulong GetSteam3DepotManifest(uint depotId, uint appId, string branch) { if (Config.ManifestId != INVALID_MANIFEST_ID) { return(Config.ManifestId); } KeyValue depots = GetSteam3AppSection(appId, EAppInfoSection.Depots); KeyValue depotChild = depots[depotId.ToString()]; if (depotChild == KeyValue.Invalid) { return(INVALID_MANIFEST_ID); } // Shared depots can either provide manifests, or leave you relying on their parent app. // It seems that with the latter, "sharedinstall" will exist (and equals 2 in the one existance I know of). // Rather than relay on the unknown sharedinstall key, just look for manifests. Test cases: 111710, 346680. if (depotChild["manifests"] == KeyValue.Invalid && depotChild["depotfromapp"] != KeyValue.Invalid) { uint otherAppId = ( uint )depotChild["depotfromapp"].AsInteger(); if (otherAppId == appId) { // This shouldn't ever happen, but ya never know with Valve. Don't infinite loop. Console.WriteLine("App {0}, Depot {1} has depotfromapp of {2}!", appId, depotId, otherAppId); return(INVALID_MANIFEST_ID); } steam3.RequestAppInfo(otherAppId); return(GetSteam3DepotManifest(depotId, otherAppId, branch)); } var manifests = depotChild["manifests"]; var manifests_encrypted = depotChild["encryptedmanifests"]; if (manifests.Children.Count == 0 && manifests_encrypted.Children.Count == 0) { return(INVALID_MANIFEST_ID); } var node = manifests[branch]; if (branch != "Public" && node == KeyValue.Invalid) { var node_encrypted = manifests_encrypted[branch]; if (node_encrypted != KeyValue.Invalid) { string password = Config.BetaPassword; if (password == null) { Console.Write("Please enter the password for branch {0}: ", branch); Config.BetaPassword = password = Console.ReadLine(); } var encrypted_v1 = node_encrypted["encrypted_gid"]; var encrypted_v2 = node_encrypted["encrypted_gid_2"]; if (encrypted_v1 != KeyValue.Invalid) { byte[] input = Util.DecodeHexString(encrypted_v1.Value); byte[] manifest_bytes = CryptoHelper.VerifyAndDecryptPassword(input, password); if (manifest_bytes == null) { Console.WriteLine("Password was invalid for branch {0}", branch); return(INVALID_MANIFEST_ID); } return(BitConverter.ToUInt64(manifest_bytes, 0)); } else if (encrypted_v2 != KeyValue.Invalid) { // Submit the password to Steam now to get encryption keys steam3.CheckAppBetaPassword(appId, Config.BetaPassword); if (!steam3.AppBetaPasswords.ContainsKey(branch)) { Console.WriteLine("Password was invalid for branch {0}", branch); return(INVALID_MANIFEST_ID); } byte[] input = Util.DecodeHexString(encrypted_v2.Value); byte[] manifest_bytes; try { manifest_bytes = CryptoHelper.SymmetricDecryptECB(input, steam3.AppBetaPasswords[branch]); } catch (Exception e) { Console.WriteLine("Failed to decrypt branch {0}: {1}", branch, e.Message); return(INVALID_MANIFEST_ID); } return(BitConverter.ToUInt64(manifest_bytes, 0)); } else { Console.WriteLine("Unhandled depot encryption for depotId {0}", depotId); return(INVALID_MANIFEST_ID); } } return(INVALID_MANIFEST_ID); } if (node.Value == null) { return(INVALID_MANIFEST_ID); } return(UInt64.Parse(node.Value)); }