ReactOS  0.4.14-dev-604-gcfdd483
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 
14 typedef struct
15 {
18  PFNKSFREE Free;
21 
22 
23 /*
24  @implemented
25 */
28 NTAPI
30  IN PKSDEVICE Device,
31  OUT KSOBJECT_BAG* ObjectBag)
32 {
33  PKSIDEVICE_HEADER DeviceHeader;
34  PKSIOBJECT_BAG Bag;
35  IKsDevice *KsDevice;
36 
37  /* get real device header */
38  DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
39 
40  /* allocate a object bag ctx */
41  Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
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,
55  IN PVOID Item)
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 */
85 NTAPI
87  IN KSOBJECT_BAG ObjectBag,
88  IN PVOID Item,
89  IN PFNKSFREE Free OPTIONAL)
90 {
91  PKSIOBJECT_BAG Bag;
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 
143 ULONG
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 */
176 KSDDKAPI
177 ULONG
178 NTAPI
180  IN KSOBJECT_BAG ObjectBag,
181  IN PVOID Item,
182  IN BOOLEAN Free)
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 */
244 KSDDKAPI
245 NTSTATUS
246 NTAPI
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 */
305 KSDDKAPI
306 VOID
307 NTAPI
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 */
330  TotalRefs = KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER)Bag->DeviceHeader, &BagEntry->Item);
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 */
355 KSDDKAPI
356 NTSTATUS
357 NTAPI
359  IN KSOBJECT_BAG ObjectBag,
360  IN OUT PVOID* PointerToPointerToItem,
361  IN ULONG NewSize,
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 
#define IN
Definition: typedefs.h:38
struct KSIOBJECT_BAG_ENTRY * PKSIOBJECT_BAG_ENTRY
#define TRUE
Definition: types.h:120
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS NTAPI KsAddItemToObjectBag(IN KSOBJECT_BAG ObjectBag, IN PVOID Item, IN PFNKSFREE Free OPTIONAL)
Definition: bag.c:86
struct KSIDEVICE_HEADER * PKSIDEVICE_HEADER
_In_ PIRP _In_ PDEVICE_OBJECT Device
Definition: fatprocs.h:2020
struct _Entry Entry
Definition: kefuncs.h:640
PVOID AllocateItem(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes)
Definition: misc.c:30
LONG NTSTATUS
Definition: precomp.h:26
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
KSDDKAPI ULONG NTAPI KsRemoveItemFromObjectBag(IN KSOBJECT_BAG ObjectBag, IN PVOID Item, IN BOOLEAN Free)
Definition: bag.c:179
PUNKNOWN OuterUnknown
Definition: kstypes.h:62
#define InsertTailList(ListHead, Entry)
LONG NTAPI KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait)
Definition: mutex.c:189
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define KSDDKAPI
Definition: ks.h:40
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
struct KSIOBJECT_BAG * PKSIOBJECT_BAG
PRKMUTEX BagMutex
Definition: ksiface.h:17
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:656
KSDDKAPI NTSTATUS NTAPI KsAllocateObjectBag(IN PKSDEVICE Device, OUT KSOBJECT_BAG *ObjectBag)
Definition: bag.c:29
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
VOID FreeItem(IN PVOID Item)
Definition: misc.c:43
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
LIST_ENTRY ObjectList
Definition: ksiface.h:16
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
PVOID DeviceHeader
Definition: ksiface.h:18
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
PFNKSFREE Free
Definition: bag.c:18
Definition: bag.c:14
ULONG KspGetObjectItemReferenceCount(IN PKSIDEVICE_HEADER DeviceHeader, IN PVOID Item)
Definition: bag.c:144
KSBASIC_HEADER BasicHeader
Definition: kstypes.h:87
#define InterlockedDecrement
Definition: armddk.h:52
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
Definition: typedefs.h:117
PKSIOBJECT_BAG_ENTRY KspFindObjectBagItem(IN PLIST_ENTRY ObjectList, IN PVOID Item)
Definition: bag.c:53
Status
Definition: gdiplustypes.h:24
LIST_ENTRY Entry
Definition: ksiface.h:15
#define InterlockedIncrement
Definition: armddk.h:53
KSDDKAPI NTSTATUS NTAPI KsCopyObjectBagItems(IN KSOBJECT_BAG ObjectBagDestination, IN KSOBJECT_BAG ObjectBagSource)
Definition: bag.c:247
PVOID Item
Definition: bag.c:17
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
LIST_ENTRY Entry
Definition: bag.c:16
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:2938
signed int * PLONG
Definition: retypes.h:5
base of all file and directory entries
Definition: entries.h:82
KSDDKAPI VOID NTAPI KsFreeObjectBag(IN KSOBJECT_BAG ObjectBag)
Definition: bag.c:308
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ULONG References
Definition: bag.c:19
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68