From f16e9efb2e9455cf6be1a348f25c4f0d079ace40 Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Fri, 18 Apr 2014 21:26:24 +0900 Subject: [PATCH 01/12] fix the return value struct. --- cpu_freebsd.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpu_freebsd.go b/cpu_freebsd.go index 33ff0d9..7fc4c7f 100644 --- a/cpu_freebsd.go +++ b/cpu_freebsd.go @@ -6,9 +6,9 @@ import ( "fmt" ) -func (c CPU) Cpu_times() map[string]string { - ret := make(map[string]string) +func (c CPU) Cpu_times() ([]CPU_Times, error) { + ret := make([]CPU_Times, 0) fmt.Println("FreeBSD") - return ret + return ret, nil } From 4ffbd2a28ffd0e8b81ce7d420dd151c02d108a7b Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Fri, 18 Apr 2014 21:27:29 +0900 Subject: [PATCH 02/12] separate struct and func due to the lack of syscall on windows. --- host.go | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/host.go b/host.go index 9a5f3bd..c5657a7 100644 --- a/host.go +++ b/host.go @@ -1,10 +1,5 @@ package main -import ( - "os" - "syscall" -) - type Host struct{} type HostInfo struct { @@ -17,22 +12,3 @@ func NewHost() Host { h := Host{} return h } - -func (h Host) HostInfo() (HostInfo, error) { - ret := HostInfo{} - sysinfo := &syscall.Sysinfo_t{} - - if err := syscall.Sysinfo(sysinfo); err != nil { - return ret, err - } - - hostname, err := os.Hostname() - if err != nil { - return ret, err - } - ret.Hostname = hostname - ret.Uptime = sysinfo.Uptime - ret.Procs = uint64(sysinfo.Procs) - - return ret, nil -} From ce819755734144cee111d6243d0a628266282ef7 Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Fri, 18 Apr 2014 21:28:00 +0900 Subject: [PATCH 03/12] add windows stub. --- cpu_windows.go | 14 ++++++++++++++ disk_windows.go | 10 ++++++++++ host_unix.go | 17 +++++++++++++++++ host_windows.go | 19 +++++++++++++++++++ load_windows.go | 9 +++++++++ mem_windows.go | 15 +++++++++++++++ 6 files changed, 84 insertions(+) create mode 100644 cpu_windows.go create mode 100644 disk_windows.go create mode 100644 host_unix.go create mode 100644 host_windows.go create mode 100644 load_windows.go create mode 100644 mem_windows.go diff --git a/cpu_windows.go b/cpu_windows.go new file mode 100644 index 0000000..909c96f --- /dev/null +++ b/cpu_windows.go @@ -0,0 +1,14 @@ +// +build windows + +package main + +import ( + "fmt" +) + +func (c CPU) Cpu_times() ([]CPU_Times, error) { + ret := make([]CPU_Times, 0) + + fmt.Println("Windows") + return ret, nil +} diff --git a/disk_windows.go b/disk_windows.go new file mode 100644 index 0000000..2598234 --- /dev/null +++ b/disk_windows.go @@ -0,0 +1,10 @@ +// +build windows + +package main + +func (d Disk) Disk_usage(path string) (Disk_usage, error) { + + ret := Disk_usage{} + + return ret, nil +} diff --git a/host_unix.go b/host_unix.go new file mode 100644 index 0000000..4c8ef36 --- /dev/null +++ b/host_unix.go @@ -0,0 +1,17 @@ +// +build linux freebsd + +package main + +import ( + "os" + "syscall" +) + +func (h Host) HostInfo() (HostInfo, error) { + ret := HostInfo{} + hostname, err := os.Hostname() + ret.Hostname = hostname + ret.Uptime = sysinfo.Uptime + + return ret, nil +} diff --git a/host_windows.go b/host_windows.go new file mode 100644 index 0000000..2f424f4 --- /dev/null +++ b/host_windows.go @@ -0,0 +1,19 @@ +// +build windows + +package main + +import ( + "os" +) + +func (h Host) HostInfo() (HostInfo, error) { + ret := HostInfo{} + hostname, err := os.Hostname() + if err != nil { + return ret, err + } + + ret.Hostname = hostname + + return ret, nil +} diff --git a/load_windows.go b/load_windows.go new file mode 100644 index 0000000..38d6e48 --- /dev/null +++ b/load_windows.go @@ -0,0 +1,9 @@ +// +build windows + +package main + +func (l Load) LoadAvg() (LoadAvg, error) { + ret := LoadAvg{} + + return ret, nil +} diff --git a/mem_windows.go b/mem_windows.go new file mode 100644 index 0000000..5bbaa8f --- /dev/null +++ b/mem_windows.go @@ -0,0 +1,15 @@ +// +build windows + +package main + +func (m Mem) Virtual_memory() (Virtual_memory, error) { + ret := Virtual_memory{} + + return ret, nil +} + +func (m Mem) Swap_memory() (Swap_memory, error) { + ret := Swap_memory{} + + return ret, nil +} From 5fc807ed235218e91eb321a86bd5d8700c91bf7b Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Fri, 18 Apr 2014 22:02:35 +0900 Subject: [PATCH 04/12] implements Host.Uptime on windows --- host_windows.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/host_windows.go b/host_windows.go index 2f424f4..b18c28a 100644 --- a/host_windows.go +++ b/host_windows.go @@ -4,6 +4,7 @@ package main import ( "os" + "syscall" ) func (h Host) HostInfo() (HostInfo, error) { @@ -15,5 +16,15 @@ func (h Host) HostInfo() (HostInfo, error) { ret.Hostname = hostname + kernel32, err := syscall.LoadLibrary("kernel32.dll") + if err != nil { + return ret, err + } + defer syscall.FreeLibrary(kernel32) + GetTickCount, _ := syscall.GetProcAddress(kernel32, "GetTickCount") + + uptimemsec, _, err := syscall.Syscall(uintptr(GetTickCount), 0, 0, 0, 0) + + ret.Uptime = int64(uptimemsec) / 1000 return ret, nil } From 8c60a8f8c55c8212a4f2ff76aa5e65212ba8a235 Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Sat, 19 Apr 2014 00:09:25 +0900 Subject: [PATCH 05/12] add Procs to Hostinfo by using mitchellh/go-ps. --- README.rst | 2 ++ common_windows.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 common_windows.go diff --git a/README.rst b/README.rst index 4a804b2..67308d9 100644 --- a/README.rst +++ b/README.rst @@ -8,3 +8,5 @@ gopsutil: psutil for golang - dstat: https://github.com/dagwieers/dstat - gosiger: https://github.com/cloudfoundry/gosigar/ - goprocinfo: https://github.com/c9s/goprocinfo +- go-ps: https://github.com/mitchellh/go-ps + diff --git a/common_windows.go b/common_windows.go new file mode 100644 index 0000000..555767b --- /dev/null +++ b/common_windows.go @@ -0,0 +1,31 @@ +// +build windows + +package main + +import ( + "fmt" + "syscall" +) + +type Proc struct { + Pid uint64 +} + +func GetProcList() ([]Proc, error) { + ret := make([]Proc, 0) + kernel32, err := syscall.LoadLibrary("kernel32.dll") + if err != nil { + return ret, err + } + defer syscall.FreeLibrary(kernel32) + Process32First, _ := syscall.GetProcAddress(kernel32, "Process32First") + + // pFirst, _, err := syscall.Syscall(uintptr(Process32First), 0, 0, 0, 0) + pFirst, _, err := syscall.Syscall(uintptr(Process32First), 0, 0, 0, 0) + if err != nil { + return ret, err + } + fmt.Printf("Proc: %v\n", pFirst) + return ret, nil + +} From ab22e78f2da2120bc000b25a481ef05b2181b6a2 Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Sat, 19 Apr 2014 01:04:22 +0900 Subject: [PATCH 06/12] implements memory information on windows. --- mem_windows.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/mem_windows.go b/mem_windows.go index 5bbaa8f..05cbfdc 100644 --- a/mem_windows.go +++ b/mem_windows.go @@ -2,9 +2,42 @@ package main +import ( + "syscall" + "unsafe" +) + +var ( + modKernel32 = syscall.NewLazyDLL("kernel32.dll") + globalMemoryStatusEx = modKernel32.NewProc("GlobalMemoryStatusEx") +) + +type MEMORYSTATUSEX struct { + cbSize uint32 + dwMemoryLoad uint32 + ullTotalPhys uint64 // in bytes + ullAvailPhys uint64 + ullTotalPageFile uint64 + ullAvailPageFile uint64 + ullTotalVirtual uint64 + ullAvailVirtual uint64 + ullAvailExtendedVirtual uint64 +} + func (m Mem) Virtual_memory() (Virtual_memory, error) { ret := Virtual_memory{} + var memInfo MEMORYSTATUSEX + memInfo.cbSize = uint32(unsafe.Sizeof(memInfo)) + mem, _, _ := globalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo))) + if mem == 0 { + return ret, syscall.GetLastError() + } + + ret.Total = memInfo.ullTotalPhys + ret.Available = memInfo.ullAvailPhys + ret.UsedPercent = float64(memInfo.dwMemoryLoad) + ret.Used = ret.Total - ret.Available return ret, nil } From 8145c0cef0afc0582cff450c00082b9a16a07dde Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Sat, 19 Apr 2014 01:05:35 +0900 Subject: [PATCH 07/12] forget to commit procs in HostInfo. --- host_windows.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/host_windows.go b/host_windows.go index b18c28a..41ff631 100644 --- a/host_windows.go +++ b/host_windows.go @@ -3,6 +3,7 @@ package main import ( + "github.com/mitchellh/go-ps" "os" "syscall" ) @@ -26,5 +27,13 @@ func (h Host) HostInfo() (HostInfo, error) { uptimemsec, _, err := syscall.Syscall(uintptr(GetTickCount), 0, 0, 0, 0) ret.Uptime = int64(uptimemsec) / 1000 + + procs, err := ps.Processes() + if err != nil { + return ret, err + } + + ret.Procs = uint64(len(procs)) + return ret, nil } From e29742b52fd03a2557b17a5e1bea0178510ae3d4 Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Sat, 19 Apr 2014 01:29:34 +0900 Subject: [PATCH 08/12] implements CPU info total on Windows. but it may be not correct. --- cpu_windows.go | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/cpu_windows.go b/cpu_windows.go index 909c96f..dbba509 100644 --- a/cpu_windows.go +++ b/cpu_windows.go @@ -3,12 +3,45 @@ package main import ( - "fmt" + "syscall" + "unsafe" ) +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + procGetSystemTimes = modkernel32.NewProc("GetSystemTimes") +) + +type FILETIME struct { + DwLowDateTime uint32 + DwHighDateTime uint32 +} + func (c CPU) Cpu_times() ([]CPU_Times, error) { ret := make([]CPU_Times, 0) - fmt.Println("Windows") + var lpIdleTime FILETIME + var lpKernelTime FILETIME + var lpUserTime FILETIME + r, _, _ := procGetSystemTimes.Call( + uintptr(unsafe.Pointer(&lpIdleTime)), + uintptr(unsafe.Pointer(&lpKernelTime)), + uintptr(unsafe.Pointer(&lpUserTime))) + if r == 0 { + return ret, syscall.GetLastError() + } + + LO_T := float64(0.0000001) + HI_T := (LO_T * 4294967296.0) + idle := ((HI_T * float64(lpIdleTime.DwHighDateTime)) + (LO_T * float64(lpIdleTime.DwLowDateTime))) + user := ((HI_T * float64(lpUserTime.DwHighDateTime)) + (LO_T * float64(lpUserTime.DwLowDateTime))) + kernel := ((HI_T * float64(lpKernelTime.DwHighDateTime)) + (LO_T * float64(lpKernelTime.DwLowDateTime))) + system := (kernel - idle) + + ret = append(ret, CPU_Times{ + Idle: uint64(idle), + User: uint64(user), + System: uint64(system), + }) return ret, nil } From 8235f42686b8f73c6290e1b18029856b3bf94fb5 Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Sun, 20 Apr 2014 00:03:47 +0900 Subject: [PATCH 09/12] implement disk usage on Windows --- disk.go | 11 +++++------ disk_test.go | 7 ++++++- disk_windows.go | 29 ++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/disk.go b/disk.go index 58edb09..79179a1 100644 --- a/disk.go +++ b/disk.go @@ -3,12 +3,11 @@ package main type Disk struct{} type Disk_usage struct { - Path string `json:"path"` - Total uint64 `json:"total"` - Free uint64 `json:"free"` - Available uint64 `json:"available"` - Used uint64 `json:"used"` - Percent float64 `json:"percent"` + Path string `json:"path"` + Total uint64 `json:"total"` + Free uint64 `json:"free"` + Used uint64 `json:"used"` + UsedPercent float64 `json:"usedPercent"` } type Disk_IO_Counters struct { diff --git a/disk_test.go b/disk_test.go index 5bb3e0b..2f38c0e 100644 --- a/disk_test.go +++ b/disk_test.go @@ -3,13 +3,18 @@ package main import ( "encoding/json" "fmt" + "runtime" "testing" ) func TestDisk_usage(t *testing.T) { disk := NewDisk() - v, err := disk.Disk_usage("/") + path := "/" + if runtime.GOOS == "windows" { + path = "C:" + } + v, err := disk.Disk_usage(path) if err != nil { t.Errorf("error %v", err) } diff --git a/disk_windows.go b/disk_windows.go index 2598234..baca9a8 100644 --- a/disk_windows.go +++ b/disk_windows.go @@ -2,9 +2,36 @@ package main -func (d Disk) Disk_usage(path string) (Disk_usage, error) { +import ( + "syscall" + "unsafe" +) + +var ( + procGetDiskFreeSpaceExW = modkernel32.NewProc("GetDiskFreeSpaceExW") + //GetLogicalDriveStrings, _ = syscall.GetProcAddress(modkernel32, "GetLogicalDriveStringsW") +) +func (d Disk) Disk_usage(path string) (Disk_usage, error) { ret := Disk_usage{} + ret.Path = path + lpFreeBytesAvailable := int64(0) + lpTotalNumberOfBytes := int64(0) + lpTotalNumberOfFreeBytes := int64(0) + diskret, _, _ := procGetDiskFreeSpaceExW.Call( + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), + uintptr(unsafe.Pointer(&lpFreeBytesAvailable)), + uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)), + uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes))) + if diskret == 0 { + return ret, syscall.GetLastError() + } + ret.Total = uint64(lpTotalNumberOfBytes) + // ret.Free = uint64(lpFreeBytesAvailable) // python psutil does not use this + ret.Free = uint64(lpTotalNumberOfFreeBytes) + ret.Used = ret.Total - ret.Free + ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0 + return ret, nil } From 8204d224c27157d974408f78628ad9526978f4f7 Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Sun, 20 Apr 2014 01:53:00 +0900 Subject: [PATCH 10/12] remove unused func. --- common_windows.go | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/common_windows.go b/common_windows.go index 555767b..7458d26 100644 --- a/common_windows.go +++ b/common_windows.go @@ -3,29 +3,9 @@ package main import ( - "fmt" "syscall" ) -type Proc struct { - Pid uint64 -} - -func GetProcList() ([]Proc, error) { - ret := make([]Proc, 0) - kernel32, err := syscall.LoadLibrary("kernel32.dll") - if err != nil { - return ret, err - } - defer syscall.FreeLibrary(kernel32) - Process32First, _ := syscall.GetProcAddress(kernel32, "Process32First") - - // pFirst, _, err := syscall.Syscall(uintptr(Process32First), 0, 0, 0, 0) - pFirst, _, err := syscall.Syscall(uintptr(Process32First), 0, 0, 0, 0) - if err != nil { - return ret, err - } - fmt.Printf("Proc: %v\n", pFirst) - return ret, nil - -} +var ( + modKernel32 = syscall.NewLazyDLL("kernel32.dll") +) From 4f591291551b0b671a76bf8550fb285143bdc9c3 Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Sun, 20 Apr 2014 01:53:34 +0900 Subject: [PATCH 11/12] implements Disk_partition on windows --- disk.go | 7 ++++++ disk_test.go | 11 ++++++++ disk_windows.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/disk.go b/disk.go index 79179a1..7f2e003 100644 --- a/disk.go +++ b/disk.go @@ -10,6 +10,13 @@ type Disk_usage struct { UsedPercent float64 `json:"usedPercent"` } +type Disk_partition struct { + Device string `json:"device"` + Mountpoint string `json:"mountpoint"` + Fstype string `json:"fstype"` + Opts string `json:"opts"` +} + type Disk_IO_Counters struct { ReadCount uint64 `json:"readCount"` WriteCount uint64 `json:"writeCount"` diff --git a/disk_test.go b/disk_test.go index 2f38c0e..c76c37c 100644 --- a/disk_test.go +++ b/disk_test.go @@ -21,3 +21,14 @@ func TestDisk_usage(t *testing.T) { d, _ := json.Marshal(v) fmt.Printf("%s\n", d) } + +func TestDisk_partitions(t *testing.T) { + disk := NewDisk() + + v, err := disk.Disk_partitions() + if err != nil { + t.Errorf("error %v", err) + } + d, _ := json.Marshal(v) + fmt.Printf("%s\n", d) +} diff --git a/disk_windows.go b/disk_windows.go index baca9a8..f271444 100644 --- a/disk_windows.go +++ b/disk_windows.go @@ -3,13 +3,21 @@ package main import ( + "bytes" "syscall" "unsafe" ) var ( - procGetDiskFreeSpaceExW = modkernel32.NewProc("GetDiskFreeSpaceExW") - //GetLogicalDriveStrings, _ = syscall.GetProcAddress(modkernel32, "GetLogicalDriveStringsW") + procGetDiskFreeSpaceExW = modkernel32.NewProc("GetDiskFreeSpaceExW") + procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW") + procGetDriveType = modkernel32.NewProc("GetDriveTypeW") + provGetVolumeInformation = modKernel32.NewProc("GetVolumeInformationW") +) + +var ( + FILE_FILE_COMPRESSION = int64(16) // 0x00000010 + FILE_READ_ONLY_VOLUME = int64(524288) // 0x00080000 ) func (d Disk) Disk_usage(path string) (Disk_usage, error) { @@ -19,13 +27,13 @@ func (d Disk) Disk_usage(path string) (Disk_usage, error) { lpFreeBytesAvailable := int64(0) lpTotalNumberOfBytes := int64(0) lpTotalNumberOfFreeBytes := int64(0) - diskret, _, _ := procGetDiskFreeSpaceExW.Call( + diskret, _, err := procGetDiskFreeSpaceExW.Call( uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), uintptr(unsafe.Pointer(&lpFreeBytesAvailable)), uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)), uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes))) if diskret == 0 { - return ret, syscall.GetLastError() + return ret, err } ret.Total = uint64(lpTotalNumberOfBytes) // ret.Free = uint64(lpFreeBytesAvailable) // python psutil does not use this @@ -35,3 +43,65 @@ func (d Disk) Disk_usage(path string) (Disk_usage, error) { return ret, nil } + +func (d Disk) Disk_partitions() ([]Disk_partition, error) { + ret := make([]Disk_partition, 0) + lpBuffer := make([]byte, 254) + diskret, _, err := procGetLogicalDriveStringsW.Call( + uintptr(len(lpBuffer)), + uintptr(unsafe.Pointer(&lpBuffer[0]))) + if diskret == 0 { + return ret, err + } + for _, v := range lpBuffer { + if v >= 65 && v <= 90 { + path := string(v) + ":" + if path == "A:" || path == "B:" { // skip floppy drives + continue + } + typepath, _ := syscall.UTF16PtrFromString(path) + typeret, _, _ := procGetDriveType.Call(uintptr(unsafe.Pointer(typepath))) + if typeret == 0 { + return ret, syscall.GetLastError() + } + // 2: DRIVE_REMOVABLE 3: DRIVE_FIXED 5: DRIVE_CDROM + + if typeret == 2 || typeret == 3 || typeret == 5 { + lpVolumeNameBuffer := make([]byte, 256) + lpVolumeSerialNumber := int64(0) + lpMaximumComponentLength := int64(0) + lpFileSystemFlags := int64(0) + lpFileSystemNameBuffer := make([]byte, 256) + volpath, _ := syscall.UTF16PtrFromString(string(v) + ":/") + driveret, _, err := provGetVolumeInformation.Call( + uintptr(unsafe.Pointer(volpath)), + uintptr(unsafe.Pointer(&lpVolumeNameBuffer[0])), + uintptr(len(lpVolumeNameBuffer)), + uintptr(unsafe.Pointer(&lpVolumeSerialNumber)), + uintptr(unsafe.Pointer(&lpMaximumComponentLength)), + uintptr(unsafe.Pointer(&lpFileSystemFlags)), + uintptr(unsafe.Pointer(&lpFileSystemNameBuffer[0])), + uintptr(len(lpFileSystemNameBuffer))) + if driveret == 0 { + return ret, err + } + opts := "rw" + if lpFileSystemFlags&FILE_READ_ONLY_VOLUME != 0 { + opts = "ro" + } + if lpFileSystemFlags&FILE_FILE_COMPRESSION != 0 { + opts += ".compress" + } + + d := Disk_partition{ + Mountpoint: path, + Device: path, + Fstype: string(bytes.Replace(lpFileSystemNameBuffer, []byte("\x00"), []byte(""), -1)), + Opts: opts, + } + ret = append(ret, d) + } + } + } + return ret, nil +} From 2b99d2b7a66715dbc8946bd5a7ae962bc9107cd2 Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Sun, 20 Apr 2014 01:54:14 +0900 Subject: [PATCH 12/12] refactor proc name. --- mem_windows.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mem_windows.go b/mem_windows.go index 05cbfdc..a8ea77b 100644 --- a/mem_windows.go +++ b/mem_windows.go @@ -8,8 +8,7 @@ import ( ) var ( - modKernel32 = syscall.NewLazyDLL("kernel32.dll") - globalMemoryStatusEx = modKernel32.NewProc("GlobalMemoryStatusEx") + procGlobalMemoryStatusEx = modKernel32.NewProc("GlobalMemoryStatusEx") ) type MEMORYSTATUSEX struct { @@ -29,7 +28,7 @@ func (m Mem) Virtual_memory() (Virtual_memory, error) { var memInfo MEMORYSTATUSEX memInfo.cbSize = uint32(unsafe.Sizeof(memInfo)) - mem, _, _ := globalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo))) + mem, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo))) if mem == 0 { return ret, syscall.GetLastError() }