-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathhardware.c
198 lines (170 loc) · 6.2 KB
/
hardware.c
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
/**
* PROJECT: Native Shell
* COPYRIGHT: LGPL; See LICENSE in the top level directory
* FILE: hardware.c
* DESCRIPTION: Device tree routines.
* DEVELOPERS: See CONTRIBUTORS.md in the top level directory
*/
#include "precomp.h"
#define MAX_DEVICE_ID_LEN 200
#define ROOT_NAME L"HTREE\\ROOT\\0"
ULONG Level = 0;
HANDLE RootKey = 0;
NTSTATUS
RtlCliGetEnumKey(OUT PHANDLE KeyHandle)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System"
L"\\CurrentControlSet\\Enum");
// Initialize the object attributes
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
// Open the key for read access
return NtOpenKey(KeyHandle, KEY_READ, &ObjectAttributes);
}
NTSTATUS
RtlCliGetChildOrSibling(IN PWCHAR Name,
OUT PWCHAR ChildName,
IN ULONG Type)
{
NTSTATUS Status;
PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
// Initialize the Root Device Node name
RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance, Name);
// Initialize the request
PlugPlayData.Relation = Type;
PlugPlayData.RelatedDeviceInstanceLength = MAX_DEVICE_ID_LEN;
PlugPlayData.RelatedDeviceInstance = ChildName;
// Get the root child node
Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
(PVOID)&PlugPlayData,
sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
return Status;
}
NTSTATUS
RtlCliPrintDeviceName(IN PWCHAR Name)
{
NTSTATUS Status = STATUS_SUCCESS;
HANDLE RegHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
PKEY_VALUE_FULL_INFORMATION FullInformation;
ULONG ResultLength;
WCHAR Buffer[MAX_DEVICE_ID_LEN];
ULONG i;
// If we don't already have a root key, get it now
if (!RootKey)
Status = RtlCliGetEnumKey(&RootKey);
if (NT_SUCCESS(Status))
{
// Root key opened, now initialize the device instance key name
RtlInitUnicodeString(&KeyName, Name);
// Setup the object attributes and open the key
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
0,
RootKey,
NULL);
Status = NtOpenKey(&RegHandle, KEY_READ, &ObjectAttributes);
if (NT_SUCCESS(Status))
{
// Setup and allocate the key data structure
ResultLength = sizeof(*FullInformation) + 256;
FullInformation = RtlAllocateHeap(RtlGetProcessHeap(),
0,
ResultLength);
// Now check for a friendly name
RtlInitUnicodeString(&KeyName, L"FriendlyName");
Status = NtQueryValueKey(RegHandle,
&KeyName,
KeyValueFullInformation,
FullInformation,
ResultLength,
&ResultLength);
if (!NT_SUCCESS(Status))
{
// No friendly name found, try the device description key
RtlInitUnicodeString(&KeyName, L"DeviceDesc");
Status = NtQueryValueKey(RegHandle,
&KeyName,
KeyValueFullInformation,
FullInformation,
ResultLength,
&ResultLength);
}
// Check if we have success until here
if (NT_SUCCESS(Status))
{
// Get the pointer to the name
Name = (PWCHAR)((ULONG_PTR)FullInformation +
FullInformation->DataOffset);
// Indent the name to create the appeareance of a tree
for (i = 0; i < (Level * 2); i++)
Buffer[i] = ' ';
Buffer[i] = UNICODE_NULL;
// Add the device name or description, and display it
wcscat(Buffer, Name);
RtlCliDisplayString("%S\n", Buffer);
DbgPrint("%S\n", Buffer);
}
// Close the key to the device instance name
NtClose(RegHandle);
}
}
// Return status to caller
return Status;
}
NTSTATUS
RtlCliListSubNodes(IN PWCHAR Parent,
IN PWCHAR Sibling,
IN PWCHAR Current)
{
NTSTATUS Status;
WCHAR FoundSibling[MAX_DEVICE_ID_LEN];
WCHAR FoundChild[MAX_DEVICE_ID_LEN];
// Start looping
do
{
// Get the first sibling
Status = RtlCliGetChildOrSibling(Current, FoundSibling, PNP_GET_SIBLING_DEVICE);
if (!NT_SUCCESS(Status))
*FoundSibling = UNICODE_NULL;
// Print its name
Status = RtlCliPrintDeviceName(Current);
// Get its children
Status = RtlCliGetChildOrSibling(Current, FoundChild, PNP_GET_CHILD_DEVICE);
if (NT_SUCCESS(Status))
{
// Get it's children's subnodes
Level++;
RtlCliListSubNodes(Current, NULL, FoundChild);
Level--;
}
// Move to the next sibling
Current = FoundSibling;
} while (*Current);
// Return status
return Status;
}
NTSTATUS
RtlCliListHardwareTree(VOID)
{
NTSTATUS Status;
WCHAR Buffer[MAX_DEVICE_ID_LEN];
// Get the root node's child
Status = RtlCliGetChildOrSibling(ROOT_NAME, Buffer, PNP_GET_CHILD_DEVICE);
if (!NT_SUCCESS(Status))
{
RtlCliDisplayString("NtPlugPlayControl get root node failed.\n");
}
// Now get the entire tree
Status = RtlCliListSubNodes(ROOT_NAME, NULL, Buffer);
if (!NT_SUCCESS(Status))
{
RtlCliDisplayString("NtPlugPlayControl get child nodes failed.\n");
}
return Status;
}