Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenbag.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/bag.c 00005 * PURPOSE: KS Object Bag functions 00006 * PROGRAMMER: Johannes Anderwald 00007 */ 00008 00009 00010 #include "priv.h" 00011 00012 typedef struct 00013 { 00014 LIST_ENTRY Entry; 00015 PVOID Item; 00016 PFNKSFREE Free; 00017 ULONG References; 00018 }KSIOBJECT_BAG_ENTRY, *PKSIOBJECT_BAG_ENTRY; 00019 00020 00021 /* 00022 @implemented 00023 */ 00024 KSDDKAPI 00025 NTSTATUS 00026 NTAPI 00027 KsAllocateObjectBag( 00028 IN PKSDEVICE Device, 00029 OUT KSOBJECT_BAG* ObjectBag) 00030 { 00031 PKSIDEVICE_HEADER DeviceHeader; 00032 PKSIOBJECT_BAG Bag; 00033 IKsDevice *KsDevice; 00034 00035 /* get real device header */ 00036 DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice); 00037 00038 /* allocate a object bag ctx */ 00039 Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG)); 00040 if (!Bag) 00041 return STATUS_INSUFFICIENT_RESOURCES; 00042 00043 /* get device interface */ 00044 KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown; 00045 00046 /* initialize object bag */ 00047 return KsDevice->lpVtbl->InitializeObjectBag(KsDevice, Bag, NULL); 00048 } 00049 00050 PKSIOBJECT_BAG_ENTRY 00051 KspFindObjectBagItem( 00052 IN PLIST_ENTRY ObjectList, 00053 IN PVOID Item) 00054 { 00055 PLIST_ENTRY Entry; 00056 PKSIOBJECT_BAG_ENTRY BagEntry; 00057 00058 /* point to first item */ 00059 Entry = ObjectList->Flink; 00060 /* first scan the list if the item is already inserted */ 00061 while(Entry != ObjectList) 00062 { 00063 /* get bag entry */ 00064 BagEntry = (PKSIOBJECT_BAG_ENTRY)CONTAINING_RECORD(Entry, KSIOBJECT_BAG_ENTRY, Entry); 00065 00066 if (BagEntry->Item == Item) 00067 { 00068 /* found entry */ 00069 return BagEntry; 00070 } 00071 /* move to next entry */ 00072 Entry = Entry->Flink; 00073 } 00074 /* item not in this object bag */ 00075 return NULL; 00076 } 00077 00078 00079 /* 00080 @implemented 00081 */ 00082 NTSTATUS 00083 NTAPI 00084 KsAddItemToObjectBag( 00085 IN KSOBJECT_BAG ObjectBag, 00086 IN PVOID Item, 00087 IN PFNKSFREE Free OPTIONAL) 00088 { 00089 PKSIOBJECT_BAG Bag; 00090 PKSIOBJECT_BAG_ENTRY BagEntry; 00091 00092 DPRINT("KsAddItemToObjectBag\n"); 00093 00094 /* get real object bag */ 00095 Bag = (PKSIOBJECT_BAG)ObjectBag; 00096 00097 /* acquire bag mutex */ 00098 KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL); 00099 00100 /* is the item already present in this object bag */ 00101 BagEntry = KspFindObjectBagItem(&Bag->ObjectList, Item); 00102 00103 if (BagEntry) 00104 { 00105 /* is is, update reference count */ 00106 InterlockedIncrement((PLONG)&BagEntry->References); 00107 /* release mutex */ 00108 KeReleaseMutex(Bag->BagMutex, FALSE); 00109 /* return result */ 00110 return STATUS_SUCCESS; 00111 } 00112 00113 /* item is new, allocate entry */ 00114 BagEntry = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG_ENTRY)); 00115 if (!BagEntry) 00116 { 00117 /* no memory */ 00118 KeReleaseMutex(Bag->BagMutex, FALSE); 00119 /* return result */ 00120 return STATUS_INSUFFICIENT_RESOURCES; 00121 } 00122 00123 /* initialize bag entry */ 00124 BagEntry->References = 1; 00125 BagEntry->Item = Item; 00126 if (Free) 00127 BagEntry->Free = Free; 00128 else 00129 BagEntry->Free = ExFreePool; 00130 00131 /* insert item */ 00132 InsertTailList(&Bag->ObjectList, &BagEntry->Entry); 00133 00134 /* release mutex */ 00135 KeReleaseMutex(Bag->BagMutex, FALSE); 00136 00137 /* done */ 00138 return STATUS_SUCCESS; 00139 } 00140 00141 ULONG 00142 KspGetObjectItemReferenceCount( 00143 IN PKSIDEVICE_HEADER DeviceHeader, 00144 IN PVOID Item) 00145 { 00146 PLIST_ENTRY Entry; 00147 PKSIOBJECT_BAG OtherBag; 00148 PKSIOBJECT_BAG_ENTRY OtherBagEntry; 00149 ULONG TotalRefs = 0; 00150 00151 /* scan all object bags and see if item is present there */ 00152 Entry = DeviceHeader->ObjectBags.Flink; 00153 while(Entry != &DeviceHeader->ObjectBags) 00154 { 00155 /* get other bag */ 00156 OtherBag = (PKSIOBJECT_BAG)CONTAINING_RECORD(Entry, KSIOBJECT_BAG, Entry); 00157 00158 /* is the item present there */ 00159 OtherBagEntry = KspFindObjectBagItem(&OtherBag->ObjectList, Item); 00160 00161 if (OtherBagEntry) 00162 TotalRefs++; 00163 00164 /* move to next item */ 00165 Entry = Entry->Flink; 00166 } 00167 00168 return TotalRefs; 00169 } 00170 00171 /* 00172 @implemented 00173 */ 00174 KSDDKAPI 00175 ULONG 00176 NTAPI 00177 KsRemoveItemFromObjectBag( 00178 IN KSOBJECT_BAG ObjectBag, 00179 IN PVOID Item, 00180 IN BOOLEAN Free) 00181 { 00182 PKSIOBJECT_BAG Bag; 00183 PKSIOBJECT_BAG_ENTRY BagEntry; 00184 ULONG TotalRefs; 00185 00186 /* get real object bag */ 00187 Bag = (PKSIOBJECT_BAG)ObjectBag; 00188 00189 /* acquire bag mutex */ 00190 KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL); 00191 00192 /* is the item already present in this object bag */ 00193 BagEntry = KspFindObjectBagItem(&Bag->ObjectList, Item); 00194 00195 if (!BagEntry) 00196 { 00197 /* item was not in this object bag */ 00198 KeReleaseMutex(Bag->BagMutex, FALSE); 00199 return 0; 00200 } 00201 00202 /* set current refs count */ 00203 TotalRefs = BagEntry->References; 00204 00205 /* get total refs count */ 00206 TotalRefs += KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER)Bag->DeviceHeader, Item); 00207 00208 /* decrease reference count */ 00209 InterlockedDecrement((PLONG)&BagEntry->References); 00210 00211 if (BagEntry->References == 0) 00212 { 00213 /* remove the entry */ 00214 RemoveEntryList(&BagEntry->Entry); 00215 } 00216 00217 if (TotalRefs == 1) 00218 { 00219 /* does the caller want to free the item */ 00220 if (Free) 00221 { 00222 /* free the item */ 00223 BagEntry->Free(BagEntry->Item); 00224 } 00225 } 00226 if (BagEntry->References == 0) 00227 { 00228 /* free bag item entry */ 00229 FreeItem(BagEntry); 00230 } 00231 00232 /* release mutex */ 00233 KeReleaseMutex(Bag->BagMutex, FALSE); 00234 00235 00236 return TotalRefs; 00237 } 00238 00239 /* 00240 @implemented 00241 */ 00242 KSDDKAPI 00243 NTSTATUS 00244 NTAPI 00245 KsCopyObjectBagItems( 00246 IN KSOBJECT_BAG ObjectBagDestination, 00247 IN KSOBJECT_BAG ObjectBagSource) 00248 { 00249 PKSIOBJECT_BAG ObjectBagDest, ObjectBagSrc; 00250 PLIST_ENTRY Entry; 00251 PKSIOBJECT_BAG_ENTRY BagEntry; 00252 NTSTATUS Status = STATUS_SUCCESS; 00253 00254 /* get object bag src */ 00255 ObjectBagSrc = (PKSIOBJECT_BAG)ObjectBagSource; 00256 00257 /* get object bag dst */ 00258 ObjectBagDest = (PKSIOBJECT_BAG)ObjectBagDestination; 00259 00260 /* acquire source mutex */ 00261 KeWaitForSingleObject(ObjectBagSrc->BagMutex, Executive, KernelMode, FALSE, NULL); 00262 00263 if (ObjectBagSrc->BagMutex != ObjectBagDest->BagMutex) 00264 { 00265 /* acquire destination mutex */ 00266 KeWaitForSingleObject(ObjectBagDest->BagMutex, Executive, KernelMode, FALSE, NULL); 00267 } 00268 00269 /* point to first item */ 00270 Entry = ObjectBagSrc->ObjectList.Flink; 00271 /* first scan the list if the item is already inserted */ 00272 while(Entry != &ObjectBagSrc->ObjectList) 00273 { 00274 /* get bag entry */ 00275 BagEntry = (PKSIOBJECT_BAG_ENTRY)CONTAINING_RECORD(Entry, KSIOBJECT_BAG_ENTRY, Entry); 00276 00277 /* add the item */ 00278 Status = KsAddItemToObjectBag(ObjectBagDestination, BagEntry->Item, BagEntry->Free); 00279 00280 /* check for success */ 00281 if (!NT_SUCCESS(Status)) 00282 break; 00283 00284 /* move to next entry */ 00285 Entry = Entry->Flink; 00286 } 00287 00288 if (ObjectBagSrc->BagMutex != ObjectBagDest->BagMutex) 00289 { 00290 /* release destination mutex */ 00291 KeReleaseMutex(ObjectBagDest->BagMutex, FALSE); 00292 } 00293 00294 /* release source mutex */ 00295 KeReleaseMutex(ObjectBagSrc->BagMutex, FALSE); 00296 00297 return Status; 00298 } 00299 00300 /* 00301 @implemented 00302 */ 00303 KSDDKAPI 00304 VOID 00305 NTAPI 00306 KsFreeObjectBag( 00307 IN KSOBJECT_BAG ObjectBag) 00308 { 00309 PLIST_ENTRY Entry; 00310 PKSIOBJECT_BAG Bag; 00311 PKSIOBJECT_BAG_ENTRY BagEntry; 00312 ULONG TotalRefs; 00313 00314 /* get real object bag */ 00315 Bag = (PKSIOBJECT_BAG)ObjectBag; 00316 00317 /* acquire bag mutex */ 00318 KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL); 00319 00320 while(!IsListEmpty(&Bag->ObjectList)) 00321 { 00322 /* get an bag entry */ 00323 Entry = RemoveHeadList(&Bag->ObjectList); 00324 /* access bag entry item */ 00325 BagEntry = (PKSIOBJECT_BAG_ENTRY)CONTAINING_RECORD(Entry, KSIOBJECT_BAG, Entry); 00326 00327 /* check if the item is present in some other bag */ 00328 TotalRefs = KspGetObjectItemReferenceCount((PKSIDEVICE_HEADER)Bag->DeviceHeader, &BagEntry->Item); 00329 00330 if (TotalRefs == 0) 00331 { 00332 /* item is ready to be freed */ 00333 BagEntry->Free(BagEntry->Item); 00334 } 00335 00336 /* free bag entry item */ 00337 FreeItem(BagEntry); 00338 } 00339 00340 /* remove bag entry from device object list */ 00341 RemoveEntryList(&Bag->Entry); 00342 00343 /* release bag mutex */ 00344 KeReleaseMutex(Bag->BagMutex, FALSE); 00345 00346 /* now free object bag */ 00347 FreeItem(Bag); 00348 } 00349 00350 /* 00351 @implemented 00352 */ 00353 KSDDKAPI 00354 NTSTATUS 00355 NTAPI 00356 _KsEdit( 00357 IN KSOBJECT_BAG ObjectBag, 00358 IN OUT PVOID* PointerToPointerToItem, 00359 IN ULONG NewSize, 00360 IN ULONG OldSize, 00361 IN ULONG Tag) 00362 { 00363 PKSIOBJECT_BAG Bag; 00364 PKSIOBJECT_BAG_ENTRY BagEntry; 00365 PVOID Item; 00366 NTSTATUS Status; 00367 00368 DPRINT("_KsEdit\n"); 00369 00370 /* get real object bag */ 00371 Bag = (PKSIOBJECT_BAG)ObjectBag; 00372 00373 /* acquire bag mutex */ 00374 KeWaitForSingleObject(Bag->BagMutex, Executive, KernelMode, FALSE, NULL); 00375 00376 00377 if (*PointerToPointerToItem) 00378 { 00379 /* search object bag for this entry */ 00380 BagEntry = KspFindObjectBagItem(&Bag->ObjectList, *PointerToPointerToItem); 00381 } 00382 else 00383 { 00384 /* pointer to null, allocate new entry */ 00385 BagEntry = NULL; 00386 } 00387 00388 if (!BagEntry || NewSize > OldSize) 00389 { 00390 /* entry does not exist or new entry must be allocated */ 00391 Item = AllocateItem(NonPagedPool, NewSize); 00392 00393 if (!Item) 00394 { 00395 /* not enough resources */ 00396 KeReleaseMutex(Bag->BagMutex, FALSE); 00397 return STATUS_INSUFFICIENT_RESOURCES; 00398 } 00399 00400 /* now add the item to the object bag */ 00401 Status = KsAddItemToObjectBag((KSOBJECT_BAG)Bag, Item, NULL); 00402 /* check for success */ 00403 if (!NT_SUCCESS(Status)) 00404 { 00405 /* failed to add item */ 00406 FreeItem(Item); 00407 KeReleaseMutex(Bag->BagMutex, FALSE); 00408 return Status; 00409 } 00410 00411 if (*PointerToPointerToItem) 00412 { 00413 /* object exists */ 00414 if (OldSize >= NewSize) 00415 { 00416 /* copy old contents */ 00417 RtlMoveMemory(Item, *PointerToPointerToItem, NewSize); 00418 } 00419 else 00420 { 00421 /* copy new contents */ 00422 RtlMoveMemory(Item, *PointerToPointerToItem, OldSize); 00423 } 00424 } 00425 00426 if (BagEntry) 00427 { 00428 /* remove old entry */ 00429 KsRemoveItemFromObjectBag(ObjectBag, BagEntry->Item, TRUE); 00430 } 00431 00432 /* store item */ 00433 *PointerToPointerToItem = Item; 00434 } 00435 00436 /* release bag mutex */ 00437 KeReleaseMutex(Bag->BagMutex, FALSE); 00438 00439 return STATUS_SUCCESS; 00440 } 00441 00442 Generated on Sat May 26 2012 04:26:32 for ReactOS by
1.7.6.1
|