mirror of
https://github.com/rvtr/ctr_Repair.git
synced 2025-10-31 13:51:08 -04:00
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@603 385bec56-5757-e545-9c3a-d8741f4650f1
216 lines
7.1 KiB
C++
216 lines
7.1 KiB
C++
/*---------------------------------------------------------------------------*
|
|
Project: Horizon
|
|
File: PreinstallImporter.cpp
|
|
|
|
Copyright 2009-2011 Nintendo. All rights reserved.
|
|
|
|
These coded instructions, statements, and computer programs contain
|
|
proprietary information of Nintendo of America Inc. and/or Nintendo
|
|
Company Ltd., and are protected by Federal copyright law. They may
|
|
not be disclosed to third parties or copied or duplicated in any form,
|
|
in whole or in part, without the prior written consent of Nintendo.
|
|
|
|
$Rev$
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
#include "CommonLogger.h"
|
|
#include "HeapManager.h"
|
|
#include "PreinstallImporter.h"
|
|
#include "XmlCreator.h"
|
|
#include "SimpleXmlPreprocessor.h"
|
|
#include <nn/xml/simple/xml_simple_SimpleXmlParser.h>
|
|
#include <cstring>
|
|
#include <nn/am/am_ApiSystemMenu.h>
|
|
|
|
namespace ConsoleRestore
|
|
{
|
|
|
|
PreinstallImporter::PreinstallImporter()
|
|
{
|
|
// TODO 自動生成されたコンストラクター・スタブ
|
|
|
|
}
|
|
|
|
PreinstallImporter::~PreinstallImporter()
|
|
{
|
|
// TODO Auto-generated destructor stub
|
|
}
|
|
|
|
nn::Result PreinstallImporter::SetupSd(bool* isAlreadyAvailable)
|
|
{
|
|
// SDカードがインポート可能状態かどうかチェック
|
|
NN_UTIL_RETURN_IF_FAILED(
|
|
nn::am::QueryAvailableExternalTitleDatabase(isAlreadyAvailable)
|
|
);
|
|
|
|
// タイトルデータベースを作成する
|
|
if (!*isAlreadyAvailable)
|
|
{
|
|
NN_UTIL_RETURN_IF_FAILED(
|
|
nn::am::InitializeExternalTitleDatabase()
|
|
);
|
|
}
|
|
|
|
return nn::ResultSuccess();
|
|
}
|
|
|
|
nn::Result PreinstallImporter::ListTitles(nn::ProgramId* list, size_t* num, bit64 deviceId, u8* serialNo)
|
|
{
|
|
// 送信用のXMLデータを構築する
|
|
XmlCreator sendXml;
|
|
sendXml.Exec(deviceId, serialNo);
|
|
|
|
// 構築したXMLデータを使ってBGSと通信する
|
|
BgsCommunicator comm;
|
|
if(!comm.Execute(sendXml.GetData().c_str(), sendXml.GetData().size()))
|
|
{
|
|
return comm.GetLastResult();
|
|
}
|
|
|
|
// 通信結果をパースしてタイトルリストを作成する
|
|
NN_UTIL_RETURN_IF_FAILED(
|
|
GetHtmlBodyAndParseXmlData(comm, list, num)
|
|
);
|
|
return nn::ResultSuccess();
|
|
}
|
|
|
|
nn::Result PreinstallImporter::GetHtmlBodyAndParseXmlData(BgsCommunicator& comm, nn::ProgramId* list, size_t* num)
|
|
{
|
|
// 通信結果を取得する
|
|
size_t bodySize;
|
|
if(!comm.GetBodySize(&bodySize))
|
|
{
|
|
return comm.GetLastResult();
|
|
}
|
|
if(common::GetAllocatableSize() < bodySize + 1)
|
|
{
|
|
// 巨大な通信結果のためFATAL。1回で受信しきれるはず
|
|
return nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON,
|
|
nn::Result::DESCRIPTION_OUT_OF_MEMORY);
|
|
}
|
|
common::HeapManager heap(bodySize + 1);
|
|
void* buf = heap.GetAddr();
|
|
if(!comm.GetBody(reinterpret_cast<u8*>(buf), bodySize + 1))
|
|
{
|
|
return comm.GetLastResult();
|
|
}
|
|
// NULL終端する
|
|
reinterpret_cast<u8*>(buf)[bodySize] = '\0';
|
|
|
|
if(!comm.Finalize())
|
|
{
|
|
return comm.GetLastResult();
|
|
}
|
|
|
|
// XMLを解析してタイトルリストを設定する
|
|
NN_UTIL_RETURN_IF_FAILED(ParseXmlData(buf, list, num));
|
|
|
|
return nn::ResultSuccess();
|
|
}
|
|
|
|
nn::Result PreinstallImporter::ParseXmlData(void* buf, nn::ProgramId* list, size_t* num)
|
|
{
|
|
// 通信結果をパースする
|
|
// SimpleXmlParserに食わせるために変換する
|
|
SimpleXmlPreprocessor pp;
|
|
// システムヒープ(8MB)を超えたら正常に動かない
|
|
std::string xmlResult(reinterpret_cast<char*>(buf));
|
|
pp.Canonicalize(xmlResult);
|
|
|
|
// XMLをパースしてタイトルリストを取得する
|
|
nn::fnd::IAllocator* pAllocator = nn::init::GetAllocator();
|
|
nn::xml::simple::SimpleXmlParser simpleXmlParser(pAllocator);
|
|
const nn::xml::simple::SimpleXmlParser::Node* pTaskIdNode;
|
|
|
|
NN_UTIL_RETURN_IF_FAILED(
|
|
SetNodetoTitleIds(simpleXmlParser, xmlResult, &pTaskIdNode)
|
|
);
|
|
|
|
// タイトルIDリストをコピーする
|
|
common::HeapManager xmlHeap(pTaskIdNode->contentSize);
|
|
void* titleIdBuffer = xmlHeap.GetAddr();
|
|
std::memcpy(titleIdBuffer, pTaskIdNode->content, pTaskIdNode->contentSize);
|
|
|
|
SplitTextAndSetupList(list, num, reinterpret_cast<char*>(titleIdBuffer));
|
|
return nn::ResultSuccess();
|
|
}
|
|
|
|
nn::Result PreinstallImporter::SetNodetoTitleIds(nn::xml::simple::SimpleXmlParser& parser, std::string& xmlData, const nn::xml::simple::SimpleXmlParser::Node** pNode)
|
|
{
|
|
/*
|
|
* SimpleXmlPreprocessorを通したXMLデータはこんな形になっている
|
|
<Envelope>
|
|
<Body>
|
|
<GetPreInstalledInfoResponse>
|
|
<GetPreInstalledInfoResponse>
|
|
<Version></Version>
|
|
<MessageId></MessageId>
|
|
<TimeStamp>1326939225587</TimeStamp>
|
|
<ErrorCode>0</ErrorCode>
|
|
<ListResultTotalSize>1</ListResultTotalSize>
|
|
<PreinstalledInfo>
|
|
<DeviceId>17179924184</DeviceId>
|
|
<SerialNo>EJA20305940</SerialNo>
|
|
<Region>JPN</Region>
|
|
<ManufactureDate>1324339327000</ManufactureDate>
|
|
<TitleIds>000400000FEEB400,000400000FEEB000</TitleIds>
|
|
</PreinstalledInfo>
|
|
</GetPreInstalledInfoResponse>
|
|
</GetPreInstalledInfoResponse>
|
|
</Body>
|
|
</Envelope>
|
|
*/
|
|
|
|
parser.parse(reinterpret_cast<u8*>(const_cast<char*>(xmlData.c_str())), xmlData.size());
|
|
|
|
if(parser.isError())
|
|
{
|
|
COMMON_LOGGER("invalid xml Data\n");
|
|
return nn::Result(nn::Result::LEVEL_STATUS, nn::Result::SUMMARY_INVALID_STATE, nn::Result::MODULE_COMMON,
|
|
nn::Result::DESCRIPTION_INVALID_RESULT_VALUE);
|
|
}
|
|
|
|
// 欲しい情報がある場所まで階層を掘り下げる
|
|
const nn::xml::simple::SimpleXmlParser::Node* pRootNode = parser.getRootNode();
|
|
const nn::xml::simple::SimpleXmlParser::Node* pTargetNode = pRootNode->firstChild;
|
|
const nn::xml::simple::SimpleXmlParser::Node* pPriorityNode = nn::xml::simple::SimpleXmlParser::FindNextNode(
|
|
pTargetNode, "Body");
|
|
pPriorityNode = nn::xml::simple::SimpleXmlParser::FindNextNode(pPriorityNode->firstChild,
|
|
"GetPreInstalledInfoResponse");
|
|
pPriorityNode = nn::xml::simple::SimpleXmlParser::FindNextNode(pPriorityNode->firstChild,
|
|
"GetPreInstalledInfoResponse");
|
|
pPriorityNode = nn::xml::simple::SimpleXmlParser::FindNextNode(pPriorityNode->firstChild, "PreinstalledInfo");
|
|
|
|
*pNode = nn::xml::simple::SimpleXmlParser::FindNextNode(pPriorityNode->firstChild, "TitleIds");
|
|
|
|
return nn::ResultSuccess();
|
|
}
|
|
|
|
void PreinstallImporter::SplitTextAndSetupList(nn::ProgramId* list, size_t* num, char* text)
|
|
{
|
|
const char* token = ",";
|
|
char* cutout;
|
|
|
|
*num = 0;
|
|
cutout = std::strtok(text, token);
|
|
if(!cutout)
|
|
{
|
|
return;
|
|
}
|
|
|
|
list[*num] = std::strtoll(cutout, NULL, 16);
|
|
(*num)++;
|
|
|
|
while( cutout )
|
|
{
|
|
cutout = std::strtok(NULL, token);
|
|
if(cutout)
|
|
{
|
|
list[*num] = std::strtoll(cutout, NULL, 16);
|
|
(*num)++;
|
|
}
|
|
}
|
|
}
|
|
|
|
} /* namespace ConsoleRestore */
|