Use different path for patched executable. (#70)

* Use different path for patched executable.

* Use error code variant on std::filesystem::create_directories.
This commit is contained in:
Darío 2025-01-10 08:57:34 -03:00 committed by GitHub
parent b9cffba14d
commit 0737ff771d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 33 deletions

View file

@ -17,6 +17,7 @@
static const std::string GameDirectory = "game"; static const std::string GameDirectory = "game";
static const std::string DLCDirectory = "dlc"; static const std::string DLCDirectory = "dlc";
static const std::string PatchedDirectory = "patched";
static const std::string ApotosShamarDirectory = DLCDirectory + "/Apotos & Shamar Adventure Pack"; static const std::string ApotosShamarDirectory = DLCDirectory + "/Apotos & Shamar Adventure Pack";
static const std::string ChunnanDirectory = DLCDirectory + "/Chun-nan Adventure Pack"; static const std::string ChunnanDirectory = DLCDirectory + "/Chun-nan Adventure Pack";
static const std::string EmpireCityAdabatDirectory = DLCDirectory + "/Empire City & Adabat Adventure Pack"; static const std::string EmpireCityAdabatDirectory = DLCDirectory + "/Empire City & Adabat Adventure Pack";
@ -104,7 +105,8 @@ static bool copyFile(const FilePair &pair, const uint64_t *fileHashes, VirtualFi
std::filesystem::path parentPath = targetPath.parent_path(); std::filesystem::path parentPath = targetPath.parent_path();
if (!std::filesystem::exists(parentPath)) if (!std::filesystem::exists(parentPath))
{ {
std::filesystem::create_directories(parentPath); std::error_code ec;
std::filesystem::create_directories(parentPath, ec);
} }
while (!parentPath.empty()) { while (!parentPath.empty()) {
@ -196,9 +198,10 @@ static DLC detectDLC(const std::filesystem::path &sourcePath, VirtualFileSystem
} }
} }
bool Installer::checkGameInstall(const std::filesystem::path &baseDirectory) bool Installer::checkGameInstall(const std::filesystem::path &baseDirectory, std::filesystem::path &modulePath)
{ {
return std::filesystem::exists(baseDirectory / GameDirectory / GameExecutableFile); modulePath = baseDirectory / PatchedDirectory / GameExecutableFile;
return std::filesystem::exists(modulePath);
} }
bool Installer::checkDLCInstall(const std::filesystem::path &baseDirectory, DLC dlc) bool Installer::checkDLCInstall(const std::filesystem::path &baseDirectory, DLC dlc)
@ -255,7 +258,8 @@ bool Installer::computeTotalSize(std::span<const FilePair> filePairs, const uint
bool Installer::copyFiles(std::span<const FilePair> filePairs, const uint64_t *fileHashes, VirtualFileSystem &sourceVfs, const std::filesystem::path &targetDirectory, const std::string &validationFile, bool skipHashChecks, Journal &journal, const std::function<void()> &progressCallback) bool Installer::copyFiles(std::span<const FilePair> filePairs, const uint64_t *fileHashes, VirtualFileSystem &sourceVfs, const std::filesystem::path &targetDirectory, const std::string &validationFile, bool skipHashChecks, Journal &journal, const std::function<void()> &progressCallback)
{ {
if (!std::filesystem::exists(targetDirectory) && !std::filesystem::create_directories(targetDirectory)) std::error_code ec;
if (!std::filesystem::exists(targetDirectory) && !std::filesystem::create_directories(targetDirectory, ec))
{ {
journal.lastResult = Journal::Result::DirectoryCreationFailed; journal.lastResult = Journal::Result::DirectoryCreationFailed;
journal.lastErrorMessage = "Unable to create directory at " + fromPath(targetDirectory); journal.lastErrorMessage = "Unable to create directory at " + fromPath(targetDirectory);
@ -452,12 +456,28 @@ bool Installer::install(const Sources &sources, const std::filesystem::path &tar
return false; return false;
} }
// Create the directory where the patched executable will be stored.
std::error_code ec;
std::filesystem::path patchedDirectory = targetDirectory / PatchedDirectory;
if (!std::filesystem::exists(patchedDirectory) && !std::filesystem::create_directories(patchedDirectory, ec))
{
journal.lastResult = Journal::Result::DirectoryCreationFailed;
journal.lastErrorMessage = "Unable to create directory at " + fromPath(patchedDirectory);
return false;
}
journal.createdDirectories.insert(patchedDirectory);
// Patch the executable with the update's file. // Patch the executable with the update's file.
std::filesystem::path baseXexPath = targetDirectory / GameDirectory / GameExecutableFile; std::filesystem::path baseXexPath = targetDirectory / GameDirectory / GameExecutableFile;
std::filesystem::path patchPath = targetDirectory / UpdateDirectory / UpdateExecutablePatchFile; std::filesystem::path patchPath = targetDirectory / UpdateDirectory / UpdateExecutablePatchFile;
std::filesystem::path patchedXexPath = targetDirectory / GameDirectory / (GameExecutableFile + TempExtension); std::filesystem::path patchedXexPath = patchedDirectory / GameExecutableFile;
XexPatcher::Result patcherResult = XexPatcher::apply(baseXexPath, patchPath, patchedXexPath); XexPatcher::Result patcherResult = XexPatcher::apply(baseXexPath, patchPath, patchedXexPath);
if (patcherResult != XexPatcher::Result::Success) if (patcherResult == XexPatcher::Result::Success)
{
journal.createdFiles.push_back(patchedXexPath);
}
else
{ {
journal.lastResult = Journal::Result::PatchProcessFailed; journal.lastResult = Journal::Result::PatchProcessFailed;
journal.lastPatcherResult = patcherResult; journal.lastPatcherResult = patcherResult;
@ -469,28 +489,6 @@ bool Installer::install(const Sources &sources, const std::filesystem::path &tar
journal.progressCounter += PatcherContribution; journal.progressCounter += PatcherContribution;
progressCallback(); progressCallback();
// Replace the executable by renaming and deleting in a safe way.
std::error_code ec;
std::filesystem::path oldXexPath = targetDirectory / GameDirectory / (GameExecutableFile + OldExtension);
std::filesystem::rename(baseXexPath, oldXexPath, ec);
if (ec)
{
journal.lastResult = Journal::Result::PatchReplacementFailed;
journal.lastErrorMessage = "Failed to rename executable.";
return false;
}
std::filesystem::rename(patchedXexPath, baseXexPath, ec);
if (ec)
{
std::filesystem::rename(oldXexPath, baseXexPath, ec);
journal.lastResult = Journal::Result::PatchReplacementFailed;
journal.lastErrorMessage = "Failed to rename executable.";
return false;
}
std::filesystem::remove(oldXexPath);
return true; return true;
} }

View file

@ -71,7 +71,7 @@ struct Installer
uint64_t totalSize = 0; uint64_t totalSize = 0;
}; };
static bool checkGameInstall(const std::filesystem::path &baseDirectory); static bool checkGameInstall(const std::filesystem::path &baseDirectory, std::filesystem::path &modulePath);
static bool checkDLCInstall(const std::filesystem::path &baseDirectory, DLC dlc); static bool checkDLCInstall(const std::filesystem::path &baseDirectory, DLC dlc);
static bool checkAllDLC(const std::filesystem::path &baseDirectory); static bool checkAllDLC(const std::filesystem::path &baseDirectory);
static bool computeTotalSize(std::span<const FilePair> filePairs, const uint64_t *fileHashes, VirtualFileSystem &sourceVfs, Journal &journal, uint64_t &totalSize); static bool computeTotalSize(std::span<const FilePair> filePairs, const uint64_t *fileHashes, VirtualFileSystem &sourceVfs, Journal &journal, uint64_t &totalSize);

View file

@ -19,8 +19,6 @@
#include <ui/installer_wizard.h> #include <ui/installer_wizard.h>
#include <mod/mod_loader.h> #include <mod/mod_loader.h>
#define GAME_XEX_PATH "game:\\default.xex"
const size_t XMAIOBegin = 0x7FEA0000; const size_t XMAIOBegin = 0x7FEA0000;
const size_t XMAIOEnd = XMAIOBegin + 0x0000FFFF; const size_t XMAIOEnd = XMAIOBegin + 0x0000FFFF;
@ -171,7 +169,8 @@ int main(int argc, char *argv[])
HostStartup(); HostStartup();
bool isGameInstalled = Installer::checkGameInstall(GAME_INSTALL_DIRECTORY); std::filesystem::path modulePath;
bool isGameInstalled = Installer::checkGameInstall(GAME_INSTALL_DIRECTORY, modulePath);
bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled; bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled;
if (runInstallerWizard) if (runInstallerWizard)
{ {
@ -189,7 +188,6 @@ int main(int argc, char *argv[])
KiSystemStartup(); KiSystemStartup();
auto modulePath = FileSystem::ResolvePath(GAME_XEX_PATH, false);
uint32_t entry = LdrLoadModule(modulePath); uint32_t entry = LdrLoadModule(modulePath);
if (!runInstallerWizard) if (!runInstallerWizard)