From 487ad3fa192718afe0617d188a686dae65f91890 Mon Sep 17 00:00:00 2001 From: Silent Date: Sat, 6 Mar 2021 18:28:10 +0100 Subject: [PATCH 1/3] CxbxFormatPartitionByHandle: Do not recurse into subdirectories Fixes a crash while formatting partitions occurring when attempting to recurse into now-deleted subdirectories. --- src/core/kernel/support/EmuFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/kernel/support/EmuFile.cpp b/src/core/kernel/support/EmuFile.cpp index 4aa93c7bc..5a38061e9 100644 --- a/src/core/kernel/support/EmuFile.cpp +++ b/src/core/kernel/support/EmuFile.cpp @@ -177,7 +177,7 @@ void CxbxFormatPartitionByHandle(HANDLE hFile) // Previously, we deleted and re-created the folder, but that caused permission issues for some users try { - for (auto& directoryEntry : std::filesystem::recursive_directory_iterator(partitionPath)) { + for (auto& directoryEntry : std::filesystem::directory_iterator(partitionPath)) { std::filesystem::remove_all(directoryEntry); } } From 35cd99a844c69b2b13b19f69e683cead52ef96dd Mon Sep 17 00:00:00 2001 From: Silent Date: Sat, 6 Mar 2021 18:37:10 +0100 Subject: [PATCH 2/3] CxbxFormatPartitionByHandle: Use non-throwing std::filesystem functions --- src/core/kernel/support/EmuFile.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/core/kernel/support/EmuFile.cpp b/src/core/kernel/support/EmuFile.cpp index 5a38061e9..b7bbb1446 100644 --- a/src/core/kernel/support/EmuFile.cpp +++ b/src/core/kernel/support/EmuFile.cpp @@ -175,17 +175,12 @@ void CxbxFormatPartitionByHandle(HANDLE hFile) // Format the partition, by iterating through the contents and removing all files/folders within // Previously, we deleted and re-created the folder, but that caused permission issues for some users - try - { - for (auto& directoryEntry : std::filesystem::directory_iterator(partitionPath)) { - std::filesystem::remove_all(directoryEntry); + std::error_code er; + for (const auto& directoryEntry : std::filesystem::directory_iterator(partitionPath, er)) { + if (!er) { + std::filesystem::remove_all(directoryEntry, er); } } - catch (std::filesystem::filesystem_error fsException) - { - printf("std::filesystem failed with message: %s\n", fsException.what()); - } - printf("Formatted EmuDisk Partition%d\n", CxbxGetPartitionNumberFromHandle(hFile)); } From f04c518d15afcfae13badddd808d6d6711cbb82d Mon Sep 17 00:00:00 2001 From: Silent Date: Sat, 6 Mar 2021 19:11:02 +0100 Subject: [PATCH 3/3] Modernize CxbxGetPartitionNumberFromHandle and CxbxGetPartitionDataPathFromHandle Now consistently uses Unicode and supports long paths --- src/core/kernel/support/EmuFile.cpp | 51 ++++++++++++++++++----------- src/core/kernel/support/EmuFile.h | 2 +- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/core/kernel/support/EmuFile.cpp b/src/core/kernel/support/EmuFile.cpp index b7bbb1446..9cde84ef6 100644 --- a/src/core/kernel/support/EmuFile.cpp +++ b/src/core/kernel/support/EmuFile.cpp @@ -132,42 +132,55 @@ FATX_SUPERBLOCK CxbxGetFatXSuperBlock(int partitionNumber) return superblock; } -int CxbxGetPartitionNumberFromHandle(HANDLE hFile) +static std::wstring CxbxGetFinalPathNameByHandle(HANDLE hFile) { - // Get which partition number is being accessed, by parsing the filename and extracting the last portion - char buffer[MAX_PATH] = {0}; - if (!GetFinalPathNameByHandle(hFile, buffer, MAX_PATH, VOLUME_NAME_DOS)) { + constexpr size_t INITIAL_BUF_SIZE = MAX_PATH; + std::wstring path(INITIAL_BUF_SIZE, '\0'); + + DWORD size = GetFinalPathNameByHandleW(hFile, path.data(), INITIAL_BUF_SIZE, VOLUME_NAME_DOS); + if (size == 0) { CxbxKrnlCleanup("CxbxGetPartitionNumberFromHandle Failed:\nUnable to determine path for HANDLE 0x%08X", hFile); } - std::string bufferString(buffer); - std::string partitionString = "\\Partition"; - std::string partitionNumberString = bufferString.substr(bufferString.find(partitionString) + partitionString.length(), 1); + // If the function fails because lpszFilePath is too small to hold the string plus the terminating null character, + // the return value is the required buffer size, in TCHARs. This value includes the size of the terminating null character. + if (size >= INITIAL_BUF_SIZE) { + path.resize(size); + size = GetFinalPathNameByHandleW(hFile, path.data(), size, VOLUME_NAME_DOS); + } + path.resize(size); - // atoi returns 0 on non-numeric characters, so we don't need to error check here - return atoi(partitionNumberString.c_str()); + return path; } -std::string CxbxGetPartitionDataPathFromHandle(HANDLE hFile) +int CxbxGetPartitionNumberFromHandle(HANDLE hFile) { // Get which partition number is being accessed, by parsing the filename and extracting the last portion - char buffer[MAX_PATH] = {0}; - if (!GetFinalPathNameByHandle(hFile, buffer, MAX_PATH, VOLUME_NAME_DOS)) { - CxbxKrnlCleanup("CxbxGetPartitionDataPathFromHandle Failed:\nUnable to determine path for HANDLE 0x%08X", hFile); - } + const std::wstring path = CxbxGetFinalPathNameByHandle(hFile); - std::string bufferString(buffer); - std::string partitionString = "\\Partition"; - std::string partitionPath = bufferString.substr(0, bufferString.find(partitionString) + partitionString.length() + 1); + const std::wstring_view partitionString = L"\\Partition"; + const std::wstring partitionNumberString = path.substr(path.find(partitionString) + partitionString.length(), 1); + + // wcstol returns 0 on non-numeric characters, so we don't need to error check here + return wcstol(partitionNumberString.c_str(), nullptr, 0); +} + +std::wstring CxbxGetPartitionDataPathFromHandle(HANDLE hFile) +{ + // Get which partition number is being accessed, by parsing the filename and extracting the last portion + const std::wstring path = CxbxGetFinalPathNameByHandle(hFile); + + const std::wstring_view partitionString = L"\\Partition"; + const std::wstring partitionPath = path.substr(0, path.find(partitionString) + partitionString.length() + 1); return partitionPath; } void CxbxFormatPartitionByHandle(HANDLE hFile) { - std::string partitionPath = CxbxGetPartitionDataPathFromHandle(hFile); + const std::wstring partitionPath = CxbxGetPartitionDataPathFromHandle(hFile); // Sanity check, make sure we are actually deleting something within the Cxbx-Reloaded folder - if (partitionPath.find("Cxbx-Reloaded") == std::string::npos) { + if (partitionPath.find(L"\\Cxbx-Reloaded\\") == std::string::npos) { EmuLog(LOG_LEVEL::WARNING, "Attempting to format a path that is not within a Cxbx-Reloaded data folder... Ignoring!\n"); return; } diff --git a/src/core/kernel/support/EmuFile.h b/src/core/kernel/support/EmuFile.h index 0c4d5a834..3fc898abf 100644 --- a/src/core/kernel/support/EmuFile.h +++ b/src/core/kernel/support/EmuFile.h @@ -307,7 +307,7 @@ typedef struct _FATX_SUPERBLOCK XboxPartitionTable CxbxGetPartitionTable(); FATX_SUPERBLOCK CxbxGetFatXSuperBlock(int partitionNumber); int CxbxGetPartitionNumberFromHandle(HANDLE hFile); -std::string CxbxGetPartitionDataPathFromHandle(HANDLE hFile); +std::wstring CxbxGetPartitionDataPathFromHandle(HANDLE hFile); void CxbxFormatPartitionByHandle(HANDLE hFile); // Ensures that an original IoStatusBlock gets passed to the completion callback