/* * @implemented */ VOID NTAPI FsRtlInitializeMcb(IN PMCB Mcb, IN POOL_TYPE PoolType) { /* Call the newer function */ FsRtlInitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly, PoolType); }
NTSTATUS UdfLoadSparingTables( PIRP_CONTEXT IrpContext, PVCB Vcb, PPCB Pcb, ULONG Reference ) /*++ Routine Description: This routine reads the sparing tables for a partition and fills in the sparing Mcb. Arguments: Vcb - the volume hosting the spared partition Pcb - the partion block corresponding to the volume Reference - the partition reference being pulled in Return Value: NTSTATUS according to whether the sparing tables were loaded --*/ { NTSTATUS Status; ULONG SparingTable; PULONG SectorBuffer; ULONG Psn; ULONG RemainingBytes; ULONG ByteOffset; ULONG TotalBytes; BOOLEAN Complete; PSPARING_TABLE_HEADER Header; PSPARING_TABLE_ENTRY Entry; PPARTITION Partition = &Pcb->Partition[Reference]; PPARTMAP_SPARABLE Map = Partition->Physical.SparingMap; ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_VCB( Vcb ); ASSERT( Map != NULL ); DebugTrace(( +1, Dbg, "UdfLoadSparingTables, Vcb %08x, PcbPartition %08x, Map @ %08x\n", Vcb, Partition, Map )); DebugTrace(( 0, Dbg, "UdfLoadSparingTables, Map sez: PacketLen %u, NTables %u, TableSize %u\n", Map->PacketLength, Map->NumSparingTables, Map->TableSize)); // // Check that the sparale map appears sane. If there are no sparing tables that // is pretty OK, and it'll wind up looking like a regular physical partition. // if (Map->NumSparingTables == 0) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, no sparing tables claimed!\n" )); DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_SUCCESS\n" )); return STATUS_SUCCESS; } if (Map->NumSparingTables > sizeof(Map->TableLocation)/sizeof(ULONG)) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, too many claimed tables to fit! (max %u)\n", sizeof(Map->TableLocation)/sizeof(ULONG))); DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" )); return STATUS_DISK_CORRUPT_ERROR; } if (Map->PacketLength != UDF_SPARING_PACKET_LENGTH) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, packet size is %u (not %u!\n", Map->PacketLength, UDF_SPARING_PACKET_LENGTH )); DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" )); return STATUS_DISK_CORRUPT_ERROR; } if (Map->TableSize < sizeof(SPARING_TABLE_HEADER) || (Map->TableSize - sizeof(SPARING_TABLE_HEADER)) % sizeof(SPARING_TABLE_ENTRY) != 0) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table size is too small or unaligned!\n" )); DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" )); return STATUS_DISK_CORRUPT_ERROR; } #ifdef UDF_SANITY DebugTrace(( 0, Dbg, "UdfLoadSparingTables" )); for (SparingTable = 0; SparingTable < Map->NumSparingTables; SparingTable++) { DebugTrace(( 0, Dbg, ", Table %u @ %x", SparingTable, Map->TableLocation[SparingTable] )); } DebugTrace(( 0, Dbg, "\n" )); #endif // // If a sparing mcb doesn't exist, manufacture one. // if (Pcb->SparingMcb == NULL) { Pcb->SparingMcb = FsRtlAllocatePoolWithTag( PagedPool, sizeof(LARGE_MCB), TAG_SPARING_MCB ); FsRtlInitializeLargeMcb( Pcb->SparingMcb, PagedPool ); } SectorBuffer = FsRtlAllocatePoolWithTag( PagedPool, PAGE_SIZE, TAG_NSR_FSD ); // // Now loop across the sparing tables and pull the data in. // try { for (Complete = FALSE, SparingTable = 0; SparingTable < Map->NumSparingTables; SparingTable++) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, loading sparing table %u!\n", SparingTable )); ByteOffset = 0; TotalBytes = 0; RemainingBytes = 0; do { if (RemainingBytes == 0) { (VOID) UdfReadSectors( IrpContext, BytesFromSectors( Vcb, Map->TableLocation[SparingTable] ) + ByteOffset, SectorSize( Vcb ), FALSE, SectorBuffer, Vcb->TargetDeviceObject ); // // Verify the descriptor at the head of the sparing table. If it is not // valid, we just break out for a chance at the next table, if any. // if (ByteOffset == 0) { Header = (PSPARING_TABLE_HEADER) SectorBuffer; if (!UdfVerifyDescriptor( IrpContext, &Header->Destag, 0, SectorSize( Vcb ), Header->Destag.Lbn, TRUE )) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table %u didn't verify destag!\n", SparingTable )); break; } if (!UdfUdfIdentifierContained( &Header->RegID, &UdfSparingTableIdentifier, UDF_VERSION_150, UDF_VERSION_RECOGNIZED, OSCLASS_INVALID, OSIDENTIFIER_INVALID)) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table %u didn't verify regid!\n", SparingTable )); break; } // // Calculate the total number bytes this map spans and check it against what // we were told the sparing table sizes are. // DebugTrace(( 0, Dbg, "UdfLoadSparingTables, Sparing table %u has %u entries\n", SparingTable, Header->TableEntries )); TotalBytes = sizeof(SPARING_TABLE_HEADER) + Header->TableEntries * sizeof(SPARING_TABLE_ENTRY); if (Map->TableSize < TotalBytes) { DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table #ents %u overflows allocation!\n", Header->TableEntries )); break; } // // So far so good, advance past the header. // ByteOffset = sizeof(SPARING_TABLE_HEADER); Entry = Add2Ptr( SectorBuffer, sizeof(SPARING_TABLE_HEADER), PSPARING_TABLE_ENTRY ); } else { // // Pick up in the new sector. // Entry = (PSPARING_TABLE_ENTRY) SectorBuffer; } RemainingBytes = Min( SectorSize( Vcb ), TotalBytes - ByteOffset ); } // // Add the mapping. Since sparing tables are an Lbn->Psn mapping, // very odd, and I want to simplify things by putting the sparing // in right at IO dispatch, translate this to a Psn->Psn mapping. // if (Entry->Original != UDF_SPARING_AVALIABLE && Entry->Original != UDF_SPARING_DEFECTIVE) { Psn = Partition->Physical.Start + SectorsFromBlocks( Vcb, Entry->Original ); DebugTrace(( 0, Dbg, "UdfLoadSparingTables, mapping from Psn %x (Lbn %x) -> Psn %x\n", Psn, Entry->Original, Entry->Mapped )); FsRtlAddLargeMcbEntry( Pcb->SparingMcb, Psn, Entry->Mapped, UDF_SPARING_PACKET_LENGTH ); } // // Advance to the next, and drop out if we've hit the end. // ByteOffset += sizeof(SPARING_TABLE_ENTRY); RemainingBytes -= sizeof(SPARING_TABLE_ENTRY); Entry++; } while ( ByteOffset < TotalBytes ); } } finally { DebugUnwind( UdfLoadSparingTables ); UdfFreePool( &SectorBuffer ); } DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_SUCCESS\n" )); return STATUS_SUCCESS; }
NTSTATUS FFSInitializeVcb( IN PFFS_IRP_CONTEXT IrpContext, IN PFFS_VCB Vcb, IN PFFS_SUPER_BLOCK FFSSb, IN PDEVICE_OBJECT TargetDevice, IN PDEVICE_OBJECT VolumeDevice, IN PVPB Vpb) { BOOLEAN VcbResourceInitialized = FALSE; USHORT VolumeLabelLength; ULONG IoctlSize; BOOLEAN NotifySyncInitialized = FALSE; LONGLONG DiskSize; LONGLONG PartSize; NTSTATUS Status = STATUS_UNSUCCESSFUL; UNICODE_STRING RootNode; USHORT Buffer[2]; ULONG ChangeCount; __try { if (!Vpb) { Status = STATUS_DEVICE_NOT_READY; __leave; } Buffer[0] = L'\\'; Buffer[1] = 0; RootNode.Buffer = Buffer; RootNode.MaximumLength = RootNode.Length = 2; Vcb->McbTree = FFSAllocateMcb(Vcb, &RootNode, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL); if (!Vcb->McbTree) { __leave; } #if FFS_READ_ONLY SetFlag(Vcb->Flags, VCB_READ_ONLY); #endif //READ_ONLY if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA)) { SetFlag(Vcb->Flags, VCB_REMOVABLE_MEDIA); } if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE)) { SetFlag(Vcb->Flags, VCB_FLOPPY_DISK); } #if 0 if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING)) { if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING)) { ClearFlag(Vcb->Flags, VCB_READ_ONLY); } else { SetFlag(Vcb->Flags, VCB_READ_ONLY); } } else #endif { SetFlag(Vcb->Flags, VCB_READ_ONLY); } ExInitializeResourceLite(&Vcb->MainResource); ExInitializeResourceLite(&Vcb->PagingIoResource); ExInitializeResourceLite(&Vcb->McbResource); VcbResourceInitialized = TRUE; Vcb->McbTree->Inode = FFS_ROOT_INO; Vcb->Vpb = Vpb; Vcb->RealDevice = Vpb->RealDevice; Vpb->DeviceObject = VolumeDevice; { UNICODE_STRING LabelName; OEM_STRING OemName; LabelName.MaximumLength = 16 * 2; LabelName.Length = 0; LabelName.Buffer = Vcb->Vpb->VolumeLabel; RtlZeroMemory(LabelName.Buffer, LabelName.MaximumLength); VolumeLabelLength = 16; while((VolumeLabelLength > 0) && ((FFSSb->fs_volname[VolumeLabelLength-1] == 0x00) || (FFSSb->fs_volname[VolumeLabelLength-1] == 0x20))) { VolumeLabelLength--; } OemName.Buffer = FFSSb->fs_volname; OemName.MaximumLength = 16; OemName.Length = VolumeLabelLength; Status = FFSOEMToUnicode(&LabelName, &OemName); if (!NT_SUCCESS(Status)) { __leave; } Vpb->VolumeLabelLength = LabelName.Length; } Vpb->SerialNumber = ((ULONG*)FFSSb->fs_id)[0] + ((ULONG*)FFSSb->fs_id)[1] + ((ULONG*)FFSSb->fs_id)[2]; Vcb->StreamObj = IoCreateStreamFileObject(NULL, Vcb->Vpb->RealDevice); if (Vcb->StreamObj) { Vcb->StreamObj->SectionObjectPointer = &(Vcb->SectionObject); Vcb->StreamObj->Vpb = Vcb->Vpb; Vcb->StreamObj->ReadAccess = TRUE; if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) { Vcb->StreamObj->WriteAccess = TRUE; Vcb->StreamObj->DeleteAccess = TRUE; } else { Vcb->StreamObj->WriteAccess = TRUE; Vcb->StreamObj->DeleteAccess = TRUE; } Vcb->StreamObj->FsContext = (PVOID) Vcb; Vcb->StreamObj->FsContext2 = NULL; Vcb->StreamObj->Vpb = Vcb->Vpb; SetFlag(Vcb->StreamObj->Flags, FO_NO_INTERMEDIATE_BUFFERING); } else { __leave; } InitializeListHead(&Vcb->FcbList); InitializeListHead(&Vcb->NotifyList); FsRtlNotifyInitializeSync(&Vcb->NotifySync); NotifySyncInitialized = TRUE; Vcb->DeviceObject = VolumeDevice; Vcb->TargetDeviceObject = TargetDevice; Vcb->OpenFileHandleCount = 0; Vcb->ReferenceCount = 0; Vcb->ffs_super_block = FFSSb; Vcb->Header.NodeTypeCode = (USHORT) FFSVCB; Vcb->Header.NodeByteSize = sizeof(FFS_VCB); Vcb->Header.IsFastIoPossible = FastIoIsNotPossible; Vcb->Header.Resource = &(Vcb->MainResource); Vcb->Header.PagingIoResource = &(Vcb->PagingIoResource); Vcb->Vpb->SerialNumber = 'PS'; DiskSize = Vcb->DiskGeometry.Cylinders.QuadPart * Vcb->DiskGeometry.TracksPerCylinder * Vcb->DiskGeometry.SectorsPerTrack * Vcb->DiskGeometry.BytesPerSector; IoctlSize = sizeof(PARTITION_INFORMATION); Status = FFSDiskIoControl( TargetDevice, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &Vcb->PartitionInformation, &IoctlSize); PartSize = Vcb->PartitionInformation.PartitionLength.QuadPart; if (!NT_SUCCESS(Status)) { Vcb->PartitionInformation.StartingOffset.QuadPart = 0; Vcb->PartitionInformation.PartitionLength.QuadPart = DiskSize; PartSize = DiskSize; Status = STATUS_SUCCESS; } IoctlSize = sizeof(ULONG); Status = FFSDiskIoControl( TargetDevice, IOCTL_DISK_CHECK_VERIFY, NULL, 0, &ChangeCount, &IoctlSize); if (!NT_SUCCESS(Status)) { __leave; } Vcb->ChangeCount = ChangeCount; Vcb->Header.AllocationSize.QuadPart = Vcb->Header.FileSize.QuadPart = PartSize; Vcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff); /* Vcb->Header.AllocationSize.QuadPart = (LONGLONG)(ffs_super_block->s_blocks_count - ffs_super_block->s_free_blocks_count) * (FFS_MIN_BLOCK << ffs_super_block->s_log_block_size); Vcb->Header.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart; Vcb->Header.ValidDataLength.QuadPart = Vcb->Header.AllocationSize.QuadPart; */ { CC_FILE_SIZES FileSizes; FileSizes.AllocationSize.QuadPart = FileSizes.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart; FileSizes.ValidDataLength.QuadPart= (LONGLONG)(0x7fffffffffffffff); CcInitializeCacheMap(Vcb->StreamObj, &FileSizes, TRUE, &(FFSGlobal->CacheManagerNoOpCallbacks), Vcb); } #if 0 // LoadGroup XXX if (!FFSLoadGroup(Vcb)) { Status = STATUS_UNSUCCESSFUL; __leave; } #endif FsRtlInitializeLargeMcb(&(Vcb->DirtyMcbs), PagedPool); InitializeListHead(&(Vcb->McbList)); if (IsFlagOn(FFSGlobal->Flags, FFS_CHECKING_BITMAP)) { FFSCheckBitmapConsistency(IrpContext, Vcb); } { ULONG dwData[FFS_BLOCK_TYPES] = {NDADDR, 1, 1, 1}; ULONG dwMeta[FFS_BLOCK_TYPES] = {0, 0, 0, 0}; ULONG i; if (FS_VERSION == 1) { for (i = 0; i < FFS_BLOCK_TYPES; i++) { dwData[i] = dwData[i] << ((BLOCK_BITS - 2) * i); if (i > 0) { dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 2)); } Vcb->dwData[i] = dwData[i]; Vcb->dwMeta[i] = dwMeta[i]; } } else { for (i = 0; i < FFS_BLOCK_TYPES; i++) { dwData[i] = dwData[i] << ((BLOCK_BITS - 3) * i); if (i > 0) { dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 3)); } Vcb->dwData[i] = dwData[i]; Vcb->dwMeta[i] = dwMeta[i]; } } } SetFlag(Vcb->Flags, VCB_INITIALIZED); } __finally { if (!NT_SUCCESS(Status)) { if (NotifySyncInitialized) { FsRtlNotifyUninitializeSync(&Vcb->NotifySync); } if (Vcb->ffs_super_block) { ExFreePool(Vcb->ffs_super_block); Vcb->ffs_super_block = NULL; } if (VcbResourceInitialized) { ExDeleteResourceLite(&Vcb->MainResource); ExDeleteResourceLite(&Vcb->PagingIoResource); } } } return Status; }