mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 12:23:31 +00:00
- 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:
@@ -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;
|
||||
}
|
||||
+93
-108
@@ -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;
|
||||
}
|
||||
+17
-43
@@ -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(
|
||||
+84
-105
@@ -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;
|
||||
+39
-39
@@ -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;
|
||||
+8
-9
@@ -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;
|
||||
}
|
||||
+9
-29
@@ -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;
|
||||
}
|
||||
+9
-7
@@ -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}};
|
||||
+332
-80
@@ -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;
|
||||
}
|
||||
+65
-80
@@ -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;
|
||||
}
|
||||
|
||||
+10
-12
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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
-1
@@ -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
|
||||
*/
|
||||
+9
-9
@@ -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;
|
||||
}
|
||||
|
||||
+52
-115
@@ -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>
|
||||
|
||||
+7
-13
@@ -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;
|
||||
+58
-17
@@ -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(
|
||||
+52
-51
@@ -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;
|
||||
}
|
||||
+24
-48
@@ -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(
|
||||
+65
-73
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user