1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxCollection.cpp 8 9 Abstract: 10 11 This module implements a simple collection class to operate on 12 objects derived from FxObject. 13 14 Author: 15 16 17 18 Environment: 19 20 Both kernel and user mode 21 22 Revision History: 23 24 --*/ 25 26 #include "fxsupportpch.hpp" 27 28 FxCollectionInternal::FxCollectionInternal( 29 VOID 30 ) 31 { 32 m_Count = 0; 33 InitializeListHead(&m_ListHead); 34 } 35 36 FxCollectionInternal::~FxCollectionInternal( 37 VOID 38 ) 39 { 40 Clear(); 41 } 42 43 VOID 44 FxCollectionInternal::Clear( 45 VOID 46 ) 47 { 48 while (!IsListEmpty(&m_ListHead)) { 49 Remove(0); 50 } 51 } 52 53 ULONG 54 FxCollectionInternal::Count( 55 VOID 56 ) 57 { 58 return m_Count; 59 } 60 61 BOOLEAN 62 FxCollectionInternal::Add( 63 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 64 __in FxObject *Item 65 ) 66 { 67 FxCollectionEntry *pNode; 68 69 pNode = AllocateEntry(FxDriverGlobals); 70 71 if (pNode != NULL) { 72 InsertTailList(&m_ListHead, &pNode->m_ListEntry); 73 74 AddEntry(pNode, Item); 75 } 76 77 return pNode != NULL; 78 } 79 80 _Must_inspect_result_ 81 FxCollectionEntry* 82 FxCollectionInternal::FindEntry( 83 __in ULONG Index 84 ) 85 { 86 PLIST_ENTRY ple; 87 ULONG i; 88 89 if (Index >= m_Count) { 90 return NULL; 91 } 92 93 for (i = 0, ple = m_ListHead.Flink; 94 ple != &m_ListHead; 95 ple = ple->Flink, i++) { 96 if (i != Index) { 97 continue; 98 } 99 100 return CONTAINING_RECORD(ple, FxCollectionEntry, m_ListEntry); 101 } 102 103 return NULL; 104 } 105 106 _Must_inspect_result_ 107 FxCollectionEntry* 108 FxCollectionInternal::FindEntryByObject( 109 __in FxObject* Object 110 ) 111 { 112 PLIST_ENTRY ple; 113 114 for (ple = m_ListHead.Flink; ple != &m_ListHead; ple = ple->Flink) { 115 FxCollectionEntry* pNode; 116 117 pNode = CONTAINING_RECORD(ple, FxCollectionEntry, m_ListEntry); 118 if (pNode->m_Object == Object) { 119 return pNode; 120 } 121 } 122 123 return NULL; 124 } 125 126 NTSTATUS 127 FxCollectionInternal::Remove( 128 __in ULONG Index 129 ) 130 { 131 FxCollectionEntry *pNode; 132 133 pNode = FindEntry(Index); 134 135 if (pNode != NULL) { 136 return RemoveEntry(pNode); 137 } 138 else { 139 return STATUS_NOT_FOUND; 140 } 141 } 142 143 _Must_inspect_result_ 144 NTSTATUS 145 FxCollectionInternal::RemoveItem( 146 __in FxObject* Item 147 ) 148 { 149 FxCollectionEntry* pNode; 150 151 pNode = FindEntryByObject(Item); 152 153 if (pNode != NULL) { 154 return RemoveEntry(pNode); 155 } 156 157 return STATUS_NOT_FOUND; 158 } 159 160 VOID 161 FxCollectionInternal::CleanupEntry( 162 __in FxCollectionEntry* Entry 163 ) 164 { 165 RemoveEntryList(&Entry->m_ListEntry); 166 delete Entry; 167 168 m_Count--; 169 } 170 171 NTSTATUS 172 FxCollectionInternal::RemoveEntry( 173 __in FxCollectionEntry* Entry 174 ) 175 { 176 CleanupEntryObject(Entry->m_Object); 177 CleanupEntry(Entry); 178 179 return STATUS_SUCCESS; 180 } 181 182 _Must_inspect_result_ 183 FxObject* 184 FxCollectionInternal::GetItem( 185 __in ULONG Index 186 ) 187 188 { 189 FxCollectionEntry* pNode; 190 191 pNode = FindEntry(Index); 192 if (pNode != NULL) { 193 return pNode->m_Object; 194 } 195 else { 196 return NULL; 197 } 198 } 199 200 _Must_inspect_result_ 201 FxObject* 202 FxCollectionInternal::GetFirstItem( 203 VOID 204 ) 205 { 206 if (IsListEmpty(&m_ListHead)) { 207 return NULL; 208 } 209 else { 210 return CONTAINING_RECORD(m_ListHead.Flink, 211 FxCollectionEntry, 212 m_ListEntry)->m_Object; 213 } 214 } 215 216 _Must_inspect_result_ 217 FxObject* 218 FxCollectionInternal::GetLastItem( 219 VOID 220 ) 221 { 222 if (IsListEmpty(&m_ListHead)) { 223 return NULL; 224 } 225 else { 226 return CONTAINING_RECORD(m_ListHead.Blink, 227 FxCollectionEntry, 228 m_ListEntry)->m_Object; 229 } 230 } 231 232 FxCollection::FxCollection( 233 __in PFX_DRIVER_GLOBALS FxDriverGlobals 234 ) : 235 FxNonPagedObject(FX_TYPE_COLLECTION, sizeof(FxCollection), FxDriverGlobals) 236 { 237 } 238 239 FxCollection::FxCollection( 240 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 241 __in WDFTYPE Type, 242 __in USHORT Size 243 ) : FxNonPagedObject(Type, Size, FxDriverGlobals) 244 { 245 } 246 247 FxCollection::~FxCollection( 248 VOID 249 ) 250 { 251 Clear(); 252 } 253 254 VOID 255 FxCollection::StealCollection( 256 __in FxCollection* Collection 257 ) 258 { 259 PLIST_ENTRY ple; 260 261 m_Count = Collection->m_Count; 262 Collection->m_Count = 0; 263 264 while (!IsListEmpty(&Collection->m_ListHead)) { 265 FxCollectionEntry* pEntry; 266 267 ple = RemoveHeadList(&Collection->m_ListHead); 268 pEntry = CONTAINING_RECORD(ple, FxCollectionEntry, m_ListEntry); 269 270 // 271 // When we are tracking reference tags, the tag associated with the 272 // reference matters. When we added the object to Collection, we used 273 // that pointer as the tag. We must remove that tag and readd the 274 // reference using the this value as a tag. 275 // 276 // Obviously, order is important here. Add the reference first so that 277 // we know the relese will make the object go away. 278 // 279 pEntry->m_Object->ADDREF(this); 280 pEntry->m_Object->RELEASE(Collection); 281 282 InsertTailList(&m_ListHead, ple); 283 } 284 } 285 286