```
#include <iostream>
#include <windows.h>
#include <string>
#include <vector>
#include <stdexcept>
#include <algorithm>

// Structure to represent a 128-bit unsigned integer using two 64-bit parts
struct UInt128 {
    ULONGLONG high;
    ULONGLONG low;

    UInt128() : high(0), low(0) {}

    // Multiply by base and add digit
    bool multiplyAndAdd(int base, int digit) {
        // Multiply low by base using _umul128
        ULONGLONG multHigh = 0;
        ULONGLONG multLow = _umul128(this->low, base, &multHigh); // MSVC supports _umul128

        // Add digit to multLow and handle carry
        ULONGLONG newLow = multLow + digit;
        ULONGLONG carry = 0;
        if (newLow < multLow) { // Overflow occurred
            carry = 1;
        }

        // Add multHigh and carry to high
        ULONGLONG newHigh = multHigh + carry;

        // Check for overflow in high
        if (newHigh < multHigh) {
            return false; // Overflow
        }

        this->low = newLow;
        this->high = newHigh;
        return true;
    }

    // Convert to bytes (little-endian)
    void toBytes(BYTE* buffer) const {
        memcpy(buffer, &low, sizeof(ULONGLONG));
        memcpy(buffer + sizeof(ULONGLONG), &high, sizeof(ULONGLONG));
    }
};

// Function to convert a single character to its integer value based on the base
int CharToInt(wchar_t ch) {
    if (ch >= L'0' && ch <= L'9') return ch - L'0';
    if (ch >= L'a' && ch <= L'z') return ch - L'a' + 10;
    if (ch >= L'A' && ch <= L'Z') return ch - L'A' + 10;
    throw std::invalid_argument("Invalid character for the specified base.");
}

// Function to parse a string into ULONGLONG based on the specified base
ULONGLONG ParseStringToULONGLONG(const std::wstring& str, int base) {
    if (str.empty()) {
        throw std::invalid_argument("Empty string is not a valid number.");
    }
    size_t idx = 0;
    ULONGLONG value = 0;
    try {
        value = std::stoull(str, &idx, base);
    }
    catch (const std::exception& e) {
        throw std::invalid_argument("Error parsing number: " + std::string(e.what()));
    }
    if (idx != str.length()) {
        throw std::invalid_argument("Invalid characters found in the number string.");
    }
    return value;
}

// Function to parse a string into UInt128 based on the specified base
UInt128 ParseStringToUInt128(const std::wstring& str, int base) {
    if (str.empty()) {
        throw std::invalid_argument("Empty string is not a valid number.");
    }

    UInt128 number;
    // Process each character in the string
    for (wchar_t ch : str) {
        // Convert character to digit
        int digit = CharToInt(ch);
        if (digit >= base) {
            throw std::invalid_argument("Digit value exceeds the specified base.");
        }

        // Multiply current number by base and add digit
        if (!number.multiplyAndAdd(base, digit)) {
            throw std::overflow_error("Overflow occurred during multiplication or addition.");
        }
    }

    return number;
}

// Function to parse a hex string into FILE_ID_128
bool ParseHexToFileId128(const std::wstring& hexStr, FILE_ID_128& fileId128) {
    if (hexStr.length() != 32) {
        throw std::invalid_argument("Hex string must be exactly 32 characters for FILE_ID_128.");
    }

    // Convert hex string to bytes
    for (size_t i = 0; i < 16; ++i) {
        wchar_t highChar = hexStr[2 * i];
        wchar_t lowChar = hexStr[2 * i + 1];
        int highNibble = CharToInt(highChar);
        int lowNibble = CharToInt(lowChar);
        fileId128.Identifier[i] = static_cast<BYTE>((highNibble << 4) | lowNibble);
    }

    return true;
}

// Function to parse a string into FILE_ID_128 based on base
bool ParseStringToFileId128(const std::wstring& str, int base, FILE_ID_128& fileId128) {
    // Convert the input string from the specified base to UInt128
    UInt128 number;
    try {
        number = ParseStringToUInt128(str, base);
    }
    catch (const std::exception& e) {
        throw std::invalid_argument("Error parsing 128-bit file ID: " + std::string(e.what()));
    }

    // Split the UInt128 into high and low parts
    // Convert to bytes (little-endian)
    number.toBytes(fileId128.Identifier);

    return true;
}

// Function to get the path from FILE_ID_DESCRIPTOR
std::wstring GetPathFromId(const std::wstring& volumePath, const FILE_ID_DESCRIPTOR& fileIdDesc) {
    HANDLE hVolume = CreateFileW(
        volumePath.c_str(),
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS,
        NULL
    );

    if (hVolume == INVALID_HANDLE_VALUE) {
        std::wcerr << L"Error opening volume \"" << volumePath << L"\". Error code: " << GetLastError() << std::endl;
        return L"";
    }

    // OpenFileById expects a non-const pointer
    FILE_ID_DESCRIPTOR mutableFileIdDesc = fileIdDesc;

    HANDLE hFile = OpenFileById(
        hVolume,
        &mutableFileIdDesc,
        FILE_READ_ATTRIBUTES, // Specify desired access
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        NULL,
        FILE_FLAG_BACKUP_SEMANTICS
    );

    CloseHandle(hVolume);

    if (hFile == INVALID_HANDLE_VALUE) {
        std::wcerr << L"Error opening file/directory by ID. Error code: " << GetLastError() << std::endl;
        return L"";
    }

    DWORD dwSize = MAX_PATH;
    std::vector<wchar_t> filePath(dwSize);
    DWORD dwRet;

    while (true) {
        dwRet = GetFinalPathNameByHandleW(hFile, filePath.data(), dwSize, FILE_NAME_NORMALIZED);
        if (dwRet == 0) {
            std::wcerr << L"Error getting file/directory path. Error code: " << GetLastError() << std::endl;
            CloseHandle(hFile);
            return L"";
        }
        if (dwRet < dwSize)
            break;
        dwSize *= 2;
        filePath.resize(dwSize);
    }

    CloseHandle(hFile);

    std::wstring result(filePath.begin(), filePath.begin() + dwRet);

    // Remove "\\?\" prefix if present
    const std::wstring prefix = L"\\\\?\\";
    if (result.substr(0, prefix.length()) == prefix)
        result = result.substr(prefix.length());

    return result;
}

int wmain(int argc, wchar_t* argv[]) {
    // Initialize default base
    int base = 10;
    std::wstring volumePath;
    std::wstring fileIdStr;

    // Positional arguments will be stored separately
    std::vector<std::wstring> positionalArgs;

    // Parse command-line arguments
    for (int i = 1; i < argc; ++i) {
        std::wstring arg = argv[i];
        if (arg.rfind(L"-", 0) == 0) { // Argument starts with '-'
            if (arg == L"-base") {
                if (i + 1 >= argc) {
                    std::wcerr << L"Option " << arg << L" requires a value." << std::endl;
                    return 1;
                }
                std::wstring baseStr = argv[++i];
                try {
                    base = std::stoi(baseStr);
                    if (base < 2 || base > 36) {
                        throw std::out_of_range("Base must be between 2 and 36.");
                    }
                }
                catch (const std::exception& e) {
                    std::wcerr << L"Invalid base value: " << baseStr << L". " << e.what() << std::endl;
                    return 1;
                }
            }
            else {
                std::wcerr << L"Unknown option: " << arg << std::endl;
                std::wcerr << L"Usage: " << argv[0] << L" [-base <base>] <volume_path> <file_id>" << std::endl;
                return 1;
            }
        }
        else { // Positional argument
            positionalArgs.push_back(arg);
        }
    }

    // After parsing, positionalArgs should have exactly 2 elements: volumePath and fileIdStr
    if (positionalArgs.size() != 2) {
        std::wcerr << L"Incorrect number of arguments." << std::endl;
        std::wcerr << L"Usage: " << argv[0] << L" [-base <base>] <volume_path> <file_id>" << std::endl;
        std::wcerr << L"Examples:" << std::endl;
        std::wcerr << L"  " << argv[0] << L" C:\\ 1234567890" << std::endl; // Default base 10, 64-bit
        std::wcerr << L"  " << argv[0] << L" -base 16 C:\\ 1A2B3C4D5E6F7890" << std::endl; // Base 16, 64-bit
        std::wcerr << L"  " << argv[0] << L" C:\\ -base 16 1A2B3C4D5E6F78901A2B3C4D5E6F7890" << std::endl; // Base 16, 128-bit
        std::wcerr << L"  " << argv[0] << L" -base 2 C:\\ 10101010101010101010101010101010" << std::endl; // Base 2, 64-bit
        return 1;
    }

    volumePath = positionalArgs[0];
    fileIdStr = positionalArgs[1];

    // Normalize the file ID string to uppercase for consistency (if base > 10 and alphanumeric)
    if (base > 10) {
        std::transform(fileIdStr.begin(), fileIdStr.end(), fileIdStr.begin(), ::towupper);
    }

    FILE_ID_DESCRIPTOR fileIdDesc = { 0 };
    fileIdDesc.dwSize = sizeof(FILE_ID_DESCRIPTOR);

    try {
        bool is128Bit = false;

        if (base == 16) {
            if (fileIdStr.length() == 32) { // 128-bit in base 16
                FILE_ID_128 fileId128;
                ParseHexToFileId128(fileIdStr, fileId128);
                fileIdDesc.Type = ExtendedFileIdType;
                memcpy(fileIdDesc.ExtendedFileId.Identifier, fileId128.Identifier, 16);
                is128Bit = true;
            }
            else if (fileIdStr.length() == 16) { // 64-bit in base 16
                ULONGLONG fileId = ParseStringToULONGLONG(fileIdStr, base);
                fileIdDesc.Type = FileIdType;
                fileIdDesc.FileId.QuadPart = fileId;
            }
            else {
                throw std::invalid_argument("For base 16, file ID must be either 16 (64-bit) or 32 (128-bit) hexadecimal characters.");
            }
        }
        else {
            // For bases other than 16, attempt to parse as UInt128 and determine if it fits in 64-bit
            UInt128 number = ParseStringToUInt128(fileIdStr, base);

            if (number.high == 0) { // Fits in 64-bit
                fileIdDesc.Type = FileIdType;
                fileIdDesc.FileId.QuadPart = number.low;
            }
            else { // Assign to ExtendedFileId
                FILE_ID_128 fileId128;
                number.toBytes(fileId128.Identifier);
                fileIdDesc.Type = ExtendedFileIdType;
                memcpy(fileIdDesc.ExtendedFileId.Identifier, fileId128.Identifier, 16);
                is128Bit = true;
            }
        }
    }
    catch (const std::exception& e) {
        std::wcerr << L"Error parsing file ID: " << e.what() << std::endl;
        return 1;
    }

    std::wstring path = GetPathFromId(volumePath, fileIdDesc);

    if (!path.empty()) {
        DWORD attributes = GetFileAttributesW(path.c_str());
        if (attributes != INVALID_FILE_ATTRIBUTES) {
            if (attributes & FILE_ATTRIBUTE_DIRECTORY) {
                std::wcout << L"Directory Path: " << path << std::endl;
            }
            else {
                std::wcout << L"File Path: " << path << std::endl;
            }
        }
        else {
            std::wcerr << L"Error getting file/directory attributes. Error code: " << GetLastError() << std::endl;
        }
    }
    else {
        std::wcerr << L"Failed to retrieve path." << std::endl;
        return 1;
    }

    return 0;
}
```

any error in the above code? here is the prompt:
```
> PathToFileId "N:\RJ360925"
NTFS File ID (64-bit): 4611686018427416623 (Base 10)
NTFS File ID (64-bit): 400000000000702F (Base 16)
NTFS File ID (128-bit): 529772043052864612859904 (Base 10)
NTFS File ID (128-bit): 000000000000702F0000000000000000 (Base 16)

> FileIdToPath.exe N: 4611686018427416623
Directory Path: N:\RJ360925

>  FileIdToPath.exe N: 529772043052864612859904
Error opening file/directory by ID. Error code: 87
Failed to retrieve path.
```