-ReadCacheSegmentChain (
- PBCB Bcb,
- ULONG ReadOffset,
- ULONG Length,
- PVOID Buffer)
-{
- PCACHE_SEGMENT head;
- PCACHE_SEGMENT current;
- PCACHE_SEGMENT previous;
- IO_STATUS_BLOCK Iosb;
- LARGE_INTEGER SegOffset;
- NTSTATUS Status;
- ULONG TempLength;
- KEVENT Event;
- PMDL Mdl;
-
- Mdl = _alloca(MmSizeOfMdl(NULL, MAX_RW_LENGTH));
-
- Status = CcRosGetCacheSegmentChain(Bcb, ReadOffset, Length, &head);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- current = head;
- while (current != NULL)
- {
- /*
- * If the current segment is valid then copy it into the
- * user buffer.
- */
- if (current->Valid)
- {
- TempLength = min(Bcb->CacheSegmentSize, Length);
- memcpy(Buffer, current->BaseAddress, TempLength);
-
- Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
-
- Length = Length - TempLength;
- previous = current;
- current = current->NextInChain;
- CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
- }
- /*
- * Otherwise read in as much as we can.
- */
- else
- {
- PCACHE_SEGMENT current2;
- ULONG current_size;
- ULONG i;
- PPFN_NUMBER MdlPages;
-
- /*
- * Count the maximum number of bytes we could read starting
- * from the current segment.
- */
- current2 = current;
- current_size = 0;
- while ((current2 != NULL) && !current2->Valid && (current_size < MAX_RW_LENGTH))
- {
- current2 = current2->NextInChain;
- current_size += Bcb->CacheSegmentSize;
- }
-
- /*
- * Create an MDL which contains all their pages.
- */
- MmInitializeMdl(Mdl, NULL, current_size);
- Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
- current2 = current;
- current_size = 0;
- MdlPages = (PPFN_NUMBER)(Mdl + 1);
- while ((current2 != NULL) && !current2->Valid && (current_size < MAX_RW_LENGTH))
- {
- PVOID address = current2->BaseAddress;
- for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++, address = RVA(address, PAGE_SIZE))
- {
- *MdlPages++ = MmGetPfnForProcess(NULL, address);
- }
- current2 = current2->NextInChain;
- current_size += Bcb->CacheSegmentSize;
- }
-
- /*
- * Read in the information.
- */
- SegOffset.QuadPart = current->FileOffset;
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Status = IoPageRead(Bcb->FileObject,
- Mdl,
- &SegOffset,
- &Event,
- &Iosb);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
- Status = Iosb.Status;
- }
- if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
- {
- MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
- }
- if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
- {
- while (current != NULL)
- {
- previous = current;
- current = current->NextInChain;
- CcRosReleaseCacheSegment(Bcb, previous, FALSE, FALSE, FALSE);
- }
- return Status;
- }
- current_size = 0;
- while (current != NULL && !current->Valid && current_size < MAX_RW_LENGTH)
- {
- previous = current;
- current = current->NextInChain;
- TempLength = min(Bcb->CacheSegmentSize, Length);
- memcpy(Buffer, previous->BaseAddress, TempLength);
-
- Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
-
- Length = Length - TempLength;
- CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
- current_size += Bcb->CacheSegmentSize;
- }
- }
- }
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-ReadCacheSegment (
- PCACHE_SEGMENT CacheSeg)