ReactOS Fundraising Campaign 2012
 
€ 3,873 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

filter.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS Kernel Streaming
00004  * FILE:            drivers/ksfilter/ks/filter.c
00005  * PURPOSE:         KS IKsFilter interface functions
00006  * PROGRAMMER:      Johannes Anderwald
00007  */
00008 
00009 
00010 #include "priv.h"
00011 
00012 typedef struct
00013 {
00014     KSBASIC_HEADER Header;
00015     KSFILTER Filter;
00016 
00017     IKsControlVtbl *lpVtblKsControl;
00018     IKsFilterFactory * FilterFactory;
00019     IKsProcessingObjectVtbl * lpVtblKsProcessingObject;
00020     LONG ref;
00021 
00022     PKSIOBJECT_HEADER ObjectHeader;
00023     KSTOPOLOGY Topology;
00024     PKSFILTERFACTORY Factory;
00025     PFILE_OBJECT FileObject;
00026     KMUTEX ControlMutex;
00027     KMUTEX ProcessingMutex;
00028 
00029     PKSWORKER Worker;
00030     WORK_QUEUE_ITEM WorkItem;
00031     KSGATE Gate;
00032 
00033     PFNKSFILTERPOWER Sleep;
00034     PFNKSFILTERPOWER Wake;
00035 
00036     ULONG *PinInstanceCount;
00037     PKSPIN * FirstPin;
00038     PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
00039 
00040 }IKsFilterImpl;
00041 
00042 const GUID IID_IKsControl = {0x28F54685L, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
00043 const GUID IID_IKsFilter  = {0x3ef6ee44L, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc0, 0x4f, 0x8e, 0xF4, 0x57}};
00044 const GUID KSPROPSETID_Topology                = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
00045 const GUID KSPROPSETID_Pin                     = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
00046 
00047 VOID
00048 IKsFilter_RemoveFilterFromFilterFactory(
00049     IKsFilterImpl * This,
00050     PKSFILTERFACTORY FilterFactory);
00051 
00052 NTSTATUS NTAPI FilterTopologyPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER  Request, IN OUT PVOID  Data);
00053 NTSTATUS NTAPI FilterPinPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER  Request, IN OUT PVOID  Data);
00054 
00055 
00056 DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet, FilterTopologyPropertyHandler);
00057 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet, FilterPinPropertyHandler, FilterPinPropertyHandler, FilterPinPropertyHandler);
00058 
00059 KSPROPERTY_SET FilterPropertySet[] =
00060 {
00061     {
00062         &KSPROPSETID_Topology,
00063         sizeof(IKsFilterTopologySet) / sizeof(KSPROPERTY_ITEM),
00064         (const KSPROPERTY_ITEM*)&IKsFilterTopologySet,
00065         0,
00066         NULL
00067     },
00068     {
00069         &KSPROPSETID_Pin,
00070         sizeof(IKsFilterPinSet) / sizeof(KSPROPERTY_ITEM),
00071         (const KSPROPERTY_ITEM*)&IKsFilterPinSet,
00072         0,
00073         NULL
00074     }
00075 };
00076 
00077 NTSTATUS
00078 NTAPI
00079 IKsProcessingObject_fnQueryInterface(
00080     IKsProcessingObject * iface,
00081     IN  REFIID refiid,
00082     OUT PVOID* Output)
00083 {
00084     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
00085 
00086     if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
00087     {
00088         *Output = &This->Header.OuterUnknown;
00089         _InterlockedIncrement(&This->ref);
00090         return STATUS_SUCCESS;
00091     }
00092     return STATUS_UNSUCCESSFUL;
00093 }
00094 
00095 ULONG
00096 NTAPI
00097 IKsProcessingObject_fnAddRef(
00098     IKsProcessingObject * iface)
00099 {
00100     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
00101 
00102     return InterlockedIncrement(&This->ref);
00103 }
00104 
00105 ULONG
00106 NTAPI
00107 IKsProcessingObject_fnRelease(
00108     IKsProcessingObject * iface)
00109 {
00110     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
00111 
00112     InterlockedDecrement(&This->ref);
00113 
00114     /* Return new reference count */
00115     return This->ref;
00116 }
00117 
00118 VOID
00119 NTAPI
00120 IKsProcessingObject_fnProcessingObjectWork(
00121     IKsProcessingObject * iface)
00122 {
00123     NTSTATUS Status;
00124     LARGE_INTEGER TimeOut;
00125     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
00126 
00127     DPRINT1("processing object\n");
00128     /* first check if running at passive level */
00129     if (KeGetCurrentIrql() == PASSIVE_LEVEL)
00130     {
00131         /* acquire processing mutex */
00132         KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, NULL);
00133     }
00134     else
00135     {
00136         /* dispatch level processing */
00137         if (KeReadStateMutex(&This->ControlMutex) == 0)
00138         {
00139             /* some thread was faster */
00140             DPRINT1("processing object too slow\n");
00141             return;
00142         }
00143 
00144         /* acquire processing mutex */
00145         TimeOut.QuadPart = 0LL;
00146         Status = KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, &TimeOut);
00147 
00148         if (Status == STATUS_TIMEOUT)
00149         {
00150             /* some thread was faster */
00151             DPRINT1("processing object too slow\n");
00152             return;
00153         }
00154     }
00155 
00156     do
00157     {
00158 
00159         /* check if the and-gate has been enabled again */
00160         if (&This->Gate.Count != 0)
00161         {
00162             /* gate is open */
00163             DPRINT1("processing object gate open\n");
00164             break;
00165         }
00166 
00167         DPRINT1("IKsProcessingObject_fnProcessingObjectWork not implemented\n");
00168         ASSERT(0);
00169 
00170     }while(TRUE);
00171 
00172     /* release process mutex */
00173     KeReleaseMutex(&This->ProcessingMutex, FALSE);
00174 }
00175 
00176 PKSGATE
00177 NTAPI
00178 IKsProcessingObject_fnGetAndGate(
00179     IKsProcessingObject * iface)
00180 {
00181     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
00182 
00183     /* return and gate */
00184     return &This->Gate;
00185 }
00186 
00187 VOID
00188 NTAPI
00189 IKsProcessingObject_fnProcess(
00190     IKsProcessingObject * iface,
00191     IN BOOLEAN Asynchronous)
00192 {
00193     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
00194 
00195     /* should the action be asynchronous */
00196     if (Asynchronous)
00197     {
00198         /* queue work item */
00199         KsQueueWorkItem(This->Worker, &This->WorkItem);
00200 DPRINT1("queueing\n");
00201         /* done */
00202         return;
00203     }
00204 
00205     /* does the filter require explicit deferred processing */
00206     if ((This->Filter.Descriptor->Flags & (KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING | KSFILTER_FLAG_CRITICAL_PROCESSING | KSFILTER_FLAG_HYPERCRITICAL_PROCESSING)) &&
00207          KeGetCurrentIrql() > PASSIVE_LEVEL)
00208     {
00209         /* queue work item */
00210         KsQueueWorkItem(This->Worker, &This->WorkItem);
00211 DPRINT1("queueing\n");
00212         /* done */
00213         return;
00214     }
00215 DPRINT1("invoke\n");
00216     /* call worker routine directly */
00217     iface->lpVtbl->ProcessingObjectWork(iface);
00218 }
00219 
00220 VOID
00221 NTAPI
00222 IKsProcessingObject_fnReset(
00223     IKsProcessingObject * iface)
00224 {
00225     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
00226 
00227     /* acquire processing mutex */
00228     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
00229 
00230     /* check if the filter supports dispatch routines */
00231     if (This->Filter.Descriptor->Dispatch)
00232     {
00233         /* has the filter a reset routine */
00234         if (This->Filter.Descriptor->Dispatch->Reset)
00235         {
00236             /* reset filter */
00237             This->Filter.Descriptor->Dispatch->Reset(&This->Filter);
00238         }
00239     }
00240 
00241     /* release process mutex */
00242     KeReleaseMutex(&This->ProcessingMutex, FALSE);
00243 }
00244 
00245 VOID
00246 NTAPI
00247 IKsProcessingObject_fnTriggerNotification(
00248     IKsProcessingObject * iface)
00249 {
00250 
00251 }
00252 
00253 static IKsProcessingObjectVtbl vt_IKsProcessingObject =
00254 {
00255     IKsProcessingObject_fnQueryInterface,
00256     IKsProcessingObject_fnAddRef,
00257     IKsProcessingObject_fnRelease,
00258     IKsProcessingObject_fnProcessingObjectWork,
00259     IKsProcessingObject_fnGetAndGate,
00260     IKsProcessingObject_fnProcess,
00261     IKsProcessingObject_fnReset,
00262     IKsProcessingObject_fnTriggerNotification
00263 };
00264 
00265 
00266 //---------------------------------------------------------------------------------------------------------
00267 NTSTATUS
00268 NTAPI
00269 IKsControl_fnQueryInterface(
00270     IKsControl * iface,
00271     IN  REFIID refiid,
00272     OUT PVOID* Output)
00273 {
00274     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
00275 
00276     if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
00277     {
00278         *Output = &This->Header.OuterUnknown;
00279         _InterlockedIncrement(&This->ref);
00280         return STATUS_SUCCESS;
00281     }
00282     return STATUS_UNSUCCESSFUL;
00283 }
00284 
00285 ULONG
00286 NTAPI
00287 IKsControl_fnAddRef(
00288     IKsControl * iface)
00289 {
00290     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
00291 
00292     return InterlockedIncrement(&This->ref);
00293 }
00294 
00295 ULONG
00296 NTAPI
00297 IKsControl_fnRelease(
00298     IKsControl * iface)
00299 {
00300     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
00301 
00302     InterlockedDecrement(&This->ref);
00303 
00304     /* Return new reference count */
00305     return This->ref;
00306 }
00307 
00308 NTSTATUS
00309 NTAPI
00310 IKsControl_fnKsProperty(
00311     IKsControl * iface,
00312     IN PKSPROPERTY Property,
00313     IN ULONG PropertyLength,
00314     IN OUT PVOID PropertyData,
00315     IN ULONG DataLength,
00316     OUT ULONG* BytesReturned)
00317 {
00318     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
00319 
00320     return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_PROPERTY, Property, PropertyLength, PropertyData, DataLength, BytesReturned);
00321 }
00322 
00323 
00324 NTSTATUS
00325 NTAPI
00326 IKsControl_fnKsMethod(
00327     IKsControl * iface,
00328     IN PKSMETHOD Method,
00329     IN ULONG MethodLength,
00330     IN OUT PVOID MethodData,
00331     IN ULONG DataLength,
00332     OUT ULONG* BytesReturned)
00333 {
00334     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
00335 
00336     return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_METHOD, Method, MethodLength, MethodData, DataLength, BytesReturned);
00337 }
00338 
00339 
00340 NTSTATUS
00341 NTAPI
00342 IKsControl_fnKsEvent(
00343     IKsControl * iface,
00344     IN PKSEVENT Event OPTIONAL,
00345     IN ULONG EventLength,
00346     IN OUT PVOID EventData,
00347     IN ULONG DataLength,
00348     OUT ULONG* BytesReturned)
00349 {
00350     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
00351 
00352     if (Event)
00353     {
00354        return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_ENABLE_EVENT, Event, EventLength, EventData, DataLength, BytesReturned);
00355     }
00356     else
00357     {
00358        return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_DISABLE_EVENT, EventData, DataLength, NULL, 0, BytesReturned);
00359     }
00360 
00361 }
00362 
00363 static IKsControlVtbl vt_IKsControl =
00364 {
00365     IKsControl_fnQueryInterface,
00366     IKsControl_fnAddRef,
00367     IKsControl_fnRelease,
00368     IKsControl_fnKsProperty,
00369     IKsControl_fnKsMethod,
00370     IKsControl_fnKsEvent
00371 };
00372 
00373 
00374 NTSTATUS
00375 NTAPI
00376 IKsFilter_fnQueryInterface(
00377     IKsFilter * iface,
00378     IN  REFIID refiid,
00379     OUT PVOID* Output)
00380 {
00381     NTSTATUS Status;
00382     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
00383 
00384     if (IsEqualGUIDAligned(refiid, &IID_IUnknown) ||
00385         IsEqualGUIDAligned(refiid, &IID_IKsFilter))
00386     {
00387         *Output = &This->Header.OuterUnknown;
00388         _InterlockedIncrement(&This->ref);
00389         return STATUS_SUCCESS;
00390     }
00391     else if (IsEqualGUIDAligned(refiid, &IID_IKsControl))
00392     {
00393         *Output = &This->lpVtblKsControl;
00394         _InterlockedIncrement(&This->ref);
00395         return STATUS_SUCCESS;
00396     }
00397 
00398     if (This->Header.ClientAggregate)
00399     {
00400          /* using client aggregate */
00401          Status = This->Header.ClientAggregate->lpVtbl->QueryInterface(This->Header.ClientAggregate, refiid, Output);
00402 
00403          if (NT_SUCCESS(Status))
00404          {
00405              /* client aggregate supports interface */
00406              return Status;
00407          }
00408     }
00409 
00410     DPRINT("IKsFilter_fnQueryInterface no interface\n");
00411     return STATUS_NOT_SUPPORTED;
00412 }
00413 
00414 ULONG
00415 NTAPI
00416 IKsFilter_fnAddRef(
00417     IKsFilter * iface)
00418 {
00419     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
00420 
00421     return InterlockedIncrement(&This->ref);
00422 }
00423 
00424 ULONG
00425 NTAPI
00426 IKsFilter_fnRelease(
00427     IKsFilter * iface)
00428 {
00429     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
00430 
00431     InterlockedDecrement(&This->ref);
00432 
00433     if (This->ref == 0)
00434     {
00435         FreeItem(This);
00436         return 0;
00437     }
00438     /* Return new reference count */
00439     return This->ref;
00440 
00441 }
00442 
00443 PKSFILTER
00444 NTAPI
00445 IKsFilter_fnGetStruct(
00446     IKsFilter * iface)
00447 {
00448     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
00449 
00450     return &This->Filter;
00451 }
00452 
00453 BOOL
00454 NTAPI
00455 IKsFilter_fnDoAllNecessaryPinsExist(
00456     IKsFilter * iface)
00457 {
00458     UNIMPLEMENTED
00459     return FALSE;
00460 }
00461 
00462 NTSTATUS
00463 NTAPI
00464 IKsFilter_fnCreateNode(
00465     IKsFilter * iface,
00466     IN PIRP Irp,
00467     IN IKsPin * Pin,
00468     IN PLIST_ENTRY ListEntry)
00469 {
00470     UNIMPLEMENTED
00471     return STATUS_NOT_IMPLEMENTED;
00472 }
00473 
00474 NTSTATUS
00475 NTAPI
00476 IKsFilter_fnBindProcessPinsToPipeSection(
00477     IKsFilter * iface,
00478     IN struct KSPROCESSPIPESECTION *Section,
00479     IN PVOID Create,
00480     IN PKSPIN KsPin,
00481     OUT IKsPin **Pin,
00482     OUT PKSGATE *OutGate)
00483 {
00484     UNIMPLEMENTED
00485     return STATUS_NOT_IMPLEMENTED;
00486 }
00487 
00488 NTSTATUS
00489 NTAPI
00490 IKsFilter_fnUnbindProcessPinsFromPipeSection(
00491     IKsFilter * iface,
00492     IN struct KSPROCESSPIPESECTION *Section)
00493 {
00494     UNIMPLEMENTED
00495     return STATUS_NOT_IMPLEMENTED;
00496 }
00497 
00498 NTSTATUS
00499 NTAPI
00500 IKsFilter_fnAddProcessPin(
00501     IKsFilter * iface,
00502     IN PKSPROCESSPIN ProcessPin)
00503 {
00504     NTSTATUS Status;
00505     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
00506 
00507     /* first acquire processing mutex */
00508     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
00509 
00510     /* sanity check */
00511     ASSERT(This->Filter.Descriptor->PinDescriptorsCount > ProcessPin->Pin->Id);
00512 
00513     /* allocate new process pin array */
00514     Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex[ProcessPin->Pin->Id].Pins,
00515                      (This->Filter.Descriptor->PinDescriptorsCount + 1) * sizeof(PVOID),
00516                      This->Filter.Descriptor->PinDescriptorsCount * sizeof(PVOID),
00517                      0);
00518 
00519     if (NT_SUCCESS(Status))
00520     {
00521         /* store process pin */
00522         This->ProcessPinIndex[ProcessPin->Pin->Id].Pins[This->ProcessPinIndex[ProcessPin->Pin->Id].Count] = ProcessPin;
00523         This->ProcessPinIndex[ProcessPin->Pin->Id].Count++;
00524     }
00525 
00526     /* release process mutex */
00527     KeReleaseMutex(&This->ProcessingMutex, FALSE);
00528 
00529     return Status;
00530 }
00531 
00532 NTSTATUS
00533 NTAPI
00534 IKsFilter_fnRemoveProcessPin(
00535     IKsFilter * iface,
00536     IN PKSPROCESSPIN ProcessPin)
00537 {
00538     ULONG Index;
00539     ULONG Count;
00540     PKSPROCESSPIN * Pins;
00541 
00542     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
00543 
00544     /* first acquire processing mutex */
00545     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
00546 
00547     /* sanity check */
00548     ASSERT(ProcessPin->Pin);
00549     ASSERT(ProcessPin->Pin->Id);
00550 
00551     Count = This->ProcessPinIndex[ProcessPin->Pin->Id].Count;
00552     Pins =  This->ProcessPinIndex[ProcessPin->Pin->Id].Pins;
00553 
00554     /* search for current process pin */
00555     for(Index = 0; Index < Count; Index++)
00556     {
00557         if (Pins[Index] == ProcessPin)
00558         {
00559             RtlMoveMemory(&Pins[Index], &Pins[Index + 1], (Count - (Index + 1)) * sizeof(PVOID));
00560             break;
00561         }
00562 
00563     }
00564 
00565     /* decrement pin count */
00566     This->ProcessPinIndex[ProcessPin->Pin->Id].Count--;
00567 
00568     if (!This->ProcessPinIndex[ProcessPin->Pin->Id].Count)
00569     {
00570         /* clear entry object bag will delete it */
00571        This->ProcessPinIndex[ProcessPin->Pin->Id].Pins = NULL;
00572     }
00573 
00574     /* release process mutex */
00575     KeReleaseMutex(&This->ProcessingMutex, FALSE);
00576 
00577     /* done */
00578     return STATUS_SUCCESS;
00579 }
00580 
00581 BOOL
00582 NTAPI
00583 IKsFilter_fnReprepareProcessPipeSection(
00584     IKsFilter * iface,
00585     IN struct KSPROCESSPIPESECTION *PipeSection,
00586     IN PULONG Data)
00587 {
00588     UNIMPLEMENTED
00589     return FALSE;
00590 }
00591 
00592 VOID
00593 NTAPI
00594 IKsFilter_fnDeliverResetState(
00595     IKsFilter * iface,
00596     IN struct KSPROCESSPIPESECTION *PipeSection,
00597     IN KSRESET ResetState)
00598 {
00599     UNIMPLEMENTED
00600 }
00601 
00602 BOOL
00603 NTAPI
00604 IKsFilter_fnIsFrameHolding(
00605     IKsFilter * iface)
00606 {
00607     UNIMPLEMENTED
00608     return FALSE;
00609 }
00610 
00611 VOID
00612 NTAPI
00613 IKsFilter_fnRegisterForCopyCallbacks(
00614     IKsFilter * iface,
00615     IKsQueue *Queue,
00616     BOOL Register)
00617 {
00618     UNIMPLEMENTED
00619 }
00620 
00621 PKSPROCESSPIN_INDEXENTRY
00622 NTAPI
00623 IKsFilter_fnGetProcessDispatch(
00624     IKsFilter * iface)
00625 {
00626     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
00627 
00628     return This->ProcessPinIndex;
00629 }
00630 
00631 static IKsFilterVtbl vt_IKsFilter =
00632 {
00633     IKsFilter_fnQueryInterface,
00634     IKsFilter_fnAddRef,
00635     IKsFilter_fnRelease,
00636     IKsFilter_fnGetStruct,
00637     IKsFilter_fnDoAllNecessaryPinsExist,
00638     IKsFilter_fnCreateNode,
00639     IKsFilter_fnBindProcessPinsToPipeSection,
00640     IKsFilter_fnUnbindProcessPinsFromPipeSection,
00641     IKsFilter_fnAddProcessPin,
00642     IKsFilter_fnRemoveProcessPin,
00643     IKsFilter_fnReprepareProcessPipeSection,
00644     IKsFilter_fnDeliverResetState,
00645     IKsFilter_fnIsFrameHolding,
00646     IKsFilter_fnRegisterForCopyCallbacks,
00647     IKsFilter_fnGetProcessDispatch
00648 };
00649 
00650 NTSTATUS
00651 IKsFilter_GetFilterFromIrp(
00652     IN PIRP Irp,
00653     OUT IKsFilter **Filter)
00654 {
00655     PIO_STACK_LOCATION IoStack;
00656     PKSIOBJECT_HEADER ObjectHeader;
00657     NTSTATUS Status;
00658 
00659     /* get current irp stack */
00660     IoStack = IoGetCurrentIrpStackLocation(Irp);
00661 
00662     /* santiy check */
00663     ASSERT(IoStack->FileObject != NULL);
00664 
00665     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
00666 
00667     /* sanity is important */
00668     ASSERT(ObjectHeader != NULL);
00669     ASSERT(ObjectHeader->Type == KsObjectTypeFilter);
00670     ASSERT(ObjectHeader->Unknown != NULL);
00671 
00672     /* get our private interface */
00673     Status = ObjectHeader->Unknown->lpVtbl->QueryInterface(ObjectHeader->Unknown, &IID_IKsFilter, (PVOID*)Filter);
00674 
00675     if (!NT_SUCCESS(Status))
00676     {
00677         /* something is wrong here */
00678         DPRINT1("KS: Misbehaving filter %p\n", ObjectHeader->Unknown);
00679         Irp->IoStatus.Status = Status;
00680 
00681         /* complete and forget irp */
00682         CompleteRequest(Irp, IO_NO_INCREMENT);
00683         return Status;
00684     }
00685     return Status;
00686 }
00687 
00688 
00689 NTSTATUS
00690 NTAPI
00691 IKsFilter_DispatchClose(
00692     IN PDEVICE_OBJECT DeviceObject,
00693     IN PIRP Irp)
00694 {
00695     IKsFilter * Filter;
00696     IKsFilterImpl * This;
00697     NTSTATUS Status;
00698 
00699     /* obtain filter from object header */
00700     Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
00701     if (!NT_SUCCESS(Status))
00702         return Status;
00703 
00704     /* get our real implementation */
00705     This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown);
00706 
00707     /* does the driver support notifications */
00708     if (This->Filter.Descriptor && This->Filter.Descriptor->Dispatch && This->Filter.Descriptor->Dispatch->Close)
00709     {
00710         /* call driver's filter close function */
00711         Status = This->Filter.Descriptor->Dispatch->Close(&This->Filter, Irp);
00712     }
00713 
00714     if (NT_SUCCESS(Status) && Status != STATUS_PENDING)
00715     {
00716         /* save the result */
00717         Irp->IoStatus.Status = Status;
00718         /* complete irp */
00719         CompleteRequest(Irp, IO_NO_INCREMENT);
00720 
00721         /* remove our instance from the filter factory */
00722         IKsFilter_RemoveFilterFromFilterFactory(This, This->Factory);
00723 
00724         /* free object header */
00725         KsFreeObjectHeader(This->ObjectHeader);
00726     }
00727     else
00728     {
00729         /* complete and forget */
00730         Irp->IoStatus.Status = Status;
00731         /* complete irp */
00732         CompleteRequest(Irp, IO_NO_INCREMENT);
00733     }
00734 
00735     /* done */
00736     return Status;
00737 }
00738 
00739 NTSTATUS
00740 KspHandlePropertyInstances(
00741     IN PIO_STATUS_BLOCK IoStatus,
00742     IN PKSIDENTIFIER  Request,
00743     IN OUT PVOID  Data,
00744     IN IKsFilterImpl * This,
00745     IN BOOL Global)
00746 {
00747     KSPIN_CINSTANCES * Instances;
00748     KSP_PIN * Pin = (KSP_PIN*)Request;
00749 
00750     if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
00751     {
00752         /* no filter / pin descriptor */
00753         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
00754         return STATUS_NOT_IMPLEMENTED;
00755     }
00756 
00757     /* ignore custom structs for now */
00758     ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
00759     ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
00760 
00761     Instances = (KSPIN_CINSTANCES*)Data;
00762     /* max instance count */
00763     Instances->PossibleCount = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesPossible;
00764     /* current instance count */
00765     Instances->CurrentCount = This->PinInstanceCount[Pin->PinId];
00766 
00767     IoStatus->Information = sizeof(KSPIN_CINSTANCES);
00768     IoStatus->Status = STATUS_SUCCESS;
00769     return STATUS_SUCCESS;
00770 }
00771 
00772 NTSTATUS
00773 KspHandleNecessaryPropertyInstances(
00774     IN PIO_STATUS_BLOCK IoStatus,
00775     IN PKSIDENTIFIER  Request,
00776     IN OUT PVOID  Data,
00777     IN IKsFilterImpl * This)
00778 {
00779     PULONG Result;
00780     KSP_PIN * Pin = (KSP_PIN*)Request;
00781 
00782     if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
00783     {
00784         /* no filter / pin descriptor */
00785         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
00786         return STATUS_NOT_IMPLEMENTED;
00787     }
00788 
00789     /* ignore custom structs for now */
00790     ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
00791     ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
00792 
00793     Result = (PULONG)Data;
00794     *Result = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesNecessary;
00795 
00796     IoStatus->Information = sizeof(ULONG);
00797     IoStatus->Status = STATUS_SUCCESS;
00798     return STATUS_SUCCESS;
00799 }
00800 
00801 NTSTATUS
00802 KspHandleDataIntersection(
00803     IN PIRP Irp,
00804     IN PIO_STATUS_BLOCK IoStatus,
00805     IN PKSIDENTIFIER Request,
00806     IN OUT PVOID  Data,
00807     IN ULONG DataLength,
00808     IN IKsFilterImpl * This)
00809 {
00810     PKSMULTIPLE_ITEM MultipleItem;
00811     PKSDATARANGE DataRange;
00812     NTSTATUS Status = STATUS_NO_MATCH;
00813     ULONG Index, Length;
00814     PIO_STACK_LOCATION IoStack;
00815     KSP_PIN * Pin = (KSP_PIN*)Request;
00816 
00817     /* get stack location */
00818     IoStack = IoGetCurrentIrpStackLocation(Irp);
00819 
00820     /* sanity check */
00821     ASSERT(DataLength == IoStack->Parameters.DeviceIoControl.OutputBufferLength);
00822 
00823     /* Access parameters */
00824     MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
00825     DataRange = (PKSDATARANGE)(MultipleItem + 1);
00826 
00827     /* FIXME make sure its 64 bit aligned */
00828     ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
00829 
00830     if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
00831     {
00832         /* no filter / pin descriptor */
00833         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
00834         return STATUS_NOT_IMPLEMENTED;
00835     }
00836 
00837     /* ignore custom structs for now */
00838     ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
00839     ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
00840 
00841     if (This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL ||
00842         This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL ||
00843         This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRangesCount == 0)
00844     {
00845         /* no driver supported intersect handler / no provided data ranges */
00846         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
00847         return STATUS_NOT_IMPLEMENTED;
00848     }
00849 
00850     for(Index = 0; Index < MultipleItem->Count; Index++)
00851     {
00852         UNICODE_STRING MajorFormat, SubFormat, Specifier;
00853         /* convert the guid to string */
00854         RtlStringFromGUID(&DataRange->MajorFormat, &MajorFormat);
00855         RtlStringFromGUID(&DataRange->SubFormat, &SubFormat);
00856         RtlStringFromGUID(&DataRange->Specifier, &Specifier);
00857 
00858         DPRINT("KspHandleDataIntersection Index %lu PinId %lu MajorFormat %S SubFormat %S Specifier %S FormatSize %lu SampleSize %lu Align %lu Flags %lx Reserved %lx DataLength %lu\n", Index, Pin->PinId, MajorFormat.Buffer, SubFormat.Buffer, Specifier.Buffer,
00859                DataRange->FormatSize, DataRange->SampleSize, DataRange->Alignment, DataRange->Flags, DataRange->Reserved, DataLength);
00860 
00861         /* FIXME implement KsPinDataIntersectionEx */
00862         /* Call miniport's properitary handler */
00863         Status = This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler(&This->Filter,
00864                                                                                       Irp,
00865                                                                                       Pin,
00866                                                                                       DataRange,
00867                                                                                       This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges[0], /* HACK */
00868                                                                                       DataLength,
00869                                                                                       Data,
00870                                                                                       &Length);
00871         DPRINT("KspHandleDataIntersection Status %lx\n", Status);
00872 
00873         if (Status == STATUS_SUCCESS || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
00874         {
00875             ASSERT(Length);
00876             IoStatus->Information = Length;
00877             break;
00878         }
00879 
00880         DataRange = (PKSDATARANGE)((PUCHAR)DataRange + DataRange->FormatSize);
00881         /* FIXME make sure its 64 bit aligned */
00882         ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
00883     }
00884     IoStatus->Status = Status;
00885     return Status;
00886 }
00887 
00888 NTSTATUS
00889 NTAPI
00890 FilterTopologyPropertyHandler(
00891     IN PIRP Irp,
00892     IN PKSIDENTIFIER  Request,
00893     IN OUT PVOID  Data)
00894 {
00895     IKsFilterImpl * This;
00896 
00897     /* get filter implementation */
00898     This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
00899 
00900     /* sanity check */
00901     ASSERT(This);
00902 
00903     return KsTopologyPropertyHandler(Irp, Request, Data, &This->Topology);
00904 
00905 }
00906 
00907 
00908 NTSTATUS
00909 NTAPI
00910 FilterPinPropertyHandler(
00911     IN PIRP Irp,
00912     IN PKSIDENTIFIER  Request,
00913     IN OUT PVOID  Data)
00914 {
00915     PIO_STACK_LOCATION IoStack;
00916     IKsFilterImpl * This;
00917     NTSTATUS Status = STATUS_UNSUCCESSFUL;
00918 
00919     /* get filter implementation */
00920     This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
00921 
00922     /* sanity check */
00923     ASSERT(This);
00924 
00925     /* get current stack location */
00926     IoStack = IoGetCurrentIrpStackLocation(Irp);
00927 
00928     switch(Request->Id)
00929     {
00930         case KSPROPERTY_PIN_CTYPES:
00931         case KSPROPERTY_PIN_DATAFLOW:
00932         case KSPROPERTY_PIN_DATARANGES:
00933         case KSPROPERTY_PIN_INTERFACES:
00934         case KSPROPERTY_PIN_MEDIUMS:
00935         case KSPROPERTY_PIN_COMMUNICATION:
00936         case KSPROPERTY_PIN_CATEGORY:
00937         case KSPROPERTY_PIN_NAME:
00938         case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
00939             Status = KspPinPropertyHandler(Irp, Request, Data, This->Filter.Descriptor->PinDescriptorsCount, (const KSPIN_DESCRIPTOR*)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize);
00940             break;
00941         case KSPROPERTY_PIN_GLOBALCINSTANCES:
00942             Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, TRUE);
00943             break;
00944         case KSPROPERTY_PIN_CINSTANCES:
00945             Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, FALSE);
00946             break;
00947         case KSPROPERTY_PIN_NECESSARYINSTANCES:
00948             Status = KspHandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, This);
00949             break;
00950 
00951         case KSPROPERTY_PIN_DATAINTERSECTION:
00952             Status = KspHandleDataIntersection(Irp, &Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This);
00953             break;
00954         default:
00955             UNIMPLEMENTED
00956             Status = STATUS_NOT_FOUND;
00957     }
00958     DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->Filter.Descriptor->PinDescriptorsCount, Request->Id, Status);
00959 
00960 
00961     return Status;
00962 }
00963 
00964 NTSTATUS
00965 NTAPI
00966 IKsFilter_DispatchDeviceIoControl(
00967     IN PDEVICE_OBJECT DeviceObject,
00968     IN PIRP Irp)
00969 {
00970     PIO_STACK_LOCATION IoStack;
00971     IKsFilter * Filter;
00972     IKsFilterImpl * This;
00973     NTSTATUS Status;
00974     PKSFILTER FilterInstance;
00975     UNICODE_STRING GuidString;
00976     PKSPROPERTY Property;
00977     ULONG SetCount = 0;
00978 
00979     /* obtain filter from object header */
00980     Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
00981     if (!NT_SUCCESS(Status))
00982         return Status;
00983 
00984     /* get our real implementation */
00985     This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown);
00986 
00987     /* current irp stack */
00988     IoStack = IoGetCurrentIrpStackLocation(Irp);
00989 
00990     /* get property from input buffer */
00991     Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
00992 
00993     /* get filter instance */
00994     FilterInstance = Filter->lpVtbl->GetStruct(Filter);
00995 
00996     /* sanity check */
00997     ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER));
00998     ASSERT(FilterInstance);
00999     ASSERT(FilterInstance->Descriptor);
01000     ASSERT(FilterInstance->Descriptor->AutomationTable);
01001 
01002     /* acquire control mutex */
01003     KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
01004 
01005     if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD)
01006     {
01007         const KSMETHOD_SET *MethodSet = NULL;
01008         ULONG MethodItemSize = 0;
01009 
01010         /* check if the driver supports method sets */
01011         if (FilterInstance->Descriptor->AutomationTable->MethodSetsCount)
01012         {
01013             SetCount = FilterInstance->Descriptor->AutomationTable->MethodSetsCount;
01014             MethodSet = FilterInstance->Descriptor->AutomationTable->MethodSets;
01015             MethodItemSize = FilterInstance->Descriptor->AutomationTable->MethodItemSize;
01016         }
01017 
01018         /* call method set handler */
01019         Status = KspMethodHandlerWithAllocator(Irp, SetCount, MethodSet, NULL, MethodItemSize);
01020     }
01021     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
01022     {
01023         const KSPROPERTY_SET *PropertySet = NULL;
01024         ULONG PropertyItemSize = 0;
01025 
01026         /* check if the driver supports method sets */
01027         if (FilterInstance->Descriptor->AutomationTable->PropertySetsCount)
01028         {
01029             SetCount = FilterInstance->Descriptor->AutomationTable->PropertySetsCount;
01030             PropertySet = FilterInstance->Descriptor->AutomationTable->PropertySets;
01031             PropertyItemSize = FilterInstance->Descriptor->AutomationTable->PropertyItemSize;
01032             // FIXME: handle variable sized property items
01033             ASSERT(PropertyItemSize == sizeof(KSPROPERTY_ITEM));
01034             PropertyItemSize = 0;
01035         }
01036 
01037         /* needed for our property handlers */
01038         KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This;
01039 
01040         /* call property handler */
01041         Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize);
01042     }
01043     else
01044     {
01045         /* sanity check */
01046         ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT ||
01047                IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT);
01048 
01049         if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
01050         {
01051             /* call enable event handlers */
01052             Status = KspEnableEvent(Irp,
01053                                     FilterInstance->Descriptor->AutomationTable->EventSetsCount,
01054                                     (PKSEVENT_SET)FilterInstance->Descriptor->AutomationTable->EventSets,
01055                                     &This->Header.EventList,
01056                                     KSEVENTS_SPINLOCK,
01057                                     (PVOID)&This->Header.EventListLock,
01058                                     NULL,
01059                                     FilterInstance->Descriptor->AutomationTable->EventItemSize);
01060         }
01061         else
01062         {
01063             /* disable event handler */
01064             Status = KsDisableEvent(Irp, &This->Header.EventList, KSEVENTS_SPINLOCK, &This->Header.EventListLock);
01065         }
01066     }
01067 
01068     RtlStringFromGUID(&Property->Set, &GuidString);
01069     DPRINT("IKsFilter_DispatchDeviceIoControl property PinCount %x\n", FilterInstance->Descriptor->PinDescriptorsCount);
01070     DPRINT("IKsFilter_DispatchDeviceIoControl property Set |%S| Id %u Flags %x Status %lx ResultLength %lu\n", GuidString.Buffer, Property->Id, Property->Flags, Status, Irp->IoStatus.Information);
01071     RtlFreeUnicodeString(&GuidString);
01072 
01073     /* release filter */
01074     Filter->lpVtbl->Release(Filter);
01075 
01076     /* release control mutex */
01077     KeReleaseMutex(This->Header.ControlMutex, FALSE);
01078 
01079     if (Status != STATUS_PENDING)
01080     {
01081         Irp->IoStatus.Status = Status;
01082         CompleteRequest(Irp, IO_NO_INCREMENT);
01083     }
01084 
01085     /* done */
01086     return Status;
01087 }
01088 
01089 static KSDISPATCH_TABLE DispatchTable =
01090 {
01091     IKsFilter_DispatchDeviceIoControl,
01092     KsDispatchInvalidDeviceRequest,
01093     KsDispatchInvalidDeviceRequest,
01094     KsDispatchInvalidDeviceRequest,
01095     IKsFilter_DispatchClose,
01096     KsDispatchQuerySecurity,
01097     KsDispatchSetSecurity,
01098     KsDispatchFastIoDeviceControlFailure,
01099     KsDispatchFastReadFailure,
01100     KsDispatchFastReadFailure,
01101 };
01102 
01103 
01104 NTSTATUS
01105 IKsFilter_CreateDescriptors(
01106     IKsFilterImpl * This,
01107     KSFILTER_DESCRIPTOR* FilterDescriptor)
01108 {
01109     ULONG Index = 0;
01110     NTSTATUS Status;
01111     PKSNODE_DESCRIPTOR NodeDescriptor;
01112 
01113     /* initialize pin descriptors */
01114     This->FirstPin = NULL;
01115     This->PinInstanceCount = NULL;
01116     This->ProcessPinIndex = NULL;
01117 
01118     /* initialize topology descriptor */
01119     This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
01120     This->Topology.Categories = FilterDescriptor->Categories;
01121     This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
01122     This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
01123     This->Topology.TopologyConnections = FilterDescriptor->Connections;
01124 
01125     /* are there any templates */
01126     if (FilterDescriptor->PinDescriptorsCount)
01127     {
01128         /* sanity check */
01129         ASSERT(FilterDescriptor->PinDescriptors);
01130 
01131         /* FIXME handle variable sized pin descriptors */
01132         ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
01133 
01134         /* store pin descriptors ex */
01135         Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount,
01136                          FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount, 0);
01137 
01138         if (!NT_SUCCESS(Status))
01139         {
01140             DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
01141             return Status;
01142         }
01143 
01144         /* store pin instance count */
01145         Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinInstanceCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount,
01146                          sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, 0);
01147 
01148         if (!NT_SUCCESS(Status))
01149         {
01150             DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
01151             return Status;
01152         }
01153 
01154         /* store instantiated pin arrays */
01155         Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PVOID) * FilterDescriptor->PinDescriptorsCount,
01156                          sizeof(PVOID) * FilterDescriptor->PinDescriptorsCount, 0);
01157 
01158         if (!NT_SUCCESS(Status))
01159         {
01160             DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
01161             return Status;
01162         }
01163 
01164         /* add new pin factory */
01165         RtlMoveMemory((PVOID)This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
01166 
01167         /* allocate process pin index */
01168         Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount,
01169                          sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount, 0);
01170 
01171         if (!NT_SUCCESS(Status))
01172         {
01173             DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
01174             return Status;
01175         }
01176 
01177     }
01178 
01179 
01180     if (FilterDescriptor->ConnectionsCount)
01181     {
01182         /* modify connections array */
01183         Status = _KsEdit(This->Filter.Bag,
01184                         (PVOID*)&This->Filter.Descriptor->Connections,
01185                          FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
01186                          FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
01187                          0);
01188 
01189        This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
01190        This->Topology.TopologyConnectionsCount = ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount = FilterDescriptor->ConnectionsCount;
01191     }
01192 
01193     if (FilterDescriptor->NodeDescriptorsCount)
01194     {
01195         /* sanity check */
01196         ASSERT(FilterDescriptor->NodeDescriptors);
01197 
01198         /* sanity check */
01199         ASSERT(FilterDescriptor->NodeDescriptorSize >= sizeof(KSNODE_DESCRIPTOR));
01200 
01201         This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
01202         /* allocate topology node types array */
01203         if (!This->Topology.TopologyNodes)
01204         {
01205             DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
01206             return STATUS_INSUFFICIENT_RESOURCES;
01207         }
01208 
01209         This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
01210         /* allocate topology names array */
01211         if (!This->Topology.TopologyNodesNames)
01212         {
01213             FreeItem((PVOID)This->Topology.TopologyNodes);
01214             DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
01215             return STATUS_INSUFFICIENT_RESOURCES;
01216         }
01217 
01218         DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
01219         NodeDescriptor = (PKSNODE_DESCRIPTOR)FilterDescriptor->NodeDescriptors;
01220         for(Index = 0; Index < FilterDescriptor->NodeDescriptorsCount; Index++)
01221         {
01222             DPRINT("Index %lu Type %p Name %p\n", Index, NodeDescriptor->Type, NodeDescriptor->Name);
01223 
01224             /* copy topology type */
01225             if (NodeDescriptor->Type)
01226                 RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID));
01227 
01228             /* copy topology name */
01229             if (NodeDescriptor->Name)
01230                 RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID));
01231 
01232             // next node descriptor
01233             NodeDescriptor = (PKSNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescriptor->NodeDescriptorSize);
01234         }
01235     }
01236     /* done! */
01237     return STATUS_SUCCESS;
01238 }
01239 
01240 NTSTATUS
01241 IKsFilter_CopyFilterDescriptor(
01242     IKsFilterImpl * This,
01243     const KSFILTER_DESCRIPTOR* FilterDescriptor)
01244 {
01245     NTSTATUS Status;
01246     KSAUTOMATION_TABLE AutomationTable;
01247 
01248     This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
01249     if (!This->Filter.Descriptor)
01250         return STATUS_INSUFFICIENT_RESOURCES;
01251 
01252     Status = KsAddItemToObjectBag(This->Filter.Bag, (PVOID)This->Filter.Descriptor, NULL);
01253     if (!NT_SUCCESS(Status))
01254     {
01255         FreeItem((PVOID)This->Filter.Descriptor);
01256         This->Filter.Descriptor = NULL;
01257         return STATUS_INSUFFICIENT_RESOURCES;
01258     }
01259 
01260     /* copy filter descriptor fields */
01261     RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
01262 
01263     /* zero automation table */
01264     RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE));
01265 
01266     /* setup filter property sets */
01267     AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM);
01268     AutomationTable.PropertySetsCount = 2;
01269     AutomationTable.PropertySets = FilterPropertySet;
01270 
01271     /* merge filter automation table */
01272     Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Filter.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)FilterDescriptor->AutomationTable, &AutomationTable, This->Filter.Bag);
01273 
01274     return Status;
01275 }
01276 
01277 
01278 VOID
01279 IKsFilter_AddPin(
01280     PKSFILTER Filter,
01281     PKSPIN Pin)
01282 {
01283     PKSPIN NextPin, CurPin;
01284     PKSBASIC_HEADER BasicHeader;
01285     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
01286 
01287     /* sanity check */
01288     ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
01289 
01290     if (This->FirstPin[Pin->Id] == NULL)
01291     {
01292         /* welcome first pin */
01293         This->FirstPin[Pin->Id] = Pin;
01294         This->PinInstanceCount[Pin->Id]++;
01295         return;
01296     }
01297 
01298     /* get first pin */
01299     CurPin = This->FirstPin[Pin->Id];
01300 
01301     do
01302     {
01303         /* get next instantiated pin */
01304         NextPin = KsPinGetNextSiblingPin(CurPin);
01305         if (!NextPin)
01306             break;
01307 
01308         NextPin = CurPin;
01309 
01310     }while(NextPin != NULL);
01311 
01312     /* get basic header */
01313     BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)CurPin - sizeof(KSBASIC_HEADER));
01314 
01315     /* store pin */
01316     BasicHeader->Next.Pin = Pin;
01317 }
01318 
01319 VOID
01320 IKsFilter_RemovePin(
01321     PKSFILTER Filter,
01322     PKSPIN Pin)
01323 {
01324     PKSPIN NextPin, CurPin, LastPin;
01325     PKSBASIC_HEADER BasicHeader;
01326     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
01327 
01328     /* sanity check */
01329     ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
01330 
01331     /* get first pin */
01332     CurPin = This->FirstPin[Pin->Id];
01333 
01334     LastPin = NULL;
01335     do
01336     {
01337         /* get next instantiated pin */
01338         NextPin = KsPinGetNextSiblingPin(CurPin);
01339 
01340         if (CurPin == Pin)
01341         {
01342             if (LastPin)
01343             {
01344                 /* get basic header of last pin */
01345                 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastPin - sizeof(KSBASIC_HEADER));
01346 
01347                 BasicHeader->Next.Pin = NextPin;
01348             }
01349             else
01350             {
01351                 /* erase last pin */
01352                 This->FirstPin[Pin->Id] = NextPin;
01353             }
01354             /* decrement pin instance count */
01355             This->PinInstanceCount[Pin->Id]--;
01356             return;
01357         }
01358 
01359         if (!NextPin)
01360             break;
01361 
01362         LastPin = CurPin;
01363         NextPin = CurPin;
01364 
01365     }while(NextPin != NULL);
01366 
01367     /* pin not found */
01368     ASSERT(0);
01369 }
01370 
01371 
01372 NTSTATUS
01373 NTAPI
01374 IKsFilter_DispatchCreatePin(
01375     IN PDEVICE_OBJECT DeviceObject,
01376     IN PIRP Irp)
01377 {
01378     IKsFilterImpl * This;
01379     PKSOBJECT_CREATE_ITEM CreateItem;
01380     PKSPIN_CONNECT Connect;
01381     NTSTATUS Status;
01382 
01383     DPRINT("IKsFilter_DispatchCreatePin\n");
01384 
01385     /* get the create item */
01386     CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
01387 
01388     /* get the filter object */
01389     This = (IKsFilterImpl*)CreateItem->Context;
01390 
01391     /* sanity check */
01392     ASSERT(This->Header.Type == KsObjectTypeFilter);
01393 
01394     /* acquire control mutex */
01395     KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
01396 
01397     /* now validate the connect request */
01398     Status = KspValidateConnectRequest(Irp, This->Filter.Descriptor->PinDescriptorsCount, (PVOID)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize, &Connect);
01399 
01400     DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status);
01401 
01402     if (NT_SUCCESS(Status))
01403     {
01404         /* sanity check */
01405         ASSERT(Connect->PinId < This->Filter.Descriptor->PinDescriptorsCount);
01406 
01407         DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId,
01408                This->PinInstanceCount[Connect->PinId],
01409                This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible);
01410 
01411         if (This->PinInstanceCount[Connect->PinId] < This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible)
01412         {
01413             /* create the pin */
01414             Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->Header.OuterUnknown, Connect, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[Connect->PinId]);
01415 
01416             DPRINT("IKsFilter_DispatchCreatePin  KspCreatePin %lx\n", Status);
01417         }
01418         else
01419         {
01420             /* maximum instance count reached, bye-bye */
01421             Status = STATUS_UNSUCCESSFUL;
01422             DPRINT("IKsFilter_DispatchCreatePin  MaxInstance %lu CurInstance %lu %lx\n", This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]);
01423         }
01424     }
01425 
01426     /* release control mutex */
01427     KeReleaseMutex(This->Header.ControlMutex, FALSE);
01428 
01429     if (Status != STATUS_PENDING)
01430     {
01431         /* complete request */
01432         Irp->IoStatus.Status = Status;
01433         CompleteRequest(Irp, IO_NO_INCREMENT);
01434     }
01435 
01436     /* done */
01437     DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status);
01438     return Status;
01439 }
01440 
01441 NTSTATUS
01442 NTAPI
01443 IKsFilter_DispatchCreateNode(
01444     IN PDEVICE_OBJECT DeviceObject,
01445     IN PIRP Irp)
01446 {
01447     UNIMPLEMENTED
01448     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
01449     CompleteRequest(Irp, IO_NO_INCREMENT);
01450     return STATUS_UNSUCCESSFUL;
01451 }
01452 
01453 
01454 VOID
01455 IKsFilter_AttachFilterToFilterFactory(
01456     IKsFilterImpl * This,
01457     PKSFILTERFACTORY FilterFactory)
01458 {
01459     PKSBASIC_HEADER BasicHeader;
01460     PKSFILTER Filter;
01461 
01462 
01463     /* get filter factory basic header */
01464     BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
01465 
01466     /* sanity check */
01467     ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
01468 
01469     if (BasicHeader->FirstChild.FilterFactory == NULL)
01470     {
01471         /* welcome first instantiated filter */
01472         BasicHeader->FirstChild.Filter = &This->Filter;
01473         return;
01474     }
01475 
01476     /* set to first entry */
01477     Filter = BasicHeader->FirstChild.Filter;
01478 
01479     do
01480     {
01481         /* get basic header */
01482         BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
01483         /* sanity check */
01484         ASSERT(BasicHeader->Type == KsObjectTypeFilter);
01485 
01486         if (BasicHeader->Next.Filter)
01487         {
01488             /* iterate to next filter factory */
01489             Filter = BasicHeader->Next.Filter;
01490         }
01491         else
01492         {
01493             /* found last entry */
01494             break;
01495         }
01496     }while(TRUE);
01497 
01498     /* attach filter factory */
01499     BasicHeader->Next.Filter = &This->Filter;
01500 }
01501 
01502 VOID
01503 IKsFilter_RemoveFilterFromFilterFactory(
01504     IKsFilterImpl * This,
01505     PKSFILTERFACTORY FilterFactory)
01506 {
01507     PKSBASIC_HEADER BasicHeader;
01508     PKSFILTER Filter, LastFilter;
01509 
01510     /* get filter factory basic header */
01511     BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
01512 
01513     /* sanity check */
01514     ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
01515     ASSERT(BasicHeader->FirstChild.Filter != NULL);
01516 
01517 
01518     /* set to first entry */
01519     Filter = BasicHeader->FirstChild.Filter;
01520     LastFilter = NULL;
01521 
01522     do
01523     {
01524          if (Filter == &This->Filter)
01525          {
01526              if (LastFilter)
01527              {
01528                  /* get basic header */
01529                  BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastFilter - sizeof(KSBASIC_HEADER));
01530                  /* remove filter instance */
01531                  BasicHeader->Next.Filter = This->Header.Next.Filter;
01532                  break;
01533              }
01534              else
01535              {
01536                  /* remove filter instance */
01537                  BasicHeader->FirstChild.Filter = This->Header.Next.Filter;
01538                  break;
01539              }
01540          }
01541 
01542         /* get basic header */
01543         BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
01544         /* sanity check */
01545         ASSERT(BasicHeader->Type == KsObjectTypeFilter);
01546 
01547         LastFilter = Filter;
01548         if (BasicHeader->Next.Filter)
01549         {
01550             /* iterate to next filter factory */
01551             Filter = BasicHeader->Next.Filter;
01552         }
01553         else
01554         {
01555             /* filter is not in list */
01556             ASSERT(0);
01557             break;
01558         }
01559     }while(TRUE);
01560 }
01561 
01562 VOID
01563 NTAPI
01564 IKsFilter_FilterCentricWorker(
01565     IN PVOID Ctx)
01566 {
01567     IKsProcessingObject * Object = (IKsProcessingObject*)Ctx;
01568 
01569     /* sanity check */
01570     ASSERT(Object);
01571 
01572     /* perform work */
01573     Object->lpVtbl->ProcessingObjectWork(Object);
01574 }
01575 
01576 NTSTATUS
01577 NTAPI
01578 KspCreateFilter(
01579     IN PDEVICE_OBJECT DeviceObject,
01580     IN PIRP Irp,
01581     IN IKsFilterFactory *iface)
01582 {
01583     IKsFilterImpl * This;
01584     IKsDevice *KsDevice;
01585     PKSFILTERFACTORY Factory;
01586     PIO_STACK_LOCATION IoStack;
01587     PDEVICE_EXTENSION DeviceExtension;
01588     NTSTATUS Status;
01589     PKSOBJECT_CREATE_ITEM CreateItem;
01590 
01591     /* get device extension */
01592     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
01593 
01594     /* get the filter factory */
01595     Factory = iface->lpVtbl->GetStruct(iface);
01596 
01597     if (!Factory || !Factory->FilterDescriptor)
01598     {
01599         /* Sorry it just will not work */
01600         return STATUS_UNSUCCESSFUL;
01601     }
01602 
01603     if (Factory->FilterDescriptor->Flags & KSFILTER_FLAG_DENY_USERMODE_ACCESS)
01604     {
01605         if (Irp->RequestorMode == UserMode)
01606         {
01607             /* filter not accessible from user mode */
01608             DPRINT1("Access denied\n");
01609             return STATUS_UNSUCCESSFUL;
01610         }
01611     }
01612 
01613     /* allocate filter instance */
01614     This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
01615     if (!This)
01616     {
01617         DPRINT1("KspCreateFilter OutOfMemory\n");
01618         return STATUS_INSUFFICIENT_RESOURCES;
01619     }
01620 
01621     /* initialize object bag */
01622     This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
01623     if (!This->Filter.Bag)
01624     {
01625         /* no memory */
01626         FreeItem(This);
01627         DPRINT1("KspCreateFilter OutOfMemory\n");
01628         return STATUS_INSUFFICIENT_RESOURCES;
01629     }
01630     KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
01631     KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
01632 
01633     /* copy filter descriptor */
01634     Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor);
01635     if (!NT_SUCCESS(Status))
01636     {
01637         /* not enough memory */
01638         FreeItem(This->Filter.Bag);
01639         FreeItem(This);
01640         DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status);
01641         return STATUS_INSUFFICIENT_RESOURCES;
01642     }
01643 
01644     /* get current irp stack */
01645     IoStack = IoGetCurrentIrpStackLocation(Irp);
01646 
01647     /* allocate create items */
01648     CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 2);
01649     if (!CreateItem)
01650     {
01651         /* no memory */
01652         FreeItem(This->Filter.Bag);
01653         FreeItem(This);
01654         DPRINT1("KspCreateFilter OutOfMemory\n");
01655         return STATUS_INSUFFICIENT_RESOURCES;
01656     }
01657 
01658     /* initialize pin create item */
01659     CreateItem[0].Create = IKsFilter_DispatchCreatePin;
01660     CreateItem[0].Context = (PVOID)This;
01661     CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
01662     RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Pin);
01663     /* initialize node create item */
01664     CreateItem[1].Create = IKsFilter_DispatchCreateNode;
01665     CreateItem[1].Context = (PVOID)This;
01666     CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
01667     RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode);
01668 
01669 
01670     /* initialize filter instance */
01671     This->ref = 1;
01672     This->Header.OuterUnknown = (PUNKNOWN)&vt_IKsFilter;
01673     This->lpVtblKsControl = &vt_IKsControl;
01674     This->lpVtblKsProcessingObject = &vt_IKsProcessingObject;
01675 
01676     This->Factory = Factory;
01677     This->FilterFactory = iface;
01678     This->FileObject = IoStack->FileObject;
01679     KeInitializeMutex(&This->ProcessingMutex, 0);
01680 
01681     /* initialize basic header */
01682     This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
01683     This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
01684     This->Header.Type = KsObjectTypeFilter;
01685     This->Header.ControlMutex = &This->ControlMutex;
01686     KeInitializeMutex(This->Header.ControlMutex, 0);
01687     InitializeListHead(&This->Header.EventList);
01688     KeInitializeSpinLock(&This->Header.EventListLock);
01689 
01690     /* initialize and gate */
01691     KsGateInitializeAnd(&This->Gate, NULL);
01692 
01693     /* FIXME initialize and gate based on pin flags */
01694 
01695     /* initialize work item */
01696     ExInitializeWorkItem(&This->WorkItem, IKsFilter_FilterCentricWorker, (PVOID)This->lpVtblKsProcessingObject);
01697 
01698     /* allocate counted work item */
01699     Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->WorkItem, &This->Worker);
01700     if (!NT_SUCCESS(Status))
01701     {
01702         /* what can go wrong, goes wrong */
01703         DPRINT1("KsRegisterCountedWorker failed with %lx\n", Status);
01704         FreeItem(This);
01705         FreeItem(CreateItem);
01706         return Status;
01707     }
01708 
01709     /* allocate the stream descriptors */
01710     Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
01711     if (!NT_SUCCESS(Status))
01712     {
01713         /* what can go wrong, goes wrong */
01714         DPRINT1("IKsFilter_CreateDescriptors failed with %lx\n", Status);
01715         KsUnregisterWorker(This->Worker);
01716         FreeItem(This);
01717         FreeItem(CreateItem);
01718         return Status;
01719     }
01720 
01721 
01722 
01723     /* does the filter have a filter dispatch */
01724     if (Factory->FilterDescriptor->Dispatch)
01725     {
01726         /* does it have a create routine */
01727         if (Factory->FilterDescriptor->Dispatch->Create)
01728         {
01729             /* now let driver initialize the filter instance */
01730 
01731             ASSERT(This->Header.KsDevice);
01732             ASSERT(This->Header.KsDevice->Started);
01733             Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
01734 
01735             if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
01736             {
01737                 /* driver failed to initialize */
01738                 DPRINT1("Driver: Status %x\n", Status);
01739 
01740                 /* free filter instance */
01741                 KsUnregisterWorker(This->Worker);
01742                 FreeItem(This);
01743                 FreeItem(CreateItem);
01744                 return Status;
01745             }
01746         }
01747     }
01748 
01749     /* now allocate the object header */
01750     Status = KsAllocateObjectHeader((PVOID*)&This->ObjectHeader, 2, CreateItem, Irp, &DispatchTable);
01751     if (!NT_SUCCESS(Status))
01752     {
01753         /* failed to allocate object header */
01754         DPRINT1("Failed to allocate object header %x\n", Status);
01755 
01756         return Status;
01757     }
01758 
01759     /* initialize object header extra fields */
01760     This->ObjectHeader->Type = KsObjectTypeFilter;
01761     This->ObjectHeader->Unknown = (PUNKNOWN)&This->Header.OuterUnknown;
01762     This->ObjectHeader->ObjectType = (PVOID)&This->Filter;
01763 
01764     /* attach filter to filter factory */
01765     IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
01766 
01767     /* completed initialization */
01768     DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
01769     return Status;
01770 }
01771 
01772 /*
01773     @implemented
01774 */
01775 KSDDKAPI
01776 VOID
01777 NTAPI
01778 KsFilterAcquireProcessingMutex(
01779     IN PKSFILTER Filter)
01780 {
01781     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
01782 
01783     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
01784 }
01785 
01786 /*
01787     @implemented
01788 */
01789 KSDDKAPI
01790 VOID
01791 NTAPI
01792 KsFilterReleaseProcessingMutex(
01793     IN PKSFILTER Filter)
01794 {
01795     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
01796 
01797     KeReleaseMutex(&This->ProcessingMutex, FALSE);
01798 }
01799 
01800 
01801 /*
01802     @implemented
01803 */
01804 KSDDKAPI
01805 NTSTATUS
01806 NTAPI
01807 KsFilterAddTopologyConnections (
01808     IN PKSFILTER Filter,
01809     IN ULONG NewConnectionsCount,
01810     IN const KSTOPOLOGY_CONNECTION *const NewTopologyConnections)
01811 {
01812     ULONG Count;
01813     NTSTATUS Status;
01814     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
01815 
01816     DPRINT("KsFilterAddTopologyConnections\n");
01817 
01818     ASSERT(This->Filter.Descriptor);
01819     Count = This->Filter.Descriptor->ConnectionsCount + NewConnectionsCount;
01820 
01821 
01822     /* modify connections array */
01823     Status = _KsEdit(This->Filter.Bag,
01824                     (PVOID*)&This->Filter.Descriptor->Connections,
01825                      Count * sizeof(KSTOPOLOGY_CONNECTION),
01826                      This->Filter.Descriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
01827                      0);
01828 
01829     if (!NT_SUCCESS(Status))
01830     {
01831         /* failed */
01832         DPRINT("KsFilterAddTopologyConnections KsEdit failed with %lx\n", Status);
01833         return Status;
01834     }
01835 
01836     /* FIXME verify connections */
01837 
01838     /* copy new connections */
01839     RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections[This->Filter.Descriptor->ConnectionsCount],
01840                   NewTopologyConnections,
01841                   NewConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION));
01842 
01843     /* update topology */
01844     This->Topology.TopologyConnectionsCount += NewConnectionsCount;
01845     ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount += NewConnectionsCount;
01846     This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
01847 
01848     return Status;
01849 }
01850 
01851 /*
01852     @implemented
01853 */
01854 KSDDKAPI
01855 VOID
01856 NTAPI
01857 KsFilterAttemptProcessing(
01858     IN PKSFILTER Filter,
01859     IN BOOLEAN Asynchronous)
01860 {
01861     PKSGATE Gate;
01862     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
01863 
01864     /* get gate */
01865     Gate = This->lpVtblKsProcessingObject->GetAndGate((IKsProcessingObject*)This->lpVtblKsProcessingObject);
01866 
01867     if (!KsGateCaptureThreshold(Gate))
01868     {
01869         /* filter control gate is closed */
01870         return;
01871     }
01872 DPRINT1("processing\n");
01873     /* try initiate processing */
01874     This->lpVtblKsProcessingObject->Process((IKsProcessingObject*)This->lpVtblKsProcessingObject, Asynchronous);
01875 }
01876 
01877 /*
01878     @unimplemented
01879 */
01880 KSDDKAPI
01881 NTSTATUS
01882 NTAPI
01883 KsFilterCreateNode (
01884     IN PKSFILTER Filter,
01885     IN const KSNODE_DESCRIPTOR *const NodeDescriptor,
01886     OUT PULONG NodeID)
01887 {
01888     UNIMPLEMENTED
01889     return STATUS_NOT_IMPLEMENTED;
01890 }
01891 
01892 /*
01893     @implemented
01894 */
01895 KSDDKAPI
01896 NTSTATUS
01897 NTAPI
01898 KsFilterCreatePinFactory (
01899     IN PKSFILTER Filter,
01900     IN const KSPIN_DESCRIPTOR_EX *const InPinDescriptor,
01901     OUT PULONG PinID)
01902 {
01903     ULONG Count;
01904     NTSTATUS Status;
01905     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
01906 
01907     DPRINT("KsFilterCreatePinFactory\n");
01908 
01909     /* calculate new count */
01910     Count = This->Filter.Descriptor->PinDescriptorsCount + 1;
01911 
01912     /* sanity check */
01913     ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
01914 
01915     /* modify pin descriptors ex array */
01916     Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, Count * This->Filter.Descriptor->PinDescriptorSize, This->Filter.Descriptor->PinDescriptorsCount * This->Filter.Descriptor->PinDescriptorSize, 0);
01917     if (!NT_SUCCESS(Status))
01918     {
01919         /* failed */
01920         DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
01921         return Status;
01922     }
01923 
01924     /* modify pin instance count array */
01925     Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->PinInstanceCount, sizeof(ULONG) * Count, sizeof(ULONG) * This->Filter.Descriptor->PinDescriptorsCount, 0);
01926     if (!NT_SUCCESS(Status))
01927     {
01928         /* failed */
01929         DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
01930         return Status;
01931     }
01932 
01933     /* modify first pin array */
01934     Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PVOID) * Count, sizeof(PVOID) * This->Filter.Descriptor->PinDescriptorsCount, 0);
01935     if (!NT_SUCCESS(Status))
01936     {
01937         /* failed */
01938         DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
01939         return Status;
01940     }
01941 
01942     /* add new pin factory */
01943     RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors[This->Filter.Descriptor->PinDescriptorsCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
01944 
01945     /* allocate process pin index */
01946     Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * Count,
01947                      sizeof(KSPROCESSPIN_INDEXENTRY) * This->Filter.Descriptor->PinDescriptorsCount, 0);
01948 
01949     if (!NT_SUCCESS(Status))
01950     {
01951         DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status);
01952         return Status;
01953     }
01954 
01955     /* store new pin id */
01956     *PinID = This->Filter.Descriptor->PinDescriptorsCount;
01957 
01958     /* increment pin descriptor count */
01959     ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->PinDescriptorsCount++;
01960 
01961 
01962     DPRINT("KsFilterCreatePinFactory done\n");
01963     return STATUS_SUCCESS;
01964 
01965 }
01966 
01967 /*
01968     @unimplemented
01969 */
01970 KSDDKAPI
01971 PKSGATE
01972 NTAPI
01973 KsFilterGetAndGate(
01974     IN PKSFILTER Filter)
01975 {
01976     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
01977 
01978     /* return and-gate */
01979     return &This->Gate;
01980 }
01981 
01982 /*
01983     @implemented
01984 */
01985 KSDDKAPI
01986 ULONG
01987 NTAPI
01988 KsFilterGetChildPinCount(
01989     IN PKSFILTER Filter,
01990     IN ULONG PinId)
01991 {
01992     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
01993 
01994     if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
01995     {
01996         /* index is out of bounds */
01997         return 0;
01998     }
01999     /* return pin instance count */
02000     return This->PinInstanceCount[PinId];
02001 }
02002 
02003 /*
02004     @implemented
02005 */
02006 KSDDKAPI
02007 PKSPIN
02008 NTAPI
02009 KsFilterGetFirstChildPin(
02010     IN PKSFILTER Filter,
02011     IN ULONG PinId)
02012 {
02013     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
02014 
02015     if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
02016     {
02017         /* index is out of bounds */
02018         return NULL;
02019     }
02020 
02021     /* return first pin index */
02022     return This->FirstPin[PinId];
02023 }
02024 
02025 /*
02026     @implemented
02027 */
02028 KSDDKAPI
02029 VOID
02030 NTAPI
02031 KsFilterRegisterPowerCallbacks(
02032     IN PKSFILTER Filter,
02033     IN PFNKSFILTERPOWER Sleep OPTIONAL,
02034     IN PFNKSFILTERPOWER Wake OPTIONAL)
02035 {
02036     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
02037 
02038     This->Sleep = Sleep;
02039     This->Wake = Wake;
02040 }
02041 
02042 /*
02043     @implemented
02044 */
02045 KSDDKAPI
02046 PKSFILTER
02047 NTAPI
02048 KsGetFilterFromIrp(
02049     IN PIRP Irp)
02050 {
02051     PIO_STACK_LOCATION IoStack;
02052     PKSIOBJECT_HEADER ObjectHeader;
02053 
02054     DPRINT("KsGetFilterFromIrp\n");
02055 
02056     /* get current irp stack location */
02057     IoStack = IoGetCurrentIrpStackLocation(Irp);
02058 
02059     /* sanity check */
02060     ASSERT(IoStack->FileObject);
02061 
02062     /* get object header */
02063     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
02064 
02065     if (ObjectHeader->Type == KsObjectTypeFilter)
02066     {
02067         /* irp is targeted at the filter */
02068         return (PKSFILTER)ObjectHeader->ObjectType;
02069     }
02070     else if (ObjectHeader->Type == KsObjectTypePin)
02071     {
02072         /* irp is for a pin */
02073         return KsPinGetParentFilter((PKSPIN)ObjectHeader->ObjectType);
02074     }
02075     else
02076     {
02077         /* irp is unappropiate to retrieve a filter */
02078         return NULL;
02079     }
02080 }

Generated on Sat May 19 2012 04:22:31 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.