|
@@ -1,3 +1,4 @@
|
|
|
+//go:build windows
|
|
|
// +build windows
|
|
|
|
|
|
package vhd
|
|
@@ -7,14 +8,13 @@ import (
|
|
|
"syscall"
|
|
|
|
|
|
"github.com/Microsoft/go-winio/pkg/guid"
|
|
|
- "github.com/pkg/errors"
|
|
|
"golang.org/x/sys/windows"
|
|
|
)
|
|
|
|
|
|
//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
|
|
@@ -62,13 +62,27 @@ type OpenVirtualDiskParameters struct {
|
|
|
Version2 OpenVersion2
|
|
|
}
|
|
|
|
|
|
+// 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
|
|
|
+ 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
|
|
|
}
|
|
|
|
|
@@ -146,16 +160,13 @@ 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.
|
|
|
func DetachVirtualDisk(handle syscall.Handle) (err error) {
|
|
|
if err := detachVirtualDisk(handle, 0, 0); err != nil {
|
|
|
- return errors.Wrap(err, "failed to detach virtual disk")
|
|
|
+ return fmt.Errorf("failed to detach virtual disk: %w", err)
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
@@ -185,7 +196,7 @@ func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtua
|
|
|
parameters,
|
|
|
nil,
|
|
|
); err != nil {
|
|
|
- return errors.Wrap(err, "failed to attach virtual disk")
|
|
|
+ return fmt.Errorf("failed to attach virtual disk: %w", err)
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
@@ -209,7 +220,7 @@ func AttachVhd(path string) (err error) {
|
|
|
AttachVirtualDiskFlagNone,
|
|
|
¶ms,
|
|
|
); err != nil {
|
|
|
- return errors.Wrap(err, "failed to attach virtual disk")
|
|
|
+ return fmt.Errorf("failed to attach virtual disk: %w", err)
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
@@ -234,19 +245,35 @@ 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, errors.Wrap(err, "failed to open virtual disk")
|
|
|
+ return 0, fmt.Errorf("failed to open virtual disk: %w", err)
|
|
|
}
|
|
|
return handle, nil
|
|
|
}
|
|
@@ -272,7 +299,7 @@ func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask,
|
|
|
nil,
|
|
|
&handle,
|
|
|
); err != nil {
|
|
|
- return handle, errors.Wrap(err, "failed to create virtual disk")
|
|
|
+ return handle, fmt.Errorf("failed to create virtual disk: %w", err)
|
|
|
}
|
|
|
return handle, nil
|
|
|
}
|
|
@@ -290,7 +317,7 @@ func GetVirtualDiskPhysicalPath(handle syscall.Handle) (_ string, err error) {
|
|
|
&diskPathSizeInBytes,
|
|
|
&diskPhysicalPathBuf[0],
|
|
|
); err != nil {
|
|
|
- return "", errors.Wrap(err, "failed to get disk physical path")
|
|
|
+ return "", fmt.Errorf("failed to get disk physical path: %w", err)
|
|
|
}
|
|
|
return windows.UTF16ToString(diskPhysicalPathBuf[:]), nil
|
|
|
}
|
|
@@ -314,10 +341,10 @@ func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error
|
|
|
createParams,
|
|
|
)
|
|
|
if err != nil {
|
|
|
- return fmt.Errorf("failed to create differencing vhd: %s", err)
|
|
|
+ return fmt.Errorf("failed to create differencing vhd: %w", err)
|
|
|
}
|
|
|
if err := syscall.CloseHandle(vhdHandle); err != nil {
|
|
|
- return fmt.Errorf("failed to close differencing vhd handle: %s", err)
|
|
|
+ return fmt.Errorf("failed to close differencing vhd handle: %w", err)
|
|
|
}
|
|
|
return nil
|
|
|
}
|