1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxResourceAPI.cpp
8 
9 Abstract:
10 
11     This module implements the resource class.
12 
13 Author:
14 
15 
16 
17 
18 Environment:
19 
20     Both kernel and user mode
21 
22 Revision History:
23 
24 --*/
25 #include "fxsupportpch.hpp"
26 
27 extern "C" {
28 // #include "FxResourceAPI.tmh"
29 }
30 
31 //
32 // Extern "C" the entire file
33 //
34 extern "C" {
35 
36 __drv_maxIRQL(DISPATCH_LEVEL)
37 VOID
38 STDCALL
39 WDFEXPORT(WdfIoResourceRequirementsListSetSlotNumber)(
40     __in
41     PWDF_DRIVER_GLOBALS DriverGlobals,
42     __in
43     WDFIORESREQLIST RequirementsList,
44     __in
45     ULONG SlotNumber
46     )
47 /*++
48 
49 Routine Description:
50     Sets the slot number for a given resource requirements list
51 
52 Arguments:
53     RequirementsList - list to be modified
54 
55     SlotNumber - slot value to assign
56 
57 Return Value:
58     None
59 
60   --*/
61 {
62     FxIoResReqList* pIoResReqList;
63 
64     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
65                          RequirementsList,
66                          FX_TYPE_IO_RES_REQ_LIST,
67                          (PVOID*) &pIoResReqList);
68 
69     if (pIoResReqList->m_SlotNumber != SlotNumber) {
70         pIoResReqList->MarkChanged();
71     }
72     pIoResReqList->m_SlotNumber = SlotNumber;
73 }
74 
75 __drv_maxIRQL(DISPATCH_LEVEL)
76 VOID
77 STDCALL
78 WDFEXPORT(WdfIoResourceRequirementsListSetInterfaceType)(
79     __in
80     PWDF_DRIVER_GLOBALS DriverGlobals,
81     __in
82     WDFIORESREQLIST RequirementsList,
83     __in
84     __drv_strictTypeMatch(__drv_typeCond)
85     INTERFACE_TYPE InterfaceType
86     )
87 /*++
88 
89 Routine Description:
90     Sets the InterfaceType for a given resource requirements list
91 
92 Arguments:
93     RequirementsList - list to be modified
94 
95     InterfaceType - interface type to assign
96 
97 Return Value:
98     None
99 
100   --*/
101 {
102     FxIoResReqList* pIoResReqList;
103 
104     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
105                          RequirementsList,
106                          FX_TYPE_IO_RES_REQ_LIST,
107                          (PVOID*) &pIoResReqList);
108 
109     if (pIoResReqList->m_InterfaceType != InterfaceType) {
110         pIoResReqList->MarkChanged();
111     }
112 
113     pIoResReqList->m_InterfaceType = InterfaceType;
114 }
115 
116 _Must_inspect_result_
117 __drv_maxIRQL(DISPATCH_LEVEL)
118 NTSTATUS
119 FxIoResourceRequirementsListInsertIoResList(
120     __in
121     PWDF_DRIVER_GLOBALS DriverGlobals,
122     __in
123     WDFIORESREQLIST RequirementsList,
124     __in
125     WDFIORESLIST IoResList,
126     ULONG Index
127     )
128 /*++
129 
130 Routine Description:
131     Inserts a resource list into a requirements list at a particular index.
132 
133 Arguments:
134     RequirementsList - list to be modified
135 
136     IoResList - resource list to add
137 
138     Index - zero based index to insert at
139 
140 Return Value:
141     NTSTATUS
142 
143   --*/
144 {
145     PFX_DRIVER_GLOBALS pFxDriverGlobals;
146     FxIoResReqList* pIoResReqList;
147     FxIoResList* pIoResList;
148     NTSTATUS status;
149 
150     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
151                                    RequirementsList,
152                                    FX_TYPE_IO_RES_REQ_LIST,
153                                    (PVOID*) &pIoResReqList,
154                                    &pFxDriverGlobals);
155 
156     FxObjectHandleGetPtr(pFxDriverGlobals,
157                          IoResList,
158                          FX_TYPE_IO_RES_LIST,
159                          (PVOID*) &pIoResList);
160 
161     if (pIoResList->m_OwningList != pIoResReqList) {
162         return STATUS_INVALID_DEVICE_REQUEST;
163     }
164 
165     status = pIoResReqList->AddAt(Index, pIoResList);
166 
167     if (NT_SUCCESS(status)) {
168         //
169         // Mirror the access flags as well.
170         //
171         pIoResList->m_AccessFlags = pIoResReqList->m_AccessFlags;
172         pIoResList->m_OwningList = pIoResReqList;
173     }
174 
175     return status;
176 }
177 
178 
179 _Must_inspect_result_
180 __drv_maxIRQL(DISPATCH_LEVEL)
181 NTSTATUS
182 STDCALL
183 WDFEXPORT(WdfIoResourceRequirementsListInsertIoResList)(
184     __in
185     PWDF_DRIVER_GLOBALS DriverGlobals,
186     __in
187     WDFIORESREQLIST RequirementsList,
188     __in
189     WDFIORESLIST IoResList,
190     __in
191     ULONG Index
192     )
193 /*++
194 
195 Routine Description:
196     Inserts a resource list into a requirements list at a particular index.
197 
198 Arguments:
199     RequirementsList - list to be modified
200 
201     IoResList - resource list to add
202 
203     Index - zero based index to insert at
204 
205 Return Value:
206     NTSTATUS
207 
208   --*/
209 {
210     return FxIoResourceRequirementsListInsertIoResList(DriverGlobals,
211                                                        RequirementsList,
212                                                        IoResList,
213                                                        Index);
214 }
215 
216 _Must_inspect_result_
217 __drv_maxIRQL(DISPATCH_LEVEL)
218 NTSTATUS
219 STDCALL
220 WDFEXPORT(WdfIoResourceRequirementsListAppendIoResList)(
221     __in
222     PWDF_DRIVER_GLOBALS DriverGlobals,
223     __in
224     WDFIORESREQLIST RequirementsList,
225     __in
226     WDFIORESLIST IoResList
227     )
228 /*++
229 
230 Routine Description:
231    Appends a resource list to a resource requirements list
232 
233 Arguments:
234     RequirementsList - list to be modified
235 
236     IoResList - resource list to append
237 
238 Return Value:
239     NTSTATUS
240 
241   --*/
242 
243 {
244     return FxIoResourceRequirementsListInsertIoResList(DriverGlobals,
245                                                        RequirementsList,
246                                                        IoResList,
247                                                        WDF_INSERT_AT_END);
248 }
249 
250 
251 __drv_maxIRQL(DISPATCH_LEVEL)
252 ULONG
253 STDCALL
254 WDFEXPORT(WdfIoResourceRequirementsListGetCount)(
255     __in
256     PWDF_DRIVER_GLOBALS DriverGlobals,
257     __in
258     WDFIORESREQLIST RequirementsList
259     )
260 /*++
261 
262 Routine Description:
263     Returns the number of resource lists in the requirements list
264 
265 
266 Arguments:
267     RequirementsList - requirements list whose count will be returned
268 
269 Return Value:
270     number of elements in the list
271 
272   --*/
273 
274 {
275     FxIoResReqList* pList;
276     ULONG count;
277     KIRQL irql;
278 
279     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
280                          RequirementsList,
281                          FX_TYPE_IO_RES_REQ_LIST,
282                          (PVOID*) &pList);
283 
284     pList->Lock(&irql);
285     count = pList->Count();
286     pList->Unlock(irql);
287 
288     return count;
289 }
290 
291 __drv_maxIRQL(DISPATCH_LEVEL)
292 WDFIORESLIST
293 STDCALL
294 WDFEXPORT(WdfIoResourceRequirementsListGetIoResList)(
295     __in
296     PWDF_DRIVER_GLOBALS DriverGlobals,
297     __in
298     WDFIORESREQLIST RequirementsList,
299     __in
300     ULONG Index
301     )
302 /*++
303 
304 Routine Description:
305     Retrieves a resource list from the requirements list at a given index.
306 
307 Arguments:
308     RequirementsList - list to retrieve the resource list from
309 
310     Index - zero based index from which to retrieve the list
311 
312 Return Value:
313     resource list handle or NULL
314 
315   --*/
316 {
317     FxIoResReqList* pIoResReqList;
318     FxObject* pObject;
319     KIRQL irql;
320 
321     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
322                          RequirementsList,
323                          FX_TYPE_IO_RES_REQ_LIST,
324                          (PVOID*) &pIoResReqList);
325 
326     pIoResReqList->Lock(&irql);
327     pObject = pIoResReqList->GetItem(Index);
328     pIoResReqList->Unlock(irql);
329 
330     if (pObject == NULL) {
331         return NULL;
332     }
333     else {
334         return (WDFIORESLIST) pObject->GetObjectHandle();
335     }
336 }
337 
338 __drv_maxIRQL(DISPATCH_LEVEL)
339 VOID
340 STDCALL
341 WDFEXPORT(WdfIoResourceRequirementsListRemove)(
342     __in
343     PWDF_DRIVER_GLOBALS DriverGlobals,
344     __in
345     WDFIORESREQLIST RequirementsList,
346     __in
347     ULONG Index
348     )
349 /*++
350 
351 Routine Description:
352     Removes a resource list from the requirements list at a given index
353 
354 Arguments:
355     RequirementsList - list of resource requirements which will be modified
356 
357     Index - zero based index which indictes location in the list to find the
358             resource list
359 
360 Return Value:
361     None
362 
363   --*/
364 {
365     PFX_DRIVER_GLOBALS pFxDriverGlobals;
366     FxIoResReqList* pList;
367 
368     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
369                                    RequirementsList,
370                                    FX_TYPE_IO_RES_REQ_LIST,
371                                    (PVOID*) &pList,
372                                    &pFxDriverGlobals);
373 
374     if (pList->RemoveAndDelete(Index) == FALSE) {
375         DoTraceLevelMessage(
376             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
377             "WDFIORESLIST %p, could not remove list at index %d (not found), "
378             "list item count is %d", RequirementsList, Index, pList->Count());
379 
380         FxVerifierDbgBreakPoint(pFxDriverGlobals);
381     }
382 }
383 
384 __drv_maxIRQL(DISPATCH_LEVEL)
385 VOID
386 STDCALL
387 WDFEXPORT(WdfIoResourceRequirementsListRemoveByIoResList)(
388     __in
389     PWDF_DRIVER_GLOBALS DriverGlobals,
390     __in
391     WDFIORESREQLIST RequirementsList,
392     __in
393     WDFIORESLIST IoResList
394     )
395 /*++
396 
397 Routine Description:
398     Removes a resource list from the requirements list based on the resource list's
399     handle
400 
401 Arguments:
402     RequirementsList - resource requirements list being modified
403 
404     IoResList - resource list to be removed
405 
406 Return Value:
407     None
408 
409   --*/
410 {
411     PFX_DRIVER_GLOBALS pFxDriverGlobals;
412     FxCollectionEntry* cur, *end;
413     FxIoResReqList* pList;
414     FxIoResList* pResList;
415     KIRQL irql;
416     BOOLEAN listFound;
417 
418     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
419                                    RequirementsList,
420                                    FX_TYPE_IO_RES_REQ_LIST,
421                                    (PVOID*) &pList,
422                                    &pFxDriverGlobals);
423 
424     if (pList->IsRemoveAllowed() == FALSE) {
425         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
426                             "WDFIORESREQLIST %p: Removes not allowed",
427                             RequirementsList);
428 
429         FxVerifierDbgBreakPoint(pFxDriverGlobals);
430         return;
431     }
432 
433     FxObjectHandleGetPtr(pFxDriverGlobals,
434                          IoResList,
435                          FX_TYPE_IO_RES_LIST,
436                          (PVOID*) &pResList);
437 
438     pList->Lock(&irql);
439 
440     cur = pList->Start();
441     end = pList->End();
442     listFound = FALSE;
443 
444     while (cur != end) {
445         if (cur->m_Object == pResList) {
446             pList->MarkChanged();
447 
448             pList->RemoveEntry(cur);
449             listFound = TRUE;
450             break;
451         }
452 
453         cur = cur->Next();
454     }
455 
456     pList->Unlock(irql);
457 
458     if (listFound) {
459         pResList->DeleteObject();
460         pResList = NULL;
461     }
462 }
463 
464 _Must_inspect_result_
465 __drv_maxIRQL(DISPATCH_LEVEL)
466 NTSTATUS
467 STDCALL
468 WDFEXPORT(WdfIoResourceListCreate)(
469     __in
470     PWDF_DRIVER_GLOBALS DriverGlobals,
471     __in
472     WDFIORESREQLIST RequirementsList,
473     __in_opt
474     PWDF_OBJECT_ATTRIBUTES Attributes,
475     __out
476     WDFIORESLIST* ResourceList
477     )
478 /*++
479 
480 Routine Description:
481    Creates a resource list.
482 
483 Arguments:
484     RequirementsList - the resource requirements list that the resource list will
485                        be associated with
486 
487     Attributes - generic object attributes for the new resource list
488 
489     ResourceList - pointer which will receive the new object handle
490 
491 Return Value:
492     NTSTATUS
493 
494   --*/
495 {
496     PFX_DRIVER_GLOBALS pFxDriverGlobals;
497     FxIoResReqList* pIoResReqList;
498     FxIoResList* pIoResList;
499     NTSTATUS status;
500 
501     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
502                                    RequirementsList,
503                                    FX_TYPE_IO_RES_REQ_LIST,
504                                    (PVOID*) &pIoResReqList,
505                                    &pFxDriverGlobals);
506 
507     FxPointerNotNull(pFxDriverGlobals, ResourceList);
508     *ResourceList = NULL;
509 
510     status = FxValidateObjectAttributes(pFxDriverGlobals,
511                                         Attributes,
512                                         FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
513 
514     if (!NT_SUCCESS(status)) {
515         return status;
516     }
517 
518     pIoResList = new (pFxDriverGlobals, Attributes) FxIoResList(
519         pFxDriverGlobals, pIoResReqList);
520 
521     if (pIoResList == NULL) {
522         return STATUS_INSUFFICIENT_RESOURCES;
523     }
524 
525     status = pIoResList->Commit(Attributes,
526                                 (WDFOBJECT*) ResourceList,
527                                 pIoResReqList);
528 
529     if (!NT_SUCCESS(status)) {
530         pIoResList->DeleteFromFailedCreate();
531     }
532 
533     return status;
534 }
535 
536 _Must_inspect_result_
537 __drv_maxIRQL(DISPATCH_LEVEL)
538 NTSTATUS
539 FxIoResourceListInsertDescriptor(
540     __in
541     PWDF_DRIVER_GLOBALS DriverGlobals,
542     __in
543     WDFIORESLIST ResourceList,
544     __in
545     PIO_RESOURCE_DESCRIPTOR Descriptor,
546     ULONG Index
547     )
548 /*++
549 
550 Routine Description:
551     Inserts a descriptor into a resource list at a particular index.
552 
553 Arguments:
554     ResourceList - list to be modified
555 
556     Descriptor - descriptor to insert
557 
558     Index - zero based index to insert at
559 
560 Return Value:
561     NTSTATUS
562 
563   --*/
564 {
565     PFX_DRIVER_GLOBALS pFxDriverGlobals;
566     FxIoResList* pList;
567     FxResourceIo* pObject;
568     NTSTATUS status;
569 
570     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
571                                    ResourceList,
572                                    FX_TYPE_IO_RES_LIST,
573                                    (PVOID*) &pList,
574                                    &pFxDriverGlobals);
575 
576     FxPointerNotNull(pFxDriverGlobals, Descriptor);
577 
578     if (pList->m_OwningList->IsAddAllowed() == FALSE) {
579         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
580                             "Removes not allowed on WDFIORESLIST %p",
581                             ResourceList);
582         FxVerifierDbgBreakPoint(pFxDriverGlobals);
583         return STATUS_ACCESS_DENIED;
584     }
585 
586     pObject = new(pFxDriverGlobals)
587         FxResourceIo(pFxDriverGlobals, Descriptor);
588 
589     if (pObject == NULL) {
590         return STATUS_INSUFFICIENT_RESOURCES;
591     }
592 
593     status = pObject->AssignParentObject(pList);
594     if (!NT_SUCCESS(status)) {
595         pObject->DeleteObject();
596         return status;
597     }
598 
599     status = pList->AddAt(Index, pObject);
600 
601     //
602     // Mark both this list and its owning list as changed so when it comes
603     // time to evaluate the entire requirements list for changes, we do not
604     // have to iterate over all the resource lists.
605     //
606     if (NT_SUCCESS(status)) {
607         pList->m_OwningList->MarkChanged();
608     }
609 
610     return status;
611 }
612 
613 _Must_inspect_result_
614 __drv_maxIRQL(DISPATCH_LEVEL)
615 NTSTATUS
616 STDCALL
617 WDFEXPORT(WdfIoResourceListInsertDescriptor)(
618     __in
619     PWDF_DRIVER_GLOBALS DriverGlobals,
620     __in
621     WDFIORESLIST ResourceList,
622     __in
623     PIO_RESOURCE_DESCRIPTOR Descriptor,
624     __in
625     ULONG Index
626     )
627 /*++
628 
629 Routine Description:
630     Inserts a descriptor into a resource list at a particular index.
631 
632 Arguments:
633     ResourceList - list to be modified
634 
635     Descriptor - descriptor to insert
636 
637     Index - zero based index to insert at
638 
639 Return Value:
640     NTSTATUS
641 
642   --*/
643 {
644     return FxIoResourceListInsertDescriptor(DriverGlobals,
645                                             ResourceList,
646                                             Descriptor,
647                                             Index);
648 }
649 
650 _Must_inspect_result_
651 __drv_maxIRQL(DISPATCH_LEVEL)
652 NTSTATUS
653 STDCALL
654 WDFEXPORT(WdfIoResourceListAppendDescriptor)(
655     __in
656     PWDF_DRIVER_GLOBALS DriverGlobals,
657     __in
658     WDFIORESLIST ResourceList,
659     __in
660     PIO_RESOURCE_DESCRIPTOR Descriptor
661     )
662 /*++
663 
664 Routine Description:
665    Appends a descriptor to a resource list
666 
667 Arguments:
668     ResourceList - list to be modified
669 
670     Descriptor - item to be appended
671 
672 Return Value:
673     NTSTATUS
674 
675   --*/
676 {
677     return FxIoResourceListInsertDescriptor(DriverGlobals,
678                                             ResourceList,
679                                             Descriptor,
680                                             WDF_INSERT_AT_END);
681 }
682 
683 __drv_maxIRQL(DISPATCH_LEVEL)
684 VOID
685 STDCALL
686 WDFEXPORT(WdfIoResourceListUpdateDescriptor)(
687     __in
688     PWDF_DRIVER_GLOBALS DriverGlobals,
689     __in
690     WDFIORESLIST ResourceList,
691     __in
692     PIO_RESOURCE_DESCRIPTOR Descriptor,
693     __in
694     ULONG Index
695     )
696 /*++
697 
698 Routine Description:
699     Updates resource requirement in place in the list.
700 
701 Arguments:
702     ResourceList - list to be modified
703 
704     Descriptor - Pointer to descriptor whic contains the updated value
705 
706     Index - zero based location in the list to update
707 
708 Return Value:
709     None
710 
711   --*/
712 {
713     PFX_DRIVER_GLOBALS pFxDriverGlobals;
714     FxIoResList* pList;
715     FxResourceIo* pObject;
716     KIRQL irql;
717 
718     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
719                                    ResourceList,
720                                    FX_TYPE_IO_RES_LIST,
721                                    (PVOID*) &pList,
722                                    &pFxDriverGlobals);
723 
724     FxPointerNotNull(pFxDriverGlobals, Descriptor);
725 
726     pList->Lock(&irql);
727     pObject = (FxResourceIo*) pList->GetItem(Index);
728     pList->Unlock(irql);
729 
730     if (pObject != NULL) {
731         //
732         // We don't check for add or remove access because we don't know what
733         // the update is actually doing (ie widening a range, shortening it, etc).
734         // For this operation we have to trust the driver that it is doing the
735         // right thing at the right time.
736         //
737         RtlCopyMemory(&pObject->m_Descriptor,
738                       Descriptor,
739                       sizeof(pObject->m_Descriptor));
740 
741         //
742         // Mark both this list and its owning list as changed so when it comes
743         // time to evaluate the entire requirements list for changes, we do not
744         // have to iterate over all the resource lists.
745         //
746         pList->MarkChanged();
747         pList->m_OwningList->MarkChanged();
748     }
749     else {
750         DoTraceLevelMessage(
751             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
752             "WDFIORESREQLIST %p, cannot update item at index %d, item not found,"
753             " list item count is %d", ResourceList, Index, pList->Count());
754 
755         FxVerifierDbgBreakPoint(pFxDriverGlobals);
756     }
757 }
758 
759 __drv_maxIRQL(DISPATCH_LEVEL)
760 ULONG
761 STDCALL
762 WDFEXPORT(WdfIoResourceListGetCount)(
763     __in
764     PWDF_DRIVER_GLOBALS DriverGlobals,
765     __in
766     WDFIORESLIST ResourceList
767     )
768 /*++
769 
770 Routine Description:
771     Returns the number of descriptors in the resource list
772 
773 Arguments:
774     ResourceList - resource list whose count will be returned
775 
776 Return Value:
777     number of elements in the list
778 
779   --*/
780 {
781     FxIoResList* pList;
782     ULONG count;
783     KIRQL irql;
784 
785     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
786                          ResourceList,
787                          FX_TYPE_IO_RES_LIST,
788                          (PVOID*) &pList);
789 
790     pList->Lock(&irql);
791     count = pList->Count();
792     pList->Unlock(irql);
793 
794     return count;
795 }
796 
797 
798 __drv_maxIRQL(DISPATCH_LEVEL)
799 PIO_RESOURCE_DESCRIPTOR
800 STDCALL
801 WDFEXPORT(WdfIoResourceListGetDescriptor)(
802     __in
803     PWDF_DRIVER_GLOBALS DriverGlobals,
804     __in
805     WDFIORESLIST ResourceList,
806     __in
807     ULONG Index
808     )
809 /*++
810 
811 Routine Description:
812     Retrieves an io resource desciptor for a given index in the resource list
813 
814 Arguments:
815     ResourceList - list being looked up
816 
817     Index - zero based index into the list to find the value of
818 
819 Return Value:
820     pointer to an io resource descriptor upon success, NULL upon error
821 
822   --*/
823 
824 {
825     FxIoResList* pList;
826     FxResourceIo* pObject;
827     KIRQL irql;
828 
829     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
830                          ResourceList,
831                          FX_TYPE_IO_RES_LIST,
832                          (PVOID*) &pList);
833 
834     pList->Lock(&irql);
835     pObject = (FxResourceIo*) pList->GetItem(Index);
836     pList->Unlock(irql);
837 
838     if (pObject == NULL) {
839         return NULL;
840     }
841     else {
842         //
843         // Copy the current descriptor to the clone and return it
844         //
845         RtlCopyMemory(&pObject->m_DescriptorClone,
846                       &pObject->m_Descriptor,
847                       sizeof(pObject->m_Descriptor));
848 
849         return &pObject->m_DescriptorClone;
850     }
851 }
852 
853 __drv_maxIRQL(DISPATCH_LEVEL)
854 VOID
855 STDCALL
856 WDFEXPORT(WdfIoResourceListRemove)(
857     __in
858     PWDF_DRIVER_GLOBALS DriverGlobals,
859     __in
860     WDFIORESLIST ResourceList,
861     __in
862     ULONG Index
863     )
864 /*++
865 
866 Routine Description:
867     Removes a descriptor in an io resource list
868 
869 Arguments:
870     ResourceList - resource list to modify
871 
872     Index - zero based index into the list in which to remove the descriptor
873 
874 Return Value:
875     None
876 
877   --*/
878 {
879     PFX_DRIVER_GLOBALS pFxDriverGlobals;
880     FxIoResList* pList;
881 
882     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
883                                    ResourceList,
884                                    FX_TYPE_IO_RES_LIST,
885                                    (PVOID*) &pList,
886                                    &pFxDriverGlobals);
887 
888     if (pList->RemoveAndDelete(Index)) {
889         //
890         // Mark this list's owning list as changed so when it comes
891         // time to evaluate the entire requirements list for changes, we do not
892         // have to iterate over all the resource lists.
893         //
894         // RemoveAndDelete marked pList as changed already
895         //
896         pList->m_OwningList->MarkChanged();
897     }
898     else {
899         DoTraceLevelMessage(
900             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
901             "WDFIORESLIST %p, could not remove item at index %d (not found), "
902             "list item count is %d", ResourceList, Index, pList->Count());
903 
904         FxVerifierDbgBreakPoint(pFxDriverGlobals);
905     }
906 }
907 
908 __drv_maxIRQL(DISPATCH_LEVEL)
909 VOID
910 STDCALL
911 WDFEXPORT(WdfIoResourceListRemoveByDescriptor)(
912     __in
913     PWDF_DRIVER_GLOBALS DriverGlobals,
914     __in
915     WDFIORESLIST ResourceList,
916     __in
917     PIO_RESOURCE_DESCRIPTOR Descriptor
918     )
919 /*++
920 
921 Routine Description:
922     Removes a descriptor by value in a given io resource list.  Equality is
923     determined by RtlCompareMemory.
924 
925 Arguments:
926     ResourceList - the io resource list to modify
927 
928     Descriptor - pointer to a descriptor to remove.
929 
930 Return Value:
931     None
932 
933   --*/
934 {
935     PFX_DRIVER_GLOBALS pFxDriverGlobals;
936     FxCollectionEntry* cur, *end;
937     FxIoResList* pList;
938     FxResourceIo* pObject;
939     KIRQL irql;
940 
941     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
942                                    ResourceList,
943                                    FX_TYPE_IO_RES_LIST,
944                                    (PVOID*) &pList,
945                                    &pFxDriverGlobals);
946 
947     FxPointerNotNull(pFxDriverGlobals, Descriptor);
948 
949     if (pList->IsRemoveAllowed() == FALSE) {
950         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
951                             "Removes not allowed on WDFIORESLIST %p",
952                             ResourceList);
953 
954         FxVerifierDbgBreakPoint(pFxDriverGlobals);
955         return;
956     }
957 
958     pList->Lock(&irql);
959 
960     cur = pList->Start();
961     end = pList->End();
962     pObject = NULL;
963 
964     while (cur != end) {
965         pObject = (FxResourceIo*) cur->m_Object;
966 
967         if (RtlCompareMemory(&pObject->m_Descriptor,
968                              Descriptor,
969                              sizeof(*Descriptor)) == sizeof(*Descriptor)) {
970             //
971             // Mark both this list and its owning list as changed so when it
972             // comes time to evaluate the entire requirements list for
973             // changes, we do not have to iterate over all the resource lists.
974             //
975             pList->MarkChanged();
976             pList->m_OwningList->MarkChanged();
977 
978             pList->RemoveEntry(cur);
979             break;
980         }
981 
982         //
983         // Set to NULL so that we do not delete it if this is the last item in
984         // the list.
985         //
986         pObject = NULL;
987 
988         cur = cur->Next();
989     }
990 
991     pList->Unlock(irql);
992 
993     if (pObject != NULL) {
994         pObject->DeleteObject();
995     }
996 }
997 
998 _Must_inspect_result_
999 __drv_maxIRQL(DISPATCH_LEVEL)
1000 NTSTATUS
1001 FxCmResourceListInsertDescriptor(
1002     __in
1003     PWDF_DRIVER_GLOBALS DriverGlobals,
1004     __in
1005     WDFCMRESLIST List,
1006     __in
1007     PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
1008     __in
1009     ULONG Index
1010     )
1011 /*++
1012 
1013 Routine Description:
1014     Inserts a descriptor into a cm resource list at a particular index.
1015 
1016 Arguments:
1017     ResourceList - list to be modified
1018 
1019     Descriptor - descriptor to insert
1020 
1021     Index - zero based index to insert at
1022 
1023 Return Value:
1024     NTSTATUS
1025 
1026   --*/
1027 {
1028     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1029     FxCmResList* pList;
1030     FxResourceCm* pObject;
1031     NTSTATUS status;
1032 
1033     pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
1034 
1035     FxPointerNotNull(pFxDriverGlobals, Descriptor);
1036 
1037     FxObjectHandleGetPtr(pFxDriverGlobals,
1038                          List,
1039                          FX_TYPE_CM_RES_LIST,
1040                          (PVOID*) &pList);
1041 
1042     pObject = new(pFxDriverGlobals) FxResourceCm(pFxDriverGlobals, Descriptor);
1043 
1044     if (pObject == NULL) {
1045         return STATUS_INSUFFICIENT_RESOURCES;
1046     }
1047 
1048     status = pObject->AssignParentObject(pList);
1049     if (!NT_SUCCESS(status)) {
1050         pObject->DeleteObject();
1051         return status;
1052     }
1053 
1054     return pList->AddAt(Index, pObject);
1055 }
1056 
1057 _Must_inspect_result_
1058 __drv_maxIRQL(DISPATCH_LEVEL)
1059 NTSTATUS
1060 STDCALL
1061 WDFEXPORT(WdfCmResourceListInsertDescriptor)(
1062     __in
1063     PWDF_DRIVER_GLOBALS DriverGlobals,
1064     __in
1065     WDFCMRESLIST List,
1066     __in
1067     PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
1068     __in
1069     ULONG Index
1070     )
1071 /*++
1072 
1073 Routine Description:
1074     Inserts a descriptor into a cm resource list at a particular index.
1075 
1076 Arguments:
1077     ResourceList - list to be modified
1078 
1079     Descriptor - descriptor to insert
1080 
1081     Index - zero based index to insert at
1082 
1083 Return Value:
1084     NTSTATUS
1085 
1086   --*/
1087 {
1088     DDI_ENTRY();
1089 
1090     return FxCmResourceListInsertDescriptor(DriverGlobals,
1091                                             List,
1092                                             Descriptor,
1093                                             Index);
1094 }
1095 
1096 _Must_inspect_result_
1097 __drv_maxIRQL(DISPATCH_LEVEL)
1098 NTSTATUS
1099 STDCALL
1100 WDFEXPORT(WdfCmResourceListAppendDescriptor)(
1101     __in
1102     PWDF_DRIVER_GLOBALS DriverGlobals,
1103     __in
1104     WDFCMRESLIST List,
1105     __in
1106     PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
1107     )
1108 /*++
1109 
1110 Routine Description:
1111    Appends a descriptor to a cm resource list
1112 
1113 Arguments:
1114     ResourceList - list to be modified
1115 
1116     Descriptor - item to be appended
1117 
1118 Return Value:
1119     NTSTATUS
1120 
1121   --*/
1122 {
1123     DDI_ENTRY();
1124 
1125     return FxCmResourceListInsertDescriptor(DriverGlobals,
1126                                             List,
1127                                             Descriptor,
1128                                             WDF_INSERT_AT_END);
1129 }
1130 
1131 __drv_maxIRQL(DISPATCH_LEVEL)
1132 ULONG
1133 STDCALL
1134 WDFEXPORT(WdfCmResourceListGetCount)(
1135     __in
1136     PWDF_DRIVER_GLOBALS DriverGlobals,
1137     __in
1138     WDFCMRESLIST List
1139     )
1140 /*++
1141 
1142 Routine Description:
1143     Returns the number of cm descriptors in the resource list
1144 
1145 Arguments:
1146     ResourceList - resource list whose count will be returned
1147 
1148 Return Value:
1149     number of elements in the list
1150 
1151   --*/
1152 {
1153     FxCmResList* pList;
1154 
1155     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
1156                          List,
1157                          FX_TYPE_CM_RES_LIST,
1158                          (PVOID*) &pList);
1159 
1160     return pList->GetCount();
1161 }
1162 
1163 
1164 __drv_maxIRQL(DISPATCH_LEVEL)
1165 PCM_PARTIAL_RESOURCE_DESCRIPTOR
1166 STDCALL
1167 WDFEXPORT(WdfCmResourceListGetDescriptor)(
1168     __in
1169     PWDF_DRIVER_GLOBALS DriverGlobals,
1170     __in
1171     WDFCMRESLIST List,
1172     __in
1173     ULONG Index
1174     )
1175 /*++
1176 
1177 Routine Description:
1178     Retrieves a cm resource desciptor for a given index in the resource list
1179 
1180 Arguments:
1181     ResourceList - list being looked up
1182 
1183     Index - zero based index into the list to find the value of
1184 
1185 Return Value:
1186     pointer to a cm resource descriptor upon success, NULL upon error
1187 
1188   --*/
1189 {
1190     DDI_ENTRY();
1191 
1192     FxCmResList* pList;
1193 
1194     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
1195                          List,
1196                          FX_TYPE_CM_RES_LIST,
1197                          (PVOID*) &pList);
1198 
1199     return pList->GetDescriptor(Index);
1200 }
1201 
1202 __drv_maxIRQL(DISPATCH_LEVEL)
1203 VOID
1204 STDCALL
1205 WDFEXPORT(WdfCmResourceListRemove)(
1206     __in
1207     PWDF_DRIVER_GLOBALS DriverGlobals,
1208     __in
1209     WDFCMRESLIST List,
1210     __in
1211     ULONG Index
1212     )
1213 /*++
1214 
1215 Routine Description:
1216     Removes a descriptor in an cm resource list
1217 
1218 Arguments:
1219     ResourceList - resource list to modify
1220 
1221     Index - zero based index into the list in which to remove the descriptor
1222 
1223 Return Value:
1224     None
1225 
1226   --*/
1227 {
1228     DDI_ENTRY();
1229 
1230     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1231     FxCmResList* pList;
1232 
1233     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1234                                    List,
1235                                    FX_TYPE_CM_RES_LIST,
1236                                    (PVOID*) &pList,
1237                                    &pFxDriverGlobals);
1238 
1239     if (pList->RemoveAndDelete(Index) == FALSE) {
1240         DoTraceLevelMessage(
1241             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1242             "WDFCMRESLIST %p, could not remove list at index %d (not found), "
1243             "list item count is %d", List, Index, pList->Count());
1244 
1245         FxVerifierDbgBreakPoint(pFxDriverGlobals);
1246     }
1247 }
1248 
1249 __drv_maxIRQL(DISPATCH_LEVEL)
1250 VOID
1251 STDCALL
1252 WDFEXPORT(WdfCmResourceListRemoveByDescriptor)(
1253     __in
1254     PWDF_DRIVER_GLOBALS DriverGlobals,
1255     __in
1256     WDFCMRESLIST List,
1257     __in
1258     PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
1259     )
1260 /*++
1261 
1262 Routine Description:
1263     Removes a descriptor by value in a given cm resource list.  Equality is
1264     determined by RtlCompareMemory.
1265 
1266 Arguments:
1267     ResourceList - the io resource list to modify
1268 
1269     Descriptor - pointer to a descriptor to remove.
1270 
1271 Return Value:
1272     None
1273 
1274   --*/
1275 {
1276     DDI_ENTRY();
1277 
1278     PFX_DRIVER_GLOBALS pFxDriverGlobals;
1279     FxCollectionEntry* cur;
1280     FxCollectionEntry* end;
1281     FxCmResList* pList;
1282     FxResourceCm* pObject;
1283     KIRQL irql;
1284 
1285     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1286                                    List,
1287                                    FX_TYPE_CM_RES_LIST,
1288                                    (PVOID*) &pList,
1289                                    &pFxDriverGlobals);
1290 
1291     FxPointerNotNull(pFxDriverGlobals, Descriptor);
1292 
1293     if (pList->IsRemoveAllowed() == FALSE) {
1294         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1295                             "Removes not allowed on WDFCMRESLIST %p", List);
1296 
1297         FxVerifierDbgBreakPoint(pFxDriverGlobals);
1298         return;
1299     }
1300 
1301     pList->Lock(&irql);
1302 
1303     cur = pList->Start();
1304     end = pList->End();
1305     pObject = NULL;
1306 
1307     while (cur != end) {
1308         pObject = (FxResourceCm*) cur->m_Object;
1309 
1310         if (RtlCompareMemory(&pObject->m_Descriptor,
1311                              Descriptor,
1312                              sizeof(*Descriptor)) == sizeof(*Descriptor)) {
1313             pList->MarkChanged();
1314 
1315             pList->RemoveEntry(cur);
1316             break;
1317         }
1318 
1319         //
1320         // Set to NULL so that we do not delete it if this is the last item in
1321         // the list.
1322         //
1323         pObject = NULL;
1324 
1325         cur = cur->Next();
1326     }
1327 
1328     pList->Unlock(irql);
1329 
1330     if (pObject != NULL) {
1331         pObject->DeleteObject();
1332         pObject = NULL;
1333     }
1334 }
1335 
1336 } // extern "C"
1337