ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

bag.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS Kernel Streaming
00004  * FILE:            drivers/ksfilter/ks/bag.c
00005  * PURPOSE:         KS Object Bag functions
00006  * PROGRAMMER:      Johannes Anderwald
00007  */
00008 
00009 
00010 #include "priv.h"
00011 
00012 typedef struct
00013 {
00014     LIST_ENTRY Entry;
00015     PVOID Item;
00016     PFNKSFREE Free;
00017     ULONG References;
00018 }KSIOBJECT_BAG_ENTRY, *PKSIOBJECT_BAG_ENTRY;
00019 
00020 
00021 /*
00022     @implemented
00023 */
00024 KSDDKAPI
00025 NTSTATUS
00026 NTAPI
00027 KsAllocateObjectBag(
00028     IN PKSDEVICE Device,
00029     OUT KSOBJECT_BAG* ObjectBag)
00030 {
00031     PKSIDEVICE_HEADER DeviceHeader;
00032     PKSIOBJECT_BAG Bag;
00033     IKsDevice *KsDevice;
00034 
00035     /* get real device header */
00036     DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
00037 
00038     /* allocate a object bag ctx */
00039     Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
00040     if (!Bag)
00041         return STATUS_INSUFFICIENT_RESOURCES;
00042 
00043     /* get device interface */
00044     KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown;
00045 
00046     /* initialize object bag */
00047     return KsDevice->lpVtbl->InitializeObjectBag(KsDevice, Bag, NULL);
00048 }
00049 
00050 PKSIOBJECT_BAG_ENTRY
00051 KspFindObjectBagItem(
00052     IN PLIST_ENTRY ObjectList,
00053     IN PVOID Item)
00054 {
00055     PLIST_ENTRY Entry;
00056     PKSIOBJECT_BAG_ENTRY BagEntry;
00057 
00058     /* point to first item */
00059     Entry = ObjectList->Flink;
00060     /* first scan the list if the item is already inserted */
00061     while(Entry != ObjectList)
00062     {
00063         /* get bag entry */
00064         BagEntry = (PKSIOBJECT_BAG_ENTRY)CONTAINING_RECORD(Entry, KSIOBJECT_BAG_ENTRY, Entry);
00065 
00066         if (BagEntry->Item == Item)
00067         {
00068             /* found entry */
00069             return BagEntry;
00070         }
00071         /* move to next entry */
00072         Entry = Entry->Flink;
00073     }
00074     /* item not in this object bag */
00075     return NULL;
00076 }
00077 
00078 
00079 /*
00080     @implemented
00081 */
00082 NTSTATUS
00083 NTAPI
00084 KsAddItemToObjectBag(
00085     IN KSOBJECT_BAG  ObjectBag,
00086     IN PVOID  Item,
00087     IN PFNKSFREE  Free  OPTIONAL)
00088 {
00089     PKSIOBJECT_BAG Bag;
00090     PKSIOBJECT_BAG_ENTRY BagEntry;
00091 
00092     DPRINT("KsAddItemToObjectBag\n");
00093 
00094     /* get real object bag */
00095     Bag = (PKSIOBJECT_BAG)ObjectBag;
00096 
00097     /* acquire bag mutex */
00098     KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL);
00099 
00100     /* is the item already present in this object bag */
00101     BagEntry = KspFindObjectBagItem(&Bag->ObjectList, Item);
00102 
00103     if (BagEntry)
00104     {
00105         /* is is, update reference count */
00106         InterlockedIncrement((PLONG)&BagEntry->References);
00107         /* release mutex */
00108         KeReleaseMutex(Bag->BagMutex, FALSE);
00109         /* return result */
00110         return STATUS_SUCCESS;
00111     }
00112 
00113     /* item is new, allocate entry */
00114     BagEntry = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG_ENTRY));
00115     if (!BagEntry)
00116     {
00117         /* no memory */
00118         KeReleaseMutex(Bag->BagMutex, FALSE);
00119         /* return result */
00120         return STATUS_INSUFFICIENT_RESOURCES;
00121     }
00122 
00123     /* initialize bag entry */
00124     BagEntry->References = 1;
00125     BagEntry->Item = Item;
00126     if (Free)
00127         BagEntry->Free = Free;
00128     else
00129         BagEntry->Free = ExFreePool;
00130 
00131     /* insert item */
00132     InsertTailList(&Bag->ObjectList, &BagEntry->Entry);
00133 
00134     /* release mutex */
00135     KeReleaseMutex(Bag->BagMutex, FALSE);
00136 
00137     /* done */
00138     return STATUS_SUCCESS;
00139 }
00140 
00141 ULONG
00142 KspGetObjectItemReferenceCount(
00143     IN PKSIDEVICE_HEADER DeviceHeader,
00144     IN PVOID Item)
00145 {
00146     PLIST_ENTRY Entry;
00147     PKSIOBJECT_BAG OtherBag;
00148     PKSIOBJECT_BAG_ENTRY OtherBagEntry;
00149     ULONG TotalRefs = 0;
00150 
00151     /* scan all object bags and see if item is present there */
00152     Entry = DeviceHeader->ObjectBags.Flink;
00153     while(Entry != &DeviceHeader->ObjectBags)
00154     {
00155         /* get other bag */
00156         OtherBag = (PKSIOBJECT_BAG)CONTAINING_RECORD(Entry, KSIOBJECT_BAG, Entry);
00157 
00158         /* is the item present there */
00159         OtherBagEntry = KspFindObjectBagItem(&OtherBag->ObjectList, Item);
00160 
00161         if (OtherBagEntry)
00162             TotalRefs++;
00163 
00164         /* move to next item */
00165         Entry = Entry->Flink;
00166     }
00167 
00168     return TotalRefs;
00169 }
00170 
00171 /*
00172     @implemented
00173 */
00174 KSDDKAPI
00175 ULONG
00176 NTAPI
00177 KsRemoveItemFromObjectBag(
00178     IN KSOBJECT_BAG ObjectBag,
00179     IN PVOID Item,
00180     IN BOOLEAN Free)
00181 {
00182     PKSIOBJECT_BAG Bag;
00183     PKSIOBJECT_BAG_ENTRY BagEntry;
00184     ULONG TotalRefs;
00185 
00186     /* get real object bag */
00187     Bag = (PKSIOBJECT_BAG)ObjectBag;
00188 
00189     /* acquire bag mutex */
00190     KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL);
00191 
00192     /* is the item already present in this object bag */
00193     BagEntry = KspFindObjectBagItem(&Bag->ObjectList, Item);
00194 
00195     if (!BagEntry)
00196     {
00197         /* item was not in this object bag */
00198         KeReleaseMutex(Bag->BagMutex, FALSE);
00199         return 0;
00200     }
00201 
00202     /* set current refs count */
00203     TotalRefs = BagEntry->References;
00204 
00205     /* get total refs count */
00206     TotalRefs += KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER)Bag->DeviceHeader, Item);
00207 
00208     /* decrease reference count */
00209     InterlockedDecrement((PLONG)&BagEntry->References);
00210 
00211     if (BagEntry->References == 0)
00212     {
00213         /* remove the entry */
00214         RemoveEntryList(&BagEntry->Entry);
00215     }
00216 
00217     if (TotalRefs == 1)
00218     {
00219         /* does the caller want to free the item */
00220         if (Free)
00221         {
00222             /* free the item */
00223             BagEntry->Free(BagEntry->Item);
00224         }
00225     }
00226     if (BagEntry->References == 0)
00227     {
00228         /* free bag item entry */
00229         FreeItem(BagEntry);
00230     }
00231 
00232     /* release mutex */
00233     KeReleaseMutex(Bag->BagMutex, FALSE);
00234 
00235 
00236     return TotalRefs;
00237 }
00238 
00239 /*
00240     @implemented
00241 */
00242 KSDDKAPI
00243 NTSTATUS
00244 NTAPI
00245 KsCopyObjectBagItems(
00246     IN KSOBJECT_BAG ObjectBagDestination,
00247     IN KSOBJECT_BAG ObjectBagSource)
00248 {
00249     PKSIOBJECT_BAG ObjectBagDest, ObjectBagSrc;
00250     PLIST_ENTRY Entry;
00251     PKSIOBJECT_BAG_ENTRY BagEntry;
00252     NTSTATUS Status = STATUS_SUCCESS;
00253 
00254     /* get object bag src */
00255     ObjectBagSrc = (PKSIOBJECT_BAG)ObjectBagSource;
00256 
00257     /* get object bag dst */
00258     ObjectBagDest = (PKSIOBJECT_BAG)ObjectBagDestination;
00259 
00260     /* acquire source mutex */
00261     KeWaitForSingleObject(ObjectBagSrc->BagMutex, Executive, KernelMode, FALSE, NULL);
00262 
00263     if (ObjectBagSrc->BagMutex != ObjectBagDest->BagMutex)
00264     {
00265         /* acquire destination mutex */
00266         KeWaitForSingleObject(ObjectBagDest->BagMutex, Executive, KernelMode, FALSE, NULL);
00267     }
00268 
00269     /* point to first item */
00270     Entry = ObjectBagSrc->ObjectList.Flink;
00271     /* first scan the list if the item is already inserted */
00272     while(Entry != &ObjectBagSrc->ObjectList)
00273     {
00274         /* get bag entry */
00275         BagEntry = (PKSIOBJECT_BAG_ENTRY)CONTAINING_RECORD(Entry, KSIOBJECT_BAG_ENTRY, Entry);
00276 
00277         /* add the item */
00278         Status = KsAddItemToObjectBag(ObjectBagDestination, BagEntry->Item, BagEntry->Free);
00279 
00280         /* check for success */
00281         if (!NT_SUCCESS(Status))
00282             break;
00283 
00284         /* move to next entry */
00285         Entry = Entry->Flink;
00286     }
00287 
00288     if (ObjectBagSrc->BagMutex != ObjectBagDest->BagMutex)
00289     {
00290         /* release destination mutex */
00291         KeReleaseMutex(ObjectBagDest->BagMutex, FALSE);
00292     }
00293 
00294     /* release source mutex */
00295      KeReleaseMutex(ObjectBagSrc->BagMutex, FALSE);
00296 
00297     return Status;
00298 }
00299 
00300 /*
00301     @implemented
00302 */
00303 KSDDKAPI
00304 VOID
00305 NTAPI
00306 KsFreeObjectBag(
00307     IN KSOBJECT_BAG ObjectBag)
00308 {
00309     PLIST_ENTRY Entry;
00310     PKSIOBJECT_BAG Bag;
00311     PKSIOBJECT_BAG_ENTRY BagEntry;
00312     ULONG TotalRefs;
00313 
00314     /* get real object bag */
00315     Bag = (PKSIOBJECT_BAG)ObjectBag;
00316 
00317     /* acquire bag mutex */
00318     KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL);
00319 
00320     while(!IsListEmpty(&Bag->ObjectList))
00321     {
00322         /* get an bag entry */
00323         Entry = RemoveHeadList(&Bag->ObjectList);
00324         /* access bag entry item */
00325         BagEntry = (PKSIOBJECT_BAG_ENTRY)CONTAINING_RECORD(Entry, KSIOBJECT_BAG, Entry);
00326 
00327         /* check if the item is present in some other bag */
00328         TotalRefs = KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER)Bag->DeviceHeader, &BagEntry->Item);
00329 
00330         if (TotalRefs == 0)
00331         {
00332             /* item is ready to be freed */
00333             BagEntry->Free(BagEntry->Item);
00334         }
00335 
00336         /* free bag entry item */
00337         FreeItem(BagEntry);
00338     }
00339 
00340     /* remove bag entry from device object list */
00341     RemoveEntryList(&Bag->Entry);
00342 
00343     /* release bag mutex */
00344     KeReleaseMutex(Bag->BagMutex, FALSE);
00345 
00346     /* now free object bag */
00347     FreeItem(Bag);
00348 }
00349 
00350 /*
00351     @implemented
00352 */
00353 KSDDKAPI
00354 NTSTATUS
00355 NTAPI
00356 _KsEdit(
00357     IN KSOBJECT_BAG ObjectBag,
00358     IN OUT PVOID* PointerToPointerToItem,
00359     IN ULONG NewSize,
00360     IN ULONG OldSize,
00361     IN ULONG Tag)
00362 {
00363     PKSIOBJECT_BAG Bag;
00364     PKSIOBJECT_BAG_ENTRY BagEntry;
00365     PVOID Item;
00366     NTSTATUS Status;
00367 
00368     DPRINT("_KsEdit\n");
00369 
00370     /* get real object bag */
00371     Bag = (PKSIOBJECT_BAG)ObjectBag;
00372 
00373     /* acquire bag mutex */
00374     KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL);
00375 
00376 
00377     if (*PointerToPointerToItem)
00378     {
00379         /* search object bag for this entry */
00380         BagEntry = KspFindObjectBagItem(&Bag->ObjectList, *PointerToPointerToItem);
00381     }
00382     else
00383     {
00384         /* pointer to null, allocate new entry */
00385         BagEntry = NULL;
00386     }
00387 
00388     if (!BagEntry || NewSize > OldSize)
00389     {
00390         /* entry does not exist or new entry must be allocated */
00391         Item = AllocateItem(NonPagedPool, NewSize);
00392 
00393         if (!Item)
00394         {
00395             /* not enough resources */
00396             KeReleaseMutex(Bag->BagMutex, FALSE);
00397             return STATUS_INSUFFICIENT_RESOURCES;
00398         }
00399 
00400         /* now add the item to the object bag */
00401         Status = KsAddItemToObjectBag((KSOBJECT_BAG)Bag, Item, NULL);
00402         /* check for success */
00403         if (!NT_SUCCESS(Status))
00404         {
00405             /* failed to add item */
00406             FreeItem(Item);
00407             KeReleaseMutex(Bag->BagMutex, FALSE);
00408             return Status;
00409         }
00410 
00411         if (*PointerToPointerToItem)
00412         {
00413             /* object exists */
00414             if (OldSize >= NewSize)
00415             {
00416                 /* copy old contents */
00417                 RtlMoveMemory(Item, *PointerToPointerToItem, NewSize);
00418             }
00419             else
00420             {
00421                 /* copy new contents */
00422                 RtlMoveMemory(Item, *PointerToPointerToItem, OldSize);
00423             }
00424         }
00425 
00426         if (BagEntry)
00427         {
00428             /* remove old entry */
00429             KsRemoveItemFromObjectBag(ObjectBag, BagEntry->Item, TRUE);
00430         }
00431 
00432         /* store item */
00433        *PointerToPointerToItem = Item;
00434     }
00435 
00436     /* release bag mutex */
00437     KeReleaseMutex(Bag->BagMutex, FALSE);
00438 
00439     return STATUS_SUCCESS;
00440 }
00441 
00442 

Generated on Sat May 26 2012 04:26:32 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.