reactos/drivers/ksfilter/ks/api.c

2612 lines
67 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/ksfilter/ks/api.c
* PURPOSE: KS API functions
* PROGRAMMER: Johannes Anderwald
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
const GUID GUID_NULL = {0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsAcquireResetValue(
IN PIRP Irp,
OUT KSRESET* ResetValue)
{
PIO_STACK_LOCATION IoStack;
KSRESET* Value;
NTSTATUS Status = STATUS_SUCCESS;
/* get current irp stack */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* check if there is reset value provided */
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSRESET))
return STATUS_INVALID_PARAMETER;
if (Irp->RequestorMode == UserMode)
{
/* need to probe the buffer */
_SEH2_TRY
{
ProbeForRead(IoStack->Parameters.DeviceIoControl.Type3InputBuffer, sizeof(KSRESET), sizeof(UCHAR));
Value = (KSRESET*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
*ResetValue = *Value;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Exception, get the error code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
}
else
{
Value = (KSRESET*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
*ResetValue = *Value;
}
return Status;
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsAcquireDeviceSecurityLock(
IN KSDEVICE_HEADER DevHeader,
IN BOOLEAN Exclusive)
{
PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
KeEnterCriticalRegion();
if (Exclusive)
{
ExAcquireResourceExclusiveLite(&Header->SecurityLock, TRUE);
}
else
{
ExAcquireResourceSharedLite(&Header->SecurityLock, TRUE);
}
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsReleaseDeviceSecurityLock(
IN KSDEVICE_HEADER DevHeader)
{
PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
DPRINT("KsReleaseDevice\n");
ExReleaseResourceLite(&Header->SecurityLock);
KeLeaveCriticalRegion();
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsDefaultDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
PKSIDEVICE_HEADER DeviceHeader;
PIO_STACK_LOCATION IoStack;
PDEVICE_OBJECT PnpDeviceObject;
NTSTATUS Status;
ULONG MinorFunction;
/* get current irp stack */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* caller wants to add the target device */
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* get device header */
DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
/* backup PnpBaseObject */
PnpDeviceObject = DeviceHeader->PnpDeviceObject;
/* backup minor function code */
MinorFunction = IoStack->MinorFunction;
if(MinorFunction == IRP_MN_REMOVE_DEVICE)
{
/* remove the device */
KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceHeader);
}
/* skip current irp stack */
IoSkipCurrentIrpStackLocation(Irp);
/* call attached pnp device object */
Status = IoCallDriver(PnpDeviceObject, Irp);
if (MinorFunction == IRP_MN_REMOVE_DEVICE)
{
/* time is over */
IoDetachDevice(PnpDeviceObject);
/* delete device */
IoDeleteDevice(DeviceObject);
}
/* done */
return Status;
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsDefaultDispatchPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
PKSIDEVICE_HEADER DeviceHeader;
PKSIOBJECT_HEADER ObjectHeader;
//PIO_STACK_LOCATION IoStack;
PLIST_ENTRY ListEntry;
NTSTATUS Status;
/* get current irp stack */
//IoStack = IoGetCurrentIrpStackLocation(Irp);
/* caller wants to add the target device */
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* get device header */
DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
/* FIXME locks */
/* loop our power dispatch list and call registered notification functions */
ListEntry = DeviceHeader->PowerDispatchList.Flink;
/* let's go */
while(ListEntry != &DeviceHeader->PowerDispatchList)
{
/* get object header */
ObjectHeader = (PKSIOBJECT_HEADER)CONTAINING_RECORD(ListEntry, KSIOBJECT_HEADER, PowerDispatchEntry);
/* does it have still a cb */
if (ObjectHeader->PowerDispatch)
{
/* call the power cb */
Status = ObjectHeader->PowerDispatch(ObjectHeader->PowerContext, Irp);
ASSERT(NT_SUCCESS(Status));
}
/* iterate to next entry */
ListEntry = ListEntry->Flink;
}
/* start next power irp */
PoStartNextPowerIrp(Irp);
/* skip current irp stack location */
IoSkipCurrentIrpStackLocation(Irp);
/* let's roll */
Status = PoCallDriver(DeviceHeader->PnpDeviceObject, Irp);
/* done */
return Status;
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsDefaultForwardIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
PKSIDEVICE_HEADER DeviceHeader;
//PIO_STACK_LOCATION IoStack;
NTSTATUS Status;
/* get current irp stack */
//IoStack = IoGetCurrentIrpStackLocation(Irp);
/* caller wants to add the target device */
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* get device header */
DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
/* forward the request to the PDO */
Status = IoCallDriver(DeviceHeader->PnpDeviceObject, Irp);
return Status;
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsSetDevicePnpAndBaseObject(
IN KSDEVICE_HEADER Header,
IN PDEVICE_OBJECT PnpDeviceObject,
IN PDEVICE_OBJECT BaseDevice)
{
PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
DeviceHeader->PnpDeviceObject = PnpDeviceObject;
DeviceHeader->BaseDevice = BaseDevice;
}
/*
@implemented
*/
KSDDKAPI
PDEVICE_OBJECT
NTAPI
KsQueryDevicePnpObject(
IN KSDEVICE_HEADER Header)
{
PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
/* return PnpDeviceObject */
return DeviceHeader->PnpDeviceObject;
}
/*
@implemented
*/
KSDDKAPI
ACCESS_MASK
NTAPI
KsQueryObjectAccessMask(
IN KSOBJECT_HEADER Header)
{
PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
/* return access mask */
return ObjectHeader->AccessMask;
}
/*
@unimplemented
*/
KSDDKAPI
VOID
NTAPI
KsRecalculateStackDepth(
IN KSDEVICE_HEADER Header,
IN BOOLEAN ReuseStackLocation)
{
UNIMPLEMENTED;
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsSetTargetState(
IN KSOBJECT_HEADER Header,
IN KSTARGET_STATE TargetState)
{
PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
/* set target state */
DeviceHeader->TargetState = TargetState;
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsSetTargetDeviceObject(
IN KSOBJECT_HEADER Header,
IN PDEVICE_OBJECT TargetDevice OPTIONAL)
{
PDEVICE_EXTENSION DeviceExtension;
PKSIDEVICE_HEADER DeviceHeader;
PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
if(ObjectHeader->TargetDevice)
{
/* there is already a target device set */
if (!TargetDevice)
{
/* caller wants to remove the target device */
DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->TargetDevice->DeviceExtension;
/* get device header */
DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
/* acquire lock */
KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
/* remove entry */
RemoveEntryList(&ObjectHeader->TargetDeviceListEntry);
/* remove device pointer */
ObjectHeader->TargetDevice = NULL;
/* release lock */
KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
}
}
else
{
/* no target device yet set */
if (TargetDevice)
{
/* caller wants to add the target device */
DeviceExtension = (PDEVICE_EXTENSION)TargetDevice->DeviceExtension;
/* get device header */
DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
/* acquire lock */
KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
/* insert list entry */
InsertTailList(&DeviceHeader->TargetDeviceList, &ObjectHeader->TargetDeviceListEntry);
/* store target device */
ObjectHeader->TargetDevice = TargetDevice;
/* release lock */
KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
}
}
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsSetPowerDispatch(
IN KSOBJECT_HEADER Header,
IN PFNKSCONTEXT_DISPATCH PowerDispatch OPTIONAL,
IN PVOID PowerContext OPTIONAL)
{
PDEVICE_EXTENSION DeviceExtension;
PKSIDEVICE_HEADER DeviceHeader;
PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
/* caller wants to add the target device */
DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->ParentDeviceObject->DeviceExtension;
/* get device header */
DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
/* acquire lock */
KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
if (PowerDispatch)
{
/* add power dispatch entry */
InsertTailList(&DeviceHeader->PowerDispatchList, &ObjectHeader->PowerDispatchEntry);
/* store function and context */
ObjectHeader->PowerDispatch = PowerDispatch;
ObjectHeader->PowerContext = PowerContext;
}
else
{
/* remove power dispatch entry */
RemoveEntryList(&ObjectHeader->PowerDispatchEntry);
/* store function and context */
ObjectHeader->PowerDispatch = NULL;
ObjectHeader->PowerContext = NULL;
}
/* release lock */
KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
}
/*
@implemented
*/
KSDDKAPI
PKSOBJECT_CREATE_ITEM
NTAPI
KsQueryObjectCreateItem(
IN KSOBJECT_HEADER Header)
{
PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
return ObjectHeader->OriginalCreateItem;
}
NTSTATUS
KspAddCreateItemToList(
OUT PLIST_ENTRY ListHead,
IN ULONG ItemsCount,
IN PKSOBJECT_CREATE_ITEM ItemsList)
{
ULONG Index;
PCREATE_ITEM_ENTRY Entry;
/* add the items */
for(Index = 0; Index < ItemsCount; Index++)
{
/* allocate item */
Entry = AllocateItem(NonPagedPool, sizeof(CREATE_ITEM_ENTRY));
if (!Entry)
{
/* no memory */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* initialize entry */
InitializeListHead(&Entry->ObjectItemList);
Entry->CreateItem = &ItemsList[Index];
Entry->ReferenceCount = 0;
Entry->ItemFreeCallback = NULL;
InsertTailList(ListHead, &Entry->Entry);
}
return STATUS_SUCCESS;
}
VOID
KspFreeCreateItems(
PLIST_ENTRY ListHead)
{
PCREATE_ITEM_ENTRY Entry;
while(!IsListEmpty(ListHead))
{
/* remove create item from list */
Entry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(RemoveHeadList(ListHead), CREATE_ITEM_ENTRY, Entry);
/* caller shouldnt have any references */
//ASSERT(Entry->ReferenceCount == 0);
//ASSERT(IsListEmpty(&Entry->ObjectItemList));
/* does the creator wish notification */
if (Entry->ItemFreeCallback)
{
/* notify creator */
Entry->ItemFreeCallback(Entry->CreateItem);
}
/* free create item entry */
FreeItem(Entry);
}
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsAllocateDeviceHeader(
OUT KSDEVICE_HEADER* OutHeader,
IN ULONG ItemsCount,
IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL)
{
NTSTATUS Status = STATUS_SUCCESS;
PKSIDEVICE_HEADER Header;
if (!OutHeader)
return STATUS_INVALID_PARAMETER;
/* allocate a device header */
Header = AllocateItem(PagedPool, sizeof(KSIDEVICE_HEADER));
/* check for success */
if (!Header)
return STATUS_INSUFFICIENT_RESOURCES;
/* clear all memory */
RtlZeroMemory(Header, sizeof(KSIDEVICE_HEADER));
/* initialize device mutex */
KeInitializeMutex(&Header->DeviceMutex, 0);
/* initialize target device list */
InitializeListHead(&Header->TargetDeviceList);
/* initialize power dispatch list */
InitializeListHead(&Header->PowerDispatchList);
/* initialize object bag lists */
InitializeListHead(&Header->ObjectBags);
/* initialize create item list */
InitializeListHead(&Header->ItemList);
/* initialize basic header */
Header->BasicHeader.Type = KsObjectTypeDevice;
Header->BasicHeader.KsDevice = &Header->KsDevice;
Header->BasicHeader.Parent.KsDevice = &Header->KsDevice;
/* are there any create items provided */
if (ItemsCount && ItemsList)
{
Status = KspAddCreateItemToList(&Header->ItemList, ItemsCount, ItemsList);
if (NT_SUCCESS(Status))
{
/* store item count */
Header->ItemListCount = ItemsCount;
}
else
{
/* release create items */
KspFreeCreateItems(&Header->ItemList);
}
}
/* store result */
*OutHeader = Header;
return Status;
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsFreeDeviceHeader(
IN KSDEVICE_HEADER DevHeader)
{
PKSIDEVICE_HEADER Header;
Header = (PKSIDEVICE_HEADER)DevHeader;
if (!DevHeader)
return;
KspFreeCreateItems(&Header->ItemList);
FreeItem(Header);
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsAllocateObjectHeader(
OUT KSOBJECT_HEADER *Header,
IN ULONG ItemsCount,
IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL,
IN PIRP Irp,
IN KSDISPATCH_TABLE* Table)
{
PIO_STACK_LOCATION IoStack;
//PDEVICE_EXTENSION DeviceExtension;
//PKSIDEVICE_HEADER DeviceHeader;
PKSIOBJECT_HEADER ObjectHeader;
//PKSOBJECT_CREATE_ITEM CreateItem;
NTSTATUS Status;
if (!Header)
return STATUS_INVALID_PARAMETER_1;
if (!Irp)
return STATUS_INVALID_PARAMETER_4;
if (!Table)
return STATUS_INVALID_PARAMETER_5;
/* get current stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* get device extension */
//DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
/* get device header */
//DeviceHeader = DeviceExtension->DeviceHeader;
/* sanity check */
ASSERT(IoStack->FileObject);
/* check for an file object */
/* allocate the object header */
ObjectHeader = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_HEADER));
if (!ObjectHeader)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize object header */
RtlZeroMemory(ObjectHeader, sizeof(KSIOBJECT_HEADER));
/* initialize create item list */
InitializeListHead(&ObjectHeader->ItemList);
/* get create item */
//CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
/* do we have a name */
if (IoStack->FileObject->FileName.Buffer)
{
/* copy object class */
ObjectHeader->ObjectClass.MaximumLength = IoStack->FileObject->FileName.MaximumLength;
ObjectHeader->ObjectClass.Buffer = AllocateItem(NonPagedPool, ObjectHeader->ObjectClass.MaximumLength);
if (!ObjectHeader->ObjectClass.Buffer)
{
FreeItem(ObjectHeader);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyUnicodeString(&ObjectHeader->ObjectClass, &IoStack->FileObject->FileName);
}
/* copy dispatch table */
RtlCopyMemory(&ObjectHeader->DispatchTable, Table, sizeof(KSDISPATCH_TABLE));
/* store create items */
if (ItemsCount && ItemsList)
{
Status = KspAddCreateItemToList(&ObjectHeader->ItemList, ItemsCount, ItemsList);
if (NT_SUCCESS(Status))
{
/* store item count */
ObjectHeader->ItemListCount = ItemsCount;
}
else
{
/* destroy header*/
KsFreeObjectHeader(ObjectHeader);
return Status;
}
}
/* store the object in the file object */
IoStack->FileObject->FsContext2 = ObjectHeader;
/* store parent device */
ObjectHeader->ParentDeviceObject = IoGetRelatedDeviceObject(IoStack->FileObject);
/* store originating create item */
ObjectHeader->OriginalCreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
/* FIXME store access mask see KsQueryObjectAccessMask */
ObjectHeader->AccessMask = IoStack->Parameters.Create.SecurityContext->DesiredAccess;
/* store result */
*Header = ObjectHeader;
DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectHeader->ObjectClass.Buffer, IoStack->FileObject, ObjectHeader);
return STATUS_SUCCESS;
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsFreeObjectHeader(
IN PVOID Header)
{
PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER) Header;
DPRINT("KsFreeObjectHeader Header %p Class %wZ\n", Header, &ObjectHeader->ObjectClass);
if (ObjectHeader->ObjectClass.Buffer)
{
/* release object class buffer */
FreeItem(ObjectHeader->ObjectClass.Buffer);
}
if (ObjectHeader->Unknown)
{
/* release associated object */
ObjectHeader->Unknown->lpVtbl->Release(ObjectHeader->Unknown);
}
/* free create items */
KspFreeCreateItems(&ObjectHeader->ItemList);
/* free object header */
FreeItem(ObjectHeader);
}
NTSTATUS
KspAddObjectCreateItemToList(
PLIST_ENTRY ListHead,
IN PDRIVER_DISPATCH Create,
IN PVOID Context,
IN PWCHAR ObjectClass,
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
{
PLIST_ENTRY Entry;
PCREATE_ITEM_ENTRY CreateEntry;
/* point to first entry */
Entry = ListHead->Flink;
while(Entry != ListHead)
{
/* get create entry */
CreateEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
/* if the create item has no create routine, then it is free to use */
if (CreateEntry->CreateItem->Create == NULL)
{
/* sanity check */
ASSERT(IsListEmpty(&CreateEntry->ObjectItemList));
ASSERT(CreateEntry->ReferenceCount == 0);
/* use free entry */
CreateEntry->CreateItem->Context = Context;
CreateEntry->CreateItem->Create = Create;
RtlInitUnicodeString(&CreateEntry->CreateItem->ObjectClass, ObjectClass);
CreateEntry->CreateItem->SecurityDescriptor = SecurityDescriptor;
return STATUS_SUCCESS;
}
if (!wcsicmp(ObjectClass, CreateEntry->CreateItem->ObjectClass.Buffer))
{
/* the same object class already exists */
return STATUS_OBJECT_NAME_COLLISION;
}
/* iterate to next entry */
Entry = Entry->Flink;
}
return STATUS_ALLOTTED_SPACE_EXCEEDED;
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsAddObjectCreateItemToDeviceHeader(
IN KSDEVICE_HEADER DevHeader,
IN PDRIVER_DISPATCH Create,
IN PVOID Context,
IN PWCHAR ObjectClass,
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
{
PKSIDEVICE_HEADER Header;
NTSTATUS Status;
Header = (PKSIDEVICE_HEADER)DevHeader;
DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
/* check if a device header has been provided */
if (!DevHeader)
return STATUS_INVALID_PARAMETER_1;
/* check if a create item has been provided */
if (!Create)
return STATUS_INVALID_PARAMETER_2;
/* check if a object class has been provided */
if (!ObjectClass)
return STATUS_INVALID_PARAMETER_4;
/* let others do the work */
Status = KspAddObjectCreateItemToList(&Header->ItemList, Create, Context, ObjectClass, SecurityDescriptor);
if (NT_SUCCESS(Status))
{
/* increment create item count */
InterlockedIncrement(&Header->ItemListCount);
}
DPRINT("KsAddObjectCreateItemToDeviceHeader Status %x\n", Status);
return Status;
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsAddObjectCreateItemToObjectHeader(
IN KSOBJECT_HEADER ObjectHeader,
IN PDRIVER_DISPATCH Create,
IN PVOID Context,
IN PWCHAR ObjectClass,
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
{
PKSIOBJECT_HEADER Header;
NTSTATUS Status;
Header = (PKSIOBJECT_HEADER)ObjectHeader;
DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
/* check if a device header has been provided */
if (!Header)
return STATUS_INVALID_PARAMETER_1;
/* check if a create item has been provided */
if (!Create)
return STATUS_INVALID_PARAMETER_2;
/* check if a object class has been provided */
if (!ObjectClass)
return STATUS_INVALID_PARAMETER_4;
/* let's work */
Status = KspAddObjectCreateItemToList(&Header->ItemList, Create, Context, ObjectClass, SecurityDescriptor);
if (NT_SUCCESS(Status))
{
/* increment create item count */
InterlockedIncrement(&Header->ItemListCount);
}
return Status;
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsAllocateObjectCreateItem(
IN KSDEVICE_HEADER DevHeader,
IN PKSOBJECT_CREATE_ITEM CreateItem,
IN BOOLEAN AllocateEntry,
IN PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL)
{
PCREATE_ITEM_ENTRY CreateEntry;
PKSIDEVICE_HEADER Header;
PKSOBJECT_CREATE_ITEM Item;
Header = (PKSIDEVICE_HEADER)DevHeader;
if (!DevHeader)
return STATUS_INVALID_PARAMETER_1;
if (!CreateItem)
return STATUS_INVALID_PARAMETER_2;
/* first allocate a create entry */
CreateEntry = AllocateItem(NonPagedPool, sizeof(CREATE_ITEM_ENTRY));
/* check for allocation success */
if (!CreateEntry)
{
/* not enough resources */
return STATUS_INSUFFICIENT_RESOURCES;
}
if (AllocateEntry)
{
/* allocate create item */
Item = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
if (!Item)
{
/* no memory */
FreeItem(CreateEntry);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* initialize descriptor */
Item->Context = CreateItem->Context;
Item->Create = CreateItem->Create;
Item->Flags = CreateItem->Flags;
Item->SecurityDescriptor = CreateItem->SecurityDescriptor;
Item->ObjectClass.Length = 0;
Item->ObjectClass.MaximumLength = CreateItem->ObjectClass.MaximumLength;
/* copy object class */
Item->ObjectClass.Buffer = AllocateItem(NonPagedPool, Item->ObjectClass.MaximumLength);
if (!Item->ObjectClass.Buffer)
{
/* release resources */
FreeItem(Item);
FreeItem(CreateEntry);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyUnicodeString(&Item->ObjectClass, &CreateItem->ObjectClass);
}
else
{
if (ItemFreeCallback)
{
/* callback is only accepted when the create item is copied */
ItemFreeCallback = NULL;
}
/* use passed create item */
Item = CreateItem;
}
/* initialize create item entry */
InitializeListHead(&CreateEntry->ObjectItemList);
CreateEntry->ItemFreeCallback = ItemFreeCallback;
CreateEntry->CreateItem = Item;
CreateEntry->ReferenceCount = 0;
/* now insert the create item entry */
InsertTailList(&Header->ItemList, &CreateEntry->Entry);
/* increment item count */
InterlockedIncrement(&Header->ItemListCount);
return STATUS_SUCCESS;
}
NTSTATUS
KspObjectFreeCreateItems(
IN KSDEVICE_HEADER Header,
IN PKSOBJECT_CREATE_ITEM CreateItem)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsFreeObjectCreateItem(
IN KSDEVICE_HEADER Header,
IN PUNICODE_STRING CreateItem)
{
KSOBJECT_CREATE_ITEM Item;
RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
RtlInitUnicodeString(&Item.ObjectClass, CreateItem->Buffer);
return KspObjectFreeCreateItems(Header, &Item);
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsFreeObjectCreateItemsByContext(
IN KSDEVICE_HEADER Header,
IN PVOID Context)
{
KSOBJECT_CREATE_ITEM Item;
RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
Item.Context = Context;
return KspObjectFreeCreateItems(Header, &Item);
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsCreateDefaultSecurity(
IN PSECURITY_DESCRIPTOR ParentSecurity OPTIONAL,
OUT PSECURITY_DESCRIPTOR* DefaultSecurity)
{
PGENERIC_MAPPING Mapping;
SECURITY_SUBJECT_CONTEXT SubjectContext;
NTSTATUS Status;
/* start capturing security context of calling thread */
SeCaptureSubjectContext(&SubjectContext);
/* get generic mapping */
Mapping = IoGetFileObjectGenericMapping();
/* build new descriptor */
Status = SeAssignSecurity(ParentSecurity, NULL, DefaultSecurity, FALSE, &SubjectContext, Mapping, NonPagedPool);
/* release security descriptor */
SeReleaseSubjectContext(&SubjectContext);
/* done */
return Status;
}
/*
@unimplemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsForwardIrp(
IN PIRP Irp,
IN PFILE_OBJECT FileObject,
IN BOOLEAN ReuseStackLocation)
{
UNIMPLEMENTED;
return STATUS_UNSUCCESSFUL;
}
/*
@unimplemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsForwardAndCatchIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PFILE_OBJECT FileObject,
IN KSSTACK_USE StackUse)
{
UNIMPLEMENTED;
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
KspSynchronousIoControlDeviceCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PIO_STATUS_BLOCK IoStatusBlock = (PIO_STATUS_BLOCK)Context;
IoStatusBlock->Information = Irp->IoStatus.Information;
IoStatusBlock->Status = Irp->IoStatus.Status;
return STATUS_SUCCESS;
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsSynchronousIoControlDevice(
IN PFILE_OBJECT FileObject,
IN KPROCESSOR_MODE RequestorMode,
IN ULONG IoControl,
IN PVOID InBuffer,
IN ULONG InSize,
OUT PVOID OutBuffer,
IN ULONG OutSize,
OUT PULONG BytesReturned)
{
PKSIOBJECT_HEADER ObjectHeader;
PDEVICE_OBJECT DeviceObject;
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatusBlock;
PIO_STACK_LOCATION IoStack;
NTSTATUS Status;
/* check for valid file object */
if (!FileObject)
return STATUS_INVALID_PARAMETER;
/* get device object to send the request to */
DeviceObject = IoGetRelatedDeviceObject(FileObject);
if (!DeviceObject)
return STATUS_UNSUCCESSFUL;
/* get object header */
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext2;
/* check if there is fast device io function */
if (ObjectHeader && ObjectHeader->DispatchTable.FastDeviceIoControl)
{
IoStatusBlock.Status = STATUS_UNSUCCESSFUL;
IoStatusBlock.Information = 0;
/* send the request */
Status = ObjectHeader->DispatchTable.FastDeviceIoControl(FileObject, TRUE, InBuffer, InSize, OutBuffer, OutSize, IoControl, &IoStatusBlock, DeviceObject);
/* check if the request was handled */
//DPRINT("Handled %u Status %x Length %u\n", Status, IoStatusBlock.Status, IoStatusBlock.Information);
if (Status)
{
/* store bytes returned */
*BytesReturned = (ULONG)IoStatusBlock.Information;
/* return status */
return IoStatusBlock.Status;
}
}
/* initialize the event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* create the irp */
Irp = IoBuildDeviceIoControlRequest(IoControl, DeviceObject, InBuffer, InSize, OutBuffer, OutSize, FALSE, &Event, &IoStatusBlock);
if (!Irp)
{
/* no memory to allocate the irp */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Store Fileobject */
IoStack = IoGetNextIrpStackLocation(Irp);
IoStack->FileObject = FileObject;
if (IoControl == IOCTL_KS_WRITE_STREAM)
{
Irp->AssociatedIrp.SystemBuffer = OutBuffer;
}
else if (IoControl == IOCTL_KS_READ_STREAM)
{
Irp->AssociatedIrp.SystemBuffer = InBuffer;
}
IoSetCompletionRoutine(Irp, KspSynchronousIoControlDeviceCompletion, (PVOID)&IoStatusBlock, TRUE, TRUE, TRUE);
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, RequestorMode, FALSE, NULL);
Status = IoStatusBlock.Status;
}
*BytesReturned = (ULONG)IoStatusBlock.Information;
return Status;
}
/*
@unimplemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsUnserializeObjectPropertiesFromRegistry(
IN PFILE_OBJECT FileObject,
IN HANDLE ParentKey OPTIONAL,
IN PUNICODE_STRING RegistryPath OPTIONAL)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsCacheMedium(
IN PUNICODE_STRING SymbolicLink,
IN PKSPIN_MEDIUM Medium,
IN ULONG PinDirection)
{
HANDLE hKey;
UNICODE_STRING Path;
UNICODE_STRING BasePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediumCache\\");
UNICODE_STRING GuidString;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
BOOLEAN PathAdjusted = FALSE;
ULONG Value = 0;
/* first check if the medium is standard */
if (IsEqualGUIDAligned(&KSMEDIUMSETID_Standard, &Medium->Set) ||
IsEqualGUIDAligned(&GUID_NULL, &Medium->Set))
{
/* no need to cache that */
return STATUS_SUCCESS;
}
/* convert guid to string */
Status = RtlStringFromGUID(&Medium->Set, &GuidString);
if (!NT_SUCCESS(Status))
return Status;
/* allocate path buffer */
Path.Length = 0;
Path.MaximumLength = BasePath.MaximumLength + GuidString.MaximumLength + 10 * sizeof(WCHAR);
Path.Buffer = AllocateItem(PagedPool, Path.MaximumLength);
if (!Path.Buffer)
{
/* not enough resources */
RtlFreeUnicodeString(&GuidString);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlAppendUnicodeStringToString(&Path, &BasePath);
RtlAppendUnicodeStringToString(&Path, &GuidString);
RtlAppendUnicodeToString(&Path, L"-");
/* FIXME append real instance id */
RtlAppendUnicodeToString(&Path, L"0");
RtlAppendUnicodeToString(&Path, L"-");
/* FIXME append real instance id */
RtlAppendUnicodeToString(&Path, L"0");
/* free guid string */
RtlFreeUnicodeString(&GuidString);
/* initialize object attributes */
InitializeObjectAttributes(&ObjectAttributes, &Path, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
/* create the key */
Status = ZwCreateKey(&hKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL);
/* free path buffer */
FreeItem(Path.Buffer);
if (NT_SUCCESS(Status))
{
/* store symbolic link */
if (SymbolicLink->Buffer[1] == L'?' && SymbolicLink->Buffer[2] == L'?')
{
/* replace kernel path with user mode path */
SymbolicLink->Buffer[1] = L'\\';
PathAdjusted = TRUE;
}
/* store the key */
Status = ZwSetValueKey(hKey, SymbolicLink, 0, REG_DWORD, &Value, sizeof(ULONG));
if (PathAdjusted)
{
/* restore kernel path */
SymbolicLink->Buffer[1] = L'?';
}
ZwClose(hKey);
}
/* done */
return Status;
}
/*
@implemented
*/
NTSTATUS
NTAPI
DllInitialize(
PUNICODE_STRING RegistryPath)
{
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
KopDispatchClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PKO_OBJECT_HEADER Header;
PIO_STACK_LOCATION IoStack;
PDEVICE_EXTENSION DeviceExtension;
/* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* get ko object header */
Header = (PKO_OBJECT_HEADER)IoStack->FileObject->FsContext2;
/* free ks object header */
KsFreeObjectHeader(Header->ObjectHeader);
/* free ko object header */
FreeItem(Header);
/* get device extension */
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* release bus object */
KsDereferenceBusObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader);
/* complete request */
Irp->IoStatus.Status = STATUS_SUCCESS;
CompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
static KSDISPATCH_TABLE KoDispatchTable =
{
KsDispatchInvalidDeviceRequest,
KsDispatchInvalidDeviceRequest,
KsDispatchInvalidDeviceRequest,
KsDispatchInvalidDeviceRequest,
KopDispatchClose,
KsDispatchQuerySecurity,
KsDispatchSetSecurity,
KsDispatchFastIoDeviceControlFailure,
KsDispatchFastReadFailure,
KsDispatchFastReadFailure,
};
NTSTATUS
NTAPI
KopDispatchCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PKO_OBJECT_HEADER Header = NULL;
PIO_STACK_LOCATION IoStack;
PKO_DRIVER_EXTENSION DriverObjectExtension;
NTSTATUS Status;
/* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (!IoStack->FileObject)
{
DPRINT1("FileObject not attached!\n");
Status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
/* get driver object extension */
DriverObjectExtension = (PKO_DRIVER_EXTENSION)IoGetDriverObjectExtension(DeviceObject->DriverObject, (PVOID)KoDriverInitialize);
if (!DriverObjectExtension)
{
DPRINT1("No DriverObjectExtension!\n");
Status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
/* allocate ko object header */
Header = (PKO_OBJECT_HEADER)AllocateItem(NonPagedPool, sizeof(KO_OBJECT_HEADER));
if (!Header)
{
DPRINT1("failed to allocate KO_OBJECT_HEADER\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
/* initialize create item */
Header->CreateItem.Create = KopDispatchCreate;
RtlInitUnicodeString(&Header->CreateItem.ObjectClass, KOSTRING_CreateObject);
/* now allocate the object header */
Status = KsAllocateObjectHeader(&Header->ObjectHeader, 1, &Header->CreateItem, Irp, &KoDispatchTable);
if (!NT_SUCCESS(Status))
{
/* failed */
goto cleanup;
}
/* FIXME
* extract clsid and interface id from irp
* call the standard create handler
*/
UNIMPLEMENTED;
IoStack->FileObject->FsContext2 = (PVOID)Header;
Irp->IoStatus.Status = Status;
CompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
cleanup:
if (Header && Header->ObjectHeader)
KsFreeObjectHeader(Header->ObjectHeader);
if (Header)
FreeItem(Header);
Irp->IoStatus.Status = Status;
CompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
NTAPI
KopAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
NTSTATUS Status = STATUS_DEVICE_REMOVED;
PDEVICE_OBJECT FunctionalDeviceObject= NULL;
PDEVICE_OBJECT NextDeviceObject;
PDEVICE_EXTENSION DeviceExtension;
PKSOBJECT_CREATE_ITEM CreateItem;
/* create the device object */
Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_KS, FILE_DEVICE_SECURE_OPEN, FALSE, &FunctionalDeviceObject);
if (!NT_SUCCESS(Status))
return Status;
/* allocate the create item */
CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
if (!CreateItem)
{
/* not enough memory */
IoDeleteDevice(FunctionalDeviceObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* initialize create item */
CreateItem->Create = KopDispatchCreate;
RtlInitUnicodeString(&CreateItem->ObjectClass, KOSTRING_CreateObject);
/* get device extension */
DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
/* now allocate the device header */
Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader, 1, CreateItem);
if (!NT_SUCCESS(Status))
{
/* failed */
IoDeleteDevice(FunctionalDeviceObject);
FreeItem(CreateItem);
return Status;
}
/* now attach to device stack */
NextDeviceObject = IoAttachDeviceToDeviceStack(FunctionalDeviceObject, PhysicalDeviceObject);
if (NextDeviceObject)
{
/* store pnp base object */
KsSetDevicePnpAndBaseObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, NextDeviceObject, FunctionalDeviceObject);
/* set device flags */
FunctionalDeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
FunctionalDeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
}
else
{
/* failed */
KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader);
FreeItem(CreateItem);
IoDeleteDevice(FunctionalDeviceObject);
Status = STATUS_DEVICE_REMOVED;
}
/* return result */
return Status;
}
/*
@implemented
*/
COMDDKAPI
NTSTATUS
NTAPI
KoDeviceInitialize(
IN PDEVICE_OBJECT DeviceObject)
{
PDEVICE_EXTENSION DeviceExtension;
/* get device extension */
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
return KsAddObjectCreateItemToDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, KopDispatchCreate, NULL, KOSTRING_CreateObject, NULL);
}
/*
@implemented
*/
COMDDKAPI
NTSTATUS
NTAPI
KoDriverInitialize(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPathName,
IN KoCreateObjectHandler CreateObjectHandler)
{
PKO_DRIVER_EXTENSION DriverObjectExtension;
NTSTATUS Status;
/* allocate driver object extension */
Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)KoDriverInitialize, sizeof(KO_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension);
/* did it work */
if (NT_SUCCESS(Status))
{
/* store create handler */
DriverObjectExtension->CreateObjectHandler = CreateObjectHandler;
/* Setting our IRP handlers */
DriverObject->MajorFunction[IRP_MJ_PNP] = KsDefaultDispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
/* The driver unload routine */
DriverObject->DriverUnload = KsNullDriverUnload;
/* The driver-supplied AddDevice */
DriverObject->DriverExtension->AddDevice = KopAddDevice;
/* KS handles these */
DPRINT1("Setting KS function handlers\n");
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
}
return Status;
}
/*
@unimplemented
*/
COMDDKAPI
VOID
NTAPI
KoRelease(
IN REFCLSID ClassId)
{
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsAcquireControl(
IN PVOID Object)
{
PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
/* sanity check */
ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
KeWaitForSingleObject(BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL);
}
/*
@implemented
*/
VOID
NTAPI
KsReleaseControl(
IN PVOID Object)
{
PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
/* sanity check */
ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
KeReleaseMutex(BasicHeader->ControlMutex, FALSE);
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsAcquireDevice(
IN PKSDEVICE Device)
{
IKsDevice *KsDevice;
PKSIDEVICE_HEADER DeviceHeader;
DPRINT("KsAcquireDevice\n");
DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
/* get device interface*/
KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown;
/* acquire device mutex */
KsDevice->lpVtbl->AcquireDevice(KsDevice);
}
/*
@implemented
*/
VOID
NTAPI
KsReleaseDevice(
IN PKSDEVICE Device)
{
IKsDevice *KsDevice;
PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
/* get device interface*/
KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown;
/* release device mutex */
KsDevice->lpVtbl->ReleaseDevice(KsDevice);
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsTerminateDevice(
IN PDEVICE_OBJECT DeviceObject)
{
IKsDevice *KsDevice;
PKSIDEVICE_HEADER DeviceHeader;
PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* get device header */
DeviceHeader = DeviceExtension->DeviceHeader;
/* get device interface*/
KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown;
/* now free device header */
KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceHeader);
/* release interface when available */
if (KsDevice)
{
/* delete IKsDevice interface */
KsDevice->lpVtbl->Release(KsDevice);
}
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsCompletePendingRequest(
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
/* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* sanity check */
ASSERT(Irp->IoStatus.Status != STATUS_PENDING);
if (IoStack->MajorFunction != IRP_MJ_CLOSE)
{
/* can be completed immediately */
CompleteRequest(Irp, IO_NO_INCREMENT);
return;
}
/* did close operation fail */
if (!NT_SUCCESS(Irp->IoStatus.Status))
{
/* closing failed, complete irp */
CompleteRequest(Irp, IO_NO_INCREMENT);
return;
}
/* FIXME
* delete object / device header
* remove dead pin / filter instance
*/
UNIMPLEMENTED;
}
NTSTATUS
NTAPI
KspSetGetBusDataCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
/* signal completion */
KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE);
/* more work needs be done, so dont free the irp */
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
KspDeviceSetGetBusData(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG DataType,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length,
IN BOOL bGet)
{
PIO_STACK_LOCATION IoStack;
PIRP Irp;
NTSTATUS Status;
KEVENT Event;
/* allocate the irp */
Irp = IoAllocateIrp(1, /*FIXME */
FALSE);
if (!Irp)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize the event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* get next stack location */
IoStack = IoGetNextIrpStackLocation(Irp);
/* setup a completion routine */
IoSetCompletionRoutine(Irp, KspSetGetBusDataCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
/* setup parameters */
IoStack->Parameters.ReadWriteConfig.Buffer = Buffer;
IoStack->Parameters.ReadWriteConfig.Length = Length;
IoStack->Parameters.ReadWriteConfig.Offset = Offset;
IoStack->Parameters.ReadWriteConfig.WhichSpace = DataType;
/* setup function code */
IoStack->MajorFunction = IRP_MJ_PNP;
IoStack->MinorFunction = (bGet ? IRP_MN_READ_CONFIG : IRP_MN_WRITE_CONFIG);
/* lets call the driver */
Status = IoCallDriver(DeviceObject, Irp);
/* is the request still pending */
if (Status == STATUS_PENDING)
{
/* have a nap */
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
/* update status */
Status = Irp->IoStatus.Status;
}
/* free the irp */
IoFreeIrp(Irp);
/* done */
return Status;
}
/*
@implemented
*/
KSDDKAPI
ULONG
NTAPI
KsDeviceSetBusData(
IN PKSDEVICE Device,
IN ULONG DataType,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length)
{
return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
DataType, Buffer, Offset, Length, FALSE);
}
/*
@implemented
*/
KSDDKAPI
ULONG
NTAPI
KsDeviceGetBusData(
IN PKSDEVICE Device,
IN ULONG DataType,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length)
{
return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
DataType, Buffer, Offset, Length, TRUE);
}
/*
@implemented
*/
KSDDKAPI
void
NTAPI
KsDeviceRegisterAdapterObject(
IN PKSDEVICE Device,
IN PADAPTER_OBJECT AdapterObject,
IN ULONG MaxMappingsByteCount,
IN ULONG MappingTableStride)
{
PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
DeviceHeader->AdapterObject = AdapterObject;
DeviceHeader->MaxMappingsByteCount = MaxMappingsByteCount;
DeviceHeader->MappingTableStride = MappingTableStride;
}
/*
@implemented
*/
KSDDKAPI
PVOID
NTAPI
KsGetFirstChild(
IN PVOID Object)
{
PKSBASIC_HEADER BasicHeader;
/* get the basic header */
BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
/* type has to be either a device or a filter factory */
ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory);
return (PVOID)BasicHeader->FirstChild.Filter;
}
/*
@implemented
*/
KSDDKAPI
PVOID
NTAPI
KsGetNextSibling(
IN PVOID Object)
{
PKSBASIC_HEADER BasicHeader;
/* get the basic header */
BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory ||
BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
return (PVOID)BasicHeader->Next.Pin;
}
ULONG
KspCountMethodSets(
IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
{
ULONG Index, SubIndex, Count;
BOOL bFound;
if (!AutomationTableA)
return AutomationTableB->MethodSetsCount;
if (!AutomationTableB)
return AutomationTableA->MethodSetsCount;
DPRINT("AutomationTableA MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableA->MethodItemSize, AutomationTableA->MethodSetsCount);
DPRINT("AutomationTableB MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableB->MethodItemSize, AutomationTableB->MethodSetsCount);
if (AutomationTableA->MethodItemSize && AutomationTableB->MethodItemSize)
{
/* sanity check */
ASSERT(AutomationTableA->MethodItemSize == AutomationTableB->MethodItemSize);
}
/* now iterate all property sets and compare their guids */
Count = AutomationTableA->MethodSetsCount;
for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++)
{
/* set found to false */
bFound = FALSE;
for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++)
{
if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set))
{
/* same property set found */
bFound = TRUE;
break;
}
}
if (!bFound)
Count++;
}
return Count;
}
ULONG
KspCountEventSets(
IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
{
ULONG Index, SubIndex, Count;
BOOL bFound;
if (!AutomationTableA)
return AutomationTableB->EventSetsCount;
if (!AutomationTableB)
return AutomationTableA->EventSetsCount;
DPRINT("AutomationTableA EventItemSize %lu EventSetsCount %lu\n", AutomationTableA->EventItemSize, AutomationTableA->EventSetsCount);
DPRINT("AutomationTableB EventItemSize %lu EventSetsCount %lu\n", AutomationTableB->EventItemSize, AutomationTableB->EventSetsCount);
if (AutomationTableA->EventItemSize && AutomationTableB->EventItemSize)
{
/* sanity check */
ASSERT(AutomationTableA->EventItemSize == AutomationTableB->EventItemSize);
}
/* now iterate all Event sets and compare their guids */
Count = AutomationTableA->EventSetsCount;
for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++)
{
/* set found to false */
bFound = FALSE;
for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++)
{
if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set))
{
/* same Event set found */
bFound = TRUE;
break;
}
}
if (!bFound)
Count++;
}
return Count;
}
ULONG
KspCountPropertySets(
IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
{
ULONG Index, SubIndex, Count;
BOOL bFound;
if (!AutomationTableA)
return AutomationTableB->PropertySetsCount;
if (!AutomationTableB)
return AutomationTableA->PropertySetsCount;
/* sanity check */
DPRINT("AutomationTableA PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableA->PropertyItemSize, AutomationTableA->PropertySetsCount);
DPRINT("AutomationTableB PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableB->PropertyItemSize, AutomationTableB->PropertySetsCount);
ASSERT(AutomationTableA->PropertyItemSize == AutomationTableB->PropertyItemSize);
/* now iterate all property sets and compare their guids */
Count = AutomationTableA->PropertySetsCount;
for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++)
{
/* set found to false */
bFound = FALSE;
for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++)
{
if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set))
{
/* same property set found */
bFound = TRUE;
break;
}
}
if (!bFound)
Count++;
}
return Count;
}
NTSTATUS
KspCopyMethodSets(
OUT PKSAUTOMATION_TABLE Table,
IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
{
ULONG Index, SubIndex, Count;
BOOL bFound;
if (!AutomationTableA)
{
/* copy of property set */
RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableB->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableB->MethodSetsCount);
return STATUS_SUCCESS;
}
else if (!AutomationTableB)
{
/* copy of property set */
RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableA->MethodSetsCount);
return STATUS_SUCCESS;
}
/* first copy all property items from dominant table */
RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableA->MethodSetsCount);
/* set counter */
Count = AutomationTableA->MethodSetsCount;
/* now copy entries which aren't available in the dominant table */
for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++)
{
/* set found to false */
bFound = FALSE;
for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++)
{
if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set))
{
/* same property set found */
bFound = TRUE;
break;
}
}
if (!bFound)
{
/* copy new property item set */
RtlMoveMemory((PVOID)&Table->MethodSets[Count], &AutomationTableB->MethodSets[Index], sizeof(KSMETHOD_SET));
Count++;
}
}
return STATUS_SUCCESS;
}
VOID
KspAddPropertyItem(
OUT PKSPROPERTY_SET OutPropertySet,
IN PKSPROPERTY_ITEM PropertyItem,
IN ULONG PropertyItemSize)
{
PKSPROPERTY_ITEM CurrentPropertyItem;
ULONG Index;
// check if the property item is already present
CurrentPropertyItem = (PKSPROPERTY_ITEM)OutPropertySet->PropertyItem;
for(Index = 0; Index < OutPropertySet->PropertiesCount; Index++)
{
if (CurrentPropertyItem->PropertyId == PropertyItem->PropertyId)
{
// item already present
return;
}
// next item
CurrentPropertyItem = (PKSPROPERTY_ITEM)((ULONG_PTR)CurrentPropertyItem + PropertyItemSize);
}
// add item
RtlCopyMemory(CurrentPropertyItem, PropertyItem, PropertyItemSize);
OutPropertySet->PropertiesCount++;
}
NTSTATUS
KspMergePropertySet(
OUT PKSAUTOMATION_TABLE Table,
OUT PKSPROPERTY_SET OutPropertySet,
IN PKSPROPERTY_SET PropertySetA,
IN PKSPROPERTY_SET PropertySetB,
IN KSOBJECT_BAG Bag OPTIONAL)
{
ULONG PropertyCount, Index;
PKSPROPERTY_ITEM PropertyItem, CurrentPropertyItem;
NTSTATUS Status;
// max properties
PropertyCount = PropertySetA->PropertiesCount + PropertySetB->PropertiesCount;
// allocate items
PropertyItem = AllocateItem(NonPagedPool, Table->PropertyItemSize * PropertyCount);
if (!PropertyItem)
return STATUS_INSUFFICIENT_RESOURCES;
if (Bag)
{
/* add table to object bag */
Status = KsAddItemToObjectBag(Bag, PropertyItem, NULL);
/* check for success */
if (!NT_SUCCESS(Status))
{
/* free table */
FreeItem(Table);
return Status;
}
}
// copy entries from dominant table
RtlCopyMemory(PropertyItem, PropertySetA->PropertyItem, Table->PropertyItemSize * PropertySetA->PropertiesCount);
// init property set
OutPropertySet->PropertiesCount = PropertySetA->PropertiesCount;
OutPropertySet->PropertyItem = PropertyItem;
// copy other entries
CurrentPropertyItem = (PKSPROPERTY_ITEM)PropertySetB->PropertyItem;
for(Index = 0; Index < PropertySetB->PropertiesCount; Index++)
{
// add entries
KspAddPropertyItem(OutPropertySet, CurrentPropertyItem, Table->PropertyItemSize);
// next entry
CurrentPropertyItem = (PKSPROPERTY_ITEM)((ULONG_PTR)CurrentPropertyItem + Table->PropertyItemSize);
}
// done
return STATUS_SUCCESS;
}
NTSTATUS
KspCopyPropertySets(
OUT PKSAUTOMATION_TABLE Table,
IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL,
IN KSOBJECT_BAG Bag OPTIONAL)
{
ULONG Index, SubIndex, Count;
BOOL bFound;
NTSTATUS Status;
if (!AutomationTableA)
{
/* copy of property set */
RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableB->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableB->PropertySetsCount);
return STATUS_SUCCESS;
}
else if (!AutomationTableB)
{
/* copy of property set */
RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableA->PropertySetsCount);
return STATUS_SUCCESS;
}
/* first copy all property items from dominant table */
RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableA->PropertySetsCount);
/* set counter */
Count = AutomationTableA->PropertySetsCount;
/* now copy entries which aren't available in the dominant table */
for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++)
{
/* set found to false */
bFound = FALSE;
for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++)
{
if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set))
{
/* same property set found */
bFound = TRUE;
break;
}
}
if (!bFound)
{
/* copy new property item set */
RtlMoveMemory((PVOID)&Table->PropertySets[Count], &AutomationTableB->PropertySets[Index], sizeof(KSPROPERTY_SET));
Count++;
}
else
{
// merge property sets
Status = KspMergePropertySet(Table, (PKSPROPERTY_SET)&Table->PropertySets[SubIndex], (PKSPROPERTY_SET)&AutomationTableA->PropertySets[SubIndex], (PKSPROPERTY_SET)&AutomationTableB->PropertySets[Index], Bag);
if (!NT_SUCCESS(Status))
{
// failed to merge
DPRINT1("[KS] Failed to merge %x\n", Status);
return Status;
}
}
}
return STATUS_SUCCESS;
}
NTSTATUS
KspCopyEventSets(
OUT PKSAUTOMATION_TABLE Table,
IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
{
ULONG Index, SubIndex, Count;
BOOL bFound;
if (!AutomationTableA)
{
/* copy of Event set */
RtlMoveMemory((PVOID)Table->EventSets, AutomationTableB->EventSets, sizeof(KSEVENT_SET) * AutomationTableB->EventSetsCount);
return STATUS_SUCCESS;
}
else if (!AutomationTableB)
{
/* copy of Event set */
RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, sizeof(KSEVENT_SET) * AutomationTableA->EventSetsCount);
return STATUS_SUCCESS;
}
/* first copy all Event items from dominant table */
RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, sizeof(KSEVENT_SET) * AutomationTableA->EventSetsCount);
/* set counter */
Count = AutomationTableA->EventSetsCount;
/* now copy entries which aren't available in the dominant table */
for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++)
{
/* set found to false */
bFound = FALSE;
for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++)
{
if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set))
{
/* same Event set found */
bFound = TRUE;
break;
}
}
if (!bFound)
{
/* copy new Event item set */
RtlMoveMemory((PVOID)&Table->EventSets[Count], &AutomationTableB->EventSets[Index], sizeof(KSEVENT_SET));
Count++;
}
}
return STATUS_SUCCESS;
}
/*
@implemented
*/
NTSTATUS
NTAPI
KsMergeAutomationTables(
OUT PKSAUTOMATION_TABLE *AutomationTableAB,
IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL,
IN KSOBJECT_BAG Bag OPTIONAL)
{
PKSAUTOMATION_TABLE Table;
NTSTATUS Status = STATUS_SUCCESS;
if (!AutomationTableA && !AutomationTableB)
{
/* nothing to merge */
return STATUS_SUCCESS;
}
/* allocate an automation table */
Table = AllocateItem(NonPagedPool, sizeof(KSAUTOMATION_TABLE));
if (!Table)
return STATUS_INSUFFICIENT_RESOURCES;
if (Bag)
{
/* add table to object bag */
Status = KsAddItemToObjectBag(Bag, Table, NULL);
/* check for success */
if (!NT_SUCCESS(Status))
{
/* free table */
FreeItem(Table);
return Status;
}
}
/* count property sets */
Table->PropertySetsCount = KspCountPropertySets(AutomationTableA, AutomationTableB);
if (Table->PropertySetsCount)
{
if (AutomationTableA)
{
/* use item size from dominant automation table */
Table->PropertyItemSize = AutomationTableA->PropertyItemSize;
}
else
{
/* use item size from 2nd automation table */
Table->PropertyItemSize = AutomationTableB->PropertyItemSize;
}
if (AutomationTableA && AutomationTableB)
{
// FIXME handle different property item sizes
ASSERT(AutomationTableA->PropertyItemSize == AutomationTableB->PropertyItemSize);
}
/* now allocate the property sets */
Table->PropertySets = AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * Table->PropertySetsCount);
if (!Table->PropertySets)
{
/* not enough memory */
goto cleanup;
}
if (Bag)
{
/* add set to property bag */
Status = KsAddItemToObjectBag(Bag, (PVOID)Table->PropertySets, NULL);
/* check for success */
if (!NT_SUCCESS(Status))
{
/* cleanup table */
goto cleanup;
}
}
/* now copy the property sets */
Status = KspCopyPropertySets(Table, AutomationTableA, AutomationTableB, Bag);
if(!NT_SUCCESS(Status))
goto cleanup;
}
/* now count the method sets */
Table->MethodSetsCount = KspCountMethodSets(AutomationTableA, AutomationTableB);
if (Table->MethodSetsCount)
{
if (AutomationTableA)
{
/* use item size from dominant automation table */
Table->MethodItemSize = AutomationTableA->MethodItemSize;
}
else
{
/* use item size from 2nd automation table */
Table->MethodItemSize = AutomationTableB->MethodItemSize;
}
/* now allocate the property sets */
Table->MethodSets = AllocateItem(NonPagedPool, sizeof(KSMETHOD_SET) * Table->MethodSetsCount);
if (!Table->MethodSets)
{
/* not enough memory */
goto cleanup;
}
if (Bag)
{
/* add set to property bag */
Status = KsAddItemToObjectBag(Bag, (PVOID)Table->MethodSets, NULL);
/* check for success */
if (!NT_SUCCESS(Status))
{
/* cleanup table */
goto cleanup;
}
}
/* now copy the property sets */
Status = KspCopyMethodSets(Table, AutomationTableA, AutomationTableB);
if(!NT_SUCCESS(Status))
goto cleanup;
}
/* now count the event sets */
Table->EventSetsCount = KspCountEventSets(AutomationTableA, AutomationTableB);
if (Table->EventSetsCount)
{
if (AutomationTableA)
{
/* use item size from dominant automation table */
Table->EventItemSize = AutomationTableA->EventItemSize;
}
else
{
/* use item size from 2nd automation table */
Table->EventItemSize = AutomationTableB->EventItemSize;
}
/* now allocate the property sets */
Table->EventSets = AllocateItem(NonPagedPool, sizeof(KSEVENT_SET) * Table->EventSetsCount);
if (!Table->EventSets)
{
/* not enough memory */
goto cleanup;
}
if (Bag)
{
/* add set to property bag */
Status = KsAddItemToObjectBag(Bag, (PVOID)Table->EventSets, NULL);
/* check for success */
if (!NT_SUCCESS(Status))
{
/* cleanup table */
goto cleanup;
}
}
/* now copy the property sets */
Status = KspCopyEventSets(Table, AutomationTableA, AutomationTableB);
if(!NT_SUCCESS(Status))
goto cleanup;
}
/* store result */
*AutomationTableAB = Table;
return Status;
cleanup:
if (Table)
{
if (Table->PropertySets)
{
/* clean property sets */
if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->PropertySets, TRUE)))
FreeItem((PVOID)Table->PropertySets);
}
if (Table->MethodSets)
{
/* clean property sets */
if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->MethodSets, TRUE)))
FreeItem((PVOID)Table->MethodSets);
}
if (Table->EventSets)
{
/* clean property sets */
if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->EventSets, TRUE)))
FreeItem((PVOID)Table->EventSets);
}
if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, Table, TRUE)))
FreeItem(Table);
}
return STATUS_INSUFFICIENT_RESOURCES;
}
/*
@unimplemented
*/
KSDDKAPI
PUNKNOWN
NTAPI
KsRegisterAggregatedClientUnknown(
IN PVOID Object,
IN PUNKNOWN ClientUnknown)
{
PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
/* sanity check */
ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory ||
BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
if (BasicHeader->ClientAggregate)
{
/* release existing aggregate */
BasicHeader->ClientAggregate->lpVtbl->Release(BasicHeader->ClientAggregate);
}
/* increment reference count */
ClientUnknown->lpVtbl->AddRef(ClientUnknown);
/* store client aggregate */
BasicHeader->ClientAggregate = ClientUnknown;
/* return objects outer unknown */
return BasicHeader->OuterUnknown;
}
/*
@unimplemented
*/
NTSTATUS
NTAPI
KsRegisterFilterWithNoKSPins(
IN PDEVICE_OBJECT DeviceObject,
IN const GUID* InterfaceClassGUID,
IN ULONG PinCount,
IN BOOL* PinDirection,
IN KSPIN_MEDIUM* MediumList,
IN GUID* CategoryList OPTIONAL)
{
ULONG Size, Index;
NTSTATUS Status;
PWSTR SymbolicLinkList;
//PUCHAR Buffer;
HANDLE hKey;
UNICODE_STRING InterfaceString;
//UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData");
if (!InterfaceClassGUID || !PinCount || !PinDirection || !MediumList)
{
/* all these parameters are required */
return STATUS_INVALID_PARAMETER;
}
/* calculate filter data value size */
Size = PinCount * sizeof(KSPIN_MEDIUM);
if (CategoryList)
{
/* add category list */
Size += PinCount * sizeof(GUID);
}
/* FIXME generate filter data blob */
UNIMPLEMENTED;
/* get symbolic link list */
Status = IoGetDeviceInterfaces(InterfaceClassGUID, DeviceObject, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &SymbolicLinkList);
if (NT_SUCCESS(Status))
{
/* initialize first symbolic link */
RtlInitUnicodeString(&InterfaceString, SymbolicLinkList);
/* open first device interface registry key */
Status = IoOpenDeviceInterfaceRegistryKey(&InterfaceString, GENERIC_WRITE, &hKey);
if (NT_SUCCESS(Status))
{
/* write filter data */
//Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Buffer, Size);
/* close the key */
ZwClose(hKey);
}
if (PinCount)
{
/* update medium cache */
for(Index = 0; Index < PinCount; Index++)
{
KsCacheMedium(&InterfaceString, &MediumList[Index], PinDirection[Index]);
}
}
/* free the symbolic link list */
FreeItem(SymbolicLinkList);
}
return Status;
}