- Fix a bug in the audio_test programm which initialized the deviceinfo before another syscall

- Complete also an unhandeled irp
- Implement IOCTL_CLOSE_WDMAUD
- Account the number of times pin can be instantiated in sysaudio and apply changes to SYSAUDIO_CLIENT structure
- There is still a bug which prevents closing the audio adapter at the 2nd time

svn path=/trunk/; revision=39753
This commit is contained in:
Johannes Anderwald 2009-02-25 15:55:21 +00:00
parent a15e6fe4ad
commit 866d5ef497
8 changed files with 188 additions and 87 deletions

View file

@ -39,6 +39,7 @@ main(int argc, char* argv[])
} }
printf("WDMAUD: opened\n"); printf("WDMAUD: opened\n");
/* clear device info */ /* clear device info */
RtlZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); RtlZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
@ -61,20 +62,13 @@ main(int argc, char* argv[])
} }
printf("WDMAUD: Num Devices %lu\n", DeviceInfo.DeviceCount); printf("WDMAUD: Num Devices %lu\n", DeviceInfo.DeviceCount);
if (!DeviceInfo.DeviceCount) if (!DeviceInfo.DeviceCount)
{ {
CloseHandle(hWdmAud); CloseHandle(hWdmAud);
return 0; 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_GETCAPABILITIES, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped); Status = DeviceIoControl(hWdmAud, IOCTL_GETCAPABILITIES, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
if (!Status) if (!Status)
@ -84,6 +78,16 @@ main(int argc, char* argv[])
printf("Failed to get iocaps %lx\n", GetLastError()); printf("Failed to get iocaps %lx\n", GetLastError());
} }
} }
printf("WDMAUD: Capabilites NumChannels %x dwFormats %lx\n", DeviceInfo.u.WaveOutCaps.wChannels, DeviceInfo.u.WaveOutCaps.dwFormats);
DeviceInfo.u.WaveFormatEx.cbSize = sizeof(WAVEFORMATEX);
DeviceInfo.u.WaveFormatEx.wFormatTag = 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); Status = DeviceIoControl(hWdmAud, IOCTL_OPEN_WDMAUD, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
@ -97,8 +101,7 @@ main(int argc, char* argv[])
} }
} }
printf("WDMAUD: opened device\n");
// //
// Allocate a buffer for 1 second // Allocate a buffer for 1 second
@ -163,8 +166,8 @@ main(int argc, char* argv[])
} }
} }
printf("WDMAUD: STOPPED\n"); printf("WDMAUD: STOPPED\n");
CloseHandle(hWdmAud);
CloseHandle(&Overlapped.hEvent); CloseHandle(&Overlapped.hEvent);
CloseHandle(hWdmAud);
printf("WDMAUD: COMPLETE\n"); printf("WDMAUD: COMPLETE\n");
return 0; return 0;
} }

View file

@ -225,6 +225,7 @@ PcPropertyHandler(
RtlFreeUnicodeString(&GuidString); RtlFreeUnicodeString(&GuidString);
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }

View file

@ -371,13 +371,14 @@ WdmAudCapabilities(
IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo) IN PWDMAUD_CLIENT ClientInfo)
{ {
NTSTATUS Status = STATUS_UNSUCCESSFUL;
KSP_PIN PinProperty; KSP_PIN PinProperty;
KSCOMPONENTID ComponentId; KSCOMPONENTID ComponentId;
KSMULTIPLE_ITEM * MultipleItem; KSMULTIPLE_ITEM * MultipleItem;
ULONG BytesReturned; ULONG BytesReturned;
PKSDATARANGE_AUDIO DataRangeAudio; PKSDATARANGE_AUDIO DataRangeAudio;
PKSDATARANGE DataRange; PKSDATARANGE DataRange;
NTSTATUS Status;
ULONG Index; ULONG Index;
ULONG wChannels = 0; ULONG wChannels = 0;
ULONG dwFormats = 0; ULONG dwFormats = 0;
@ -420,8 +421,6 @@ WdmAudCapabilities(
return SetIrpIoStatus(Irp, Status, 0); return SetIrpIoStatus(Irp, Status, 0);
} }
MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned); MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned);
if (!MultipleItem) if (!MultipleItem)
{ {
@ -477,6 +476,31 @@ WdmAudCapabilities(
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
} }
NTSTATUS
NTAPI
WdmAudClose(
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] == DeviceInfo->hDevice)
{
DPRINT1("Closing device %p\n", DeviceInfo->hDevice);
ZwClose(DeviceInfo->hDevice);
ClientInfo->hPins[Index] = NULL;
SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
return STATUS_SUCCESS;
}
}
SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
return STATUS_INVALID_PARAMETER;
}
NTSTATUS NTSTATUS
NTAPI NTAPI
WdmAudDeviceControl( WdmAudDeviceControl(
@ -530,6 +554,7 @@ WdmAudDeviceControl(
case IOCTL_GETCAPABILITIES: case IOCTL_GETCAPABILITIES:
return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo); return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo);
case IOCTL_CLOSE_WDMAUD: case IOCTL_CLOSE_WDMAUD:
return WdmAudClose(DeviceObject, Irp, DeviceInfo, ClientInfo);
case IOCTL_GETDEVID: case IOCTL_GETDEVID:
case IOCTL_GETVOLUME: case IOCTL_GETVOLUME:
case IOCTL_SETVOLUME: case IOCTL_SETVOLUME:

View file

@ -203,7 +203,12 @@ WdmAudCleanup(
if (pClient) if (pClient)
{ {
for (Index = 0; Index < pClient->NumPins; Index++) for (Index = 0; Index < pClient->NumPins; Index++)
ZwClose(pClient->hPins[Index]); {
if (pClient->hPins[Index])
{
ZwClose(pClient->hPins[Index]);
}
}
if (pClient->hPins) if (pClient->hPins)
{ {

View file

@ -8,7 +8,7 @@
#define YDEBUG #define YDEBUG
#include <debug.h> #include <debug.h>
#include <ksmedia.h> #include <ksmedia.h>
#include <mmsystem.h> #include <mmsystem.h>
#include "interface.h" #include "interface.h"

View file

@ -58,8 +58,7 @@ SysAudioOpenVirtualDevice(
IN ULONG DeviceNumber, IN ULONG DeviceNumber,
PSYSAUDIODEVEXT DeviceExtension) PSYSAUDIODEVEXT DeviceExtension)
{ {
PULONG Index; PSYSAUDIO_CLIENT_HANDELS Index;
PHANDLE Handle;
ULONG Count; ULONG Count;
PSYSAUDIO_CLIENT ClientInfo; PSYSAUDIO_CLIENT ClientInfo;
PKSAUDIO_DEVICE_ENTRY Entry; PKSAUDIO_DEVICE_ENTRY Entry;
@ -85,23 +84,17 @@ SysAudioOpenVirtualDevice(
if (!ClientInfo->NumDevices) if (!ClientInfo->NumDevices)
{ {
/* first device to be openend */ /* first device to be openend */
ClientInfo->Devices = ExAllocatePool(NonPagedPool, sizeof(ULONG)); ClientInfo->Devs = ExAllocatePool(NonPagedPool, sizeof(SYSAUDIO_CLIENT_HANDELS));
if (!ClientInfo->Devices) if (!ClientInfo->Devs)
{
/* no memory */
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
}
ClientInfo->Handels = ExAllocatePool(NonPagedPool, sizeof(HANDLE));
if (!ClientInfo->Devices)
{ {
/* no memory */ /* no memory */
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0); return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
} }
ClientInfo->NumDevices = 1; ClientInfo->NumDevices = 1;
ClientInfo->Devices[0] = DeviceNumber; ClientInfo->Devs[0].DeviceId = DeviceNumber;
ClientInfo->Handels[0] = NULL; ClientInfo->Devs[0].ClientHandles = NULL;
ClientInfo->Devs[0].ClientHandlesCount = 0;
/* increase usage count */ /* increase usage count */
Entry->NumberOfClients++; Entry->NumberOfClients++;
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0); return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
@ -110,46 +103,37 @@ SysAudioOpenVirtualDevice(
/* check if device has already been openend */ /* check if device has already been openend */
for(Count = 0; Count < ClientInfo->NumDevices; Count++) for(Count = 0; Count < ClientInfo->NumDevices; Count++)
{ {
if (ClientInfo->Devices[Count] == DeviceNumber) if (ClientInfo->Devs[Count].DeviceId == DeviceNumber)
{ {
/* device has already been opened */ /* device has already been opened */
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0); return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
} }
} }
/* new device to be openend */ /* new device to be openend */
Index = ExAllocatePool(NonPagedPool, sizeof(ULONG) * (ClientInfo->NumDevices + 1)); Index = ExAllocatePool(NonPagedPool, sizeof(SYSAUDIO_CLIENT_HANDELS) * (ClientInfo->NumDevices + 1));
if (!Index) if (!Index)
{ {
/* no memory */ /* no memory */
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0); return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
} }
Handle = ExAllocatePool(NonPagedPool, sizeof(HANDLE) * (ClientInfo->NumDevices + 1)); if (ClientInfo->NumDevices)
if (!Handle)
{ {
/* no memory */ /* copy device count array */
ExFreePool(Index); RtlMoveMemory(Index, ClientInfo->Devs, ClientInfo->NumDevices * sizeof(SYSAUDIO_CLIENT_HANDELS));
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
} }
Index[ClientInfo->NumDevices].DeviceId = DeviceNumber;
Index[ClientInfo->NumDevices].ClientHandlesCount = 0;
Index[ClientInfo->NumDevices].ClientHandles = NULL;
/* increase usage count */ /* increase usage count */
Entry->NumberOfClients++; Entry->NumberOfClients++;
/* copy device count array */ ExFreePool(ClientInfo->Devs);
if (ClientInfo->NumDevices)
{
RtlMoveMemory(Index, ClientInfo->Devices, ClientInfo->NumDevices * sizeof(ULONG));
RtlMoveMemory(Handle, ClientInfo->Handels, ClientInfo->NumDevices * sizeof(HANDLE));
}
Index[ClientInfo->NumDevices] = DeviceNumber; ClientInfo->Devs = Index;
Handle[ClientInfo->NumDevices] = NULL;
ExFreePool(ClientInfo->Handels);
ExFreePool(ClientInfo->Devices);
ClientInfo->NumDevices++; ClientInfo->NumDevices++;
ClientInfo->Devices = Index;
ClientInfo->Handels = Handle;
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0); return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
} }
@ -160,9 +144,12 @@ CreatePinWorkerRoutine(
IN PVOID Context) IN PVOID Context)
{ {
NTSTATUS Status; NTSTATUS Status;
HANDLE PinHandle; PSYSAUDIO_CLIENT AudioClient;
HANDLE RealPinHandle, VirtualPinHandle;
HANDLE Filter; HANDLE Filter;
ULONG NumHandels;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PSYSAUDIO_PIN_HANDLE ClientPinHandle;
PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context; PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context;
Filter = WorkerContext->PinConnect->PinToHandle; Filter = WorkerContext->PinConnect->PinToHandle;
@ -172,7 +159,7 @@ CreatePinWorkerRoutine(
if (WorkerContext->CreateRealPin) if (WorkerContext->CreateRealPin)
{ {
/* create the real pin */ /* create the real pin */
Status = KsCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &PinHandle); Status = KsCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failed to create Pin with %x\n", Status); DPRINT1("Failed to create Pin with %x\n", Status);
@ -182,13 +169,18 @@ CreatePinWorkerRoutine(
} }
/* get pin file object */ /* get pin file object */
Status = ObReferenceObjectByHandle(PinHandle, Status = ObReferenceObjectByHandle(RealPinHandle,
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle = PinHandle; if (WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].MaxPinInstanceCount == 1)
{
/* store the pin handle there is the pin can only be instantiated once*/
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle = RealPinHandle;
}
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References = 1; WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References = 1;
WorkerContext->DispatchContext->Handle = PinHandle; WorkerContext->DispatchContext->Handle = RealPinHandle;
WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId; WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId;
WorkerContext->DispatchContext->AudioEntry = WorkerContext->Entry; WorkerContext->DispatchContext->AudioEntry = WorkerContext->Entry;
@ -204,7 +196,7 @@ CreatePinWorkerRoutine(
WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId; WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId;
/* get pin file object */ /* get pin file object */
Status = ObReferenceObjectByHandle(PinHandle, Status = ObReferenceObjectByHandle(WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle,
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
@ -220,7 +212,7 @@ CreatePinWorkerRoutine(
DPRINT1("creating virtual pin\n"); DPRINT1("creating virtual pin\n");
/* now create the virtual audio pin which is exposed to wdmaud */ /* now create the virtual audio pin which is exposed to wdmaud */
Status = KsCreatePin(Filter, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &PinHandle); Status = KsCreatePin(Filter, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &VirtualPinHandle);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -237,7 +229,7 @@ CreatePinWorkerRoutine(
} }
/* get pin file object */ /* get pin file object */
Status = ObReferenceObjectByHandle(PinHandle, Status = ObReferenceObjectByHandle(VirtualPinHandle,
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
@ -250,7 +242,7 @@ CreatePinWorkerRoutine(
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References = 0; WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References = 0;
} }
ZwClose(PinHandle); ZwClose(VirtualPinHandle);
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0); SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
ExFreePool(WorkerContext); ExFreePool(WorkerContext);
return; return;
@ -261,19 +253,59 @@ CreatePinWorkerRoutine(
ASSERT(WorkerContext->DispatchContext->FileObject != NULL); ASSERT(WorkerContext->DispatchContext->FileObject != NULL);
ASSERT(WorkerContext->DispatchContext->Handle != NULL); ASSERT(WorkerContext->DispatchContext->Handle != NULL);
ASSERT(WorkerContext->AudioClient); ASSERT(WorkerContext->AudioClient);
ASSERT(WorkerContext->AudioClient->Handels); ASSERT(WorkerContext->AudioClient->NumDevices > 0);
ASSERT(WorkerContext->AudioClient->Handels[WorkerContext->AudioClient->NumDevices -1] == NULL); ASSERT(WorkerContext->AudioClient->Devs != NULL);
ASSERT(WorkerContext->Entry->Pins != NULL);
ASSERT(WorkerContext->Entry->NumberOfPins > WorkerContext->PinConnect->PinId);
AudioClient = WorkerContext->AudioClient;
NumHandels = AudioClient->Devs[AudioClient->NumDevices -1].ClientHandlesCount;
ClientPinHandle = ExAllocatePool(NonPagedPool, sizeof(SYSAUDIO_PIN_HANDLE) * (NumHandels+1));
if (ClientPinHandle)
{
if (NumHandels)
{
ASSERT(AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles != NULL);
RtlMoveMemory(ClientPinHandle,
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles,
sizeof(SYSAUDIO_PIN_HANDLE) * NumHandels);
ExFreePool(AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles);
}
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles = ClientPinHandle;
/// if the pin can be instantiated more than once
/// then store the real pin handle in the client context
/// otherwise just the pin id of the available pin
if (WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].MaxPinInstanceCount > 1)
{
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].bHandle = TRUE;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = RealPinHandle;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId;
}
else
{
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].bHandle = FALSE;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = NULL;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId;
}
/// increase reference count
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References++;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandlesCount++;
}
/* store pin context */ /* store pin context */
FileObject->FsContext2 = (PVOID)WorkerContext->DispatchContext; FileObject->FsContext2 = (PVOID)WorkerContext->DispatchContext;
/* store pin handle in client specific struct */ DPRINT1("Successfully created virtual pin %p\n", VirtualPinHandle);
WorkerContext->AudioClient->Handels[WorkerContext->AudioClient->NumDevices-1] = PinHandle; *((PHANDLE)WorkerContext->Irp->UserBuffer) = VirtualPinHandle;
DPRINT1("Successfully created Pin %p\n", WorkerContext->Irp);
*((PHANDLE)WorkerContext->Irp->UserBuffer) = PinHandle;
SetIrpIoStatus(WorkerContext->Irp, STATUS_SUCCESS, sizeof(HANDLE)); SetIrpIoStatus(WorkerContext->Irp, STATUS_SUCCESS, sizeof(HANDLE));
ExFreePool(WorkerContext);
} }
@ -425,7 +457,7 @@ SysAudioHandleProperty(
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
} }
/* store last opened device number */ /* store last opened device number */
*Index = ClientInfo->Devices[ClientInfo->NumDevices-1]; *Index = ClientInfo->Devs[ClientInfo->NumDevices-1].DeviceId;
/* found no device with that device index open */ /* found no device with that device index open */
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(ULONG)); return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(ULONG));
} }
@ -458,7 +490,7 @@ SysAudioHandleProperty(
} }
for(Count = 0; Count < ClientInfo->NumDevices; Count++) for(Count = 0; Count < ClientInfo->NumDevices; Count++)
{ {
if (ClientInfo->Devices[Count] == InstanceInfo->DeviceNumber) if (ClientInfo->Devs[Count].DeviceId == InstanceInfo->DeviceNumber)
{ {
/* specified device is open */ /* specified device is open */
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0); return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
@ -493,8 +525,8 @@ SysAudioHandleProperty(
ClientInfo = (PSYSAUDIO_CLIENT)CreateItem->Context; ClientInfo = (PSYSAUDIO_CLIENT)CreateItem->Context;
ASSERT(ClientInfo); ASSERT(ClientInfo);
ASSERT(ClientInfo->NumDevices >= 1); ASSERT(ClientInfo->NumDevices >= 1);
ASSERT(ClientInfo->Devices != NULL); ASSERT(ClientInfo->Devs != NULL);
ASSERT(ClientInfo->Devices[ClientInfo->NumDevices-1] == InstanceInfo->DeviceNumber); ASSERT(ClientInfo->Devs[ClientInfo->NumDevices-1].DeviceId == InstanceInfo->DeviceNumber);
/* get sysaudio entry */ /* get sysaudio entry */
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, InstanceInfo->DeviceNumber); Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, InstanceInfo->DeviceNumber);
@ -541,14 +573,14 @@ SysAudioHandleProperty(
PinRequest.Property.Flags = KSPROPERTY_TYPE_GET; PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES; PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES;
//RtlZeroMemory(&PinInstances, sizeof(KSPIN_CINSTANCES));
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned); Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("Property Request KSPROPERTY_PIN_GLOBALCINSTANCES failed with %x\n", Status); DPRINT("Property Request KSPROPERTY_PIN_GLOBALCINSTANCES failed with %x\n", Status);
return SetIrpIoStatus(Irp, Status, 0); return SetIrpIoStatus(Irp, Status, 0);
} }
DPRINT1("PinInstances Current %u Max %u\n", PinInstances.CurrentCount, PinInstances.PossibleCount); DPRINT("PinInstances Current %u Max %u\n", PinInstances.CurrentCount, PinInstances.PossibleCount);
Entry->Pins[PinConnect->PinId].MaxPinInstanceCount = PinInstances.PossibleCount;
WorkItem = IoAllocateWorkItem(DeviceObject); WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkItem) if (!WorkItem)
@ -588,10 +620,10 @@ SysAudioHandleProperty(
DbgBreakPoint(); DbgBreakPoint();
ASSERT(Entry->Pins[PinConnect->PinId].PinHandle != NULL); ASSERT(Entry->Pins[PinConnect->PinId].PinHandle != NULL);
if (Entry->Pins[PinConnect->PinId].References != 0) if (Entry->Pins[PinConnect->PinId].References > 1)
{ {
/* FIXME need ksmixer */ /* FIXME need ksmixer */
DPRINT1("Device %u Pin %u is already occupied, try later\n", InstanceInfo->DeviceNumber, PinConnect->PinId); DPRINT1("Device %u Pin %u References %u is already occupied, try later\n", InstanceInfo->DeviceNumber, PinConnect->PinId, Entry->Pins[PinConnect->PinId].References);
IoFreeWorkItem(WorkItem); IoFreeWorkItem(WorkItem);
ExFreePool(WorkerContext); ExFreePool(WorkerContext);
ExFreePool(DispatchContext); ExFreePool(DispatchContext);

View file

@ -91,30 +91,48 @@ Dispatch_fnClose(
PIRP Irp) PIRP Irp)
{ {
PSYSAUDIO_CLIENT Client; PSYSAUDIO_CLIENT Client;
PKSAUDIO_DEVICE_ENTRY Entry;
PIO_STACK_LOCATION IoStatus; PIO_STACK_LOCATION IoStatus;
ULONG Index; ULONG Index, SubIndex;
PSYSAUDIODEVEXT DeviceExtension;
DPRINT1("Dispatch_fnClose called DeviceObject %p Irp %p\n", DeviceObject);
IoStatus = IoGetCurrentIrpStackLocation(Irp); IoStatus = IoGetCurrentIrpStackLocation(Irp);
Client = (PSYSAUDIO_CLIENT)IoStatus->FileObject->FsContext2; Client = (PSYSAUDIO_CLIENT)IoStatus->FileObject->FsContext2;
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
DPRINT1("Client %p NumDevices %u\n", Client, Client->NumDevices); DPRINT1("Client %p NumDevices %u\n", Client, Client->NumDevices);
for(Index = 0; Index < Client->NumDevices; Index++) for(Index = 0; Index < Client->NumDevices; Index++)
{ {
if (Client->Handels[Index]) if (Client->Devs[Index].ClientHandlesCount)
{ {
ZwClose(Client->Handels[Index]); Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, Client->Devs[Index].DeviceId);
ASSERT(Entry != NULL);
for(SubIndex = 0; SubIndex < Client->Devs[Index].ClientHandlesCount; SubIndex++)
{
ASSERT(Entry->NumberOfPins > Client->Devs[Index].ClientHandles[SubIndex].PinId);
if (Client->Devs[Index].ClientHandles[SubIndex].bHandle)
{
DPRINT1("Closing handle %p\n", Client->Devs[Index].ClientHandles[SubIndex].hPin);
ZwClose(Client->Devs[Index].ClientHandles[SubIndex].hPin);
Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References--;
}
else
{
/* this is pin which can only be instantiated once
* so we just need to release the reference count on that pin */
Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References--;
}
}
ExFreePool(Client->Devs[Index].ClientHandles);
} }
} }
if (Client->Handels) if (Client->Devs)
ExFreePool(Client->Handels); ExFreePool(Client->Devs);
if (Client->Devices)
ExFreePool(Client->Devices);
ExFreePool(Client); ExFreePool(Client);
@ -250,7 +268,8 @@ DispatchCreateSysAudio(
if (!wcsncmp(KS_NAME_PIN, Buffer, wcslen(KS_NAME_PIN))) if (!wcsncmp(KS_NAME_PIN, Buffer, wcslen(KS_NAME_PIN)))
{ {
Status = CreateDispatcher(Irp); Status = CreateDispatcher(Irp);
DPRINT1("Virtual pin Status %x\n", Status); DPRINT1("Virtual pin Status %x FileObject %p\n", Status, IoStatus->FileObject);
DbgBreakPoint();
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);

View file

@ -1,16 +1,32 @@
#ifndef SYSAUDIO_H__ #ifndef SYSAUDIO_H__
#define SYSAUDIO_H__ #define SYSAUDIO_H__
typedef struct
{
BOOL bHandle;
ULONG PinId;
HANDLE hPin;
}SYSAUDIO_PIN_HANDLE, *PSYSAUDIO_PIN_HANDLE;
typedef struct
{
ULONG DeviceId;
ULONG ClientHandlesCount;
PSYSAUDIO_PIN_HANDLE ClientHandles;
}SYSAUDIO_CLIENT_HANDELS, *PSYSAUDIO_CLIENT_HANDELS;
typedef struct typedef struct
{ {
ULONG NumDevices; ULONG NumDevices;
PULONG Devices; PSYSAUDIO_CLIENT_HANDELS Devs;
PHANDLE Handels;
}SYSAUDIO_CLIENT, *PSYSAUDIO_CLIENT; }SYSAUDIO_CLIENT, *PSYSAUDIO_CLIENT;
typedef struct typedef struct
{ {
ULONG MaxPinInstanceCount;
HANDLE PinHandle; HANDLE PinHandle;
ULONG References; ULONG References;
}PIN_INFO; }PIN_INFO;