Merge pull request #2254 from RadWolfie/cleanup-emufile

Small Clean Up Portion of EmuFile Usage
This commit is contained in:
ergo720 2021-07-05 11:25:01 +02:00 committed by GitHub
commit 6e68433dbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 85 additions and 72 deletions

View File

@ -95,9 +95,6 @@ char szFolder_CxbxReloadedData[MAX_PATH] = { 0 };
char szFilePath_EEPROM_bin[MAX_PATH] = { 0 }; char szFilePath_EEPROM_bin[MAX_PATH] = { 0 };
char szFilePath_Xbe[xbox::max_path*2] = { 0 }; // NOTE: LAUNCH_DATA_HEADER's szLaunchPath is xbox::max_path*2 = 520 char szFilePath_Xbe[xbox::max_path*2] = { 0 }; // NOTE: LAUNCH_DATA_HEADER's szLaunchPath is xbox::max_path*2 = 520
std::string CxbxBasePath;
std::string MuBasePath;
HANDLE CxbxBasePathHandle;
Xbe* CxbxKrnl_Xbe = NULL; Xbe* CxbxKrnl_Xbe = NULL;
bool g_bIsChihiro = false; bool g_bIsChihiro = false;
bool g_bIsDebug = false; bool g_bIsDebug = false;
@ -1431,17 +1428,18 @@ __declspec(noreturn) void CxbxKrnlInit
// Initialize devices : // Initialize devices :
{ {
char szBuffer[sizeof(szFilePath_Xbe)]; char cxbxr_data_path[sizeof(szFilePath_Xbe)];
g_EmuShared->GetStorageLocation(szBuffer); g_EmuShared->GetStorageLocation(cxbxr_data_path);
MuBasePath = std::string(szBuffer) + "\\EmuMu"; g_DiskBasePath = std::string(cxbxr_data_path) + "\\EmuDisk";
CxbxBasePath = std::string(szBuffer) + "\\EmuDisk"; g_MuBasePath = std::string(cxbxr_data_path) + "\\EmuMu";
CxbxResolveHostToFullPath(CxbxBasePath, "Cxbx-Reloaded's EmuDisk directory"); CxbxResolveHostToFullPath(g_DiskBasePath, "Cxbx-Reloaded's EmuDisk directory");
CxbxResolveHostToFullPath(MuBasePath, "Cxbx-Reloaded's EmuMu directory"); CxbxResolveHostToFullPath(g_MuBasePath, "Cxbx-Reloaded's EmuMu directory");
// Since canonical always remove the extra slash, we need to manually add it back. // Since canonical always remove the extra slash, we need to manually add it back.
// TODO: Once CxbxBasePath is filesystem::path, replace CxbxBasePath's + operators to / for include path separator internally. // TODO: Once g_DiskBasePath is filesystem::path, replace g_DiskBasePath's + operators to / for include path separator internally.
CxbxBasePath = std::filesystem::path(CxbxBasePath).append("").string(); g_DiskBasePath = std::filesystem::path(g_DiskBasePath).append("").string();
MuBasePath = std::filesystem::path(MuBasePath).append("").string(); g_MuBasePath = std::filesystem::path(g_MuBasePath).append("").string();
// NOTE: Do NOT modify global variables above after this point!
} }
// Determine xbe path // Determine xbe path
@ -1471,9 +1469,9 @@ __declspec(noreturn) void CxbxKrnlInit
} }
CxbxResolveHostToFullPath(relative_path, "xbe's directory"); CxbxResolveHostToFullPath(relative_path, "xbe's directory");
CxbxBasePathHandle = CreateFile(CxbxBasePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); g_DiskBasePathHandle = CreateFile(g_DiskBasePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
int CxbxCdrom0DeviceIndex = -1; int CxbxCdrom0DeviceIndex = -1;
bool isEmuDisk = _strnicmp(relative_path.c_str(), CxbxBasePath.c_str(), CxbxBasePath.size() - 1) == 0; bool isEmuDisk = CxbxrIsPathInsideEmuDisk(relative_path);
// Check if title mounth path is already set. This may occur from early boot of Chihiro title. // Check if title mounth path is already set. This may occur from early boot of Chihiro title.
char title_mount_path[sizeof(szFilePath_Xbe)]; char title_mount_path[sizeof(szFilePath_Xbe)];
const char* p_default_mount_path = title_mount_path; const char* p_default_mount_path = title_mount_path;
@ -1489,6 +1487,7 @@ __declspec(noreturn) void CxbxKrnlInit
// TODO: Find a place to make permanent placement for DeviceCdrom0 that does not have disc loaded. // TODO: Find a place to make permanent placement for DeviceCdrom0 that does not have disc loaded.
if (p_default_mount_path[0] != '\0') { if (p_default_mount_path[0] != '\0') {
// NOTE: Don't need to perform CxbxResolveHostToFullPath again for p_default_mount_path.
CxbxCdrom0DeviceIndex = CxbxRegisterDeviceHostPath(DeviceCdrom0, p_default_mount_path); CxbxCdrom0DeviceIndex = CxbxRegisterDeviceHostPath(DeviceCdrom0, p_default_mount_path);
// Since Chihiro also map Mbfs to the same path as Cdrom0, we'll map it the same way. // Since Chihiro also map Mbfs to the same path as Cdrom0, we'll map it the same way.
if (g_bIsChihiro) { if (g_bIsChihiro) {
@ -1497,31 +1496,31 @@ __declspec(noreturn) void CxbxKrnlInit
} }
// Partition 0 contains configuration data, and is accessed as a native file, instead as a folder : // Partition 0 contains configuration data, and is accessed as a native file, instead as a folder :
CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition0, CxbxBasePath + "Partition0", /*IsFile=*/true); CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition0, g_DiskBasePath + "Partition0", /*IsFile=*/true);
// The first two partitions are for Data and Shell files, respectively : // The first two partitions are for Data and Shell files, respectively :
CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition1, CxbxBasePath + "Partition1"); CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition1, g_DiskBasePath + "Partition1");
CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition2, CxbxBasePath + "Partition2"); CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition2, g_DiskBasePath + "Partition2");
// The following partitions are for caching purposes - for now we allocate up to 7 (as xbmp needs that many) : // The following partitions are for caching purposes - for now we allocate up to 7 (as xbmp needs that many) :
CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition3, CxbxBasePath + "Partition3"); CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition3, g_DiskBasePath + "Partition3");
CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition4, CxbxBasePath + "Partition4"); CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition4, g_DiskBasePath + "Partition4");
CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition5, CxbxBasePath + "Partition5"); CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition5, g_DiskBasePath + "Partition5");
CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition6, CxbxBasePath + "Partition6"); CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition6, g_DiskBasePath + "Partition6");
CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition7, CxbxBasePath + "Partition7"); CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition7, g_DiskBasePath + "Partition7");
CxbxRegisterDeviceHostPath(DevicePrefix + "\\Chihiro", CxbxBasePath + "Chihiro"); CxbxRegisterDeviceHostPath(DevicePrefix + "\\Chihiro", g_DiskBasePath + "Chihiro");
// Create the MU directories and the bin files // Create the MU directories and the bin files
CxbxRegisterDeviceHostPath(DeviceMU0, MuBasePath + "F", false, sizeof(FATX_SUPERBLOCK)); CxbxRegisterDeviceHostPath(DeviceMU0, g_MuBasePath + "F", false, sizeof(FATX_SUPERBLOCK));
CxbxRegisterDeviceHostPath(DeviceMU1, MuBasePath + "G", false, sizeof(FATX_SUPERBLOCK)); CxbxRegisterDeviceHostPath(DeviceMU1, g_MuBasePath + "G", false, sizeof(FATX_SUPERBLOCK));
CxbxRegisterDeviceHostPath(DeviceMU2, MuBasePath + "H", false, sizeof(FATX_SUPERBLOCK)); CxbxRegisterDeviceHostPath(DeviceMU2, g_MuBasePath + "H", false, sizeof(FATX_SUPERBLOCK));
CxbxRegisterDeviceHostPath(DeviceMU3, MuBasePath + "I", false, sizeof(FATX_SUPERBLOCK)); CxbxRegisterDeviceHostPath(DeviceMU3, g_MuBasePath + "I", false, sizeof(FATX_SUPERBLOCK));
CxbxRegisterDeviceHostPath(DeviceMU4, MuBasePath + "J", false, sizeof(FATX_SUPERBLOCK)); CxbxRegisterDeviceHostPath(DeviceMU4, g_MuBasePath + "J", false, sizeof(FATX_SUPERBLOCK));
CxbxRegisterDeviceHostPath(DeviceMU5, MuBasePath + "K", false, sizeof(FATX_SUPERBLOCK)); CxbxRegisterDeviceHostPath(DeviceMU5, g_MuBasePath + "K", false, sizeof(FATX_SUPERBLOCK));
CxbxRegisterDeviceHostPath(DeviceMU6, MuBasePath + "L", false, sizeof(FATX_SUPERBLOCK)); CxbxRegisterDeviceHostPath(DeviceMU6, g_MuBasePath + "L", false, sizeof(FATX_SUPERBLOCK));
CxbxRegisterDeviceHostPath(DeviceMU7, MuBasePath + "M", false, sizeof(FATX_SUPERBLOCK)); CxbxRegisterDeviceHostPath(DeviceMU7, g_MuBasePath + "M", false, sizeof(FATX_SUPERBLOCK));
std::mbstate_t ps = std::mbstate_t(); std::mbstate_t ps = std::mbstate_t();
const char *src = MuBasePath.c_str(); const char *src = g_MuBasePath.c_str();
std::wstring wMuBasePath(MuBasePath.size(), L'0'); std::wstring wMuBasePath(g_MuBasePath.size(), L'0');
std::mbsrtowcs(wMuBasePath.data(), &src, wMuBasePath.size(), &ps); std::mbsrtowcs(wMuBasePath.data(), &src, wMuBasePath.size(), &ps);
g_io_mu_metadata = new io_mu_metadata(wMuBasePath); g_io_mu_metadata = new io_mu_metadata(wMuBasePath);

View File

@ -47,7 +47,11 @@
#include <filesystem> #include <filesystem>
// partition emulation directory handles // partition emulation directory handles
HANDLE g_hCurDir_hack = NULL; // HACK: We should not be depending on this variable. Instead, we should fix/implement Ob/Io objects such as IoCreateDevice. HANDLE g_hCurDir_hack = NULL; // HACK: We should not be depending on this variable. Instead, we should fix/implement Ob/Io objects such as IoCreateDevice.
HANDLE g_DiskBasePathHandle;
std::string g_DiskBasePath;
std::string g_MuBasePath;
// Default Xbox Partition Table // Default Xbox Partition Table
#define PE_PARTFLAGS_IN_USE 0x80000000 #define PE_PARTFLAGS_IN_USE 0x80000000
@ -157,23 +161,44 @@ void io_mu_metadata::flush(const wchar_t lett)
ofs.flush(); ofs.flush();
} }
// NOTE: root_path input must already had called canonical function for optimization purpose.
static bool CxbxrIsPathInsideRootPath(const std::filesystem::path& path, const std::filesystem::path& root_path)
{
std::error_code rootError, finalError;
const std::filesystem::path rootPath = std::filesystem::canonical(root_path, rootError); // TODO: Replace rootPath to root_path when possible.
const std::filesystem::path finalPath = std::filesystem::canonical(path, finalError);
if (rootError || finalError) {
return false;
}
auto match = std::mismatch(rootPath.begin(), rootPath.end(), finalPath.begin(), finalPath.end());
return match.first == rootPath.end();
}
bool CxbxrIsPathInsideEmuDisk(const std::filesystem::path& path)
{
return CxbxrIsPathInsideRootPath(path, g_DiskBasePath);
}
static bool CxbxrIsPathInsideEmuMu(const std::filesystem::path& path)
{
return CxbxrIsPathInsideRootPath(path, g_MuBasePath);
}
DeviceType CxbxrGetDeviceTypeFromHandle(HANDLE hFile) DeviceType CxbxrGetDeviceTypeFromHandle(HANDLE hFile)
{ {
const std::wstring path = CxbxGetFinalPathNameByHandle(hFile); const std::filesystem::path path = CxbxGetFinalPathNameByHandle(hFile);
size_t pos = path.rfind(L"\\EmuDisk\\Partition"); if (CxbxrIsPathInsideEmuDisk(path)) {
if (pos != std::string::npos) {
return DeviceType::Harddisk0; return DeviceType::Harddisk0;
} }
pos = path.rfind(L"\\EmuMu"); if (CxbxrIsPathInsideEmuMu(path)) {
if (pos != std::string::npos) {
return DeviceType::MU; return DeviceType::MU;
} }
EmuDirPath hybrid_path; EmuDirPath hybrid_path;
FindEmuDirPathByDevice(DeviceCdrom0, hybrid_path); FindEmuDirPathByDevice(DeviceCdrom0, hybrid_path);
if (hybrid_path.HostDirPath != "") { if (!hybrid_path.HostDirPath.empty() && CxbxrIsPathInsideRootPath(path, hybrid_path.HostDirPath)) {
return DeviceType::Cdrom0; return DeviceType::Cdrom0;
} }
@ -202,9 +227,9 @@ void CxbxCreatePartitionHeaderFile(std::string filename, bool partition0 = false
XboxPartitionTable CxbxGetPartitionTable() XboxPartitionTable CxbxGetPartitionTable()
{ {
XboxPartitionTable table; XboxPartitionTable table;
FILE* fp = fopen((CxbxBasePath + "Partition0.bin").c_str(), "rb"); FILE* fp = fopen((g_DiskBasePath + "Partition0.bin").c_str(), "rb");
if (fp == nullptr) { if (fp == nullptr) {
CxbxKrnlCleanup("CxbxGetPartitionTable Failed:\nUnable to open file: %s", (CxbxBasePath + "Partition0.bin").c_str()); CxbxKrnlCleanup("CxbxGetPartitionTable Failed:\nUnable to open file: %s", (g_DiskBasePath + "Partition0.bin").c_str());
} }
fread(&table, sizeof(XboxPartitionTable), 1, fp); fread(&table, sizeof(XboxPartitionTable), 1, fp);
@ -215,8 +240,8 @@ XboxPartitionTable CxbxGetPartitionTable()
// Or invalid partition tables left behind from previous versions // Or invalid partition tables left behind from previous versions
// of Cxbx-Reloaded // of Cxbx-Reloaded
if (memcmp(table.Magic, BackupPartTbl.Magic, 16) != 0) { if (memcmp(table.Magic, BackupPartTbl.Magic, 16) != 0) {
DeleteFile((CxbxBasePath + "Partition0.bin").c_str()); DeleteFile((g_DiskBasePath + "Partition0.bin").c_str());
CxbxCreatePartitionHeaderFile(CxbxBasePath + "Partition0.bin", true); CxbxCreatePartitionHeaderFile(g_DiskBasePath + "Partition0.bin", true);
memcpy(&table, &BackupPartTbl, sizeof(XboxPartitionTable)); memcpy(&table, &BackupPartTbl, sizeof(XboxPartitionTable));
} }
@ -228,7 +253,7 @@ FATX_SUPERBLOCK CxbxGetFatXSuperBlock(int partitionNumber)
FATX_SUPERBLOCK superblock; FATX_SUPERBLOCK superblock;
std::stringstream ss; std::stringstream ss;
ss << CxbxBasePath << "Partition" << partitionNumber << ".bin"; ss << g_DiskBasePath << "Partition" << partitionNumber << ".bin";
FILE* fp = fopen(ss.str().c_str(), "rb"); FILE* fp = fopen(ss.str().c_str(), "rb");
fread(&superblock, sizeof(FATX_SUPERBLOCK), 1, fp); fread(&superblock, sizeof(FATX_SUPERBLOCK), 1, fp);
fclose(fp); fclose(fp);
@ -256,19 +281,6 @@ std::wstring CxbxGetFinalPathNameByHandle(HANDLE hFile)
return path; return path;
} }
static bool CxbxIsPathInsideEmuDisk(const std::filesystem::path& path)
{
std::error_code rootError, finalError;
const std::filesystem::path rootPath = std::filesystem::canonical(CxbxBasePath, rootError);
const std::filesystem::path finalPath = std::filesystem::canonical(path, finalError);
if (rootError || finalError) {
return false;
}
auto match = std::mismatch(rootPath.begin(), rootPath.end(), finalPath.begin(), finalPath.end());
return match.first == rootPath.end();
}
static int CxbxGetPartitionNumber(const std::wstring_view path) static int CxbxGetPartitionNumber(const std::wstring_view path)
{ {
const std::wstring_view partitionString = L"\\EmuDisk\\Partition"; const std::wstring_view partitionString = L"\\EmuDisk\\Partition";
@ -314,7 +326,7 @@ void CxbxFormatPartitionByHandle(HANDLE hFile)
const std::filesystem::path partitionPath = CxbxGetPartitionDataPathFromHandle(hFile); const std::filesystem::path partitionPath = CxbxGetPartitionDataPathFromHandle(hFile);
// Sanity check, make sure we are actually deleting something within the Cxbx-Reloaded folder // Sanity check, make sure we are actually deleting something within the Cxbx-Reloaded folder
if (!CxbxIsPathInsideEmuDisk(partitionPath)) { if (!CxbxrIsPathInsideEmuDisk(partitionPath)) {
EmuLog(LOG_LEVEL::WARNING, "Attempting to format a path that is not within a Cxbx-Reloaded data folder... Ignoring!\n"); EmuLog(LOG_LEVEL::WARNING, "Attempting to format a path that is not within a Cxbx-Reloaded data folder... Ignoring!\n");
return; return;
} }
@ -539,16 +551,16 @@ NTSTATUS CxbxConvertFilePath(
if (RelativePath.compare(0, DrivePrefix.length(), DrivePrefix.c_str()) == 0) if (RelativePath.compare(0, DrivePrefix.length(), DrivePrefix.c_str()) == 0)
RelativePath.erase(0, 4); RelativePath.erase(0, 4);
// Check if we where called from a File-handling API : // Check if we were called from a File-handling API :
if (!aFileAPIName.empty()) { if (!aFileAPIName.empty()) {
if (RelativePath.compare(DriveMbrom0) == 0) { if (RelativePath.compare(DriveMbrom0) == 0) {
*RootDirectory = CxbxBasePathHandle; *RootDirectory = g_DiskBasePathHandle;
HostPath = CxbxBasePath; HostPath = g_DiskBasePath;
RelativePath = MediaBoardSegaBoot0; RelativePath = MediaBoardSegaBoot0;
} }
else if (RelativePath.compare(DriveMbrom1) == 0) { else if (RelativePath.compare(DriveMbrom1) == 0) {
*RootDirectory = CxbxBasePathHandle; *RootDirectory = g_DiskBasePathHandle;
HostPath = CxbxBasePath; HostPath = g_DiskBasePath;
RelativePath = MediaBoardSegaBoot1; RelativePath = MediaBoardSegaBoot1;
} }
else if (!partitionHeader) { else if (!partitionHeader) {
@ -607,8 +619,8 @@ NTSTATUS CxbxConvertFilePath(
// Remove Harddisk0 prefix, in the hope that the remaining path might work : // Remove Harddisk0 prefix, in the hope that the remaining path might work :
RelativePath.erase(0, DeviceHarddisk0.length() + 1); RelativePath.erase(0, DeviceHarddisk0.length() + 1);
// And set Root to the folder containing the partition-folders : // And set Root to the folder containing the partition-folders :
*RootDirectory = CxbxBasePathHandle; *RootDirectory = g_DiskBasePathHandle;
HostPath = CxbxBasePath; HostPath = g_DiskBasePath;
} }
// NOTE: RootDirectory cannot be ignored. // NOTE: RootDirectory cannot be ignored.
// Any special handling for it should be done below. // Any special handling for it should be done below.
@ -650,8 +662,8 @@ NTSTATUS CxbxConvertFilePath(
*RootDirectory = find_path.HostDirHandle; *RootDirectory = find_path.HostDirHandle;
} }
} else { } else {
*RootDirectory = CxbxBasePathHandle; *RootDirectory = g_DiskBasePathHandle;
HostPath = CxbxBasePath; HostPath = g_DiskBasePath;
RelativePath = RelativeXboxPath.substr(DeviceHarddisk0.length()) + ".bin"; RelativePath = RelativeXboxPath.substr(DeviceHarddisk0.length()) + ".bin";
} }
@ -669,8 +681,8 @@ NTSTATUS CxbxConvertFilePath(
if (g_bPrintfOn) { if (g_bPrintfOn) {
EmuLog(LOG_LEVEL::DEBUG, "%s Corrected path...", aFileAPIName.c_str()); EmuLog(LOG_LEVEL::DEBUG, "%s Corrected path...", aFileAPIName.c_str());
EmuLog(LOG_LEVEL::DEBUG, " Org:\"%s\"", OriginalPath.c_str()); EmuLog(LOG_LEVEL::DEBUG, " Org:\"%s\"", OriginalPath.c_str());
if (_strnicmp(HostPath.c_str(), CxbxBasePath.c_str(), CxbxBasePath.length()) == 0) { if (_strnicmp(HostPath.c_str(), g_DiskBasePath.c_str(), g_DiskBasePath.length()) == 0) {
EmuLog(LOG_LEVEL::DEBUG, " New:\"$CxbxPath\\%s%s\"", (HostPath.substr(CxbxBasePath.length(), std::string::npos)).c_str(), RelativePath.c_str()); EmuLog(LOG_LEVEL::DEBUG, " New:\"$CxbxPath\\%s%s\"", (HostPath.substr(g_DiskBasePath.length(), std::string::npos)).c_str(), RelativePath.c_str());
} }
else else
EmuLog(LOG_LEVEL::DEBUG, " New:\"$XbePath\\%s\"", RelativePath.c_str()); EmuLog(LOG_LEVEL::DEBUG, " New:\"$XbePath\\%s\"", RelativePath.c_str());

View File

@ -119,8 +119,9 @@ inline constexpr xbox::ulong_xt fsctl_read_fatx_metadata = 0x0009411C;
inline constexpr xbox::ulong_xt fsctl_write_fatx_metadata = 0x00098120; inline constexpr xbox::ulong_xt fsctl_write_fatx_metadata = 0x00098120;
inline constexpr std::size_t mu_max_name_lenght = 32 * sizeof(xbox::wchar_xt); // MU names are in wide chars inline constexpr std::size_t mu_max_name_lenght = 32 * sizeof(xbox::wchar_xt); // MU names are in wide chars
extern std::string CxbxBasePath; extern std::string g_DiskBasePath;
extern HANDLE CxbxBasePathHandle; extern std::string g_MuBasePath;
extern HANDLE g_DiskBasePathHandle;
const size_t XboxFileInfoStructSizes[xbox::FileMaximumInformation] = { const size_t XboxFileInfoStructSizes[xbox::FileMaximumInformation] = {
0, // (index 0) 0, // (index 0)
@ -277,6 +278,7 @@ int CxbxDeviceIndexByDevicePath(const char *XboxDevicePath);
XboxDevice* CxbxDeviceByDevicePath(const std::string_view XboxDevicePath); XboxDevice* CxbxDeviceByDevicePath(const std::string_view XboxDevicePath);
XboxDevice* CxbxDeviceByHostPath(const std::string_view HostPath); XboxDevice* CxbxDeviceByHostPath(const std::string_view HostPath);
std::string CxbxConvertXboxToHostPath(const std::string_view XboxDevicePath); std::string CxbxConvertXboxToHostPath(const std::string_view XboxDevicePath);
bool CxbxrIsPathInsideEmuDisk(const std::filesystem::path& path);
char SymbolicLinkToDriveLetter(std::string aSymbolicLinkName); char SymbolicLinkToDriveLetter(std::string aSymbolicLinkName);
EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByDriveLetter(const char DriveLetter); EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByDriveLetter(const char DriveLetter);