-
Notifications
You must be signed in to change notification settings - Fork 0
/
stack.go
157 lines (121 loc) · 3.73 KB
/
stack.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
package devcon
import (
"regexp"
"strings"
)
var (
reSetupClass = regexp.MustCompile(`Setup Class: {(?P<GUID>.*)} (?P<Name>.*)`)
)
// DriverStack contains driver stack details for a device.
type DriverStack struct {
// Device is the device that the stack is associated with.
Device Device `json:"device"`
// SetupClassGUID is the GUID of the setup class.
SetupClassGUID string `json:"setupClassGuid"`
// SetupClassName is the name of the setup class.
SetupClassName string `json:"setupClassName"`
// ControllingService is the Windows Service that controls the driver.
ControllingService string `json:"controllingService"`
// UpperFilters represent a configuration that monitors all IRP traffic
// into or out of the device driver within the device's driver stack,
// regardless of whether the driver processed the IRP or passed it through
// to lower device drivers.
UpperFilters string `json:"upperFilters"`
// LowerFilters represent a configuration that monitors all IRP traffic into
// or out of the device driver from lower drivers within the device's driver stack.
LowerFilters string `json:"lowerFilters"`
}
// Stack returns the expected driver stack for the specified devices, and the
// GUID and the name of the device setup class for each device. Although the
// actual driver stack typically matches the expected stack, variations are
// possible.
//
// To investigate a device problem, compare the expected driver stack from the
// stack operation with the actual drivers that the device uses, as returned
// from DriverFiles().
//
// Running with the WithRemoteComputer() option is allowed.
//
// See https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/devcon-stack for more information.
func (dc *DevCon) Stack() ([]DriverStack, error) {
lines, err := dc.run(commandStack)
if err != nil {
return nil, err
}
type searchStatus int
const (
None searchStatus = iota
UpperFilter
Service
LowerFilter
)
groupIndices := make([]int, 0)
for index, line := range lines {
if !strings.HasPrefix(line, " ") {
groupIndices = append(groupIndices, index)
}
}
groupIndices = append(groupIndices, len(lines))
stacks := make([]DriverStack, 0)
for index, groupStart := range groupIndices {
nextIndex := index + 1
if len(groupIndices) == nextIndex {
break
}
groupEnd := groupIndices[nextIndex]
stack := DriverStack{
Device: Device{
ID: "",
Name: "",
},
SetupClassGUID: "",
SetupClassName: "",
ControllingService: "",
UpperFilters: "",
LowerFilters: "",
}
search := None
for lineIndex := groupStart; lineIndex < groupEnd; lineIndex++ {
line := trimSpaces(lines[lineIndex])
switch {
case lineIndex == groupStart:
stack.Device.ID = line
case lineIndex == groupStart+1:
nameParams := parseParams(reName, line)
if name, ok := nameParams["Name"]; ok {
stack.Device.Name = name
}
case strings.Contains(line, "Setup Class"):
params := parseParams(reSetupClass, line)
if guid, ok := params["GUID"]; ok {
stack.SetupClassGUID = guid
}
if name, ok := params["Name"]; ok {
stack.SetupClassName = name
}
case strings.Contains(line, "pper filters:"):
search = UpperFilter
case strings.Contains(line, "service:"):
search = Service
case strings.Contains(line, "ower filters:"):
search = LowerFilter
default:
search = None
}
//goland:noinspection GoDfaConstantCondition
switch search {
case UpperFilter:
stack.UpperFilters = line
case Service:
stack.ControllingService = line
case LowerFilter:
stack.LowerFilters = line
case None: // Do nothing
}
}
if stack.Device.Name != "" {
stacks = append(stacks, stack)
}
}
return stacks, nil
}