memory_windows.go raw

   1  // +build windows
   2  
   3  package memory
   4  
   5  import (
   6  	"syscall"
   7  	"unsafe"
   8  )
   9  
  10  // omitting a few fields for brevity...
  11  // https://msdn.microsoft.com/en-us/library/windows/desktop/aa366589(v=vs.85).aspx
  12  type memStatusEx struct {
  13  	dwLength     uint32
  14  	dwMemoryLoad uint32
  15  	ullTotalPhys uint64
  16  	ullAvailPhys uint64
  17  	unused       [5]uint64
  18  }
  19  
  20  func sysTotalMemory() uint64 {
  21  	kernel32, err := syscall.LoadDLL("kernel32.dll")
  22  	if err != nil {
  23  		return 0
  24  	}
  25  	// GetPhysicallyInstalledSystemMemory is simpler, but broken on
  26  	// older versions of windows (and uses this under the hood anyway).
  27  	globalMemoryStatusEx, err := kernel32.FindProc("GlobalMemoryStatusEx")
  28  	if err != nil {
  29  		return 0
  30  	}
  31  	msx := &memStatusEx{
  32  		dwLength: 64,
  33  	}
  34  	r, _, _ := globalMemoryStatusEx.Call(uintptr(unsafe.Pointer(msx)))
  35  	if r == 0 {
  36  		return 0
  37  	}
  38  	return msx.ullTotalPhys
  39  }
  40  
  41  func sysFreeMemory() uint64 {
  42  	kernel32, err := syscall.LoadDLL("kernel32.dll")
  43  	if err != nil {
  44  		return 0
  45  	}
  46  	// GetPhysicallyInstalledSystemMemory is simpler, but broken on
  47  	// older versions of windows (and uses this under the hood anyway).
  48  	globalMemoryStatusEx, err := kernel32.FindProc("GlobalMemoryStatusEx")
  49  	if err != nil {
  50  		return 0
  51  	}
  52  	msx := &memStatusEx{
  53  		dwLength: 64,
  54  	}
  55  	r, _, _ := globalMemoryStatusEx.Call(uintptr(unsafe.Pointer(msx)))
  56  	if r == 0 {
  57  		return 0
  58  	}
  59  	return msx.ullAvailPhys
  60  }
  61