This repository has been archived by the owner on Jun 20, 2022. It is now read-only.
/
appfilter_windows.go
117 lines (98 loc) · 2.27 KB
/
appfilter_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
//go:build windows
package filter
import (
"fmt"
"path/filepath"
"sync"
"unsafe"
"golang.org/x/sys/windows"
)
var (
kernel32 = windows.MustLoadDLL("kernel32.dll")
queryFullProcessImageNameW = kernel32.MustFindProc("QueryFullProcessImageNameW")
)
// QueryFullProcessImageName is ...
func QueryFullProcessImageName(process windows.Handle, flags uint32, b []uint16) (string, error) {
n := uint32(windows.MAX_PATH)
// BOOL QueryFullProcessImageNameW(
// HANDLE hProcess,
// DWORD dwFlags,
// LPSTR lpExeName,
// PDWORD lpdwSize
// );
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-queryfullprocessimagenamew
ret, _, errno := queryFullProcessImageNameW.Call(
uintptr(process),
uintptr(flags),
uintptr(unsafe.Pointer(&b[0])),
uintptr(unsafe.Pointer(&n)),
)
if ret == 0 {
return "", errno
}
return windows.UTF16ToString(b[:n]), nil
}
// QueryNameByPID is ...
func QueryNameByPID(id uint32, b []uint16) (string, error) {
h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, id)
if err != nil {
return "", fmt.Errorf("open process error: %w", err)
}
defer windows.CloseHandle(h)
path, err := QueryFullProcessImageName(h, 0, b)
if err != nil {
return "", fmt.Errorf("query full process name error: %w", err)
}
_, file := filepath.Split(path)
return file, nil
}
// AppFilter is ...
type AppFilter struct {
// RWMutex is ...
sync.RWMutex
// PIDs is ...
PIDs map[uint32]struct{}
// Apps is ...
Apps map[string]struct{}
buff []uint16
}
// NewAppFilter is ...
func NewAppFilter() *AppFilter {
f := &AppFilter{
PIDs: make(map[uint32]struct{}),
Apps: make(map[string]struct{}),
buff: make([]uint16, windows.MAX_PATH),
}
return f
}
// SetPIDs is ...
func (f *AppFilter) SetPIDs(ids []uint32) {
f.Lock()
for _, v := range ids {
f.PIDs[v] = struct{}{}
}
f.Unlock()
}
// Add is ...
func (f *AppFilter) Add(s string) {
f.Lock()
f.UnsafeAdd(s)
f.Unlock()
}
// UnsafeAdd is ...
func (f *AppFilter) UnsafeAdd(s string) {
f.Apps[s] = struct{}{}
}
// Lookup is ...
func (f *AppFilter) Lookup(id uint32) bool {
f.RLock()
defer f.RUnlock()
// use PID
if _, ok := f.PIDs[id]; ok {
return true
}
// use name
file, _ := QueryNameByPID(id, f.buff)
_, ok := f.Apps[file]
return ok
}