mirror of
https://github.com/reactos/reactos.git
synced 2024-10-05 00:43:21 +00:00
[KS]
- The pin creation parameters are now placed right after the reference string. Handle this case in KsValidateConnectRequest - Only store the passed create items, no need to copy the passed create items. This is required for enabling dynamic audio devices - Fix copying of the object class in KsAllocateObjectHeader - Check for KSCREATE_ITEM_IRP_STORAGE flag in KsCreate [PORTCLS] - Reduce initial audio buffer to about 1/3 second which greatly improves performance [SYSAUDIO] - Remove concept of audio subdevices - Remove imported KsCreatePin - Replace OpenDevice loop hack svn path=/trunk/; revision=41842
This commit is contained in:
parent
976cb25f51
commit
b046ce1926
|
@ -45,15 +45,23 @@ KsValidateConnectRequest(
|
|||
PKSPIN_CONNECT ConnectDetails;
|
||||
LPWSTR PinName = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}\\";
|
||||
PKSDATAFORMAT DataFormat;
|
||||
LPWSTR Offset;
|
||||
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
if (!IoStack->FileObject->FileName.Buffer)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (wcsncmp(IoStack->FileObject->FileName.Buffer, PinName, wcslen(PinName)))
|
||||
if (IoStack->FileObject->FileName.Length < wcslen(PinName) + sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
ConnectDetails = (PKSPIN_CONNECT)(IoStack->FileObject->FileName.Buffer + wcslen(PinName));
|
||||
Offset = wcsstr(IoStack->FileObject->FileName.Buffer, PinName);
|
||||
if (!Offset)
|
||||
{
|
||||
/* request is not targeted for a pin */
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ConnectDetails = (PKSPIN_CONNECT)(Offset + wcslen(PinName));
|
||||
|
||||
if (ConnectDetails->PinToHandle != NULL)
|
||||
{
|
||||
|
@ -61,11 +69,6 @@ KsValidateConnectRequest(
|
|||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (IoStack->FileObject->FileName.Length < wcslen(PinName) + sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
ConnectDetails = (PKSPIN_CONNECT)(IoStack->FileObject->FileName.Buffer + wcslen(PinName));
|
||||
|
||||
if (ConnectDetails->PinId >= DescriptorsCount)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
|
|
|
@ -104,14 +104,15 @@ KsAddObjectCreateItemToDeviceHeader(
|
|||
/* now scan the list and check for a free item */
|
||||
for(Index = 0; Index < Header->MaxItems; Index++)
|
||||
{
|
||||
if (!Header->ItemList[Index].bCreated)
|
||||
{
|
||||
if (FreeIndex == (ULONG)-1)
|
||||
FreeIndex = Index;
|
||||
ASSERT(Header->ItemList[Index].CreateItem);
|
||||
|
||||
continue;
|
||||
if (Header->ItemList[Index].CreateItem->Create == NULL)
|
||||
{
|
||||
FreeIndex = Index;
|
||||
break;
|
||||
}
|
||||
else if (!wcsicmp(ObjectClass, Header->ItemList[Index].CreateItem.ObjectClass.Buffer))
|
||||
|
||||
if (!wcsicmp(ObjectClass, Header->ItemList[Index].CreateItem->ObjectClass.Buffer))
|
||||
{
|
||||
/* the same object class already exists */
|
||||
return STATUS_OBJECT_NAME_COLLISION;
|
||||
|
@ -120,26 +121,17 @@ KsAddObjectCreateItemToDeviceHeader(
|
|||
/* found a free index */
|
||||
if (FreeIndex == (ULONG)-1)
|
||||
{
|
||||
/* allocate a new device entry */
|
||||
PDEVICE_ITEM Item = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_ITEM) * (Header->MaxItems + 1), TAG_DEVICE_HEADER);
|
||||
if (!Item)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
RtlMoveMemory(Item, Header->ItemList, Header->MaxItems * sizeof(DEVICE_ITEM));
|
||||
ExFreePoolWithTag(Header->ItemList, TAG_DEVICE_HEADER);
|
||||
|
||||
Header->ItemList = Item;
|
||||
FreeIndex = Header->MaxItems;
|
||||
Header->MaxItems++;
|
||||
/* no empty space found */
|
||||
return STATUS_ALLOTTED_SPACE_EXCEEDED;
|
||||
}
|
||||
|
||||
/* store the new item */
|
||||
Header->ItemList[FreeIndex].bCreated = TRUE;
|
||||
Header->ItemList[FreeIndex].CreateItem.Create = Create;
|
||||
Header->ItemList[FreeIndex].CreateItem.Context = Context;
|
||||
RtlInitUnicodeString(&Header->ItemList[FreeIndex].CreateItem.ObjectClass, ObjectClass);
|
||||
Header->ItemList[FreeIndex].CreateItem.SecurityDescriptor = SecurityDescriptor;
|
||||
Header->ItemList[FreeIndex].CreateItem.Flags = 0;
|
||||
/* initialize create item */
|
||||
Header->ItemList[FreeIndex].CreateItem->Create = Create;
|
||||
Header->ItemList[FreeIndex].CreateItem->Context = Context;
|
||||
RtlInitUnicodeString(&Header->ItemList[FreeIndex].CreateItem->ObjectClass, ObjectClass);
|
||||
Header->ItemList[FreeIndex].CreateItem->SecurityDescriptor = SecurityDescriptor;
|
||||
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -187,12 +179,8 @@ KsAllocateDeviceHeader(
|
|||
|
||||
for(Index = 0; Index < ItemsCount; Index++)
|
||||
{
|
||||
/* copy provided create items */
|
||||
RtlMoveMemory(&Header->ItemList[Index].CreateItem, &ItemsList[Index], sizeof(KSOBJECT_CREATE_ITEM));
|
||||
if (ItemsList[Index].Create!= NULL)
|
||||
{
|
||||
Header->ItemList[Index].bCreated = TRUE;
|
||||
}
|
||||
/* store provided create items */
|
||||
Header->ItemList[Index].CreateItem = &ItemsList[Index];
|
||||
}
|
||||
Header->MaxItems = ItemsCount;
|
||||
}
|
||||
|
@ -294,7 +282,6 @@ KsAllocateObjectHeader(
|
|||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
WCHAR ObjectClass[50];
|
||||
|
||||
if (!Header)
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
|
@ -312,18 +299,10 @@ KsAllocateObjectHeader(
|
|||
/* get device header */
|
||||
DeviceHeader = DeviceExtension->DeviceHeader;
|
||||
|
||||
ObjectClass[0] = L'\0';
|
||||
/* sanity check */
|
||||
ASSERT(IoStack->FileObject);
|
||||
/* check for an file object */
|
||||
if (IoStack->FileObject != NULL)
|
||||
{
|
||||
/* validate the file name */
|
||||
if (IoStack->FileObject->FileName.Length >= 38)
|
||||
{
|
||||
RtlMoveMemory(ObjectClass, IoStack->FileObject->FileName.Buffer, 38 * sizeof(WCHAR));
|
||||
ObjectClass[38] = L'\0';
|
||||
DPRINT("ObjectClass %S\n", ObjectClass);
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate the object header */
|
||||
ObjectHeader = ExAllocatePoolWithTag(NonPagedPool, sizeof(KSIOBJECT_HEADER), TAG_DEVICE_HEADER);
|
||||
if (!ObjectHeader)
|
||||
|
@ -333,13 +312,17 @@ KsAllocateObjectHeader(
|
|||
RtlZeroMemory(ObjectHeader, sizeof(KSIOBJECT_HEADER));
|
||||
|
||||
/* do we have a name */
|
||||
if (ObjectClass[0])
|
||||
if (IoStack->FileObject->FileName.Buffer)
|
||||
{
|
||||
ObjectHeader->ObjectClass = ExAllocatePoolWithTag(NonPagedPool, 40 * sizeof(WCHAR), TAG_DEVICE_HEADER);
|
||||
if (ObjectHeader->ObjectClass)
|
||||
/* copy object class */
|
||||
ObjectHeader->ObjectClass.MaximumLength = IoStack->FileObject->FileName.MaximumLength;
|
||||
ObjectHeader->ObjectClass.Buffer = ExAllocatePoolWithTag(NonPagedPool, ObjectHeader->ObjectClass.MaximumLength, TAG_DEVICE_HEADER);
|
||||
if (!ObjectHeader->ObjectClass.Buffer)
|
||||
{
|
||||
wcscpy(ObjectHeader->ObjectClass, ObjectClass);
|
||||
ExFreePoolWithTag(ObjectHeader, TAG_DEVICE_HEADER);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
RtlCopyUnicodeString(&ObjectHeader->ObjectClass, &IoStack->FileObject->FileName);
|
||||
}
|
||||
|
||||
/* copy dispatch table */
|
||||
|
@ -362,7 +345,6 @@ KsAllocateObjectHeader(
|
|||
{
|
||||
/* the object header is for a audio filter */
|
||||
ASSERT(DeviceHeader->DeviceIndex < DeviceHeader->MaxItems);
|
||||
DeviceHeader->ItemList[DeviceHeader->DeviceIndex].ObjectHeader = ObjectHeader;
|
||||
IoStack->FileObject->FsContext = ObjectHeader;
|
||||
}
|
||||
|
||||
|
@ -370,7 +352,7 @@ KsAllocateObjectHeader(
|
|||
*Header = ObjectHeader;
|
||||
|
||||
|
||||
DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectClass, IoStack->FileObject, ObjectHeader);
|
||||
DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectHeader->ObjectClass.Buffer, IoStack->FileObject, ObjectHeader);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
|
@ -725,8 +707,9 @@ KsCreate(
|
|||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
ULONG Index;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
NTSTATUS Status;
|
||||
KIRQL OldLevel;
|
||||
ULONG Length;
|
||||
|
||||
DPRINT("KS / CREATE\n");
|
||||
/* get current stack location */
|
||||
|
@ -738,56 +721,85 @@ KsCreate(
|
|||
|
||||
/* acquire list lock */
|
||||
KeAcquireSpinLock(&DeviceHeader->ItemListLock, &OldLevel);
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(IoStack->FileObject);
|
||||
|
||||
if (IoStack->FileObject->FileName.Buffer == NULL && DeviceHeader->MaxItems == 1)
|
||||
{
|
||||
/* hack for bug 4566 */
|
||||
if (!DeviceHeader->ItemList[0].CreateItem || !DeviceHeader->ItemList[0].CreateItem->Create)
|
||||
{
|
||||
/* no valid create item */
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&DeviceHeader->ItemListLock, OldLevel);
|
||||
/* return status */
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* set object create item */
|
||||
KSCREATE_ITEM_IRP_STORAGE(Irp) = DeviceHeader->ItemList[0].CreateItem;
|
||||
|
||||
/* call create function */
|
||||
Status = DeviceHeader->ItemList[0].CreateItem->Create(DeviceObject, Irp);
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&DeviceHeader->ItemListLock, OldLevel);
|
||||
/* return result */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/* hack for bug 4566 */
|
||||
if (IoStack->FileObject->FileName.Buffer == NULL)
|
||||
{
|
||||
DPRINT("Using reference string hack\n");
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&DeviceHeader->ItemListLock, OldLevel);
|
||||
Irp->IoStatus.Information = 0;
|
||||
/* set return status */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* loop all device items */
|
||||
for(Index = 0; Index < DeviceHeader->MaxItems; Index++)
|
||||
{
|
||||
if (DeviceHeader->ItemList[Index].bCreated && DeviceHeader->ItemList[Index].ObjectHeader == NULL)
|
||||
/* is there a create item */
|
||||
if (DeviceHeader->ItemList[Index].CreateItem == NULL)
|
||||
continue;
|
||||
|
||||
/* check if the create item is initialized */
|
||||
if (!DeviceHeader->ItemList[Index].CreateItem->Create)
|
||||
continue;
|
||||
|
||||
ASSERT(DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer);
|
||||
DPRINT("CreateItem %p Request %S\n", DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer,
|
||||
IoStack->FileObject->FileName.Buffer);
|
||||
|
||||
/* get object class length */
|
||||
Length = wcslen(DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer);
|
||||
/* now check if the object class is the same */
|
||||
if (!_wcsnicmp(DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer, &IoStack->FileObject->FileName.Buffer[1], Length) ||
|
||||
(DeviceHeader->ItemList[Index].CreateItem->Flags & KSCREATE_ITEM_WILDCARD))
|
||||
{
|
||||
/* setup create parameters */
|
||||
DeviceHeader->DeviceIndex = Index;
|
||||
/* set object create item */
|
||||
KSCREATE_ITEM_IRP_STORAGE(Irp) = &DeviceHeader->ItemList[Index].CreateItem;
|
||||
Status = DeviceHeader->ItemList[Index].CreateItem.Create(DeviceObject, Irp);
|
||||
KSCREATE_ITEM_IRP_STORAGE(Irp) = DeviceHeader->ItemList[Index].CreateItem;
|
||||
|
||||
/* FIXME IoRegisterDeviceInterface does not support reference strings */
|
||||
/* FIXME Check the irp target with the create item's object class */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&DeviceHeader->ItemListLock, OldLevel);
|
||||
return Status;
|
||||
}
|
||||
/* call create function */
|
||||
Status = DeviceHeader->ItemList[Index].CreateItem->Create(DeviceObject, Irp);
|
||||
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&DeviceHeader->ItemListLock, OldLevel);
|
||||
|
||||
/* return result */
|
||||
return Status;
|
||||
}
|
||||
else if (DeviceHeader->ItemList[Index].bCreated && IoStack->FileObject->FileName.Buffer != NULL)
|
||||
{
|
||||
ULONG Length;
|
||||
|
||||
ASSERT(DeviceHeader->ItemList[Index].ObjectHeader);
|
||||
ASSERT(DeviceHeader->ItemList[Index].ObjectHeader->CreateItem);
|
||||
ASSERT(DeviceHeader->ItemList[Index].ObjectHeader->CreateItem->ObjectClass.Buffer);
|
||||
|
||||
Length = wcslen(DeviceHeader->ItemList[Index].ObjectHeader->CreateItem->ObjectClass.Buffer);
|
||||
|
||||
/* filter for that type has already exists */
|
||||
if (!_wcsnicmp(DeviceHeader->ItemList[Index].ObjectHeader->CreateItem->ObjectClass.Buffer,
|
||||
IoStack->FileObject->FileName.Buffer,
|
||||
Length))
|
||||
{
|
||||
if (IoStack->FileObject->FileName.Buffer[0] != L'{')
|
||||
{
|
||||
RtlMoveMemory(IoStack->FileObject->FileName.Buffer, &IoStack->FileObject->FileName.Buffer[Length+1],
|
||||
IoStack->FileObject->FileName.Length - (Length + 1) * sizeof(WCHAR));
|
||||
|
||||
IoStack->FileObject->FileName.Length -= (Length + 1)* sizeof(WCHAR);
|
||||
}
|
||||
|
||||
|
||||
KSCREATE_ITEM_IRP_STORAGE(Irp) = &DeviceHeader->ItemList[Index].CreateItem;
|
||||
Status = DeviceHeader->ItemList[Index].CreateItem.Create(DeviceObject, Irp);
|
||||
KeReleaseSpinLock(&DeviceHeader->ItemListLock, OldLevel);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* release lock */
|
||||
|
@ -810,7 +822,6 @@ KsClose(
|
|||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
ULONG Index;
|
||||
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
@ -827,20 +838,20 @@ KsClose(
|
|||
ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
|
||||
|
||||
KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
|
||||
|
||||
for(Index = 0; Index < DeviceHeader->MaxItems; Index++)
|
||||
{
|
||||
if (DeviceHeader->ItemList[Index].ObjectHeader == ObjectHeader)
|
||||
{
|
||||
DeviceHeader->ItemList[Index].ObjectHeader = NULL;
|
||||
}
|
||||
}
|
||||
return ObjectHeader->DispatchTable.Close(DeviceObject, Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
DPRINT1("Expected Object Header FileObject %p FsContext %p\n", IoStack->FileObject, IoStack->FileObject->FsContext);
|
||||
KeBugCheckEx(0, 0, 0, 0, 0);
|
||||
#else
|
||||
DPRINT("Using reference string hack\n");
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
#endif
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -853,10 +864,63 @@ KsDeviceControl(
|
|||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
ULONG Length, Index;
|
||||
LPWSTR Buffer;
|
||||
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* hack for bug 4566 */
|
||||
if (IoStack->MajorFunction == IRP_MJ_DEVICE_CONTROL && IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_OBJECT_CLASS)
|
||||
{
|
||||
/* get device extension */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
|
||||
/* get device header */
|
||||
DeviceHeader = DeviceExtension->DeviceHeader;
|
||||
|
||||
/* retrieve all available reference strings registered */
|
||||
Length = 0;
|
||||
|
||||
for(Index = 0; Index < DeviceHeader->MaxItems; Index++)
|
||||
{
|
||||
if (!DeviceHeader->ItemList[Index].CreateItem || !DeviceHeader->ItemList[Index].CreateItem->Create || !DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer)
|
||||
continue;
|
||||
|
||||
Length += wcslen(DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer) + 1;
|
||||
}
|
||||
|
||||
/* add extra zero */
|
||||
Length += 1;
|
||||
|
||||
/* allocate the buffer */
|
||||
Buffer = ExAllocatePool(NonPagedPool, Length * sizeof(WCHAR));
|
||||
if (!Buffer)
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
*((LPWSTR*)Irp->UserBuffer) = Buffer;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(LPWSTR);
|
||||
|
||||
for(Index = 0; Index < DeviceHeader->MaxItems; Index++)
|
||||
{
|
||||
if (!DeviceHeader->ItemList[Index].CreateItem || !DeviceHeader->ItemList[Index].CreateItem->Create || !DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer)
|
||||
continue;
|
||||
|
||||
wcscpy(Buffer, DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer);
|
||||
Buffer += wcslen(Buffer) + 1;
|
||||
}
|
||||
*Buffer = L'\0';
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DPRINT("KS / DeviceControl\n");
|
||||
if (IoStack->FileObject && IoStack->FileObject->FsContext)
|
||||
{
|
||||
|
@ -864,14 +928,6 @@ KsDeviceControl(
|
|||
|
||||
KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
|
||||
|
||||
if (IoStack->MajorFunction == IRP_MJ_DEVICE_CONTROL && IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_OBJECT_CLASS)
|
||||
{
|
||||
*((LPWSTR*)Irp->UserBuffer) = ObjectHeader->CreateItem->ObjectClass.Buffer;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(LPWSTR);
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
return ObjectHeader->DispatchTable.DeviceIoControl(DeviceObject, Irp);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -6,17 +6,15 @@ struct KSIDEVICE_HEADER;
|
|||
typedef struct
|
||||
{
|
||||
KSDISPATCH_TABLE DispatchTable;
|
||||
LPWSTR ObjectClass;
|
||||
ULONG ItemCount;
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
|
||||
UNICODE_STRING ObjectClass;
|
||||
}KSIOBJECT_HEADER, *PKSIOBJECT_HEADER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BOOL bCreated;
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
KSOBJECT_CREATE_ITEM CreateItem;
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
}DEVICE_ITEM, *PDEVICE_ITEM;
|
||||
|
||||
|
||||
|
|
|
@ -282,16 +282,18 @@ KsSynchronousIoControlDevice(
|
|||
if (!DeviceObject)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
|
||||
/* get object header */
|
||||
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
|
||||
#if 0
|
||||
if (!ObjectHeader)
|
||||
{
|
||||
DPRINT("Expected object header\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* check if there is fast device io function */
|
||||
if (ObjectHeader->DispatchTable.FastDeviceIoControl)
|
||||
if (ObjectHeader && ObjectHeader->DispatchTable.FastDeviceIoControl)
|
||||
{
|
||||
IoStatusBlock.Status = STATUS_UNSUCCESSFUL;
|
||||
IoStatusBlock.Information = 0;
|
||||
|
|
|
@ -17,26 +17,56 @@ KspCreateObjectType(
|
|||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
PFILE_OBJECT FileObject;
|
||||
UNICODE_STRING Name;
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
|
||||
Name.Length = Name.MaximumLength = (wcslen(ObjectType) + 1) * sizeof(WCHAR) + CreateParametersSize;
|
||||
/* acquire parent file object */
|
||||
Status = ObReferenceObjectByHandle(ParentHandle,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Failed to reference parent %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* get parent object header */
|
||||
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
|
||||
/* sanity check */
|
||||
ASSERT(ObjectHeader);
|
||||
|
||||
/* calculate request length */
|
||||
Name.Length = 0;
|
||||
Name.MaximumLength = wcslen(ObjectType) * sizeof(WCHAR) + CreateParametersSize + ObjectHeader->ObjectClass.MaximumLength + 2 * sizeof(WCHAR);
|
||||
Name.MaximumLength += sizeof(WCHAR);
|
||||
/* acquire request buffer */
|
||||
Name.Buffer = ExAllocatePool(NonPagedPool, Name.MaximumLength);
|
||||
|
||||
/* check for success */
|
||||
if (!Name.Buffer)
|
||||
{
|
||||
/* insufficient resources */
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
wcscpy(Name.Buffer, ObjectType);
|
||||
Name.Buffer[wcslen(ObjectType)] = '\\';
|
||||
|
||||
RtlMoveMemory(Name.Buffer + wcslen(ObjectType) +1, CreateParameters, CreateParametersSize);
|
||||
/* build a request which looks like \Parent\{ObjectGuid}\CreateParameters
|
||||
* For pins the parent is the reference string used in registration
|
||||
* For clocks it is full path for pin\{ClockGuid}\ClockCreateParams
|
||||
*/
|
||||
|
||||
RtlAppendUnicodeStringToString(&Name, &ObjectHeader->ObjectClass);
|
||||
RtlAppendUnicodeToString(&Name, L"\\");
|
||||
RtlAppendUnicodeToString(&Name, ObjectType);
|
||||
RtlAppendUnicodeToString(&Name, L"\\");
|
||||
/* append create parameters */
|
||||
RtlMoveMemory(Name.Buffer + (Name.Length / sizeof(WCHAR)), CreateParameters, CreateParametersSize);
|
||||
Name.Length += CreateParametersSize;
|
||||
Name.Buffer[Name.Length / 2] = L'\0';
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, ParentHandle, NULL);
|
||||
|
||||
|
||||
/* create the instance */
|
||||
Status = IoCreateFile(NodeHandle,
|
||||
DesiredAccess,
|
||||
&ObjectAttributes,
|
||||
|
@ -52,7 +82,10 @@ KspCreateObjectType(
|
|||
NULL,
|
||||
IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK);
|
||||
|
||||
/* free request buffer */
|
||||
ExFreePool(Name.Buffer);
|
||||
/* release parent handle */
|
||||
ObDereferenceObject(FileObject);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -314,7 +314,7 @@ IIrpQueue_fnMinimumDataAvailable(
|
|||
if (This->StartStream)
|
||||
return TRUE;
|
||||
|
||||
if (This->DataFormat->WaveFormatEx.nAvgBytesPerSec < This->NumDataAvailable)
|
||||
if (This->DataFormat->WaveFormatEx.nAvgBytesPerSec/3 < This->NumDataAvailable)
|
||||
{
|
||||
This->StartStream = TRUE;
|
||||
Result = TRUE;
|
||||
|
|
|
@ -542,6 +542,8 @@ PcCreateItemDispatch(
|
|||
IIrpTarget *Filter;
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
PPIN_WORKER_CONTEXT Context;
|
||||
LPWSTR Buffer;
|
||||
static LPWSTR KS_NAME_PIN = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}";
|
||||
|
||||
DPRINT1("PcCreateItemDispatch called DeviceObject %p\n", DeviceObject);
|
||||
|
||||
|
@ -604,60 +606,55 @@ PcCreateItemDispatch(
|
|||
return Status;
|
||||
}
|
||||
|
||||
/* is just the filter requested */
|
||||
if (IoStack->FileObject->FileName.Buffer == NULL)
|
||||
/* get the buffer */
|
||||
Buffer = IoStack->FileObject->FileName.Buffer;
|
||||
|
||||
/* check if the request contains a pin request */
|
||||
if (!wcsstr(Buffer, KS_NAME_PIN))
|
||||
{
|
||||
/* create the dispatch object */
|
||||
/* creator just wants the filter object */
|
||||
Status = NewDispatchObject(Irp, Filter, CreateItem->ObjectClass.Buffer);
|
||||
|
||||
DPRINT1("Filter %p\n", Filter);
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
else
|
||||
{
|
||||
LPWSTR Buffer = IoStack->FileObject->FileName.Buffer;
|
||||
|
||||
static LPWSTR KS_NAME_PIN = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}";
|
||||
|
||||
/* is the request for a new pin */
|
||||
if (!wcsncmp(KS_NAME_PIN, Buffer, wcslen(KS_NAME_PIN)))
|
||||
/* try to create new pin */
|
||||
Context = AllocateItem(NonPagedPool, sizeof(PIN_WORKER_CONTEXT), TAG_PORTCLASS);
|
||||
if (!Context)
|
||||
{
|
||||
/* try to create new pin */
|
||||
Context = AllocateItem(NonPagedPool, sizeof(PIN_WORKER_CONTEXT), TAG_PORTCLASS);
|
||||
if (!Context)
|
||||
{
|
||||
DPRINT("Failed to allocate worker context\n");
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
/* allocate work item */
|
||||
Context->WorkItem = IoAllocateWorkItem(DeviceObject);
|
||||
if (!Context->WorkItem)
|
||||
{
|
||||
DPRINT("Failed to allocate workitem\n");
|
||||
FreeItem(Context, TAG_PORTCLASS);
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Context->Filter = Filter;
|
||||
Context->Irp = Irp;
|
||||
|
||||
DPRINT("Queueing IRP %p Irql %u\n", Irp, KeGetCurrentIrql());
|
||||
DPRINT("Failed to allocate worker context\n");
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_PENDING;
|
||||
IoMarkIrpPending(Irp);
|
||||
IoQueueWorkItem(Context->WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
|
||||
return STATUS_PENDING;
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
/* allocate work item */
|
||||
Context->WorkItem = IoAllocateWorkItem(DeviceObject);
|
||||
if (!Context->WorkItem)
|
||||
{
|
||||
DPRINT("Failed to allocate workitem\n");
|
||||
FreeItem(Context, TAG_PORTCLASS);
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Context->Filter = Filter;
|
||||
Context->Irp = Irp;
|
||||
|
||||
DPRINT("Queueing IRP %p Irql %u\n", Irp, KeGetCurrentIrql());
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_PENDING;
|
||||
IoMarkIrpPending(Irp);
|
||||
IoQueueWorkItem(Context->WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ DispatchCreateKMix(
|
|||
if (Buffer)
|
||||
{
|
||||
/* is the request for a new pin */
|
||||
if (!wcsncmp(KS_NAME_PIN, Buffer, wcslen(KS_NAME_PIN)))
|
||||
if (!wcsstr(KS_NAME_PIN, Buffer))
|
||||
{
|
||||
Status = CreatePin(Irp);
|
||||
|
||||
|
|
|
@ -20,97 +20,13 @@ const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce,
|
|||
|
||||
NTSTATUS
|
||||
ComputeCompatibleFormat(
|
||||
IN PKSAUDIO_SUBDEVICE_ENTRY Entry,
|
||||
IN PKSAUDIO_DEVICE_ENTRY Entry,
|
||||
IN ULONG PinId,
|
||||
IN PSYSAUDIODEVEXT DeviceExtension,
|
||||
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
||||
OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat);
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspCreateObjectType(
|
||||
IN HANDLE ParentHandle,
|
||||
IN LPWSTR ObjectType,
|
||||
PVOID CreateParameters,
|
||||
UINT CreateParametersSize,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
OUT PHANDLE NodeHandle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING Name;
|
||||
|
||||
Name.Length = Name.MaximumLength = (wcslen(ObjectType) + 1) * sizeof(WCHAR) + CreateParametersSize;
|
||||
Name.MaximumLength += sizeof(WCHAR);
|
||||
Name.Buffer = ExAllocatePool(NonPagedPool, Name.MaximumLength);
|
||||
|
||||
if (!Name.Buffer)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
wcscpy(Name.Buffer, ObjectType);
|
||||
Name.Buffer[wcslen(ObjectType)] = '\\';
|
||||
|
||||
RtlMoveMemory(Name.Buffer + wcslen(ObjectType) +1, CreateParameters, CreateParametersSize);
|
||||
|
||||
Name.Buffer[Name.Length / 2] = L'\0';
|
||||
InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, ParentHandle, NULL);
|
||||
|
||||
|
||||
Status = IoCreateFile(NodeHandle,
|
||||
DesiredAccess,
|
||||
&ObjectAttributes,
|
||||
&IoStatusBlock,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
FILE_OPEN,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
NULL,
|
||||
0,
|
||||
CreateFileTypeNone,
|
||||
NULL,
|
||||
IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK);
|
||||
|
||||
ExFreePool(Name.Buffer);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsoCreatePin(
|
||||
IN HANDLE FilterHandle,
|
||||
IN PKSPIN_CONNECT Connect,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
OUT PHANDLE ConnectionHandle,
|
||||
IN LPWSTR ObjectClass)
|
||||
{
|
||||
WCHAR szBuffer[100];
|
||||
UINT ConnectSize = sizeof(KSPIN_CONNECT);
|
||||
|
||||
PKSDATAFORMAT_WAVEFORMATEX Format = (PKSDATAFORMAT_WAVEFORMATEX)(Connect + 1);
|
||||
if (Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) ||
|
||||
Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX))
|
||||
{
|
||||
ConnectSize += Format->DataFormat.FormatSize;
|
||||
}
|
||||
|
||||
swprintf(szBuffer, L"%s\\{146F1A80-4791-11D0-A5D6-28DB04C10000}", ObjectClass);
|
||||
|
||||
return KspCreateObjectType(FilterHandle,
|
||||
szBuffer,
|
||||
(PVOID)Connect,
|
||||
ConnectSize,
|
||||
DesiredAccess,
|
||||
ConnectionHandle);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
SetIrpIoStatus(
|
||||
IN PIRP Irp,
|
||||
|
@ -131,38 +47,20 @@ SetIrpIoStatus(
|
|||
|
||||
}
|
||||
|
||||
PKSAUDIO_SUBDEVICE_ENTRY
|
||||
PKSAUDIO_DEVICE_ENTRY
|
||||
GetListEntry(
|
||||
IN PLIST_ENTRY Head,
|
||||
IN ULONG Index)
|
||||
{
|
||||
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
|
||||
PKSAUDIO_SUBDEVICE_ENTRY SubDeviceEntry;
|
||||
PLIST_ENTRY SubEntry, Entry = Head->Flink;
|
||||
|
||||
while(Entry != Head)
|
||||
{
|
||||
DeviceEntry = (PKSAUDIO_DEVICE_ENTRY)CONTAINING_RECORD(Entry, KSAUDIO_DEVICE_ENTRY, Entry);
|
||||
if (Index < DeviceEntry->NumSubDevices)
|
||||
{
|
||||
SubEntry = DeviceEntry->SubDeviceList.Flink;
|
||||
while(SubEntry != &DeviceEntry->SubDeviceList && Index--)
|
||||
SubEntry = SubEntry->Flink;
|
||||
|
||||
SubDeviceEntry = (PKSAUDIO_SUBDEVICE_ENTRY)CONTAINING_RECORD(SubEntry, KSAUDIO_SUBDEVICE_ENTRY, Entry);
|
||||
return SubDeviceEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
Index -= DeviceEntry->NumSubDevices;
|
||||
}
|
||||
PLIST_ENTRY Entry = Head->Flink;
|
||||
|
||||
while(Index-- && Entry != Head)
|
||||
Entry = Entry->Flink;
|
||||
|
||||
}
|
||||
DPRINT1("Not Found index %u\n", Index);
|
||||
if (Entry == Head)
|
||||
return NULL;
|
||||
|
||||
return NULL;
|
||||
return (PKSAUDIO_DEVICE_ENTRY)CONTAINING_RECORD(Entry, KSAUDIO_DEVICE_ENTRY, Entry);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -171,7 +69,7 @@ SysAudioOpenVirtualDevice(
|
|||
IN ULONG DeviceNumber,
|
||||
PSYSAUDIODEVEXT DeviceExtension)
|
||||
{
|
||||
PKSAUDIO_SUBDEVICE_ENTRY Entry;
|
||||
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
|
||||
/* access the create item */
|
||||
|
@ -243,7 +141,7 @@ CreateMixerPinAndSetFormat(
|
|||
HANDLE PinHandle;
|
||||
PFILE_OBJECT FileObject;
|
||||
|
||||
Status = KsoCreatePin(KMixerHandle, PinConnect, GENERIC_READ | GENERIC_WRITE, &PinHandle, L"KMixer");
|
||||
Status = KsCreatePin(KMixerHandle, PinConnect, GENERIC_READ | GENERIC_WRITE, &PinHandle);//, L"KMixer");
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -305,7 +203,7 @@ CreatePinWorkerRoutine(
|
|||
|
||||
|
||||
/* Let's try to create the audio irp pin */
|
||||
Status = KsoCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle, WorkerContext->Entry->ObjectClass);
|
||||
Status = KsCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -345,7 +243,7 @@ CreatePinWorkerRoutine(
|
|||
}
|
||||
|
||||
/* Retry with Mixer format */
|
||||
Status = KsoCreatePin(WorkerContext->Entry->Handle, MixerPinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle, WorkerContext->Entry->ObjectClass);
|
||||
Status = KsCreatePin(WorkerContext->Entry->Handle, MixerPinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); //, WorkerContext->Entry->ObjectClass);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* This should not fail */
|
||||
|
@ -390,7 +288,7 @@ CreatePinWorkerRoutine(
|
|||
|
||||
DPRINT1("creating virtual pin\n");
|
||||
/* now create the virtual audio pin which is exposed to wdmaud */
|
||||
Status = KsoCreatePin(Filter, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &VirtualPinHandle, L"SysAudio");
|
||||
Status = KsCreatePin(Filter, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &VirtualPinHandle); //, L"SysAudio");
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -454,7 +352,7 @@ HandleSysAudioFilterPinProperties(
|
|||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
PKSAUDIO_SUBDEVICE_ENTRY Entry;
|
||||
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||
ULONG BytesReturned;
|
||||
PKSP_PIN Pin;
|
||||
|
||||
|
@ -541,7 +439,7 @@ HandleSysAudioFilterPinProperties(
|
|||
|
||||
NTSTATUS
|
||||
ComputeCompatibleFormat(
|
||||
IN PKSAUDIO_SUBDEVICE_ENTRY Entry,
|
||||
IN PKSAUDIO_DEVICE_ENTRY Entry,
|
||||
IN ULONG PinId,
|
||||
IN PSYSAUDIODEVEXT DeviceExtension,
|
||||
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
||||
|
@ -676,7 +574,7 @@ ComputeCompatibleFormat(
|
|||
|
||||
NTSTATUS
|
||||
GetPinInstanceCount(
|
||||
PKSAUDIO_SUBDEVICE_ENTRY Entry,
|
||||
PKSAUDIO_DEVICE_ENTRY Entry,
|
||||
PKSPIN_CINSTANCES PinInstances,
|
||||
PKSPIN_CONNECT PinConnect)
|
||||
{
|
||||
|
@ -701,7 +599,7 @@ HandleSysAudioFilterPinCreation(
|
|||
PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
ULONG Length;
|
||||
PKSAUDIO_SUBDEVICE_ENTRY Entry;
|
||||
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||
KSPIN_CONNECT * PinConnect;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
||||
|
@ -848,7 +746,7 @@ SysAudioHandleProperty(
|
|||
PULONG Index;
|
||||
PKSPROPERTY Property;
|
||||
PSYSAUDIODEVEXT DeviceExtension;
|
||||
PKSAUDIO_SUBDEVICE_ENTRY Entry;
|
||||
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
||||
ULONG BytesReturned;
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
|
|
|
@ -18,7 +18,7 @@ const GUID DMOCATEGORY_ACOUSTIC_ECHO_CANCEL = {0xBF963D80L, 0xC559, 0x11D0, {
|
|||
|
||||
VOID
|
||||
QueryFilterRoutine(
|
||||
IN PKSAUDIO_SUBDEVICE_ENTRY DeviceEntry)
|
||||
IN PKSAUDIO_DEVICE_ENTRY DeviceEntry)
|
||||
{
|
||||
KSPROPERTY PropertyRequest;
|
||||
KSP_PIN PinRequest;
|
||||
|
@ -32,15 +32,6 @@ QueryFilterRoutine(
|
|||
|
||||
DPRINT("Querying filter...\n");
|
||||
|
||||
Status = KsSynchronousIoControlDevice(DeviceEntry->FileObject, KernelMode, IOCTL_KS_OBJECT_CLASS, NULL, 0, &DeviceEntry->ObjectClass, sizeof(LPWSTR), &BytesReturned);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to query object class Status %x\n", Status);
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINT("ObjectClass %S\n", DeviceEntry->ObjectClass);
|
||||
|
||||
PropertyRequest.Set = KSPROPSETID_Pin;
|
||||
PropertyRequest.Flags = KSPROPERTY_TYPE_GET;
|
||||
PropertyRequest.Id = KSPROPERTY_PIN_CTYPES;
|
||||
|
@ -114,9 +105,6 @@ QueryFilterRoutine(
|
|||
DPRINT("Num Pins %u Num WaveIn Pins %u Name WaveOut Pins %u\n", DeviceEntry->NumberOfPins, NumWaveInPin, NumWaveOutPin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
FilterPinWorkerRoutine(
|
||||
|
@ -124,21 +112,11 @@ FilterPinWorkerRoutine(
|
|||
IN PVOID Context)
|
||||
{
|
||||
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
|
||||
PKSAUDIO_SUBDEVICE_ENTRY SubDeviceEntry;
|
||||
PLIST_ENTRY ListEntry;
|
||||
|
||||
PFILTER_WORKER_CONTEXT Ctx = (PFILTER_WORKER_CONTEXT)Context;
|
||||
|
||||
DeviceEntry = Ctx->DeviceEntry;
|
||||
|
||||
ListEntry = DeviceEntry->SubDeviceList.Flink;
|
||||
while(ListEntry != &DeviceEntry->SubDeviceList)
|
||||
{
|
||||
SubDeviceEntry = (PKSAUDIO_SUBDEVICE_ENTRY)CONTAINING_RECORD(ListEntry, KSAUDIO_SUBDEVICE_ENTRY, Entry);
|
||||
QueryFilterRoutine(SubDeviceEntry);
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
QueryFilterRoutine(DeviceEntry);
|
||||
|
||||
/* free work item */
|
||||
IoFreeWorkItem(Ctx->WorkItem);
|
||||
|
@ -177,7 +155,7 @@ OpenDevice(
|
|||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ZwCreateFile failed with %x\n", Status);
|
||||
DPRINT("ZwCreateFile failed with %x %S\n", Status, DeviceName->Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -195,125 +173,92 @@ OpenDevice(
|
|||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DeviceInterfaceChangeCallback(
|
||||
IN PVOID NotificationStructure,
|
||||
IN PVOID Context)
|
||||
InsertAudioDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PUNICODE_STRING DeviceName,
|
||||
IN LPWSTR ReferenceString)
|
||||
{
|
||||
DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PFILTER_WORKER_CONTEXT Ctx = NULL;
|
||||
PIO_WORKITEM WorkItem = NULL;
|
||||
PSYSAUDIODEVEXT DeviceExtension;
|
||||
PKSAUDIO_DEVICE_ENTRY DeviceEntry = NULL;
|
||||
PKSAUDIO_SUBDEVICE_ENTRY SubDeviceEntry;
|
||||
PIO_WORKITEM WorkItem = NULL;
|
||||
PFILTER_WORKER_CONTEXT Ctx = NULL;
|
||||
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
|
||||
|
||||
/* a new device has arrived */
|
||||
DeviceEntry = ExAllocatePool(NonPagedPool, sizeof(KSAUDIO_DEVICE_ENTRY));
|
||||
if (!DeviceEntry)
|
||||
{
|
||||
/* no memory */
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* initialize audio device entry */
|
||||
RtlZeroMemory(DeviceEntry, sizeof(KSAUDIO_DEVICE_ENTRY));
|
||||
|
||||
/* allocate filter ctx */
|
||||
Ctx = ExAllocatePool(NonPagedPool, sizeof(FILTER_WORKER_CONTEXT));
|
||||
if (!Ctx)
|
||||
{
|
||||
/* no memory */
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* allocate work item */
|
||||
WorkItem = IoAllocateWorkItem(DeviceObject);
|
||||
if (!WorkItem)
|
||||
{
|
||||
/* no memory */
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* set device name */
|
||||
DeviceEntry->DeviceName.Length = 0;
|
||||
DeviceEntry->DeviceName.MaximumLength = DeviceName->MaximumLength + 10 * sizeof(WCHAR);
|
||||
|
||||
/* hack for bug 4566 */
|
||||
if (ReferenceString)
|
||||
{
|
||||
DeviceEntry->DeviceName.MaximumLength += (wcslen(ReferenceString) + 2) * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
DeviceEntry->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceEntry->DeviceName.MaximumLength);
|
||||
|
||||
if (!DeviceEntry->DeviceName.Buffer)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
RtlAppendUnicodeToString(&DeviceEntry->DeviceName, L"\\??\\");
|
||||
RtlAppendUnicodeStringToString(&DeviceEntry->DeviceName, DeviceName);
|
||||
|
||||
if (ReferenceString)
|
||||
{
|
||||
RtlAppendUnicodeToString(&DeviceEntry->DeviceName, L"\\");
|
||||
RtlAppendUnicodeToString(&DeviceEntry->DeviceName, ReferenceString);
|
||||
}
|
||||
|
||||
Status = OpenDevice(&DeviceEntry->DeviceName, &DeviceEntry->Handle, &DeviceEntry->FileObject);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
Ctx->DeviceEntry = DeviceEntry;
|
||||
Ctx->WorkItem = WorkItem;
|
||||
|
||||
/* fetch device extension */
|
||||
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
|
||||
/* insert new audio device */
|
||||
ExInterlockedInsertTailList(&DeviceExtension->KsAudioDeviceList, &DeviceEntry->Entry, &DeviceExtension->Lock);
|
||||
InterlockedIncrement((PLONG)&DeviceExtension->NumberOfKsAudioDevices);
|
||||
|
||||
Event = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure;
|
||||
|
||||
if (IsEqualGUIDAligned(&Event->Event,
|
||||
&GUID_DEVICE_INTERFACE_ARRIVAL))
|
||||
{
|
||||
|
||||
/* a new device has arrived */
|
||||
DeviceEntry = ExAllocatePool(NonPagedPool, sizeof(KSAUDIO_DEVICE_ENTRY));
|
||||
if (!DeviceEntry)
|
||||
{
|
||||
/* no memory */
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* initialize audio device entry */
|
||||
RtlZeroMemory(DeviceEntry, sizeof(KSAUDIO_DEVICE_ENTRY));
|
||||
|
||||
/* allocate filter ctx */
|
||||
Ctx = ExAllocatePool(NonPagedPool, sizeof(FILTER_WORKER_CONTEXT));
|
||||
if (!Ctx)
|
||||
{
|
||||
/* no memory */
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* allocate work item */
|
||||
WorkItem = IoAllocateWorkItem(DeviceObject);
|
||||
if (!WorkItem)
|
||||
{
|
||||
/* no memory */
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* set device name */
|
||||
DeviceEntry->DeviceName.Length = 0;
|
||||
DeviceEntry->DeviceName.MaximumLength = Event->SymbolicLinkName->Length + 10 * sizeof(WCHAR);
|
||||
DeviceEntry->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceEntry->DeviceName.MaximumLength);
|
||||
|
||||
if (!DeviceEntry->DeviceName.Buffer)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(RtlAppendUnicodeToString(&DeviceEntry->DeviceName, L"\\??\\")))
|
||||
{
|
||||
DPRINT1("RtlAppendUnicodeToString failed with %x\n", Status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(RtlAppendUnicodeStringToString(&DeviceEntry->DeviceName, Event->SymbolicLinkName)))
|
||||
{
|
||||
DPRINT1("RtlAppendUnicodeStringToString failed with %x\n", Status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* FIXME Ros does not support device interface strings */
|
||||
/* Workarround: repeatly call IoCreateFile untill ks wont find a create item which has no object header attached */
|
||||
|
||||
InitializeListHead(&DeviceEntry->SubDeviceList);
|
||||
do
|
||||
{
|
||||
SubDeviceEntry = ExAllocatePool(NonPagedPool, sizeof(KSAUDIO_SUBDEVICE_ENTRY));
|
||||
if (SubDeviceEntry)
|
||||
{
|
||||
RtlZeroMemory(SubDeviceEntry, sizeof(KSAUDIO_SUBDEVICE_ENTRY));
|
||||
Status = OpenDevice(&DeviceEntry->DeviceName, &SubDeviceEntry->Handle, &SubDeviceEntry->FileObject);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
InsertTailList(&DeviceEntry->SubDeviceList, &SubDeviceEntry->Entry);
|
||||
DeviceEntry->NumSubDevices++;
|
||||
/* increment audio device count */
|
||||
InterlockedIncrement((PLONG)&DeviceExtension->NumberOfKsAudioDevices);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExFreePool(SubDeviceEntry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}while(NT_SUCCESS(Status) && SubDeviceEntry != NULL);
|
||||
|
||||
DPRINT("Successfully opened audio device %u Device %S NumberOfSubDevices %u\n", DeviceExtension->NumberOfKsAudioDevices, DeviceEntry->DeviceName.Buffer, DeviceEntry->NumSubDevices);
|
||||
|
||||
Ctx->DeviceEntry = DeviceEntry;
|
||||
Ctx->WorkItem = WorkItem;
|
||||
|
||||
/* fetch device extension */
|
||||
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
|
||||
/* insert new audio device */
|
||||
ExInterlockedInsertTailList(&DeviceExtension->KsAudioDeviceList, &DeviceEntry->Entry, &DeviceExtension->Lock);
|
||||
|
||||
IoQueueWorkItem(WorkItem, FilterPinWorkerRoutine, DelayedWorkQueue, (PVOID)Ctx);
|
||||
return Status;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Remove interface to audio device!\n");
|
||||
UNIMPLEMENTED
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
DPRINT("Successfully opened audio device %u Device %S\n", DeviceExtension->NumberOfKsAudioDevices, DeviceEntry->DeviceName.Buffer);
|
||||
IoQueueWorkItem(WorkItem, FilterPinWorkerRoutine, DelayedWorkQueue, (PVOID)Ctx);
|
||||
return Status;
|
||||
|
||||
cleanup:
|
||||
if (Ctx)
|
||||
|
@ -331,6 +276,93 @@ cleanup:
|
|||
}
|
||||
|
||||
return Status;
|
||||
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DeviceInterfaceChangeCallback(
|
||||
IN PVOID NotificationStructure,
|
||||
IN PVOID Context)
|
||||
{
|
||||
DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PSYSAUDIODEVEXT DeviceExtension;
|
||||
UNICODE_STRING DeviceName;
|
||||
HANDLE Handle;
|
||||
PFILE_OBJECT FileObject;
|
||||
LPWSTR ReferenceString;
|
||||
ULONG BytesReturned;
|
||||
|
||||
|
||||
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
|
||||
|
||||
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
|
||||
|
||||
Event = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure;
|
||||
|
||||
if (IsEqualGUIDAligned(&Event->Event,
|
||||
&GUID_DEVICE_INTERFACE_ARRIVAL))
|
||||
{
|
||||
/*<HACK>
|
||||
* 1) Open the filter w/o reference string
|
||||
* 2) Retrieve reference strings with our private IOCTL_KS_OBJECT_CLASS
|
||||
* 3) Append these reference strings to symbolic link we got
|
||||
* * see bug 4566
|
||||
*/
|
||||
|
||||
DeviceName.Length = 0;
|
||||
DeviceName.MaximumLength = Event->SymbolicLinkName->Length + 10 * sizeof(WCHAR);
|
||||
|
||||
DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceName.MaximumLength);
|
||||
|
||||
if (!DeviceName.Buffer)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlAppendUnicodeToString(&DeviceName, L"\\??\\");
|
||||
RtlAppendUnicodeStringToString(&DeviceName, Event->SymbolicLinkName);
|
||||
|
||||
|
||||
Status = OpenDevice(&DeviceName, &Handle, &FileObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePool(DeviceName.Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_OBJECT_CLASS, NULL, 0, &ReferenceString, sizeof(LPWSTR), &BytesReturned);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("failed Status %x\n", Status);
|
||||
|
||||
ExFreePool(DeviceName.Buffer);
|
||||
ObDereferenceObject(FileObject);
|
||||
ZwClose(Handle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
while(*ReferenceString)
|
||||
{
|
||||
Status = InsertAudioDevice(DeviceObject, Event->SymbolicLinkName, ReferenceString);
|
||||
ReferenceString += wcslen(ReferenceString) + 1;
|
||||
}
|
||||
//ExFreePool(ReferenceString);
|
||||
ObDereferenceObject(FileObject);
|
||||
ZwClose(Handle);
|
||||
ExFreePool(DeviceName.Buffer);
|
||||
return Status;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Remove interface to audio device!\n");
|
||||
UNIMPLEMENTED
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
|
|
@ -201,7 +201,7 @@ DispatchCreateSysAudio(
|
|||
if (Buffer)
|
||||
{
|
||||
/* is the request for a new pin */
|
||||
if (!wcsncmp(KS_NAME_PIN, Buffer, wcslen(KS_NAME_PIN)))
|
||||
if (wcsstr(Buffer, KS_NAME_PIN))
|
||||
{
|
||||
Status = CreateDispatcher(Irp);
|
||||
DPRINT("Virtual pin Status %x FileObject %p\n", Status, IoStatus->FileObject);
|
||||
|
@ -259,6 +259,7 @@ SysAudioAllocateDeviceHeader(
|
|||
RtlZeroMemory(CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
|
||||
CreateItem->Create = DispatchCreateSysAudio;
|
||||
RtlInitUnicodeString(&CreateItem->ObjectClass, L"SysAudio");
|
||||
CreateItem->Flags = KSCREATE_ITEM_WILDCARD;
|
||||
|
||||
Status = KsAllocateDeviceHeader(&DeviceExtension->KsDeviceHeader,
|
||||
1,
|
||||
|
@ -271,7 +272,6 @@ SysAudioOpenKMixer(
|
|||
IN SYSAUDIODEVEXT *DeviceExtension)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\kmixer");
|
||||
UNICODE_STRING DevicePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\kmixer");
|
||||
|
||||
|
|
|
@ -34,9 +34,8 @@ SysAudio_Shutdown(
|
|||
IN PIRP Irp)
|
||||
{
|
||||
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
|
||||
PKSAUDIO_SUBDEVICE_ENTRY SubDeviceEntry;
|
||||
PSYSAUDIODEVEXT DeviceExtension;
|
||||
PLIST_ENTRY Entry, SubEntry;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
DPRINT1("SysAudio_Shutdown called\n");
|
||||
|
||||
|
@ -50,16 +49,6 @@ SysAudio_Shutdown(
|
|||
DPRINT1("Freeing item %wZ\n", &DeviceEntry->DeviceName);
|
||||
RtlFreeUnicodeString(&DeviceEntry->DeviceName);
|
||||
|
||||
while(!IsListEmpty(&DeviceEntry->SubDeviceList))
|
||||
{
|
||||
SubEntry = RemoveHeadList(&DeviceEntry->SubDeviceList);
|
||||
SubDeviceEntry = (PKSAUDIO_SUBDEVICE_ENTRY)CONTAINING_RECORD(SubEntry, KSAUDIO_SUBDEVICE_ENTRY, Entry);
|
||||
|
||||
ZwClose(SubDeviceEntry->Handle);
|
||||
ObDereferenceObject(SubDeviceEntry->FileObject);
|
||||
ExFreePool(SubDeviceEntry->Pins);
|
||||
ExFreePool(SubDeviceEntry);
|
||||
}
|
||||
ExFreePool(DeviceEntry);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry; // linked list entry to KSAUDIO_DEVICE_ENTRY
|
||||
LIST_ENTRY Entry; // device entry for KsAudioDeviceList
|
||||
UNICODE_STRING DeviceName; // symbolic link of audio device
|
||||
|
||||
HANDLE Handle; // handle to audio sub device
|
||||
PFILE_OBJECT FileObject; // file objecto to audio sub device
|
||||
|
@ -30,18 +31,6 @@ typedef struct
|
|||
ULONG NumberOfPins; // number of pins of audio device
|
||||
PIN_INFO * Pins; // array of PIN_INFO
|
||||
|
||||
LPWSTR ObjectClass; // object class of sub device
|
||||
|
||||
}KSAUDIO_SUBDEVICE_ENTRY, *PKSAUDIO_SUBDEVICE_ENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry; // device entry for KsAudioDeviceList
|
||||
UNICODE_STRING DeviceName; // symbolic link of audio device
|
||||
|
||||
ULONG NumSubDevices; // number of subdevices
|
||||
LIST_ENTRY SubDeviceList; // audio sub device list
|
||||
|
||||
}KSAUDIO_DEVICE_ENTRY, *PKSAUDIO_DEVICE_ENTRY;
|
||||
|
||||
typedef struct
|
||||
|
@ -71,7 +60,7 @@ typedef struct
|
|||
{
|
||||
HANDLE Handle; // audio irp pin handle
|
||||
ULONG PinId; // pin id of device
|
||||
PKSAUDIO_SUBDEVICE_ENTRY AudioEntry; // pointer to audio device entry
|
||||
PKSAUDIO_DEVICE_ENTRY AudioEntry; // pointer to audio device entry
|
||||
|
||||
HANDLE hMixerPin; // handle to mixer pin
|
||||
}DISPATCH_CONTEXT, *PDISPATCH_CONTEXT;
|
||||
|
@ -86,7 +75,7 @@ typedef struct
|
|||
PIRP Irp;
|
||||
BOOL CreateRealPin;
|
||||
BOOL CreateMixerPin;
|
||||
PKSAUDIO_SUBDEVICE_ENTRY Entry;
|
||||
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||
KSPIN_CONNECT * PinConnect;
|
||||
PDISPATCH_CONTEXT DispatchContext;
|
||||
PSYSAUDIODEVEXT DeviceExtension;
|
||||
|
@ -129,7 +118,7 @@ OpenDevice(
|
|||
IN PHANDLE HandleOut,
|
||||
IN PFILE_OBJECT * FileObjectOut);
|
||||
|
||||
PKSAUDIO_SUBDEVICE_ENTRY
|
||||
PKSAUDIO_DEVICE_ENTRY
|
||||
GetListEntry(
|
||||
IN PLIST_ENTRY Head,
|
||||
IN ULONG Index);
|
||||
|
|
Loading…
Reference in a new issue