2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/bag.c
5 * PURPOSE: KS Object Bag functions
6 * PROGRAMMER: Johannes Anderwald
18 }KSIOBJECT_BAG_ENTRY
, *PKSIOBJECT_BAG_ENTRY
;
29 OUT KSOBJECT_BAG
* ObjectBag
)
31 PKSIDEVICE_HEADER DeviceHeader
;
35 /* get real device header */
36 DeviceHeader
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(Device
, KSIDEVICE_HEADER
, KsDevice
);
38 /* allocate a object bag ctx */
39 Bag
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG
));
41 return STATUS_INSUFFICIENT_RESOURCES
;
43 /* get device interface */
44 KsDevice
= (IKsDevice
*)&DeviceHeader
->BasicHeader
.OuterUnknown
;
46 /* initialize object bag */
47 return KsDevice
->lpVtbl
->InitializeObjectBag(KsDevice
, Bag
, NULL
);
52 IN PLIST_ENTRY ObjectList
,
56 PKSIOBJECT_BAG_ENTRY BagEntry
;
58 /* point to first item */
59 Entry
= ObjectList
->Flink
;
60 /* first scan the list if the item is already inserted */
61 while(Entry
!= ObjectList
)
64 BagEntry
= (PKSIOBJECT_BAG_ENTRY
)CONTAINING_RECORD(Entry
, KSIOBJECT_BAG_ENTRY
, Entry
);
66 if (BagEntry
->Item
== Item
)
71 /* move to next entry */
74 /* item not in this object bag */
85 IN KSOBJECT_BAG ObjectBag
,
87 IN PFNKSFREE Free OPTIONAL
)
90 PKSIOBJECT_BAG_ENTRY BagEntry
;
92 DPRINT("KsAddItemToObjectBag\n");
94 /* get real object bag */
95 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
97 /* acquire bag mutex */
98 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
100 /* is the item already present in this object bag */
101 BagEntry
= KspFindObjectBagItem(&Bag
->ObjectList
, Item
);
105 /* is is, update reference count */
106 InterlockedIncrement((PLONG
)&BagEntry
->References
);
108 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
110 return STATUS_SUCCESS
;
113 /* item is new, allocate entry */
114 BagEntry
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG_ENTRY
));
118 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
120 return STATUS_INSUFFICIENT_RESOURCES
;
123 /* initialize bag entry */
124 BagEntry
->References
= 1;
125 BagEntry
->Item
= Item
;
127 BagEntry
->Free
= Free
;
129 BagEntry
->Free
= ExFreePool
;
132 InsertTailList(&Bag
->ObjectList
, &BagEntry
->Entry
);
135 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
138 return STATUS_SUCCESS
;
142 KspGetObjectItemReferenceCount(
143 IN PKSIDEVICE_HEADER DeviceHeader
,
147 PKSIOBJECT_BAG OtherBag
;
148 PKSIOBJECT_BAG_ENTRY OtherBagEntry
;
151 /* scan all object bags and see if item is present there */
152 Entry
= DeviceHeader
->ObjectBags
.Flink
;
153 while(Entry
!= &DeviceHeader
->ObjectBags
)
156 OtherBag
= (PKSIOBJECT_BAG
)CONTAINING_RECORD(Entry
, KSIOBJECT_BAG
, Entry
);
158 /* is the item present there */
159 OtherBagEntry
= KspFindObjectBagItem(&OtherBag
->ObjectList
, Item
);
164 /* move to next item */
165 Entry
= Entry
->Flink
;
177 KsRemoveItemFromObjectBag(
178 IN KSOBJECT_BAG ObjectBag
,
183 PKSIOBJECT_BAG_ENTRY BagEntry
;
186 /* get real object bag */
187 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
189 /* acquire bag mutex */
190 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
192 /* is the item already present in this object bag */
193 BagEntry
= KspFindObjectBagItem(&Bag
->ObjectList
, Item
);
197 /* item was not in this object bag */
198 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
202 /* set current refs count */
203 TotalRefs
= BagEntry
->References
;
205 /* get total refs count */
206 TotalRefs
+= KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER
)Bag
->DeviceHeader
, Item
);
208 /* decrease reference count */
209 InterlockedDecrement((PLONG
)&BagEntry
->References
);
211 if (BagEntry
->References
== 0)
213 /* remove the entry */
214 RemoveEntryList(&BagEntry
->Entry
);
219 /* does the caller want to free the item */
223 BagEntry
->Free(BagEntry
->Item
);
226 if (BagEntry
->References
== 0)
228 /* free bag item entry */
233 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
245 KsCopyObjectBagItems(
246 IN KSOBJECT_BAG ObjectBagDestination
,
247 IN KSOBJECT_BAG ObjectBagSource
)
249 PKSIOBJECT_BAG ObjectBagDest
, ObjectBagSrc
;
251 PKSIOBJECT_BAG_ENTRY BagEntry
;
252 NTSTATUS Status
= STATUS_SUCCESS
;
254 /* get object bag src */
255 ObjectBagSrc
= (PKSIOBJECT_BAG
)ObjectBagSource
;
257 /* get object bag dst */
258 ObjectBagDest
= (PKSIOBJECT_BAG
)ObjectBagDestination
;
260 /* acquire source mutex */
261 KeWaitForSingleObject(ObjectBagSrc
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
263 if (ObjectBagSrc
->BagMutex
!= ObjectBagDest
->BagMutex
)
265 /* acquire destination mutex */
266 KeWaitForSingleObject(ObjectBagDest
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
269 /* point to first item */
270 Entry
= ObjectBagSrc
->ObjectList
.Flink
;
271 /* first scan the list if the item is already inserted */
272 while(Entry
!= &ObjectBagSrc
->ObjectList
)
275 BagEntry
= (PKSIOBJECT_BAG_ENTRY
)CONTAINING_RECORD(Entry
, KSIOBJECT_BAG_ENTRY
, Entry
);
278 Status
= KsAddItemToObjectBag(ObjectBagDestination
, BagEntry
->Item
, BagEntry
->Free
);
280 /* check for success */
281 if (!NT_SUCCESS(Status
))
284 /* move to next entry */
285 Entry
= Entry
->Flink
;
288 if (ObjectBagSrc
->BagMutex
!= ObjectBagDest
->BagMutex
)
290 /* release destination mutex */
291 KeReleaseMutex(ObjectBagDest
->BagMutex
, FALSE
);
294 /* release source mutex */
295 KeReleaseMutex(ObjectBagSrc
->BagMutex
, FALSE
);
307 IN KSOBJECT_BAG ObjectBag
)
311 PKSIOBJECT_BAG_ENTRY BagEntry
;
314 /* get real object bag */
315 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
317 /* acquire bag mutex */
318 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
320 while(!IsListEmpty(&Bag
->ObjectList
))
322 /* get an bag entry */
323 Entry
= RemoveHeadList(&Bag
->ObjectList
);
324 /* access bag entry item */
325 BagEntry
= (PKSIOBJECT_BAG_ENTRY
)CONTAINING_RECORD(Entry
, KSIOBJECT_BAG
, Entry
);
327 /* check if the item is present in some other bag */
328 TotalRefs
= KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER
)Bag
->DeviceHeader
, &BagEntry
->Item
);
332 /* item is ready to be freed */
333 BagEntry
->Free(BagEntry
->Item
);
336 /* free bag entry item */
340 /* remove bag entry from device object list */
341 RemoveEntryList(&Bag
->Entry
);
343 /* release bag mutex */
344 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
346 /* now free object bag */
357 IN KSOBJECT_BAG ObjectBag
,
358 IN OUT PVOID
* PointerToPointerToItem
,
364 PKSIOBJECT_BAG_ENTRY BagEntry
;
370 /* get real object bag */
371 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
373 /* acquire bag mutex */
374 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
377 if (*PointerToPointerToItem
)
379 /* search object bag for this entry */
380 BagEntry
= KspFindObjectBagItem(&Bag
->ObjectList
, *PointerToPointerToItem
);
384 /* pointer to null, allocate new entry */
388 if (!BagEntry
|| NewSize
> OldSize
)
390 /* entry does not exist or new entry must be allocated */
391 Item
= AllocateItem(NonPagedPool
, NewSize
);
395 /* not enough resources */
396 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
397 return STATUS_INSUFFICIENT_RESOURCES
;
400 /* now add the item to the object bag */
401 Status
= KsAddItemToObjectBag((KSOBJECT_BAG
)Bag
, Item
, NULL
);
402 /* check for success */
403 if (!NT_SUCCESS(Status
))
405 /* failed to add item */
407 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
411 if (*PointerToPointerToItem
)
414 if (OldSize
>= NewSize
)
416 /* copy old contents */
417 RtlMoveMemory(Item
, *PointerToPointerToItem
, NewSize
);
421 /* copy new contents */
422 RtlMoveMemory(Item
, *PointerToPointerToItem
, OldSize
);
428 /* remove old entry */
429 KsRemoveItemFromObjectBag(ObjectBag
, BagEntry
->Item
, TRUE
);
433 *PointerToPointerToItem
= Item
;
436 /* release bag mutex */
437 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
439 return STATUS_SUCCESS
;