ReactOS 0.4.15-dev-7887-g64a59a1
bag.c
Go to the documentation of this file.
1/*
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
7 */
8
9#include "precomp.h"
10
11#define NDEBUG
12#include <debug.h>
13
14typedef struct
15{
18 PFNKSFREE Free;
21
22
23/*
24 @implemented
25*/
30 IN PKSDEVICE Device,
31 OUT KSOBJECT_BAG* ObjectBag)
32{
33 PKSIDEVICE_HEADER DeviceHeader;
35 IKsDevice *KsDevice;
36
37 /* get real device header */
39
40 /* allocate a object bag ctx */
42 if (!Bag)
44
45 /* get device interface */
46 KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown;
47
48 /* initialize object bag */
49 return KsDevice->lpVtbl->InitializeObjectBag(KsDevice, Bag, NULL);
50}
51
54 IN PLIST_ENTRY ObjectList,
56{
58 PKSIOBJECT_BAG_ENTRY BagEntry;
59
60 /* point to first item */
61 Entry = ObjectList->Flink;
62 /* first scan the list if the item is already inserted */
63 while(Entry != ObjectList)
64 {
65 /* get bag entry */
67
68 if (BagEntry->Item == Item)
69 {
70 /* found entry */
71 return BagEntry;
72 }
73 /* move to next entry */
74 Entry = Entry->Flink;
75 }
76 /* item not in this object bag */
77 return NULL;
78}
79
80
81/*
82 @implemented
83*/
87 IN KSOBJECT_BAG ObjectBag,
89 IN PFNKSFREE Free OPTIONAL)
90{
92 PKSIOBJECT_BAG_ENTRY BagEntry;
93
94 DPRINT("KsAddItemToObjectBag\n");
95
96 /* get real object bag */
97 Bag = (PKSIOBJECT_BAG)ObjectBag;
98
99 /* acquire bag mutex */
101
102 /* is the item already present in this object bag */
103 BagEntry = KspFindObjectBagItem(&Bag->ObjectList, Item);
104
105 if (BagEntry)
106 {
107 /* is is, update reference count */
109 /* release mutex */
111 /* return result */
112 return STATUS_SUCCESS;
113 }
114
115 /* item is new, allocate entry */
116 BagEntry = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG_ENTRY));
117 if (!BagEntry)
118 {
119 /* no memory */
121 /* return result */
123 }
124
125 /* initialize bag entry */
126 BagEntry->References = 1;
127 BagEntry->Item = Item;
128 if (Free)
129 BagEntry->Free = Free;
130 else
131 BagEntry->Free = ExFreePool;
132
133 /* insert item */
134 InsertTailList(&Bag->ObjectList, &BagEntry->Entry);
135
136 /* release mutex */
138
139 /* done */
140 return STATUS_SUCCESS;
141}
142
143ULONG
145 IN PKSIDEVICE_HEADER DeviceHeader,
146 IN PVOID Item)
147{
149 PKSIOBJECT_BAG OtherBag;
150 PKSIOBJECT_BAG_ENTRY OtherBagEntry;
151 ULONG TotalRefs = 0;
152
153 /* scan all object bags and see if item is present there */
154 Entry = DeviceHeader->ObjectBags.Flink;
155 while(Entry != &DeviceHeader->ObjectBags)
156 {
157 /* get other bag */
159
160 /* is the item present there */
161 OtherBagEntry = KspFindObjectBagItem(&OtherBag->ObjectList, Item);
162
163 if (OtherBagEntry)
164 TotalRefs++;
165
166 /* move to next item */
167 Entry = Entry->Flink;
168 }
169
170 return TotalRefs;
171}
172
173/*
174 @implemented
175*/
177ULONG
178NTAPI
180 IN KSOBJECT_BAG ObjectBag,
181 IN PVOID Item,
183{
184 PKSIOBJECT_BAG Bag;
185 PKSIOBJECT_BAG_ENTRY BagEntry;
186 ULONG TotalRefs;
187
188 /* get real object bag */
189 Bag = (PKSIOBJECT_BAG)ObjectBag;
190
191 /* acquire bag mutex */
193
194 /* is the item already present in this object bag */
195 BagEntry = KspFindObjectBagItem(&Bag->ObjectList, Item);
196
197 if (!BagEntry)
198 {
199 /* item was not in this object bag */
201 return 0;
202 }
203
204 /* set current refs count */
205 TotalRefs = BagEntry->References;
206
207 /* get total refs count */
209
210 /* decrease reference count */
212
213 if (BagEntry->References == 0)
214 {
215 /* remove the entry */
216 RemoveEntryList(&BagEntry->Entry);
217 }
218
219 if (TotalRefs == 1)
220 {
221 /* does the caller want to free the item */
222 if (Free)
223 {
224 /* free the item */
225 BagEntry->Free(BagEntry->Item);
226 }
227 }
228 if (BagEntry->References == 0)
229 {
230 /* free bag item entry */
231 FreeItem(BagEntry);
232 }
233
234 /* release mutex */
236
237
238 return TotalRefs;
239}
240
241/*
242 @implemented
243*/
246NTAPI
248 IN KSOBJECT_BAG ObjectBagDestination,
249 IN KSOBJECT_BAG ObjectBagSource)
250{
251 PKSIOBJECT_BAG ObjectBagDest, ObjectBagSrc;
253 PKSIOBJECT_BAG_ENTRY BagEntry;
255
256 /* get object bag src */
257 ObjectBagSrc = (PKSIOBJECT_BAG)ObjectBagSource;
258
259 /* get object bag dst */
260 ObjectBagDest = (PKSIOBJECT_BAG)ObjectBagDestination;
261
262 /* acquire source mutex */
264
265 if (ObjectBagSrc->BagMutex != ObjectBagDest->BagMutex)
266 {
267 /* acquire destination mutex */
269 }
270
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)
275 {
276 /* get bag entry */
278
279 /* add the item */
280 Status = KsAddItemToObjectBag(ObjectBagDestination, BagEntry->Item, BagEntry->Free);
281
282 /* check for success */
283 if (!NT_SUCCESS(Status))
284 break;
285
286 /* move to next entry */
287 Entry = Entry->Flink;
288 }
289
290 if (ObjectBagSrc->BagMutex != ObjectBagDest->BagMutex)
291 {
292 /* release destination mutex */
293 KeReleaseMutex(ObjectBagDest->BagMutex, FALSE);
294 }
295
296 /* release source mutex */
297 KeReleaseMutex(ObjectBagSrc->BagMutex, FALSE);
298
299 return Status;
300}
301
302/*
303 @implemented
304*/
306VOID
307NTAPI
309 IN KSOBJECT_BAG ObjectBag)
310{
312 PKSIOBJECT_BAG Bag;
313 PKSIOBJECT_BAG_ENTRY BagEntry;
314 ULONG TotalRefs;
315
316 /* get real object bag */
317 Bag = (PKSIOBJECT_BAG)ObjectBag;
318
319 /* acquire bag mutex */
321
322 while(!IsListEmpty(&Bag->ObjectList))
323 {
324 /* get an bag entry */
326 /* access bag entry item */
328
329 /* check if the item is present in some other bag */
331
332 if (TotalRefs == 0)
333 {
334 /* item is ready to be freed */
335 BagEntry->Free(BagEntry->Item);
336 }
337
338 /* free bag entry item */
339 FreeItem(BagEntry);
340 }
341
342 /* remove bag entry from device object list */
343 RemoveEntryList(&Bag->Entry);
344
345 /* release bag mutex */
347
348 /* now free object bag */
349 FreeItem(Bag);
350}
351
352/*
353 @implemented
354*/
357NTAPI
359 IN KSOBJECT_BAG ObjectBag,
360 IN OUT PVOID* PointerToPointerToItem,
362 IN ULONG OldSize,
363 IN ULONG Tag)
364{
365 PKSIOBJECT_BAG Bag;
366 PKSIOBJECT_BAG_ENTRY BagEntry;
367 PVOID Item;
369
370 DPRINT("_KsEdit\n");
371
372 /* get real object bag */
373 Bag = (PKSIOBJECT_BAG)ObjectBag;
374
375 /* acquire bag mutex */
377
378
379 if (*PointerToPointerToItem)
380 {
381 /* search object bag for this entry */
382 BagEntry = KspFindObjectBagItem(&Bag->ObjectList, *PointerToPointerToItem);
383 }
384 else
385 {
386 /* pointer to null, allocate new entry */
387 BagEntry = NULL;
388 }
389
390 if (!BagEntry || NewSize > OldSize)
391 {
392 /* entry does not exist or new entry must be allocated */
394
395 if (!Item)
396 {
397 /* not enough resources */
400 }
401
402 /* now add the item to the object bag */
404 /* check for success */
405 if (!NT_SUCCESS(Status))
406 {
407 /* failed to add item */
408 FreeItem(Item);
409 KeReleaseMutex(Bag->BagMutex, FALSE);
410 return Status;
411 }
412
413 if (*PointerToPointerToItem)
414 {
415 /* object exists */
416 if (OldSize >= NewSize)
417 {
418 /* copy old contents */
419 RtlMoveMemory(Item, *PointerToPointerToItem, NewSize);
420 }
421 else
422 {
423 /* copy new contents */
424 RtlMoveMemory(Item, *PointerToPointerToItem, OldSize);
425 }
426 }
427
428 if (BagEntry)
429 {
430 /* remove old entry */
431 KsRemoveItemFromObjectBag(ObjectBag, BagEntry->Item, TRUE);
432 }
433
434 /* store item */
435 *PointerToPointerToItem = Item;
436 }
437
438 /* release bag mutex */
440
441 return STATUS_SUCCESS;
442}
443
444
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
NTSTATUS NTAPI KsAddItemToObjectBag(IN KSOBJECT_BAG ObjectBag, IN PVOID Item, IN PFNKSFREE Free OPTIONAL)
Definition: bag.c:86
KSDDKAPI VOID NTAPI KsFreeObjectBag(IN KSOBJECT_BAG ObjectBag)
Definition: bag.c:308
KSDDKAPI NTSTATUS NTAPI _KsEdit(IN KSOBJECT_BAG ObjectBag, IN OUT PVOID *PointerToPointerToItem, IN ULONG NewSize, IN ULONG OldSize, IN ULONG Tag)
Definition: bag.c:358
PKSIOBJECT_BAG_ENTRY KspFindObjectBagItem(IN PLIST_ENTRY ObjectList, IN PVOID Item)
Definition: bag.c:53
KSDDKAPI ULONG NTAPI KsRemoveItemFromObjectBag(IN KSOBJECT_BAG ObjectBag, IN PVOID Item, IN BOOLEAN Free)
Definition: bag.c:179
struct KSIOBJECT_BAG_ENTRY * PKSIOBJECT_BAG_ENTRY
ULONG KspGetObjectItemReferenceCount(IN PKSIDEVICE_HEADER DeviceHeader, IN PVOID Item)
Definition: bag.c:144
KSDDKAPI NTSTATUS NTAPI KsCopyObjectBagItems(IN KSOBJECT_BAG ObjectBagDestination, IN KSOBJECT_BAG ObjectBagSource)
Definition: bag.c:247
KSDDKAPI NTSTATUS NTAPI KsAllocateObjectBag(IN PKSDEVICE Device, OUT KSOBJECT_BAG *ObjectBag)
Definition: bag.c:29
LONG NTSTATUS
Definition: precomp.h:26
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
Status
Definition: gdiplustypes.h:25
#define KSDDKAPI
Definition: ks.h:40
PVOID AllocateItem(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes)
Definition: misc.c:29
VOID FreeItem(IN PVOID Item)
Definition: misc.c:37
struct KSIOBJECT_BAG * PKSIOBJECT_BAG
struct KSIDEVICE_HEADER * PKSIDEVICE_HEADER
#define KernelMode
Definition: asm.h:34
LONG NTAPI KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait)
Definition: mutex.c:189
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
base of all file and directory entries
Definition: entries.h:83
PUNKNOWN OuterUnknown
Definition: kstypes.h:62
KSBASIC_HEADER BasicHeader
Definition: kstypes.h:87
Definition: bag.c:15
ULONG References
Definition: bag.c:19
PVOID Item
Definition: bag.c:17
LIST_ENTRY Entry
Definition: bag.c:16
PFNKSFREE Free
Definition: bag.c:18
PVOID DeviceHeader
Definition: ksiface.h:18
LIST_ENTRY ObjectList
Definition: ksiface.h:16
LIST_ENTRY Entry
Definition: ksiface.h:15
PRKMUTEX BagMutex
Definition: ksiface.h:17
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_In_ WDFCOLLECTION _In_ WDFOBJECT Item
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:815
@ Executive
Definition: ketypes.h:415