- 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; goto cleanup;
} }
/* store max subdevice count */
portcls_ext->MaxSubDevices = MaxObjects;
/* store the physical device object */ /* store the physical device object */
portcls_ext->PhysicalDeviceObject = PhysicalDeviceObject; portcls_ext->PhysicalDeviceObject = PhysicalDeviceObject;
/* set up the start device function */ /* set up the start device function */
@ -237,6 +239,8 @@ PcRegisterSubdevice(
SUBDEVICE_DESCRIPTOR * SubDeviceDescriptor; SUBDEVICE_DESCRIPTOR * SubDeviceDescriptor;
ULONG Index; ULONG Index;
UNICODE_STRING RefName; UNICODE_STRING RefName;
PSUBDEVICE_ENTRY Entry;
PSYMBOLICLINK_ENTRY SymEntry;
DPRINT1("PcRegisterSubdevice DeviceObject %p Name %S Unknown %p\n", DeviceObject, Name, Unknown); DPRINT1("PcRegisterSubdevice DeviceObject %p Name %S Unknown %p\n", DeviceObject, Name, Unknown);
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
@ -276,12 +280,22 @@ PcRegisterSubdevice(
return STATUS_UNSUCCESSFUL; 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 */ /* add an create item to the device header */
Status = KsAddObjectCreateItemToDeviceHeader(DeviceExt->KsDeviceHeader, PcCreateItemDispatch, (PVOID)SubDevice, Name, NULL); Status = KsAddObjectCreateItemToDeviceHeader(DeviceExt->KsDeviceHeader, PcCreateItemDispatch, (PVOID)SubDevice, Name, NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* failed to attach */ /* failed to attach */
SubDevice->lpVtbl->Release(SubDevice); SubDevice->lpVtbl->Release(SubDevice);
FreeItem(Entry, TAG_PORTCLASS);
DPRINT1("KsAddObjectCreateItemToDeviceHeader failed with %x\n", Status); DPRINT1("KsAddObjectCreateItemToDeviceHeader failed with %x\n", Status);
return Status; return Status;
} }
@ -289,6 +303,14 @@ PcRegisterSubdevice(
/* initialize reference string */ /* initialize reference string */
RtlInitUnicodeString(&RefName, Name); 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++) for(Index = 0; Index < SubDeviceDescriptor->InterfaceCount; Index++)
{ {
/* FIXME /* FIXME
@ -300,12 +322,26 @@ PcRegisterSubdevice(
&SymbolicLinkName); &SymbolicLinkName);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* activate device interface */
IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE); 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); SubDevice->lpVtbl->Release(SubDevice);
return STATUS_SUCCESS; return STATUS_SUCCESS;

View file

@ -20,8 +20,13 @@ PcGetDeviceProperty(
OUT PVOID PropertyBuffer, OUT PVOID PropertyBuffer,
OUT PULONG ResultLength) OUT PULONG ResultLength)
{ {
PPCLASS_DEVICE_EXTENSION DeviceExtension;
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 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_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_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_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); return NewPortClsVersion((PPORTCLSVERSION*)Output);
} }
else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
{
return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS) if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{ {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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