*/
#include "wdmaud.h"
-const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
-const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
-const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
-const GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
-const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
-const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
-const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
-const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
-const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
-
NTSTATUS
WdmAudControlOpen(
return WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo);
}
+ if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE)
+ {
+ return WdmAudControlOpenMidi(DeviceObject, Irp, DeviceInfo, ClientInfo);
+ }
+
+
return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
}
IN PWDMAUD_CLIENT ClientInfo)
{
ULONG Result = 0;
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_SUCCESS;
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
{
- Result = DeviceExtension->MixerInfoCount;
+ Result = WdmAudGetMixerDeviceCount();
}
else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
{
- Result = DeviceExtension->WaveOutDeviceCount;
+ Result = WdmAudGetWaveInDeviceCount();
}
else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
{
- Result = DeviceExtension->WaveInDeviceCount;
+ Result = WdmAudGetWaveOutDeviceCount();
+ }
+ else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE)
+ {
+ Result = WdmAudGetMidiInDeviceCount();
}
+ else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE)
+ {
+ Result = WdmAudGetMidiOutDeviceCount();
+ }
+
/* store result count */
DeviceInfo->DeviceCount = Result;
ULONG BytesReturned;
PFILE_OBJECT FileObject;
- //DPRINT1("WdmAudControlDeviceState\n");
+ DPRINT("WdmAudControlDeviceState\n");
Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status))
ObDereferenceObject(FileObject);
- //DPRINT1("WdmAudControlDeviceState Status %x\n", Status);
+ DPRINT("WdmAudControlDeviceState Status %x\n", Status);
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
}
{
Status = WdmAudWaveCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
}
+ else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE)
+ {
+ Status = WdmAudMidiCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
+ }
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
}
SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
return STATUS_SUCCESS;
}
+ else if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE)
+ {
+ if (ClientInfo->hPins[Index].NotifyEvent)
+ {
+ ObDereferenceObject(ClientInfo->hPins[Index].NotifyEvent);
+ ClientInfo->hPins[Index].NotifyEvent = NULL;
+ }
+ }
}
SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT1("Invalid buffer handle %x\n", DeviceInfo->hDevice);
+ DPRINT1("Invalid buffer handle %p\n", DeviceInfo->hDevice);
return SetIrpIoStatus(Irp, Status, 0);
}
}
+NTSTATUS
+NTAPI
+WdmAudGetDeviceInterface(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PWDMAUD_DEVICE_INFO DeviceInfo)
+{
+ PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+ LPWSTR Device;
+ ULONG Size, Length;
+
+ /* get device extension */
+ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ /* get device interface string input length */
+ Size = DeviceInfo->u.Interface.DeviceInterfaceStringSize;
+
+ /* get mixer info */
+ Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device);
+
+ /* check for success */
+ if (!NT_SUCCESS(Status))
+ {
+ /* invalid device id */
+ return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
+ }
+
+ /* calculate length */
+ Length = (wcslen(Device)+1) * sizeof(WCHAR);
+
+ if (!Size)
+ {
+ /* store device interface size */
+ DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
+ }
+ else if (Size < Length)
+ {
+ /* buffer too small */
+ DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
+ return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, sizeof(WDMAUD_DEVICE_INFO));
+ }
+ else
+ {
+ //FIXME SEH
+ RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length);
+ }
+
+ FreeItem(Device);
+ return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
+}
+
+NTSTATUS
+NTAPI
+WdmAudResetStream(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PWDMAUD_DEVICE_INFO DeviceInfo)
+{
+ KSRESET ResetStream;
+ NTSTATUS Status;
+ ULONG BytesReturned;
+ PFILE_OBJECT FileObject;
+
+ DPRINT("WdmAudResetStream\n");
+
+ Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType);
+ return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
+ }
+
+ ResetStream = DeviceInfo->u.ResetStream;
+ ASSERT(ResetStream == KSRESET_BEGIN || ResetStream == KSRESET_END);
+
+ Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_RESET_STATE, (PVOID)&ResetStream, sizeof(KSRESET), NULL, 0, &BytesReturned);
+
+ ObDereferenceObject(FileObject);
+
+ DPRINT("WdmAudResetStream Status %x\n", Status);
+ return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
+}
NTSTATUS
NTAPI
return WdmAudSetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
case IOCTL_GETCONTROLDETAILS:
return WdmAudGetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
-
+ case IOCTL_QUERYDEVICEINTERFACESTRING:
+ return WdmAudGetDeviceInterface(DeviceObject, Irp, DeviceInfo);
+ case IOCTL_GET_MIXER_EVENT:
+ return WdmAudGetMixerEvent(DeviceObject, Irp, DeviceInfo, ClientInfo);
+ case IOCTL_RESET_STREAM:
+ return WdmAudResetStream(DeviceObject, Irp, DeviceInfo);
case IOCTL_GETPOS:
case IOCTL_GETDEVID:
case IOCTL_GETVOLUME:
NTSTATUS
NTAPI
-WdmAudWriteCompletion(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP LowerIrp,
- IN PVOID Context)
+IoCompletion (
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Ctx)
{
- //PIRP Irp;
- ASSERT(LowerIrp->PendingReturned == FALSE);
- /* get original irp */
- //Irp = (PIRP)Context;
-
- /* save status */
- //Irp->IoStatus.Status = LowerIrp->IoStatus.Status;
- //Irp->IoStatus.Information = LowerIrp->IoStatus.Information;
- /* complete request */
- //IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
- /* return success to free irp */
+ PKSSTREAM_HEADER Header;
+ ULONG Length = 0;
+ PMDL Mdl, NextMdl;
+ PWDMAUD_COMPLETION_CONTEXT Context = (PWDMAUD_COMPLETION_CONTEXT)Ctx;
+
+ /* get stream header */
+ Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
+
+ /* sanity check */
+ ASSERT(Header);
+
+ /* time to free all allocated mdls */
+ Mdl = Irp->MdlAddress;
+
+ while(Mdl)
+ {
+ /* get next mdl */
+ NextMdl = Mdl->Next;
+
+ /* unlock pages */
+ MmUnlockPages(Mdl);
+
+ /* grab next mdl */
+ Mdl = NextMdl;
+ }
+
+ /* clear mdl list */
+ Irp->MdlAddress = NULL;
+
+ /* check if mdl is locked */
+ if (Context->Mdl->MdlFlags & MDL_PAGES_LOCKED)
+ {
+ /* unlock pages */
+ MmUnlockPages(Context->Mdl);
+ }
+
+ /* now free the mdl */
+ IoFreeMdl(Context->Mdl);
+
+ DPRINT("IoCompletion Irp %p IoStatus %lx Information %lx Length %lu\n", Irp, Irp->IoStatus.Status, Irp->IoStatus.Information, Length);
+
+ if (!NT_SUCCESS(Irp->IoStatus.Status))
+ {
+ /* failed */
+ Irp->IoStatus.Information = 0;
+ }
+
+ /* free context */
+ FreeItem(Context);
+
return STATUS_SUCCESS;
}
-
NTSTATUS
NTAPI
-WdmAudWrite(
+WdmAudReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- PIO_STACK_LOCATION IoStack;
+ NTSTATUS Status;
PWDMAUD_DEVICE_INFO DeviceInfo;
- PWDMAUD_CLIENT ClientInfo;
- NTSTATUS Status = STATUS_SUCCESS;
- PUCHAR Buffer;
PFILE_OBJECT FileObject;
+ PIO_STACK_LOCATION IoStack;
+ ULONG Length;
PMDL Mdl;
- //PIRP LowerIrp;
- PCONTEXT_WRITE Packet;
- PVOID SystemBuffer;
- //LARGE_INTEGER Offset;
- IO_STATUS_BLOCK IoStatusBlock;
-
- IoStack = IoGetCurrentIrpStackLocation(Irp);
+ BOOLEAN Read = TRUE;
+ PWDMAUD_COMPLETION_CONTEXT Context;
- //DPRINT("WdmAudWrite entered\n");
+ /* allocate completion context */
+ Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT));
- if (IoStack->Parameters.Write.Length < sizeof(WDMAUD_DEVICE_INFO))
+ if (!Context)
{
- /* invalid parameter */
- DPRINT1("Input buffer too small size %u expected %u\n", IoStack->Parameters.Write.Length, sizeof(WDMAUD_DEVICE_INFO));
- return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
- }
-
- DeviceInfo = (PWDMAUD_DEVICE_INFO)MmGetMdlVirtualAddress(Irp->MdlAddress);
+ /* not enough memory */
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Invalid buffer handle %x\n", DeviceInfo->hDevice);
- return SetIrpIoStatus(Irp, Status, 0);
+ /* done */
+ return STATUS_INSUFFICIENT_RESOURCES;
}
+ /* get current irp stack location */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
- //DPRINT("DeviceInfo %p %p %p\n", DeviceInfo, Irp->MdlAddress->StartVa, Irp->MdlAddress->MappedSystemVa);
- if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE)
- {
- /* invalid parameter */
- DPRINT1("Error: device type not set\n");
- ObDereferenceObject(FileObject);
- return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
- }
+ /* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */
+ Irp->UserBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
- if (!IoStack->FileObject)
- {
- /* file object parameter */
- DPRINT1("Error: file object is not attached\n");
- ObDereferenceObject(FileObject);
- return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
- }
- ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
+ /* sanity check */
+ ASSERT(Irp->UserBuffer);
+ /* get the length of the request length */
+ Length = IoStack->Parameters.Write.Length;
- /* setup stream context */
- Packet = (PCONTEXT_WRITE)ExAllocatePool(NonPagedPool, sizeof(CONTEXT_WRITE));
- if (!Packet)
- {
- /* no memory */
- return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
- }
+ /* store outputbuffer length */
+ IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length;
- Packet->Header.FrameExtent = DeviceInfo->Header.FrameExtent;
- Packet->Header.DataUsed = DeviceInfo->Header.DataUsed;
- Packet->Header.Size = sizeof(KSSTREAM_HEADER);
- Packet->Header.PresentationTime.Numerator = 1;
- Packet->Header.PresentationTime.Denominator = 1;
- Packet->Irp = Irp;
+ /* setup context */
+ Context->Length = Length;
+ Context->Function = (IoStack->MajorFunction == IRP_MJ_WRITE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM);
+ Context->Mdl = Irp->MdlAddress;
- Buffer = ExAllocatePool(NonPagedPool, DeviceInfo->Header.DataUsed);
- if (!Buffer)
- {
- /* no memory */
- ExFreePool(Packet);
- ObDereferenceObject(FileObject);
- return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
- }
- Packet->Header.Data = Buffer;
+ /* store mdl address */
+ Mdl = Irp->MdlAddress;
- Mdl = IoAllocateMdl(DeviceInfo->Header.Data, DeviceInfo->Header.DataUsed, FALSE, FALSE, FALSE);
- if (!Mdl)
- {
- /* no memory */
- ExFreePool(Packet);
- ObDereferenceObject(FileObject);
- ExFreePool(Buffer);
- return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
- }
+ /* remove mdladdress as KsProbeStreamIrp will interprete it as an already probed audio buffer */
+ Irp->MdlAddress = NULL;
- _SEH2_TRY
+ /* check for success */
+
+ if (IoStack->MajorFunction == IRP_MJ_WRITE)
{
- MmProbeAndLockPages(Mdl, UserMode, IoReadAccess);
+ /* probe the write stream irp */
+ Read = FALSE;
+ Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ else
{
- /* Exception, get the error code */
- Status = _SEH2_GetExceptionCode();
+ /* probe the read stream irp */
+ Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMREAD | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
}
- _SEH2_END;
if (!NT_SUCCESS(Status))
{
- DPRINT1("Invalid buffer supplied\n");
- ExFreePool(Buffer);
- ExFreePool(Packet);
- IoFreeMdl(Mdl);
- ObDereferenceObject(FileObject);
+ DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status, Irp->Cancel);
+ Irp->MdlAddress = Mdl;
return SetIrpIoStatus(Irp, Status, 0);
}
- SystemBuffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority );
- if (!SystemBuffer)
+ /* get device info */
+ DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
+ ASSERT(DeviceInfo);
+
+ /* now get sysaudio file object */
+ Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+ if (!NT_SUCCESS(Status))
{
- DPRINT1("Invalid buffer supplied\n");
- ExFreePool(Buffer);
- ExFreePool(Packet);
- IoFreeMdl(Mdl);
- ObDereferenceObject(FileObject);
- return SetIrpIoStatus(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
+ DPRINT1("Invalid pin handle %p\n", DeviceInfo->hDevice);
+ return SetIrpIoStatus(Irp, Status, 0);
}
- RtlMoveMemory(Buffer, SystemBuffer, DeviceInfo->Header.DataUsed);
- MmUnlockPages(Mdl);
- IoFreeMdl(Mdl);
-
-#if 1
- KsStreamIo(FileObject, NULL, NULL, NULL, NULL, 0, &IoStatusBlock, Packet, sizeof(CONTEXT_WRITE), KSSTREAM_WRITE, UserMode);
- /* dereference file object */
- ObDereferenceObject(FileObject);
- return IoStatusBlock.Status;
-#else
- Offset.QuadPart = 0L;
+ /* skip current irp stack location */
+ IoSkipCurrentIrpStackLocation(Irp);
- /* now build the irp */
- LowerIrp = IoBuildAsynchronousFsdRequest (IRP_MJ_WRITE,
- IoGetRelatedDeviceObject(FileObject),
- Packet,
- sizeof(KSSTREAM_HEADER),
- &Offset,
- NULL);
+ /* get next stack location */
+ IoStack = IoGetNextIrpStackLocation(Irp);
- if (!LowerIrp)
+ if (Read)
{
- /* failed to create an associated irp */
- ExFreePool(Buffer);
- ExFreePool(Packet);
- ObDereferenceObject(FileObject);
-
- return SetIrpIoStatus(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
+ IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_KS_READ_STREAM;
+ }
+ else
+ {
+ IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_KS_WRITE_STREAM;
}
-
- /* get next stack location */
- IoStack = IoGetNextIrpStackLocation(LowerIrp);
/* attach file object */
IoStack->FileObject = FileObject;
+ IoStack->Parameters.Write.Length = Length;
+ IoStack->MajorFunction = IRP_MJ_WRITE;
+
+ IoSetCompletionRoutine(Irp, IoCompletion, (PVOID)Context, TRUE, TRUE, TRUE);
- /* set a completion routine */
- IoSetCompletionRoutine(LowerIrp, WdmAudWriteCompletion, (PVOID)Irp, TRUE, TRUE, TRUE);
/* mark irp as pending */
- //IoMarkIrpPending(Irp);
- Irp->IoStatus.Information = DeviceInfo->BufferSize;
- Irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- DPRINT1("Wrote %u\n", DeviceInfo->BufferSize);
+// IoMarkIrpPending(Irp);
/* call the driver */
- Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), LowerIrp);
+ Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
/* dereference file object */
ObDereferenceObject(FileObject);
- return STATUS_SUCCESS;
-#endif
+ return Status;
}