Ejemplo n.º 1
0
Archivo: mcb.c Proyecto: GYGit/reactos
/*
 * @implemented
 */
VOID
NTAPI
FsRtlInitializeMcb(IN PMCB Mcb,
                   IN POOL_TYPE PoolType)
{
    /* Call the newer function */
    FsRtlInitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly,
                            PoolType);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}