From 64fa3b028fe16bff22ad3c542aec8092802bd8e9 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Tue, 28 Jul 2009 16:18:05 +0000 Subject: [PATCH] - Implement KsGetObjectFromFileObject, KsGetObjectFromFileObject, KsGetObjectTypeFromIrp, KsGetParent - Create object bag for IKsFilter, IKsFilterFactory and IKsDevice svn path=/trunk/; revision=42275 --- reactos/drivers/ksfilter/ks/api.c | 2 + reactos/drivers/ksfilter/ks/bag.c | 243 +++++++++++++++++++- reactos/drivers/ksfilter/ks/device.c | 45 +++- reactos/drivers/ksfilter/ks/filter.c | 15 ++ reactos/drivers/ksfilter/ks/filterfactory.c | 10 +- reactos/drivers/ksfilter/ks/ksiface.h | 14 +- reactos/drivers/ksfilter/ks/kstypes.h | 5 +- 7 files changed, 311 insertions(+), 23 deletions(-) diff --git a/reactos/drivers/ksfilter/ks/api.c b/reactos/drivers/ksfilter/ks/api.c index ceee766c1c6..66b3f165127 100644 --- a/reactos/drivers/ksfilter/ks/api.c +++ b/reactos/drivers/ksfilter/ks/api.c @@ -509,6 +509,8 @@ KsAllocateDeviceHeader( InitializeListHead(&Header->TargetDeviceList); /* initialize power dispatch list */ InitializeListHead(&Header->PowerDispatchList); + /* initialize object bag lists */ + InitializeListHead(&Header->ObjectBags); /* initialize create item list */ InitializeListHead(&Header->ItemList); diff --git a/reactos/drivers/ksfilter/ks/bag.c b/reactos/drivers/ksfilter/ks/bag.c index e9fafbb9401..fa2486ba117 100644 --- a/reactos/drivers/ksfilter/ks/bag.c +++ b/reactos/drivers/ksfilter/ks/bag.c @@ -9,8 +9,17 @@ #include "priv.h" +typedef struct +{ + LIST_ENTRY Entry; + PVOID Item; + PFNKSFREE Free; + ULONG References; +}KSIOBJECT_BAG_ENTRY, *PKSIOBJECT_BAG_ENTRY; + + /* - @unimplemented + @implemented */ KSDDKAPI NTSTATUS @@ -19,12 +28,56 @@ KsAllocateObjectBag( IN PKSDEVICE Device, OUT KSOBJECT_BAG* ObjectBag) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + PKSIDEVICE_HEADER DeviceHeader; + PKSIOBJECT_BAG Bag; + IKsDevice *KsDevice; + + /* get real device header */ + DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice); + + /* allocate a object bag ctx */ + Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG)); + if (!Bag) + return STATUS_INSUFFICIENT_RESOURCES; + + /* get device interface */ + KsDevice = (IKsDevice*)&DeviceHeader->lpVtblIKsDevice; + + /* initialize object bag */ + return KsDevice->lpVtbl->InitializeObjectBag(KsDevice, Bag, NULL); } +PKSIOBJECT_BAG_ENTRY +KspFindObjectBagItem( + IN PLIST_ENTRY ObjectList, + IN PVOID Item) +{ + PLIST_ENTRY Entry; + PKSIOBJECT_BAG_ENTRY BagEntry; + + /* point to first item */ + Entry = ObjectList->Flink; + /* first scan the list if the item is already inserted */ + while(Entry != ObjectList) + { + /* get bag entry */ + BagEntry = (PKSIOBJECT_BAG_ENTRY)CONTAINING_RECORD(Entry, KSIOBJECT_BAG_ENTRY, Entry); + + if (BagEntry->Item == Item) + { + /* found entry */ + return BagEntry; + } + /* move to next entry */ + Entry = Entry->Flink; + } + /* item not in this object bag */ + return NULL; +} + + /* - @unimplemented + @implemented */ NTSTATUS NTAPI @@ -33,12 +86,88 @@ KsAddItemToObjectBag( IN PVOID Item, IN PFNKSFREE Free OPTIONAL) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + PKSIOBJECT_BAG Bag; + PKSIOBJECT_BAG_ENTRY BagEntry; + + /* get real object bag */ + Bag = (PKSIOBJECT_BAG)ObjectBag; + + /* acquire bag mutex */ + KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL); + + /* is the item already present in this object bag */ + BagEntry = KspFindObjectBagItem(&Bag->ObjectList, Item); + + if (BagEntry) + { + /* is is, update reference count */ + InterlockedIncrement((PLONG)&BagEntry->References); + /* release mutex */ + KeReleaseMutex(Bag->BagMutex, FALSE); + /* return result */ + return STATUS_SUCCESS; + } + + /* item is new, allocate entry */ + BagEntry = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG_ENTRY)); + if (!BagEntry) + { + /* no memory */ + KeReleaseMutex(Bag->BagMutex, FALSE); + /* return result */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* initialize bag entry */ + BagEntry->References = 1; + BagEntry->Item = Item; + if (Free) + BagEntry->Free = Free; + else + BagEntry->Free = ExFreePool; + + /* insert item */ + InsertTailList(&Bag->ObjectList, &Bag->Entry); + + /* release mutex */ + KeReleaseMutex(Bag->BagMutex, FALSE); + + /* done */ + return STATUS_SUCCESS; +} + +ULONG +KspGetObjectItemReferenceCount( + IN PKSIDEVICE_HEADER DeviceHeader, + IN PVOID Item) +{ + PLIST_ENTRY Entry; + PKSIOBJECT_BAG OtherBag; + PKSIOBJECT_BAG_ENTRY OtherBagEntry; + ULONG TotalRefs = 0; + + /* scan all object bags and see if item is present there */ + Entry = DeviceHeader->ObjectBags.Flink; + while(Entry != &DeviceHeader->ObjectBags) + { + /* get other bag */ + OtherBag = (PKSIOBJECT_BAG)CONTAINING_RECORD(Entry, KSIOBJECT_BAG, Entry); + + /* is the item present there */ + OtherBagEntry = KspFindObjectBagItem(&OtherBag->ObjectList, Item); + + if (OtherBagEntry) + TotalRefs++; + + /* move to next item */ + Entry = Entry->Flink; + } + + return TotalRefs; } /* - @unimplemented + @implemented */ KSDDKAPI ULONG @@ -48,8 +177,61 @@ KsRemoveItemFromObjectBag( IN PVOID Item, IN BOOLEAN Free) { - UNIMPLEMENTED - return 0; + PKSIOBJECT_BAG Bag; + PKSIOBJECT_BAG_ENTRY BagEntry; + ULONG TotalRefs; + + /* get real object bag */ + Bag = (PKSIOBJECT_BAG)ObjectBag; + + /* acquire bag mutex */ + KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL); + + /* is the item already present in this object bag */ + BagEntry = KspFindObjectBagItem(&Bag->ObjectList, Item); + + if (!BagEntry) + { + /* item was not in this object bag */ + KeReleaseMutex(Bag->BagMutex, FALSE); + return 0; + } + + /* set current refs count */ + TotalRefs = BagEntry->References; + + /* get total refs count */ + TotalRefs += KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER)Bag->DeviceHeader, Item); + + /* decrease reference count */ + InterlockedDecrement((PLONG)&BagEntry->References); + + if (BagEntry->References == 0) + { + /* remove the entry */ + RemoveEntryList(&BagEntry->Entry); + } + + if (TotalRefs == 1) + { + /* does the caller want to free the item */ + if (Free) + { + /* free the item */ + BagEntry->Free(BagEntry->Item); + } + } + if (BagEntry->References == 0) + { + /* free bag item entry */ + FreeItem(BagEntry); + } + + /* release mutex */ + KeReleaseMutex(Bag->BagMutex, FALSE); + + + return TotalRefs; } /* @@ -66,13 +248,54 @@ KsCopyObjectBagItems( return STATUS_NOT_IMPLEMENTED; } +/* + @implemented +*/ KSDDKAPI VOID NTAPI KsFreeObjectBag( IN KSOBJECT_BAG ObjectBag) { - UNIMPLEMENTED + PLIST_ENTRY Entry; + PKSIOBJECT_BAG Bag; + PKSIOBJECT_BAG_ENTRY BagEntry; + ULONG TotalRefs; + + /* get real object bag */ + Bag = (PKSIOBJECT_BAG)ObjectBag; + + /* acquire bag mutex */ + KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL); + + while(!IsListEmpty(&Bag->ObjectList)) + { + /* get an bag entry */ + Entry = RemoveHeadList(&Bag->ObjectList); + /* access bag entry item */ + BagEntry = (PKSIOBJECT_BAG_ENTRY)CONTAINING_RECORD(Entry, KSIOBJECT_BAG, Entry); + + /* check if the item is present in some other bag */ + TotalRefs = KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER)Bag->DeviceHeader, &BagEntry->Item); + + if (TotalRefs == 0) + { + /* item is ready to be freed */ + BagEntry->Free(BagEntry->Item); + } + + /* free bag entry item */ + FreeItem(BagEntry); + } + + /* remove bag entry from device object list */ + RemoveEntryList(&Bag->Entry); + + /* release bag mutex */ + KeReleaseMutex(Bag->BagMutex, FALSE); + + /* now free object bag */ + FreeItem(Bag); } diff --git a/reactos/drivers/ksfilter/ks/device.c b/reactos/drivers/ksfilter/ks/device.c index 1ae81a651c6..6a218a32d11 100644 --- a/reactos/drivers/ksfilter/ks/device.c +++ b/reactos/drivers/ksfilter/ks/device.c @@ -66,13 +66,26 @@ NTSTATUS NTAPI IKsDevice_fnInitializeObjectBag( IN IKsDevice * iface, - IN struct KSIOBJECTBAG *Bag, - IN KMUTANT * Mutant) + IN PKSIOBJECT_BAG Bag, + IN PRKMUTEX Mutex) { - //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice); + PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice); - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + if (!Mutex) + { + /* use device mutex */ + Mutex = &This->DeviceMutex; + } + + /* initialize object bag */ + Bag->BagMutex = Mutex; + Bag->DeviceHeader = (PKSIDEVICE_HEADER)This; + InitializeListHead(&Bag->ObjectList); + + /* insert bag into device list */ + InsertTailList(&This->ObjectBags, &Bag->Entry); + + return STATUS_SUCCESS; } NTSTATUS @@ -627,6 +640,7 @@ KsInitializeDevice( PDEVICE_EXTENSION DeviceExtension; PKSIDEVICE_HEADER Header; ULONG Index; + IKsDevice * KsDevice; NTSTATUS Status = STATUS_SUCCESS; /* get device extension */ @@ -645,15 +659,30 @@ KsInitializeDevice( return Status; } + /* initialize IKsDevice interface */ + Header->lpVtblIKsDevice = &vt_IKsDevice; + Header->ref = 1; + + /* initialize object bag */ + Header->KsDevice.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG)); + if (!Header->KsDevice.Bag) + { + /* no memory */ + KsFreeDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader); + return STATUS_INSUFFICIENT_RESOURCES; + } + + KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice; + KsDevice->lpVtbl->InitializeObjectBag(KsDevice, Header->KsDevice.Bag, NULL); + + /* initialize device header */ Header->KsDevice.FunctionalDeviceObject = FunctionalDeviceObject; Header->KsDevice.PhysicalDeviceObject = PhysicalDeviceObject; Header->KsDevice.NextDeviceObject = NextDeviceObject; Header->KsDevice.Descriptor = Descriptor; KsSetDevicePnpAndBaseObject(Header, PhysicalDeviceObject, NextDeviceObject); - /* initialize IKsDevice interface */ - Header->lpVtblIKsDevice = &vt_IKsDevice; - Header->ref = 1; + /* FIXME Power state */ diff --git a/reactos/drivers/ksfilter/ks/filter.c b/reactos/drivers/ksfilter/ks/filter.c index 5b86c3cc6e8..5d0a5a4ae68 100644 --- a/reactos/drivers/ksfilter/ks/filter.c +++ b/reactos/drivers/ksfilter/ks/filter.c @@ -831,6 +831,7 @@ KspCreateFilter( IN IKsFilterFactory *iface) { IKsFilterImpl * This; + IKsDevice *KsDevice; PKSFILTERFACTORY Factory; PIO_STACK_LOCATION IoStack; PDEVICE_EXTENSION DeviceExtension; @@ -856,10 +857,24 @@ KspCreateFilter( /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* initialize object bag */ + This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG)); + if (!This->Filter.Bag) + { + /* no memory */ + FreeItem(This); + return STATUS_INSUFFICIENT_RESOURCES; + } + + KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice; + KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL); + /* initialize filter instance */ This->ref = 1; This->lpVtbl = &vt_IKsFilter; This->lpVtblKsControl = &vt_IKsControl; + This->Filter.Descriptor = Factory->FilterDescriptor; This->Factory = Factory; This->FilterFactory = iface; diff --git a/reactos/drivers/ksfilter/ks/filterfactory.c b/reactos/drivers/ksfilter/ks/filterfactory.c index 24a48343911..65098126efd 100644 --- a/reactos/drivers/ksfilter/ks/filterfactory.c +++ b/reactos/drivers/ksfilter/ks/filterfactory.c @@ -173,6 +173,7 @@ IKsFilterFactory_fnInitialize( PDEVICE_EXTENSION DeviceExtension; KSOBJECT_CREATE_ITEM CreateItem; BOOL FreeString = FALSE; + IKsDevice * KsDevice; IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl); @@ -253,7 +254,14 @@ IKsFilterFactory_fnInitialize( /* return filterfactory */ *FilterFactory = &This->FilterFactory; - /*FIXME create object bag */ + /* create a object bag for the filter factory */ + This->FilterFactory.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG)); + if (This->FilterFactory.Bag) + { + /* initialize object bag */ + KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice; + KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->FilterFactory.Bag, NULL); + } } diff --git a/reactos/drivers/ksfilter/ks/ksiface.h b/reactos/drivers/ksfilter/ks/ksiface.h index f323e1a84c8..3078f567d56 100644 --- a/reactos/drivers/ksfilter/ks/ksiface.h +++ b/reactos/drivers/ksfilter/ks/ksiface.h @@ -14,6 +14,15 @@ STDMETHOD_(ULONG,Release)(THIS) PURE; #endif +typedef struct +{ + LIST_ENTRY Entry; + LIST_ENTRY ObjectList; + PRKMUTEX BagMutex; + PVOID DeviceHeader; +}KSIOBJECT_BAG, *PKSIOBJECT_BAG; + + /***************************************************************************** * IKsAllocator ***************************************************************************** @@ -199,7 +208,6 @@ DECLARE_INTERFACE_(IKsPowerNotify, IUnknown) #undef INTERFACE #define INTERFACE IKsDevice -struct KSIOBJECTBAG; struct KSPOWER_ENTRY; DECLARE_INTERFACE_(IKsDevice, IUnknown) @@ -209,8 +217,8 @@ DECLARE_INTERFACE_(IKsDevice, IUnknown) STDMETHOD_(KSDEVICE*,GetStruct)(THIS) PURE; STDMETHOD_(NTSTATUS, InitializeObjectBag)(THIS_ - IN struct KSIOBJECTBAG *Bag, - IN KMUTANT * Mutant) PURE; + IN PKSIOBJECT_BAG Bag, + IN PRKMUTEX Mutex) PURE; STDMETHOD_(NTSTATUS,AcquireDevice)(THIS) PURE; STDMETHOD_(NTSTATUS,ReleaseDevice)(THIS) PURE; diff --git a/reactos/drivers/ksfilter/ks/kstypes.h b/reactos/drivers/ksfilter/ks/kstypes.h index faba9f84cfb..a278246eeb0 100644 --- a/reactos/drivers/ksfilter/ks/kstypes.h +++ b/reactos/drivers/ksfilter/ks/kstypes.h @@ -1,6 +1,9 @@ #ifndef KSTYPES_H__ #define KSTYPES_H__ +#include +#include + typedef struct { KoCreateObjectHandler CreateObjectHandler; @@ -87,10 +90,10 @@ typedef struct KSDEVICE_DESCRIPTOR* Descriptor; LIST_ENTRY PowerDispatchList; + LIST_ENTRY ObjectBags; }KSIDEVICE_HEADER, *PKSIDEVICE_HEADER; - typedef struct { PKSIDEVICE_HEADER DeviceHeader;