NTSTATUS NTAPI PcRegisterSubdevice( IN PDEVICE_OBJECT DeviceObject, IN PWCHAR Name, IN PUNKNOWN Unknown) { PPCLASS_DEVICE_EXTENSION DeviceExt; NTSTATUS Status; ISubdevice *SubDevice; UNICODE_STRING SymbolicLinkName; PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor; ULONG Index; UNICODE_STRING RefName; PSYMBOLICLINK_ENTRY SymEntry; DPRINT("PcRegisterSubdevice DeviceObject %p Name %S Unknown %p\n", DeviceObject, Name, Unknown); PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); // check if all parameters are valid if (!DeviceObject || !Name || !Unknown) { DPRINT("PcRegisterSubdevice invalid parameter\n"); return STATUS_INVALID_PARAMETER; } // get device extension DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; if (!DeviceExt) { // should not happen DbgBreakPoint(); return STATUS_UNSUCCESSFUL; } // look up our undocumented interface Status = Unknown->QueryInterface(IID_ISubdevice, (LPVOID*)&SubDevice); if (!NT_SUCCESS(Status)) { DPRINT("No ISubdevice interface\n"); // the provided port driver doesnt support ISubdevice return STATUS_INVALID_PARAMETER; } // get the subdevice descriptor Status = SubDevice->GetDescriptor(&SubDeviceDescriptor); if (!NT_SUCCESS(Status)) { DPRINT("Failed to get subdevice descriptor %x\n", Status); SubDevice->Release(); return STATUS_UNSUCCESSFUL; } // add an create item to the device header Status = KsAddObjectCreateItemToDeviceHeader(DeviceExt->KsDeviceHeader, PcCreateItemDispatch, (PVOID)SubDevice, Name, NULL); if (!NT_SUCCESS(Status)) { // failed to attach SubDevice->Release(); DPRINT("KsAddObjectCreateItemToDeviceHeader failed with %x\n", Status); return Status; } // initialize reference string RtlInitUnicodeString(&RefName, Name); RtlInitUnicodeString(&SubDeviceDescriptor->RefString, Name); for(Index = 0; Index < SubDeviceDescriptor->InterfaceCount; Index++) { // FIXME // check if reference string with that name already exists Status = IoRegisterDeviceInterface(DeviceExt->PhysicalDeviceObject, &SubDeviceDescriptor->Interfaces[Index], &RefName, &SymbolicLinkName); if (NT_SUCCESS(Status)) { // activate device interface IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE); // allocate symbolic link entry SymEntry = (PSYMBOLICLINK_ENTRY)AllocateItem(NonPagedPool, sizeof(SYMBOLICLINK_ENTRY), TAG_PORTCLASS); if (SymEntry) { // initialize symbolic link item RtlInitUnicodeString(&SymEntry->SymbolicLink, SymbolicLinkName.Buffer); // store item InsertTailList(&SubDeviceDescriptor->SymbolicLinkList, &SymEntry->Entry); } else { // allocating failed RtlFreeUnicodeString(&SymbolicLinkName); } } } // release SubDevice reference SubDevice->Release(); return STATUS_SUCCESS; }
NTSTATUS NTAPI PcCreateItemDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS Status; ISubdevice * SubDevice; IIrpTarget *Filter; PKSOBJECT_CREATE_ITEM CreateItem, PinCreateItem; // access the create item CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp); DPRINT("PcCreateItemDispatch called DeviceObject %p %S Name\n", DeviceObject, CreateItem->ObjectClass.Buffer); // get the subdevice SubDevice = (ISubdevice*)CreateItem->Context; // sanity checks PC_ASSERT(SubDevice != NULL); #if KS_IMPLEMENTED Status = KsReferenceSoftwareBusObject(DeviceExt->KsDeviceHeader); if (!NT_SUCCESS(Status) && Status != STATUS_NOT_IMPLEMENTED) { DPRINT("PcCreateItemDispatch failed to reference device header\n"); FreeItem(Entry, TAG_PORTCLASS); goto cleanup; } #endif // get filter object Status = SubDevice->NewIrpTarget(&Filter, NULL, NULL, NonPagedPool, DeviceObject, Irp, NULL); if (!NT_SUCCESS(Status)) { DPRINT("Failed to get filter object\n"); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } // allocate pin create item PinCreateItem = (PKSOBJECT_CREATE_ITEM)AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM), TAG_PORTCLASS); if (!PinCreateItem) { // not enough memory Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INSUFFICIENT_RESOURCES; } // initialize pin create item PinCreateItem->Context = (PVOID)Filter; PinCreateItem->Create = PcCreatePinDispatch; RtlInitUnicodeString(&PinCreateItem->ObjectClass, KSSTRING_Pin); // FIXME copy security descriptor // now allocate a dispatch object Status = NewDispatchObject(Irp, Filter, 1, PinCreateItem); // complete request Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; }
NTSTATUS NTAPI PinPropertyHandler( IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data) { PIO_STACK_LOCATION IoStack; //PKSOBJECT_CREATE_ITEM CreateItem; PSUBDEVICE_DESCRIPTOR Descriptor; IIrpTarget * IrpTarget; IPort *Port; ISubdevice *SubDevice; PDISPATCH_CONTEXT DispatchContext; NTSTATUS Status = STATUS_UNSUCCESSFUL; Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); PC_ASSERT(Descriptor); // get current irp stack IoStack = IoGetCurrentIrpStackLocation(Irp); // get dispatch context DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; // Get the IrpTarget IrpTarget = DispatchContext->Target; PC_ASSERT(IrpTarget); // Get the parent Status = IrpTarget->QueryInterface(IID_IPort, (PVOID*)&Port); if (!NT_SUCCESS(Status)) { DPRINT("Failed to obtain IPort interface from filter\n"); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL; } // Get private ISubdevice interface Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&SubDevice); if (!NT_SUCCESS(Status)) { DPRINT("Failed to obtain ISubdevice interface from port driver\n"); DbgBreakPoint(); while(TRUE); } // get current stack location IoStack = IoGetCurrentIrpStackLocation(Irp); switch(Request->Id) { case KSPROPERTY_PIN_CTYPES: case KSPROPERTY_PIN_DATAFLOW: case KSPROPERTY_PIN_DATARANGES: case KSPROPERTY_PIN_INTERFACES: case KSPROPERTY_PIN_MEDIUMS: case KSPROPERTY_PIN_COMMUNICATION: case KSPROPERTY_PIN_CATEGORY: case KSPROPERTY_PIN_NAME: case KSPROPERTY_PIN_PROPOSEDATAFORMAT: Status = KsPinPropertyHandler(Irp, Request, Data, Descriptor->Factory.PinDescriptorCount, Descriptor->Factory.KsPinDescriptor); break; case KSPROPERTY_PIN_GLOBALCINSTANCES: Status = HandlePropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, TRUE, SubDevice); break; case KSPROPERTY_PIN_CINSTANCES: Status = HandlePropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, FALSE, SubDevice); break; case KSPROPERTY_PIN_NECESSARYINSTANCES: Status = HandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, SubDevice); break; case KSPROPERTY_PIN_DATAINTERSECTION: Status = HandleDataIntersection(&Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Descriptor, SubDevice); break; case KSPROPERTY_PIN_PHYSICALCONNECTION: Status = HandlePhysicalConnection(&Irp->IoStatus, Request, IoStack->Parameters.DeviceIoControl.InputBufferLength, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Descriptor); break; case KSPROPERTY_PIN_CONSTRAINEDDATARANGES: UNIMPLEMENTED Status = STATUS_NOT_IMPLEMENTED; break; default: UNIMPLEMENTED Status = STATUS_UNSUCCESSFUL; } // Release reference Port->Release(); // Release subdevice reference SubDevice->Release(); return Status; }
NTSTATUS NTAPI CPortPinWavePci::Init( IN PPORTWAVEPCI Port, IN PPORTFILTERWAVEPCI Filter, IN KSPIN_CONNECT * ConnectDetails, IN KSPIN_DESCRIPTOR * KsPinDescriptor, IN PDEVICE_OBJECT DeviceObject) { NTSTATUS Status; PKSDATAFORMAT DataFormat; BOOLEAN Capture; ISubdevice * Subdevice = NULL; PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL; // check if it is a source / sink pin if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN) { // sink pin Capture = FALSE; } else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT) { // source pin Capture = TRUE; } else { DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow); DbgBreakPoint(); while(TRUE); } // add port / filter reference Port->AddRef(); Filter->AddRef(); // initialize pin m_Port = Port; m_Filter = Filter; m_KsPinDescriptor = KsPinDescriptor; m_ConnectDetails = ConnectDetails; m_Miniport = GetWavePciMiniport(Port); m_DeviceObject = DeviceObject; m_State = KSSTATE_STOP; m_Capture = Capture; DPRINT("IPortPinWavePci_fnInit entered\n"); // get dataformat DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1); // allocate data format m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS); if (!m_Format) { // release references m_Port->Release(); m_Filter->Release(); // no dangling pointers Port = NULL; Filter = NULL; // failed to allocate data format return STATUS_INSUFFICIENT_RESOURCES; } // copy data format RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize); // allocate new stream Status = m_Miniport->NewStream(&m_Stream, NULL, NonPagedPool, PPORTWAVEPCISTREAM(this), ConnectDetails->PinId, Capture, m_Format, &m_DmaChannel, &m_ServiceGroup); DPRINT("IPortPinWavePci_fnInit Status %x\n", Status); if (!NT_SUCCESS(Status)) { // free references Port->Release(); Filter->Release(); // free data format FreeItem(m_Format, TAG_PORTCLASS); // no dangling pointers m_Port = NULL; m_Filter = NULL; m_Format = NULL; // failed to allocate stream return Status; } // get allocator requirements for pin Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming); if (NT_SUCCESS(Status)) { DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n", m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment); } // allocate new irp queue Status = NewIrpQueue(&m_IrpQueue); if (!NT_SUCCESS(Status)) { // free references Port->Release(); Filter->Release(); m_Stream->Release(); // free data format FreeItem(m_Format, TAG_PORTCLASS); // no dangling pointers m_Port = NULL; m_Filter = NULL; m_Format = NULL; m_Stream = NULL; // failed to allocate irp queue return Status; } // initialize irp queue Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, TRUE); if (!NT_SUCCESS(Status)) { // this should never happen ASSERT(0); } // get subdevice interface Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice); if (!NT_SUCCESS(Status)) { // this function should never fail ASSERT(0); } // get subdevice descriptor Status = Subdevice->GetDescriptor(&SubDeviceDescriptor); if (!NT_SUCCESS(Status)) { // this function should never fail ASSERT(0); } // release subdevice Subdevice->Release(); /* set up subdevice descriptor */ RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR)); m_Descriptor.FilterPropertySet = PinWavePciPropertySet; m_Descriptor.FilterPropertySetCount = sizeof(PinWavePciPropertySet) / sizeof(KSPROPERTY_SET); m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream; m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor; m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport; m_Descriptor.PortPin = (PVOID)this; if (m_ServiceGroup) { Status = m_ServiceGroup->AddMember(PSERVICESINK(this)); if (!NT_SUCCESS(Status)) { // free references m_Stream->Release(); Port->Release(); Filter->Release(); // free data format FreeItem(m_Format, TAG_PORTCLASS); // no dangling pointers m_Stream = NULL; m_Port = NULL; m_Filter = NULL; m_Format = NULL; // failed to add to service group return Status; } } return STATUS_SUCCESS; }