//go:build windows // +build windows package hypervctl import ( "encoding/xml" "fmt" "io" "strings" "github.com/containers/libhvee/pkg/wmiext" ) const ( KvpOperationFailed = 32768 KvpAccessDenied = 32769 KvpNotSupported = 32770 KvpStatusUnknown = 32771 KvpTimeoutOccurred = 32772 KvpIllegalArgument = 32773 KvpSystemInUse = 32774 KvpInvalidState = 32775 KvpIncorrectDataType = 32776 KvpSystemNotAvailable = 32777 KvpOutOfMemory = 32778 KvpNotFound = 32779 KvpExchangeDataItemName = "Msvm_KvpExchangeDataItem" MemorySettingDataName = "Msvm_MemorySettingData" ) type CimKvpItems struct { Instances []CimKvpItem `xml:"INSTANCE"` } type CimKvpItem struct { Properties []CimKvpItemProperty `xml:"PROPERTY"` } type CimKvpItemProperty struct { Name string `xml:"NAME,attr"` Value string `xml:"VALUE"` } type KvpError struct { ErrorCode int message string } func (k *KvpError) Error() string { return fmt.Sprintf("%s (%d)", k.message, k.ErrorCode) } func createKvpItem(service *wmiext.Service, key string, value string) (string, error) { item, err := service.SpawnInstance(KvpExchangeDataItemName) if err != nil { return "", err } defer item.Close() _ = item.Put("Name", key) _ = item.Put("Data", value) _ = item.Put("Source", 0) itemStr := item.GetCimText() return itemStr, nil } func parseKvpMapXml(kvpXml string) (map[string]string, error) { // Workaround XML decoder's inability to handle multiple root elements r := io.MultiReader( strings.NewReader(""), strings.NewReader(kvpXml), strings.NewReader(""), ) var items CimKvpItems if err := xml.NewDecoder(r).Decode(&items); err != nil { return nil, err } ret := make(map[string]string) for _, item := range items.Instances { var key, value string for _, prop := range item.Properties { if strings.EqualFold(prop.Name, "Name") { key = prop.Value } else if strings.EqualFold(prop.Name, "Data") { value = prop.Value } } if len(key) > 0 { ret[key] = value } } return ret, nil } func translateKvpError(source error, illegalSuggestion string) error { j, ok := source.(*wmiext.JobError) if !ok { return source } var message string switch j.ErrorCode { case KvpOperationFailed: message = "Operation failed" case KvpAccessDenied: message = "Access denied" case KvpNotSupported: message = "Not supported" case KvpStatusUnknown: message = "Status is unknown" case KvpTimeoutOccurred: message = "Timeout occurred" case KvpIllegalArgument: message = "Illegal argument (" + illegalSuggestion + ")" case KvpSystemInUse: message = "System is in use" case KvpInvalidState: message = "Invalid state for this operation" case KvpIncorrectDataType: message = "Incorrect data type" case KvpSystemNotAvailable: message = "System is not available" case KvpOutOfMemory: message = "Out of memory" case KvpNotFound: message = "Not found" default: return source } return &KvpError{j.ErrorCode, message} }