Microsoft公司 .CAB文件格式
_Inside Windows Cabinet Files_
Listing One
// =================================================================
// CAB FILE LAYOUT
// =================================================================
/*
(1) CAB_HEADER structure
(2) Reserved area, if CAB_HEADER.flags & CAB_FLAG_RESERVE
(3) Previous cabinet name, if CAB_HEADER.flags & CAB_FLAG_HASPREV
(4) Previous disk name, if CAB_HEADER.flags & CAB_FLAG_HASPREV
(5) Next cabinet name, if CAB_HEADER.flags & CAB_FLAG_HASNEXT
(6) Next disk name, if CAB_HEADER.flags & CAB_FLAG_HASNEXT
(7) CAB_FOLDER structures (n = CAB_HEADER.cFolders)
(8) CAB_ENTRY structures / file names (n = CAB_HEADER.cFiles)
(9) File data (offset = CAB_FOLDER.coffCabStart)
*/
// =================================================================
// MACROS
// =================================================================
#define SWAPWORD(x) ((WORD) (((x) << 8) | ((x) >> 8)))
#define SWAPDWORD(x) ((SWAPWORD ((WORD) (x)) << 16) | (SWAPWORD ((WORD) ((x) >> 16))))
// =================================================================
// CONSTANTS
// =================================================================
#define CAB_SIGNATURE SWAPDWORD ('MSCF')
#define CAB_VERSION 0x0103
#define CAB_FLAG_HASPREV 0x0001
#define CAB_FLAG_HASNEXT 0x0002
#define CAB_FLAG_RESERVE 0x0004
#define CAB_ATTRIB_READONLY 0x0001
#define CAB_ATTRIB_HIDDEN 0x0002
#define CAB_ATTRIB_SYSTEM 0x0004
#define CAB_ATTRIB_VOLUME 0x0008
#define CAB_ATTRIB_DIRECTORY 0x0010
#define CAB_ATTRIB_ARCHIVE 0x0020
#define CAB_FILE_FIRST 0x0000
#define CAB_FILE_NEXT 0x0001
#define CAB_FILE_SPLIT 0xFFFE
#define CAB_FILE_CONTINUED 0xFFFD
#define CAB_NOTIFY_OK 1
#define CAB_NOTIFY_ERROR 0
#define CAB_NOTIFY_SKIP 0
#define CAB_NOTIFY_ABORT (-1)
// =================================================================
// CABINET STRUCTURES
// =================================================================
typedef struct _CAB_HEADER
{
DWORD sig; // file signature 'MSCF' (CAB_SIGNATURE)
DWORD csumHeader; // header checksum (0 if not used)
DWORD cbCabinet; // cabinet file size
DWORD csumFolders; // folders checksum (0 if not used)
DWORD coffFiles; // offset of first CAB_ENTRY
DWORD csumFiles; // files checksum (0 if not used)
WORD version; // cabinet version (CAB_VERSION)
WORD cFolders; // number of folders
WORD cFiles; // number of files
WORD flags; // cabinet flags (CAB_FLAG_*)
WORD setID; // cabinet set id
WORD iCabinet; // zero-based cabinet number
}
CAB_HEADER, *PCAB_HEADER;
#define CAB_HEADER_ sizeof (CAB_HEADER)
// -----------------------------------------------------------------
typedef struct _CAB_FOLDER
{
DWORD coffCabStart; // offset of folder data
WORD cCFData; // ???
WORD typeCompress; // compression type (tcomp* in FDI.h)
}
CAB_FOLDER, *PCAB_FOLDER;
#define CAB_FOLDER_ sizeof (CAB_FOLDER)
// -----------------------------------------------------------------
typedef struct _CAB_ENTRY
{
DWORD cbFile; // uncompressed file size
DWORD uoffFolderStart; // file offset after decompression
WORD iFolder; // file control id (CAB_FILE_*)
WORD date; // file date stamp, as used by DOS
WORD time; // file time stamp, as used by DOS
WORD attribs; // file attributes (CAB_ATTRIB_*)
}
CAB_ENTRY, *PCAB_ENTRY;
#define CAB_ENTRY_ sizeof (CAB_ENTRY)
Listing Two
// =================================================================
// FILE EXTRACTION CALLBACK
// =================================================================
int DIAMONDAPI FDIExtract (FDINOTIFICATIONTYPE fdint,
PFDINOTIFICATION pfdin)
{
FILETIME ft, lft;
BYTE abFile [MAX_PATH];
int hf, iResult;
switch (fdint)
{
case fdintCOPY_FILE:
if (lstrcmpi (pfdin->psz1,
((PEXTRACT_FILE) pfdin->pv)->pbEntry))
{
iResult = CAB_NOTIFY_SKIP;
}
else
{
hf = FDIOpen (((PEXTRACT_FILE) pfdin->pv)->pbFile,
_O_RDWR | _O_CREAT | _O_TRUNC,
_S_IREAD | _S_IWRITE);
if (hf != -1)
{
iResult = hf;
}
else
{
printfMessage
(((PEXTRACT_FILE) pfdin->pv)->hWnd,
MB_ICONERROR | MB_OK,
"CabLib Error",
"Unable to create file \"%s\"",
((PEXTRACT_FILE) pfdin->pv)->pbFile);
iResult = CAB_NOTIFY_ABORT;
}
}
break;
case fdintNEXT_CABINET:
if (lstrlen (pfdin->psz3) + lstrlen (pfdin->psz1)
< MAX_PATH)
{
lstrcpy (abFile, pfdin->psz3);
lstrcat (abFile, pfdin->psz1);
hf = FDIOpen (abFile, _O_RDONLY, 0);
}
else
{
hf = -1;
}
if (hf != -1)
{
FDIClose (hf);
iResult = CAB_NOTIFY_OK;
}
else
{
printfMessage (((PEXTRACT_FILE) pfdin->pv)->hWnd,
MB_ICONERROR | MB_OK,
"CabLib Error",
"Unable to open file \"%s%s\"",
pfdin->psz3,
pfdin->psz1);
iResult = CAB_NOTIFY_ABORT;
}
break;
case fdintCLOSE_FILE_INFO:
DosDateTimeToFileTime (pfdin->date, pfdin->time, &lft);
LocalFileTimeToFileTime (&lft, &ft);
SetFileTime ((HANDLE) pfdin->hf, &ft, &ft, &ft);
if (FDIClose (pfdin->hf) == -1)
{
printfMessage (((PEXTRACT_FILE) pfdin->pv)->hWnd,
MB_ICONERROR | MB_OK,
"CabLib Error",
"Unable to close file \"%s\"",
((PEXTRACT_FILE) pfdin->pv)->pbFile);
}
iResult = CAB_NOTIFY_OK;
break;
default:
iResult = CAB_NOTIFY_OK;
break;
}
return iResult;
}
Example 1:
HFDI FAR DIAMONDAPI FDICreate (PFNALLOC pfnalloc,
PFNFREE pfnfree,
PFNOPEN pfnopen,
PFNREAD pfnread,
PFNWRITE pfnwrite,
PFNCLOSE pfnclose,
PFNSEEK pfnseek,
int cpuType,
PERF perf);
Example 2:
BOOL FAR DIAMONDAPI FDICopy (HFDI hfdi,
char FAR *pszCabinet,
char FAR *pszCabPath,
int flags,
PFNFDINOTIFY pfnfdin,
PFNFDIDECRYPT pfnfdid,
void FAR *pvUser);
4