2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS cabinet manager
4 * FILE: apps/cabman/cabinet.h
5 * PURPOSE: Cabinet definitions
16 #define NORMAL_MASK 0x000000FF
17 #define SPECIAL_MASK 0xFFFFFF00
18 #define MIN_TRACE 0x00000001
19 #define MID_TRACE 0x00000002
20 #define MAX_TRACE 0x00000003
22 #define DEBUG_MEMORY 0x00000100
26 extern DWORD DebugTraceLevel;
28 #define DPRINT(_t_, _x_) \
29 if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \
30 ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \
31 printf("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \
35 #define ASSERT(_b_) { \
37 printf("(%s:%d)(%s) ASSERTION: ", __FILE__, __LINE__, __FUNCTION__); \
45 #define DPRINT(_t_, _x_)
55 #define CopyMemory(destination, source, length) memcpy(destination, source, length)
56 #endif /* CopyMemory */
58 /* Cabinet constants */
60 #define CAB_SIGNATURE 0x4643534D // "MSCF"
61 #define CAB_VERSION 0x0103
62 #define CAB_BLOCKSIZE 32768
64 #define CAB_COMP_MASK 0x00FF
65 #define CAB_COMP_NONE 0x0000
66 #define CAB_COMP_MSZIP 0x0001
67 #define CAB_COMP_QUANTUM 0x0002
68 #define CAB_COMP_LZX 0x0003
70 #define CAB_FLAG_HASPREV 0x0001
71 #define CAB_FLAG_HASNEXT 0x0002
72 #define CAB_FLAG_RESERVE 0x0004
74 #define CAB_ATTRIB_READONLY 0x0001
75 #define CAB_ATTRIB_HIDDEN 0x0002
76 #define CAB_ATTRIB_SYSTEM 0x0004
77 #define CAB_ATTRIB_VOLUME 0x0008
78 #define CAB_ATTRIB_DIRECTORY 0x0010
79 #define CAB_ATTRIB_ARCHIVE 0x0020
80 #define CAB_ATTRIB_EXECUTE 0x0040
81 #define CAB_ATTRIB_UTF_NAME 0x0080
83 #define CAB_FILE_MAX_FOLDER 0xFFFC
84 #define CAB_FILE_CONTINUED 0xFFFD
85 #define CAB_FILE_SPLIT 0xFFFE
86 #define CAB_FILE_PREV_NEXT 0xFFFF
89 /* Cabinet structures */
91 typedef struct _CFHEADER
93 DWORD Signature; // File signature 'MSCF' (CAB_SIGNATURE)
94 DWORD Reserved1; // Reserved field
95 DWORD CabinetSize; // Cabinet file size
96 DWORD Reserved2; // Reserved field
97 DWORD FileTableOffset; // Offset of first CFFILE
98 DWORD Reserved3; // Reserved field
99 WORD Version; // Cabinet version (CAB_VERSION)
100 WORD FolderCount; // Number of folders
101 WORD FileCount; // Number of files
102 WORD Flags; // Cabinet flags (CAB_FLAG_*)
103 WORD SetID; // Cabinet set id
104 WORD CabinetNumber; // Zero-based cabinet number
105 /* Optional fields (depends on Flags)
106 WORD CabinetResSize // Per-cabinet reserved area size
107 CHAR FolderResSize // Per-folder reserved area size
108 CHAR FileResSize // Per-file reserved area size
109 CHAR CabinetReserved[] // Per-cabinet reserved area
110 CHAR CabinetPrev[] // Name of previous cabinet file
111 CHAR DiskPrev[] // Name of previous disk
112 CHAR CabinetNext[] // Name of next cabinet file
113 CHAR DiskNext[] // Name of next disk
115 } CFHEADER, *PCFHEADER;
118 typedef struct _CFFOLDER
120 DWORD DataOffset; // Absolute offset of first CFDATA block in this folder
121 WORD DataBlockCount; // Number of CFDATA blocks in this folder in this cabinet
122 WORD CompressionType; // Type of compression used for all CFDATA blocks in this folder
123 /* Optional fields (depends on Flags)
124 CHAR FolderReserved[] // Per-folder reserved area
126 } CFFOLDER, *PCFFOLDER;
129 typedef struct _CFFILE
131 DWORD FileSize; // Uncompressed file size in bytes
132 DWORD FileOffset; // Uncompressed offset of file in the folder
133 WORD FileControlID; // File control ID (CAB_FILE_*)
134 WORD FileDate; // File date stamp, as used by DOS
135 WORD FileTime; // File time stamp, as used by DOS
136 WORD Attributes; // File attributes (CAB_ATTRIB_*)
137 /* After this is the NULL terminated filename */
141 typedef struct _CFDATA
143 DWORD Checksum; // Checksum of CFDATA entry
144 WORD CompSize; // Number of compressed bytes in this block
145 WORD UncompSize; // Number of uncompressed bytes in this block
146 /* Optional fields (depends on Flags)
147 CHAR DataReserved[] // Per-datablock reserved area
151 typedef struct _CFDATA_NODE
153 struct _CFDATA_NODE *Next;
154 struct _CFDATA_NODE *Prev;
155 DWORD ScratchFilePosition; // Absolute offset in scratch file
156 DWORD AbsoluteOffset; // Absolute offset in cabinet
157 DWORD UncompOffset; // Uncompressed offset in folder
159 } CFDATA_NODE, *PCFDATA_NODE;
161 typedef struct _CFFOLDER_NODE
163 struct _CFFOLDER_NODE *Next;
164 struct _CFFOLDER_NODE *Prev;
165 DWORD UncompOffset; // File size accumulator
166 DWORD AbsoluteOffset;
167 DWORD TotalFolderSize; // Total size of folder in current disk
168 PCFDATA_NODE DataListHead;
169 PCFDATA_NODE DataListTail;
171 BOOL Commit; // TRUE if the folder should be committed
172 BOOL Delete; // TRUE if marked for deletion
174 } CFFOLDER_NODE, *PCFFOLDER_NODE;
176 typedef struct _CFFILE_NODE
178 struct _CFFILE_NODE *Next;
179 struct _CFFILE_NODE *Prev;
182 PCFDATA_NODE DataBlock; // First data block of file. NULL if not known
183 BOOL Commit; // TRUE if the file data should be committed
184 BOOL Delete; // TRUE if marked for deletion
185 PCFFOLDER_NODE FolderNode; // Folder this file belong to
186 } CFFILE_NODE, *PCFFILE_NODE;
189 typedef struct _CAB_SEARCH
191 TCHAR Search[MAX_PATH]; // Search criteria
192 PCFFILE_NODE Next; // Pointer to next node
193 PCFFILE File; // Pointer to current CFFILE
194 LPTSTR FileName; // Current filename
195 } CAB_SEARCH, *PCAB_SEARCH;
201 #define CAB_STATUS_SUCCESS 0x00000000
202 #define CAB_STATUS_FAILURE 0x00000001
203 #define CAB_STATUS_NOMEMORY 0x00000002
204 #define CAB_STATUS_CANNOT_OPEN 0x00000003
205 #define CAB_STATUS_CANNOT_CREATE 0x00000004
206 #define CAB_STATUS_CANNOT_READ 0x00000005
207 #define CAB_STATUS_CANNOT_WRITE 0x00000006
208 #define CAB_STATUS_FILE_EXISTS 0x00000007
209 #define CAB_STATUS_INVALID_CAB 0x00000008
210 #define CAB_STATUS_NOFILE 0x00000009
211 #define CAB_STATUS_UNSUPPCOMP 0x0000000A
219 /* Default constructor */
221 /* Default destructor */
222 virtual ~CCABCodec() {};
223 /* Compresses a data block */
224 virtual ULONG Compress(PVOID OutputBuffer,
227 PDWORD OutputLength) = 0;
228 /* Uncompresses a data block */
229 virtual ULONG Uncompress(PVOID OutputBuffer,
232 PDWORD OutputLength) = 0;
236 /* Codec status codes */
237 #define CS_SUCCESS 0x0000 /* All data consumed */
238 #define CS_NOMEMORY 0x0001 /* Not enough free memory */
239 #define CS_BADSTREAM 0x0002 /* Bad data stream */
242 /* Codec indentifiers */
243 #define CAB_CODEC_RAW 0x00
244 #define CAB_CODEC_LZX 0x01
245 #define CAB_CODEC_MSZIP 0x02
251 #ifndef CAB_READ_ONLY
253 class CCFDATAStorage {
255 /* Default constructor */
257 /* Default destructor */
258 virtual ~CCFDATAStorage();
259 ULONG Create(LPTSTR FileName);
263 ULONG Seek(LONG Position);
264 ULONG ReadBlock(PCFDATA Data, PVOID Buffer, PDWORD BytesRead);
265 ULONG WriteBlock(PCFDATA Data, PVOID Buffer, PDWORD BytesWritten);
271 #endif /* CAB_READ_ONLY */
275 /* Default constructor */
277 /* Default destructor */
279 /* Returns a pointer to the filename part of a fully qualified filename */
280 LPTSTR GetFileName(LPTSTR Path);
281 /* Removes a filename from a fully qualified filename */
282 VOID RemoveFileName(LPTSTR Path);
283 /* Normalizes a path */
284 BOOL NormalizePath(LPTSTR Path, DWORD Length);
285 /* Returns name of cabinet file */
286 LPTSTR GetCabinetName();
287 /* Sets the name of the cabinet file */
288 VOID SetCabinetName(LPTSTR FileName);
289 /* Sets destination path for extracted files */
290 VOID SetDestinationPath(LPTSTR DestinationPath);
291 /* Returns destination path */
292 LPTSTR GetDestinationPath();
293 /* Returns zero-based current disk number */
294 DWORD GetCurrentDiskNumber();
295 /* Opens the current cabinet file */
297 /* Closes the current open cabinet file */
299 /* Locates the first file in the current cabinet file that matches a search criteria */
300 ULONG FindFirst(LPTSTR FileName, PCAB_SEARCH Search);
301 /* Locates the next file in the current cabinet file */
302 ULONG FindNext(PCAB_SEARCH Search);
303 /* Extracts a file from the current cabinet file */
304 ULONG ExtractFile(LPTSTR FileName);
305 /* Select codec engine to use */
306 VOID SelectCodec(ULONG Id);
307 #ifndef CAB_READ_ONLY
308 /* Creates a new cabinet file */
310 /* Forces a new disk to be created */
312 /* Forces a new folder to be created */
314 /* Writes a file to scratch storage */
315 ULONG WriteFileToScratchStorage(PCFFILE_NODE FileNode);
316 /* Forces the current disk to be written */
317 ULONG WriteDisk(DWORD MoreDisks);
318 /* Commits the current disk */
319 ULONG CommitDisk(DWORD MoreDisks);
320 /* Closes the current disk */
322 /* Closes the current cabinet */
323 ULONG CloseCabinet();
324 /* Adds a file to the current disk */
325 ULONG AddFile(LPTSTR FileName);
326 /* Sets the maximum size of the current disk */
327 VOID SetMaxDiskSize(DWORD Size);
328 #endif /* CAB_READ_ONLY */
330 /* Default event handlers */
332 /* Handler called when a file is about to be overridden */
333 virtual BOOL OnOverwrite(PCFFILE Entry, LPTSTR FileName);
334 /* Handler called when a file is about to be extracted */
335 virtual VOID OnExtract(PCFFILE Entry, LPTSTR FileName);
336 /* Handler called when a new disk is to be processed */
337 virtual VOID OnDiskChange(LPTSTR CabinetName, LPTSTR DiskLabel);
338 #ifndef CAB_READ_ONLY
339 /* Handler called when a file is about to be added */
340 virtual VOID OnAdd(PCFFILE Entry, LPTSTR FileName);
341 /* Handler called when a cabinet need a name */
342 virtual BOOL OnCabinetName(ULONG Number, LPTSTR Name);
343 /* Handler called when a disk needs a label */
344 virtual BOOL OnDiskLabel(ULONG Number, LPTSTR Label);
345 #endif /* CAB_READ_ONLY */
347 PCFFOLDER_NODE LocateFolderNode(DWORD Index);
348 ULONG GetAbsoluteOffset(PCFFILE_NODE File);
349 ULONG LocateFile(LPTSTR FileName, PCFFILE_NODE *File);
350 ULONG ReadString(LPTSTR String, DWORD MaxLength);
351 ULONG ReadFileTable();
352 ULONG ReadDataBlocks(PCFFOLDER_NODE FolderNode);
353 PCFFOLDER_NODE NewFolderNode();
354 PCFFILE_NODE NewFileNode();
355 PCFDATA_NODE NewDataNode(PCFFOLDER_NODE FolderNode);
356 VOID DestroyDataNodes(PCFFOLDER_NODE FolderNode);
357 VOID DestroyFileNodes();
358 VOID DestroyDeletedFileNodes();
359 VOID DestroyFolderNodes();
360 VOID DestroyDeletedFolderNodes();
361 ULONG ComputeChecksum(PVOID Buffer, UINT Size, ULONG Seed);
362 ULONG ReadBlock(PVOID Buffer, DWORD Size, PDWORD BytesRead);
363 #ifndef CAB_READ_ONLY
364 ULONG InitCabinetHeader();
365 ULONG WriteCabinetHeader(BOOL MoreDisks);
366 ULONG WriteFolderEntries();
367 ULONG WriteFileEntries();
368 ULONG CommitDataBlocks(PCFFOLDER_NODE FolderNode);
369 ULONG WriteDataBlock();
370 ULONG GetAttributesOnFile(PCFFILE_NODE File);
371 ULONG SetAttributesOnFile(PCFFILE_NODE File);
372 #endif /* CAB_READ_ONLY */
373 DWORD CurrentDiskNumber; // Zero based disk number
374 TCHAR CabinetName[256]; // Filename of current cabinet
375 TCHAR CabinetPrev[256]; // Filename of previous cabinet
376 TCHAR DiskPrev[256]; // Label of cabinet in file CabinetPrev
377 TCHAR CabinetNext[256]; // Filename of next cabinet
378 TCHAR DiskNext[256]; // Label of cabinet in file CabinetNext
379 DWORD TotalHeaderSize; // Size of header and optional fields
380 DWORD NextFieldsSize; // Size of next cabinet name and next disk label
381 DWORD TotalFolderSize; // Size of all folder entries
382 DWORD TotalFileSize; // Size of all file entries
383 DWORD FolderUncompSize; // Uncompressed size of folder
384 DWORD BytesLeftInBlock; // Number of bytes left in current block
386 TCHAR DestPath[MAX_PATH];
390 ULONG CabinetReserved;
391 ULONG FolderReserved;
393 PCFFOLDER_NODE FolderListHead;
394 PCFFOLDER_NODE FolderListTail;
395 PCFFOLDER_NODE CurrentFolderNode;
396 PCFDATA_NODE CurrentDataNode;
397 PCFFILE_NODE FileListHead;
398 PCFFILE_NODE FileListTail;
403 PVOID CurrentIBuffer; // Current offset in input buffer
404 DWORD CurrentIBufferSize; // Bytes left in input buffer
406 DWORD TotalCompSize; // Total size of current CFDATA block
407 PVOID CurrentOBuffer; // Current offset in output buffer
408 DWORD CurrentOBufferSize; // Bytes left in output buffer
409 DWORD BytesLeftInCabinet;
411 DWORD LastFileOffset; // Uncompressed offset of last extracted file
412 #ifndef CAB_READ_ONLY
413 DWORD LastBlockStart; // Uncompressed offset of last block in folder
416 DWORD PrevCabinetNumber; // Previous cabinet number (where split file starts)
418 BOOL CreateNewFolder;
420 CCFDATAStorage *ScratchFile;
423 DWORD TotalBytesLeft;
424 BOOL BlockIsSplit; // TRUE if current data block is split
425 ULONG NextFolderNumber; // Zero based folder number
426 #endif /* CAB_READ_ONLY */
429 #endif /* __CABINET_H */