363 lines
17 KiB
C
363 lines
17 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
Cvf.h
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module defines the Compressed Volume File (CVF) structure
|
|||
|
of the DblSpace file system.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Gary Kimura [GaryKi] 10-Jun-1993
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#ifndef _CVF_
|
|||
|
#define _CVF_
|
|||
|
|
|||
|
//
|
|||
|
// First DblSpace is simply fat with a few embelishments, so we'll start
|
|||
|
// with the fat on disk structure and add the DblSpace extensions
|
|||
|
//
|
|||
|
|
|||
|
#include "fat.h"
|
|||
|
|
|||
|
//
|
|||
|
// In DOS 6.0 a DblSpace disk is really just a regular FAT disk with
|
|||
|
// one big file named "DBLSPACE.nnn" which we'll also call the Compressed
|
|||
|
// Volume File (CVF). Everything needed by the DblSpace is stored
|
|||
|
// in this one file. In NT this means that DblSpace.sys can simply do
|
|||
|
// non-cached reads and writes of this file. In theory this file can
|
|||
|
// exist on FAT, HPFS, or NTFS partition and can be completely contiguous
|
|||
|
// or totally fragmented.
|
|||
|
//
|
|||
|
// For simplicity we'll shift of meaning of LBN/VBN from the usual
|
|||
|
// meaning. In DblSpace terminology an LBN/LBO will be the sector/byte
|
|||
|
// relative to the start of the CVF, and an VBN/VBO will be the sector/byte
|
|||
|
// relative to the start of a files stored within the CVF. DblSpace will
|
|||
|
// not need to deal with the actual location of data on the disk.
|
|||
|
//
|
|||
|
//
|
|||
|
// The global layout of the CVF is as follows:
|
|||
|
//
|
|||
|
// CVF_HEADER - Contains the BPB for the CVF, describes the maximum
|
|||
|
// capacity of the file and sorta gives the LBN for the other parts
|
|||
|
// within the CVF. Sorta meaning that the there is some computation
|
|||
|
// involved that involves the CVF file size.
|
|||
|
//
|
|||
|
// CVF_BITMAP - This is the bitmap for the "SectorHeap"
|
|||
|
//
|
|||
|
// CVF_RESERVED_AREA_1 - Reserved
|
|||
|
//
|
|||
|
// CVF_FAT_EXTENSIONS - This is a table with a 1-to-1 mapping against
|
|||
|
// the normal DOS FAT. Each entry in this table gives the location
|
|||
|
// of the FAT cluster within the CVF_HEAP, and indicates if the
|
|||
|
// data is compressed or uncompressed, and the size of the data in
|
|||
|
// both compressed and uncompressed form.
|
|||
|
//
|
|||
|
// CVF_RESERVED_AREA_2 - Reserved
|
|||
|
//
|
|||
|
// DOS_BOOT_SECTOR - This is a copy of the boot sector needed by DOS. It
|
|||
|
// is uncompressed, and not used by NT.
|
|||
|
//
|
|||
|
// CVF_RESERVED_AREA_3 - Reserved, contains a DblSpace signature.
|
|||
|
//
|
|||
|
// DOS_FAT - This is a normal FAT. It is uncompressed. There is only
|
|||
|
// one FAT per disk.
|
|||
|
//
|
|||
|
// DOS_ROOT_DIRECTORY - This is a standard FAT root directory. It is
|
|||
|
// uncompressed, and has space for exactly 512 entries.
|
|||
|
//
|
|||
|
// CVF_RESERVED_AREA_4 - Reserved
|
|||
|
//
|
|||
|
// CVF_HEAP - This is the storage location for the file data and
|
|||
|
// subdirectory data.
|
|||
|
//
|
|||
|
// CVF_RESERVED_AREA_5 - Reserved, contains a second DblSpace signature.
|
|||
|
//
|
|||
|
//
|
|||
|
//
|
|||
|
// Size and location of each CVF component:
|
|||
|
//
|
|||
|
// The size and location of the CVF_HEADER is fixed, everything else
|
|||
|
// is based up the information stored in the CVF_HEADER and the size of
|
|||
|
// CVF itself.
|
|||
|
//
|
|||
|
//
|
|||
|
// CVF_HEADER Lbn: 0x0
|
|||
|
// Allocation: 1 sector
|
|||
|
// Size: sizeof(CVF_HEADER)
|
|||
|
//
|
|||
|
// CVF_BITMAP Lbn: 0x1
|
|||
|
// Allocation: Capacity of CVF in sectors / 8 bits per byte
|
|||
|
// Size: 1 bit per CVF_HEAP sector rounded up to a byte
|
|||
|
//
|
|||
|
// CVF_RESERVED_AREA_1 Lbn: First sector after CVF_BITMAP
|
|||
|
// Allocation: 1 sector
|
|||
|
// Size: 0x0
|
|||
|
//
|
|||
|
// CVF_FAT_EXTENSIONS Lbn: Stored in CVF_HEADER
|
|||
|
// Allocation: Maximum clusters that the CVF can hold
|
|||
|
// Size: Maximum clusters in the DOS_FAT
|
|||
|
//
|
|||
|
// CVF_RESERVED_AREA_2 Lbn: First sector after CVF_FAT_EXTENSIONS
|
|||
|
// Allocation: 31 sectors
|
|||
|
// Size: 0x0
|
|||
|
//
|
|||
|
// DOS_BOOT_SECTOR Lbn: Stored in CVF_HEADER
|
|||
|
// Allocation: 1 sector
|
|||
|
// Size: 1 sector
|
|||
|
//
|
|||
|
// CVF_RESERVED_AREA_3 Lbn: First sector after DOS_BOOT_SECTOR
|
|||
|
// Allocation: Stored in CVF_HEADER
|
|||
|
// Size: 0
|
|||
|
//
|
|||
|
// DOS_FAT Lbn: First sector after CVF_RESERVED_AREA_3
|
|||
|
// Allocation: Stored in CVF_HEADER
|
|||
|
// Size: Stored in CVF_HEADER
|
|||
|
//
|
|||
|
// DOS_ROOT_DIRECTORY Lbn: Stored in CVF_HEADER
|
|||
|
// Allocation: Stored in CVF_HEADER (exactly 512 entries)
|
|||
|
// Size: Stored in CVF_HEADER (exactly 512 entries)
|
|||
|
//
|
|||
|
// CVF_RESERVED_AREA_4 Lbn: First sector after DOS_ROOT_DIRECTORY
|
|||
|
// Allocation: 2 sectors
|
|||
|
// Size: 0
|
|||
|
//
|
|||
|
// CVF_HEAP Lbn: First sector after CVF_RESERVED_AREA_4
|
|||
|
// Allocation: Based on CVF file size
|
|||
|
// Size: Based on CVF file size
|
|||
|
//
|
|||
|
// CVF_RESERVED_AREA_5 Lbn: Last full sector on the CVF
|
|||
|
// Allocation: 1 sector
|
|||
|
// Size: 0
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// The CVF HEADER is almost like a regular DOS boot. It contains a BPB
|
|||
|
// with DblSpace extensions
|
|||
|
//
|
|||
|
|
|||
|
typedef struct _PACKED_CVF_HEADER {
|
|||
|
|
|||
|
//
|
|||
|
// First a typical start of a boot sector
|
|||
|
//
|
|||
|
|
|||
|
UCHAR Jump[3]; // offset = 0x000 0
|
|||
|
UCHAR Oem[8]; // offset = 0x003 3
|
|||
|
PACKED_BIOS_PARAMETER_BLOCK PackedBpb; // offset = 0x00B 11
|
|||
|
|
|||
|
//
|
|||
|
// Now the DblSpace extensions
|
|||
|
//
|
|||
|
|
|||
|
UCHAR CvfFatExtensionsLbnMinus1[2]; // offset = 0x024 36
|
|||
|
UCHAR LogOfBytesPerSector[1]; // offset = 0x026 38
|
|||
|
UCHAR DosBootSectorLbn[2]; // offset = 0x027 39
|
|||
|
UCHAR DosRootDirectoryOffset[2]; // offset = 0x029 41
|
|||
|
UCHAR CvfHeapOffset[2]; // offset = 0x02B 43
|
|||
|
UCHAR CvfFatFirstDataEntry[2]; // offset = 0x02D 45
|
|||
|
UCHAR CvfBitmap2KSize[1]; // offset = 0x02F 47
|
|||
|
UCHAR Reserved1[2]; // offset = 0x030 48
|
|||
|
UCHAR LogOfSectorsPerCluster[1]; // offset = 0x032 50
|
|||
|
UCHAR Reserved2[2+4+4]; // offset = 0x033 51
|
|||
|
UCHAR Is12BitFat[1]; // offset = 0x03D 61
|
|||
|
UCHAR CvfMaximumCapacity[2]; // offset = 0x03E 62
|
|||
|
|
|||
|
} PACKED_CVF_HEADER; // sizeof = 0x040 64
|
|||
|
typedef PACKED_CVF_HEADER *PPACKED_CVF_HEADER;
|
|||
|
|
|||
|
//
|
|||
|
// For the unpacked version we'll only define the necessary field and skip
|
|||
|
// the jump and oem fields.
|
|||
|
//
|
|||
|
|
|||
|
typedef struct _CVF_HEADER {
|
|||
|
|
|||
|
BIOS_PARAMETER_BLOCK Bpb;
|
|||
|
|
|||
|
USHORT CvfFatExtensionsLbnMinus1;
|
|||
|
UCHAR LogOfBytesPerSector;
|
|||
|
USHORT DosBootSectorLbn;
|
|||
|
USHORT DosRootDirectoryOffset;
|
|||
|
USHORT CvfHeapOffset;
|
|||
|
USHORT CvfFatFirstDataEntry;
|
|||
|
UCHAR CvfBitmap2KSize;
|
|||
|
UCHAR LogOfSectorsPerCluster;
|
|||
|
UCHAR Is12BitFat;
|
|||
|
USHORT CvfMaximumCapacity;
|
|||
|
|
|||
|
} CVF_HEADER;
|
|||
|
typedef CVF_HEADER *PCVF_HEADER;
|
|||
|
|
|||
|
//
|
|||
|
// Here is NT's typical routine/macro to unpack the cvf header because DOS
|
|||
|
// doesn't bother to naturally align anything.
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// CvfUnpackCvfHeader (
|
|||
|
// IN OUT PCVF_HEADER UnpackedHeader,
|
|||
|
// IN PPACKED_CVF_HEADER PackedHeader
|
|||
|
// );
|
|||
|
//
|
|||
|
|
|||
|
#define CvfUnpackCvfHeader(UH,PH) { \
|
|||
|
FatUnpackBios( &(UH)->Bpb, &(PH)->PackedBpb ); \
|
|||
|
CopyUchar2( &(UH)->CvfFatExtensionsLbnMinus1, &(PH)->CvfFatExtensionsLbnMinus1[0] ); \
|
|||
|
CopyUchar1( &(UH)->LogOfBytesPerSector, &(PH)->LogOfBytesPerSector[0] ); \
|
|||
|
CopyUchar2( &(UH)->DosBootSectorLbn, &(PH)->DosBootSectorLbn[0] ); \
|
|||
|
CopyUchar2( &(UH)->DosRootDirectoryOffset, &(PH)->DosRootDirectoryOffset[0] ); \
|
|||
|
CopyUchar2( &(UH)->CvfHeapOffset, &(PH)->CvfHeapOffset[0] ); \
|
|||
|
CopyUchar2( &(UH)->CvfFatFirstDataEntry, &(PH)->CvfFatFirstDataEntry[0] ); \
|
|||
|
CopyUchar1( &(UH)->CvfBitmap2KSize, &(PH)->CvfBitmap2KSize[0] ); \
|
|||
|
CopyUchar1( &(UH)->LogOfSectorsPerCluster, &(PH)->LogOfSectorsPerCluster[0] ); \
|
|||
|
CopyUchar1( &(UH)->Is12BitFat, &(PH)->Is12BitFat[0] ); \
|
|||
|
CopyUchar2( &(UH)->CvfMaximumCapacity, &(PH)->CvfMaximumCapacity[0] ); \
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// The CVF FAT EXTENSIONS is a table is ULONG entries. Each entry corresponds
|
|||
|
// to a FAT cluster. The entries describe where in the CVF_HEAP to locate
|
|||
|
// the data for the cluster. It indicates if the data is compressed and the
|
|||
|
// length of the compressed and uncompressed form.
|
|||
|
//
|
|||
|
|
|||
|
typedef struct _CVF_FAT_EXTENSIONS {
|
|||
|
|
|||
|
ULONG CvfHeapLbnMinus1 : 21;
|
|||
|
ULONG Reserved : 1;
|
|||
|
ULONG CompressedSectorLengthMinus1 : 4;
|
|||
|
ULONG UncompressedSectorLengthMinus1 : 4;
|
|||
|
ULONG IsDataUncompressed : 1;
|
|||
|
ULONG IsEntryInUse : 1;
|
|||
|
|
|||
|
} CVF_FAT_EXTENSIONS;
|
|||
|
typedef CVF_FAT_EXTENSIONS *PCVF_FAT_EXTENSIONS;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// The following structure is not on the disk but will be used in-memory to
|
|||
|
// store the starting lbo, allocation, and size of each cvf component.
|
|||
|
//
|
|||
|
|
|||
|
typedef struct _COMPONENT_LOCATION {
|
|||
|
|
|||
|
LBO Lbo;
|
|||
|
ULONG Allocation;
|
|||
|
ULONG Size;
|
|||
|
|
|||
|
} COMPONENT_LOCATION;
|
|||
|
typedef COMPONENT_LOCATION *PCOMPONENT_LOCATION;
|
|||
|
|
|||
|
typedef struct _CVF_LAYOUT {
|
|||
|
|
|||
|
COMPONENT_LOCATION CvfHeader;
|
|||
|
COMPONENT_LOCATION CvfBitmap;
|
|||
|
COMPONENT_LOCATION CvfReservedArea1;
|
|||
|
COMPONENT_LOCATION CvfFatExtensions;
|
|||
|
COMPONENT_LOCATION CvfReservedArea2;
|
|||
|
COMPONENT_LOCATION DosBootSector;
|
|||
|
COMPONENT_LOCATION CvfReservedArea3;
|
|||
|
COMPONENT_LOCATION DosFat;
|
|||
|
COMPONENT_LOCATION DosRootDirectory;
|
|||
|
COMPONENT_LOCATION CvfReservedArea4;
|
|||
|
COMPONENT_LOCATION CvfHeap;
|
|||
|
COMPONENT_LOCATION CvfReservedArea5;
|
|||
|
|
|||
|
} CVF_LAYOUT;
|
|||
|
typedef CVF_LAYOUT *PCVF_LAYOUT;
|
|||
|
|
|||
|
//
|
|||
|
// Some sizes and fixed so we'll declare them as manifest constants
|
|||
|
//
|
|||
|
|
|||
|
#define CVF_RESERVED_AREA_1_SECTOR_SIZE (1)
|
|||
|
#define CVF_RESERVED_AREA_2_SECTOR_SIZE (31)
|
|||
|
#define CVF_RESERVED_AREA_4_SECTOR_SIZE (2)
|
|||
|
|
|||
|
//
|
|||
|
// The following macro is used to fill up the cvf layout structure. It takes
|
|||
|
// as input an unpacked cvf header and the size of the cvf, in bytes.
|
|||
|
//
|
|||
|
// VOID CvfLayout (
|
|||
|
// IN OUT PCVF_LAYOUT Layout,
|
|||
|
// IN PCVF_HEADER Header,
|
|||
|
// IN ULONG FileSize
|
|||
|
// );
|
|||
|
//
|
|||
|
|
|||
|
#define CvfLayout(L,H,F) { \
|
|||
|
\
|
|||
|
ULONG _bps = (H)->Bpb.BytesPerSector; \
|
|||
|
ULONG _Tc = (((H)->Bpb.Sectors + (H)->Bpb.LargeSectors) / (H)->Bpb.SectorsPerCluster); \
|
|||
|
\
|
|||
|
/* The Header and Ending Reserved Area are at fixed size and location */ \
|
|||
|
/* so we'll compute them first. Everything else is relative to the */ \
|
|||
|
/* header and ending reserved area */ \
|
|||
|
\
|
|||
|
(L)->CvfHeader.Lbo = 0; \
|
|||
|
(L)->CvfHeader.Allocation = _bps; \
|
|||
|
(L)->CvfHeader.Size = sizeof(CVF_HEADER); \
|
|||
|
\
|
|||
|
(L)->CvfReservedArea5.Lbo = ((F) & 0xfffffe00) - 0x200; \
|
|||
|
(L)->CvfReservedArea5.Allocation = 0x200; \
|
|||
|
(L)->CvfReservedArea5.Size = 0; \
|
|||
|
\
|
|||
|
(L)->CvfBitmap.Lbo = (L)->CvfHeader.Lbo + (L)->CvfHeader.Allocation; \
|
|||
|
(L)->CvfBitmap.Allocation = (H)->CvfBitmap2KSize * 2048; \
|
|||
|
\
|
|||
|
(L)->CvfReservedArea1.Lbo = (L)->CvfBitmap.Lbo + (L)->CvfBitmap.Allocation; \
|
|||
|
(L)->CvfReservedArea1.Allocation = CVF_RESERVED_AREA_1_SECTOR_SIZE * _bps; \
|
|||
|
(L)->CvfReservedArea1.Size = 0; \
|
|||
|
\
|
|||
|
(L)->CvfFatExtensions.Lbo = ((H)->CvfFatExtensionsLbnMinus1 + 1) * _bps; \
|
|||
|
(L)->CvfFatExtensions.Allocation = ((H)->DosBootSectorLbn * _bps) - \
|
|||
|
((L)->CvfHeader.Allocation) - \
|
|||
|
((L)->CvfBitmap.Allocation) - \
|
|||
|
(CVF_RESERVED_AREA_1_SECTOR_SIZE * _bps) - \
|
|||
|
(CVF_RESERVED_AREA_2_SECTOR_SIZE * _bps); \
|
|||
|
(L)->CvfFatExtensions.Size = _Tc * sizeof(CVF_FAT_EXTENSIONS); \
|
|||
|
\
|
|||
|
(L)->CvfReservedArea2.Lbo = (L)->CvfFatExtensions.Lbo + (L)->CvfFatExtensions.Allocation; \
|
|||
|
(L)->CvfReservedArea2.Allocation = CVF_RESERVED_AREA_2_SECTOR_SIZE * _bps; \
|
|||
|
(L)->CvfReservedArea2.Size = 0; \
|
|||
|
\
|
|||
|
(L)->DosBootSector.Lbo = (H)->DosBootSectorLbn * _bps; \
|
|||
|
(L)->DosBootSector.Allocation = _bps; \
|
|||
|
(L)->DosBootSector.Size = _bps; \
|
|||
|
\
|
|||
|
(L)->CvfReservedArea3.Lbo = (L)->DosBootSector.Lbo + (L)->DosBootSector.Allocation; \
|
|||
|
(L)->CvfReservedArea3.Allocation = ((H)->Bpb.ReservedSectors - 1) * _bps; \
|
|||
|
(L)->CvfReservedArea3.Size = 0; \
|
|||
|
\
|
|||
|
(L)->DosFat.Lbo = (L)->DosBootSector.Lbo + ((H)->Bpb.ReservedSectors * _bps); \
|
|||
|
(L)->DosFat.Allocation = (H)->Bpb.SectorsPerFat * _bps; \
|
|||
|
(L)->DosFat.Size = ((H)->Is12BitFat ? (_Tc * 3) / 2 : _Tc * 2); \
|
|||
|
\
|
|||
|
(L)->DosRootDirectory.Lbo = ((H)->DosRootDirectoryOffset + (H)->DosBootSectorLbn) * _bps; \
|
|||
|
(L)->DosRootDirectory.Allocation = (H)->Bpb.RootEntries * sizeof(DIRENT); \
|
|||
|
(L)->DosRootDirectory.Size = (L)->DosRootDirectory.Allocation; \
|
|||
|
\
|
|||
|
(L)->CvfReservedArea4.Lbo = (L)->DosRootDirectory.Lbo + (L)->DosRootDirectory.Allocation; \
|
|||
|
(L)->CvfReservedArea4.Allocation = CVF_RESERVED_AREA_4_SECTOR_SIZE * _bps; \
|
|||
|
(L)->CvfReservedArea4.Size = 0; \
|
|||
|
\
|
|||
|
(L)->CvfHeap.Lbo = (L)->CvfReservedArea4.Lbo + (L)->CvfReservedArea4.Allocation; \
|
|||
|
(L)->CvfHeap.Allocation = (L)->CvfReservedArea5.Lbo - (L)->CvfHeap.Lbo; \
|
|||
|
(L)->CvfHeap.Size = (L)->CvfHeap.Allocation; \
|
|||
|
\
|
|||
|
(L)->CvfBitmap.Size = (((L)->CvfHeap.Size / _bps) + 7) / 8; \
|
|||
|
}
|
|||
|
|
|||
|
#endif // _CVF_
|