Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfilterfactory.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
1.7.6.1
|