/* @implemented */ KSDDKAPI NTSTATUS NTAPI KsCopyObjectBagItems( IN KSOBJECT_BAG ObjectBagDestination, IN KSOBJECT_BAG ObjectBagSource) { PKSIOBJECT_BAG ObjectBagDest, ObjectBagSrc; PLIST_ENTRY Entry; PKSIOBJECT_BAG_ENTRY BagEntry; NTSTATUS Status = STATUS_SUCCESS; /* get object bag src */ ObjectBagSrc = (PKSIOBJECT_BAG)ObjectBagSource; /* get object bag dst */ ObjectBagDest = (PKSIOBJECT_BAG)ObjectBagDestination; /* acquire source mutex */ KeWaitForSingleObject(ObjectBagSrc->BagMutex, Executive, KernelMode, FALSE, NULL); if (ObjectBagSrc->BagMutex != ObjectBagDest->BagMutex) { /* acquire destination mutex */ KeWaitForSingleObject(ObjectBagDest->BagMutex, Executive, KernelMode, FALSE, NULL); } /* point to first item */ Entry = ObjectBagSrc->ObjectList.Flink; /* first scan the list if the item is already inserted */ while(Entry != &ObjectBagSrc->ObjectList) { /* get bag entry */ BagEntry = (PKSIOBJECT_BAG_ENTRY)CONTAINING_RECORD(Entry, KSIOBJECT_BAG_ENTRY, Entry); /* add the item */ Status = KsAddItemToObjectBag(ObjectBagDestination, BagEntry->Item, BagEntry->Free); /* check for success */ if (!NT_SUCCESS(Status)) break; /* move to next entry */ Entry = Entry->Flink; } if (ObjectBagSrc->BagMutex != ObjectBagDest->BagMutex) { /* release destination mutex */ KeReleaseMutex(ObjectBagDest->BagMutex, FALSE); } /* release source mutex */ KeReleaseMutex(ObjectBagSrc->BagMutex, FALSE); return Status; }
// DispatchCreate是一个类静态函数,它注册给AVStream框架, // 当框架要创建一个Filter对象的时候,将调用此函数。 NTSTATUS CFilter::DispatchCreate ( IN PKSFILTER pKsFilter, IN PIRP Irp ) { PAGED_CODE(); NTSTATUS Status = STATUS_SUCCESS; // 先创建一个CFilter类对象,在系统的非分页池中申请内容。 CFilter *pFilterObj = new (NonPagedPool) CFilter (pKsFilter); do{ if (!pFilterObj) { Status = STATUS_INSUFFICIENT_RESOURCES; break; } // 在AVStream架构中,很重要的一点是要善于利用对象包。 // 把申请到的所有资源都放到对象包中,可以避免资源泄漏。 Status = KsAddItemToObjectBag ( pKsFilter -> Bag, reinterpret_cast <PVOID> (pFilterObj), ClearObj // 释放函数,此处设置为空亦可。 ); if (!NT_SUCCESS (Status)) { delete pFilterObj; break; } // 下面一步非常重要:将Filter类对象指针作为环境参数,保存 // 在KSFILTER框架对象中。由于框架对象是唯一且不变的,所以每 // 次Filter回调被执行的时候,都可以从框架对象中取出类对象。 pKsFilter -> Context = reinterpret_cast <PVOID> (pFilterObj); }while(0); return Status; }
NTSTATUS CCaptureDevice:: Prepare() { PAGED_CODE(); NTSTATUS Status = Initialize(); if( !NT_SUCCESS(Status) ) { return Status; } // // Add the item to the object bag if we were successful. // Whenever the device goes away, the bag is cleaned up and // we will be freed. // // For backwards compatibility with DirectX 8.0, we must grab // the device mutex before doing this. For Windows XP, this is // not required, but it is still safe. // PKSDEVICE Device = m_Device; LockDevice Lock(Device); Status = KsAddItemToObjectBag ( Device -> Bag, reinterpret_cast <PVOID> (this), reinterpret_cast <PFNKSFREE> (CCaptureDevice::Cleanup) ); if( NT_SUCCESS (Status) ) { Device->Context=this; } return Status; }
NTSTATUS CCaptureDevice:: DispatchCreate ( IN PKSDEVICE Device ) /*++ Routine Description: Create the capture device. This is the creation dispatch for the capture device. Arguments: Device - The AVStream device being created. Return Value: Success / Failure --*/ { PAGED_CODE(); NTSTATUS Status; CCaptureDevice *CapDevice = new (NonPagedPool) CCaptureDevice (Device); if (!CapDevice) { // // Return failure if we couldn't create the pin. // Status = STATUS_INSUFFICIENT_RESOURCES; } else { // // Add the item to the object bag if we were successful. // Whenever the device goes away, the bag is cleaned up and // we will be freed. // // For backwards compatibility with DirectX 8.0, we must grab // the device mutex before doing this. For Windows XP, this is // not required, but it is still safe. // KsAcquireDevice (Device); Status = KsAddItemToObjectBag ( Device -> Bag, reinterpret_cast <PVOID> (CapDevice), reinterpret_cast <PFNKSFREE> (CCaptureDevice::Cleanup) ); KsReleaseDevice (Device); if (!NT_SUCCESS (Status)) { delete CapDevice; } else { Device -> Context = reinterpret_cast <PVOID> (CapDevice); } } return Status; }
NTSTATUS CCaptureDevice:: PnpStart ( IN PCM_RESOURCE_LIST TranslatedResourceList, IN PCM_RESOURCE_LIST UntranslatedResourceList ) /*++ Routine Description: Called at Pnp start. We start up our virtual hardware simulation. Arguments: TranslatedResourceList - The translated resource list from Pnp UntranslatedResourceList - The untranslated resource list from Pnp Return Value: Success / Failure --*/ { PAGED_CODE(); // // Normally, we'd do things here like parsing the resource lists and // connecting our interrupt. Since this is a simulation, there isn't // much to parse. The parsing and connection should be the same as // any WDM driver. The sections that will differ are illustrated below // in setting up a simulated DMA. // NTSTATUS Status = STATUS_SUCCESS; if (!m_Device -> Started) { // Create the Filter for the device KsAcquireDevice(m_Device); Status = KsCreateFilterFactory( m_Device->FunctionalDeviceObject, &CaptureFilterDescriptor, L"GLOBAL", NULL, KSCREATE_ITEM_FREEONSTOP, NULL, NULL, NULL ); KsReleaseDevice(m_Device); } // // By PnP, it's possible to receive multiple starts without an intervening // stop (to reevaluate resources, for example). Thus, we only perform // creations of the simulation on the initial start and ignore any // subsequent start. Hardware drivers with resources should evaluate // resources and make changes on 2nd start. // if (NT_SUCCESS(Status) && (!m_Device -> Started)) { m_HardwareSimulation = new (NonPagedPool) CHardwareSimulation (this); if (!m_HardwareSimulation) { // // If we couldn't create the hardware simulation, fail. // Status = STATUS_INSUFFICIENT_RESOURCES; } else { Status = KsAddItemToObjectBag ( m_Device -> Bag, reinterpret_cast <PVOID> (m_HardwareSimulation), reinterpret_cast <PFNKSFREE> (CHardwareSimulation::Cleanup) ); if (!NT_SUCCESS (Status)) { delete m_HardwareSimulation; } } #if defined(_X86_) // // DMA operations illustrated in this sample are applicable only for 32bit platform. // INTERFACE_TYPE InterfaceBuffer; ULONG InterfaceLength; DEVICE_DESCRIPTION DeviceDescription; if (NT_SUCCESS (Status)) { // // Set up DMA... // // Ordinarilly, we'd be using InterfaceBuffer or // InterfaceTypeUndefined if !NT_SUCCESS (IfStatus) as the // InterfaceType below; however, for the purposes of this sample, // we lie and say we're on the PCI Bus. Otherwise, we're using map // registers on x86 32 bit physical to 32 bit logical and this isn't // what I want to show in this sample. // // // NTSTATUS IfStatus = IoGetDeviceProperty ( m_Device -> PhysicalDeviceObject, DevicePropertyLegacyBusType, sizeof (INTERFACE_TYPE), &InterfaceBuffer, &InterfaceLength ); // // Initialize our fake device description. We claim to be a // bus-mastering 32-bit scatter/gather capable piece of hardware. // DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; DeviceDescription.DmaChannel = ((ULONG) ~0); DeviceDescription.InterfaceType = PCIBus; DeviceDescription.DmaWidth = Width32Bits; DeviceDescription.DmaSpeed = Compatible; DeviceDescription.ScatterGather = TRUE; DeviceDescription.Master = TRUE; DeviceDescription.Dma32BitAddresses = TRUE; DeviceDescription.AutoInitialize = FALSE; DeviceDescription.MaximumLength = (ULONG) -1; // // Get a DMA adapter object from the system. // m_DmaAdapterObject = IoGetDmaAdapter ( m_Device -> PhysicalDeviceObject, &DeviceDescription, &m_NumberOfMapRegisters ); if (!m_DmaAdapterObject) { Status = STATUS_UNSUCCESSFUL; } } if (NT_SUCCESS (Status)) { // // Initialize our DMA adapter object with AVStream. This is // **ONLY** necessary **IF** you are doing DMA directly into // capture buffers as this sample does. For this, // KSPIN_FLAG_GENERATE_MAPPINGS must be specified on a queue. // // // The (1 << 20) below is the maximum size of a single s/g mapping // that this hardware can handle. Note that I have pulled this // number out of thin air for the "fake" hardware. // KsDeviceRegisterAdapterObject ( m_Device, m_DmaAdapterObject, (1 << 20), sizeof (KSMAPPING) ); } #endif } return Status; }
NTSTATUS CStillPin:: DispatchCreate ( IN PKSPIN Pin, IN PIRP Irp ) /*++ Routine Description: Create a new capture pin. This is the creation dispatch for the video capture pin. Arguments: Pin - The pin being created Irp - The creation Irp Return Value: Success / Failure --*/ { PAGED_CODE(); NTSTATUS Status = STATUS_SUCCESS; DBGU_TRACE("Enter CStillPin::DispatchCreate\n"); CStillPin *StiPin = new (NonPagedPool) CStillPin (Pin); if (!StiPin) { // // Return failure if we couldn't create the pin. // Status = STATUS_INSUFFICIENT_RESOURCES; } else { // // Add the item to the object bag if we we were successful. // Whenever the pin closes, the bag is cleaned up and we will be // freed. // Status = KsAddItemToObjectBag ( Pin -> Bag, reinterpret_cast <PVOID> (StiPin), reinterpret_cast <PFNKSFREE> (CStillPin::Cleanup) ); if (!NT_SUCCESS (Status)) { delete StiPin; } else { Pin -> Context = reinterpret_cast <PVOID> (StiPin); } } // // If we succeeded so far, stash the video info header away and change // our allocator framing to reflect the fact that only now do we know // the framing requirements based on the connection format. // PKS_VIDEOINFOHEADER VideoInfoHeader = NULL; // for Vista change to KS_VIDEOINFOHEADER2 if (NT_SUCCESS (Status)) { VideoInfoHeader = StiPin -> CaptureVideoInfoHeader (); if (!VideoInfoHeader) { Status = STATUS_INSUFFICIENT_RESOURCES; } } if (NT_SUCCESS (Status)) { // // We need to edit the descriptor to ensure we don't mess up any other // pins using the descriptor or touch read-only memory. // Status = KsEdit ( Pin, &Pin -> Descriptor, AVSHWS_POOLTAG); if (NT_SUCCESS (Status)) { do { PKSFILTER Filter = (PKSFILTER)KsGetParent(Pin); if (!Filter) { Status = STATUS_UNSUCCESSFUL; break; } CCaptureFilter* ParentFilter = static_cast<CCaptureFilter*>(Filter -> Context); if (!ParentFilter) { Status = STATUS_UNSUCCESSFUL; break; } } while (FALSE); } // // If the edits proceeded without running out of memory, adjust // the framing based on the video info header. // Status = KsEdit ( Pin, &Pin -> Descriptor -> AllocatorFraming, AVSHWS_POOLTAG); if (NT_SUCCESS (Status)) { // // We've KsEdit'ed this... I'm safe to cast away constness as // long as the edit succeeded. // PKSALLOCATOR_FRAMING_EX Framing = const_cast <PKSALLOCATOR_FRAMING_EX> ( Pin -> Descriptor -> AllocatorFraming ); Framing -> FramingItem [0].Frames = 2; // // The physical and optimal ranges must be biSizeImage. We only // support one frame size, precisely the size of each capture // image. // Framing -> FramingItem [0].PhysicalRange.MinFrameSize = Framing -> FramingItem [0].PhysicalRange.MaxFrameSize = Framing -> FramingItem [0].FramingRange.Range.MinFrameSize = Framing -> FramingItem [0].FramingRange.Range.MaxFrameSize = VideoInfoHeader -> bmiHeader.biSizeImage; Framing -> FramingItem [0].PhysicalRange.Stepping = Framing -> FramingItem [0].FramingRange.Range.Stepping = 0; } } PKSDEVICE pDevice = KsPinGetDevice (Pin); CCaptureDevice *pCapDevice = reinterpret_cast <CCaptureDevice *> (pDevice -> Context); if (!pCapDevice) Status = STATUS_UNSUCCESSFUL; if (NT_SUCCESS (Status)) { Status = pCapDevice->StreamOpen(TRUE,Pin); } DBGU_TRACE("Exit CStillPin::DispatchCreate Status= %X\n",Status); return Status; }
PKS_VIDEOINFOHEADER CStillPin:: CaptureVideoInfoHeader ( ) /*++ Routine Description: Capture the video info header out of the connection format. This is what we use to base synthesized images off. Arguments: None Return Value: The captured video info header or NULL if there is insufficient memory. --*/ { PAGED_CODE(); DBGU_TRACE("Enter CStillPin::CaptureVideoInfoHeader\n"); PKS_VIDEOINFOHEADER ConnectionHeader = &((reinterpret_cast <PKS_DATAFORMAT_VIDEOINFOHEADER> (m_Pin -> ConnectionFormat)) -> VideoInfoHeader); // for KS_VIDEOINFOHEADER2 m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> ( ExAllocatePoolWithTag ( NonPagedPool, KS_SIZE_VIDEOHEADER (ConnectionHeader), AVSHWS_POOLTAG ) ); if (!m_VideoInfoHeader) return NULL; // // Bag the newly allocated header space. This will get cleaned up // automatically when the pin closes. // NTSTATUS Status = KsAddItemToObjectBag ( m_Pin -> Bag, reinterpret_cast <PVOID> (m_VideoInfoHeader), NULL ); if (!NT_SUCCESS (Status)) { ExFreePoolWithTag (m_VideoInfoHeader); m_VideoInfoHeader = NULL; return NULL; } else { // // Copy the connection format video info header into the newly // allocated "captured" video info header. // RtlCopyMemory ( m_VideoInfoHeader, ConnectionHeader, KS_SIZE_VIDEOHEADER (ConnectionHeader) ); } return m_VideoInfoHeader; }
NTSTATUS CCaptureFilter:: DispatchCreate ( IN PKSFILTER Filter, IN PIRP Irp ) /*++ Routine Description: This is the creation dispatch for the capture filter. It creates the CCaptureFilter object, associates it with the AVStream filter object, and bag the CCaptureFilter for later cleanup. Arguments: Filter - The AVStream filter being created Irp - The creation Irp Return Value: Success / failure --*/ { PAGED_CODE(); NTSTATUS Status = STATUS_SUCCESS; DBGU_TRACE("Enter CCaptureFilter::DispatchCreate\n"); CCaptureFilter *CapFilter = new (NonPagedPool) CCaptureFilter (Filter); if (!CapFilter) { // // Return failure if we couldn't create the filter. // Status = STATUS_INSUFFICIENT_RESOURCES; } else { // // Add the item to the object bag if we we were successful. // Whenever the filter closes, the bag is cleaned up and we will be // freed. // Status = KsAddItemToObjectBag ( Filter -> Bag, reinterpret_cast <PVOID> (CapFilter), reinterpret_cast <PFNKSFREE> (CCaptureFilter::Cleanup) ); if (!NT_SUCCESS (Status)) { delete CapFilter; } else { Filter -> Context = reinterpret_cast <PVOID> (CapFilter); CCaptureDevice *pCaptureDevice = reinterpret_cast<CCaptureDevice *>(CapFilter->m_Device->Context); if (!pCaptureDevice) return STATUS_UNSUCCESSFUL; InterlockedIncrement(&pCaptureDevice->pdx->m_cRef); //2010/8/26 11:05¤W¤È //if (pCaptureDevice->pdx->m_bDeviceIdle) if (pCaptureDevice->pdx->m_cRef > 0&& pCaptureDevice->pdx->m_bDeviceIdle && pCaptureDevice->pdx->DevicePowerState != PowerDeviceD0) { pCaptureDevice->pdx->pVideoDevice->CancelSelectiveSuspend(); pCaptureDevice->pdx->pVideoDevice->SendDeviceSetPower(PowerDeviceD0, FALSE); pCaptureDevice->pdx->m_bDeviceIdle = FALSE; } } } DBGU_TRACE("Leave CCaptureFilter::DispatchCreate with %d\n", Status); return Status; }
NTSTATUS CCaptureFilter:: DispatchCreate ( IN PKSFILTER Filter, IN PIRP Irp ) /*++ Routine Description: This is the creation dispatch for the capture filter. It creates the CCaptureFilter object, associates it with the AVStream filter object, and bag the CCaptureFilter for later cleanup. Arguments: Filter - The AVStream filter being created Irp - The creation Irp Return Value: Success / failure --*/ { PAGED_CODE(); NTSTATUS Status = STATUS_SUCCESS; CCaptureFilter *CapFilter = new (NonPagedPool) CCaptureFilter (Filter); if (!CapFilter) { // // Return failure if we couldn't create the filter. // Status = STATUS_INSUFFICIENT_RESOURCES; } else { // // Add the item to the object bag if we we were successful. // Whenever the filter closes, the bag is cleaned up and we will be // freed. // Status = KsAddItemToObjectBag ( Filter -> Bag, reinterpret_cast <PVOID> (CapFilter), reinterpret_cast <PFNKSFREE> (CCaptureFilter::Cleanup) ); if (!NT_SUCCESS (Status)) { delete CapFilter; } else { Filter -> Context = reinterpret_cast <PVOID> (CapFilter); } } return Status; }
NTSTATUS CEncoderPin:: DispatchCreate ( IN PKSPIN Pin, IN PIRP Irp ) /*++ Routine Description: Create a new capture pin. This is the creation dispatch for the video capture pin. Arguments: Pin - The pin being created Irp - The creation Irp Return Value: Success / Failure --*/ { PAGED_CODE(); NTSTATUS Status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(Irp); CEncoderPin *EncPin = new (NonPagedPool, MS_SAMPLE_ANALOG_POOL_TAG) CEncoderPin (Pin); if (!EncPin) { // // Return failure if we couldn't create the pin. // Status = STATUS_INSUFFICIENT_RESOURCES; } else { // // Add the item to the object bag if we we were successful. // Whenever the pin closes, the bag is cleaned up and we will be // freed. // Status = KsAddItemToObjectBag ( Pin -> Bag, reinterpret_cast <PVOID> (EncPin), reinterpret_cast <PFNKSFREE> (CEncoderPin::Cleanup) ); if (!NT_SUCCESS (Status)) { delete EncPin; } else { Pin -> Context = reinterpret_cast <PVOID> (EncPin); } } // // If we succeeded so far, stash the video info header away and change // our allocator framing to reflect the fact that only now do we know // the framing requirements based on the connection format. // PBDA_TRANSPORT_INFO TransportInfo = NULL; if (NT_SUCCESS (Status)) { TransportInfo = EncPin -> EncoderBdaTransportInfo (); if (!TransportInfo) { Status = STATUS_INSUFFICIENT_RESOURCES; } } if (NT_SUCCESS (Status)) { // // We need to edit the descriptor to ensure we don't mess up any other // pins using the descriptor or touch read-only memory. // Status = KsEdit (Pin, &Pin -> Descriptor, MS_SAMPLE_ANALOG_POOL_TAG); if (NT_SUCCESS (Status)) { Status = KsEdit ( Pin, &(Pin -> Descriptor -> AllocatorFraming), MS_SAMPLE_ANALOG_POOL_TAG ); } // // If the edits proceeded without running out of memory, adjust // the framing based on the video info header. // if (NT_SUCCESS (Status)) { // // We've KsEdit'ed this... I'm safe to cast away constness as // long as the edit succeeded. // PKSALLOCATOR_FRAMING_EX Framing = const_cast <PKSALLOCATOR_FRAMING_EX> ( Pin -> Descriptor -> AllocatorFraming ); Framing -> FramingItem [0].Frames = 8; // // The physical and optimal ranges must be biSizeImage. We only // support one frame size, precisely the size of each capture // image. // Framing -> FramingItem [0].PhysicalRange.MinFrameSize = Framing -> FramingItem [0].PhysicalRange.MaxFrameSize = Framing -> FramingItem [0].FramingRange.Range.MinFrameSize = Framing -> FramingItem [0].FramingRange.Range.MaxFrameSize = TransportInfo -> ulcbPhyiscalFrame; Framing -> FramingItem [0].PhysicalRange.Stepping = Framing -> FramingItem [0].FramingRange.Range.Stepping = 0; } } return Status; }
PBDA_TRANSPORT_INFO CEncoderPin:: EncoderBdaTransportInfo ( ) /*++ Routine Description: Encoder the video info header out of the connection format. This is what we use to base synthesized images off. Arguments: None Return Value: The captured video info header or NULL if there is insufficient memory. --*/ { PAGED_CODE(); m_TransportInfo = reinterpret_cast <PBDA_TRANSPORT_INFO> ( ExAllocatePoolWithTag ( NonPagedPool, sizeof(BDA_TRANSPORT_INFO), MS_SAMPLE_ANALOG_POOL_TAG ) ); if (!m_TransportInfo) return NULL; // // Bag the newly allocated header space. This will get cleaned up // automatically when the pin closes. // NTSTATUS Status = KsAddItemToObjectBag ( m_Pin -> Bag, reinterpret_cast <PVOID> (m_TransportInfo), NULL ); if (!NT_SUCCESS (Status)) { ExFreePool (m_TransportInfo); return NULL; } else { m_TransportInfo->ulcbPhyiscalPacket = PS_PACKET_SIZE; m_TransportInfo->ulcbPhyiscalFrame = PS_SAMPLE_SIZE; m_TransportInfo->ulcbPhyiscalFrameAlignment = 1; m_TransportInfo->AvgTimePerFrame = PS_SAMPLE_SIZE * 8 * 10 / 15; //in 100ns units, <15Mbit/s } return m_TransportInfo; }
/***************************************************************************** * CreateMidiFilterFactory() ***************************************************************************** *//*! * @brief * Filter factory create function. * @details * Creates a device control filter factory. * @return * Returns STATUS_SUCCESS if successful. Otherwise, returns an appropriate * error code. */ NTSTATUS CreateMidiFilterFactory ( IN PKSDEVICE KsDevice, IN PWCHAR RefString, IN PVOID Parameter1, IN PVOID Parameter2 ) { PAGED_CODE(); _DbgPrintF(DEBUGLVL_BLAB,("[CMidiFilterFactory::Instantiate]")); NTSTATUS ntStatus; CMidiFilterFactory * FilterFactory = new(NonPagedPool,'rCcP') CMidiFilterFactory(NULL); if (FilterFactory) { FilterFactory->AddRef(); ntStatus = FilterFactory->Init(KsDevice, Parameter1, Parameter2); PKSFILTER_DESCRIPTOR KsFilterDescriptor = NULL; if (NT_SUCCESS(ntStatus)) { ntStatus = FilterFactory->GetFilterDescription(&KsFilterDescriptor); } if (NT_SUCCESS(ntStatus)) { #define PROXY_CLSID L"{17CCA71B-ECD7-11D0-B908-00A0C9223196}" PKSADAPTER KsAdapter = PKSADAPTER(KsDevice->Context); for (ULONG i = 0; i < KsFilterDescriptor->CategoriesCount; i++) { // Do what normally done by INF AddInterface directive. KsAdapter->AddSubDeviceInterface(RefString, KsFilterDescriptor->Categories[i]); KsAdapter->SetSubDeviceParameter(RefString, KsFilterDescriptor->Categories[i], L"CLSID", REG_SZ, PROXY_CLSID, sizeof(PROXY_CLSID)); } CMidiFilterFactory::SetupFriendlyName(KsAdapter, KsFilterDescriptor, RefString, Parameter1, Parameter2); KsAcquireDevice(KsDevice); PKSFILTERFACTORY KsFilterFactory = NULL; ntStatus = KsCreateFilterFactory ( KsDevice->FunctionalDeviceObject, KsFilterDescriptor, RefString, NULL, 0, CMidiFilterFactory::SleepCallback, CMidiFilterFactory::WakeCallback, &KsFilterFactory ); if (NT_SUCCESS(ntStatus)) { KsFilterFactory->Context = PVOID(FilterFactory); } KsReleaseDevice(KsDevice); } if (NT_SUCCESS(ntStatus)) { // // Add the item to the object bag if we were successful. Whenever the device goes // away, the bag is cleaned up and we will be freed. // // For backwards compatibility with DirectX 8.0, we must grab the device mutex // before doing this. For Windows XP, this is not required, but it is still safe. // KsAcquireDevice(KsDevice); ntStatus = KsAddItemToObjectBag(KsDevice->Bag, FilterFactory, (PFNKSFREE)CMidiFilterFactory::Destruct); KsReleaseDevice(KsDevice); } if (NT_SUCCESS(ntStatus)) { // Keeping this object... FilterFactory->AddRef(); } // Release the private reference. FilterFactory->Release(); } else { ntStatus = STATUS_INSUFFICIENT_RESOURCES; } return ntStatus; }
/* @implemented */ KSDDKAPI NTSTATUS NTAPI _KsEdit( IN KSOBJECT_BAG ObjectBag, IN OUT PVOID* PointerToPointerToItem, IN ULONG NewSize, IN ULONG OldSize, IN ULONG Tag) { PKSIOBJECT_BAG Bag; PKSIOBJECT_BAG_ENTRY BagEntry; PVOID Item; NTSTATUS Status; DPRINT("_KsEdit\n"); /* get real object bag */ Bag = (PKSIOBJECT_BAG)ObjectBag; /* acquire bag mutex */ KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL); if (*PointerToPointerToItem) { /* search object bag for this entry */ BagEntry = KspFindObjectBagItem(&Bag->ObjectList, *PointerToPointerToItem); } else { /* pointer to null, allocate new entry */ BagEntry = NULL; } if (!BagEntry || NewSize > OldSize) { /* entry does not exist or new entry must be allocated */ Item = AllocateItem(NonPagedPool, NewSize); if (!Item) { /* not enough resources */ KeReleaseMutex(Bag->BagMutex, FALSE); return STATUS_INSUFFICIENT_RESOURCES; } /* now add the item to the object bag */ Status = KsAddItemToObjectBag((KSOBJECT_BAG)Bag, Item, NULL); /* check for success */ if (!NT_SUCCESS(Status)) { /* failed to add item */ FreeItem(Item); KeReleaseMutex(Bag->BagMutex, FALSE); return Status; } if (*PointerToPointerToItem) { /* object exists */ if (OldSize >= NewSize) { /* copy old contents */ RtlMoveMemory(Item, *PointerToPointerToItem, NewSize); } else { /* copy new contents */ RtlMoveMemory(Item, *PointerToPointerToItem, OldSize); } } if (BagEntry) { /* remove old entry */ KsRemoveItemFromObjectBag(ObjectBag, BagEntry->Item, TRUE); } /* store item */ *PointerToPointerToItem = Item; } /* release bag mutex */ KeReleaseMutex(Bag->BagMutex, FALSE); return STATUS_SUCCESS; }