mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 15:33:07 +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
13 changed files with 458 additions and 461 deletions
|
@ -45,15 +45,23 @@ KsValidateConnectRequest(
|
||||||
PKSPIN_CONNECT ConnectDetails;
|
PKSPIN_CONNECT ConnectDetails;
|
||||||
LPWSTR PinName = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}\\";
|
LPWSTR PinName = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}\\";
|
||||||
PKSDATAFORMAT DataFormat;
|
PKSDATAFORMAT DataFormat;
|
||||||
|
LPWSTR Offset;
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
if (!IoStack->FileObject->FileName.Buffer)
|
if (!IoStack->FileObject->FileName.Buffer)
|
||||||
return STATUS_INVALID_PARAMETER;
|
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;
|
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)
|
if (ConnectDetails->PinToHandle != NULL)
|
||||||
{
|
{
|
||||||
|
@ -61,11 +69,6 @@ KsValidateConnectRequest(
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
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)
|
if (ConnectDetails->PinId >= DescriptorsCount)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
|
|
@ -104,14 +104,15 @@ KsAddObjectCreateItemToDeviceHeader(
|
||||||
/* now scan the list and check for a free item */
|
/* now scan the list and check for a free item */
|
||||||
for(Index = 0; Index < Header->MaxItems; Index++)
|
for(Index = 0; Index < Header->MaxItems; Index++)
|
||||||
{
|
{
|
||||||
if (!Header->ItemList[Index].bCreated)
|
ASSERT(Header->ItemList[Index].CreateItem);
|
||||||
{
|
|
||||||
if (FreeIndex == (ULONG)-1)
|
|
||||||
FreeIndex = Index;
|
|
||||||
|
|
||||||
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 */
|
/* the same object class already exists */
|
||||||
return STATUS_OBJECT_NAME_COLLISION;
|
return STATUS_OBJECT_NAME_COLLISION;
|
||||||
|
@ -120,26 +121,17 @@ KsAddObjectCreateItemToDeviceHeader(
|
||||||
/* found a free index */
|
/* found a free index */
|
||||||
if (FreeIndex == (ULONG)-1)
|
if (FreeIndex == (ULONG)-1)
|
||||||
{
|
{
|
||||||
/* allocate a new device entry */
|
/* no empty space found */
|
||||||
PDEVICE_ITEM Item = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_ITEM) * (Header->MaxItems + 1), TAG_DEVICE_HEADER);
|
return STATUS_ALLOTTED_SPACE_EXCEEDED;
|
||||||
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++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store the new item */
|
/* initialize create item */
|
||||||
Header->ItemList[FreeIndex].bCreated = TRUE;
|
Header->ItemList[FreeIndex].CreateItem->Create = Create;
|
||||||
Header->ItemList[FreeIndex].CreateItem.Create = Create;
|
Header->ItemList[FreeIndex].CreateItem->Context = Context;
|
||||||
Header->ItemList[FreeIndex].CreateItem.Context = Context;
|
RtlInitUnicodeString(&Header->ItemList[FreeIndex].CreateItem->ObjectClass, ObjectClass);
|
||||||
RtlInitUnicodeString(&Header->ItemList[FreeIndex].CreateItem.ObjectClass, ObjectClass);
|
Header->ItemList[FreeIndex].CreateItem->SecurityDescriptor = SecurityDescriptor;
|
||||||
Header->ItemList[FreeIndex].CreateItem.SecurityDescriptor = SecurityDescriptor;
|
|
||||||
Header->ItemList[FreeIndex].CreateItem.Flags = 0;
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,12 +179,8 @@ KsAllocateDeviceHeader(
|
||||||
|
|
||||||
for(Index = 0; Index < ItemsCount; Index++)
|
for(Index = 0; Index < ItemsCount; Index++)
|
||||||
{
|
{
|
||||||
/* copy provided create items */
|
/* store provided create items */
|
||||||
RtlMoveMemory(&Header->ItemList[Index].CreateItem, &ItemsList[Index], sizeof(KSOBJECT_CREATE_ITEM));
|
Header->ItemList[Index].CreateItem = &ItemsList[Index];
|
||||||
if (ItemsList[Index].Create!= NULL)
|
|
||||||
{
|
|
||||||
Header->ItemList[Index].bCreated = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Header->MaxItems = ItemsCount;
|
Header->MaxItems = ItemsCount;
|
||||||
}
|
}
|
||||||
|
@ -294,7 +282,6 @@ KsAllocateObjectHeader(
|
||||||
PDEVICE_EXTENSION DeviceExtension;
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
PKSIDEVICE_HEADER DeviceHeader;
|
PKSIDEVICE_HEADER DeviceHeader;
|
||||||
PKSIOBJECT_HEADER ObjectHeader;
|
PKSIOBJECT_HEADER ObjectHeader;
|
||||||
WCHAR ObjectClass[50];
|
|
||||||
|
|
||||||
if (!Header)
|
if (!Header)
|
||||||
return STATUS_INVALID_PARAMETER_1;
|
return STATUS_INVALID_PARAMETER_1;
|
||||||
|
@ -312,18 +299,10 @@ KsAllocateObjectHeader(
|
||||||
/* get device header */
|
/* get device header */
|
||||||
DeviceHeader = DeviceExtension->DeviceHeader;
|
DeviceHeader = DeviceExtension->DeviceHeader;
|
||||||
|
|
||||||
ObjectClass[0] = L'\0';
|
/* sanity check */
|
||||||
|
ASSERT(IoStack->FileObject);
|
||||||
/* check for an file object */
|
/* 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 */
|
/* allocate the object header */
|
||||||
ObjectHeader = ExAllocatePoolWithTag(NonPagedPool, sizeof(KSIOBJECT_HEADER), TAG_DEVICE_HEADER);
|
ObjectHeader = ExAllocatePoolWithTag(NonPagedPool, sizeof(KSIOBJECT_HEADER), TAG_DEVICE_HEADER);
|
||||||
if (!ObjectHeader)
|
if (!ObjectHeader)
|
||||||
|
@ -333,13 +312,17 @@ KsAllocateObjectHeader(
|
||||||
RtlZeroMemory(ObjectHeader, sizeof(KSIOBJECT_HEADER));
|
RtlZeroMemory(ObjectHeader, sizeof(KSIOBJECT_HEADER));
|
||||||
|
|
||||||
/* do we have a name */
|
/* do we have a name */
|
||||||
if (ObjectClass[0])
|
if (IoStack->FileObject->FileName.Buffer)
|
||||||
{
|
{
|
||||||
ObjectHeader->ObjectClass = ExAllocatePoolWithTag(NonPagedPool, 40 * sizeof(WCHAR), TAG_DEVICE_HEADER);
|
/* copy object class */
|
||||||
if (ObjectHeader->ObjectClass)
|
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 */
|
/* copy dispatch table */
|
||||||
|
@ -362,7 +345,6 @@ KsAllocateObjectHeader(
|
||||||
{
|
{
|
||||||
/* the object header is for a audio filter */
|
/* the object header is for a audio filter */
|
||||||
ASSERT(DeviceHeader->DeviceIndex < DeviceHeader->MaxItems);
|
ASSERT(DeviceHeader->DeviceIndex < DeviceHeader->MaxItems);
|
||||||
DeviceHeader->ItemList[DeviceHeader->DeviceIndex].ObjectHeader = ObjectHeader;
|
|
||||||
IoStack->FileObject->FsContext = ObjectHeader;
|
IoStack->FileObject->FsContext = ObjectHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +352,7 @@ KsAllocateObjectHeader(
|
||||||
*Header = ObjectHeader;
|
*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;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
@ -725,8 +707,9 @@ KsCreate(
|
||||||
PDEVICE_EXTENSION DeviceExtension;
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
PKSIDEVICE_HEADER DeviceHeader;
|
PKSIDEVICE_HEADER DeviceHeader;
|
||||||
ULONG Index;
|
ULONG Index;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status;
|
||||||
KIRQL OldLevel;
|
KIRQL OldLevel;
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
DPRINT("KS / CREATE\n");
|
DPRINT("KS / CREATE\n");
|
||||||
/* get current stack location */
|
/* get current stack location */
|
||||||
|
@ -738,56 +721,85 @@ KsCreate(
|
||||||
|
|
||||||
/* acquire list lock */
|
/* acquire list lock */
|
||||||
KeAcquireSpinLock(&DeviceHeader->ItemListLock, &OldLevel);
|
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 */
|
/* loop all device items */
|
||||||
for(Index = 0; Index < DeviceHeader->MaxItems; Index++)
|
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;
|
DeviceHeader->DeviceIndex = Index;
|
||||||
/* set object create item */
|
/* set object create item */
|
||||||
KSCREATE_ITEM_IRP_STORAGE(Irp) = &DeviceHeader->ItemList[Index].CreateItem;
|
KSCREATE_ITEM_IRP_STORAGE(Irp) = DeviceHeader->ItemList[Index].CreateItem;
|
||||||
Status = DeviceHeader->ItemList[Index].CreateItem.Create(DeviceObject, Irp);
|
|
||||||
|
|
||||||
/* FIXME IoRegisterDeviceInterface does not support reference strings */
|
/* call create function */
|
||||||
/* FIXME Check the irp target with the create item's object class */
|
Status = DeviceHeader->ItemList[Index].CreateItem->Create(DeviceObject, Irp);
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
/* release lock */
|
||||||
/* release lock */
|
KeReleaseSpinLock(&DeviceHeader->ItemListLock, OldLevel);
|
||||||
KeReleaseSpinLock(&DeviceHeader->ItemListLock, OldLevel);
|
|
||||||
return Status;
|
/* 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 */
|
/* release lock */
|
||||||
|
@ -810,7 +822,6 @@ KsClose(
|
||||||
PKSIOBJECT_HEADER ObjectHeader;
|
PKSIOBJECT_HEADER ObjectHeader;
|
||||||
PDEVICE_EXTENSION DeviceExtension;
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
PKSIDEVICE_HEADER DeviceHeader;
|
PKSIDEVICE_HEADER DeviceHeader;
|
||||||
ULONG Index;
|
|
||||||
|
|
||||||
/* get current stack location */
|
/* get current stack location */
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
@ -827,20 +838,20 @@ KsClose(
|
||||||
ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
|
ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
|
||||||
|
|
||||||
KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
|
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);
|
return ObjectHeader->DispatchTable.Close(DeviceObject, Irp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
DPRINT1("Expected Object Header FileObject %p FsContext %p\n", IoStack->FileObject, IoStack->FileObject->FsContext);
|
DPRINT1("Expected Object Header FileObject %p FsContext %p\n", IoStack->FileObject, IoStack->FileObject->FsContext);
|
||||||
KeBugCheckEx(0, 0, 0, 0, 0);
|
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;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -853,10 +864,63 @@ KsDeviceControl(
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
PKSIOBJECT_HEADER ObjectHeader;
|
PKSIOBJECT_HEADER ObjectHeader;
|
||||||
|
PKSIDEVICE_HEADER DeviceHeader;
|
||||||
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
|
ULONG Length, Index;
|
||||||
|
LPWSTR Buffer;
|
||||||
|
|
||||||
/* get current stack location */
|
/* get current stack location */
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
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");
|
DPRINT("KS / DeviceControl\n");
|
||||||
if (IoStack->FileObject && IoStack->FileObject->FsContext)
|
if (IoStack->FileObject && IoStack->FileObject->FsContext)
|
||||||
{
|
{
|
||||||
|
@ -864,14 +928,6 @@ KsDeviceControl(
|
||||||
|
|
||||||
KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
|
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);
|
return ObjectHeader->DispatchTable.DeviceIoControl(DeviceObject, Irp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -6,17 +6,15 @@ struct KSIDEVICE_HEADER;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
KSDISPATCH_TABLE DispatchTable;
|
KSDISPATCH_TABLE DispatchTable;
|
||||||
LPWSTR ObjectClass;
|
|
||||||
ULONG ItemCount;
|
ULONG ItemCount;
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
|
|
||||||
|
UNICODE_STRING ObjectClass;
|
||||||
}KSIOBJECT_HEADER, *PKSIOBJECT_HEADER;
|
}KSIOBJECT_HEADER, *PKSIOBJECT_HEADER;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
BOOL bCreated;
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
PKSIOBJECT_HEADER ObjectHeader;
|
|
||||||
KSOBJECT_CREATE_ITEM CreateItem;
|
|
||||||
}DEVICE_ITEM, *PDEVICE_ITEM;
|
}DEVICE_ITEM, *PDEVICE_ITEM;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -282,16 +282,18 @@ KsSynchronousIoControlDevice(
|
||||||
if (!DeviceObject)
|
if (!DeviceObject)
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
|
||||||
/* get object header */
|
/* get object header */
|
||||||
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
|
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
|
||||||
|
#if 0
|
||||||
if (!ObjectHeader)
|
if (!ObjectHeader)
|
||||||
{
|
{
|
||||||
DPRINT("Expected object header\n");
|
DPRINT("Expected object header\n");
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* check if there is fast device io function */
|
/* check if there is fast device io function */
|
||||||
if (ObjectHeader->DispatchTable.FastDeviceIoControl)
|
if (ObjectHeader && ObjectHeader->DispatchTable.FastDeviceIoControl)
|
||||||
{
|
{
|
||||||
IoStatusBlock.Status = STATUS_UNSUCCESSFUL;
|
IoStatusBlock.Status = STATUS_UNSUCCESSFUL;
|
||||||
IoStatusBlock.Information = 0;
|
IoStatusBlock.Information = 0;
|
||||||
|
|
|
@ -17,26 +17,56 @@ KspCreateObjectType(
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
UNICODE_STRING Name;
|
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);
|
Name.MaximumLength += sizeof(WCHAR);
|
||||||
|
/* acquire request buffer */
|
||||||
Name.Buffer = ExAllocatePool(NonPagedPool, Name.MaximumLength);
|
Name.Buffer = ExAllocatePool(NonPagedPool, Name.MaximumLength);
|
||||||
|
/* check for success */
|
||||||
if (!Name.Buffer)
|
if (!Name.Buffer)
|
||||||
{
|
{
|
||||||
|
/* insufficient resources */
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
wcscpy(Name.Buffer, ObjectType);
|
/* build a request which looks like \Parent\{ObjectGuid}\CreateParameters
|
||||||
Name.Buffer[wcslen(ObjectType)] = '\\';
|
* For pins the parent is the reference string used in registration
|
||||||
|
* For clocks it is full path for pin\{ClockGuid}\ClockCreateParams
|
||||||
RtlMoveMemory(Name.Buffer + wcslen(ObjectType) +1, CreateParameters, CreateParametersSize);
|
*/
|
||||||
|
|
||||||
|
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';
|
Name.Buffer[Name.Length / 2] = L'\0';
|
||||||
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, ParentHandle, NULL);
|
InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, ParentHandle, NULL);
|
||||||
|
/* create the instance */
|
||||||
|
|
||||||
Status = IoCreateFile(NodeHandle,
|
Status = IoCreateFile(NodeHandle,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
&ObjectAttributes,
|
&ObjectAttributes,
|
||||||
|
@ -52,7 +82,10 @@ KspCreateObjectType(
|
||||||
NULL,
|
NULL,
|
||||||
IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK);
|
IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK);
|
||||||
|
|
||||||
|
/* free request buffer */
|
||||||
ExFreePool(Name.Buffer);
|
ExFreePool(Name.Buffer);
|
||||||
|
/* release parent handle */
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -314,7 +314,7 @@ IIrpQueue_fnMinimumDataAvailable(
|
||||||
if (This->StartStream)
|
if (This->StartStream)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (This->DataFormat->WaveFormatEx.nAvgBytesPerSec < This->NumDataAvailable)
|
if (This->DataFormat->WaveFormatEx.nAvgBytesPerSec/3 < This->NumDataAvailable)
|
||||||
{
|
{
|
||||||
This->StartStream = TRUE;
|
This->StartStream = TRUE;
|
||||||
Result = TRUE;
|
Result = TRUE;
|
||||||
|
|
|
@ -542,6 +542,8 @@ PcCreateItemDispatch(
|
||||||
IIrpTarget *Filter;
|
IIrpTarget *Filter;
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
PPIN_WORKER_CONTEXT Context;
|
PPIN_WORKER_CONTEXT Context;
|
||||||
|
LPWSTR Buffer;
|
||||||
|
static LPWSTR KS_NAME_PIN = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}";
|
||||||
|
|
||||||
DPRINT1("PcCreateItemDispatch called DeviceObject %p\n", DeviceObject);
|
DPRINT1("PcCreateItemDispatch called DeviceObject %p\n", DeviceObject);
|
||||||
|
|
||||||
|
@ -604,60 +606,55 @@ PcCreateItemDispatch(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is just the filter requested */
|
/* get the buffer */
|
||||||
if (IoStack->FileObject->FileName.Buffer == NULL)
|
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);
|
Status = NewDispatchObject(Irp, Filter, CreateItem->ObjectClass.Buffer);
|
||||||
|
|
||||||
DPRINT1("Filter %p\n", Filter);
|
DPRINT1("Filter %p\n", Filter);
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LPWSTR Buffer = IoStack->FileObject->FileName.Buffer;
|
/* try to create new pin */
|
||||||
|
Context = AllocateItem(NonPagedPool, sizeof(PIN_WORKER_CONTEXT), TAG_PORTCLASS);
|
||||||
static LPWSTR KS_NAME_PIN = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}";
|
if (!Context)
|
||||||
|
|
||||||
/* is the request for a new pin */
|
|
||||||
if (!wcsncmp(KS_NAME_PIN, Buffer, wcslen(KS_NAME_PIN)))
|
|
||||||
{
|
{
|
||||||
/* try to create new pin */
|
DPRINT("Failed to allocate worker context\n");
|
||||||
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());
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_PENDING;
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
IoMarkIrpPending(Irp);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
IoQueueWorkItem(Context->WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
return STATUS_PENDING;
|
|
||||||
}
|
}
|
||||||
|
/* 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)
|
if (Buffer)
|
||||||
{
|
{
|
||||||
/* is the request for a new pin */
|
/* 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);
|
Status = CreatePin(Irp);
|
||||||
|
|
||||||
|
|
|
@ -20,97 +20,13 @@ const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce,
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
ComputeCompatibleFormat(
|
ComputeCompatibleFormat(
|
||||||
IN PKSAUDIO_SUBDEVICE_ENTRY Entry,
|
IN PKSAUDIO_DEVICE_ENTRY Entry,
|
||||||
IN ULONG PinId,
|
IN ULONG PinId,
|
||||||
IN PSYSAUDIODEVEXT DeviceExtension,
|
IN PSYSAUDIODEVEXT DeviceExtension,
|
||||||
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
||||||
OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat);
|
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
|
NTSTATUS
|
||||||
SetIrpIoStatus(
|
SetIrpIoStatus(
|
||||||
IN PIRP Irp,
|
IN PIRP Irp,
|
||||||
|
@ -131,38 +47,20 @@ SetIrpIoStatus(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PKSAUDIO_SUBDEVICE_ENTRY
|
PKSAUDIO_DEVICE_ENTRY
|
||||||
GetListEntry(
|
GetListEntry(
|
||||||
IN PLIST_ENTRY Head,
|
IN PLIST_ENTRY Head,
|
||||||
IN ULONG Index)
|
IN ULONG Index)
|
||||||
{
|
{
|
||||||
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
|
PLIST_ENTRY Entry = Head->Flink;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
while(Index-- && Entry != Head)
|
||||||
Entry = Entry->Flink;
|
Entry = Entry->Flink;
|
||||||
|
|
||||||
}
|
if (Entry == Head)
|
||||||
DPRINT1("Not Found index %u\n", Index);
|
return NULL;
|
||||||
|
|
||||||
return NULL;
|
return (PKSAUDIO_DEVICE_ENTRY)CONTAINING_RECORD(Entry, KSAUDIO_DEVICE_ENTRY, Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -171,7 +69,7 @@ SysAudioOpenVirtualDevice(
|
||||||
IN ULONG DeviceNumber,
|
IN ULONG DeviceNumber,
|
||||||
PSYSAUDIODEVEXT DeviceExtension)
|
PSYSAUDIODEVEXT DeviceExtension)
|
||||||
{
|
{
|
||||||
PKSAUDIO_SUBDEVICE_ENTRY Entry;
|
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
|
|
||||||
/* access the create item */
|
/* access the create item */
|
||||||
|
@ -243,7 +141,7 @@ CreateMixerPinAndSetFormat(
|
||||||
HANDLE PinHandle;
|
HANDLE PinHandle;
|
||||||
PFILE_OBJECT FileObject;
|
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))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -305,7 +203,7 @@ CreatePinWorkerRoutine(
|
||||||
|
|
||||||
|
|
||||||
/* Let's try to create the audio irp pin */
|
/* 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))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -345,7 +243,7 @@ CreatePinWorkerRoutine(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retry with Mixer format */
|
/* 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))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* This should not fail */
|
/* This should not fail */
|
||||||
|
@ -390,7 +288,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 = 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))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -454,7 +352,7 @@ HandleSysAudioFilterPinProperties(
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PKSAUDIO_SUBDEVICE_ENTRY Entry;
|
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||||
ULONG BytesReturned;
|
ULONG BytesReturned;
|
||||||
PKSP_PIN Pin;
|
PKSP_PIN Pin;
|
||||||
|
|
||||||
|
@ -541,7 +439,7 @@ HandleSysAudioFilterPinProperties(
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
ComputeCompatibleFormat(
|
ComputeCompatibleFormat(
|
||||||
IN PKSAUDIO_SUBDEVICE_ENTRY Entry,
|
IN PKSAUDIO_DEVICE_ENTRY Entry,
|
||||||
IN ULONG PinId,
|
IN ULONG PinId,
|
||||||
IN PSYSAUDIODEVEXT DeviceExtension,
|
IN PSYSAUDIODEVEXT DeviceExtension,
|
||||||
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
||||||
|
@ -676,7 +574,7 @@ ComputeCompatibleFormat(
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
GetPinInstanceCount(
|
GetPinInstanceCount(
|
||||||
PKSAUDIO_SUBDEVICE_ENTRY Entry,
|
PKSAUDIO_DEVICE_ENTRY Entry,
|
||||||
PKSPIN_CINSTANCES PinInstances,
|
PKSPIN_CINSTANCES PinInstances,
|
||||||
PKSPIN_CONNECT PinConnect)
|
PKSPIN_CONNECT PinConnect)
|
||||||
{
|
{
|
||||||
|
@ -701,7 +599,7 @@ HandleSysAudioFilterPinCreation(
|
||||||
PDEVICE_OBJECT DeviceObject)
|
PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
PKSAUDIO_SUBDEVICE_ENTRY Entry;
|
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||||
KSPIN_CONNECT * PinConnect;
|
KSPIN_CONNECT * PinConnect;
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
||||||
|
@ -848,7 +746,7 @@ SysAudioHandleProperty(
|
||||||
PULONG Index;
|
PULONG Index;
|
||||||
PKSPROPERTY Property;
|
PKSPROPERTY Property;
|
||||||
PSYSAUDIODEVEXT DeviceExtension;
|
PSYSAUDIODEVEXT DeviceExtension;
|
||||||
PKSAUDIO_SUBDEVICE_ENTRY Entry;
|
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||||
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
||||||
ULONG BytesReturned;
|
ULONG BytesReturned;
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
|
|
|
@ -18,7 +18,7 @@ const GUID DMOCATEGORY_ACOUSTIC_ECHO_CANCEL = {0xBF963D80L, 0xC559, 0x11D0, {
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
QueryFilterRoutine(
|
QueryFilterRoutine(
|
||||||
IN PKSAUDIO_SUBDEVICE_ENTRY DeviceEntry)
|
IN PKSAUDIO_DEVICE_ENTRY DeviceEntry)
|
||||||
{
|
{
|
||||||
KSPROPERTY PropertyRequest;
|
KSPROPERTY PropertyRequest;
|
||||||
KSP_PIN PinRequest;
|
KSP_PIN PinRequest;
|
||||||
|
@ -32,15 +32,6 @@ QueryFilterRoutine(
|
||||||
|
|
||||||
DPRINT("Querying filter...\n");
|
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.Set = KSPROPSETID_Pin;
|
||||||
PropertyRequest.Flags = KSPROPERTY_TYPE_GET;
|
PropertyRequest.Flags = KSPROPERTY_TYPE_GET;
|
||||||
PropertyRequest.Id = KSPROPERTY_PIN_CTYPES;
|
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);
|
DPRINT("Num Pins %u Num WaveIn Pins %u Name WaveOut Pins %u\n", DeviceEntry->NumberOfPins, NumWaveInPin, NumWaveOutPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
FilterPinWorkerRoutine(
|
FilterPinWorkerRoutine(
|
||||||
|
@ -124,21 +112,11 @@ FilterPinWorkerRoutine(
|
||||||
IN PVOID Context)
|
IN PVOID Context)
|
||||||
{
|
{
|
||||||
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
|
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
|
||||||
PKSAUDIO_SUBDEVICE_ENTRY SubDeviceEntry;
|
|
||||||
PLIST_ENTRY ListEntry;
|
|
||||||
|
|
||||||
PFILTER_WORKER_CONTEXT Ctx = (PFILTER_WORKER_CONTEXT)Context;
|
PFILTER_WORKER_CONTEXT Ctx = (PFILTER_WORKER_CONTEXT)Context;
|
||||||
|
|
||||||
DeviceEntry = Ctx->DeviceEntry;
|
DeviceEntry = Ctx->DeviceEntry;
|
||||||
|
|
||||||
ListEntry = DeviceEntry->SubDeviceList.Flink;
|
QueryFilterRoutine(DeviceEntry);
|
||||||
while(ListEntry != &DeviceEntry->SubDeviceList)
|
|
||||||
{
|
|
||||||
SubDeviceEntry = (PKSAUDIO_SUBDEVICE_ENTRY)CONTAINING_RECORD(ListEntry, KSAUDIO_SUBDEVICE_ENTRY, Entry);
|
|
||||||
QueryFilterRoutine(SubDeviceEntry);
|
|
||||||
ListEntry = ListEntry->Flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* free work item */
|
/* free work item */
|
||||||
IoFreeWorkItem(Ctx->WorkItem);
|
IoFreeWorkItem(Ctx->WorkItem);
|
||||||
|
@ -177,7 +155,7 @@ OpenDevice(
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("ZwCreateFile failed with %x\n", Status);
|
DPRINT("ZwCreateFile failed with %x %S\n", Status, DeviceName->Buffer);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,125 +173,92 @@ OpenDevice(
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
InsertAudioDevice(
|
||||||
DeviceInterfaceChangeCallback(
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PVOID NotificationStructure,
|
IN PUNICODE_STRING DeviceName,
|
||||||
IN PVOID Context)
|
IN LPWSTR ReferenceString)
|
||||||
{
|
{
|
||||||
DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event;
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PFILTER_WORKER_CONTEXT Ctx = NULL;
|
||||||
|
PIO_WORKITEM WorkItem = NULL;
|
||||||
PSYSAUDIODEVEXT DeviceExtension;
|
PSYSAUDIODEVEXT DeviceExtension;
|
||||||
PKSAUDIO_DEVICE_ENTRY DeviceEntry = NULL;
|
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;
|
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;
|
DPRINT("Successfully opened audio device %u Device %S\n", DeviceExtension->NumberOfKsAudioDevices, DeviceEntry->DeviceName.Buffer);
|
||||||
|
IoQueueWorkItem(WorkItem, FilterPinWorkerRoutine, DelayedWorkQueue, (PVOID)Ctx);
|
||||||
if (IsEqualGUIDAligned(&Event->Event,
|
return Status;
|
||||||
&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;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (Ctx)
|
if (Ctx)
|
||||||
|
@ -331,6 +276,93 @@ cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
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
|
NTSTATUS
|
||||||
|
|
|
@ -201,7 +201,7 @@ DispatchCreateSysAudio(
|
||||||
if (Buffer)
|
if (Buffer)
|
||||||
{
|
{
|
||||||
/* is the request for a new pin */
|
/* 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);
|
Status = CreateDispatcher(Irp);
|
||||||
DPRINT("Virtual pin Status %x FileObject %p\n", Status, IoStatus->FileObject);
|
DPRINT("Virtual pin Status %x FileObject %p\n", Status, IoStatus->FileObject);
|
||||||
|
@ -259,6 +259,7 @@ SysAudioAllocateDeviceHeader(
|
||||||
RtlZeroMemory(CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
|
RtlZeroMemory(CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
|
||||||
CreateItem->Create = DispatchCreateSysAudio;
|
CreateItem->Create = DispatchCreateSysAudio;
|
||||||
RtlInitUnicodeString(&CreateItem->ObjectClass, L"SysAudio");
|
RtlInitUnicodeString(&CreateItem->ObjectClass, L"SysAudio");
|
||||||
|
CreateItem->Flags = KSCREATE_ITEM_WILDCARD;
|
||||||
|
|
||||||
Status = KsAllocateDeviceHeader(&DeviceExtension->KsDeviceHeader,
|
Status = KsAllocateDeviceHeader(&DeviceExtension->KsDeviceHeader,
|
||||||
1,
|
1,
|
||||||
|
@ -271,7 +272,6 @@ SysAudioOpenKMixer(
|
||||||
IN SYSAUDIODEVEXT *DeviceExtension)
|
IN SYSAUDIODEVEXT *DeviceExtension)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\kmixer");
|
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\kmixer");
|
||||||
UNICODE_STRING DevicePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\kmixer");
|
UNICODE_STRING DevicePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\kmixer");
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,8 @@ SysAudio_Shutdown(
|
||||||
IN PIRP Irp)
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
|
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
|
||||||
PKSAUDIO_SUBDEVICE_ENTRY SubDeviceEntry;
|
|
||||||
PSYSAUDIODEVEXT DeviceExtension;
|
PSYSAUDIODEVEXT DeviceExtension;
|
||||||
PLIST_ENTRY Entry, SubEntry;
|
PLIST_ENTRY Entry;
|
||||||
|
|
||||||
DPRINT1("SysAudio_Shutdown called\n");
|
DPRINT1("SysAudio_Shutdown called\n");
|
||||||
|
|
||||||
|
@ -50,16 +49,6 @@ SysAudio_Shutdown(
|
||||||
DPRINT1("Freeing item %wZ\n", &DeviceEntry->DeviceName);
|
DPRINT1("Freeing item %wZ\n", &DeviceEntry->DeviceName);
|
||||||
RtlFreeUnicodeString(&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);
|
ExFreePool(DeviceEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@ typedef struct
|
||||||
|
|
||||||
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
|
HANDLE Handle; // handle to audio sub device
|
||||||
PFILE_OBJECT FileObject; // file objecto 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
|
ULONG NumberOfPins; // number of pins of audio device
|
||||||
PIN_INFO * Pins; // array of PIN_INFO
|
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;
|
}KSAUDIO_DEVICE_ENTRY, *PKSAUDIO_DEVICE_ENTRY;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -71,7 +60,7 @@ typedef struct
|
||||||
{
|
{
|
||||||
HANDLE Handle; // audio irp pin handle
|
HANDLE Handle; // audio irp pin handle
|
||||||
ULONG PinId; // pin id of device
|
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
|
HANDLE hMixerPin; // handle to mixer pin
|
||||||
}DISPATCH_CONTEXT, *PDISPATCH_CONTEXT;
|
}DISPATCH_CONTEXT, *PDISPATCH_CONTEXT;
|
||||||
|
@ -86,7 +75,7 @@ typedef struct
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
BOOL CreateRealPin;
|
BOOL CreateRealPin;
|
||||||
BOOL CreateMixerPin;
|
BOOL CreateMixerPin;
|
||||||
PKSAUDIO_SUBDEVICE_ENTRY Entry;
|
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||||
KSPIN_CONNECT * PinConnect;
|
KSPIN_CONNECT * PinConnect;
|
||||||
PDISPATCH_CONTEXT DispatchContext;
|
PDISPATCH_CONTEXT DispatchContext;
|
||||||
PSYSAUDIODEVEXT DeviceExtension;
|
PSYSAUDIODEVEXT DeviceExtension;
|
||||||
|
@ -129,7 +118,7 @@ OpenDevice(
|
||||||
IN PHANDLE HandleOut,
|
IN PHANDLE HandleOut,
|
||||||
IN PFILE_OBJECT * FileObjectOut);
|
IN PFILE_OBJECT * FileObjectOut);
|
||||||
|
|
||||||
PKSAUDIO_SUBDEVICE_ENTRY
|
PKSAUDIO_DEVICE_ENTRY
|
||||||
GetListEntry(
|
GetListEntry(
|
||||||
IN PLIST_ENTRY Head,
|
IN PLIST_ENTRY Head,
|
||||||
IN ULONG Index);
|
IN ULONG Index);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue