-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathkernel32.go
249 lines (218 loc) · 8.72 KB
/
kernel32.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// +build windows
package windows
import (
"fmt"
"syscall"
"time"
"unsafe"
"github.com/pkg/errors"
)
// Syscalls
//sys _GetNativeSystemInfo(systemInfo *SystemInfo) = kernel32.GetNativeSystemInfo
//sys _GetTickCount64() (millis uint64, err error) = kernel32.GetTickCount64
//sys _GetSystemTimes(idleTime *syscall.Filetime, kernelTime *syscall.Filetime, userTime *syscall.Filetime) (err error) = kernel32.GetSystemTimes
//sys _GlobalMemoryStatusEx(buffer *MemoryStatusEx) (err error) = kernel32.GlobalMemoryStatusEx
//sys _ReadProcessMemory(handle syscall.Handle, baseAddress uintptr, buffer uintptr, size uintptr, numRead *uintptr) (err error) = kernel32.ReadProcessMemory
//sys _GetProcessHandleCount(handle syscall.Handle, pdwHandleCount *uint32) (err error) = kernel32.GetProcessHandleCount
var (
sizeofMemoryStatusEx = uint32(unsafe.Sizeof(MemoryStatusEx{}))
)
// SystemInfo is an equivalent representation of SYSTEM_INFO in the Windows API.
// https://msdn.microsoft.com/en-us/library/ms724958%28VS.85%29.aspx?f=255&MSPPError=-2147217396
type SystemInfo struct {
ProcessorArchitecture ProcessorArchitecture
Reserved uint16
PageSize uint32
MinimumApplicationAddress uintptr
MaximumApplicationAddress uintptr
ActiveProcessorMask uint64
NumberOfProcessors uint32
ProcessorType ProcessorType
AllocationGranularity uint32
ProcessorLevel uint16
ProcessorRevision uint16
}
// ProcessorArchitecture specifies the processor architecture that the OS requires.
type ProcessorArchitecture uint16
// List of processor architectures associated with SystemInfo.
const (
ProcessorArchitectureAMD64 ProcessorArchitecture = 9
ProcessorArchitectureARM ProcessorArchitecture = 5
ProcessorArchitectureARM64 ProcessorArchitecture = 12
ProcessorArchitectureIA64 ProcessorArchitecture = 6
ProcessorArchitectureIntel ProcessorArchitecture = 0
ProcessorArchitectureUnknown ProcessorArchitecture = 0xFFFF
)
// ErrReadFailed is returned by ReadProcessMemory on failure
var ErrReadFailed = errors.New("ReadProcessMemory failed")
func (a ProcessorArchitecture) String() string {
names := map[ProcessorArchitecture]string{
ProcessorArchitectureAMD64: "x86_64",
ProcessorArchitectureARM: "arm",
ProcessorArchitectureARM64: "arm64",
ProcessorArchitectureIA64: "ia64",
ProcessorArchitectureIntel: "x86",
}
name, found := names[a]
if !found {
return "unknown"
}
return name
}
// ProcessorType specifies the type of processor.
type ProcessorType uint32
// List of processor types associated with SystemInfo.
const (
ProcessorTypeIntel386 ProcessorType = 386
ProcessorTypeIntel486 ProcessorType = 486
ProcessorTypeIntelPentium ProcessorType = 586
ProcessorTypeIntelIA64 ProcessorType = 2200
ProcessorTypeAMDX8664 ProcessorType = 8664
)
func (t ProcessorType) String() string {
names := map[ProcessorType]string{
ProcessorTypeIntel386: "386",
ProcessorTypeIntel486: "486",
ProcessorTypeIntelPentium: "586",
ProcessorTypeIntelIA64: "ia64",
ProcessorTypeAMDX8664: "x64_64",
}
name, found := names[t]
if !found {
return "unknown"
}
return name
}
// MemoryStatusEx is an equivalent representation of MEMORYSTATUSEX in the
// Windows API. It contains information about the current state of both physical
// and virtual memory, including extended memory.
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366770
type MemoryStatusEx struct {
length uint32
MemoryLoad uint32
TotalPhys uint64
AvailPhys uint64
TotalPageFile uint64
AvailPageFile uint64
TotalVirtual uint64
AvailVirtual uint64
AvailExtendedVirtual uint64
}
// GetNativeSystemInfo retrieves information about the current system to an
// application running under WOW64. If the function is called from a 64-bit
// application, it is equivalent to the GetSystemInfo function.
// https://msdn.microsoft.com/en-us/library/ms724340%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
func GetNativeSystemInfo() (SystemInfo, error) {
var systemInfo SystemInfo
_GetNativeSystemInfo(&systemInfo)
return systemInfo, nil
}
// Version identifies a Windows version by major, minor, and build number.
type Version struct {
Major int
Minor int
Build int
}
// GetWindowsVersion returns the Windows version information. Applications not
// manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version
// value (6.2).
//
// For a table of version numbers see:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
func GetWindowsVersion() Version {
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
ver, err := syscall.GetVersion()
if err != nil {
// GetVersion should never return an error.
panic(fmt.Errorf("GetVersion failed: %v", err))
}
return Version{
Major: int(ver & 0xFF),
Minor: int(ver >> 8 & 0xFF),
Build: int(ver >> 16),
}
}
// IsWindowsVistaOrGreater returns true if the Windows version is Vista or
// greater.
func (v Version) IsWindowsVistaOrGreater() bool {
// Vista is 6.0.
return v.Major >= 6 && v.Minor >= 0
}
// GetTickCount64 retrieves the number of milliseconds that have elapsed since
// the system was started.
// This function is available on Windows Vista and newer.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724411(v=vs.85).aspx
func GetTickCount64() (uint64, error) {
return _GetTickCount64()
}
// GetSystemTimes retrieves system timing information. On a multiprocessor
// system, the values returned are the sum of the designated times across all
// processors. The returned kernel time does not include the system idle time.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724400(v=vs.85).aspx
func GetSystemTimes() (idle, kernel, user time.Duration, err error) {
var idleTime, kernelTime, userTime syscall.Filetime
err = _GetSystemTimes(&idleTime, &kernelTime, &userTime)
if err != nil {
return 0, 0, 0, errors.Wrap(err, "GetSystemTimes failed")
}
idle = FiletimeToDuration(&idleTime)
kernel = FiletimeToDuration(&kernelTime) // Kernel time includes idle time so we subtract it out.
user = FiletimeToDuration(&userTime)
return idle, kernel - idle, user, nil
}
// FiletimeToDuration converts a Filetime to a time.Duration. Do not use this
// method to convert a Filetime to an actual clock time, for that use
// Filetime.Nanosecond().
func FiletimeToDuration(ft *syscall.Filetime) time.Duration {
n := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) // in 100-nanosecond intervals
return time.Duration(n * 100)
}
// GlobalMemoryStatusEx retrieves information about the system's current usage
// of both physical and virtual memory.
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366589(v=vs.85).aspx
func GlobalMemoryStatusEx() (MemoryStatusEx, error) {
memoryStatusEx := MemoryStatusEx{length: sizeofMemoryStatusEx}
err := _GlobalMemoryStatusEx(&memoryStatusEx)
if err != nil {
return MemoryStatusEx{}, errors.Wrap(err, "GlobalMemoryStatusEx failed")
}
return memoryStatusEx, nil
}
// ReadProcessMemory reads from another process memory. The Handle needs to have
// the PROCESS_VM_READ right.
// A zero-byte read is a no-op, no error is returned.
func ReadProcessMemory(handle syscall.Handle, baseAddress uintptr, dest []byte) (numRead uintptr, err error) {
n := len(dest)
if n == 0 {
return 0, nil
}
if err = _ReadProcessMemory(handle, baseAddress, uintptr(unsafe.Pointer(&dest[0])), uintptr(n), &numRead); err != nil {
return 0, err
}
return numRead, nil
}
// GetProcessHandleCount retrieves the number of open handles of a process.
// https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-getprocesshandlecount
func GetProcessHandleCount(process syscall.Handle) (uint32, error) {
var count uint32
if err := _GetProcessHandleCount(process, &count); err != nil {
return 0, errors.Wrap(err, "GetProcessHandleCount failed")
}
return count, nil
}