- Implement dynamic unregistration of audio devices

- IoGetDeviceProperty expects the PDO, not FDO
- Implement IUnregisterSubdevice interface for all port drivers


svn path=/trunk/; revision=41890
This commit is contained in:
Johannes Anderwald 2009-07-11 17:44:41 +00:00
parent 038d68b156
commit 9913f96067
11 changed files with 256 additions and 6 deletions

View file

@ -145,6 +145,8 @@ PcAddAdapterDevice(
goto cleanup;
}
/* store max subdevice count */
portcls_ext->MaxSubDevices = MaxObjects;
/* store the physical device object */
portcls_ext->PhysicalDeviceObject = PhysicalDeviceObject;
/* set up the start device function */
@ -237,6 +239,8 @@ PcRegisterSubdevice(
SUBDEVICE_DESCRIPTOR * SubDeviceDescriptor;
ULONG Index;
UNICODE_STRING RefName;
PSUBDEVICE_ENTRY Entry;
PSYMBOLICLINK_ENTRY SymEntry;
DPRINT1("PcRegisterSubdevice DeviceObject %p Name %S Unknown %p\n", DeviceObject, Name, Unknown);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
@ -276,12 +280,22 @@ PcRegisterSubdevice(
return STATUS_UNSUCCESSFUL;
}
/* allocate subdevice entry */
Entry = AllocateItem(NonPagedPool, sizeof(SUBDEVICE_ENTRY), TAG_PORTCLASS);
if (!Entry)
{
/* Insufficient memory */
SubDevice->lpVtbl->Release(SubDevice);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* 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);
FreeItem(Entry, TAG_PORTCLASS);
DPRINT1("KsAddObjectCreateItemToDeviceHeader failed with %x\n", Status);
return Status;
}
@ -289,6 +303,14 @@ PcRegisterSubdevice(
/* initialize reference string */
RtlInitUnicodeString(&RefName, Name);
/* initialize subdevice entry */
Entry->SubDevice = SubDevice;
RtlInitUnicodeString(&Entry->Name, Name);
InitializeListHead(&Entry->SymbolicLinkList);
/* store subdevice entry */
InsertTailList(&DeviceExt->SubDeviceList, &Entry->Entry);
for(Index = 0; Index < SubDeviceDescriptor->InterfaceCount; Index++)
{
/* FIXME
@ -300,12 +322,26 @@ PcRegisterSubdevice(
&SymbolicLinkName);
if (NT_SUCCESS(Status))
{
/* activate device interface */
IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE);
RtlFreeUnicodeString(&SymbolicLinkName);
/* allocate symbolic link entry */
SymEntry = AllocateItem(NonPagedPool, sizeof(SYMBOLICLINK_ENTRY), TAG_PORTCLASS);
if (SymEntry)
{
/* initialize symbolic link item */
RtlInitUnicodeString(&SymEntry->SymbolicLink, SymbolicLinkName.Buffer);
/* store item */
InsertTailList(&Entry->SymbolicLinkList, &SymEntry->Entry);
}
else
{
/* allocating failed */
RtlFreeUnicodeString(&SymbolicLinkName);
}
}
}
/* Release SubDevice reference */
/* release SubDevice reference */
SubDevice->lpVtbl->Release(SubDevice);
return STATUS_SUCCESS;

View file

@ -20,8 +20,13 @@ PcGetDeviceProperty(
OUT PVOID PropertyBuffer,
OUT PULONG ResultLength)
{
PPCLASS_DEVICE_EXTENSION DeviceExtension;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
return IoGetDeviceProperty(DeviceObject, DeviceProperty, BufferLength, PropertyBuffer, ResultLength);
DeviceExtension = (PPCLASS_DEVICE_EXTENSION)((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
return IoGetDeviceProperty(DeviceExtension->PhysicalDeviceObject, DeviceProperty, BufferLength, PropertyBuffer, ResultLength);
}
/*

View file

@ -91,5 +91,6 @@ const GUID IID_IPortWaveRTStream = {0x1809ce5a, 0x64bc, 0x4e62,
const GUID IID_IMiniportWaveRT = {0x0f9fc4d6, 0x6061, 0x4f3c, {0xb1, 0xfc, 0x7, 0x5e, 0x35, 0xf7, 0x96, 0xa}};
const GUID IID_IMiniportWaveRTStream = {0x000ac9ab, 0xfaab, 0x4f3d, {0x94, 0x55, 0x6f, 0xf8, 0x30, 0x6a, 0x74, 0xa0}};
const GUID IID_IMiniportWaveRTStreamNotification = {0x23759128, 0x96f1, 0x423b, {0xab, 0x4d, 0x81, 0x63, 0x5b, 0xcf, 0x8c, 0xa1}};
const GUID IID_IUnregisterSubdevice = {0x16738177, 0xe199, 0x41f9, {0x9a, 0x87, 0xab, 0xb2, 0xa5, 0x43, 0x2f, 0x21}};
const GUID IID_IUnregisterPhysicalConnection = {0x6c38e231, 0x2a0d, 0x428d, {0x81, 0xf8, 0x07, 0xcc, 0x42, 0x8b, 0xb9, 0xa4}};

View file

@ -83,6 +83,10 @@ IPortDMus_fnQueryInterface(
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{

View file

@ -101,6 +101,10 @@ IPortTopology_fnQueryInterface(
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{

View file

@ -226,6 +226,10 @@ IPortWaveCyclic_fnQueryInterface(
{
return NewIDrmPort((PDRMPORT2*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{

View file

@ -286,6 +286,10 @@ IPortWavePci_fnQueryInterface(
{
return NewPortClsVersion((PPORTCLSVERSION*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{

View file

@ -222,6 +222,10 @@ IPortWaveRT_fnQueryInterface(
{
return NewIDrmPort((PDRMPORT2*)Output);
}
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{

View file

@ -49,6 +49,7 @@
<file>resource.c</file>
<file>service_group.c</file>
<file>undoc.c</file>
<file>unregister.c</file>
<file>version.c</file>
<file>portcls.rc</file>
</module>

View file

@ -295,6 +295,12 @@ PcIoTimerRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context);
NTSTATUS
NTAPI
NewIUnregisterSubdevice(
OUT PUNREGISTERSUBDEVICE *OutDevice);
#define DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PinSet,\
PropGeneral, PropInstances, PropIntersection)\
DEFINE_KSPROPERTY_TABLE(PinSet) {\
@ -315,8 +321,17 @@ DEFINE_KSPROPERTY_TABLE(PinSet) {\
typedef struct
{
LIST_ENTRY Entry;
KSOBJECT_HEADER ObjectHeader;
}SUBDEVICE_ENTRY;
UNICODE_STRING SymbolicLink;
}SYMBOLICLINK_ENTRY, *PSYMBOLICLINK_ENTRY;
typedef struct
{
LIST_ENTRY Entry;
ISubdevice *SubDevice;
UNICODE_STRING Name;
LIST_ENTRY SymbolicLinkList;
}SUBDEVICE_ENTRY, *PSUBDEVICE_ENTRY;
typedef struct
{

View file

@ -0,0 +1,172 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/unregister.c
* PURPOSE: Unregisters a subdevice
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IUnregisterSubdeviceVtbl *lpVtbl;
LONG ref;
}IUnregisterSubdeviceImpl;
NTSTATUS
NTAPI
IUnregisterSubdevice_fnQueryInterface(
IUnregisterSubdevice* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IUnregisterSubdeviceImpl * This = (IUnregisterSubdeviceImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
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,
IN PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN Unknown)
{
PPCLASS_DEVICE_EXTENSION DeviceExtension;
PLIST_ENTRY Entry;
PSUBDEVICE_ENTRY SubDeviceEntry;
PSYMBOLICLINK_ENTRY SymLinkEntry;
ISubdevice *SubDevice;
ULONG Found;
ULONG Index;
NTSTATUS Status;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
DeviceExtension = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension);
/* look up our undocumented interface */
Status = Unknown->lpVtbl->QueryInterface(Unknown, &IID_ISubdevice, (LPVOID)&SubDevice);
if (!NT_SUCCESS(Status))
{
DPRINT1("No ISubdevice interface\n");
/* 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 */
while(Entry != &DeviceExtension->SubDeviceList)
{
SubDeviceEntry = (PSUBDEVICE_ENTRY)CONTAINING_RECORD(Entry, SUBDEVICE_ENTRY, Entry);
if (SubDeviceEntry->SubDevice == SubDevice)
{
Found = TRUE;
break;
}
Entry = Entry->Flink;
}
/* release the subdevice */
SubDevice->lpVtbl->Release(SubDevice);
if (!Found)
return STATUS_NOT_FOUND;
/* remove subdevice entry */
RemoveEntryList(&SubDeviceEntry->Entry);
/* 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))
{
DeviceExtension->CreateItems[Index].Create = NULL;
RtlInitUnicodeString(&DeviceExtension->CreateItems[Index].ObjectClass, NULL);
break;
}
}
/* now unregister device interfaces */
while(!IsListEmpty(&SubDeviceEntry->SymbolicLinkList))
{
/* remove entry */
Entry = RemoveHeadList(&SubDeviceEntry->SymbolicLinkList);
/* get symlink entry */
SymLinkEntry = (PSYMBOLICLINK_ENTRY)CONTAINING_RECORD(Entry, SYMBOLICLINK_ENTRY, Entry);
/* unregister device interface */
IoSetDeviceInterfaceState(&SymLinkEntry->SymbolicLink, FALSE);
/* free symbolic link */
RtlFreeUnicodeString(&SymLinkEntry->SymbolicLink);
/* free sym entry */
FreeItem(SymLinkEntry, TAG_PORTCLASS);
}
/* 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);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
This->lpVtbl = &vt_IUnregisterSubdeviceVtbl;
This->ref = 1;
*OutDevice = (PUNREGISTERSUBDEVICE)&This->lpVtbl;
return STATUS_SUCCESS;
}