forked from parsiya/golnk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathheaderutils.go
More file actions
executable file
·132 lines (115 loc) · 3.77 KB
/
headerutils.go
File metadata and controls
executable file
·132 lines (115 loc) · 3.77 KB
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
package lnk
import (
"encoding/binary"
"fmt"
"strconv"
"strings"
"time"
)
// ShellLinkHeader utilities.
/*
ShowCommand valid values:
0x00000001 - SW_SHOWNORMAL - The application is open and its window is open in a normal fashion.
0x00000003 - SW_SHOWMAXIMIZED - The application is open, and keyboard focus is given to the application, but its window is not shown.
0x00000007 - SW_SHOWMINNOACTIVE - The application is open, but its window is not shown. It is not given the keyboard focus.
All other values are SW_SHOWNORMAL.
*/
// showCommand returns the string associated with ShowCommand uint32 field.
func showCommand(s uint32) string {
switch s {
case 0x03:
return "SW_SHOWMAXIMIZED"
case 0x07:
return "SW_SHOWMINNOACTIVE"
}
// Anything other than these two (include 0x01) is "SW_SHOWNORMAL"
return "SW_SHOWNORMAL"
}
/*
HotKeyFlags contains the hotkey.
Although it's 4 bytes, only the first 2 bytes are used.
First byte is LowByte.
If between 0x30 and 0x5A inclusive, it's ASCII-hex of the key.
If between 0x70 and 0x87 it's F(num-0x70+1) (e.g. 0x70 == F1 and 0x87 == F24).
0x90 == NUM LOCK and 0x91 SCROLL LOCK.
Second byte is HighByte.
0x01: SHIFT
0X02: CTRL
0X03: ALT
*/
// HotKey returns the string representation of the hotkey uint32.
func HotKey(hotkey uint16) string {
var sb strings.Builder
lb := byteMaskuint16(hotkey, 0) // first byte
hb := byteMaskuint16(hotkey, 1) // second byte
switch hb {
case 0x01:
sb.WriteString("SHIFT")
case 0x02:
sb.WriteString("CTRL")
case 0x04:
sb.WriteString("ALT")
default:
// 0x00 is technically "no key assigned", but any value other than these
// are the same.
return "No Key Assigned"
}
sb.WriteString("+")
switch {
case 0x30 <= lb && lb <= 0x5A:
sb.WriteString(string(rune(lb)))
case 0x70 <= lb && lb <= 0x87:
sb.WriteString("F" + strconv.Itoa(int(lb-0x70+1)))
case lb == 0x90:
sb.WriteString("NUM LOCK")
case lb == 0x91:
sb.WriteString("SCROLL LOCK")
default:
// 0x00 is technically "no key assigned", but any value other than these
// are the same.
return "No Key Assigned"
}
return sb.String()
}
// toTime converts an 8-byte Windows Filetime to time.Time.
func toTime(t [8]byte) time.Time {
// unix epoch in 100ns intervals
const epoch int64 = 116444736000000000
// Taken from https://golang.org/src/syscall/types_windows.go#L352, which is only available on Windows
nsec := int64(binary.LittleEndian.Uint32(t[4:]))<<32 + int64(binary.LittleEndian.Uint32(t[:4]))
// if the time is before unix epoch, return a zero time
if nsec < epoch {
return time.Time{}
}
// change starting time to the Epoch (00:00:00 UTC, January 1, 1970)
nsec -= epoch
// convert to seconds and nanoseconds individually to avoid any possible overflow risk.
seconds := nsec / 10000000 // nsec is 100ns intervals, so divide by 10000000 to get seconds
nanos := (nsec % 10000000) * 100 // take the remainder and multiply by 100 to get nanoseconds
return time.Unix(seconds, nanos)
}
// Flag utilities.
/*
matchFlag does the following:
Given an uint32 flag read in littleEndian from disk and a []string,
match the flag bits and return a map[string]bool (FlagMap) that has the
// matched flags as keys.
Flag bits must be reversed because bits are matched to the flags from 0
onwards but the bit string is the other way around.
*/
func matchFlag(flag uint32, flagText []string) FlagMap {
// Convert to bits and then reverse.
flagBits := reverse(fmt.Sprintf("%b", flag))
mp := make(FlagMap)
// If we have more bits than flags (something has gone wrong or the file is corrupted),
// then reduce the flagbits.
if len(flagBits) > len(flagText) {
flagBits = flagBits[:len(flagText)]
}
for bitIndex := 0; bitIndex < len(flagBits); bitIndex++ {
if flagBits[bitIndex] == 0x31 {
mp[flagText[bitIndex]] = true
}
}
return mp
}