mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:42:57 +00:00
- Fix a bug in KsAllocateDeviceHeader which copied the create item to the wrong offset
- Set Created status to true when create function is not zero - Partly implement KsStreamIo - Implement IOCTL for opening / setting state and writing wave data - Clear KSAUDIO_DEVICE_ENTRY - Open the pin in a worker context as IoCreateFile must be called at APC_LEVEL < - Add dispatcher object to sysaudio will dispatch the device requests to the real pin - Add a test application to play a wav sound - ReactOS can now play a wave tone svn path=/trunk/; revision=39702
This commit is contained in:
parent
b997856046
commit
b94b97a10e
16 changed files with 1016 additions and 39 deletions
|
@ -188,7 +188,11 @@ KsAllocateDeviceHeader(
|
||||||
for(Index = 0; Index < ItemsCount; Index++)
|
for(Index = 0; Index < ItemsCount; Index++)
|
||||||
{
|
{
|
||||||
/* copy provided create items */
|
/* copy provided create items */
|
||||||
RtlMoveMemory(&Header->ItemList[Index], &ItemsList[Index], sizeof(KSOBJECT_CREATE_ITEM));
|
RtlMoveMemory(&Header->ItemList[Index].CreateItem, &ItemsList[Index], sizeof(KSOBJECT_CREATE_ITEM));
|
||||||
|
if (ItemsList[Index].Create!= NULL)
|
||||||
|
{
|
||||||
|
Header->ItemList[Index].bCreated = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Header->MaxItems = ItemsCount;
|
Header->MaxItems = ItemsCount;
|
||||||
}
|
}
|
||||||
|
@ -716,7 +720,7 @@ KsCreate(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp)
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
//PIO_STACK_LOCATION IoStack;
|
||||||
PDEVICE_EXTENSION DeviceExtension;
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
PKSIDEVICE_HEADER DeviceHeader;
|
PKSIDEVICE_HEADER DeviceHeader;
|
||||||
ULONG Index;
|
ULONG Index;
|
||||||
|
@ -725,7 +729,7 @@ KsCreate(
|
||||||
|
|
||||||
DPRINT1("KS / CREATE\n");
|
DPRINT1("KS / CREATE\n");
|
||||||
/* get current stack location */
|
/* get current stack location */
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
//IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
/* get device extension */
|
/* get device extension */
|
||||||
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
/* get device header */
|
/* get device header */
|
||||||
|
@ -856,7 +860,7 @@ KsWrite(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINT1("Expected Object Header\n");
|
DPRINT1("Expected Object Header %p\n", IoStack->FileObject);
|
||||||
KeBugCheckEx(0, 0, 0, 0, 0);
|
KeBugCheckEx(0, 0, 0, 0, 0);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1049,9 +1053,11 @@ KsDispatchIrp(
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@unimplemented
|
@implemented
|
||||||
*/
|
*/
|
||||||
KSDDKAPI NTSTATUS NTAPI
|
KSDDKAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
KsStreamIo(
|
KsStreamIo(
|
||||||
IN PFILE_OBJECT FileObject,
|
IN PFILE_OBJECT FileObject,
|
||||||
IN PKEVENT Event OPTIONAL,
|
IN PKEVENT Event OPTIONAL,
|
||||||
|
@ -1065,8 +1071,52 @@ KsStreamIo(
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
IN KPROCESSOR_MODE RequestorMode)
|
IN KPROCESSOR_MODE RequestorMode)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
PIRP Irp;
|
||||||
return STATUS_UNSUCCESSFUL;
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
ULONG Code;
|
||||||
|
NTSTATUS Status;
|
||||||
|
LARGE_INTEGER Offset;
|
||||||
|
|
||||||
|
if (Flags == KSSTREAM_READ)
|
||||||
|
Code = IRP_MJ_READ;
|
||||||
|
else if (Flags == KSSTREAM_WRITE)
|
||||||
|
Code = IRP_MJ_WRITE;
|
||||||
|
else
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||||
|
if (!DeviceObject)
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (Event)
|
||||||
|
{
|
||||||
|
KeResetEvent(Event);
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset.QuadPart = 0LL;
|
||||||
|
Irp = IoBuildSynchronousFsdRequest(Code, DeviceObject, (PVOID)StreamHeaders, Length, &Offset, Event, IoStatusBlock);
|
||||||
|
if (!Irp)
|
||||||
|
{
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (CompletionRoutine)
|
||||||
|
{
|
||||||
|
IoSetCompletionRoutine(Irp,
|
||||||
|
CompletionRoutine,
|
||||||
|
CompletionContext,
|
||||||
|
(CompletionInvocationFlags & KsInvokeOnSuccess),
|
||||||
|
(CompletionInvocationFlags & KsInvokeOnError),
|
||||||
|
(CompletionInvocationFlags & KsInvokeOnCancel));
|
||||||
|
}
|
||||||
|
|
||||||
|
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||||
|
IoStack->FileObject = FileObject;
|
||||||
|
|
||||||
|
Status = IoCallDriver(DeviceObject, Irp);
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
152
reactos/drivers/wdm/audio/backpln/audio_test/audio_test.c
Normal file
152
reactos/drivers/wdm/audio/backpln/audio_test/audio_test.c
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
#define _UNICODE
|
||||||
|
#define UNICODE
|
||||||
|
#include <windows.h>
|
||||||
|
#include <mmsystem.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define _2pi 6.283185307179586476925286766559
|
||||||
|
|
||||||
|
#include <ks.h>
|
||||||
|
#include <ksmedia.h>
|
||||||
|
#include "interface.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
__cdecl
|
||||||
|
main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
ULONG Length;
|
||||||
|
PSHORT SoundBuffer;
|
||||||
|
ULONG i = 0;
|
||||||
|
BOOL Status;
|
||||||
|
OVERLAPPED Overlapped;
|
||||||
|
DWORD BytesReturned;
|
||||||
|
HANDLE hWdmAud;
|
||||||
|
WDMAUD_DEVICE_INFO DeviceInfo;
|
||||||
|
|
||||||
|
|
||||||
|
hWdmAud = CreateFileW(L"\\\\.\\wdmaud",
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_FLAG_OVERLAPPED,
|
||||||
|
NULL);
|
||||||
|
if (!hWdmAud)
|
||||||
|
{
|
||||||
|
printf("Failed to open wdmaud with %lx\n", GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("WDMAUD: opened\n");
|
||||||
|
/* clear device info */
|
||||||
|
RtlZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
|
||||||
|
|
||||||
|
ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
|
||||||
|
Overlapped.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
|
|
||||||
|
DeviceInfo.DeviceType = WAVE_OUT_DEVICE_TYPE;
|
||||||
|
|
||||||
|
Status = DeviceIoControl(hWdmAud, IOCTL_GETNUMDEVS_TYPE, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
|
||||||
|
|
||||||
|
if (!Status)
|
||||||
|
{
|
||||||
|
if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
printf("Failed to get num of wave out devices with %lx\n", GetLastError());
|
||||||
|
CloseHandle(hWdmAud);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("WDMAUD: Num Devices %lu\n", DeviceInfo.DeviceCount);
|
||||||
|
if (!DeviceInfo.DeviceCount)
|
||||||
|
{
|
||||||
|
CloseHandle(hWdmAud);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceInfo.u.WaveFormatEx.cbSize = sizeof(WAVEFORMATEX);
|
||||||
|
DeviceInfo.u.WaveFormatEx.wFormatTag = 0x1; //WAVE_FORMAT_PCM;
|
||||||
|
DeviceInfo.u.WaveFormatEx.nChannels = 2;
|
||||||
|
DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 48000;
|
||||||
|
DeviceInfo.u.WaveFormatEx.nBlockAlign = 4;
|
||||||
|
DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 48000 * 4;
|
||||||
|
DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Status = DeviceIoControl(hWdmAud, IOCTL_OPEN_WDMAUD, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
|
||||||
|
if (!Status)
|
||||||
|
{
|
||||||
|
if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
printf("Failed to open device with %lx\n", GetLastError());
|
||||||
|
CloseHandle(hWdmAud);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate a buffer for 1 second
|
||||||
|
//
|
||||||
|
Length = 48000 * 4;
|
||||||
|
SoundBuffer = (PSHORT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Fill the buffer with a 500 Hz sine tone
|
||||||
|
//
|
||||||
|
while (i < Length / 2)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Generate the wave for each channel:
|
||||||
|
// Amplitude * sin( Sample * Frequency * 2PI / SamplesPerSecond )
|
||||||
|
//
|
||||||
|
SoundBuffer[i] = 0x7FFF * sin(0.5 * (i - 1) * 500 * _2pi / 48000);
|
||||||
|
i++;
|
||||||
|
SoundBuffer[i] = 0x7FFF * sin((0.5 * i - 2) * 500 * _2pi / 48000);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceInfo.State = KSSTATE_RUN;
|
||||||
|
Status = DeviceIoControl(hWdmAud, IOCTL_SETDEVICE_STATE, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
|
||||||
|
if (!Status)
|
||||||
|
{
|
||||||
|
if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
printf("Failed to set device into run state %lx\n", GetLastError());
|
||||||
|
CloseHandle(hWdmAud);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Play our 1-second buffer
|
||||||
|
//
|
||||||
|
DeviceInfo.Buffer = (PUCHAR)SoundBuffer;
|
||||||
|
DeviceInfo.BufferSize = Length;
|
||||||
|
Status = DeviceIoControl(hWdmAud, IOCTL_WRITEDATA, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
|
||||||
|
if (!Status)
|
||||||
|
{
|
||||||
|
if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
printf("Failed to play buffer %lx\n", GetLastError());
|
||||||
|
CloseHandle(hWdmAud);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceInfo.State = KSSTATE_STOP;
|
||||||
|
Status = DeviceIoControl(hWdmAud, IOCTL_SETDEVICE_STATE, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
|
||||||
|
if (!Status)
|
||||||
|
{
|
||||||
|
if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
printf("Failed to set device into stop state %lx\n", GetLastError());
|
||||||
|
CloseHandle(hWdmAud);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle(hWdmAud);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE module SYSTEM "../../../../../tools/rbuild/project.dtd">
|
||||||
|
<module name="audio_test" type="win32cui" installbase="system32" installname="audio_test.exe">
|
||||||
|
<define name="PC_NO_IMPORTS" />
|
||||||
|
<include base="ReactOS">include/reactos/libs/sound</include>
|
||||||
|
<include base="wdmaud_kernel">.</include>
|
||||||
|
<library>kernel32</library>
|
||||||
|
|
||||||
|
<file>audio_test.c</file>
|
||||||
|
|
||||||
|
</module>
|
|
@ -1,6 +1,9 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE group SYSTEM "../../../../tools/rbuild/project.dtd">
|
<!DOCTYPE group SYSTEM "../../../../tools/rbuild/project.dtd">
|
||||||
<group xmlns:xi="http://www.w3.org/2001/XInclude">
|
<group xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||||
|
<directory name="audio_test">
|
||||||
|
<xi:include href="audio_test/audio_test.rbuild" />
|
||||||
|
</directory>
|
||||||
<directory name="portcls">
|
<directory name="portcls">
|
||||||
<xi:include href="portcls/portcls.rbuild" />
|
<xi:include href="portcls/portcls.rbuild" />
|
||||||
</directory>
|
</directory>
|
||||||
|
|
|
@ -350,7 +350,7 @@ IPortPinWaveCyclic_HandleKsProperty(
|
||||||
{
|
{
|
||||||
PKSPROPERTY Property;
|
PKSPROPERTY Property;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
UNICODE_STRING GuidString, GuidString2;
|
UNICODE_STRING GuidString;
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
|
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
|
||||||
|
|
||||||
|
@ -413,6 +413,7 @@ IPortPinWaveCyclic_HandleKsProperty(
|
||||||
This->State = *State;
|
This->State = *State;
|
||||||
Irp->IoStatus.Information = sizeof(KSSTATE);
|
Irp->IoStatus.Information = sizeof(KSSTATE);
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
|
@ -484,11 +485,9 @@ IPortPinWaveCyclic_HandleKsProperty(
|
||||||
|
|
||||||
}
|
}
|
||||||
RtlStringFromGUID(&Property->Set, &GuidString);
|
RtlStringFromGUID(&Property->Set, &GuidString);
|
||||||
RtlStringFromGUID(&KSPROPSETID_Connection, &GuidString2);
|
DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
|
||||||
DPRINT1("Unhandeled property Set |%S| |%S|Id %u Flags %x\n", GuidString.Buffer, GuidString2.Buffer, Property->Id, Property->Flags);
|
|
||||||
DbgBreakPoint();
|
DbgBreakPoint();
|
||||||
RtlFreeUnicodeString(&GuidString);
|
RtlFreeUnicodeString(&GuidString);
|
||||||
RtlFreeUnicodeString(&GuidString2);
|
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
|
@ -8,6 +8,322 @@
|
||||||
*/
|
*/
|
||||||
#include "wdmaud.h"
|
#include "wdmaud.h"
|
||||||
|
|
||||||
|
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}};
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
SetIrpIoStatus(
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN NTSTATUS Status,
|
||||||
|
IN ULONG Length)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = Length;
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
WdmAudControlOpen(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
||||||
|
IN PWDMAUD_CLIENT ClientInfo)
|
||||||
|
{
|
||||||
|
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ACCESS_MASK DesiredAccess = 0;
|
||||||
|
HANDLE PinHandle;
|
||||||
|
KSPIN_CONNECT * PinConnect;
|
||||||
|
KSDATAFORMAT_WAVEFORMATEX * DataFormat;
|
||||||
|
|
||||||
|
if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE)
|
||||||
|
{
|
||||||
|
DPRINT1("FIXME: only waveout devices are supported\n");
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
InstanceInfo = ExAllocatePool(NonPagedPool, sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(KSPIN_CONNECT));
|
||||||
|
if (!InstanceInfo)
|
||||||
|
{
|
||||||
|
/* no memory */
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
InstanceInfo->Property.Set = KSPROPSETID_Sysaudio;
|
||||||
|
InstanceInfo->Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO;
|
||||||
|
InstanceInfo->Property.Flags = KSPROPERTY_TYPE_SET;
|
||||||
|
InstanceInfo->Flags = 0;
|
||||||
|
InstanceInfo->DeviceNumber = DeviceInfo->DeviceIndex;
|
||||||
|
|
||||||
|
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* failed to acquire audio device */
|
||||||
|
DPRINT1("KsSynchronousIoControlDevice failed with %x\n", Status);
|
||||||
|
ExFreePool(InstanceInfo);
|
||||||
|
return SetIrpIoStatus(Irp, Status, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE ||
|
||||||
|
DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE ||
|
||||||
|
DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
||||||
|
{
|
||||||
|
DesiredAccess |= GENERIC_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ||
|
||||||
|
DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE ||
|
||||||
|
DeviceInfo->DeviceType == AUX_DEVICE_TYPE ||
|
||||||
|
DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
||||||
|
{
|
||||||
|
DesiredAccess |= GENERIC_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PinConnect = (KSPIN_CONNECT*)InstanceInfo;
|
||||||
|
|
||||||
|
|
||||||
|
PinConnect->Interface.Set = KSINTERFACESETID_Standard;
|
||||||
|
PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
|
||||||
|
PinConnect->Interface.Flags = 0;
|
||||||
|
PinConnect->Medium.Set = KSMEDIUMSETID_Standard;
|
||||||
|
PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
|
||||||
|
PinConnect->Medium.Flags = 0;
|
||||||
|
PinConnect->PinId = 0; //FIXME
|
||||||
|
PinConnect->PinToHandle = NULL;
|
||||||
|
PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
|
||||||
|
PinConnect->Priority.PrioritySubClass = 1;
|
||||||
|
|
||||||
|
|
||||||
|
DataFormat = (KSDATAFORMAT_WAVEFORMATEX*) (PinConnect + 1);
|
||||||
|
DataFormat->WaveFormatEx.wFormatTag = DeviceInfo->u.WaveFormatEx.wFormatTag;
|
||||||
|
DataFormat->WaveFormatEx.nChannels = DeviceInfo->u.WaveFormatEx.nChannels;
|
||||||
|
DataFormat->WaveFormatEx.nSamplesPerSec = DeviceInfo->u.WaveFormatEx.nSamplesPerSec;
|
||||||
|
DataFormat->WaveFormatEx.nBlockAlign = DeviceInfo->u.WaveFormatEx.nBlockAlign;
|
||||||
|
DataFormat->WaveFormatEx.nAvgBytesPerSec = DeviceInfo->u.WaveFormatEx.nAvgBytesPerSec;
|
||||||
|
DataFormat->WaveFormatEx.wBitsPerSample = DeviceInfo->u.WaveFormatEx.wBitsPerSample;
|
||||||
|
DataFormat->WaveFormatEx.cbSize = 0;
|
||||||
|
DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
|
||||||
|
DataFormat->DataFormat.Flags = 0;
|
||||||
|
DataFormat->DataFormat.Reserved = 0;
|
||||||
|
DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
|
||||||
|
|
||||||
|
if (DeviceInfo->u.WaveFormatEx.wFormatTag != WAVE_FORMAT_PCM)
|
||||||
|
DPRINT1("FIXME\n");
|
||||||
|
|
||||||
|
DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||||
|
DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
|
||||||
|
DataFormat->DataFormat.SampleSize = 4;
|
||||||
|
|
||||||
|
|
||||||
|
Status = KsCreatePin(ClientInfo->hSysAudio, PinConnect, DesiredAccess, &PinHandle);
|
||||||
|
DPRINT1("KsCreatePin Status %x\n", Status);
|
||||||
|
|
||||||
|
|
||||||
|
/* free buffer */
|
||||||
|
ExFreePool(InstanceInfo);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DeviceInfo->hDevice = PinHandle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeviceInfo->hDevice = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
WdmAudControlDeviceType(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
||||||
|
IN PWDMAUD_CLIENT ClientInfo)
|
||||||
|
{
|
||||||
|
KSPROPERTY Property;
|
||||||
|
ULONG Result, BytesReturned;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE)
|
||||||
|
{
|
||||||
|
DPRINT1("FIXME: only waveout devices are supported\n");
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Property.Set = KSPROPSETID_Sysaudio;
|
||||||
|
Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT;
|
||||||
|
Property.Flags = KSPROPERTY_TYPE_GET;
|
||||||
|
|
||||||
|
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Result, sizeof(ULONG), &BytesReturned);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
DeviceInfo->DeviceCount = Result;
|
||||||
|
else
|
||||||
|
DeviceInfo->DeviceCount = 0;
|
||||||
|
|
||||||
|
DPRINT1("WdmAudControlDeviceType Status %x Devices %u\n", Status, DeviceInfo->DeviceCount);
|
||||||
|
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE)
|
||||||
|
{
|
||||||
|
DPRINT1("FIXME: only waveout devices are supported\n");
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Error: invalid device handle provided %p\n", DeviceInfo->hDevice);
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Property.Set = KSPROPSETID_Connection;
|
||||||
|
Property.Id = KSPROPERTY_CONNECTION_STATE;
|
||||||
|
Property.Flags = KSPROPERTY_TYPE_SET;
|
||||||
|
|
||||||
|
State = DeviceInfo->State;
|
||||||
|
|
||||||
|
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned);
|
||||||
|
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
|
|
||||||
|
DPRINT1("WdmAudControlDeviceState Status %x\n", Status);
|
||||||
|
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
WdmAudWriteCompleted(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Ctx)
|
||||||
|
{
|
||||||
|
PWRITE_CONTEXT Context = (PWRITE_CONTEXT)Ctx;
|
||||||
|
|
||||||
|
Context->Irp->IoStatus.Information = Context->Length;
|
||||||
|
Context->Irp->IoStatus.Status = Irp->IoStatus.Status;
|
||||||
|
IoCompleteRequest(Context->Irp, IO_SOUND_INCREMENT);
|
||||||
|
|
||||||
|
ExFreePool(Context);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
WdmAudControlWriteData(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
||||||
|
IN PWDMAUD_CLIENT ClientInfo)
|
||||||
|
{
|
||||||
|
PKSSTREAM_HEADER Packet;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
PWRITE_CONTEXT Context;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
PUCHAR Buffer;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE)
|
||||||
|
{
|
||||||
|
DPRINT1("FIXME: only waveout devices are supported\n");
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
ProbeForRead(DeviceInfo->Buffer, DeviceInfo->BufferSize, TYPE_ALIGNMENT(char));
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
/* Exception, get the error code */
|
||||||
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Invalid buffer supplied\n");
|
||||||
|
return SetIrpIoStatus(Irp, Status, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer = ExAllocatePool(NonPagedPool, DeviceInfo->BufferSize);
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
/* no memory */
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlMoveMemory(Buffer, DeviceInfo->Buffer, DeviceInfo->BufferSize);
|
||||||
|
|
||||||
|
|
||||||
|
Context = ExAllocatePool(NonPagedPool, sizeof(WRITE_CONTEXT));
|
||||||
|
if (!Context)
|
||||||
|
{
|
||||||
|
/* no memory */
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup completion context */
|
||||||
|
Context->Irp = Irp;
|
||||||
|
Context->Length = DeviceInfo->BufferSize;
|
||||||
|
|
||||||
|
/* setup stream context */
|
||||||
|
Packet = (PKSSTREAM_HEADER)ExAllocatePool(NonPagedPool, sizeof(KSSTREAM_HEADER));
|
||||||
|
Packet->Data = Buffer;
|
||||||
|
Packet->FrameExtent = DeviceInfo->BufferSize;
|
||||||
|
Packet->DataUsed = DeviceInfo->BufferSize;
|
||||||
|
Packet->Size = sizeof(KSSTREAM_HEADER);
|
||||||
|
Packet->PresentationTime.Numerator = 1;
|
||||||
|
Packet->PresentationTime.Denominator = 1;
|
||||||
|
ASSERT(FileObject->FsContext != NULL);
|
||||||
|
|
||||||
|
|
||||||
|
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM, (PVOID)Packet, sizeof(KSSTREAM_HEADER), NULL, 0, &BytesReturned);
|
||||||
|
|
||||||
|
DPRINT1("KsSynchronousIoControlDevice result %x\n", Status);
|
||||||
|
|
||||||
|
IoMarkIrpPending(Irp);
|
||||||
|
Irp->IoStatus.Information = DeviceInfo->BufferSize;
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
|
||||||
|
ExFreePool(Buffer);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -16,42 +332,59 @@ WdmAudDeviceControl(
|
||||||
IN PIRP Irp)
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PWDMAUD_DEVICE_INFO DeviceInfo;
|
||||||
|
PWDMAUD_CLIENT ClientInfo;
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
DPRINT1("WdmAudDeviceControl entered\n");
|
||||||
|
DbgBreakPoint();
|
||||||
|
|
||||||
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO))
|
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO))
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
/* invalid parameter */
|
||||||
Irp->IoStatus.Information = 0;
|
DPRINT1("Input buffer too small size %u expected %u\n", IoStack->Parameters.DeviceIoControl.InputBufferLength, sizeof(WDMAUD_DEVICE_INFO));
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/* file object parameter */
|
||||||
|
DPRINT1("Error: file object is not attached\n");
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
|
}
|
||||||
|
ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
|
||||||
|
|
||||||
DPRINT1("WdmAudDeviceControl entered\n");
|
DPRINT1("WdmAudDeviceControl entered\n");
|
||||||
|
|
||||||
switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
|
switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
|
||||||
{
|
{
|
||||||
case IOCTL_OPEN_WDMAUD:
|
case IOCTL_OPEN_WDMAUD:
|
||||||
//return WdmAudDeviceControlOpen(DeviceObject, Irp);
|
return WdmAudControlOpen(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
||||||
case IOCTL_CLOSE_WDMAUD:
|
|
||||||
case IOCTL_GETNUMDEVS_TYPE:
|
case IOCTL_GETNUMDEVS_TYPE:
|
||||||
|
return WdmAudControlDeviceType(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
||||||
case IOCTL_SETDEVICE_STATE:
|
case IOCTL_SETDEVICE_STATE:
|
||||||
|
return WdmAudControlDeviceState(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
||||||
|
case IOCTL_WRITEDATA:
|
||||||
|
return WdmAudControlWriteData(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
||||||
|
|
||||||
|
case IOCTL_CLOSE_WDMAUD:
|
||||||
case IOCTL_GETDEVID:
|
case IOCTL_GETDEVID:
|
||||||
case IOCTL_GETVOLUME:
|
case IOCTL_GETVOLUME:
|
||||||
case IOCTL_SETVOLUME:
|
case IOCTL_SETVOLUME:
|
||||||
case IOCTL_GETCAPABILITIES:
|
case IOCTL_GETCAPABILITIES:
|
||||||
case IOCTL_WRITEDATA:
|
DPRINT1("Unhandeled %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
|
||||||
|
|
||||||
|
|
||||||
UNIMPLEMENTED
|
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ WdmAudCreate(
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
WDMAUD_CLIENT *pClient;
|
PWDMAUD_CLIENT pClient;
|
||||||
|
|
||||||
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
|
@ -189,12 +189,12 @@ WdmAudClose(
|
||||||
pClient = (WDMAUD_CLIENT*)IoStack->FileObject->FsContext;
|
pClient = (WDMAUD_CLIENT*)IoStack->FileObject->FsContext;
|
||||||
if (pClient)
|
if (pClient)
|
||||||
{
|
{
|
||||||
|
ObDereferenceObject(pClient->FileObject);
|
||||||
ZwClose(pClient->hSysAudio);
|
ZwClose(pClient->hSysAudio);
|
||||||
ExFreePool(pClient);
|
ExFreePool(pClient);
|
||||||
IoStack->FileObject->FsContext = NULL;
|
IoStack->FileObject->FsContext = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
|
@ -44,7 +44,7 @@ typedef struct
|
||||||
WAVEINCAPS WaveInCaps;
|
WAVEINCAPS WaveInCaps;
|
||||||
}u;
|
}u;
|
||||||
|
|
||||||
}WDMAUD_DEVICE_INFO;
|
}WDMAUD_DEVICE_INFO, *PWDMAUD_DEVICE_INFO;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef WDMAUD_H__
|
#ifndef WDMAUD_H__
|
||||||
#define WDMAUD_H__
|
#define WDMAUD_H__
|
||||||
|
|
||||||
|
#include <pseh/pseh2.h>
|
||||||
#include <ntddk.h>
|
#include <ntddk.h>
|
||||||
#include <portcls.h>
|
#include <portcls.h>
|
||||||
#include <ks.h>
|
#include <ks.h>
|
||||||
|
@ -86,6 +87,14 @@ typedef struct
|
||||||
|
|
||||||
}WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION;
|
}WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PIRP Irp;
|
||||||
|
IO_STATUS_BLOCK StatusBlock;
|
||||||
|
ULONG Length;
|
||||||
|
}WRITE_CONTEXT, *PWRITE_CONTEXT;
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
WdmAudRegisterDeviceInterface(
|
WdmAudRegisterDeviceInterface(
|
||||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
<include base="ReactOS">include/reactos/libs/sound</include>
|
<include base="ReactOS">include/reactos/libs/sound</include>
|
||||||
<library>ntoskrnl</library>
|
<library>ntoskrnl</library>
|
||||||
<library>ks</library>
|
<library>ks</library>
|
||||||
|
<library>pseh</library>
|
||||||
<file>control.c</file>
|
<file>control.c</file>
|
||||||
<file>deviface.c</file>
|
<file>deviface.c</file>
|
||||||
<file>entry.c</file>
|
<file>entry.c</file>
|
||||||
|
|
|
@ -29,6 +29,7 @@ SetIrpIoStatus(
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Information = Length;
|
Irp->IoStatus.Information = Length;
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return Status;
|
return Status;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -242,7 +243,7 @@ SysAudioHandleProperty(
|
||||||
}
|
}
|
||||||
else if (Property->Id == KSPROPERTY_SYSAUDIO_INSTANCE_INFO)
|
else if (Property->Id == KSPROPERTY_SYSAUDIO_INSTANCE_INFO)
|
||||||
{
|
{
|
||||||
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SYSAUDIO_INSTANCE_INFO))
|
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SYSAUDIO_INSTANCE_INFO))
|
||||||
{
|
{
|
||||||
/* too small buffer */
|
/* too small buffer */
|
||||||
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(SYSAUDIO_INSTANCE_INFO));
|
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(SYSAUDIO_INSTANCE_INFO));
|
||||||
|
|
|
@ -52,6 +52,8 @@ DeviceInterfaceChangeCallback(
|
||||||
DPRINT1("No Mem\n");
|
DPRINT1("No Mem\n");
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(DeviceEntry, sizeof(KSAUDIO_DEVICE_ENTRY));
|
||||||
DeviceEntry->DeviceName.Length = 0;
|
DeviceEntry->DeviceName.Length = 0;
|
||||||
DeviceEntry->DeviceName.MaximumLength = Event->SymbolicLinkName->Length + 5 * sizeof(WCHAR);
|
DeviceEntry->DeviceName.MaximumLength = Event->SymbolicLinkName->Length + 5 * sizeof(WCHAR);
|
||||||
DeviceEntry->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceEntry->DeviceName.MaximumLength);
|
DeviceEntry->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceEntry->DeviceName.MaximumLength);
|
||||||
|
|
|
@ -175,6 +175,61 @@ static KSDISPATCH_TABLE DispatchTable =
|
||||||
Dispatch_fnFastWrite,
|
Dispatch_fnFastWrite,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CreatePinWorkerRoutine(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE PinHandle;
|
||||||
|
HANDLE * Handels;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
PIRP Irp;
|
||||||
|
PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context;
|
||||||
|
|
||||||
|
Handels = ExAllocatePool(NonPagedPool, (WorkerContext->Entry->NumberOfPins + 1) * sizeof(HANDLE));
|
||||||
|
if (!Handels)
|
||||||
|
{
|
||||||
|
DPRINT1("No Memory \n");
|
||||||
|
WorkerContext->Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
||||||
|
WorkerContext->Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(WorkerContext->Irp, IO_SOUND_INCREMENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Status = KsCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &PinHandle);
|
||||||
|
DPRINT1("KsCreatePin status %x\n", Status);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Status = ObReferenceObjectByHandle(PinHandle, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Status = CreateDispatcher(WorkerContext->Irp, PinHandle, FileObject);
|
||||||
|
DPRINT1("Pins %x\n", WorkerContext->Entry->NumberOfPins);
|
||||||
|
if (WorkerContext->Entry->NumberOfPins)
|
||||||
|
{
|
||||||
|
RtlMoveMemory(Handels, WorkerContext->Entry->Pins, WorkerContext->Entry->NumberOfPins * sizeof(HANDLE));
|
||||||
|
ExFreePool(WorkerContext->Entry->Pins);
|
||||||
|
}
|
||||||
|
Handels[WorkerContext->Entry->NumberOfPins-1] = PinHandle;
|
||||||
|
WorkerContext->Entry->Pins = Handels;
|
||||||
|
WorkerContext->Entry->NumberOfPins++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT1("CreatePinWorkerRoutine completing irp\n");
|
||||||
|
WorkerContext->Irp->IoStatus.Status = Status;
|
||||||
|
WorkerContext->Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
Irp = WorkerContext->Irp;
|
||||||
|
ExFreePool(Context);
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
DispatchCreateSysAudio(
|
DispatchCreateSysAudio(
|
||||||
|
@ -185,9 +240,79 @@ DispatchCreateSysAudio(
|
||||||
KSOBJECT_HEADER ObjectHeader;
|
KSOBJECT_HEADER ObjectHeader;
|
||||||
PSYSAUDIO_CLIENT Client;
|
PSYSAUDIO_CLIENT Client;
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
|
PIO_STACK_LOCATION IoStatus;
|
||||||
|
LPWSTR Buffer;
|
||||||
|
ULONG Length, DeviceIndex;
|
||||||
|
PSYSAUDIODEVEXT DeviceExtension;
|
||||||
|
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||||
|
KSPIN_CONNECT * PinConnect;
|
||||||
|
PIO_WORKITEM WorkItem;
|
||||||
|
PPIN_WORKER_CONTEXT Context;
|
||||||
|
static LPWSTR KS_NAME_PIN = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}";
|
||||||
|
|
||||||
|
IoStatus = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
Buffer = IoStatus->FileObject->FileName.Buffer;
|
||||||
|
|
||||||
DPRINT1("DispatchCreateSysAudio entered\n");
|
DPRINT1("DispatchCreateSysAudio entered\n");
|
||||||
DbgBreakPoint();
|
|
||||||
|
if (Buffer)
|
||||||
|
{
|
||||||
|
/* is the request for a new pin */
|
||||||
|
if (!wcsncmp(KS_NAME_PIN, Buffer, wcslen(KS_NAME_PIN)))
|
||||||
|
{
|
||||||
|
Client = (PSYSAUDIO_CLIENT)Irp->Tail.Overlay.OriginalFileObject->FsContext2;
|
||||||
|
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
|
||||||
|
if (Client)
|
||||||
|
{
|
||||||
|
ASSERT(Client->NumDevices >= 1);
|
||||||
|
DeviceIndex = Client->Devices[Client->NumDevices-1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT1("Warning: using HACK\n");
|
||||||
|
DeviceIndex = 0;
|
||||||
|
}
|
||||||
|
ASSERT(DeviceIndex < DeviceExtension->NumberOfKsAudioDevices);
|
||||||
|
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, DeviceIndex);
|
||||||
|
ASSERT(Entry);
|
||||||
|
|
||||||
|
Length = (IoStatus->FileObject->FileName.Length - ((wcslen(KS_NAME_PIN)+1) * sizeof(WCHAR)));
|
||||||
|
PinConnect = ExAllocatePool(NonPagedPool, Length);
|
||||||
|
if (!PinConnect)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
RtlMoveMemory(PinConnect, IoStatus->FileObject->FileName.Buffer + (wcslen(KS_NAME_PIN)+1), Length);
|
||||||
|
Context = ExAllocatePool(NonPagedPool, sizeof(PIN_WORKER_CONTEXT));
|
||||||
|
if (!Context)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
Context->PinConnect = PinConnect;
|
||||||
|
Context->Entry = Entry;
|
||||||
|
Context->Irp = Irp;
|
||||||
|
|
||||||
|
WorkItem = IoAllocateWorkItem(DeviceObject);
|
||||||
|
if (!WorkItem)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
IoQueueWorkItem(WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_PENDING;
|
||||||
|
IoMarkIrpPending(Irp);
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate create item */
|
/* allocate create item */
|
||||||
CreateItem = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
|
CreateItem = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
|
||||||
|
@ -209,6 +334,9 @@ DispatchCreateSysAudio(
|
||||||
/* store create context */
|
/* store create context */
|
||||||
CreateItem->Context = (PVOID)Client;
|
CreateItem->Context = (PVOID)Client;
|
||||||
|
|
||||||
|
/* store the object in FsContext */
|
||||||
|
IoStatus->FileObject->FsContext2 = (PVOID)Client;
|
||||||
|
|
||||||
/* allocate object header */
|
/* allocate object header */
|
||||||
Status = KsAllocateObjectHeader(&ObjectHeader, 1, CreateItem, Irp, &DispatchTable);
|
Status = KsAllocateObjectHeader(&ObjectHeader, 1, CreateItem, Irp, &DispatchTable);
|
||||||
|
|
||||||
|
@ -228,8 +356,6 @@ SysAudioAllocateDeviceHeader(
|
||||||
if (!CreateItem)
|
if (!CreateItem)
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* initialize create item struct */
|
/* initialize create item struct */
|
||||||
RtlZeroMemory(CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
|
RtlZeroMemory(CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
|
||||||
CreateItem->Create = DispatchCreateSysAudio;
|
CreateItem->Create = DispatchCreateSysAudio;
|
||||||
|
@ -238,7 +364,6 @@ SysAudioAllocateDeviceHeader(
|
||||||
Status = KsAllocateDeviceHeader(&DeviceExtension->KsDeviceHeader,
|
Status = KsAllocateDeviceHeader(&DeviceExtension->KsDeviceHeader,
|
||||||
1,
|
1,
|
||||||
CreateItem);
|
CreateItem);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
261
reactos/drivers/wdm/audio/sysaudio/pin.c
Normal file
261
reactos/drivers/wdm/audio/sysaudio/pin.c
Normal file
|
@ -0,0 +1,261 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Kernel Streaming
|
||||||
|
* FILE: drivers/wdm/audio/sysaudio/deviface.c
|
||||||
|
* PURPOSE: System Audio graph builder
|
||||||
|
* PROGRAMMER: Johannes Anderwald
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ntifs.h>
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <portcls.h>
|
||||||
|
#include <ks.h>
|
||||||
|
#include <ksmedia.h>
|
||||||
|
#include <math.h>
|
||||||
|
#define YDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
#include "sysaudio.h"
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Pin_fnDeviceIoControl(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PDISPATCH_CONTEXT Context;
|
||||||
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
|
||||||
|
DPRINT1("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
/* access the create item */
|
||||||
|
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
|
||||||
|
Context = (PDISPATCH_CONTEXT)CreateItem->Context;
|
||||||
|
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
Status = KsSynchronousIoControlDevice(Context->FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode,
|
||||||
|
IoStack->Parameters.DeviceIoControl.Type3InputBuffer,
|
||||||
|
IoStack->Parameters.DeviceIoControl.InputBufferLength,
|
||||||
|
Irp->UserBuffer,
|
||||||
|
IoStack->Parameters.DeviceIoControl.OutputBufferLength,
|
||||||
|
&BytesReturned);
|
||||||
|
|
||||||
|
DPRINT1("Status %x\n", Status);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = BytesReturned;
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Pin_fnRead(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
DPRINT1("Pin_fnRead called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
PinWriteCompletionRoutine(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
PIRP CIrp = (PIRP)Context;
|
||||||
|
|
||||||
|
CIrp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
CIrp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(CIrp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Pin_fnWrite(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PDISPATCH_CONTEXT Context;
|
||||||
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT1("Pin_fnWrite called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
/* access the create item */
|
||||||
|
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
|
||||||
|
Context = (PDISPATCH_CONTEXT)CreateItem->Context;
|
||||||
|
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
Status = KsSynchronousIoControlDevice(Context->FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
|
||||||
|
IoStack->Parameters.DeviceIoControl.Type3InputBuffer,
|
||||||
|
IoStack->Parameters.DeviceIoControl.InputBufferLength,
|
||||||
|
Irp->UserBuffer,
|
||||||
|
IoStack->Parameters.DeviceIoControl.OutputBufferLength,
|
||||||
|
&BytesReturned);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = BytesReturned;
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Pin_fnFlush(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
DPRINT1("Pin_fnFlush called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Pin_fnClose(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
DPRINT1("Pin_fnClose called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Pin_fnQuerySecurity(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
DPRINT1("Pin_fnQuerySecurity called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Pin_fnSetSecurity(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
|
||||||
|
DPRINT1("Pin_fnSetSecurity called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
Pin_fnFastDeviceIoControl(
|
||||||
|
PFILE_OBJECT FileObject,
|
||||||
|
BOOLEAN Wait,
|
||||||
|
PVOID InputBuffer,
|
||||||
|
ULONG InputBufferLength,
|
||||||
|
PVOID OutputBuffer,
|
||||||
|
ULONG OutputBufferLength,
|
||||||
|
ULONG IoControlCode,
|
||||||
|
PIO_STATUS_BLOCK IoStatus,
|
||||||
|
PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
DPRINT1("Pin_fnFastDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
Pin_fnFastRead(
|
||||||
|
PFILE_OBJECT FileObject,
|
||||||
|
PLARGE_INTEGER FileOffset,
|
||||||
|
ULONG Length,
|
||||||
|
BOOLEAN Wait,
|
||||||
|
ULONG LockKey,
|
||||||
|
PVOID Buffer,
|
||||||
|
PIO_STATUS_BLOCK IoStatus,
|
||||||
|
PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
DPRINT1("Pin_fnFastRead called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
Pin_fnFastWrite(
|
||||||
|
PFILE_OBJECT FileObject,
|
||||||
|
PLARGE_INTEGER FileOffset,
|
||||||
|
ULONG Length,
|
||||||
|
BOOLEAN Wait,
|
||||||
|
ULONG LockKey,
|
||||||
|
PVOID Buffer,
|
||||||
|
PIO_STATUS_BLOCK IoStatus,
|
||||||
|
PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
DPRINT1("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static KSDISPATCH_TABLE PinTable =
|
||||||
|
{
|
||||||
|
Pin_fnDeviceIoControl,
|
||||||
|
Pin_fnRead,
|
||||||
|
Pin_fnWrite,
|
||||||
|
Pin_fnFlush,
|
||||||
|
Pin_fnClose,
|
||||||
|
Pin_fnQuerySecurity,
|
||||||
|
Pin_fnSetSecurity,
|
||||||
|
Pin_fnFastDeviceIoControl,
|
||||||
|
Pin_fnFastRead,
|
||||||
|
Pin_fnFastWrite,
|
||||||
|
};
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CreateDispatcher(
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN HANDLE Handle,
|
||||||
|
IN PFILE_OBJECT FileObject)
|
||||||
|
{
|
||||||
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
|
NTSTATUS Status;
|
||||||
|
KSOBJECT_HEADER ObjectHeader;
|
||||||
|
PDISPATCH_CONTEXT Context;
|
||||||
|
|
||||||
|
/* allocate create item */
|
||||||
|
CreateItem = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
|
||||||
|
if (!CreateItem)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
Context = ExAllocatePool(NonPagedPool, sizeof(DISPATCH_CONTEXT));
|
||||||
|
if (!Context)
|
||||||
|
{
|
||||||
|
ExFreePool(CreateItem);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context->Handle = Handle;
|
||||||
|
Context->FileObject = FileObject;
|
||||||
|
|
||||||
|
|
||||||
|
CreateItem->Context = (PVOID)Context;
|
||||||
|
|
||||||
|
/* allocate object header */
|
||||||
|
Status = KsAllocateObjectHeader(&ObjectHeader, 1, CreateItem, Irp, &PinTable);
|
||||||
|
return Status;
|
||||||
|
}
|
|
@ -15,16 +15,19 @@ typedef struct
|
||||||
HANDLE Handle;
|
HANDLE Handle;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
UNICODE_STRING DeviceName;
|
UNICODE_STRING DeviceName;
|
||||||
|
|
||||||
ULONG NumberOfClients;
|
ULONG NumberOfClients;
|
||||||
|
|
||||||
|
ULONG NumberOfPins;
|
||||||
|
HANDLE * Pins;
|
||||||
|
|
||||||
}KSAUDIO_DEVICE_ENTRY, *PKSAUDIO_DEVICE_ENTRY;
|
}KSAUDIO_DEVICE_ENTRY, *PKSAUDIO_DEVICE_ENTRY;
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
KSDEVICE_HEADER KsDeviceHeader;
|
||||||
PDEVICE_OBJECT PhysicalDeviceObject;
|
PDEVICE_OBJECT PhysicalDeviceObject;
|
||||||
PDEVICE_OBJECT NextDeviceObject;
|
PDEVICE_OBJECT NextDeviceObject;
|
||||||
KSDEVICE_HEADER KsDeviceHeader;
|
|
||||||
ULONG NumberOfKsAudioDevices;
|
ULONG NumberOfKsAudioDevices;
|
||||||
|
|
||||||
LIST_ENTRY KsAudioDeviceList;
|
LIST_ENTRY KsAudioDeviceList;
|
||||||
|
@ -33,6 +36,20 @@ typedef struct
|
||||||
KMUTEX Mutex;
|
KMUTEX Mutex;
|
||||||
}SYSAUDIODEVEXT, *PSYSAUDIODEVEXT;
|
}SYSAUDIODEVEXT, *PSYSAUDIODEVEXT;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PIRP Irp;
|
||||||
|
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||||
|
KSPIN_CONNECT * PinConnect;
|
||||||
|
|
||||||
|
}PIN_WORKER_CONTEXT, *PPIN_WORKER_CONTEXT;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
HANDLE Handle;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
}DISPATCH_CONTEXT, *PDISPATCH_CONTEXT;
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
SysAudioAllocateDeviceHeader(
|
SysAudioAllocateDeviceHeader(
|
||||||
IN SYSAUDIODEVEXT *DeviceExtension);
|
IN SYSAUDIODEVEXT *DeviceExtension);
|
||||||
|
@ -51,4 +68,15 @@ SysAudioHandleProperty(
|
||||||
PDEVICE_OBJECT DeviceObject,
|
PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp);
|
PIRP Irp);
|
||||||
|
|
||||||
|
PKSAUDIO_DEVICE_ENTRY
|
||||||
|
GetListEntry(
|
||||||
|
IN PLIST_ENTRY Head,
|
||||||
|
IN ULONG Index);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CreateDispatcher(
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN HANDLE Handle,
|
||||||
|
IN PFILE_OBJECT FileObject);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,11 +4,13 @@
|
||||||
<include base="sysaudio">.</include>
|
<include base="sysaudio">.</include>
|
||||||
<library>ntoskrnl</library>
|
<library>ntoskrnl</library>
|
||||||
<library>ks</library>
|
<library>ks</library>
|
||||||
|
<library>hal</library>
|
||||||
<library>libcntpr</library>
|
<library>libcntpr</library>
|
||||||
<define name="_COMDDK_" />
|
<define name="_COMDDK_" />
|
||||||
<file>control.c</file>
|
<file>control.c</file>
|
||||||
<file>deviface.c</file>
|
<file>deviface.c</file>
|
||||||
<file>dispatcher.c</file>
|
<file>dispatcher.c</file>
|
||||||
<file>main.c</file>
|
<file>main.c</file>
|
||||||
|
<file>pin.c</file>
|
||||||
<file>sysaudio.rc</file>
|
<file>sysaudio.rc</file>
|
||||||
</module>
|
</module>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue