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
20 }KSIOBJECT_BAG_ENTRY
, *PKSIOBJECT_BAG_ENTRY
;
31 OUT KSOBJECT_BAG
* ObjectBag
)
33 PKSIDEVICE_HEADER DeviceHeader
;
37 /* get real device header */
38 DeviceHeader
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(Device
, KSIDEVICE_HEADER
, KsDevice
);
40 /* allocate a object bag ctx */
41 Bag
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG
));
43 return STATUS_INSUFFICIENT_RESOURCES
;
45 /* get device interface */
46 KsDevice
= (IKsDevice
*)&DeviceHeader
->BasicHeader
.OuterUnknown
;
48 /* initialize object bag */
49 return KsDevice
->lpVtbl
->InitializeObjectBag(KsDevice
, Bag
, NULL
);
54 IN PLIST_ENTRY ObjectList
,
58 PKSIOBJECT_BAG_ENTRY BagEntry
;
60 /* point to first item */
61 Entry
= ObjectList
->Flink
;
62 /* first scan the list if the item is already inserted */
63 while(Entry
!= ObjectList
)
66 BagEntry
= (PKSIOBJECT_BAG_ENTRY
)CONTAINING_RECORD(Entry
, KSIOBJECT_BAG_ENTRY
, Entry
);
68 if (BagEntry
->Item
== Item
)
73 /* move to next entry */
76 /* item not in this object bag */
87 IN KSOBJECT_BAG ObjectBag
,
89 IN PFNKSFREE Free OPTIONAL
)
92 PKSIOBJECT_BAG_ENTRY BagEntry
;
94 DPRINT("KsAddItemToObjectBag\n");
96 /* get real object bag */
97 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
99 /* acquire bag mutex */
100 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
102 /* is the item already present in this object bag */
103 BagEntry
= KspFindObjectBagItem(&Bag
->ObjectList
, Item
);
107 /* is is, update reference count */
108 InterlockedIncrement((PLONG
)&BagEntry
->References
);
110 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
112 return STATUS_SUCCESS
;
115 /* item is new, allocate entry */
116 BagEntry
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG_ENTRY
));
120 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
122 return STATUS_INSUFFICIENT_RESOURCES
;
125 /* initialize bag entry */
126 BagEntry
->References
= 1;
127 BagEntry
->Item
= Item
;
129 BagEntry
->Free
= Free
;
131 BagEntry
->Free
= ExFreePool
;
134 InsertTailList(&Bag
->ObjectList
, &BagEntry
->Entry
);
137 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
140 return STATUS_SUCCESS
;
144 KspGetObjectItemReferenceCount(
145 IN PKSIDEVICE_HEADER DeviceHeader
,
149 PKSIOBJECT_BAG OtherBag
;
150 PKSIOBJECT_BAG_ENTRY OtherBagEntry
;
153 /* scan all object bags and see if item is present there */
154 Entry
= DeviceHeader
->ObjectBags
.Flink
;
155 while(Entry
!= &DeviceHeader
->ObjectBags
)
158 OtherBag
= (PKSIOBJECT_BAG
)CONTAINING_RECORD(Entry
, KSIOBJECT_BAG
, Entry
);
160 /* is the item present there */
161 OtherBagEntry
= KspFindObjectBagItem(&OtherBag
->ObjectList
, Item
);
166 /* move to next item */
167 Entry
= Entry
->Flink
;
179 KsRemoveItemFromObjectBag(
180 IN KSOBJECT_BAG ObjectBag
,
185 PKSIOBJECT_BAG_ENTRY BagEntry
;
188 /* get real object bag */
189 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
191 /* acquire bag mutex */
192 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
194 /* is the item already present in this object bag */
195 BagEntry
= KspFindObjectBagItem(&Bag
->ObjectList
, Item
);
199 /* item was not in this object bag */
200 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
204 /* set current refs count */
205 TotalRefs
= BagEntry
->References
;
207 /* get total refs count */
208 TotalRefs
+= KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER
)Bag
->DeviceHeader
, Item
);
210 /* decrease reference count */
211 InterlockedDecrement((PLONG
)&BagEntry
->References
);
213 if (BagEntry
->References
== 0)
215 /* remove the entry */
216 RemoveEntryList(&BagEntry
->Entry
);
221 /* does the caller want to free the item */
225 BagEntry
->Free(BagEntry
->Item
);
228 if (BagEntry
->References
== 0)
230 /* free bag item entry */
235 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
247 KsCopyObjectBagItems(
248 IN KSOBJECT_BAG ObjectBagDestination
,
249 IN KSOBJECT_BAG ObjectBagSource
)
251 PKSIOBJECT_BAG ObjectBagDest
, ObjectBagSrc
;
253 PKSIOBJECT_BAG_ENTRY BagEntry
;
254 NTSTATUS Status
= STATUS_SUCCESS
;
256 /* get object bag src */
257 ObjectBagSrc
= (PKSIOBJECT_BAG
)ObjectBagSource
;
259 /* get object bag dst */
260 ObjectBagDest
= (PKSIOBJECT_BAG
)ObjectBagDestination
;
262 /* acquire source mutex */
263 KeWaitForSingleObject(ObjectBagSrc
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
265 if (ObjectBagSrc
->BagMutex
!= ObjectBagDest
->BagMutex
)
267 /* acquire destination mutex */
268 KeWaitForSingleObject(ObjectBagDest
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
271 /* point to first item */
272 Entry
= ObjectBagSrc
->ObjectList
.Flink
;
273 /* first scan the list if the item is already inserted */
274 while(Entry
!= &ObjectBagSrc
->ObjectList
)
277 BagEntry
= (PKSIOBJECT_BAG_ENTRY
)CONTAINING_RECORD(Entry
, KSIOBJECT_BAG_ENTRY
, Entry
);
280 Status
= KsAddItemToObjectBag(ObjectBagDestination
, BagEntry
->Item
, BagEntry
->Free
);
282 /* check for success */
283 if (!NT_SUCCESS(Status
))
286 /* move to next entry */
287 Entry
= Entry
->Flink
;
290 if (ObjectBagSrc
->BagMutex
!= ObjectBagDest
->BagMutex
)
292 /* release destination mutex */
293 KeReleaseMutex(ObjectBagDest
->BagMutex
, FALSE
);
296 /* release source mutex */
297 KeReleaseMutex(ObjectBagSrc
->BagMutex
, FALSE
);
309 IN KSOBJECT_BAG ObjectBag
)
313 PKSIOBJECT_BAG_ENTRY BagEntry
;
316 /* get real object bag */
317 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
319 /* acquire bag mutex */
320 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
322 while(!IsListEmpty(&Bag
->ObjectList
))
324 /* get an bag entry */
325 Entry
= RemoveHeadList(&Bag
->ObjectList
);
326 /* access bag entry item */
327 BagEntry
= (PKSIOBJECT_BAG_ENTRY
)CONTAINING_RECORD(Entry
, KSIOBJECT_BAG
, Entry
);
329 /* check if the item is present in some other bag */
330 TotalRefs
= KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER
)Bag
->DeviceHeader
, &BagEntry
->Item
);
334 /* item is ready to be freed */
335 BagEntry
->Free(BagEntry
->Item
);
338 /* free bag entry item */
342 /* remove bag entry from device object list */
343 RemoveEntryList(&Bag
->Entry
);
345 /* release bag mutex */
346 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
348 /* now free object bag */
359 IN KSOBJECT_BAG ObjectBag
,
360 IN OUT PVOID
* PointerToPointerToItem
,
366 PKSIOBJECT_BAG_ENTRY BagEntry
;
372 /* get real object bag */
373 Bag
= (PKSIOBJECT_BAG
)ObjectBag
;
375 /* acquire bag mutex */
376 KeWaitForSingleObject(Bag
->BagMutex
, Executive
, KernelMode
, FALSE
, NULL
);
379 if (*PointerToPointerToItem
)
381 /* search object bag for this entry */
382 BagEntry
= KspFindObjectBagItem(&Bag
->ObjectList
, *PointerToPointerToItem
);
386 /* pointer to null, allocate new entry */
390 if (!BagEntry
|| NewSize
> OldSize
)
392 /* entry does not exist or new entry must be allocated */
393 Item
= AllocateItem(NonPagedPool
, NewSize
);
397 /* not enough resources */
398 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
399 return STATUS_INSUFFICIENT_RESOURCES
;
402 /* now add the item to the object bag */
403 Status
= KsAddItemToObjectBag((KSOBJECT_BAG
)Bag
, Item
, NULL
);
404 /* check for success */
405 if (!NT_SUCCESS(Status
))
407 /* failed to add item */
409 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
413 if (*PointerToPointerToItem
)
416 if (OldSize
>= NewSize
)
418 /* copy old contents */
419 RtlMoveMemory(Item
, *PointerToPointerToItem
, NewSize
);
423 /* copy new contents */
424 RtlMoveMemory(Item
, *PointerToPointerToItem
, OldSize
);
430 /* remove old entry */
431 KsRemoveItemFromObjectBag(ObjectBag
, BagEntry
->Item
, TRUE
);
435 *PointerToPointerToItem
= Item
;
438 /* release bag mutex */
439 KeReleaseMutex(Bag
->BagMutex
, FALSE
);
441 return STATUS_SUCCESS
;