Reactos
at master 285 lines 5.1 kB view raw
1/*++ 2 3Copyright (c) Microsoft Corporation 4 5Module Name: 6 7 FxCollection.cpp 8 9Abstract: 10 11 This module implements a simple collection class to operate on 12 objects derived from FxObject. 13 14Author: 15 16 17 18Environment: 19 20 Both kernel and user mode 21 22Revision History: 23 24--*/ 25 26#include "fxsupportpch.hpp" 27 28FxCollectionInternal::FxCollectionInternal( 29 VOID 30 ) 31{ 32 m_Count = 0; 33 InitializeListHead(&m_ListHead); 34} 35 36FxCollectionInternal::~FxCollectionInternal( 37 VOID 38 ) 39{ 40 Clear(); 41} 42 43VOID 44FxCollectionInternal::Clear( 45 VOID 46 ) 47{ 48 while (!IsListEmpty(&m_ListHead)) { 49 Remove(0); 50 } 51} 52 53ULONG 54FxCollectionInternal::Count( 55 VOID 56 ) 57{ 58 return m_Count; 59} 60 61BOOLEAN 62FxCollectionInternal::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_ 81FxCollectionEntry* 82FxCollectionInternal::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_ 107FxCollectionEntry* 108FxCollectionInternal::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 126NTSTATUS 127FxCollectionInternal::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_ 144NTSTATUS 145FxCollectionInternal::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 160VOID 161FxCollectionInternal::CleanupEntry( 162 __in FxCollectionEntry* Entry 163 ) 164{ 165 RemoveEntryList(&Entry->m_ListEntry); 166 delete Entry; 167 168 m_Count--; 169} 170 171NTSTATUS 172FxCollectionInternal::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_ 183FxObject* 184FxCollectionInternal::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_ 201FxObject* 202FxCollectionInternal::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_ 217FxObject* 218FxCollectionInternal::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 232FxCollection::FxCollection( 233 __in PFX_DRIVER_GLOBALS FxDriverGlobals 234 ) : 235 FxNonPagedObject(FX_TYPE_COLLECTION, sizeof(FxCollection), FxDriverGlobals) 236{ 237} 238 239FxCollection::FxCollection( 240 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 241 __in WDFTYPE Type, 242 __in USHORT Size 243 ) : FxNonPagedObject(Type, Size, FxDriverGlobals) 244{ 245} 246 247FxCollection::~FxCollection( 248 VOID 249 ) 250{ 251 Clear(); 252} 253 254VOID 255FxCollection::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