golang 获取windows磁盘GUID
package main
import (
"fmt"
"syscall"
"unsafe"
)
type PartitionStyle uint32
const (
IOCTL_DISK_GET_DRIVE_LAYOUT_EX = 0x00070050
PartitionStyleMbr PartitionStyle = 0
PartitionStyleGpt PartitionStyle = 1
PartitionStyleRaw PartitionStyle = 2
)
type GUID struct {
Data1 uint32
Data2 uint16
Data3 uint16
Data4 [8]byte
}
type DRIVE_LAYOUT_INFORMATION_GPT struct {
DiskId GUID
StartingUsableOffset uint64
UsableLength uint64
MaxPartitionCount uint32
}
type PARTITION_INFORMATION_MBR struct {
PartitionType byte
BootIndicator bool
RecognizedPartition bool
HiddenSectors uint32
PartitionId GUID
}
type PARTITION_INFORMATION_GPT struct {
PartitionType GUID
PartitionId GUID
Attributes uint64
Name [36]uint16
}
type PARTITION_INFORMATION_EX struct {
PartitionStyle PartitionStyle
StartingOffset int64
PartitionLength int64
PartitionNumber int32
RewritePartition bool
Rev01 bool
Rev02 bool
Rev03 bool
PartitionInfo [112]byte
}
type DRIVE_LAYOUT_INFORMATION_MBR struct {
Signature uint32
CheckSum uint32
}
type DRIVE_LAYOUT_INFORMATION_EX_HEADER struct {
PartitionStyle PartitionStyle
PartitionCount uint32
}
func getDiskHandleByNum(num int) (syscall.Handle, error) {
diskName := fmt.Sprintf(`\\.\PhysicalDrive%d`, num)
disk, _ := syscall.UTF16PtrFromString(diskName)
handle, err := syscall.CreateFile(
disk,
syscall.GENERIC_READ,
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE,
nil,
syscall.OPEN_EXISTING,
0,
0,
)
return handle, err
}
func GetSizeOf_DRIVE_LAYOUT_INFORMATION() int {
a := unsafe.Sizeof(DRIVE_LAYOUT_INFORMATION_GPT{})
b := unsafe.Sizeof(DRIVE_LAYOUT_INFORMATION_MBR{})
if a > b {
return int(a)
} else {
return int(b)
}
}
func getAllPartitionInfo(diskHandle syscall.Handle) ([]byte, error) {
var bytesReturned uint32
buffer := make([]byte, 4096)
err := syscall.DeviceIoControl(diskHandle, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, nil, 0, &buffer[0], uint32(len(buffer)), &bytesReturned, nil)
if err != nil {
return nil, err
}
return buffer, nil
}
func guidToString(guid GUID) string {
return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x",
guid.Data1, guid.Data2, guid.Data3,
(guid.Data4[0:2]), (guid.Data4[2:8]))
}
func GetDriveGUID(num int) string {
var disk syscall.Handle
disk, err := getDiskHandleByNum(num)
if err != nil {
fmt.Printf("Failed to get disk handle: %v\n", err)
return ""
}
defer syscall.CloseHandle(disk)
data, err := getAllPartitionInfo(disk)
if err != nil {
fmt.Printf("Failed to get partition info: %v\n", err)
return ""
}
header := (*DRIVE_LAYOUT_INFORMATION_EX_HEADER)(unsafe.Pointer(&data[0]))
next := data[int(unsafe.Sizeof(*header)):]
entryOffset := GetSizeOf_DRIVE_LAYOUT_INFORMATION()
entryData := next[entryOffset:]
partitionEntry := (*PARTITION_INFORMATION_EX)(unsafe.Pointer(&entryData[0]))
var guidStr string
if partitionEntry.PartitionStyle == PartitionStyleGpt {
info := (*PARTITION_INFORMATION_GPT)(unsafe.Pointer(&partitionEntry.PartitionInfo[0]))
guidStr = guidToString(info.PartitionId)
} else if partitionEntry.PartitionStyle == PartitionStyleMbr {
partitionInfo := (*PARTITION_INFORMATION_MBR)(unsafe.Pointer(&partitionEntry.PartitionInfo[0]))
guidStr = guidToString(partitionInfo.PartitionId)
}
return guidStr
}
func main() {
fmt.Println("磁盘0的GUID为:", GetDriveGUID(0))
}