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
->lpVtblIKsDevice
;
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 /* get real object bag */
93 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
95 /* acquire bag mutex */
96 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
98 /* is the item already present in this object bag */
99 BagEntry
= KspFindObjectBagItem(&Bag
->ObjectList
, Item
);
103 /* is is, update reference count */
104 InterlockedIncrement((PLONG
)&BagEntry
->References
);
106 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
108 return STATUS_SUCCESS
;
111 /* item is new, allocate entry */
112 BagEntry
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG_ENTRY
));
116 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
118 return STATUS_INSUFFICIENT_RESOURCES
;
121 /* initialize bag entry */
122 BagEntry
->References
= 1;
123 BagEntry
->Item
= Item
;
125 BagEntry
->Free
= Free
;
127 BagEntry
->Free
= ExFreePool
;
130 InsertTailList(&Bag
->ObjectList
, &Bag
->Entry
);
133 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
136 return STATUS_SUCCESS
;
140 KspGetObjectItemReferenceCount(
141 IN PKSIDEVICE_HEADER DeviceHeader
,
145 PKSIOBJECT_BAG OtherBag
;
146 PKSIOBJECT_BAG_ENTRY OtherBagEntry
;
149 /* scan all object bags and see if item is present there */
150 Entry
= DeviceHeader
->ObjectBags
.Flink
;
151 while(Entry
!= &DeviceHeader
->ObjectBags
)
154 OtherBag
= (PKSIOBJECT_BAG
)CONTAINING_RECORD(Entry
, KSIOBJECT_BAG
, Entry
);
156 /* is the item present there */
157 OtherBagEntry
= KspFindObjectBagItem(&OtherBag
->ObjectList
, Item
);
162 /* move to next item */
163 Entry
= Entry
->Flink
;
175 KsRemoveItemFromObjectBag(
176 IN KSOBJECT_BAG ObjectBag
,
181 PKSIOBJECT_BAG_ENTRY BagEntry
;
184 /* get real object bag */
185 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
187 /* acquire bag mutex */
188 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
190 /* is the item already present in this object bag */
191 BagEntry
= KspFindObjectBagItem(&Bag
->ObjectList
, Item
);
195 /* item was not in this object bag */
196 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
200 /* set current refs count */
201 TotalRefs
= BagEntry
->References
;
203 /* get total refs count */
204 TotalRefs
+= KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER
)Bag
->DeviceHeader
, Item
);
206 /* decrease reference count */
207 InterlockedDecrement((PLONG
)&BagEntry
->References
);
209 if (BagEntry
->References
== 0)
211 /* remove the entry */
212 RemoveEntryList(&BagEntry
->Entry
);
217 /* does the caller want to free the item */
221 BagEntry
->Free(BagEntry
->Item
);
224 if (BagEntry
->References
== 0)
226 /* free bag item entry */
231 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
243 KsCopyObjectBagItems(
244 IN KSOBJECT_BAG ObjectBagDestination
,
245 IN KSOBJECT_BAG ObjectBagSource
)
247 PKSIOBJECT_BAG ObjectBagDest
, ObjectBagSrc
;
249 PKSIOBJECT_BAG_ENTRY BagEntry
;
250 NTSTATUS Status
= STATUS_SUCCESS
;
252 /* get object bag src */
253 ObjectBagSrc
= (PKSIOBJECT_BAG
)ObjectBagSource
;
255 /* get object bag dst */
256 ObjectBagDest
= (PKSIOBJECT_BAG
)ObjectBagDestination
;
258 /* acquire source mutex */
259 KeWaitForSingleObject(ObjectBagSrc
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
261 if (ObjectBagSrc
->BagMutex
!= ObjectBagDest
->BagMutex
)
263 /* acquire destination mutex */
264 KeWaitForSingleObject(ObjectBagDest
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
267 /* point to first item */
268 Entry
= ObjectBagSrc
->ObjectList
.Flink
;
269 /* first scan the list if the item is already inserted */
270 while(Entry
!= &ObjectBagSrc
->ObjectList
)
273 BagEntry
= (PKSIOBJECT_BAG_ENTRY
)CONTAINING_RECORD(Entry
, KSIOBJECT_BAG_ENTRY
, Entry
);
276 Status
= KsAddItemToObjectBag(ObjectBagDestination
, BagEntry
->Item
, BagEntry
->Free
);
278 /* check for success */
279 if (!NT_SUCCESS(Status
))
282 /* move to next entry */
283 Entry
= Entry
->Flink
;
286 if (ObjectBagSrc
->BagMutex
!= ObjectBagDest
->BagMutex
)
288 /* release destination mutex */
289 KeReleaseMutex(ObjectBagDest
->BagMutex
, FALSE
);
292 /* release source mutex */
293 KeReleaseMutex(ObjectBagSrc
->BagMutex
, FALSE
);
305 IN KSOBJECT_BAG ObjectBag
)
309 PKSIOBJECT_BAG_ENTRY BagEntry
;
312 /* get real object bag */
313 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
315 /* acquire bag mutex */
316 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
318 while(!IsListEmpty(&Bag
->ObjectList
))
320 /* get an bag entry */
321 Entry
= RemoveHeadList(&Bag
->ObjectList
);
322 /* access bag entry item */
323 BagEntry
= (PKSIOBJECT_BAG_ENTRY
)CONTAINING_RECORD(Entry
, KSIOBJECT_BAG
, Entry
);
325 /* check if the item is present in some other bag */
326 TotalRefs
= KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER
)Bag
->DeviceHeader
, &BagEntry
->Item
);
330 /* item is ready to be freed */
331 BagEntry
->Free(BagEntry
->Item
);
334 /* free bag entry item */
338 /* remove bag entry from device object list */
339 RemoveEntryList(&Bag
->Entry
);
341 /* release bag mutex */
342 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
344 /* now free object bag */
355 IN KSOBJECT_BAG ObjectBag
,
356 IN OUT PVOID
* PointerToPointerToItem
,
362 PKSIOBJECT_BAG_ENTRY BagEntry
;
366 /* get real object bag */
367 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
369 /* acquire bag mutex */
370 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
373 if (*PointerToPointerToItem
)
375 /* search object bag for this entry */
376 BagEntry
= KspFindObjectBagItem(&Bag
->ObjectList
, *PointerToPointerToItem
);
380 /* pointer to null, allocate new entry */
384 if (!BagEntry
|| NewSize
> OldSize
)
386 /* entry does not exist or new entry must be allocated */
387 Item
= AllocateItem(NonPagedPool
, NewSize
);
391 /* not enough resources */
392 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
393 return STATUS_INSUFFICIENT_RESOURCES
;
396 /* now add the item to the object bag */
397 Status
= KsAddItemToObjectBag((KSOBJECT_BAG
)Bag
, Item
, NULL
);
398 /* check for success */
399 if (!NT_SUCCESS(Status
))
401 /* failed to add item */
403 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
407 if (*PointerToPointerToItem
)
410 if (OldSize
>= NewSize
)
412 /* copy old contents */
413 RtlMoveMemory(Item
, *PointerToPointerToItem
, NewSize
);
417 /* copy new contents */
418 RtlMoveMemory(Item
, *PointerToPointerToItem
, OldSize
);
424 /* remove old entry */
425 KsRemoveItemFromObjectBag(ObjectBag
, BagEntry
->Item
, TRUE
);
429 *PointerToPointerToItem
= Item
;
432 /* release bag mutex */
433 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
435 return STATUS_SUCCESS
;