NTSTATUS WdmAudControlDeviceState( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { KSPROPERTY Property; KSSTATE State; NTSTATUS Status; ULONG BytesReturned; PFILE_OBJECT FileObject; DPRINT("WdmAudControlDeviceState\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); } Property.Set = KSPROPSETID_Connection; Property.Id = KSPROPERTY_CONNECTION_STATE; Property.Flags = KSPROPERTY_TYPE_SET; State = DeviceInfo->u.State; Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned); ObDereferenceObject(FileObject); DPRINT("WdmAudControlDeviceState Status %x\n", Status); return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); }
NTSTATUS NTAPI WdmAudIoctlClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { ULONG Index; for(Index = 0; Index < ClientInfo->NumPins; Index++) { if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE) { DPRINT1("Closing device %p\n", DeviceInfo->hDevice); ZwClose(DeviceInfo->hDevice); ClientInfo->hPins[Index].Handle = NULL; 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)); return STATUS_INVALID_PARAMETER; }
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 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 WdmAudControlOpen( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { return WdmAudControlOpenMixer(DeviceObject, Irp, DeviceInfo, ClientInfo); } if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { 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)); }
NTSTATUS WdmAudCapabilities( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { PWDMAUD_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status = STATUS_UNSUCCESSFUL; DPRINT("WdmAudCapabilities entered\n"); DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { Status = WdmAudMixerCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); } else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { 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)); }
NTSTATUS NTAPI WdmAudGetMixerEvent( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { PLIST_ENTRY Entry; PEVENT_ENTRY EventEntry; /* enumerate event list and check if there is a new event */ Entry = ClientInfo->MixerEventList.Flink; while(Entry != &ClientInfo->MixerEventList) { /* grab event entry */ EventEntry = (PEVENT_ENTRY)CONTAINING_RECORD(Entry, EVENT_ENTRY, Entry); if (EventEntry->hMixer == DeviceInfo->hDevice) { /* found an entry */ DeviceInfo->u.MixerEvent.hMixer = EventEntry->hMixer; DeviceInfo->u.MixerEvent.NotificationType = EventEntry->NotificationType; DeviceInfo->u.MixerEvent.Value = EventEntry->Value; /* remove entry from list */ RemoveEntryList(&EventEntry->Entry); /* free event entry */ FreeItem(EventEntry); /* done */ return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); } /* move to next */ Entry = Entry->Flink; } /* no event entry available */ return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); }
NTSTATUS NTAPI WdmAudFrameSize( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { PFILE_OBJECT FileObject; KSPROPERTY Property; ULONG BytesReturned; KSALLOCATOR_FRAMING Framing; NTSTATUS Status; /* Get sysaudio pin file object */ Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Invalid buffer handle %p\n", DeviceInfo->hDevice); return SetIrpIoStatus(Irp, Status, 0); } /* Setup get framing request */ Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING; Property.Flags = KSPROPERTY_TYPE_GET; Property.Set = KSPROPSETID_Connection; Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned); /* Did we succeed */ if (NT_SUCCESS(Status)) { /* Store framesize */ DeviceInfo->u.FrameSize = Framing.FrameSize; } /* Release file object */ ObDereferenceObject(FileObject); return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); }
NTSTATUS WdmAudControlOpenMidi( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { MIXER_STATUS Status; PIN_CREATE_CONTEXT Context; Context.ClientInfo = ClientInfo; Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; Context.DeviceType = DeviceInfo->DeviceType; Status = MMixerOpenMidi(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE, CreatePinCallback, &Context, &DeviceInfo->hDevice); if (Status == MM_STATUS_SUCCESS) return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); else return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); }
NTSTATUS NTAPI WdmAudSetControlDetails( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { MIXER_STATUS Status; /* clear hmixer type flag */ DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; /* query mixer library */ Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails); if (Status == MM_STATUS_SUCCESS) return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); else return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); }
NTSTATUS WdmAudControlDeviceType( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { ULONG Result = 0; NTSTATUS Status = STATUS_SUCCESS; PWDMAUD_DEVICE_EXTENSION DeviceExtension; DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { Result = WdmAudGetMixerDeviceCount(); } else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { Result = WdmAudGetWaveInDeviceCount(); } else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { 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; DPRINT("WdmAudControlDeviceType Status %x Devices %u\n", Status, DeviceInfo->DeviceCount); return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); }
NTSTATUS WdmAudControlOpenMixer( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { HANDLE hMixer; PWDMAUD_HANDLE Handles; //PWDMAUD_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status; PKEVENT EventObject = NULL; DPRINT("WdmAudControlOpenMixer\n"); //DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; if (DeviceInfo->u.hNotifyEvent) { Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo); DbgBreakPoint(); return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); } } if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, ClientInfo, EventCallback, &hMixer) != MM_STATUS_SUCCESS) { ObDereferenceObject(EventObject); DPRINT1("Failed to open mixer\n"); return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); } Handles = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); if (Handles) { if (ClientInfo->NumPins) { RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins); FreeItem(ClientInfo->hPins); } ClientInfo->hPins = Handles; ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer; ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE; ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject; ClientInfo->NumPins++; } else { ObDereferenceObject(EventObject); return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); } DeviceInfo->hDevice = hMixer; return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); }
NTSTATUS NTAPI WdmAudReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS Status; PWDMAUD_DEVICE_INFO DeviceInfo; PFILE_OBJECT FileObject; PIO_STACK_LOCATION IoStack; 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 the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */ Irp->UserBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); /* sanity check */ ASSERT(Irp->UserBuffer); /* get the length of the request length */ Length = IoStack->Parameters.Write.Length; /* 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; /* remove mdladdress as KsProbeStreamIrp will interprete it as an already probed audio buffer */ Irp->MdlAddress = NULL; if (IoStack->MajorFunction == IRP_MJ_WRITE) { /* probe the write stream irp */ Read = FALSE; Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length); } else { /* probe the read stream irp */ Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMREAD | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length); } if (!NT_SUCCESS(Status)) { DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status, Irp->Cancel); Irp->MdlAddress = Mdl; FreeItem(Context); return SetIrpIoStatus(Irp, Status, 0); } /* 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 pin handle %p\n", DeviceInfo->hDevice); Irp->MdlAddress = Mdl; FreeItem(Context); return SetIrpIoStatus(Irp, Status, 0); } /* store file object whose reference is released in the completion callback */ Context->FileObject = FileObject; /* skip current irp stack location */ IoSkipCurrentIrpStackLocation(Irp); /* get next stack location */ IoStack = IoGetNextIrpStackLocation(Irp); /* prepare stack location */ IoStack->FileObject = FileObject; IoStack->Parameters.Write.Length = Length; IoStack->MajorFunction = IRP_MJ_WRITE; IoStack->Parameters.DeviceIoControl.IoControlCode = (Read ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM); IoSetCompletionRoutine(Irp, IoCompletion, (PVOID)Context, TRUE, TRUE, TRUE); /* mark irp as pending */ // IoMarkIrpPending(Irp); /* call the driver */ Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); return Status; }
NTSTATUS NTAPI WdmAudDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IoStack; PWDMAUD_DEVICE_INFO DeviceInfo; PWDMAUD_CLIENT ClientInfo; IoStack = IoGetCurrentIrpStackLocation(Irp); DPRINT("WdmAudDeviceControl entered\n"); if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO)) { /* invalid parameter */ DPRINT1("Input buffer too small size %u expected %u\n", IoStack->Parameters.DeviceIoControl.InputBufferLength, sizeof(WDMAUD_DEVICE_INFO)); return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); } DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE) { /* invalid parameter */ DPRINT1("Error: device type not set\n"); return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); } if (!IoStack->FileObject || !IoStack->FileObject->FsContext) { /* file object parameter */ DPRINT1("Error: file object is not attached\n"); return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); } ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext; DPRINT("WdmAudDeviceControl entered\n"); switch(IoStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_OPEN_WDMAUD: return WdmAudControlOpen(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_GETNUMDEVS_TYPE: return WdmAudControlDeviceType(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_SETDEVICE_STATE: return WdmAudControlDeviceState(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_GETCAPABILITIES: return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_CLOSE_WDMAUD: return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_GETFRAMESIZE: return WdmAudFrameSize(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_GETLINEINFO: return WdmAudGetLineInfo(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_GETLINECONTROLS: return WdmAudGetLineControls(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_SETCONTROLDETAILS: 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: case IOCTL_SETVOLUME: DPRINT1("Unhandeled %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); break; } return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0); }