- Convert portcls to a C++ driver

- Tested with Vbox 2.2.4 + AC97 with Winamp
- WIP, Testing recommended

svn path=/trunk/; revision=43026
This commit is contained in:
Johannes Anderwald
2009-09-11 06:33:55 +00:00
parent 82376f839e
commit ad2cf72549
70 changed files with 11968 additions and 15160 deletions
@@ -1,255 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS
* FILE: drivers/multimedia/portcls/helpers/ResourceList.c
* PURPOSE: Port Class driver / ResourceList implementation
* PROGRAMMER: Andrew Greenwood
*
* HISTORY:
* 27 Jan 07 Created
*/
#include "private.h"
#include <portcls.h>
#include <stdunk.h>
typedef struct CResourceList
{
union
{
IUnknown IUnknown;
IResourceList IResourceList;
};
LONG m_ref_count;
PUNKNOWN m_outer_unknown;
PCM_RESOURCE_LIST translated_resources;
PCM_RESOURCE_LIST untranslated_resources;
} CResourceList;
/*
Basic IUnknown methods
*/
NTSTATUS
STDMETHODCALLTYPE
ResourceList_QueryInterface(
IResourceList* this_container,
IN REFIID refiid,
OUT PVOID* output)
{
/* TODO */
return STATUS_SUCCESS;
}
ULONG
STDMETHODCALLTYPE
ResourceList_AddRef(
IResourceList* this_container)
{
struct CUnknown* this = CONTAINING_RECORD(this_container, struct CUnknown, IUnknown);
/* fixme */
/* ExInterlockedIncrement(&this->m_ref_count); */
return this->m_ref_count;
}
ULONG
STDMETHODCALLTYPE
ResourceList_Release(
IResourceList* this_container)
{
struct CUnknown* this = CONTAINING_RECORD(this_container, struct CUnknown, IUnknown);
/* fixme */
/* ExInterlockedDecrement(&this->m_ref_count); */
if ( this->m_ref_count == 0 )
{
ExFreePool(this);
return 0;
}
return this->m_ref_count;
}
/*
IResourceList methods
*/
ULONG
STDMETHODCALLTYPE
ResourceList_NumberOfEntries(IResourceList* this_container)
{
return 0;
}
ULONG
STDMETHODCALLTYPE
ResourceList_NumberOfEntriesOfType(
IResourceList* this_container,
IN CM_RESOURCE_TYPE type)
{
/* I guess the translated and untranslated lists will be same length? */
CResourceList* this = CONTAINING_RECORD(this_container, CResourceList, IResourceList);
ULONG index, count = 0;
for ( index = 0; index < this->translated_resources->Count; index ++ )
{
PCM_FULL_RESOURCE_DESCRIPTOR full_desc = &this->translated_resources->List[index];
ULONG sub_index;
for ( sub_index = 0; sub_index < full_desc->PartialResourceList.Count; sub_index ++ )
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR partial_desc;
partial_desc = &full_desc->PartialResourceList.PartialDescriptors[sub_index];
if ( partial_desc->Type == type )
{
/* Yay! Finally found one that matches! */
count ++;
}
}
}
DPRINT("Found %d\n", count);
return count;
}
PCM_PARTIAL_RESOURCE_DESCRIPTOR
STDMETHODCALLTYPE
ResourceList_FindTranslatedEntry(
IResourceList* this_container,
IN CM_RESOURCE_TYPE Type,
IN ULONG Index)
{
return NULL;
}
PCM_PARTIAL_RESOURCE_DESCRIPTOR
STDMETHODCALLTYPE
ResourceList_FindUntranslatedEntry(
IResourceList* this_container,
IN CM_RESOURCE_TYPE Type,
IN ULONG Index)
{
return NULL;
}
NTSTATUS
STDMETHODCALLTYPE
ResourceList_AddEntry(
IResourceList* this_container,
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Untranslated)
{
return STATUS_SUCCESS;
}
NTSTATUS
STDMETHODCALLTYPE
ResourceList_AddEntryFromParent(
IResourceList* this_container,
IN IResourceList* Parent,
IN CM_RESOURCE_TYPE Type,
IN ULONG Index)
{
return STATUS_SUCCESS;
}
PCM_RESOURCE_LIST
STDMETHODCALLTYPE
ResourceList_TranslatedList(
IResourceList* this_container)
{
return NULL;
}
PCM_RESOURCE_LIST
STDMETHODCALLTYPE
ResourceList_UntranslatedList(
IResourceList* this_container)
{
return NULL;
}
/*
ResourceList V-Table
*/
static const IResourceListVtbl ResourceListVtbl =
{
/* IUnknown */
ResourceList_QueryInterface,
ResourceList_AddRef,
ResourceList_Release,
/* IResourceList */
ResourceList_NumberOfEntries,
ResourceList_NumberOfEntriesOfType,
ResourceList_FindTranslatedEntry,
ResourceList_FindUntranslatedEntry,
ResourceList_AddEntry,
ResourceList_AddEntryFromParent,
ResourceList_TranslatedList,
ResourceList_UntranslatedList
};
/*
Factory for creating a resource list
*/
PORTCLASSAPI NTSTATUS NTAPI
PcNewResourceList(
OUT PRESOURCELIST* OutResourceList,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PCM_RESOURCE_LIST TranslatedResources,
IN PCM_RESOURCE_LIST UntranslatedResources)
{
IResourceList* new_list = NULL;
CResourceList* this = NULL;
/* TODO: Validate parameters */
DPRINT("PcNewResourceList\n");
new_list = ExAllocatePoolWithTag(sizeof(IResourceList), PoolType, TAG_PORTCLASS);
if ( ! new_list )
{
DPRINT("ExAllocatePoolWithTag failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Obtain our private data */
this = CONTAINING_RECORD(new_list, CResourceList, IResourceList);
ASSERT(this);
/* Initialize */
this->m_outer_unknown = OuterUnknown;
this->translated_resources = TranslatedResources;
this->untranslated_resources = UntranslatedResources;
/* Increment our usage count and set the pointer to this object */
*OutResourceList = new_list;
ResourceListVtbl.AddRef(*OutResourceList);
return STATUS_SUCCESS;
}
PORTCLASSAPI NTSTATUS NTAPI
PcNewResourceSublist(
OUT PRESOURCELIST* OutResourceList,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PRESOURCELIST ParentList,
IN ULONG MaximumEntries)
{
return STATUS_UNSUCCESSFUL;
}
@@ -1,54 +1,37 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/api.c
* FILE: drivers/wdm/audio/backpln/portcls/api.cpp
* PURPOSE: Port Class driver / DriverEntry and IRP handlers
* PROGRAMMER: Andrew Greenwood
*
* Johannes Anderwald
* HISTORY:
* 27 Jan 07 Created
*/
#include "private.h"
#include "private.hpp"
/*
This is called from DriverEntry so that PortCls can take care of some
IRPs and map some others to the main KS driver. In most cases this will
be the first function called by an audio driver.
First 2 parameters are from DriverEntry.
The AddDevice parameter is a driver-supplied pointer to a function which
typically then calls PcAddAdapterDevice (see below.)
*/
NTSTATUS NTAPI
//
// This is called from DriverEntry so that PortCls can take care of some
// IRPs and map some others to the main KS driver. In most cases this will
// be the first function called by an audio driver.
//
// First 2 parameters are from DriverEntry.
//
// The AddDevice parameter is a driver-supplied pointer to a function which
// typically then calls PcAddAdapterDevice (see below.)
//
NTSTATUS
NTAPI
PcInitializeAdapterDriver(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPathName,
IN PDRIVER_ADD_DEVICE AddDevice)
{
/*
(* = implement here, otherwise KS default)
IRP_MJ_CLOSE
* IRP_MJ_CREATE
IRP_MJ_DEVICE_CONTROL
IRP_MJ_FLUSH_BUFFERS
* IRP_MJ_PNP
* IRP_MJ_POWER
IRP_MJ_QUERY_SECURITY
IRP_MJ_READ
IRP_MJ_SET_SECURITY
* IRP_MJ_SYSTEM_CONTROL
IRP_MJ_WRITE
*/
//NTSTATUS status;
//ULONG i;
DPRINT1("PcInitializeAdapterDriver\n");
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
/* Our IRP handlers */
// Our IRP handlers
DPRINT1("Setting IRP handlers\n");
DriverObject->MajorFunction[IRP_MJ_CREATE] = PcDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_PNP] = PcDispatchIrp;
@@ -56,10 +39,10 @@ PcInitializeAdapterDriver(
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = PcDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = PcDispatchIrp;
/* The driver-supplied AddDevice */
// The driver-supplied AddDevice
DriverObject->DriverExtension->AddDevice = AddDevice;
/* KS handles these */
// KS handles these
DPRINT("Setting KS function handlers\n");
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
@@ -74,15 +57,16 @@ PcInitializeAdapterDriver(
return STATUS_SUCCESS;
}
/*
Typically called by a driver's AddDevice function, which is set when
calling PcInitializeAdapterDriver. This performs some common driver
operations, such as creating a device extension.
The StartDevice parameter is a driver-supplied function which gets
called in response to IRP_MJ_PNP / IRP_MN_START_DEVICE.
*/
NTSTATUS NTAPI
//
// Typically called by a driver's AddDevice function, which is set when
// calling PcInitializeAdapterDriver. This performs some common driver
// operations, such as creating a device extension.
//
// The StartDevice parameter is a driver-supplied function which gets
// called in response to IRP_MJ_PNP / IRP_MN_START_DEVICE.
//
NTSTATUS
NTAPI
PcAddAdapterDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject,
@@ -96,27 +80,27 @@ PcAddAdapterDevice(
PPCLASS_DEVICE_EXTENSION portcls_ext = NULL;
DPRINT1("PcAddAdapterDevice called\n");
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!DriverObject || !PhysicalDeviceObject || !StartDevice)
{
return STATUS_INVALID_PARAMETER;
}
/* check if the DeviceExtensionSize is provided */
// check if the DeviceExtensionSize is provided
if ( DeviceExtensionSize < PORT_CLASS_DEVICE_EXTENSION_SIZE )
{
/* driver does not need a device extension */
// driver does not need a device extension
if ( DeviceExtensionSize != 0 )
{
/* DeviceExtensionSize must be zero*/
// DeviceExtensionSize must be zero
return STATUS_INVALID_PARAMETER;
}
/* set size to our extension size */
// set size to our extension size
DeviceExtensionSize = PORT_CLASS_DEVICE_EXTENSION_SIZE;
}
/* create the device */
// create the device
status = IoCreateDevice(DriverObject,
DeviceExtensionSize,
NULL,
@@ -131,69 +115,69 @@ PcAddAdapterDevice(
return status;
}
/* Obtain the new device extension */
// Obtain the new device extension
portcls_ext = (PPCLASS_DEVICE_EXTENSION) fdo->DeviceExtension;
/* initialize the device extension */
// initialize the device extension
RtlZeroMemory(portcls_ext, DeviceExtensionSize);
/* allocate create item */
portcls_ext->CreateItems = AllocateItem(NonPagedPool, MaxObjects * sizeof(KSOBJECT_CREATE_ITEM), TAG_PORTCLASS);
// allocate create item
portcls_ext->CreateItems = (PKSOBJECT_CREATE_ITEM)AllocateItem(NonPagedPool, MaxObjects * sizeof(KSOBJECT_CREATE_ITEM), TAG_PORTCLASS);
if (!portcls_ext->CreateItems)
{
/* not enough resources */
// not enough resources
status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
/* store max subdevice count */
// store max subdevice count
portcls_ext->MaxSubDevices = MaxObjects;
/* store the physical device object */
// store the physical device object
portcls_ext->PhysicalDeviceObject = PhysicalDeviceObject;
/* set up the start device function */
// set up the start device function
portcls_ext->StartDevice = StartDevice;
/* prepare the subdevice list */
// prepare the subdevice list
InitializeListHead(&portcls_ext->SubDeviceList);
/* prepare the physical connection list */
// prepare the physical connection list
InitializeListHead(&portcls_ext->PhysicalConnectionList);
/* initialize timer lock */
// initialize timer lock
KeInitializeSpinLock(&portcls_ext->TimerListLock);
/* initialize timer list */
// initialize timer list
InitializeListHead(&portcls_ext->TimerList);
/* initialize io timer */
// initialize io timer
IoInitializeTimer(fdo, PcIoTimerRoutine, NULL);
/* start the io timer */
// start the io timer
IoStartTimer(fdo);
/* set io flags */
// set io flags
fdo->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
/* clear initializing flag */
// clear initializing flag
fdo->Flags &= ~ DO_DEVICE_INITIALIZING;
/* allocate the device header */
// allocate the device header
status = KsAllocateDeviceHeader(&portcls_ext->KsDeviceHeader, MaxObjects, portcls_ext->CreateItems);
/* did we succeed */
// did we succeed
if (!NT_SUCCESS(status))
{
goto cleanup;
}
/* attach device to device stack */
// attach device to device stack
PrevDeviceObject = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
/* did we succeed */
// did we succeed
if (PrevDeviceObject)
{
/* store the device object in the device header */
// store the device object in the device header
//KsSetDevicePnpBaseObject(portcls_ext->KsDeviceHeader, fdo, PrevDeviceObject);
portcls_ext->PrevDeviceObject = PrevDeviceObject;
}
else
{
/* return error code */
// return error code
status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
/* register shutdown notification */
// register shutdown notification
IoRegisterShutdownNotification(PhysicalDeviceObject);
return status;
@@ -202,17 +186,17 @@ cleanup:
if (portcls_ext->KsDeviceHeader)
{
/* free the device header */
// free the device header
KsFreeDeviceHeader(portcls_ext->KsDeviceHeader);
}
if (portcls_ext->CreateItems)
{
/* free previously allocated create items */
// free previously allocated create items
FreeItem(portcls_ext->CreateItems, TAG_PORTCLASS);
}
/* delete created fdo */
// delete created fdo
IoDeleteDevice(fdo);
@@ -237,79 +221,80 @@ PcRegisterSubdevice(
PSYMBOLICLINK_ENTRY SymEntry;
DPRINT1("PcRegisterSubdevice DeviceObject %p Name %S Unknown %p\n", DeviceObject, Name, Unknown);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
/* check if all parameters are valid */
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
// check if all parameters are valid
if (!DeviceObject || !Name || !Unknown)
{
DPRINT("PcRegisterSubdevice invalid parameter\n");
return STATUS_INVALID_PARAMETER;
}
/* get device extension */
// get device extension
DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (!DeviceExt)
{
/* should not happen */
// should not happen
KeBugCheck(0);
return STATUS_UNSUCCESSFUL;
}
/* look up our undocumented interface */
Status = Unknown->lpVtbl->QueryInterface(Unknown, &IID_ISubdevice, (LPVOID)&SubDevice);
// look up our undocumented interface
Status = Unknown->QueryInterface(IID_ISubdevice, (LPVOID*)&SubDevice);
if (!NT_SUCCESS(Status))
{
DPRINT1("No ISubdevice interface\n");
/* the provided port driver doesnt support ISubdevice */
// the provided port driver doesnt support ISubdevice
return STATUS_INVALID_PARAMETER;
}
/* get the subdevice descriptor */
Status = SubDevice->lpVtbl->GetDescriptor(SubDevice, &SubDeviceDescriptor);
// get the subdevice descriptor
Status = SubDevice->GetDescriptor(&SubDeviceDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get subdevice descriptor %x\n", Status);
SubDevice->lpVtbl->Release(SubDevice);
SubDevice->Release();
return STATUS_UNSUCCESSFUL;
}
/* allocate subdevice entry */
Entry = AllocateItem(NonPagedPool, sizeof(SUBDEVICE_ENTRY), TAG_PORTCLASS);
// allocate subdevice entry
Entry = (PSUBDEVICE_ENTRY)AllocateItem(NonPagedPool, sizeof(SUBDEVICE_ENTRY), TAG_PORTCLASS);
if (!Entry)
{
/* Insufficient memory */
SubDevice->lpVtbl->Release(SubDevice);
// Insufficient memory
SubDevice->Release();
return STATUS_INSUFFICIENT_RESOURCES;
}
/* add an create item to the device header */
// add an create item to the device header
Status = KsAddObjectCreateItemToDeviceHeader(DeviceExt->KsDeviceHeader, PcCreateItemDispatch, (PVOID)SubDevice, Name, NULL);
if (!NT_SUCCESS(Status))
{
/* failed to attach */
SubDevice->lpVtbl->Release(SubDevice);
// failed to attach
SubDevice->Release();
FreeItem(Entry, TAG_PORTCLASS);
DPRINT1("KsAddObjectCreateItemToDeviceHeader failed with %x\n", Status);
return Status;
}
/* initialize reference string */
// initialize reference string
RtlInitUnicodeString(&RefName, Name);
/* initialize subdevice entry */
// initialize subdevice entry
Entry->SubDevice = SubDevice;
RtlInitUnicodeString(&Entry->Name, Name);
InitializeListHead(&Entry->SymbolicLinkList);
/* store subdevice entry */
// store subdevice entry
InsertTailList(&DeviceExt->SubDeviceList, &Entry->Entry);
for(Index = 0; Index < SubDeviceDescriptor->InterfaceCount; Index++)
{
/* FIXME
* check if reference string with that name already exists
*/
// FIXME
// check if reference string with that name already exists
Status = IoRegisterDeviceInterface(DeviceExt->PhysicalDeviceObject,
&SubDeviceDescriptor->Interfaces[Index],
&RefName,
@@ -317,27 +302,27 @@ PcRegisterSubdevice(
if (NT_SUCCESS(Status))
{
/* activate device interface */
// activate device interface
IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE);
/* allocate symbolic link entry */
SymEntry = AllocateItem(NonPagedPool, sizeof(SYMBOLICLINK_ENTRY), TAG_PORTCLASS);
// allocate symbolic link entry
SymEntry = (PSYMBOLICLINK_ENTRY)AllocateItem(NonPagedPool, sizeof(SYMBOLICLINK_ENTRY), TAG_PORTCLASS);
if (SymEntry)
{
/* initialize symbolic link item */
// initialize symbolic link item
RtlInitUnicodeString(&SymEntry->SymbolicLink, SymbolicLinkName.Buffer);
/* store item */
// store item
InsertTailList(&Entry->SymbolicLinkList, &SymEntry->Entry);
}
else
{
/* allocating failed */
// allocating failed
RtlFreeUnicodeString(&SymbolicLinkName);
}
}
}
/* release SubDevice reference */
SubDevice->lpVtbl->Release(SubDevice);
// release SubDevice reference
SubDevice->Release();
return STATUS_SUCCESS;
}
@@ -1,16 +1,13 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/api.c
* FILE: drivers/wdm/audio/backpln/portcls/api.cpp
* PURPOSE: Port api functions
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
#include "private.hpp"
/*
* @implemented
*/
NTSTATUS
NTAPI
PcGetDeviceProperty(
@@ -22,16 +19,13 @@ PcGetDeviceProperty(
{
PPCLASS_DEVICE_EXTENSION DeviceExtension;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
DeviceExtension = (PPCLASS_DEVICE_EXTENSION)((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
return IoGetDeviceProperty(DeviceExtension->PhysicalDeviceObject, DeviceProperty, BufferLength, PropertyBuffer, ResultLength);
}
/*
* @implemented
*/
ULONGLONG
NTAPI
PcGetTimeInterval(
@@ -44,10 +38,6 @@ PcGetTimeInterval(
return (CurrentTime.QuadPart - Since);
}
/*
* @implemented
*/
VOID
NTAPI
PcIoTimerRoutine(
@@ -78,10 +68,8 @@ PcIoTimerRoutine(
KeReleaseSpinLock(&DeviceExtension->TimerListLock, OldIrql);
}
/*
* @implemented
*/
NTSTATUS NTAPI
NTSTATUS
NTAPI
PcRegisterIoTimeout(
IN PDEVICE_OBJECT pDeviceObject,
IN PIO_TIMER_ROUTINE pTimerRoutine,
@@ -94,14 +82,14 @@ PcRegisterIoTimeout(
BOOLEAN bFound;
PPCLASS_DEVICE_EXTENSION DeviceExtension;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!pDeviceObject || !pDeviceObject->DeviceExtension)
return STATUS_INVALID_PARAMETER;
DeviceExtension = (PPCLASS_DEVICE_EXTENSION)pDeviceObject->DeviceExtension;
TimerContext = AllocateItem(NonPagedPool, sizeof(TIMER_CONTEXT), TAG_PORTCLASS);
TimerContext = (PTIMER_CONTEXT)AllocateItem(NonPagedPool, sizeof(TIMER_CONTEXT), TAG_PORTCLASS);
if (!TimerContext)
{
DPRINT1("Failed to allocate memory\n");
@@ -138,9 +126,6 @@ PcRegisterIoTimeout(
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcUnregisterIoTimeout(
@@ -154,7 +139,7 @@ PcUnregisterIoTimeout(
BOOLEAN bFound;
PPCLASS_DEVICE_EXTENSION DeviceExtension;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!pDeviceObject || !pDeviceObject->DeviceExtension)
return STATUS_INVALID_PARAMETER;
@@ -191,41 +176,32 @@ PcUnregisterIoTimeout(
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcCompletePendingPropertyRequest(
IN PPCPROPERTY_REQUEST PropertyRequest,
IN NTSTATUS NtStatus)
{
/* sanity checks */
ASSERT_IRQL(DISPATCH_LEVEL);
// sanity checks
PC_ASSERT_IRQL(DISPATCH_LEVEL);
if (!PropertyRequest)
if (!PropertyRequest || !PropertyRequest->Irp || NtStatus == STATUS_PENDING)
return STATUS_INVALID_PARAMETER;
ASSERT(PropertyRequest->Irp);
ASSERT(NtStatus != STATUS_PENDING);
/* set the final status code */
// set the final status code
PropertyRequest->Irp->IoStatus.Status = NtStatus;
/* complete the irp */
// complete the irp
IoCompleteRequest(PropertyRequest->Irp, IO_SOUND_INCREMENT);
/* free the property request */
// free the property request
ExFreePool(PropertyRequest);
/* return success */
// return success
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcDmaMasterDescription(
@@ -256,9 +232,7 @@ PcDmaMasterDescription(
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcDmaSlaveDescription(
@@ -7,62 +7,69 @@
*/
#include "private.h"
#include "private.hpp"
typedef struct
extern
"C"
NTSYSAPI
BOOLEAN
NTAPI
RtlCreateUnicodeString(
PUNICODE_STRING DestinationString,
PCWSTR SourceString
);
class CUnregisterPhysicalConnection : public IUnregisterPhysicalConnection
{
IUnregisterPhysicalConnectionVtbl *lpVtbl;
LONG ref;
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
}IUnregisterPhysicalConnectionImpl;
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IUnregisterPhysicalConnection;
CUnregisterPhysicalConnection(IUnknown *OuterUnknown){}
virtual ~CUnregisterPhysicalConnection(){}
protected:
LONG m_Ref;
};
NTSTATUS
NTAPI
IUnregisterPhysicalConnection_fnQueryInterface(
IUnregisterPhysicalConnection* iface,
CUnregisterPhysicalConnection::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
IUnregisterPhysicalConnectionImpl * This = (IUnregisterPhysicalConnectionImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IUnregisterPhysicalConnection) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IUnregisterPhysicalConnection_fnAddRef(
IUnregisterPhysicalConnection* iface)
{
IUnregisterPhysicalConnectionImpl * This = (IUnregisterPhysicalConnectionImpl*)iface;
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IUnregisterPhysicalConnection_fnRelease(
IUnregisterPhysicalConnection* iface)
{
IUnregisterPhysicalConnectionImpl * This = (IUnregisterPhysicalConnectionImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
return This->ref;
}
static
NTSTATUS
UnRegisterConnection(
@@ -86,15 +93,15 @@ UnRegisterConnection(
if (FromUnknown)
{
/* get our private interface */
Status = FromUnknown->lpVtbl->QueryInterface(FromUnknown, &IID_ISubdevice, (PVOID*)&FromSubDevice);
// get our private interface
Status = FromUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&FromSubDevice);
if (!NT_SUCCESS(Status))
return STATUS_INVALID_PARAMETER;
}
if (ToUnknown)
{
Status = ToUnknown->lpVtbl->QueryInterface(ToUnknown, &IID_ISubdevice, (PVOID*)&ToSubDevice);
Status = ToUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&ToSubDevice);
if (!NT_SUCCESS(Status))
goto cleanup;
}
@@ -102,11 +109,11 @@ UnRegisterConnection(
Entry = DeviceExt->PhysicalConnectionList.Flink;
bFound = FALSE;
/* loop physical connection list */
// loop physical connection list
while(Entry != &DeviceExt->PhysicalConnectionList)
{
Connection = (PPHYSICAL_CONNECTION)CONTAINING_RECORD(Entry, PHYSICAL_CONNECTION, Entry);
/* compare current entry */
// compare current entry
if (Connection->FromPin == FromPin && Connection->ToPin == ToPin &&
Connection->FromSubDevice == FromSubDevice && Connection->ToSubDevice == ToSubDevice)
{
@@ -114,7 +121,7 @@ UnRegisterConnection(
{
if (!RtlCompareUnicodeString(FromString, &Connection->FromUnicodeString, TRUE))
{
/* UnregisterPhysicalConnectionFromExternal */
// UnregisterPhysicalConnectionFromExternal
bFound = TRUE;
break;
}
@@ -123,14 +130,14 @@ UnRegisterConnection(
{
if (!RtlCompareUnicodeString(ToString, &Connection->ToUnicodeString, TRUE))
{
/* UnregisterPhysicalConnectionToExternal */
// UnregisterPhysicalConnectionToExternal
bFound = TRUE;
break;
}
}
else
{
/* UnregisterPhysicalConnection */
// UnregisterPhysicalConnection
bFound = TRUE;
break;
}
@@ -140,21 +147,21 @@ UnRegisterConnection(
if (!bFound)
{
/* not found */
// not found
Status = STATUS_NOT_FOUND;
goto cleanup;
}
/* remove list entry */
// remove list entry
RemoveEntryList(&Connection->Entry);
/* release resources */
// release resources
if (Connection->FromSubDevice)
Connection->FromSubDevice->lpVtbl->Release(Connection->FromSubDevice);
Connection->FromSubDevice->Release();
if (Connection->ToSubDevice)
Connection->ToSubDevice->lpVtbl->Release(Connection->ToSubDevice);
Connection->ToSubDevice->Release();
if (Connection->FromUnicodeString.Buffer)
RtlFreeUnicodeString(&Connection->FromUnicodeString);
@@ -168,10 +175,10 @@ UnRegisterConnection(
cleanup:
if (FromSubDevice)
FromSubDevice->lpVtbl->Release(FromSubDevice);
FromSubDevice->Release();
if (ToSubDevice)
ToSubDevice->lpVtbl->Release(ToSubDevice);
ToSubDevice->Release();
return Status;
@@ -179,8 +186,7 @@ cleanup:
NTSTATUS
NTAPI
IUnregisterPhysicalConnection_fnUnregisterPhysicalConnection(
IN IUnregisterPhysicalConnection* iface,
CUnregisterPhysicalConnection::UnregisterPhysicalConnection(
IN PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN FromUnknown,
IN ULONG FromPin,
@@ -195,8 +201,7 @@ IUnregisterPhysicalConnection_fnUnregisterPhysicalConnection(
NTSTATUS
NTAPI
IUnregisterPhysicalConnection_fnUnregisterPhysicalConnectionToExternal(
IN IUnregisterPhysicalConnection* iface,
CUnregisterPhysicalConnection::UnregisterPhysicalConnectionToExternal(
IN PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN FromUnknown,
IN ULONG FromPin,
@@ -211,8 +216,7 @@ IUnregisterPhysicalConnection_fnUnregisterPhysicalConnectionToExternal(
NTSTATUS
NTAPI
IUnregisterPhysicalConnection_fnUnregisterPhysicalConnectionFromExternal(
IN IUnregisterPhysicalConnection* iface,
CUnregisterPhysicalConnection::UnregisterPhysicalConnectionFromExternal(
IN PDEVICE_OBJECT DeviceObject,
IN PUNICODE_STRING FromString,
IN ULONG FromPin,
@@ -225,41 +229,22 @@ IUnregisterPhysicalConnection_fnUnregisterPhysicalConnectionFromExternal(
return UnRegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin);
}
static IUnregisterPhysicalConnectionVtbl vt_IUnregisterPhysicalConnection =
{
IUnregisterPhysicalConnection_fnQueryInterface,
IUnregisterPhysicalConnection_fnAddRef,
IUnregisterPhysicalConnection_fnRelease,
IUnregisterPhysicalConnection_fnUnregisterPhysicalConnection,
IUnregisterPhysicalConnection_fnUnregisterPhysicalConnectionToExternal,
IUnregisterPhysicalConnection_fnUnregisterPhysicalConnectionFromExternal
};
NTSTATUS
NTAPI
NewIUnregisterPhysicalConnection(
OUT PUNREGISTERPHYSICALCONNECTION *OutConnection)
{
IUnregisterPhysicalConnectionImpl * This = (IUnregisterPhysicalConnectionImpl*)AllocateItem(NonPagedPool, sizeof(IUnregisterPhysicalConnectionImpl), TAG_PORTCLASS);
if (!This)
CUnregisterPhysicalConnection *new_ptr = new(NonPagedPool, TAG_PORTCLASS) CUnregisterPhysicalConnection(NULL);
if (!new_ptr)
return STATUS_INSUFFICIENT_RESOURCES;
This->lpVtbl = &vt_IUnregisterPhysicalConnection;
This->ref = 1;
*OutConnection = (PUNREGISTERPHYSICALCONNECTION)&This->lpVtbl;
new_ptr->AddRef();
*OutConnection = (PUNREGISTERPHYSICALCONNECTION)new_ptr;
return STATUS_SUCCESS;
}
NTSYSAPI
BOOLEAN
NTAPI
RtlCreateUnicodeString(
PUNICODE_STRING DestinationString,
PCWSTR SourceString
);
static
NTSTATUS
RegisterConnection(
IN OUT PDEVICE_OBJECT DeviceObject,
@@ -276,7 +261,7 @@ RegisterConnection(
DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
NewConnection = AllocateItem(NonPagedPool, sizeof(PHYSICAL_CONNECTION), TAG_PORTCLASS);
NewConnection = (PPHYSICAL_CONNECTION)AllocateItem(NonPagedPool, sizeof(PHYSICAL_CONNECTION), TAG_PORTCLASS);
if (!NewConnection)
{
return STATUS_INSUFFICIENT_RESOURCES;
@@ -285,7 +270,7 @@ RegisterConnection(
if (FromUnknown)
{
Status = FromUnknown->lpVtbl->QueryInterface(FromUnknown, &IID_ISubdevice, (PVOID*)&NewConnection->FromSubDevice);
Status = FromUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&NewConnection->FromSubDevice);
if (!NT_SUCCESS(Status))
goto cleanup;
}
@@ -300,7 +285,7 @@ RegisterConnection(
if (ToUnknown)
{
Status = ToUnknown->lpVtbl->QueryInterface(ToUnknown, &IID_ISubdevice, (PVOID*)&NewConnection->ToSubDevice);
Status = ToUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&NewConnection->ToSubDevice);
if (!NT_SUCCESS(Status))
goto cleanup;
}
@@ -319,10 +304,10 @@ RegisterConnection(
cleanup:
if (NewConnection->FromSubDevice)
NewConnection->FromSubDevice->lpVtbl->Release(NewConnection->FromSubDevice);
NewConnection->FromSubDevice->Release();
if (NewConnection->ToSubDevice)
NewConnection->ToSubDevice->lpVtbl->Release(NewConnection->ToSubDevice);
NewConnection->ToSubDevice->Release();
if (NewConnection->FromUnicodeString.Buffer)
RtlFreeUnicodeString(&NewConnection->FromUnicodeString);
@@ -335,10 +320,8 @@ cleanup:
return Status;
}
/*
* @implemented
*/
NTSTATUS NTAPI
NTSTATUS
NTAPI
PcRegisterPhysicalConnection(
IN PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN FromUnknown,
@@ -347,7 +330,7 @@ PcRegisterPhysicalConnection(
IN ULONG ToPin)
{
DPRINT("PcRegisterPhysicalConnection\n");
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!DeviceObject || !FromUnknown || !ToUnknown)
return STATUS_INVALID_PARAMETER;
@@ -355,10 +338,8 @@ PcRegisterPhysicalConnection(
return RegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, ToUnknown, NULL, ToPin);
}
/*
* @implemented
*/
NTSTATUS NTAPI
NTSTATUS
NTAPI
PcRegisterPhysicalConnectionFromExternal(
IN PDEVICE_OBJECT DeviceObject,
IN PUNICODE_STRING FromString,
@@ -366,7 +347,7 @@ PcRegisterPhysicalConnectionFromExternal(
IN PUNKNOWN ToUnknown,
IN ULONG ToPin)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!DeviceObject || !FromString || !ToUnknown)
return STATUS_INVALID_PARAMETER;
@@ -374,10 +355,8 @@ PcRegisterPhysicalConnectionFromExternal(
return RegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin);
}
/*
* @implemented
*/
NTSTATUS NTAPI
NTSTATUS
NTAPI
PcRegisterPhysicalConnectionToExternal(
IN PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN FromUnknown,
@@ -385,7 +364,7 @@ PcRegisterPhysicalConnectionToExternal(
IN PUNICODE_STRING ToString,
IN ULONG ToPin)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!DeviceObject || !FromUnknown || !ToString)
return STATUS_INVALID_PARAMETER;
@@ -7,7 +7,7 @@
*/
#include "private.h"
#include "private.hpp"
NTSTATUS
NTAPI
@@ -18,14 +18,14 @@ Dispatch_fnDeviceIoControl(
PIO_STACK_LOCATION IoStack;
IIrpTarget * IrpTarget;
/* get current irp stack */
// get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* access IrpTarget */
// access IrpTarget
IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext2;
/* let IrpTarget handle request */
return IrpTarget->lpVtbl->DeviceIoControl(IrpTarget, DeviceObject, Irp);
// let IrpTarget handle request
return IrpTarget->DeviceIoControl(DeviceObject, Irp);
}
NTSTATUS
@@ -37,15 +37,15 @@ Dispatch_fnRead(
PIO_STACK_LOCATION IoStack;
IIrpTarget * IrpTarget;
/* get current irp stack */
// get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* access IrpTarget */
// access IrpTarget
IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext2;
/* let IrpTarget handle request */
return IrpTarget->lpVtbl->Read(IrpTarget, DeviceObject, Irp);
// let IrpTarget handle request
return IrpTarget->Read(DeviceObject, Irp);
}
NTSTATUS
@@ -57,15 +57,15 @@ Dispatch_fnWrite(
PIO_STACK_LOCATION IoStack;
IIrpTarget * IrpTarget;
/* get current irp stack */
// get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* access IrpTarget */
// access IrpTarget
IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext2;
/* let IrpTarget handle request */
return IrpTarget->lpVtbl->Write(IrpTarget, DeviceObject, Irp);
// let IrpTarget handle request
return IrpTarget->Write(DeviceObject, Irp);
}
NTSTATUS
@@ -77,15 +77,15 @@ Dispatch_fnFlush(
PIO_STACK_LOCATION IoStack;
IIrpTarget * IrpTarget;
/* get current irp stack */
// get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* access IrpTarget */
// access IrpTarget
IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext2;
/* let IrpTarget handle request */
return IrpTarget->lpVtbl->Flush(IrpTarget, DeviceObject, Irp);
// let IrpTarget handle request
return IrpTarget->Flush(DeviceObject, Irp);
}
NTSTATUS
@@ -97,15 +97,15 @@ Dispatch_fnClose(
PIO_STACK_LOCATION IoStack;
IIrpTarget * IrpTarget;
/* get current irp stack */
// get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* access IrpTarget */
// access IrpTarget
IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext2;
/* let IrpTarget handle request */
return IrpTarget->lpVtbl->Close(IrpTarget, DeviceObject, Irp);
// let IrpTarget handle request
return IrpTarget->Close(DeviceObject, Irp);
}
NTSTATUS
@@ -117,15 +117,15 @@ Dispatch_fnQuerySecurity(
PIO_STACK_LOCATION IoStack;
IIrpTarget * IrpTarget;
/* get current irp stack */
// get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* access IrpTarget */
// access IrpTarget
IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext2;
/* let IrpTarget handle request */
return IrpTarget->lpVtbl->QuerySecurity(IrpTarget, DeviceObject, Irp);
// let IrpTarget handle request
return IrpTarget->QuerySecurity(DeviceObject, Irp);
}
NTSTATUS
@@ -137,15 +137,15 @@ Dispatch_fnSetSecurity(
PIO_STACK_LOCATION IoStack;
IIrpTarget * IrpTarget;
/* get current irp stack */
// get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* access IrpTarget */
// access IrpTarget
IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext2;
/* let IrpTarget handle request */
return IrpTarget->lpVtbl->SetSecurity(IrpTarget, DeviceObject, Irp);
// let IrpTarget handle request
return IrpTarget->SetSecurity(DeviceObject, Irp);
}
BOOLEAN
@@ -163,11 +163,11 @@ Dispatch_fnFastDeviceIoControl(
{
IIrpTarget * IrpTarget;
/* access IrpTarget */
// access IrpTarget
IrpTarget = (IIrpTarget *)FileObject->FsContext2;
/* let IrpTarget handle request */
return IrpTarget->lpVtbl->FastDeviceIoControl(IrpTarget, FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, IoStatus, DeviceObject);
// let IrpTarget handle request
return IrpTarget->FastDeviceIoControl(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, IoStatus, DeviceObject);
}
@@ -185,11 +185,11 @@ Dispatch_fnFastRead(
{
IIrpTarget * IrpTarget;
/* access IrpTarget */
// access IrpTarget
IrpTarget = (IIrpTarget *)FileObject->FsContext2;
/* let IrpTarget handle request */
return IrpTarget->lpVtbl->FastRead(IrpTarget, FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
// let IrpTarget handle request
return IrpTarget->FastRead(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
}
BOOLEAN
@@ -206,10 +206,10 @@ Dispatch_fnFastWrite(
{
IIrpTarget * IrpTarget;
/* access IrpTarget */
// access IrpTarget
IrpTarget = (IIrpTarget *)FileObject->FsContext2;
/* let IrpTarget handle request */
return IrpTarget->lpVtbl->FastWrite(IrpTarget, FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
// let IrpTarget handle request
return IrpTarget->FastWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
}
static KSDISPATCH_TABLE DispatchTable =
@@ -239,7 +239,7 @@ NewDispatchObject(
KSOBJECT_HEADER ObjectHeader;
PIO_STACK_LOCATION IoStack;
/* get current irp stack location */
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
IoStack->FileObject->FsContext2 = (PVOID)Target;
@@ -1,17 +1,14 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/dll.c
* FILE: drivers/wdm/audio/backpln/portcls/dll.cpp
* PURPOSE: portcls generic dispatcher
* PROGRAMMER: Andrew Greenwood
*/
#include "private.h"
#include "private.hpp"
/*
* @implemented
*/
ULONG
NTAPI
DllInitialize(ULONG Unknown)
@@ -19,12 +16,14 @@ DllInitialize(ULONG Unknown)
return 0;
}
/*
* @implemented
*/
extern
"C"
{
ULONG
NTAPI
DllUnload(VOID)
DllUnload()
{
return 0;
}
}
@@ -1,572 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/dma_Init.c
* PURPOSE: portcls dma support object
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IDmaChannelInitVtbl *lpVtbl;
LONG ref;
PDEVICE_OBJECT pDeviceObject;
PDMA_ADAPTER pAdapter;
BOOL DmaStarted;
ULONG MapSize;
PVOID MapRegisterBase;
ULONG LastTransferCount;
ULONG MaximumBufferSize;
ULONG MaxMapRegisters;
ULONG AllocatedBufferSize;
ULONG BufferSize;
PHYSICAL_ADDRESS Address;
PVOID Buffer;
PMDL Mdl;
BOOLEAN WriteToDevice;
}IDmaChannelInitImpl;
//---------------------------------------------------------------
// IUnknown methods
//
extern GUID IID_IDmaChannelSlave;
NTSTATUS
NTAPI
IDmaChannelInit_fnQueryInterface(
IDmaChannelInit * iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IUnknown) ||
IsEqualGUIDAligned(refiid, &IID_IDmaChannel) ||
IsEqualGUIDAligned(refiid, &IID_IDmaChannelSlave))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
DPRINT1("No interface!!!\n");
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IDmaChannelInit_fnAddRef(
IDmaChannelInit * iface)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_AddRef: This %p\n", This);
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IDmaChannelInit_fnRelease(
IDmaChannelInit* iface)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
InterlockedDecrement(&This->ref);
DPRINT("IDmaChannelInit_Release: This %p new ref %u\n", This, This->ref);
if (This->ref == 0)
{
This->pAdapter->DmaOperations->PutDmaAdapter(This->pAdapter);
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
//---------------------------------------------------------------
// IDmaChannel methods
//
NTSTATUS
NTAPI
IDmaChannelInit_fnAllocateBuffer(
IN IDmaChannelInit * iface,
IN ULONG BufferSize,
IN PPHYSICAL_ADDRESS PhysicalAddressConstraint OPTIONAL)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
/* Did the caller already allocate a buffer ?*/
if (This->Buffer)
{
DPRINT1("IDmaChannelInit_AllocateBuffer free common buffer first \n");
return STATUS_UNSUCCESSFUL;
}
This->Buffer = This->pAdapter->DmaOperations->AllocateCommonBuffer(This->pAdapter, BufferSize, &This->Address, FALSE);
if (!This->Buffer)
{
DPRINT1("IDmaChannelInit_AllocateBuffer fAllocateCommonBuffer failed \n");
return STATUS_UNSUCCESSFUL;
}
This->BufferSize = BufferSize;
This->AllocatedBufferSize = BufferSize;
DPRINT1("IDmaChannelInit_fnAllocateBuffer Success Buffer %p BufferSize %u Address %x\n", This->Buffer, BufferSize, This->Address);
return STATUS_SUCCESS;
}
ULONG
NTAPI
IDmaChannelInit_fnAllocatedBufferSize(
IN IDmaChannelInit * iface)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_AllocatedBufferSize: This %p BufferSize %u\n", This, This->BufferSize);
return This->AllocatedBufferSize;
}
VOID
NTAPI
IDmaChannelInit_fnCopyFrom(
IN IDmaChannelInit * iface,
IN PVOID Destination,
IN PVOID Source,
IN ULONG ByteCount
)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_CopyFrom: This %p Destination %p Source %p ByteCount %u\n", This, Destination, Source, ByteCount);
iface->lpVtbl->CopyTo(iface, Destination, Source, ByteCount);
}
VOID
NTAPI
IDmaChannelInit_fnCopyTo(
IN IDmaChannelInit * iface,
IN PVOID Destination,
IN PVOID Source,
IN ULONG ByteCount
)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_CopyTo: This %p Destination %p Source %p ByteCount %u\n", This, Destination, Source, ByteCount);
RtlCopyMemory(Destination, Source, ByteCount);
}
VOID
NTAPI
IDmaChannelInit_fnFreeBuffer(
IN IDmaChannelInit * iface)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_FreeBuffer: This %p\n", This);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->Buffer)
{
DPRINT1("IDmaChannelInit_FreeBuffer allocate common buffer first \n");
return;
}
This->pAdapter->DmaOperations->FreeCommonBuffer(This->pAdapter, This->AllocatedBufferSize, This->Address, This->Buffer, FALSE);
This->Buffer = NULL;
This->AllocatedBufferSize = 0;
This->Address.QuadPart = 0LL;
if (This->Mdl)
{
IoFreeMdl(This->Mdl);
This->Mdl = NULL;
}
}
PADAPTER_OBJECT
NTAPI
IDmaChannelInit_fnGetAdapterObject(
IN IDmaChannelInit * iface)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_GetAdapterObject: This %p\n", This);
return (PADAPTER_OBJECT)This->pAdapter;
}
ULONG
NTAPI
IDmaChannelInit_fnMaximumBufferSize(
IN IDmaChannelInit * iface)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_MaximumBufferSize: This %p\n", This);
return This->MaximumBufferSize;
}
PHYSICAL_ADDRESS
NTAPI
IDmaChannelInit_fnPhysicalAdress(
IN IDmaChannelInit * iface,
PPHYSICAL_ADDRESS Address)
{
PHYSICAL_ADDRESS Result;
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_PhysicalAdress: This %p Virtuell %p Physical High %x Low %x%\n", This, This->Buffer, This->Address.HighPart, This->Address.LowPart);
Address->QuadPart = This->Address.QuadPart;
Result.QuadPart = (PtrToUlong(Address));
return Result;
}
VOID
NTAPI
IDmaChannelInit_fnSetBufferSize(
IN IDmaChannelInit * iface,
IN ULONG BufferSize)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_SetBufferSize: This %p\n", This);
This->BufferSize = BufferSize;
}
ULONG
NTAPI
IDmaChannelInit_fnBufferSize(
IN IDmaChannelInit * iface)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
return This->BufferSize;
}
PVOID
NTAPI
IDmaChannelInit_fnSystemAddress(
IN IDmaChannelInit * iface)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_SystemAddress: This %p\n", This);
return This->Buffer;
}
ULONG
NTAPI
IDmaChannelInit_fnTransferCount(
IN IDmaChannelInit * iface)
{
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_TransferCount: This %p\n", This);
return This->LastTransferCount;
}
ULONG
NTAPI
IDmaChannelInit_fnReadCounter(
IN IDmaChannelInit * iface)
{
ULONG Counter;
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
ASSERT_IRQL(DISPATCH_LEVEL);
Counter = This->pAdapter->DmaOperations->ReadDmaCounter(This->pAdapter);
if (!This->DmaStarted || Counter >= This->LastTransferCount) //FIXME
Counter = 0;
return Counter;
}
IO_ALLOCATION_ACTION
NTAPI
AdapterControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID MapRegisterBase,
IN PVOID Context)
{
ULONG Length;
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)Context;
Length = This->MapSize;
This->MapRegisterBase = MapRegisterBase;
This->pAdapter->DmaOperations->MapTransfer(This->pAdapter,
This->Mdl,
MapRegisterBase,
(PVOID)((ULONG_PTR)This->Mdl->StartVa + This->Mdl->ByteOffset),
&Length,
This->WriteToDevice);
if (Length == This->BufferSize)
{
This->DmaStarted = TRUE;
}
return KeepObject;
}
NTSTATUS
NTAPI
IDmaChannelInit_fnStart(
IN IDmaChannelInit * iface,
ULONG MapSize,
BOOLEAN WriteToDevice)
{
NTSTATUS Status;
ULONG MapRegisters;
KIRQL OldIrql;
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_Start: This %p\n", This);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->DmaStarted)
return STATUS_UNSUCCESSFUL;
if (!This->Mdl)
{
This->Mdl = IoAllocateMdl(This->Buffer, This->MaximumBufferSize, FALSE, FALSE, NULL);
if (!This->Mdl)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool(This->Mdl);
}
This->MapSize = MapSize;
This->WriteToDevice = WriteToDevice;
This->LastTransferCount = MapSize;
//FIXME
// synchronize access
//
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
MapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(This->Buffer, MapSize);
Status = This->pAdapter->DmaOperations->AllocateAdapterChannel(This->pAdapter, This->pDeviceObject, MapRegisters, AdapterControl, (PVOID)This);
KeLowerIrql(OldIrql);
if(!NT_SUCCESS(Status))
This->LastTransferCount = 0;
return Status;
}
NTSTATUS
NTAPI
IDmaChannelInit_fnStop(
IN IDmaChannelInit * iface)
{
KIRQL OldIrql;
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
DPRINT("IDmaChannelInit_fnStop: This %p\n", This);
ASSERT_IRQL(DISPATCH_LEVEL);
if (!This->DmaStarted)
return STATUS_SUCCESS;
This->pAdapter->DmaOperations->FlushAdapterBuffers(This->pAdapter,
This->Mdl,
This->MapRegisterBase,
(PVOID)((ULONG_PTR)This->Mdl->StartVa + This->Mdl->ByteOffset),
This->MapSize,
This->WriteToDevice);
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
This->pAdapter->DmaOperations->FreeAdapterChannel(This->pAdapter);
KeLowerIrql(OldIrql);
This->DmaStarted = FALSE;
IoFreeMdl(This->Mdl);
This->Mdl = NULL;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IDmaChannelInit_fnWaitForTC(
IN IDmaChannelInit * iface,
ULONG Timeout)
{
ULONG RetryCount;
ULONG BytesRemaining;
ULONG PrevBytesRemaining;
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
BytesRemaining = This->pAdapter->DmaOperations->ReadDmaCounter(This->pAdapter);
if (!BytesRemaining)
{
return STATUS_SUCCESS;
}
RetryCount = Timeout / 10;
PrevBytesRemaining = 0xFFFFFFFF;
do
{
BytesRemaining = This->pAdapter->DmaOperations->ReadDmaCounter(This->pAdapter);
if (!BytesRemaining)
break;
if (PrevBytesRemaining == BytesRemaining)
break;
KeStallExecutionProcessor(10);
PrevBytesRemaining = BytesRemaining;
}while(RetryCount-- >= 1);
if (BytesRemaining)
{
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IDmaChannelInit_fnInit(
IN IDmaChannelInit * iface,
IN PDEVICE_DESCRIPTION DeviceDescription,
IN PDEVICE_OBJECT DeviceObject)
{
INTERFACE_TYPE BusType;
NTSTATUS Status;
PDMA_ADAPTER Adapter;
PPCLASS_DEVICE_EXTENSION DeviceExt;
ULONG MapRegisters;
ULONG ResultLength;
IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
/* Get bus type */
Status = IoGetDeviceProperty(DeviceObject, DevicePropertyLegacyBusType, sizeof(BusType), (PVOID)&BusType, &ResultLength);
if (NT_SUCCESS(Status))
{
DeviceDescription->InterfaceType = BusType;
}
/* Fetch device extension */
DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
/* Acquire dma adapter */
Adapter = IoGetDmaAdapter(DeviceExt->PhysicalDeviceObject, DeviceDescription, &MapRegisters);
if (!Adapter)
{
FreeItem(This, TAG_PORTCLASS);
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
/* initialize object */
This->ref = 1;
This->pAdapter = Adapter;
This->pDeviceObject = DeviceObject;
This->MaximumBufferSize = DeviceDescription->MaximumLength;
This->MaxMapRegisters = MapRegisters;
return STATUS_SUCCESS;
}
IDmaChannelInitVtbl vt_IDmaChannelInitVtbl =
{
/* IUnknown methods */
IDmaChannelInit_fnQueryInterface,
IDmaChannelInit_fnAddRef,
IDmaChannelInit_fnRelease,
/* IDmaChannel methods */
IDmaChannelInit_fnAllocateBuffer,
IDmaChannelInit_fnFreeBuffer,
IDmaChannelInit_fnTransferCount,
IDmaChannelInit_fnMaximumBufferSize,
IDmaChannelInit_fnAllocatedBufferSize,
IDmaChannelInit_fnBufferSize,
IDmaChannelInit_fnSetBufferSize,
IDmaChannelInit_fnSystemAddress,
IDmaChannelInit_fnPhysicalAdress,
IDmaChannelInit_fnGetAdapterObject,
IDmaChannelInit_fnCopyTo,
IDmaChannelInit_fnCopyFrom,
/* IDmaChannelSlave methods */
IDmaChannelInit_fnStart,
IDmaChannelInit_fnStop,
IDmaChannelInit_fnReadCounter,
IDmaChannelInit_fnWaitForTC,
/* IDmaChannelInit methods */
IDmaChannelInit_fnInit
};
/*
* @unimplemented
*/
NTSTATUS NTAPI
PcNewDmaChannel(
OUT PDMACHANNEL* OutDmaChannel,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PDEVICE_DESCRIPTION DeviceDescription,
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
IDmaChannelInitImpl * This;
DPRINT("OutDmaChannel %p OuterUnknown %p PoolType %p DeviceDescription %p DeviceObject %p\n",
OutDmaChannel, OuterUnknown, PoolType, DeviceDescription, DeviceObject);
This = AllocateItem(PoolType, sizeof(IDmaChannelInitImpl), TAG_PORTCLASS);
if (!This)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
/* initialize object */
Status = IDmaChannelInit_fnInit((IDmaChannelInit*)This, DeviceDescription, DeviceObject);
if (NT_SUCCESS(Status))
{
/* store result */
This->lpVtbl = &vt_IDmaChannelInitVtbl;
*OutDmaChannel = (PVOID)(&This->lpVtbl);
}
return Status;
}
@@ -0,0 +1,481 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/dma_init.c
* PURPOSE: portcls dma support object
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CDmaChannelInit : public IDmaChannelInit
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IDmaChannelInit;
CDmaChannelInit(IUnknown * OuterUnknown){}
virtual ~CDmaChannelInit(){}
protected:
PDEVICE_OBJECT m_pDeviceObject;
PDMA_ADAPTER m_pAdapter;
BOOL m_DmaStarted;
ULONG m_MapSize;
PVOID m_MapRegisterBase;
ULONG m_LastTransferCount;
ULONG m_MaximumBufferSize;
ULONG m_MaxMapRegisters;
ULONG m_AllocatedBufferSize;
ULONG m_BufferSize;
PHYSICAL_ADDRESS m_Address;
PVOID m_Buffer;
PMDL m_Mdl;
BOOLEAN m_WriteToDevice;
friend IO_ALLOCATION_ACTION NTAPI AdapterControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context);
LONG m_Ref;
};
//---------------------------------------------------------------
// IUnknown methods
//
extern GUID IID_IDmaChannelSlave;
NTSTATUS
NTAPI
CDmaChannelInit::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
if (IsEqualGUIDAligned(refiid, IID_IUnknown) ||
IsEqualGUIDAligned(refiid, IID_IDmaChannel))
//IsEqualGUIDAligned(refiid, IID_IDmaChannelSlave)) // HACK
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
DPRINT1("No interface!!!\n");
return STATUS_UNSUCCESSFUL;
}
//---------------------------------------------------------------
// IDmaChannel methods
//
NTSTATUS
NTAPI
CDmaChannelInit::AllocateBuffer(
IN ULONG BufferSize,
IN PPHYSICAL_ADDRESS PhysicalAddressConstraint OPTIONAL)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
// Did the caller already allocate a buffer ?*/
if (m_Buffer)
{
DPRINT1("CDmaChannelInit_AllocateBuffer free common buffer first \n");
return STATUS_UNSUCCESSFUL;
}
m_Buffer = m_pAdapter->DmaOperations->AllocateCommonBuffer(m_pAdapter, BufferSize, &m_Address, FALSE);
if (!m_Buffer)
{
DPRINT1("CDmaChannelInit_AllocateBuffer fAllocateCommonBuffer failed \n");
return STATUS_UNSUCCESSFUL;
}
m_BufferSize = BufferSize;
m_AllocatedBufferSize = BufferSize;
DPRINT1("CDmaChannelInit::AllocateBuffer Success Buffer %p BufferSize %u Address %x\n", m_Buffer, BufferSize, m_Address);
return STATUS_SUCCESS;
}
ULONG
NTAPI
CDmaChannelInit::AllocatedBufferSize()
{
DPRINT("CDmaChannelInit_AllocatedBufferSize: this %p BufferSize %u\n", this, m_BufferSize);
return m_AllocatedBufferSize;
}
VOID
NTAPI
CDmaChannelInit::CopyFrom(
IN PVOID Destination,
IN PVOID Source,
IN ULONG ByteCount
)
{
DPRINT("CDmaChannelInit_CopyFrom: this %p Destination %p Source %p ByteCount %u\n", this, Destination, Source, ByteCount);
CopyTo(Destination, Source, ByteCount);
}
VOID
NTAPI
CDmaChannelInit::CopyTo(
IN PVOID Destination,
IN PVOID Source,
IN ULONG ByteCount
)
{
DPRINT("CDmaChannelInit_CopyTo: this %p Destination %p Source %p ByteCount %u\n", this, Destination, Source, ByteCount);
RtlCopyMemory(Destination, Source, ByteCount);
}
VOID
NTAPI
CDmaChannelInit::FreeBuffer()
{
DPRINT("CDmaChannelInit_FreeBuffer: this %p\n", this);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_Buffer)
{
DPRINT1("CDmaChannelInit_FreeBuffer allocate common buffer first \n");
return;
}
m_pAdapter->DmaOperations->FreeCommonBuffer(m_pAdapter, m_AllocatedBufferSize, m_Address, m_Buffer, FALSE);
m_Buffer = NULL;
m_AllocatedBufferSize = 0;
m_Address.QuadPart = 0LL;
if (m_Mdl)
{
IoFreeMdl(m_Mdl);
m_Mdl = NULL;
}
}
PADAPTER_OBJECT
NTAPI
CDmaChannelInit::GetAdapterObject()
{
DPRINT("CDmaChannelInit_GetAdapterObject: this %p\n", this);
return (PADAPTER_OBJECT)m_pAdapter;
}
ULONG
NTAPI
CDmaChannelInit::MaximumBufferSize()
{
DPRINT("CDmaChannelInit_MaximumBufferSize: this %p\n", this);
return m_MaximumBufferSize;
}
PHYSICAL_ADDRESS
NTAPI
CDmaChannelInit::PhysicalAddress()
{
DPRINT("CDmaChannelInit_PhysicalAdress: this %p Virtuell %p Physical High %x Low %x%\n", this, m_Buffer, m_Address.HighPart, m_Address.LowPart);
return m_Address;
}
VOID
NTAPI
CDmaChannelInit::SetBufferSize(
IN ULONG BufferSize)
{
DPRINT("CDmaChannelInit_SetBufferSize: this %p\n", this);
m_BufferSize = BufferSize;
}
ULONG
NTAPI
CDmaChannelInit::BufferSize()
{
return m_BufferSize;
}
PVOID
NTAPI
CDmaChannelInit::SystemAddress()
{
DPRINT("CDmaChannelInit_SystemAddress: this %p\n", this);
return m_Buffer;
}
ULONG
NTAPI
CDmaChannelInit::TransferCount()
{
DPRINT("CDmaChannelInit_TransferCount: this %p\n", this);
return m_LastTransferCount;
}
ULONG
NTAPI
CDmaChannelInit::ReadCounter()
{
ULONG Counter;
PC_ASSERT_IRQL(DISPATCH_LEVEL);
Counter = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter);
if (!m_DmaStarted || Counter >= m_LastTransferCount)
Counter = 0;
return Counter;
}
IO_ALLOCATION_ACTION
NTAPI
AdapterControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID MapRegisterBase,
IN PVOID Context)
{
ULONG Length;
CDmaChannelInit * This = (CDmaChannelInit*)Context;
Length = This->m_MapSize;
This->m_MapRegisterBase = MapRegisterBase;
This->m_pAdapter->DmaOperations->MapTransfer(This->m_pAdapter,
This->m_Mdl,
MapRegisterBase,
(PVOID)((ULONG_PTR)This->m_Mdl->StartVa + This->m_Mdl->ByteOffset),
&Length,
This->m_WriteToDevice);
if (Length == This->m_BufferSize)
{
This->m_DmaStarted = TRUE;
}
return KeepObject;
}
NTSTATUS
NTAPI
CDmaChannelInit::Start(
ULONG MapSize,
BOOLEAN WriteToDevice)
{
NTSTATUS Status;
ULONG MapRegisters;
KIRQL OldIrql;
DPRINT("CDmaChannelInit_Start: this %p\n", this);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_DmaStarted)
return STATUS_UNSUCCESSFUL;
if (!m_Mdl)
{
m_Mdl = IoAllocateMdl(m_Buffer, m_MaximumBufferSize, FALSE, FALSE, NULL);
if (!m_Mdl)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool(m_Mdl);
}
m_MapSize = MapSize;
m_WriteToDevice = WriteToDevice;
m_LastTransferCount = MapSize;
//FIXME
// synchronize access
//
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
MapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(m_Buffer, MapSize);
Status = m_pAdapter->DmaOperations->AllocateAdapterChannel(m_pAdapter, m_pDeviceObject, MapRegisters, AdapterControl, (PVOID)this);
KeLowerIrql(OldIrql);
if(!NT_SUCCESS(Status))
m_LastTransferCount = 0;
return Status;
}
NTSTATUS
NTAPI
CDmaChannelInit::Stop()
{
KIRQL OldIrql;
DPRINT("CDmaChannelInit::Stop: this %p\n", this);
PC_ASSERT_IRQL(DISPATCH_LEVEL);
if (!m_DmaStarted)
return STATUS_SUCCESS;
m_pAdapter->DmaOperations->FlushAdapterBuffers(m_pAdapter,
m_Mdl,
m_MapRegisterBase,
(PVOID)((ULONG_PTR)m_Mdl->StartVa + m_Mdl->ByteOffset),
m_MapSize,
m_WriteToDevice);
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
m_pAdapter->DmaOperations->FreeAdapterChannel(m_pAdapter);
KeLowerIrql(OldIrql);
m_DmaStarted = FALSE;
IoFreeMdl(m_Mdl);
m_Mdl = NULL;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CDmaChannelInit::WaitForTC(
ULONG Timeout)
{
ULONG RetryCount;
ULONG BytesRemaining;
ULONG PrevBytesRemaining;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
BytesRemaining = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter);
if (!BytesRemaining)
{
return STATUS_SUCCESS;
}
RetryCount = Timeout / 10;
PrevBytesRemaining = 0xFFFFFFFF;
do
{
BytesRemaining = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter);
if (!BytesRemaining)
break;
if (PrevBytesRemaining == BytesRemaining)
break;
KeStallExecutionProcessor(10);
PrevBytesRemaining = BytesRemaining;
}while(RetryCount-- >= 1);
if (BytesRemaining)
{
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CDmaChannelInit::Init(
IN PDEVICE_DESCRIPTION DeviceDescription,
IN PDEVICE_OBJECT DeviceObject)
{
INTERFACE_TYPE BusType;
NTSTATUS Status;
PDMA_ADAPTER Adapter;
PPCLASS_DEVICE_EXTENSION DeviceExt;
ULONG MapRegisters;
ULONG ResultLength;
// Get bus type
Status = IoGetDeviceProperty(DeviceObject, DevicePropertyLegacyBusType, sizeof(BusType), (PVOID)&BusType, &ResultLength);
if (NT_SUCCESS(Status))
{
DeviceDescription->InterfaceType = BusType;
}
// Fetch device extension
DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
// Acquire dma adapter
Adapter = IoGetDmaAdapter(DeviceExt->PhysicalDeviceObject, DeviceDescription, &MapRegisters);
if (!Adapter)
{
FreeItem(this, TAG_PORTCLASS);
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
// initialize object
m_pAdapter = Adapter;
m_pDeviceObject = DeviceObject;
m_MaximumBufferSize = DeviceDescription->MaximumLength;
m_MaxMapRegisters = MapRegisters;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
PcNewDmaChannel(
OUT PDMACHANNEL* OutDmaChannel,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PDEVICE_DESCRIPTION DeviceDescription,
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
CDmaChannelInit * This;
DPRINT("OutDmaChannel %p OuterUnknown %p PoolType %p DeviceDescription %p DeviceObject %p\n",
OutDmaChannel, OuterUnknown, PoolType, DeviceDescription, DeviceObject);
This = new(PoolType, TAG_PORTCLASS)CDmaChannelInit(OuterUnknown);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
Status = This->QueryInterface(IID_IDmaChannel, (PVOID*)OutDmaChannel);
if (!NT_SUCCESS(Status))
{
delete This;
return Status;
}
Status = This->Init(DeviceDescription, DeviceObject);
if (!NT_SUCCESS(Status))
{
delete This;
return Status;
}
return Status;
}
@@ -1,16 +1,14 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/drm.c
* FILE: drivers/wdm/audio/backpln/portcls/drm.cpp
* PURPOSE: portcls drm functions
* PROGRAMMER: Andrew Greenwood
*/
#include "private.h"
#include "private.hpp"
/*
* @implemented
*/
NTSTATUS
NTAPI
PcAddContentHandlers(
@@ -18,13 +16,10 @@ PcAddContentHandlers(
IN PVOID *paHandlers,
IN ULONG NumHandlers)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmAddContentHandlers(ContentId, paHandlers, NumHandlers);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcCreateContentMixed(
@@ -32,25 +27,19 @@ PcCreateContentMixed(
IN ULONG cContentId,
OUT PULONG pMixedContentId)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmCreateContentMixed(paContentId, cContentId, pMixedContentId);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcDestroyContent(
IN ULONG ContentId)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmDestroyContent(ContentId);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcForwardContentToDeviceObject(
@@ -58,26 +47,20 @@ PcForwardContentToDeviceObject(
IN PVOID Reserved,
IN PCDRMFORWARD DrmForward)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmForwardContentToDeviceObject(ContentId, Reserved, DrmForward);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcForwardContentToFileObject(
IN ULONG ContentId,
IN PFILE_OBJECT FileObject)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmForwardContentToFileObject(ContentId, FileObject);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcForwardContentToInterface(
@@ -88,15 +71,12 @@ PcForwardContentToInterface(
return DrmForwardContentToInterface(ContentId, pUnknown, NumMethods);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcGetContentRights(
IN ULONG ContentId,
OUT PDRMRIGHTS DrmRights)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmGetContentRights(ContentId, DrmRights);
}
@@ -1,181 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/drm_port.c
* PURPOSE: portcls drm port object
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IDrmPort2Vtbl *lpVtbl;
LONG ref;
}IDrmPort2Impl;
ULONG
NTAPI
IDrmPort2_fnAddRef(
IN IDrmPort2* iface)
{
IDrmPort2Impl * This = (IDrmPort2Impl*)iface;
DPRINT("IDrmPort2_AddRef: This %p\n", This);
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IDrmPort2_fnRelease(
IN IDrmPort2* iface)
{
IDrmPort2Impl * This = (IDrmPort2Impl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
NTSTATUS
NTAPI
IDrmPort2_fnQueryInterface(
IN IDrmPort2* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
IDrmPort2Impl * This = (IDrmPort2Impl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IDrmPort) ||
IsEqualGUIDAligned(refiid, &IID_IDrmPort2) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = (PVOID)&This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IDrmPort2_QueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
IDrmPort2_fnCreateContentMixed(
IN IDrmPort2 * iface,
IN PULONG paContentId,
IN ULONG cContentId,
OUT PULONG pMixedContentId)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmCreateContentMixed(paContentId, cContentId, pMixedContentId);
}
NTSTATUS
NTAPI
IDrmPort2_fnDestroyContent(
IN IDrmPort2 * iface,
IN ULONG ContentId)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmDestroyContent(ContentId);
}
NTSTATUS
NTAPI
IDrmPort2_fnForwardContentToFileObject(
IN IDrmPort2 * iface,
IN ULONG ContentId,
IN PFILE_OBJECT FileObject)
{
return DrmForwardContentToFileObject(ContentId, FileObject);
}
NTSTATUS
NTAPI
IDrmPort2_fnForwardContentToInterface(
IN IDrmPort2 * iface,
IN ULONG ContentId,
IN PUNKNOWN pUnknown,
IN ULONG NumMethods)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmForwardContentToInterface(ContentId, pUnknown, NumMethods);
}
NTSTATUS
NTAPI
IDrmPort2_fnGetContentRights(
IN IDrmPort2 * iface,
IN ULONG ContentId,
OUT PDRMRIGHTS DrmRights)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmGetContentRights(ContentId, DrmRights);
}
NTSTATUS
NTAPI
IDrmPort2_fnAddContentHandlers(
IN IDrmPort2 * iface,
IN ULONG ContentId,
IN PVOID * paHandlers,
IN ULONG NumHandlers)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmAddContentHandlers(ContentId, paHandlers, NumHandlers);
}
NTSTATUS
NTAPI
IDrmPort2_fnForwardContentToDeviceObject(
IN IDrmPort2 * iface,
IN ULONG ContentId,
IN PVOID Reserved,
IN PCDRMFORWARD DrmForward)
{
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmForwardContentToDeviceObject(ContentId, Reserved, DrmForward);
}
static IDrmPort2Vtbl vt_IDrmPort2 =
{
/* IUnknown methods */
IDrmPort2_fnQueryInterface,
IDrmPort2_fnAddRef,
IDrmPort2_fnRelease,
IDrmPort2_fnCreateContentMixed,
IDrmPort2_fnDestroyContent,
IDrmPort2_fnForwardContentToFileObject,
IDrmPort2_fnForwardContentToInterface,
IDrmPort2_fnGetContentRights,
IDrmPort2_fnAddContentHandlers,
IDrmPort2_fnForwardContentToDeviceObject
};
NTSTATUS
NewIDrmPort(
OUT PDRMPORT2 *OutPort)
{
IDrmPort2Impl * This = AllocateItem(NonPagedPool, sizeof(IDrmPort2Impl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->lpVtbl = &vt_IDrmPort2;
This->ref = 1;
*OutPort = (PDRMPORT2)&This->lpVtbl;
return STATUS_SUCCESS;
}
@@ -0,0 +1,152 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/drm_port.cpp
* PURPOSE: portcls drm port object
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CDrmPort2 : public IDrmPort2
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IDrmPort2;
CDrmPort2(IUnknown *OuterUnknown){}
virtual ~CDrmPort2(){}
protected:
LONG m_Ref;
};
NTSTATUS
NTAPI
CDrmPort2::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
if (IsEqualGUIDAligned(refiid, IID_IDrmPort) ||
IsEqualGUIDAligned(refiid, IID_IDrmPort2) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IDrmPort2_QueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CDrmPort2::CreateContentMixed(
IN PULONG paContentId,
IN ULONG cContentId,
OUT PULONG pMixedContentId)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmCreateContentMixed(paContentId, cContentId, pMixedContentId);
}
NTSTATUS
NTAPI
CDrmPort2::DestroyContent(
IN ULONG ContentId)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmDestroyContent(ContentId);
}
NTSTATUS
NTAPI
CDrmPort2::ForwardContentToFileObject(
IN ULONG ContentId,
IN PFILE_OBJECT FileObject)
{
return DrmForwardContentToFileObject(ContentId, FileObject);
}
NTSTATUS
NTAPI
CDrmPort2::ForwardContentToInterface(
IN ULONG ContentId,
IN PUNKNOWN pUnknown,
IN ULONG NumMethods)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmForwardContentToInterface(ContentId, pUnknown, NumMethods);
}
NTSTATUS
NTAPI
CDrmPort2::GetContentRights(
IN ULONG ContentId,
OUT PDRMRIGHTS DrmRights)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmGetContentRights(ContentId, DrmRights);
}
NTSTATUS
NTAPI
CDrmPort2::AddContentHandlers(
IN ULONG ContentId,
IN PVOID * paHandlers,
IN ULONG NumHandlers)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmAddContentHandlers(ContentId, paHandlers, NumHandlers);
}
NTSTATUS
NTAPI
CDrmPort2::ForwardContentToDeviceObject(
IN ULONG ContentId,
IN PVOID Reserved,
IN PCDRMFORWARD DrmForward)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return DrmForwardContentToDeviceObject(ContentId, Reserved, DrmForward);
}
NTSTATUS
NewIDrmPort(
OUT PDRMPORT2 *OutPort)
{
CDrmPort2 * This = new(NonPagedPool, TAG_PORTCLASS)CDrmPort2(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->AddRef();
*OutPort = (PDRMPORT2)This;
return STATUS_SUCCESS;
}
@@ -1,503 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/filter_dmus.c
* PURPOSE: portcls wave pci filter
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IPortFilterDMusVtbl *lpVtbl;
LONG ref;
IPortDMus* Port;
IPortPinDMus ** Pins;
SUBDEVICE_DESCRIPTOR * Descriptor;
}IPortFilterDMusImpl;
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterDMus_fnQueryInterface(
IPortFilterDMus* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPort))
{
*Output = This->Port;
This->Port->lpVtbl->AddRef(This->Port);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterDMus_fnAddRef(
IPortFilterDMus* iface)
{
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
return InterlockedIncrement(&This->ref);
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterDMus_fnRelease(
IPortFilterDMus* iface)
{
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
return This->ref;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterDMus_fnNewIrpTarget(
IN IPortFilterDMus* iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortPinDMus * Pin;
PKSPIN_CONNECT ConnectDetails;
IPortFilterDMusImpl * This = (IPortFilterDMusImpl *)iface;
ASSERT(This->Port);
ASSERT(This->Descriptor);
ASSERT(This->Pins);
DPRINT("IPortFilterDMus_fnNewIrpTarget entered\n");
/* let's verify the connection request */
Status = PcValidateConnectRequest(Irp, &This->Descriptor->Factory, &ConnectDetails);
if (!NT_SUCCESS(Status))
{
return STATUS_UNSUCCESSFUL;
}
if (This->Pins[ConnectDetails->PinId] && This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount)
{
/* release existing instance */
ASSERT(0);
}
/* now create the pin */
Status = NewPortPinDMus(&Pin);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* initialize the pin */
Status = Pin->lpVtbl->Init(Pin, This->Port, iface, ConnectDetails, &This->Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId], DeviceObject);
if (!NT_SUCCESS(Status))
{
Pin->lpVtbl->Release(Pin);
return Status;
}
/* release existing pin */
if (This->Pins[ConnectDetails->PinId])
{
This->Pins[ConnectDetails->PinId]->lpVtbl->Release(This->Pins[ConnectDetails->PinId]);
}
/* store pin */
This->Pins[ConnectDetails->PinId] = Pin;
/* store result */
*OutTarget = (IIrpTarget*)Pin;
/* increment current instance count */
This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterDMus_fnDeviceIoControl(
IN IPortFilterDMus* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
ISubdevice *SubDevice = NULL;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
IPortFilterDMusImpl * This = (IPortFilterDMusImpl *)iface;
IoStack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&SubDevice);
ASSERT(Status == STATUS_SUCCESS);
ASSERT(SubDevice != NULL);
Status = SubDevice->lpVtbl->GetDescriptor(SubDevice, &Descriptor);
ASSERT(Status == STATUS_SUCCESS);
ASSERT(Descriptor != NULL);
SubDevice->lpVtbl->Release(SubDevice);
return PcPropertyHandler(Irp, Descriptor);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterDMus_fnRead(
IN IPortFilterDMus* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterDMus_fnWrite(
IN IPortFilterDMus* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterDMus_fnFlush(
IN IPortFilterDMus* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterDMus_fnClose(
IN IPortFilterDMus* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG Index;
IPortFilterDMusImpl * This = (IPortFilterDMusImpl *)iface;
for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
{
if (This->Pins[Index])
{
This->Pins[Index]->lpVtbl->Close(This->Pins[Index], DeviceObject, NULL);
}
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterDMus_fnQuerySecurity(
IN IPortFilterDMus* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterDMus_fnSetSecurity(
IN IPortFilterDMus* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterDMus_fnFastDeviceIoControl(
IN IPortFilterDMus* iface,
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
ULONG Index;
PKSPROPERTY Property;
NTSTATUS Status;
ISubdevice * SubDevice = NULL;
PSUBDEVICE_DESCRIPTOR Descriptor = NULL;
IPortFilterDMusImpl * This = (IPortFilterDMusImpl *)iface;
Property = (PKSPROPERTY)InputBuffer;
if (InputBufferLength < sizeof(KSPROPERTY))
return FALSE;
/* get private interface */
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&SubDevice);
if (!NT_SUCCESS(Status))
return FALSE;
/* get descriptor */
Status = SubDevice->lpVtbl->GetDescriptor(SubDevice, &Descriptor);
if (!NT_SUCCESS(Status))
{
SubDevice->lpVtbl->Release(SubDevice);
return FALSE;
}
for(Index = 0; Index < Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++)
{
if (IsEqualGUIDAligned(&Property->Set, Descriptor->FilterPropertySet.Properties[Index].Set))
{
FastPropertyHandler(FileObject, (PKSPROPERTY)InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, StatusBlock,
1,
&Descriptor->FilterPropertySet.Properties[Index],
Descriptor, SubDevice);
}
}
return TRUE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterDMus_fnFastRead(
IN IPortFilterDMus* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterDMus_fnFastWrite(
IN IPortFilterDMus* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
/*
* @implemented
*/
static
NTSTATUS
NTAPI
IPortFilterDMus_fnInit(
IN IPortFilterDMus* iface,
IN IPortDMus* Port)
{
ISubdevice * ISubDevice;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
This->Port = Port;
/* get our private interface */
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* get the subdevice descriptor */
Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor);
/* release subdevice interface */
ISubDevice->lpVtbl->Release(ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* save descriptor */
This->Descriptor = Descriptor;
/* allocate pin array */
This->Pins = AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinDMus*), TAG_PORTCLASS);
if (!This->Pins)
return STATUS_UNSUCCESSFUL;
/* increment reference count */
Port->lpVtbl->AddRef(Port);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
IPortFilterDMus_fnFreePin(
IN IPortFilterDMus* iface,
IN struct IPortPinDMus* Pin)
{
ULONG Index;
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
{
if (This->Pins[Index] == Pin)
{
This->Pins[Index]->lpVtbl->Release(This->Pins[Index]);
This->Pins[Index] = NULL;
return STATUS_SUCCESS;
}
}
return STATUS_UNSUCCESSFUL;
}
static
VOID
NTAPI
IPortFilterDMus_fnNotifyPins(
IN IPortFilterDMus* iface)
{
ULONG Index;
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
DPRINT("Notifying %u pins\n", This->Descriptor->Factory.PinDescriptorCount);
for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
{
This->Pins[Index]->lpVtbl->Notify(This->Pins[Index]);
}
}
static IPortFilterDMusVtbl vt_IPortFilterDMus =
{
IPortFilterDMus_fnQueryInterface,
IPortFilterDMus_fnAddRef,
IPortFilterDMus_fnRelease,
IPortFilterDMus_fnNewIrpTarget,
IPortFilterDMus_fnDeviceIoControl,
IPortFilterDMus_fnRead,
IPortFilterDMus_fnWrite,
IPortFilterDMus_fnFlush,
IPortFilterDMus_fnClose,
IPortFilterDMus_fnQuerySecurity,
IPortFilterDMus_fnSetSecurity,
IPortFilterDMus_fnFastDeviceIoControl,
IPortFilterDMus_fnFastRead,
IPortFilterDMus_fnFastWrite,
IPortFilterDMus_fnInit,
IPortFilterDMus_fnFreePin,
IPortFilterDMus_fnNotifyPins
};
NTSTATUS
NewPortFilterDMus(
OUT PPORTFILTERDMUS * OutFilter)
{
IPortFilterDMusImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IPortFilterDMusImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize IPortFilterDMus */
This->ref = 1;
This->lpVtbl = &vt_IPortFilterDMus;
/* return result */
*OutFilter = (IPortFilterDMus*)&This->lpVtbl;
return STATUS_SUCCESS;
}
@@ -0,0 +1,332 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/filter_dmus.cpp
* PURPOSE: portcls wave pci filter
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortFilterDMus : public IPortFilterDMus
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortFilterDMus;
CPortFilterDMus(IUnknown *OuterUnknown){}
virtual ~CPortFilterDMus(){}
protected:
IPortDMus* m_Port;
IPortPinDMus ** m_Pins;
SUBDEVICE_DESCRIPTOR * m_Descriptor;
LONG m_Ref;
};
NTSTATUS
NTAPI
CPortFilterDMus::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPort))
{
*Output = PUNKNOWN(m_Port);
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortFilterDMus::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortPinDMus * Pin;
PKSPIN_CONNECT ConnectDetails;
PC_ASSERT(m_Port);
PC_ASSERT(m_Descriptor);
PC_ASSERT(m_Pins);
DPRINT("CPortFilterDMus::NewIrpTarget entered\n");
// let's verify the connection request
Status = PcValidateConnectRequest(Irp, &m_Descriptor->Factory, &ConnectDetails);
if (!NT_SUCCESS(Status))
{
return STATUS_UNSUCCESSFUL;
}
if (m_Pins[ConnectDetails->PinId] && m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount)
{
// release existing instance
PC_ASSERT(0);
}
// now create the pin
Status = NewPortPinDMus(&Pin);
if (!NT_SUCCESS(Status))
{
return Status;
}
// initialize the pin
Status = Pin->Init(m_Port, this, ConnectDetails, &m_Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId], DeviceObject);
if (!NT_SUCCESS(Status))
{
Pin->Release();
return Status;
}
// store pin
m_Pins[ConnectDetails->PinId] = Pin;
// store result
*OutTarget = (IIrpTarget*)Pin;
// increment current instance count
m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
return Status;
}
NTSTATUS
NTAPI
CPortFilterDMus::DeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return PcPropertyHandler(Irp, m_Descriptor);
}
NTSTATUS
NTAPI
CPortFilterDMus::Read(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterDMus::Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterDMus::Flush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterDMus::Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortFilterDMus::QuerySecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterDMus::SetSecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
BOOLEAN
NTAPI
CPortFilterDMus::FastDeviceIoControl(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortFilterDMus::FastRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
BOOLEAN
NTAPI
CPortFilterDMus::FastWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
NTSTATUS
NTAPI
CPortFilterDMus::Init(
IN IPortDMus* Port)
{
ISubdevice * ISubDevice;
NTSTATUS Status;
m_Port = Port;
// get our private interface
Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
// get the subdevice descriptor
Status = ISubDevice->GetDescriptor(&m_Descriptor);
// release subdevice interface
ISubDevice->Release();
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
// allocate pin array
m_Pins = (IPortPinDMus**)AllocateItem(NonPagedPool, m_Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinDMus*), TAG_PORTCLASS);
if (!m_Pins)
return STATUS_UNSUCCESSFUL;
// increment reference count
Port->AddRef();
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortFilterDMus::FreePin(
IN struct IPortPinDMus* Pin)
{
ULONG Index;
for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
{
if (m_Pins[Index] == Pin)
{
m_Pins[Index]->Release();
m_Pins[Index] = NULL;
return STATUS_SUCCESS;
}
}
return STATUS_UNSUCCESSFUL;
}
VOID
NTAPI
CPortFilterDMus::NotifyPins()
{
ULONG Index;
DPRINT("Notifying %u pins\n", m_Descriptor->Factory.PinDescriptorCount);
for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
{
m_Pins[Index]->Notify();
}
}
NTSTATUS
NewPortFilterDMus(
OUT PPORTFILTERDMUS * OutFilter)
{
CPortFilterDMus * This;
This = new(NonPagedPool, TAG_PORTCLASS) CPortFilterDMus(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->AddRef();
// return result
*OutFilter = (CPortFilterDMus*)This;
return STATUS_SUCCESS;
}
@@ -1,372 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/filter_topology.c
* PURPOSE: portcls topology filter
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IPortFilterTopologyVtbl *lpVtbl;
LONG ref;
IPortTopology* Port;
SUBDEVICE_DESCRIPTOR * Descriptor;
ISubdevice *SubDevice;
}IPortFilterTopologyImpl;
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnQueryInterface(
IPortFilterTopology* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPort))
{
*Output = This->Port;
This->Port->lpVtbl->AddRef(This->Port);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterTopology_fnAddRef(
IPortFilterTopology* iface)
{
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl*)iface;
return InterlockedIncrement(&This->ref);
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterTopology_fnRelease(
IPortFilterTopology* iface)
{
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
return This->ref;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnNewIrpTarget(
IN IPortFilterTopology* iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
DPRINT("IPortFilterTopology_fnNewIrpTarget entered\n");
return STATUS_NOT_SUPPORTED;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnDeviceIoControl(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl *)iface;
IoStack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
return PcPropertyHandler(Irp, This->Descriptor);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnRead(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnWrite(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnFlush(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnClose(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
NTSTATUS Status = STATUS_SUCCESS;
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl *)iface;
/* FIXME handle DirectSound */
if (This->ref == 1)
{
/* release reference to port */
This->SubDevice->lpVtbl->Release(This->SubDevice);
/* time to shutdown the audio system */
Status = This->SubDevice->lpVtbl->ReleaseChildren(This->SubDevice);
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnQuerySecurity(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnSetSecurity(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterTopology_fnFastDeviceIoControl(
IN IPortFilterTopology* iface,
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
ULONG Index;
PKSPROPERTY Property;
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl*)iface;
Property = (PKSPROPERTY)InputBuffer;
if (InputBufferLength < sizeof(KSPROPERTY))
return FALSE;
for(Index = 0; Index < This->Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++)
{
if (IsEqualGUIDAligned(&Property->Set, This->Descriptor->FilterPropertySet.Properties[Index].Set))
{
FastPropertyHandler(FileObject, (PKSPROPERTY)InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, StatusBlock,
1,
&This->Descriptor->FilterPropertySet.Properties[Index],
This->Descriptor, This->SubDevice);
}
}
return TRUE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterTopology_fnFastRead(
IN IPortFilterTopology* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterTopology_fnFastWrite(
IN IPortFilterTopology* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
/*
* @implemented
*/
static
NTSTATUS
NTAPI
IPortFilterTopology_fnInit(
IN IPortFilterTopology* iface,
IN IPortTopology* Port)
{
ISubdevice * ISubDevice;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl*)iface;
/* get our private interface */
Status = Port->lpVtbl->QueryInterface(Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* get the subdevice descriptor */
Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor);
/* store subdevice interface */
This->SubDevice = ISubDevice;
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* save descriptor */
This->Descriptor = Descriptor;
/* store port object */
This->Port = Port;
return STATUS_SUCCESS;
}
static IPortFilterTopologyVtbl vt_IPortFilterTopology =
{
IPortFilterTopology_fnQueryInterface,
IPortFilterTopology_fnAddRef,
IPortFilterTopology_fnRelease,
IPortFilterTopology_fnNewIrpTarget,
IPortFilterTopology_fnDeviceIoControl,
IPortFilterTopology_fnRead,
IPortFilterTopology_fnWrite,
IPortFilterTopology_fnFlush,
IPortFilterTopology_fnClose,
IPortFilterTopology_fnQuerySecurity,
IPortFilterTopology_fnSetSecurity,
IPortFilterTopology_fnFastDeviceIoControl,
IPortFilterTopology_fnFastRead,
IPortFilterTopology_fnFastWrite,
IPortFilterTopology_fnInit
};
NTSTATUS
NewPortFilterTopology(
OUT IPortFilterTopology ** OutFilter)
{
IPortFilterTopologyImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IPortFilterTopologyImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize IPortFilterTopology */
This->ref = 1;
This->lpVtbl = &vt_IPortFilterTopology;
/* return result */
*OutFilter = (IPortFilterTopology*)&This->lpVtbl;
return STATUS_SUCCESS;
}
@@ -0,0 +1,268 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/filter_topology.c
* PURPOSE: portcls topology filter
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortFilterTopology : public IPortFilterTopology
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortFilterTopology;
CPortFilterTopology(IUnknown *OuterUnknown){}
virtual ~CPortFilterTopology(){}
protected:
IPortTopology * m_Port;
SUBDEVICE_DESCRIPTOR * m_Descriptor;
ISubdevice * m_SubDevice;
LONG m_Ref;
};
NTSTATUS
NTAPI
CPortFilterTopology::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPort))
{
*Output = PVOID(PUNKNOWN(m_Port));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortFilterTopology::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
DPRINT("CPortFilterTopology::NewIrpTarget entered\n");
return STATUS_NOT_SUPPORTED;
}
NTSTATUS
NTAPI
CPortFilterTopology::DeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
IoStack = IoGetCurrentIrpStackLocation(Irp);
PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
return PcPropertyHandler(Irp, m_Descriptor);
}
NTSTATUS
NTAPI
CPortFilterTopology::Read(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterTopology::Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterTopology::Flush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterTopology::Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
NTSTATUS Status = STATUS_SUCCESS;
// FIXME handle DirectSound
#if 0
//FIXME
if (m_ref == 1)
{
// release reference to port
This->SubDevice->lpVtbl->Release(This->SubDevice);
// time to shutdown the audio system
Status = This->SubDevice->lpVtbl->ReleaseChildren(This->SubDevice);
}
#endif
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortFilterTopology::QuerySecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterTopology::SetSecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
BOOLEAN
NTAPI
CPortFilterTopology::FastDeviceIoControl(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortFilterTopology::FastRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortFilterTopology::FastWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
NTSTATUS
NTAPI
CPortFilterTopology::Init(
IN IPortTopology* Port)
{
ISubdevice * ISubDevice;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
// get our private interface
Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
// get the subdevice descriptor
Status = ISubDevice->GetDescriptor(&Descriptor);
// store subdevice interface
m_SubDevice = ISubDevice;
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
// save descriptor
m_Descriptor = Descriptor;
// store port object
m_Port = Port;
return STATUS_SUCCESS;
}
NTSTATUS
NewPortFilterTopology(
OUT IPortFilterTopology ** OutFilter)
{
CPortFilterTopology * This;
This = new(NonPagedPool, TAG_PORTCLASS)CPortFilterTopology(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->AddRef();
// return result
*OutFilter = (CPortFilterTopology*)This;
return STATUS_SUCCESS;
}
@@ -1,457 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/filter_wavecyclic.c
* PURPOSE: portcls wave cyclic filter
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IPortFilterWaveCyclicVtbl *lpVtbl;
LONG ref;
IPortWaveCyclic* Port;
IPortPinWaveCyclic ** Pins;
SUBDEVICE_DESCRIPTOR * Descriptor;
ISubdevice * SubDevice;
}IPortFilterWaveCyclicImpl;
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveCyclic_fnQueryInterface(
IPortFilterWaveCyclic* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPort))
{
*Output = This->Port;
This->Port->lpVtbl->AddRef(This->Port);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterWaveCyclic_fnAddRef(
IPortFilterWaveCyclic* iface)
{
IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl*)iface;
return InterlockedIncrement(&This->ref);
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterWaveCyclic_fnRelease(
IPortFilterWaveCyclic* iface)
{
IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
return This->ref;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveCyclic_fnNewIrpTarget(
IN IPortFilterWaveCyclic* iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortPinWaveCyclic * Pin;
PKSPIN_CONNECT ConnectDetails;
IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl *)iface;
ASSERT(This->Port);
ASSERT(This->Descriptor);
ASSERT(This->Pins);
DPRINT("IPortFilterWaveCyclic_fnNewIrpTarget entered\n");
/* let's verify the connection request */
Status = PcValidateConnectRequest(Irp, &This->Descriptor->Factory, &ConnectDetails);
if (!NT_SUCCESS(Status))
{
return STATUS_UNSUCCESSFUL;
}
if (This->Pins[ConnectDetails->PinId] &&
(This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount == This->Descriptor->Factory.Instances[ConnectDetails->PinId].MaxFilterInstanceCount))
{
/* release existing instance */
return STATUS_UNSUCCESSFUL;
}
/* now create the pin */
Status = NewPortPinWaveCyclic(&Pin);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* initialize the pin */
Status = Pin->lpVtbl->Init(Pin, This->Port, iface, ConnectDetails, &This->Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId]);
if (!NT_SUCCESS(Status))
{
Pin->lpVtbl->Release(Pin);
return Status;
}
/* store pin */
This->Pins[ConnectDetails->PinId] = Pin;
/* store result */
*OutTarget = (IIrpTarget*)Pin;
/* increment current instance count */
This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveCyclic_fnDeviceIoControl(
IN IPortFilterWaveCyclic* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl *)iface;
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
{
DPRINT1("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
return PcPropertyHandler(Irp, This->Descriptor);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveCyclic_fnRead(
IN IPortFilterWaveCyclic* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveCyclic_fnWrite(
IN IPortFilterWaveCyclic* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveCyclic_fnFlush(
IN IPortFilterWaveCyclic* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveCyclic_fnClose(
IN IPortFilterWaveCyclic* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG Index;
NTSTATUS Status = STATUS_SUCCESS;
IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl *)iface;
DPRINT("IPortFilterWaveCyclic_fnClose ref %u\n", This->ref);
if (This->ref == 1)
{
for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
{
/* all pins should have been closed by now */
ASSERT(This->Pins[Index] == NULL);
}
/* release reference to port */
This->SubDevice->lpVtbl->Release(This->SubDevice);
/* time to shutdown the audio system */
Status = This->SubDevice->lpVtbl->ReleaseChildren(This->SubDevice);
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveCyclic_fnQuerySecurity(
IN IPortFilterWaveCyclic* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveCyclic_fnSetSecurity(
IN IPortFilterWaveCyclic* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterWaveCyclic_fnFastDeviceIoControl(
IN IPortFilterWaveCyclic* iface,
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterWaveCyclic_fnFastRead(
IN IPortFilterWaveCyclic* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterWaveCyclic_fnFastWrite(
IN IPortFilterWaveCyclic* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
/*
* @implemented
*/
static
NTSTATUS
NTAPI
IPortFilterWaveCyclic_fnInit(
IN IPortFilterWaveCyclic* iface,
IN IPortWaveCyclic* Port)
{
ISubdevice * ISubDevice;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl*)iface;
/* get our private interface */
Status = Port->lpVtbl->QueryInterface(Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* get the subdevice descriptor */
Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor);
/* store subdevice interface */
This->SubDevice = ISubDevice;
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* save descriptor */
This->Descriptor = Descriptor;
/* allocate pin array */
This->Pins = AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinWaveCyclic*), TAG_PORTCLASS);
if (!This->Pins)
return STATUS_UNSUCCESSFUL;
/* store port driver */
This->Port = Port;
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
IPortFilterWaveCyclic_fnFreePin(
IN IPortFilterWaveCyclic* iface,
IN struct IPortPinWaveCyclic* Pin)
{
ULONG Index;
IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl*)iface;
for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
{
if (This->Pins[Index] == Pin)
{
This->Descriptor->Factory.Instances[Index].CurrentPinInstanceCount--;
This->Pins[Index]->lpVtbl->Release(This->Pins[Index]);
This->Pins[Index] = NULL;
return STATUS_SUCCESS;
}
}
return STATUS_UNSUCCESSFUL;
}
static IPortFilterWaveCyclicVtbl vt_IPortFilterWaveCyclic =
{
IPortFilterWaveCyclic_fnQueryInterface,
IPortFilterWaveCyclic_fnAddRef,
IPortFilterWaveCyclic_fnRelease,
IPortFilterWaveCyclic_fnNewIrpTarget,
IPortFilterWaveCyclic_fnDeviceIoControl,
IPortFilterWaveCyclic_fnRead,
IPortFilterWaveCyclic_fnWrite,
IPortFilterWaveCyclic_fnFlush,
IPortFilterWaveCyclic_fnClose,
IPortFilterWaveCyclic_fnQuerySecurity,
IPortFilterWaveCyclic_fnSetSecurity,
IPortFilterWaveCyclic_fnFastDeviceIoControl,
IPortFilterWaveCyclic_fnFastRead,
IPortFilterWaveCyclic_fnFastWrite,
IPortFilterWaveCyclic_fnInit,
IPortFilterWaveCyclic_fnFreePin
};
NTSTATUS
NewPortFilterWaveCyclic(
OUT IPortFilterWaveCyclic ** OutFilter)
{
IPortFilterWaveCyclicImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IPortFilterWaveCyclicImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize IPortFilterWaveCyclic */
This->ref = 1;
This->lpVtbl = &vt_IPortFilterWaveCyclic;
/* return result */
*OutFilter = (IPortFilterWaveCyclic*)&This->lpVtbl;
return STATUS_SUCCESS;
}
@@ -0,0 +1,361 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/filter_wavecyclic.c
* PURPOSE: portcls wave cyclic filter
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortFilterWaveCyclic : public IPortFilterWaveCyclic
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortFilterWaveCyclic;
CPortFilterWaveCyclic(IUnknown *OuterUnknown){}
virtual ~CPortFilterWaveCyclic(){}
protected:
IPortWaveCyclic* m_Port;
IPortPinWaveCyclic ** m_Pins;
SUBDEVICE_DESCRIPTOR * m_Descriptor;
ISubdevice * m_SubDevice;
LONG m_Ref;
};
NTSTATUS
NTAPI
CPortFilterWaveCyclic::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPort))
{
*Output = PUNKNOWN(m_Port);
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortFilterWaveCyclic::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortPinWaveCyclic * Pin;
PKSPIN_CONNECT ConnectDetails;
#if 0
ASSERT(m_Port);
ASSERT(m_Descriptor);
ASSERT(m_Pins);
#endif
DPRINT("CPortFilterWaveCyclic::NewIrpTarget entered\n");
// let's verify the connection request
Status = PcValidateConnectRequest(Irp, &m_Descriptor->Factory, &ConnectDetails);
if (!NT_SUCCESS(Status))
{
return STATUS_UNSUCCESSFUL;
}
if (m_Pins[ConnectDetails->PinId] &&
(m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount == m_Descriptor->Factory.Instances[ConnectDetails->PinId].MaxFilterInstanceCount))
{
// release existing instance
return STATUS_UNSUCCESSFUL;
}
// now create the pin
Status = NewPortPinWaveCyclic(&Pin);
if (!NT_SUCCESS(Status))
{
return Status;
}
// initialize the pin
Status = Pin->Init(m_Port, this, ConnectDetails, &m_Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId]);
if (!NT_SUCCESS(Status))
{
Pin->Release();
return Status;
}
// store pin
m_Pins[ConnectDetails->PinId] = Pin;
// store result
*OutTarget = (IIrpTarget*)Pin;
// increment current instance count
m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
return Status;
}
NTSTATUS
NTAPI
CPortFilterWaveCyclic::DeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
{
DPRINT1("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
return PcPropertyHandler(Irp, m_Descriptor);
}
NTSTATUS
NTAPI
CPortFilterWaveCyclic::Read(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWaveCyclic::Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWaveCyclic::Flush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWaveCyclic::Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
//ULONG Index;
NTSTATUS Status = STATUS_SUCCESS;
#if 0
if (m_ref == 1)
{
for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
{
// all pins should have been closed by now
ASSERT(m_Pins[Index] == NULL);
}
// release reference to port
m_SubDevice->Release(m_SubDevice);
// time to shutdown the audio system
Status = m_SubDevice->ReleaseChildren(m_SubDevice);
}
#endif
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortFilterWaveCyclic::QuerySecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWaveCyclic::SetSecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
BOOLEAN
NTAPI
CPortFilterWaveCyclic::FastDeviceIoControl(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
BOOLEAN
NTAPI
CPortFilterWaveCyclic::FastRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
BOOLEAN
NTAPI
CPortFilterWaveCyclic::FastWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
NTSTATUS
NTAPI
CPortFilterWaveCyclic::Init(
IN IPortWaveCyclic* Port)
{
ISubdevice * ISubDevice;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
// get our private interface
Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
// get the subdevice descriptor
Status = ISubDevice->GetDescriptor(&Descriptor);
// store subdevice interface
m_SubDevice = ISubDevice;
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
// save descriptor
m_Descriptor = Descriptor;
// allocate pin array
m_Pins = (IPortPinWaveCyclic**)AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinWaveCyclic*), TAG_PORTCLASS);
if (!m_Pins)
return STATUS_UNSUCCESSFUL;
// store port driver
m_Port = Port;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortFilterWaveCyclic::FreePin(
IN struct IPortPinWaveCyclic* Pin)
{
ULONG Index;
for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
{
if (m_Pins[Index] == Pin)
{
m_Descriptor->Factory.Instances[Index].CurrentPinInstanceCount--;
m_Pins[Index]->Release();
m_Pins[Index] = NULL;
return STATUS_SUCCESS;
}
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NewPortFilterWaveCyclic(
OUT IPortFilterWaveCyclic ** OutFilter)
{
CPortFilterWaveCyclic * This;
This = new(NonPagedPool, TAG_PORTCLASS)CPortFilterWaveCyclic(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->AddRef();
// return result
*OutFilter = (IPortFilterWaveCyclic*)This;
return STATUS_SUCCESS;
}
@@ -1,458 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/filter_wavepci.c
* PURPOSE: portcls wave pci filter
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IPortFilterWavePciVtbl *lpVtbl;
LONG ref;
IPortWavePci* Port;
IPortPinWavePci ** Pins;
SUBDEVICE_DESCRIPTOR * Descriptor;
}IPortFilterWavePciImpl;
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWavePci_fnQueryInterface(
IPortFilterWavePci* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortFilterWavePciImpl * This = (IPortFilterWavePciImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPort))
{
*Output = This->Port;
This->Port->lpVtbl->AddRef(This->Port);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterWavePci_fnAddRef(
IPortFilterWavePci* iface)
{
IPortFilterWavePciImpl * This = (IPortFilterWavePciImpl*)iface;
return InterlockedIncrement(&This->ref);
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterWavePci_fnRelease(
IPortFilterWavePci* iface)
{
IPortFilterWavePciImpl * This = (IPortFilterWavePciImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
return This->ref;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWavePci_fnNewIrpTarget(
IN IPortFilterWavePci* iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortPinWavePci * Pin;
PKSPIN_CONNECT ConnectDetails;
IPortFilterWavePciImpl * This = (IPortFilterWavePciImpl *)iface;
ASSERT(This->Port);
ASSERT(This->Descriptor);
ASSERT(This->Pins);
DPRINT("IPortFilterWavePci_fnNewIrpTarget entered\n");
/* let's verify the connection request */
Status = PcValidateConnectRequest(Irp, &This->Descriptor->Factory, &ConnectDetails);
if (!NT_SUCCESS(Status))
{
return STATUS_UNSUCCESSFUL;
}
if (This->Pins[ConnectDetails->PinId] && This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount)
{
/* release existing instance */
ASSERT(0);
This->Pins[ConnectDetails->PinId]->lpVtbl->Close(This->Pins[ConnectDetails->PinId], DeviceObject, NULL);
}
/* now create the pin */
Status = NewPortPinWavePci(&Pin);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* initialize the pin */
Status = Pin->lpVtbl->Init(Pin, This->Port, iface, ConnectDetails, &This->Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId], GetDeviceObjectFromPortWavePci(This->Port));
if (!NT_SUCCESS(Status))
{
Pin->lpVtbl->Release(Pin);
return Status;
}
/* store pin */
This->Pins[ConnectDetails->PinId] = Pin;
/* store result */
*OutTarget = (IIrpTarget*)Pin;
/* increment current instance count */
This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWavePci_fnDeviceIoControl(
IN IPortFilterWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
ISubdevice *SubDevice = NULL;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
IPortFilterWavePciImpl * This = (IPortFilterWavePciImpl *)iface;
IoStack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&SubDevice);
ASSERT(Status == STATUS_SUCCESS);
ASSERT(SubDevice != NULL);
Status = SubDevice->lpVtbl->GetDescriptor(SubDevice, &Descriptor);
ASSERT(Status == STATUS_SUCCESS);
ASSERT(Descriptor != NULL);
SubDevice->lpVtbl->Release(SubDevice);
return PcPropertyHandler(Irp, Descriptor);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWavePci_fnRead(
IN IPortFilterWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWavePci_fnWrite(
IN IPortFilterWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWavePci_fnFlush(
IN IPortFilterWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWavePci_fnClose(
IN IPortFilterWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG Index;
IPortFilterWavePciImpl * This = (IPortFilterWavePciImpl *)iface;
for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
{
if (This->Pins[Index])
{
This->Pins[Index]->lpVtbl->Close(This->Pins[Index], DeviceObject, NULL);
}
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWavePci_fnQuerySecurity(
IN IPortFilterWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWavePci_fnSetSecurity(
IN IPortFilterWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterWavePci_fnFastDeviceIoControl(
IN IPortFilterWavePci* iface,
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
ULONG Index;
PKSPROPERTY Property;
NTSTATUS Status;
ISubdevice * SubDevice = NULL;
PSUBDEVICE_DESCRIPTOR Descriptor = NULL;
IPortFilterWavePciImpl * This = (IPortFilterWavePciImpl *)iface;
Property = (PKSPROPERTY)InputBuffer;
if (InputBufferLength < sizeof(KSPROPERTY))
return FALSE;
/* get private interface */
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&SubDevice);
if (!NT_SUCCESS(Status))
return FALSE;
/* get descriptor */
Status = SubDevice->lpVtbl->GetDescriptor(SubDevice, &Descriptor);
if (!NT_SUCCESS(Status))
{
SubDevice->lpVtbl->Release(SubDevice);
return FALSE;
}
for(Index = 0; Index < Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++)
{
if (IsEqualGUIDAligned(&Property->Set, Descriptor->FilterPropertySet.Properties[Index].Set))
{
FastPropertyHandler(FileObject, (PKSPROPERTY)InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, StatusBlock,
1,
&Descriptor->FilterPropertySet.Properties[Index],
Descriptor, SubDevice);
}
}
return TRUE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterWavePci_fnFastRead(
IN IPortFilterWavePci* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterWavePci_fnFastWrite(
IN IPortFilterWavePci* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
/*
* @implemented
*/
static
NTSTATUS
NTAPI
IPortFilterWavePci_fnInit(
IN IPortFilterWavePci* iface,
IN IPortWavePci* Port)
{
ISubdevice * ISubDevice;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
IPortFilterWavePciImpl * This = (IPortFilterWavePciImpl*)iface;
This->Port = Port;
/* get our private interface */
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* get the subdevice descriptor */
Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor);
/* release subdevice interface */
ISubDevice->lpVtbl->Release(ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* save descriptor */
This->Descriptor = Descriptor;
/* allocate pin array */
This->Pins = AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinWavePci*), TAG_PORTCLASS);
if (!This->Pins)
return STATUS_UNSUCCESSFUL;
/* increment reference count */
Port->lpVtbl->AddRef(Port);
return STATUS_SUCCESS;
}
static IPortFilterWavePciVtbl vt_IPortFilterWavePci =
{
IPortFilterWavePci_fnQueryInterface,
IPortFilterWavePci_fnAddRef,
IPortFilterWavePci_fnRelease,
IPortFilterWavePci_fnNewIrpTarget,
IPortFilterWavePci_fnDeviceIoControl,
IPortFilterWavePci_fnRead,
IPortFilterWavePci_fnWrite,
IPortFilterWavePci_fnFlush,
IPortFilterWavePci_fnClose,
IPortFilterWavePci_fnQuerySecurity,
IPortFilterWavePci_fnSetSecurity,
IPortFilterWavePci_fnFastDeviceIoControl,
IPortFilterWavePci_fnFastRead,
IPortFilterWavePci_fnFastWrite,
IPortFilterWavePci_fnInit
};
NTSTATUS
NewPortFilterWavePci(
OUT IPortFilterWavePci ** OutFilter)
{
IPortFilterWavePciImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IPortFilterWavePciImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize IPortFilterWavePci */
This->ref = 1;
This->lpVtbl = &vt_IPortFilterWavePci;
/* return result */
*OutFilter = (IPortFilterWavePci*)&This->lpVtbl;
return STATUS_SUCCESS;
}
@@ -0,0 +1,302 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/filter_wavepci.cpp
* PURPOSE: portcls wave pci filter
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortFilterWavePci : public IPortFilterWavePci
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortFilterPci;
CPortFilterWavePci(IUnknown *OuterUnknown){}
virtual ~CPortFilterWavePci(){}
protected:
IPortWavePci* m_Port;
IPortPinWavePci ** m_Pins;
SUBDEVICE_DESCRIPTOR * m_Descriptor;
LONG m_Ref;
};
NTSTATUS
NTAPI
CPortFilterWavePci::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPort))
{
*Output = PUNKNOWN(m_Port);
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortFilterWavePci::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortPinWavePci * Pin;
PKSPIN_CONNECT ConnectDetails;
#if 0
ASSERT(m_Port);
ASSERT(m_Descriptor);
ASSERT(m_Pins);
#endif
DPRINT("CPortFilterWavePci::NewIrpTarget entered\n");
// let's verify the connection request
Status = PcValidateConnectRequest(Irp, &m_Descriptor->Factory, &ConnectDetails);
if (!NT_SUCCESS(Status))
{
return STATUS_UNSUCCESSFUL;
}
if (m_Pins[ConnectDetails->PinId] && m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount)
{
// release existing instance
PC_ASSERT(0);
m_Pins[ConnectDetails->PinId]->Close(DeviceObject, NULL);
}
// now create the pin
Status = NewPortPinWavePci(&Pin);
if (!NT_SUCCESS(Status))
{
return Status;
}
// initialize the pin
Status = Pin->Init(m_Port, this, ConnectDetails, &m_Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId], GetDeviceObjectFromPortWavePci(m_Port));
if (!NT_SUCCESS(Status))
{
Pin->Release();
return Status;
}
// store pin
m_Pins[ConnectDetails->PinId] = Pin;
// store result
*OutTarget = (IIrpTarget*)Pin;
// increment current instance count
m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
return Status;
}
NTSTATUS
NTAPI
CPortFilterWavePci::DeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return PcPropertyHandler(Irp, m_Descriptor);
}
NTSTATUS
NTAPI
CPortFilterWavePci::Read(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWavePci::Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWavePci::Flush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWavePci::Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortFilterWavePci::QuerySecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWavePci::SetSecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
BOOLEAN
NTAPI
CPortFilterWavePci::FastDeviceIoControl(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortFilterWavePci::FastRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortFilterWavePci::FastWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
NTSTATUS
NTAPI
CPortFilterWavePci::Init(
IN IPortWavePci* Port)
{
ISubdevice * ISubDevice;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
m_Port = Port;
// get our private interface
Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
// get the subdevice descriptor
Status = ISubDevice->GetDescriptor(&Descriptor);
// release subdevice interface
ISubDevice->Release();
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
// save descriptor
m_Descriptor = Descriptor;
// allocate pin array
m_Pins = (IPortPinWavePci**)AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinWavePci*), TAG_PORTCLASS);
if (!m_Pins)
return STATUS_UNSUCCESSFUL;
// increment reference count
Port->AddRef();
return STATUS_SUCCESS;
}
NTSTATUS
NewPortFilterWavePci(
OUT IPortFilterWavePci ** OutFilter)
{
CPortFilterWavePci * This;
This = new(NonPagedPool, TAG_PORTCLASS)CPortFilterWavePci(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->AddRef();
// return result
*OutFilter = (IPortFilterWavePci*)This;
return STATUS_SUCCESS;
}
@@ -1,462 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/filter_wavert.c
* PURPOSE: portcls wave RT filter
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IPortFilterWaveRTVtbl *lpVtbl;
LONG ref;
IPortWaveRT* Port;
IPortPinWaveRT ** Pins;
SUBDEVICE_DESCRIPTOR * Descriptor;
}IPortFilterWaveRTImpl;
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveRT_fnQueryInterface(
IPortFilterWaveRT* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPort))
{
*Output = This->Port;
This->Port->lpVtbl->AddRef(This->Port);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterWaveRT_fnAddRef(
IPortFilterWaveRT* iface)
{
IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl*)iface;
return InterlockedIncrement(&This->ref);
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterWaveRT_fnRelease(
IPortFilterWaveRT* iface)
{
IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
return This->ref;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveRT_fnNewIrpTarget(
IN IPortFilterWaveRT* iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortPinWaveRT * Pin;
PKSPIN_CONNECT ConnectDetails;
IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl *)iface;
ASSERT(This->Port);
ASSERT(This->Descriptor);
ASSERT(This->Pins);
DPRINT("IPortFilterWaveRT_fnNewIrpTarget entered\n");
/* let's verify the connection request */
Status = PcValidateConnectRequest(Irp, &This->Descriptor->Factory, &ConnectDetails);
if (!NT_SUCCESS(Status))
{
return STATUS_UNSUCCESSFUL;
}
if (This->Pins[ConnectDetails->PinId] && This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount)
{
/* release existing instance */
ASSERT(0);
This->Pins[ConnectDetails->PinId]->lpVtbl->Close(This->Pins[ConnectDetails->PinId], DeviceObject, NULL);
}
/* now create the pin */
Status = NewPortPinWaveRT(&Pin);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* initialize the pin */
Status = Pin->lpVtbl->Init(Pin, This->Port, iface, ConnectDetails, &This->Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId], GetDeviceObjectFromPortWaveRT(This->Port));
if (!NT_SUCCESS(Status))
{
Pin->lpVtbl->Release(Pin);
return Status;
}
/* release existing pin */
if (This->Pins[ConnectDetails->PinId])
{
This->Pins[ConnectDetails->PinId]->lpVtbl->Release(This->Pins[ConnectDetails->PinId]);
}
/* store pin */
This->Pins[ConnectDetails->PinId] = Pin;
/* store result */
*OutTarget = (IIrpTarget*)Pin;
/* increment current instance count */
This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveRT_fnDeviceIoControl(
IN IPortFilterWaveRT* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
ISubdevice *SubDevice = NULL;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl *)iface;
IoStack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&SubDevice);
ASSERT(Status == STATUS_SUCCESS);
ASSERT(SubDevice != NULL);
Status = SubDevice->lpVtbl->GetDescriptor(SubDevice, &Descriptor);
ASSERT(Status == STATUS_SUCCESS);
ASSERT(Descriptor != NULL);
SubDevice->lpVtbl->Release(SubDevice);
return PcPropertyHandler(Irp, Descriptor);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveRT_fnRead(
IN IPortFilterWaveRT* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveRT_fnWrite(
IN IPortFilterWaveRT* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveRT_fnFlush(
IN IPortFilterWaveRT* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveRT_fnClose(
IN IPortFilterWaveRT* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG Index;
IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl *)iface;
for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
{
if (This->Pins[Index])
{
This->Pins[Index]->lpVtbl->Close(This->Pins[Index], DeviceObject, NULL);
}
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveRT_fnQuerySecurity(
IN IPortFilterWaveRT* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterWaveRT_fnSetSecurity(
IN IPortFilterWaveRT* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterWaveRT_fnFastDeviceIoControl(
IN IPortFilterWaveRT* iface,
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
ULONG Index;
PKSPROPERTY Property;
NTSTATUS Status;
ISubdevice * SubDevice = NULL;
PSUBDEVICE_DESCRIPTOR Descriptor = NULL;
IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl *)iface;
Property = (PKSPROPERTY)InputBuffer;
if (InputBufferLength < sizeof(KSPROPERTY))
return FALSE;
/* get private interface */
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&SubDevice);
if (!NT_SUCCESS(Status))
return FALSE;
/* get descriptor */
Status = SubDevice->lpVtbl->GetDescriptor(SubDevice, &Descriptor);
if (!NT_SUCCESS(Status))
{
SubDevice->lpVtbl->Release(SubDevice);
return FALSE;
}
for(Index = 0; Index < Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++)
{
if (IsEqualGUIDAligned(&Property->Set, Descriptor->FilterPropertySet.Properties[Index].Set))
{
FastPropertyHandler(FileObject, (PKSPROPERTY)InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, StatusBlock,
1,
&Descriptor->FilterPropertySet.Properties[Index],
Descriptor, SubDevice);
}
}
return TRUE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterWaveRT_fnFastRead(
IN IPortFilterWaveRT* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterWaveRT_fnFastWrite(
IN IPortFilterWaveRT* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
/*
* @implemented
*/
static
NTSTATUS
NTAPI
IPortFilterWaveRT_fnInit(
IN IPortFilterWaveRT* iface,
IN IPortWaveRT* Port)
{
ISubdevice * ISubDevice;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl*)iface;
This->Port = Port;
/* get our private interface */
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* get the subdevice descriptor */
Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor);
/* release subdevice interface */
ISubDevice->lpVtbl->Release(ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* save descriptor */
This->Descriptor = Descriptor;
/* allocate pin array */
This->Pins = AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinWaveRT*), TAG_PORTCLASS);
if (!This->Pins)
return STATUS_UNSUCCESSFUL;
/* increment reference count */
Port->lpVtbl->AddRef(Port);
return STATUS_SUCCESS;
}
static IPortFilterWaveRTVtbl vt_IPortFilterWaveRT =
{
IPortFilterWaveRT_fnQueryInterface,
IPortFilterWaveRT_fnAddRef,
IPortFilterWaveRT_fnRelease,
IPortFilterWaveRT_fnNewIrpTarget,
IPortFilterWaveRT_fnDeviceIoControl,
IPortFilterWaveRT_fnRead,
IPortFilterWaveRT_fnWrite,
IPortFilterWaveRT_fnFlush,
IPortFilterWaveRT_fnClose,
IPortFilterWaveRT_fnQuerySecurity,
IPortFilterWaveRT_fnSetSecurity,
IPortFilterWaveRT_fnFastDeviceIoControl,
IPortFilterWaveRT_fnFastRead,
IPortFilterWaveRT_fnFastWrite,
IPortFilterWaveRT_fnInit
};
NTSTATUS
NewPortFilterWaveRT(
OUT IPortFilterWaveRT ** OutFilter)
{
IPortFilterWaveRTImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IPortFilterWaveRTImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize IPortFilterWaveRT */
This->ref = 1;
This->lpVtbl = &vt_IPortFilterWaveRT;
/* return result */
*OutFilter = (IPortFilterWaveRT*)&This->lpVtbl;
return STATUS_SUCCESS;
}
@@ -0,0 +1,307 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/filter_wavert.cpp
* PURPOSE: portcls wave RT filter
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortFilterWaveRT : public IPortFilterWaveRT
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortFilterWaveRT;
CPortFilterWaveRT(IUnknown *OuterUnknown){}
virtual ~CPortFilterWaveRT(){}
protected:
IPortWaveRT* m_Port;
IPortPinWaveRT ** m_Pins;
SUBDEVICE_DESCRIPTOR * m_Descriptor;
LONG m_Ref;
};
NTSTATUS
NTAPI
CPortFilterWaveRT::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPort))
{
*Output = PUNKNOWN(m_Port);
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortFilterWaveRT::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortPinWaveRT * Pin;
PKSPIN_CONNECT ConnectDetails;
#if 0
ASSERT(m_Port);
ASSERT(m_Descriptor);
ASSERT(m_Pins);
#endif
DPRINT("CPortFilterWaveRT::NewIrpTarget entered\n");
// let's verify the connection request
Status = PcValidateConnectRequest(Irp, &m_Descriptor->Factory, &ConnectDetails);
if (!NT_SUCCESS(Status))
{
return STATUS_UNSUCCESSFUL;
}
if (m_Pins[ConnectDetails->PinId] && m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount)
{
// release existing instance
PC_ASSERT(0);
m_Pins[ConnectDetails->PinId]->Close(DeviceObject, NULL);
}
// now create the pin
Status = NewPortPinWaveRT(&Pin);
if (!NT_SUCCESS(Status))
{
return Status;
}
// initialize the pin
Status = Pin->Init(m_Port, this, ConnectDetails, &m_Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId], GetDeviceObjectFromPortWaveRT(m_Port));
if (!NT_SUCCESS(Status))
{
Pin->Release();
return Status;
}
// release existing pin
if (m_Pins[ConnectDetails->PinId])
{
m_Pins[ConnectDetails->PinId]->Release();
}
// store pin
m_Pins[ConnectDetails->PinId] = Pin;
// store result
*OutTarget = (IIrpTarget*)Pin;
// increment current instance count
m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
return Status;
}
NTSTATUS
NTAPI
CPortFilterWaveRT::DeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return PcPropertyHandler(Irp, m_Descriptor);
}
NTSTATUS
NTAPI
CPortFilterWaveRT::Read(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWaveRT::Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWaveRT::Flush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWaveRT::Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortFilterWaveRT::QuerySecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortFilterWaveRT::SetSecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
BOOLEAN
NTAPI
CPortFilterWaveRT::FastDeviceIoControl(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortFilterWaveRT::FastRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortFilterWaveRT::FastWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
NTSTATUS
NTAPI
CPortFilterWaveRT::Init(
IN IPortWaveRT* Port)
{
ISubdevice * ISubDevice;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
m_Port = Port;
// get our private interface
Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
// get the subdevice descriptor
Status = ISubDevice->GetDescriptor(&Descriptor);
// release subdevice interface
ISubDevice->Release();
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
// save descriptor
m_Descriptor = Descriptor;
// allocate pin array
m_Pins = (IPortPinWaveRT**)AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinWaveRT*), TAG_PORTCLASS);
if (!m_Pins)
return STATUS_UNSUCCESSFUL;
// increment reference count
Port->AddRef();
return STATUS_SUCCESS;
}
NTSTATUS
NewPortFilterWaveRT(
OUT IPortFilterWaveRT ** OutFilter)
{
CPortFilterWaveRT * This;
This = new(NonPagedPool, TAG_PORTCLASS)CPortFilterWaveRT(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->AddRef();
// return result
*OutFilter = (CPortFilterWaveRT*)This;
return STATUS_SUCCESS;
}
@@ -1,13 +1,13 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/guids.c
* FILE: drivers/wdm/audio/backpln/portcls/guids.cpp
* PURPOSE: portcls guid mess
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
#include "private.hpp"
const GUID CLSID_PortTopology = {0xb4c90a32L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
const GUID CLSID_PortMidi = {0xb4c90a43L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
@@ -25,11 +25,13 @@ const GUID GUID_NULL ={0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x0
const GUID IID_IPortTopology = {0xb4c90a30L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
const GUID CLSID_MiniportDriverDMusUART;
const GUID CLSID_MiniportDriverUart;
const GUID CLSID_MiniportDriverDMusUARTCapture;
const GUID CLSID_MiniportDriverFmSynth;
const GUID CLSID_MiniportDriverFmSynthWithVol;
const GUID CLSID_MiniportDriverDMusUART = {0xd3f0ce1c, 0xfffc, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}};
const GUID CLSID_MiniportDriverDMusUARTCapture = {0xd3f0ce1d, 0xfffc, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}};
const GUID CLSID_MiniportDriverUart = {0xb4c90ae1L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
const GUID CLSID_MiniportDriverFmSynth = {0xb4c90ae0L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
const GUID CLSID_MiniportDriverFmSynthWithVol = {0xe5a3c139L, 0xf0f2, 0x11d1, {0x81, 0xaf, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}};
const GUID IID_IPort = {0xb4c90a25L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
const GUID IID_IDrmPort = {0x286D3DF8L, 0xCA22, 0x4E2E, {0xB9, 0xBC, 0x20, 0xB4, 0xF0, 0xE2, 0x01, 0xCE}};
@@ -11,6 +11,75 @@ DEFINE_GUID(IID_IIrpTargetFactory, 0xB4C90A62, 0x5791, 0x11D0, 0xF9, 0x86, 0x00,
*****************************************************************************
*/
#define IMP_IIrpTarget \
STDMETHODIMP_(NTSTATUS) NewIrpTarget(THIS_ \
OUT struct IIrpTarget **OutTarget, \
IN WCHAR * Name, \
IN PUNKNOWN Unknown, \
IN POOL_TYPE PoolType, \
IN PDEVICE_OBJECT DeviceObject, \
IN PIRP Irp, \
IN KSOBJECT_CREATE *CreateObject); \
\
STDMETHODIMP_(NTSTATUS) DeviceIoControl(THIS_ \
IN PDEVICE_OBJECT DeviceObject, \
IN PIRP Irp); \
\
STDMETHODIMP_(NTSTATUS) Read(THIS_ \
IN PDEVICE_OBJECT DeviceObject, \
IN PIRP Irp); \
\
STDMETHODIMP_(NTSTATUS) Write(THIS_ \
IN PDEVICE_OBJECT DeviceObject, \
IN PIRP Irp); \
\
STDMETHODIMP_(NTSTATUS) Flush(THIS_ \
IN PDEVICE_OBJECT DeviceObject, \
IN PIRP Irp); \
\
STDMETHODIMP_(NTSTATUS) Close(THIS_ \
IN PDEVICE_OBJECT DeviceObject, \
IN PIRP Irp); \
\
STDMETHODIMP_(NTSTATUS) QuerySecurity(THIS_ \
IN PDEVICE_OBJECT DeviceObject, \
IN PIRP Irp); \
\
STDMETHODIMP_(NTSTATUS) SetSecurity(THIS_ \
IN PDEVICE_OBJECT DeviceObject, \
IN PIRP Irp); \
\
STDMETHODIMP_(BOOLEAN) FastDeviceIoControl(THIS_ \
IN PFILE_OBJECT FileObject, \
IN BOOLEAN Wait, \
IN PVOID InputBuffer, \
IN ULONG InputBufferLength, \
OUT PVOID OutputBuffer, \
IN ULONG OutputBufferLength, \
IN ULONG IoControlCode, \
OUT PIO_STATUS_BLOCK StatusBlock, \
IN PDEVICE_OBJECT DeviceObject); \
\
STDMETHODIMP_(BOOLEAN) FastRead(THIS_ \
IN PFILE_OBJECT FileObject, \
IN PLARGE_INTEGER FileOffset, \
IN ULONG Length, \
IN BOOLEAN Wait, \
IN ULONG LockKey, \
IN PVOID Buffer, \
OUT PIO_STATUS_BLOCK StatusBlock, \
IN PDEVICE_OBJECT DeviceObject); \
\
STDMETHODIMP_(BOOLEAN) FastWrite(THIS_ \
IN PFILE_OBJECT FileObject, \
IN PLARGE_INTEGER FileOffset, \
IN ULONG Length, \
IN BOOLEAN Wait, \
IN ULONG LockKey, \
IN PVOID Buffer, \
OUT PIO_STATUS_BLOCK StatusBlock, \
IN PDEVICE_OBJECT DeviceObject)
#define DEFINE_ABSTRACT_IRPTARGET() \
STDMETHOD_(NTSTATUS, NewIrpTarget)(THIS_ \
OUT struct IIrpTarget **OutTarget, \
@@ -80,6 +149,8 @@ DEFINE_GUID(IID_IIrpTargetFactory, 0xB4C90A62, 0x5791, 0x11D0, 0xF9, 0x86, 0x00,
OUT PIO_STATUS_BLOCK StatusBlock, \
IN PDEVICE_OBJECT DeviceObject)PURE;
#undef INTERFACE
#define INTERFACE IIrpTarget
@@ -136,50 +207,85 @@ typedef struct
#undef INTERFACE
#define INTERFACE ISubdevice
DECLARE_INTERFACE_(ISubdevice, IUnknown)
{
STDMETHOD_(NTSTATUS, QueryInterface)(THIS_
REFIID InterfaceId,
PVOID* Interface
) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD_(NTSTATUS, NewIrpTarget)(THIS_
OUT IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject) PURE;
STDMETHOD_(NTSTATUS, ReleaseChildren)(THIS) PURE;
STDMETHOD_(NTSTATUS, GetDescriptor)(THIS_
IN SUBDEVICE_DESCRIPTOR **) PURE;
STDMETHOD_(NTSTATUS, DataRangeIntersection)(THIS_
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength) PURE;
STDMETHOD_(NTSTATUS, PowerChangeNotify)(THIS_
IN POWER_STATE PowerState) PURE;
STDMETHOD_(NTSTATUS, PinCount)(THIS_
IN ULONG PinId,
IN OUT PULONG FilterNecessary,
IN OUT PULONG FilterCurrent,
IN OUT PULONG FilterPossible,
IN OUT PULONG GlobalCurrent,
#define DEFINE_ABSTRACT_ISUBDEVICE() \
STDMETHOD_(NTSTATUS, NewIrpTarget)(THIS_ \
OUT IIrpTarget **OutTarget, \
IN WCHAR * Name, \
IN PUNKNOWN Unknown, \
IN POOL_TYPE PoolType, \
IN PDEVICE_OBJECT DeviceObject, \
IN PIRP Irp, \
IN KSOBJECT_CREATE *CreateObject) PURE; \
\
STDMETHOD_(NTSTATUS, ReleaseChildren)(THIS) PURE; \
\
STDMETHOD_(NTSTATUS, GetDescriptor)(THIS_ \
IN SUBDEVICE_DESCRIPTOR **) PURE; \
\
STDMETHOD_(NTSTATUS, DataRangeIntersection)(THIS_ \
IN ULONG PinId, \
IN PKSDATARANGE DataRange, \
IN PKSDATARANGE MatchingDataRange, \
IN ULONG OutputBufferLength, \
OUT PVOID ResultantFormat OPTIONAL, \
OUT PULONG ResultantFormatLength) PURE; \
\
STDMETHOD_(NTSTATUS, PowerChangeNotify)(THIS_ \
IN POWER_STATE PowerState) PURE; \
\
STDMETHOD_(NTSTATUS, PinCount)(THIS_ \
IN ULONG PinId, \
IN OUT PULONG FilterNecessary, \
IN OUT PULONG FilterCurrent, \
IN OUT PULONG FilterPossible, \
IN OUT PULONG GlobalCurrent, \
IN OUT PULONG GlobalPossible)PURE;
#define IMP_ISubdevice \
STDMETHODIMP_(NTSTATUS) NewIrpTarget( \
OUT IIrpTarget **OutTarget, \
IN WCHAR * Name, \
IN PUNKNOWN Unknown, \
IN POOL_TYPE PoolType, \
IN PDEVICE_OBJECT DeviceObject, \
IN PIRP Irp, \
IN KSOBJECT_CREATE *CreateObject); \
\
STDMETHODIMP_(NTSTATUS) ReleaseChildren(THIS); \
\
STDMETHODIMP_(NTSTATUS) GetDescriptor(THIS_ \
IN SUBDEVICE_DESCRIPTOR **); \
\
STDMETHODIMP_(NTSTATUS) DataRangeIntersection( \
IN ULONG PinId, \
IN PKSDATARANGE DataRange, \
IN PKSDATARANGE MatchingDataRange, \
IN ULONG OutputBufferLength, \
OUT PVOID ResultantFormat OPTIONAL, \
OUT PULONG ResultantFormatLength); \
\
STDMETHODIMP_(NTSTATUS) PowerChangeNotify( \
IN POWER_STATE PowerState); \
\
STDMETHODIMP_(NTSTATUS) PinCount( \
IN ULONG PinId, \
IN OUT PULONG FilterNecessary, \
IN OUT PULONG FilterCurrent, \
IN OUT PULONG FilterPossible, \
IN OUT PULONG GlobalCurrent, \
IN OUT PULONG GlobalPossible)
DECLARE_INTERFACE_(ISubdevice, IUnknown)
{
DEFINE_ABSTRACT_UNKNOWN()
DEFINE_ABSTRACT_ISUBDEVICE()
};
typedef ISubdevice *PSUBDEVICE;
/*****************************************************************************
* IIrpQueue
*****************************************************************************
@@ -241,6 +347,54 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
};
#define IMP_IIrpQueue \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN KSPIN_CONNECT *ConnectDetails, \
IN PKSDATAFORMAT DataFormat, \
IN PDEVICE_OBJECT DeviceObject, \
IN ULONG FrameSize, \
IN ULONG Alignment, \
IN PVOID SilenceBuffer); \
\
STDMETHODIMP_(NTSTATUS) AddMapping(THIS_ \
IN PUCHAR Buffer, \
IN ULONG BufferSize, \
IN PIRP Irp); \
\
STDMETHODIMP_(NTSTATUS) GetMapping(THIS_ \
OUT PUCHAR * Buffer, \
OUT PULONG BufferSize); \
\
STDMETHODIMP_(VOID) UpdateMapping(THIS_ \
IN ULONG BytesWritten); \
\
STDMETHODIMP_(ULONG) NumMappings(THIS); \
\
STDMETHODIMP_(ULONG) NumData(THIS); \
\
STDMETHODIMP_(BOOL) MinimumDataAvailable(THIS); \
\
STDMETHODIMP_(BOOL) CancelBuffers(THIS); \
\
STDMETHODIMP_(VOID) UpdateFormat(THIS_ \
IN PKSDATAFORMAT DataFormat); \
\
STDMETHODIMP_(NTSTATUS) GetMappingWithTag(THIS_ \
IN PVOID Tag, \
OUT PPHYSICAL_ADDRESS PhysicalAddress, \
OUT PVOID *VirtualAddress, \
OUT PULONG ByteCount, \
OUT PULONG Flags); \
\
STDMETHODIMP_(NTSTATUS) ReleaseMappingWithTag( \
IN PVOID Tag); \
\
STDMETHODIMP_(BOOL) HasLastMappingFailed(THIS); \
STDMETHODIMP_(VOID) PrintQueueStatus(THIS); \
STDMETHODIMP_(VOID) SetMinimumDataThreshold( \
IN ULONG MinimumDataThreshold); \
STDMETHODIMP_(ULONG) GetMinimumDataThreshold(VOID)
/*****************************************************************************
* IKsWorkSink
*****************************************************************************
@@ -453,6 +607,10 @@ DECLARE_INTERFACE_(IPortFilterWavePci, IIrpTarget)
typedef IPortFilterWavePci *PPORTFILTERWAVEPCI;
#define IMP_IPortFilterPci \
IMP_IIrpTarget; \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN PPORTWAVEPCI Port)
/*****************************************************************************
* IPortPinWavePci
@@ -479,8 +637,23 @@ DECLARE_INTERFACE_(IPortPinWavePci, IIrpTarget)
STDMETHOD_(PMINIPORT, GetMiniport)(THIS);
};
#define IMP_IPortPinWavePci \
IMP_IIrpTarget; \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN PPORTWAVEPCI Port, \
IN PPORTFILTERWAVEPCI Filter, \
IN KSPIN_CONNECT * ConnectDetails, \
IN KSPIN_DESCRIPTOR * PinDescriptor, \
IN PDEVICE_OBJECT DeviceObject); \
\
STDMETHODIMP_(PVOID) GetIrpStream(THIS); \
STDMETHODIMP_(PMINIPORT) GetMiniport(THIS)
typedef IPortPinWavePci *PPORTPINWAVEPCI;
#if (NTDDI_VERSION >= NTDDI_VISTA)
/*****************************************************************************
@@ -503,6 +676,12 @@ DECLARE_INTERFACE_(IPortFilterWaveRT, IIrpTarget)
typedef IPortFilterWaveRT *PPORTFILTERWAVERT;
#define IMP_IPortFilterWaveRT \
IMP_IIrpTarget; \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN PPORTWAVERT Port)
/*****************************************************************************
* IPortPinWaveRT
*****************************************************************************
@@ -527,6 +706,16 @@ DECLARE_INTERFACE_(IPortPinWaveRT, IIrpTarget)
typedef IPortPinWaveRT *PPORTPINWAVERT;
#define IMP_IPortPinWaveRT \
IMP_IIrpTarget; \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN PPORTWAVERT Port, \
IN PPORTFILTERWAVERT Filter, \
IN KSPIN_CONNECT * ConnectDetails, \
IN KSPIN_DESCRIPTOR * PinDescriptor, \
IN PDEVICE_OBJECT DeviceObject)
#endif
/*****************************************************************************
@@ -554,6 +743,14 @@ DECLARE_INTERFACE_(IPortFilterWaveCyclic, IIrpTarget)
typedef IPortFilterWaveCyclic *PPORTFILTERWAVECYCLIC;
#define IMP_IPortFilterWaveCyclic \
IMP_IIrpTarget; \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN PPORTWAVECYCLIC Port); \
STDMETHODIMP_(NTSTATUS) FreePin(THIS_ \
IN struct IPortPinWaveCyclic* Pin)
/*****************************************************************************
* IPortPinWaveCyclic
*****************************************************************************
@@ -581,6 +778,20 @@ DECLARE_INTERFACE_(IPortPinWaveCyclic, IIrpTarget)
STDMETHOD_(PMINIPORT, GetMiniport)(THIS);
};
#define IMP_IPortPinWaveCyclic \
IMP_IIrpTarget; \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN PPORTWAVECYCLIC Port, \
IN PPORTFILTERWAVECYCLIC Filter, \
IN KSPIN_CONNECT * ConnectDetails, \
IN KSPIN_DESCRIPTOR * PinDescriptor); \
STDMETHODIMP_(ULONG) GetCompletedPosition(THIS); \
STDMETHODIMP_(ULONG) GetCycleCount(THIS); \
STDMETHODIMP_(ULONG) GetDeviceBufferSize(THIS); \
STDMETHODIMP_(PVOID) GetIrpStream(THIS); \
STDMETHODIMP_(PMINIPORT) GetMiniport(THIS)
/*****************************************************************************
* IPortFilterDMus
*****************************************************************************
@@ -591,7 +802,7 @@ DECLARE_INTERFACE_(IPortPinWaveCyclic, IIrpTarget)
struct IPortPinDMus;
DECLARE_INTERFACE_(IPortFilterDMus, IIrpTarget)
DECLARE_INTERFACE_(IPortFilterDMus, IUnknown)
{
DEFINE_ABSTRACT_UNKNOWN()
@@ -608,6 +819,14 @@ DECLARE_INTERFACE_(IPortFilterDMus, IIrpTarget)
typedef IPortFilterDMus *PPORTFILTERDMUS;
#define IMP_IPortFilterDMus \
IMP_IIrpTarget; \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN PPORTDMUS Port); \
STDMETHODIMP_(NTSTATUS) FreePin(THIS_ \
IN struct IPortPinDMus* Pin); \
STDMETHODIMP_(VOID) NotifyPins(THIS)
/*****************************************************************************
* IPortPinDMus
*****************************************************************************
@@ -632,6 +851,16 @@ DECLARE_INTERFACE_(IPortPinDMus, IIrpTarget)
STDMETHOD_(VOID, Notify)(THIS);
};
#define IMP_IPortPinDMus \
IMP_IIrpTarget; \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN PPORTDMUS Port, \
IN PPORTFILTERDMUS Filter, \
IN KSPIN_CONNECT * ConnectDetails, \
IN KSPIN_DESCRIPTOR * PinDescriptor, \
IN PDEVICE_OBJECT DeviceObject); \
STDMETHODIMP_(VOID) Notify(THIS)
typedef IPortPinDMus *PPORTPINDMUS;
/*****************************************************************************
@@ -645,51 +874,23 @@ typedef IPortPinDMus *PPORTPINDMUS;
DECLARE_INTERFACE_(IDmaChannelInit, IUnknown)
{
DEFINE_ABSTRACT_UNKNOWN()
STDMETHOD_(NTSTATUS,AllocateBuffer)(THIS_
IN ULONG BufferSize,
IN PPHYSICAL_ADDRESS PhysicalAddressConstraint OPTIONAL);
STDMETHOD_(VOID, FreeBuffer)(THIS);
STDMETHOD_(ULONG, TransferCount)(THIS);
STDMETHOD_(ULONG, MaximumBufferSize)(THIS);
STDMETHOD_(ULONG, AllocatedBufferSize)(THIS);
STDMETHOD_(ULONG, BufferSize)(THIS);
STDMETHOD_(VOID, SetBufferSize)(THIS_
IN ULONG BufferSize);
STDMETHOD_(PVOID, SystemAddress)(THIS);
STDMETHOD_(PHYSICAL_ADDRESS, PhysicalAddress)(THIS_
IN PPHYSICAL_ADDRESS Address);
STDMETHOD_(PADAPTER_OBJECT, GetAdapterObject)(THIS);
STDMETHOD_(VOID, CopyTo)(THIS_
IN PVOID Destination,
IN PVOID Source,
IN ULONG ByteCount);
STDMETHOD_(VOID, CopyFrom)(THIS_
IN PVOID Destination,
IN PVOID Source,
IN ULONG ByteCount);
STDMETHOD_(NTSTATUS, Start)( THIS_
IN ULONG MapSize,
IN BOOLEAN WriteToDevice) PURE;
STDMETHOD_(NTSTATUS, Stop)( THIS ) PURE;
STDMETHOD_(ULONG, ReadCounter)( THIS ) PURE;
STDMETHOD_(NTSTATUS, WaitForTC)( THIS_
ULONG Timeout) PURE;
DEFINE_ABSTRACT_DMACHANNEL()
DEFINE_ABSTRACT_DMACHANNELSLAVE()
STDMETHOD_(NTSTATUS, Init)( THIS_
IN PDEVICE_DESCRIPTION DeviceDescription,
IN PDEVICE_OBJECT DeviceObject) PURE;
};
#define IMP_IDmaChannelInit\
IMP_IDmaChannelSlave;\
STDMETHODIMP_(NTSTATUS) Init( \
IN PDEVICE_DESCRIPTION DeviceDescription, \
IN PDEVICE_OBJECT DeviceObject)
#undef INTERFACE
/*****************************************************************************
@@ -712,6 +913,11 @@ DECLARE_INTERFACE_(IPortFilterTopology, IIrpTarget)
typedef IPortFilterTopology *PPORTFILTERTOPOLOGY;
#define IMP_IPortFilterTopology \
IMP_IIrpTarget; \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN PPORTTOPOLOGY Port)
#undef INTERFACE
/*****************************************************************************
@@ -772,4 +978,50 @@ DECLARE_INTERFACE_(IPortWaveRTStreamInit, IUnknown)
#undef INTERFACE
#define IMP_IPortWaveRTStreamInit \
STDMETHODIMP_(PMDL) AllocatePagesForMdl \
( THIS_ \
IN PHYSICAL_ADDRESS HighAddress, \
IN SIZE_T TotalBytes \
); \
\
STDMETHODIMP_(PMDL) AllocateContiguousPagesForMdl \
( THIS_ \
IN PHYSICAL_ADDRESS LowAddress, \
IN PHYSICAL_ADDRESS HighAddress, \
IN SIZE_T TotalBytes \
); \
\
STDMETHODIMP_(PVOID) MapAllocatedPages \
( THIS_ \
IN PMDL MemoryDescriptorList, \
IN MEMORY_CACHING_TYPE CacheType \
); \
\
STDMETHODIMP_(VOID) UnmapAllocatedPages \
( THIS_ \
IN PVOID BaseAddress, \
IN PMDL MemoryDescriptorList \
); \
\
STDMETHODIMP_(VOID) FreePagesFromMdl \
( THIS_ \
IN PMDL MemoryDescriptorList \
); \
\
STDMETHODIMP_(ULONG) GetPhysicalPagesCount \
( THIS_ \
IN PMDL MemoryDescriptorList \
); \
\
STDMETHODIMP_(PHYSICAL_ADDRESS) GetPhysicalPageAddress \
( THIS_ \
IN PPHYSICAL_ADDRESS Address, \
IN PMDL MemoryDescriptorList, \
IN ULONG Index \
)
#endif
@@ -1,376 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/interrupt.c
* PURPOSE: portcls interrupt object
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
LIST_ENTRY ListEntry;
PINTERRUPTSYNCROUTINE SyncRoutine;
PVOID DynamicContext;
}SYNC_ENTRY, *PSYNC_ENTRY;
typedef struct
{
IInterruptSyncVtbl *lpVtbl;
LONG ref;
KSPIN_LOCK Lock;
LIST_ENTRY ServiceRoutines;
PKINTERRUPT Interrupt;
INTERRUPTSYNCMODE Mode;
PRESOURCELIST ResourceList;
ULONG ResourceIndex;
PINTERRUPTSYNCROUTINE SyncRoutine;
PVOID DynamicContext;
}IInterruptSyncImpl;
//---------------------------------------------------------------
// IUnknown methods
//
NTSTATUS
NTAPI
IInterruptSync_fnQueryInterface(
IInterruptSync * iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface;
DPRINT("IInterruptSync_fnQueryInterface: This %p\n", This);
if (IsEqualGUIDAligned(refiid, &IID_IInterruptSync) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
DPRINT1("IInterruptSync_fnQueryInterface: This %p UNKNOWN interface requested\n", This);
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IInterruptSync_fnAddRef(
IInterruptSync * iface)
{
IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface;
DPRINT("IInterruptSync_AddRef: This %p\n", This);
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IInterruptSync_fnRelease(
IInterruptSync* iface)
{
PLIST_ENTRY CurEntry;
PSYNC_ENTRY Entry;
IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface;
InterlockedDecrement(&This->ref);
DPRINT("IInterruptSync_Release: This %p new ref %u\n", This, This->ref);
if (This->ref == 0)
{
while(!IsListEmpty(&This->ServiceRoutines))
{
CurEntry = RemoveHeadList(&This->ServiceRoutines);
Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry);
FreeItem(Entry, TAG_PORTCLASS);
}
This->ResourceList->lpVtbl->Release(This->ResourceList);
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
//---------------------------------------------------------------
// IInterruptSync methods
//
BOOLEAN
NTAPI
IInterruptSynchronizedRoutine(
IN PVOID ServiceContext)
{
IInterruptSyncImpl * This = (IInterruptSyncImpl*)ServiceContext;
DPRINT("IInterruptSynchronizedRoutine This %p SyncRoutine %p Context %p\n", This, This->SyncRoutine, This->DynamicContext);
return This->SyncRoutine((IInterruptSync*)&This->lpVtbl, This->DynamicContext);
}
NTSTATUS
NTAPI
IInterruptSync_fnCallSynchronizedRoutine(
IN IInterruptSync * iface,
IN PINTERRUPTSYNCROUTINE Routine,
IN PVOID DynamicContext)
{
KIRQL OldIrql;
IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface;
DPRINT("IInterruptSync_fnCallSynchronizedRoutine This %p Routine %p DynamicContext %p Irql %x Interrupt %p\n", This, Routine, DynamicContext, KeGetCurrentIrql(), This->Interrupt);
if (!This->Interrupt)
{
DPRINT("IInterruptSync_CallSynchronizedRoutine %p no interrupt connected\n", This);
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
return STATUS_UNSUCCESSFUL;
KeAcquireSpinLock(&This->Lock, &OldIrql);
This->SyncRoutine = Routine;
This->DynamicContext = DynamicContext;
IInterruptSynchronizedRoutine((PVOID)This);
KeReleaseSpinLock(&This->Lock, OldIrql);
return STATUS_SUCCESS;
}
This->SyncRoutine = Routine;
This->DynamicContext = DynamicContext;
if (KeSynchronizeExecution(This->Interrupt, IInterruptSynchronizedRoutine, (PVOID)This))
return STATUS_SUCCESS;
else
return STATUS_UNSUCCESSFUL;
}
PKINTERRUPT
NTAPI
IInterruptSync_fnGetKInterrupt(
IN IInterruptSync * iface)
{
IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface;
DPRINT("IInterruptSynchronizedRoutine\n");
return This->Interrupt;
}
BOOLEAN
NTAPI
IInterruptServiceRoutine(
IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext)
{
PLIST_ENTRY CurEntry;
PSYNC_ENTRY Entry;
NTSTATUS Status;
BOOL Success;
IInterruptSyncImpl * This = (IInterruptSyncImpl*)ServiceContext;
//DPRINT("IInterruptServiceRoutine Mode %u\n", This->Mode);
if (This->Mode == InterruptSyncModeNormal)
{
CurEntry = This->ServiceRoutines.Flink;
while (CurEntry != &This->ServiceRoutines)
{
Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry);
Status = Entry->SyncRoutine((IInterruptSync*)This, Entry->DynamicContext);
if (NT_SUCCESS(Status))
{
return TRUE;
}
CurEntry = CurEntry->Flink;
}
return FALSE;
}
else if (This->Mode == InterruptSyncModeAll)
{
CurEntry = This->ServiceRoutines.Flink;
while (CurEntry != &This->ServiceRoutines)
{
Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry);
Status = Entry->SyncRoutine((IInterruptSync*)This, Entry->DynamicContext);
CurEntry = CurEntry->Flink;
}
DPRINT("Returning TRUE with mode InterruptSyncModeAll\n");
return TRUE; //FIXME
}
else if (This->Mode == InterruptSyncModeRepeat)
{
do
{
Success = FALSE;
CurEntry = This->ServiceRoutines.Flink;
while (CurEntry != &This->ServiceRoutines)
{
Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry);
Status = Entry->SyncRoutine((IInterruptSync*)This, Entry->DynamicContext);
if (NT_SUCCESS(Status))
Success = TRUE;
CurEntry = CurEntry->Flink;
}
}while(Success);
DPRINT("Returning TRUE with mode InterruptSyncModeRepeat\n");
return TRUE; //FIXME
}
else
{
DPRINT("Unknown mode %u\n", This->Mode);
return FALSE; //FIXME
}
}
NTSTATUS
NTAPI
IInterruptSync_fnConnect(
IN IInterruptSync * iface)
{
IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface;
NTSTATUS Status;
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
DPRINT("IInterruptSync_fnConnect\n");
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
Descriptor = This->ResourceList->lpVtbl->FindTranslatedEntry(This->ResourceList, CmResourceTypeInterrupt, This->ResourceIndex);
if (!Descriptor)
return STATUS_UNSUCCESSFUL;
if (IsListEmpty(&This->ServiceRoutines))
return STATUS_UNSUCCESSFUL;
Status = IoConnectInterrupt(&This->Interrupt,
IInterruptServiceRoutine,
(PVOID)This,
&This->Lock,
Descriptor->u.Interrupt.Vector,
Descriptor->u.Interrupt.Level,
Descriptor->u.Interrupt.Level,
(Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED),
(Descriptor->Flags != CM_RESOURCE_INTERRUPT_LATCHED),
Descriptor->u.Interrupt.Affinity,
FALSE);
DPRINT("IInterruptSync_fnConnect result %x\n", Status);
return Status;
}
VOID
NTAPI
IInterruptSync_fnDisconnect(
IN IInterruptSync * iface)
{
IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface;
DPRINT("IInterruptSync_fnDisconnect\n");
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->Interrupt)
{
DPRINT("IInterruptSync_Disconnect %p no interrupt connected\n", This);
return;
}
IoDisconnectInterrupt(This->Interrupt);
This->Interrupt = NULL;
}
NTSTATUS
NTAPI
IInterruptSync_fnRegisterServiceRoutine(
IN IInterruptSync * iface,
IN PINTERRUPTSYNCROUTINE Routine,
IN PVOID DynamicContext,
IN BOOLEAN First)
{
PSYNC_ENTRY NewEntry;
IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface;
DPRINT("IInterruptSync_fnRegisterServiceRoutine\n");
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
NewEntry = AllocateItem(NonPagedPool, sizeof(SYNC_ENTRY), TAG_PORTCLASS);
if (!NewEntry)
return STATUS_INSUFFICIENT_RESOURCES;
NewEntry->SyncRoutine = Routine;
NewEntry->DynamicContext = DynamicContext;
if (First)
InsertHeadList(&This->ServiceRoutines, &NewEntry->ListEntry);
else
InsertTailList(&This->ServiceRoutines, &NewEntry->ListEntry);
return STATUS_SUCCESS;
}
static IInterruptSyncVtbl vt_IInterruptSyncVtbl =
{
/* IUnknown methods */
IInterruptSync_fnQueryInterface,
IInterruptSync_fnAddRef,
IInterruptSync_fnRelease,
/* IInterruptSync methods */
IInterruptSync_fnCallSynchronizedRoutine,
IInterruptSync_fnGetKInterrupt,
IInterruptSync_fnConnect,
IInterruptSync_fnDisconnect,
IInterruptSync_fnRegisterServiceRoutine
};
/*
* @implemented
*/
NTSTATUS NTAPI
PcNewInterruptSync(
OUT PINTERRUPTSYNC* OutInterruptSync,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN PRESOURCELIST ResourceList,
IN ULONG ResourceIndex,
IN INTERRUPTSYNCMODE Mode)
{
IInterruptSyncImpl * This;
DPRINT("PcNewInterruptSync entered OutInterruptSync %p OuterUnknown %p ResourceList %p ResourceIndex %u Mode %d\n",
OutInterruptSync, OuterUnknown, ResourceList, ResourceIndex, Mode);
if (!OutInterruptSync || !ResourceList || Mode < InterruptSyncModeNormal || Mode > InterruptSyncModeRepeat)
return STATUS_INVALID_PARAMETER;
if (ResourceIndex > ResourceList->lpVtbl->NumberOfEntriesOfType(ResourceList, CmResourceTypeInterrupt))
return STATUS_INVALID_PARAMETER;
ResourceList->lpVtbl->AddRef(ResourceList);
This = AllocateItem(NonPagedPool, sizeof(IInterruptSyncImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize object */
This->lpVtbl = &vt_IInterruptSyncVtbl;
This->ref = 1;
This->Mode = Mode;
This->ResourceIndex = ResourceIndex;
This->ResourceList = ResourceList;
InitializeListHead(&This->ServiceRoutines);
KeInitializeSpinLock(&This->Lock);
*OutInterruptSync = (PINTERRUPTSYNC)&This->lpVtbl;
DPRINT("PcNewInterruptSync success %p\n", *OutInterruptSync);
return STATUS_SUCCESS;
}
@@ -0,0 +1,338 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/interrupt.cpp
* PURPOSE: portcls interrupt object
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
typedef struct
{
LIST_ENTRY ListEntry;
PINTERRUPTSYNCROUTINE SyncRoutine;
PVOID DynamicContext;
}SYNC_ENTRY, *PSYNC_ENTRY;
class CInterruptSync : public IInterruptSync
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IInterruptSync;
CInterruptSync(IUnknown *OuterUnknown){}
virtual ~CInterruptSync(){}
public:
KSPIN_LOCK m_Lock;
LIST_ENTRY m_ServiceRoutines;
PKINTERRUPT m_Interrupt;
INTERRUPTSYNCMODE m_Mode;
PRESOURCELIST m_ResourceList;
ULONG m_ResourceIndex;
PINTERRUPTSYNCROUTINE m_SyncRoutine;
PVOID m_DynamicContext;
LONG m_Ref;
friend BOOLEAN NTAPI CInterruptSynchronizedRoutine(IN PVOID ServiceContext);
friend BOOLEAN NTAPI IInterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext);
};
//---------------------------------------------------------------
// IUnknown methods
//
NTSTATUS
NTAPI
CInterruptSync::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
DPRINT("CInterruptSync::QueryInterface: this %p\n", this);
if (IsEqualGUIDAligned(refiid, IID_IInterruptSync) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
DPRINT1("CInterruptSync::QueryInterface: this %p UNKNOWN interface requested\n", this);
return STATUS_UNSUCCESSFUL;
}
//---------------------------------------------------------------
// CInterruptSync methods
//
BOOLEAN
NTAPI
CInterruptSynchronizedRoutine(
IN PVOID ServiceContext)
{
CInterruptSync * This = (CInterruptSync*)ServiceContext;
DPRINT("CInterruptSynchronizedRoutine this %p SyncRoutine %p Context %p\n", This, This->m_SyncRoutine, This->m_DynamicContext);
return This->m_SyncRoutine(This, This->m_DynamicContext);
}
NTSTATUS
NTAPI
CInterruptSync::CallSynchronizedRoutine(
IN PINTERRUPTSYNCROUTINE Routine,
IN PVOID DynamicContext)
{
KIRQL OldIrql;
DPRINT("CInterruptSync::CallSynchronizedRoutine this %p Routine %p DynamicContext %p Irql %x Interrupt %p\n", this, Routine, DynamicContext, KeGetCurrentIrql(), m_Interrupt);
if (!m_Interrupt)
{
DPRINT("CInterruptSync_CallSynchronizedRoutine %p no interrupt connected\n", this);
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
return STATUS_UNSUCCESSFUL;
KeAcquireSpinLock(&m_Lock, &OldIrql);
m_SyncRoutine = Routine;
m_DynamicContext = DynamicContext;
CInterruptSynchronizedRoutine((PVOID)this);
KeReleaseSpinLock(&m_Lock, OldIrql);
return STATUS_SUCCESS;
}
m_SyncRoutine = Routine;
m_DynamicContext = DynamicContext;
if (KeSynchronizeExecution(m_Interrupt, CInterruptSynchronizedRoutine, (PVOID)this))
return STATUS_SUCCESS;
else
return STATUS_UNSUCCESSFUL;
}
PKINTERRUPT
NTAPI
CInterruptSync::GetKInterrupt()
{
DPRINT("CInterruptSynchronizedRoutine\n");
return m_Interrupt;
}
BOOLEAN
NTAPI
IInterruptServiceRoutine(
IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext)
{
PLIST_ENTRY CurEntry;
PSYNC_ENTRY Entry;
NTSTATUS Status;
BOOL Success;
//DPRINT("IInterruptServiceRoutine Mode %u\n", m_Mode);
CInterruptSync * This = (CInterruptSync*)ServiceContext;
if (This->m_Mode == InterruptSyncModeNormal)
{
CurEntry = This->m_ServiceRoutines.Flink;
while (CurEntry != &This->m_ServiceRoutines)
{
Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry);
Status = Entry->SyncRoutine((CInterruptSync*)This, Entry->DynamicContext);
if (NT_SUCCESS(Status))
{
return TRUE;
}
CurEntry = CurEntry->Flink;
}
return FALSE;
}
else if (This->m_Mode == InterruptSyncModeAll)
{
CurEntry = This->m_ServiceRoutines.Flink;
while (CurEntry != &This->m_ServiceRoutines)
{
Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry);
Status = Entry->SyncRoutine((CInterruptSync*)This, Entry->DynamicContext);
CurEntry = CurEntry->Flink;
}
DPRINT("Returning TRUE with mode InterruptSyncModeAll\n");
return TRUE; //FIXME
}
else if (This->m_Mode == InterruptSyncModeRepeat)
{
do
{
Success = FALSE;
CurEntry = This->m_ServiceRoutines.Flink;
while (CurEntry != &This->m_ServiceRoutines)
{
Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry);
Status = Entry->SyncRoutine((CInterruptSync*)This, Entry->DynamicContext);
if (NT_SUCCESS(Status))
Success = TRUE;
CurEntry = CurEntry->Flink;
}
}while(Success);
DPRINT("Returning TRUE with mode InterruptSyncModeRepeat\n");
return TRUE; //FIXME
}
else
{
DPRINT("Unknown mode %u\n", This->m_Mode);
return FALSE; //FIXME
}
}
NTSTATUS
NTAPI
CInterruptSync::Connect()
{
NTSTATUS Status;
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
DPRINT("CInterruptSync::Connect\n");
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
Descriptor = m_ResourceList->FindTranslatedEntry(CmResourceTypeInterrupt, m_ResourceIndex);
if (!Descriptor)
return STATUS_UNSUCCESSFUL;
if (IsListEmpty(&m_ServiceRoutines))
return STATUS_UNSUCCESSFUL;
Status = IoConnectInterrupt(&m_Interrupt,
IInterruptServiceRoutine,
(PVOID)this,
&m_Lock,
Descriptor->u.Interrupt.Vector,
Descriptor->u.Interrupt.Level,
Descriptor->u.Interrupt.Level,
(KINTERRUPT_MODE)(Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED),
(Descriptor->Flags != CM_RESOURCE_INTERRUPT_LATCHED),
Descriptor->u.Interrupt.Affinity,
FALSE);
DPRINT("CInterruptSync::Connect result %x\n", Status);
return Status;
}
VOID
NTAPI
CInterruptSync::Disconnect()
{
DPRINT("CInterruptSync::Disconnect\n");
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_Interrupt)
{
DPRINT("CInterruptSync_Disconnect %p no interrupt connected\n", this);
return;
}
IoDisconnectInterrupt(m_Interrupt);
m_Interrupt = NULL;
}
NTSTATUS
NTAPI
CInterruptSync::RegisterServiceRoutine(
IN PINTERRUPTSYNCROUTINE Routine,
IN PVOID DynamicContext,
IN BOOLEAN First)
{
PSYNC_ENTRY NewEntry;
DPRINT("CInterruptSync::RegisterServiceRoutine\n");
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
NewEntry = (PSYNC_ENTRY)AllocateItem(NonPagedPool, sizeof(SYNC_ENTRY), TAG_PORTCLASS);
if (!NewEntry)
return STATUS_INSUFFICIENT_RESOURCES;
NewEntry->SyncRoutine = Routine;
NewEntry->DynamicContext = DynamicContext;
if (First)
InsertHeadList(&m_ServiceRoutines, &NewEntry->ListEntry);
else
InsertTailList(&m_ServiceRoutines, &NewEntry->ListEntry);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
PcNewInterruptSync(
OUT PINTERRUPTSYNC* OutInterruptSync,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN PRESOURCELIST ResourceList,
IN ULONG ResourceIndex,
IN INTERRUPTSYNCMODE Mode)
{
CInterruptSync * This;
NTSTATUS Status;
DPRINT("PcNewInterruptSync entered OutInterruptSync %p OuterUnknown %p ResourceList %p ResourceIndex %u Mode %d\n",
OutInterruptSync, OuterUnknown, ResourceList, ResourceIndex, Mode);
if (!OutInterruptSync || !ResourceList || Mode < InterruptSyncModeNormal || Mode > InterruptSyncModeRepeat)
return STATUS_INVALID_PARAMETER;
if (ResourceIndex > ResourceList->NumberOfEntriesOfType(CmResourceTypeInterrupt))
return STATUS_INVALID_PARAMETER;
This = new(NonPagedPool, TAG_PORTCLASS)CInterruptSync(OuterUnknown);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
Status = This->QueryInterface(IID_IInterruptSync, (PVOID*)OutInterruptSync);
if (!NT_SUCCESS(Status))
{
delete This;
return Status;
}
ResourceList->AddRef();
//
// initialize object
//
This->m_Mode = Mode;
This->m_ResourceIndex = ResourceIndex;
This->m_ResourceList = ResourceList;
InitializeListHead(&This->m_ServiceRoutines);
KeInitializeSpinLock(&This->m_Lock);
return Status;
}
@@ -1,7 +1,7 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS
* FILE: drivers/wdm/audio/backpln/portcls/irp.c
* FILE: drivers/wdm/audio/backpln/portcls/irp.cpp
* PURPOSE: Port Class driver / IRP Handling
* PROGRAMMER: Andrew Greenwood
* Johannes Anderwald
@@ -10,13 +10,8 @@
*/
#include "private.h"
#include <portcls.h>
#include "private.hpp"
/*
Handles IRP_MJ_CREATE, which occurs when someone wants to make use of
a device.
*/
NTSTATUS
NTAPI
PortClsCreate(
@@ -29,10 +24,6 @@ PortClsCreate(
}
/*
IRP_MJ_PNP handler
Used for things like IRP_MN_START_DEVICE
*/
NTSTATUS
NTAPI
PortClsPnp(
@@ -44,24 +35,20 @@ PortClsPnp(
PIO_STACK_LOCATION IoStack;
IResourceList* resource_list = NULL;
DPRINT("PortClsPnp called\n");
DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
IoStack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(DeviceExt);
/*
if IRP_MN_START_DEVICE, call the driver's customer start device routine.
Before we do so, we must create a ResourceList to pass to the Start
routine.
*/
DPRINT("PortClsPnp called %u\n", IoStack->MinorFunction);
//PC_ASSERT(DeviceExt);
switch (IoStack->MinorFunction)
{
case IRP_MN_START_DEVICE:
DPRINT("IRP_MN_START_DEVICE\n");
/* Create the resource list */
// Create the resource list
Status = PcNewResourceList(
&resource_list,
NULL,
@@ -76,22 +63,22 @@ PortClsPnp(
return Status;
}
/* forward irp to lower device object */
// forward irp to lower device object
Status = PcForwardIrpSynchronous(DeviceObject, Irp);
if (!NT_SUCCESS(Status))
{
/* lower device object failed to start */
resource_list->lpVtbl->Release(resource_list);
/* complete the request */
// lower device object failed to start
resource_list->Release();
// complete the request
IoCompleteRequest(Irp, IO_NO_INCREMENT);
/* return result */
// return result
return Status;
}
/* sanity check */
ASSERT(DeviceExt->StartDevice);
/* Call the StartDevice routine */
// sanity check
//PC_ASSERT(DeviceExt->StartDevice);
// Call the StartDevice routine
DPRINT("Calling StartDevice at 0x%8p\n", DeviceExt->StartDevice);
Status = DeviceExt->StartDevice(DeviceObject, Irp, resource_list);
if (!NT_SUCCESS(Status))
@@ -102,7 +89,7 @@ PortClsPnp(
return Status;
}
/* Assign the resource list to our extension */
// Assign the resource list to our extension
DeviceExt->resources = resource_list;
Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -110,13 +97,13 @@ PortClsPnp(
return Status;
case IRP_MN_REMOVE_DEVICE:
/* Clean up */
// Clean up
DPRINT("IRP_MN_REMOVE_DEVICE\n");
DeviceExt->resources->lpVtbl->Release(DeviceExt->resources);
DeviceExt->resources->Release();
IoDeleteDevice(DeviceObject);
/* Do not complete? */
// Do not complete?
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
@@ -146,10 +133,6 @@ PortClsPnp(
return STATUS_UNSUCCESSFUL;
}
/*
Power management. Handles IRP_MJ_POWER
(not implemented)
*/
NTSTATUS
NTAPI
PortClsPower(
@@ -158,7 +141,7 @@ PortClsPower(
{
DPRINT("PortClsPower called\n");
/* TODO */
// TODO
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
@@ -167,10 +150,6 @@ PortClsPower(
return STATUS_SUCCESS;
}
/*
System control. Handles IRP_MJ_SYSTEM_CONTROL
(not implemented)
*/
NTSTATUS
NTAPI
PortClsSysControl(
@@ -179,7 +158,7 @@ PortClsSysControl(
{
DPRINT("PortClsSysControl called\n");
/* TODO */
// TODO
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
@@ -199,33 +178,33 @@ PortClsShutdown(
PPHYSICAL_CONNECTION Connection;
DPRINT("PortClsShutdown called\n");
/* get device extension */
// get device extension
DeviceExtension = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
while(!IsListEmpty(&DeviceExtension->PhysicalConnectionList))
{
/* get connection entry */
// get connection entry
Entry = RemoveHeadList(&DeviceExtension->PhysicalConnectionList);
Connection = (PPHYSICAL_CONNECTION)CONTAINING_RECORD(Entry, PHYSICAL_CONNECTION, Entry);
if (Connection->FromSubDevice)
{
/* release subdevice */
Connection->FromSubDevice->lpVtbl->Release(Connection->FromSubDevice);
// release subdevice
Connection->FromSubDevice->Release();
}
if (Connection->ToSubDevice)
{
/* release subdevice */
Connection->ToSubDevice->lpVtbl->Release(Connection->ToSubDevice);
// release subdevice
Connection->ToSubDevice->Release();
}
FreeItem(Connection, TAG_PORTCLASS);
}
if (DeviceExtension->AdapterPowerManagement)
{
/* release adapter power management */
DPRINT1("Power %u\n", DeviceExtension->AdapterPowerManagement->lpVtbl->Release(DeviceExtension->AdapterPowerManagement));
// release adapter power management
DPRINT1("Power %u\n", DeviceExtension->AdapterPowerManagement->Release());
}
Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -235,19 +214,8 @@ PortClsShutdown(
return STATUS_SUCCESS;
}
/*
==========================================================================
API EXPORTS
==========================================================================
*/
/*
Drivers may implement their own IRP handlers. If a driver decides to let
PortCls handle the IRP, it can do so by calling this.
*/
NTSTATUS NTAPI
NTSTATUS
NTAPI
PcDispatchIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
@@ -260,7 +228,7 @@ PcDispatchIrp(
switch ( IoStack->MajorFunction )
{
/* PortCls */
// PortCls
case IRP_MJ_CREATE :
return PortClsCreate(DeviceObject, Irp);
@@ -287,7 +255,7 @@ PcDispatchIrp(
break;
};
/* If we reach here, we just complete the IRP */
// If we reach here, we just complete the IRP
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -295,9 +263,7 @@ PcDispatchIrp(
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcCompleteIrp(
@@ -305,9 +271,11 @@ PcCompleteIrp(
IN PIRP Irp,
IN NTSTATUS Status)
{
ASSERT(DeviceObject);
ASSERT(Irp);
ASSERT(Status != STATUS_PENDING);
#if 0
PC_ASSERT(DeviceObject);
PC_ASSERT(Irp);
PC_ASSERT(Status != STATUS_PENDING);
#endif
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -329,11 +297,28 @@ CompletionRoutine(
return STATUS_MORE_PROCESSING_REQUIRED;
}
#undef IoSetCompletionRoutine
#define IoSetCompletionRoutine(_Irp, \
_CompletionRoutine, \
_Context, \
_InvokeOnSuccess, \
_InvokeOnError, \
_InvokeOnCancel) \
{ \
PIO_STACK_LOCATION _IrpSp; \
_IrpSp = IoGetNextIrpStackLocation(_Irp); \
_IrpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)(_CompletionRoutine); \
_IrpSp->Context = (_Context); \
_IrpSp->Control = 0; \
if (_InvokeOnSuccess) _IrpSp->Control = SL_INVOKE_ON_SUCCESS; \
if (_InvokeOnError) _IrpSp->Control |= SL_INVOKE_ON_ERROR; \
if (_InvokeOnCancel) _IrpSp->Control |= SL_INVOKE_ON_CANCEL; \
}
/*
* @implemented
*/
NTSTATUS NTAPI
NTSTATUS
NTAPI
PcForwardIrpSynchronous(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
@@ -342,23 +327,23 @@ PcForwardIrpSynchronous(
PPCLASS_DEVICE_EXTENSION DeviceExt;
NTSTATUS Status;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* initialize the notification event */
// initialize the notification event
KeInitializeEvent(&Event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, CompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE);
/* now call the driver */
// now call the driver
Status = IoCallDriver(DeviceExt->PrevDeviceObject, Irp);
/* did the request complete yet */
// did the request complete yet
if (Status == STATUS_PENDING)
{
/* not yet, lets wait a bit */
// not yet, lets wait a bit
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}
@@ -1,563 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/irpstream.c
* PURPOSE: IRP Stream handling
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IIrpQueueVtbl *lpVtbl;
LONG ref;
ULONG CurrentOffset;
LONG NumMappings;
ULONG NumDataAvailable;
BOOL StartStream;
KSPIN_CONNECT *ConnectDetails;
PKSDATAFORMAT_WAVEFORMATEX DataFormat;
KSPIN_LOCK IrpListLock;
LIST_ENTRY IrpList;
LIST_ENTRY FreeIrpList;
PIRP Irp;
PVOID SilenceBuffer;
ULONG OutOfMapping;
ULONG MaxFrameSize;
ULONG Alignment;
ULONG MinimumDataThreshold;
}IIrpQueueImpl;
NTSTATUS
NTAPI
IIrpQueue_fnQueryInterface(
IIrpQueue* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
_InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IIrpQueue_fnAddRef(
IIrpQueue* iface)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
return _InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IIrpQueue_fnRelease(
IIrpQueue* iface)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
_InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
NTSTATUS
NTAPI
IIrpQueue_fnInit(
IN IIrpQueue *iface,
IN KSPIN_CONNECT *ConnectDetails,
IN PKSDATAFORMAT DataFormat,
IN PDEVICE_OBJECT DeviceObject,
IN ULONG FrameSize,
IN ULONG Alignment,
IN PVOID SilenceBuffer)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
This->ConnectDetails = ConnectDetails;
This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
This->MaxFrameSize = FrameSize;
This->SilenceBuffer = SilenceBuffer;
This->Alignment = Alignment;
This->MinimumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nAvgBytesPerSec / 3;
InitializeListHead(&This->IrpList);
InitializeListHead(&This->FreeIrpList);
KeInitializeSpinLock(&This->IrpListLock);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IIrpQueue_fnAddMapping(
IN IIrpQueue *iface,
IN PUCHAR Buffer,
IN ULONG BufferSize,
IN PIRP Irp)
{
PKSSTREAM_HEADER Header;
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IoStack;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
/* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (!Buffer)
{
/* probe the stream irp */
Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_ALLOWFORMATCHANGE | KSPROBE_SYSTEMADDRESS, 0);
/* check for success */
if (!NT_SUCCESS(Status))
{
DPRINT1("KsProbeStreamIrp failed with %x\n", Status);
return Status;
}
/* get the stream header */
Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
ASSERT(Header);
ASSERT(Irp->MdlAddress);
if (Irp->RequestorMode != KernelMode)
{
/* use allocated mdl */
Header->Data = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
}
}
else
{
/* HACK */
Header = (PKSSTREAM_HEADER)Buffer;
}
/* HACK */
Irp->Tail.Overlay.DriverContext[2] = (PVOID)Header;
/* sanity check */
ASSERT(Header);
/* dont exceed max frame size */
//ASSERT(This->MaxFrameSize >= Header->DataUsed);
/* increment num mappings */
InterlockedIncrement(&This->NumMappings);
/* increment num data available */
This->NumDataAvailable += Header->DataUsed;
/* mark irp as pending */
IoMarkIrpPending(Irp);
/* add irp to cancelable queue */
KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL);
/* done */
return Status;
}
NTSTATUS
NTAPI
IIrpQueue_fnGetMapping(
IN IIrpQueue *iface,
OUT PUCHAR * Buffer,
OUT PULONG BufferSize)
{
PIRP Irp;
ULONG Offset;
//PIO_STACK_LOCATION IoStack;
PKSSTREAM_HEADER StreamHeader;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
/* check if there is an irp in the partially processed */
if (This->Irp)
{
/* use last irp */
if (This->Irp->Cancel == FALSE)
{
Irp = This->Irp;
Offset = This->CurrentOffset;
}
else
{
/* irp has been cancelled */
This->Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(This->Irp, IO_NO_INCREMENT);
This->Irp = Irp = NULL;
}
}
else
{
/* get a fresh new irp from the queue */
This->Irp = Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
This->CurrentOffset = Offset = 0;
}
if (!Irp)
{
/* no irp available, use silence buffer */
*Buffer = This->SilenceBuffer;
*BufferSize = This->MaxFrameSize;
/* flag for port wave pci driver */
This->OutOfMapping = TRUE;
/* indicate flag to restart fast buffering */
This->StartStream = FALSE;
return STATUS_SUCCESS;
}
#if 0
/* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* get stream header */
StreamHeader = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
#else
/* HACK get stream header */
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
#endif
/* sanity check */
ASSERT(StreamHeader);
/* store buffersize */
*BufferSize = StreamHeader->DataUsed - Offset;
/* store buffer */
*Buffer = &((PUCHAR)StreamHeader->Data)[Offset];
/* unset flag that no irps are available */
This->OutOfMapping = FALSE;
return STATUS_SUCCESS;
}
VOID
NTAPI
IIrpQueue_fnUpdateMapping(
IN IIrpQueue *iface,
IN ULONG BytesWritten)
{
//PIO_STACK_LOCATION IoStack;
PKSSTREAM_HEADER StreamHeader;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
if (!This->Irp)
{
/* silence buffer was used */
return;
}
#if 0
/* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(This->Irp);
/* get stream header */
StreamHeader = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
#else
/* HACK get stream header */
StreamHeader = (PKSSTREAM_HEADER)This->Irp->Tail.Overlay.DriverContext[2];
#endif
/* sanity check */
ASSERT(StreamHeader);
/* add to current offset */
This->CurrentOffset += BytesWritten;
/* decrement available data counter */
This->NumDataAvailable -= BytesWritten;
if (This->CurrentOffset >= StreamHeader->DataUsed)
{
/* irp has been processed completly */
This->Irp->IoStatus.Status = STATUS_SUCCESS;
/* frame extend contains the original request size, DataUsed contains the real buffer size
* is different when kmixer performs channel conversion, upsampling etc
*/
This->Irp->IoStatus.Information = StreamHeader->FrameExtent;
if (This->Irp->RequestorMode != KernelMode)
{
/* HACK - WDMAUD should pass PKSSTREAM_HEADERs */
ExFreePool(StreamHeader->Data);
ExFreePool(StreamHeader);
}
/* complete the request */
IoCompleteRequest(This->Irp, IO_SOUND_INCREMENT);
/* remove irp as it is complete */
This->Irp = NULL;
This->CurrentOffset = 0;
}
}
ULONG
NTAPI
IIrpQueue_fnNumMappings(
IN IIrpQueue *iface)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
/* returns the amount of mappings available */
return This->NumMappings;
}
ULONG
NTAPI
IIrpQueue_fnNumData(
IN IIrpQueue *iface)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
/* returns the amount of audio stream data available */
return This->NumDataAvailable;
}
BOOL
NTAPI
IIrpQueue_fnMinimumDataAvailable(
IN IIrpQueue *iface)
{
BOOL Result;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
if (This->StartStream)
return TRUE;
if (This->MinimumDataThreshold < This->NumDataAvailable)
{
This->StartStream = TRUE;
Result = TRUE;
}
else
{
Result = FALSE;
}
return Result;
}
BOOL
NTAPI
IIrpQueue_fnCancelBuffers(
IN IIrpQueue *iface)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
This->StartStream = FALSE;
return TRUE;
}
VOID
NTAPI
IIrpQueue_fnUpdateFormat(
IN IIrpQueue *iface,
PKSDATAFORMAT DataFormat)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
This->MinimumDataThreshold = This->DataFormat->WaveFormatEx.nAvgBytesPerSec / 3;
This->StartStream = FALSE;
This->NumDataAvailable = 0;
}
NTSTATUS
NTAPI
IIrpQueue_fnGetMappingWithTag(
IN IIrpQueue *iface,
IN PVOID Tag,
OUT PPHYSICAL_ADDRESS PhysicalAddress,
OUT PVOID *VirtualAddress,
OUT PULONG ByteCount,
OUT PULONG Flags)
{
PKSSTREAM_HEADER StreamHeader;
PIRP Irp;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
*Flags = 0;
ASSERT(Tag != NULL);
/* get an irp from the queue */
Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
/* check if there is an irp */
if (!Irp)
{
/* no irp available */
This->OutOfMapping = TRUE;
This->StartStream = FALSE;
return STATUS_UNSUCCESSFUL;
}
/* HACK get stream header */
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
/* store mapping in the free list */
ExInterlockedInsertTailList(&This->FreeIrpList, &Irp->Tail.Overlay.ListEntry, &This->IrpListLock);
/* return mapping */
*PhysicalAddress = MmGetPhysicalAddress(StreamHeader->Data);
*VirtualAddress = StreamHeader->Data;
*ByteCount = StreamHeader->DataUsed;
/* decrement mapping count */
InterlockedDecrement(&This->NumMappings);
/* decrement num data available */
This->NumDataAvailable -= StreamHeader->DataUsed;
/* store tag in irp */
Irp->Tail.Overlay.DriverContext[3] = Tag;
/* done */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IIrpQueue_fnReleaseMappingWithTag(
IN IIrpQueue *iface,
IN PVOID Tag)
{
PIRP Irp;
PLIST_ENTRY CurEntry;
PKSSTREAM_HEADER StreamHeader;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p\n", Tag);
/* remove irp from used list */
CurEntry = ExInterlockedRemoveHeadList(&This->FreeIrpList, &This->IrpListLock);
/* sanity check */
ASSERT(CurEntry);
/* get irp from list entry */
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
/* HACK get stream header */
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
/* driver must release items in the same order */
ASSERT(Irp->Tail.Overlay.DriverContext[3] == Tag);
/* irp has been processed completly */
Irp->IoStatus.Status = STATUS_SUCCESS;
/* frame extend contains the original request size, DataUsed contains the real buffer size
* is different when kmixer performs channel conversion, upsampling etc
*/
Irp->IoStatus.Information = StreamHeader->FrameExtent;
/* free stream data, no tag as wdmaud.drv does it atm */
ExFreePool(StreamHeader->Data);
/* free stream header, no tag as wdmaud.drv allocates it atm */
ExFreePool(StreamHeader);
/* complete the request */
IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
return STATUS_SUCCESS;
}
BOOL
NTAPI
IIrpQueue_fnHasLastMappingFailed(
IN IIrpQueue *iface)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
return This->OutOfMapping;
}
VOID
NTAPI
IIrpQueue_fnPrintQueueStatus(
IN IIrpQueue *iface)
{
}
VOID
NTAPI
IIrpQueue_fnSetMinimumDataThreshold(
IN IIrpQueue *iface,
ULONG MinimumDataThreshold)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
This->MinimumDataThreshold = MinimumDataThreshold;
}
ULONG
NTAPI
IIrpQueue_fnGetMinimumDataThreshold(
IN IIrpQueue *iface)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
return This->MinimumDataThreshold;
}
static IIrpQueueVtbl vt_IIrpQueue =
{
IIrpQueue_fnQueryInterface,
IIrpQueue_fnAddRef,
IIrpQueue_fnRelease,
IIrpQueue_fnInit,
IIrpQueue_fnAddMapping,
IIrpQueue_fnGetMapping,
IIrpQueue_fnUpdateMapping,
IIrpQueue_fnNumMappings,
IIrpQueue_fnNumData,
IIrpQueue_fnMinimumDataAvailable,
IIrpQueue_fnCancelBuffers,
IIrpQueue_fnUpdateFormat,
IIrpQueue_fnGetMappingWithTag,
IIrpQueue_fnReleaseMappingWithTag,
IIrpQueue_fnHasLastMappingFailed,
IIrpQueue_fnPrintQueueStatus,
IIrpQueue_fnSetMinimumDataThreshold,
IIrpQueue_fnGetMinimumDataThreshold
};
NTSTATUS
NTAPI
NewIrpQueue(
IN IIrpQueue **Queue)
{
IIrpQueueImpl *This = AllocateItem(NonPagedPool, sizeof(IIrpQueueImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->ref = 1;
This->lpVtbl = &vt_IIrpQueue;
*Queue = (IIrpQueue*)This;
return STATUS_SUCCESS;
}
@@ -0,0 +1,499 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/irpstream.cpp
* PURPOSE: IRP Stream handling
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CIrpQueue : public IIrpQueue
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IIrpQueue;
CIrpQueue(IUnknown *OuterUnknown){}
virtual ~CIrpQueue(){}
protected:
ULONG m_CurrentOffset;
LONG m_NumMappings;
ULONG m_NumDataAvailable;
BOOL m_StartStream;
KSPIN_CONNECT * m_ConnectDetails;
PKSDATAFORMAT_WAVEFORMATEX m_DataFormat;
KSPIN_LOCK m_IrpListLock;
LIST_ENTRY m_IrpList;
LIST_ENTRY m_FreeIrpList;
PIRP m_Irp;
PVOID m_SilenceBuffer;
ULONG m_OutOfMapping;
ULONG m_MaxFrameSize;
ULONG m_Alignment;
ULONG m_MinimumDataThreshold;
LONG m_Ref;
};
NTSTATUS
NTAPI
CIrpQueue::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
if (IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CIrpQueue::Init(
IN KSPIN_CONNECT *ConnectDetails,
IN PKSDATAFORMAT DataFormat,
IN PDEVICE_OBJECT DeviceObject,
IN ULONG FrameSize,
IN ULONG Alignment,
IN PVOID SilenceBuffer)
{
m_ConnectDetails = ConnectDetails;
m_DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
m_MaxFrameSize = FrameSize;
m_SilenceBuffer = SilenceBuffer;
m_Alignment = Alignment;
m_MinimumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nAvgBytesPerSec / 3;
InitializeListHead(&m_IrpList);
InitializeListHead(&m_FreeIrpList);
KeInitializeSpinLock(&m_IrpListLock);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CIrpQueue::AddMapping(
IN PUCHAR Buffer,
IN ULONG BufferSize,
IN PIRP Irp)
{
PKSSTREAM_HEADER Header;
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IoStack;
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (!Buffer)
{
// probe the stream irp
Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_ALLOWFORMATCHANGE | KSPROBE_SYSTEMADDRESS, 0);
// check for success
if (!NT_SUCCESS(Status))
{
DPRINT1("KsProbeStreamIrp failed with %x\n", Status);
return Status;
}
// get the stream header
Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
PC_ASSERT(Header);
PC_ASSERT(Irp->MdlAddress);
if (Irp->RequestorMode != KernelMode)
{
// use allocated mdl
Header->Data = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
}
}
else
{
// HACK
Header = (PKSSTREAM_HEADER)Buffer;
}
// HACK
Irp->Tail.Overlay.DriverContext[2] = (PVOID)Header;
// sanity check
PC_ASSERT(Header);
// dont exceed max frame size
PC_ASSERT(m_MaxFrameSize >= Header->DataUsed);
// increment num mappings
InterlockedIncrement(&m_NumMappings);
// increment num data available
m_NumDataAvailable += Header->DataUsed;
// mark irp as pending
IoMarkIrpPending(Irp);
// add irp to cancelable queue
KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, Irp, KsListEntryTail, NULL);
// done
return Status;
}
NTSTATUS
NTAPI
CIrpQueue::GetMapping(
OUT PUCHAR * Buffer,
OUT PULONG BufferSize)
{
PIRP Irp;
ULONG Offset;
//PIO_STACK_LOCATION IoStack;
PKSSTREAM_HEADER StreamHeader;
// check if there is an irp in the partially processed
if (m_Irp)
{
// use last irp
if (m_Irp->Cancel == FALSE)
{
Irp = m_Irp;
Offset = m_CurrentOffset;
}
else
{
// irp has been cancelled
m_Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
m_Irp = Irp = NULL;
}
}
else
{
// get a fresh new irp from the queue
m_Irp = Irp = KsRemoveIrpFromCancelableQueue(&m_IrpList, &m_IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
m_CurrentOffset = Offset = 0;
}
if (!Irp)
{
// no irp available, use silence buffer
*Buffer = (PUCHAR)m_SilenceBuffer;
*BufferSize = m_MaxFrameSize;
// flag for port wave pci driver
m_OutOfMapping = TRUE;
// indicate flag to restart fast buffering
m_StartStream = FALSE;
return STATUS_SUCCESS;
}
#if 0
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
// get stream header
StreamHeader = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
#else
// HACK get stream header
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
#endif
// sanity check
PC_ASSERT(StreamHeader);
// store buffersize
*BufferSize = StreamHeader->DataUsed - Offset;
// store buffer
*Buffer = &((PUCHAR)StreamHeader->Data)[Offset];
// unset flag that no irps are available
m_OutOfMapping = FALSE;
return STATUS_SUCCESS;
}
VOID
NTAPI
CIrpQueue::UpdateMapping(
IN ULONG BytesWritten)
{
//PIO_STACK_LOCATION IoStack;
PKSSTREAM_HEADER StreamHeader;
if (!m_Irp)
{
// silence buffer was used
return;
}
#if 0
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(m_Irp);
// get stream header
StreamHeader = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
#else
// HACK get stream header
StreamHeader = (PKSSTREAM_HEADER)m_Irp->Tail.Overlay.DriverContext[2];
#endif
// sanity check
// ASSERT(StreamHeader);
// add to current offset
m_CurrentOffset += BytesWritten;
// decrement available data counter
m_NumDataAvailable -= BytesWritten;
if (m_CurrentOffset >= StreamHeader->DataUsed)
{
// irp has been processed completly
m_Irp->IoStatus.Status = STATUS_SUCCESS;
// frame extend contains the original request size, DataUsed contains the real buffer size
//is different when kmixer performs channel conversion, upsampling etc
m_Irp->IoStatus.Information = StreamHeader->FrameExtent;
if (m_Irp->RequestorMode != KernelMode)
{
// HACK - WDMAUD should pass PKSSTREAM_HEADERs
ExFreePool(StreamHeader->Data);
ExFreePool(StreamHeader);
}
// complete the request
IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT);
// remove irp as it is complete
m_Irp = NULL;
m_CurrentOffset = 0;
}
}
ULONG
NTAPI
CIrpQueue::NumMappings()
{
// returns the amount of mappings available
return m_NumMappings;
}
ULONG
NTAPI
CIrpQueue::NumData()
{
// returns the amount of audio stream data available
return m_NumDataAvailable;
}
BOOL
NTAPI
CIrpQueue::MinimumDataAvailable()
{
BOOL Result;
if (m_StartStream)
return TRUE;
if (m_MinimumDataThreshold < m_NumDataAvailable)
{
m_StartStream = TRUE;
Result = TRUE;
}
else
{
Result = FALSE;
}
return Result;
}
BOOL
NTAPI
CIrpQueue::CancelBuffers()
{
m_StartStream = FALSE;
return TRUE;
}
VOID
NTAPI
CIrpQueue::UpdateFormat(
PKSDATAFORMAT DataFormat)
{
m_DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
m_MinimumDataThreshold = m_DataFormat->WaveFormatEx.nAvgBytesPerSec / 3;
m_StartStream = FALSE;
m_NumDataAvailable = 0;
}
NTSTATUS
NTAPI
CIrpQueue::GetMappingWithTag(
IN PVOID Tag,
OUT PPHYSICAL_ADDRESS PhysicalAddress,
OUT PVOID *VirtualAddress,
OUT PULONG ByteCount,
OUT PULONG Flags)
{
PKSSTREAM_HEADER StreamHeader;
PIRP Irp;
*Flags = 0;
PC_ASSERT(Tag != NULL);
// get an irp from the queue
Irp = KsRemoveIrpFromCancelableQueue(&m_IrpList, &m_IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
// check if there is an irp
if (!Irp)
{
// no irp available
m_OutOfMapping = TRUE;
m_StartStream = FALSE;
return STATUS_UNSUCCESSFUL;
}
// HACK get stream header
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
// store mapping in the free list
ExInterlockedInsertTailList(&m_FreeIrpList, &Irp->Tail.Overlay.ListEntry, &m_IrpListLock);
// return mapping
*PhysicalAddress = MmGetPhysicalAddress(StreamHeader->Data);
*VirtualAddress = StreamHeader->Data;
*ByteCount = StreamHeader->DataUsed;
// decrement mapping count
InterlockedDecrement(&m_NumMappings);
// decrement num data available
m_NumDataAvailable -= StreamHeader->DataUsed;
// store tag in irp
Irp->Tail.Overlay.DriverContext[3] = Tag;
// done
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CIrpQueue::ReleaseMappingWithTag(
IN PVOID Tag)
{
PIRP Irp;
PLIST_ENTRY CurEntry;
PKSSTREAM_HEADER StreamHeader;
DPRINT("CIrpQueue::ReleaseMappingWithTag Tag %p\n", Tag);
// remove irp from used list
CurEntry = ExInterlockedRemoveHeadList(&m_FreeIrpList, &m_IrpListLock);
// sanity check
PC_ASSERT(CurEntry);
// get irp from list entry
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
// HACK get stream header
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
// driver must release items in the same order
PC_ASSERT(Irp->Tail.Overlay.DriverContext[3] == Tag);
// irp has been processed completly
Irp->IoStatus.Status = STATUS_SUCCESS;
// frame extend contains the original request size, DataUsed contains the real buffer size
// is different when kmixer performs channel conversion, upsampling etc
Irp->IoStatus.Information = StreamHeader->FrameExtent;
// free stream data, no tag as wdmaud.drv does it atm
ExFreePool(StreamHeader->Data);
// free stream header, no tag as wdmaud.drv allocates it atm
ExFreePool(StreamHeader);
// complete the request
IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
return STATUS_SUCCESS;
}
BOOL
NTAPI
CIrpQueue::HasLastMappingFailed()
{
return m_OutOfMapping;
}
VOID
NTAPI
CIrpQueue::PrintQueueStatus()
{
}
VOID
NTAPI
CIrpQueue::SetMinimumDataThreshold(
ULONG MinimumDataThreshold)
{
m_MinimumDataThreshold = MinimumDataThreshold;
}
ULONG
NTAPI
CIrpQueue::GetMinimumDataThreshold()
{
return m_MinimumDataThreshold;
}
NTSTATUS
NTAPI
NewIrpQueue(
IN IIrpQueue **Queue)
{
CIrpQueue *This = new(NonPagedPool, TAG_PORTCLASS)CIrpQueue(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->AddRef();
*Queue = (IIrpQueue*)This;
return STATUS_SUCCESS;
}
@@ -1,17 +1,15 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/miniport.c
* FILE: drivers/wdm/audio/backpln/portcls/miniport.cpp
* PURPOSE: Miniport construction api
* PROGRAMMER: Andrew Greenwood
*/
#include "private.h"
#include "private.hpp"
/*
* @implemented
*/
NTSTATUS NTAPI
NTSTATUS
NTAPI
PcNewMiniport(
OUT PMINIPORT* OutMiniport,
IN REFCLSID ClassId)
@@ -19,7 +17,7 @@ PcNewMiniport(
NTSTATUS Status = STATUS_INVALID_PARAMETER;
DPRINT("PcNewMiniport entered\n");
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!OutMiniport)
{
@@ -27,14 +25,14 @@ PcNewMiniport(
return STATUS_INVALID_PARAMETER;
}
if (IsEqualGUIDAligned(ClassId, &CLSID_MiniportDriverDMusUART) ||
IsEqualGUIDAligned(ClassId, &CLSID_MiniportDriverUart) ||
IsEqualGUIDAligned(ClassId, &CLSID_MiniportDriverDMusUARTCapture))
if (IsEqualGUIDAligned(ClassId, CLSID_MiniportDriverDMusUART) ||
IsEqualGUIDAligned(ClassId, CLSID_MiniportDriverUart) ||
IsEqualGUIDAligned(ClassId, CLSID_MiniportDriverDMusUARTCapture))
{
Status = NewMiniportDMusUART(OutMiniport, ClassId);
}
else if (IsEqualGUIDAligned(ClassId, &CLSID_MiniportDriverFmSynth) ||
IsEqualGUIDAligned(ClassId, &CLSID_MiniportDriverFmSynthWithVol))
else if (IsEqualGUIDAligned(ClassId, CLSID_MiniportDriverFmSynth) ||
IsEqualGUIDAligned(ClassId, CLSID_MiniportDriverFmSynthWithVol))
{
Status = NewMiniportFmSynth(OutMiniport, ClassId);
}
@@ -1,172 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/miniport_dmus.c
* PURPOSE: DirectMusic miniport
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IMiniportDMusVtbl *lpVtbl;
LONG ref;
CLSID ClassId;
}IMiniportDMusImpl;
/* IUnknown methods */
NTSTATUS
NTAPI
IMiniportDMus_fnQueryInterface(
IMiniportDMus* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IMiniportDMusImpl * This = (IMiniportDMusImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IMiniportDMus))
{
*Output = &This->lpVtbl;
_InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IMiniportDMus_fnAddRef(
IMiniportDMus* iface)
{
IMiniportDMusImpl * This = (IMiniportDMusImpl*)iface;
return _InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IMiniportDMust_fnRelease(
IMiniportDMus* iface)
{
IMiniportDMusImpl * This = (IMiniportDMusImpl*)iface;
_InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
/* IMiniport methods */
NTSTATUS
NTAPI
IMiniportDMus_fnDataRangeIntersection(
IN IMiniportDMus * iface,
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
IMiniportDMus_fnGetDescription(
IN IMiniportDMus * iface,
OUT PPCFILTER_DESCRIPTOR *Description
)
{
return STATUS_UNSUCCESSFUL;
}
/* IMinIMiniportDMus methods */
HRESULT
NTAPI
IMiniportDMus_fnInit(
IN IMiniportDMus * iface,
IN PUNKNOWN pUnknownAdapter,
IN PRESOURCELIST pResourceList,
IN PPORTDMUS pPort,
OUT PSERVICEGROUP *ppServiceGroup
)
{
return STATUS_UNSUCCESSFUL;
}
HRESULT
NTAPI
IMiniportDMus_fnNewStream(
IN IMiniportDMus * iface,
OUT PMXF *ppMXF,
IN PUNKNOWN pOuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN ULONG uPinId,
IN DMUS_STREAM_TYPE StreamType,
IN PKSDATAFORMAT pDataFormat,
OUT PSERVICEGROUP *ppServiceGroup,
IN PAllocatorMXF pAllocatorMXF,
IN PMASTERCLOCK pMasterClock,
OUT PULONGLONG puuSchedulePreFetch
)
{
return STATUS_UNSUCCESSFUL;
}
VOID
NTAPI
IMiniportDMus_fnService(
IN IMiniportDMus * iface)
{
}
static IMiniportDMusVtbl vt_PortDMusVtbl =
{
/* IUnknown */
IMiniportDMus_fnQueryInterface,
IMiniportDMus_fnAddRef,
IMiniportDMust_fnRelease,
/* IMiniport */
IMiniportDMus_fnGetDescription,
IMiniportDMus_fnDataRangeIntersection,
/* IMiniportDMus */
IMiniportDMus_fnInit,
IMiniportDMus_fnService,
IMiniportDMus_fnNewStream
};
NTSTATUS
NewMiniportDMusUART(
OUT PMINIPORT* OutMiniport,
IN REFCLSID ClassId)
{
IMiniportDMusImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IMiniportDMusImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
/* Initialize IMiniportDMus */
RtlCopyMemory(&This->ClassId, ClassId, sizeof(CLSID));
This->ref = 1;
This->lpVtbl = &vt_PortDMusVtbl;
*OutMiniport = (PMINIPORT)&This->lpVtbl;
return STATUS_SUCCESS;
}
@@ -0,0 +1,135 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/miniport_dmus.cpp
* PURPOSE: DirectMusic miniport
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CMiniportDMus : public IMiniportDMus
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IMiniportDMus;
CMiniportDMus(IUnknown *OuterUnknown){}
virtual ~CMiniportDMus(){}
protected:
LONG m_Ref;
};
// IUnknown methods
NTSTATUS
NTAPI
CMiniportDMus::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
if (IsEqualGUIDAligned(refiid, IID_IMiniportDMus))
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
// IMiniport methods
NTSTATUS
NTAPI
CMiniportDMus::DataRangeIntersection(
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CMiniportDMus::GetDescription(
OUT PPCFILTER_DESCRIPTOR *Description)
{
return STATUS_UNSUCCESSFUL;
}
HRESULT
NTAPI
CMiniportDMus::Init(
IN PUNKNOWN pUnknownAdapter,
IN PRESOURCELIST pResourceList,
IN PPORTDMUS pPort,
OUT PSERVICEGROUP *ppServiceGroup
)
{
return STATUS_UNSUCCESSFUL;
}
HRESULT
NTAPI
CMiniportDMus::NewStream(
OUT PMXF *ppMXF,
IN PUNKNOWN pOuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN ULONG uPinId,
IN DMUS_STREAM_TYPE StreamType,
IN PKSDATAFORMAT pDataFormat,
OUT PSERVICEGROUP *ppServiceGroup,
IN PAllocatorMXF pAllocatorMXF,
IN PMASTERCLOCK pMasterClock,
OUT PULONGLONG puuSchedulePreFetch
)
{
return STATUS_UNSUCCESSFUL;
}
VOID
NTAPI
CMiniportDMus::Service()
{
}
NTSTATUS
NewMiniportDMusUART(
OUT PMINIPORT* OutMiniport,
IN REFCLSID ClassId)
{
CMiniportDMus * This;
This = new(NonPagedPool, TAG_PORTCLASS)CMiniportDMus(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
*OutMiniport = (PMINIPORT)This;
This->AddRef();
return STATUS_SUCCESS;
}
@@ -1,12 +1,12 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/miniport_fmsynth.c
* FILE: drivers/wdm/audio/backpln/portcls/miniport_fmsynth.cpp
* PURPOSE: Miniport FM Synth
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
#include "private.hpp"
NTSTATUS NewMiniportFmSynth(
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,808 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/pin_dmus.cpp
* PURPOSE: DMus IRP Audio Pin
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortPinDMus : public IPortPinDMus
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortPinDMus;
IMP_IServiceSink;
IMP_IMasterClock;
IMP_IAllocatorMXF;
CPortPinDMus(IUnknown * OuterUnknown){}
virtual ~CPortPinDMus(){}
protected:
VOID TransferMidiDataToDMus();
VOID TransferMidiData();
VOID NTAPI SetStreamState(IN KSSTATE State);
IPortDMus * m_Port;
IPortFilterDMus * m_Filter;
KSPIN_DESCRIPTOR * m_KsPinDescriptor;
PMINIPORTDMUS m_Miniport;
PSERVICEGROUP m_ServiceGroup;
PMXF m_Mxf;
ULONGLONG m_SchedulePreFetch;
NPAGED_LOOKASIDE_LIST m_LookAsideEvent;
NPAGED_LOOKASIDE_LIST m_LookAsideBuffer;
PMINIPORTMIDI m_MidiMiniport;
PMINIPORTMIDISTREAM m_MidiStream;
KSSTATE m_State;
PKSDATAFORMAT m_Format;
KSPIN_CONNECT * m_ConnectDetails;
DMUS_STREAM_TYPE m_Capture;
PDEVICE_OBJECT m_DeviceObject;
IIrpQueue * m_IrpQueue;
ULONG m_TotalPackets;
ULONG m_PreCompleted;
ULONG m_PostCompleted;
ULONG m_LastTag;
LONG m_Ref;
friend VOID NTAPI SetStreamWorkerRoutineDMus(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
friend VOID NTAPI CloseStreamRoutineDMus(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
};
typedef struct
{
DMUS_KERNEL_EVENT Event;
PVOID Tag;
}DMUS_KERNEL_EVENT_WITH_TAG, *PDMUS_KERNEL_EVENT_WITH_TAG;
typedef struct
{
CPortPinDMus *Pin;
PIO_WORKITEM WorkItem;
KSSTATE State;
}SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
//==================================================================================================================================
NTSTATUS
NTAPI
CPortPinDMus::GetTime(OUT REFERENCE_TIME *prtTime)
{
UNIMPLEMENTED
return STATUS_SUCCESS;
}
//==================================================================================================================================
NTSTATUS
NTAPI
CPortPinDMus::GetMessage(
OUT PDMUS_KERNEL_EVENT * ppDMKEvt)
{
PVOID Buffer;
Buffer = ExAllocateFromNPagedLookasideList(&m_LookAsideEvent);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
*ppDMKEvt = (PDMUS_KERNEL_EVENT)Buffer;
RtlZeroMemory(Buffer, sizeof(DMUS_KERNEL_EVENT));
return STATUS_SUCCESS;
}
USHORT
NTAPI
CPortPinDMus::GetBufferSize()
{
return PAGE_SIZE;
}
NTSTATUS
NTAPI
CPortPinDMus::GetBuffer(
OUT PBYTE * ppBuffer)
{
PVOID Buffer;
Buffer = ExAllocateFromNPagedLookasideList(&m_LookAsideBuffer);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
*ppBuffer = (PBYTE)Buffer;
RtlZeroMemory(Buffer, PAGE_SIZE);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortPinDMus::PutBuffer(
IN PBYTE pBuffer)
{
PDMUS_KERNEL_EVENT_WITH_TAG Event = (PDMUS_KERNEL_EVENT_WITH_TAG)pBuffer;
m_IrpQueue->ReleaseMappingWithTag(Event->Tag);
ExFreeToNPagedLookasideList(&m_LookAsideBuffer, pBuffer);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortPinDMus::SetState(
IN KSSTATE State)
{
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
CPortPinDMus::PutMessage(
IN PDMUS_KERNEL_EVENT pDMKEvt)
{
ExFreeToNPagedLookasideList(&m_LookAsideEvent, pDMKEvt);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortPinDMus::ConnectOutput(
IN PMXF sinkMXF)
{
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
CPortPinDMus::DisconnectOutput(
IN PMXF sinkMXF)
{
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
//==================================================================================================================================
VOID
NTAPI
SetStreamWorkerRoutineDMus(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
CPortPinDMus* This;
KSSTATE State;
NTSTATUS Status;
PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
This = Ctx->Pin;
State = Ctx->State;
IoFreeWorkItem(Ctx->WorkItem);
FreeItem(Ctx, TAG_PORTCLASS);
// Has the audio stream resumed?
if (This->m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
return;
// Set the state
if (This->m_MidiStream)
{
Status = This->m_MidiStream->SetState(State);
}
else
{
Status = This->m_Mxf->SetState(State);
}
if (NT_SUCCESS(Status))
{
// Set internal state to requested state
This->m_State = State;
if (This->m_State == KSSTATE_STOP)
{
// reset start stream
This->m_IrpQueue->CancelBuffers(); //FIX function name
DPRINT1("Stopping PreCompleted %u PostCompleted %u\n", This->m_PreCompleted, This->m_PostCompleted);
}
}
}
VOID
NTAPI
CPortPinDMus::SetStreamState(
IN KSSTATE State)
{
PIO_WORKITEM WorkItem;
PSETSTREAM_CONTEXT Context;
PC_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
// Has the audio stream resumed?
if (m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
return;
// Has the audio state already been set?
if (m_State == State)
return;
// allocate set state context
Context = (PSETSTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(SETSTREAM_CONTEXT), TAG_PORTCLASS);
if (!Context)
return;
// allocate work item
WorkItem = IoAllocateWorkItem(m_DeviceObject);
if (!WorkItem)
{
ExFreePool(Context);
return;
}
Context->Pin = this;
Context->WorkItem = WorkItem;
Context->State = State;
// queue the work item
IoQueueWorkItem(WorkItem, SetStreamWorkerRoutineDMus, DelayedWorkQueue, (PVOID)Context);
}
VOID
CPortPinDMus::TransferMidiData()
{
NTSTATUS Status;
PUCHAR Buffer;
ULONG BufferSize;
ULONG BytesWritten;
do
{
Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
if (!NT_SUCCESS(Status))
{
SetStreamState(KSSTATE_STOP);
return;
}
if (m_Capture)
{
Status = m_MidiStream->Read(Buffer, BufferSize, &BytesWritten);
if (!NT_SUCCESS(Status))
{
DPRINT("Read failed with %x\n", Status);
return;
}
}
else
{
Status = m_MidiStream->Write(Buffer, BufferSize, &BytesWritten);
if (!NT_SUCCESS(Status))
{
DPRINT("Write failed with %x\n", Status);
return;
}
}
if (!BytesWritten)
{
DPRINT("Device is busy retry later\n");
return;
}
m_IrpQueue->UpdateMapping(BytesWritten);
}while(TRUE);
}
VOID
CPortPinDMus::TransferMidiDataToDMus()
{
NTSTATUS Status;
PHYSICAL_ADDRESS PhysicalAddress;
ULONG BufferSize, Flags;
PVOID Buffer;
PDMUS_KERNEL_EVENT_WITH_TAG Event, LastEvent = NULL, Root = NULL;
do
{
m_LastTag++;
Status = m_IrpQueue->GetMappingWithTag(UlongToPtr(m_LastTag), &PhysicalAddress, &Buffer, &BufferSize, &Flags);
if (!NT_SUCCESS(Status))
{
break;
}
Status = GetMessage((PDMUS_KERNEL_EVENT*)&Event);
if (!NT_SUCCESS(Status))
break;
//FIXME
//set up struct
//Event->Event.usFlags = DMUS_KEF_EVENT_COMPLETE;
Event->Event.cbStruct = sizeof(DMUS_KERNEL_EVENT);
Event->Event.cbEvent = BufferSize;
Event->Event.uData.pbData = (PBYTE)Buffer;
if (!Root)
Root = Event;
else
LastEvent->Event.pNextEvt = (struct _DMUS_KERNEL_EVENT *)Event;
LastEvent = Event;
LastEvent->Event.pNextEvt = NULL;
LastEvent->Tag = UlongToPtr(m_LastTag);
}while(TRUE);
if (!Root)
{
SetStreamState(KSSTATE_STOP);
return;
}
Status = m_Mxf->PutMessage((PDMUS_KERNEL_EVENT)Root);
DPRINT("Status %x\n", Status);
}
VOID
NTAPI
CPortPinDMus::RequestService()
{
PC_ASSERT_IRQL(DISPATCH_LEVEL);
if (m_MidiStream)
{
TransferMidiData();
}
else if (m_Mxf)
{
TransferMidiDataToDMus();
}
}
//==================================================================================================================================
NTSTATUS
NTAPI
CPortPinDMus::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortPinDMus::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
UNIMPLEMENTED
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortPinDMus::DeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortPinDMus::Read(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortPinDMus::Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortPinDMus::Flush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
VOID
NTAPI
CloseStreamRoutineDMus(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
PMINIPORTMIDISTREAM Stream = NULL;
NTSTATUS Status;
ISubdevice *ISubDevice;
PSUBDEVICE_DESCRIPTOR Descriptor;
CPortPinDMus * This;
PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
This = (CPortPinDMus*)Ctx->Pin;
if (This->m_MidiStream)
{
if (This->m_State != KSSTATE_STOP)
{
This->m_MidiStream->SetState(KSSTATE_STOP);
}
Stream = This->m_MidiStream;
This->m_MidiStream = NULL;
}
if (This->m_ServiceGroup)
{
This->m_ServiceGroup->RemoveMember(PSERVICESINK(This));
}
Status = This->m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
if (NT_SUCCESS(Status))
{
Status = ISubDevice->GetDescriptor(&Descriptor);
if (NT_SUCCESS(Status))
{
Descriptor->Factory.Instances[This->m_ConnectDetails->PinId].CurrentPinInstanceCount--;
ISubDevice->Release();
}
}
if (This->m_Format)
{
ExFreePool(This->m_Format);
This->m_Format = NULL;
}
// complete the irp
Ctx->Irp->IoStatus.Information = 0;
Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
// free the work item
IoFreeWorkItem(Ctx->WorkItem);
// free work item ctx
FreeItem(Ctx, TAG_PORTCLASS);
// destroy DMus pin
This->m_Filter->FreePin(PPORTPINDMUS(This));
if (Stream)
{
DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
Stream->Release();
}
}
NTSTATUS
NTAPI
CPortPinDMus::Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PCLOSESTREAM_CONTEXT Ctx;
if (m_MidiStream || m_Mxf)
{
Ctx = (PCLOSESTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
if (!Ctx)
{
DPRINT1("Failed to allocate stream context\n");
goto cleanup;
}
Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
if (!Ctx->WorkItem)
{
DPRINT1("Failed to allocate work item\n");
goto cleanup;
}
Ctx->Irp = Irp;
Ctx->Pin = this;
IoMarkIrpPending(Irp);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_PENDING;
// defer work item
IoQueueWorkItem(Ctx->WorkItem, CloseStreamRoutineDMus, DelayedWorkQueue, (PVOID)Ctx);
// Return result
return STATUS_PENDING;
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
cleanup:
if (Ctx)
FreeItem(Ctx, TAG_PORTCLASS);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortPinDMus::QuerySecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortPinDMus::SetSecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
BOOLEAN
NTAPI
CPortPinDMus::FastDeviceIoControl(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortPinDMus::FastRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortPinDMus::FastWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
NTSTATUS
NTAPI
CPortPinDMus::Init(
IN PPORTDMUS Port,
IN PPORTFILTERDMUS Filter,
IN KSPIN_CONNECT * ConnectDetails,
IN KSPIN_DESCRIPTOR * KsPinDescriptor,
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
PKSDATAFORMAT DataFormat;
DMUS_STREAM_TYPE Type;
Port->AddRef();
Filter->AddRef();
m_Port = Port;
m_Filter = Filter;
m_KsPinDescriptor = KsPinDescriptor;
m_ConnectDetails = ConnectDetails;
m_DeviceObject = DeviceObject;
GetDMusMiniport(Port, &m_Miniport, &m_MidiMiniport);
DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
DPRINT("CPortPinDMus::Init entered\n");
m_Format = (PKSDATAFORMAT)ExAllocatePoolWithTag(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
if (!m_Format)
return STATUS_INSUFFICIENT_RESOURCES;
RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
{
Type = DMUS_STREAM_MIDI_RENDER;
}
else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
{
Type = DMUS_STREAM_MIDI_CAPTURE;
}
else
{
DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
KeBugCheck(0);
}
Status = NewIrpQueue(&m_IrpQueue);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to allocate IrpQueue with %x\n", Status);
return Status;
}
if (m_MidiMiniport)
{
Status = m_MidiMiniport->NewStream(&m_MidiStream, NULL, NonPagedPool, ConnectDetails->PinId, Type, m_Format, &m_ServiceGroup);
DPRINT("CPortPinDMus::Init Status %x\n", Status);
if (!NT_SUCCESS(Status))
return Status;
}
else
{
Status = m_Miniport->NewStream(&m_Mxf, NULL, NonPagedPool, ConnectDetails->PinId, Type, m_Format, &m_ServiceGroup, PAllocatorMXF(this), PMASTERCLOCK(this),&m_SchedulePreFetch);
DPRINT("CPortPinDMus::Init Status %x\n", Status);
if (!NT_SUCCESS(Status))
return Status;
if (Type == DMUS_STREAM_MIDI_CAPTURE)
{
Status = m_Mxf->ConnectOutput(PMXF(this));
if (!NT_SUCCESS(Status))
{
DPRINT("IMXF_ConnectOutput failed with Status %x\n", Status);
return Status;
}
}
ExInitializeNPagedLookasideList(&m_LookAsideEvent, NULL, NULL, 0, sizeof(DMUS_KERNEL_EVENT_WITH_TAG), TAG_PORTCLASS, 0);
ExInitializeNPagedLookasideList(&m_LookAsideBuffer, NULL, NULL, 0, PAGE_SIZE, TAG_PORTCLASS, 0);
}
if (m_ServiceGroup)
{
Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to add pin to service group\n");
return Status;
}
m_ServiceGroup->SupportDelayedService();
}
Status = m_IrpQueue->Init(ConnectDetails, m_Format, DeviceObject, 0, 0, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("IrpQueue_Init failed with %x\n", Status);
return Status;
}
m_State = KSSTATE_STOP;
m_Capture = Type;
return STATUS_SUCCESS;
}
VOID
NTAPI
CPortPinDMus::Notify()
{
m_ServiceGroup->RequestService();
}
NTSTATUS
NewPortPinDMus(
OUT IPortPinDMus ** OutPin)
{
CPortPinDMus * This;
This = new (NonPagedPool, TAG_PORTCLASS)CPortPinDMus(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->AddRef();
// store result
*OutPin = (IPortPinDMus*)This;
return STATUS_SUCCESS;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,863 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp
* PURPOSE: WavePci IRP Audio Pin
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortPinWavePci : public IPortPinWavePci,
public IServiceSink,
public IPortWavePciStream
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortPinWavePci;
IMP_IServiceSink;
IMP_IPortWavePciStream;
CPortPinWavePci(IUnknown *OuterUnknown) {}
virtual ~CPortPinWavePci(){}
VOID NTAPI SetState( IN KSSTATE State);
VOID NTAPI CloseStream();
protected:
IPortWavePci * m_Port;
IPortFilterWavePci * m_Filter;
KSPIN_DESCRIPTOR * m_KsPinDescriptor;
PMINIPORTWAVEPCI m_Miniport;
PSERVICEGROUP m_ServiceGroup;
PDMACHANNEL m_DmaChannel;
PMINIPORTWAVEPCISTREAM m_Stream;
KSSTATE m_State;
PKSDATAFORMAT m_Format;
KSPIN_CONNECT * m_ConnectDetails;
BOOL m_Capture;
PDEVICE_OBJECT m_DeviceObject;
IIrpQueue * m_IrpQueue;
ULONG m_TotalPackets;
ULONG m_PreCompleted;
ULONG m_PostCompleted;
ULONG m_StopCount;
ULONG m_Delay;
BOOL m_bUsePrefetch;
ULONG m_PrefetchOffset;
KSALLOCATOR_FRAMING m_AllocatorFraming;
LONG m_Ref;
NTSTATUS NTAPI HandleKsProperty(IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN PIO_STATUS_BLOCK IoStatusBlock);
VOID NTAPI SetStreamState( IN KSSTATE State);
};
typedef struct
{
CPortPinWavePci *Pin;
PIO_WORKITEM WorkItem;
KSSTATE State;
}SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
//==================================================================================================================================
NTSTATUS
NTAPI
CPortPinWavePci::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
DPRINT("CPortPinWavePci::QueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN((IIrpTarget*)this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
{
*Output = PVOID(PSERVICESINK(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
if (IsEqualGUIDAligned(refiid, IID_IPortWavePciStream))
{
*Output = PVOID(PPORTWAVEPCISTREAM(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortPinWavePci::GetMapping(
IN PVOID Tag,
OUT PPHYSICAL_ADDRESS PhysicalAddress,
OUT PVOID *VirtualAddress,
OUT PULONG ByteCount,
OUT PULONG Flags)
{
PC_ASSERT_IRQL(DISPATCH_LEVEL);
return m_IrpQueue->GetMappingWithTag(Tag, PhysicalAddress, VirtualAddress, ByteCount, Flags);
}
NTSTATUS
NTAPI
CPortPinWavePci::ReleaseMapping(
IN PVOID Tag)
{
PC_ASSERT_IRQL(DISPATCH_LEVEL);
return m_IrpQueue->ReleaseMappingWithTag(Tag);
}
NTSTATUS
NTAPI
CPortPinWavePci::TerminatePacket()
{
UNIMPLEMENTED
PC_ASSERT_IRQL(DISPATCH_LEVEL);
return STATUS_SUCCESS;
}
VOID
CPortPinWavePci::SetState(KSSTATE State)
{
ULONG MinimumDataThreshold;
ULONG MaximumDataThreshold;
// Has the audio stream resumed?
if (m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
return;
// Set the state
if (NT_SUCCESS(m_Stream->SetState(State)))
{
// Save new internal state
m_State = State;
if (m_State == KSSTATE_STOP)
{
// reset start stream
m_IrpQueue->CancelBuffers(); //FIX function name
//This->ServiceGroup->lpVtbl->CancelDelayedService(This->ServiceGroup);
// increase stop counter
m_StopCount++;
// get current data threshold
MinimumDataThreshold = m_IrpQueue->GetMinimumDataThreshold();
// get maximum data threshold
MaximumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)m_Format)->WaveFormatEx.nAvgBytesPerSec;
// increase minimum data threshold by 10 frames
MinimumDataThreshold += m_AllocatorFraming.FrameSize * 10;
// assure it has not exceeded
MinimumDataThreshold = min(MinimumDataThreshold, MaximumDataThreshold);
// store minimum data threshold
m_IrpQueue->SetMinimumDataThreshold(MinimumDataThreshold);
DPRINT1("Stopping PreCompleted %u PostCompleted %u StopCount %u MinimumDataThreshold %u\n", m_PreCompleted, m_PostCompleted, m_StopCount, MinimumDataThreshold);
}
if (m_State == KSSTATE_RUN)
{
// start the notification timer
//m_ServiceGroup->RequestDelayedService(m_ServiceGroup, m_Delay);
}
}
}
VOID
NTAPI
PinWavePciSetStreamWorkerRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
CPortPinWavePci * This;
PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
KSSTATE State;
This = Ctx->Pin;
State = Ctx->State;
IoFreeWorkItem(Ctx->WorkItem);
FreeItem(Ctx, TAG_PORTCLASS);
This->SetState(State);
}
VOID
NTAPI
CPortPinWavePci::SetStreamState(
IN KSSTATE State)
{
PDEVICE_OBJECT DeviceObject;
PIO_WORKITEM WorkItem;
PSETSTREAM_CONTEXT Context;
PC_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
// Has the audio stream resumed?
if (m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
return;
// Has the audio state already been set?
if (m_State == State)
return;
// Get device object
DeviceObject = GetDeviceObjectFromPortWavePci(m_Port);
// allocate set state context
Context = (PSETSTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(SETSTREAM_CONTEXT), TAG_PORTCLASS);
if (!Context)
return;
// allocate work item
WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkItem)
{
ExFreePool(Context);
return;
}
Context->Pin = this;
Context->WorkItem = WorkItem;
Context->State = State;
// queue the work item
IoQueueWorkItem(WorkItem, PinWavePciSetStreamWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
}
VOID
NTAPI
CPortPinWavePci::RequestService()
{
PC_ASSERT_IRQL(DISPATCH_LEVEL);
if (m_IrpQueue->HasLastMappingFailed())
{
if (m_IrpQueue->NumMappings() == 0)
{
DPRINT("Stopping stream...\n");
SetStreamState(KSSTATE_STOP);
return;
}
}
m_Stream->Service();
//TODO
//generate events
}
//==================================================================================================================================
NTSTATUS
NTAPI
CPortPinWavePci::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
UNIMPLEMENTED
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortPinWavePci::HandleKsProperty(
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
IN PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN PIO_STATUS_BLOCK IoStatusBlock)
{
PKSPROPERTY Property;
NTSTATUS Status;
UNICODE_STRING GuidString;
DPRINT("IPortPinWavePci_HandleKsProperty entered\n");
if (InputBufferLength < sizeof(KSPROPERTY))
{
IoStatusBlock->Information = 0;
IoStatusBlock->Status = STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
}
Property = (PKSPROPERTY)InputBuffer;
if (IsEqualGUIDAligned(Property->Set, KSPROPSETID_Connection))
{
if (Property->Id == KSPROPERTY_CONNECTION_STATE)
{
PKSSTATE State = (PKSSTATE)OutputBuffer;
PC_ASSERT_IRQL(DISPATCH_LEVEL);
if (OutputBufferLength < sizeof(KSSTATE))
{
IoStatusBlock->Information = sizeof(KSSTATE);
IoStatusBlock->Status = STATUS_BUFFER_TOO_SMALL;
return STATUS_BUFFER_TOO_SMALL;
}
if (Property->Flags & KSPROPERTY_TYPE_SET)
{
Status = STATUS_UNSUCCESSFUL;
IoStatusBlock->Information = 0;
if (m_Stream)
{
Status = m_Stream->SetState(*State);
DPRINT1("Setting state %u %x\n", *State, Status);
if (NT_SUCCESS(Status))
{
m_State = *State;
}
}
IoStatusBlock->Status = Status;
return Status;
}
else if (Property->Flags & KSPROPERTY_TYPE_GET)
{
*State = m_State;
IoStatusBlock->Information = sizeof(KSSTATE);
IoStatusBlock->Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
}
else if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT)
{
PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)OutputBuffer;
if (Property->Flags & KSPROPERTY_TYPE_SET)
{
PKSDATAFORMAT NewDataFormat;
if (!RtlCompareMemory(DataFormat, m_Format, DataFormat->FormatSize))
{
IoStatusBlock->Information = DataFormat->FormatSize;
IoStatusBlock->Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
if (!NewDataFormat)
{
IoStatusBlock->Information = 0;
IoStatusBlock->Status = STATUS_NO_MEMORY;
return STATUS_NO_MEMORY;
}
RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
if (m_Stream)
{
#if 0
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO));
ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM));
ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
ASSERT(This->State == KSSTATE_STOP);
#endif
DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
Status = m_Stream->SetFormat(NewDataFormat);
if (NT_SUCCESS(Status))
{
if (m_Format)
ExFreePoolWithTag(m_Format, TAG_PORTCLASS);
m_IrpQueue->UpdateFormat((PKSDATAFORMAT)NewDataFormat);
m_Format = NewDataFormat;
IoStatusBlock->Information = DataFormat->FormatSize;
IoStatusBlock->Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
}
DPRINT1("Failed to set format\n");
IoStatusBlock->Information = 0;
IoStatusBlock->Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
else if (Property->Flags & KSPROPERTY_TYPE_GET)
{
if (!m_Format)
{
DPRINT1("No format\n");
IoStatusBlock->Information = 0;
IoStatusBlock->Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
if (m_Format->FormatSize > OutputBufferLength)
{
IoStatusBlock->Information = m_Format->FormatSize;
IoStatusBlock->Status = STATUS_BUFFER_TOO_SMALL;
return STATUS_BUFFER_TOO_SMALL;
}
RtlMoveMemory(DataFormat, m_Format, m_Format->FormatSize);
IoStatusBlock->Information = DataFormat->FormatSize;
IoStatusBlock->Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
}
else if (Property->Id == KSPROPERTY_CONNECTION_ALLOCATORFRAMING)
{
PKSALLOCATOR_FRAMING Framing = (PKSALLOCATOR_FRAMING)OutputBuffer;
PC_ASSERT_IRQL(DISPATCH_LEVEL);
// Validate input buffer
if (OutputBufferLength < sizeof(KSALLOCATOR_FRAMING))
{
IoStatusBlock->Information = sizeof(KSALLOCATOR_FRAMING);
IoStatusBlock->Status = STATUS_BUFFER_TOO_SMALL;
return STATUS_BUFFER_TOO_SMALL;
}
// copy frame allocator struct
RtlMoveMemory(Framing, &m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING));
IoStatusBlock->Information = sizeof(KSALLOCATOR_FRAMING);
IoStatusBlock->Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
}
RtlStringFromGUID(Property->Set, &GuidString);
DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
RtlFreeUnicodeString(&GuidString);
IoStatusBlock->Status = STATUS_NOT_IMPLEMENTED;
IoStatusBlock->Information = 0;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
CPortPinWavePci::DeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
NTSTATUS Status;
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
{
Status = HandleKsProperty(IoStack->Parameters.DeviceIoControl.Type3InputBuffer, IoStack->Parameters.DeviceIoControl.InputBufferLength, Irp->UserBuffer, IoStack->Parameters.DeviceIoControl.OutputBufferLength, &Irp->IoStatus);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
UNIMPLEMENTED
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortPinWavePci::Read(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortPinWavePci::Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortPinWavePci::Flush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
VOID
NTAPI
CPortPinWavePci::CloseStream()
{
PMINIPORTWAVEPCISTREAM Stream;
ISubdevice *ISubDevice;
NTSTATUS Status;
PSUBDEVICE_DESCRIPTOR Descriptor;
if (m_Stream)
{
if (m_State != KSSTATE_STOP)
{
m_Stream->SetState(KSSTATE_STOP);
}
}
if (m_ServiceGroup)
{
m_ServiceGroup->RemoveMember(PSERVICESINK(this));
}
Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
if (NT_SUCCESS(Status))
{
Status = ISubDevice->GetDescriptor(&Descriptor);
if (NT_SUCCESS(Status))
{
Descriptor->Factory.Instances[m_ConnectDetails->PinId].CurrentPinInstanceCount--;
}
ISubDevice->Release();
}
if (m_Format)
{
ExFreePool(m_Format);
m_Format = NULL;
}
if (m_Stream)
{
Stream = m_Stream;
m_Stream = 0;
DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
Stream->Release();
}
}
VOID
NTAPI
PinWavePciCloseStreamRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
CPortPinWavePci * This;
PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
This = (CPortPinWavePci*)Ctx->Pin;
This->CloseStream();
// complete the irp
Ctx->Irp->IoStatus.Information = 0;
Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
// free the work item
IoFreeWorkItem(Ctx->WorkItem);
// free work item ctx
FreeItem(Ctx, TAG_PORTCLASS);
}
NTSTATUS
NTAPI
CPortPinWavePci::Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PCLOSESTREAM_CONTEXT Ctx;
if (m_Stream)
{
Ctx = (PCLOSESTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
if (!Ctx)
{
DPRINT1("Failed to allocate stream context\n");
goto cleanup;
}
Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
if (!Ctx->WorkItem)
{
DPRINT1("Failed to allocate work item\n");
goto cleanup;
}
Ctx->Irp = Irp;
Ctx->Pin = (PVOID)this;
IoMarkIrpPending(Irp);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_PENDING;
// defer work item
IoQueueWorkItem(Ctx->WorkItem, PinWavePciCloseStreamRoutine, DelayedWorkQueue, (PVOID)Ctx);
// Return result
return STATUS_PENDING;
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
cleanup:
if (Ctx)
FreeItem(Ctx, TAG_PORTCLASS);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortPinWavePci::QuerySecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortPinWavePci::SetSecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
BOOLEAN
NTAPI
CPortPinWavePci::FastDeviceIoControl(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortPinWavePci::FastRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortPinWavePci::FastWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
NTSTATUS
NTAPI
CPortPinWavePci::Init(
IN PPORTWAVEPCI Port,
IN PPORTFILTERWAVEPCI Filter,
IN KSPIN_CONNECT * ConnectDetails,
IN KSPIN_DESCRIPTOR * KsPinDescriptor,
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
PKSDATAFORMAT DataFormat;
BOOL Capture;
Port->AddRef();
Filter->AddRef();
m_Port = Port;
m_Filter = Filter;
m_KsPinDescriptor = KsPinDescriptor;
m_ConnectDetails = ConnectDetails;
m_Miniport = GetWavePciMiniport(Port);
m_DeviceObject = DeviceObject;
DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
DPRINT("IPortPinWavePci_fnInit entered\n");
m_Format = (PKSDATAFORMAT)ExAllocatePoolWithTag(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
if (!m_Format)
return STATUS_INSUFFICIENT_RESOURCES;
RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
{
Capture = FALSE;
}
else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
{
Capture = TRUE;
}
else
{
DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
KeBugCheck(0);
}
Status = m_Miniport->NewStream(&m_Stream,
NULL,
NonPagedPool,
PPORTWAVEPCISTREAM(this),
ConnectDetails->PinId,
Capture,
m_Format,
&m_DmaChannel,
&m_ServiceGroup);
DPRINT("IPortPinWavePci_fnInit Status %x\n", Status);
if (!NT_SUCCESS(Status))
return Status;
if (m_ServiceGroup)
{
Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to add pin to service group\n");
return Status;
}
m_ServiceGroup->SupportDelayedService();
}
// delay of 10 milisec
m_Delay = Int32x32To64(10, -10000);
Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming);
if (!NT_SUCCESS(Status))
{
DPRINT1("GetAllocatorFraming failed with %x\n", Status);
return Status;
}
DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n",
m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment);
Status = NewIrpQueue(&m_IrpQueue);
if (!NT_SUCCESS(Status))
return Status;
Status = m_IrpQueue->Init(ConnectDetails, m_Format, DeviceObject, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("IrpQueue_Init failed with %x\n", Status);
return Status;
}
m_State = KSSTATE_STOP;
m_Capture = Capture;
return STATUS_SUCCESS;
}
PVOID
NTAPI
CPortPinWavePci::GetIrpStream()
{
return (PVOID)m_IrpQueue;
}
PMINIPORT
NTAPI
CPortPinWavePci::GetMiniport()
{
return (PMINIPORT)m_Miniport;
}
NTSTATUS
NewPortPinWavePci(
OUT IPortPinWavePci ** OutPin)
{
CPortPinWavePci * This;
This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWavePci(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->AddRef();
// store result
*OutPin = (IPortPinWavePci*)This;
return STATUS_SUCCESS;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,911 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/pin_wavert.cpp
* PURPOSE: WaveRT IRP Audio Pin
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortPinWaveRT : public IPortPinWaveRT,
public IServiceSink //hack
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortPinWaveRT;
IMP_IServiceSink; //HACK
CPortPinWaveRT(IUnknown *OuterUnknown){}
virtual ~CPortPinWaveRT(){}
protected:
IPortWaveRT * m_Port;
IPortFilterWaveRT * m_Filter;
KSPIN_DESCRIPTOR * m_KsPinDescriptor;
PMINIPORTWAVERT m_Miniport;
PMINIPORTWAVERTSTREAM m_Stream;
PPORTWAVERTSTREAM m_PortStream;
PSERVICEGROUP m_ServiceGroup;
KSSTATE m_State;
PKSDATAFORMAT m_Format;
KSPIN_CONNECT * m_ConnectDetails;
PVOID m_CommonBuffer;
ULONG m_CommonBufferSize;
ULONG m_CommonBufferOffset;
IIrpQueue * m_IrpQueue;
BOOL m_Capture;
ULONG m_TotalPackets;
ULONG m_PreCompleted;
ULONG m_PostCompleted;
ULONGLONG m_Delay;
MEMORY_CACHING_TYPE m_CacheType;
PMDL m_Mdl;
LONG m_Ref;
NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp);
NTSTATUS NTAPI HandleKsStream(IN PIRP Irp);
VOID NTAPI SetStreamState(IN KSSTATE State);
VOID UpdateCommonBuffer(ULONG Position);
VOID UpdateCommonBufferOverlap(ULONG Position);
friend VOID NTAPI SetStreamWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
friend VOID NTAPI CloseStreamRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
};
typedef struct
{
CPortPinWaveRT *Pin;
PIO_WORKITEM WorkItem;
KSSTATE State;
}SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
VOID
CPortPinWaveRT::UpdateCommonBuffer(
ULONG Position)
{
ULONG BufferLength;
ULONG BytesToCopy;
ULONG BufferSize;
PUCHAR Buffer;
NTSTATUS Status;
BufferLength = Position - m_CommonBufferOffset;
while(BufferLength)
{
Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
if (!NT_SUCCESS(Status))
return;
BytesToCopy = min(BufferLength, BufferSize);
if (m_Capture)
{
RtlMoveMemory(Buffer, (PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BytesToCopy);
}
else
{
RtlMoveMemory((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, Buffer, BytesToCopy);
}
m_IrpQueue->UpdateMapping(BytesToCopy);
m_CommonBufferOffset += BytesToCopy;
BufferLength = Position - m_CommonBufferOffset;
}
}
VOID
CPortPinWaveRT::UpdateCommonBufferOverlap(
ULONG Position)
{
ULONG BufferLength;
ULONG BytesToCopy;
ULONG BufferSize;
PUCHAR Buffer;
NTSTATUS Status;
BufferLength = m_CommonBufferSize - m_CommonBufferOffset;
while(BufferLength)
{
Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
if (!NT_SUCCESS(Status))
return;
BytesToCopy = min(BufferLength, BufferSize);
if (m_Capture)
{
RtlMoveMemory(Buffer, (PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BytesToCopy);
}
else
{
RtlMoveMemory((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, Buffer, BytesToCopy);
}
m_IrpQueue->UpdateMapping(BytesToCopy);
m_CommonBufferOffset += BytesToCopy;
BufferLength = m_CommonBufferSize - m_CommonBufferOffset;
}
m_CommonBufferOffset = 0;
UpdateCommonBuffer(Position);
}
//==================================================================================================================================
NTSTATUS
NTAPI
CPortPinWaveRT::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
DPRINT("IServiceSink_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
{
*Output = PVOID(PSERVICEGROUP(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN((IIrpTarget*)this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
VOID
NTAPI
CPortPinWaveRT::RequestService()
{
KSAUDIO_POSITION Position;
NTSTATUS Status;
PUCHAR Buffer;
ULONG BufferSize;
PC_ASSERT_IRQL(DISPATCH_LEVEL);
Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
if (!NT_SUCCESS(Status))
{
SetStreamState(KSSTATE_STOP);
return;
}
Status = m_Stream->GetPosition(&Position);
DPRINT("PlayOffset %lu WriteOffset %lu Buffer %p BufferSize %u CommonBufferSize %u\n", Position.PlayOffset, Position.WriteOffset, Buffer, BufferSize, m_CommonBufferSize);
if (Position.PlayOffset < m_CommonBufferOffset)
{
UpdateCommonBufferOverlap(Position.PlayOffset);
}
else if (Position.PlayOffset >= m_CommonBufferOffset)
{
UpdateCommonBuffer(Position.PlayOffset);
}
}
VOID
NTAPI
SetStreamWorkerRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
CPortPinWaveRT * This;
PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
KSSTATE State;
This = Ctx->Pin;
State = Ctx->State;
IoFreeWorkItem(Ctx->WorkItem);
FreeItem(Ctx, TAG_PORTCLASS);
// Has the audio stream resumed?
if (This->m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
return;
// Set the state
if (NT_SUCCESS(This->m_Stream->SetState(State)))
{
// Set internal state to stop
This->m_State = State;
if (This->m_State == KSSTATE_STOP)
{
// reset start stream
This->m_IrpQueue->CancelBuffers(); //FIX function name
This->m_ServiceGroup->CancelDelayedService();
DPRINT1("Stopping PreCompleted %u PostCompleted %u\n", This->m_PreCompleted, This->m_PostCompleted);
}
if (This->m_State == KSSTATE_RUN)
{
// start the notification timer
This->m_ServiceGroup->RequestDelayedService(This->m_Delay);
}
}
}
VOID
NTAPI
CPortPinWaveRT::SetStreamState(
IN KSSTATE State)
{
PDEVICE_OBJECT DeviceObject;
PIO_WORKITEM WorkItem;
PSETSTREAM_CONTEXT Context;
PC_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
// Has the audio stream resumed?
if (m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
return;
// Has the audio state already been set?
if (m_State == State)
return;
// Get device object
DeviceObject = GetDeviceObjectFromPortWaveRT(m_Port);
// allocate set state context
Context = (PSETSTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(SETSTREAM_CONTEXT), TAG_PORTCLASS);
if (!Context)
return;
// allocate work item
WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkItem)
{
ExFreePool(Context);
return;
}
Context->Pin = this;
Context->WorkItem = WorkItem;
Context->State = State;
// queue the work item
IoQueueWorkItem(WorkItem, SetStreamWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
}
//==================================================================================================================================
NTSTATUS
NTAPI
CPortPinWaveRT::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
UNIMPLEMENTED
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortPinWaveRT::HandleKsProperty(
IN PIRP Irp)
{
PKSPROPERTY Property;
NTSTATUS Status;
UNICODE_STRING GuidString;
PIO_STACK_LOCATION IoStack;
IoStack = IoGetCurrentIrpStackLocation(Irp);
DPRINT("IPortPinWave_HandleKsProperty entered\n");
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_PARAMETER;
}
Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
if (IsEqualGUIDAligned(Property->Set, KSPROPSETID_Connection))
{
if (Property->Id == KSPROPERTY_CONNECTION_STATE)
{
PKSSTATE State = (PKSSTATE)Irp->UserBuffer;
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSSTATE))
{
Irp->IoStatus.Information = sizeof(KSSTATE);
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_BUFFER_TOO_SMALL;
}
if (Property->Flags & KSPROPERTY_TYPE_SET)
{
Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
if (m_Stream)
{
Status = m_Stream->SetState(*State);
DPRINT1("Setting state %u %x\n", *State, Status);
if (NT_SUCCESS(Status))
{
m_State = *State;
}
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
else if (Property->Flags & KSPROPERTY_TYPE_GET)
{
*State = m_State;
Irp->IoStatus.Information = sizeof(KSSTATE);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
}
else if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT)
{
PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
if (Property->Flags & KSPROPERTY_TYPE_SET)
{
PKSDATAFORMAT NewDataFormat;
if (!RtlCompareMemory(DataFormat, m_Format, DataFormat->FormatSize))
{
Irp->IoStatus.Information = DataFormat->FormatSize;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
if (!NewDataFormat)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_NO_MEMORY;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NO_MEMORY;
}
RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
if (m_Stream)
{
#if 0
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO));
ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM));
ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
ASSERT(m_State == KSSTATE_STOP);
#endif
DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
Status = m_Stream->SetFormat(NewDataFormat);
if (NT_SUCCESS(Status))
{
if (m_Format)
ExFreePoolWithTag(m_Format, TAG_PORTCLASS);
m_IrpQueue->UpdateFormat((PKSDATAFORMAT)NewDataFormat);
m_Format = NewDataFormat;
Irp->IoStatus.Information = DataFormat->FormatSize;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
}
DPRINT1("Failed to set format\n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
else if (Property->Flags & KSPROPERTY_TYPE_GET)
{
if (!m_Format)
{
DPRINT1("No format\n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
if (m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
{
Irp->IoStatus.Information = m_Format->FormatSize;
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_BUFFER_TOO_SMALL;
}
RtlMoveMemory(DataFormat, m_Format, m_Format->FormatSize);
Irp->IoStatus.Information = DataFormat->FormatSize;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
}
}
RtlStringFromGUID(Property->Set, &GuidString);
DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
RtlFreeUnicodeString(&GuidString);
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
CPortPinWaveRT::HandleKsStream(
IN PIRP Irp)
{
DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p\n", m_State, m_Stream);
return STATUS_PENDING;
}
NTSTATUS
NTAPI
CPortPinWaveRT::DeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
{
return HandleKsProperty(Irp);
}
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
{
/// FIXME
/// handle enable event
}
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
{
/// FIXME
/// handle disable event
}
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
{
/// FIXME
/// handle reset state
}
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
{
return HandleKsStream(Irp);
}
else
{
return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
}
UNIMPLEMENTED
DbgBreakPoint();
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortPinWaveRT::Read(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortPinWaveRT::Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortPinWaveRT::Flush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
VOID
NTAPI
CloseStreamRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
PMINIPORTWAVERTSTREAM Stream;
NTSTATUS Status;
ISubdevice *ISubDevice;
PSUBDEVICE_DESCRIPTOR Descriptor;
CPortPinWaveRT * This;
PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
This = (CPortPinWaveRT*)Ctx->Pin;
if (This->m_Stream)
{
if (This->m_State != KSSTATE_STOP)
{
This->m_Stream->SetState(KSSTATE_STOP);
KeStallExecutionProcessor(10);
}
}
Status = This->m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
if (NT_SUCCESS(Status))
{
Status = ISubDevice->GetDescriptor(&Descriptor);
if (NT_SUCCESS(Status))
{
Descriptor->Factory.Instances[This->m_ConnectDetails->PinId].CurrentPinInstanceCount--;
}
ISubDevice->Release();
}
if (This->m_Format)
{
ExFreePool(This->m_Format);
This->m_Format = NULL;
}
if (This->m_IrpQueue)
{
This->m_IrpQueue->Release();
}
// complete the irp
Ctx->Irp->IoStatus.Information = 0;
Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
// free the work item
IoFreeWorkItem(Ctx->WorkItem);
// free work item ctx
FreeItem(Ctx, TAG_PORTCLASS);
if (This->m_Stream)
{
Stream = This->m_Stream;
This->m_Stream = NULL;
DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
Stream->Release();
}
}
NTSTATUS
NTAPI
CPortPinWaveRT::Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PCLOSESTREAM_CONTEXT Ctx;
if (m_Stream)
{
Ctx = (PCLOSESTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
if (!Ctx)
{
DPRINT1("Failed to allocate stream context\n");
goto cleanup;
}
Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
if (!Ctx->WorkItem)
{
DPRINT1("Failed to allocate work item\n");
goto cleanup;
}
Ctx->Irp = Irp;
Ctx->Pin = this;
IoMarkIrpPending(Irp);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_PENDING;
// defer work item
IoQueueWorkItem(Ctx->WorkItem, CloseStreamRoutine, DelayedWorkQueue, (PVOID)Ctx);
// Return result
return STATUS_PENDING;
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
cleanup:
if (Ctx)
FreeItem(Ctx, TAG_PORTCLASS);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortPinWaveRT::QuerySecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
NTSTATUS
NTAPI
CPortPinWaveRT::SetSecurity(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
BOOLEAN
NTAPI
CPortPinWaveRT::FastDeviceIoControl(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
BOOLEAN
NTAPI
CPortPinWaveRT::FastRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
BOOLEAN
NTAPI
CPortPinWaveRT::FastWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
NTSTATUS
NTAPI
CPortPinWaveRT::Init(
IN PPORTWAVERT Port,
IN PPORTFILTERWAVERT Filter,
IN KSPIN_CONNECT * ConnectDetails,
IN KSPIN_DESCRIPTOR * KsPinDescriptor,
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
PKSDATAFORMAT DataFormat;
BOOL Capture;
KSRTAUDIO_HWLATENCY Latency;
Port->AddRef();
Filter->AddRef();
m_Port = Port;
m_Filter = Filter;
m_KsPinDescriptor = KsPinDescriptor;
m_ConnectDetails = ConnectDetails;
m_Miniport = GetWaveRTMiniport(Port);
DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
DPRINT("CPortPinWaveRT::Init entered\n");
m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
if (!m_Format)
return STATUS_INSUFFICIENT_RESOURCES;
RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
Status = NewIrpQueue(&m_IrpQueue);
if (!NT_SUCCESS(Status))
{
goto cleanup;
}
Status = m_IrpQueue->Init(ConnectDetails, DataFormat, DeviceObject, 0, 0, NULL);
if (!NT_SUCCESS(Status))
{
goto cleanup;
}
Status = NewPortWaveRTStream(&m_PortStream);
if (!NT_SUCCESS(Status))
{
goto cleanup;
}
Status = PcNewServiceGroup(&m_ServiceGroup, NULL);
if (!NT_SUCCESS(Status))
{
goto cleanup;
}
m_ServiceGroup->AddMember(PSERVICESINK(this));
m_ServiceGroup->SupportDelayedService();
if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
{
Capture = FALSE;
}
else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
{
Capture = TRUE;
}
else
{
DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
KeBugCheck(0);
}
Status = m_Miniport->NewStream(&m_Stream, m_PortStream, ConnectDetails->PinId, Capture, m_Format);
DPRINT("CPortPinWaveRT::Init Status %x\n", Status);
if (!NT_SUCCESS(Status))
goto cleanup;
m_Stream->GetHWLatency(&Latency);
// delay of 10 milisec
m_Delay = Int32x32To64(10, -10000);
Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl, &m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType);
if (!NT_SUCCESS(Status))
{
DPRINT1("AllocateAudioBuffer failed with %x\n", Status);
goto cleanup;
}
m_CommonBuffer = MmGetSystemAddressForMdlSafe(m_Mdl, NormalPagePriority);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get system address %x\n", Status);
IoFreeMdl(m_Mdl);
m_Mdl = NULL;
goto cleanup;
}
DPRINT1("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
DPRINT1("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
m_State = KSSTATE_PAUSE;
return STATUS_SUCCESS;
cleanup:
if (m_IrpQueue)
{
m_IrpQueue->Release();
m_IrpQueue = NULL;
}
if (m_Format)
{
FreeItem(m_Format, TAG_PORTCLASS);
m_Format = NULL;
}
if (m_Stream)
{
m_Stream->Release();
m_Stream = NULL;
}
else
{
if (m_PortStream)
{
m_PortStream->Release();
m_PortStream = NULL;
}
}
return Status;
}
NTSTATUS
NewPortPinWaveRT(
OUT IPortPinWaveRT ** OutPin)
{
CPortPinWaveRT * This;
This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWaveRT(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->AddRef();
// store result
*OutPin = (PPORTPINWAVERT)This;
return STATUS_SUCCESS;
}
@@ -1,7 +1,7 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/pool.c
* FILE: drivers/wdm/audio/backpln/portcls/pool.cpp
* PURPOSE: Memory functions
* PROGRAMMER: Johannes Anderwald
*/
@@ -1,13 +1,13 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port.c
* FILE: drivers/wdm/audio/backpln/portcls/port.cpp
* PURPOSE: Port construction API
* PROGRAMMER: Johannes Anderwald
* Andrew Greenwood
*/
#include "private.h"
#include "private.hpp"
@@ -22,7 +22,7 @@ PcNewPort(
DPRINT("PcNewPort entered\n");
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!OutPort)
{
@@ -30,17 +30,17 @@ PcNewPort(
return STATUS_INVALID_PARAMETER;
}
if (IsEqualGUIDAligned(ClassId, &CLSID_PortMidi))
if (IsEqualGUIDAligned(ClassId, CLSID_PortMidi))
Status = NewPortDMus(OutPort);
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortDMus))
else if (IsEqualGUIDAligned(ClassId, CLSID_PortDMus))
Status = NewPortDMus(OutPort);
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortTopology))
else if (IsEqualGUIDAligned(ClassId, CLSID_PortTopology))
Status = NewPortTopology(OutPort);
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortWaveCyclic))
else if (IsEqualGUIDAligned(ClassId, CLSID_PortWaveCyclic))
Status = NewPortWaveCyclic(OutPort);
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortWavePci))
else if (IsEqualGUIDAligned(ClassId, CLSID_PortWavePci))
Status = NewPortWavePci(OutPort);
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortWaveRT))
else if (IsEqualGUIDAligned(ClassId, CLSID_PortWaveRT))
Status = NewPortWaveRT(OutPort);
else
{
@@ -1,701 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port_dmus.c
* PURPOSE: DirectMusic Port driver
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IPortDMusVtbl *lpVtbl;
IServiceSinkVtbl *lpVtblServiceSink;
ISubdeviceVtbl *lpVtblSubDevice;
LONG ref;
BOOL bInitialized;
IMiniportDMus *pMiniport;
IMiniportMidi *pMiniportMidi;
DEVICE_OBJECT *pDeviceObject;
PSERVICEGROUP ServiceGroup;
PPINCOUNT pPinCount;
PPOWERNOTIFY pPowerNotify;
PPORTFILTERDMUS Filter;
PPCFILTER_DESCRIPTOR pDescriptor;
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
}IPortDMusImpl;
static GUID InterfaceGuids[3] =
{
{
/// KS_CATEGORY_AUDIO
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KS_CATEGORY_RENDER
0x65E8773E, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KS_CATEGORY_CAPTURE
0x65E8773D, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
}
};
DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterDMusTopologySet, TopologyPropertyHandler);
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterDMusPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
KSPROPERTY_SET PortDMusPropertySet[] =
{
{
&KSPROPSETID_Topology,
sizeof(PortFilterDMusTopologySet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterDMusTopologySet,
0,
NULL
},
{
&KSPROPSETID_Pin,
sizeof(PortFilterDMusPinSet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterDMusPinSet,
0,
NULL
}
};
//---------------------------------------------------------------
// IUnknown interface functions
//
NTSTATUS
NTAPI
IPortDMus_fnQueryInterface(
IPortDMus* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
IPortDMusImpl * This = (IPortDMusImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IPortDMus) ||
IsEqualGUIDAligned(refiid, &IID_IPortMidi) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_ISubdevice))
{
*Output = &This->lpVtblSubDevice;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IDrmPort) ||
IsEqualGUIDAligned(refiid, &IID_IDrmPort2))
{
return NewIDrmPort((PDRMPORT2*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion))
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterPhysicalConnection))
{
return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IPortMidi_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IPortDMus_fnAddRef(
IPortDMus* iface)
{
IPortDMusImpl * This = (IPortDMusImpl*)iface;
return _InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IPortDMus_fnRelease(
IPortDMus* iface)
{
IPortDMusImpl * This = (IPortDMusImpl*)iface;
_InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
if (This->bInitialized)
{
This->pMiniport->lpVtbl->Release(This->pMiniport);
}
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
//---------------------------------------------------------------
// IPort interface functions
//
NTSTATUS
NTAPI
IPortDMus_fnGetDeviceProperty(
IN IPortDMus * iface,
IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
IN ULONG BufferLength,
OUT PVOID PropertyBuffer,
OUT PULONG ReturnLength)
{
IPortDMusImpl * This = (IPortDMusImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortDMus_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return IoGetDeviceProperty(This->pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
}
NTSTATUS
NTAPI
IPortDMus_fnInit(
IN IPortDMus * iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUNKNOWN UnknownMiniport,
IN PUNKNOWN UnknownAdapter OPTIONAL,
IN PRESOURCELIST ResourceList)
{
IMiniportDMus * Miniport = NULL;
IMiniportMidi * MidiMiniport = NULL;
NTSTATUS Status;
PSERVICEGROUP ServiceGroup = NULL;
PPINCOUNT PinCount;
PPOWERNOTIFY PowerNotify;
IPortDMusImpl * This = (IPortDMusImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->bInitialized)
{
DPRINT("IPortDMus_Init called again\n");
return STATUS_SUCCESS;
}
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportDMus, (PVOID*)&Miniport);
if (!NT_SUCCESS(Status))
{
/* check for legacy interface */
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportMidi, (PVOID*)&MidiMiniport);
if (!NT_SUCCESS(Status))
{
DPRINT("IPortDMus_Init called with invalid IMiniport adapter\n");
return STATUS_INVALID_PARAMETER;
}
}
/* Initialize port object */
This->pMiniport = Miniport;
This->pMiniportMidi = MidiMiniport;
This->pDeviceObject = DeviceObject;
This->bInitialized = TRUE;
if (Miniport)
{
/* initialize IMiniportDMus */
Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface, &ServiceGroup);
if (!NT_SUCCESS(Status))
{
DPRINT("IMiniportDMus_Init failed with %x\n", Status);
This->bInitialized = FALSE;
return Status;
}
/* get the miniport device descriptor */
Status = Miniport->lpVtbl->GetDescription(Miniport, &This->pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
Miniport->lpVtbl->Release(Miniport);
This->bInitialized = FALSE;
return Status;
}
/* increment reference on miniport adapter */
Miniport->lpVtbl->AddRef(Miniport);
}
else
{
/* initialize IMiniportMidi */
Status = MidiMiniport->lpVtbl->Init(MidiMiniport, UnknownAdapter, ResourceList, (IPortMidi*)iface, &ServiceGroup);
if (!NT_SUCCESS(Status))
{
DPRINT("IMiniportMidi_Init failed with %x\n", Status);
This->bInitialized = FALSE;
return Status;
}
/* get the miniport device descriptor */
Status = MidiMiniport->lpVtbl->GetDescription(MidiMiniport, &This->pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
MidiMiniport->lpVtbl->Release(MidiMiniport);
This->bInitialized = FALSE;
return Status;
}
/* increment reference on miniport adapter */
MidiMiniport->lpVtbl->AddRef(MidiMiniport);
}
/* create the subdevice descriptor */
Status = PcCreateSubdeviceDescriptor(&This->SubDeviceDescriptor,
3,
InterfaceGuids,
0,
NULL,
2,
PortDMusPropertySet,
0,
0,
0,
NULL,
0,
NULL,
This->pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create descriptior\n");
if (Miniport)
Miniport->lpVtbl->Release(Miniport);
else
MidiMiniport->lpVtbl->Release(MidiMiniport);
This->bInitialized = FALSE;
return Status;
}
if (This->ServiceGroup == NULL && ServiceGroup)
{
/* register service group */
This->ServiceGroup = ServiceGroup;
}
/* check if it supports IPinCount interface */
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPinCount, (PVOID*)&PinCount);
if (NT_SUCCESS(Status))
{
/* store IPinCount interface */
This->pPinCount = PinCount;
}
/* does the Miniport adapter support IPowerNotify interface*/
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPowerNotify, (PVOID*)&PowerNotify);
if (NT_SUCCESS(Status))
{
/* store reference */
This->pPowerNotify = PowerNotify;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IPortDMus_fnNewRegistryKey(
IN IPortDMus * iface,
OUT PREGISTRYKEY *OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
IPortDMusImpl * This = (IPortDMusImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortDMus_fnNewRegistryKey called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
return PcNewRegistryKey(OutRegistryKey,
OuterUnknown,
RegistryKeyType,
DesiredAccess,
This->pDeviceObject,
NULL,//FIXME
ObjectAttributes,
CreateOptions,
Disposition);
}
VOID
NTAPI
IPortDMus_fnNotify(
IN IPortDMus * iface,
IN PSERVICEGROUP ServiceGroup OPTIONAL)
{
IPortDMusImpl * This = (IPortDMusImpl*)iface;
if (ServiceGroup)
{
ServiceGroup->lpVtbl->RequestService (ServiceGroup);
return;
}
ASSERT(This->ServiceGroup);
/* notify miniport service group */
This->ServiceGroup->lpVtbl->RequestService(This->ServiceGroup);
/* notify stream miniport service group */
if (This->Filter)
{
This->Filter->lpVtbl->NotifyPins(This->Filter);
}
}
VOID
NTAPI
IPortDMus_fnRegisterServiceGroup(
IN IPortDMus * iface,
IN PSERVICEGROUP ServiceGroup)
{
IPortDMusImpl * This = (IPortDMusImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
This->ServiceGroup = ServiceGroup;
ServiceGroup->lpVtbl->AddRef(ServiceGroup);
ServiceGroup->lpVtbl->AddMember(ServiceGroup, (PSERVICESINK)&This->lpVtblServiceSink);
}
static IPortDMusVtbl vt_IPortDMus =
{
/* IUnknown methods */
IPortDMus_fnQueryInterface,
IPortDMus_fnAddRef,
IPortDMus_fnRelease,
/* IPort methods */
IPortDMus_fnInit,
IPortDMus_fnGetDeviceProperty,
IPortDMus_fnNewRegistryKey,
IPortDMus_fnNotify,
IPortDMus_fnRegisterServiceGroup
};
//---------------------------------------------------------------
// ISubdevice interface
//
static
NTSTATUS
NTAPI
ISubDevice_fnQueryInterface(
IN ISubdevice *iface,
IN REFIID InterfaceId,
IN PVOID* Interface)
{
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
return IPortDMus_fnQueryInterface((IPortDMus*)This, InterfaceId, Interface);
}
static
ULONG
NTAPI
ISubDevice_fnAddRef(
IN ISubdevice *iface)
{
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
return IPortDMus_fnAddRef((IPortDMus*)This);
}
static
ULONG
NTAPI
ISubDevice_fnRelease(
IN ISubdevice *iface)
{
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
return IPortDMus_fnRelease((IPortDMus*)This);
}
static
NTSTATUS
NTAPI
ISubDevice_fnNewIrpTarget(
IN ISubdevice *iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
PPORTFILTERDMUS Filter;
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
DPRINT("ISubDevice_NewIrpTarget this %p\n", This);
if (This->Filter)
{
*OutTarget = (IIrpTarget*)This->Filter;
return STATUS_SUCCESS;
}
Status = NewPortFilterDMus(&Filter);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = Filter->lpVtbl->Init(Filter, (PPORTDMUS)This);
if (!NT_SUCCESS(Status))
{
Filter->lpVtbl->Release(Filter);
return Status;
}
*OutTarget = (IIrpTarget*)Filter;
return Status;
}
static
NTSTATUS
NTAPI
ISubDevice_fnReleaseChildren(
IN ISubdevice *iface)
{
//IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
UNIMPLEMENTED
return STATUS_UNSUCCESSFUL;
}
static
NTSTATUS
NTAPI
ISubDevice_fnGetDescriptor(
IN ISubdevice *iface,
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
{
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
DPRINT("ISubDevice_GetDescriptor this %p\n", This);
*Descriptor = This->SubDeviceDescriptor;
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnDataRangeIntersection(
IN ISubdevice *iface,
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
DPRINT("ISubDevice_DataRangeIntersection this %p\n", This);
if (This->pMiniport)
{
return This->pMiniport->lpVtbl->DataRangeIntersection (This->pMiniport, PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
}
return STATUS_UNSUCCESSFUL;
}
static
NTSTATUS
NTAPI
ISubDevice_fnPowerChangeNotify(
IN ISubdevice *iface,
IN POWER_STATE PowerState)
{
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
if (This->pPowerNotify)
{
This->pPowerNotify->lpVtbl->PowerChangeNotify(This->pPowerNotify, PowerState);
}
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnPinCount(
IN ISubdevice *iface,
IN ULONG PinId,
IN OUT PULONG FilterNecessary,
IN OUT PULONG FilterCurrent,
IN OUT PULONG FilterPossible,
IN OUT PULONG GlobalCurrent,
IN OUT PULONG GlobalPossible)
{
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
if (This->pPinCount)
{
This->pPinCount->lpVtbl->PinCount(This->pPinCount, PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
return STATUS_SUCCESS;
}
/* FIXME
* scan filter descriptor
*/
return STATUS_UNSUCCESSFUL;
}
static ISubdeviceVtbl vt_ISubdevice =
{
ISubDevice_fnQueryInterface,
ISubDevice_fnAddRef,
ISubDevice_fnRelease,
ISubDevice_fnNewIrpTarget,
ISubDevice_fnReleaseChildren,
ISubDevice_fnGetDescriptor,
ISubDevice_fnDataRangeIntersection,
ISubDevice_fnPowerChangeNotify,
ISubDevice_fnPinCount
};
static
NTSTATUS
NTAPI
IServiceSink_fnQueryInterface(
IServiceSink* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblServiceSink);
if (IsEqualGUIDAligned(refiid, &IID_IServiceSink) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtblServiceSink;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
DPRINT("Unknown interface requested\n");
return STATUS_UNSUCCESSFUL;
}
static
ULONG
NTAPI
IServiceSink_fnAddRef(
IServiceSink* iface)
{
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblServiceSink);
return IPortDMus_fnAddRef((IPortDMus*)This);
}
static
ULONG
NTAPI
IServiceSink_fnRelease(
IServiceSink* iface)
{
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblServiceSink);
return IPortDMus_fnRelease((IPortDMus*)This);
}
static
VOID
NTAPI
IServiceSink_fnRequestService(
IServiceSink* iface)
{
UNIMPLEMENTED
}
static IServiceSinkVtbl vt_IServiceSink =
{
IServiceSink_fnQueryInterface,
IServiceSink_fnAddRef,
IServiceSink_fnRelease,
IServiceSink_fnRequestService
};
NTSTATUS
NewPortDMus(
OUT PPORT* OutPort)
{
IPortDMusImpl * This = AllocateItem(NonPagedPool, sizeof(IPortDMusImpl), TAG_PORTCLASS);
if (!This)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
This->ref = 1;
This->lpVtbl = &vt_IPortDMus;
This->lpVtblServiceSink = &vt_IServiceSink;
This->lpVtblSubDevice = &vt_ISubdevice;
*OutPort = (PPORT)&This->lpVtbl;
return STATUS_SUCCESS;
}
VOID
GetDMusMiniport(
IN IPortDMus * iface,
IN PMINIPORTDMUS * Miniport,
IN PMINIPORTMIDI * MidiMiniport)
{
IPortDMusImpl * This = (IPortDMusImpl*)iface;
*Miniport = This->pMiniport;
*MidiMiniport = This->pMiniportMidi;
}
@@ -0,0 +1,535 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port_dmus.cpp
* PURPOSE: DirectMusic Port driver
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortDMus : public IPortDMus,
public ISubdevice
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortDMus;
IMP_ISubdevice;
CPortDMus(IUnknown *OuterUnknown){}
virtual ~CPortDMus(){}
protected:
BOOL m_bInitialized;
IMiniportDMus * m_pMiniport;
IMiniportMidi * m_pMiniportMidi;
DEVICE_OBJECT * m_pDeviceObject;
PSERVICEGROUP m_ServiceGroup;
PPINCOUNT m_pPinCount;
PPOWERNOTIFY m_pPowerNotify;
PPORTFILTERDMUS m_Filter;
PPCFILTER_DESCRIPTOR m_pDescriptor;
PSUBDEVICE_DESCRIPTOR m_SubDeviceDescriptor;
LONG m_Ref;
friend VOID GetDMusMiniport(IN IPortDMus * iface, IN PMINIPORTDMUS * Miniport, IN PMINIPORTMIDI * MidiMiniport);
};
static GUID InterfaceGuids[3] =
{
{
/// KS_CATEGORY_AUDIO
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KS_CATEGORY_RENDER
0x65E8773E, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KS_CATEGORY_CAPTURE
0x65E8773D, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
}
};
DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterDMusTopologySet, TopologyPropertyHandler);
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterDMusPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
KSPROPERTY_SET PortDMusPropertySet[] =
{
{
&KSPROPSETID_Topology,
sizeof(PortFilterDMusTopologySet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterDMusTopologySet,
0,
NULL
},
{
&KSPROPSETID_Pin,
sizeof(PortFilterDMusPinSet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterDMusPinSet,
0,
NULL
}
};
//---------------------------------------------------------------
// IUnknown interface functions
//
NTSTATUS
NTAPI
CPortDMus::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
if (IsEqualGUIDAligned(refiid, IID_IPortDMus) ||
IsEqualGUIDAligned(refiid, IID_IPortMidi) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN((IPortDMus*)this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_ISubdevice))
{
*Output = PVOID(PSUBDEVICE(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IDrmPort) ||
IsEqualGUIDAligned(refiid, IID_IDrmPort2))
{
return NewIDrmPort((PDRMPORT2*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IPortClsVersion))
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection))
{
return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IPortMidi_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
//---------------------------------------------------------------
// IPort interface functions
//
NTSTATUS
NTAPI
CPortDMus::GetDeviceProperty(
IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
IN ULONG BufferLength,
OUT PVOID PropertyBuffer,
OUT PULONG ReturnLength)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortDMus_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
}
NTSTATUS
NTAPI
CPortDMus::Init(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUNKNOWN UnknownMiniport,
IN PUNKNOWN UnknownAdapter OPTIONAL,
IN PRESOURCELIST ResourceList)
{
IMiniportDMus * Miniport = NULL;
IMiniportMidi * MidiMiniport = NULL;
NTSTATUS Status;
PSERVICEGROUP ServiceGroup = NULL;
PPINCOUNT PinCount;
PPOWERNOTIFY PowerNotify;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_bInitialized)
{
DPRINT("IPortDMus_Init called again\n");
return STATUS_SUCCESS;
}
Status = UnknownMiniport->QueryInterface(IID_IMiniportDMus, (PVOID*)&Miniport);
if (!NT_SUCCESS(Status))
{
// check for legacy interface
Status = UnknownMiniport->QueryInterface(IID_IMiniportMidi, (PVOID*)&MidiMiniport);
if (!NT_SUCCESS(Status))
{
DPRINT("IPortDMus_Init called with invalid IMiniport adapter\n");
return STATUS_INVALID_PARAMETER;
}
}
// Initialize port object
m_pMiniport = Miniport;
m_pMiniportMidi = MidiMiniport;
m_pDeviceObject = DeviceObject;
m_bInitialized = TRUE;
if (Miniport)
{
// initialize IMiniportDMus
Status = Miniport->Init(UnknownAdapter, ResourceList, this, &ServiceGroup);
if (!NT_SUCCESS(Status))
{
DPRINT("IMiniportDMus_Init failed with %x\n", Status);
m_bInitialized = FALSE;
return Status;
}
// get the miniport device descriptor
Status = Miniport->GetDescription(&m_pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
Miniport->Release();
m_bInitialized = FALSE;
return Status;
}
// increment reference on miniport adapter
Miniport->AddRef();
}
else
{
// initialize IMiniportMidi
Status = MidiMiniport->Init(UnknownAdapter, ResourceList, (IPortMidi*)this, &ServiceGroup);
if (!NT_SUCCESS(Status))
{
DPRINT("IMiniportMidi_Init failed with %x\n", Status);
m_bInitialized = FALSE;
return Status;
}
// get the miniport device descriptor
Status = MidiMiniport->GetDescription(&m_pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
MidiMiniport->Release();
m_bInitialized = FALSE;
return Status;
}
// increment reference on miniport adapter
MidiMiniport->AddRef();
}
// create the subdevice descriptor
Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
3,
InterfaceGuids,
0,
NULL,
2,
PortDMusPropertySet,
0,
0,
0,
NULL,
0,
NULL,
m_pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create descriptior\n");
if (Miniport)
Miniport->Release();
else
MidiMiniport->Release();
m_bInitialized = FALSE;
return Status;
}
if (m_ServiceGroup == NULL && ServiceGroup)
{
// register service group
m_ServiceGroup = ServiceGroup;
}
// check if it supports IPinCount interface
Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount);
if (NT_SUCCESS(Status))
{
// store IPinCount interface
m_pPinCount = PinCount;
}
// does the Miniport adapter support IPowerNotify interface*/
Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify);
if (NT_SUCCESS(Status))
{
// store reference
m_pPowerNotify = PowerNotify;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortDMus::NewRegistryKey(
OUT PREGISTRYKEY *OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortDMus_fnNewRegistryKey called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
return PcNewRegistryKey(OutRegistryKey,
OuterUnknown,
RegistryKeyType,
DesiredAccess,
m_pDeviceObject,
NULL,//FIXME
ObjectAttributes,
CreateOptions,
Disposition);
}
VOID
NTAPI
CPortDMus::Notify(
IN PSERVICEGROUP ServiceGroup OPTIONAL)
{
if (ServiceGroup)
{
ServiceGroup->RequestService ();
return;
}
PC_ASSERT(m_ServiceGroup);
// notify miniport service group
m_ServiceGroup->RequestService();
// notify stream miniport service group
if (m_Filter)
{
m_Filter->NotifyPins();
}
}
VOID
NTAPI
CPortDMus::RegisterServiceGroup(
IN PSERVICEGROUP ServiceGroup)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
m_ServiceGroup = ServiceGroup;
ServiceGroup->AddMember(PSERVICESINK(this));
}
//---------------------------------------------------------------
// ISubdevice interface
//
NTSTATUS
NTAPI
CPortDMus::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
PPORTFILTERDMUS Filter;
DPRINT("ISubDevice_NewIrpTarget this %p\n", this);
if (m_Filter)
{
*OutTarget = (IIrpTarget*)m_Filter;
return STATUS_SUCCESS;
}
Status = NewPortFilterDMus(&Filter);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = Filter->Init(PPORTDMUS(this));
if (!NT_SUCCESS(Status))
{
Filter->Release();
return Status;
}
*OutTarget = (IIrpTarget*)Filter;
return Status;
}
NTSTATUS
NTAPI
CPortDMus::ReleaseChildren()
{
UNIMPLEMENTED
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortDMus::GetDescriptor(
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
{
DPRINT("ISubDevice_GetDescriptor this %p\n", this);
*Descriptor = m_SubDeviceDescriptor;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortDMus::DataRangeIntersection(
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
if (m_pMiniport)
{
return m_pMiniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortDMus::PowerChangeNotify(
IN POWER_STATE PowerState)
{
if (m_pPowerNotify)
{
m_pPowerNotify->PowerChangeNotify(PowerState);
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortDMus::PinCount(
IN ULONG PinId,
IN OUT PULONG FilterNecessary,
IN OUT PULONG FilterCurrent,
IN OUT PULONG FilterPossible,
IN OUT PULONG GlobalCurrent,
IN OUT PULONG GlobalPossible)
{
if (m_pPinCount)
{
m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
return STATUS_SUCCESS;
}
// FIXME
// scan filter descriptor
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NewPortDMus(
OUT PPORT* OutPort)
{
NTSTATUS Status;
CPortDMus * Port = new(NonPagedPool, TAG_PORTCLASS) CPortDMus(NULL);
if (!Port)
return STATUS_INSUFFICIENT_RESOURCES;
Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort);
if (!NT_SUCCESS(Status))
{
delete Port;
}
DPRINT("NewPortDMus %p Status %u\n", Port, Status);
return Status;
}
VOID
GetDMusMiniport(
IN IPortDMus * iface,
IN PMINIPORTDMUS * Miniport,
IN PMINIPORTMIDI * MidiMiniport)
{
CPortDMus * This = (CPortDMus*)iface;
*Miniport = This->m_pMiniport;
*MidiMiniport = This->m_pMiniportMidi;
}
@@ -1,823 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port_topology.c
* PURPOSE: Topology Port driver
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IPortTopologyVtbl *lpVtbl;
ISubdeviceVtbl *lpVtblSubDevice;
IPortEventsVtbl *lpVtblPortEvents;
LONG ref;
BOOL bInitialized;
PMINIPORTTOPOLOGY pMiniport;
PDEVICE_OBJECT pDeviceObject;
PPINCOUNT pPinCount;
PPOWERNOTIFY pPowerNotify;
PPCFILTER_DESCRIPTOR pDescriptor;
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
IPortFilterTopology * Filter;
}IPortTopologyImpl;
typedef struct
{
PIRP Irp;
IIrpTarget *Filter;
PIO_WORKITEM WorkItem;
}PIN_WORKER_CONTEXT, *PPIN_WORKER_CONTEXT;
static GUID InterfaceGuids[2] =
{
{
/// KS_CATEGORY_TOPOLOGY
0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}
},
{
/// KS_CATEGORY_AUDIO
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
}
};
DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterTopologyTopologySet, TopologyPropertyHandler);
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterTopologyPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
KSPROPERTY_SET TopologyPropertySet[] =
{
{
&KSPROPSETID_Topology,
sizeof(PortFilterTopologyTopologySet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterTopologyTopologySet,
0,
NULL
},
{
&KSPROPSETID_Pin,
sizeof(PortFilterTopologyPinSet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterTopologyPinSet,
0,
NULL
}
};
//---------------------------------------------------------------
// IPortEvents
//
static
NTSTATUS
NTAPI
IPortEvents_fnQueryInterface(
IPortEvents* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, &IID_IPortEvents) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtblPortEvents;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
static
ULONG
NTAPI
IPortEvents_fnAddRef(
IPortEvents* iface)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnQueryInterface entered\n");
return InterlockedIncrement(&This->ref);
}
static
ULONG
NTAPI
IPortEvents_fnRelease(
IPortEvents* iface)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnRelease entered\n");
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
static
void
NTAPI
IPortEvents_fnAddEventToEventList(
IPortEvents* iface,
IN PKSEVENT_ENTRY EventEntry)
{
UNIMPLEMENTED
}
static
void
NTAPI
IPortEvents_fnGenerateEventList(
IPortEvents* iface,
IN GUID* Set OPTIONAL,
IN ULONG EventId,
IN BOOL PinEvent,
IN ULONG PinId,
IN BOOL NodeEvent,
IN ULONG NodeId)
{
UNIMPLEMENTED
}
static IPortEventsVtbl vt_IPortEvents =
{
IPortEvents_fnQueryInterface,
IPortEvents_fnAddRef,
IPortEvents_fnRelease,
IPortEvents_fnAddEventToEventList,
IPortEvents_fnGenerateEventList
};
//---------------------------------------------------------------
// IUnknown interface functions
//
NTSTATUS
NTAPI
IPortTopology_fnQueryInterface(
IPortTopology* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
DPRINT("IPortTopology_fnQueryInterface\n");
if (IsEqualGUIDAligned(refiid, &IID_IPortTopology) ||
IsEqualGUIDAligned(refiid, &IID_IPort) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_ISubdevice))
{
*Output = &This->lpVtblSubDevice;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPortEvents))
{
*Output = &This->lpVtblPortEvents;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion))
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterPhysicalConnection))
{
return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IPortTopology_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IPortTopology_fnAddRef(
IPortTopology* iface)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IPortTopology_fnRelease(
IPortTopology* iface)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
InterlockedDecrement(&This->ref);
DPRINT("Reference Count %u\n", This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
//---------------------------------------------------------------
// IPort interface functions
//
NTSTATUS
NTAPI
IPortTopology_fnGetDeviceProperty(
IN IPortTopology * iface,
IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
IN ULONG BufferLength,
OUT PVOID PropertyBuffer,
OUT PULONG ReturnLength)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortTopology_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return IoGetDeviceProperty(This->pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
}
NTSTATUS
NTAPI
IPortTopology_fnInit(
IN IPortTopology * iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUNKNOWN UnknownMiniport,
IN PUNKNOWN UnknownAdapter OPTIONAL,
IN PRESOURCELIST ResourceList)
{
IMiniportTopology * Miniport;
NTSTATUS Status;
IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
DPRINT("IPortTopology_fnInit entered This %p DeviceObject %p Irp %p UnknownMiniport %p UnknownAdapter %p ResourceList %p\n",
This, DeviceObject, Irp, UnknownMiniport, UnknownAdapter, ResourceList);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->bInitialized)
{
DPRINT1("IPortTopology_Init called again\n");
return STATUS_SUCCESS;
}
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportTopology, (PVOID*)&Miniport);
if (!NT_SUCCESS(Status))
{
DPRINT1("IPortTopology_Init called with invalid IMiniport adapter\n");
return STATUS_INVALID_PARAMETER;
}
/* Initialize port object */
This->pMiniport = Miniport;
This->pDeviceObject = DeviceObject;
This->bInitialized = TRUE;
/* now initialize the miniport driver */
Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface);
if (!NT_SUCCESS(Status))
{
DPRINT1("IPortTopology_Init failed with %x\n", Status);
This->bInitialized = FALSE;
Miniport->lpVtbl->Release(Miniport);
return Status;
}
/* get the miniport device descriptor */
Status = Miniport->lpVtbl->GetDescription(Miniport, &This->pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
Miniport->lpVtbl->Release(Miniport);
This->bInitialized = FALSE;
return Status;
}
/* create the subdevice descriptor */
Status = PcCreateSubdeviceDescriptor(&This->SubDeviceDescriptor,
2,
InterfaceGuids,
0,
NULL,
2,
TopologyPropertySet,
0,
0,
0,
NULL,
0,
NULL,
This->pDescriptor);
DPRINT("IPortTopology_fnInit success\n");
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IPortTopology_fnNewRegistryKey(
IN IPortTopology * iface,
OUT PREGISTRYKEY *OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortTopology_fnNewRegistryKey called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
return PcNewRegistryKey(OutRegistryKey,
OuterUnknown,
RegistryKeyType,
DesiredAccess,
This->pDeviceObject,
NULL,//FIXME
ObjectAttributes,
CreateOptions,
Disposition);
}
static IPortTopologyVtbl vt_IPortTopology =
{
/* IUnknown methods */
IPortTopology_fnQueryInterface,
IPortTopology_fnAddRef,
IPortTopology_fnRelease,
/* IPort methods */
IPortTopology_fnInit,
IPortTopology_fnGetDeviceProperty,
IPortTopology_fnNewRegistryKey
};
//---------------------------------------------------------------
// ISubdevice interface
//
static
NTSTATUS
NTAPI
ISubDevice_fnQueryInterface(
IN ISubdevice *iface,
IN REFIID InterfaceId,
IN PVOID* Interface)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
return IPortTopology_fnQueryInterface((IPortTopology*)This, InterfaceId, Interface);
}
static
ULONG
NTAPI
ISubDevice_fnAddRef(
IN ISubdevice *iface)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
return IPortTopology_fnAddRef((IPortTopology*)This);
}
static
ULONG
NTAPI
ISubDevice_fnRelease(
IN ISubdevice *iface)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
return IPortTopology_fnRelease((IPortTopology*)This);
}
static
NTSTATUS
NTAPI
ISubDevice_fnNewIrpTarget(
IN ISubdevice *iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortFilterTopology * Filter;
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
/* is there already an instance of the filter */
if (This->Filter)
{
/* it is, let's return the result */
*OutTarget = (IIrpTarget*)This->Filter;
/* increment reference */
This->Filter->lpVtbl->AddRef(This->Filter);
return STATUS_SUCCESS;
}
/* create new instance of filter */
Status = NewPortFilterTopology(&Filter);
if (!NT_SUCCESS(Status))
{
/* not enough memory */
return Status;
}
/* initialize the filter */
Status = Filter->lpVtbl->Init(Filter, (IPortTopology*)This);
if (!NT_SUCCESS(Status))
{
/* destroy filter */
Filter->lpVtbl->Release(Filter);
/* return status */
return Status;
}
/* store result */
*OutTarget = (IIrpTarget*)Filter;
/* store for later re-use */
This->Filter = Filter;
/* return status */
return Status;
}
static
NTSTATUS
NTAPI
ISubDevice_fnReleaseChildren(
IN ISubdevice *iface)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
DPRINT1("ISubDevice_fnReleaseChildren with ref %u\n", This->ref);
/* release the filter */
This->Filter->lpVtbl->Release(This->Filter);
/* release the miniport */
DPRINT("Refs %u %u\n", This->pMiniport->lpVtbl->Release(This->pMiniport), This->ref);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnGetDescriptor(
IN ISubdevice *iface,
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
DPRINT("ISubDevice_GetDescriptor this %p Descp %p\n", This, This->SubDeviceDescriptor);
*Descriptor = This->SubDeviceDescriptor;
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnDataRangeIntersection(
IN ISubdevice *iface,
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
DPRINT("ISubDevice_DataRangeIntersection this %p\n", This);
if (This->pMiniport)
{
return This->pMiniport->lpVtbl->DataRangeIntersection (This->pMiniport, PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
}
return STATUS_UNSUCCESSFUL;
}
static
NTSTATUS
NTAPI
ISubDevice_fnPowerChangeNotify(
IN ISubdevice *iface,
IN POWER_STATE PowerState)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
if (This->pPowerNotify)
{
This->pPowerNotify->lpVtbl->PowerChangeNotify(This->pPowerNotify, PowerState);
}
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnPinCount(
IN ISubdevice *iface,
IN ULONG PinId,
IN OUT PULONG FilterNecessary,
IN OUT PULONG FilterCurrent,
IN OUT PULONG FilterPossible,
IN OUT PULONG GlobalCurrent,
IN OUT PULONG GlobalPossible)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
if (This->pPinCount)
{
This->pPinCount->lpVtbl->PinCount(This->pPinCount, PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
return STATUS_SUCCESS;
}
/* FIXME
* scan filter descriptor
*/
return STATUS_UNSUCCESSFUL;
}
static ISubdeviceVtbl vt_ISubdeviceVtbl =
{
ISubDevice_fnQueryInterface,
ISubDevice_fnAddRef,
ISubDevice_fnRelease,
ISubDevice_fnNewIrpTarget,
ISubDevice_fnReleaseChildren,
ISubDevice_fnGetDescriptor,
ISubDevice_fnDataRangeIntersection,
ISubDevice_fnPowerChangeNotify,
ISubDevice_fnPinCount
};
VOID
NTAPI
CreatePinWorkerRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
NTSTATUS Status;
IIrpTarget *Pin;
PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context;
DPRINT("CreatePinWorkerRoutine called\n");
/* create the pin */
Status = WorkerContext->Filter->lpVtbl->NewIrpTarget(WorkerContext->Filter,
&Pin,
NULL,
NULL,
NonPagedPool,
DeviceObject,
WorkerContext->Irp,
NULL);
DPRINT1("CreatePinWorkerRoutine Status %x\n", Status);
if (NT_SUCCESS(Status))
{
/* create the dispatch object */
/* FIXME need create item for clock */
Status = NewDispatchObject(WorkerContext->Irp, Pin, 0, NULL);
DPRINT("Pin %p\n", Pin);
}
DPRINT("CreatePinWorkerRoutine completing irp %p\n", WorkerContext->Irp);
/* save status in irp */
WorkerContext->Irp->IoStatus.Status = Status;
WorkerContext->Irp->IoStatus.Information = 0;
/* complete the request */
IoCompleteRequest(WorkerContext->Irp, IO_SOUND_INCREMENT);
/* free allocated work item */
IoFreeWorkItem(WorkerContext->WorkItem);
/* free context */
FreeItem(WorkerContext, TAG_PORTCLASS);
}
NTSTATUS
NTAPI
PcCreatePinDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
IIrpTarget *Filter;
PKSOBJECT_CREATE_ITEM CreateItem;
PPIN_WORKER_CONTEXT Context;
/* access the create item */
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
/* sanity check */
ASSERT(CreateItem);
DPRINT1("PcCreatePinDispatch called DeviceObject %p %S Name\n", DeviceObject, CreateItem->ObjectClass.Buffer);
Filter = (IIrpTarget*)CreateItem->Context;
/* sanity checks */
ASSERT(Filter != NULL);
#if KS_IMPLEMENTED
Status = KsReferenceSoftwareBusObject(DeviceExt->KsDeviceHeader);
if (!NT_SUCCESS(Status) && Status != STATUS_NOT_IMPLEMENTED)
{
DPRINT1("PcCreatePinDispatch failed to reference device header\n");
FreeItem(Entry, TAG_PORTCLASS);
goto cleanup;
}
#endif
/* new pins are instantiated at passive level,
* so allocate a work item and context for it
*/
Context = AllocateItem(NonPagedPool, sizeof(PIN_WORKER_CONTEXT), TAG_PORTCLASS);
if (!Context)
{
DPRINT("Failed to allocate worker context\n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* allocate work item */
Context->WorkItem = IoAllocateWorkItem(DeviceObject);
if (!Context->WorkItem)
{
DPRINT("Failed to allocate workitem\n");
FreeItem(Context, TAG_PORTCLASS);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
Context->Filter = Filter;
Context->Irp = Irp;
DPRINT("Queueing IRP %p Irql %u\n", Irp, KeGetCurrentIrql());
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_PENDING;
IoMarkIrpPending(Irp);
IoQueueWorkItem(Context->WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
return STATUS_PENDING;
}
NTSTATUS
NTAPI
PcCreateItemDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
NTSTATUS Status;
ISubdevice * SubDevice;
IIrpTarget *Filter;
PKSOBJECT_CREATE_ITEM CreateItem, PinCreateItem;
static LPWSTR KS_NAME_PIN = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}";
/* access the create item */
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
DPRINT1("PcCreateItemDispatch called DeviceObject %p %S Name\n", DeviceObject, CreateItem->ObjectClass.Buffer);
/* get the subdevice */
SubDevice = (ISubdevice*)CreateItem->Context;
/* sanity checks */
ASSERT(SubDevice != NULL);
#if KS_IMPLEMENTED
Status = KsReferenceSoftwareBusObject(DeviceExt->KsDeviceHeader);
if (!NT_SUCCESS(Status) && Status != STATUS_NOT_IMPLEMENTED)
{
DPRINT1("PcCreateItemDispatch failed to reference device header\n");
FreeItem(Entry, TAG_PORTCLASS);
goto cleanup;
}
#endif
/* get filter object
* is implemented as a singleton
*/
Status = SubDevice->lpVtbl->NewIrpTarget(SubDevice,
&Filter,
NULL,
NULL,
NonPagedPool,
DeviceObject,
Irp,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get filter object\n");
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
/* allocate pin create item */
PinCreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM), TAG_PORTCLASS);
if (!PinCreateItem)
{
/* not enough memory */
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* initialize pin create item */
PinCreateItem->Context = (PVOID)Filter;
PinCreateItem->Create = PcCreatePinDispatch;
RtlInitUnicodeString(&PinCreateItem->ObjectClass, KS_NAME_PIN);
/* FIXME copy security descriptor */
/* now allocate a dispatch object */
Status = NewDispatchObject(Irp, Filter, 1, PinCreateItem);
/* complete request */
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NewPortTopology(
OUT PPORT* OutPort)
{
IPortTopologyImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IPortTopologyImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->lpVtbl = &vt_IPortTopology;
This->lpVtblSubDevice = &vt_ISubdeviceVtbl;
This->lpVtblPortEvents = &vt_IPortEvents;
This->ref = 1;
*OutPort = (PPORT)(&This->lpVtbl);
DPRINT("NewPortTopology result %p\n", *OutPort);
return STATUS_SUCCESS;
}
PMINIPORTTOPOLOGY
GetTopologyMiniport(
PPORTTOPOLOGY Port)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)Port;
return This->pMiniport;
}
@@ -0,0 +1,665 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port_topology.cpp
* PURPOSE: Topology Port driver
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortTopology : public IPortTopology,
public ISubdevice,
public IPortEvents
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortTopology;
IMP_ISubdevice;
IMP_IPortEvents;
CPortTopology(IUnknown *OuterUnknown){}
virtual ~CPortTopology(){}
protected:
BOOL m_bInitialized;
PMINIPORTTOPOLOGY m_pMiniport;
PDEVICE_OBJECT m_pDeviceObject;
PPINCOUNT m_pPinCount;
PPOWERNOTIFY m_pPowerNotify;
PPCFILTER_DESCRIPTOR m_pDescriptor;
PSUBDEVICE_DESCRIPTOR m_SubDeviceDescriptor;
IPortFilterTopology * m_Filter;
LONG m_Ref;
friend PMINIPORTTOPOLOGY GetTopologyMiniport(PPORTTOPOLOGY Port);
};
typedef struct
{
PIRP Irp;
IIrpTarget *Filter;
PIO_WORKITEM WorkItem;
}PIN_WORKER_CONTEXT, *PPIN_WORKER_CONTEXT;
static GUID InterfaceGuids[2] =
{
{
/// KS_CATEGORY_TOPOLOGY
0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}
},
{
/// KS_CATEGORY_AUDIO
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
}
};
DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterTopologyTopologySet, TopologyPropertyHandler);
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterTopologyPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
KSPROPERTY_SET TopologyPropertySet[] =
{
{
&KSPROPSETID_Topology,
sizeof(PortFilterTopologyTopologySet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterTopologyTopologySet,
0,
NULL
},
{
&KSPROPSETID_Pin,
sizeof(PortFilterTopologyPinSet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterTopologyPinSet,
0,
NULL
}
};
//---------------------------------------------------------------
// IPortEvents
//
void
NTAPI
CPortTopology::AddEventToEventList(
IN PKSEVENT_ENTRY EventEntry)
{
UNIMPLEMENTED
}
void
NTAPI
CPortTopology::GenerateEventList(
IN GUID* Set OPTIONAL,
IN ULONG EventId,
IN BOOL PinEvent,
IN ULONG PinId,
IN BOOL NodeEvent,
IN ULONG NodeId)
{
UNIMPLEMENTED
}
//---------------------------------------------------------------
// IUnknown interface functions
//
NTSTATUS
NTAPI
CPortTopology::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
DPRINT("IPortTopology_fnQueryInterface\n");
if (IsEqualGUIDAligned(refiid, IID_IPortTopology) ||
IsEqualGUIDAligned(refiid, IID_IPort) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN((IPortTopology*)this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_ISubdevice))
{
*Output = PVOID(PSUBDEVICE(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPortEvents))
{
*Output = PVOID(PPORTEVENTS(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPortClsVersion))
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection))
{
return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IPortTopology_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
//---------------------------------------------------------------
// IPort interface functions
//
NTSTATUS
NTAPI
CPortTopology::GetDeviceProperty(
IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
IN ULONG BufferLength,
OUT PVOID PropertyBuffer,
OUT PULONG ReturnLength)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortTopology_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
}
NTSTATUS
NTAPI
CPortTopology::Init(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUNKNOWN UnknownMiniport,
IN PUNKNOWN UnknownAdapter OPTIONAL,
IN PRESOURCELIST ResourceList)
{
IMiniportTopology * Miniport;
NTSTATUS Status;
DPRINT("IPortTopology_fnInit entered This %p DeviceObject %p Irp %p UnknownMiniport %p UnknownAdapter %p ResourceList %p\n",
this, DeviceObject, Irp, UnknownMiniport, UnknownAdapter, ResourceList);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_bInitialized)
{
DPRINT1("IPortTopology_Init called again\n");
return STATUS_SUCCESS;
}
Status = UnknownMiniport->QueryInterface(IID_IMiniportTopology, (PVOID*)&Miniport);
if (!NT_SUCCESS(Status))
{
DPRINT1("IPortTopology_Init called with invalid IMiniport adapter\n");
return STATUS_INVALID_PARAMETER;
}
// Initialize port object
m_pMiniport = Miniport;
m_pDeviceObject = DeviceObject;
m_bInitialized = TRUE;
// now initialize the miniport driver
Status = Miniport->Init(UnknownAdapter, ResourceList, this);
if (!NT_SUCCESS(Status))
{
DPRINT1("IPortTopology_Init failed with %x\n", Status);
m_bInitialized = FALSE;
Miniport->Release();
return Status;
}
// get the miniport device descriptor
Status = Miniport->GetDescription(&m_pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
Miniport->Release();
m_bInitialized = FALSE;
return Status;
}
// create the subdevice descriptor
Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
2,
InterfaceGuids,
0,
NULL,
2,
TopologyPropertySet,
0,
0,
0,
NULL,
0,
NULL,
m_pDescriptor);
DPRINT("IPortTopology_fnInit success\n");
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortTopology::NewRegistryKey(
OUT PREGISTRYKEY *OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortTopology_fnNewRegistryKey called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
return PcNewRegistryKey(OutRegistryKey,
OuterUnknown,
RegistryKeyType,
DesiredAccess,
m_pDeviceObject,
NULL,//FIXME
ObjectAttributes,
CreateOptions,
Disposition);
}
//---------------------------------------------------------------
// ISubdevice interface
//
NTSTATUS
NTAPI
CPortTopology::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortFilterTopology * Filter;
// is there already an instance of the filter
if (m_Filter)
{
// it is, let's return the result
*OutTarget = (IIrpTarget*)m_Filter;
// increment reference
m_Filter->AddRef();
return STATUS_SUCCESS;
}
// create new instance of filter
Status = NewPortFilterTopology(&Filter);
if (!NT_SUCCESS(Status))
{
// not enough memory
return Status;
}
// initialize the filter
Status = Filter->Init((IPortTopology*)this);
if (!NT_SUCCESS(Status))
{
// destroy filter
Filter->Release();
// return status
return Status;
}
// store result
*OutTarget = (IIrpTarget*)Filter;
// store for later re-use
m_Filter = Filter;
// return status
return Status;
}
NTSTATUS
NTAPI
CPortTopology::ReleaseChildren()
{
DPRINT1("ISubDevice_fnReleaseChildren\n");
// release the filter
m_Filter->Release();
// release the miniport
DPRINT("Refs %u\n", m_pMiniport->Release());
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortTopology::GetDescriptor(
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
{
DPRINT("ISubDevice_GetDescriptor this %p Descp %p\n", this, m_SubDeviceDescriptor);
*Descriptor = m_SubDeviceDescriptor;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortTopology::DataRangeIntersection(
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
if (m_pMiniport)
{
return m_pMiniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortTopology::PowerChangeNotify(
IN POWER_STATE PowerState)
{
if (m_pPowerNotify)
{
m_pPowerNotify->PowerChangeNotify(PowerState);
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortTopology::PinCount(
IN ULONG PinId,
IN OUT PULONG FilterNecessary,
IN OUT PULONG FilterCurrent,
IN OUT PULONG FilterPossible,
IN OUT PULONG GlobalCurrent,
IN OUT PULONG GlobalPossible)
{
if (m_pPinCount)
{
m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
return STATUS_SUCCESS;
}
// FIXME
// scan filter descriptor
return STATUS_UNSUCCESSFUL;
}
VOID
NTAPI
CreatePinWorkerRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
NTSTATUS Status;
IIrpTarget *Pin;
PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context;
DPRINT("CreatePinWorkerRoutine called\n");
// create the pin
Status = WorkerContext->Filter->NewIrpTarget(&Pin,
NULL,
NULL,
NonPagedPool,
DeviceObject,
WorkerContext->Irp,
NULL);
DPRINT1("CreatePinWorkerRoutine Status %x\n", Status);
if (NT_SUCCESS(Status))
{
// create the dispatch object
// FIXME need create item for clock
Status = NewDispatchObject(WorkerContext->Irp, Pin, 0, NULL);
DPRINT("Pin %p\n", Pin);
}
DPRINT("CreatePinWorkerRoutine completing irp %p\n", WorkerContext->Irp);
// save status in irp
WorkerContext->Irp->IoStatus.Status = Status;
WorkerContext->Irp->IoStatus.Information = 0;
// complete the request
IoCompleteRequest(WorkerContext->Irp, IO_SOUND_INCREMENT);
// free allocated work item
IoFreeWorkItem(WorkerContext->WorkItem);
// free context
FreeItem(WorkerContext, TAG_PORTCLASS);
}
NTSTATUS
NTAPI
PcCreatePinDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
IIrpTarget *Filter;
PKSOBJECT_CREATE_ITEM CreateItem;
PPIN_WORKER_CONTEXT Context;
// access the create item
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
// sanity check
PC_ASSERT(CreateItem);
DPRINT1("PcCreatePinDispatch called DeviceObject %p %S Name\n", DeviceObject, CreateItem->ObjectClass.Buffer);
Filter = (IIrpTarget*)CreateItem->Context;
// sanity checks
PC_ASSERT(Filter != NULL);
#if KS_IMPLEMENTED
Status = KsReferenceSoftwareBusObject(DeviceExt->KsDeviceHeader);
if (!NT_SUCCESS(Status) && Status != STATUS_NOT_IMPLEMENTED)
{
DPRINT1("PcCreatePinDispatch failed to reference device header\n");
FreeItem(Entry, TAG_PORTCLASS);
goto cleanup;
}
#endif
// new pins are instantiated at passive level,
// so allocate a work item and context for it
Context = (PPIN_WORKER_CONTEXT)AllocateItem(NonPagedPool, sizeof(PIN_WORKER_CONTEXT), TAG_PORTCLASS);
if (!Context)
{
DPRINT("Failed to allocate worker context\n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
// allocate work item
Context->WorkItem = IoAllocateWorkItem(DeviceObject);
if (!Context->WorkItem)
{
DPRINT("Failed to allocate workitem\n");
FreeItem(Context, TAG_PORTCLASS);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
Context->Filter = Filter;
Context->Irp = Irp;
DPRINT("Queueing IRP %p Irql %u\n", Irp, KeGetCurrentIrql());
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_PENDING;
IoMarkIrpPending(Irp);
IoQueueWorkItem(Context->WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
return STATUS_PENDING;
}
NTSTATUS
NTAPI
PcCreateItemDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
NTSTATUS Status;
ISubdevice * SubDevice;
IIrpTarget *Filter;
PKSOBJECT_CREATE_ITEM CreateItem, PinCreateItem;
// access the create item
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
DPRINT1("PcCreateItemDispatch called DeviceObject %p %S Name\n", DeviceObject, CreateItem->ObjectClass.Buffer);
// get the subdevice
SubDevice = (ISubdevice*)CreateItem->Context;
// sanity checks
PC_ASSERT(SubDevice != NULL);
#if KS_IMPLEMENTED
Status = KsReferenceSoftwareBusObject(DeviceExt->KsDeviceHeader);
if (!NT_SUCCESS(Status) && Status != STATUS_NOT_IMPLEMENTED)
{
DPRINT1("PcCreateItemDispatch failed to reference device header\n");
FreeItem(Entry, TAG_PORTCLASS);
goto cleanup;
}
#endif
// get filter object
Status = SubDevice->NewIrpTarget(&Filter,
NULL,
NULL,
NonPagedPool,
DeviceObject,
Irp,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get filter object\n");
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
// allocate pin create item
PinCreateItem = (PKSOBJECT_CREATE_ITEM)AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM), TAG_PORTCLASS);
if (!PinCreateItem)
{
// not enough memory
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
// initialize pin create item
PinCreateItem->Context = (PVOID)Filter;
PinCreateItem->Create = PcCreatePinDispatch;
RtlInitUnicodeString(&PinCreateItem->ObjectClass, KSSTRING_Pin);
// FIXME copy security descriptor
// now allocate a dispatch object
Status = NewDispatchObject(Irp, Filter, 1, PinCreateItem);
// complete request
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NewPortTopology(
OUT PPORT* OutPort)
{
CPortTopology * This;
NTSTATUS Status;
This= new(NonPagedPool, TAG_PORTCLASS) CPortTopology(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
Status = This->QueryInterface(IID_IPort, (PVOID*)OutPort);
if (!NT_SUCCESS(Status))
{
delete This;
}
DPRINT("NewPortTopology %p Status %x\n", *OutPort, Status);
return Status;
}
PMINIPORTTOPOLOGY
GetTopologyMiniport(
PPORTTOPOLOGY Port)
{
CPortTopology * This = (CPortTopology*)Port;
return This->m_pMiniport;
}
@@ -1,807 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port_wavecyclic.c
* PURPOSE: WaveCyclic Port Driver
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
extern GUID IID_IDmaChannelSlave;
typedef struct
{
IPortWaveCyclicVtbl *lpVtbl;
IPortEventsVtbl *lpVtblPortEvents;
ISubdeviceVtbl *lpVtblSubDevice;
LONG ref;
BOOL bInitialized;
PDEVICE_OBJECT pDeviceObject;
PMINIPORTWAVECYCLIC pMiniport;
PRESOURCELIST pResourceList;
PPINCOUNT pPinCount;
PPOWERNOTIFY pPowerNotify;
PPCFILTER_DESCRIPTOR pDescriptor;
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
IPortFilterWaveCyclic * Filter;
}IPortWaveCyclicImpl;
GUID KSPROPERTY_SETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
static GUID InterfaceGuids[4] =
{
{
/// KSCATEGORY_RENDER
0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KSCATEGORY_CAPTURE
0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
//KS_CATEGORY_AUDIO
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
///KSCATEGORY_AUDIO_DEVICE
0xFBF6F530L, 0x07B9, 0x11D2, {0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}
}
};
DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWaveCyclicTopologySet, TopologyPropertyHandler);
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWaveCyclicPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
KSPROPERTY_SET WaveCyclicPropertySet[] =
{
{
&KSPROPSETID_Topology,
sizeof(PortFilterWaveCyclicTopologySet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWaveCyclicTopologySet,
0,
NULL
},
{
&KSPROPSETID_Pin,
sizeof(PortFilterWaveCyclicPinSet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWaveCyclicPinSet,
0,
NULL
}
};
//KSEVENTSETID_LoopedStreaming, Type = KSEVENT_LOOPEDSTREAMING_POSITION
//KSEVENTSETID_Connection, Type = KSEVENT_CONNECTION_ENDOFSTREAM,
#if 0
static const KSIDENTIFIER Identifiers[] =
{
{
&KSINTERFACESETID_Standard,
0,
0
},
{
&KSINTERFACESETID_Standard,
1,
0
}
};
#endif
//---------------------------------------------------------------
// IPortEvents
//
static
NTSTATUS
NTAPI
IPortEvents_fnQueryInterface(
IPortEvents* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, &IID_IPortEvents) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtblPortEvents;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
static
ULONG
NTAPI
IPortEvents_fnAddRef(
IPortEvents* iface)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnQueryInterface entered\n");
return InterlockedIncrement(&This->ref);
}
static
ULONG
NTAPI
IPortEvents_fnRelease(
IPortEvents* iface)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnRelease entered\n");
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
static
void
NTAPI
IPortEvents_fnAddEventToEventList(
IPortEvents* iface,
IN PKSEVENT_ENTRY EventEntry)
{
UNIMPLEMENTED
}
static
void
NTAPI
IPortEvents_fnGenerateEventList(
IPortEvents* iface,
IN GUID* Set OPTIONAL,
IN ULONG EventId,
IN BOOL PinEvent,
IN ULONG PinId,
IN BOOL NodeEvent,
IN ULONG NodeId)
{
UNIMPLEMENTED
}
static IPortEventsVtbl vt_IPortEvents =
{
IPortEvents_fnQueryInterface,
IPortEvents_fnAddRef,
IPortEvents_fnRelease,
IPortEvents_fnAddEventToEventList,
IPortEvents_fnGenerateEventList
};
//---------------------------------------------------------------
// IUnknown interface functions
//
NTSTATUS
NTAPI
IPortWaveCyclic_fnQueryInterface(
IPortWaveCyclic* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IPortWaveCyclic) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPortEvents))
{
*Output = &This->lpVtblPortEvents;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_ISubdevice))
{
*Output = &This->lpVtblSubDevice;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion))
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IDrmPort) ||
IsEqualGUIDAligned(refiid, &IID_IDrmPort2))
{
return NewIDrmPort((PDRMPORT2*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterPhysicalConnection))
{
return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IPortWaveCyclic_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IPortWaveCyclic_fnAddRef(
IPortWaveCyclic* iface)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)iface;
DPRINT("IPortWaveCyclic_fnAddRef %u entered\n", This->ref);
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IPortWaveCyclic_fnRelease(
IPortWaveCyclic* iface)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)iface;
InterlockedDecrement(&This->ref);
DPRINT("IPortWaveCyclic_fnRelease %u entered\n", This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
//---------------------------------------------------------------
// IPort interface functions
//
NTSTATUS
NTAPI
IPortWaveCyclic_fnGetDeviceProperty(
IN IPortWaveCyclic * iface,
IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
IN ULONG BufferLength,
OUT PVOID PropertyBuffer,
OUT PULONG ReturnLength)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortWaveCyclic_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return IoGetDeviceProperty(This->pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
}
NTSTATUS
NTAPI
IPortWaveCyclic_fnInit(
IN IPortWaveCyclic * iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUNKNOWN UnknownMiniport,
IN PUNKNOWN UnknownAdapter OPTIONAL,
IN PRESOURCELIST ResourceList)
{
IMiniportWaveCyclic * Miniport;
NTSTATUS Status;
PPINCOUNT PinCount;
PPOWERNOTIFY PowerNotify;
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)iface;
DPRINT("IPortWaveCyclic_Init entered %p\n", This);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->bInitialized)
{
DPRINT("IPortWaveCyclic_Init called again\n");
return STATUS_SUCCESS;
}
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportWaveCyclic, (PVOID*)&Miniport);
if (!NT_SUCCESS(Status))
{
DPRINT("IPortWaveCyclic_Init called with invalid IMiniport adapter\n");
return STATUS_INVALID_PARAMETER;
}
/* Initialize port object */
This->pMiniport = Miniport;
This->pDeviceObject = DeviceObject;
This->bInitialized = TRUE;
This->pResourceList = ResourceList;
if (ResourceList)
{
/* increment reference on resource list */
ResourceList->lpVtbl->AddRef(ResourceList);
}
Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface);
if (!NT_SUCCESS(Status))
{
DPRINT("IMiniportWaveCyclic_Init failed with %x\n", Status);
Miniport->lpVtbl->Release(Miniport);
This->bInitialized = FALSE;
return Status;
}
/* get the miniport device descriptor */
Status = Miniport->lpVtbl->GetDescription(Miniport, &This->pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
Miniport->lpVtbl->Release(Miniport);
This->bInitialized = FALSE;
return Status;
}
/* create the subdevice descriptor */
Status = PcCreateSubdeviceDescriptor(&This->SubDeviceDescriptor,
4,
InterfaceGuids,
0,
NULL,
2,
WaveCyclicPropertySet,
0,
0,
0,
NULL,
0,
NULL,
This->pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("PcCreateSubdeviceDescriptor failed with %x\n", Status);
Miniport->lpVtbl->Release(Miniport);
This->bInitialized = FALSE;
return Status;
}
/* check if it supports IPinCount interface */
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPinCount, (PVOID*)&PinCount);
if (NT_SUCCESS(Status))
{
/* store IPinCount interface */
This->pPinCount = PinCount;
}
/* does the Miniport adapter support IPowerNotify interface*/
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPowerNotify, (PVOID*)&PowerNotify);
if (NT_SUCCESS(Status))
{
/* store reference */
This->pPowerNotify = PowerNotify;
}
DPRINT("IPortWaveCyclic successfully initialized\n");
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IPortWaveCyclic_fnNewRegistryKey(
IN IPortWaveCyclic * iface,
OUT PREGISTRYKEY *OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortWaveCyclic_fnNewRegistryKey called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, DesiredAccess, This->pDeviceObject, NULL /*FIXME*/, ObjectAttributes, CreateOptions, Disposition);
}
//---------------------------------------------------------------
// IPortWaveCyclic interface functions
//
NTSTATUS
NTAPI
IPortWaveCyclic_fnNewMasterDmaChannel(
IN IPortWaveCyclic * iface,
OUT PDMACHANNEL* DmaChannel,
IN PUNKNOWN OuterUnknown,
IN PRESOURCELIST ResourceList OPTIONAL,
IN ULONG MaximumLength,
IN BOOL Dma32BitAddresses,
IN BOOL Dma64BitAddresses,
IN DMA_WIDTH DmaWidth,
IN DMA_SPEED DmaSpeed)
{
NTSTATUS Status;
DEVICE_DESCRIPTION DeviceDescription;
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortWaveCyclic_fnNewSlaveDmaChannel called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
Status = PcDmaMasterDescription(ResourceList, (Dma32BitAddresses | Dma64BitAddresses), Dma32BitAddresses, 0, Dma64BitAddresses, DmaWidth, DmaSpeed, MaximumLength, 0, &DeviceDescription);
if (NT_SUCCESS(Status))
{
return PcNewDmaChannel(DmaChannel, OuterUnknown, NonPagedPool, &DeviceDescription, This->pDeviceObject);
}
return Status;
}
NTSTATUS
NTAPI
IPortWaveCyclic_fnNewSlaveDmaChannel(
IN IPortWaveCyclic * iface,
OUT PDMACHANNELSLAVE* OutDmaChannel,
IN PUNKNOWN OuterUnknown,
IN PRESOURCELIST ResourceList OPTIONAL,
IN ULONG DmaIndex,
IN ULONG MaximumLength,
IN BOOL DemandMode,
IN DMA_SPEED DmaSpeed)
{
DEVICE_DESCRIPTION DeviceDescription;
PDMACHANNEL DmaChannel;
NTSTATUS Status;
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortWaveCyclic_fnNewSlaveDmaChannel called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
// FIXME
// Check for F-Type DMA Support
//
Status = PcDmaSlaveDescription(ResourceList, DmaIndex, DemandMode, TRUE, DmaSpeed, MaximumLength, 0, &DeviceDescription);
if (NT_SUCCESS(Status))
{
Status = PcNewDmaChannel(&DmaChannel, OuterUnknown, NonPagedPool, &DeviceDescription, This->pDeviceObject);
if (NT_SUCCESS(Status))
{
Status = DmaChannel->lpVtbl->QueryInterface(DmaChannel, &IID_IDmaChannelSlave, (PVOID*)OutDmaChannel);
DmaChannel->lpVtbl->Release(DmaChannel);
}
}
return Status;
}
VOID
NTAPI
IPortWaveCyclic_fnNotify(
IN IPortWaveCyclic * iface,
IN PSERVICEGROUP ServiceGroup)
{
ServiceGroup->lpVtbl->RequestService (ServiceGroup);
}
static IPortWaveCyclicVtbl vt_IPortWaveCyclicVtbl =
{
IPortWaveCyclic_fnQueryInterface,
IPortWaveCyclic_fnAddRef,
IPortWaveCyclic_fnRelease,
IPortWaveCyclic_fnInit,
IPortWaveCyclic_fnGetDeviceProperty,
IPortWaveCyclic_fnNewRegistryKey,
IPortWaveCyclic_fnNotify,
IPortWaveCyclic_fnNewSlaveDmaChannel,
IPortWaveCyclic_fnNewMasterDmaChannel
};
//---------------------------------------------------------------
// ISubdevice interface
//
static
NTSTATUS
NTAPI
ISubDevice_fnQueryInterface(
IN ISubdevice *iface,
IN REFIID InterfaceId,
IN PVOID* Interface)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblSubDevice);
return IPortWaveCyclic_fnQueryInterface((IPortWaveCyclic*)This, InterfaceId, Interface);
}
static
ULONG
NTAPI
ISubDevice_fnAddRef(
IN ISubdevice *iface)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblSubDevice);
return IPortWaveCyclic_fnAddRef((IPortWaveCyclic*)This);
}
static
ULONG
NTAPI
ISubDevice_fnRelease(
IN ISubdevice *iface)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblSubDevice);
return IPortWaveCyclic_fnRelease((IPortWaveCyclic*)This);
}
static
NTSTATUS
NTAPI
ISubDevice_fnNewIrpTarget(
IN ISubdevice *iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortFilterWaveCyclic * Filter;
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblSubDevice);
DPRINT("ISubDevice_NewIrpTarget this %p\n", This);
/* is there already an instance of the filter */
if (This->Filter)
{
/* it is, let's return the result */
*OutTarget = (IIrpTarget*)This->Filter;
/* increment reference */
This->Filter->lpVtbl->AddRef(This->Filter);
return STATUS_SUCCESS;
}
/* create new instance of filter */
Status = NewPortFilterWaveCyclic(&Filter);
if (!NT_SUCCESS(Status))
{
/* not enough memory */
return Status;
}
/* initialize the filter */
Status = Filter->lpVtbl->Init(Filter, (IPortWaveCyclic*)This);
if (!NT_SUCCESS(Status))
{
/* destroy filter */
Filter->lpVtbl->Release(Filter);
/* return status */
return Status;
}
/* store result */
*OutTarget = (IIrpTarget*)Filter;
/* store for later re-use */
This->Filter = Filter;
/* return status */
return Status;
}
static
NTSTATUS
NTAPI
ISubDevice_fnReleaseChildren(
IN ISubdevice *iface)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblSubDevice);
DPRINT("ISubDevice_fnReleaseChildren ref %u\n", This->ref);
/* release the filter */
This->Filter->lpVtbl->Release(This->Filter);
if (This->pPinCount)
{
/* release pincount interface */
This->pPinCount->lpVtbl->Release(This->pPinCount);
}
if (This->pPowerNotify)
{
/* release power notify interface */
This->pPowerNotify->lpVtbl->Release(This->pPowerNotify);
}
/* now release the miniport */
This->pMiniport->lpVtbl->Release(This->pMiniport);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnGetDescriptor(
IN ISubdevice *iface,
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblSubDevice);
ASSERT(This->SubDeviceDescriptor != NULL);
*Descriptor = This->SubDeviceDescriptor;
DPRINT("ISubDevice_GetDescriptor this %p desc %p\n", This, This->SubDeviceDescriptor);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnDataRangeIntersection(
IN ISubdevice *iface,
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblSubDevice);
DPRINT("ISubDevice_DataRangeIntersection this %p\n", This);
if (This->pMiniport)
{
return This->pMiniport->lpVtbl->DataRangeIntersection (This->pMiniport, PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
}
return STATUS_UNSUCCESSFUL;
}
static
NTSTATUS
NTAPI
ISubDevice_fnPowerChangeNotify(
IN ISubdevice *iface,
IN POWER_STATE PowerState)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblSubDevice);
if (This->pPowerNotify)
{
This->pPowerNotify->lpVtbl->PowerChangeNotify(This->pPowerNotify, PowerState);
}
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnPinCount(
IN ISubdevice *iface,
IN ULONG PinId,
IN OUT PULONG FilterNecessary,
IN OUT PULONG FilterCurrent,
IN OUT PULONG FilterPossible,
IN OUT PULONG GlobalCurrent,
IN OUT PULONG GlobalPossible)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblSubDevice);
if (This->pPinCount)
{
This->pPinCount->lpVtbl->PinCount(This->pPinCount, PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
return STATUS_SUCCESS;
}
/* FIXME
* scan filter descriptor
*/
return STATUS_UNSUCCESSFUL;
}
static ISubdeviceVtbl vt_ISubdeviceVtbl =
{
ISubDevice_fnQueryInterface,
ISubDevice_fnAddRef,
ISubDevice_fnRelease,
ISubDevice_fnNewIrpTarget,
ISubDevice_fnReleaseChildren,
ISubDevice_fnGetDescriptor,
ISubDevice_fnDataRangeIntersection,
ISubDevice_fnPowerChangeNotify,
ISubDevice_fnPinCount
};
///--------------------------------------------------------------
PMINIPORTWAVECYCLIC
GetWaveCyclicMiniport(
IN IPortWaveCyclic* iface)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl *)iface;
return This->pMiniport;
}
PDEVICE_OBJECT
GetDeviceObject(
PPORTWAVECYCLIC iface)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl *)iface;
return This->pDeviceObject;
}
//---------------------------------------------------------------
// IPortWaveCyclic constructor
//
NTSTATUS
NewPortWaveCyclic(
OUT PPORT* OutPort)
{
IPortWaveCyclicImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IPortWaveCyclicImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->lpVtbl = &vt_IPortWaveCyclicVtbl;
This->lpVtblSubDevice = &vt_ISubdeviceVtbl;
This->lpVtblPortEvents = &vt_IPortEvents;
This->ref = 1;
*OutPort = (PPORT)(&This->lpVtbl);
DPRINT("NewPortWaveCyclic %p\n", *OutPort);
return STATUS_SUCCESS;
}
@@ -0,0 +1,629 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp
* PURPOSE: WaveCyclic Port Driver
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
GUID IID_IDmaChannelSlave;
class CPortWaveCyclic : public IPortWaveCyclic,
public IPortEvents,
public ISubdevice
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
DPRINT1("Release %u\n", m_Ref);
if (!m_Ref)
{
//delete this;
return 0;
}
return m_Ref;
}
IMP_IPortWaveCyclic;
IMP_ISubdevice;
IMP_IPortEvents;
CPortWaveCyclic(IUnknown *OuterUnknown){}
virtual ~CPortWaveCyclic(){}
protected:
BOOL m_bInitialized;
PDEVICE_OBJECT m_pDeviceObject;
PMINIPORTWAVECYCLIC m_pMiniport;
PRESOURCELIST m_pResourceList;
PPINCOUNT m_pPinCount;
PPOWERNOTIFY m_pPowerNotify;
PPCFILTER_DESCRIPTOR m_pDescriptor;
PSUBDEVICE_DESCRIPTOR m_SubDeviceDescriptor;
IPortFilterWaveCyclic * m_Filter;
LONG m_Ref;
friend PMINIPORTWAVECYCLIC GetWaveCyclicMiniport(IN IPortWaveCyclic* iface);
friend PDEVICE_OBJECT GetDeviceObject(PPORTWAVECYCLIC iface);
};
GUID KSPROPERTY_SETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
static GUID InterfaceGuids[4] =
{
{
/// KSCATEGORY_RENDER
0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KSCATEGORY_CAPTURE
0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
//KS_CATEGORY_AUDIO
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
///KSCATEGORY_AUDIO_DEVICE
0xFBF6F530L, 0x07B9, 0x11D2, {0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}
}
};
DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWaveCyclicTopologySet, TopologyPropertyHandler);
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWaveCyclicPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
KSPROPERTY_SET WaveCyclicPropertySet[] =
{
{
&KSPROPSETID_Topology,
sizeof(PortFilterWaveCyclicTopologySet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWaveCyclicTopologySet,
0,
NULL
},
{
&KSPROPSETID_Pin,
sizeof(PortFilterWaveCyclicPinSet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWaveCyclicPinSet,
0,
NULL
}
};
//KSEVENTSETID_LoopedStreaming, Type = KSEVENT_LOOPEDSTREAMING_POSITION
//KSEVENTSETID_Connection, Type = KSEVENT_CONNECTION_ENDOFSTREAM,
//---------------------------------------------------------------
// IPortEvents
//
void
NTAPI
CPortWaveCyclic::AddEventToEventList(
IN PKSEVENT_ENTRY EventEntry)
{
UNIMPLEMENTED
}
void
NTAPI
CPortWaveCyclic::GenerateEventList(
IN GUID* Set OPTIONAL,
IN ULONG EventId,
IN BOOL PinEvent,
IN ULONG PinId,
IN BOOL NodeEvent,
IN ULONG NodeId)
{
UNIMPLEMENTED
}
//---------------------------------------------------------------
// IUnknown interface functions
//
NTSTATUS
NTAPI
CPortWaveCyclic::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
if (IsEqualGUIDAligned(refiid, IID_IPortWaveCyclic) ||
IsEqualGUIDAligned(refiid, IID_IPort) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PPORTWAVECYCLIC(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPortEvents))
{
*Output = PVOID(PPORTEVENTS(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_ISubdevice))
{
*Output = PVOID(PSUBDEVICE(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPortClsVersion))
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IDrmPort) ||
IsEqualGUIDAligned(refiid, IID_IDrmPort2))
{
return NewIDrmPort((PDRMPORT2*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection))
{
return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IPortWaveCyclic_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
//---------------------------------------------------------------
// IPort interface functions
//
NTSTATUS
NTAPI
CPortWaveCyclic::GetDeviceProperty(
IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
IN ULONG BufferLength,
OUT PVOID PropertyBuffer,
OUT PULONG ReturnLength)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortWaveCyclic_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
}
NTSTATUS
NTAPI
CPortWaveCyclic::Init(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUNKNOWN UnknownMiniport,
IN PUNKNOWN UnknownAdapter OPTIONAL,
IN PRESOURCELIST ResourceList)
{
IMiniportWaveCyclic * Miniport;
NTSTATUS Status;
PPINCOUNT PinCount;
PPOWERNOTIFY PowerNotify;
DPRINT("IPortWaveCyclic_Init entered %p\n", this);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_bInitialized)
{
DPRINT("IPortWaveCyclic_Init called again\n");
return STATUS_SUCCESS;
}
Status = UnknownMiniport->QueryInterface(IID_IMiniportWaveCyclic, (PVOID*)&Miniport);
if (!NT_SUCCESS(Status))
{
DPRINT("IPortWaveCyclic_Init called with invalid IMiniport adapter\n");
return STATUS_INVALID_PARAMETER;
}
// Initialize port object
m_pMiniport = Miniport;
m_pDeviceObject = DeviceObject;
m_bInitialized = TRUE;
m_pResourceList = ResourceList;
if (ResourceList)
{
// increment reference on resource list
ResourceList->AddRef();
}
Status = Miniport->Init(UnknownAdapter, ResourceList, this);
if (!NT_SUCCESS(Status))
{
DPRINT("IMiniportWaveCyclic_Init failed with %x\n", Status);
Miniport->Release();
m_bInitialized = FALSE;
return Status;
}
// get the miniport device descriptor
Status = Miniport->GetDescription(&m_pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
Miniport->Release();
m_bInitialized = FALSE;
return Status;
}
// create the subdevice descriptor
Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
4,
InterfaceGuids,
0,
NULL,
2,
WaveCyclicPropertySet,
0,
0,
0,
NULL,
0,
NULL,
m_pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("PcCreateSubdeviceDescriptor failed with %x\n", Status);
Miniport->Release();
m_bInitialized = FALSE;
return Status;
}
// check if it supports IPinCount interface
Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount);
if (NT_SUCCESS(Status))
{
// store IPinCount interface
m_pPinCount = PinCount;
}
// does the Miniport adapter support IPowerNotify interface*/
Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify);
if (NT_SUCCESS(Status))
{
// store reference
m_pPowerNotify = PowerNotify;
}
DPRINT("IPortWaveCyclic successfully initialized\n");
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortWaveCyclic::NewRegistryKey(
OUT PREGISTRYKEY *OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortWaveCyclic_fnNewRegistryKey called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, DesiredAccess, m_pDeviceObject, NULL /*FIXME*/, ObjectAttributes, CreateOptions, Disposition);
}
//---------------------------------------------------------------
// IPortWaveCyclic interface functions
//
NTSTATUS
NTAPI
CPortWaveCyclic::NewMasterDmaChannel(
OUT PDMACHANNEL* DmaChannel,
IN PUNKNOWN OuterUnknown,
IN PRESOURCELIST ResourceList OPTIONAL,
IN ULONG MaximumLength,
IN BOOL Dma32BitAddresses,
IN BOOL Dma64BitAddresses,
IN DMA_WIDTH DmaWidth,
IN DMA_SPEED DmaSpeed)
{
NTSTATUS Status;
DEVICE_DESCRIPTION DeviceDescription;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortWaveCyclic_fnNewSlaveDmaChannel called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
Status = PcDmaMasterDescription(ResourceList, (Dma32BitAddresses | Dma64BitAddresses), Dma32BitAddresses, 0, Dma64BitAddresses, DmaWidth, DmaSpeed, MaximumLength, 0, &DeviceDescription);
if (NT_SUCCESS(Status))
{
return PcNewDmaChannel(DmaChannel, OuterUnknown, NonPagedPool, &DeviceDescription, m_pDeviceObject);
}
return Status;
}
NTSTATUS
NTAPI
CPortWaveCyclic::NewSlaveDmaChannel(
OUT PDMACHANNELSLAVE* OutDmaChannel,
IN PUNKNOWN OuterUnknown,
IN PRESOURCELIST ResourceList OPTIONAL,
IN ULONG DmaIndex,
IN ULONG MaximumLength,
IN BOOL DemandMode,
IN DMA_SPEED DmaSpeed)
{
DEVICE_DESCRIPTION DeviceDescription;
PDMACHANNEL DmaChannel;
NTSTATUS Status;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortWaveCyclic_fnNewSlaveDmaChannel called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
// FIXME
// Check for F-Type DMA Support
//
Status = PcDmaSlaveDescription(ResourceList, DmaIndex, DemandMode, TRUE, DmaSpeed, MaximumLength, 0, &DeviceDescription);
if (NT_SUCCESS(Status))
{
Status = PcNewDmaChannel(&DmaChannel, OuterUnknown, NonPagedPool, &DeviceDescription, m_pDeviceObject);
if (NT_SUCCESS(Status))
{
Status = DmaChannel->QueryInterface(IID_IDmaChannelSlave, (PVOID*)OutDmaChannel);
DmaChannel->Release();
}
}
return Status;
}
VOID
NTAPI
CPortWaveCyclic::Notify(
IN PSERVICEGROUP ServiceGroup)
{
ServiceGroup->RequestService ();
}
//---------------------------------------------------------------
// ISubdevice interface
//
NTSTATUS
NTAPI
CPortWaveCyclic::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortFilterWaveCyclic * Filter;
DPRINT("ISubDevice_NewIrpTarget this %p\n", this);
// is there already an instance of the filter
if (m_Filter)
{
// it is, let's return the result
*OutTarget = (IIrpTarget*)m_Filter;
// increment reference
m_Filter->AddRef();
return STATUS_SUCCESS;
}
// create new instance of filter
Status = NewPortFilterWaveCyclic(&Filter);
if (!NT_SUCCESS(Status))
{
// not enough memory
return Status;
}
// initialize the filter
Status = Filter->Init((IPortWaveCyclic*)this);
if (!NT_SUCCESS(Status))
{
// destroy filter
Filter->Release();
// return status
return Status;
}
// store result
*OutTarget = (IIrpTarget*)Filter;
// store for later re-use
m_Filter = Filter;
// return status
return Status;
}
NTSTATUS
NTAPI
CPortWaveCyclic::ReleaseChildren()
{
DPRINT("ISubDevice_fnReleaseChildren\n");
// release the filter
m_Filter->Release();
if (m_pPinCount)
{
// release pincount interface
m_pPinCount->Release();
}
if (m_pPowerNotify)
{
// release power notify interface
m_pPowerNotify->Release();
}
// now release the miniport
m_pMiniport->Release();
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortWaveCyclic::GetDescriptor(
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
{
PC_ASSERT(m_SubDeviceDescriptor != NULL);
*Descriptor = m_SubDeviceDescriptor;
DPRINT("ISubDevice_GetDescriptor this %p desc %p\n", this, m_SubDeviceDescriptor);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortWaveCyclic::DataRangeIntersection(
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
if (m_pMiniport)
{
return m_pMiniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortWaveCyclic::PowerChangeNotify(
IN POWER_STATE PowerState)
{
if (m_pPowerNotify)
{
m_pPowerNotify->PowerChangeNotify(PowerState);
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortWaveCyclic::PinCount(
IN ULONG PinId,
IN OUT PULONG FilterNecessary,
IN OUT PULONG FilterCurrent,
IN OUT PULONG FilterPossible,
IN OUT PULONG GlobalCurrent,
IN OUT PULONG GlobalPossible)
{
if (m_pPinCount)
{
m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
return STATUS_SUCCESS;
}
// FIXME
// scan filter descriptor
return STATUS_UNSUCCESSFUL;
}
///--------------------------------------------------------------
PMINIPORTWAVECYCLIC
GetWaveCyclicMiniport(
IN IPortWaveCyclic* iface)
{
CPortWaveCyclic * This = (CPortWaveCyclic *)iface;
return This->m_pMiniport;
}
PDEVICE_OBJECT
GetDeviceObject(
PPORTWAVECYCLIC iface)
{
CPortWaveCyclic * This = (CPortWaveCyclic *)iface;
return This->m_pDeviceObject;
}
//---------------------------------------------------------------
// IPortWaveCyclic constructor
//
NTSTATUS
NewPortWaveCyclic(
OUT PPORT* OutPort)
{
NTSTATUS Status;
CPortWaveCyclic * Port;
Port = new(NonPagedPool, TAG_PORTCLASS)CPortWaveCyclic(NULL);
if (!Port)
return STATUS_INSUFFICIENT_RESOURCES;
Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort);
if (!NT_SUCCESS(Status))
{
delete Port;
}
DPRINT("NewPortWaveCyclic %p Status %u\n", Port, Status);
return Status;
}
@@ -1,822 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port_wavepci.c
* PURPOSE: Wave PCI Port driver
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IPortWavePciVtbl *lpVtbl;
IServiceSinkVtbl *lpVtblServiceSink;
IPortEventsVtbl *lpVtblPortEvents;
ISubdeviceVtbl *lpVtblSubDevice;
#if 0
IUnregisterSubdevice *lpVtblUnregisterSubDevice;
#endif
LONG ref;
PMINIPORTWAVEPCI Miniport;
PDEVICE_OBJECT pDeviceObject;
BOOL bInitialized;
PRESOURCELIST pResourceList;
PSERVICEGROUP ServiceGroup;
PPINCOUNT pPinCount;
PPOWERNOTIFY pPowerNotify;
PPCFILTER_DESCRIPTOR pDescriptor;
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
IPortFilterWavePci * Filter;
LIST_ENTRY EventList;
KSPIN_LOCK EventListLock;
}IPortWavePciImpl;
static GUID InterfaceGuids[3] =
{
{
/// KSCATEGORY_RENDER
0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KSCATEGORY_CAPTURE
0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KS_CATEGORY_AUDIO
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
}
};
DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWavePciTopologySet, TopologyPropertyHandler);
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWavePciPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
KSPROPERTY_SET WavePciPropertySet[] =
{
{
&KSPROPSETID_Topology,
sizeof(PortFilterWavePciTopologySet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWavePciTopologySet,
0,
NULL
},
{
&KSPROPSETID_Pin,
sizeof(PortFilterWavePciPinSet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWavePciPinSet,
0,
NULL
}
};
//---------------------------------------------------------------
// IPortEvents
//
static
NTSTATUS
NTAPI
IPortEvents_fnQueryInterface(
IPortEvents* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, &IID_IPortEvents) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtblPortEvents;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
static
ULONG
NTAPI
IPortEvents_fnAddRef(
IPortEvents* iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnAddRef entered\n");
return InterlockedIncrement(&This->ref);
}
static
ULONG
NTAPI
IPortEvents_fnRelease(
IPortEvents* iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnRelease entered\n");
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
static
void
NTAPI
IPortEvents_fnAddEventToEventList(
IPortEvents* iface,
IN PKSEVENT_ENTRY EventEntry)
{
KIRQL OldIrql;
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblPortEvents);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
KeAcquireSpinLock(&This->EventListLock, &OldIrql);
InsertTailList(&This->EventList, &EventEntry->ListEntry);
KeReleaseSpinLock(&This->EventListLock, OldIrql);
}
static
void
NTAPI
IPortEvents_fnGenerateEventList(
IPortEvents* iface,
IN GUID* Set OPTIONAL,
IN ULONG EventId,
IN BOOL PinEvent,
IN ULONG PinId,
IN BOOL NodeEvent,
IN ULONG NodeId)
{
UNIMPLEMENTED
}
static IPortEventsVtbl vt_IPortEvents =
{
IPortEvents_fnQueryInterface,
IPortEvents_fnAddRef,
IPortEvents_fnRelease,
IPortEvents_fnAddEventToEventList,
IPortEvents_fnGenerateEventList
};
//---------------------------------------------------------------
// IServiceSink
//
static
NTSTATUS
NTAPI
IServiceSink_fnQueryInterface(
IServiceSink* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblServiceSink);
DPRINT("IServiceSink_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, &IID_IServiceSink) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtblServiceSink;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
static
ULONG
NTAPI
IServiceSink_fnAddRef(
IServiceSink* iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblServiceSink);
DPRINT("IServiceSink_fnAddRef entered\n");
return InterlockedIncrement(&This->ref);
}
static
ULONG
NTAPI
IServiceSink_fnRelease(
IServiceSink* iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblServiceSink);
DPRINT("IServiceSink_fnRelease entered\n");
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
static
VOID
NTAPI
IServiceSink_fnRequestService(
IServiceSink* iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblServiceSink);
//DPRINT("IServiceSink_fnRequestService entered\n");
if (This->Miniport)
{
This->Miniport->lpVtbl->Service(This->Miniport);
}
}
static IServiceSinkVtbl vt_IServiceSink =
{
IServiceSink_fnQueryInterface,
IServiceSink_fnAddRef,
IServiceSink_fnRelease,
IServiceSink_fnRequestService
};
//---------------------------------------------------------------
// IPortWavePci
//
static
NTSTATUS
NTAPI
IPortWavePci_fnQueryInterface(
IPortWavePci* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
DPRINT("IPortWavePci_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, &IID_IPortWavePci) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IServiceSink))
{
*Output = &This->lpVtblServiceSink;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPortEvents))
{
*Output = &This->lpVtblPortEvents;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_ISubdevice))
{
*Output = &This->lpVtblSubDevice;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion))
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterPhysicalConnection))
{
return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IPortWavePci_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
static
ULONG
NTAPI
IPortWavePci_fnAddRef(
IPortWavePci* iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
DPRINT("IPortWavePci_fnAddRef entered\n");
return InterlockedIncrement(&This->ref);
}
static
ULONG
NTAPI
IPortWavePci_fnRelease(
IPortWavePci* iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
DPRINT("IPortWavePci_fnRelease entered\n");
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
NTSTATUS
NTAPI
IPortWavePci_fnInit(
IN IPortWavePci * iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUNKNOWN UnknownMiniport,
IN PUNKNOWN UnknownAdapter OPTIONAL,
IN PRESOURCELIST ResourceList)
{
IMiniportWavePci * Miniport;
PSERVICEGROUP ServiceGroup;
NTSTATUS Status;
PPINCOUNT PinCount;
PPOWERNOTIFY PowerNotify;
IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
DPRINT("IPortWavePci_fnInit entered with This %p, DeviceObject %p Irp %p UnknownMiniport %p, UnknownAdapter %p ResourceList %p\n",
This, DeviceObject, Irp, UnknownMiniport, UnknownAdapter, ResourceList);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->bInitialized)
{
DPRINT("IPortWavePci_fnInit called again\n");
return STATUS_SUCCESS;
}
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportWavePci, (PVOID*)&Miniport);
if (!NT_SUCCESS(Status))
{
DPRINT("IPortWavePci_fnInit called with invalid IMiniport adapter\n");
return STATUS_INVALID_PARAMETER;
}
/* Initialize port object */
This->Miniport = Miniport;
This->pDeviceObject = DeviceObject;
This->bInitialized = TRUE;
This->pResourceList = ResourceList;
InitializeListHead(&This->EventList);
KeInitializeSpinLock(&This->EventListLock);
/* increment reference on miniport adapter */
Miniport->lpVtbl->AddRef(Miniport);
/* increment reference on resource list */
ResourceList->lpVtbl->AddRef(ResourceList);
Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface, &ServiceGroup);
if (!NT_SUCCESS(Status))
{
DPRINT("IPortWavePci_fnInit failed with %x\n", Status);
This->bInitialized = FALSE;
/* release reference on miniport adapter */
Miniport->lpVtbl->Release(Miniport);
/* increment reference on resource list */
ResourceList->lpVtbl->Release(ResourceList);
return Status;
}
/* check if the miniport adapter provides a valid device descriptor */
Status = Miniport->lpVtbl->GetDescription(Miniport, &This->pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
Miniport->lpVtbl->Release(Miniport);
This->bInitialized = FALSE;
return Status;
}
/* create the subdevice descriptor */
Status = PcCreateSubdeviceDescriptor(&This->SubDeviceDescriptor,
3,
InterfaceGuids,
0,
NULL,
2,
WavePciPropertySet,
0,
0,
0,
NULL,
0,
NULL,
This->pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("PcCreateSubdeviceDescriptor failed with %x\n", Status);
Miniport->lpVtbl->Release(Miniport);
This->bInitialized = FALSE;
return Status;
}
/* did we get a service group */
if (ServiceGroup)
{
/* store service group in context */
This->ServiceGroup = ServiceGroup;
/* add ourselves to service group which is called when miniport receives an isr */
ServiceGroup->lpVtbl->AddMember(ServiceGroup, (PSERVICESINK)&This->lpVtblServiceSink);
/* increment reference on service group */
ServiceGroup->lpVtbl->AddRef(ServiceGroup);
}
/* check if it supports IPinCount interface */
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPinCount, (PVOID*)&PinCount);
if (NT_SUCCESS(Status))
{
/* store IPinCount interface */
This->pPinCount = PinCount;
}
/* does the Miniport adapter support IPowerNotify interface*/
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPowerNotify, (PVOID*)&PowerNotify);
if (NT_SUCCESS(Status))
{
/* store reference */
This->pPowerNotify = PowerNotify;
}
DPRINT("IPortWavePci_Init sucessfully initialized\n");
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IPortWavePci_fnNewRegistryKey(
IN IPortWavePci * iface,
OUT PREGISTRYKEY *OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
DPRINT("IPortWavePci_fnNewRegistryKey entered\n");
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortWavePci_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return PcNewRegistryKey(OutRegistryKey,
OuterUnknown,
RegistryKeyType,
DesiredAccess,
This->pDeviceObject,
NULL,//FIXME
ObjectAttributes,
CreateOptions,
Disposition);
}
NTSTATUS
NTAPI
IPortWavePci_fnGetDeviceProperty(
IN IPortWavePci * iface,
IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
IN ULONG BufferLength,
OUT PVOID PropertyBuffer,
OUT PULONG ReturnLength)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
DPRINT("IPortWavePci_fnGetDeviceProperty entered\n");
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortWavePci_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return IoGetDeviceProperty(This->pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
}
NTSTATUS
NTAPI
IPortWavePci_fnNewMasterDmaChannel(
IN IPortWavePci * iface,
OUT PDMACHANNEL *DmaChannel,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PRESOURCELIST ResourceList OPTIONAL,
IN BOOLEAN ScatterGather,
IN BOOLEAN Dma32BitAddresses,
IN BOOLEAN Dma64BitAddresses,
IN BOOLEAN IgnoreCount,
IN DMA_WIDTH DmaWidth,
IN DMA_SPEED DmaSpeed,
IN ULONG MaximumLength,
IN ULONG DmaPort)
{
NTSTATUS Status;
DEVICE_DESCRIPTION DeviceDescription;
IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
DPRINT("IPortWavePci_fnNewMasterDmaChannel This %p entered\n", This);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
Status = PcDmaMasterDescription(ResourceList, ScatterGather, Dma32BitAddresses, IgnoreCount, Dma64BitAddresses, DmaWidth, DmaSpeed, MaximumLength, DmaPort, &DeviceDescription);
if (NT_SUCCESS(Status))
{
return PcNewDmaChannel(DmaChannel, OuterUnknown, PoolType, &DeviceDescription, This->pDeviceObject);
}
return Status;
}
VOID
NTAPI
IPortWavePci_fnNotify(
IN IPortWavePci * iface,
IN PSERVICEGROUP ServiceGroup)
{
//IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
//DPRINT("IPortWavePci_fnNotify entered %p, ServiceGroup %p\n", This, ServiceGroup);
if (ServiceGroup)
{
ServiceGroup->lpVtbl->RequestService (ServiceGroup);
}
}
static IPortWavePciVtbl vt_IPortWavePci =
{
/* IUnknown methods */
IPortWavePci_fnQueryInterface,
IPortWavePci_fnAddRef,
IPortWavePci_fnRelease,
/* IPort methods */
IPortWavePci_fnInit,
IPortWavePci_fnGetDeviceProperty,
IPortWavePci_fnNewRegistryKey,
/* IPortWavePci methods */
IPortWavePci_fnNotify,
IPortWavePci_fnNewMasterDmaChannel,
};
//---------------------------------------------------------------
// ISubdevice interface
//
static
NTSTATUS
NTAPI
ISubDevice_fnQueryInterface(
IN ISubdevice *iface,
IN REFIID InterfaceId,
IN PVOID* Interface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
return IPortWavePci_fnQueryInterface((IPortWavePci*)This, InterfaceId, Interface);
}
static
ULONG
NTAPI
ISubDevice_fnAddRef(
IN ISubdevice *iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
return IPortWavePci_fnAddRef((IPortWavePci*)This);
}
static
ULONG
NTAPI
ISubDevice_fnRelease(
IN ISubdevice *iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
return IPortWavePci_fnRelease((IPortWavePci*)This);
}
static
NTSTATUS
NTAPI
ISubDevice_fnNewIrpTarget(
IN ISubdevice *iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortFilterWavePci * Filter;
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
DPRINT("ISubDevice_NewIrpTarget this %p\n", This);
if (This->Filter)
{
*OutTarget = (IIrpTarget*)This->Filter;
return STATUS_SUCCESS;
}
Status = NewPortFilterWavePci(&Filter);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = Filter->lpVtbl->Init(Filter, (IPortWavePci*)This);
if (!NT_SUCCESS(Status))
{
Filter->lpVtbl->Release(Filter);
return Status;
}
*OutTarget = (IIrpTarget*)Filter;
This->Filter = Filter;
return Status;
}
static
NTSTATUS
NTAPI
ISubDevice_fnReleaseChildren(
IN ISubdevice *iface)
{
//IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
UNIMPLEMENTED
return STATUS_UNSUCCESSFUL;
}
static
NTSTATUS
NTAPI
ISubDevice_fnGetDescriptor(
IN ISubdevice *iface,
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
DPRINT1("ISubDevice_GetDescriptor this %p\n", This);
*Descriptor = This->SubDeviceDescriptor;
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnDataRangeIntersection(
IN ISubdevice *iface,
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
DPRINT("ISubDevice_DataRangeIntersection this %p\n", This);
if (This->Miniport)
{
return This->Miniport->lpVtbl->DataRangeIntersection (This->Miniport, PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
}
return STATUS_UNSUCCESSFUL;
}
static
NTSTATUS
NTAPI
ISubDevice_fnPowerChangeNotify(
IN ISubdevice *iface,
IN POWER_STATE PowerState)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
if (This->pPowerNotify)
{
This->pPowerNotify->lpVtbl->PowerChangeNotify(This->pPowerNotify, PowerState);
}
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnPinCount(
IN ISubdevice *iface,
IN ULONG PinId,
IN OUT PULONG FilterNecessary,
IN OUT PULONG FilterCurrent,
IN OUT PULONG FilterPossible,
IN OUT PULONG GlobalCurrent,
IN OUT PULONG GlobalPossible)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
if (This->pPinCount)
{
This->pPinCount->lpVtbl->PinCount(This->pPinCount, PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
return STATUS_SUCCESS;
}
/* FIXME
* scan filter descriptor
*/
return STATUS_UNSUCCESSFUL;
}
static ISubdeviceVtbl vt_ISubdeviceVtbl =
{
ISubDevice_fnQueryInterface,
ISubDevice_fnAddRef,
ISubDevice_fnRelease,
ISubDevice_fnNewIrpTarget,
ISubDevice_fnReleaseChildren,
ISubDevice_fnGetDescriptor,
ISubDevice_fnDataRangeIntersection,
ISubDevice_fnPowerChangeNotify,
ISubDevice_fnPinCount
};
NTSTATUS
NewPortWavePci(
OUT PPORT* OutPort)
{
IPortWavePciImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IPortWavePciImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->lpVtblServiceSink = &vt_IServiceSink;
This->lpVtbl = &vt_IPortWavePci;
This->lpVtblSubDevice = &vt_ISubdeviceVtbl;
This->lpVtblPortEvents = &vt_IPortEvents;
This->ref = 1;
*OutPort = (PPORT)&This->lpVtbl;
DPRINT("NewPortWavePci %p\n", *OutPort);
return STATUS_SUCCESS;
}
PDEVICE_OBJECT
GetDeviceObjectFromPortWavePci(
IPortWavePci* iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
return This->pDeviceObject;
}
PMINIPORTWAVEPCI
GetWavePciMiniport(
PPORTWAVEPCI iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
return This->Miniport;
}
@@ -0,0 +1,591 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port_wavepci.cpp
* PURPOSE: Wave PCI Port driver
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortWavePci : public IPortWavePci,
public IPortEvents,
public ISubdevice,
public IServiceSink
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortWavePci;
IMP_ISubdevice;
IMP_IPortEvents;
IMP_IServiceSink;
CPortWavePci(IUnknown *OuterUnknown){}
virtual ~CPortWavePci() {}
protected:
PMINIPORTWAVEPCI m_Miniport;
PDEVICE_OBJECT m_pDeviceObject;
BOOL m_bInitialized;
PRESOURCELIST m_pResourceList;
PSERVICEGROUP m_ServiceGroup;
PPINCOUNT m_pPinCount;
PPOWERNOTIFY m_pPowerNotify;
PPCFILTER_DESCRIPTOR m_pDescriptor;
PSUBDEVICE_DESCRIPTOR m_SubDeviceDescriptor;
IPortFilterWavePci * m_Filter;
LIST_ENTRY m_EventList;
KSPIN_LOCK m_EventListLock;
LONG m_Ref;
friend PDEVICE_OBJECT GetDeviceObjectFromPortWavePci(IPortWavePci* iface);
friend PMINIPORTWAVEPCI GetWavePciMiniport(PPORTWAVEPCI iface);
};
static GUID InterfaceGuids[3] =
{
{
/// KSCATEGORY_RENDER
0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KSCATEGORY_CAPTURE
0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KS_CATEGORY_AUDIO
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
}
};
DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWavePciTopologySet, TopologyPropertyHandler);
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWavePciPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
KSPROPERTY_SET WavePciPropertySet[] =
{
{
&KSPROPSETID_Topology,
sizeof(PortFilterWavePciTopologySet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWavePciTopologySet,
0,
NULL
},
{
&KSPROPSETID_Pin,
sizeof(PortFilterWavePciPinSet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWavePciPinSet,
0,
NULL
}
};
//---------------------------------------------------------------
// IPortEvents
//
void
NTAPI
CPortWavePci::AddEventToEventList(
IN PKSEVENT_ENTRY EventEntry)
{
KIRQL OldIrql;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
KeAcquireSpinLock(&m_EventListLock, &OldIrql);
InsertTailList(&m_EventList, &EventEntry->ListEntry);
KeReleaseSpinLock(&m_EventListLock, OldIrql);
}
void
NTAPI
CPortWavePci::GenerateEventList(
IN GUID* Set OPTIONAL,
IN ULONG EventId,
IN BOOL PinEvent,
IN ULONG PinId,
IN BOOL NodeEvent,
IN ULONG NodeId)
{
UNIMPLEMENTED
}
//---------------------------------------------------------------
// IServiceSink
//
VOID
NTAPI
CPortWavePci::RequestService()
{
//DPRINT("IServiceSink_fnRequestService entered\n");
if (m_Miniport)
{
m_Miniport->Service();
}
}
//---------------------------------------------------------------
// IPortWavePci
//
NTSTATUS
NTAPI
CPortWavePci::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
DPRINT("IPortWavePci_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, IID_IPortWavePci) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PPORTWAVEPCI(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
{
*Output = PVOID(PSERVICESINK(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPortEvents))
{
*Output = PVOID(PPORTEVENTS(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_ISubdevice))
{
*Output = PVOID(PSUBDEVICE(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPortClsVersion))
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection))
{
return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IPortWavePci_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortWavePci::Init(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUNKNOWN UnknownMiniport,
IN PUNKNOWN UnknownAdapter OPTIONAL,
IN PRESOURCELIST ResourceList)
{
IMiniportWavePci * Miniport;
PSERVICEGROUP ServiceGroup;
NTSTATUS Status;
PPINCOUNT PinCount;
PPOWERNOTIFY PowerNotify;
DPRINT("IPortWavePci_fnInit entered with This %p, DeviceObject %p Irp %p UnknownMiniport %p, UnknownAdapter %p ResourceList %p\n",
this, DeviceObject, Irp, UnknownMiniport, UnknownAdapter, ResourceList);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_bInitialized)
{
DPRINT("IPortWavePci_fnInit called again\n");
return STATUS_SUCCESS;
}
Status = UnknownMiniport->QueryInterface(IID_IMiniportWavePci, (PVOID*)&Miniport);
if (!NT_SUCCESS(Status))
{
DPRINT("IPortWavePci_fnInit called with invalid IMiniport adapter\n");
return STATUS_INVALID_PARAMETER;
}
// Initialize port object
m_Miniport = Miniport;
m_pDeviceObject = DeviceObject;
m_bInitialized = TRUE;
m_pResourceList = ResourceList;
InitializeListHead(&m_EventList);
KeInitializeSpinLock(&m_EventListLock);
// increment reference on miniport adapter
Miniport->AddRef();
// increment reference on resource list
ResourceList->AddRef();
Status = Miniport->Init(UnknownAdapter, ResourceList, this, &ServiceGroup);
if (!NT_SUCCESS(Status))
{
DPRINT("IPortWavePci_fnInit failed with %x\n", Status);
m_bInitialized = FALSE;
// release reference on miniport adapter
Miniport->Release();
// increment reference on resource list
ResourceList->Release();
return Status;
}
// check if the miniport adapter provides a valid device descriptor
Status = Miniport->GetDescription(&m_pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
Miniport->Release();
m_bInitialized = FALSE;
return Status;
}
// create the subdevice descriptor
Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
3,
InterfaceGuids,
0,
NULL,
2,
WavePciPropertySet,
0,
0,
0,
NULL,
0,
NULL,
m_pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("PcCreateSubdeviceDescriptor failed with %x\n", Status);
Miniport->Release();
m_bInitialized = FALSE;
return Status;
}
// did we get a service group
if (ServiceGroup)
{
// store service group in context
m_ServiceGroup = ServiceGroup;
// add ourselves to service group which is called when miniport receives an isr
m_ServiceGroup->AddMember(PSERVICESINK(this));
// increment reference on service group
m_ServiceGroup->AddRef();
}
// check if it supports IPinCount interface
Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount);
if (NT_SUCCESS(Status))
{
// store IPinCount interface
m_pPinCount = PinCount;
}
// does the Miniport adapter support IPowerNotify interface*/
Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify);
if (NT_SUCCESS(Status))
{
// store reference
m_pPowerNotify = PowerNotify;
}
DPRINT("IPortWavePci_Init sucessfully initialized\n");
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortWavePci::NewRegistryKey(
OUT PREGISTRYKEY *OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
DPRINT("IPortWavePci_fnNewRegistryKey entered\n");
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortWavePci_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return PcNewRegistryKey(OutRegistryKey,
OuterUnknown,
RegistryKeyType,
DesiredAccess,
m_pDeviceObject,
NULL,//FIXME
ObjectAttributes,
CreateOptions,
Disposition);
}
NTSTATUS
NTAPI
CPortWavePci::GetDeviceProperty(
IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
IN ULONG BufferLength,
OUT PVOID PropertyBuffer,
OUT PULONG ReturnLength)
{
DPRINT("IPortWavePci_fnGetDeviceProperty entered\n");
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortWavePci_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
}
NTSTATUS
NTAPI
CPortWavePci::NewMasterDmaChannel(
OUT PDMACHANNEL *DmaChannel,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PRESOURCELIST ResourceList OPTIONAL,
IN BOOLEAN ScatterGather,
IN BOOLEAN Dma32BitAddresses,
IN BOOLEAN Dma64BitAddresses,
IN BOOLEAN IgnoreCount,
IN DMA_WIDTH DmaWidth,
IN DMA_SPEED DmaSpeed,
IN ULONG MaximumLength,
IN ULONG DmaPort)
{
NTSTATUS Status;
DEVICE_DESCRIPTION DeviceDescription;
DPRINT("IPortWavePci_fnNewMasterDmaChannel This %p entered\n", this);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
Status = PcDmaMasterDescription(ResourceList, ScatterGather, Dma32BitAddresses, IgnoreCount, Dma64BitAddresses, DmaWidth, DmaSpeed, MaximumLength, DmaPort, &DeviceDescription);
if (NT_SUCCESS(Status))
{
return PcNewDmaChannel(DmaChannel, OuterUnknown, PoolType, &DeviceDescription, m_pDeviceObject);
}
return Status;
}
VOID
NTAPI
CPortWavePci::Notify(
IN PSERVICEGROUP ServiceGroup)
{
//IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
//DPRINT("IPortWavePci_fnNotify entered %p, ServiceGroup %p\n", This, ServiceGroup);
if (ServiceGroup)
{
ServiceGroup->RequestService ();
}
}
//---------------------------------------------------------------
// ISubdevice interface
//
NTSTATUS
NTAPI
CPortWavePci::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortFilterWavePci * Filter;
DPRINT("ISubDevice_NewIrpTarget this %p\n", this);
if (m_Filter)
{
*OutTarget = (IIrpTarget*)m_Filter;
return STATUS_SUCCESS;
}
Status = NewPortFilterWavePci(&Filter);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = Filter->Init((IPortWavePci*)this);
if (!NT_SUCCESS(Status))
{
Filter->Release();
return Status;
}
*OutTarget = (IIrpTarget*)Filter;
m_Filter = Filter;
return Status;
}
NTSTATUS
NTAPI
CPortWavePci::ReleaseChildren()
{
//IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
UNIMPLEMENTED
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortWavePci::GetDescriptor(
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
{
DPRINT1("ISubDevice_GetDescriptor this %p\n", this);
*Descriptor = m_SubDeviceDescriptor;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortWavePci::DataRangeIntersection(
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
if (m_Miniport)
{
return m_Miniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortWavePci::PowerChangeNotify(
IN POWER_STATE PowerState)
{
if (m_pPowerNotify)
{
m_pPowerNotify->PowerChangeNotify(PowerState);
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortWavePci::PinCount(
IN ULONG PinId,
IN OUT PULONG FilterNecessary,
IN OUT PULONG FilterCurrent,
IN OUT PULONG FilterPossible,
IN OUT PULONG GlobalCurrent,
IN OUT PULONG GlobalPossible)
{
if (m_pPinCount)
{
m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
return STATUS_SUCCESS;
}
// FIXME
// scan filter descriptor
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NewPortWavePci(
OUT PPORT* OutPort)
{
CPortWavePci * Port;
NTSTATUS Status;
Port = new(NonPagedPool, TAG_PORTCLASS) CPortWavePci(NULL);
if (!Port)
return STATUS_INSUFFICIENT_RESOURCES;
Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort);
if (!NT_SUCCESS(Status))
{
delete Port;
}
DPRINT("NewPortWavePci %p Status %u\n", Port, Status);
return Status;
}
PDEVICE_OBJECT
GetDeviceObjectFromPortWavePci(
IPortWavePci* iface)
{
CPortWavePci * This = (CPortWavePci*)iface;
return This->m_pDeviceObject;
}
PMINIPORTWAVEPCI
GetWavePciMiniport(
PPORTWAVEPCI iface)
{
CPortWavePci * This = (CPortWavePci*)iface;
return This->m_Miniport;
}
@@ -1,685 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port_wavert.c
* PURPOSE: WaveRT Port Driver
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IPortWaveRTVtbl *lpVtbl;
IPortEventsVtbl *lpVbtlPortEvents;
IUnregisterSubdeviceVtbl *lpVtblUnregisterSubdevice;
IUnregisterPhysicalConnectionVtbl *lpVtblPhysicalConnection;
IPortEventsVtbl *lpVtblPortEvents;
ISubdeviceVtbl *lpVtblSubDevice;
LONG ref;
BOOL bInitialized;
PDEVICE_OBJECT pDeviceObject;
PMINIPORTWAVERT pMiniport;
PRESOURCELIST pResourceList;
PPINCOUNT pPinCount;
PPOWERNOTIFY pPowerNotify;
PPCFILTER_DESCRIPTOR pDescriptor;
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
IPortFilterWaveRT * Filter;
}IPortWaveRTImpl;
static GUID InterfaceGuids[3] =
{
{
/// KSCATEGORY_RENDER
0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KSCATEGORY_CAPTURE
0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KS_CATEGORY_AUDIO
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
}
};
DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWaveRTTopologySet, TopologyPropertyHandler);
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWaveRTPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
KSPROPERTY_SET WaveRTPropertySet[] =
{
{
&KSPROPSETID_Topology,
sizeof(PortFilterWaveRTTopologySet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWaveRTTopologySet,
0,
NULL
},
{
&KSPROPSETID_Pin,
sizeof(PortFilterWaveRTPinSet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWaveRTPinSet,
0,
NULL
}
};
//KSEVENTSETID_LoopedStreaming, Type = KSEVENT_LOOPEDSTREAMING_POSITION
//KSEVENTSETID_Connection, Type = KSEVENT_CONNECTION_ENDOFSTREAM,
#if 0
static const KSIDENTIFIER Identifiers[] =
{
{
&KSINTERFACESETID_Standard,
0,
0
},
{
&KSINTERFACESETID_Standard,
1,
0
}
};
#endif
//---------------------------------------------------------------
// IPortEvents
//
static
NTSTATUS
NTAPI
IPortEvents_fnQueryInterface(
IPortEvents* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, &IID_IPortEvents) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVbtlPortEvents;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
static
ULONG
NTAPI
IPortEvents_fnAddRef(
IPortEvents* iface)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnQueryInterface entered\n");
return InterlockedIncrement(&This->ref);
}
static
ULONG
NTAPI
IPortEvents_fnRelease(
IPortEvents* iface)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblPortEvents);
DPRINT("IPortEvents_fnRelease entered\n");
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
static
void
NTAPI
IPortEvents_fnAddEventToEventList(
IPortEvents* iface,
IN PKSEVENT_ENTRY EventEntry)
{
UNIMPLEMENTED
}
static
void
NTAPI
IPortEvents_fnGenerateEventList(
IPortEvents* iface,
IN GUID* Set OPTIONAL,
IN ULONG EventId,
IN BOOL PinEvent,
IN ULONG PinId,
IN BOOL NodeEvent,
IN ULONG NodeId)
{
UNIMPLEMENTED
}
static IPortEventsVtbl vt_IPortEvents =
{
IPortEvents_fnQueryInterface,
IPortEvents_fnAddRef,
IPortEvents_fnRelease,
IPortEvents_fnAddEventToEventList,
IPortEvents_fnGenerateEventList
};
//---------------------------------------------------------------
// IUnknown interface functions
//
NTSTATUS
NTAPI
IPortWaveRT_fnQueryInterface(
IPortWaveRT* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IPortWaveRT) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPortEvents))
{
*Output = &This->lpVtblPortEvents;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_ISubdevice))
{
*Output = &This->lpVtblSubDevice;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion))
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IDrmPort) ||
IsEqualGUIDAligned(refiid, &IID_IDrmPort2))
{
return NewIDrmPort((PDRMPORT2*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterPhysicalConnection))
{
return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IPortWaveRT_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IPortWaveRT_fnAddRef(
IPortWaveRT* iface)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IPortWaveRT_fnRelease(
IPortWaveRT* iface)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
if (This->bInitialized)
{
This->pMiniport->lpVtbl->Release(This->pMiniport);
}
if (This->pPinCount)
This->pPinCount->lpVtbl->Release(This->pPinCount);
if (This->pPowerNotify)
This->pPowerNotify->lpVtbl->Release(This->pPowerNotify);
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
//---------------------------------------------------------------
// IPort interface functions
//
NTSTATUS
NTAPI
IPortWaveRT_fnGetDeviceProperty(
IN IPortWaveRT * iface,
IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
IN ULONG BufferLength,
OUT PVOID PropertyBuffer,
OUT PULONG ReturnLength)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortWaveRT_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return IoGetDeviceProperty(This->pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
}
NTSTATUS
NTAPI
IPortWaveRT_fnInit(
IN IPortWaveRT * iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUNKNOWN UnknownMiniport,
IN PUNKNOWN UnknownAdapter OPTIONAL,
IN PRESOURCELIST ResourceList)
{
IMiniportWaveRT * Miniport;
NTSTATUS Status;
PPINCOUNT PinCount;
PPOWERNOTIFY PowerNotify;
IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
DPRINT("IPortWaveRT_Init entered %p\n", This);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->bInitialized)
{
DPRINT("IPortWaveRT_Init called again\n");
return STATUS_SUCCESS;
}
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportWaveRT, (PVOID*)&Miniport);
if (!NT_SUCCESS(Status))
{
DPRINT("IPortWaveRT_Init called with invalid IMiniport adapter\n");
return STATUS_INVALID_PARAMETER;
}
/* Initialize port object */
This->pMiniport = Miniport;
This->pDeviceObject = DeviceObject;
This->bInitialized = TRUE;
This->pResourceList = ResourceList;
/* increment reference on miniport adapter */
Miniport->lpVtbl->AddRef(Miniport);
Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface);
if (!NT_SUCCESS(Status))
{
DPRINT("IMiniportWaveRT_Init failed with %x\n", Status);
Miniport->lpVtbl->Release(Miniport);
This->bInitialized = FALSE;
return Status;
}
/* get the miniport device descriptor */
Status = Miniport->lpVtbl->GetDescription(Miniport, &This->pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
Miniport->lpVtbl->Release(Miniport);
This->bInitialized = FALSE;
return Status;
}
/* create the subdevice descriptor */
Status = PcCreateSubdeviceDescriptor(&This->SubDeviceDescriptor,
3,
InterfaceGuids,
0,
NULL,
2,
WaveRTPropertySet,
0,
0,
0,
NULL,
0,
NULL,
This->pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("PcCreateSubdeviceDescriptor failed with %x\n", Status);
Miniport->lpVtbl->Release(Miniport);
This->bInitialized = FALSE;
return Status;
}
/* check if it supports IPinCount interface */
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPinCount, (PVOID*)&PinCount);
if (NT_SUCCESS(Status))
{
/* store IPinCount interface */
This->pPinCount = PinCount;
}
/* does the Miniport adapter support IPowerNotify interface*/
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPowerNotify, (PVOID*)&PowerNotify);
if (NT_SUCCESS(Status))
{
/* store reference */
This->pPowerNotify = PowerNotify;
}
/* increment reference on resource list */
ResourceList->lpVtbl->AddRef(ResourceList);
DPRINT("IPortWaveRT successfully initialized\n");
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IPortWaveRT_fnNewRegistryKey(
IN IPortWaveRT * iface,
OUT PREGISTRYKEY *OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->bInitialized)
{
DPRINT("IPortWaveRT_fnNewRegistryKey called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, DesiredAccess, This->pDeviceObject, NULL /*FIXME*/, ObjectAttributes, CreateOptions, Disposition);
}
static IPortWaveRTVtbl vt_IPortWaveRTVtbl =
{
IPortWaveRT_fnQueryInterface,
IPortWaveRT_fnAddRef,
IPortWaveRT_fnRelease,
IPortWaveRT_fnInit,
IPortWaveRT_fnGetDeviceProperty,
IPortWaveRT_fnNewRegistryKey
};
//---------------------------------------------------------------
// ISubdevice interface
//
static
NTSTATUS
NTAPI
ISubDevice_fnQueryInterface(
IN ISubdevice *iface,
IN REFIID InterfaceId,
IN PVOID* Interface)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
return IPortWaveRT_fnQueryInterface((IPortWaveRT*)This, InterfaceId, Interface);
}
static
ULONG
NTAPI
ISubDevice_fnAddRef(
IN ISubdevice *iface)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
return IPortWaveRT_fnAddRef((IPortWaveRT*)This);
}
static
ULONG
NTAPI
ISubDevice_fnRelease(
IN ISubdevice *iface)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
return IPortWaveRT_fnRelease((IPortWaveRT*)This);
}
static
NTSTATUS
NTAPI
ISubDevice_fnNewIrpTarget(
IN ISubdevice *iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortFilterWaveRT * Filter;
IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
DPRINT("ISubDevice_NewIrpTarget this %p\n", This);
if (This->Filter)
{
*OutTarget = (IIrpTarget*)This->Filter;
return STATUS_SUCCESS;
}
Status = NewPortFilterWaveRT(&Filter);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = Filter->lpVtbl->Init(Filter, (IPortWaveRT*)This);
if (!NT_SUCCESS(Status))
{
Filter->lpVtbl->Release(Filter);
return Status;
}
*OutTarget = (IIrpTarget*)Filter;
This->Filter = Filter;
return Status;
}
static
NTSTATUS
NTAPI
ISubDevice_fnReleaseChildren(
IN ISubdevice *iface)
{
//IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
UNIMPLEMENTED
return STATUS_UNSUCCESSFUL;
}
static
NTSTATUS
NTAPI
ISubDevice_fnGetDescriptor(
IN ISubdevice *iface,
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
ASSERT(This->SubDeviceDescriptor != NULL);
*Descriptor = This->SubDeviceDescriptor;
DPRINT("ISubDevice_GetDescriptor this %p desc %p\n", This, This->SubDeviceDescriptor);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnDataRangeIntersection(
IN ISubdevice *iface,
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
DPRINT("ISubDevice_DataRangeIntersection this %p\n", This);
if (This->pMiniport)
{
return This->pMiniport->lpVtbl->DataRangeIntersection (This->pMiniport, PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
}
return STATUS_UNSUCCESSFUL;
}
static
NTSTATUS
NTAPI
ISubDevice_fnPowerChangeNotify(
IN ISubdevice *iface,
IN POWER_STATE PowerState)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
if (This->pPowerNotify)
{
This->pPowerNotify->lpVtbl->PowerChangeNotify(This->pPowerNotify, PowerState);
}
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
ISubDevice_fnPinCount(
IN ISubdevice *iface,
IN ULONG PinId,
IN OUT PULONG FilterNecessary,
IN OUT PULONG FilterCurrent,
IN OUT PULONG FilterPossible,
IN OUT PULONG GlobalCurrent,
IN OUT PULONG GlobalPossible)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
if (This->pPinCount)
{
This->pPinCount->lpVtbl->PinCount(This->pPinCount, PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
return STATUS_SUCCESS;
}
/* FIXME
* scan filter descriptor
*/
return STATUS_UNSUCCESSFUL;
}
static ISubdeviceVtbl vt_ISubdeviceVtbl =
{
ISubDevice_fnQueryInterface,
ISubDevice_fnAddRef,
ISubDevice_fnRelease,
ISubDevice_fnNewIrpTarget,
ISubDevice_fnReleaseChildren,
ISubDevice_fnGetDescriptor,
ISubDevice_fnDataRangeIntersection,
ISubDevice_fnPowerChangeNotify,
ISubDevice_fnPinCount
};
///--------------------------------------------------------------
PMINIPORTWAVERT
GetWaveRTMiniport(
IN IPortWaveRT* iface)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl *)iface;
return This->pMiniport;
}
PDEVICE_OBJECT
GetDeviceObjectFromPortWaveRT(
PPORTWAVERT iface)
{
IPortWaveRTImpl * This = (IPortWaveRTImpl *)iface;
return This->pDeviceObject;
}
//---------------------------------------------------------------
// IPortWaveRT constructor
//
NTSTATUS
NewPortWaveRT(
OUT PPORT* OutPort)
{
IPortWaveRTImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IPortWaveRTImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->lpVtbl = &vt_IPortWaveRTVtbl;
This->lpVtblSubDevice = &vt_ISubdeviceVtbl;
This->lpVtblPortEvents = &vt_IPortEvents;
This->ref = 1;
*OutPort = (PPORT)(&This->lpVtbl);
DPRINT("NewPortWaveRT %p\n", *OutPort);
return STATUS_SUCCESS;
}
@@ -0,0 +1,498 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port_wavert.cpp
* PURPOSE: WaveRT Port Driver
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortWaveRT : public IPortWaveRT,
public IPortEvents,
public ISubdevice
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortWaveRT;
IMP_ISubdevice;
IMP_IPortEvents;
CPortWaveRT(IUnknown *OuterUnknown) {}
virtual ~CPortWaveRT() {}
protected:
BOOL m_bInitialized;
PDEVICE_OBJECT m_pDeviceObject;
PMINIPORTWAVERT m_pMiniport;
PRESOURCELIST m_pResourceList;
PPINCOUNT m_pPinCount;
PPOWERNOTIFY m_pPowerNotify;
PPCFILTER_DESCRIPTOR m_pDescriptor;
PSUBDEVICE_DESCRIPTOR m_SubDeviceDescriptor;
IPortFilterWaveRT * m_Filter;
friend PMINIPORTWAVERT GetWaveRTMiniport(IN IPortWaveRT* iface);
friend PDEVICE_OBJECT GetDeviceObjectFromPortWaveRT(PPORTWAVERT iface);
LONG m_Ref;
};
static GUID InterfaceGuids[3] =
{
{
/// KSCATEGORY_RENDER
0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KSCATEGORY_CAPTURE
0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
},
{
/// KS_CATEGORY_AUDIO
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
}
};
DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWaveRTTopologySet, TopologyPropertyHandler);
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWaveRTPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
KSPROPERTY_SET WaveRTPropertySet[] =
{
{
&KSPROPSETID_Topology,
sizeof(PortFilterWaveRTTopologySet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWaveRTTopologySet,
0,
NULL
},
{
&KSPROPSETID_Pin,
sizeof(PortFilterWaveRTPinSet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterWaveRTPinSet,
0,
NULL
}
};
//KSEVENTSETID_LoopedStreaming, Type = KSEVENT_LOOPEDSTREAMING_POSITION
//KSEVENTSETID_Connection, Type = KSEVENT_CONNECTION_ENDOFSTREAM,
//---------------------------------------------------------------
// IPortEvents
//
void
NTAPI
CPortWaveRT::AddEventToEventList(
IN PKSEVENT_ENTRY EventEntry)
{
UNIMPLEMENTED
}
void
NTAPI
CPortWaveRT::GenerateEventList(
IN GUID* Set OPTIONAL,
IN ULONG EventId,
IN BOOL PinEvent,
IN ULONG PinId,
IN BOOL NodeEvent,
IN ULONG NodeId)
{
UNIMPLEMENTED
}
//---------------------------------------------------------------
// IUnknown interface functions
//
NTSTATUS
NTAPI
CPortWaveRT::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
if (IsEqualGUIDAligned(refiid, IID_IPortWaveRT) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PPORTWAVERT(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPortEvents))
{
*Output = PVOID(PPORTEVENTS(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_ISubdevice))
{
*Output = PVOID(PSUBDEVICE(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, IID_IPortClsVersion))
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IDrmPort) ||
IsEqualGUIDAligned(refiid, IID_IDrmPort2))
{
return NewIDrmPort((PDRMPORT2*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
else if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection))
{
return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IPortWaveRT_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
//---------------------------------------------------------------
// IPort interface functions
//
NTSTATUS
NTAPI
CPortWaveRT::GetDeviceProperty(
IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
IN ULONG BufferLength,
OUT PVOID PropertyBuffer,
OUT PULONG ReturnLength)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortWaveRT_fnNewRegistryKey called w/o initiazed\n");
return STATUS_UNSUCCESSFUL;
}
return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
}
NTSTATUS
NTAPI
CPortWaveRT::Init(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUNKNOWN UnknownMiniport,
IN PUNKNOWN UnknownAdapter OPTIONAL,
IN PRESOURCELIST ResourceList)
{
IMiniportWaveRT * Miniport;
NTSTATUS Status;
PPINCOUNT PinCount;
PPOWERNOTIFY PowerNotify;
DPRINT("IPortWaveRT_Init entered %p\n", this);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_bInitialized)
{
DPRINT("IPortWaveRT_Init called again\n");
return STATUS_SUCCESS;
}
Status = UnknownMiniport->QueryInterface(IID_IMiniportWaveRT, (PVOID*)&Miniport);
if (!NT_SUCCESS(Status))
{
DPRINT("IPortWaveRT_Init called with invalid IMiniport adapter\n");
return STATUS_INVALID_PARAMETER;
}
// Initialize port object
m_pMiniport = Miniport;
m_pDeviceObject = DeviceObject;
m_bInitialized = TRUE;
m_pResourceList = ResourceList;
// increment reference on miniport adapter
Miniport->AddRef();
Status = Miniport->Init(UnknownAdapter, ResourceList, this);
if (!NT_SUCCESS(Status))
{
DPRINT("IMiniportWaveRT_Init failed with %x\n", Status);
Miniport->Release();
m_bInitialized = FALSE;
return Status;
}
// get the miniport device descriptor
Status = Miniport->GetDescription(&m_pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("failed to get description\n");
Miniport->Release();
m_bInitialized = FALSE;
return Status;
}
// create the subdevice descriptor
Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
3,
InterfaceGuids,
0,
NULL,
2,
WaveRTPropertySet,
0,
0,
0,
NULL,
0,
NULL,
m_pDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("PcCreateSubdeviceDescriptor failed with %x\n", Status);
Miniport->Release();
m_bInitialized = FALSE;
return Status;
}
// check if it supports IPinCount interface
Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount);
if (NT_SUCCESS(Status))
{
// store IPinCount interface
m_pPinCount = PinCount;
}
// does the Miniport adapter support IPowerNotify interface*/
Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify);
if (NT_SUCCESS(Status))
{
// store reference
m_pPowerNotify = PowerNotify;
}
// increment reference on resource list
ResourceList->AddRef();
DPRINT("IPortWaveRT successfully initialized\n");
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortWaveRT::NewRegistryKey(
OUT PREGISTRYKEY *OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_bInitialized)
{
DPRINT("IPortWaveRT_fnNewRegistryKey called w/o initialized\n");
return STATUS_UNSUCCESSFUL;
}
return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, DesiredAccess, m_pDeviceObject, NULL /*FIXME*/, ObjectAttributes, CreateOptions, Disposition);
}
//---------------------------------------------------------------
// ISubdevice interface
//
NTSTATUS
NTAPI
CPortWaveRT::NewIrpTarget(
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
NTSTATUS Status;
IPortFilterWaveRT * Filter;
DPRINT("ISubDevice_NewIrpTarget this %p\n", this);
if (m_Filter)
{
*OutTarget = (IIrpTarget*)m_Filter;
return STATUS_SUCCESS;
}
Status = NewPortFilterWaveRT(&Filter);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = Filter->Init(this);
if (!NT_SUCCESS(Status))
{
Filter->Release();
return Status;
}
*OutTarget = (IIrpTarget*)Filter;
m_Filter = Filter;
return Status;
}
NTSTATUS
NTAPI
CPortWaveRT::ReleaseChildren()
{
UNIMPLEMENTED
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortWaveRT::GetDescriptor(
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
{
PC_ASSERT(m_SubDeviceDescriptor != NULL);
*Descriptor = m_SubDeviceDescriptor;
DPRINT("ISubDevice_GetDescriptor this %p desc %p\n", this, m_SubDeviceDescriptor);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortWaveRT::DataRangeIntersection(
IN ULONG PinId,
IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat OPTIONAL,
OUT PULONG ResultantFormatLength)
{
DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
if (m_pMiniport)
{
return m_pMiniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CPortWaveRT::PowerChangeNotify(
IN POWER_STATE PowerState)
{
if (m_pPowerNotify)
{
m_pPowerNotify->PowerChangeNotify(PowerState);
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CPortWaveRT::PinCount(
IN ULONG PinId,
IN OUT PULONG FilterNecessary,
IN OUT PULONG FilterCurrent,
IN OUT PULONG FilterPossible,
IN OUT PULONG GlobalCurrent,
IN OUT PULONG GlobalPossible)
{
if (m_pPinCount)
{
m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
return STATUS_SUCCESS;
}
// FIXME
// scan filter descriptor
return STATUS_UNSUCCESSFUL;
}
///--------------------------------------------------------------
PMINIPORTWAVERT
GetWaveRTMiniport(
IN IPortWaveRT* iface)
{
CPortWaveRT * This = (CPortWaveRT *)iface;
return This->m_pMiniport;
}
PDEVICE_OBJECT
GetDeviceObjectFromPortWaveRT(
PPORTWAVERT iface)
{
CPortWaveRT * This = (CPortWaveRT *)iface;
return This->m_pDeviceObject;
}
//---------------------------------------------------------------
// IPortWaveRT constructor
//
NTSTATUS
NewPortWaveRT(
OUT PPORT* OutPort)
{
CPortWaveRT * Port;
NTSTATUS Status;
Port = new(NonPagedPool, TAG_PORTCLASS) CPortWaveRT(NULL);
if (!Port)
return STATUS_INSUFFICIENT_RESOURCES;
Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort);
if (!NT_SUCCESS(Status))
{
delete Port;
}
DPRINT("NewPortWaveRT %p Status %u\n", Port, Status);
return Status;
}
@@ -1,106 +1,75 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/port_wavertstream.c
* FILE: drivers/wdm/audio/backpln/portcls/port_wavertstream.cpp
* PURPOSE: WaveRTStream helper object
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
#include "private.hpp"
typedef struct
class CPortWaveRTStreamInit : public IPortWaveRTStreamInit
{
IPortWaveRTStreamInitVtbl *lpVtbl;
LONG ref;
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
}IPortWaveRTStreamImpl;
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortWaveRTStreamInit;
CPortWaveRTStreamInit(IUnknown *OuterUnknown) {}
virtual ~CPortWaveRTStreamInit() {}
protected:
LONG m_Ref;
};
/*
* @implemented
*/
static
NTSTATUS
NTAPI
IPortWaveRTStreamInit_fnQueryInterface(
IPortWaveRTStreamInit * iface,
CPortWaveRTStreamInit::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
IPortWaveRTStreamImpl * This = (IPortWaveRTStreamImpl*)iface;
DPRINT("IPortWaveRTStream_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, &IID_IPortWaveRTStream) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
if (IsEqualGUIDAligned(refiid, IID_IPortWaveRTStream) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
*Output = PVOID(PPORTWAVERTSTREAM(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
static
ULONG
NTAPI
IPortWaveRTStreamInit_fnAddRef(
IPortWaveRTStreamInit * iface)
{
IPortWaveRTStreamImpl * This = (IPortWaveRTStreamImpl*)iface;
DPRINT("IPortWaveRTStream_fnAddRef entered\n");
return InterlockedIncrement(&This->ref);
}
/*
* @implemented
*/
static
ULONG
NTAPI
IPortWaveRTStreamInit_fnRelease(
IPortWaveRTStreamInit * iface)
{
IPortWaveRTStreamImpl * This = (IPortWaveRTStreamImpl*)iface;
InterlockedDecrement(&This->ref);
DPRINT("IPortWaveRTStream_fnRelease entered %u\n", This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
/*
* @implemented
*/
static
PMDL
NTAPI
IPortWaveRTStreamInit_fnAllocatePagesForMdl(
IN IPortWaveRTStreamInit * iface,
CPortWaveRTStreamInit::AllocatePagesForMdl(
IN PHYSICAL_ADDRESS HighAddress,
IN SIZE_T TotalBytes)
{
return MmAllocatePagesForMdl(RtlConvertUlongToLargeInteger(0), HighAddress, RtlConvertUlongToLargeInteger(0), TotalBytes);
}
/*
* @implemented
*/
static
PMDL
NTAPI
IPortWaveRTStreamInit_fnAllocateContiguousPagesForMdl(
IN IPortWaveRTStreamInit * iface,
CPortWaveRTStreamInit::AllocateContiguousPagesForMdl(
IN PHYSICAL_ADDRESS LowAddress,
IN PHYSICAL_ADDRESS HighAddress,
IN SIZE_T TotalBytes)
@@ -139,69 +108,44 @@ IPortWaveRTStreamInit_fnAllocateContiguousPagesForMdl(
return Mdl;
}
/*
* @implemented
*/
static
PVOID
NTAPI
IPortWaveRTStreamInit_fnMapAllocatedPages(
IN IPortWaveRTStreamInit * iface,
CPortWaveRTStreamInit::MapAllocatedPages(
IN PMDL MemoryDescriptorList,
IN MEMORY_CACHING_TYPE CacheType)
{
return MmMapLockedPagesSpecifyCache(MemoryDescriptorList, KernelMode, CacheType, NULL, 0, NormalPagePriority);
}
/*
* @implemented
*/
static
VOID
NTAPI
IPortWaveRTStreamInit_fnUnmapAllocatedPages(
IN IPortWaveRTStreamInit * iface,
CPortWaveRTStreamInit::UnmapAllocatedPages(
IN PVOID BaseAddress,
IN PMDL MemoryDescriptorList)
{
MmUnmapLockedPages(BaseAddress, MemoryDescriptorList);
}
/*
* @implemented
*/
static
VOID
NTAPI
IPortWaveRTStreamInit_fnFreePagesFromMdl(
IN IPortWaveRTStreamInit * iface,
CPortWaveRTStreamInit::FreePagesFromMdl(
IN PMDL MemoryDescriptorList)
{
MmFreePagesFromMdl(MemoryDescriptorList);
ExFreePool(MemoryDescriptorList);
}
/*
* @implemented
*/
static
ULONG
NTAPI
IPortWaveRTStreamInit_fnGetPhysicalPagesCount(
IN IPortWaveRTStreamInit * iface,
CPortWaveRTStreamInit::GetPhysicalPagesCount(
IN PMDL MemoryDescriptorList)
{
return ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, MmGetMdlByteCount(MemoryDescriptorList));
}
/*
* @implemented
*/
static
PHYSICAL_ADDRESS
NTAPI
IPortWaveRTStreamInit_fnGetPhysicalPageAddress(
IN IPortWaveRTStreamInit * iface,
CPortWaveRTStreamInit::GetPhysicalPageAddress(
IN PPHYSICAL_ADDRESS Address,
IN PMDL MemoryDescriptorList,
IN ULONG Index)
@@ -226,31 +170,24 @@ IPortWaveRTStreamInit_fnGetPhysicalPageAddress(
return Result;
}
static IPortWaveRTStreamInitVtbl vt_PortWaveRTStream =
{
IPortWaveRTStreamInit_fnQueryInterface,
IPortWaveRTStreamInit_fnAddRef,
IPortWaveRTStreamInit_fnRelease,
IPortWaveRTStreamInit_fnAllocatePagesForMdl,
IPortWaveRTStreamInit_fnAllocateContiguousPagesForMdl,
IPortWaveRTStreamInit_fnMapAllocatedPages,
IPortWaveRTStreamInit_fnUnmapAllocatedPages,
IPortWaveRTStreamInit_fnFreePagesFromMdl,
IPortWaveRTStreamInit_fnGetPhysicalPagesCount,
IPortWaveRTStreamInit_fnGetPhysicalPageAddress
};
NTSTATUS
NewPortWaveRTStream(
PPORTWAVERTSTREAM *OutStream)
{
IPortWaveRTStreamImpl* This = AllocateItem(NonPagedPool, sizeof(IPortWaveRTStreamImpl), TAG_PORTCLASS);
NTSTATUS Status;
CPortWaveRTStreamInit* This = new(NonPagedPool, TAG_PORTCLASS) CPortWaveRTStreamInit(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->ref = 1;
This->lpVtbl = &vt_PortWaveRTStream;
Status = This->QueryInterface(IID_IPortWaveRTStream, (PVOID*)OutStream);
*OutStream = (PPORTWAVERTSTREAM)&This->lpVtbl;
return STATUS_SUCCESS;
if (!NT_SUCCESS(Status))
{
delete This;
return Status;
}
*OutStream = (PPORTWAVERTSTREAM)This;
return Status;
}
@@ -11,45 +11,52 @@
<library>hal</library>
<library>libcntpr</library>
<library>pseh</library>
<file>adapter.c</file>
<file>api.c</file>
<file>connection.c</file>
<file>dispatcher.c</file>
<file>dll.c</file>
<file>dma_slave.c</file>
<file>drm.c</file>
<file>drm_port.c</file>
<file>filter_topology.c</file>
<file>filter_dmus.c</file>
<file>filter_wavecyclic.c</file>
<file>filter_wavepci.c</file>
<file>filter_wavert.c</file>
<file>guids.c</file>
<file>interrupt.c</file>
<file>irp.c</file>
<file>irpstream.c</file>
<file>miniport.c</file>
<file>miniport_dmus.c</file>
<file>miniport_fmsynth.c</file>
<file>pin_dmus.c</file>
<file>pin_wavecyclic.c</file>
<file>pin_wavepci.c</file>
<file>pin_wavert.c</file>
<file>pool.c</file>
<file>port.c</file>
<file>port_dmus.c</file>
<file>port_topology.c</file>
<file>port_wavecyclic.c</file>
<file>port_wavepci.c</file>
<file>port_wavert.c</file>
<file>port_wavertstream.c</file>
<file>power.c</file>
<file>propertyhandler.c</file>
<file>registry.c</file>
<file>resource.c</file>
<file>service_group.c</file>
<file>undoc.c</file>
<file>unregister.c</file>
<file>version.c</file>
<group compilerset="gcc">
<compilerflag compiler="cxx">-fno-exceptions</compilerflag>
<compilerflag compiler="cxx">-fno-rtti</compilerflag>
</group>
<file>adapter.cpp</file>
<file>api.cpp</file>
<file>connection.cpp</file>
<file>dispatcher.cpp</file>
<file>dll.cpp</file>
<file>dma_slave.cpp</file>
<file>drm.cpp</file>
<file>drm_port.cpp</file>
<file>filter_topology.cpp</file>
<file>filter_dmus.cpp</file>
<file>filter_wavecyclic.cpp</file>
<file>filter_wavepci.cpp</file>
<file>filter_wavert.cpp</file>
<file>guids.cpp</file>
<file>interrupt.cpp</file>
<file>irp.cpp</file>
<file>irpstream.cpp</file>
<file>miniport.cpp</file>
<file>miniport_dmus.cpp</file>
<file>miniport_fmsynth.cpp</file>
<file>pin_dmus.cpp</file>
<file>pin_wavecyclic.cpp</file>
<file>pin_wavepci.cpp</file>
<file>pin_wavert.cpp</file>
<file>pool.cpp</file>
<file>port.cpp</file>
<file>port_dmus.cpp</file>
<file>port_topology.cpp</file>
<file>port_wavecyclic.cpp</file>
<file>port_wavepci.cpp</file>
<file>port_wavert.cpp</file>
<file>port_wavertstream.cpp</file>
<file>power.cpp</file>
<file>propertyhandler.cpp</file>
<file>purecall.cpp</file>
<file>registry.cpp</file>
<file>resource.cpp</file>
<file>service_group.cpp</file>
<file>undoc.cpp</file>
<file>unregister.cpp</file>
<file>version.cpp</file>
<file>portcls.rc</file>
</module>
@@ -1,16 +1,12 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/power.c
* FILE: drivers/wdm/audio/backpln/portcls/power.cpp
* PURPOSE: Power support functions
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
/*
* @implemented
*/
#include "private.hpp"
NTSTATUS
NTAPI
@@ -24,7 +20,7 @@ PcRegisterAdapterPowerManagement(
IAdapterPowerManagement * pPower;
DPRINT("PcRegisterAdapterPowerManagement pUnknown %p pvContext %p\n", pUnknown, pvContext);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!pUnknown || !pvContext)
return STATUS_INVALID_PARAMETER;
@@ -33,7 +29,7 @@ PcRegisterAdapterPowerManagement(
pDeviceObject = (PDEVICE_OBJECT)pvContext;
DeviceExt = (PPCLASS_DEVICE_EXTENSION)pDeviceObject->DeviceExtension;
Status = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IAdapterPowerManagement, (PVOID*)&pPower);
Status = pUnknown->QueryInterface(IID_IAdapterPowerManagement, (PVOID*)&pPower);
if (!NT_SUCCESS(Status))
{
DPRINT1("PcRegisterAdapterPowerManagement no IAdapterPowerManagement interface %x\n", Status);
@@ -60,10 +56,8 @@ PwrCompletionCallback(
KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE);
}
/*
* @implemented
*/
NTSTATUS NTAPI
NTSTATUS
NTAPI
PcRequestNewPowerState(
IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_POWER_STATE RequestedNewState)
@@ -73,7 +67,7 @@ PcRequestNewPowerState(
POWER_STATE PowerState;
PPCLASS_DEVICE_EXTENSION DeviceExt;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!DeviceObject || !RequestedNewState)
return STATUS_INVALID_PARAMETER;
@@ -8,86 +8,114 @@
#define PORTCLS_PRIVATE_H
//#define _KS_NO_ANONYMOUS_STRUCTURES_
#define PC_IMPLEMENTATION
#include <ntddk.h>
#include <portcls.h>
#define NDEBUG
#define YDEBUG
#include <debug.h>
#include <dmusicks.h>
#include "interfaces.h"
#include <kcom.h>
#include "stdunk.h"
#include "interfaces.hpp"
#include <ks.h>
#include <ksmedia.h>
#include <stdio.h>
#include <math.h>
#include <intrin.h>
#include <assert.h>
#define TAG_PORTCLASS 'SLCP'
#define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x))
#define PC_ASSERT(exp) \
(VOID)((!(exp)) ? \
RtlAssert((PVOID) #exp, (PVOID)__FILE__, __LINE__, NULL ), FALSE : TRUE)
#define PC_ASSERT_IRQL(x) PC_ASSERT(KeGetCurrentIrql() <= (x))
#define PC_ASSERT_IRQL_EQUAL(x) PC_ASSERT(KeGetCurrentIrql()==(x))
extern
"C"
NTSTATUS
NTAPI
PortClsCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
extern
"C"
NTSTATUS
NTAPI
PortClsPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
extern
"C"
NTSTATUS
NTAPI
PortClsPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
extern
"C"
NTSTATUS
NTAPI
PortClsSysControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS NewMiniportDMusUART(
NTSTATUS
NewMiniportDMusUART(
OUT PMINIPORT* OutMiniport,
IN REFCLSID ClassId);
NTSTATUS NewMiniportFmSynth(
NTSTATUS
NewMiniportFmSynth(
OUT PMINIPORT* OutMiniport,
IN REFCLSID ClassId);
NTSTATUS NewPortDMus(
NTSTATUS
NewPortDMus(
OUT PPORT* OutPort);
NTSTATUS NewPortTopology(
NTSTATUS
NewPortTopology(
OUT PPORT* OutPort);
NTSTATUS NewPortWaveCyclic(
NTSTATUS
NewPortWaveCyclic(
OUT PPORT* OutPort);
NTSTATUS NewPortWavePci(
NTSTATUS
NewPortWavePci(
OUT PPORT* OutPort);
NTSTATUS NewIDrmPort(
NTSTATUS
NewIDrmPort(
OUT PDRMPORT2 *OutPort);
NTSTATUS NewPortClsVersion(
NTSTATUS
NewPortClsVersion(
OUT PPORTCLSVERSION * OutVersion);
NTSTATUS NewPortFilterWaveCyclic(
NTSTATUS
NewPortFilterWaveCyclic(
OUT IPortFilterWaveCyclic ** OutFilter);
NTSTATUS NewPortPinWaveCyclic(
NTSTATUS
NewPortPinWaveCyclic(
OUT IPortPinWaveCyclic ** OutPin);
NTSTATUS
NewPortFilterWavePci(
OUT IPortFilterWavePci ** OutFilter);
NTSTATUS NewPortPinWavePci(
NTSTATUS
NewPortPinWavePci(
OUT IPortPinWavePci ** OutPin);
PDEVICE_OBJECT
@@ -102,11 +130,14 @@ PMINIPORTWAVEPCI
GetWavePciMiniport(
PPORTWAVEPCI Port);
NTSTATUS
NewPortFilterDMus(
OUT PPORTFILTERDMUS * OutFilter);
NTSTATUS NewPortPinDMus(
NTSTATUS
NewPortPinDMus(
OUT PPORTPINDMUS * OutPin);
VOID
@@ -121,7 +152,8 @@ NTSTATUS
NewPortFilterWaveRT(
OUT IPortFilterWaveRT ** OutFilter);
NTSTATUS NewPortPinWaveRT(
NTSTATUS
NewPortPinWaveRT(
OUT IPortPinWaveRT ** OutPin);
PMINIPORTWAVERT
@@ -132,6 +164,7 @@ PDEVICE_OBJECT
GetDeviceObjectFromPortWaveRT(
IPortWaveRT* iface);
NTSTATUS
NewPortWaveRTStream(
PPORTWAVERTSTREAM *OutStream);
@@ -193,6 +226,8 @@ PinPropertyHandler(
IN PKSIDENTIFIER Request,
IN OUT PVOID Data);
extern
"C"
NTSTATUS
NTAPI
PcDmaMasterDescription(
@@ -207,6 +242,8 @@ PcDmaMasterDescription(
IN ULONG DmaPort,
OUT PDEVICE_DESCRIPTION DeviceDescription);
extern
"C"
NTSTATUS
NTAPI
PcDmaSlaveDescription(
@@ -219,6 +256,8 @@ PcDmaSlaveDescription(
IN ULONG DmaPort,
OUT PDEVICE_DESCRIPTION DeviceDescription);
extern
"C"
NTSTATUS
NTAPI
PcCreateSubdeviceDescriptor(
@@ -237,6 +276,8 @@ PcCreateSubdeviceDescriptor(
IN KSEVENT_SET * EventSet,
IN PPCFILTER_DESCRIPTOR FilterDescription);
extern
"C"
NTSTATUS
NTAPI
PcValidateConnectRequest(
@@ -1,12 +1,12 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/propertyhandler.c
* FILE: drivers/wdm/audio/backpln/portcls/propertyhandler.cpp
* PURPOSE: Pin property handler
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
#include "private.hpp"
NTSTATUS
FindPropertyHandler(
@@ -90,24 +90,24 @@ HandleDataIntersection(
NTSTATUS Status = STATUS_NO_MATCH;
ULONG Index, Length;
/* Access parameters */
// Access parameters
MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
DataRange = (PKSDATARANGE)(MultipleItem + 1);
for(Index = 0; Index < MultipleItem->Count; Index++)
{
/* Call miniport's properitary handler */
ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRangesCount);
ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0]);
Status = SubDevice->lpVtbl->DataRangeIntersection(SubDevice, Pin->PinId, DataRange, (PKSDATARANGE)Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0],
DataLength, Data, &Length);
// Call miniport's properitary handler
PC_ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRangesCount);
PC_ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0]);
Status = SubDevice->DataRangeIntersection(Pin->PinId, DataRange, (PKSDATARANGE)Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0],
DataLength, Data, &Length);
if (Status == STATUS_SUCCESS)
{
IoStatus->Information = Length;
break;
}
DataRange = UlongToPtr(PtrToUlong(DataRange) + DataRange->FormatSize);
DataRange = (PKSDATARANGE) UlongToPtr(PtrToUlong(DataRange) + DataRange->FormatSize);
}
IoStatus->Status = Status;
@@ -133,15 +133,15 @@ PinPropertyHandler(
NTSTATUS Status = STATUS_UNSUCCESSFUL;
Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
ASSERT(Descriptor);
PC_ASSERT(Descriptor);
/* get current irp stack */
// get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* Get the IrpTarget */
// Get the IrpTarget
IrpTarget = (IIrpTarget*)IoStack->FileObject->FsContext2;
/* Get the parent */
Status = IrpTarget->lpVtbl->QueryInterface(IrpTarget, &IID_IPort, (PVOID*)&Port);
// Get the parent
Status = IrpTarget->QueryInterface(IID_IPort, (PVOID*)&Port);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to obtain IPort interface from filter\n");
@@ -150,15 +150,15 @@ PinPropertyHandler(
return STATUS_UNSUCCESSFUL;
}
/* Get private ISubdevice interface */
Status = Port->lpVtbl->QueryInterface(Port, &IID_ISubdevice, (PVOID*)&SubDevice);
// Get private ISubdevice interface
Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&SubDevice);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to obtain ISubdevice interface from port driver\n");
KeBugCheck(0);
}
/* get current stack location */
// get current stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
switch(Request->Id)
@@ -197,11 +197,11 @@ PinPropertyHandler(
Status = STATUS_UNSUCCESSFUL;
}
/* Release reference */
Port->lpVtbl->Release(Port);
// Release reference
Port->Release();
/* Release subdevice reference */
SubDevice->lpVtbl->Release(SubDevice);
// Release subdevice reference
SubDevice->Release();
return Status;
}
@@ -226,18 +226,18 @@ FastPropertyHandler(
ULONG Size, Index;
PKSMULTIPLE_ITEM Item;
ASSERT(Descriptor);
PC_ASSERT(Descriptor);
if (!IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Pin))
if (!IsEqualGUIDAligned(Property->Set, KSPROPSETID_Pin))
{
/* the fast handler only supports pin properties atm*/
// the fast handler only supports pin properties atm*/
DPRINT("Only KSPROPSETID_Pin is supported\n");
IoStatus->Status = Status = STATUS_NOT_IMPLEMENTED;
IoStatus->Information = 0;
return Status;
}
/* property handler is used to verify input parameters */
// property handler is used to verify input parameters
Status = FindPropertyHandler(IoStatus, Descriptor, Property, PropertyLength, DataLength, Data, &PropertyHandler);
if (!NT_SUCCESS(Status))
{
@@ -378,7 +378,7 @@ FindPropertyHandler(
for(Index = 0; Index < Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++)
{
if (IsEqualGUIDAligned(&Property->Set, Descriptor->FilterPropertySet.Properties[Index].Set))
if (IsEqualGUIDAligned(Property->Set, *Descriptor->FilterPropertySet.Properties[Index].Set))
{
for(ItemIndex = 0; ItemIndex < Descriptor->FilterPropertySet.Properties[Index].PropertiesCount; ItemIndex++)
{
@@ -394,14 +394,14 @@ FindPropertyHandler(
{
if (sizeof(ULONG) > OutputBufferLength)
{
/* too small buffer */
// too small buffer
return STATUS_INVALID_PARAMETER;
}
/* get output buffer */
// get output buffer
Flags = (PULONG)OutputBuffer;
/* clear flags */
// clear flags
*Flags = KSPROPERTY_TYPE_BASICSUPPORT;
if (Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].GetSupported)
@@ -414,10 +414,10 @@ FindPropertyHandler(
if (OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
{
/* get output buffer */
// get output buffer
Description = (PKSPROPERTY_DESCRIPTION)OutputBuffer;
/* store result */
// store result
Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
Description->PropTypeSet.Set = KSPROPTYPESETID_General;
Description->PropTypeSet.Id = 0;
@@ -434,7 +434,7 @@ FindPropertyHandler(
if (Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].MinProperty > InputBufferLength)
{
/* too small input buffer */
// too small input buffer
IoStatus->Information = Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].MinProperty;
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
return STATUS_BUFFER_TOO_SMALL;
@@ -442,7 +442,7 @@ FindPropertyHandler(
if (Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].MinData > OutputBufferLength)
{
/* too small output buffer */
// too small output buffer
IoStatus->Information = Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].MinData;
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
return STATUS_BUFFER_TOO_SMALL;
@@ -465,7 +465,7 @@ PcCountProperties(
PIO_STACK_LOCATION IoStack;
LPGUID Guid;
/* count property items */
// count property items
Properties = Descriptor->FilterPropertySet.FreeKsPropertySetOffset;
if (Descriptor->DeviceDescriptor->AutomationTable)
@@ -473,26 +473,26 @@ PcCountProperties(
Properties = Descriptor->DeviceDescriptor->AutomationTable->PropertyCount;
}
/* get current irp stack */
// get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* store output size */
// store output size
Irp->IoStatus.Information = sizeof(GUID) * Properties;
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GUID) * Properties)
{
/* buffer too small */
// buffer too small
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_BUFFER_OVERFLOW;
}
/* get output buffer */
Guid = Irp->UserBuffer;
// get output buffer
Guid = (LPGUID)Irp->UserBuffer;
/* copy property guids from filter */
// copy property guids from filter
Offset = 0;
for(Index = 0; Index < Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++)
{
@@ -502,7 +502,7 @@ PcCountProperties(
if (Descriptor->DeviceDescriptor->AutomationTable)
{
/* copy property guids from driver */
// copy property guids from driver
for(Index = 0; Index < Descriptor->DeviceDescriptor->AutomationTable->PropertyCount; Index++)
{
RtlMoveMemory(&Guid[Offset], Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Set, sizeof(GUID));
@@ -510,7 +510,7 @@ PcCountProperties(
}
}
/* done */
// done
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -535,29 +535,29 @@ PcPropertyHandler(
IoStack = IoGetCurrentIrpStackLocation(Irp);
Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
ASSERT(Property);
PC_ASSERT(Property);
if (IsEqualGUIDAligned(&Property->Set, &GUID_NULL) && Property->Id == 0 && Property->Flags == KSPROPERTY_TYPE_SETSUPPORT)
if (IsEqualGUIDAligned(Property->Set, GUID_NULL) && Property->Id == 0 && Property->Flags == KSPROPERTY_TYPE_SETSUPPORT)
{
return PcCountProperties(Irp, Descriptor);
}
/* check properties provided by the driver */
// check properties provided by the driver
if (Descriptor->DeviceDescriptor->AutomationTable)
{
for(Index = 0; Index < Descriptor->DeviceDescriptor->AutomationTable->PropertyCount; Index++)
{
if (IsEqualGUID(Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Set, &Property->Set))
if (IsEqualGUID(*Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Set, Property->Set))
{
if (Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Id == Property->Id)
{
if(Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Flags & Property->Flags)
{
PropertyRequest = ExAllocatePool(NonPagedPool, sizeof(PCPROPERTY_REQUEST));
PropertyRequest = (PPCPROPERTY_REQUEST)ExAllocatePool(NonPagedPool, sizeof(PCPROPERTY_REQUEST));
if (!PropertyRequest)
{
/* no memory */
// no memory
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -585,18 +585,19 @@ PcPropertyHandler(
Status = FindPropertyHandler(&Irp->IoStatus, Descriptor, Property, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Irp->UserBuffer, &PropertyHandler);
if (NT_SUCCESS(Status) && PropertyHandler)
{
KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PVOID)Descriptor;
// HACK
KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (const KSPROPERTY_ITEM*)Descriptor;
DPRINT("Calling property handler %p\n", PropertyHandler);
Status = PropertyHandler(Irp, Property, Irp->UserBuffer);
}
else if (!NT_SUCCESS(Status))
{
RtlStringFromGUID(&Property->Set, &GuidString);
RtlStringFromGUID(Property->Set, &GuidString);
DPRINT1("Unhandeled property: Set %S Id %u Flags %x InputLength %u OutputLength %u\n", GuidString.Buffer, Property->Id, Property->Flags, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
RtlFreeUnicodeString(&GuidString);
}
/* the information member is set by the handler */
// the information member is set by the handler
Irp->IoStatus.Status = Status;
DPRINT("Result %x Length %u\n", Status, Irp->IoStatus.Information);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -0,0 +1,23 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/connection.c
* PURPOSE: purecall stub
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
extern "C" {
void
__cxa_pure_virtual()
{
// put error handling here
KeBugCheck(0);
}
}
@@ -1,388 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/registry.c
* PURPOSE: Registry access object
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IRegistryKeyVtbl * lpVtbl;
LONG ref;
HANDLE hKey;
BOOL Deleted;
}IRegistryKeyImpl;
ULONG
NTAPI
IRegistryKey_fnAddRef(
IN IRegistryKey* iface)
{
IRegistryKeyImpl * This = (IRegistryKeyImpl*)iface;
DPRINT("IRegistryKey_AddRef: This %p\n", This);
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IRegistryKey_fnRelease(
IN IRegistryKey* iface)
{
IRegistryKeyImpl * This = (IRegistryKeyImpl*)iface;
InterlockedDecrement(&This->ref);
DPRINT("IRegistryKey_fnRelease ref %u this %p entered\n", This->ref, This);
if (This->ref == 0)
{
if (This->hKey)
{
ZwClose(This->hKey);
}
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
NTSTATUS
NTAPI
IRegistryKey_fnQueryInterface(
IN IRegistryKey* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IRegistryKeyImpl * This = (IRegistryKeyImpl*)iface;
DPRINT("IRegistryKey_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, &IID_IRegistryKey))
{
*Output = (PVOID)&This->lpVtbl;
_InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
DPRINT("IRegistryKey_QueryInterface: This %p unknown iid\n", This, This->ref);
DbgBreakPoint();
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
IRegistryKey_fnDeleteKey(
IN IRegistryKey* iface)
{
IRegistryKeyImpl * This = (IRegistryKeyImpl*)iface;
NTSTATUS Status;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->Deleted)
{
return STATUS_INVALID_HANDLE;
}
Status = ZwDeleteKey(This->hKey);
if (NT_SUCCESS(Status))
{
This->Deleted = TRUE;
}
return Status;
}
NTSTATUS
NTAPI
IRegistryKey_fnEnumerateKey(
IN IRegistryKey* iface,
IN ULONG Index,
IN KEY_INFORMATION_CLASS KeyInformationClass,
OUT PVOID KeyInformation,
IN ULONG Length,
OUT PULONG ResultLength)
{
IRegistryKeyImpl * This = (IRegistryKeyImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->Deleted)
{
return STATUS_INVALID_HANDLE;
}
return ZwEnumerateKey(This->hKey, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
}
NTSTATUS
NTAPI
IRegistryKey_fnEnumerateKeyValue(
IN IRegistryKey* iface,
IN ULONG Index,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength)
{
IRegistryKeyImpl * This = (IRegistryKeyImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->Deleted)
{
return STATUS_INVALID_HANDLE;
}
return ZwEnumerateValueKey(This->hKey, Index, KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
}
NTSTATUS
NTAPI
IRegistryKey_fnNewSubKey(
IN IRegistryKey* iface,
OUT PREGISTRYKEY *RegistrySubKey,
IN PUNKNOWN OuterUnknown,
IN ACCESS_MASK DesiredAccess,
IN PUNICODE_STRING SubKeyName,
IN ULONG CreateOptions,
OUT PULONG Disposition OPTIONAL)
{
OBJECT_ATTRIBUTES Attributes;
NTSTATUS Status;
HANDLE hKey;
IRegistryKeyImpl * NewThis, *This = (IRegistryKeyImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
DPRINT("IRegistryKey_fnNewSubKey entered %S\n", SubKeyName->Buffer);
if (This->Deleted)
{
return STATUS_INVALID_HANDLE;
}
InitializeObjectAttributes(&Attributes, SubKeyName, 0, This->hKey, NULL);
Status = ZwCreateKey(&hKey, KEY_READ | KEY_WRITE, &Attributes, 0, NULL, 0, Disposition);
if (!NT_SUCCESS(Status))
{
DPRINT1("IRegistryKey_fnNewSubKey failed with %x\n", Status);
DbgBreakPoint();
return Status;
}
NewThis = AllocateItem(NonPagedPool, sizeof(IRegistryKeyImpl), TAG_PORTCLASS);
if (!NewThis)
{
ZwClose(hKey);
return STATUS_INSUFFICIENT_RESOURCES;
}
if (OuterUnknown)
OuterUnknown->lpVtbl->AddRef(OuterUnknown);
NewThis->hKey = hKey;
NewThis->ref = 1;
NewThis->lpVtbl = This->lpVtbl;
*RegistrySubKey = (PREGISTRYKEY)&NewThis->lpVtbl;
DPRINT("IRegistryKey_fnNewSubKey RESULT %p\n", *RegistrySubKey );
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IRegistryKey_fnQueryKey(
IN IRegistryKey* iface,
IN KEY_INFORMATION_CLASS KeyInformationClass,
OUT PVOID KeyInformation,
IN ULONG Length,
OUT PULONG ResultLength)
{
IRegistryKeyImpl * This = (IRegistryKeyImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->Deleted)
{
return STATUS_INVALID_HANDLE;
}
return ZwQueryKey(This->hKey, KeyInformationClass, KeyInformation, Length, ResultLength);
}
NTSTATUS
NTAPI
IRegistryKey_fnQueryRegistryValues(
IN IRegistryKey* iface,
IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
IN PVOID Context OPTIONAL)
{
IRegistryKeyImpl * This = (IRegistryKeyImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->Deleted)
{
return STATUS_INVALID_HANDLE;
}
return RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, (PCWSTR)This->hKey, QueryTable, Context, NULL);
}
NTSTATUS
NTAPI
IRegistryKey_fnQueryValueKey(
IN IRegistryKey* iface,
IN PUNICODE_STRING ValueName,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength)
{
NTSTATUS Status;
IRegistryKeyImpl * This = (IRegistryKeyImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->Deleted)
{
return STATUS_INVALID_HANDLE;
}
Status = ZwQueryValueKey(This->hKey, ValueName, KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
DPRINT("IRegistryKey_fnQueryValueKey entered %p value %wZ Status %x\n", This, ValueName, Status);
return Status;
}
NTSTATUS
NTAPI
IRegistryKey_fnSetValueKey(
IN IRegistryKey* iface,
IN PUNICODE_STRING ValueName OPTIONAL,
IN ULONG Type,
IN PVOID Data,
IN ULONG DataSize
)
{
IRegistryKeyImpl * This = (IRegistryKeyImpl*)iface;
DPRINT("IRegistryKey_fnSetValueKey entered %S\n", ValueName->Buffer);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (This->Deleted)
{
return STATUS_INVALID_HANDLE;
}
return ZwSetValueKey(This->hKey, ValueName, 0, Type, Data, DataSize);
}
static IRegistryKeyVtbl vt_IRegistryKey =
{
/* IUnknown methods */
IRegistryKey_fnQueryInterface,
IRegistryKey_fnAddRef,
IRegistryKey_fnRelease,
/* IRegistryKey methods */
IRegistryKey_fnQueryKey,
IRegistryKey_fnEnumerateKey,
IRegistryKey_fnQueryValueKey,
IRegistryKey_fnEnumerateKeyValue,
IRegistryKey_fnSetValueKey,
IRegistryKey_fnQueryRegistryValues,
IRegistryKey_fnNewSubKey,
IRegistryKey_fnDeleteKey
};
/*
* @implemented
*/
NTSTATUS NTAPI
PcNewRegistryKey(
OUT PREGISTRYKEY* OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN PVOID DeviceObject OPTIONAL,
IN PVOID SubDevice OPTIONAL,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
HANDLE hHandle;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
IRegistryKeyImpl * This;
PPCLASS_DEVICE_EXTENSION DeviceExt;
DPRINT("PcNewRegistryKey entered\n");
if (!OutRegistryKey)
return STATUS_INVALID_PARAMETER;
if (RegistryKeyType != GeneralRegistryKey &&
RegistryKeyType != DeviceRegistryKey &&
RegistryKeyType != DriverRegistryKey &&
RegistryKeyType != HwProfileRegistryKey &&
RegistryKeyType != DeviceInterfaceRegistryKey)
{
return STATUS_INVALID_PARAMETER;
}
/* check for the key type */
if (RegistryKeyType == GeneralRegistryKey)
{
/* do we have the required object attributes */
if (!ObjectAttributes)
{
/* object attributes is mandatory */
return STATUS_INVALID_PARAMETER;
}
/* try to open the key */
Status = ZwOpenKey(&hHandle, DesiredAccess, ObjectAttributes);
}
else if (RegistryKeyType == DeviceRegistryKey ||
RegistryKeyType == DriverRegistryKey ||
RegistryKeyType == HwProfileRegistryKey)
{
/* check for HwProfileRegistryKey case */
if (RegistryKeyType == HwProfileRegistryKey)
{
/* IoOpenDeviceRegistryKey used different constant */
RegistryKeyType = PLUGPLAY_REGKEY_CURRENT_HWPROFILE;
}
/* obtain the new device extension */
DeviceExt = (PPCLASS_DEVICE_EXTENSION) ((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
Status = IoOpenDeviceRegistryKey(DeviceExt->PhysicalDeviceObject, RegistryKeyType, DesiredAccess, &hHandle);
}
else if (RegistryKeyType == DeviceInterfaceRegistryKey)
{
/* FIXME */
UNIMPLEMENTED
DbgBreakPoint();
}
if (!NT_SUCCESS(Status))
{
return Status;
}
This = AllocateItem(NonPagedPool, sizeof(IRegistryKeyImpl), TAG_PORTCLASS);
if (!This)
{
ZwClose(hHandle);
return STATUS_INSUFFICIENT_RESOURCES;
}
if (OuterUnknown)
OuterUnknown->lpVtbl->AddRef(OuterUnknown);
This->hKey = hHandle;
This->lpVtbl = &vt_IRegistryKey;
This->ref = 1;
*OutRegistryKey = (PREGISTRYKEY)&This->lpVtbl;
DPRINT("PcNewRegistryKey result %p\n", *OutRegistryKey);
return STATUS_SUCCESS;
}
@@ -0,0 +1,342 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/registry.cpp
* PURPOSE: Registry access object
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CRegistryKey : public IRegistryKey
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IRegistryKey;
CRegistryKey(IUnknown * OuterUnknown, HANDLE hKey) : m_hKey(hKey){}
virtual ~CRegistryKey();
protected:
HANDLE m_hKey;
BOOL m_Deleted;
LONG m_Ref;
};
CRegistryKey::~CRegistryKey()
{
if (m_hKey)
ZwClose(m_hKey);
}
NTSTATUS
NTAPI
CRegistryKey::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
DPRINT("CRegistryKey::QueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, IID_IRegistryKey) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PREGISTRYKEY(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
DPRINT("IRegistryKey_QueryInterface: This %p\n", this);
DbgBreakPoint();
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
CRegistryKey::DeleteKey()
{
NTSTATUS Status;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_Deleted)
{
return STATUS_INVALID_HANDLE;
}
Status = ZwDeleteKey(m_hKey);
if (NT_SUCCESS(Status))
{
m_Deleted = TRUE;
}
return Status;
}
NTSTATUS
NTAPI
CRegistryKey::EnumerateKey(
IN ULONG Index,
IN KEY_INFORMATION_CLASS KeyInformationClass,
OUT PVOID KeyInformation,
IN ULONG Length,
OUT PULONG ResultLength)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_Deleted)
{
return STATUS_INVALID_HANDLE;
}
return ZwEnumerateKey(m_hKey, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
}
NTSTATUS
NTAPI
CRegistryKey::EnumerateValueKey(
IN ULONG Index,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_Deleted)
{
return STATUS_INVALID_HANDLE;
}
return ZwEnumerateValueKey(m_hKey, Index, KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
}
NTSTATUS
NTAPI
CRegistryKey::NewSubKey(
OUT PREGISTRYKEY *RegistrySubKey,
IN PUNKNOWN OuterUnknown,
IN ACCESS_MASK DesiredAccess,
IN PUNICODE_STRING SubKeyName,
IN ULONG CreateOptions,
OUT PULONG Disposition OPTIONAL)
{
OBJECT_ATTRIBUTES Attributes;
NTSTATUS Status;
HANDLE hKey;
CRegistryKey * RegistryKey;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
DPRINT("CRegistryKey::NewSubKey entered %S\n", SubKeyName->Buffer);
if (m_Deleted)
{
return STATUS_INVALID_HANDLE;
}
InitializeObjectAttributes(&Attributes, SubKeyName, 0, m_hKey, NULL);
Status = ZwCreateKey(&hKey, KEY_READ | KEY_WRITE, &Attributes, 0, NULL, 0, Disposition);
if (!NT_SUCCESS(Status))
{
DPRINT1("CRegistryKey::NewSubKey failed with %x\n", Status);
return Status;
}
RegistryKey = new(NonPagedPool, TAG_PORTCLASS)CRegistryKey(OuterUnknown, hKey);
if (!RegistryKey)
return STATUS_INSUFFICIENT_RESOURCES;
Status = RegistryKey->QueryInterface(IID_IRegistryKey, (PVOID*)RegistrySubKey);
if (!NT_SUCCESS(Status))
{
ZwClose(hKey);
delete RegistryKey;
}
*RegistrySubKey = (PREGISTRYKEY)RegistryKey;
DPRINT("CRegistryKey::NewSubKey RESULT %p\n", *RegistrySubKey);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CRegistryKey::QueryKey(
IN KEY_INFORMATION_CLASS KeyInformationClass,
OUT PVOID KeyInformation,
IN ULONG Length,
OUT PULONG ResultLength)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_Deleted)
{
return STATUS_INVALID_HANDLE;
}
return ZwQueryKey(m_hKey, KeyInformationClass, KeyInformation, Length, ResultLength);
}
NTSTATUS
NTAPI
CRegistryKey::QueryRegistryValues(
IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
IN PVOID Context OPTIONAL)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_Deleted)
{
return STATUS_INVALID_HANDLE;
}
return RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, (PCWSTR)m_hKey, QueryTable, Context, NULL);
}
NTSTATUS
NTAPI
CRegistryKey::QueryValueKey(
IN PUNICODE_STRING ValueName,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength)
{
NTSTATUS Status;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_Deleted)
{
return STATUS_INVALID_HANDLE;
}
Status = ZwQueryValueKey(m_hKey, ValueName, KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
DPRINT("CRegistryKey::QueryValueKey entered %p value %wZ Status %x\n", this, ValueName, Status);
return Status;
}
NTSTATUS
NTAPI
CRegistryKey::SetValueKey(
IN PUNICODE_STRING ValueName OPTIONAL,
IN ULONG Type,
IN PVOID Data,
IN ULONG DataSize
)
{
DPRINT("CRegistryKey::SetValueKey entered %S\n", ValueName->Buffer);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (m_Deleted)
{
return STATUS_INVALID_HANDLE;
}
return ZwSetValueKey(m_hKey, ValueName, 0, Type, Data, DataSize);
}
NTSTATUS
NTAPI
PcNewRegistryKey(
OUT PREGISTRYKEY* OutRegistryKey,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN ULONG RegistryKeyType,
IN ACCESS_MASK DesiredAccess,
IN PVOID DeviceObject OPTIONAL,
IN PVOID SubDevice OPTIONAL,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN ULONG CreateOptions OPTIONAL,
OUT PULONG Disposition OPTIONAL)
{
HANDLE hHandle;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
CRegistryKey * RegistryKey;
PPCLASS_DEVICE_EXTENSION DeviceExt;
DPRINT("PcNewRegistryKey entered\n");
if (!OutRegistryKey)
return STATUS_INVALID_PARAMETER;
if (RegistryKeyType != GeneralRegistryKey &&
RegistryKeyType != DeviceRegistryKey &&
RegistryKeyType != DriverRegistryKey &&
RegistryKeyType != HwProfileRegistryKey &&
RegistryKeyType != DeviceInterfaceRegistryKey)
{
return STATUS_INVALID_PARAMETER;
}
// check for the key type
if (RegistryKeyType == GeneralRegistryKey)
{
// do we have the required object attributes
if (!ObjectAttributes)
{
// object attributes is mandatory
return STATUS_INVALID_PARAMETER;
}
// try to open the key
Status = ZwOpenKey(&hHandle, DesiredAccess, ObjectAttributes);
}
else if (RegistryKeyType == DeviceRegistryKey ||
RegistryKeyType == DriverRegistryKey ||
RegistryKeyType == HwProfileRegistryKey)
{
// check for HwProfileRegistryKey case
if (RegistryKeyType == HwProfileRegistryKey)
{
// IoOpenDeviceRegistryKey used different constant
RegistryKeyType = PLUGPLAY_REGKEY_CURRENT_HWPROFILE;
}
// obtain the new device extension
DeviceExt = (PPCLASS_DEVICE_EXTENSION) ((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
Status = IoOpenDeviceRegistryKey(DeviceExt->PhysicalDeviceObject, RegistryKeyType, DesiredAccess, &hHandle);
}
else if (RegistryKeyType == DeviceInterfaceRegistryKey)
{
// FIXME
UNIMPLEMENTED
DbgBreakPoint();
}
if (!NT_SUCCESS(Status))
{
return Status;
}
RegistryKey = new(NonPagedPool, TAG_PORTCLASS)CRegistryKey(OuterUnknown, hHandle);
if (!RegistryKey)
return STATUS_INSUFFICIENT_RESOURCES;
Status = RegistryKey->QueryInterface(IID_IRegistryKey, (PVOID*)OutRegistryKey);
if (!NT_SUCCESS(Status))
{
delete RegistryKey;
}
DPRINT("PcNewRegistryKey result %p\n", *OutRegistryKey);
return STATUS_SUCCESS;
}
@@ -1,510 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS
* FILE: drivers/wdm/audio/backpln/portcls/resource.c
* PURPOSE: Port Class driver / ResourceList implementation
* PROGRAMMER: Andrew Greenwood
* Johannes Anderwald
* HISTORY:
* 27 Jan 07 Created
*/
#include "private.h"
#include <portcls.h>
#include <stdunk.h>
#include <intrin.h>
typedef struct CResourceList
{
IResourceListVtbl *lpVtbl;
LONG ref;
PUNKNOWN OuterUnknown;
POOL_TYPE PoolType;
PCM_RESOURCE_LIST TranslatedResourceList;
PCM_RESOURCE_LIST UntranslatedResourceList;
ULONG NumberOfEntries;
} IResourceListImpl;
/*
Basic IUnknown methods
*/
NTSTATUS
NTAPI
IResourceList_fnQueryInterface(
IResourceList* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
IResourceListImpl * This = (IResourceListImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IResourceList) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IResourceList_QueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IResourceList_fnAddRef(
IResourceList* iface)
{
IResourceListImpl * This = (IResourceListImpl*)iface;
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IResourceList_fnRelease(
IResourceList* iface)
{
IResourceListImpl * This = (IResourceListImpl*)iface;
InterlockedDecrement(&This->ref);
DPRINT("IResourceList_fnRelease %p ref %x\n", This, This->ref);
if (This->ref == 0)
{
FreeItem(This->TranslatedResourceList, TAG_PORTCLASS);
FreeItem(This->UntranslatedResourceList, TAG_PORTCLASS);
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
/*
IResourceList methods
*/
ULONG
NTAPI
IResourceList_fnNumberOfEntries(IResourceList* iface)
{
IResourceListImpl * This = (IResourceListImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return This->NumberOfEntries;
}
ULONG
NTAPI
IResourceList_fnNumberOfEntriesOfType(
IResourceList* iface,
IN CM_RESOURCE_TYPE Type)
{
IResourceListImpl * This = (IResourceListImpl*)iface;
ULONG Index, Count = 0;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->TranslatedResourceList)
{
/* no resource list */
return 0;
}
/* I guess the translated and untranslated lists will be same length? */
for (Index = 0; Index < This->TranslatedResourceList->List[0].PartialResourceList.Count; Index ++ )
{
PartialDescriptor = &This->TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
DPRINT("Descriptor Type %u\n", PartialDescriptor->Type);
if (PartialDescriptor->Type == Type)
{
/* Yay! Finally found one that matches! */
Count++;
}
}
DPRINT("Found %d type %d\n", Count, Type);
return Count;
}
PCM_PARTIAL_RESOURCE_DESCRIPTOR
NTAPI
IResourceList_fnFindTranslatedEntry(
IResourceList* iface,
IN CM_RESOURCE_TYPE Type,
IN ULONG Index)
{
IResourceListImpl * This = (IResourceListImpl*)iface;
ULONG DescIndex, Count = 0;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->TranslatedResourceList)
{
/* no resource list */
return NULL;
}
for (DescIndex = 0; DescIndex < This->TranslatedResourceList->List[0].PartialResourceList.Count; DescIndex ++ )
{
PartialDescriptor = &This->TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[DescIndex];
if (PartialDescriptor->Type == Type)
{
/* Yay! Finally found one that matches! */
if (Index == Count)
{
return PartialDescriptor;
}
Count++;
}
}
return NULL;
}
PCM_PARTIAL_RESOURCE_DESCRIPTOR
NTAPI
IResourceList_fnFindUntranslatedEntry(
IResourceList* iface,
IN CM_RESOURCE_TYPE Type,
IN ULONG Index)
{
IResourceListImpl * This = (IResourceListImpl*)iface;
ULONG DescIndex, Count = 0;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!This->UntranslatedResourceList)
{
/* no resource list */
return NULL;
}
for (DescIndex = 0; DescIndex < This->UntranslatedResourceList->List[0].PartialResourceList.Count; DescIndex ++ )
{
PartialDescriptor = &This->UntranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[DescIndex];
if (PartialDescriptor->Type == Type)
{
/* Yay! Finally found one that matches! */
if (Index == Count)
{
return PartialDescriptor;
}
Count++;
}
}
return NULL;
}
NTSTATUS
NTAPI
IResourceList_fnAddEntry(
IResourceList* iface,
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Untranslated)
{
PCM_RESOURCE_LIST NewUntranslatedResources, NewTranslatedResources;
ULONG NewTranslatedSize, NewUntranslatedSize, TranslatedSize, UntranslatedSize, ResourceCount;
IResourceListImpl * This = (IResourceListImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
/* calculate translated resource list size */
ResourceCount = This->TranslatedResourceList->List[0].PartialResourceList.Count;
NewTranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount+1]);
TranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount]);
NewTranslatedResources = AllocateItem(This->PoolType, NewTranslatedSize, TAG_PORTCLASS);
if (!NewTranslatedResources)
return STATUS_INSUFFICIENT_RESOURCES;
/* calculate untranslated resouce list size */
ResourceCount = This->UntranslatedResourceList->List[0].PartialResourceList.Count;
NewUntranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount+1]);
UntranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount]);
/* allocate untranslated resource list size */
NewUntranslatedResources = AllocateItem(This->PoolType, NewUntranslatedSize, TAG_PORTCLASS);
if (!NewUntranslatedResources)
{
FreeItem(NewTranslatedResources, TAG_PORTCLASS);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* now copy translated resource list */
RtlMoveMemory(NewTranslatedResources, This->TranslatedResourceList, TranslatedSize);
RtlMoveMemory((PUCHAR)NewTranslatedResources + TranslatedSize, Translated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
/* now copy untranslated resource list */
RtlMoveMemory(NewUntranslatedResources, This->UntranslatedResourceList, UntranslatedSize);
RtlMoveMemory((PUCHAR)NewUntranslatedResources + UntranslatedSize, Untranslated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
/* free old lists */
FreeItem(This->TranslatedResourceList, TAG_PORTCLASS);
FreeItem(This->UntranslatedResourceList, TAG_PORTCLASS);
/* store new lists */
This->UntranslatedResourceList = NewUntranslatedResources;
This->TranslatedResourceList = NewTranslatedResources;
/* increment descriptor count */
NewUntranslatedResources->List[0].PartialResourceList.Count++;
NewTranslatedResources->List[0].PartialResourceList.Count++;
/* add entry count */
This->NumberOfEntries++;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IResourceList_fnAddEntryFromParent(
IResourceList* iface,
IN IResourceList* Parent,
IN CM_RESOURCE_TYPE Type,
IN ULONG Index)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated, Untranslated;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
Translated = Parent->lpVtbl->FindTranslatedEntry(Parent, Type, Index);
Untranslated = Parent->lpVtbl->FindUntranslatedEntry(Parent, Type, Index);
if (Translated && Untranslated)
{
/* add entry from parent */
return iface->lpVtbl->AddEntry(iface, Translated, Untranslated);
}
/* entry not found */
return STATUS_INVALID_PARAMETER;
}
PCM_RESOURCE_LIST
NTAPI
IResourceList_fnTranslatedList(
IResourceList* iface)
{
IResourceListImpl * This = (IResourceListImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return This->TranslatedResourceList;
}
PCM_RESOURCE_LIST
NTAPI
IResourceList_fnUntranslatedList(
IResourceList* iface)
{
IResourceListImpl * This = (IResourceListImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return This->UntranslatedResourceList;
}
/*
ResourceList V-Table
*/
static const IResourceListVtbl vt_ResourceListVtbl =
{
/* IUnknown */
IResourceList_fnQueryInterface,
IResourceList_fnAddRef,
IResourceList_fnRelease,
/* IResourceList */
IResourceList_fnNumberOfEntries,
IResourceList_fnNumberOfEntriesOfType,
IResourceList_fnFindTranslatedEntry,
IResourceList_fnFindUntranslatedEntry,
IResourceList_fnAddEntry,
IResourceList_fnAddEntryFromParent,
IResourceList_fnTranslatedList,
IResourceList_fnUntranslatedList
};
/*
Factory for creating a resource list
*/
PORTCLASSAPI
NTSTATUS
NTAPI
PcNewResourceList(
OUT PRESOURCELIST* OutResourceList,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PCM_RESOURCE_LIST TranslatedResourceList,
IN PCM_RESOURCE_LIST UntranslatedResourceList)
{
PCM_RESOURCE_LIST NewUntranslatedResources, NewTranslatedResources;
ULONG NewTranslatedSize, NewUntranslatedSize, ResourceCount;
IResourceListImpl* NewList;
if (!TranslatedResourceList)
{
/* if the untranslated resource list is also not provided, it becomes an empty resource list */
if (UntranslatedResourceList)
{
/* invalid parameter mix */
return STATUS_INVALID_PARAMETER;
}
}
else
{
/* if the translated resource list is also not provided, it becomes an empty resource list */
if (!UntranslatedResourceList)
{
/* invalid parameter mix */
return STATUS_INVALID_PARAMETER;
}
}
/* allocate resource list ctx */
NewList = AllocateItem(PoolType, sizeof(IResourceListImpl), TAG_PORTCLASS);
/* check for success */
if (!NewList)
{
DPRINT("AllocateItem failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Initialize */
NewList->lpVtbl = (IResourceListVtbl*)&vt_ResourceListVtbl;
NewList->ref = 1;
NewList->OuterUnknown = OuterUnknown;
NewList->PoolType = PoolType;
if (!TranslatedResourceList || !UntranslatedResourceList)
{
/* empty resource list */
*OutResourceList = (IResourceList*)&NewList->lpVtbl;
return STATUS_SUCCESS;
}
/* calculate translated resource list size */
ResourceCount = TranslatedResourceList->List[0].PartialResourceList.Count;
NewTranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount]);
/* store resource count */
NewList->NumberOfEntries = ResourceCount;
/* calculate untranslated resouce list size */
ResourceCount = UntranslatedResourceList->List[0].PartialResourceList.Count;
NewUntranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount]);
/* allocate translated resource list */
NewTranslatedResources = AllocateItem(PoolType, NewTranslatedSize, TAG_PORTCLASS);
if (!NewTranslatedResources)
{
FreeItem(NewList, TAG_PORTCLASS);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* allocate untranslated resource list */
NewUntranslatedResources = AllocateItem(PoolType, NewUntranslatedSize, TAG_PORTCLASS);
if (!NewUntranslatedResources)
{
FreeItem(NewList, TAG_PORTCLASS);
FreeItem(NewTranslatedResources, TAG_PORTCLASS);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* copy resource lists */
RtlCopyMemory(NewTranslatedResources, TranslatedResourceList, NewTranslatedSize);
RtlCopyMemory(NewUntranslatedResources, UntranslatedResourceList, NewUntranslatedSize);
/* store resource lists */
NewList->TranslatedResourceList= NewTranslatedResources;
NewList->UntranslatedResourceList = NewUntranslatedResources;
/* Increment our usage count and set the pointer to this object */
*OutResourceList = (IResourceList*)&NewList->lpVtbl;
return STATUS_SUCCESS;
}
PORTCLASSAPI
NTSTATUS
NTAPI
PcNewResourceSublist(
OUT PRESOURCELIST* OutResourceList,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PRESOURCELIST ParentList,
IN ULONG MaximumEntries)
{
IResourceListImpl* NewList, *Parent;
if (!OutResourceList || !ParentList || !MaximumEntries)
return STATUS_INVALID_PARAMETER;
Parent = (IResourceListImpl*)ParentList;
DPRINT("PcNewResourceSublist entered\n");
if (!Parent->TranslatedResourceList->List->PartialResourceList.Count ||
!Parent->UntranslatedResourceList->List->PartialResourceList.Count)
{
/* parent list can't be empty */
return STATUS_INVALID_PARAMETER;
}
NewList = AllocateItem(PoolType, sizeof(IResourceListImpl), TAG_PORTCLASS);
if (!NewList)
return STATUS_INSUFFICIENT_RESOURCES;
NewList->TranslatedResourceList = AllocateItem(PoolType, sizeof(CM_RESOURCE_LIST), TAG_PORTCLASS);
if (!NewList->TranslatedResourceList)
{
FreeItem(NewList, TAG_PORTCLASS);
return STATUS_INSUFFICIENT_RESOURCES;
}
NewList->UntranslatedResourceList = AllocateItem(PoolType, sizeof(CM_RESOURCE_LIST), TAG_PORTCLASS);
if (!NewList->UntranslatedResourceList)
{
FreeItem(NewList->TranslatedResourceList, TAG_PORTCLASS);
FreeItem(NewList, TAG_PORTCLASS);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(NewList->TranslatedResourceList, Parent->TranslatedResourceList, sizeof(CM_RESOURCE_LIST));
RtlCopyMemory(NewList->UntranslatedResourceList, Parent->UntranslatedResourceList, sizeof(CM_RESOURCE_LIST));
/* mark list as empty */
NewList->TranslatedResourceList->List->PartialResourceList.Count = 0;
NewList->UntranslatedResourceList->List->PartialResourceList.Count = 0;
NewList->lpVtbl = (IResourceListVtbl*)&vt_ResourceListVtbl;
NewList->ref = 1;
NewList->OuterUnknown = OuterUnknown;
NewList->PoolType = PoolType;
*OutResourceList = (IResourceList*)&NewList->lpVtbl;
DPRINT("PcNewResourceSublist OutResourceList %p OuterUnknown %p ParentList %p\n", *OutResourceList, OuterUnknown, ParentList);
return STATUS_SUCCESS;
}
@@ -0,0 +1,456 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS
* FILE: drivers/wdm/audio/backpln/portcls/resource.cpp
* PURPOSE: Port Class driver / ResourceList implementation
* PROGRAMMER: Andrew Greenwood
* Johannes Anderwald
* HISTORY:
* 27 Jan 07 Created
*/
#include "private.hpp"
class CResourceList : public IResourceList
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IResourceList;
CResourceList(IUnknown * OuterUnknown) {}
virtual ~CResourceList() {}
public:
PUNKNOWN m_OuterUnknown;
POOL_TYPE m_PoolType;
PCM_RESOURCE_LIST m_TranslatedResourceList;
PCM_RESOURCE_LIST m_UntranslatedResourceList;
ULONG m_NumberOfEntries;
LONG m_Ref;
};
NTSTATUS
NTAPI
CResourceList::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
if (IsEqualGUIDAligned(refiid, IID_IResourceList) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PRESOURCELIST(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IResourceList_QueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
CResourceList::NumberOfEntries()
{
// ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return m_NumberOfEntries;
}
ULONG
NTAPI
CResourceList::NumberOfEntriesOfType(
IN CM_RESOURCE_TYPE Type)
{
ULONG Index, Count = 0;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_TranslatedResourceList)
{
// no resource list
return 0;
}
// I guess the translated and untranslated lists will be same length?
for (Index = 0; Index < m_TranslatedResourceList->List[0].PartialResourceList.Count; Index ++ )
{
PartialDescriptor = &m_TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
DPRINT("Descriptor Type %u\n", PartialDescriptor->Type);
if (PartialDescriptor->Type == Type)
{
// Yay! Finally found one that matches!
Count++;
}
}
DPRINT("Found %d type %d\n", Count, Type);
return Count;
}
PCM_PARTIAL_RESOURCE_DESCRIPTOR
NTAPI
CResourceList::FindTranslatedEntry(
IN CM_RESOURCE_TYPE Type,
IN ULONG Index)
{
ULONG DescIndex, Count = 0;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_TranslatedResourceList)
{
// no resource list
return NULL;
}
for (DescIndex = 0; DescIndex < m_TranslatedResourceList->List[0].PartialResourceList.Count; DescIndex ++ )
{
PartialDescriptor = &m_TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[DescIndex];
if (PartialDescriptor->Type == Type)
{
// Yay! Finally found one that matches!
if (Index == Count)
{
return PartialDescriptor;
}
Count++;
}
}
return NULL;
}
PCM_PARTIAL_RESOURCE_DESCRIPTOR
NTAPI
CResourceList::FindUntranslatedEntry(
IN CM_RESOURCE_TYPE Type,
IN ULONG Index)
{
ULONG DescIndex, Count = 0;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!m_UntranslatedResourceList)
{
// no resource list
return NULL;
}
for (DescIndex = 0; DescIndex < m_UntranslatedResourceList->List[0].PartialResourceList.Count; DescIndex ++ )
{
PartialDescriptor = &m_UntranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[DescIndex];
if (PartialDescriptor->Type == Type)
{
// Yay! Finally found one that matches!
if (Index == Count)
{
return PartialDescriptor;
}
Count++;
}
}
return NULL;
}
NTSTATUS
NTAPI
CResourceList::AddEntry(
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Untranslated)
{
PCM_RESOURCE_LIST NewUntranslatedResources, NewTranslatedResources;
ULONG NewTranslatedSize, NewUntranslatedSize, TranslatedSize, UntranslatedSize, ResourceCount;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
// calculate translated resource list size
ResourceCount = m_TranslatedResourceList->List[0].PartialResourceList.Count;
#ifdef _MSC_VER
NewTranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount+1]);
TranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount]);
#else
NewTranslatedSize = sizeof(CM_RESOURCE_LIST) + (ResourceCount > 0 ? (ResourceCount+1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) : 0);
TranslatedSize = sizeof(CM_RESOURCE_LIST) + (ResourceCount > 0 ? (ResourceCount) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) : 0);
#endif
NewTranslatedResources = (PCM_RESOURCE_LIST)AllocateItem(m_PoolType, NewTranslatedSize, TAG_PORTCLASS);
if (!NewTranslatedResources)
return STATUS_INSUFFICIENT_RESOURCES;
// calculate untranslated resouce list size
ResourceCount = m_UntranslatedResourceList->List[0].PartialResourceList.Count;
#ifdef _MSC_VER
NewUntranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount+1]);
UntranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount]);
#else
NewUntranslatedSize = sizeof(CM_RESOURCE_LIST) + (ResourceCount > 0 ? (ResourceCount+1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) : 0);
UntranslatedSize = sizeof(CM_RESOURCE_LIST) + (ResourceCount > 0 ? (ResourceCount) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) : 0);
#endif
// allocate untranslated resource list size
NewUntranslatedResources = (PCM_RESOURCE_LIST)AllocateItem(m_PoolType, NewUntranslatedSize, TAG_PORTCLASS);
if (!NewUntranslatedResources)
{
FreeItem(NewTranslatedResources, TAG_PORTCLASS);
return STATUS_INSUFFICIENT_RESOURCES;
}
// now copy translated resource list
RtlMoveMemory(NewTranslatedResources, m_TranslatedResourceList, TranslatedSize);
RtlMoveMemory((PUCHAR)NewTranslatedResources + TranslatedSize, Translated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
// now copy untranslated resource list
RtlMoveMemory(NewUntranslatedResources, m_UntranslatedResourceList, UntranslatedSize);
RtlMoveMemory((PUCHAR)NewUntranslatedResources + UntranslatedSize, Untranslated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
// free old lists
FreeItem(m_TranslatedResourceList, TAG_PORTCLASS);
FreeItem(m_UntranslatedResourceList, TAG_PORTCLASS);
// store new lists
m_UntranslatedResourceList = NewUntranslatedResources;
m_TranslatedResourceList = NewTranslatedResources;
// increment descriptor count
NewUntranslatedResources->List[0].PartialResourceList.Count++;
NewTranslatedResources->List[0].PartialResourceList.Count++;
// add entry count
m_NumberOfEntries++;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CResourceList::AddEntryFromParent(
IN IResourceList* Parent,
IN CM_RESOURCE_TYPE Type,
IN ULONG Index)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated, Untranslated;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
Translated = Parent->FindTranslatedEntry(Type, Index);
Untranslated = Parent->FindUntranslatedEntry(Type, Index);
if (Translated && Untranslated)
{
// add entry from parent
return AddEntry(Translated, Untranslated);
}
// entry not found
return STATUS_INVALID_PARAMETER;
}
PCM_RESOURCE_LIST
NTAPI
CResourceList::TranslatedList()
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return m_TranslatedResourceList;
}
PCM_RESOURCE_LIST
NTAPI
CResourceList::UntranslatedList()
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return m_UntranslatedResourceList;
}
PORTCLASSAPI
NTSTATUS
NTAPI
PcNewResourceList(
OUT PRESOURCELIST* OutResourceList,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PCM_RESOURCE_LIST TranslatedResourceList,
IN PCM_RESOURCE_LIST UntranslatedResourceList)
{
PCM_RESOURCE_LIST NewUntranslatedResources, NewTranslatedResources;
ULONG NewTranslatedSize, NewUntranslatedSize, ResourceCount;
CResourceList* NewList;
NTSTATUS Status;
if (!TranslatedResourceList)
{
//
// if the untranslated resource list is also not provided, it becomes an empty resource list
//
if (UntranslatedResourceList)
{
// invalid parameter mix
return STATUS_INVALID_PARAMETER;
}
}
else
{
//
// if the translated resource list is also not provided, it becomes an empty resource list
//
if (!UntranslatedResourceList)
{
// invalid parameter mix
return STATUS_INVALID_PARAMETER;
}
}
NewList = new(PoolType, TAG_PORTCLASS)CResourceList(OuterUnknown);
if (!NewList)
return STATUS_INSUFFICIENT_RESOURCES;
Status = NewList->QueryInterface(IID_IResourceList, (PVOID*)OutResourceList);
if (!NT_SUCCESS(Status))
{
delete NewList;
}
// calculate translated resource list size
ResourceCount = TranslatedResourceList->List[0].PartialResourceList.Count;
#ifdef _MSC_VER
NewTranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount]);
#else
NewTranslatedSize = sizeof(CM_RESOURCE_LIST) + (ResourceCount > 0 ? (ResourceCount-1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) : 0);
#endif
// store resource count
NewList->m_NumberOfEntries = ResourceCount;
// calculate untranslated resouce list size
ResourceCount = UntranslatedResourceList->List[0].PartialResourceList.Count;
#ifdef _MSC_VER
NewUntranslatedSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount]);
#else
NewUntranslatedSize = sizeof(CM_RESOURCE_LIST) + (ResourceCount > 0 ? (ResourceCount-1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) : 0);
#endif
// allocate translated resource list
NewTranslatedResources = (PCM_RESOURCE_LIST)AllocateItem(PoolType, NewTranslatedSize, TAG_PORTCLASS);
if (!NewTranslatedResources)
{
FreeItem(NewList, TAG_PORTCLASS);
return STATUS_INSUFFICIENT_RESOURCES;
}
// allocate untranslated resource list
NewUntranslatedResources = (PCM_RESOURCE_LIST)AllocateItem(PoolType, NewUntranslatedSize, TAG_PORTCLASS);
if (!NewUntranslatedResources)
{
FreeItem(NewList, TAG_PORTCLASS);
FreeItem(NewTranslatedResources, TAG_PORTCLASS);
return STATUS_INSUFFICIENT_RESOURCES;
}
// copy resource lists
RtlCopyMemory(NewTranslatedResources, TranslatedResourceList, NewTranslatedSize);
RtlCopyMemory(NewUntranslatedResources, UntranslatedResourceList, NewUntranslatedSize);
// store resource lists
NewList->m_TranslatedResourceList= NewTranslatedResources;
NewList->m_UntranslatedResourceList = NewUntranslatedResources;
return STATUS_SUCCESS;
}
PORTCLASSAPI
NTSTATUS
NTAPI
PcNewResourceSublist(
OUT PRESOURCELIST* OutResourceList,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PRESOURCELIST ParentList,
IN ULONG MaximumEntries)
{
CResourceList* NewList, *Parent;
if (!OutResourceList || !ParentList || !MaximumEntries)
return STATUS_INVALID_PARAMETER;
Parent = (CResourceList*)ParentList;
if (!Parent->m_TranslatedResourceList->List->PartialResourceList.Count ||
!Parent->m_UntranslatedResourceList->List->PartialResourceList.Count)
{
// parent list can't be empty
return STATUS_INVALID_PARAMETER;
}
NewList = new(PoolType, TAG_PORTCLASS) CResourceList(OuterUnknown);
if (!NewList)
return STATUS_INSUFFICIENT_RESOURCES;
NewList->m_TranslatedResourceList = (PCM_RESOURCE_LIST)AllocateItem(PoolType, sizeof(CM_RESOURCE_LIST), TAG_PORTCLASS);
if (!NewList->m_TranslatedResourceList)
{
delete NewList;
return STATUS_INSUFFICIENT_RESOURCES;
}
NewList->m_UntranslatedResourceList = (PCM_RESOURCE_LIST)AllocateItem(PoolType, sizeof(CM_RESOURCE_LIST), TAG_PORTCLASS);
if (!NewList->m_UntranslatedResourceList)
{
delete NewList;
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(NewList->m_TranslatedResourceList, Parent->m_TranslatedResourceList, sizeof(CM_RESOURCE_LIST));
RtlCopyMemory(NewList->m_UntranslatedResourceList, Parent->m_UntranslatedResourceList, sizeof(CM_RESOURCE_LIST));
// mark list as empty
NewList->m_TranslatedResourceList->List->PartialResourceList.Count = 0;
NewList->m_UntranslatedResourceList->List->PartialResourceList.Count = 0;
// store members
NewList->m_OuterUnknown = OuterUnknown;
NewList->m_PoolType = PoolType;
NewList->m_Ref = 1;
*OutResourceList = (IResourceList*)NewList;
DPRINT("PcNewResourceSublist OutResourceList %p OuterUnknown %p ParentList %p\n", *OutResourceList, OuterUnknown, ParentList);
return STATUS_SUCCESS;
}
@@ -1,346 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/service_group.c
* PURPOSE: ServiceGroup object implementation
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
LIST_ENTRY Entry;
IN PSERVICESINK pServiceSink;
}GROUP_ENTRY, *PGROUP_ENTRY;
typedef struct
{
IServiceGroupVtbl *lpVtbl;
LONG ref;
LIST_ENTRY ServiceSinkHead;
BOOL Initialized;
BOOL TimerActive;
KTIMER Timer;
KDPC Dpc;
KEVENT Event;
LONG ThreadActive;
}IServiceGroupImpl;
//---------------------------------------------------------------
// IUnknown methods
//
NTSTATUS
NTAPI
IServiceGroup_fnQueryInterface(
IServiceGroup* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
IServiceGroupImpl * This = (IServiceGroupImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IServiceGroup) ||
IsEqualGUIDAligned(refiid, &IID_IServiceSink) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("IServiceGroup_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IServiceGroup_fnAddRef(
IServiceGroup* iface)
{
IServiceGroupImpl * This = (IServiceGroupImpl*)iface;
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IServiceGroup_fnRelease(
IServiceGroup* iface)
{
PLIST_ENTRY CurEntry;
PGROUP_ENTRY Entry;
IServiceGroupImpl * This = (IServiceGroupImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
while(!IsListEmpty(&This->ServiceSinkHead))
{
CurEntry = RemoveHeadList(&This->ServiceSinkHead);
Entry = CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry);
Entry->pServiceSink->lpVtbl->Release(Entry->pServiceSink);
FreeItem(Entry, TAG_PORTCLASS);
}
KeCancelTimer(&This->Timer);
if (This->ThreadActive)
{
KeSetEvent(&This->Event, 0, TRUE);
}
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
//---------------------------------------------------------------
// IServiceSink methods
//
VOID
NTAPI
IServiceGroup_fnRequestService(
IN IServiceGroup * iface)
{
KIRQL OldIrql;
IServiceGroupImpl * This = (IServiceGroupImpl*)iface;
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
{
KeInsertQueueDpc(&This->Dpc, NULL, NULL);
return;
}
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
KeInsertQueueDpc(&This->Dpc, NULL, NULL);
KeLowerIrql(OldIrql);
}
//---------------------------------------------------------------
// IServiceGroup methods
//
NTSTATUS
NTAPI
IServiceGroup_fnAddMember(
IN IServiceGroup * iface,
IN PSERVICESINK pServiceSink)
{
PGROUP_ENTRY Entry;
IServiceGroupImpl * This = (IServiceGroupImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
Entry = AllocateItem(NonPagedPool, sizeof(GROUP_ENTRY), TAG_PORTCLASS);
if (!Entry)
return STATUS_INSUFFICIENT_RESOURCES;
Entry->pServiceSink = pServiceSink;
pServiceSink->lpVtbl->AddRef(pServiceSink);
InsertTailList(&This->ServiceSinkHead, &Entry->Entry);
return STATUS_SUCCESS;
}
VOID
NTAPI
IServiceGroup_fnRemoveMember(
IN IServiceGroup * iface,
IN PSERVICESINK pServiceSink)
{
PLIST_ENTRY CurEntry;
PGROUP_ENTRY Entry;
IServiceGroupImpl * This = (IServiceGroupImpl*)iface;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
CurEntry = This->ServiceSinkHead.Flink;
while (CurEntry != &This->ServiceSinkHead)
{
Entry = CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry);
if (Entry->pServiceSink == pServiceSink)
{
RemoveEntryList(&Entry->Entry);
pServiceSink->lpVtbl->Release(pServiceSink);
FreeItem(Entry, TAG_PORTCLASS);
return;
}
CurEntry = CurEntry->Flink;
}
}
VOID
NTAPI
IServiceGroupDpc(
IN struct _KDPC *Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
{
PLIST_ENTRY CurEntry;
PGROUP_ENTRY Entry;
IServiceGroupImpl * This = (IServiceGroupImpl*)DeferredContext;
CurEntry = This->ServiceSinkHead.Flink;
while (CurEntry != &This->ServiceSinkHead)
{
Entry = CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry);
Entry->pServiceSink->lpVtbl->RequestService(Entry->pServiceSink);
CurEntry = CurEntry->Flink;
}
}
VOID
NTAPI
ServiceGroupThread(IN PVOID StartContext)
{
NTSTATUS Status;
KWAIT_BLOCK WaitBlockArray[2];
PVOID WaitObjects[2];
IServiceGroupImpl * This = (IServiceGroupImpl*)StartContext;
/* Set thread state */
InterlockedIncrement(&This->ThreadActive);
/* Setup the wait objects */
WaitObjects[0] = &This->Timer;
WaitObjects[1] = &This->Event;
do
{
/* Wait on our objects */
Status = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, Executive, KernelMode, FALSE, NULL, WaitBlockArray);
switch(Status)
{
case STATUS_WAIT_0:
IServiceGroupDpc(&This->Dpc, (PVOID)This, NULL, NULL);
break;
case STATUS_WAIT_1:
PsTerminateSystemThread(STATUS_SUCCESS);
return;
}
}while(TRUE);
}
VOID
NTAPI
IServiceGroup_fnSupportDelayedService(
IN IServiceGroup * iface)
{
NTSTATUS Status;
HANDLE ThreadHandle;
IServiceGroupImpl * This = (IServiceGroupImpl*)iface;
ASSERT_IRQL(DISPATCH_LEVEL);
if (This->Initialized)
return;
KeInitializeTimerEx(&This->Timer, NotificationTimer);
Status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, NULL, 0, NULL, ServiceGroupThread, (PVOID)This);
if (NT_SUCCESS(Status))
{
ZwClose(ThreadHandle);
This->Initialized = TRUE;
}
}
VOID
NTAPI
IServiceGroup_fnRequestDelayedService(
IN IServiceGroup * iface,
IN ULONGLONG ullDelay)
{
LARGE_INTEGER DueTime;
IServiceGroupImpl * This = (IServiceGroupImpl*)iface;
ASSERT_IRQL(DISPATCH_LEVEL);
DueTime.QuadPart = ullDelay;
if (This->Initialized)
{
if (KeGetCurrentIrql() <= DISPATCH_LEVEL)
KeSetTimer(&This->Timer, DueTime, &This->Dpc);
else
KeInsertQueueDpc(&This->Dpc, NULL, NULL);
}
}
VOID
NTAPI
IServiceGroup_fnCancelDelayedService(
IN IServiceGroup * iface)
{
IServiceGroupImpl * This = (IServiceGroupImpl*)iface;
ASSERT_IRQL(DISPATCH_LEVEL);
if (This->Initialized)
{
KeCancelTimer(&This->Timer);
}
}
static IServiceGroupVtbl vt_IServiceGroup =
{
/* IUnknown methods */
IServiceGroup_fnQueryInterface,
IServiceGroup_fnAddRef,
IServiceGroup_fnRelease,
IServiceGroup_fnRequestService,
IServiceGroup_fnAddMember,
IServiceGroup_fnRemoveMember,
IServiceGroup_fnSupportDelayedService,
IServiceGroup_fnRequestDelayedService,
IServiceGroup_fnCancelDelayedService
};
/*
* @implemented
*/
NTSTATUS NTAPI
PcNewServiceGroup(
OUT PSERVICEGROUP* OutServiceGroup,
IN PUNKNOWN OuterUnknown OPTIONAL)
{
IServiceGroupImpl * This;
DPRINT("PcNewServiceGroup entered\n");
This = AllocateItem(NonPagedPool, sizeof(IServiceGroupImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->lpVtbl = &vt_IServiceGroup;
This->ref = 1;
KeInitializeDpc(&This->Dpc, IServiceGroupDpc, (PVOID)This);
KeSetImportanceDpc(&This->Dpc, HighImportance);
KeInitializeEvent(&This->Event, NotificationEvent, FALSE);
InitializeListHead(&This->ServiceSinkHead);
*OutServiceGroup = (PSERVICEGROUP)&This->lpVtbl;
return STATUS_SUCCESS;
}
@@ -0,0 +1,319 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/service_group.cpp
* PURPOSE: ServiceGroup object implementation
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
VOID
NTAPI
IServiceGroupDpc(
IN struct _KDPC *Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
typedef struct
{
LIST_ENTRY Entry;
IN PSERVICESINK pServiceSink;
}GROUP_ENTRY, *PGROUP_ENTRY;
class CServiceGroup : public IServiceGroup
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IServiceGroup;
CServiceGroup(IUnknown * OuterUnknown);
virtual ~CServiceGroup() {}
protected:
LIST_ENTRY m_ServiceSinkHead;
BOOL m_Initialized;
BOOL m_TimerActive;
KTIMER m_Timer;
KDPC m_Dpc;
KEVENT m_Event;
LONG m_ThreadActive;
friend VOID NTAPI IServiceGroupDpc(IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
LONG m_Ref;
};
//---------------------------------------------------------------
// IUnknown methods
//
NTSTATUS
NTAPI
CServiceGroup::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
if (IsEqualGUIDAligned(refiid, IID_IServiceGroup) ||
IsEqualGUIDAligned(refiid, IID_IServiceSink) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PSERVICEGROUP(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("CServiceGroup::QueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
//---------------------------------------------------------------
// IServiceSink methods
//
CServiceGroup::CServiceGroup(IUnknown * OuterUnknown)
{
KeInitializeDpc(&m_Dpc, IServiceGroupDpc, (PVOID)this);
KeSetImportanceDpc(&m_Dpc, HighImportance);
KeInitializeEvent(&m_Event, NotificationEvent, FALSE);
InitializeListHead(&m_ServiceSinkHead);
}
VOID
NTAPI
CServiceGroup::RequestService()
{
KIRQL OldIrql;
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
{
KeInsertQueueDpc(&m_Dpc, NULL, NULL);
return;
}
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
KeInsertQueueDpc(&m_Dpc, NULL, NULL);
KeLowerIrql(OldIrql);
}
//---------------------------------------------------------------
// IServiceGroup methods
//
NTSTATUS
NTAPI
CServiceGroup::AddMember(
IN PSERVICESINK pServiceSink)
{
PGROUP_ENTRY Entry;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
Entry = (PGROUP_ENTRY)AllocateItem(NonPagedPool, sizeof(GROUP_ENTRY), TAG_PORTCLASS);
if (!Entry)
return STATUS_INSUFFICIENT_RESOURCES;
Entry->pServiceSink = pServiceSink;
pServiceSink->AddRef();
InsertTailList(&m_ServiceSinkHead, &Entry->Entry);
return STATUS_SUCCESS;
}
VOID
NTAPI
CServiceGroup::RemoveMember(
IN PSERVICESINK pServiceSink)
{
PLIST_ENTRY CurEntry;
PGROUP_ENTRY Entry;
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
CurEntry = m_ServiceSinkHead.Flink;
while (CurEntry != &m_ServiceSinkHead)
{
Entry = CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry);
if (Entry->pServiceSink == pServiceSink)
{
RemoveEntryList(&Entry->Entry);
pServiceSink->Release();
FreeItem(Entry, TAG_PORTCLASS);
return;
}
CurEntry = CurEntry->Flink;
}
}
VOID
NTAPI
IServiceGroupDpc(
IN struct _KDPC *Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
{
PLIST_ENTRY CurEntry;
PGROUP_ENTRY Entry;
CServiceGroup * This = (CServiceGroup*)DeferredContext;
CurEntry = This->m_ServiceSinkHead.Flink;
while (CurEntry != &This->m_ServiceSinkHead)
{
Entry = (PGROUP_ENTRY)CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry);
Entry->pServiceSink->RequestService();
CurEntry = CurEntry->Flink;
}
}
#if 0
VOID
NTAPI
ServiceGroupThread(IN PVOID StartContext)
{
NTSTATUS Status;
KWAIT_BLOCK WaitBlockArray[2];
PVOID WaitObjects[2];
CServiceGroup * This = (CServiceGroup*)StartContext;
// Set thread state
InterlockedIncrement(&This->m_ThreadActive);
// Setup the wait objects
WaitObjects[0] = &m_Timer;
WaitObjects[1] = &m_Event;
do
{
// Wait on our objects
Status = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, Executive, KernelMode, FALSE, NULL, WaitBlockArray);
switch(Status)
{
case STATUS_WAIT_0:
IServiceGroupDpc(&This->m_Dpc, (PVOID)This, NULL, NULL);
break;
case STATUS_WAIT_1:
PsTerminateSystemThread(STATUS_SUCCESS);
return;
}
}while(TRUE);
}
#endif
VOID
NTAPI
CServiceGroup::SupportDelayedService()
{
//NTSTATUS Status;
//HANDLE ThreadHandle;
PC_ASSERT_IRQL(DISPATCH_LEVEL);
if (m_Initialized)
return;
KeInitializeTimerEx(&m_Timer, NotificationTimer);
#if 0
Status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, NULL, 0, NULL, ServiceGroupThread, (PVOID)This);
if (NT_SUCCESS(Status))
{
ZwClose(ThreadHandle);
m_Initialized = TRUE;
}
#endif
}
VOID
NTAPI
CServiceGroup::RequestDelayedService(
IN ULONGLONG ullDelay)
{
LARGE_INTEGER DueTime;
PC_ASSERT_IRQL(DISPATCH_LEVEL);
DueTime.QuadPart = ullDelay;
if (m_Initialized)
{
if (KeGetCurrentIrql() <= DISPATCH_LEVEL)
KeSetTimer(&m_Timer, DueTime, &m_Dpc);
else
KeInsertQueueDpc(&m_Dpc, NULL, NULL);
}
}
VOID
NTAPI
CServiceGroup::CancelDelayedService()
{
PC_ASSERT_IRQL(DISPATCH_LEVEL);
if (m_Initialized)
{
KeCancelTimer(&m_Timer);
}
}
NTSTATUS
NTAPI
PcNewServiceGroup(
OUT PSERVICEGROUP* OutServiceGroup,
IN PUNKNOWN OuterUnknown OPTIONAL)
{
CServiceGroup * This;
NTSTATUS Status;
DPRINT("PcNewServiceGroup entered\n");
This = new(NonPagedPool, TAG_PORTCLASS)CServiceGroup(OuterUnknown);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
Status = This->QueryInterface(IID_IServiceSink, (PVOID*)OutServiceGroup);
if (!NT_SUCCESS(Status))
{
delete This;
return Status;
}
return Status;
}
@@ -1,20 +1,13 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/api.c
* FILE: drivers/wdm/audio/backpln/portcls/api.cpp
* PURPOSE: Port api functions
* PROGRAMMER: Johannes Anderwald
*/
/*
Undocumented PortCls exports
*/
#include "private.hpp"
#include "private.h"
/*
* @unimplemented
*/
NTSTATUS
NTAPI
KsoDispatchCreateWithGenericFactory(
@@ -25,23 +18,17 @@ KsoDispatchCreateWithGenericFactory(
return STATUS_NOT_IMPLEMENTED;
}
/*
* @implemented
*/
IIrpTarget *
NTAPI
KsoGetIrpTargetFromFileObject(
PFILE_OBJECT FileObject)
{
ASSERT(FileObject);
PC_ASSERT(FileObject);
/* IrpTarget is stored in FsContext2 */
return FileObject->FsContext2;
// IrpTarget is stored in FsContext2
return (IIrpTarget*)FileObject->FsContext2;
}
/*
* @implemented
*/
IIrpTarget *
NTAPI
KsoGetIrpTargetFromIrp(
@@ -49,16 +36,13 @@ KsoGetIrpTargetFromIrp(
{
PKSOBJECT_CREATE_ITEM CreateItem;
/* access the create item */
// access the create item
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
/* IIrpTarget is stored in Context member */
return CreateItem->Context;
// IIrpTarget is stored in Context member
return (IIrpTarget*)CreateItem->Context;
}
/*
* @unimplemented
*/
VOID
NTAPI
PcAcquireFormatResources(
@@ -68,7 +52,6 @@ PcAcquireFormatResources(
LONG Unknown4)
{
UNIMPLEMENTED;
return;
}
NTSTATUS
@@ -126,7 +109,7 @@ AddToPropertyTable(
if (FilterProperty->PropertiesCount)
{
Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].PropertyItem = AllocateItem(NonPagedPool,
Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].PropertyItem = (const KSPROPERTY_ITEM*)AllocateItem(NonPagedPool,
sizeof(KSPROPERTY_ITEM) * FilterProperty->PropertiesCount,
TAG_PORTCLASS);
@@ -140,13 +123,13 @@ AddToPropertyTable(
sizeof(KSPROPERTY_ITEM) * FilterProperty->PropertiesCount);
}
Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].Set = AllocateItem(NonPagedPool, sizeof(GUID), TAG_PORTCLASS);
Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].Set = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID), TAG_PORTCLASS);
if (!Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].Set)
return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyMemory((PVOID)Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].Set, FilterProperty->Set, sizeof(GUID));
/* ignore fast io table for now */
// ignore fast io table for now
Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].FastIoCount = 0;
Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].FastIoTable = NULL;
@@ -155,9 +138,6 @@ AddToPropertyTable(
return STATUS_SUCCESS;
}
/*
* @unimplemented
*/
NTSTATUS
NTAPI
PcCreateSubdeviceDescriptor(
@@ -181,15 +161,15 @@ PcCreateSubdeviceDescriptor(
PKSDATARANGE DataRange;
NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
Descriptor = AllocateItem(NonPagedPool, sizeof(SUBDEVICE_DESCRIPTOR), TAG_PORTCLASS);
Descriptor = (PSUBDEVICE_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(SUBDEVICE_DESCRIPTOR), TAG_PORTCLASS);
if (!Descriptor)
return STATUS_INSUFFICIENT_RESOURCES;
Descriptor->Interfaces = AllocateItem(NonPagedPool, sizeof(GUID) * InterfaceCount, TAG_PORTCLASS);
Descriptor->Interfaces = (GUID*)AllocateItem(NonPagedPool, sizeof(GUID) * InterfaceCount, TAG_PORTCLASS);
if (!Descriptor->Interfaces)
goto cleanup;
/* copy interface guids */
// copy interface guids
RtlCopyMemory(Descriptor->Interfaces, InterfaceGuids, sizeof(GUID) * InterfaceCount);
Descriptor->InterfaceCount = InterfaceCount;
@@ -197,7 +177,7 @@ PcCreateSubdeviceDescriptor(
{
/// FIXME
/// handle driver properties
Descriptor->FilterPropertySet.Properties = AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
Descriptor->FilterPropertySet.Properties = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
if (! Descriptor->FilterPropertySet.Properties)
goto cleanup;
@@ -210,13 +190,13 @@ PcCreateSubdeviceDescriptor(
}
}
Descriptor->Topology = AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
if (!Descriptor->Topology)
goto cleanup;
if (FilterDescription->ConnectionCount)
{
Descriptor->Topology->TopologyConnections = AllocateItem(NonPagedPool, sizeof(PCCONNECTION_DESCRIPTOR) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
if (!Descriptor->Topology->TopologyConnections)
goto cleanup;
@@ -226,11 +206,11 @@ PcCreateSubdeviceDescriptor(
if (FilterDescription->NodeCount)
{
Descriptor->Topology->TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
if (!Descriptor->Topology->TopologyNodes)
goto cleanup;
Descriptor->Topology->TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
if (!Descriptor->Topology->TopologyNodesNames)
goto cleanup;
@@ -250,31 +230,31 @@ PcCreateSubdeviceDescriptor(
if (FilterDescription->PinCount)
{
Descriptor->Factory.KsPinDescriptor = AllocateItem(NonPagedPool, FilterDescription->PinSize * FilterDescription->PinCount, TAG_PORTCLASS);
Descriptor->Factory.KsPinDescriptor = (PKSPIN_DESCRIPTOR)AllocateItem(NonPagedPool, FilterDescription->PinSize * FilterDescription->PinCount, TAG_PORTCLASS);
if (!Descriptor->Factory.KsPinDescriptor)
goto cleanup;
Descriptor->Factory.Instances = AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS);
Descriptor->Factory.Instances = (PPIN_INSTANCE_INFO)AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS);
if (!Descriptor->Factory.Instances)
goto cleanup;
Descriptor->Factory.PinDescriptorCount = FilterDescription->PinCount;
Descriptor->Factory.PinDescriptorSize = FilterDescription->PinSize;
/* copy pin factories */
// copy pin factories
for(Index = 0; Index < FilterDescription->PinCount; Index++)
{
RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &FilterDescription->Pins[Index].KsPinDescriptor, FilterDescription->PinSize);
if (FilterDescription->Pins[Index].KsPinDescriptor.DataRangesCount)
{
Descriptor->Factory.KsPinDescriptor[Index].DataRanges = AllocateItem(NonPagedPool, FilterDescription->Pins[Index].KsPinDescriptor.DataRangesCount * sizeof(PKSDATARANGE), TAG_PORTCLASS);
Descriptor->Factory.KsPinDescriptor[Index].DataRanges = (const PKSDATARANGE*)AllocateItem(NonPagedPool, FilterDescription->Pins[Index].KsPinDescriptor.DataRangesCount * sizeof(PKSDATARANGE), TAG_PORTCLASS);
if(!Descriptor->Factory.KsPinDescriptor[Index].DataRanges)
goto cleanup;
for (SubIndex = 0; SubIndex < FilterDescription->Pins[Index].KsPinDescriptor.DataRangesCount; SubIndex++)
{
DataRange = AllocateItem(NonPagedPool, FilterDescription->Pins[Index].KsPinDescriptor.DataRanges[SubIndex]->FormatSize, TAG_PORTCLASS);
DataRange = (PKSDATARANGE)AllocateItem(NonPagedPool, FilterDescription->Pins[Index].KsPinDescriptor.DataRanges[SubIndex]->FormatSize, TAG_PORTCLASS);
if (!DataRange)
goto cleanup;
@@ -313,10 +293,6 @@ cleanup:
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PcValidateConnectRequest(
@@ -1,71 +1,66 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/unregister.c
* FILE: drivers/wdm/audio/backpln/portcls/unregister.cpp
* PURPOSE: Unregisters a subdevice
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
#include "private.hpp"
typedef struct
class CUnregisterSubdevice : public IUnregisterSubdevice
{
IUnregisterSubdeviceVtbl *lpVtbl;
LONG ref;
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
}IUnregisterSubdeviceImpl;
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IUnregisterSubdevice;
CUnregisterSubdevice(IUnknown * OuterUnknown) : m_Ref(0) {}
virtual ~CUnregisterSubdevice(){}
protected:
LONG m_Ref;
};
NTSTATUS
NTAPI
IUnregisterSubdevice_fnQueryInterface(
IUnregisterSubdevice* iface,
CUnregisterSubdevice::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
IUnregisterSubdeviceImpl * This = (IUnregisterSubdeviceImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
*Output = PVOID(PUNREGISTERSUBDEVICE(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IUnregisterSubdevice_fnAddRef(
IUnregisterSubdevice* iface)
{
IUnregisterSubdeviceImpl * This = (IUnregisterSubdeviceImpl*)iface;
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IUnregisterSubdevice_fnRelease(
IUnregisterSubdevice* iface)
{
IUnregisterSubdeviceImpl * This = (IUnregisterSubdeviceImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
return This->ref;
}
NTSTATUS
NTAPI
IUnregisterSubdevice_fnUnregisterSubdevice(
IUnregisterSubdevice* iface,
CUnregisterSubdevice::UnregisterSubdevice(
IN PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN Unknown)
{
@@ -78,7 +73,7 @@ IUnregisterSubdevice_fnUnregisterSubdevice(
ULONG Index;
NTSTATUS Status;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
#if defined(__GNUC__) && \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ == 40400)
@@ -87,20 +82,20 @@ IUnregisterSubdevice_fnUnregisterSubdevice(
#endif
DeviceExtension = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension);
PC_ASSERT(DeviceExtension);
/* look up our undocumented interface */
Status = Unknown->lpVtbl->QueryInterface(Unknown, &IID_ISubdevice, (LPVOID)&SubDevice);
// look up our undocumented interface
Status = Unknown->QueryInterface(IID_ISubdevice, (LPVOID*)&SubDevice);
if (!NT_SUCCESS(Status))
{
DPRINT1("No ISubdevice interface\n");
/* the provided port driver doesnt support ISubdevice */
// the provided port driver doesnt support ISubdevice
return STATUS_INVALID_PARAMETER;
}
Entry = DeviceExtension->SubDeviceList.Flink;
Found = FALSE;
/* loop subdevice entry list and search for the subdevice */
// loop subdevice entry list and search for the subdevice
while(Entry != &DeviceExtension->SubDeviceList)
{
SubDeviceEntry = (PSUBDEVICE_ENTRY)CONTAINING_RECORD(Entry, SUBDEVICE_ENTRY, Entry);
@@ -111,16 +106,16 @@ IUnregisterSubdevice_fnUnregisterSubdevice(
}
Entry = Entry->Flink;
}
/* release the subdevice */
SubDevice->lpVtbl->Release(SubDevice);
// release the subdevice
SubDevice->Release();
if (!Found)
return STATUS_NOT_FOUND;
/* remove subdevice entry */
// remove subdevice entry
RemoveEntryList(&SubDeviceEntry->Entry);
/* loop our create items and disable the create handler */
// loop our create items and disable the create handler
for(Index = 0; Index < DeviceExtension->MaxSubDevices; Index++)
{
if (!RtlCompareUnicodeString(&SubDeviceEntry->Name, &DeviceExtension->CreateItems[Index].ObjectClass, TRUE))
@@ -131,48 +126,45 @@ IUnregisterSubdevice_fnUnregisterSubdevice(
}
}
/* now unregister device interfaces */
// now unregister device interfaces
while(!IsListEmpty(&SubDeviceEntry->SymbolicLinkList))
{
/* remove entry */
// remove entry
Entry = RemoveHeadList(&SubDeviceEntry->SymbolicLinkList);
/* get symlink entry */
// get symlink entry
SymLinkEntry = (PSYMBOLICLINK_ENTRY)CONTAINING_RECORD(Entry, SYMBOLICLINK_ENTRY, Entry);
/* unregister device interface */
// unregister device interface
IoSetDeviceInterfaceState(&SymLinkEntry->SymbolicLink, FALSE);
/* free symbolic link */
// free symbolic link
RtlFreeUnicodeString(&SymLinkEntry->SymbolicLink);
/* free sym entry */
// free sym entry
FreeItem(SymLinkEntry, TAG_PORTCLASS);
}
/* free subdevice entry */
// free subdevice entry
ExFreePool(SubDeviceEntry);
return STATUS_SUCCESS;
}
static IUnregisterSubdeviceVtbl vt_IUnregisterSubdeviceVtbl =
{
IUnregisterSubdevice_fnQueryInterface,
IUnregisterSubdevice_fnAddRef,
IUnregisterSubdevice_fnRelease,
IUnregisterSubdevice_fnUnregisterSubdevice
};
NTSTATUS
NTAPI
NewIUnregisterSubdevice(
OUT PUNREGISTERSUBDEVICE *OutDevice)
{
IUnregisterSubdeviceImpl * This = AllocateItem(NonPagedPool, sizeof(IUnregisterSubdeviceImpl), TAG_PORTCLASS);
NTSTATUS Status;
CUnregisterSubdevice * This = new(NonPagedPool, TAG_PORTCLASS) CUnregisterSubdevice(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->lpVtbl = &vt_IUnregisterSubdeviceVtbl;
This->ref = 1;
Status = This->QueryInterface(IID_IUnregisterSubdevice, (PVOID*)OutDevice);
if (!NT_SUCCESS(Status))
{
delete This;
return Status;
}
*OutDevice = (PUNREGISTERSUBDEVICE)&This->lpVtbl;
return STATUS_SUCCESS;
*OutDevice = (PUNREGISTERSUBDEVICE)This;
return Status;
}
@@ -1,96 +0,0 @@
#include "private.h"
typedef struct
{
IPortClsVersionVtbl *lpVtbl;
LONG ref;
}IPortClsVersionImpl;
//---------------------------------------------------------------
// IPortClsVersion interface functions
//
NTSTATUS
NTAPI
IPortClsVersion_fnQueryInterface(
IPortClsVersion * iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortClsVersionImpl * This = (IPortClsVersionImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
_InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
IPortClsVersion_fnAddRef(
IPortClsVersion * iface)
{
IPortClsVersionImpl * This = (IPortClsVersionImpl*)iface;
return InterlockedIncrement(&This->ref);
}
ULONG
NTAPI
IPortClsVersion_fnRelease(
IPortClsVersion * iface)
{
IPortClsVersionImpl * This = (IPortClsVersionImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
DWORD
NTAPI
IPortClsVersion_fnGetVersion(
IPortClsVersion * iface)
{
return kVersionWinXP_UAAQFE;
}
static IPortClsVersionVtbl vt_PortClsVersion =
{
/* IUnknown methods */
IPortClsVersion_fnQueryInterface,
IPortClsVersion_fnAddRef,
IPortClsVersion_fnRelease,
IPortClsVersion_fnGetVersion
};
NTSTATUS NewPortClsVersion(
OUT PPORTCLSVERSION * OutVersion)
{
IPortClsVersionImpl * This = AllocateItem(NonPagedPool, sizeof(IPortClsVersionImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->lpVtbl = &vt_PortClsVersion;
This->ref = 1;
*OutVersion = (PPORTCLSVERSION)&This->lpVtbl;
return STATUS_SUCCESS;
}
@@ -0,0 +1,93 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/version.cpp
* PURPOSE: Implements IPortClsVersion interface
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
class CPortClsVersion : public IPortClsVersion
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
IMP_IPortClsVersion;
CPortClsVersion(IUnknown *OuterUnknown)
{
m_Ref = 0;
}
virtual ~CPortClsVersion()
{
}
protected:
LONG m_Ref;
};
//---------------------------------------------------------------
// IPortClsVersion interface functions
//
NTSTATUS
NTAPI
CPortClsVersion::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
if (IsEqualGUIDAligned(refiid, IID_IPortClsVersion) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PPORTCLSVERSION(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
DWORD
NTAPI
CPortClsVersion::GetVersion()
{
return kVersionWinXP_UAAQFE;
}
NTSTATUS NewPortClsVersion(
OUT PPORTCLSVERSION * OutVersion)
{
CPortClsVersion * This = new(NonPagedPool, TAG_PORTCLASS) CPortClsVersion(NULL);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->AddRef();
*OutVersion = (PPORTCLSVERSION)This;
return STATUS_SUCCESS;
}