ReactOS 0.4.16-dev-319-g6cf4263
fxchildlist.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation. All rights reserved.
4
5Module Name:
6
7 FxChildList.cpp
8
9Abstract:
10
11 This module implements the FxChildList class
12
13Author:
14
15
16
17Environment:
18
19 Kernel mode only
20
21Revision History:
22
23--*/
24
25#include "fxcorepch.hpp"
26
27extern "C" {
28// #include "FxChildList.tmh"
29}
30
33 __in ULONG AddressDescriptionSize,
35 )
36{
39 this, WDF_ALIGN_SIZE_UP(sizeof(*this), sizeof(PVOID)));
40
42 AddressDescriptionSize;
43
48 WDF_ALIGN_SIZE_UP(AddressDescriptionSize, sizeof(PVOID)));
49
52 }
53
56
58
60
64
65 //
66 // The parent DO can go away while the child still exists (stuck in a
67 // suprise remove state w/an open handle). As such, when the parent is
68 // destroyed, it will release its reference on the FxChildList. Each
69 // description will have its own reference to the list to keep the list
70 // alive as long as the child DO exists.
71 //
72 m_DeviceList->ADDREF(this);
73}
74
76{
77 m_DeviceList->RELEASE(this);
78}
79
82FxDeviceDescriptionEntry::operator new(
83 __in size_t AllocatorBlock,
84 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
85 __in size_t TotalDescriptionSize
86 )
87{
88 PVOID p;
89
90 UNREFERENCED_PARAMETER(AllocatorBlock);
91
92 p = FxPoolAllocate(FxDriverGlobals, NonPagedPool, TotalDescriptionSize);
93
94 if (p != NULL) {
95 RtlZeroMemory(p, TotalDescriptionSize);
96 }
97
98 return p;
99}
100
101VOID
103 VOID
104 )
105{
106 KIRQL irql;
107
111}
112
115 VOID
116 )
117/*++
118
119Routine Description:
120 This function tells the caller if the description has been reported missing
121 to the Pnp manager. It does not change the actual state of the description,
122 unlike IsDeviceRemoved().
123
124Arguments:
125 None
126
127Return Value:
128 TRUE if it has been reported missing, FALSE otherwise
129
130 --*/
131{
132 KIRQL irql;
134
137 result = TRUE;
138 }
139 else {
140 result = FALSE;
141 }
143
144 return result;
145}
146
149 VOID
150 )
151{
152 KIRQL irql;
153 BOOLEAN removed;
155
157 removed = FALSE;
159
161
163
165 //
166 // We should delete this entry as it was reported missing.
167 //
169
171
172 //
173 // Remove from the current list if no scan going on.
174 // Note that the description entry can't be removed from list if scan
175 // count is > 0 because it might be part of an iterator that driver is
176 // still using to iterate thru the child list.
177 //
178 if (pList->GetScanCount() == 0) {
179 //
180 // Remove from the current list
181 //
184 }
185 else {
186 //
187 // The entry will be removed and deleted when scan count goes to
188 // zero by the scanning thread, so make sure pdo deosn't reference
189 // the entry any more.
190 //
192 if (m_Pdo != NULL) {
194 }
195 }
196
197 removed = TRUE;
198
199 //
200 // No need to add a reference to m_DeviceList becuase as we hold a
201 // reference to it already. This reference is bound by the lifetime
202 // of this object, so we can always safely touch m_DeviceList even if
203 // the FDO is gone before the child is removed.
204 //
205 }
206
208
209 return removed;
210}
211
212VOID
214 VOID
215 )
216{
217 LIST_ENTRY freeHead;
218 KIRQL irql;
220
222
224 InitializeListHead(&freeHead);
226
227 //
228 // Remove from the current list. In some cases the entry may not be in any
229 // list in which case RemoveEntryList() will be a noop.
230 // Note that the description entry can't be removed from list if scan count
231 // is > 0 because it might be part of an iterator that driver is still using
232 // to iterate thru the child list.
233 //
236
237 //
238 // Instead of reimplementing a single description cleanup, just use the
239 // version which cleans up a list.
240 //
242 }
243 else {
244 //
245 // The entry will be removed when scan count goes to zero.
246 //
250 }
251
253
255}
256
260 __inout PLIST_ENTRY FreeListHead
261 )
262{
263 FxDeviceDescriptionEntry* pNewEntry;
265
266 pNewEntry = new(m_DeviceList->GetDriverGlobals(),
271
272 if (pNewEntry == NULL) {
273 return NULL;
274 }
275
278
282 }
283
284 if (NT_SUCCESS(status)) {
285 pNewEntry->m_FoundInLastScan = TRUE;
286 }
287 else {
288 //
289 // Free it later
290 //
291 InsertTailList(FreeListHead, &pNewEntry->m_DescriptionLink);
292 pNewEntry = NULL;
293 }
294
295 return pNewEntry;
296}
297
299 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
300 __in size_t TotalDescriptionSize,
303 ) :
305 m_TotalDescriptionSize(TotalDescriptionSize),
306 m_EvtCreateDevice(FxDriverGlobals),
307 m_EvtScanForChildren(FxDriverGlobals)
308{
309 //
310 // Transaction link into list of FxChildList pointers maintained by
311 // FxDevice's pnp package.
312 //
314
316
319
324
328
332
334
338
339 m_EnumRetries = 0;
340
341 m_ScanTag = NULL;
342 m_ScanCount = 0;
343
344 //
345 // We want all waiters on the event to be satisfied, not just the first one
346 //
348
350}
351
354 VOID
355 )
356{
357 if (m_IsAdded) {
358 ASSERT(m_Device != NULL);
360 }
361
362 return TRUE;
363}
364
369 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
370 __in PWDF_OBJECT_ATTRIBUTES ListAttributes,
371 __in size_t TotalDescriptionSize,
373 __in PWDF_CHILD_LIST_CONFIG ListConfig,
375 )
376{
377 NTSTATUS ntStatus;
378 FxChildList *childList = NULL;
379
380 //
381 // Initialize
382 //
383 *ChildList = NULL;
384
385 //
386 // Allocate a new child list object
387 //
388 childList = new(FxDriverGlobals, ListAttributes)
389 FxChildList(FxDriverGlobals, TotalDescriptionSize, Device, Static);
390 if (childList == NULL) {
393 "No memory for WDFCHILDLIST handle, %!STATUS!",
394 ntStatus);
395 goto exit;
396 }
397
398 //
399 // Initialize the child list object
400 //
401 childList->Initialize(ListConfig);
402
403 *ChildList = childList;
404 ntStatus = STATUS_SUCCESS;
405
406exit:
407 if (!NT_SUCCESS(ntStatus)) {
408 if (NULL != childList) {
409 childList->DeleteFromFailedCreate();
410 }
411 }
412 return ntStatus;
413}
414
415VOID
418 )
419{
420 //
421 // Driver cannot call WdfObjectDelete on this handle
422 //
424
425 m_IdentificationDescriptionSize = Config->IdentificationDescriptionSize;
426 m_AddressDescriptionSize = Config->AddressDescriptionSize;
427
428 m_EvtCreateDevice.m_Method = Config->EvtChildListCreateDevice;
429 m_EvtScanForChildren.m_Method = Config->EvtChildListScanForChildren;
430
431 m_EvtIdentificationDescriptionDuplicate = Config->EvtChildListIdentificationDescriptionDuplicate;
432 m_EvtIdentificationDescriptionCopy = Config->EvtChildListIdentificationDescriptionCopy;
433 m_EvtIdentificationDescriptionCleanup = Config->EvtChildListIdentificationDescriptionCleanup;
434 m_EvtIdentificationDescriptionCompare = Config->EvtChildListIdentificationDescriptionCompare;
435
436 m_EvtAddressDescriptionDuplicate = Config->EvtChildListAddressDescriptionDuplicate;
437 m_EvtAddressDescriptionCopy = Config->EvtChildListAddressDescriptionCopy;
438 m_EvtAddressDescriptionCleanup = Config->EvtChildListAddressDescriptionCleanup;
439
440 m_EvtChildListDeviceReenumerated = Config->EvtChildListDeviceReenumerated;
441
442 //
443 // Add this ChildList to the parent device's list of children lists.
444 //
445 m_Device->AddChildList(this);
446 m_IsAdded = TRUE;
447}
448
449WDFDEVICE
451 VOID
452 )
453{
454 return m_Device->GetHandle();
455}
456
460 )
461{
465 KIRQL irql;
466
467 device = NULL;
468
470
472 Info->IdentificationDescription);
473
474 if (pEntry != NULL && pEntry->m_ModificationState == ModificationInsert) {
476 }
477 else {
479 Info->IdentificationDescription);
480
481 if (pEntry != NULL) {
482 if (pEntry->m_DescriptionState == DescriptionPresentNeedsInstantiation) {
484 }
485 else {
487 device = pEntry->m_Pdo;
488 }
489 }
490 else {
492 }
493 }
494
495 if (pEntry != NULL && Info->AddressDescription != NULL) {
496 CopyAddress(Info->AddressDescription,
497 pEntry->m_AddressDescription);
498 }
499
501
502 Info->Status = status;
503
504 return device;
505}
506
512 )
513{
516 KIRQL irql;
517
519
522
523 if (pEntry == NULL) {
526 }
527
528 if (pEntry != NULL) {
529 CopyAddress(AddressDescription, pEntry->m_AddressDescription);
531 }
532 else {
534 }
535
537
538 return status;
539}
540
541VOID
545 )
546{
547 KIRQL irql;
548
550 CopyAddress(AddressDescription, Entry->m_AddressDescription);
552}
553
554VOID
556 __out_opt PULONG ScanTag
557 )
558{
561 KIRQL irql;
562
564
565 // KeClearEvent is faster than KeResetEvent for putting event to not-signaled state
567 m_ScanCount++;
568
571 "Begin scan on WDFCHILDLIST %p, scan count %d",
573
574 if (ScanTag != NULL) {
575 if (m_ScanTag != NULL) {
577 }
578
579 *ScanTag = ScanTagActive;
580 m_ScanTag = ScanTag;
581 }
582
583 //
584 // Start by walking over all entries and setting their FoundInLastScan
585 // fields to FALSE. We need to set both present items in the Desc list
586 // and inserts in the Mod list. It's actually easier just to walk over
587 // everything.
588 //
591 ple = ple->Flink) {
593 pEntry->m_FoundInLastScan = FALSE;
594 }
595
598 ple = ple->Flink) {
600 pEntry->m_FoundInLastScan = FALSE;
601 }
602
604}
605
606VOID
608 __inout_opt PULONG ScanTag
609 )
610{
611 PLIST_ENTRY pCur, pNext;
612 LIST_ENTRY freeHead;
614 KIRQL irql;
615
616 InitializeListHead(&freeHead);
617
619
620 if (ScanTag != NULL) {
621 if (*ScanTag != ScanTagActive) {
622 ASSERT(*ScanTag == ScanTagCancelled);
624 return;
625 }
626
627 *ScanTag = ScanTagFinished;
628 m_ScanTag = NULL;
629 }
630
631 m_ScanCount--;
632
635 "End scan on WDFCHILDLIST %p, scan count %d",
637
638 if (m_ScanCount == 0) {
639 //
640 // Walk over all modification entries and remove any pending insert that
641 // wasn't seen in the scan. Note that MarkDescriptionNotPresentWorker will
642 // enqueue the entry to be freed later.
643 //
644 // Also, convert any clones of devices not reported as present to
645 // removal modifications so that the original is still reported missing.
646 //
649 pCur = pNext) {
650
651 pNext = pCur->Flink;
652
654
657 "entry %p modified in last scan, "
658 "mod state %!FxChildListModificationState!,"
659 "desc state %!FxChildListDescriptionState!",
660 pEntry, pEntry->m_ModificationState,
661 pEntry->m_DescriptionState);
662
663 if (pEntry->m_FoundInLastScan == FALSE) {
664 switch (pEntry->m_ModificationState) {
666 //
667 // Insertion that never made through to the end of a scan.
668 //
670 break;
671
675 "clone of PDO WDFDEVICE %p, !devobj %p dropped because "
676 "it is missing", pEntry->m_Pdo->GetHandle(),
677 pEntry->m_Pdo->GetDeviceObject());
678
679 //
680 // We were asked for a clone in the middle of a scan and the
681 // device was not reported, so it is now missing. Convert
682 // the clone modification to a remove modification.
683 //
684 pEntry->m_ModificationState = ModificationRemoveNotify;
685
686 //
687 // Remove the modification from the current mod list. It
688 // will be re-added below when we iterate over the
689 // descriptions list.
690 //
691 RemoveEntryList(&pEntry->m_ModificationLink);
692 InitializeListHead(&pEntry->m_ModificationLink);
693
694 //
695 // We can only have been cloning a device which is present
696 // and not yet reported missing to the OS.
697 //
698 ASSERT(pEntry->m_DescriptionState ==
700 break;
701 }
702 }
703 }
704
705 //
706 // Walk over all desc entries and remove anything that wasn't found in the
707 // scan. Since MarkDescriptionNotPresentWorker doesn't drain the
708 // modifications, we don't have to worry about any entries disappearing.
709 //
712 pCur = pCur->Flink) {
713
715
716 if (pEntry->m_PendingDeleteOnScanEnd) {
717 //
718 // The entry was pnp removed but was not removed from list
719 // because scan count was > 0. It is safe to remove and delete
720 // it now.
721
722 // Update the current pointer before the entry is removed.
723 pCur = pCur->Blink;
724
725 RemoveEntryList(&pEntry->m_DescriptionLink);
726 InsertTailList(&freeHead, &pEntry->m_DescriptionLink);
727 pEntry = NULL;
728 continue;
729 }
730 else if (pEntry->IsPresent() && pEntry->m_FoundInLastScan == FALSE) {
731 if (pEntry->m_Pdo != NULL) {
734 "marking PDO WDFDEVICE %p, !devobj %p as not present",
735 pEntry->m_Pdo->GetHandle(),
736 pEntry->m_Pdo->GetDeviceObject());
737
738 }
739 else {
742 "marking PDO (entry %p) which needs instantiation as "
743 "not present", pEntry);
744 }
745
747 }
748 }
749
750 //
751 // Attempt to drain any mods we made.
752 //
754
755 //
756 // We need to check m_KnownPdo here because if this
757 // object is attached to a PDO, the PDO's devobj could be in a state where
758 // PnP does not know it is a PDO yet. m_KnownPdo
759 // is set when the PDO receives a start device and by the time start
760 // device arrives, we definitely know the PDO is known the PnP.
761 //
762 // No need to hold a lock while checking m_KnownPdo
763 // because if miss the transition from FALSE to TRUE, relations will
764 // automaticaly be invalidated by the cause of that transition (start
765 // device arrival). PnP automatically sends a QDR after a successful
766 // start.
767 //
768
770 PDEVICE_OBJECT pdo;
771
772 //
773 // This does the m_KnownPdo check.
774 //
776
777 if (pdo != NULL) {
780 }
781 }
782
784 }
785
787
788 //
789 // Free structures outside of any internal WDF lock
790 //
791 DrainFreeListHead(&freeHead);
792}
793
794VOID
796 __in BOOLEAN EndTheScan,
797 __inout_opt PULONG ScanTag
798 )
799{
800 *ScanTag = ScanTagCancelled;
801
802 if (EndTheScan) {
803 EndScan(ScanTag);
804 }
805}
806
807VOID
810 )
811{
813
815 Iterator->Reserved[ModificationIndex] = ULongToPtr(1);
816 }
817}
818
819VOID
822 )
823{
824 KIRQL irql;
825
826 //
827 // Almost the same semantic as BeginScan except we don't mark all of the
828 // children as missing when we start.
829 //
831
833 //
834 // Set the scanevent to non-signaled state. Some code paths such as
835 // PDO eject will wait for the completion of child list iteration or scan
836 // so that a QDR that follows eject is guaranteed to pick up the change in
837 // PDO state that the code path made. Note that scan and iteration can be
838 // nested and in that case this event will be clear each time but it will be
839 // set (signalled) only after all the iteration and scan opeartions have
840 // completed.
841 //
843 m_ScanCount++;
844
846 "Begin iteration on WDFCHILDLIST %p, scan count %d",
848
850}
851
852VOID
855 )
856{
858 "end iteration on WDFCHILDLIST");
859
860 //
861 // Semantic is exactly the same as EndScan. Basically, all changes are
862 // delayed until there are no more active scans, so the end of an interation
863 // is the same as the end of a scan.
864 //
865 EndScan();
866
867 RtlZeroMemory(&Iterator->Reserved[0], sizeof(Iterator->Reserved));
868}
869
873 __out WDFDEVICE* Device,
876 )
877{
882 ULONG cur, i;
883 KIRQL irql;
884 BOOLEAN found;
885
886 pEntry = NULL;
888
890
891 ASSERT(m_ScanCount > 0);
892 if (m_ScanCount == 0) {
894
897 "WDFCHILDLIST %p cannot retrieve next device if the list is not "
898 "locked for iteration, %!STATUS!", GetHandle(), status);
899
900 goto Done;
901 }
902
904
905 if (ple != NULL) {
908 if (!NT_SUCCESS(status)) {
909 goto Done;
910 }
911 }
912
913 found = FALSE;
914
915 //
916 // Try to find the next entry
917 //
918 for (ple = ple->Flink; ple != &m_DescriptionListHead; ple = ple->Flink) {
920
921 if (pEntry->MatchStateToFlags(Iterator->Flags)) {
922 //
923 // An item was found
924 //
925 found = TRUE;
926
927 //
928 // Call the caller's compare function to further refine the match
929 // if necessary.
930 //
931 if (Info != NULL &&
932 Info->EvtChildListIdentificationDescriptionCompare != NULL) {
933
934 found = Info->EvtChildListIdentificationDescriptionCompare(
935 GetHandle(),
936 Info->IdentificationDescription,
937 pEntry->m_IdentificationDescription);
938 }
939
940 if (found) {
941 break;
942 }
943 }
944 }
945
946 if (found) {
947 //
948 // We can safely store the description entry because we are
949 // guaranteed it will stay in the description list until m_ScanCount
950 // reaches zero. In that case, the caller would need to call
951 // EndIteration
952 //
953 Iterator->Reserved[DescriptionIndex] = ple;
954
955 if (pEntry->m_Pdo != NULL) {
956 *Device = pEntry->m_Pdo->GetHandle();
958 }
959 else {
961 }
962
963 if (Info != NULL) {
964 if (Info->IdentificationDescription != NULL) {
965 CopyId(Info->IdentificationDescription,
966 pEntry->m_IdentificationDescription);
967 }
968 if (Info->AddressDescription != NULL) {
969 CopyAddress(Info->AddressDescription,
970 pEntry->m_AddressDescription);
971 }
972
973 Info->Status = dstatus;
974 }
975
977 }
978 else {
979 Iterator->Reserved[DescriptionIndex] = NULL;
980 ple = NULL;
982 }
983 }
984
986
987 if ((Iterator->Flags & WdfRetrievePendingChildren) == 0 ||
988 cur == 0) {
989 goto Done;
990 }
991
992
993 //
994 // Walk the modification list. Since this list can change from call to call
995 // to GetNextDevice we can't rely on the previous entry still being present
996 // so we must use an index into the list. This is not guaranteed to
997 // enumerate all pending additions, but it should be good enough.
998 //
999 found = FALSE;
1000
1001 for (i = 1, ple = m_ModificationListHead.Flink;
1003 ple = ple->Flink) {
1004
1006
1007 if (pEntry->m_ModificationState == ModificationInsert) {
1008 i++;
1009
1010 if (i > cur) {
1011 found = TRUE;
1012
1013 if (Info != NULL &&
1014 Info->EvtChildListIdentificationDescriptionCompare != NULL) {
1015
1016 found = Info->EvtChildListIdentificationDescriptionCompare(
1017 GetHandle(),
1018 Info->IdentificationDescription,
1019 pEntry->m_IdentificationDescription);
1020 }
1021
1022 if (found) {
1023 //
1024 // Store the next item number
1025 //
1026 Iterator->Reserved[ModificationIndex] = ULongToPtr(i);
1027
1028 if (Info != NULL) {
1029 if (Info->IdentificationDescription != NULL) {
1030 CopyId(Info->IdentificationDescription,
1031 pEntry->m_IdentificationDescription);
1032 }
1033 if (Info->AddressDescription != NULL) {
1034 CopyAddress(Info->AddressDescription,
1035 pEntry->m_AddressDescription);
1036 }
1037
1039 }
1040
1042 break;
1043 }
1044 }
1045 }
1046 }
1047
1048 if (found == FALSE) {
1049 Iterator->Reserved[ModificationIndex] = ULongToPtr(0);
1050 }
1051
1052Done:
1054
1055 return status;
1056}
1057
1058WDFDEVICE
1060 __in WDFDEVICE PreviousDevice,
1062 )
1063{
1064 FxStaticChildDescription *pStatic;
1066 WDFDEVICE result;
1068 KIRQL irql;
1069 BOOLEAN isNext;
1070
1072
1073 result = NULL;
1074
1075 if (PreviousDevice == NULL) {
1076 //
1077 // No previous handle, we want the first device we find
1078 //
1079 isNext = TRUE;
1080 }
1081 else {
1082 //
1083 // We have a previuos handle, find it in the list first before setting
1084 // isNext.
1085 //
1086 isNext = FALSE;
1087 }
1088
1090
1091 ASSERT(m_ScanCount > 0);
1092 if (m_ScanCount == 0) {
1093 goto Done;
1094 }
1095
1096 //
1097 // Try to find the next entry
1098 //
1102 ple = ple->Flink) {
1104
1105 //
1106 // If the entry is marked pending delete, skip it, because the
1107 // relationship between entry and its PDO has been removed and PDO
1108 // may have actually been deleted by this time. The only reason
1109 // this entry is here is because there is still a scan going on
1110 // and the entry can't be removed in the midst of a scan.
1111 //
1112 if (pEntry->m_PendingDeleteOnScanEnd) {
1113 continue;
1114 }
1115
1116 pStatic = CONTAINING_RECORD(pEntry->m_IdentificationDescription,
1118 Header);
1119
1120 //
1121 // Only return a handle if it is in a state in which the caller is
1122 // interested in hearing about.
1123 //
1124 if (isNext && pEntry->MatchStateToFlags(Flags)) {
1125 result = pStatic->Pdo->GetHandle();
1126 break;
1127 }
1128 else if (pStatic->Pdo->GetHandle() == PreviousDevice) {
1129 isNext = TRUE;
1130 }
1131 }
1132 }
1133
1134 //
1135 // We have taken care of all the other states (reported, pending removal,
1136 // removed) in the previuos loop.
1137 //
1139 //
1140 // Walk the modification list. Since this list can change from call to
1141 // call, there is no way to definitively give the driver a snapshot of
1142 // this list of modifications.
1143 //
1146 ple = ple->Flink) {
1147
1149
1150 if (pEntry->m_PendingDeleteOnScanEnd) {
1151 continue;
1152 }
1153
1154 pStatic = CONTAINING_RECORD(pEntry->m_IdentificationDescription,
1156 Header);
1157
1158 //
1159 // Only return a handle if it is in a state in which the caller is
1160 // interested in hearing about.
1161 //
1162 if (isNext && pEntry->m_ModificationState == ModificationInsert) {
1163 result = pStatic->Pdo->GetHandle();
1164 break;
1165 }
1166 else if (pStatic->Pdo->GetHandle() == PreviousDevice) {
1167 isNext = TRUE;
1168 }
1169 }
1170 }
1171
1172Done:
1174
1175 return result;
1176}
1177
1182 )
1183{
1185 LIST_ENTRY freeHead;
1187 KIRQL irql;
1188
1189 //
1190 // Assume success
1191 //
1193 InitializeListHead(&freeHead);
1194
1196
1198
1199 if (pEntry != NULL) {
1200
1201
1202
1203
1204
1205
1206
1207
1209 }
1210 else {
1212
1213 if (pEntry != NULL) {
1214 if (pEntry->IsPresent()) {
1216 }
1217 }
1218 else {
1219 //
1220 // Couldn't find anything
1221 //
1223 }
1224 }
1225
1226 ProcessModificationsLocked(&freeHead);
1227
1229
1230 DrainFreeListHead(&freeHead);
1231
1232 return status;
1233}
1234
1239 )
1240/*++
1241
1242Routine Description:
1243 Same as UpdateAsMissing except instead of a device description, we have the
1244 device itself.
1245
1246Arguments:
1247 Device - the device to mark as missing
1248
1249Return Value:
1250 NTSTATUS
1251
1252 --*/
1253{
1255 LIST_ENTRY freeHead, *ple;
1256 KIRQL irql;
1257 BOOLEAN found;
1258 CfxDevice *pdo;
1259
1260 found = FALSE;
1261 pdo = NULL;
1262 InitializeListHead(&freeHead);
1263
1265
1268 ple = ple->Blink) {
1269
1271
1272 //
1273 // Static PDO may not be populated in m_Pdo yet, so check the PDO
1274 // from id description.
1275 //
1276 if (m_StaticList) {
1277 pdo = CONTAINING_RECORD(pEntry->m_IdentificationDescription,
1279 Header)->Pdo;
1280 }
1281 else {
1282 pdo = pEntry->m_Pdo;
1283 }
1284
1285 if (pdo == Device) {
1286 found = TRUE;
1288 break;
1289 }
1290 }
1291
1292 if (found == FALSE) {
1295 ple = ple->Blink) {
1296
1298
1299 //
1300 // Static PDO may not be populated in m_Pdo yet, so check the PDO
1301 // from id description.
1302 //
1303 if (m_StaticList) {
1304 pdo = CONTAINING_RECORD(pEntry->m_IdentificationDescription,
1306 Header)->Pdo;
1307 }
1308 else {
1309 pdo = pEntry->m_Pdo;
1310 }
1311
1312 if (pdo == Device) {
1313 found = TRUE;
1314
1315 if (pEntry->IsPresent()) {
1317 }
1318
1319 break;
1320 }
1321 }
1322 }
1323
1324 ProcessModificationsLocked(&freeHead);
1325
1327
1328 DrainFreeListHead(&freeHead);
1329
1330 if (found) {
1331 return STATUS_SUCCESS;
1332 }
1333 else {
1334 return STATUS_NO_SUCH_DEVICE;
1335 }
1336}
1337
1338BOOLEAN
1341 __in BOOLEAN FromQDR
1342 )
1343{
1345
1346 //
1347 // Check to see if there are modifications pending
1348 //
1349 if (IsListEmpty(&Entry->m_ModificationLink) && Entry->IsPresent()) {
1350 //
1351 // No mods pending...
1352 //
1353
1354 //
1355 // We can only go down this path if the device was reported to the system
1356 // b/c the stack on our PDO is the one invoking this call.
1357 //
1358 ASSERT(Entry->m_DescriptionState == DescriptionInstantiatedHasObject);
1359
1360 if (FromQDR == FALSE) {
1361 //
1362 // The entry has not been reported as missing by the driver, try to
1363 // clone it and insert a modification.
1364 //
1365 Entry->m_ModificationState = ModificationClone;
1366 InsertTailList(&m_ModificationListHead, &Entry->m_ModificationLink);
1367 }
1368
1371 "Inserting clone modification for PDO WDFDEVICE %p, !devobj %p",
1372 Entry->m_Pdo->GetHandle(), Entry->m_Pdo->GetDeviceObject());
1373
1374 result = TRUE;
1375 }
1376 else {
1377 //
1378 // If there is a pending modification, we don't do anything.
1379 // If the device is already not present, we don't do anything.
1380 //
1381 // ModficiationRemove or
1382 // ModficiationRemoveNotify: we would be reenumerating a device which
1383 // is being removed which is not what we want
1384 //
1385 // ModificationClone: we would be cloning a clone which is not what
1386 // we want either
1387 //
1390 "Requested reenumeration for PDO WDFDEVICE %p, !devobj %p"
1391 " no possible (pending mod %d, currently present %d)",
1392 Entry->m_Pdo->GetHandle(), Entry->m_Pdo->GetDeviceObject(),
1393 IsListEmpty(&Entry->m_ModificationLink), Entry->IsPresent());
1394
1395 result = FALSE;
1396 }
1397
1398 return result;
1399}
1400
1401VOID
1404 )
1405{
1406 LIST_ENTRY freeHead;
1407 KIRQL irql;
1408
1409 InitializeListHead(&freeHead);
1410
1413 ProcessModificationsLocked(&freeHead);
1415
1416 DrainFreeListHead(&freeHead);
1417}
1418
1419
1420VOID
1422 __in_opt PULONG ScanTag
1423 )
1424{
1425 PLIST_ENTRY pCur, pNext;
1426 LIST_ENTRY freeHead;
1428 KIRQL irql;
1429
1431
1432 if (ScanTag != NULL) {
1433 if (*ScanTag != ScanTagActive) {
1434 ASSERT(*ScanTag == ScanTagCancelled);
1436 return;
1437 }
1438 }
1439
1440 //
1441 // Walk over all mod entries and ensure any inserts are still marked
1442 // present.
1443 //
1446 pCur = pNext) {
1447
1448 pNext = pCur->Flink;
1449
1451
1452 if (pEntry->m_ModificationState == ModificationInsert) {
1453 pEntry->m_FoundInLastScan = TRUE;
1454 }
1455 }
1456
1457 //
1458 // Walk over all desc entries and ensure they are marked present.
1459 //
1462 pCur = pCur->Flink) {
1463
1465
1466 if (pEntry->IsPresent()) {
1467 ASSERT(pEntry->m_ModificationState != ModificationRemoveNotify);
1468
1469 if (pEntry->m_ModificationState != ModificationRemove) {
1470 pEntry->m_FoundInLastScan = TRUE;
1471 }
1472 }
1473 }
1474
1475 //
1476 // Attempt to drain any mods we made.
1477 //
1478 InitializeListHead(&freeHead);
1479 ProcessModificationsLocked(&freeHead);
1480
1482
1483 DrainFreeListHead(&freeHead);
1484}
1485
1491 __in_opt PULONG ScanTag
1492 )
1493{
1494 LIST_ENTRY freeHead;
1495 KIRQL irql;
1498 BOOLEAN allocNewEntry;
1499
1500 if (ScanTag != NULL) {
1501 if (*ScanTag != ScanTagActive) {
1502 ASSERT(*ScanTag == ScanTagCancelled);
1503
1504 //
1505 // The descriptions are duplicated if needed, so no need to clean
1506 // them up
1507 //
1508 // CleanupDescriptions(IdentificationDescription,
1509 // AddressDescription);
1510
1511 return STATUS_CANCELLED;
1512 }
1513 }
1514
1516 allocNewEntry = FALSE;
1517 InitializeListHead(&freeHead);
1518
1520
1523 );
1524
1525 if (pEntry != NULL) {
1526 switch (pEntry->m_ModificationState) {
1527 case ModificationInsert:
1528 if (HasAddressDescriptions()) {
1529 CopyAddress(pEntry->m_AddressDescription,
1531 }
1532
1533 //
1534 // There is already a pending insert operation. All we need do is
1535 // update the stored description.
1536 //
1537 pEntry->m_FoundInLastScan = TRUE;
1538
1540 break;
1541
1542 case ModificationRemove:
1544 //
1545 // We found a pending remove. Therefore we need to add an insert
1546 // operation to the end of the mod list.
1547 //
1548 allocNewEntry = TRUE;
1549 break;
1550
1551 default:
1552 ASSERTMSG("Invalid description modification state\n", FALSE);
1553 break;
1554 }
1555 }
1556 else {
1557 //
1558 // There are no matching modifications queued in the list. Go examine
1559 // the main list. We can't modify any of the child links right now
1560 // because the list might be locked down, but it is scannable!
1561 //
1564 );
1565
1566 if (pEntry != NULL && pEntry->IsPresent()) {
1567 //
1568 // This is an update. Enqueue it through this node.
1569 //
1570 ASSERT(pEntry->m_ModificationState == ModificationUnspecified);
1571
1572 if (HasAddressDescriptions()) {
1573 CopyAddress(pEntry->m_AddressDescription,
1575 }
1576
1577 pEntry->m_FoundInLastScan = TRUE;
1579 }
1580 else {
1581 //
1582 // Either no entry was found, or a "missing" entry was identified
1583 // instead. In both cases we need to add an insert operation to the
1584 // end of the modification list.
1585 //
1586 allocNewEntry = TRUE;
1587 }
1588 }
1589
1590 if (allocNewEntry) {
1591
1592 pEntry =
1597
1598 if (pEntry != NULL) {
1599 status = DuplicateId(pEntry->m_IdentificationDescription,
1601
1603 status = DuplicateAddress(pEntry->m_AddressDescription,
1605 }
1606
1607 if (NT_SUCCESS(status)) {
1608 pEntry->m_FoundInLastScan = TRUE;
1610 &pEntry->m_ModificationLink);
1611
1612 if (m_StaticList) {
1613 FxDevice* pPdo;
1614
1615 pPdo = CONTAINING_RECORD(pEntry->m_IdentificationDescription,
1617 Header)->Pdo;
1618
1619 //
1620 // The device is no longer deletable by the driver writer
1621 //
1623
1624 //
1625 // Plug in the description like we do for dynamic PDOs in
1626 // FxPkgPdo::Initialize.
1627 //
1629
1630 //
1631 // Let the device know it was inserted into the list. This
1632 // used to know in pPdo::DeleteObject how to proceed.
1633 //
1635 }
1636 }
1637 else {
1638 InsertTailList(&freeHead, &pEntry->m_DescriptionLink);
1639 }
1640 }
1641 else {
1643 }
1644 }
1645
1646 ProcessModificationsLocked(&freeHead);
1647
1649
1650 DrainFreeListHead(&freeHead);
1651
1652 return status;
1653}
1654
1655VOID
1659 )
1660{
1661 KIRQL irql;
1662
1664 CopyAddress(Entry->m_AddressDescription, AddressDescription);
1666
1667
1668
1669
1670
1671
1672}
1673
1674BOOLEAN
1676 __inout PLIST_ENTRY FreeListHead,
1678 __in BOOLEAN FromQDR
1679 )
1680{
1682 BOOLEAN invalidateRelations;
1683
1686 "attempting to clone PDO WDFDEVICE %p, !devobj %p, From QDR %d",
1687 Entry->m_Pdo->GetHandle(), Entry->m_Pdo->GetDeviceObject(), FromQDR);
1688
1689 invalidateRelations = FALSE;
1690
1691 pClone = Entry->Clone(FreeListHead);
1692
1693 if (pClone != NULL) {
1694 //
1695 // Check to see if the driver writer OKs the cloning, aka
1696 // reenumeration.
1697 //
1700 GetHandle(),
1701 Entry->m_Pdo->GetHandle(),
1702 Entry->m_AddressDescription,
1703 pClone->m_AddressDescription) == FALSE){
1704 //
1705 // The clone will be freed later by the caller by placing
1706 // it on the free list.
1707 //
1708 InsertTailList(FreeListHead, &pClone->m_DescriptionLink);
1709 }
1710 else {
1713 "clone successful (new entry is %p), marking PDO "
1714 "WDFDEVICE %p, !devobj %p as missing", pClone,
1715 Entry->m_Pdo->GetHandle(), Entry->m_Pdo->GetDeviceObject());
1716
1717 //
1718 // Setup the state of the clone
1719 //
1722
1723 //
1724 // This is important that this is last. If a subsequent
1725 // modification arrives for this device, we want to find the
1726 // clone before the old device. Since all changes search the
1727 // list backwards, inserting at the tail accomplishes this.
1728 //
1730 &pClone->m_DescriptionLink);
1731
1732 if (FromQDR == FALSE) {
1733 Entry->m_DescriptionState = DescriptionNotPresent;
1734 invalidateRelations = TRUE;
1735 }
1736 }
1737 }
1738 else {
1739 //
1740 // Could not allocate a clone, do not anything.
1741 //
1742 DO_NOTHING();
1743 }
1744
1745 //
1746 // Convert the original device's modification state back to a
1747 // unspecified in all cases.
1748 //
1749 Entry->m_ModificationState = ModificationUnspecified;
1750
1751 return invalidateRelations;
1752}
1753
1754VOID
1756 __inout PLIST_ENTRY FreeListHead
1757 )
1758{
1760 PLIST_ENTRY pCur, pNext;
1761 BOOLEAN invalidateRelations;
1762
1763 //
1764 // If the list is locked or there are still active scans, we must not process
1765 // any modifications.
1766 //
1767 if (m_State != ListUnlocked || m_ScanCount > 0) {
1770 "Not processing modifications on WDFCHILDLIST %p (list state %d, "
1771 "scan count %d)", GetObjectHandle(), m_State, m_ScanCount);
1772 return;
1773 }
1774
1777 "Begin processing modifications on WDFCHILDLIST %p", GetObjectHandle());
1778
1779 //
1780 // First do the mod updates. As quick as possible. Note that we need to
1781 // update
1782 //
1785 pCur = pNext) {
1786
1787 pNext = pCur->Flink;
1788
1790
1791 switch (pEntry->m_ModificationState) {
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808 pEntry->m_ModificationState = ModificationRemove;
1809 break;
1810
1811 default:
1812 break;
1813 }
1814 }
1815
1816 invalidateRelations = FALSE;
1819
1822
1823 ASSERT(pEntry->m_ModificationState == ModificationInsert ||
1824 pEntry->m_ModificationState == ModificationClone ||
1825 pEntry->m_ModificationState == ModificationRemove);
1826
1829 "entry %p, mod state is %!FxChildListModificationState!",
1830 pEntry, pEntry->m_ModificationState);
1831
1832 switch (pEntry->m_ModificationState) {
1833 case ModificationRemove:
1834 //
1835 // Remove's are stacked on top of the entry they need to take out.
1836 //
1837 ASSERT(pEntry->IsPresent());
1838
1839 pEntry->m_ModificationState = ModificationUnspecified;
1840
1843 "processing remove on entry %p, description state is "
1844 "%!FxChildListDescriptionState!",
1845 pEntry, pEntry->m_DescriptionState);
1846
1847 switch (pEntry->m_DescriptionState) {
1849 //
1850 // We got to the entry before a DO could be created for it or
1851 // an instantiation failed. If deleeted before creation, the
1852 // list entry points to itself. If the instantiation failed,
1853 // the list entry is in the description list and must be
1854 // removed from it.
1855 //
1856 // Mark it for deletion now (outside of the lock being held).
1857 //
1860 "entry %p never reported to pnp, mark for deletion", pEntry);
1861
1862 RemoveEntryList(&pEntry->m_DescriptionLink);
1863 InsertTailList(FreeListHead, &pEntry->m_DescriptionLink);
1864 break;
1865
1869 "committing PDO WDFDEVICE %p, !devobj %p as not present",
1870 pEntry->m_Pdo->GetHandle(), pEntry->m_Pdo->GetDeviceObject());
1871
1872 pEntry->m_DescriptionState = DescriptionNotPresent;
1873 invalidateRelations = TRUE;
1874 break;
1875
1876 default:
1877 ASSERTMSG("Invalid description state\n", FALSE);
1878 break;
1879 }
1880
1881 break;
1882
1883 case ModificationInsert:
1884 //
1885 // CurEntry is our entry to insert into the list. We simply "move"
1886 // the mod entries to desc entries.
1887 //
1888 ASSERT(pEntry->m_DescriptionState == DescriptionUnspecified);
1889 pEntry->m_DescriptionState = DescriptionPresentNeedsInstantiation;
1890
1893 "marking entry %p as needing instantiation", pEntry);
1894
1895 InsertTailList(&m_DescriptionListHead, &pEntry->m_DescriptionLink);
1896 pEntry->m_ModificationState = ModificationUnspecified;
1897 invalidateRelations = TRUE;
1898 break;
1899
1900 case ModificationClone:
1901 invalidateRelations = CloneEntryLocked(FreeListHead, pEntry, FALSE);
1902 break;
1903
1904 default:
1905 ASSERTMSG("Invalid description modification state\n", FALSE);
1906 break;
1907 }
1908 }
1909
1910 if (invalidateRelations) {
1911 PDEVICE_OBJECT pdo;
1912
1913 if (m_ScanCount) {
1915 }
1916 else if ((pdo = m_Device->GetSafePhysicalDevice()) != NULL) {
1917 //
1918 // See previous usage of m_Device->m_KnownPdo for
1919 // comments on why a lock is not necessary when reading its value.
1920 //
1923 }
1924 else {
1926 }
1927 }
1928
1931 "end processing modifications on WDFCHILDLIST %p", GetObjectHandle());
1932}
1933
1934VOID
1936 __inout FxDeviceDescriptionEntry* DescriptionEntry,
1937 __in BOOLEAN ModificationCanBeQueued
1938 )
1939/*++
1940
1941Routine Description:
1942
1943 This worker function marks the passed in mod or desc entry in the device
1944 list "not present". The change is enqueued in the mod list but the mod
1945 list is not drained.
1946
1947Arguments:
1948
1949 DescriptionEntry - Entry to be marked as "not present".
1950
1951 ModificationCanBeQueued - whether the caller allows for this description
1952 to be a modification already queued on the modification list
1953
1954Assumes:
1955 DescriptionEntry->IsPresent() == TRUE
1956
1957Return Value:
1958 None
1959
1960--*/
1961{
1962 BOOLEAN queueMod;
1963
1964 ASSERT(DescriptionEntry->IsPresent());
1965
1966 queueMod = FALSE;
1967
1968 if (ModificationCanBeQueued) {
1969 if (IsListEmpty(&DescriptionEntry->m_ModificationLink)) {
1970 queueMod = TRUE;
1971 }
1972 else {
1973 //
1974 // If the modification is queued, it must be removal
1975 //
1976 ASSERT(DescriptionEntry->m_ModificationState ==
1978 ASSERT(DescriptionEntry->m_FoundInLastScan == FALSE);
1979 }
1980 }
1981 else {
1982 queueMod = TRUE;
1983 }
1984
1985 if (queueMod) {
1986 ASSERT(IsListEmpty(&DescriptionEntry->m_ModificationLink));
1987 ASSERT(DescriptionEntry->m_ModificationState == ModificationUnspecified);
1988
1989 //
1990 // Add a removal modification entry into the modification list.
1991 // The ModificationRemoveNotify state will be converted into
1992 // ModificationRemove later while the list lock is still being held.
1993 //
1994 DescriptionEntry->m_ModificationState = ModificationRemoveNotify;
1995 DescriptionEntry->m_FoundInLastScan = FALSE;
1996
1998 &DescriptionEntry->m_ModificationLink);
1999 }
2000}
2001
2002VOID
2004 __inout PLIST_ENTRY FreeListHead,
2005 __inout FxDeviceDescriptionEntry* ModificationEntry
2006 )
2007/*++
2008
2009Routine Description:
2010
2011 This worker function marks the passed in mod or desc entry in the device
2012 list "not present". The change is enqueued in the mod list but the mod
2013 list is not drained.
2014
2015Arguments:
2016
2017 FreeListHead - Free list of entries.
2018
2019 ModificationEntry - Entry to be marked as "not present".
2020
2021Return Value:
2022 None
2023
2024--*/
2025{
2026 switch (ModificationEntry->m_ModificationState) {
2027 case ModificationInsert:
2028 //
2029 // This one was never reported to the OS. Remove it now.
2030 //
2031 RemoveEntryList(&ModificationEntry->m_ModificationLink);
2032 InitializeListHead(&ModificationEntry->m_ModificationLink);
2033
2034 if (IsStaticList()) {
2035 //
2036 // There is a corner case of a static PDO being added and
2037 // immediately marked as missing before it has a chance to move to
2038 // description list. This case is handled here by marking the
2039 // modification state to ModificationNeedsPnpRemoval. Fx cannot just
2040 // delete the description because there is a driver-created PDO
2041 // associated with the description and it needs to be cleaned up.
2042 //
2043 ModificationEntry->m_ModificationState = ModificationNeedsPnpRemoval;
2044 ASSERT(ModificationEntry->m_DescriptionState == DescriptionUnspecified);
2045 }
2046
2047 ASSERT(IsListEmpty(&ModificationEntry->m_DescriptionLink));
2048 InsertTailList(FreeListHead, &ModificationEntry->m_DescriptionLink);
2049 break;
2050
2051 case ModificationClone:
2052 //
2053 // In between the PDOs stack asking for a reenumeration and applying
2054 // this change, the bus driver has reported the child as missing.
2055 // Convert the clone modification to a removal modification.
2056 //
2057
2058 //
2059 // MarkDescriptionNotPresentWorker expects that m_ModificationEntry is
2060 // not in any list and points to itself.
2061 //
2062 RemoveEntryList(&ModificationEntry->m_ModificationLink);
2063 InitializeListHead(&ModificationEntry->m_ModificationLink);
2064
2065 MarkDescriptionNotPresentWorker(ModificationEntry, FALSE);
2066 break;
2067
2068 default:
2069 DO_NOTHING();
2070 break;
2071 }
2072}
2073
2074VOID
2076 __inout PLIST_ENTRY FreeListHead
2077 )
2078{
2080 FxDevice* pPdo;
2082
2083 while (!IsListEmpty(FreeListHead)) {
2084 pCur = RemoveHeadList(FreeListHead);
2086
2088
2089 //
2090 // If this is a static list and the entry has not yet been instantiated,
2091 // tell PnP to remove the device.
2092 //
2093 // There is a corner case of a static PDO being added and
2094 // immediately marked as missing before it has a chance to move to
2095 // description list. This case is handled here by checking the
2096 // modification state of ModificationNeedsPnpRemoval. Fx cannot just
2097 // delete the description because there is a driver-created PDO
2098 // associated with the description and it needs to be cleaned up.
2099 //
2100 if (m_StaticList &&
2101 (pEntry->m_DescriptionState == DescriptionPresentNeedsInstantiation ||
2102 pEntry->m_ModificationState == ModificationNeedsPnpRemoval )) {
2103
2104 pPdo = CONTAINING_RECORD(pEntry->m_IdentificationDescription,
2106 Header)->Pdo;
2107
2108 //
2109 // The pnp removal path expects that there is no modifcation pending
2110 // when removing the description.
2111 //
2112 if (pEntry->m_ModificationState == ModificationNeedsPnpRemoval) {
2113 ASSERT(pEntry->m_DescriptionState == DescriptionUnspecified);
2114 ASSERT(IsListEmpty(&pEntry->m_ModificationLink));
2115
2116 pEntry->m_ModificationState = ModificationUnspecified;
2117 }
2118
2119 //
2120 // Change the state to reported missing (which is what we are basically
2121 // simulating here anyways) so that when we process the entry again
2122 // when the PDO really goes away we cleanup the entry.
2123 //
2124 // Also, when posting PnpEventRemove to the child, child will
2125 // call FxDeviceDescriptionEntry::IsDeviceRemoved which checks for
2126 // reported missing before reporting if the device has been removed
2127 // (and we want the device to be reported as removed).
2128 //
2129 pEntry->m_DescriptionState = DescriptionReportedMissing;
2130
2131 //
2132 // Not yet reported to PnP, so it should be in the initial state
2133 //
2135
2136 //
2137 // m_Description should be set when the FxPkgPdo was created
2138 //
2140
2141 //
2142 // Since the pPdo->m_PkgPnp->m_DeviceRemoveProcessed == NULL, the
2143 // pnp state machine will delete the PDO. We are simulating the same
2144 // situation where an FDO is in the remove path and is telling each
2145 // of its removed PDOs to delete themselves.
2146 //
2148 }
2149 else {
2150 CleanupDescriptions(pEntry->m_IdentificationDescription,
2151 pEntry->m_AddressDescription);
2152
2153 delete pEntry;
2154 }
2155 }
2156}
2157
2161 )
2162{
2165
2168 ple = ple->Blink) {
2169
2171
2172 if (CompareId(pEntry->m_IdentificationDescription, Id)) {
2173 return pEntry;
2174 }
2175 }
2176
2177 return NULL;
2178}
2179
2183 )
2184{
2187
2190 ple = ple->Blink) {
2191
2193
2194 if (CompareId(pEntry->m_IdentificationDescription, Id)) {
2195 return pEntry;
2196 }
2197 }
2198
2199 return NULL;
2200}
2201
2206 )
2207{
2208 if (Entry == &m_DescriptionListHead) {
2209 return STATUS_SUCCESS;
2210 }
2211 else {
2213
2216 ple = ple->Flink) {
2217 if (Entry == ple) {
2218 return STATUS_SUCCESS;
2219 }
2220 }
2221
2223 }
2224}
2225
2230 )
2231{
2232 if (Entry == &m_ModificationListHead) {
2233 return STATUS_SUCCESS;
2234 }
2235 else {
2237
2240 ple = ple->Flink) {
2241 if (Entry == ple) {
2242 return STATUS_SUCCESS;
2243 }
2244 }
2245
2247 }
2248}
2249
2250BOOLEAN
2253 __inout PBOOLEAN InvalidateRelations
2254 )
2255{
2258 KIRQL irql;
2259
2260 init.CreatedOnStack = TRUE;
2261 init.SetPdo(m_Device);
2262 init.Pdo.DescriptionEntry = Entry;
2263
2264 if (m_StaticList) {
2265 init.CreatedDevice =
2266 CONTAINING_RECORD(Entry->m_IdentificationDescription,
2268 Header)->Pdo;
2269 }
2270 else {
2271 //
2272 // This description needs a device, create it now.
2273 //
2275 GetHandle(), Entry->m_IdentificationDescription, &init);
2276
2277 if (status == STATUS_RETRY) {
2278 if (init.CreatedDevice != NULL) {
2279 //
2280 // Destroy any allocations assocated with the device.
2281 //
2282 init.CreatedDevice->Destroy();
2283 }
2284
2285 *InvalidateRelations = TRUE;
2286
2287 return FALSE;
2288 }
2289
2290 if (NT_SUCCESS(status)) {
2291 //
2292 // Make sure that a framework device was actually created
2293 //
2294 if (init.CreatedDevice == NULL) {
2295 //
2296 // Driver didn't actually create the device, even though its
2297 // EvtChildListCreateDevice returned a successful return code.
2298 // Change the status to indicate an error, so that we enter the
2299 // error handling code below.
2300 //
2303 "EvtChildListCreateDevice returned a successful status "
2304 "%!STATUS! but did not create a device object", status);
2305
2307
2309 }
2310 }
2311
2312 if (!NT_SUCCESS(status)) {
2313 if (init.CreatedDevice != NULL) {
2315 //
2316 // Set to missing so that when the pnp machine evaluates whether the
2317 // PDO has been reported missing or not, it chooses missing and
2318 // deletes the PDO immediately.
2319 //
2320 Entry->m_DescriptionState = DescriptionReportedMissing;
2321
2322 if (Entry->m_ModificationState != ModificationUnspecified) {
2323 //
2324 // Cannot be ModificationInsert since this device ID is already
2325 // in the list.
2326 //
2327 // Cannot be ModificationClone since the FDO for this device
2328 // is the only one who can ask for that and since PDO creation
2329 // failed, there is no FDO.
2330 //
2331 // Cannot be ModificationRemove because the list is locked
2332 // against changes and ModificationRemoveNotify becomes
2333 // ModificationRemove only after the list has been unlocked.
2334 //
2335 ASSERT(Entry->m_ModificationState == ModificationRemoveNotify);
2336
2337 //
2338 // Remove the modification from the list. The call to
2339 // DeleteDeviceFromFailedCreate below will destroy this
2340 // Entry due to the pnp state machine deleting the PDO.
2341 //
2342 RemoveEntryList(&Entry->m_ModificationLink);
2343 }
2345
2346 ASSERT(init.CreatedDevice->IsPnp());
2347 ASSERT(init.CreatedDevice->GetDevicePnpState() == WdfDevStatePnpInit);
2348 ASSERT(init.CreatedDevice->GetPdoPkg()->m_Description != NULL);
2349
2350 ASSERT(Entry->m_Pdo == NULL);
2351
2354 "WDFDEVICE %p !devobj %p created, but EvtChildListCreateDevice "
2355 "returned status %!STATUS!", init.CreatedDevice->GetHandle(),
2356 init.CreatedDevice->GetDeviceObject(), status);
2357
2358 //
2359 // Simulate a remove event coming to the device. After this call
2360 // returns, init.CreatedDevice is no longer a valid pointer!
2361 //
2362 // Please note that DeleteDeviceFromFailedCreate just returns
2363 // the passed status back unless device is a filter, in which
2364 // case it changes it to success.
2365 //
2366 // It is not really the status of DeleteDeviceFromFailedCreate
2367 // operation, which is why we don't check it.
2368 //
2369 (void) init.CreatedDevice->DeleteDeviceFromFailedCreate(
2370 status,
2371 TRUE);
2372
2373 init.CreatedDevice = NULL;
2374 }
2375 else {
2376 LIST_ENTRY freeHead;
2377
2378 InitializeListHead(&freeHead);
2379
2380 //
2381 // Add a modification that this entry is now gone. If there is
2382 // an active scan and it has added this device, there would
2383 // be no entry in the modification case list because the add
2384 // would have updated the description entry.
2385 //
2388 ProcessModificationsLocked(&freeHead);
2390
2391 //
2392 // Free structures outside of any internal WDF lock
2393 //
2394 DrainFreeListHead(&freeHead);
2395 }
2396
2397 return FALSE;
2398 }
2399 }
2400
2401 //
2402 // Assign m_Pdo here once we have a fully baked and created device. We only
2403 // assign m_Pdo after we have completely initalized device because we check
2404 // for m_Pdo in PostParentToD0.
2405 //
2406 Entry->m_Pdo = init.CreatedDevice;
2407 Entry->m_DescriptionState = DescriptionInstantiatedHasObject;
2408
2409 return TRUE;
2410}
2411
2415 __inout PDEVICE_RELATIONS *DeviceRelations
2416 )
2417{
2418 LIST_ENTRY freeHead;
2419 PLIST_ENTRY ple, pNext;
2421 PDEVICE_RELATIONS pPriorRelations, pNewRelations;
2423 BOOLEAN needToReportMissingChildren, invalidateRelations, cleanupRelations;
2424 ULONG additionalCount, totalCount, i;
2425 size_t size;
2427 KIRQL irql;
2429
2431
2432 pNewRelations = NULL;
2433 invalidateRelations = FALSE;
2434 cleanupRelations = TRUE;
2435 InitializeListHead(&freeHead);
2437
2438 //
2439 // Get the count of DO's we will need to add. While we're at it, free any
2440 // extensions that never got a chance for a DO, and note extensions that
2441 // will need to wait for a remove IRP.
2442 //
2444
2446
2447 additionalCount = 0;
2448 needToReportMissingChildren = FALSE;
2449
2452 ple = ple->Flink) {
2453
2455
2456 switch (pEntry->m_DescriptionState) {
2457
2460 //
2461 // We'll be needing a DO here.
2462 //
2463 additionalCount++;
2464 break;
2465
2467 //
2468 // We will now report the description as missing
2469 //
2472 "PDO WDFDEVICE %p !devobj %p in a not present state, need to "
2473 "report as missing",
2474 pEntry->m_Pdo->GetHandle(), pEntry->m_Pdo->GetDeviceObject());
2475
2476 needToReportMissingChildren = TRUE;
2477 break;
2478
2480 //
2481 // Already reported missing in a previous handling of QDR
2482 //
2483 break;
2484
2485 default:
2486 ASSERTMSG("Invalid description state\n", FALSE);
2487 break;
2488 }
2489 }
2490
2492
2493 pPriorRelations = *DeviceRelations;
2494
2495 //
2496 // If we have
2497 // 1) no devices in the list AND
2498 // a) we have nothing to report OR
2499 // b) we have something to report and there are previous relations (which
2500 // if left unchanged will be used to report our missing devices)
2501 //
2502 // THEN nothing else to do except marking the NotPresent children as
2503 // missing, unlock the list and return the special return
2504 // code STATUS_NOT_SUPPORTED indicating this condition.
2505 //
2506 if (additionalCount == 0 &&
2507 (needToReportMissingChildren == FALSE || pPriorRelations != NULL)) {
2508 //
2509 // We have nothing to add, nor subtract from prior allocations. Note
2510 // the careful logic with counting missing children - the OS does not
2511 // treat no list and an empty list identically. As such we must be
2512 // sure to return some kind of list in the case where we reported
2513 // something previously.
2514 //
2515 // Mark the NotPresent children as Missing
2516 // We can walk the ChildList without holding the spinlock because we set
2517 // m_State to ListLockedForEnum.
2518 //
2519 if (needToReportMissingChildren) {
2522 ple = pNext) {
2523 pNext = ple->Flink;
2524
2526
2527 if (pEntry->m_DescriptionState == DescriptionNotPresent) {
2528 //
2529 // We will now report the description as missing
2530 //
2533 "PDO WDFDEVICE %p !devobj %p reported as missing to pnp",
2534 pEntry->m_Pdo->GetHandle(), pEntry->m_Pdo->GetDeviceObject());
2535
2536 pEntry->m_DescriptionState = DescriptionReportedMissing;
2537 pEntry->m_ReportedMissingCallbackState = CallbackNeedsToBeInvoked;
2538 }
2539 }
2540 }
2541 else {
2544 "Nothing to report on WDFCHILDLIST %p, returning early", GetHandle());
2545 }
2546
2547 cleanupRelations = FALSE;
2549 goto Done;
2550 }
2551
2552 //
2553 // Adjust the count for any existing relations.
2554 //
2555 totalCount = additionalCount;
2556 if (pPriorRelations != NULL) {
2557 totalCount += pPriorRelations->Count;
2558 }
2559
2560 size = _ComputeRelationsSize(totalCount);
2561
2562 pNewRelations = (PDEVICE_RELATIONS)
2564
2565 if (pNewRelations == NULL) {
2566 //
2567 // We can't add our information.
2568 //
2570 "Could not allocate relations for %d devices",
2571 totalCount);
2572
2573 //
2574 // Just like above, STATUS_NOT_SUPPORTED is a special value indicating
2575 // to the caller that the QDR has not been handled and that the caller
2576 // should not change the status or the existing relations in the irp.
2577 //
2578 cleanupRelations = FALSE;
2580
2581 m_EnumRetries++;
2583 invalidateRelations = TRUE;
2584 }
2585 else {
2586 if (needToReportMissingChildren) {
2589 "WDFCHILDLIST %p could not allocate relations required for "
2590 "reporting children as missing after max retries",
2591 GetHandle());
2592 }
2593
2596 "WDFCHILDLIST %p retried %d times to report relations, but "
2597 "failed each time", GetHandle(), FX_CHILD_LIST_MAX_RETRIES);
2598 }
2599
2600 if (pPriorRelations == NULL) {
2601 //
2602 // If the prior relations are NULL we can just return failure and
2603 // not affect anyone else's state that had previous thought they
2604 // committed a relations structure back to pnp (which we tried to
2605 // update but could not b/c of no memory).
2606 //
2607 // By returning failure that is != STATUS_NOT_SUPPORTED, the pnp
2608 // manager will not process a change in the relations.
2609 //
2611 }
2612 else {
2613 //
2614 // Do *not* throw away the old list and return error because that
2615 // will put the driver which created the existing relations into an
2616 // inconsistent state with respect to the pnp manager state if we
2617 // fail it here and the pnp manager never seeds the changes.
2618 //
2619 // Instead, we must process the failure locally and mark each object
2620 // which is already reported as present as missing.
2621 //
2624 ple = pNext) {
2625
2626 pNext = ple->Flink;
2628
2629 switch (pEntry->m_DescriptionState) {
2631 //
2632 // This description can stay in this state b/c we will just
2633 // ask for another QDR.
2634 //
2635 break;
2636
2640 "PDO WDFDEVICE %p !devobj %p being marked as missing "
2641 "because of failure to allocate device relations and "
2642 "an already existing relations %p",
2643 pEntry->m_Pdo->GetHandle(),
2644 pEntry->m_Pdo->GetDeviceObject(), pPriorRelations);
2645
2647 if (m_StaticList == FALSE) {
2652 "PDO WDFDEVICE %p !devobj %p being cloned "
2653 "because of the failure to allocate device "
2654 "relations",
2655 pEntry->m_Pdo->GetHandle(),
2656 pEntry->m_Pdo->GetDeviceObject());
2657
2658 (void) CloneEntryLocked(&freeHead, pEntry, TRUE);
2659 }
2660 }
2661 else {
2665 "PDO WDFDEVICE %p !devobj %p is a statically "
2666 "enumerated PDO therefore can not be cloned and is "
2667 "being marked missing because of failure to "
2668 "allocate device relations. It will be surprise "
2669 "removed by pnp manager. Bus driver may continue "
2670 "to function normally but will lose this child PDO",
2671 pEntry->m_Pdo->GetHandle(),
2672 pEntry->m_Pdo->GetDeviceObject());
2673 }
2674 pEntry->m_DescriptionState = DescriptionReportedMissing;
2675 pEntry->m_ReportedMissingCallbackState = CallbackNeedsToBeInvoked;
2677 break;
2678
2680 //
2681 // We will now report the description as missing
2682 //
2685 "PDO WDFDEVICE %p !devobj %p reported as missing to pnp "
2686 "(by using existing relations)",
2687 pEntry->m_Pdo->GetHandle(),
2688 pEntry->m_Pdo->GetDeviceObject());
2689
2690 pEntry->m_DescriptionState = DescriptionReportedMissing;
2691 pEntry->m_ReportedMissingCallbackState = CallbackNeedsToBeInvoked;
2692 break;
2693 }
2694 }
2695 }
2696
2697 goto Done;
2698 }
2699
2700 RtlZeroMemory(pNewRelations, size);
2701
2702 if (pPriorRelations != NULL && pPriorRelations->Count > 0) {
2705 "WDFCHILDLIST %p prior relations %p contained %d objects",
2706 GetHandle(), pPriorRelations, pPriorRelations->Count
2707 );
2708
2709 RtlCopyMemory(pNewRelations,
2710 pPriorRelations,
2711 _ComputeRelationsSize(pPriorRelations->Count));
2712 }
2713
2714 //
2715 // We can walk the ChildList without holding the spinlock because we set
2716 // m_State to ListLockedForEnum.
2717 //
2719
2722 ple = pNext) {
2723 pNext = ple->Flink;
2724
2726
2727 switch (pEntry->m_DescriptionState) {
2729 //
2730 // This extension needs a device handle. Create one now.
2731 //
2733 "Creating PDO device object from reported device");
2734 if (CreateDevice(pEntry, &invalidateRelations) == FALSE) {
2735 break;
2736 }
2737
2740 "PDO created successfully, WDFDEVICE %p !devobj %p",
2741 pEntry->m_Pdo->GetHandle(), pEntry->m_Pdo->GetDeviceObject());
2742
2743 // || || Fall through || ||
2744 // \/ \/ \/ \/
2746
2748 "Reporting PDO WDFDEVICE %p !devobj %p",
2749 pEntry->m_Pdo->GetHandle(),
2750 pEntry->m_Pdo->GetDeviceObject());
2751
2752 pDevice = pEntry->m_Pdo->GetDeviceObject();
2754 pNewRelations->Objects[pNewRelations->Count] = pDevice;
2755 pNewRelations->Count++;
2756 break;
2757
2759 //
2760 // We will now report the description as missing
2761 //
2764 "PDO WDFDEVICE %p !devobj %p reported as missing to pnp",
2765 pEntry->m_Pdo->GetHandle(), pEntry->m_Pdo->GetDeviceObject());
2766
2767 pEntry->m_DescriptionState = DescriptionReportedMissing;
2768 pEntry->m_ReportedMissingCallbackState = CallbackNeedsToBeInvoked;
2769
2770 break;
2771
2773 break;
2774
2775 default:
2776 ASSERTMSG("Invalid description state\n", FALSE);
2777 break;
2778 }
2779 }
2780
2781Done:
2783
2784 //
2785 // Make sure that the description we just dequeued is not on the modification
2786 // list.
2787 //
2789 ProcessModificationsLocked(&freeHead);
2790
2791 if (NT_SUCCESS(status)) {
2792 m_EnumRetries = 0;
2793 }
2794
2796
2797 if (invalidateRelations) {
2798 //
2799 // We failed for some reason or other. Queue up a new attempt.
2800 //
2801 // NOTE: no need to check m_Device->m_KnownPdo here
2802 // because we are in the middle of a QDR for m_Device which means
2803 // that it, or its stack, is already known to PnP.
2804 //
2806 }
2807
2808 DrainFreeListHead(&freeHead);
2809
2810 if (cleanupRelations) {
2811 if (pPriorRelations != NULL) {
2814 "Freeing prior relations %p", pPriorRelations);
2815
2816 ExFreePool(pPriorRelations);
2817 pPriorRelations = NULL;
2818 }
2819
2820 if (!NT_SUCCESS(status) && pNewRelations != NULL) {
2821 for(i = 0; i < pNewRelations->Count; i++) {
2822 ObDereferenceObject(pNewRelations->Objects[i]);
2823 }
2824
2825 ExFreePool(pNewRelations);
2826 pNewRelations = NULL;
2827 }
2828
2829 *DeviceRelations = pNewRelations;
2830 }
2831
2832 return status;
2833}
2834
2835VOID
2837 VOID
2838 )
2839{
2840 PLIST_ENTRY ple, pNext;
2841 KIRQL irql;
2843 LIST_ENTRY freeHead;
2844
2845 InitializeListHead(&freeHead);
2846
2847 //
2848 // Prevent modification list processing so that we can walk the
2849 // description list safely.
2850 //
2854
2855 //
2856 // Invoke the ReportedMissing callback if present for children reported
2857 // missing.
2858 //
2861 ple = pNext) {
2862 pNext = ple->Flink;
2863
2865
2866 if (pEntry->m_ReportedMissingCallbackState == CallbackNeedsToBeInvoked) {
2867 (pEntry->m_Pdo->GetPdoPkg())->m_DeviceReportedMissing.Invoke(
2868 pEntry->m_Pdo->GetHandle());
2869
2870 pEntry->m_ReportedMissingCallbackState = CallbackInvoked;
2871 }
2872 }
2873
2876 ProcessModificationsLocked(&freeHead);
2878
2879 DrainFreeListHead(&freeHead);
2880}
2881
2882VOID
2884 VOID
2885 )
2886{
2889 KIRQL irql;
2890
2894 ple = ple->Flink) {
2895
2897
2898 if (pEntry->m_PendingDeleteOnScanEnd) {
2899 COVERAGE_TRAP();
2900 continue;
2901 }
2902
2903 if (pEntry->m_Pdo != NULL) {
2904 pEntry->m_Pdo->m_PkgPnp->PowerProcessEvent(PowerParentToD0);
2905 }
2906 }
2908}
2909
2910VOID
2913 )
2914/*++
2915
2916Routine Description:
2917 Propagates the wait wake status to all the child PDOs. This will cause any
2918 pended wait wake requests to be completed with the given wait wake status.
2919
2920Arguments:
2921 WaitWakeStatus - The NTSTATUS value to use for compeleting any pended wait
2922 wake requests on the child PDOs.
2923
2924Return Value:
2925 None
2926
2927 --*/
2928{
2931 KIRQL irql;
2932
2936 ple = ple->Flink) {
2937
2939
2940 if (pEntry->m_PendingDeleteOnScanEnd) {
2941 COVERAGE_TRAP();
2942 continue;
2943 }
2944
2945 if (pEntry->m_Pdo != NULL) {
2946 ASSERT(pEntry->m_Pdo->m_PkgPnp->m_SharedPower.m_WaitWakeOwner == TRUE);
2947 pEntry->m_Pdo->m_PkgPnp->PowerIndicateWaitWakeStatus(WaitWakeStatus);
2948 }
2949 }
2951}
2952
2953VOID
2955 VOID
2956 )
2957/*++
2958
2959Routine Description:
2960 Notification through IFxStateChangeNotification that the parent device is
2961 being surprise removed
2962
2963Arguments:
2964 None
2965
2966Return Value:
2967 None
2968
2969 --*/
2970{
2971 PLIST_ENTRY pCur, pNext;
2972 LIST_ENTRY freeHead;
2974 KIRQL irql;
2975
2976 InitializeListHead(&freeHead);
2977
2979
2981
2982 //
2983 // Walk over all mod entries and remove any pending inserts. Note that
2984 // MarkModificationNotPresentWorker will add any such INSERTs found in the
2985 // mod list to the free list.
2986 //
2989 pCur = pNext) {
2990
2991 pNext = pCur->Flink;
2992
2994
2995 if (pEntry->m_ModificationState == ModificationInsert) {
2997 }
2998 }
2999
3000 //
3001 // Walk over all desc entries and remove them. Since
3002 // MarkDescriptionNotPresentWorker doesn't drain the mods,
3003 // we don't have to worry about any entries disappearing.
3004 //
3007 pCur = pCur->Flink) {
3008
3010
3011 if (pEntry->IsPresent()) {
3013 }
3014 }
3015
3016 //
3017 // Attempt to drain any mods we made.
3018 //
3019 ProcessModificationsLocked(&freeHead);
3020
3021 //
3022 // Walk over all desc entries and advance them to missing.
3023 //
3026 pCur = pCur->Flink) {
3027
3029
3030 if (pEntry->m_DescriptionState == DescriptionNotPresent) {
3031 pEntry->m_DescriptionState = DescriptionReportedMissing;
3032 }
3033 }
3034
3036
3037 DrainFreeListHead(&freeHead);
3038}
3039
3040VOID
3042 __inout PLONG ChildCount
3043 )
3044/*++
3045
3046Routine Description:
3047 Notification through IFxStateChangeNotification that the parent device is
3048 being removed.
3049
3050Arguments:
3051 None
3052
3053Return Value:
3054 None
3055
3056 --*/
3057{
3059 LIST_ENTRY freeHead;
3061 KIRQL irql;
3062
3064 "WDFCHILDLIST %p: removing children", GetHandle());
3065
3066 InitializeListHead(&freeHead);
3067 pEntry = NULL;
3068
3070
3071 //
3072 // Surprise remove handling covers the first stage of processing. This will
3073 // process the modification list, esp the insert modifications which will
3074 // be cleaned up.
3075 //
3077
3079
3080 ProcessModificationsLocked(&freeHead);
3081
3083
3084 for ( ; ; ) {
3085
3086 //
3087 // Find the first child which was not surprise removed. If surprise
3088 // removed and not yet removed, then there is an outstanding handle
3089 // which has not yet been closed.
3090 //
3093 pCur = pCur->Flink) {
3094
3096
3097 ASSERT(pEntry->m_DescriptionState == DescriptionReportedMissing);
3098
3099 if (pEntry->m_ProcessingSurpriseRemove == FALSE) {
3100 break;
3101 }
3102 }
3103
3104 //
3105 // If we are at the end of the list, we are done
3106 //
3107 if (pCur == &m_DescriptionListHead) {
3108 break;
3109 }
3110
3112 "Removing entry %p, WDFDEVICE %p, PDO %p",
3113 pEntry, pEntry->m_Pdo->GetHandle(),
3114 pEntry->m_Pdo->GetPhysicalDevice());
3115
3116 ASSERT(pEntry->m_ModificationState == ModificationUnspecified);
3117 RemoveEntryList(&pEntry->m_DescriptionLink);
3118 InitializeListHead(&pEntry->m_DescriptionLink);
3119
3121
3122 //
3123 // Go through FxPkgPdo to handle cleanup. CleanupOrphanedDevice will
3124 // free this entry.
3125 //
3126 ASSERT(pEntry->m_Pdo != NULL);
3127 ASSERT(pEntry->m_PendingDeleteOnScanEnd == FALSE);
3128
3129 pEntry->m_Pdo->SetParentWaitingOnRemoval();
3130 InterlockedIncrement(ChildCount);
3131
3132 //
3133 // Start the child going away
3134 //
3135 pEntry->m_Pdo->m_PkgPnp->PnpProcessEvent(PnpEventParentRemoved);
3136
3138 }
3139
3141 ProcessModificationsLocked(&freeHead);
3142
3144
3145 DrainFreeListHead(&freeHead);
3146}
3147
3151 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
3153 __in size_t* TotalDescriptionSize
3154 )
3155{
3157
3158 if (Config == NULL) {
3161 "Invalid Config, NULL is not allowed, %!STATUS!", status);
3162 return status;
3163 }
3164
3165 if (Config->Size != sizeof(WDF_CHILD_LIST_CONFIG)) {
3168 "Config->Size incorrect, expected %d, got %d, %!STATUS!",
3169 sizeof(WDF_CHILD_LIST_CONFIG), Config->Size, status);
3170 return status;
3171 }
3172 if (Config->IdentificationDescriptionSize == 0) {
3175 "Config->IdentificationDescriptionSize must be non zero, "
3176 "%!STATUS!", status);
3177 return status;
3178 }
3179 if (Config->EvtChildListCreateDevice == NULL) {
3182 "Config->EvtChildListCreateDevice, NULL is not allowed, "
3183 "%!STATUS!", status);
3184 return status;
3185 }
3186
3187 return _ComputeTotalDescriptionSize(FxDriverGlobals,
3188 Config,
3189 TotalDescriptionSize);
3190}
3191
3195 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
3197 __in size_t* TotalDescriptionSize
3198 )
3199{
3200 size_t addressAligned, idAligned;
3202
3203 *TotalDescriptionSize = 0;
3204
3205 //
3206 // FxDeviceDescriptionEntry::operator new() will allocate a block of memory
3207 // that is
3208 // size =
3209 // WDF_ALIGN_SIZE_UP(sizeof(FxDeviceDescriptionEntry), sizeof(PVOID)) +
3210 // WDF_ALIGN_SIZE_UP(AddressDescriptionSize, sizeof(PVOID)) +
3211 // WDF_ALIGN_SIZE_UP(IdentificationDescriptionSize, sizeof(PVOID));
3212 //
3213 // Validate the size now beforehand, not every we allocate
3214 //
3215 //
3216 // Test for overflow
3217 //
3218 idAligned = WDF_ALIGN_SIZE_UP(Config->IdentificationDescriptionSize,
3219 sizeof(PVOID));
3220 if (idAligned < Config->IdentificationDescriptionSize) {
3223 "Config->IdentificationDescriptionSize %d too large"
3224 "%!STATUS!", Config->IdentificationDescriptionSize,
3225 status);
3226 return status;
3227 }
3228
3229 addressAligned = WDF_ALIGN_SIZE_UP(Config->AddressDescriptionSize,
3230 sizeof(PVOID));
3231 if (addressAligned < Config->AddressDescriptionSize) {
3234 "Config->AddressDescriptionSize %d too large, %!STATUS!",
3235 Config->AddressDescriptionSize, status);
3236 return status;
3237 }
3238
3239 status = RtlSizeTAdd(
3241 idAligned,
3242 TotalDescriptionSize
3243 );
3244 if (!NT_SUCCESS(status)) {
3246 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
3247 "Could not add ID description size to block size, %!STATUS!",
3248 status);
3249 return status;
3250 }
3251
3252 status = RtlSizeTAdd(*TotalDescriptionSize,
3253 addressAligned,
3254 TotalDescriptionSize);
3255 if (!NT_SUCCESS(status)) {
3257 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
3258 "Could not add address description size to block size, %!STATUS!",
3259 status);
3260 return status;
3261 }
3262
3263 return STATUS_SUCCESS;
3264}
DWORD Id
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
#define ULongToPtr(ul)
Definition: basetsd.h:92
_Must_inspect_result_ NTSTATUS UpdateDeviceAsMissing(__in CfxDevice *Device)
VOID GetAddressDescriptionFromEntry(__in FxDeviceDescriptionEntry *Entry, __out PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER AddressDescription)
VOID EndScan(__inout_opt PULONG ScanTag=NULL)
MxEvent m_ScanEvent
KSPIN_LOCK m_ListLock
VOID PostParentToD0(VOID)
PFN_WDF_CHILD_LIST_ADDRESS_DESCRIPTION_DUPLICATE m_EvtAddressDescriptionDuplicate
VOID NotifyDeviceRemove(__inout PLONG ChildCount)
VOID ReenumerateEntry(__inout FxDeviceDescriptionEntry *Entry)
BOOLEAN m_IsAdded
PFN_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_DUPLICATE m_EvtIdentificationDescriptionDuplicate
_Must_inspect_result_ NTSTATUS GetNextDevice(__out WDFDEVICE *Device, __inout PWDF_CHILD_LIST_ITERATOR Iterator, __inout_opt PWDF_CHILD_RETRIEVE_INFO Info)
_Must_inspect_result_ NTSTATUS VerifyDescriptionEntry(__in PLIST_ENTRY Entry)
virtual BOOLEAN Dispose(VOID)
BOOLEAN HasAddressDescriptions(VOID)
friend struct FxDeviceDescriptionEntry
static _Must_inspect_result_ NTSTATUS _ValidateConfig(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_CHILD_LIST_CONFIG Config, __in size_t *TotalDescriptionSize)
VOID DrainFreeListHead(__inout PLIST_ENTRY FreeListHead)
ULONG m_IdentificationDescriptionSize
ULONG m_ScanCount
WDFDEVICE GetDevice(VOID)
VOID CopyAddress(__out PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER Dest, __in_opt PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER Source)
PFN_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_CLEANUP m_EvtIdentificationDescriptionCleanup
VOID BeginScan(__out_opt PULONG ScanTag=NULL)
CfxDevice * GetDeviceFromId(__inout PWDF_CHILD_RETRIEVE_INFO Info)
PFN_WDF_CHILD_LIST_DEVICE_REENUMERATED m_EvtChildListDeviceReenumerated
BOOLEAN IsStaticList(VOID)
_Must_inspect_result_ NTSTATUS GetAddressDescription(__in PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, __out PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER AddressDescription)
BOOLEAN m_StaticList
UCHAR m_EnumRetries
LIST_ENTRY m_ModificationListHead
FxTransactionedEntry m_TransactionLink
VOID MarkDescriptionNotPresentWorker(__inout FxDeviceDescriptionEntry *DescriptionEntry, __in BOOLEAN ModificationCanBeQueued)
VOID InvokeReportedMissingCallback(VOID)
VOID CleanupDescriptions(__in_opt PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdDescription, __in_opt PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER AddrDescription)
VOID ProcessModificationsLocked(__inout PLIST_ENTRY FreeListHead)
VOID BeginIteration(__inout PWDF_CHILD_LIST_ITERATOR Iterator)
FxDeviceDescriptionEntry * SearchBackwardsForMatchingDescriptionLocked(__in PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Id)
FxDeviceDescriptionEntry * SearchBackwardsForMatchingModificationLocked(__in PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Id)
_Must_inspect_result_ NTSTATUS VerifyModificationEntry(__in PLIST_ENTRY Entry)
VOID IndicateWakeStatus(__in NTSTATUS WakeWakeStatus)
VOID NotifyDeviceSurpriseRemove(VOID)
_Must_inspect_result_ NTSTATUS Add(__in PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, __in_opt PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER AddressDescription, __in_opt PULONG ScanTag=NULL)
static _Must_inspect_result_ NTSTATUS _CreateAndInit(__out FxChildList **ChildList, __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_OBJECT_ATTRIBUTES ListAttributes, __in size_t TotalDescriptionSize, __in CfxDevice *Device, __in PWDF_CHILD_LIST_CONFIG ListConfig, __in BOOLEAN Static=FALSE)
BOOLEAN CompareId(__in PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Lhs, __in PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Rhs)
VOID InitIterator(__inout PWDF_CHILD_LIST_ITERATOR Iterator)
ULONG GetScanCount(VOID)
VOID UpdateAddressDescriptionFromEntry(__inout FxDeviceDescriptionEntry *Entry, __in PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER AddressDescription)
VOID EndIteration(__inout PWDF_CHILD_LIST_ITERATOR Iterator)
PFN_WDF_CHILD_LIST_ADDRESS_DESCRIPTION_COPY m_EvtAddressDescriptionCopy
PFN_WDF_CHILD_LIST_ADDRESS_DESCRIPTION_CLEANUP m_EvtAddressDescriptionCleanup
PULONG m_ScanTag
BOOLEAN CreateDevice(__inout FxDeviceDescriptionEntry *Entry, __inout PBOOLEAN InvalidateRelations)
FxChildListCreateDeviceCallback m_EvtCreateDevice
ULONG m_AddressDescriptionSize
static _Must_inspect_result_ NTSTATUS _ComputeTotalDescriptionSize(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_CHILD_LIST_CONFIG Config, __in size_t *TotalDescriptionSize)
VOID CopyId(__out PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Dest, __in PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Source)
WDFDEVICE GetNextStaticDevice(__in WDFDEVICE PreviousDevice, __in ULONG Flags)
BOOLEAN ReenumerateEntryLocked(__inout FxDeviceDescriptionEntry *Entry, __in BOOLEAN FromQDR)
FxChildListScanForChildrenCallback m_EvtScanForChildren
static size_t _ComputeRelationsSize(__in ULONG Count)
BOOLEAN CloneEntryLocked(__inout PLIST_ENTRY FreeListHead, __inout FxDeviceDescriptionEntry *Entry, __in BOOLEAN FromQDR)
VOID CancelScan(__in BOOLEAN EndTheScan, __inout_opt PULONG ScanTag)
_Must_inspect_result_ NTSTATUS DuplicateId(__out PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Dest, __in PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Source)
_Must_inspect_result_ NTSTATUS DuplicateAddress(__out PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER Dest, __in PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER Source)
VOID UpdateAllAsPresent(__in_opt PULONG ScanTag=NULL)
_Must_inspect_result_ NTSTATUS ProcessBusRelations(__inout PDEVICE_RELATIONS *DeviceRelations)
PFN_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COMPARE m_EvtIdentificationDescriptionCompare
PFN_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COPY m_EvtIdentificationDescriptionCopy
VOID Initialize(__in PWDF_CHILD_LIST_CONFIG Config)
LIST_ENTRY m_DescriptionListHead
FxChildList(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in size_t TotalDescriptionSize, __in CfxDevice *Device, __in BOOLEAN Static)
FxChildListState m_State
VOID MarkModificationNotPresentWorker(__inout PLIST_ENTRY FreeListHead, __inout FxDeviceDescriptionEntry *ModificationEntry)
BOOLEAN m_InvalidationNeeded
size_t m_TotalDescriptionSize
_Must_inspect_result_ NTSTATUS UpdateAsMissing(__in PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Description)
__inline FxDriver * GetDriver(VOID)
Definition: fxdevice.hpp:164
MdDeviceObject __inline GetPhysicalDevice(VOID)
Definition: fxdevice.hpp:228
WDFDEVICE __inline GetHandle(VOID)
Definition: fxdevice.hpp:237
virtual VOID AddChildList(__inout FxChildList *List)
Definition: fxdevicekm.cpp:431
FxPkgPnp * m_PkgPnp
Definition: fxdevice.hpp:670
MdDeviceObject __inline GetSafePhysicalDevice(VOID)
Definition: fxdevice.hpp:1005
virtual VOID RemoveChildList(__inout FxChildList *List)
Definition: fxdevicekm.cpp:441
__inline FxPkgPdo * GetPdoPkg(VOID)
Definition: fxdevice.hpp:1254
__inline WDF_DEVICE_PNP_STATE GetDevicePnpState()
Definition: fxdevice.hpp:1149
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
CfxDevice * m_Device
Definition: fxobject.hpp:329
VOID MarkNoDeleteDDI(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1118
VOID DeleteFromFailedCreate(VOID)
Definition: fxobject.cpp:391
VOID MarkDisposeOverride(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1101
BOOLEAN m_AddedToStaticList
Definition: fxpkgpdo.hpp:63
FxDeviceDescriptionEntry * m_Description
Definition: fxpkgpdo.hpp:40
VOID PnpProcessEvent(__in FxPnpEvent Event, __in BOOLEAN ProcessEventOnDifferentThread=FALSE)
Definition: Header.h:9
__inline VOID Clear()
Definition: mxeventkm.h:102
__inline VOID Set()
Definition: mxeventkm.h:91
CHECK_RETURN_IF_USER_MODE __inline NTSTATUS Initialize(__in EVENT_TYPE Type, __in BOOLEAN InitialState)
Definition: mxeventkm.h:55
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define __out_opt
Definition: dbghelp.h:65
#define __inout_opt
Definition: dbghelp.h:53
#define __in
Definition: dbghelp.h:35
#define __inout
Definition: dbghelp.h:50
#define __in_opt
Definition: dbghelp.h:38
#define __out
Definition: dbghelp.h:62
#define TRACINGPNP
Definition: dbgtrace.h:67
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
static const WCHAR Description[]
Definition: oid.c:1266
PDEVICE_LIST DeviceList
Definition: utils.c:27
KIRQL irql
Definition: wave.h:1
#define PtrToUlong(u)
Definition: config.h:107
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define PagedPool
Definition: env_spec_w32.h:308
@ ModificationRemoveNotify
@ ModificationRemove
@ ModificationUnspecified
@ ModificationNeedsPnpRemoval
@ ModificationClone
@ ModificationInsert
@ ScanTagFinished
Definition: fxchildlist.hpp:99
@ ScanTagActive
Definition: fxchildlist.hpp:97
@ ScanTagCancelled
Definition: fxchildlist.hpp:98
@ ListUnlocked
Definition: fxchildlist.hpp:90
@ ListLockedForEnum
Definition: fxchildlist.hpp:91
@ ListLockedForParentRemove
Definition: fxchildlist.hpp:92
@ ModificationIndex
Definition: fxchildlist.hpp:31
@ DescriptionIndex
Definition: fxchildlist.hpp:30
@ DescriptionNotPresent
@ DescriptionPresentNeedsInstantiation
@ DescriptionUnspecified
@ DescriptionReportedMissing
@ DescriptionInstantiatedHasObject
@ FX_CHILD_LIST_MAX_RETRIES
@ CallbackInvoked
@ CallbackNeedsToBeInvoked
FxChildList * pList
FxDevice * pDevice
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
pList EndScan()
PFX_DRIVER_GLOBALS pFxDriverGlobals
return pObject GetObjectHandle()
description Header IdentificationDescriptionSize
FxDevice * pPdo
SINGLE_LIST_ENTRY * pCur
PSINGLE_LIST_ENTRY ple
FxVerifierDbgBreakPoint(pFxDriverGlobals)
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
#define COVERAGE_TRAP()
Definition: fxmacros.hpp:246
@ ObjectDoNotLock
Definition: fxobject.hpp:128
@ PnpEventRemove
@ PnpEventParentRemoved
@ PowerParentToD0
FxCollectionEntry * cur
@ FX_TYPE_CHILD_LIST
Definition: fxtypes.h:82
__inline NTSTATUS FxVerifierCheckIrqlLevel(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in KIRQL Irql)
Definition: fxverifier.h:158
GLsizeiptr size
Definition: glext.h:5919
GLfloat GLfloat p
Definition: glext.h:8902
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define DO_NOTHING()
Definition: mxgeneral.h:32
#define _Must_inspect_result_
Definition: no_sal2.h:62
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
@ NotificationEvent
#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER
Definition: ntstatus.h:915
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:114
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:1772
#define exit(n)
Definition: config.h:202
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
base of all file and directory entries
Definition: entries.h:83
_Must_inspect_result_ NTSTATUS Invoke(__in WDFCHILDLIST DeviceList, __in PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, __in PWDFDEVICE_INIT ChildInit)
Definition: fxchildlist.hpp:46
PFN_WDF_CHILD_LIST_CREATE_DEVICE m_Method
Definition: fxchildlist.hpp:61
PFN_WDF_CHILD_LIST_SCAN_FOR_CHILDREN m_Method
Definition: fxchildlist.hpp:86
FxDeviceDescriptionEntry(__inout FxChildList *DeviceList, __in ULONG AddressDescriptionSize, __in ULONG IdentificationDescriptionSize)
Definition: fxchildlist.cpp:31
static FxDeviceDescriptionEntry * _FromDescriptionLink(__in PLIST_ENTRY Link)
_Must_inspect_result_ FxDeviceDescriptionEntry * Clone(__inout PLIST_ENTRY FreeListHead)
FxChildListDescriptionState m_DescriptionState
VOID DeviceSurpriseRemoved(VOID)
PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER m_IdentificationDescription
PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER m_AddressDescription
BOOLEAN IsDeviceReportedMissing(VOID)
FxChildList * m_DeviceList
FxChildListModificationState m_ModificationState
BOOLEAN IsDeviceRemoved(VOID)
static FxDeviceDescriptionEntry * _FromModificationLink(__in PLIST_ENTRY Link)
FxChildList * GetParentList(VOID)
VOID SetTransactionedObject(__in FxObject *Object)
Definition: window.h:585
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
BOOLEAN FxVerifierOn
Definition: fxglobals.h:420
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: devices.h:37
Definition: ps.c:97
#define GetHandle(h)
Definition: treelist.c:116
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PBOOLEAN
Definition: typedefs.h:53
struct _LIST_ENTRY * PLIST_ENTRY
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
int32_t * PLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_RETRY
Definition: udferr_usr.h:182
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
_In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR Iterator
Definition: wdfchildlist.h:656
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
struct _WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER * PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER
@ WdfRetrievePendingChildren
Definition: wdfchildlist.h:63
@ WdfRetrievePresentChildren
Definition: wdfchildlist.h:61
_In_ PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription
Definition: wdfchildlist.h:124
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_CHILD_LIST_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFCHILDLIST * ChildList
Definition: wdfchildlist.h:481
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_CHILD_LIST_CONFIG Config
Definition: wdfchildlist.h:476
struct _WDF_CHILD_ADDRESS_DESCRIPTION_HEADER * PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER
@ WdfChildListRetrieveDeviceNotYetCreated
Definition: wdfchildlist.h:55
@ WdfChildListRetrieveDeviceNoSuchDevice
Definition: wdfchildlist.h:56
@ WdfChildListRetrieveDeviceSuccess
Definition: wdfchildlist.h:54
WDF_EXTERN_C_START enum _WDF_CHILD_LIST_RETRIEVE_DEVICE_STATUS WDF_CHILD_LIST_RETRIEVE_DEVICE_STATUS
_Inout_ PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER AddressDescription
Definition: wdfchildlist.h:255
FORCEINLINE size_t WDF_ALIGN_SIZE_UP(_In_ size_t Length, _In_ size_t AlignTo)
Definition: wdfcore.h:129
#define WDF_PTR_ADD_OFFSET(_ptr, _offset)
Definition: wdfcore.h:144
@ WdfDevStatePnpInit
Definition: wdfdevice.h:69
_Must_inspect_result_ _In_ WDFDEVICE _In_ NTSTATUS WaitWakeStatus
Definition: wdfdevice.h:3945
static int init
Definition: wintirpc.c:33
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
@ BusRelations
Definition: iotypes.h:2152
struct _DEVICE_RELATIONS * PDEVICE_RELATIONS
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204