123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- // +build windows
- package common
- import (
- "context"
- "unsafe"
- "github.com/StackExchange/wmi"
- "golang.org/x/sys/windows"
- )
- // 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 = windows.NewLazyDLL("kernel32.dll")
- ModNt = windows.NewLazyDLL("ntdll.dll")
- ModPdh = windows.NewLazyDLL("pdh.dll")
- ModPsapi = windows.NewLazyDLL("psapi.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])
- }
- // CounterInfo
- // copied from https://github.com/mackerelio/mackerel-agent/
- type CounterInfo struct {
- PostName string
- CounterName string
- Counter windows.Handle
- }
- // CreateQuery XXX
- // copied from https://github.com/mackerelio/mackerel-agent/
- func CreateQuery() (windows.Handle, error) {
- var query windows.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 windows.Handle, pname, cname string) (*CounterInfo, error) {
- var counter windows.Handle
- r, _, err := PdhAddCounter.Call(
- uintptr(query),
- uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(cname))),
- 0,
- uintptr(unsafe.Pointer(&counter)))
- if r != 0 {
- return nil, err
- }
- return &CounterInfo{
- PostName: pname,
- CounterName: cname,
- Counter: counter,
- }, nil
- }
- // WMIQueryWithContext - wraps wmi.Query with a timed-out context to avoid hanging
- func WMIQueryWithContext(ctx context.Context, query string, dst interface{}, connectServerArgs ...interface{}) error {
- if _, ok := ctx.Deadline(); !ok {
- ctxTimeout, cancel := context.WithTimeout(ctx, Timeout)
- defer cancel()
- ctx = ctxTimeout
- }
- errChan := make(chan error, 1)
- go func() {
- errChan <- wmi.Query(query, dst, connectServerArgs...)
- }()
- select {
- case <-ctx.Done():
- return ctx.Err()
- case err := <-errChan:
- return err
- }
- }
|