Ejemplo n.º 1
0
        public bool VirtualToLogicalDriveOffset(ulong virtualOffset, out ulong logicalOffset)
        {
            logicalOffset = 0;

            if (virtualOffset >= Header.DriveSize)
            {
                throw new InvalidOperationException(
                          $"Virtual offset 0x{virtualOffset:X} is outside drivedata length 0x{Header.DriveSize:X}");
            }
            if (Header.Type > XvdType.Dynamic)
            {
                throw new NotSupportedException($"Xvd type {Header.Type} is unhandled");
            }


            if (Header.Type == XvdType.Dynamic)
            {
                var dataStartOffset  = virtualOffset + XvdMath.PageNumberToOffset(Header.NumberOfMetadataPages);
                var pageNumber       = XvdMath.OffsetToPageNumber(dataStartOffset);
                var inBlockOffset    = XvdMath.InBlockOffset(dataStartOffset);
                var firstDynamicPage = XvdMath.QueryFirstDynamicPage(Header.NumberOfMetadataPages);

                if (pageNumber >= firstDynamicPage)
                {
                    var   firstDynamicPageBytes = XvdMath.PageNumberToOffset(firstDynamicPage);
                    var   blockNumber           = XvdMath.OffsetToBlockNumber(dataStartOffset - firstDynamicPageBytes);
                    ulong allocatedBlock        = ReadBat(blockNumber);
                    if (allocatedBlock == INVALID_SECTOR)
                    {
                        return(false);
                    }

                    dataStartOffset = XvdMath.PageNumberToOffset(allocatedBlock) + inBlockOffset;
                    pageNumber      = XvdMath.OffsetToPageNumber(dataStartOffset);
                }

                var dataBackingBlockNum = XvdMath.ComputeDataBackingPageNumber(Header.Type,
                                                                               HashTreeLevels,
                                                                               HashTreePageCount,
                                                                               pageNumber);
                logicalOffset  = XvdMath.PageNumberToOffset(dataBackingBlockNum);
                logicalOffset += XvdMath.InPageOffset(dataStartOffset);
                logicalOffset += XvdMath.PageNumberToOffset(Header.EmbeddedXvdPageCount);
                logicalOffset += Header.MutableDataLength;
                logicalOffset += XVD_HEADER_INCL_SIGNATURE_SIZE;
                logicalOffset += PAGE_SIZE;
            }
            else
            { // Xvd type fixed
                logicalOffset  = virtualOffset;
                logicalOffset += XvdMath.PageNumberToOffset(Header.EmbeddedXvdPageCount);
                logicalOffset += Header.MutableDataLength;
                logicalOffset += XvdMath.PageNumberToOffset(Header.NumberOfMetadataPages);
                logicalOffset += XVD_HEADER_INCL_SIGNATURE_SIZE;
                logicalOffset += PAGE_SIZE;
            }

            return(true);
        }