ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 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

filterfactory.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/filterfactory.c
00005  * PURPOSE:         KS IKsFilterFactory interface functions
00006  * PROGRAMMER:      Johannes Anderwald
00007  */
00008 
00009 
00010 #include "priv.h"
00011 
00012 typedef struct
00013 {
00014     KSBASIC_HEADER Header;
00015     KSFILTERFACTORY FilterFactory;
00016 
00017     LONG ref;
00018     PKSIDEVICE_HEADER DeviceHeader;
00019     PFNKSFILTERFACTORYPOWER SleepCallback;
00020     PFNKSFILTERFACTORYPOWER WakeCallback;
00021 
00022     LIST_ENTRY SymbolicLinkList;
00023     KMUTEX ControlMutex;
00024 
00025 }IKsFilterFactoryImpl;
00026 
00027 VOID
00028 NTAPI
00029 IKsFilterFactory_ItemFreeCb(
00030     IN PKSOBJECT_CREATE_ITEM  CreateItem)
00031 {
00032     /* callback when create item is freed in the device header */
00033     IKsFilterFactory * iface = (IKsFilterFactory*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
00034 
00035     iface->lpVtbl->Release(iface);
00036 }
00037 
00038 NTSTATUS
00039 NTAPI
00040 IKsFilterFactory_Create(
00041     IN PDEVICE_OBJECT DeviceObject,
00042     IN PIRP Irp)
00043 {
00044     PKSOBJECT_CREATE_ITEM CreateItem;
00045     IKsFilterFactoryImpl * Factory;
00046     IKsFilterFactory * iface;
00047     NTSTATUS Status;
00048 
00049     /* access the create item */
00050     CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
00051     if (!CreateItem)
00052     {
00053         DPRINT1("IKsFilterFactory_Create no CreateItem\n");
00054         return STATUS_UNSUCCESSFUL;
00055     }
00056 
00057     /* get filter factory interface */
00058     Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
00059 
00060     /* get interface */
00061     iface = (IKsFilterFactory*)&Factory->Header.OuterUnknown;
00062 
00063     /* create a filter instance */
00064     Status = KspCreateFilter(DeviceObject, Irp, iface);
00065 
00066     DPRINT("KspCreateFilter Status %x\n", Status);
00067 
00068     if (Status != STATUS_PENDING)
00069     {
00070         Irp->IoStatus.Information = 0;
00071         Irp->IoStatus.Status = Status;
00072         CompleteRequest(Irp, IO_NO_INCREMENT);
00073     }
00074 
00075     return Status;
00076 }
00077 
00078 
00079 NTSTATUS
00080 NTAPI
00081 IKsFilterFactory_fnQueryInterface(
00082     IKsFilterFactory * iface,
00083     IN  REFIID refiid,
00084     OUT PVOID* Output)
00085 {
00086     NTSTATUS Status;
00087 
00088     IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, Header.OuterUnknown);
00089 
00090     if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
00091     {
00092         *Output = &This->Header.OuterUnknown;
00093         _InterlockedIncrement(&This->ref);
00094         return STATUS_SUCCESS;
00095     }
00096 
00097     if (This->Header.ClientAggregate)
00098     {
00099          /* using client aggregate */
00100          Status = This->Header.ClientAggregate->lpVtbl->QueryInterface(This->Header.ClientAggregate, refiid, Output);
00101 
00102          if (NT_SUCCESS(Status))
00103          {
00104              /* client aggregate supports interface */
00105              return Status;
00106          }
00107     }
00108 
00109     DPRINT("IKsFilterFactory_fnQueryInterface no interface\n");
00110     return STATUS_NOT_SUPPORTED;
00111 }
00112 
00113 ULONG
00114 NTAPI
00115 IKsFilterFactory_fnAddRef(
00116     IKsFilterFactory * iface)
00117 {
00118     IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, Header.OuterUnknown);
00119 
00120     return InterlockedIncrement(&This->ref);
00121 }
00122 
00123 ULONG
00124 NTAPI
00125 IKsFilterFactory_fnRelease(
00126     IKsFilterFactory * iface)
00127 {
00128     IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, Header.OuterUnknown);
00129 
00130     InterlockedDecrement(&This->ref);
00131 
00132     if (This->ref == 0)
00133     {
00134         if (!IsListEmpty(&This->SymbolicLinkList))
00135         {
00136             /* disable device interfaces */
00137             KspSetDeviceInterfacesState(&This->SymbolicLinkList, FALSE);
00138             /* free device interface strings */
00139             KspFreeDeviceInterfaces(&This->SymbolicLinkList);
00140         }
00141 
00142         FreeItem(This);
00143         return 0;
00144     }
00145     /* Return new reference count */
00146     return This->ref;
00147 }
00148 
00149 KSFILTERFACTORY*
00150 NTAPI
00151 IKsFilterFactory_fnGetStruct(
00152     IKsFilterFactory * iface)
00153 {
00154     IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, Header.OuterUnknown);
00155 
00156     return &This->FilterFactory;
00157 }
00158 
00159 NTSTATUS
00160 NTAPI
00161 IKsFilterFactory_fnSetDeviceClassesState(
00162     IKsFilterFactory * iface,
00163     IN BOOLEAN Enable)
00164 {
00165     IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, Header.OuterUnknown);
00166 
00167     return KspSetDeviceInterfacesState(&This->SymbolicLinkList, Enable);
00168 }
00169 
00170 VOID
00171 IKsFilterFactory_AttachFilterFactoryToDeviceHeader(
00172     IKsFilterFactoryImpl * This,
00173     PKSIDEVICE_HEADER DeviceHeader)
00174 {
00175     PKSBASIC_HEADER BasicHeader;
00176     PKSFILTERFACTORY FilterFactory;
00177 
00178     if (DeviceHeader->BasicHeader.FirstChild.FilterFactory == NULL)
00179     {
00180         /* first attached filter factory */
00181         DeviceHeader->BasicHeader.FirstChild.FilterFactory = &This->FilterFactory;
00182         return;
00183     }
00184 
00185     /* set to first entry */
00186     FilterFactory = DeviceHeader->BasicHeader.FirstChild.FilterFactory;
00187 
00188     do
00189     {
00190         /* get basic header */
00191         BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
00192         /* sanity check */
00193         ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
00194 
00195         if (BasicHeader->Next.FilterFactory)
00196         {
00197             /* iterate to next filter factory */
00198             FilterFactory = BasicHeader->Next.FilterFactory;
00199         }
00200         else
00201         {
00202             /* found last entry */
00203             break;
00204         }
00205     }while(FilterFactory);
00206 
00207     /* attach filter factory */
00208     BasicHeader->Next.FilterFactory = &This->FilterFactory;
00209 }
00210 
00211 NTSTATUS
00212 NTAPI
00213 IKsFilterFactory_fnInitialize(
00214     IKsFilterFactory * iface,
00215     IN PDEVICE_OBJECT  DeviceObject,
00216     IN const KSFILTER_DESCRIPTOR  *Descriptor,
00217     IN PWSTR  RefString OPTIONAL,
00218     IN PSECURITY_DESCRIPTOR  SecurityDescriptor OPTIONAL,
00219     IN ULONG  CreateItemFlags,
00220     IN PFNKSFILTERFACTORYPOWER  SleepCallback OPTIONAL,
00221     IN PFNKSFILTERFACTORYPOWER  WakeCallback OPTIONAL,
00222     OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
00223 {
00224     UNICODE_STRING ReferenceString;
00225     NTSTATUS Status;
00226     PDEVICE_EXTENSION DeviceExtension;
00227     KSOBJECT_CREATE_ITEM CreateItem;
00228     BOOL FreeString = FALSE;
00229     IKsDevice * KsDevice;
00230 
00231     IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, Header.OuterUnknown);
00232 
00233     /* get device extension */
00234     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
00235 
00236     /* initialize filterfactory */
00237     This->SleepCallback = SleepCallback;
00238     This->WakeCallback = WakeCallback;
00239     This->FilterFactory.FilterDescriptor = Descriptor;
00240     This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
00241     This->Header.Type = KsObjectTypeFilterFactory;
00242     This->Header.Parent.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
00243     This->DeviceHeader = DeviceExtension->DeviceHeader;
00244 
00245     /* initialize filter factory control mutex */
00246     This->Header.ControlMutex = &This->ControlMutex;
00247     KeInitializeMutex(This->Header.ControlMutex, 0);
00248 
00249     /* unused fields */
00250     InitializeListHead(&This->Header.EventList);
00251     KeInitializeSpinLock(&This->Header.EventListLock);
00252 
00253     InitializeListHead(&This->SymbolicLinkList);
00254 
00255     /* does the device use a reference string */
00256     if (RefString || !Descriptor->ReferenceGuid)
00257     {
00258         /* use device reference string */
00259         RtlInitUnicodeString(&ReferenceString, RefString);
00260     }
00261     else
00262     {
00263         /* create reference string from descriptor guid */
00264         Status = RtlStringFromGUID(Descriptor->ReferenceGuid, &ReferenceString);
00265 
00266         /* check for success */
00267         if (!NT_SUCCESS(Status))
00268         {
00269             /* omg, we failed */
00270             return Status;
00271         }
00272 
00273         FreeString = TRUE;
00274     }
00275 
00276     DPRINT("IKsFilterFactory_fnInitialize CategoriesCount %u ReferenceString '%S'\n", Descriptor->CategoriesCount,ReferenceString.Buffer);
00277 
00278     /* now register the device interface */
00279     Status = KspRegisterDeviceInterfaces(DeviceExtension->DeviceHeader->KsDevice.PhysicalDeviceObject,
00280                                          Descriptor->CategoriesCount,
00281                                          Descriptor->Categories,
00282                                          &ReferenceString,
00283                                          &This->SymbolicLinkList);
00284     /* check for success */
00285     if (!NT_SUCCESS(Status))
00286     {
00287         DPRINT1("KspRegisterDeviceInterfaces failed with %x\n", Status);
00288 
00289         if (FreeString)
00290         {
00291             /* free unicode string */
00292             RtlFreeUnicodeString(&ReferenceString);
00293         }
00294 
00295         return Status;
00296     }
00297 
00298     /* now setup the create item */
00299     CreateItem.SecurityDescriptor = SecurityDescriptor;
00300     CreateItem.Flags = CreateItemFlags;
00301     CreateItem.Create = IKsFilterFactory_Create;
00302     CreateItem.Context = (PVOID)&This->FilterFactory;
00303     RtlInitUnicodeString(&CreateItem.ObjectClass, ReferenceString.Buffer);
00304 
00305     /* insert create item to device header */
00306     Status = KsAllocateObjectCreateItem((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
00307 
00308     if (FreeString)
00309     {
00310         /* free unicode string */
00311         RtlFreeUnicodeString(&ReferenceString);
00312     }
00313 
00314     if (FilterFactory)
00315     {
00316         /* return filterfactory */
00317         *FilterFactory = &This->FilterFactory;
00318 
00319         /* create a object bag for the filter factory */
00320         This->FilterFactory.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
00321         if (This->FilterFactory.Bag)
00322         {
00323             /* initialize object bag */
00324             KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
00325             KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->FilterFactory.Bag, NULL);
00326         }
00327     }
00328 
00329     /* attach filterfactory to device header */
00330     IKsFilterFactory_AttachFilterFactoryToDeviceHeader(This, DeviceExtension->DeviceHeader);
00331 
00332     /* return result */
00333     return Status;
00334 }
00335 
00336 static IKsFilterFactoryVtbl vt_IKsFilterFactoryVtbl =
00337 {
00338     IKsFilterFactory_fnQueryInterface,
00339     IKsFilterFactory_fnAddRef,
00340     IKsFilterFactory_fnRelease,
00341     IKsFilterFactory_fnGetStruct,
00342     IKsFilterFactory_fnSetDeviceClassesState,
00343     IKsFilterFactory_fnInitialize
00344 };
00345 
00346 
00347 NTSTATUS
00348 NTAPI
00349 KspCreateFilterFactory(
00350     IN PDEVICE_OBJECT  DeviceObject,
00351     IN const KSFILTER_DESCRIPTOR  *Descriptor,
00352     IN PWSTR  RefString OPTIONAL,
00353     IN PSECURITY_DESCRIPTOR  SecurityDescriptor OPTIONAL,
00354     IN ULONG  CreateItemFlags,
00355     IN PFNKSFILTERFACTORYPOWER  SleepCallback OPTIONAL,
00356     IN PFNKSFILTERFACTORYPOWER  WakeCallback OPTIONAL,
00357     OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
00358 {
00359     IKsFilterFactoryImpl * This;
00360     IKsFilterFactory * Filter;
00361     NTSTATUS Status;
00362 
00363     DPRINT("KsCreateFilterFactory\n");
00364 
00365     /* Lets allocate a filterfactory */
00366     This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactoryImpl));
00367     if (!This)
00368     {
00369         /* not enough memory */
00370         return STATUS_INSUFFICIENT_RESOURCES;
00371     }
00372 
00373     /* initialize struct */
00374     This->ref = 1;
00375     This->Header.OuterUnknown = (PUNKNOWN)&vt_IKsFilterFactoryVtbl;
00376 
00377     /* map to com object */
00378     Filter = (IKsFilterFactory*)&This->Header.OuterUnknown;
00379 
00380     /* initialize filter */
00381     Status = Filter->lpVtbl->Initialize(Filter, DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
00382     /* did we succeed */
00383     if (!NT_SUCCESS(Status))
00384     {
00385         /* destroy filterfactory */
00386         Filter->lpVtbl->Release(Filter);
00387     }
00388 
00389     /* return result */
00390     DPRINT("KsCreateFilterFactory %x\n", Status);
00391     /* sanity check */
00392     ASSERT(Status == STATUS_SUCCESS);
00393 
00394     return Status;
00395 }
00396 
00397 /*
00398     @implemented
00399 */
00400 KSDDKAPI
00401 NTSTATUS
00402 NTAPI
00403 KsCreateFilterFactory(
00404     IN PDEVICE_OBJECT  DeviceObject,
00405     IN const KSFILTER_DESCRIPTOR  *Descriptor,
00406     IN PWSTR  RefString OPTIONAL,
00407     IN PSECURITY_DESCRIPTOR  SecurityDescriptor OPTIONAL,
00408     IN ULONG  CreateItemFlags,
00409     IN PFNKSFILTERFACTORYPOWER  SleepCallback OPTIONAL,
00410     IN PFNKSFILTERFACTORYPOWER  WakeCallback OPTIONAL,
00411     OUT PKSFILTERFACTORY  *FilterFactory OPTIONAL)
00412 {
00413     return KspCreateFilterFactory(DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
00414 
00415 }
00416 
00417 /*
00418     @implemented
00419 */
00420 KSDDKAPI
00421 NTSTATUS
00422 NTAPI
00423 KsFilterFactorySetDeviceClassesState(
00424     IN PKSFILTERFACTORY  FilterFactory,
00425     IN BOOLEAN  NewState)
00426 {
00427     IKsFilterFactory * Factory;
00428     IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
00429 
00430     Factory = (IKsFilterFactory*)&This->Header.OuterUnknown;
00431     return Factory->lpVtbl->SetDeviceClassesState(Factory, NewState);
00432 }
00433 
00434 
00435 /*
00436     @implemented
00437 */
00438 KSDDKAPI
00439 PUNICODE_STRING
00440 NTAPI
00441 KsFilterFactoryGetSymbolicLink(
00442     IN PKSFILTERFACTORY  FilterFactory)
00443 {
00444     PSYMBOLIC_LINK_ENTRY LinkEntry;
00445     IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
00446 
00447     if (IsListEmpty(&Factory->SymbolicLinkList))
00448     {
00449         /* device has not registered any interfaces */
00450         return NULL;
00451     }
00452 
00453     /* get first entry */
00454     LinkEntry = (PSYMBOLIC_LINK_ENTRY)CONTAINING_RECORD(Factory->SymbolicLinkList.Flink, SYMBOLIC_LINK_ENTRY, Entry);
00455 
00456     /* return first link */
00457     return &LinkEntry->SymbolicLink;
00458 }
00459 
00460 /*
00461     @implemented
00462 */
00463 KSDDKAPI
00464 NTSTATUS
00465 NTAPI
00466 KsFilterFactoryAddCreateItem(
00467     IN PKSFILTERFACTORY  FilterFactory,
00468     IN PWSTR  RefString,
00469     IN PSECURITY_DESCRIPTOR  SecurityDescriptor OPTIONAL,
00470     IN ULONG  CreateItemFlags)
00471 {
00472     KSOBJECT_CREATE_ITEM CreateItem;
00473 
00474     IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
00475 
00476     /* initialize create item */
00477     CreateItem.Context = (PVOID)&Factory->FilterFactory;
00478     CreateItem.Create = IKsFilterFactory_Create;
00479     CreateItem.Flags = CreateItemFlags;
00480     CreateItem.SecurityDescriptor = SecurityDescriptor;
00481     RtlInitUnicodeString(&CreateItem.ObjectClass, RefString);
00482 
00483     /* insert create item to device header */
00484     return KsAllocateObjectCreateItem((KSDEVICE_HEADER)Factory->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
00485 }
00486 
00487 ULONG
00488 KspCacheAddData(
00489     PKSPCACHE_DESCRIPTOR Descriptor,
00490     LPCVOID Data,
00491     ULONG Length)
00492 {
00493     ULONG Index;
00494 
00495     for(Index = 0; Index < Descriptor->DataOffset; Index++)
00496     {
00497         if (RtlCompareMemory(Descriptor->DataCache, Data, Length) == Length)
00498         {
00499             if (Index + Length > Descriptor->DataOffset)
00500             {
00501                 /* adjust used space */
00502                 Descriptor->DataOffset = Index + Length;
00503                 /* return absolute offset */
00504                 return Descriptor->DataLength + Index;
00505             }
00506         }
00507     }
00508 
00509     /* sanity check */
00510     ASSERT(Descriptor->DataOffset + Length < Descriptor->DataLength);
00511 
00512     /* copy to data blob */
00513     RtlMoveMemory((Descriptor->DataCache + Descriptor->DataOffset), Data, Length);
00514 
00515     /* backup offset */
00516     Index = Descriptor->DataOffset;
00517 
00518     /* adjust used space */
00519     Descriptor->DataOffset += Length;
00520 
00521     /* return absolute offset */
00522     return Descriptor->DataLength + Index;
00523 }
00524 
00525 /*
00526     @implemented
00527 */
00528 KSDDKAPI
00529 NTSTATUS
00530 NTAPI
00531 KsFilterFactoryUpdateCacheData(
00532     IN PKSFILTERFACTORY  FilterFactory,
00533     IN const KSFILTER_DESCRIPTOR*  FilterDescriptor OPTIONAL)
00534 {
00535     KSPCACHE_DESCRIPTOR Descriptor;
00536     PKSPCACHE_FILTER_HEADER FilterHeader;
00537     UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData");
00538     PKSPCACHE_PIN_HEADER PinHeader;
00539     ULONG Index, SubIndex;
00540     PLIST_ENTRY Entry;
00541     PSYMBOLIC_LINK_ENTRY SymEntry;
00542     BOOLEAN Found;
00543     HKEY hKey;
00544     NTSTATUS Status = STATUS_SUCCESS;
00545 
00546     IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
00547 
00548     DPRINT("KsFilterFactoryUpdateCacheData %p\n", FilterDescriptor);
00549 
00550     if (!FilterDescriptor)
00551         FilterDescriptor = Factory->FilterFactory.FilterDescriptor;
00552 
00553     ASSERT(FilterDescriptor);
00554 
00555     /* initialize cache descriptor */
00556     RtlZeroMemory(&Descriptor, sizeof(KSPCACHE_DESCRIPTOR));
00557 
00558     /* calculate filter data size */
00559     Descriptor.FilterLength = sizeof(KSPCACHE_FILTER_HEADER);
00560 
00561     /* FIXME support variable size pin descriptors */
00562     ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
00563 
00564     for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
00565     {
00566         /* add filter descriptor */
00567         Descriptor.FilterLength += sizeof(KSPCACHE_PIN_HEADER);
00568 
00569         if (FilterDescriptor->PinDescriptors[Index].PinDescriptor.Category)
00570         {
00571             /* add extra ULONG for offset to category */
00572             Descriptor.FilterLength += sizeof(ULONG);
00573 
00574             /* add size for clsid */
00575             Descriptor.DataLength += sizeof(CLSID);
00576         }
00577 
00578         /* add space for formats */
00579         Descriptor.FilterLength += FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRangesCount * sizeof(KSPCACHE_DATARANGE);
00580 
00581         /* add space for MajorFormat / MinorFormat */
00582         Descriptor.DataLength += FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRangesCount * sizeof(CLSID) * 2;
00583 
00584         /* add space for mediums */
00585         Descriptor.FilterLength += FilterDescriptor->PinDescriptors[Index].PinDescriptor.MediumsCount * sizeof(ULONG);
00586 
00587         /* add space for the data */
00588         Descriptor.DataLength += FilterDescriptor->PinDescriptors[Index].PinDescriptor.MediumsCount * sizeof(KSPCACHE_MEDIUM);
00589     }
00590 
00591     /* now allocate the space */
00592     Descriptor.FilterData = (PUCHAR)AllocateItem(NonPagedPool, Descriptor.DataLength + Descriptor.FilterLength);
00593     if (!Descriptor.FilterData)
00594     {
00595         /* no memory */
00596         return STATUS_INSUFFICIENT_RESOURCES;
00597     }
00598 
00599     /* initialize data cache */
00600     Descriptor.DataCache = (PUCHAR)((ULONG_PTR)Descriptor.FilterData + Descriptor.FilterLength);
00601 
00602     /* setup filter header */
00603     FilterHeader = (PKSPCACHE_FILTER_HEADER)Descriptor.FilterData;
00604 
00605     FilterHeader->dwVersion = 2;
00606     FilterHeader->dwMerit = MERIT_DO_NOT_USE;
00607     FilterHeader->dwUnused = 0;
00608     FilterHeader->dwPins = FilterDescriptor->PinDescriptorsCount;
00609 
00610     Descriptor.FilterOffset = sizeof(KSPCACHE_FILTER_HEADER);
00611 
00612     /* write pin headers */
00613     for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
00614     {
00615         /* get offset to pin */
00616         PinHeader = (PKSPCACHE_PIN_HEADER)((ULONG_PTR)Descriptor.FilterData + Descriptor.FilterOffset);
00617 
00618         /* write pin header */
00619         PinHeader->Signature = 0x33697030 + Index;
00620         PinHeader->Flags = 0;
00621         PinHeader->Instances = FilterDescriptor->PinDescriptors[Index].InstancesPossible;
00622         if (PinHeader->Instances > 1)
00623             PinHeader->Flags |= REG_PINFLAG_B_MANY;
00624 
00625 
00626         PinHeader->MediaTypes = FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRangesCount;
00627         PinHeader->Mediums = FilterDescriptor->PinDescriptors[Index].PinDescriptor.MediumsCount;
00628         PinHeader->Category = (FilterDescriptor->PinDescriptors[Index].PinDescriptor.Category ? TRUE : FALSE);
00629 
00630         Descriptor.FilterOffset += sizeof(KSPCACHE_PIN_HEADER);
00631 
00632         if (PinHeader->Category)
00633         {
00634             /* get category offset */
00635             PULONG Category = (PULONG)(PinHeader + 1);
00636 
00637             /* write category offset */
00638             *Category = KspCacheAddData(&Descriptor, FilterDescriptor->PinDescriptors[Index].PinDescriptor.Category, sizeof(CLSID));
00639 
00640             /* adjust offset */
00641             Descriptor.FilterOffset += sizeof(ULONG);
00642         }
00643 
00644         /* add dataranges */
00645         for(SubIndex = 0; SubIndex < FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRangesCount; SubIndex++)
00646         {
00647             /* get datarange offset */
00648             PKSPCACHE_DATARANGE DataRange = (PKSPCACHE_DATARANGE)((ULONG_PTR)Descriptor.FilterData + Descriptor.FilterOffset);
00649 
00650             /* initialize data range */
00651             DataRange->Signature = 0x33797430 + SubIndex;
00652             DataRange->dwUnused = 0;
00653             DataRange->OffsetMajor = KspCacheAddData(&Descriptor, &FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRanges[SubIndex]->MajorFormat, sizeof(CLSID));
00654             DataRange->OffsetMinor = KspCacheAddData(&Descriptor, &FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRanges[SubIndex]->SubFormat, sizeof(CLSID));
00655 
00656             /* adjust offset */
00657             Descriptor.FilterOffset += sizeof(KSPCACHE_DATARANGE);
00658         }
00659 
00660         /* add mediums */
00661         for(SubIndex = 0; SubIndex < FilterDescriptor->PinDescriptors[Index].PinDescriptor.MediumsCount; SubIndex++)
00662         {
00663             KSPCACHE_MEDIUM Medium;
00664             PULONG MediumOffset;
00665 
00666             /* get pin medium offset */
00667             MediumOffset = (PULONG)((ULONG_PTR)Descriptor.FilterData + Descriptor.FilterOffset);
00668 
00669             /* copy medium guid */
00670             RtlMoveMemory(&Medium.Medium, &FilterDescriptor->PinDescriptors[Index].PinDescriptor.Mediums[SubIndex].Set, sizeof(GUID));
00671             Medium.dw1 = FilterDescriptor->PinDescriptors[Index].PinDescriptor.Mediums[SubIndex].Id; /* FIXME verify */
00672             Medium.dw2 = 0;
00673 
00674             *MediumOffset = KspCacheAddData(&Descriptor, &Medium, sizeof(KSPCACHE_MEDIUM));
00675 
00676             /* adjust offset */
00677             Descriptor.FilterOffset += sizeof(ULONG);
00678         }
00679     }
00680 
00681     /* sanity checks */
00682     ASSERT(Descriptor.FilterOffset == Descriptor.FilterLength);
00683     ASSERT(Descriptor.DataOffset <= Descriptor.DataLength);
00684 
00685 
00686     /* now go through all entries and update 'FilterData' key */
00687     for(Index = 0; Index < FilterDescriptor->CategoriesCount; Index++)
00688     {
00689         /* get first entry */
00690         Entry = Factory->SymbolicLinkList.Flink;
00691 
00692         /* set status to not found */
00693         Found = FALSE;
00694         /* loop list until the the current category is found */
00695         while(Entry != &Factory->SymbolicLinkList)
00696         {
00697             /* fetch symbolic link entry */
00698             SymEntry = (PSYMBOLIC_LINK_ENTRY)CONTAINING_RECORD(Entry, SYMBOLIC_LINK_ENTRY, Entry);
00699 
00700             if (IsEqualGUIDAligned(&SymEntry->DeviceInterfaceClass, &FilterDescriptor->Categories[Index]))
00701             {
00702                 /* found category */
00703                 Found = TRUE;
00704                 break;
00705             }
00706 
00707             /* move to next entry */
00708             Entry = Entry->Flink;
00709         }
00710 
00711         if (!Found)
00712         {
00713             /* filter category is not present */
00714             Status = STATUS_INVALID_PARAMETER;
00715             break;
00716         }
00717 
00718         /* now open device interface */
00719         Status = IoOpenDeviceInterfaceRegistryKey(&SymEntry->SymbolicLink, KEY_WRITE, &hKey);
00720         if (!NT_SUCCESS(Status))
00721         {
00722             /* failed to open interface key */
00723             break;
00724         }
00725 
00726         /* update filterdata key */
00727         Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Descriptor.FilterData, Descriptor.FilterLength + Descriptor.DataOffset);
00728 
00729         /* close filterdata key */
00730         ZwClose(hKey);
00731 
00732         if (!NT_SUCCESS(Status))
00733         {
00734             /* failed to set key value */
00735             break;
00736         }
00737     }
00738     /* free filter data */
00739     FreeItem(Descriptor.FilterData);
00740 
00741     /* done */
00742     return Status;
00743 }   
00744 

Generated on Fri May 25 2012 04:26:03 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.