1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Kernel
3c2c66affSColin Finck * COPYRIGHT: GPL - See COPYING in the top level directory
4c2c66affSColin Finck * FILE: ntoskrnl/io/pnpmgr/pnpres.c
5c2c66affSColin Finck * PURPOSE: Resource handling code
6c2c66affSColin Finck * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
7c2c66affSColin Finck * ReactOS Portable Systems Group
8c2c66affSColin Finck */
9c2c66affSColin Finck
10c2c66affSColin Finck #include <ntoskrnl.h>
11c2c66affSColin Finck
12c2c66affSColin Finck #define NDEBUG
13c2c66affSColin Finck #include <debug.h>
14c2c66affSColin Finck
15b82bf8ceSTimo Kreuzer FORCEINLINE
16b82bf8ceSTimo Kreuzer PIO_RESOURCE_LIST
IopGetNextResourceList(_In_ const IO_RESOURCE_LIST * ResourceList)17b82bf8ceSTimo Kreuzer IopGetNextResourceList(
18b82bf8ceSTimo Kreuzer _In_ const IO_RESOURCE_LIST *ResourceList)
19b82bf8ceSTimo Kreuzer {
20b82bf8ceSTimo Kreuzer ASSERT((ResourceList->Count > 0) && (ResourceList->Count < 1000));
21b82bf8ceSTimo Kreuzer return (PIO_RESOURCE_LIST)(
22b82bf8ceSTimo Kreuzer &ResourceList->Descriptors[ResourceList->Count]);
23b82bf8ceSTimo Kreuzer }
24b82bf8ceSTimo Kreuzer
25c2c66affSColin Finck static
26c2c66affSColin Finck BOOLEAN
IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc,OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)279538c3ccSEric Kohl IopCheckDescriptorForConflict(
289538c3ccSEric Kohl PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc,
299538c3ccSEric Kohl OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
30c2c66affSColin Finck {
31c2c66affSColin Finck CM_RESOURCE_LIST CmList;
32c2c66affSColin Finck NTSTATUS Status;
33c2c66affSColin Finck
34c2c66affSColin Finck CmList.Count = 1;
35c2c66affSColin Finck CmList.List[0].InterfaceType = InterfaceTypeUndefined;
36c2c66affSColin Finck CmList.List[0].BusNumber = 0;
37c2c66affSColin Finck CmList.List[0].PartialResourceList.Version = 1;
38c2c66affSColin Finck CmList.List[0].PartialResourceList.Revision = 1;
39c2c66affSColin Finck CmList.List[0].PartialResourceList.Count = 1;
40c2c66affSColin Finck CmList.List[0].PartialResourceList.PartialDescriptors[0] = *CmDesc;
41c2c66affSColin Finck
42c2c66affSColin Finck Status = IopDetectResourceConflict(&CmList, TRUE, ConflictingDescriptor);
43c2c66affSColin Finck if (Status == STATUS_CONFLICTING_ADDRESSES)
44c2c66affSColin Finck return TRUE;
45c2c66affSColin Finck
46c2c66affSColin Finck return FALSE;
47c2c66affSColin Finck }
48c2c66affSColin Finck
49c2c66affSColin Finck static
50c2c66affSColin Finck BOOLEAN
IopFindBusNumberResource(IN PIO_RESOURCE_DESCRIPTOR IoDesc,OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)51c2c66affSColin Finck IopFindBusNumberResource(
52c2c66affSColin Finck IN PIO_RESOURCE_DESCRIPTOR IoDesc,
53c2c66affSColin Finck OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
54c2c66affSColin Finck {
55c2c66affSColin Finck ULONG Start;
56c2c66affSColin Finck CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc;
57c2c66affSColin Finck
58c2c66affSColin Finck ASSERT(IoDesc->Type == CmDesc->Type);
59c2c66affSColin Finck ASSERT(IoDesc->Type == CmResourceTypeBusNumber);
60c2c66affSColin Finck
61c2c66affSColin Finck for (Start = IoDesc->u.BusNumber.MinBusNumber;
62c2c66affSColin Finck Start <= IoDesc->u.BusNumber.MaxBusNumber - IoDesc->u.BusNumber.Length + 1;
63c2c66affSColin Finck Start++)
64c2c66affSColin Finck {
65c2c66affSColin Finck CmDesc->u.BusNumber.Length = IoDesc->u.BusNumber.Length;
66c2c66affSColin Finck CmDesc->u.BusNumber.Start = Start;
67c2c66affSColin Finck
68c2c66affSColin Finck if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc))
69c2c66affSColin Finck {
70c2c66affSColin Finck Start += ConflictingDesc.u.BusNumber.Start + ConflictingDesc.u.BusNumber.Length;
71c2c66affSColin Finck }
72c2c66affSColin Finck else
73c2c66affSColin Finck {
74c2c66affSColin Finck DPRINT1("Satisfying bus number requirement with 0x%x (length: 0x%x)\n", Start, CmDesc->u.BusNumber.Length);
75c2c66affSColin Finck return TRUE;
76c2c66affSColin Finck }
77c2c66affSColin Finck }
78c2c66affSColin Finck
79c2c66affSColin Finck return FALSE;
80c2c66affSColin Finck }
81c2c66affSColin Finck
82c2c66affSColin Finck static
83c2c66affSColin Finck BOOLEAN
IopFindMemoryResource(IN PIO_RESOURCE_DESCRIPTOR IoDesc,OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)84c2c66affSColin Finck IopFindMemoryResource(
85c2c66affSColin Finck IN PIO_RESOURCE_DESCRIPTOR IoDesc,
86c2c66affSColin Finck OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
87c2c66affSColin Finck {
88c2c66affSColin Finck ULONGLONG Start;
89c2c66affSColin Finck CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc;
90c2c66affSColin Finck
91c2c66affSColin Finck ASSERT(IoDesc->Type == CmDesc->Type);
92c2c66affSColin Finck ASSERT(IoDesc->Type == CmResourceTypeMemory);
93c2c66affSColin Finck
94c2c66affSColin Finck /* HACK */
959538c3ccSEric Kohl if (IoDesc->u.Memory.Alignment == 0)
969538c3ccSEric Kohl IoDesc->u.Memory.Alignment = 1;
97c2c66affSColin Finck
98c2c66affSColin Finck for (Start = (ULONGLONG)IoDesc->u.Memory.MinimumAddress.QuadPart;
99c2c66affSColin Finck Start <= (ULONGLONG)IoDesc->u.Memory.MaximumAddress.QuadPart - IoDesc->u.Memory.Length + 1;
100c2c66affSColin Finck Start += IoDesc->u.Memory.Alignment)
101c2c66affSColin Finck {
102c2c66affSColin Finck CmDesc->u.Memory.Length = IoDesc->u.Memory.Length;
103c2c66affSColin Finck CmDesc->u.Memory.Start.QuadPart = (LONGLONG)Start;
104c2c66affSColin Finck
105c2c66affSColin Finck if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc))
106c2c66affSColin Finck {
107c2c66affSColin Finck Start += (ULONGLONG)ConflictingDesc.u.Memory.Start.QuadPart +
108c2c66affSColin Finck ConflictingDesc.u.Memory.Length;
109c2c66affSColin Finck }
110c2c66affSColin Finck else
111c2c66affSColin Finck {
112c2c66affSColin Finck DPRINT1("Satisfying memory requirement with 0x%I64x (length: 0x%x)\n", Start, CmDesc->u.Memory.Length);
113c2c66affSColin Finck return TRUE;
114c2c66affSColin Finck }
115c2c66affSColin Finck }
116c2c66affSColin Finck
117c2c66affSColin Finck return FALSE;
118c2c66affSColin Finck }
119c2c66affSColin Finck
120c2c66affSColin Finck static
121c2c66affSColin Finck BOOLEAN
IopFindPortResource(IN PIO_RESOURCE_DESCRIPTOR IoDesc,OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)122c2c66affSColin Finck IopFindPortResource(
123c2c66affSColin Finck IN PIO_RESOURCE_DESCRIPTOR IoDesc,
124c2c66affSColin Finck OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
125c2c66affSColin Finck {
126c2c66affSColin Finck ULONGLONG Start;
127c2c66affSColin Finck CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc;
128c2c66affSColin Finck
129c2c66affSColin Finck ASSERT(IoDesc->Type == CmDesc->Type);
130c2c66affSColin Finck ASSERT(IoDesc->Type == CmResourceTypePort);
131c2c66affSColin Finck
132c2c66affSColin Finck /* HACK */
1339538c3ccSEric Kohl if (IoDesc->u.Port.Alignment == 0)
1349538c3ccSEric Kohl IoDesc->u.Port.Alignment = 1;
135c2c66affSColin Finck
136c2c66affSColin Finck for (Start = (ULONGLONG)IoDesc->u.Port.MinimumAddress.QuadPart;
137c2c66affSColin Finck Start <= (ULONGLONG)IoDesc->u.Port.MaximumAddress.QuadPart - IoDesc->u.Port.Length + 1;
138c2c66affSColin Finck Start += IoDesc->u.Port.Alignment)
139c2c66affSColin Finck {
140c2c66affSColin Finck CmDesc->u.Port.Length = IoDesc->u.Port.Length;
141c2c66affSColin Finck CmDesc->u.Port.Start.QuadPart = (LONGLONG)Start;
142c2c66affSColin Finck
143c2c66affSColin Finck if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc))
144c2c66affSColin Finck {
145c2c66affSColin Finck Start += (ULONGLONG)ConflictingDesc.u.Port.Start.QuadPart + ConflictingDesc.u.Port.Length;
146c2c66affSColin Finck }
147c2c66affSColin Finck else
148c2c66affSColin Finck {
149c2c66affSColin Finck DPRINT("Satisfying port requirement with 0x%I64x (length: 0x%x)\n", Start, CmDesc->u.Port.Length);
150c2c66affSColin Finck return TRUE;
151c2c66affSColin Finck }
152c2c66affSColin Finck }
153c2c66affSColin Finck
154c2c66affSColin Finck DPRINT1("IopFindPortResource failed!\n");
155c2c66affSColin Finck return FALSE;
156c2c66affSColin Finck }
157c2c66affSColin Finck
158c2c66affSColin Finck static
159c2c66affSColin Finck BOOLEAN
IopFindDmaResource(IN PIO_RESOURCE_DESCRIPTOR IoDesc,OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)160c2c66affSColin Finck IopFindDmaResource(
161c2c66affSColin Finck IN PIO_RESOURCE_DESCRIPTOR IoDesc,
162c2c66affSColin Finck OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
163c2c66affSColin Finck {
164c2c66affSColin Finck ULONG Channel;
165c2c66affSColin Finck
166c2c66affSColin Finck ASSERT(IoDesc->Type == CmDesc->Type);
167c2c66affSColin Finck ASSERT(IoDesc->Type == CmResourceTypeDma);
168c2c66affSColin Finck
169c2c66affSColin Finck for (Channel = IoDesc->u.Dma.MinimumChannel;
170c2c66affSColin Finck Channel <= IoDesc->u.Dma.MaximumChannel;
171c2c66affSColin Finck Channel++)
172c2c66affSColin Finck {
173c2c66affSColin Finck CmDesc->u.Dma.Channel = Channel;
174c2c66affSColin Finck CmDesc->u.Dma.Port = 0;
175c2c66affSColin Finck
176c2c66affSColin Finck if (!IopCheckDescriptorForConflict(CmDesc, NULL))
177c2c66affSColin Finck {
178c2c66affSColin Finck DPRINT1("Satisfying DMA requirement with channel 0x%x\n", Channel);
179c2c66affSColin Finck return TRUE;
180c2c66affSColin Finck }
181c2c66affSColin Finck }
182c2c66affSColin Finck
183c2c66affSColin Finck return FALSE;
184c2c66affSColin Finck }
185c2c66affSColin Finck
186c2c66affSColin Finck static
187c2c66affSColin Finck BOOLEAN
IopFindInterruptResource(IN PIO_RESOURCE_DESCRIPTOR IoDesc,OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)188c2c66affSColin Finck IopFindInterruptResource(
189c2c66affSColin Finck IN PIO_RESOURCE_DESCRIPTOR IoDesc,
190c2c66affSColin Finck OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
191c2c66affSColin Finck {
192c2c66affSColin Finck ULONG Vector;
193c2c66affSColin Finck
194c2c66affSColin Finck ASSERT(IoDesc->Type == CmDesc->Type);
195c2c66affSColin Finck ASSERT(IoDesc->Type == CmResourceTypeInterrupt);
196c2c66affSColin Finck
197c2c66affSColin Finck for (Vector = IoDesc->u.Interrupt.MinimumVector;
198c2c66affSColin Finck Vector <= IoDesc->u.Interrupt.MaximumVector;
199c2c66affSColin Finck Vector++)
200c2c66affSColin Finck {
201c2c66affSColin Finck CmDesc->u.Interrupt.Vector = Vector;
202c2c66affSColin Finck CmDesc->u.Interrupt.Level = Vector;
203c2c66affSColin Finck CmDesc->u.Interrupt.Affinity = (KAFFINITY)-1;
204c2c66affSColin Finck
205c2c66affSColin Finck if (!IopCheckDescriptorForConflict(CmDesc, NULL))
206c2c66affSColin Finck {
207c2c66affSColin Finck DPRINT1("Satisfying interrupt requirement with IRQ 0x%x\n", Vector);
208c2c66affSColin Finck return TRUE;
209c2c66affSColin Finck }
210c2c66affSColin Finck }
211c2c66affSColin Finck
212b82bf8ceSTimo Kreuzer DPRINT1("Failed to satisfy interrupt requirement with IRQ 0x%x-0x%x\n",
213b82bf8ceSTimo Kreuzer IoDesc->u.Interrupt.MinimumVector,
214b82bf8ceSTimo Kreuzer IoDesc->u.Interrupt.MaximumVector);
215c2c66affSColin Finck return FALSE;
216c2c66affSColin Finck }
217c2c66affSColin Finck
218c2c66affSColin Finck NTSTATUS NTAPI
IopFixupResourceListWithRequirements(IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList,OUT PCM_RESOURCE_LIST * ResourceList)219c2c66affSColin Finck IopFixupResourceListWithRequirements(
220c2c66affSColin Finck IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList,
221c2c66affSColin Finck OUT PCM_RESOURCE_LIST *ResourceList)
222c2c66affSColin Finck {
223c2c66affSColin Finck ULONG i, OldCount;
224c2c66affSColin Finck BOOLEAN AlternateRequired = FALSE;
225b82bf8ceSTimo Kreuzer PIO_RESOURCE_LIST ResList;
226c2c66affSColin Finck
227c2c66affSColin Finck /* Save the initial resource count when we got here so we can restore if an alternate fails */
228c2c66affSColin Finck if (*ResourceList != NULL)
229c2c66affSColin Finck OldCount = (*ResourceList)->List[0].PartialResourceList.Count;
230c2c66affSColin Finck else
231c2c66affSColin Finck OldCount = 0;
232c2c66affSColin Finck
233b82bf8ceSTimo Kreuzer ResList = &RequirementsList->List[0];
234b82bf8ceSTimo Kreuzer for (i = 0; i < RequirementsList->AlternativeLists; i++, ResList = IopGetNextResourceList(ResList))
235c2c66affSColin Finck {
236c2c66affSColin Finck ULONG ii;
237c2c66affSColin Finck
238c2c66affSColin Finck /* We need to get back to where we were before processing the last alternative list */
239c2c66affSColin Finck if (OldCount == 0 && *ResourceList != NULL)
240c2c66affSColin Finck {
241c2c66affSColin Finck /* Just free it and kill the pointer */
242c2c66affSColin Finck ExFreePool(*ResourceList);
243c2c66affSColin Finck *ResourceList = NULL;
244c2c66affSColin Finck }
245c2c66affSColin Finck else if (OldCount != 0)
246c2c66affSColin Finck {
247c2c66affSColin Finck PCM_RESOURCE_LIST NewList;
248c2c66affSColin Finck
249c2c66affSColin Finck /* Let's resize it */
250c2c66affSColin Finck (*ResourceList)->List[0].PartialResourceList.Count = OldCount;
251c2c66affSColin Finck
252c2c66affSColin Finck /* Allocate the new smaller list */
253c2c66affSColin Finck NewList = ExAllocatePool(PagedPool, PnpDetermineResourceListSize(*ResourceList));
254c2c66affSColin Finck if (!NewList)
255c2c66affSColin Finck return STATUS_NO_MEMORY;
256c2c66affSColin Finck
257c2c66affSColin Finck /* Copy the old stuff back */
258c2c66affSColin Finck RtlCopyMemory(NewList, *ResourceList, PnpDetermineResourceListSize(*ResourceList));
259c2c66affSColin Finck
260c2c66affSColin Finck /* Free the old one */
261c2c66affSColin Finck ExFreePool(*ResourceList);
262c2c66affSColin Finck
263c2c66affSColin Finck /* Store the pointer to the new one */
264c2c66affSColin Finck *ResourceList = NewList;
265c2c66affSColin Finck }
266c2c66affSColin Finck
267c2c66affSColin Finck for (ii = 0; ii < ResList->Count; ii++)
268c2c66affSColin Finck {
269c2c66affSColin Finck ULONG iii;
270c2c66affSColin Finck PCM_PARTIAL_RESOURCE_LIST PartialList = (*ResourceList) ? &(*ResourceList)->List[0].PartialResourceList : NULL;
271c2c66affSColin Finck PIO_RESOURCE_DESCRIPTOR IoDesc = &ResList->Descriptors[ii];
272c2c66affSColin Finck BOOLEAN Matched = FALSE;
273c2c66affSColin Finck
274c2c66affSColin Finck /* Skip alternates if we don't need one */
275c2c66affSColin Finck if (!AlternateRequired && (IoDesc->Option & IO_RESOURCE_ALTERNATIVE))
276c2c66affSColin Finck {
277c2c66affSColin Finck DPRINT("Skipping unneeded alternate\n");
278c2c66affSColin Finck continue;
279c2c66affSColin Finck }
280c2c66affSColin Finck
281c2c66affSColin Finck /* Check if we couldn't satsify a requirement or its alternates */
282c2c66affSColin Finck if (AlternateRequired && !(IoDesc->Option & IO_RESOURCE_ALTERNATIVE))
283c2c66affSColin Finck {
284c2c66affSColin Finck DPRINT1("Unable to satisfy preferred resource or alternates in list %lu\n", i);
285c2c66affSColin Finck
286c2c66affSColin Finck /* Break out of this loop and try the next list */
287c2c66affSColin Finck break;
288c2c66affSColin Finck }
289c2c66affSColin Finck
290c2c66affSColin Finck for (iii = 0; PartialList && iii < PartialList->Count && !Matched; iii++)
291c2c66affSColin Finck {
292b82bf8ceSTimo Kreuzer /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
293b82bf8ceSTimo Kreuzer but only one is allowed and it must be the last one in the list! */
294c2c66affSColin Finck PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc = &PartialList->PartialDescriptors[iii];
295c2c66affSColin Finck
296c2c66affSColin Finck /* First check types */
297c2c66affSColin Finck if (IoDesc->Type != CmDesc->Type)
298c2c66affSColin Finck continue;
299c2c66affSColin Finck
300c2c66affSColin Finck switch (IoDesc->Type)
301c2c66affSColin Finck {
302c2c66affSColin Finck case CmResourceTypeInterrupt:
303c2c66affSColin Finck /* Make sure it satisfies our vector range */
304c2c66affSColin Finck if (CmDesc->u.Interrupt.Vector >= IoDesc->u.Interrupt.MinimumVector &&
305c2c66affSColin Finck CmDesc->u.Interrupt.Vector <= IoDesc->u.Interrupt.MaximumVector)
306c2c66affSColin Finck {
307c2c66affSColin Finck /* Found it */
308c2c66affSColin Finck Matched = TRUE;
309c2c66affSColin Finck }
310c2c66affSColin Finck else
311c2c66affSColin Finck {
312c2c66affSColin Finck DPRINT("Interrupt - Not a match! 0x%x not inside 0x%x to 0x%x\n",
313c2c66affSColin Finck CmDesc->u.Interrupt.Vector,
314c2c66affSColin Finck IoDesc->u.Interrupt.MinimumVector,
315c2c66affSColin Finck IoDesc->u.Interrupt.MaximumVector);
316c2c66affSColin Finck }
317c2c66affSColin Finck break;
318c2c66affSColin Finck
319c2c66affSColin Finck case CmResourceTypeMemory:
320c2c66affSColin Finck case CmResourceTypePort:
321c2c66affSColin Finck /* Make sure the length matches and it satisfies our address range */
322c2c66affSColin Finck if (CmDesc->u.Memory.Length == IoDesc->u.Memory.Length &&
323c2c66affSColin Finck (ULONGLONG)CmDesc->u.Memory.Start.QuadPart >= (ULONGLONG)IoDesc->u.Memory.MinimumAddress.QuadPart &&
324c2c66affSColin Finck (ULONGLONG)CmDesc->u.Memory.Start.QuadPart + CmDesc->u.Memory.Length - 1 <= (ULONGLONG)IoDesc->u.Memory.MaximumAddress.QuadPart)
325c2c66affSColin Finck {
326c2c66affSColin Finck /* Found it */
327c2c66affSColin Finck Matched = TRUE;
328c2c66affSColin Finck }
329c2c66affSColin Finck else
330c2c66affSColin Finck {
331c2c66affSColin Finck DPRINT("Memory/Port - Not a match! 0x%I64x with length 0x%x not inside 0x%I64x to 0x%I64x with length 0x%x\n",
332c2c66affSColin Finck CmDesc->u.Memory.Start.QuadPart,
333c2c66affSColin Finck CmDesc->u.Memory.Length,
334c2c66affSColin Finck IoDesc->u.Memory.MinimumAddress.QuadPart,
335c2c66affSColin Finck IoDesc->u.Memory.MaximumAddress.QuadPart,
336c2c66affSColin Finck IoDesc->u.Memory.Length);
337c2c66affSColin Finck }
338c2c66affSColin Finck break;
339c2c66affSColin Finck
340c2c66affSColin Finck case CmResourceTypeBusNumber:
341c2c66affSColin Finck /* Make sure the length matches and it satisfies our bus number range */
342c2c66affSColin Finck if (CmDesc->u.BusNumber.Length == IoDesc->u.BusNumber.Length &&
343c2c66affSColin Finck CmDesc->u.BusNumber.Start >= IoDesc->u.BusNumber.MinBusNumber &&
344c2c66affSColin Finck CmDesc->u.BusNumber.Start + CmDesc->u.BusNumber.Length - 1 <= IoDesc->u.BusNumber.MaxBusNumber)
345c2c66affSColin Finck {
346c2c66affSColin Finck /* Found it */
347c2c66affSColin Finck Matched = TRUE;
348c2c66affSColin Finck }
349c2c66affSColin Finck else
350c2c66affSColin Finck {
351c2c66affSColin Finck DPRINT("Bus Number - Not a match! 0x%x with length 0x%x not inside 0x%x to 0x%x with length 0x%x\n",
352c2c66affSColin Finck CmDesc->u.BusNumber.Start,
353c2c66affSColin Finck CmDesc->u.BusNumber.Length,
354c2c66affSColin Finck IoDesc->u.BusNumber.MinBusNumber,
355c2c66affSColin Finck IoDesc->u.BusNumber.MaxBusNumber,
356c2c66affSColin Finck IoDesc->u.BusNumber.Length);
357c2c66affSColin Finck }
358c2c66affSColin Finck break;
359c2c66affSColin Finck
360c2c66affSColin Finck case CmResourceTypeDma:
361c2c66affSColin Finck /* Make sure it fits in our channel range */
362c2c66affSColin Finck if (CmDesc->u.Dma.Channel >= IoDesc->u.Dma.MinimumChannel &&
363c2c66affSColin Finck CmDesc->u.Dma.Channel <= IoDesc->u.Dma.MaximumChannel)
364c2c66affSColin Finck {
365c2c66affSColin Finck /* Found it */
366c2c66affSColin Finck Matched = TRUE;
367c2c66affSColin Finck }
368c2c66affSColin Finck else
369c2c66affSColin Finck {
370c2c66affSColin Finck DPRINT("DMA - Not a match! 0x%x not inside 0x%x to 0x%x\n",
371c2c66affSColin Finck CmDesc->u.Dma.Channel,
372c2c66affSColin Finck IoDesc->u.Dma.MinimumChannel,
373c2c66affSColin Finck IoDesc->u.Dma.MaximumChannel);
374c2c66affSColin Finck }
375c2c66affSColin Finck break;
376c2c66affSColin Finck
377c2c66affSColin Finck default:
378c2c66affSColin Finck /* Other stuff is fine */
379c2c66affSColin Finck Matched = TRUE;
380c2c66affSColin Finck break;
381c2c66affSColin Finck }
382c2c66affSColin Finck }
383c2c66affSColin Finck
384c2c66affSColin Finck /* Check if we found a matching descriptor */
385c2c66affSColin Finck if (!Matched)
386c2c66affSColin Finck {
387c2c66affSColin Finck PCM_RESOURCE_LIST NewList;
388c2c66affSColin Finck CM_PARTIAL_RESOURCE_DESCRIPTOR NewDesc;
389c2c66affSColin Finck PCM_PARTIAL_RESOURCE_DESCRIPTOR DescPtr;
390c2c66affSColin Finck BOOLEAN FoundResource = TRUE;
391c2c66affSColin Finck
392c2c66affSColin Finck /* Setup the new CM descriptor */
393c2c66affSColin Finck NewDesc.Type = IoDesc->Type;
394c2c66affSColin Finck NewDesc.Flags = IoDesc->Flags;
395c2c66affSColin Finck NewDesc.ShareDisposition = IoDesc->ShareDisposition;
396c2c66affSColin Finck
397c2c66affSColin Finck /* Let'se see if we can find a resource to satisfy this */
398c2c66affSColin Finck switch (IoDesc->Type)
399c2c66affSColin Finck {
400c2c66affSColin Finck case CmResourceTypeInterrupt:
401c2c66affSColin Finck /* Find an available interrupt */
402c2c66affSColin Finck if (!IopFindInterruptResource(IoDesc, &NewDesc))
403c2c66affSColin Finck {
404c2c66affSColin Finck DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
405c2c66affSColin Finck IoDesc->u.Interrupt.MinimumVector, IoDesc->u.Interrupt.MaximumVector);
406c2c66affSColin Finck
407c2c66affSColin Finck FoundResource = FALSE;
408c2c66affSColin Finck }
409c2c66affSColin Finck break;
410c2c66affSColin Finck
411c2c66affSColin Finck case CmResourceTypePort:
412c2c66affSColin Finck /* Find an available port range */
413c2c66affSColin Finck if (!IopFindPortResource(IoDesc, &NewDesc))
414c2c66affSColin Finck {
415c2c66affSColin Finck DPRINT1("Failed to find an available port resource (0x%I64x to 0x%I64x length: 0x%x)\n",
416c2c66affSColin Finck IoDesc->u.Port.MinimumAddress.QuadPart, IoDesc->u.Port.MaximumAddress.QuadPart,
417c2c66affSColin Finck IoDesc->u.Port.Length);
418c2c66affSColin Finck
419c2c66affSColin Finck FoundResource = FALSE;
420c2c66affSColin Finck }
421c2c66affSColin Finck break;
422c2c66affSColin Finck
423c2c66affSColin Finck case CmResourceTypeMemory:
424c2c66affSColin Finck /* Find an available memory range */
425c2c66affSColin Finck if (!IopFindMemoryResource(IoDesc, &NewDesc))
426c2c66affSColin Finck {
427c2c66affSColin Finck DPRINT1("Failed to find an available memory resource (0x%I64x to 0x%I64x length: 0x%x)\n",
428c2c66affSColin Finck IoDesc->u.Memory.MinimumAddress.QuadPart, IoDesc->u.Memory.MaximumAddress.QuadPart,
429c2c66affSColin Finck IoDesc->u.Memory.Length);
430c2c66affSColin Finck
431c2c66affSColin Finck FoundResource = FALSE;
432c2c66affSColin Finck }
433c2c66affSColin Finck break;
434c2c66affSColin Finck
435c2c66affSColin Finck case CmResourceTypeBusNumber:
436c2c66affSColin Finck /* Find an available bus address range */
437c2c66affSColin Finck if (!IopFindBusNumberResource(IoDesc, &NewDesc))
438c2c66affSColin Finck {
439c2c66affSColin Finck DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
440c2c66affSColin Finck IoDesc->u.BusNumber.MinBusNumber, IoDesc->u.BusNumber.MaxBusNumber,
441c2c66affSColin Finck IoDesc->u.BusNumber.Length);
442c2c66affSColin Finck
443c2c66affSColin Finck FoundResource = FALSE;
444c2c66affSColin Finck }
445c2c66affSColin Finck break;
446c2c66affSColin Finck
447c2c66affSColin Finck case CmResourceTypeDma:
448c2c66affSColin Finck /* Find an available DMA channel */
449c2c66affSColin Finck if (!IopFindDmaResource(IoDesc, &NewDesc))
450c2c66affSColin Finck {
451c2c66affSColin Finck DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
452c2c66affSColin Finck IoDesc->u.Dma.MinimumChannel, IoDesc->u.Dma.MaximumChannel);
453c2c66affSColin Finck
454c2c66affSColin Finck FoundResource = FALSE;
455c2c66affSColin Finck }
456c2c66affSColin Finck break;
457c2c66affSColin Finck
458c2c66affSColin Finck default:
459c2c66affSColin Finck DPRINT1("Unsupported resource type: %x\n", IoDesc->Type);
460c2c66affSColin Finck FoundResource = FALSE;
461c2c66affSColin Finck break;
462c2c66affSColin Finck }
463c2c66affSColin Finck
464c2c66affSColin Finck /* Check if it's missing and required */
465c2c66affSColin Finck if (!FoundResource && IoDesc->Option == 0)
466c2c66affSColin Finck {
467c2c66affSColin Finck /* Break out of this loop and try the next list */
468c2c66affSColin Finck DPRINT1("Unable to satisfy required resource in list %lu\n", i);
469c2c66affSColin Finck break;
470c2c66affSColin Finck }
471c2c66affSColin Finck else if (!FoundResource)
472c2c66affSColin Finck {
473c2c66affSColin Finck /* Try an alternate for this preferred descriptor */
474c2c66affSColin Finck AlternateRequired = TRUE;
475c2c66affSColin Finck continue;
476c2c66affSColin Finck }
477c2c66affSColin Finck else
478c2c66affSColin Finck {
479c2c66affSColin Finck /* Move on to the next preferred or required descriptor after this one */
480c2c66affSColin Finck AlternateRequired = FALSE;
481c2c66affSColin Finck }
482c2c66affSColin Finck
483c2c66affSColin Finck /* Figure out what we need */
484c2c66affSColin Finck if (PartialList == NULL)
485c2c66affSColin Finck {
486c2c66affSColin Finck /* We need a new list */
487c2c66affSColin Finck NewList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST));
488c2c66affSColin Finck if (!NewList)
489c2c66affSColin Finck return STATUS_NO_MEMORY;
490c2c66affSColin Finck
491c2c66affSColin Finck /* Set it up */
492c2c66affSColin Finck NewList->Count = 1;
493c2c66affSColin Finck NewList->List[0].InterfaceType = RequirementsList->InterfaceType;
494c2c66affSColin Finck NewList->List[0].BusNumber = RequirementsList->BusNumber;
495c2c66affSColin Finck NewList->List[0].PartialResourceList.Version = 1;
496c2c66affSColin Finck NewList->List[0].PartialResourceList.Revision = 1;
497c2c66affSColin Finck NewList->List[0].PartialResourceList.Count = 1;
498c2c66affSColin Finck
499c2c66affSColin Finck /* Set our pointer */
500c2c66affSColin Finck DescPtr = &NewList->List[0].PartialResourceList.PartialDescriptors[0];
501c2c66affSColin Finck }
502c2c66affSColin Finck else
503c2c66affSColin Finck {
504c2c66affSColin Finck /* Allocate the new larger list */
505c2c66affSColin Finck NewList = ExAllocatePool(PagedPool, PnpDetermineResourceListSize(*ResourceList) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
506c2c66affSColin Finck if (!NewList)
507c2c66affSColin Finck return STATUS_NO_MEMORY;
508c2c66affSColin Finck
509c2c66affSColin Finck /* Copy the old stuff back */
510c2c66affSColin Finck RtlCopyMemory(NewList, *ResourceList, PnpDetermineResourceListSize(*ResourceList));
511c2c66affSColin Finck
512c2c66affSColin Finck /* Set our pointer */
513c2c66affSColin Finck DescPtr = &NewList->List[0].PartialResourceList.PartialDescriptors[NewList->List[0].PartialResourceList.Count];
514c2c66affSColin Finck
515c2c66affSColin Finck /* Increment the descriptor count */
516c2c66affSColin Finck NewList->List[0].PartialResourceList.Count++;
517c2c66affSColin Finck
518c2c66affSColin Finck /* Free the old list */
519c2c66affSColin Finck ExFreePool(*ResourceList);
520c2c66affSColin Finck }
521c2c66affSColin Finck
522c2c66affSColin Finck /* Copy the descriptor in */
523c2c66affSColin Finck *DescPtr = NewDesc;
524c2c66affSColin Finck
525c2c66affSColin Finck /* Store the new list */
526c2c66affSColin Finck *ResourceList = NewList;
527c2c66affSColin Finck }
528c2c66affSColin Finck }
529c2c66affSColin Finck
530c2c66affSColin Finck /* Check if we need an alternate with no resources left */
531c2c66affSColin Finck if (AlternateRequired)
532c2c66affSColin Finck {
533c2c66affSColin Finck DPRINT1("Unable to satisfy preferred resource or alternates in list %lu\n", i);
534c2c66affSColin Finck
535c2c66affSColin Finck /* Try the next alternate list */
536c2c66affSColin Finck continue;
537c2c66affSColin Finck }
538c2c66affSColin Finck
539c2c66affSColin Finck /* We're done because we satisfied one of the alternate lists */
540c2c66affSColin Finck return STATUS_SUCCESS;
541c2c66affSColin Finck }
542c2c66affSColin Finck
543c2c66affSColin Finck /* We ran out of alternates */
544c2c66affSColin Finck DPRINT1("Out of alternate lists!\n");
545c2c66affSColin Finck
546c2c66affSColin Finck /* Free the list */
547c2c66affSColin Finck if (*ResourceList)
548c2c66affSColin Finck {
549c2c66affSColin Finck ExFreePool(*ResourceList);
550c2c66affSColin Finck *ResourceList = NULL;
551c2c66affSColin Finck }
552c2c66affSColin Finck
553c2c66affSColin Finck /* Fail */
554c2c66affSColin Finck return STATUS_CONFLICTING_ADDRESSES;
555c2c66affSColin Finck }
556c2c66affSColin Finck
557c2c66affSColin Finck static
558c2c66affSColin Finck BOOLEAN
IopCheckResourceDescriptor(IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc,IN PCM_RESOURCE_LIST ResourceList,IN BOOLEAN Silent,OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)559c2c66affSColin Finck IopCheckResourceDescriptor(
560c2c66affSColin Finck IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc,
561c2c66affSColin Finck IN PCM_RESOURCE_LIST ResourceList,
562c2c66affSColin Finck IN BOOLEAN Silent,
563c2c66affSColin Finck OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
564c2c66affSColin Finck {
565c2c66affSColin Finck ULONG i, ii;
566c2c66affSColin Finck BOOLEAN Result = FALSE;
567b82bf8ceSTimo Kreuzer PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
568c2c66affSColin Finck
569b82bf8ceSTimo Kreuzer FullDescriptor = &ResourceList->List[0];
570c2c66affSColin Finck for (i = 0; i < ResourceList->Count; i++)
571c2c66affSColin Finck {
572b82bf8ceSTimo Kreuzer PCM_PARTIAL_RESOURCE_LIST ResList = &FullDescriptor->PartialResourceList;
573b82bf8ceSTimo Kreuzer FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor);
574b82bf8ceSTimo Kreuzer
575c2c66affSColin Finck for (ii = 0; ii < ResList->Count; ii++)
576c2c66affSColin Finck {
577b82bf8ceSTimo Kreuzer /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
578b82bf8ceSTimo Kreuzer but only one is allowed and it must be the last one in the list! */
579c2c66affSColin Finck PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2 = &ResList->PartialDescriptors[ii];
580c2c66affSColin Finck
581c2c66affSColin Finck /* We don't care about shared resources */
582c2c66affSColin Finck if (ResDesc->ShareDisposition == CmResourceShareShared &&
583c2c66affSColin Finck ResDesc2->ShareDisposition == CmResourceShareShared)
584c2c66affSColin Finck continue;
585c2c66affSColin Finck
586c2c66affSColin Finck /* Make sure we're comparing the same types */
587c2c66affSColin Finck if (ResDesc->Type != ResDesc2->Type)
588c2c66affSColin Finck continue;
589c2c66affSColin Finck
590c2c66affSColin Finck switch (ResDesc->Type)
591c2c66affSColin Finck {
592c2c66affSColin Finck case CmResourceTypeMemory:
59343f1d916SVictor Perevertkin {
59443f1d916SVictor Perevertkin /* NOTE: ranges are in a form [x1;x2) */
59543f1d916SVictor Perevertkin UINT64 rStart = (UINT64)ResDesc->u.Memory.Start.QuadPart;
59643f1d916SVictor Perevertkin UINT64 rEnd = (UINT64)ResDesc->u.Memory.Start.QuadPart
59743f1d916SVictor Perevertkin + ResDesc->u.Memory.Length;
59843f1d916SVictor Perevertkin UINT64 r2Start = (UINT64)ResDesc2->u.Memory.Start.QuadPart;
59943f1d916SVictor Perevertkin UINT64 r2End = (UINT64)ResDesc2->u.Memory.Start.QuadPart
60043f1d916SVictor Perevertkin + ResDesc2->u.Memory.Length;
60143f1d916SVictor Perevertkin
60243f1d916SVictor Perevertkin if (rStart < r2End && r2Start < rEnd)
603c2c66affSColin Finck {
604c2c66affSColin Finck if (!Silent)
605c2c66affSColin Finck {
606c2c66affSColin Finck DPRINT1("Resource conflict: Memory (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
60743f1d916SVictor Perevertkin rStart, rEnd, r2Start, r2End);
608c2c66affSColin Finck }
609c2c66affSColin Finck
610c2c66affSColin Finck Result = TRUE;
611c2c66affSColin Finck
612c2c66affSColin Finck goto ByeBye;
613c2c66affSColin Finck }
614c2c66affSColin Finck break;
61543f1d916SVictor Perevertkin }
616c2c66affSColin Finck case CmResourceTypePort:
61743f1d916SVictor Perevertkin {
61843f1d916SVictor Perevertkin /* NOTE: ranges are in a form [x1;x2) */
61943f1d916SVictor Perevertkin UINT64 rStart = (UINT64)ResDesc->u.Port.Start.QuadPart;
62043f1d916SVictor Perevertkin UINT64 rEnd = (UINT64)ResDesc->u.Port.Start.QuadPart
62143f1d916SVictor Perevertkin + ResDesc->u.Port.Length;
62243f1d916SVictor Perevertkin UINT64 r2Start = (UINT64)ResDesc2->u.Port.Start.QuadPart;
62343f1d916SVictor Perevertkin UINT64 r2End = (UINT64)ResDesc2->u.Port.Start.QuadPart
62443f1d916SVictor Perevertkin + ResDesc2->u.Port.Length;
62543f1d916SVictor Perevertkin
62643f1d916SVictor Perevertkin if (rStart < r2End && r2Start < rEnd)
627c2c66affSColin Finck {
628c2c66affSColin Finck if (!Silent)
629c2c66affSColin Finck {
630c2c66affSColin Finck DPRINT1("Resource conflict: Port (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
63143f1d916SVictor Perevertkin rStart, rEnd, r2Start, r2End);
632c2c66affSColin Finck }
633c2c66affSColin Finck
634c2c66affSColin Finck Result = TRUE;
635c2c66affSColin Finck
636c2c66affSColin Finck goto ByeBye;
637c2c66affSColin Finck }
638c2c66affSColin Finck break;
63943f1d916SVictor Perevertkin }
640c2c66affSColin Finck case CmResourceTypeInterrupt:
64143f1d916SVictor Perevertkin {
642c2c66affSColin Finck if (ResDesc->u.Interrupt.Vector == ResDesc2->u.Interrupt.Vector)
643c2c66affSColin Finck {
644c2c66affSColin Finck if (!Silent)
645c2c66affSColin Finck {
646c2c66affSColin Finck DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
647c2c66affSColin Finck ResDesc->u.Interrupt.Vector, ResDesc->u.Interrupt.Level,
648c2c66affSColin Finck ResDesc2->u.Interrupt.Vector, ResDesc2->u.Interrupt.Level);
649c2c66affSColin Finck }
650c2c66affSColin Finck
651c2c66affSColin Finck Result = TRUE;
652c2c66affSColin Finck
653c2c66affSColin Finck goto ByeBye;
654c2c66affSColin Finck }
655c2c66affSColin Finck break;
65643f1d916SVictor Perevertkin }
657c2c66affSColin Finck case CmResourceTypeBusNumber:
65843f1d916SVictor Perevertkin {
65943f1d916SVictor Perevertkin /* NOTE: ranges are in a form [x1;x2) */
66043f1d916SVictor Perevertkin UINT32 rStart = ResDesc->u.BusNumber.Start;
66143f1d916SVictor Perevertkin UINT32 rEnd = ResDesc->u.BusNumber.Start + ResDesc->u.BusNumber.Length;
66243f1d916SVictor Perevertkin UINT32 r2Start = ResDesc2->u.BusNumber.Start;
66343f1d916SVictor Perevertkin UINT32 r2End = ResDesc2->u.BusNumber.Start + ResDesc2->u.BusNumber.Length;
66443f1d916SVictor Perevertkin
66543f1d916SVictor Perevertkin if (rStart < r2End && r2Start < rEnd)
666c2c66affSColin Finck {
667c2c66affSColin Finck if (!Silent)
668c2c66affSColin Finck {
669c2c66affSColin Finck DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
67043f1d916SVictor Perevertkin rStart, rEnd, r2Start, r2End);
671c2c66affSColin Finck }
672c2c66affSColin Finck
673c2c66affSColin Finck Result = TRUE;
674c2c66affSColin Finck
675c2c66affSColin Finck goto ByeBye;
676c2c66affSColin Finck }
677c2c66affSColin Finck break;
67843f1d916SVictor Perevertkin }
679c2c66affSColin Finck case CmResourceTypeDma:
68043f1d916SVictor Perevertkin {
681c2c66affSColin Finck if (ResDesc->u.Dma.Channel == ResDesc2->u.Dma.Channel)
682c2c66affSColin Finck {
683c2c66affSColin Finck if (!Silent)
684c2c66affSColin Finck {
685c2c66affSColin Finck DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
686c2c66affSColin Finck ResDesc->u.Dma.Channel, ResDesc->u.Dma.Port,
687c2c66affSColin Finck ResDesc2->u.Dma.Channel, ResDesc2->u.Dma.Port);
688c2c66affSColin Finck }
689c2c66affSColin Finck
690c2c66affSColin Finck Result = TRUE;
691c2c66affSColin Finck
692c2c66affSColin Finck goto ByeBye;
693c2c66affSColin Finck }
694c2c66affSColin Finck break;
695c2c66affSColin Finck }
696c2c66affSColin Finck }
697c2c66affSColin Finck }
69843f1d916SVictor Perevertkin }
699c2c66affSColin Finck
700c2c66affSColin Finck ByeBye:
701c2c66affSColin Finck
702c2c66affSColin Finck if (Result && ConflictingDescriptor)
703c2c66affSColin Finck {
704c2c66affSColin Finck RtlCopyMemory(ConflictingDescriptor,
705c2c66affSColin Finck ResDesc,
706c2c66affSColin Finck sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
707c2c66affSColin Finck }
708c2c66affSColin Finck
709b82bf8ceSTimo Kreuzer // Hacked, because after fixing resource list parsing
710b82bf8ceSTimo Kreuzer // we actually detect resource conflicts
711b82bf8ceSTimo Kreuzer return Silent ? Result : FALSE; // Result;
712c2c66affSColin Finck }
713c2c66affSColin Finck
714c2c66affSColin Finck static
715c2c66affSColin Finck NTSTATUS
IopUpdateControlKeyWithResources(IN PDEVICE_NODE DeviceNode)7169538c3ccSEric Kohl IopUpdateControlKeyWithResources(
7179538c3ccSEric Kohl IN PDEVICE_NODE DeviceNode)
718c2c66affSColin Finck {
719c2c66affSColin Finck UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT);
720c2c66affSColin Finck UNICODE_STRING Control = RTL_CONSTANT_STRING(L"Control");
721c2c66affSColin Finck UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"AllocConfig");
722c2c66affSColin Finck HANDLE EnumKey, InstanceKey, ControlKey;
723c2c66affSColin Finck NTSTATUS Status;
724c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes;
725c2c66affSColin Finck
726c2c66affSColin Finck /* Open the Enum key */
727c2c66affSColin Finck Status = IopOpenRegistryKeyEx(&EnumKey, NULL, &EnumRoot, KEY_ENUMERATE_SUB_KEYS);
728c2c66affSColin Finck if (!NT_SUCCESS(Status))
729c2c66affSColin Finck return Status;
730c2c66affSColin Finck
731c2c66affSColin Finck /* Open the instance key (eg. Root\PNP0A03) */
732c2c66affSColin Finck Status = IopOpenRegistryKeyEx(&InstanceKey, EnumKey, &DeviceNode->InstancePath, KEY_ENUMERATE_SUB_KEYS);
733c2c66affSColin Finck ZwClose(EnumKey);
734c2c66affSColin Finck
735c2c66affSColin Finck if (!NT_SUCCESS(Status))
736c2c66affSColin Finck return Status;
737c2c66affSColin Finck
738c2c66affSColin Finck /* Create/Open the Control key */
739c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes,
740c2c66affSColin Finck &Control,
741c2c66affSColin Finck OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
742c2c66affSColin Finck InstanceKey,
743c2c66affSColin Finck NULL);
744c2c66affSColin Finck Status = ZwCreateKey(&ControlKey,
745c2c66affSColin Finck KEY_SET_VALUE,
746c2c66affSColin Finck &ObjectAttributes,
747c2c66affSColin Finck 0,
748c2c66affSColin Finck NULL,
749c2c66affSColin Finck REG_OPTION_VOLATILE,
750c2c66affSColin Finck NULL);
751c2c66affSColin Finck ZwClose(InstanceKey);
752c2c66affSColin Finck
753c2c66affSColin Finck if (!NT_SUCCESS(Status))
754c2c66affSColin Finck return Status;
755c2c66affSColin Finck
756c2c66affSColin Finck /* Write the resource list */
757c2c66affSColin Finck Status = ZwSetValueKey(ControlKey,
758c2c66affSColin Finck &ValueName,
759c2c66affSColin Finck 0,
760c2c66affSColin Finck REG_RESOURCE_LIST,
761c2c66affSColin Finck DeviceNode->ResourceList,
762c2c66affSColin Finck PnpDetermineResourceListSize(DeviceNode->ResourceList));
763c2c66affSColin Finck ZwClose(ControlKey);
764c2c66affSColin Finck
765c2c66affSColin Finck if (!NT_SUCCESS(Status))
766c2c66affSColin Finck return Status;
767c2c66affSColin Finck
768c2c66affSColin Finck return STATUS_SUCCESS;
769c2c66affSColin Finck }
770c2c66affSColin Finck
771c2c66affSColin Finck static
772c2c66affSColin Finck NTSTATUS
IopFilterResourceRequirements(IN PDEVICE_NODE DeviceNode)7739538c3ccSEric Kohl IopFilterResourceRequirements(
7749538c3ccSEric Kohl IN PDEVICE_NODE DeviceNode)
775c2c66affSColin Finck {
776c2c66affSColin Finck IO_STACK_LOCATION Stack;
777c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock;
778c2c66affSColin Finck NTSTATUS Status;
779c2c66affSColin Finck
780c2c66affSColin Finck DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
781c2c66affSColin Finck
782c2c66affSColin Finck Stack.Parameters.FilterResourceRequirements.IoResourceRequirementList = DeviceNode->ResourceRequirements;
7839538c3ccSEric Kohl Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
784c2c66affSColin Finck &IoStatusBlock,
785c2c66affSColin Finck IRP_MN_FILTER_RESOURCE_REQUIREMENTS,
786c2c66affSColin Finck &Stack);
787c2c66affSColin Finck if (!NT_SUCCESS(Status) && Status != STATUS_NOT_SUPPORTED)
788c2c66affSColin Finck {
789c2c66affSColin Finck DPRINT1("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
790c2c66affSColin Finck return Status;
791c2c66affSColin Finck }
792c2c66affSColin Finck else if (NT_SUCCESS(Status) && IoStatusBlock.Information)
793c2c66affSColin Finck {
794c2c66affSColin Finck DeviceNode->ResourceRequirements = (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
795c2c66affSColin Finck }
796c2c66affSColin Finck
797c2c66affSColin Finck return STATUS_SUCCESS;
798c2c66affSColin Finck }
799c2c66affSColin Finck
800c2c66affSColin Finck
801c2c66affSColin Finck NTSTATUS
IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode,PWCHAR Level1Key,PWCHAR Level2Key)8029538c3ccSEric Kohl IopUpdateResourceMap(
8039538c3ccSEric Kohl IN PDEVICE_NODE DeviceNode,
8049538c3ccSEric Kohl PWCHAR Level1Key,
8059538c3ccSEric Kohl PWCHAR Level2Key)
806c2c66affSColin Finck {
807c2c66affSColin Finck NTSTATUS Status;
808c2c66affSColin Finck ULONG Disposition;
809c2c66affSColin Finck HANDLE PnpMgrLevel1, PnpMgrLevel2, ResourceMapKey;
810c2c66affSColin Finck UNICODE_STRING KeyName;
811c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes;
812c2c66affSColin Finck
813c2c66affSColin Finck RtlInitUnicodeString(&KeyName,
814c2c66affSColin Finck L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
815c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes,
816c2c66affSColin Finck &KeyName,
817c2c66affSColin Finck OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_KERNEL_HANDLE,
818c2c66affSColin Finck NULL,
819c2c66affSColin Finck NULL);
820c2c66affSColin Finck Status = ZwCreateKey(&ResourceMapKey,
821c2c66affSColin Finck KEY_ALL_ACCESS,
822c2c66affSColin Finck &ObjectAttributes,
823c2c66affSColin Finck 0,
824c2c66affSColin Finck NULL,
825c2c66affSColin Finck REG_OPTION_VOLATILE,
826c2c66affSColin Finck &Disposition);
827c2c66affSColin Finck if (!NT_SUCCESS(Status))
828c2c66affSColin Finck return Status;
829c2c66affSColin Finck
830c2c66affSColin Finck RtlInitUnicodeString(&KeyName, Level1Key);
831c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes,
832c2c66affSColin Finck &KeyName,
833c2c66affSColin Finck OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_KERNEL_HANDLE,
834c2c66affSColin Finck ResourceMapKey,
835c2c66affSColin Finck NULL);
836c2c66affSColin Finck Status = ZwCreateKey(&PnpMgrLevel1,
837c2c66affSColin Finck KEY_ALL_ACCESS,
838c2c66affSColin Finck &ObjectAttributes,
839c2c66affSColin Finck 0,
840c2c66affSColin Finck NULL,
841c2c66affSColin Finck REG_OPTION_VOLATILE,
842c2c66affSColin Finck &Disposition);
843c2c66affSColin Finck ZwClose(ResourceMapKey);
844c2c66affSColin Finck if (!NT_SUCCESS(Status))
845c2c66affSColin Finck return Status;
846c2c66affSColin Finck
847c2c66affSColin Finck RtlInitUnicodeString(&KeyName, Level2Key);
848c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes,
849c2c66affSColin Finck &KeyName,
850c2c66affSColin Finck OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_KERNEL_HANDLE,
851c2c66affSColin Finck PnpMgrLevel1,
852c2c66affSColin Finck NULL);
853c2c66affSColin Finck Status = ZwCreateKey(&PnpMgrLevel2,
854c2c66affSColin Finck KEY_ALL_ACCESS,
855c2c66affSColin Finck &ObjectAttributes,
856c2c66affSColin Finck 0,
857c2c66affSColin Finck NULL,
858c2c66affSColin Finck REG_OPTION_VOLATILE,
859c2c66affSColin Finck &Disposition);
860c2c66affSColin Finck ZwClose(PnpMgrLevel1);
861c2c66affSColin Finck if (!NT_SUCCESS(Status))
862c2c66affSColin Finck return Status;
863c2c66affSColin Finck
864c2c66affSColin Finck if (DeviceNode->ResourceList)
865c2c66affSColin Finck {
866c2c66affSColin Finck UNICODE_STRING NameU;
867c2c66affSColin Finck UNICODE_STRING RawSuffix, TranslatedSuffix;
868c2c66affSColin Finck ULONG OldLength = 0;
869c2c66affSColin Finck
870c2c66affSColin Finck ASSERT(DeviceNode->ResourceListTranslated);
871c2c66affSColin Finck
872c2c66affSColin Finck RtlInitUnicodeString(&TranslatedSuffix, L".Translated");
873c2c66affSColin Finck RtlInitUnicodeString(&RawSuffix, L".Raw");
874c2c66affSColin Finck
875c2c66affSColin Finck Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
876c2c66affSColin Finck DevicePropertyPhysicalDeviceObjectName,
877c2c66affSColin Finck 0,
878c2c66affSColin Finck NULL,
879c2c66affSColin Finck &OldLength);
880c2c66affSColin Finck if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
881c2c66affSColin Finck {
882c2c66affSColin Finck ASSERT(OldLength);
883c2c66affSColin Finck
884c2c66affSColin Finck NameU.Buffer = ExAllocatePool(PagedPool, OldLength + TranslatedSuffix.Length);
885c2c66affSColin Finck if (!NameU.Buffer)
886c2c66affSColin Finck {
887c2c66affSColin Finck ZwClose(PnpMgrLevel2);
888c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
889c2c66affSColin Finck }
890c2c66affSColin Finck
891c2c66affSColin Finck NameU.Length = 0;
892c2c66affSColin Finck NameU.MaximumLength = (USHORT)OldLength + TranslatedSuffix.Length;
893c2c66affSColin Finck
894c2c66affSColin Finck Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
895c2c66affSColin Finck DevicePropertyPhysicalDeviceObjectName,
896c2c66affSColin Finck NameU.MaximumLength,
897c2c66affSColin Finck NameU.Buffer,
898c2c66affSColin Finck &OldLength);
899c2c66affSColin Finck if (!NT_SUCCESS(Status))
900c2c66affSColin Finck {
901c2c66affSColin Finck ZwClose(PnpMgrLevel2);
902c2c66affSColin Finck ExFreePool(NameU.Buffer);
903c2c66affSColin Finck return Status;
904c2c66affSColin Finck }
905c2c66affSColin Finck }
906c2c66affSColin Finck else if (!NT_SUCCESS(Status))
907c2c66affSColin Finck {
908c2c66affSColin Finck /* Some failure */
909c2c66affSColin Finck ZwClose(PnpMgrLevel2);
910c2c66affSColin Finck return Status;
911c2c66affSColin Finck }
912c2c66affSColin Finck else
913c2c66affSColin Finck {
914c2c66affSColin Finck /* This should never happen */
915c2c66affSColin Finck ASSERT(FALSE);
916c2c66affSColin Finck }
917c2c66affSColin Finck
918a86c3794SHervé Poussineau NameU.Length = (USHORT)OldLength - sizeof(UNICODE_NULL); /* Remove final NULL */
919c2c66affSColin Finck
920c2c66affSColin Finck RtlAppendUnicodeStringToString(&NameU, &RawSuffix);
921c2c66affSColin Finck
922c2c66affSColin Finck Status = ZwSetValueKey(PnpMgrLevel2,
923c2c66affSColin Finck &NameU,
924c2c66affSColin Finck 0,
925c2c66affSColin Finck REG_RESOURCE_LIST,
926c2c66affSColin Finck DeviceNode->ResourceList,
927c2c66affSColin Finck PnpDetermineResourceListSize(DeviceNode->ResourceList));
928c2c66affSColin Finck if (!NT_SUCCESS(Status))
929c2c66affSColin Finck {
930c2c66affSColin Finck ZwClose(PnpMgrLevel2);
931c2c66affSColin Finck ExFreePool(NameU.Buffer);
932c2c66affSColin Finck return Status;
933c2c66affSColin Finck }
934c2c66affSColin Finck
935c2c66affSColin Finck /* "Remove" the suffix by setting the length back to what it used to be */
936a86c3794SHervé Poussineau NameU.Length = (USHORT)OldLength - sizeof(UNICODE_NULL); /* Remove final NULL */
937c2c66affSColin Finck
938c2c66affSColin Finck RtlAppendUnicodeStringToString(&NameU, &TranslatedSuffix);
939c2c66affSColin Finck
940c2c66affSColin Finck Status = ZwSetValueKey(PnpMgrLevel2,
941c2c66affSColin Finck &NameU,
942c2c66affSColin Finck 0,
943c2c66affSColin Finck REG_RESOURCE_LIST,
944c2c66affSColin Finck DeviceNode->ResourceListTranslated,
945c2c66affSColin Finck PnpDetermineResourceListSize(DeviceNode->ResourceListTranslated));
946c2c66affSColin Finck ZwClose(PnpMgrLevel2);
947c2c66affSColin Finck ExFreePool(NameU.Buffer);
948c2c66affSColin Finck
949c2c66affSColin Finck if (!NT_SUCCESS(Status))
950c2c66affSColin Finck return Status;
951c2c66affSColin Finck }
952c2c66affSColin Finck else
953c2c66affSColin Finck {
954c2c66affSColin Finck ZwClose(PnpMgrLevel2);
955c2c66affSColin Finck }
956c2c66affSColin Finck
957c2c66affSColin Finck return STATUS_SUCCESS;
958c2c66affSColin Finck }
959c2c66affSColin Finck
960c2c66affSColin Finck NTSTATUS
IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode)9619538c3ccSEric Kohl IopUpdateResourceMapForPnPDevice(
9629538c3ccSEric Kohl IN PDEVICE_NODE DeviceNode)
963c2c66affSColin Finck {
964c2c66affSColin Finck return IopUpdateResourceMap(DeviceNode, L"PnP Manager", L"PnpManager");
965c2c66affSColin Finck }
966c2c66affSColin Finck
967c2c66affSColin Finck static
968c2c66affSColin Finck NTSTATUS
IopTranslateDeviceResources(IN PDEVICE_NODE DeviceNode)969c2c66affSColin Finck IopTranslateDeviceResources(
970c2c66affSColin Finck IN PDEVICE_NODE DeviceNode)
971c2c66affSColin Finck {
972c2c66affSColin Finck PCM_PARTIAL_RESOURCE_LIST pPartialResourceList;
973c2c66affSColin Finck PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated;
974b82bf8ceSTimo Kreuzer PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
975c2c66affSColin Finck ULONG i, j, ListSize;
976c2c66affSColin Finck NTSTATUS Status;
977c2c66affSColin Finck
978c2c66affSColin Finck if (!DeviceNode->ResourceList)
979c2c66affSColin Finck {
980c2c66affSColin Finck DeviceNode->ResourceListTranslated = NULL;
981c2c66affSColin Finck return STATUS_SUCCESS;
982c2c66affSColin Finck }
983c2c66affSColin Finck
984c2c66affSColin Finck /* That's easy to translate a resource list. Just copy the
985c2c66affSColin Finck * untranslated one and change few fields in the copy
986c2c66affSColin Finck */
987c2c66affSColin Finck ListSize = PnpDetermineResourceListSize(DeviceNode->ResourceList);
988c2c66affSColin Finck
989c2c66affSColin Finck DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, ListSize);
990c2c66affSColin Finck if (!DeviceNode->ResourceListTranslated)
991c2c66affSColin Finck {
992c2c66affSColin Finck Status = STATUS_NO_MEMORY;
993c2c66affSColin Finck goto cleanup;
994c2c66affSColin Finck }
995c2c66affSColin Finck RtlCopyMemory(DeviceNode->ResourceListTranslated, DeviceNode->ResourceList, ListSize);
996c2c66affSColin Finck
997b82bf8ceSTimo Kreuzer FullDescriptor = &DeviceNode->ResourceList->List[0];
998c2c66affSColin Finck for (i = 0; i < DeviceNode->ResourceList->Count; i++)
999c2c66affSColin Finck {
1000b82bf8ceSTimo Kreuzer pPartialResourceList = &FullDescriptor->PartialResourceList;
1001b82bf8ceSTimo Kreuzer FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor);
1002b82bf8ceSTimo Kreuzer
1003c2c66affSColin Finck for (j = 0; j < pPartialResourceList->Count; j++)
1004c2c66affSColin Finck {
1005b82bf8ceSTimo Kreuzer /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
1006b82bf8ceSTimo Kreuzer but only one is allowed and it must be the last one in the list! */
1007c2c66affSColin Finck DescriptorRaw = &pPartialResourceList->PartialDescriptors[j];
1008b82bf8ceSTimo Kreuzer
1009b82bf8ceSTimo Kreuzer /* Calculate the location of the translated resource descriptor */
1010b82bf8ceSTimo Kreuzer DescriptorTranslated = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)(
1011b82bf8ceSTimo Kreuzer (PUCHAR)DeviceNode->ResourceListTranslated +
1012b82bf8ceSTimo Kreuzer ((PUCHAR)DescriptorRaw - (PUCHAR)DeviceNode->ResourceList));
1013b82bf8ceSTimo Kreuzer
1014c2c66affSColin Finck switch (DescriptorRaw->Type)
1015c2c66affSColin Finck {
1016c2c66affSColin Finck case CmResourceTypePort:
1017c2c66affSColin Finck {
1018c2c66affSColin Finck ULONG AddressSpace = 1; /* IO space */
1019c2c66affSColin Finck if (!HalTranslateBusAddress(
1020c2c66affSColin Finck DeviceNode->ResourceList->List[i].InterfaceType,
1021c2c66affSColin Finck DeviceNode->ResourceList->List[i].BusNumber,
1022c2c66affSColin Finck DescriptorRaw->u.Port.Start,
1023c2c66affSColin Finck &AddressSpace,
1024c2c66affSColin Finck &DescriptorTranslated->u.Port.Start))
1025c2c66affSColin Finck {
1026c2c66affSColin Finck Status = STATUS_UNSUCCESSFUL;
1027c2c66affSColin Finck DPRINT1("Failed to translate port resource (Start: 0x%I64x)\n", DescriptorRaw->u.Port.Start.QuadPart);
1028c2c66affSColin Finck goto cleanup;
1029c2c66affSColin Finck }
1030c2c66affSColin Finck
1031c2c66affSColin Finck if (AddressSpace == 0)
1032c2c66affSColin Finck {
1033c2c66affSColin Finck DPRINT1("Guessed incorrect address space: 1 -> 0\n");
1034c2c66affSColin Finck
1035c2c66affSColin Finck /* FIXME: I think all other CM_RESOURCE_PORT_XXX flags are
1036c2c66affSColin Finck * invalid for this state but I'm not 100% sure */
1037c2c66affSColin Finck DescriptorRaw->Flags =
1038c2c66affSColin Finck DescriptorTranslated->Flags = CM_RESOURCE_PORT_MEMORY;
1039c2c66affSColin Finck }
1040c2c66affSColin Finck break;
1041c2c66affSColin Finck }
1042c2c66affSColin Finck case CmResourceTypeInterrupt:
1043c2c66affSColin Finck {
1044b82bf8ceSTimo Kreuzer KIRQL Irql;
1045c2c66affSColin Finck DescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector(
1046c2c66affSColin Finck DeviceNode->ResourceList->List[i].InterfaceType,
1047c2c66affSColin Finck DeviceNode->ResourceList->List[i].BusNumber,
1048c2c66affSColin Finck DescriptorRaw->u.Interrupt.Level,
1049c2c66affSColin Finck DescriptorRaw->u.Interrupt.Vector,
1050b82bf8ceSTimo Kreuzer &Irql,
1051c2c66affSColin Finck &DescriptorTranslated->u.Interrupt.Affinity);
1052b82bf8ceSTimo Kreuzer DescriptorTranslated->u.Interrupt.Level = Irql;
1053c2c66affSColin Finck if (!DescriptorTranslated->u.Interrupt.Vector)
1054c2c66affSColin Finck {
1055c2c66affSColin Finck Status = STATUS_UNSUCCESSFUL;
1056c2c66affSColin Finck DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw->u.Interrupt.Vector,
1057c2c66affSColin Finck DescriptorRaw->u.Interrupt.Level);
1058c2c66affSColin Finck goto cleanup;
1059c2c66affSColin Finck }
1060c2c66affSColin Finck break;
1061c2c66affSColin Finck }
1062c2c66affSColin Finck case CmResourceTypeMemory:
1063c2c66affSColin Finck {
1064c2c66affSColin Finck ULONG AddressSpace = 0; /* Memory space */
1065c2c66affSColin Finck if (!HalTranslateBusAddress(
1066c2c66affSColin Finck DeviceNode->ResourceList->List[i].InterfaceType,
1067c2c66affSColin Finck DeviceNode->ResourceList->List[i].BusNumber,
1068c2c66affSColin Finck DescriptorRaw->u.Memory.Start,
1069c2c66affSColin Finck &AddressSpace,
1070c2c66affSColin Finck &DescriptorTranslated->u.Memory.Start))
1071c2c66affSColin Finck {
1072c2c66affSColin Finck Status = STATUS_UNSUCCESSFUL;
1073c2c66affSColin Finck DPRINT1("Failed to translate memory resource (Start: 0x%I64x)\n", DescriptorRaw->u.Memory.Start.QuadPart);
1074c2c66affSColin Finck goto cleanup;
1075c2c66affSColin Finck }
1076c2c66affSColin Finck
1077c2c66affSColin Finck if (AddressSpace != 0)
1078c2c66affSColin Finck {
1079c2c66affSColin Finck DPRINT1("Guessed incorrect address space: 0 -> 1\n");
1080c2c66affSColin Finck
1081c2c66affSColin Finck /* This should never happen for memory space */
1082c2c66affSColin Finck ASSERT(FALSE);
1083c2c66affSColin Finck }
1084c2c66affSColin Finck }
1085c2c66affSColin Finck
1086c2c66affSColin Finck case CmResourceTypeDma:
1087c2c66affSColin Finck case CmResourceTypeBusNumber:
1088129e009aSHervé Poussineau case CmResourceTypeDevicePrivate:
1089c2c66affSColin Finck case CmResourceTypeDeviceSpecific:
1090c2c66affSColin Finck /* Nothing to do */
1091c2c66affSColin Finck break;
1092c2c66affSColin Finck default:
1093c2c66affSColin Finck DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw->Type);
1094c2c66affSColin Finck Status = STATUS_NOT_IMPLEMENTED;
1095c2c66affSColin Finck goto cleanup;
1096c2c66affSColin Finck }
1097c2c66affSColin Finck }
1098c2c66affSColin Finck }
1099c2c66affSColin Finck return STATUS_SUCCESS;
1100c2c66affSColin Finck
1101c2c66affSColin Finck cleanup:
1102c2c66affSColin Finck /* Yes! Also delete ResourceList because ResourceList and
1103c2c66affSColin Finck * ResourceListTranslated should be a pair! */
1104c2c66affSColin Finck ExFreePool(DeviceNode->ResourceList);
1105c2c66affSColin Finck DeviceNode->ResourceList = NULL;
1106c2c66affSColin Finck if (DeviceNode->ResourceListTranslated)
1107c2c66affSColin Finck {
1108c2c66affSColin Finck ExFreePool(DeviceNode->ResourceListTranslated);
1109c2c66affSColin Finck DeviceNode->ResourceList = NULL;
1110c2c66affSColin Finck }
1111c2c66affSColin Finck return Status;
1112c2c66affSColin Finck }
1113c2c66affSColin Finck
1114c2c66affSColin Finck NTSTATUS
1115c2c66affSColin Finck NTAPI
IopAssignDeviceResources(IN PDEVICE_NODE DeviceNode)1116c2c66affSColin Finck IopAssignDeviceResources(
1117c2c66affSColin Finck IN PDEVICE_NODE DeviceNode)
1118c2c66affSColin Finck {
1119c2c66affSColin Finck NTSTATUS Status;
1120c2c66affSColin Finck ULONG ListSize;
1121c2c66affSColin Finck
1122c2c66affSColin Finck Status = IopFilterResourceRequirements(DeviceNode);
1123c2c66affSColin Finck if (!NT_SUCCESS(Status))
1124c2c66affSColin Finck goto ByeBye;
1125c2c66affSColin Finck
1126c2c66affSColin Finck if (!DeviceNode->BootResources && !DeviceNode->ResourceRequirements)
1127c2c66affSColin Finck {
1128c2c66affSColin Finck /* No resource needed for this device */
1129c2c66affSColin Finck DeviceNode->ResourceList = NULL;
1130c2c66affSColin Finck DeviceNode->ResourceListTranslated = NULL;
1131798fc13bSVictor Perevertkin PiSetDevNodeState(DeviceNode, DeviceNodeResourcesAssigned);
1132798fc13bSVictor Perevertkin DeviceNode->Flags |= DNF_NO_RESOURCE_REQUIRED;
1133c2c66affSColin Finck
1134c2c66affSColin Finck return STATUS_SUCCESS;
1135c2c66affSColin Finck }
1136c2c66affSColin Finck
1137c2c66affSColin Finck if (DeviceNode->BootResources)
1138c2c66affSColin Finck {
1139c2c66affSColin Finck ListSize = PnpDetermineResourceListSize(DeviceNode->BootResources);
1140c2c66affSColin Finck
1141c2c66affSColin Finck DeviceNode->ResourceList = ExAllocatePool(PagedPool, ListSize);
1142c2c66affSColin Finck if (!DeviceNode->ResourceList)
1143c2c66affSColin Finck {
1144c2c66affSColin Finck Status = STATUS_NO_MEMORY;
1145c2c66affSColin Finck goto ByeBye;
1146c2c66affSColin Finck }
1147c2c66affSColin Finck
1148c2c66affSColin Finck RtlCopyMemory(DeviceNode->ResourceList, DeviceNode->BootResources, ListSize);
1149c2c66affSColin Finck
1150c2c66affSColin Finck Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL);
1151c2c66affSColin Finck if (!NT_SUCCESS(Status))
1152c2c66affSColin Finck {
1153c2c66affSColin Finck DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode->InstancePath);
1154c2c66affSColin Finck ExFreePool(DeviceNode->ResourceList);
1155c2c66affSColin Finck DeviceNode->ResourceList = NULL;
1156c2c66affSColin Finck }
1157c2c66affSColin Finck }
1158c2c66affSColin Finck else
1159c2c66affSColin Finck {
1160c2c66affSColin Finck /* We'll make this from the requirements */
1161c2c66affSColin Finck DeviceNode->ResourceList = NULL;
1162c2c66affSColin Finck }
1163c2c66affSColin Finck
1164c2c66affSColin Finck /* No resources requirements */
1165c2c66affSColin Finck if (!DeviceNode->ResourceRequirements)
1166c2c66affSColin Finck goto Finish;
1167c2c66affSColin Finck
1168c2c66affSColin Finck /* Call HAL to fixup our resource requirements list */
1169c2c66affSColin Finck HalAdjustResourceList(&DeviceNode->ResourceRequirements);
1170c2c66affSColin Finck
1171c2c66affSColin Finck /* Add resource requirements that aren't in the list we already got */
1172c2c66affSColin Finck Status = IopFixupResourceListWithRequirements(DeviceNode->ResourceRequirements,
1173c2c66affSColin Finck &DeviceNode->ResourceList);
1174c2c66affSColin Finck if (!NT_SUCCESS(Status))
1175c2c66affSColin Finck {
1176c2c66affSColin Finck DPRINT1("Failed to fixup a resource list from supplied resources for %wZ\n", &DeviceNode->InstancePath);
1177c2c66affSColin Finck DeviceNode->Problem = CM_PROB_NORMAL_CONFLICT;
1178c2c66affSColin Finck goto ByeBye;
1179c2c66affSColin Finck }
1180c2c66affSColin Finck
1181c2c66affSColin Finck /* IopFixupResourceListWithRequirements should NEVER give us a conflicting list */
1182c2c66affSColin Finck ASSERT(IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL) != STATUS_CONFLICTING_ADDRESSES);
1183c2c66affSColin Finck
1184c2c66affSColin Finck Finish:
1185c2c66affSColin Finck Status = IopTranslateDeviceResources(DeviceNode);
1186c2c66affSColin Finck if (!NT_SUCCESS(Status))
1187c2c66affSColin Finck {
1188c2c66affSColin Finck DeviceNode->Problem = CM_PROB_TRANSLATION_FAILED;
1189c2c66affSColin Finck DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode->InstancePath);
1190c2c66affSColin Finck goto ByeBye;
1191c2c66affSColin Finck }
1192c2c66affSColin Finck
1193c2c66affSColin Finck Status = IopUpdateResourceMapForPnPDevice(DeviceNode);
1194c2c66affSColin Finck if (!NT_SUCCESS(Status))
1195c2c66affSColin Finck goto ByeBye;
1196c2c66affSColin Finck
1197c2c66affSColin Finck Status = IopUpdateControlKeyWithResources(DeviceNode);
1198c2c66affSColin Finck if (!NT_SUCCESS(Status))
1199c2c66affSColin Finck goto ByeBye;
1200c2c66affSColin Finck
1201798fc13bSVictor Perevertkin PiSetDevNodeState(DeviceNode, DeviceNodeResourcesAssigned);
1202c2c66affSColin Finck
1203c2c66affSColin Finck return STATUS_SUCCESS;
1204c2c66affSColin Finck
1205c2c66affSColin Finck ByeBye:
1206c2c66affSColin Finck if (DeviceNode->ResourceList)
1207c2c66affSColin Finck {
1208c2c66affSColin Finck ExFreePool(DeviceNode->ResourceList);
1209c2c66affSColin Finck DeviceNode->ResourceList = NULL;
1210c2c66affSColin Finck }
1211c2c66affSColin Finck
1212c2c66affSColin Finck DeviceNode->ResourceListTranslated = NULL;
1213c2c66affSColin Finck
1214c2c66affSColin Finck return Status;
1215c2c66affSColin Finck }
1216c2c66affSColin Finck
1217c2c66affSColin Finck static
1218c2c66affSColin Finck BOOLEAN
IopCheckForResourceConflict(IN PCM_RESOURCE_LIST ResourceList1,IN PCM_RESOURCE_LIST ResourceList2,IN BOOLEAN Silent,OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)1219c2c66affSColin Finck IopCheckForResourceConflict(
1220c2c66affSColin Finck IN PCM_RESOURCE_LIST ResourceList1,
1221c2c66affSColin Finck IN PCM_RESOURCE_LIST ResourceList2,
1222c2c66affSColin Finck IN BOOLEAN Silent,
1223c2c66affSColin Finck OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
1224c2c66affSColin Finck {
1225c2c66affSColin Finck ULONG i, ii;
1226c2c66affSColin Finck BOOLEAN Result = FALSE;
1227b82bf8ceSTimo Kreuzer PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
1228c2c66affSColin Finck
1229b82bf8ceSTimo Kreuzer FullDescriptor = &ResourceList1->List[0];
1230c2c66affSColin Finck for (i = 0; i < ResourceList1->Count; i++)
1231c2c66affSColin Finck {
1232b82bf8ceSTimo Kreuzer PCM_PARTIAL_RESOURCE_LIST ResList = &FullDescriptor->PartialResourceList;
1233b82bf8ceSTimo Kreuzer FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor);
1234b82bf8ceSTimo Kreuzer
1235c2c66affSColin Finck for (ii = 0; ii < ResList->Count; ii++)
1236c2c66affSColin Finck {
1237b82bf8ceSTimo Kreuzer /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
1238b82bf8ceSTimo Kreuzer but only one is allowed and it must be the last one in the list! */
1239c2c66affSColin Finck PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc = &ResList->PartialDescriptors[ii];
1240c2c66affSColin Finck
1241c2c66affSColin Finck Result = IopCheckResourceDescriptor(ResDesc,
1242c2c66affSColin Finck ResourceList2,
1243c2c66affSColin Finck Silent,
1244c2c66affSColin Finck ConflictingDescriptor);
1245c2c66affSColin Finck if (Result) goto ByeBye;
1246c2c66affSColin Finck }
1247c2c66affSColin Finck }
1248c2c66affSColin Finck
1249c2c66affSColin Finck ByeBye:
1250c2c66affSColin Finck
1251c2c66affSColin Finck return Result;
1252c2c66affSColin Finck }
1253c2c66affSColin Finck
1254c2c66affSColin Finck NTSTATUS NTAPI
IopDetectResourceConflict(IN PCM_RESOURCE_LIST ResourceList,IN BOOLEAN Silent,OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)1255c2c66affSColin Finck IopDetectResourceConflict(
1256c2c66affSColin Finck IN PCM_RESOURCE_LIST ResourceList,
1257c2c66affSColin Finck IN BOOLEAN Silent,
1258c2c66affSColin Finck OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
1259c2c66affSColin Finck {
1260c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes;
1261c2c66affSColin Finck UNICODE_STRING KeyName;
1262c2c66affSColin Finck HANDLE ResourceMapKey = NULL, ChildKey2 = NULL, ChildKey3 = NULL;
1263c2c66affSColin Finck ULONG KeyInformationLength, RequiredLength, KeyValueInformationLength, KeyNameInformationLength;
1264c2c66affSColin Finck PKEY_BASIC_INFORMATION KeyInformation;
1265c2c66affSColin Finck PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
1266c2c66affSColin Finck PKEY_VALUE_BASIC_INFORMATION KeyNameInformation;
1267*49358f34SHervé Poussineau ULONG ChildKeyIndex1 = 0, ChildKeyIndex2, ChildKeyIndex3;
1268c2c66affSColin Finck NTSTATUS Status;
1269c2c66affSColin Finck
1270c2c66affSColin Finck RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1271c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes,
1272c2c66affSColin Finck &KeyName,
1273c2c66affSColin Finck OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1274c2c66affSColin Finck NULL,
1275c2c66affSColin Finck NULL);
1276c2c66affSColin Finck Status = ZwOpenKey(&ResourceMapKey, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes);
1277c2c66affSColin Finck if (!NT_SUCCESS(Status))
1278c2c66affSColin Finck {
1279c2c66affSColin Finck /* The key is missing which means we are the first device */
1280c2c66affSColin Finck return STATUS_SUCCESS;
1281c2c66affSColin Finck }
1282c2c66affSColin Finck
1283c2c66affSColin Finck while (TRUE)
1284c2c66affSColin Finck {
1285c2c66affSColin Finck Status = ZwEnumerateKey(ResourceMapKey,
1286c2c66affSColin Finck ChildKeyIndex1,
1287c2c66affSColin Finck KeyBasicInformation,
1288c2c66affSColin Finck NULL,
1289c2c66affSColin Finck 0,
1290c2c66affSColin Finck &RequiredLength);
1291c2c66affSColin Finck if (Status == STATUS_NO_MORE_ENTRIES)
1292c2c66affSColin Finck break;
1293c2c66affSColin Finck else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
1294c2c66affSColin Finck {
1295c2c66affSColin Finck KeyInformationLength = RequiredLength;
1296c2c66affSColin Finck KeyInformation = ExAllocatePoolWithTag(PagedPool,
1297c2c66affSColin Finck KeyInformationLength,
1298c2c66affSColin Finck TAG_IO);
1299c2c66affSColin Finck if (!KeyInformation)
1300c2c66affSColin Finck {
1301c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
1302c2c66affSColin Finck goto cleanup;
1303c2c66affSColin Finck }
1304c2c66affSColin Finck
1305c2c66affSColin Finck Status = ZwEnumerateKey(ResourceMapKey,
1306c2c66affSColin Finck ChildKeyIndex1,
1307c2c66affSColin Finck KeyBasicInformation,
1308c2c66affSColin Finck KeyInformation,
1309c2c66affSColin Finck KeyInformationLength,
1310c2c66affSColin Finck &RequiredLength);
1311c2c66affSColin Finck }
1312c2c66affSColin Finck else
1313c2c66affSColin Finck goto cleanup;
1314c2c66affSColin Finck ChildKeyIndex1++;
1315c2c66affSColin Finck if (!NT_SUCCESS(Status))
1316c2c66affSColin Finck {
1317c2c66affSColin Finck ExFreePoolWithTag(KeyInformation, TAG_IO);
1318c2c66affSColin Finck goto cleanup;
1319c2c66affSColin Finck }
1320c2c66affSColin Finck
1321c2c66affSColin Finck KeyName.Buffer = KeyInformation->Name;
1322c2c66affSColin Finck KeyName.MaximumLength = KeyName.Length = (USHORT)KeyInformation->NameLength;
1323c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes,
1324c2c66affSColin Finck &KeyName,
1325c2c66affSColin Finck OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1326c2c66affSColin Finck ResourceMapKey,
1327c2c66affSColin Finck NULL);
1328c2c66affSColin Finck Status = ZwOpenKey(&ChildKey2,
1329c2c66affSColin Finck KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
1330c2c66affSColin Finck &ObjectAttributes);
1331c2c66affSColin Finck ExFreePoolWithTag(KeyInformation, TAG_IO);
1332c2c66affSColin Finck if (!NT_SUCCESS(Status))
1333c2c66affSColin Finck goto cleanup;
1334c2c66affSColin Finck
1335*49358f34SHervé Poussineau ChildKeyIndex2 = 0;
1336c2c66affSColin Finck while (TRUE)
1337c2c66affSColin Finck {
1338c2c66affSColin Finck Status = ZwEnumerateKey(ChildKey2,
1339c2c66affSColin Finck ChildKeyIndex2,
1340c2c66affSColin Finck KeyBasicInformation,
1341c2c66affSColin Finck NULL,
1342c2c66affSColin Finck 0,
1343c2c66affSColin Finck &RequiredLength);
1344c2c66affSColin Finck if (Status == STATUS_NO_MORE_ENTRIES)
1345c2c66affSColin Finck break;
1346c2c66affSColin Finck else if (Status == STATUS_BUFFER_TOO_SMALL)
1347c2c66affSColin Finck {
1348c2c66affSColin Finck KeyInformationLength = RequiredLength;
1349c2c66affSColin Finck KeyInformation = ExAllocatePoolWithTag(PagedPool,
1350c2c66affSColin Finck KeyInformationLength,
1351c2c66affSColin Finck TAG_IO);
1352c2c66affSColin Finck if (!KeyInformation)
1353c2c66affSColin Finck {
1354c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
1355c2c66affSColin Finck goto cleanup;
1356c2c66affSColin Finck }
1357c2c66affSColin Finck
1358c2c66affSColin Finck Status = ZwEnumerateKey(ChildKey2,
1359c2c66affSColin Finck ChildKeyIndex2,
1360c2c66affSColin Finck KeyBasicInformation,
1361c2c66affSColin Finck KeyInformation,
1362c2c66affSColin Finck KeyInformationLength,
1363c2c66affSColin Finck &RequiredLength);
1364c2c66affSColin Finck }
1365c2c66affSColin Finck else
1366c2c66affSColin Finck goto cleanup;
1367c2c66affSColin Finck ChildKeyIndex2++;
1368c2c66affSColin Finck if (!NT_SUCCESS(Status))
1369c2c66affSColin Finck {
1370c2c66affSColin Finck ExFreePoolWithTag(KeyInformation, TAG_IO);
1371c2c66affSColin Finck goto cleanup;
1372c2c66affSColin Finck }
1373c2c66affSColin Finck
1374c2c66affSColin Finck KeyName.Buffer = KeyInformation->Name;
1375c2c66affSColin Finck KeyName.MaximumLength = KeyName.Length = (USHORT)KeyInformation->NameLength;
1376c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes,
1377c2c66affSColin Finck &KeyName,
1378c2c66affSColin Finck OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1379c2c66affSColin Finck ChildKey2,
1380c2c66affSColin Finck NULL);
1381c2c66affSColin Finck Status = ZwOpenKey(&ChildKey3, KEY_QUERY_VALUE, &ObjectAttributes);
1382c2c66affSColin Finck ExFreePoolWithTag(KeyInformation, TAG_IO);
1383c2c66affSColin Finck if (!NT_SUCCESS(Status))
1384c2c66affSColin Finck goto cleanup;
1385c2c66affSColin Finck
1386*49358f34SHervé Poussineau ChildKeyIndex3 = 0;
1387c2c66affSColin Finck while (TRUE)
1388c2c66affSColin Finck {
1389c2c66affSColin Finck Status = ZwEnumerateValueKey(ChildKey3,
1390c2c66affSColin Finck ChildKeyIndex3,
1391c2c66affSColin Finck KeyValuePartialInformation,
1392c2c66affSColin Finck NULL,
1393c2c66affSColin Finck 0,
1394c2c66affSColin Finck &RequiredLength);
1395c2c66affSColin Finck if (Status == STATUS_NO_MORE_ENTRIES)
1396c2c66affSColin Finck break;
1397c2c66affSColin Finck else if (Status == STATUS_BUFFER_TOO_SMALL)
1398c2c66affSColin Finck {
1399c2c66affSColin Finck KeyValueInformationLength = RequiredLength;
1400c2c66affSColin Finck KeyValueInformation = ExAllocatePoolWithTag(PagedPool,
1401c2c66affSColin Finck KeyValueInformationLength,
1402c2c66affSColin Finck TAG_IO);
1403c2c66affSColin Finck if (!KeyValueInformation)
1404c2c66affSColin Finck {
1405c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
1406c2c66affSColin Finck goto cleanup;
1407c2c66affSColin Finck }
1408c2c66affSColin Finck
1409c2c66affSColin Finck Status = ZwEnumerateValueKey(ChildKey3,
1410c2c66affSColin Finck ChildKeyIndex3,
1411c2c66affSColin Finck KeyValuePartialInformation,
1412c2c66affSColin Finck KeyValueInformation,
1413c2c66affSColin Finck KeyValueInformationLength,
1414c2c66affSColin Finck &RequiredLength);
1415c2c66affSColin Finck }
1416c2c66affSColin Finck else
1417c2c66affSColin Finck goto cleanup;
1418c2c66affSColin Finck if (!NT_SUCCESS(Status))
1419c2c66affSColin Finck {
1420c2c66affSColin Finck ExFreePoolWithTag(KeyValueInformation, TAG_IO);
1421c2c66affSColin Finck goto cleanup;
1422c2c66affSColin Finck }
1423c2c66affSColin Finck
1424c2c66affSColin Finck Status = ZwEnumerateValueKey(ChildKey3,
1425c2c66affSColin Finck ChildKeyIndex3,
1426c2c66affSColin Finck KeyValueBasicInformation,
1427c2c66affSColin Finck NULL,
1428c2c66affSColin Finck 0,
1429c2c66affSColin Finck &RequiredLength);
1430c2c66affSColin Finck if (Status == STATUS_BUFFER_TOO_SMALL)
1431c2c66affSColin Finck {
1432c2c66affSColin Finck KeyNameInformationLength = RequiredLength;
1433c2c66affSColin Finck KeyNameInformation = ExAllocatePoolWithTag(PagedPool,
1434c2c66affSColin Finck KeyNameInformationLength + sizeof(WCHAR),
1435c2c66affSColin Finck TAG_IO);
1436c2c66affSColin Finck if (!KeyNameInformation)
1437c2c66affSColin Finck {
1438c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
1439c2c66affSColin Finck goto cleanup;
1440c2c66affSColin Finck }
1441c2c66affSColin Finck
1442c2c66affSColin Finck Status = ZwEnumerateValueKey(ChildKey3,
1443c2c66affSColin Finck ChildKeyIndex3,
1444c2c66affSColin Finck KeyValueBasicInformation,
1445c2c66affSColin Finck KeyNameInformation,
1446c2c66affSColin Finck KeyNameInformationLength,
1447c2c66affSColin Finck &RequiredLength);
1448c2c66affSColin Finck }
1449c2c66affSColin Finck else
1450c2c66affSColin Finck goto cleanup;
1451c2c66affSColin Finck ChildKeyIndex3++;
1452c2c66affSColin Finck if (!NT_SUCCESS(Status))
1453c2c66affSColin Finck {
1454c2c66affSColin Finck ExFreePoolWithTag(KeyNameInformation, TAG_IO);
1455c2c66affSColin Finck goto cleanup;
1456c2c66affSColin Finck }
1457c2c66affSColin Finck
1458c2c66affSColin Finck KeyNameInformation->Name[KeyNameInformation->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
1459c2c66affSColin Finck
1460c2c66affSColin Finck /* Skip translated entries */
1461c2c66affSColin Finck if (wcsstr(KeyNameInformation->Name, L".Translated"))
1462c2c66affSColin Finck {
1463c2c66affSColin Finck ExFreePoolWithTag(KeyNameInformation, TAG_IO);
1464c2c66affSColin Finck ExFreePoolWithTag(KeyValueInformation, TAG_IO);
1465c2c66affSColin Finck continue;
1466c2c66affSColin Finck }
1467c2c66affSColin Finck
1468c2c66affSColin Finck ExFreePoolWithTag(KeyNameInformation, TAG_IO);
1469c2c66affSColin Finck
1470c2c66affSColin Finck if (IopCheckForResourceConflict(ResourceList,
1471c2c66affSColin Finck (PCM_RESOURCE_LIST)KeyValueInformation->Data,
1472c2c66affSColin Finck Silent,
1473c2c66affSColin Finck ConflictingDescriptor))
1474c2c66affSColin Finck {
1475c2c66affSColin Finck ExFreePoolWithTag(KeyValueInformation, TAG_IO);
1476c2c66affSColin Finck Status = STATUS_CONFLICTING_ADDRESSES;
1477c2c66affSColin Finck goto cleanup;
1478c2c66affSColin Finck }
1479c2c66affSColin Finck
1480c2c66affSColin Finck ExFreePoolWithTag(KeyValueInformation, TAG_IO);
1481c2c66affSColin Finck }
1482c2c66affSColin Finck }
1483c2c66affSColin Finck }
1484c2c66affSColin Finck
1485c2c66affSColin Finck cleanup:
1486c2c66affSColin Finck if (ResourceMapKey != NULL)
1487c2c66affSColin Finck ObCloseHandle(ResourceMapKey, KernelMode);
1488c2c66affSColin Finck if (ChildKey2 != NULL)
1489c2c66affSColin Finck ObCloseHandle(ChildKey2, KernelMode);
1490c2c66affSColin Finck if (ChildKey3 != NULL)
1491c2c66affSColin Finck ObCloseHandle(ChildKey3, KernelMode);
1492c2c66affSColin Finck
1493c2c66affSColin Finck if (Status == STATUS_NO_MORE_ENTRIES)
1494c2c66affSColin Finck Status = STATUS_SUCCESS;
1495c2c66affSColin Finck
1496c2c66affSColin Finck return Status;
1497c2c66affSColin Finck }
1498c2c66affSColin Finck
1499