Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfssup.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel 00004 * FILE: ntoskrnl/cache/fssup.c 00005 * PURPOSE: Logging and configuration routines 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Art Yerkes 00008 */ 00009 00010 /* INCLUDES *******************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #include "newcc.h" 00014 #include "section/newmm.h" 00015 #define NDEBUG 00016 #include <debug.h> 00017 00018 /* GLOBALS ********************************************************************/ 00019 00020 PFSN_PREFETCHER_GLOBALS CcPfGlobals; 00021 extern LONG CcOutstandingDeletes; 00022 extern KEVENT CcpLazyWriteEvent; 00023 extern KEVENT CcFinalizeEvent; 00024 extern VOID NTAPI CcpUnmapThread(PVOID Unused); 00025 extern VOID NTAPI CcpLazyWriteThread(PVOID Unused); 00026 HANDLE CcUnmapThreadHandle, CcLazyWriteThreadHandle; 00027 CLIENT_ID CcUnmapThreadId, CcLazyWriteThreadId; 00028 FAST_MUTEX GlobalPageOperation; 00029 00030 /* 00031 00032 A note about private cache maps. 00033 00034 CcInitializeCacheMap and CcUninitializeCacheMap are not meant to be paired, 00035 although they can work that way. 00036 00037 The actual operation I've gleaned from reading both jan kratchovil's writing 00038 and real filesystems is this: 00039 00040 CcInitializeCacheMap means: 00041 00042 Make the indicated FILE_OBJECT have a private cache map if it doesn't already 00043 and make it have a shared cache map if it doesn't already. 00044 00045 CcUninitializeCacheMap means: 00046 00047 Take away the private cache map from this FILE_OBJECT. If it's the last 00048 private cache map corresponding to a specific shared cache map (the one that 00049 was present in the FILE_OBJECT when it was created), then delete that too, 00050 flusing all cached information. 00051 00052 Using these simple semantics, filesystems can do all the things they actually 00053 do: 00054 00055 - Copy out the shared cache map pointer from a newly initialized file object 00056 and store it in the fcb cache. 00057 - Copy it back into any file object and call CcInitializeCacheMap to make 00058 that file object be associated with the caching of all the other siblings. 00059 - Call CcUninitializeCacheMap on a FILE_OBJECT many times, but have only the 00060 first one count for each specific FILE_OBJECT. 00061 - Have the actual last call to CcUninitializeCacheMap (that is, the one that 00062 causes zero private cache maps to be associated with a shared cache map) to 00063 delete the cache map and flush. 00064 00065 So private cache map here is a light weight structure that just remembers 00066 what shared cache map it associates with. 00067 00068 */ 00069 typedef struct _NOCC_PRIVATE_CACHE_MAP 00070 { 00071 LIST_ENTRY ListEntry; 00072 PFILE_OBJECT FileObject; 00073 PNOCC_CACHE_MAP Map; 00074 } NOCC_PRIVATE_CACHE_MAP, *PNOCC_PRIVATE_CACHE_MAP; 00075 00076 LIST_ENTRY CcpAllSharedCacheMaps; 00077 00078 /* FUNCTIONS ******************************************************************/ 00079 00080 BOOLEAN 00081 NTAPI 00082 CcInitializeCacheManager(VOID) 00083 { 00084 int i; 00085 00086 DPRINT("Initialize\n"); 00087 for (i = 0; i < CACHE_NUM_SECTIONS; i++) 00088 { 00089 KeInitializeEvent(&CcCacheSections[i].ExclusiveWait, 00090 SynchronizationEvent, 00091 FALSE); 00092 00093 InitializeListHead(&CcCacheSections[i].ThisFileList); 00094 } 00095 00096 InitializeListHead(&CcpAllSharedCacheMaps); 00097 00098 KeInitializeEvent(&CcDeleteEvent, SynchronizationEvent, FALSE); 00099 KeInitializeEvent(&CcFinalizeEvent, SynchronizationEvent, FALSE); 00100 KeInitializeEvent(&CcpLazyWriteEvent, SynchronizationEvent, FALSE); 00101 00102 CcCacheBitmap->Buffer = ((PULONG)&CcCacheBitmap[1]); 00103 CcCacheBitmap->SizeOfBitMap = ROUND_UP(CACHE_NUM_SECTIONS, 32); 00104 DPRINT1("Cache has %d entries\n", CcCacheBitmap->SizeOfBitMap); 00105 ExInitializeFastMutex(&CcMutex); 00106 00107 return TRUE; 00108 } 00109 00110 VOID 00111 NTAPI 00112 CcPfInitializePrefetcher(VOID) 00113 { 00114 /* Notify debugger */ 00115 DbgPrintEx(DPFLTR_PREFETCHER_ID, 00116 DPFLTR_TRACE_LEVEL, 00117 "CCPF: InitializePrefetecher()\n"); 00118 00119 /* Setup the Prefetcher Data */ 00120 InitializeListHead(&CcPfGlobals.ActiveTraces); 00121 InitializeListHead(&CcPfGlobals.CompletedTraces); 00122 ExInitializeFastMutex(&CcPfGlobals.CompletedTracesLock); 00123 00124 /* FIXME: Setup the rest of the prefetecher */ 00125 } 00126 00127 BOOLEAN 00128 NTAPI 00129 CcpAcquireFileLock(PNOCC_CACHE_MAP Map) 00130 { 00131 DPRINT("Calling AcquireForLazyWrite: %x\n", Map->LazyContext); 00132 return Map->Callbacks.AcquireForLazyWrite(Map->LazyContext, TRUE); 00133 } 00134 00135 VOID 00136 NTAPI 00137 CcpReleaseFileLock(PNOCC_CACHE_MAP Map) 00138 { 00139 DPRINT("Releasing Lazy Write %x\n", Map->LazyContext); 00140 Map->Callbacks.ReleaseFromLazyWrite(Map->LazyContext); 00141 } 00142 00143 /* 00144 00145 Cc functions are required to treat alternate streams of a file as the same 00146 for the purpose of caching, meaning that we must be able to find the shared 00147 cache map associated with the ``real'' stream associated with a stream file 00148 object, if one exists. We do that by identifying a private cache map in 00149 our gamut that has the same volume, device and fscontext as the stream file 00150 object we're holding. It's heavy but it does work. This can probably be 00151 improved, although there doesn't seem to be any real association between 00152 a stream file object and a sibling file object in the file object struct 00153 itself. 00154 00155 */ 00156 00157 /* Must have CcpLock() */ 00158 PFILE_OBJECT CcpFindOtherStreamFileObject(PFILE_OBJECT FileObject) 00159 { 00160 PLIST_ENTRY Entry, Private; 00161 for (Entry = CcpAllSharedCacheMaps.Flink; 00162 Entry != &CcpAllSharedCacheMaps; 00163 Entry = Entry->Flink) 00164 { 00165 /* 'Identical' test for other stream file object */ 00166 PNOCC_CACHE_MAP Map = CONTAINING_RECORD(Entry, NOCC_CACHE_MAP, Entry); 00167 for (Private = Map->PrivateCacheMaps.Flink; 00168 Private != &Map->PrivateCacheMaps; 00169 Private = Private->Flink) 00170 { 00171 PNOCC_PRIVATE_CACHE_MAP PrivateMap = CONTAINING_RECORD(Private, 00172 NOCC_PRIVATE_CACHE_MAP, 00173 ListEntry); 00174 00175 if (PrivateMap->FileObject->Flags & FO_STREAM_FILE && 00176 PrivateMap->FileObject->DeviceObject == FileObject->DeviceObject && 00177 PrivateMap->FileObject->Vpb == FileObject->Vpb && 00178 PrivateMap->FileObject->FsContext == FileObject->FsContext && 00179 PrivateMap->FileObject->FsContext2 == FileObject->FsContext2 && 00180 1) 00181 { 00182 return PrivateMap->FileObject; 00183 } 00184 } 00185 } 00186 return 0; 00187 } 00188 00189 /* Thanks: http://windowsitpro.com/Windows/Articles/ArticleID/3864/pg/2/2.html */ 00190 00191 VOID 00192 NTAPI 00193 CcInitializeCacheMap(IN PFILE_OBJECT FileObject, 00194 IN PCC_FILE_SIZES FileSizes, 00195 IN BOOLEAN PinAccess, 00196 IN PCACHE_MANAGER_CALLBACKS Callbacks, 00197 IN PVOID LazyWriteContext) 00198 { 00199 PNOCC_CACHE_MAP Map = FileObject->SectionObjectPointer->SharedCacheMap; 00200 PNOCC_PRIVATE_CACHE_MAP PrivateCacheMap = FileObject->PrivateCacheMap; 00201 00202 CcpLock(); 00203 /* We don't have a shared cache map. First find out if we have a sibling 00204 stream file object we can take it from. */ 00205 if (!Map && FileObject->Flags & FO_STREAM_FILE) 00206 { 00207 PFILE_OBJECT IdenticalStreamFileObject = CcpFindOtherStreamFileObject(FileObject); 00208 if (IdenticalStreamFileObject) 00209 Map = IdenticalStreamFileObject->SectionObjectPointer->SharedCacheMap; 00210 if (Map) 00211 { 00212 DPRINT1("Linking SFO %x to previous SFO %x through cache map %x #\n", 00213 FileObject, 00214 IdenticalStreamFileObject, 00215 Map); 00216 } 00217 } 00218 /* We still don't have a shared cache map. We need to create one. */ 00219 if (!Map) 00220 { 00221 DPRINT("Initializing file object for (%p) %wZ\n", 00222 FileObject, 00223 &FileObject->FileName); 00224 00225 Map = ExAllocatePool(NonPagedPool, sizeof(NOCC_CACHE_MAP)); 00226 FileObject->SectionObjectPointer->SharedCacheMap = Map; 00227 Map->FileSizes = *FileSizes; 00228 Map->LazyContext = LazyWriteContext; 00229 Map->ReadAheadGranularity = PAGE_SIZE; 00230 RtlCopyMemory(&Map->Callbacks, Callbacks, sizeof(*Callbacks)); 00231 00232 /* For now ... */ 00233 DPRINT("FileSizes->ValidDataLength %08x%08x\n", 00234 FileSizes->ValidDataLength.HighPart, 00235 FileSizes->ValidDataLength.LowPart); 00236 00237 InitializeListHead(&Map->AssociatedBcb); 00238 InitializeListHead(&Map->PrivateCacheMaps); 00239 InsertTailList(&CcpAllSharedCacheMaps, &Map->Entry); 00240 DPRINT("New Map %x\n", Map); 00241 } 00242 /* We don't have a private cache map. Link it with the shared cache map 00243 to serve as a held reference. When the list in the shared cache map 00244 is empty, we know we can delete it. */ 00245 if (!PrivateCacheMap) 00246 { 00247 PrivateCacheMap = ExAllocatePool(NonPagedPool, 00248 sizeof(*PrivateCacheMap)); 00249 00250 FileObject->PrivateCacheMap = PrivateCacheMap; 00251 PrivateCacheMap->FileObject = FileObject; 00252 ObReferenceObject(PrivateCacheMap->FileObject); 00253 } 00254 00255 PrivateCacheMap->Map = Map; 00256 InsertTailList(&Map->PrivateCacheMaps, &PrivateCacheMap->ListEntry); 00257 00258 CcpUnlock(); 00259 } 00260 00261 /* 00262 00263 This function is used by NewCC's MM to determine whether any section objects 00264 for a given file are not cache sections. If that's true, we're not allowed 00265 to resize the file, although nothing actually prevents us from doing ;-) 00266 00267 */ 00268 00269 ULONG 00270 NTAPI 00271 CcpCountCacheSections(IN PNOCC_CACHE_MAP Map) 00272 { 00273 PLIST_ENTRY Entry; 00274 ULONG Count; 00275 00276 for (Count = 0, Entry = Map->AssociatedBcb.Flink; 00277 Entry != &Map->AssociatedBcb; 00278 Entry = Entry->Flink, Count++); 00279 00280 return Count; 00281 } 00282 00283 BOOLEAN 00284 NTAPI 00285 CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, 00286 IN OPTIONAL PLARGE_INTEGER TruncateSize, 00287 IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent) 00288 { 00289 BOOLEAN LastMap = FALSE; 00290 PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; 00291 PNOCC_PRIVATE_CACHE_MAP PrivateCacheMap = FileObject->PrivateCacheMap; 00292 00293 DPRINT("Uninitializing file object for %wZ SectionObjectPointer %x\n", 00294 &FileObject->FileName, 00295 FileObject->SectionObjectPointer); 00296 00297 ASSERT(UninitializeEvent == NULL); 00298 00299 /* It may not be strictly necessary to flush here, but we do just for 00300 kicks. */ 00301 if (Map) 00302 CcpFlushCache(Map, NULL, 0, NULL, FALSE); 00303 00304 CcpLock(); 00305 /* We have a private cache map, so we've been initialized and haven't been 00306 * uninitialized. */ 00307 if (PrivateCacheMap) 00308 { 00309 ASSERT(!Map || Map == PrivateCacheMap->Map); 00310 ASSERT(PrivateCacheMap->FileObject == FileObject); 00311 00312 RemoveEntryList(&PrivateCacheMap->ListEntry); 00313 /* That was the last private cache map. It's time to delete all 00314 cache stripes and all aspects of caching on the file. */ 00315 if (IsListEmpty(&PrivateCacheMap->Map->PrivateCacheMaps)) 00316 { 00317 /* Get rid of all the cache stripes. */ 00318 while (!IsListEmpty(&PrivateCacheMap->Map->AssociatedBcb)) 00319 { 00320 PNOCC_BCB Bcb = CONTAINING_RECORD(PrivateCacheMap->Map->AssociatedBcb.Flink, 00321 NOCC_BCB, 00322 ThisFileList); 00323 00324 DPRINT("Evicting cache stripe #%x\n", Bcb - CcCacheSections); 00325 Bcb->RefCount = 1; 00326 CcpDereferenceCache(Bcb - CcCacheSections, TRUE); 00327 } 00328 RemoveEntryList(&PrivateCacheMap->Map->Entry); 00329 ExFreePool(PrivateCacheMap->Map); 00330 FileObject->SectionObjectPointer->SharedCacheMap = NULL; 00331 LastMap = TRUE; 00332 } 00333 ObDereferenceObject(PrivateCacheMap->FileObject); 00334 FileObject->PrivateCacheMap = NULL; 00335 ExFreePool(PrivateCacheMap); 00336 } 00337 CcpUnlock(); 00338 00339 DPRINT("Uninit complete\n"); 00340 00341 /* The return from CcUninitializeCacheMap means that 'caching was stopped'. */ 00342 return LastMap; 00343 } 00344 00345 /* 00346 00347 CcSetFileSizes is used to tell the cache manager that the file changed 00348 size. In our case, we use the internal Mm method MmExtendCacheSection 00349 to notify Mm that our section potentially changed size, which may mean 00350 truncating off data. 00351 00352 */ 00353 VOID 00354 NTAPI 00355 CcSetFileSizes(IN PFILE_OBJECT FileObject, 00356 IN PCC_FILE_SIZES FileSizes) 00357 { 00358 PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; 00359 PNOCC_BCB Bcb; 00360 00361 if (!Map) return; 00362 Map->FileSizes = *FileSizes; 00363 Bcb = Map->AssociatedBcb.Flink == &Map->AssociatedBcb ? 00364 NULL : CONTAINING_RECORD(Map->AssociatedBcb.Flink, NOCC_BCB, ThisFileList); 00365 if (!Bcb) return; 00366 MmExtendCacheSection(Bcb->SectionObject, &FileSizes->FileSize, FALSE); 00367 DPRINT("FileSizes->FileSize %x\n", FileSizes->FileSize.LowPart); 00368 DPRINT("FileSizes->AllocationSize %x\n", FileSizes->AllocationSize.LowPart); 00369 DPRINT("FileSizes->ValidDataLength %x\n", FileSizes->ValidDataLength.LowPart); 00370 } 00371 00372 BOOLEAN 00373 NTAPI 00374 CcGetFileSizes(IN PFILE_OBJECT FileObject, 00375 IN PCC_FILE_SIZES FileSizes) 00376 { 00377 PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; 00378 if (!Map) return FALSE; 00379 *FileSizes = Map->FileSizes; 00380 return TRUE; 00381 } 00382 00383 BOOLEAN 00384 NTAPI 00385 CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, 00386 IN OPTIONAL PLARGE_INTEGER FileOffset, 00387 IN ULONG Length, 00388 IN BOOLEAN UninitializeCacheMaps) 00389 { 00390 PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap; 00391 if (!Map) return TRUE; 00392 CcpFlushCache(Map, NULL, 0, NULL, TRUE); 00393 return TRUE; 00394 } 00395 00396 VOID 00397 NTAPI 00398 CcSetDirtyPageThreshold(IN PFILE_OBJECT FileObject, 00399 IN ULONG DirtyPageThreshold) 00400 { 00401 UNIMPLEMENTED; 00402 while (TRUE); 00403 } 00404 00405 /* 00406 00407 This could be implemented much more intelligently by mapping instances 00408 of a CoW zero page into the affected regions. We just RtlZeroMemory 00409 for now. 00410 00411 */ 00412 BOOLEAN 00413 NTAPI 00414 CcZeroData(IN PFILE_OBJECT FileObject, 00415 IN PLARGE_INTEGER StartOffset, 00416 IN PLARGE_INTEGER EndOffset, 00417 IN BOOLEAN Wait) 00418 { 00419 PNOCC_BCB Bcb = NULL; 00420 PLIST_ENTRY ListEntry = NULL; 00421 LARGE_INTEGER LowerBound = *StartOffset; 00422 LARGE_INTEGER UpperBound = *EndOffset; 00423 LARGE_INTEGER Target, End; 00424 PVOID PinnedBcb, PinnedBuffer; 00425 PNOCC_CACHE_MAP Map = FileObject->SectionObjectPointer->SharedCacheMap; 00426 00427 DPRINT("S %08x%08x E %08x%08x\n", 00428 StartOffset->u.HighPart, 00429 StartOffset->u.LowPart, 00430 EndOffset->u.HighPart, 00431 EndOffset->u.LowPart); 00432 00433 if (!Map) 00434 { 00435 NTSTATUS Status; 00436 IO_STATUS_BLOCK IOSB; 00437 PCHAR ZeroBuf = ExAllocatePool(PagedPool, PAGE_SIZE); 00438 ULONG ToWrite; 00439 00440 if (!ZeroBuf) RtlRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); 00441 DPRINT1("RtlZeroMemory(%x,%x)\n", ZeroBuf, PAGE_SIZE); 00442 RtlZeroMemory(ZeroBuf, PAGE_SIZE); 00443 00444 Target.QuadPart = PAGE_ROUND_DOWN(LowerBound.QuadPart); 00445 End.QuadPart = PAGE_ROUND_UP(UpperBound.QuadPart); 00446 00447 // Handle leading page 00448 if (LowerBound.QuadPart != Target.QuadPart) 00449 { 00450 ToWrite = MIN(UpperBound.QuadPart - LowerBound.QuadPart, 00451 (PAGE_SIZE - LowerBound.QuadPart) & (PAGE_SIZE - 1)); 00452 00453 DPRINT("Zero last half %08x%08x %x\n", 00454 Target.u.HighPart, 00455 Target.u.LowPart, 00456 ToWrite); 00457 00458 Status = MiSimpleRead(FileObject, 00459 &Target, 00460 ZeroBuf, 00461 PAGE_SIZE, 00462 TRUE, 00463 &IOSB); 00464 00465 if (!NT_SUCCESS(Status)) 00466 { 00467 ExFreePool(ZeroBuf); 00468 RtlRaiseStatus(Status); 00469 } 00470 00471 DPRINT1("RtlZeroMemory(%x,%x)\n", 00472 ZeroBuf + LowerBound.QuadPart - Target.QuadPart, 00473 ToWrite); 00474 00475 RtlZeroMemory(ZeroBuf + LowerBound.QuadPart - Target.QuadPart, 00476 ToWrite); 00477 00478 Status = MiSimpleWrite(FileObject, 00479 &Target, 00480 ZeroBuf, 00481 MIN(PAGE_SIZE, 00482 UpperBound.QuadPart-Target.QuadPart), 00483 &IOSB); 00484 00485 if (!NT_SUCCESS(Status)) 00486 { 00487 ExFreePool(ZeroBuf); 00488 RtlRaiseStatus(Status); 00489 } 00490 Target.QuadPart += PAGE_SIZE; 00491 } 00492 00493 DPRINT1("RtlZeroMemory(%x,%x)\n", ZeroBuf, PAGE_SIZE); 00494 RtlZeroMemory(ZeroBuf, PAGE_SIZE); 00495 00496 while (UpperBound.QuadPart - Target.QuadPart > PAGE_SIZE) 00497 { 00498 DPRINT("Zero full page %08x%08x\n", 00499 Target.u.HighPart, 00500 Target.u.LowPart); 00501 00502 Status = MiSimpleWrite(FileObject, 00503 &Target, 00504 ZeroBuf, 00505 PAGE_SIZE, 00506 &IOSB); 00507 00508 if (!NT_SUCCESS(Status)) 00509 { 00510 ExFreePool(ZeroBuf); 00511 RtlRaiseStatus(Status); 00512 } 00513 Target.QuadPart += PAGE_SIZE; 00514 } 00515 00516 if (UpperBound.QuadPart > Target.QuadPart) 00517 { 00518 ToWrite = UpperBound.QuadPart - Target.QuadPart; 00519 DPRINT("Zero first half %08x%08x %x\n", 00520 Target.u.HighPart, 00521 Target.u.LowPart, 00522 ToWrite); 00523 00524 Status = MiSimpleRead(FileObject, 00525 &Target, 00526 ZeroBuf, 00527 PAGE_SIZE, 00528 TRUE, 00529 &IOSB); 00530 00531 if (!NT_SUCCESS(Status)) 00532 { 00533 ExFreePool(ZeroBuf); 00534 RtlRaiseStatus(Status); 00535 } 00536 DPRINT1("RtlZeroMemory(%x,%x)\n", ZeroBuf, ToWrite); 00537 RtlZeroMemory(ZeroBuf, ToWrite); 00538 Status = MiSimpleWrite(FileObject, 00539 &Target, 00540 ZeroBuf, 00541 MIN(PAGE_SIZE, 00542 UpperBound.QuadPart-Target.QuadPart), 00543 &IOSB); 00544 if (!NT_SUCCESS(Status)) 00545 { 00546 ExFreePool(ZeroBuf); 00547 RtlRaiseStatus(Status); 00548 } 00549 Target.QuadPart += PAGE_SIZE; 00550 } 00551 00552 ExFreePool(ZeroBuf); 00553 return TRUE; 00554 } 00555 00556 CcpLock(); 00557 ListEntry = Map->AssociatedBcb.Flink; 00558 00559 while (ListEntry != &Map->AssociatedBcb) 00560 { 00561 Bcb = CONTAINING_RECORD(ListEntry, NOCC_BCB, ThisFileList); 00562 CcpReferenceCache(Bcb - CcCacheSections); 00563 00564 if (Bcb->FileOffset.QuadPart + Bcb->Length >= LowerBound.QuadPart && 00565 Bcb->FileOffset.QuadPart < UpperBound.QuadPart) 00566 { 00567 DPRINT("Bcb #%x (@%08x%08x)\n", 00568 Bcb - CcCacheSections, 00569 Bcb->FileOffset.u.HighPart, 00570 Bcb->FileOffset.u.LowPart); 00571 00572 Target.QuadPart = MAX(Bcb->FileOffset.QuadPart, 00573 LowerBound.QuadPart); 00574 00575 End.QuadPart = MIN(Map->FileSizes.ValidDataLength.QuadPart, 00576 UpperBound.QuadPart); 00577 00578 End.QuadPart = MIN(End.QuadPart, 00579 Bcb->FileOffset.QuadPart + Bcb->Length); 00580 00581 CcpUnlock(); 00582 00583 if (!CcPreparePinWrite(FileObject, 00584 &Target, 00585 End.QuadPart - Target.QuadPart, 00586 TRUE, 00587 Wait, 00588 &PinnedBcb, 00589 &PinnedBuffer)) 00590 { 00591 return FALSE; 00592 } 00593 00594 ASSERT(PinnedBcb == Bcb); 00595 00596 CcpLock(); 00597 ListEntry = ListEntry->Flink; 00598 /* Return from pin state */ 00599 CcpUnpinData(PinnedBcb, TRUE); 00600 } 00601 00602 CcpUnpinData(Bcb, TRUE); 00603 } 00604 00605 CcpUnlock(); 00606 00607 return TRUE; 00608 } 00609 00610 PFILE_OBJECT 00611 NTAPI 00612 CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointer) 00613 { 00614 PFILE_OBJECT Result = NULL; 00615 PNOCC_CACHE_MAP Map = SectionObjectPointer->SharedCacheMap; 00616 CcpLock(); 00617 if (!IsListEmpty(&Map->AssociatedBcb)) 00618 { 00619 PNOCC_BCB Bcb = CONTAINING_RECORD(Map->AssociatedBcb.Flink, 00620 NOCC_BCB, 00621 ThisFileList); 00622 00623 Result = MmGetFileObjectForSection((PROS_SECTION_OBJECT)Bcb->SectionObject); 00624 } 00625 CcpUnlock(); 00626 return Result; 00627 } 00628 00629 PFILE_OBJECT 00630 NTAPI 00631 CcGetFileObjectFromBcb(PVOID Bcb) 00632 { 00633 PNOCC_BCB RealBcb = (PNOCC_BCB)Bcb; 00634 DPRINT("BCB #%x\n", RealBcb - CcCacheSections); 00635 return MmGetFileObjectForSection((PROS_SECTION_OBJECT)RealBcb->SectionObject); 00636 } 00637 00638 /* EOF */ Generated on Sat May 26 2012 04:35:55 for ReactOS by
1.7.6.1
|