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 */