diff --git a/src/iso.c b/src/iso.c index f9e6c5d0..4e05aa28 100644 --- a/src/iso.c +++ b/src/iso.c @@ -920,3 +920,155 @@ out: udf_close(p_udf); return r; } + +/* + * The following is used for native ISO mounting in Windows 8 or later + */ +const GUID VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT = + { 0xEC984AECL, 0xA0F9, 0x47e9, { 0x90, 0x1F, 0x71, 0x41, 0x5A, 0x66, 0x34, 0x5B } }; + +typedef enum _VIRTUAL_DISK_ACCESS_MASK { + VIRTUAL_DISK_ACCESS_NONE = 0x00000000, + VIRTUAL_DISK_ACCESS_ATTACH_RO = 0x00010000, + VIRTUAL_DISK_ACCESS_ATTACH_RW = 0x00020000, + VIRTUAL_DISK_ACCESS_DETACH = 0x00040000, + VIRTUAL_DISK_ACCESS_GET_INFO = 0x00080000, + VIRTUAL_DISK_ACCESS_CREATE = 0x00100000, + VIRTUAL_DISK_ACCESS_METAOPS = 0x00200000, + VIRTUAL_DISK_ACCESS_READ = 0x000d0000, + VIRTUAL_DISK_ACCESS_ALL = 0x003f0000, + VIRTUAL_DISK_ACCESS_WRITABLE = 0x00320000 +} VIRTUAL_DISK_ACCESS_MASK; + +typedef enum _OPEN_VIRTUAL_DISK_FLAG { + OPEN_VIRTUAL_DISK_FLAG_NONE = 0x00000000, + OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS = 0x00000001, + OPEN_VIRTUAL_DISK_FLAG_BLANK_FILE = 0x00000002, + OPEN_VIRTUAL_DISK_FLAG_BOOT_DRIVE = 0x00000004, + OPEN_VIRTUAL_DISK_FLAG_CACHED_IO = 0x00000008, + OPEN_VIRTUAL_DISK_FLAG_CUSTOM_DIFF_CHAIN = 0x00000010 +} OPEN_VIRTUAL_DISK_FLAG; + +typedef enum _OPEN_VIRTUAL_DISK_VERSION { + OPEN_VIRTUAL_DISK_VERSION_UNSPECIFIED = 0, + OPEN_VIRTUAL_DISK_VERSION_1 = 1, + OPEN_VIRTUAL_DISK_VERSION_2 = 2 +} OPEN_VIRTUAL_DISK_VERSION; + +typedef enum _ATTACH_VIRTUAL_DISK_FLAG { + ATTACH_VIRTUAL_DISK_FLAG_NONE = 0x00000000, + ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY = 0x00000001, + ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER = 0x00000002, + ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME = 0x00000004, + ATTACH_VIRTUAL_DISK_FLAG_NO_LOCAL_HOST = 0x00000008 +} ATTACH_VIRTUAL_DISK_FLAG; + +typedef enum _ATTACH_VIRTUAL_DISK_VERSION { + ATTACH_VIRTUAL_DISK_VERSION_UNSPECIFIED = 0, + ATTACH_VIRTUAL_DISK_VERSION_1 = 1 +} ATTACH_VIRTUAL_DISK_VERSION; + +typedef enum _DETACH_VIRTUAL_DISK_FLAG { + DETACH_VIRTUAL_DISK_FLAG_NONE = 0x00000000 +} DETACH_VIRTUAL_DISK_FLAG; + +typedef struct _VIRTUAL_STORAGE_TYPE { + ULONG DeviceId; + GUID VendorId; +} VIRTUAL_STORAGE_TYPE, *PVIRTUAL_STORAGE_TYPE; + +typedef struct _OPEN_VIRTUAL_DISK_PARAMETERS { + OPEN_VIRTUAL_DISK_VERSION Version; + union { + struct { + ULONG RWDepth; + } Version1; + struct { + BOOL GetInfoOnly; + BOOL ReadOnly; + GUID ResiliencyGuid; + } Version2; + }; +} OPEN_VIRTUAL_DISK_PARAMETERS, *POPEN_VIRTUAL_DISK_PARAMETERS; + +typedef struct _ATTACH_VIRTUAL_DISK_PARAMETERS { + ATTACH_VIRTUAL_DISK_VERSION Version; + union { + struct { + ULONG Reserved; + } Version1; + }; +} ATTACH_VIRTUAL_DISK_PARAMETERS, *PATTACH_VIRTUAL_DISK_PARAMETERS; + +// VirtDisk API Prototypes - Only available for Windows 8 or later +PF_TYPE_DECL(WINAPI, DWORD, OpenVirtualDisk, (PVIRTUAL_STORAGE_TYPE, PCWSTR, + VIRTUAL_DISK_ACCESS_MASK, OPEN_VIRTUAL_DISK_FLAG, POPEN_VIRTUAL_DISK_PARAMETERS, PHANDLE)); +PF_TYPE_DECL(WINAPI, DWORD, AttachVirtualDisk, (HANDLE, PSECURITY_DESCRIPTOR, + ATTACH_VIRTUAL_DISK_FLAG, ULONG, PATTACH_VIRTUAL_DISK_PARAMETERS, LPOVERLAPPED)); +PF_TYPE_DECL(WINAPI, DWORD, DetachVirtualDisk, (HANDLE, DETACH_VIRTUAL_DISK_FLAG, ULONG)); +PF_TYPE_DECL(WINAPI, DWORD, GetVirtualDiskPhysicalPath, (HANDLE, PULONG, PWSTR)); + +static char physical_path[128] = ""; +static HANDLE mounted_handle = INVALID_HANDLE_VALUE; + +char* MountISO(const char* path) +{ + VIRTUAL_STORAGE_TYPE vtype = { 1, VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT }; + ATTACH_VIRTUAL_DISK_PARAMETERS vparams = { ATTACH_VIRTUAL_DISK_VERSION_1, 0 }; + DWORD r; + wchar_t wtmp[128]; + ULONG size = ARRAYSIZE(wtmp); + wconvert(path); + char* ret = NULL; + + PF_INIT_OR_OUT(OpenVirtualDisk, VirtDisk); + PF_INIT_OR_OUT(AttachVirtualDisk, VirtDisk); + PF_INIT_OR_OUT(GetVirtualDiskPhysicalPath, VirtDisk); + + if ((mounted_handle != NULL) && (mounted_handle != INVALID_HANDLE_VALUE)) + UnMountISO(); + + r = pfOpenVirtualDisk(&vtype, wpath, VIRTUAL_DISK_ACCESS_READ | VIRTUAL_DISK_ACCESS_GET_INFO, + OPEN_VIRTUAL_DISK_FLAG_NONE, NULL, &mounted_handle); + if (r != ERROR_SUCCESS) { + SetLastError(r); + uprintf("Could not open ISO '%s': %s", path, WindowsErrorString()); + goto out; + } + + r = pfAttachVirtualDisk(mounted_handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | + ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER, 0, &vparams, NULL); + if (r != ERROR_SUCCESS) { + SetLastError(r); + uprintf("Could not mount ISO '%s': %s", path, WindowsErrorString()); + goto out; + } + + r = pfGetVirtualDiskPhysicalPath(mounted_handle, &size, wtmp); + if (r != ERROR_SUCCESS) { + SetLastError(r); + uprintf("Could not obtain physical path for mounted ISO '%s': %s", path, WindowsErrorString()); + goto out; + } + wchar_to_utf8_no_alloc(wtmp, physical_path, sizeof(physical_path)); + ret = physical_path; + +out: + if (ret == NULL) + UnMountISO(); + wfree(path); + return ret; +} + +void UnMountISO(void) +{ + PF_INIT_OR_OUT(DetachVirtualDisk, VirtDisk); + + if ((mounted_handle == NULL) || (mounted_handle == INVALID_HANDLE_VALUE)) + goto out; + + pfDetachVirtualDisk(mounted_handle, DETACH_VIRTUAL_DISK_FLAG_NONE, 0); + safe_closehandle(mounted_handle); +out: + physical_path[0] = 0; +} diff --git a/src/rufus.c b/src/rufus.c index 1206ea5d..3d0b072a 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -1959,6 +1959,9 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA ShowWindow(hLogDlg, log_displayed?SW_SHOW:SW_HIDE); break; #ifdef RUFUS_TEST + case IDC_TEST: + uprintf("Mounted ISO: '%s'", MountISO("D:\\ISOs\\archlinux-2012.08.04-dual.iso")); +#if 0 if (format_thid != NULL) { return (INT_PTR)TRUE; } @@ -2006,6 +2009,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA } if (format_thid == NULL) format_op_in_progress = FALSE; +#endif break; #endif case IDC_LANG: diff --git a/src/rufus.h b/src/rufus.h index 962d4a64..e343c797 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -385,6 +385,8 @@ extern SIZE GetTextSize(HWND hCtrl); extern BOOL ExtractDOS(const char* path); extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan); extern int64_t ExtractISOFile(const char* iso, const char* iso_file, const char* dest_file, DWORD attributes); +extern char* MountISO(const char* path); +extern void UnMountISO(void); extern BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs); extern uint16_t GetSyslinuxVersion(char* buf, size_t buf_size, char** ext); extern BOOL CreateProgress(void); diff --git a/src/rufus.rc b/src/rufus.rc index 8be43350..b0ae43e4 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Rufus 2.0.0.572" +CAPTION "Rufus 2.0.0.573" FONT 8, "Segoe UI", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 @@ -157,7 +157,7 @@ END IDD_DIALOG_XP DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Rufus 2.0.0.572" +CAPTION "Rufus 2.0.0.573" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 @@ -283,7 +283,7 @@ END IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL -CAPTION "Rufus 2.0.0.572" +CAPTION "Rufus 2.0.0.573" FONT 8, "Segoe UI", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 @@ -415,7 +415,7 @@ END IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL -CAPTION "Rufus 2.0.0.572" +CAPTION "Rufus 2.0.0.573" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 @@ -669,8 +669,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,0,572 - PRODUCTVERSION 2,0,0,572 + FILEVERSION 2,0,0,573 + PRODUCTVERSION 2,0,0,573 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -687,13 +687,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "2.0.0.572" + VALUE "FileVersion", "2.0.0.573" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2015 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "2.0.0.572" + VALUE "ProductVersion", "2.0.0.573" END END BLOCK "VarFileInfo"