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));
}
{
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;
{
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));
}
/* get device interface string input length */
Size = DeviceInfo->u.Interface.DeviceInterfaceStringSize;
- if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
- {
- /* get wave info */
- Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device);
+ /* 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));
- }
+ /* 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);
+ /* 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);
- }
-
- ExFreePool(Device);
- return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
+ if (!Size)
+ {
+ /* store device interface size */
+ DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
}
- else if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
+ else if (Size < Length)
{
- if (DeviceInfo->DeviceIndex >= WdmAudGetMixerDeviceCount())
- {
- /* invalid device id */
- return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
- }
-
- Status = WdmAudGetMixerPnpNameByIndex(DeviceInfo->DeviceIndex, &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);
- }
- return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
+ /* 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);
}
- return SetIrpIoStatus(Irp, STATUS_INVALID_DEVICE_REQUEST, sizeof(WDMAUD_DEVICE_INFO));
+ FreeItem(Device);
+ return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
}
NTSTATUS
return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
}
+NTSTATUS
+NTAPI
+IoCompletion (
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Ctx)
+{
+ 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);
+
+ /* iterate through all stream headers and collect size */
+ do
+ {
+ if (Context->Function == IOCTL_KS_READ_STREAM)
+ {
+ /* length is stored in DataUsed */
+ Length += Header->DataUsed;
+ }
+ else
+ {
+ /* length stored in frameextend */
+ Length += Header->FrameExtent;
+ }
+
+ /* subtract size */
+ Context->Length -= Header->Size;
+
+ /* move to next stream header */
+ Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size);
+
+ }while(Context->Length);
+
+ /* 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 (Irp->IoStatus.Status == STATUS_SUCCESS)
+ {
+ /* store the length */
+ Irp->IoStatus.Information = Length;
+ }
+ else
+ {
+ /* failed */
+ Irp->IoStatus.Information = 0;
+ }
+
+ /* free context */
+ FreeItem(Context);
+
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
NTAPI
ULONG Length;
PMDL Mdl;
BOOLEAN Read = TRUE;
+ PWDMAUD_COMPLETION_CONTEXT Context;
+
+ /* allocate completion context */
+ Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT));
+
+ if (!Context)
+ {
+ /* not enough memory */
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ /* done */
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
/* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* store outputbuffer length */
IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length;
+ /* setup context */
+ Context->Length = Length;
+ Context->Function = (IoStack->MajorFunction == IRP_MJ_WRITE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM);
+ Context->Mdl = Irp->MdlAddress;
+
/* store mdl address */
Mdl = Irp->MdlAddress;
Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMREAD | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
}
- /* now free the mdl */
- IoFreeMdl(Mdl);
-
if (!NT_SUCCESS(Status))
{
DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status, Irp->Cancel);
+ Irp->MdlAddress = Mdl;
return SetIrpIoStatus(Irp, Status, 0);
}
IoStack->Parameters.Write.Length = Length;
IoStack->MajorFunction = IRP_MJ_WRITE;
+ IoSetCompletionRoutine(Irp, IoCompletion, (PVOID)Context, TRUE, TRUE, TRUE);
+
+
/* mark irp as pending */
// IoMarkIrpPending(Irp);
/* call the driver */