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
FxCollectionInternal(VOID)28 FxCollectionInternal::FxCollectionInternal(
29 VOID
30 )
31 {
32 m_Count = 0;
33 InitializeListHead(&m_ListHead);
34 }
35
~FxCollectionInternal(VOID)36 FxCollectionInternal::~FxCollectionInternal(
37 VOID
38 )
39 {
40 Clear();
41 }
42
43 VOID
Clear(VOID)44 FxCollectionInternal::Clear(
45 VOID
46 )
47 {
48 while (!IsListEmpty(&m_ListHead)) {
49 Remove(0);
50 }
51 }
52
53 ULONG
Count(VOID)54 FxCollectionInternal::Count(
55 VOID
56 )
57 {
58 return m_Count;
59 }
60
61 BOOLEAN
Add(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in FxObject * Item)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*
FindEntry(__in ULONG Index)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*
FindEntryByObject(__in FxObject * Object)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
Remove(__in ULONG Index)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
RemoveItem(__in FxObject * Item)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
CleanupEntry(__in FxCollectionEntry * Entry)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
RemoveEntry(__in FxCollectionEntry * Entry)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*
GetItem(__in ULONG Index)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*
GetFirstItem(VOID)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*
GetLastItem(VOID)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
FxCollection(__in PFX_DRIVER_GLOBALS FxDriverGlobals)232 FxCollection::FxCollection(
233 __in PFX_DRIVER_GLOBALS FxDriverGlobals
234 ) :
235 FxNonPagedObject(FX_TYPE_COLLECTION, sizeof(FxCollection), FxDriverGlobals)
236 {
237 }
238
FxCollection(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in WDFTYPE Type,__in USHORT Size)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
~FxCollection(VOID)247 FxCollection::~FxCollection(
248 VOID
249 )
250 {
251 Clear();
252 }
253
254 VOID
StealCollection(__in FxCollection * Collection)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