Merge r51067
[reactos.git] / reactos / drivers / wdm / audio / legacy / wdmaud / control.c
index ecf3645..3343405 100644 (file)
@@ -8,17 +8,7 @@
  */
 #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(
@@ -37,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));
 }
 
@@ -48,23 +44,32 @@ WdmAudControlDeviceType(
     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;
@@ -86,7 +91,7 @@ WdmAudControlDeviceState(
     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))
@@ -105,7 +110,7 @@ WdmAudControlDeviceState(
 
     ObDereferenceObject(FileObject);
 
-    //DPRINT1("WdmAudControlDeviceState Status %x\n", Status);
+    DPRINT("WdmAudControlDeviceState Status %x\n", Status);
     return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
 }
 
@@ -131,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));
 }
@@ -155,6 +164,14 @@ WdmAudIoctlClose(
             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));
@@ -179,7 +196,7 @@ WdmAudFrameSize(
     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);
     }
 
@@ -203,6 +220,89 @@ WdmAudFrameSize(
 
 }
 
+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
@@ -266,7 +366,12 @@ WdmAudDeviceControl(
             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:
@@ -281,204 +386,181 @@ WdmAudDeviceControl(
 
 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;
 }