Last active
October 11, 2022 04:19
-
-
Save uemuraj/404e864f0ae9bc27a7b307d6a794f450 to your computer and use it in GitHub Desktop.
ISO ファイルをマウントしてプログラムから使用する。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define INITGUID | |
#include <Windows.h> | |
#include <virtdisk.h> | |
#include <locale> | |
#include <iostream> | |
#include <filesystem> | |
#include <system_error> | |
class VirtualDisk | |
{ | |
HANDLE m_handle; | |
public: | |
VirtualDisk(const std::filesystem::path & path) : m_handle{} | |
{ | |
constexpr auto flag = OPEN_VIRTUAL_DISK_FLAG_NONE; | |
constexpr auto mask = VIRTUAL_DISK_ACCESS_ATTACH_RO | VIRTUAL_DISK_ACCESS_DETACH | VIRTUAL_DISK_ACCESS_GET_INFO; | |
VIRTUAL_STORAGE_TYPE type{ VIRTUAL_STORAGE_TYPE_DEVICE_ISO, VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN }; | |
if (auto errocode = ::OpenVirtualDisk(&type, std::filesystem::absolute(path).c_str(), mask, flag, nullptr, &m_handle); errocode != ERROR_SUCCESS) | |
{ | |
throw std::system_error(errocode, std::system_category(), __FUNCTION__); | |
} | |
} | |
~VirtualDisk() noexcept | |
{ | |
::CloseHandle(m_handle); | |
} | |
operator HANDLE() const | |
{ | |
return m_handle; | |
} | |
}; | |
class AttachedVirtualDisk | |
{ | |
const VirtualDisk & m_disk; | |
public: | |
AttachedVirtualDisk(const VirtualDisk & disk) : m_disk(disk) | |
{ | |
constexpr auto flag = ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME; | |
ATTACH_VIRTUAL_DISK_PARAMETERS param{ ATTACH_VIRTUAL_DISK_VERSION_1 }; | |
if (auto errcode = ::AttachVirtualDisk(m_disk, nullptr, flag, 0, ¶m, nullptr); errcode != ERROR_SUCCESS) | |
{ | |
throw std::system_error(errcode, std::system_category(), __FUNCTION__); | |
} | |
} | |
~AttachedVirtualDisk() | |
{ | |
constexpr auto flag = DETACH_VIRTUAL_DISK_FLAG_NONE; | |
if (auto errcode = ::DetachVirtualDisk(m_disk, flag, 0); errcode != ERROR_SUCCESS) | |
{ | |
std::cerr << std::system_category().message(errcode) << std::endl; | |
} | |
} | |
operator std::filesystem::path() const | |
{ | |
return GetDrivePath(); | |
} | |
std::filesystem::path GetPhysicalPath() const | |
{ | |
std::wstring buff(7, 0); | |
ULONG size = (buff.size() + 1) * sizeof(wchar_t); | |
if (auto errcode = ::GetVirtualDiskPhysicalPath(m_disk, &size, buff.data()); errcode == ERROR_SUCCESS) | |
{ | |
return buff; | |
} | |
else if (errcode != ERROR_INSUFFICIENT_BUFFER) | |
{ | |
throw std::system_error(errcode, std::system_category(), __FUNCTION__); | |
} | |
buff.resize(size / sizeof(wchar_t) - 1); | |
if (auto errcode = ::GetVirtualDiskPhysicalPath(m_disk, &size, buff.data()); errcode == ERROR_SUCCESS) | |
{ | |
return buff; | |
} | |
else | |
{ | |
throw std::system_error(errcode, std::system_category(), __FUNCTION__); | |
} | |
} | |
std::filesystem::path GetDrivePath() const | |
{ | |
auto name = GetPhysicalPath().stem(); | |
DWORD index = 0, drives = ::GetLogicalDrives(); | |
while (BitScanForward(&index, drives)) | |
{ | |
wchar_t root[] = { (wchar_t) (L'A' + index), L':', L'\0', L'\0' }; | |
wchar_t buff[MAX_PATH]{}; | |
if (::QueryDosDevice(root, buff, _countof(buff)) == 0) | |
{ | |
throw std::system_error(::GetLastError(), std::system_category(), __FUNCTION__); | |
} | |
auto device = std::filesystem::path(buff).stem(); | |
if (_wcsicmp(device.c_str(), name.c_str()) == 0) | |
{ | |
root[2] = std::filesystem::path::preferred_separator; | |
return root; | |
} | |
BitTestAndReset((LONG *) &drives, index); | |
} | |
throw std::system_error(ERROR_PATH_NOT_FOUND, std::system_category(), __FUNCTION__); | |
} | |
}; | |
int wmain(int argc, wchar_t * argv[]) | |
{ | |
try | |
{ | |
std::locale::global(std::locale("")); | |
if (argc > 1) | |
{ | |
VirtualDisk iso(argv[1]); | |
AttachedVirtualDisk disk(iso); | |
for (const auto & entry : std::filesystem::directory_iterator(disk)) | |
{ | |
std::wcout << entry.path() << std::endl; | |
} | |
} | |
return 0; | |
} | |
catch (const std::exception & e) | |
{ | |
std::cerr << e.what() << std::endl; | |
return 1; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment