1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
cvf.hxx
Abstract:
This module contains basic declarations and definitions for
the double-space file system format. Note that more extensive
description of the file system structures may be found in
ntos\fastfat\cvf.h
Author:
Bill McJohn [BillMc] 24-September-1993
Revision History:
--*/
#if !defined( _UFATDB_DEFN_ )
#define _UFATDB_DEFN_
#include "bpb.hxx"
// Manifest constants for fixed values on a Double Space drive:
//
CONST DoubleSpaceBytesPerSector = 512;
CONST DoubleSpaceLog2BytesPerSector = 9;
CONST DoubleSpaceSectorsPerCluster = 16;
CONST DoubleSpaceLog2SectorsPerCluster = 4;
CONST DoubleSpaceReservedSectors = 16;
CONST DoubleSpaceFats = 1;
CONST DoubleSpaceSectorsInRootDir = 32;
CONST DoubleSpaceRootEntries = 512;
CONST DoubleSpaceMediaByte = 0xf8;
CONST DoubleSpaceSectorsPerTrack = 0x11;
CONST DoubleSpaceHeads = 6;
CONST DoubleSpaceHiddenSectors = 0;
CONST DoubleSpaceReservedSectors2 = 31;
CONST DSBytesPerBitmapPage = 2048;
CONST DSSectorsPerBitmapPage = 4;
CONST ULONG EIGHT_MEG = 8 * 1024L * 1024L;
CONST DbSignatureLength = 4;
CONST UCHAR FirstDbSignature[DbSignatureLength] = { (UCHAR)0xf8, 'D', 'R', 0 };
CONST UCHAR SecondDbSignature[DbSignatureLength] = "MDR";
INLINE
ULONG
ComputeMaximumCapacity(
IN ULONG HostDriveSize
)
/*++
Routine Description:
This function computes the maximum capacity for a compressed
volume file on a host volume of a given size.
Arguments:
HostDriveSize -- Supplies the size in bytes of the host drive.
Return Value:
The appropriate Maximum Capacity.
--*/
{
ULONG MaxCap;
if( HostDriveSize < 20 * 1024L * 1024L ) {
MaxCap = 16 * HostDriveSize;
} else if ( HostDriveSize < 64 * 1024L * 1024L ) {
MaxCap = 8 * HostDriveSize;
} else {
MaxCap = 4 * HostDriveSize;
}
if( MaxCap < 4 * 1024L * 1024L ) {
MaxCap = 4 * 1024L * 1024L;
} else if( MaxCap > 512 * 1024L * 1024L ) {
MaxCap = 512 * 1024L * 1024L;
}
return MaxCap;
}
typedef struct _PACKED_CVF_HEADER {
//
// First a typical start of a boot sector
//
UCHAR Jump[1]; // offset = 0x000 0
UCHAR JmpOffset[2];
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]; // offset = 0x033
UCHAR MinFile[4]; // offset = 0x035
UCHAR Reserved3[4]; // offset = 0x039
UCHAR Is12BitFat[1]; // offset = 0x03D 61
UCHAR CvfMaximumCapacity[2]; // offset = 0x03E 62
UCHAR StartBootCode;
} 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 {
UCHAR Jump;
USHORT JmpOffset;
UCHAR Oem[8];
BIOS_PARAMETER_BLOCK Bpb;
USHORT CvfFatExtensionsLbnMinus1;
UCHAR LogOfBytesPerSector;
USHORT DosBootSectorLbn;
USHORT DosRootDirectoryOffset;
USHORT CvfHeapOffset;
USHORT CvfFatFirstDataEntry;
UCHAR CvfBitmap2KSize;
UCHAR LogOfSectorsPerCluster;
UCHAR Is12BitFat;
ULONG MinFile;
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) { \
\
memcpy( &(UH)->Jump, &(PH)->Jump, 1 ); \
memcpy( &(UH)->JmpOffset, &(PH)->JmpOffset, 2 ); \
memcpy( &(UH)->Oem, &(PH)->Oem, 8 ); \
UnpackBios( &(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] ); \
CopyUchar4( &(UH)->MinFile, &(PH)->MinFile[0] ); \
CopyUchar2( &(UH)->CvfMaximumCapacity, &(PH)->CvfMaximumCapacity[0] ); \
}
#define CvfPackCvfHeader(PH,UH) { \
\
memcpy( &(PH)->Jump, &(UH)->Jump, 1 ); \
memcpy( &(PH)->JmpOffset, &(UH)->JmpOffset, 2 ); \
memcpy( &(PH)->Oem, &(UH)->Oem, 8 ); \
PackBios( &(UH)->Bpb, &(PH)->PackedBpb, ); \
CopyUchar2( (PH)->CvfFatExtensionsLbnMinus1, &(UH)->CvfFatExtensionsLbnMinus1 ); \
CopyUchar1( (PH)->LogOfBytesPerSector, &(UH)->LogOfBytesPerSector ); \
CopyUchar2( (PH)->DosBootSectorLbn, &(UH)->DosBootSectorLbn ); \
CopyUchar2( (PH)->DosRootDirectoryOffset, &(UH)->DosRootDirectoryOffset ); \
CopyUchar2( (PH)->CvfHeapOffset, &(UH)->CvfHeapOffset ); \
CopyUchar2( (PH)->CvfFatFirstDataEntry, &(UH)->CvfFatFirstDataEntry ); \
CopyUchar1( (PH)->CvfBitmap2KSize, &(UH)->CvfBitmap2KSize ); \
CopyUchar1( (PH)->LogOfSectorsPerCluster, &(UH)->LogOfSectorsPerCluster ); \
CopyUchar1( (PH)->Is12BitFat, &(UH)->Is12BitFat ); \
CopyUchar4( (PH)->MinFile, &(UH)->MinFile ); \
CopyUchar2( (PH)->CvfMaximumCapacity, &(UH)->CvfMaximumCapacity ); \
memset( (PH)->Reserved1, 0, 2 ); \
memset( (PH)->Reserved2, 0, 2 ); \
memset( (PH)->Reserved3, 0, 4 ); \
}
//
// 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;
//
// Some sizes are fixed so we'll declare them as manifest constants
//
#define CVF_MINIMUM_DISK_SIZE (512 * 1024L)
#define CVF_FATFAILSAFE (1024L)
#define CVF_MIN_HEAP_SECTORS (60)
#define CVF_RESERVED_AREA_1_SECTOR_SIZE (1)
#define CVF_RESERVED_AREA_2_SECTOR_SIZE (31)
#define CVF_RESERVED_AREA_4_SECTOR_SIZE (2)
#endif // _UFATDB_DEFN_
|