reactos/drivers/wdm/audio/backpln/portcls/connection.cpp

335 lines
8.7 KiB
C++

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/connection.c
* PURPOSE: portcls physical connection registration
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
#ifndef YDEBUG
#define NDEBUG
#endif
#include <debug.h>
extern
"C"
NTSYSAPI
BOOLEAN
NTAPI
RtlCreateUnicodeString(
PUNICODE_STRING DestinationString,
PCWSTR SourceString
);
class CUnregisterPhysicalConnection : public IUnregisterPhysicalConnection
{
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_IUnregisterPhysicalConnection;
CUnregisterPhysicalConnection(IUnknown *OuterUnknown){}
virtual ~CUnregisterPhysicalConnection(){}
protected:
LONG m_Ref;
};
NTSTATUS
NTAPI
CUnregisterPhysicalConnection::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
UNICODE_STRING GuidString;
if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection) ||
IsEqualGUIDAligned(refiid, IID_IUnknown))
{
*Output = PVOID(PUNKNOWN(this));
PUNKNOWN(*Output)->AddRef();
return STATUS_SUCCESS;
}
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
{
DPRINT1("CUnregisterPhysicalConnection::QueryInterface no interface!!! iface %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
}
return STATUS_UNSUCCESSFUL;
}
static
NTSTATUS
UnRegisterConnection(
IN OUT PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN FromUnknown,
IN PUNICODE_STRING FromString,
IN ULONG FromPin,
IN PUNKNOWN ToUnknown,
IN PUNICODE_STRING ToString,
IN ULONG ToPin)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
CUnregisterPhysicalConnection::UnregisterPhysicalConnection(
IN PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN FromUnknown,
IN ULONG FromPin,
IN PUNKNOWN ToUnknown,
IN ULONG ToPin)
{
if (!DeviceObject || !FromUnknown || !ToUnknown)
return STATUS_INVALID_PARAMETER;
return UnRegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, ToUnknown, NULL, ToPin);
}
NTSTATUS
NTAPI
CUnregisterPhysicalConnection::UnregisterPhysicalConnectionToExternal(
IN PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN FromUnknown,
IN ULONG FromPin,
IN PUNICODE_STRING ToString,
IN ULONG ToPin)
{
if (!DeviceObject || !FromUnknown || !ToString)
return STATUS_INVALID_PARAMETER;
return UnRegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, NULL, ToString, ToPin);
}
NTSTATUS
NTAPI
CUnregisterPhysicalConnection::UnregisterPhysicalConnectionFromExternal(
IN PDEVICE_OBJECT DeviceObject,
IN PUNICODE_STRING FromString,
IN ULONG FromPin,
IN PUNKNOWN ToUnknown,
IN ULONG ToPin)
{
if (!DeviceObject || !FromString || !ToUnknown)
return STATUS_INVALID_PARAMETER;
return UnRegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin);
}
NTSTATUS
NTAPI
NewIUnregisterPhysicalConnection(
OUT PUNREGISTERPHYSICALCONNECTION *OutConnection)
{
CUnregisterPhysicalConnection *new_ptr = new(NonPagedPool, TAG_PORTCLASS) CUnregisterPhysicalConnection(NULL);
if (!new_ptr)
return STATUS_INSUFFICIENT_RESOURCES;
new_ptr->AddRef();
*OutConnection = (PUNREGISTERPHYSICALCONNECTION)new_ptr;
return STATUS_SUCCESS;
}
NTSTATUS
RegisterConnection(
IN OUT PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN FromUnknown,
IN PUNICODE_STRING FromString,
IN ULONG FromPin,
IN PUNKNOWN ToUnknown,
IN PUNICODE_STRING ToString,
IN ULONG ToPin)
{
PSUBDEVICE_DESCRIPTOR FromSubDeviceDescriptor = NULL, ToSubDeviceDescriptor = NULL;
PSYMBOLICLINK_ENTRY SymEntry;
ISubdevice * FromSubDevice = NULL, *ToSubDevice = NULL;
NTSTATUS Status;
PPHYSICAL_CONNECTION_ENTRY FromEntry = NULL, ToEntry = NULL;
if (FromUnknown)
{
Status = FromUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&FromSubDevice);
if (!NT_SUCCESS(Status))
goto cleanup;
Status = FromSubDevice->GetDescriptor(&FromSubDeviceDescriptor);
if (!NT_SUCCESS(Status))
goto cleanup;
if (IsListEmpty(&FromSubDeviceDescriptor->SymbolicLinkList))
{
Status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
SymEntry = (PSYMBOLICLINK_ENTRY)CONTAINING_RECORD(FromSubDeviceDescriptor->SymbolicLinkList.Flink, SYMBOLICLINK_ENTRY, Entry);
FromString = &SymEntry->SymbolicLink;
}
if (ToUnknown)
{
Status = ToUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&ToSubDevice);
if (!NT_SUCCESS(Status))
goto cleanup;
Status = ToSubDevice->GetDescriptor(&ToSubDeviceDescriptor);
if (!NT_SUCCESS(Status))
goto cleanup;
if (IsListEmpty(&ToSubDeviceDescriptor->SymbolicLinkList))
{
Status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
SymEntry = (PSYMBOLICLINK_ENTRY)CONTAINING_RECORD(ToSubDeviceDescriptor->SymbolicLinkList.Flink, SYMBOLICLINK_ENTRY, Entry);
ToString = &SymEntry->SymbolicLink;
}
if (FromSubDeviceDescriptor)
{
FromEntry = (PPHYSICAL_CONNECTION_ENTRY)AllocateItem(NonPagedPool, sizeof(PHYSICAL_CONNECTION_ENTRY) + ToString->MaximumLength + sizeof(WCHAR), TAG_PORTCLASS);
if (!FromEntry)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
}
if (ToSubDeviceDescriptor)
{
ToEntry = (PPHYSICAL_CONNECTION_ENTRY)AllocateItem(NonPagedPool, sizeof(PHYSICAL_CONNECTION_ENTRY) + FromString->MaximumLength + sizeof(WCHAR), TAG_PORTCLASS);
if (!ToEntry)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
}
if (FromSubDeviceDescriptor)
{
FromEntry->FromPin = FromPin;
FromEntry->Connection.Pin = ToPin;
FromEntry->Connection.Size = sizeof(KSPIN_PHYSICALCONNECTION) + ToString->MaximumLength + sizeof(WCHAR);
RtlMoveMemory(&FromEntry->Connection.SymbolicLinkName, ToString->Buffer, ToString->MaximumLength);
FromEntry->Connection.SymbolicLinkName[ToString->Length / sizeof(WCHAR)] = UNICODE_NULL;
InsertTailList(&FromSubDeviceDescriptor->PhysicalConnectionList, &FromEntry->Entry);
}
if (ToSubDeviceDescriptor)
{
ToEntry->FromPin = ToPin;
ToEntry->Connection.Pin = FromPin;
ToEntry->Connection.Size = sizeof(KSPIN_PHYSICALCONNECTION) + FromString->MaximumLength + sizeof(WCHAR);
RtlMoveMemory(&ToEntry->Connection.SymbolicLinkName, FromString->Buffer, FromString->MaximumLength);
ToEntry->Connection.SymbolicLinkName[FromString->Length / sizeof(WCHAR)] = UNICODE_NULL;
InsertTailList(&ToSubDeviceDescriptor->PhysicalConnectionList, &ToEntry->Entry);
}
return STATUS_SUCCESS;
cleanup:
if (FromSubDevice)
FromSubDevice->Release();
if (ToSubDevice)
ToSubDevice->Release();
if (FromEntry)
FreeItem(FromEntry, TAG_PORTCLASS);
if (ToEntry)
FreeItem(ToEntry, TAG_PORTCLASS);
return Status;
}
NTSTATUS
NTAPI
PcRegisterPhysicalConnection(
IN PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN FromUnknown,
IN ULONG FromPin,
IN PUNKNOWN ToUnknown,
IN ULONG ToPin)
{
DPRINT("PcRegisterPhysicalConnection\n");
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!DeviceObject || !FromUnknown || !ToUnknown)
return STATUS_INVALID_PARAMETER;
return RegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, ToUnknown, NULL, ToPin);
}
NTSTATUS
NTAPI
PcRegisterPhysicalConnectionFromExternal(
IN PDEVICE_OBJECT DeviceObject,
IN PUNICODE_STRING FromString,
IN ULONG FromPin,
IN PUNKNOWN ToUnknown,
IN ULONG ToPin)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!DeviceObject || !FromString || !ToUnknown)
return STATUS_INVALID_PARAMETER;
return RegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin);
}
NTSTATUS
NTAPI
PcRegisterPhysicalConnectionToExternal(
IN PDEVICE_OBJECT DeviceObject,
IN PUNKNOWN FromUnknown,
IN ULONG FromPin,
IN PUNICODE_STRING ToString,
IN ULONG ToPin)
{
PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
if (!DeviceObject || !FromUnknown || !ToString)
return STATUS_INVALID_PARAMETER;
return RegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, NULL, ToString, ToPin);
}