- Implement KsGetObjectFromFileObject, KsGetObjectFromFileObject, KsGetObjectTypeFromIrp, KsGetParent

- Create object bag for IKsFilter, IKsFilterFactory and IKsDevice

svn path=/trunk/; revision=42275
This commit is contained in:
Johannes Anderwald 2009-07-28 16:18:05 +00:00
parent ca60ae56c0
commit 64fa3b028f
7 changed files with 311 additions and 23 deletions

View file

@ -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);

View file

@ -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);
}

View file

@ -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 */

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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;

View file

@ -1,6 +1,9 @@
#ifndef KSTYPES_H__
#define KSTYPES_H__
#include <ntddk.h>
#include <ks.h>
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;