Merge r51067
[reactos.git] / reactos / drivers / wdm / audio / legacy / wdmaud / control.c
index 4fc1d67..3343405 100644 (file)
@@ -27,6 +27,12 @@ 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));
 }
 
@@ -55,6 +61,15 @@ WdmAudControlDeviceType(
     {
         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;
@@ -121,6 +136,10 @@ WdmAudCapabilities(
     {
         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));
 }
@@ -219,80 +238,38 @@ WdmAudGetDeviceInterface(
     /* 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);
-
-        /* check for success */
-        if (!NT_SUCCESS(Status))
-        {
-            /* invalid device id */
-            return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
-        }
+   /* get mixer info */
+   Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device);
 
-        /* calculate length */
-        Length = (wcslen(Device)+1) * sizeof(WCHAR);
+   /* check for success */
+   if (!NT_SUCCESS(Status))
+   {
+        /* invalid device id */
+        return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
+   }
 
-        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);
-        }
+   /* calculate length */
+   Length = (wcslen(Device)+1) * sizeof(WCHAR);
 
-        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
@@ -407,6 +384,65 @@ WdmAudDeviceControl(
     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);
+
+    /* 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
@@ -421,6 +457,20 @@ WdmAudReadWrite(
     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);
@@ -437,6 +487,11 @@ WdmAudReadWrite(
     /* 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;
 
@@ -464,9 +519,6 @@ WdmAudReadWrite(
         return SetIrpIoStatus(Irp, Status, 0);
     }
 
-    /* now free the mdl */
-    IoFreeMdl(Mdl);
-
     /* get device info */
     DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
     ASSERT(DeviceInfo);
@@ -499,6 +551,9 @@ WdmAudReadWrite(
     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 */