145 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
| // +build windows
 | |
| 
 | |
| package common
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"os/exec"
 | |
| 	"strings"
 | |
| 	"syscall"
 | |
| 	"unsafe"
 | |
| )
 | |
| 
 | |
| // for double values
 | |
| type PDH_FMT_COUNTERVALUE_DOUBLE struct {
 | |
| 	CStatus     uint32
 | |
| 	DoubleValue float64
 | |
| }
 | |
| 
 | |
| // for 64 bit integer values
 | |
| type PDH_FMT_COUNTERVALUE_LARGE struct {
 | |
| 	CStatus    uint32
 | |
| 	LargeValue int64
 | |
| }
 | |
| 
 | |
| // for long values
 | |
| type PDH_FMT_COUNTERVALUE_LONG struct {
 | |
| 	CStatus   uint32
 | |
| 	LongValue int32
 | |
| 	padding   [4]byte
 | |
| }
 | |
| 
 | |
| // windows system const
 | |
| const (
 | |
| 	ERROR_SUCCESS        = 0
 | |
| 	ERROR_FILE_NOT_FOUND = 2
 | |
| 	DRIVE_REMOVABLE      = 2
 | |
| 	DRIVE_FIXED          = 3
 | |
| 	HKEY_LOCAL_MACHINE   = 0x80000002
 | |
| 	RRF_RT_REG_SZ        = 0x00000002
 | |
| 	RRF_RT_REG_DWORD     = 0x00000010
 | |
| 	PDH_FMT_LONG         = 0x00000100
 | |
| 	PDH_FMT_DOUBLE       = 0x00000200
 | |
| 	PDH_FMT_LARGE        = 0x00000400
 | |
| 	PDH_INVALID_DATA     = 0xc0000bc6
 | |
| 	PDH_INVALID_HANDLE   = 0xC0000bbc
 | |
| 	PDH_NO_DATA          = 0x800007d5
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	Modkernel32 = syscall.NewLazyDLL("kernel32.dll")
 | |
| 	ModNt       = syscall.NewLazyDLL("ntdll.dll")
 | |
| 	ModPdh      = syscall.NewLazyDLL("pdh.dll")
 | |
| 
 | |
| 	ProcGetSystemTimes           = Modkernel32.NewProc("GetSystemTimes")
 | |
| 	ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation")
 | |
| 	PdhOpenQuery                 = ModPdh.NewProc("PdhOpenQuery")
 | |
| 	PdhAddCounter                = ModPdh.NewProc("PdhAddCounterW")
 | |
| 	PdhCollectQueryData          = ModPdh.NewProc("PdhCollectQueryData")
 | |
| 	PdhGetFormattedCounterValue  = ModPdh.NewProc("PdhGetFormattedCounterValue")
 | |
| 	PdhCloseQuery                = ModPdh.NewProc("PdhCloseQuery")
 | |
| )
 | |
| 
 | |
| type FILETIME struct {
 | |
| 	DwLowDateTime  uint32
 | |
| 	DwHighDateTime uint32
 | |
| }
 | |
| 
 | |
| // borrowed from net/interface_windows.go
 | |
| func BytePtrToString(p *uint8) string {
 | |
| 	a := (*[10000]uint8)(unsafe.Pointer(p))
 | |
| 	i := 0
 | |
| 	for a[i] != 0 {
 | |
| 		i++
 | |
| 	}
 | |
| 	return string(a[:i])
 | |
| }
 | |
| 
 | |
| // exec wmic and return lines splited by newline
 | |
| func GetWmic(target string, query ...string) ([][]string, error) {
 | |
| 	cmd := []string{target}
 | |
| 	cmd = append(cmd, query...)
 | |
| 	cmd = append(cmd, "/format:csv")
 | |
| 	out, err := exec.Command("wmic", cmd...).Output()
 | |
| 	if err != nil {
 | |
| 		return [][]string{}, err
 | |
| 	}
 | |
| 	lines := strings.Split(string(out), "\r\r\n")
 | |
| 	if len(lines) <= 2 {
 | |
| 		return [][]string{}, fmt.Errorf("wmic result malformed: [%q]", lines)
 | |
| 	}
 | |
| 	var ret [][]string
 | |
| 	for _, l := range lines[2:] { // skip first two lines
 | |
| 		var lr []string
 | |
| 		for _, r := range strings.Split(l, ",") {
 | |
| 			if r == "" {
 | |
| 				continue
 | |
| 			}
 | |
| 			lr = append(lr, strings.TrimSpace(r))
 | |
| 		}
 | |
| 		if len(lr) != 0 {
 | |
| 			ret = append(ret, lr)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return ret, nil
 | |
| 
 | |
| }
 | |
| 
 | |
| // CounterInfo
 | |
| // copied from https://github.com/mackerelio/mackerel-agent/
 | |
| type CounterInfo struct {
 | |
| 	PostName    string
 | |
| 	CounterName string
 | |
| 	Counter     syscall.Handle
 | |
| }
 | |
| 
 | |
| // CreateQuery XXX
 | |
| // copied from https://github.com/mackerelio/mackerel-agent/
 | |
| func CreateQuery() (syscall.Handle, error) {
 | |
| 	var query syscall.Handle
 | |
| 	r, _, err := PdhOpenQuery.Call(0, 0, uintptr(unsafe.Pointer(&query)))
 | |
| 	if r != 0 {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 	return query, nil
 | |
| }
 | |
| 
 | |
| // CreateCounter XXX
 | |
| func CreateCounter(query syscall.Handle, pname, cname string) (*CounterInfo, error) {
 | |
| 	var counter syscall.Handle
 | |
| 	r, _, err := PdhAddCounter.Call(
 | |
| 		uintptr(query),
 | |
| 		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(cname))),
 | |
| 		0,
 | |
| 		uintptr(unsafe.Pointer(&counter)))
 | |
| 	if r != 0 {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &CounterInfo{
 | |
| 		PostName:    pname,
 | |
| 		CounterName: cname,
 | |
| 		Counter:     counter,
 | |
| 	}, nil
 | |
| }
 |