From f8931c487e10c430d012db087bb1202fa4d40545 Mon Sep 17 00:00:00 2001 From: Daniel Canter Date: Tue, 30 Nov 2021 19:06:27 -0800 Subject: [PATCH 1/2] Fix 'OpenVirtualDiskParameters' BOOL fields While reworking the vhd package I'd mistakingly replaced some of the fields in the OpenVersion2 structure with the incorrect types. They're defined as Windows BOOLS which is just a type alias for an int, and I'd put their type as go bools. As the type is already passed into some functions, to avoid a breaking change just convert the incorrect type to a new structure with the correct definition internally. Truthfully this turns out a bit better as supplying a bool makes more sense and is more go friendly. Signed-off-by: Daniel Canter --- vhd/vhd.go | 42 +++++++++++++++++++++++++++++++++++------- vhd/zvhd_windows.go | 4 ++-- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/vhd/vhd.go b/vhd/vhd.go index 2d65f090..709e3cc4 100644 --- a/vhd/vhd.go +++ b/vhd/vhd.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package vhd @@ -13,7 +14,7 @@ import ( //go:generate go run mksyscall_windows.go -output zvhd_windows.go vhd.go //sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (win32err error) = virtdisk.CreateVirtualDisk -//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (win32err error) = virtdisk.OpenVirtualDisk +//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) = virtdisk.OpenVirtualDisk //sys attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (win32err error) = virtdisk.AttachVirtualDisk //sys detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (win32err error) = virtdisk.DetachVirtualDisk //sys getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (win32err error) = virtdisk.GetVirtualDiskPhysicalPath @@ -61,13 +62,27 @@ type OpenVirtualDiskParameters struct { Version2 OpenVersion2 } +// The OpenVersion2 structure was mistakingly changed to have the GetInfoOnly and ReadOnly fields be go bools instead +// of int32's (they're defined as Windows BOOL's so int32 is the correct type). Fix this mistake here by making the right structure we need to pass +// and not exporting it. We'll translate to the correct type as needed in any of the Open___ calls. +type openVersion2 struct { + getInfoOnly int32 + readOnly int32 + resiliencyGUID guid.GUID +} + +type openVirtualDiskParameters struct { + version uint32 + version2 openVersion2 +} + type AttachVersion2 struct { RestrictedOffset uint64 RestrictedLength uint64 } type AttachVirtualDiskParameters struct { - Version uint32 // Must always be set to 2 + Version uint32 Version2 AttachVersion2 } @@ -145,10 +160,7 @@ func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error { return err } - if err := syscall.CloseHandle(handle); err != nil { - return err - } - return nil + return syscall.CloseHandle(handle) } // DetachVirtualDisk detaches a virtual hard disk by handle. @@ -233,16 +245,32 @@ func OpenVirtualDiskWithParameters(vhdPath string, virtualDiskAccessMask Virtual var ( handle syscall.Handle defaultType VirtualStorageType + getInfoOnly int32 + readOnly int32 ) if parameters.Version != 2 { return handle, fmt.Errorf("only version 2 VHDs are supported, found version: %d", parameters.Version) } + if parameters.Version2.GetInfoOnly { + getInfoOnly = 1 + } + if parameters.Version2.ReadOnly { + readOnly = 1 + } + params := &openVirtualDiskParameters{ + version: parameters.Version, + version2: openVersion2{ + getInfoOnly, + readOnly, + parameters.Version2.ResiliencyGUID, + }, + } if err := openVirtualDisk( &defaultType, vhdPath, uint32(virtualDiskAccessMask), uint32(openVirtualDiskFlags), - parameters, + params, &handle, ); err != nil { return 0, fmt.Errorf("failed to open virtual disk: %w", err) diff --git a/vhd/zvhd_windows.go b/vhd/zvhd_windows.go index 7fb5f365..1d7498db 100644 --- a/vhd/zvhd_windows.go +++ b/vhd/zvhd_windows.go @@ -88,7 +88,7 @@ func getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint return } -func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (win32err error) { +func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) { var _p0 *uint16 _p0, win32err = syscall.UTF16PtrFromString(path) if win32err != nil { @@ -97,7 +97,7 @@ func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtua return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, openVirtualDiskFlags, parameters, handle) } -func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (win32err error) { +func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) { r0, _, _ := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(openVirtualDiskFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle))) if r0 != 0 { win32err = syscall.Errno(r0) From 0252c4c5b085ee106b59f1a4eb23ebd9687222d0 Mon Sep 17 00:00:00 2001 From: Daniel Canter Date: Fri, 3 Dec 2021 17:01:47 -0800 Subject: [PATCH 2/2] PR feedback Change openVersion2 comment Signed-off-by: Daniel Canter --- vhd/vhd.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vhd/vhd.go b/vhd/vhd.go index 709e3cc4..f7f78fc2 100644 --- a/vhd/vhd.go +++ b/vhd/vhd.go @@ -62,9 +62,9 @@ type OpenVirtualDiskParameters struct { Version2 OpenVersion2 } -// The OpenVersion2 structure was mistakingly changed to have the GetInfoOnly and ReadOnly fields be go bools instead -// of int32's (they're defined as Windows BOOL's so int32 is the correct type). Fix this mistake here by making the right structure we need to pass -// and not exporting it. We'll translate to the correct type as needed in any of the Open___ calls. +// The higher level `OpenVersion2` struct uses bools to refer to `GetInfoOnly` and `ReadOnly` for ease of use. However, +// the internal windows structure uses `BOOLS` aka int32s for these types. `openVersion2` is used for translating +// `OpenVersion2` fields to the correct windows internal field types on the `Open____` methods. type openVersion2 struct { getInfoOnly int32 readOnly int32