// +build windows package vhd import "syscall" //go:generate go run mksyscall_windows.go -output zvhd.go vhd.go //sys createVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.CreateVirtualDisk //sys openVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, flags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.OpenVirtualDisk //sys detachVirtualDisk(handle syscall.Handle, flags uint32, providerSpecificFlags uint32) (err error) [failretval != 0] = VirtDisk.DetachVirtualDisk type virtualStorageType struct { DeviceID uint32 VendorID [16]byte } type ( createVirtualDiskFlag uint32 VirtualDiskAccessMask uint32 VirtualDiskFlag uint32 ) const ( // Flags for creating a VHD (not exported) createVirtualDiskFlagNone createVirtualDiskFlag = 0 createVirtualDiskFlagFullPhysicalAllocation createVirtualDiskFlag = 1 createVirtualDiskFlagPreventWritesToSourceDisk createVirtualDiskFlag = 2 createVirtualDiskFlagDoNotCopyMetadataFromParent createVirtualDiskFlag = 4 // Access Mask for opening a VHD VirtualDiskAccessNone VirtualDiskAccessMask = 0 VirtualDiskAccessAttachRO VirtualDiskAccessMask = 65536 VirtualDiskAccessAttachRW VirtualDiskAccessMask = 131072 VirtualDiskAccessDetach VirtualDiskAccessMask = 262144 VirtualDiskAccessGetInfo VirtualDiskAccessMask = 524288 VirtualDiskAccessCreate VirtualDiskAccessMask = 1048576 VirtualDiskAccessMetaOps VirtualDiskAccessMask = 2097152 VirtualDiskAccessRead VirtualDiskAccessMask = 851968 VirtualDiskAccessAll VirtualDiskAccessMask = 4128768 VirtualDiskAccessWritable VirtualDiskAccessMask = 3276800 // Flags for opening a VHD OpenVirtualDiskFlagNone VirtualDiskFlag = 0 OpenVirtualDiskFlagNoParents VirtualDiskFlag = 0x1 OpenVirtualDiskFlagBlankFile VirtualDiskFlag = 0x2 OpenVirtualDiskFlagBootDrive VirtualDiskFlag = 0x4 OpenVirtualDiskFlagCachedIO VirtualDiskFlag = 0x8 OpenVirtualDiskFlagCustomDiffChain VirtualDiskFlag = 0x10 OpenVirtualDiskFlagParentCachedIO VirtualDiskFlag = 0x20 OpenVirtualDiskFlagVhdSetFileOnly VirtualDiskFlag = 0x40 OpenVirtualDiskFlagIgnoreRelativeParentLocator VirtualDiskFlag = 0x80 OpenVirtualDiskFlagNoWriteHardening VirtualDiskFlag = 0x100 ) type createVersion2 struct { UniqueID [16]byte // GUID MaximumSize uint64 BlockSizeInBytes uint32 SectorSizeInBytes uint32 ParentPath *uint16 // string SourcePath *uint16 // string OpenFlags uint32 ParentVirtualStorageType virtualStorageType SourceVirtualStorageType virtualStorageType ResiliencyGUID [16]byte // GUID } type createVirtualDiskParameters struct { Version uint32 // Must always be set to 2 Version2 createVersion2 } type openVersion2 struct { GetInfoOnly int32 // bool but 4-byte aligned ReadOnly int32 // bool but 4-byte aligned ResiliencyGUID [16]byte // GUID } type openVirtualDiskParameters struct { Version uint32 // Must always be set to 2 Version2 openVersion2 } // CreateVhdx will create a simple vhdx file at the given path using default values. func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error { var ( defaultType virtualStorageType handle syscall.Handle ) parameters := createVirtualDiskParameters{ Version: 2, Version2: createVersion2{ MaximumSize: uint64(maxSizeInGb) * 1024 * 1024 * 1024, BlockSizeInBytes: blockSizeInMb * 1024 * 1024, }, } if err := createVirtualDisk( &defaultType, path, uint32(VirtualDiskAccessNone), nil, uint32(createVirtualDiskFlagNone), 0, ¶meters, nil, &handle); err != nil { return err } if err := syscall.CloseHandle(handle); err != nil { return err } return nil } // DetachVhd detaches a mounted container layer vhd found at `path`. func DetachVhd(path string) error { handle, err := OpenVirtualDisk( path, VirtualDiskAccessNone, OpenVirtualDiskFlagCachedIO|OpenVirtualDiskFlagIgnoreRelativeParentLocator) if err != nil { return err } defer syscall.CloseHandle(handle) return detachVirtualDisk(handle, 0, 0) } // OpenVirtualDisk obtains a handle to a VHD opened with supplied access mask and flags. func OpenVirtualDisk(path string, accessMask VirtualDiskAccessMask, flag VirtualDiskFlag) (syscall.Handle, error) { var ( defaultType virtualStorageType handle syscall.Handle ) parameters := openVirtualDiskParameters{Version: 2} if err := openVirtualDisk( &defaultType, path, uint32(accessMask), uint32(flag), ¶meters, &handle); err != nil { return 0, err } return handle, nil }