-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfunc_windows.go
309 lines (282 loc) · 8.56 KB
/
func_windows.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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
// -----------------------------------------------------------------------------
// ZR Library: Windows 32 API zr-win/[func_windows.go]
// (c) [email protected] License: MIT
// -----------------------------------------------------------------------------
package win
// # Constants
//
// # System Information Functions
// FirmwareDate() string
// FirmwareVersion() string
// IsWindows() bool
// OSClass() OSType
// OSFolder() string
// SystemVolumeID() uint32
// VolumeID(path string) uint32
//
// # Registry Function
// GetRegistryString(key, valueName string) string
//
// # Internal Constants
// rootKeys = []struct
//
// # Internal Functions
// getRegistryKey(key string) HKEY
// getRegistrySubkey(key string) string
// registryHardwareInfo(valueName string) string
// windowsVersionInfo() OSVERSIONINFO
import (
"bytes"
"fmt"
"strings"
"unsafe"
"github.com/balacode/zr"
)
// -----------------------------------------------------------------------------
// # Constants
// OSType _ _
type OSType int
const (
// OSUnknown indicates the operating system is unknown.
OSUnknown = OSType(0)
// OSLinux indicates the operating system is any version of Linux.
OSLinux = OSType('L')
// OSWindows indicates the operating system is any version of Windows.
OSWindows = OSType('W')
)
// -----------------------------------------------------------------------------
// # System Information Functions
// FirmwareDate _ _
func FirmwareDate() string {
if IsWindows() {
return registryHardwareInfo("SystemBiosDate")
}
zr.IMPLEMENT()
return ""
} // FirmwareDate
// FirmwareVersion _ _
func FirmwareVersion() string {
if IsWindows() {
return registryHardwareInfo("SystemBiosVersion")
}
zr.IMPLEMENT()
return ""
} // FirmwareVersion
// IsWindows returns true if the operating system is Windows.
func IsWindows() bool {
return OSClass() == OSWindows
} // IsWindows
// OSClass _ _
func OSClass() OSType {
switch windowsVersionInfo().dwPlatformId {
// ancient Windows platforms e.g. Windows ME
// (Win32s: could likely be platform 0)
case 1:
{
return OSUnknown
}
// Windows-NT based OS, e.g. Windows XP and above
case 2:
return OSWindows
}
return OSUnknown
} // OSClass
// OSFolder _ _
func OSFolder() string {
var buffer [MAX_PATH + 1]WCHAR // buffer to receive Windows directory
count := GetWindowsDirectory(
&buffer[0], // buffer for Windows directory
MAX_PATH+1, // size of buffer
)
var ret string
for i := UINT(0); i < count; i++ {
ret += string(buffer[i])
}
return ret
} // OSFolder
// SystemVolumeID _ _
func SystemVolumeID() uint32 {
return VolumeID(OSFolder())
} // SystemVolumeID
// VolumeID _ _
func VolumeID(path string) uint32 {
switch len(path) {
case 0:
{
return 0
}
// assume a drive letter
case 1:
{
path += ":\\"
}
case 2:
path += "\\"
}
var (
drive = path[:3]
ret = DWORD(0)
result = GetVolumeInformation(
drive, // in LPCTSTR lpRootPathName
nil, // out LPTSTR lpVolumeNameBuffer
0, // in DWORD nVolumeNameSize
&ret, // out LPDWORD lpVolumeSerialNumber
nil, // out LPDWORD lpMaximumComponentLength
nil, // out LPDWORD lpFileSystemFlags
nil, // out LPTSTR lpFileSystemNameBuffer
0) // in DWORD nFileSystemNameSize
)
if result == FALSE {
return 0
}
return uint32(ret)
} // VolumeID
// -----------------------------------------------------------------------------
// # Registry Function
// GetRegistryString reads a string value from
// the named registry key and value name
// -----------------------------------------------------------------------------
// details: use hasRegistryValue()
// to test for existence of the key and value name,
// because this function logs an error if the key is not found
//
// params.: key - string specifying the registry key to be opened,
// it should begin with one of the following:
// HKEY_CLASSES_ROOT,
// HKEY_CURRENT_CONFIG,
// HKEY_CURRENT_USER,
// HKEY_DYN_DATA,
// HKEY_LOCAL_MACHINE,
// HKEY_PERFORMANCE_DATA,
// HKEY_USERS
//
// valueName - name of registry value to enquire
//
// returns: the stored string value, or a zero-length
// string if value not found
//
// example: GetRegistryString(
// `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion`,
// "Version")
// -----------------------------------------------------------------------------
func GetRegistryString(key, valueName string) string {
const erv = ""
if len(key) == 0 {
zr.Error("Key is blank")
return erv
}
// prepare a buffer for reading the result
const BufferSize = 1024
var ar [BufferSize]WCHAR
//
// split registry key and subkey
rootKey := getRegistryKey(key)
subkey := getRegistrySubkey(key)
//
// open the specified registry location
openKey := HKEY(0)
result := RegOpenKeyEx(
rootKey, // hKey [in] HKEY
subkey, // lpSubKey [in] LPCTSTR
0, // ulOptions DWORD
KEY_READ, // samDesired [in] REGSAM
&openKey, // phkResult [out] PHKEY
)
if result != ERROR_SUCCESS {
zr.Error(result, "failed opening key:^", key,
"root:", fmt.Sprintf("0x%X", rootKey),
"subkey:^", subkey)
return erv
}
// read the specified registry value
lpData := LPBYTE(unsafe.Pointer(&ar[0]))
bufSize := DWORD(BufferSize)
result = RegQueryValueEx(
openKey, // hKey HKEY
valueName, // lpValueName string
nil, // lpReserved LPDWORD
nil, // lpType LPDWORD
lpData, // lpData LPBYTE
&bufSize, // lpcbData LPDWORD
)
if result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND {
zr.Error(zr.EFailedReading, "registry key^", key, "value^", valueName)
// TODO: add SystemErrorName(result) (in GetRegistryString)
return erv
}
// copy the array to a string
var (
retBuf = bytes.NewBuffer(make([]byte, 0, bufSize))
ws = retBuf.WriteString
)
for i := 0; ar[i] != 0; i++ {
ws(string(ar[i]))
}
return retBuf.String()
} // GetRegistryString
// -----------------------------------------------------------------------------
// # Internal Constants
// rootKeys _ _
var rootKeys = []struct {
name string
key HKEY
}{
{"HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT},
{"HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG},
{"HKEY_CURRENT_USER", HKEY_CURRENT_USER},
{"HKEY_DYN_DATA", HKEY_DYN_DATA},
{"HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE},
{"HKEY_PERFORMANCE_DATA", HKEY_PERFORMANCE_DATA},
{"HKEY_USERS", HKEY_USERS},
}
// -----------------------------------------------------------------------------
// # Internal Functions
// getRegistryKey _ _
func getRegistryKey(key string) HKEY {
const erv = HKEY(0)
if len(key) == 0 {
zr.Error("Key is blank")
return erv
}
for _, iter := range rootKeys {
if strings.HasPrefix(strings.ToUpper(key), iter.name) {
return iter.key
}
}
zr.Error("Invalid key^", key)
return erv
} // getRegistryKey
// getRegistrySubkey returns the subkey value
// from the specified registry key string
func getRegistrySubkey(key string) string {
const erv = ""
for _, iter := range rootKeys {
if strings.HasPrefix(strings.ToUpper(key), iter.name) {
pos := len(iter.name)
ret := key[pos+1:]
return ret
}
}
zr.Error("Invalid key^", key)
return erv
} // getRegistrySubkey
// registryHardwareInfo _ _
func registryHardwareInfo(valueName string) string {
ret := GetRegistryString(
`HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System`,
valueName,
)
ret = strings.TrimSpace(ret)
return ret
} // registryHardwareInfo
// windowsVersionInfo _ _
func windowsVersionInfo() OSVERSIONINFO {
var ret OSVERSIONINFO
ret.dwOSVersionInfoSize = DWORD(unsafe.Sizeof(ret))
result := GetVersionEx(&ret) != 0
if !result {
// TODO: handle failure to get OS version (in windowsVersionInfo)
}
return ret
} // windowsVersionInfo
// end