1 /*
2  * PROJECT:     ReactOS Kernel
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Helper functions to parse CM_RESOURCE_LISTs
5  * COPYRIGHT:   Copyright 2020 Timo Kreuzer (timo.kreuzer@reactos.org)
6  */
7 
8 #include <wdm.h>
9 
10 //
11 // Resource list helpers
12 //
13 
14 /* Usage note:
15  * As there can be only one variable-sized CM_PARTIAL_RESOURCE_DESCRIPTOR in the list (and it must be the last one),
16  * a right looping through resources can look like this:
17  *
18  * PCM_FULL_RESOURCE_DESCRIPTOR FullDesc = &ResourceList->List[0];
19  * for (ULONG i = 0; i < ResourceList->Count; i++, FullDesc = CmiGetNextResourceDescriptor(FullDesc))
20  * {
21  *    for (ULONG j = 0; j < FullDesc->PartialResourceList.Count; j++)
22  *    {
23  *        PartialDesc = &FullDesc->PartialResourceList.PartialDescriptors[j];
24  *        // work with PartialDesc
25  *    }
26  * }
27  */
28 
29 FORCEINLINE
30 PCM_PARTIAL_RESOURCE_DESCRIPTOR
CmiGetNextPartialDescriptor(_In_ const CM_PARTIAL_RESOURCE_DESCRIPTOR * PartialDescriptor)31 CmiGetNextPartialDescriptor(
32     _In_ const CM_PARTIAL_RESOURCE_DESCRIPTOR *PartialDescriptor)
33 {
34     const CM_PARTIAL_RESOURCE_DESCRIPTOR *NextDescriptor;
35 
36     /* Assume the descriptors are the fixed size ones */
37     NextDescriptor = PartialDescriptor + 1;
38 
39     /* But check if this is actually a variable-sized descriptor */
40     if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific)
41     {
42         /* Add the size of the variable section as well */
43         NextDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)((ULONG_PTR)NextDescriptor +
44                          PartialDescriptor->u.DeviceSpecificData.DataSize);
45         ASSERT(NextDescriptor >= PartialDescriptor + 1);
46     }
47 
48     /* Now the correct pointer has been computed, return it */
49     return (PCM_PARTIAL_RESOURCE_DESCRIPTOR)NextDescriptor;
50 }
51 
52 FORCEINLINE
53 PCM_FULL_RESOURCE_DESCRIPTOR
CmiGetNextResourceDescriptor(_In_ const CM_FULL_RESOURCE_DESCRIPTOR * ResourceDescriptor)54 CmiGetNextResourceDescriptor(
55     _In_ const CM_FULL_RESOURCE_DESCRIPTOR *ResourceDescriptor)
56 {
57     const CM_PARTIAL_RESOURCE_DESCRIPTOR *LastPartialDescriptor;
58 
59     /* Calculate the location of the last partial descriptor, which can have a
60        variable size! */
61     LastPartialDescriptor = &ResourceDescriptor->PartialResourceList.PartialDescriptors[
62             ResourceDescriptor->PartialResourceList.Count - 1];
63 
64     /* Next full resource descriptor follows the last partial descriptor */
65     return (PCM_FULL_RESOURCE_DESCRIPTOR)CmiGetNextPartialDescriptor(LastPartialDescriptor);
66 }
67