24c8ba6753c59b6034ca15fc860dbfcf1bcfc664
[reactos.git] / reactos / ntoskrnl / io / pnpmgr / pnpinit.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnpinit.c
5 * PURPOSE: PnP Initialization Code
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ********************************************************************/
16
17 PUNICODE_STRING PiInitGroupOrderTable;
18 ULONG PiInitGroupOrderTableCount;
19
20 /* FUNCTIONS ******************************************************************/
21
22 NTSTATUS
23 NTAPI
24 PiInitCacheGroupInformation(VOID)
25 {
26 HANDLE KeyHandle;
27 NTSTATUS Status;
28 PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
29 PUNICODE_STRING GroupTable;
30 ULONG Count;
31 UNICODE_STRING GroupString =
32 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet"
33 L"\\Control\\ServiceGroupOrder");
34
35 /* ReactOS HACK for SETUPLDR */
36 if (KeLoaderBlock->SetupLdrBlock)
37 {
38 /* Bogus data */
39 PiInitGroupOrderTableCount = 0;
40 PiInitGroupOrderTable = (PVOID)0xBABEB00B;
41 return STATUS_SUCCESS;
42 }
43
44 /* Open the registry key */
45 Status = IopOpenRegistryKeyEx(&KeyHandle,
46 NULL,
47 &GroupString,
48 KEY_READ);
49 if (NT_SUCCESS(Status))
50 {
51 /* Get the list */
52 Status = IopGetRegistryValue(KeyHandle, L"List", &KeyValueInformation);
53 ZwClose(KeyHandle);
54
55 /* Make sure we got it */
56 if (NT_SUCCESS(Status))
57 {
58 /* Make sure it's valid */
59 if ((KeyValueInformation->Type == REG_MULTI_SZ) &&
60 (KeyValueInformation->DataLength))
61 {
62 /* Convert it to unicode strings */
63 Status = PnpRegMultiSzToUnicodeStrings(KeyValueInformation,
64 &GroupTable,
65 &Count);
66
67 /* Cache it for later */
68 PiInitGroupOrderTable = GroupTable;
69 PiInitGroupOrderTableCount = Count;
70 }
71 else
72 {
73 /* Fail */
74 Status = STATUS_UNSUCCESSFUL;
75 }
76
77 /* Free the information */
78 ExFreePool(KeyValueInformation);
79 }
80 }
81
82 /* Return status */
83 return Status;
84 }
85
86 USHORT
87 NTAPI
88 PpInitGetGroupOrderIndex(IN HANDLE ServiceHandle)
89 {
90 NTSTATUS Status;
91 PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
92 ULONG i;
93 PVOID Buffer;
94 UNICODE_STRING Group;
95 PAGED_CODE();
96
97 /* Make sure we have a cache */
98 if (!PiInitGroupOrderTable) return -1;
99
100 /* If we don't have a handle, the rest is easy -- return the count */
101 if (!ServiceHandle) return PiInitGroupOrderTableCount + 1;
102
103 /* Otherwise, get the group value */
104 Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation);
105 if (!NT_SUCCESS(Status)) return PiInitGroupOrderTableCount;
106
107 /* Make sure we have a valid string */
108 ASSERT(KeyValueInformation->Type == REG_SZ);
109 ASSERT(KeyValueInformation->DataLength);
110
111 /* Convert to unicode string */
112 Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset);
113 PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length);
114 Group.MaximumLength = KeyValueInformation->DataLength;
115 Group.Buffer = Buffer;
116
117 /* Loop the groups */
118 for (i = 0; i < PiInitGroupOrderTableCount; i++)
119 {
120 /* Try to find a match */
121 if (RtlEqualUnicodeString(&Group, &PiInitGroupOrderTable[i], TRUE)) break;
122 }
123
124 /* We're done */
125 ExFreePool(KeyValueInformation);
126 return i;
127 }
128
129 USHORT
130 NTAPI
131 PipGetDriverTagPriority(IN HANDLE ServiceHandle)
132 {
133 NTSTATUS Status;
134 HANDLE KeyHandle = NULL;
135 PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL;
136 PKEY_VALUE_FULL_INFORMATION KeyValueInformationTag;
137 PKEY_VALUE_FULL_INFORMATION KeyValueInformationGroupOrderList;
138 PVOID Buffer;
139 UNICODE_STRING Group;
140 PULONG GroupOrder;
141 ULONG i = -1, Count, Tag = 0;
142 UNICODE_STRING GroupString =
143 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet"
144 L"\\Control\\ServiceGroupOrder");
145
146 /* Open the key */
147 Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &GroupString, KEY_READ);
148 if (!NT_SUCCESS(Status)) goto Quickie;
149
150 /* Read the group */
151 Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation);
152 if (!NT_SUCCESS(Status)) goto Quickie;
153
154 /* Make sure we have a group */
155 if ((KeyValueInformation->Type == REG_SZ) &&
156 (KeyValueInformation->DataLength))
157 {
158 /* Convert to unicode string */
159 Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset);
160 PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length);
161 Group.MaximumLength = KeyValueInformation->DataLength;
162 Group.Buffer = Buffer;
163 }
164
165 /* Now read the tag */
166 Status = IopGetRegistryValue(ServiceHandle, L"Tag", &KeyValueInformationTag);
167 if (!NT_SUCCESS(Status)) goto Quickie;
168
169 /* Make sure we have a tag */
170 if ((KeyValueInformationTag->Type == REG_DWORD) &&
171 (KeyValueInformationTag->DataLength))
172 {
173 /* Read it */
174 Tag = *(PULONG)((ULONG_PTR)KeyValueInformationTag +
175 KeyValueInformationTag->DataOffset);
176 }
177
178 /* We can get rid of this now */
179 ExFreePool(KeyValueInformationTag);
180
181 /* Now let's read the group's tag order */
182 Status = IopGetRegistryValue(KeyHandle,
183 Group.Buffer,
184 &KeyValueInformationGroupOrderList);
185
186 /* We can get rid of this now */
187 Quickie:
188 if (KeyValueInformation) ExFreePool(KeyValueInformation);
189 if (KeyHandle) NtClose(KeyHandle);
190 if (!NT_SUCCESS(Status)) return -1;
191
192 /* We're on the success path -- validate the tag order*/
193 if ((KeyValueInformationGroupOrderList->Type == REG_BINARY) &&
194 (KeyValueInformationGroupOrderList->DataLength))
195 {
196 /* Get the order array */
197 GroupOrder = (PULONG)((ULONG_PTR)KeyValueInformationGroupOrderList +
198 KeyValueInformationGroupOrderList->DataOffset);
199
200 /* Get the count */
201 Count = *GroupOrder;
202 ASSERT(((Count + 1) * sizeof(ULONG)) <=
203 KeyValueInformationGroupOrderList->DataLength);
204
205 /* Now loop each tag */
206 GroupOrder++;
207 for (i = 1; i <= Count; i++)
208 {
209 /* If we found it, we're out */
210 if (Tag == *GroupOrder) break;
211
212 /* Try the next one */
213 GroupOrder++;
214 }
215 }
216
217 /* Last buffer to free */
218 ExFreePool(KeyValueInformationGroupOrderList);
219 return i;
220 }
221
222 NTSTATUS
223 NTAPI
224 PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode,
225 IN BOOLEAN LoadDriver,
226 IN PDRIVER_OBJECT DriverObject)
227 {
228 NTSTATUS Status;
229 HANDLE EnumRootKey, SubKey, ControlKey, ClassKey, PropertiesKey;
230 UNICODE_STRING ClassGuid, Properties;
231 UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT);
232 UNICODE_STRING ControlClass =
233 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class");
234 PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL;
235 PWCHAR Buffer;
236
237 /* Open enumeration root key */
238 Status = IopOpenRegistryKeyEx(&EnumRootKey,
239 NULL,
240 &EnumRoot,
241 KEY_READ);
242 if (!NT_SUCCESS(Status))
243 {
244 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
245 return Status;
246 }
247
248 /* Open instance subkey */
249 Status = IopOpenRegistryKeyEx(&SubKey,
250 EnumRootKey,
251 &DeviceNode->InstancePath,
252 KEY_READ);
253 if (!NT_SUCCESS(Status))
254 {
255 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
256 ZwClose(EnumRootKey);
257 return Status;
258 }
259
260 /* Get class GUID */
261 Status = IopGetRegistryValue(SubKey,
262 REGSTR_VAL_CLASSGUID,
263 &KeyValueInformation);
264 if (NT_SUCCESS(Status))
265 {
266 /* Convert to unicode string */
267 Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset);
268 PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &ClassGuid.Length);
269 ClassGuid.MaximumLength = KeyValueInformation->DataLength;
270 ClassGuid.Buffer = Buffer;
271
272 /* Open the key */
273 Status = IopOpenRegistryKeyEx(&ControlKey,
274 NULL,
275 &ControlClass,
276 KEY_READ);
277 if (!NT_SUCCESS(Status))
278 {
279 /* No class key */
280 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
281 ClassKey = NULL;
282 }
283 else
284 {
285 /* Open the class key */
286 Status = IopOpenRegistryKeyEx(&ClassKey,
287 ControlKey,
288 &ClassGuid,
289 KEY_READ);
290 ZwClose(ControlKey);
291 if (!NT_SUCCESS(Status))
292 {
293 /* No class key */
294 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
295 ClassKey = NULL;
296 }
297 }
298
299 /* Check if we made it till here */
300 if (ClassKey)
301 {
302 /* Get the device properties */
303 RtlInitUnicodeString(&Properties, REGSTR_KEY_DEVICE_PROPERTIES);
304 Status = IopOpenRegistryKeyEx(&PropertiesKey,
305 ClassKey,
306 &Properties,
307 KEY_READ);
308 if (!NT_SUCCESS(Status))
309 {
310 /* No properties */
311 DPRINT("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
312 PropertiesKey = NULL;
313 }
314 }
315
316 /* Free the registry data */
317 ExFreePool(KeyValueInformation);
318 }
319
320 /* Do ReactOS-style setup */
321 IopAttachFilterDrivers(DeviceNode, TRUE);
322 Status = IopInitializeDevice(DeviceNode, DriverObject);
323 if (NT_SUCCESS(Status))
324 {
325 IopAttachFilterDrivers(DeviceNode, FALSE);
326 IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
327 Status = IopStartDevice(DeviceNode);
328 }
329
330 /* Return status */
331 return Status;
332 }
333
334 /* EOF */