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