windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/pkitrust/mssip32/cabinet.h
2020-09-26 16:20:57 +08:00

407 lines
17 KiB
C

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: cabinet.h
//
//--------------------------------------------------------------------------
/*** cabinet.h - Definitions for Cabinet File structure
*
* Author:
* Benjamin W. Slivka
*
* History:
* 15-Aug-1993 bens Initial version
* 05-Sep-1993 bens Added Overview section
* 29-Nov-1993 chuckst Added disk names to folder first & next
* Used "CF" consistently
* Eliminated redundant cch fields
* 09-Feb-1994 chuckst merged in some related global constants
* 09-Mar-1994 bens Add RESERVE defintions (for encryption)
* 17-Mar-1994 bens Improve comments about split CFDATA structures
* 25-Mar-1994 bens Add cabinet set ID
* 13-May-1994 bens Define bad value for iCabinet
* 15-Jun-1997 pberkman added CABSignatureStruct_
*
* Overview:
* This file contains definitions for the Diamond Cabinet File format.
* A Cabinet File exists to store one or more files. Usually these
* files have been compressed, but that is not required. It is also
* possible for a cabinet file to contain only a portion of a larger
* file.
*
* In designing this format, the following goals where achieved:
* 1) Minimize overhead in the CF format
* ==> Where ever possible BYTEs or USHORTs were used, rather
* than using LONGs, even though the latter would be easier
* to manipulate on certain RISC platforms.
* 2) Support little-endian and big-endian byte ordering.
* ==> For simplicity on x86 systems, multi-byte numbers are
* stored in a little-endian form, but the code to read and
* write these numbers operates correctly on either type of
* computer.
*
* A cabinet file contains the following structures in the following
* order:
* Name Description
* ----------- -------------------
* CFHEADER Cabinet description
* [CFRESERVE] Optional RESERVED control information in CFHEADER
* CFFOLDER(s) Folder descriptions
* [reserved] Optional RESERVED data per folder
* CFFILE(s) File descriptions
* CFDATA(s) Data blocks
* [reserved] Optional RESERVED data per data block
*
* Data Integrity Strategy:
* The Cabinet File has built-in data integrity checks, since it is
* possible for customers to have damaged diskettes, or for accidental
* or malicious damage to occur. Rather than doing an individual
* checksum for the entire cabinet file (which would have a dramatic
* impact on the speed of installation from floppy disk, since the
* entire file would need to be read), we have per-component
* checksums, and compute and check them as we read the various
* components of the file.
*
* 1) Checksum CFHEADER
* 2) Store cabinet file length in CFHEADER (to detect file truncation)
* 3) Checksum entire set of CFFOLDER structures
* 4) Checksum entire set of CFFILE structures
* 5) Checksum each (compressed) data block independantly
*
* This approach allows us to avoid reading unnecessary parts of the
* file cabinet (though reading all of CFFOLDER and CFFILE structures
* would otherwise not be required in all cases), while still providing
* adequate integrity checking.
*/
#ifndef INCLUDED_CABINET
#define INCLUDED_CABINET 1
typedef unsigned long CHECKSUM;
typedef unsigned long COFF;
typedef unsigned long UOFF;
//** Pack structures tightly in cabinet files!
#pragma pack(1)
/*** verCF - Cabinet File format version
*
* The low-order byte is interpreted as a decimal number for the minor
* (1/100ths) portion of the version number.
* The high-order byte is interpreted as a decimal number for the major
* portion of the version number.
*
* Examples:
* 0x0000 0.00
* 0x010A 1.10
* 0x0410 4.16
*
* History:
* 1.01 Original
* 1.02 Added flags field, changed signature
* 1.03 Added setId,iCabinet so FDI can ensure correct cabinet
* on continuation.
*/
#define verCF 0x0103 // CF version 1.03
/*** Various cabinet file limits
*
*/
#define cMAX_FOLDERS_PER_CABINET (ifoldMASK-1)
#define cMAX_FILES_PER_CABINET 65535
/*** cbRESERVE_XXX_MAX - Maximum size of RESERVE sections
*
* NOTE: cbRESERVE_HEADER_MAX is a fair bit less than 64K because in
* the 16-bit version of this code, we want to have a USHORT
* variable that holds the size of the CFHEADER structure +
* the size of the CFRESERVE structure + the size of the per-header
* reserved data.
*/
#define cbRESERVE_HEADER_MAX 60000 // Fits in a USHORT
#define cbRESERVE_FOLDER_MAX 255 // Fits in a BYTE
#define cbRESERVE_DATA_MAX 255 // Fits in a BYTE
/*** ifoldXXXX - Special values for CFFILE.iFolder
*
*/
#define ifoldMASK 0xFFFC // Low two bits zero
#define ifoldCONTINUED_FROM_PREV 0xFFFD
#define ifoldCONTINUED_TO_NEXT 0xFFFE
#define ifoldCONTINUED_PREV_AND_NEXT 0xFFFF
#define IS_CONTD_FORWARD(ifold) ((ifold & 0xfffe) == ifoldCONTINUED_TO_NEXT)
#define IS_CONTD_BACK(ifold) ((ifold & 0xfffd) == ifoldCONTINUED_FROM_PREV)
#ifndef MAKESIG
/*** MAKESIG - Construct a 4 byte signature
*
* Entry:
* ch1,ch2,ch3,ch4 - four characters
*
* Exit:
* returns unsigned long
*/
#define MAKESIG(ch1,ch2,ch3,ch4) \
( ((unsigned long)ch1) + \
(((unsigned long)ch2)<< 8) + \
(((unsigned long)ch3)<<16) + \
(((unsigned long)ch4)<<24) )
#endif // !MAKESIG
#define sigCFHEADER MAKESIG('M','S','C','F') // CFHEADER signature
/*** cfhdrXXX - bit flags for cfheader.flags field
*
*/
#define cfhdrPREV_CABINET 0x0001 // Set if previous cab/disk present
#define cfhdrNEXT_CABINET 0x0002 // Set if next cab/disk present
#define cfhdrRESERVE_PRESENT 0x0004 // Set if RESERVE_CONTROL is present
/*** CFHEADER - Cabinet File Header
*
*/
typedef struct {
//** LONGs are first, to ensure alignment
long sig; // Cabinet File identification string
CHECKSUM csumHeader; // Structure checksum (excluding csumHeader!)
long cbCabinet; // Total length of file (consistency check)
CHECKSUM csumFolders; // Checksum of CFFOLDER list
COFF coffFiles; // Location in cabinet file of CFFILE list
CHECKSUM csumFiles; // Checksum of CFFILE list
//** SHORTs are next, to ensure alignment
USHORT version; // Cabinet File version (verCF)
USHORT cFolders; // Count of folders (CFIFOLDERs) in cabinet
USHORT cFiles; // Count of files (CFIFILEs) in cabinet
USHORT flags; // Flags to indicate optional data presence
USHORT setID; // Cabinet set ID (identifies set of cabinets)
USHORT iCabinet; // Cabinet number in set (0 based)
#define iCABINET_BAD 0xFFFF // Illegal number for iCabinet
//** If flags has the cfhdrRESERVE_PRESENT bit set, then a CFRESERVE
// structure appears here, followed possibly by some CFHEADER reserved
// space. The CFRESERVE structure has fields to define how much reserved
// space is present in the CFHEADER, CFFOLDER, and CFDATA structures.
// If CFRESERVE.cbCFHeader is non-zero, then abReserve[] immediately
// follows the CFRESERVE structure. Note that all of these sizes are
// multiples of 4 bytes, to ensure structure alignment!
//
// CFRESERVE cfres; // Reserve information
// BYTE abReserve[]; // Reserved data space
//
//** The following fields presence depends upon the settings in the flags
// field above. If cfhdrPREV_CABINET is set, then there are two ASCIIZ
// strings to describe the previous disk and cabinet.
//
// NOTE: This "previous" cabinet is not necessarily the immediately
// preceding cabinet! While it usually will be, if a file is
// continued into the current cabinet, then the "previous"
// cabinet identifies the cabinet where the folder that contains
// this file *starts*! For example, if EXCEL.EXE starts in
// cabinet excel.1 and is continued through excel.2 to excel.3,
// then cabinet excel.3 will point back to *cabinet.1*, since
// that is where you have to start in order to extract EXCEL.EXE.
//
// char szCabinetPrev[]; // Prev Cabinet filespec
// char szDiskPrev[]; // Prev descriptive disk name
//
// Similarly, If cfhdrNEXT_CABINET is set, then there are two ASCIIZ
// strings to describe the next disk and cabinet:
//
// char szCabinetNext[]; // Next Cabinet filespec
// char szDiskNext[]; // Next descriptive disk name
//
} CFHEADER; /* cfheader */
/*** CFRESERVE - Cabinet File Reserved data information
*
* This structure is present in the middle of the CFHEADER structure if
* CFHEADER.flags has the cfhdrRESERVE_PRESENT bit set. This structure
* defines the sizes of all the reserved data sections in the CFHEADER,
* CFFOLDER, and CFDATA structures.
*
* These reserved sizes can be zero (although it would be strange to have
* all of them be zero), but otherwise must be a multiple of 4, to ensure
* structure alignment for RISC machines.
*/
typedef struct {
USHORT cbCFHeader; // Size of abReserve in CFHEADER structure
BYTE cbCFFolder; // Size of abReserve in CFFOLDER structure
BYTE cbCFData; // Size of abReserve in CFDATA structure
} CFRESERVE; /* cfreserve */
#define cbCF_HEADER_BAD 0xFFFF // Bad value for CFRESERVE.cbCFHeader
//
// the following struct identifies the content of the signature area
// of abReserved for Athenticode version 2.
//
typedef struct CABSignatureStruct_
{
DWORD cbFileOffset;
DWORD cbSig;
BYTE Filler[8];
} CABSignatureStruct_;
/*** CFFOLDER - Cabinet Folder
*
* This structure describes a partial or complete "compression unit".
* A folder is by definition a stream of compressed data. To retrieve
* an uncompressed data from a folder, you *must* start decompressing
* the data at the start of the folder, regardless of how far into the
* folder the data you want actually starts.
*
* Folders may start in one cabinet, and continue on to one or more
* succeeding cabinets. In general, if a folder has been continued over
* a cabinet boundary, Diamond/FCI will terminate that folder as soon as
* the current file has been completely compressed. Generally this means
* that a folder would span at most two cabinets, but if the file is really
* large, it could span more than two cabinets.
*
* Note: CFFOLDERs actually refer to folder *fragments*, not necessarily
* complete folders. You know that a CFFOLDER is the beginning of a
* folder (as opposed to a continuation in a subsequent cabinet file)
* if a file starts in it (i.e., the CFFILE.uoffFolderStart field is
* 0).
*/
typedef struct {
COFF coffCabStart; // Offset in cabinet file of first CFDATA
// block for this folder.
USHORT cCFData; // Count of CFDATAs for this folder that
// are actually in this cabinet. Note that
// a folder can continue into another cabinet
// and have many more CFDATA blocks in that
// cabinet, *and* a folder may have started
// in a previous cabinet. This count is
// only of CFDATAs for this folder that are
// (at least partially) in this cabinet.
short typeCompress; // Indicates compression type for all CFDATA
// blocks for this folder. The valid values
// are defined in the types.h built into
// fci.h/fdi.h.
//** If CFHEADER.flags has the cfhdrRESERVE_PRESENT bit set, and
// CFRESERVE.cbCFFolder is non-zero, then abReserve[] appears here.
//
// BYTE abReserve[]; // Reserved data space
//
} CFFOLDER; /* cffolder */
/*** CFFILE - Cabinet File structure describing a single file in the cabinet
*
* NOTE: iFolder is used to indicatate continuation cases, so we have to
* calculate the real iFolder by examining the cabinet files:
*
* ifoldCONTINUED_FROM_PREV
* This file ends in this cabinet, but is continued from a
* previous cabinet. Therefore, the portion of the file contained
* in *this* cabinet *must* start in the first folder.
*
* NOTE: szCabinetPrev is the name of the cabinet where this file
* *starts*, which is not necessarily the immediately
* preceeding cabinet! Since it only makes sense to
* decompress a file from its start, the starting cabinet
* is what is important!
*
* ifoldCONTINUED_TO_NEXT
* This file starts in this cabinet, but is continued to the next
* cabinet. Therfore, this file must start in the *last* folder
* in this cabinet.
*
* ifoldCONTINUED_PREV_AND_NEXT
* This file is the *middle* portion of a file that started in a
* previous cabinet and is continued in the next cabinet. Since
* this cabinet only contain this piece of a single file, there
* is only a single folder fragment in this cabinet.
*/
typedef struct {
long cbFile; // Uncompressed size of file
UOFF uoffFolderStart; // Offset in folder IN UNCOMPRESSED BYTES
// of the start of this file
USHORT iFolder; // Index of folder containing this file;
// 0 is first folder in this cabinet.
// See ifoldCONTINUED_XXXX values above
// for treatment of continuation files.
USHORT date; // Date stamp in FAT file system format
USHORT time; // Time stamp in FAT file system format
USHORT attribs; // Attribute in FAT file system format
// char szName[]; // File name (may include path characters)
} CFFILE; /* cffile */
/*** CFDATA - Cabinet File structure describing a data block
*
*/
typedef struct {
CHECKSUM csum; // Checksum (excluding this field itself!)
// of this structure and the data that
// follows. If this CFDATA structure is
// continued to the next cabinet, then
// the value of this field is ignored
// (and set to zero).
USHORT cbData; // Size of ab[] data that resides in the
// current cabinet. A CFDATA may be split
// across a cabinet boundary, so this
// value indicates only the amount of data
// store in this cabinet.
USHORT cbUncomp; // Uncompressed size of ab[] data; if this
// CFDATA block is continued to the next
// cabinet, then this value is zero!
// If this CFDATA block the remainder of
// of a CFDATA block that started in the
// previous cabinet, then this value is
// the total size of the uncompressed data
// represented by the two CFDATA blocks!
//** If CFHEADER.flags has the cfhdrRESERVE_PRESENT bit set, and
// CFRESERVE.cbCFData is non-zero, then abReserve[] appears here.
//
// BYTE abReserve[]; // Reserved data space
//
//** The actual data follows here, cbData bytes in length.
//
// BYTE ab[]; // Data
//
} CFDATA; /* cfdata */
//** Attribute Bit to use for Run after extract
#define RUNATTRIB 0x40
//** Revert to default structure packing!
#pragma pack()
#endif // !INCLUDED_CABINET