예제 #1
0
파일: mmixer.c 프로젝트: hoangduit/reactos
MIXER_STATUS
CreatePinCallback(
    IN PVOID Ctx,
    IN ULONG VirtualDeviceId,
    IN ULONG PinId,
    IN HANDLE hFilter,
    IN PKSPIN_CONNECT PinConnect,
    IN ACCESS_MASK DesiredAccess,
    OUT PHANDLE PinHandle)
{
    ULONG BytesReturned;
    SYSAUDIO_INSTANCE_INFO InstanceInfo;
    NTSTATUS Status;
    ULONG FreeIndex;
    PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx;

    /* setup property request */
    InstanceInfo.Property.Set = KSPROPSETID_Sysaudio;
    InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO;
    InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET;
    InstanceInfo.Flags = 0;
    InstanceInfo.DeviceNumber = VirtualDeviceId;

    /* attach to virtual device */
    Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);

    if (!NT_SUCCESS(Status))
        return MM_STATUS_UNSUCCESSFUL;

    /* close existing pin */
    FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType);

    /* now create the pin */
    Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle);

    /* check for success */
    if (!NT_SUCCESS(Status))
        return MM_STATUS_UNSUCCESSFUL;

    /* store the handle */
    Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex);
    if (!NT_SUCCESS(Status))
    {
        /* failed to insert handle */
        ZwClose(*PinHandle);
        return MM_STATUS_UNSUCCESSFUL;
    }

    return MM_STATUS_SUCCESS;
}
예제 #2
0
파일: pin.cpp 프로젝트: borgestrand/winuac2
/*****************************************************************************
 * CKsPin::CKsPin()
 *****************************************************************************
 *//*!
 * @brief
 * Destructor.
 */
CKsPin::
~CKsPin
(	void
)
{
    ClosePin();

    // Need to cast to BYTE *, because that's how CKsAudioRenderPin::CKsAudioRenderPin
    // and CKsAudioRenderPin::SetFormat allocate the memory.
    delete[] (BYTE *)m_KsPinConnect;

    // Need to cast to BYTE *, because that's how CKsFilter::GetPinPropertyMulti 
	// allocates the memory.
    delete[] (BYTE *)m_PinDescriptor.MultipleDataRanges;
    delete[] (BYTE *)m_PinDescriptor.MultipleInterfaces;
    delete[] (BYTE *)m_PinDescriptor.MultipleMediums;
}
NTSTATUS RtAudioPin::InitRtBuffer(ULONG size)
{
    KSRTAUDIO_BUFFER_PROPERTY_WITH_NOTIFICATION RtAudioProperty = { 0 };
    KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY RtNotificationProperty = { 0 };
    KSRTAUDIO_HWREGISTER_PROPERTY HwRegProperty = { 0 };
    KSRTAUDIO_HWREGISTER HwRegister = { 0 };
    IO_STATUS_BLOCK StatusBlock = { 0 };
    KSPROPERTY KsProperty;
    KSRTAUDIO_HWLATENCY Latency = { 0 };
    NTSTATUS status;

    PAGED_CODE();
    ASSERT(m_BufferMdl == NULL);
    ASSERT(m_PositionPointerMdl == NULL);

    //
    // Allocate a realtime audio buffer
    //
    RtAudioProperty.Property.Set = KSPROPSETID_RtAudio;
    RtAudioProperty.Property.Id = KSPROPERTY_RTAUDIO_BUFFER_WITH_NOTIFICATION;
    RtAudioProperty.Property.Flags = KSPROPERTY_TYPE_GET;
    RtAudioProperty.BaseAddress = NULL;
    RtAudioProperty.RequestedBufferSize = size;
    RtAudioProperty.NotificationCount = 2;

    status = SendIoctl(IOCTL_KS_PROPERTY,
        &RtAudioProperty,
        sizeof(RtAudioProperty),
        &m_RtBuffer,
        sizeof(m_RtBuffer),
        &StatusBlock,
        TRUE);

    ASSERT(NT_SUCCESS(status));
    ASSERT(NT_SUCCESS(StatusBlock.Status));
    ASSERT(StatusBlock.Information == sizeof(m_RtBuffer));

    if (!NT_SUCCESS(status))
    {
        RtlZeroMemory(&m_RtBuffer, sizeof(m_RtBuffer));
        ClosePin();
        return status;
    }

	//
	// Portcls.sys assumes that the RtAudio buffer will be accessed via user
	// mode and we need a kernel mode mapping (a.k.a. 'system address') in order to access the buffer
	// in an arbitrary thread context via the timer DPC.
	//
    if (m_RtBuffer.BufferAddress)
    {
        m_BufferMdl = IoAllocateMdl(m_RtBuffer.BufferAddress, m_RtBuffer.ActualBufferSize, FALSE, FALSE, NULL);
        ASSERT(m_BufferMdl != NULL);

        if (m_BufferMdl != NULL)
        {
            MmProbeAndLockPages(m_BufferMdl, KernelMode, IoModifyAccess);
            m_RtBuffer.BufferAddress = MmGetSystemAddressForMdlSafe(m_BufferMdl, NormalPagePriority | MdlMappingNoExecute);
        }
        else
        {
            ClosePin();
            return STATUS_NO_MEMORY;
        }
    }

    //
    // Setup m_pPositionRegister.
    //
    HwRegProperty.Property.Set = KSPROPSETID_RtAudio;
    HwRegProperty.Property.Id = KSPROPERTY_RTAUDIO_POSITIONREGISTER;
    HwRegProperty.Property.Flags = KSPROPERTY_TYPE_GET;
    HwRegProperty.BaseAddress = NULL;
    
    status = SendIoctl(IOCTL_KS_PROPERTY,
        &HwRegProperty,
        sizeof(HwRegProperty),
        &HwRegister,
        sizeof(HwRegister),
        &StatusBlock,
        TRUE);

    ASSERT(NT_SUCCESS(status));
    ASSERT(NT_SUCCESS(StatusBlock.Status));
    ASSERT(StatusBlock.Information == sizeof(HwRegister));

    if (!NT_SUCCESS(status))
    {
        RtlZeroMemory(&m_RtBuffer, sizeof(m_RtBuffer));
        ClosePin();
        return status;
    }

    ASSERT(HwRegister.Width == 32);
    m_PositionPointerMdl = IoAllocateMdl(HwRegister.Register, HwRegister.Width / 8, FALSE, FALSE, NULL);
    ASSERT(m_PositionPointerMdl != NULL);

    if (m_PositionPointerMdl != NULL)
    {
        MmProbeAndLockPages(m_PositionPointerMdl, KernelMode, IoModifyAccess);
        m_pPositionRegister = (PULONG) MmGetSystemAddressForMdlSafe(m_PositionPointerMdl, 
                                                                    NormalPagePriority | MdlMappingNoExecute);
    }
    else
    {
        ClosePin();
        return STATUS_NO_MEMORY;
    }


    //
    // Calculate m_FifoSizeInFrames.
    //
    if (NT_SUCCESS(status))
    {
        KsProperty.Set = KSPROPSETID_RtAudio;
        KsProperty.Id = KSPROPERTY_RTAUDIO_HWLATENCY;
        KsProperty.Flags = KSPROPERTY_TYPE_GET;

        status = SendIoctl(IOCTL_KS_PROPERTY,
            &KsProperty,
            sizeof(KsProperty),
            &Latency,
            sizeof(Latency),
            &StatusBlock,
            TRUE);

        ASSERT(NT_SUCCESS(status));
        ASSERT(NT_SUCCESS(StatusBlock.Status));
        ASSERT(StatusBlock.Information == sizeof(Latency));
    }

    if (NT_SUCCESS(status))
    {
        WORD BlockAlign = m_Format.WaveFormatExt.Format.nBlockAlign;
        // Make sure we round up instead of down
        m_FifoSizeInFrames = (Latency.FifoSize + BlockAlign - 1) / BlockAlign;
    }
    else
    {
        RtlZeroMemory(&m_RtBuffer, sizeof(m_RtBuffer));
        ClosePin();
        return status;
    }

    return status;
}
RtAudioPin::~RtAudioPin()
{
    PAGED_CODE();

    ClosePin();
}