Reactos
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