2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS cabinet manager
4 * FILE: tools/cabman/cabinet.h
5 * PURPOSE: Cabinet definitions
15 #include <sys/types.h>
17 #include <host/typedefs.h>
33 #define DIR_SEPARATOR_CHAR '\\'
34 #define DIR_SEPARATOR_STRING "\\"
36 #define strcasecmp _strcmpi
37 #define strdup _strdup
39 #define AllocateMemory(size) HeapAlloc(GetProcessHeap(), 0, size)
40 #define FreeMemory(buffer) HeapFree(GetProcessHeap(), 0, buffer)
41 #define FILEHANDLE HANDLE
42 #define CloseFile(handle) CloseHandle(handle)
44 #define DIR_SEPARATOR_CHAR '/'
45 #define DIR_SEPARATOR_STRING "/"
47 #define AllocateMemory(size) malloc(size)
48 #define FreeMemory(buffer) free(buffer)
49 #define CloseFile(handle) fclose(handle)
50 #define FILEHANDLE FILE*
57 #define NORMAL_MASK 0x000000FF
58 #define SPECIAL_MASK 0xFFFFFF00
59 #define MIN_TRACE 0x00000001
60 #define MID_TRACE 0x00000002
61 #define MAX_TRACE 0x00000003
63 #define DEBUG_MEMORY 0x00000100
67 extern ULONG DebugTraceLevel
;
70 #define DPRINT(_t_, _x_) \
71 if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \
72 ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \
73 printf("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \
78 #define ASSERT(_b_) { \
80 printf("(%s:%d)(%s) ASSERTION: ", __FILE__, __LINE__, __FUNCTION__); \
89 #define DPRINT(_t_, _x_)
97 /* Cabinet constants */
99 #define CAB_SIGNATURE 0x4643534D // "MSCF"
100 #define CAB_VERSION 0x0103
101 #define CAB_BLOCKSIZE 32768
103 #define CAB_COMP_MASK 0x00FF
104 #define CAB_COMP_NONE 0x0000
105 #define CAB_COMP_MSZIP 0x0001
106 #define CAB_COMP_QUANTUM 0x0002
107 #define CAB_COMP_LZX 0x0003
109 #define CAB_FLAG_HASPREV 0x0001
110 #define CAB_FLAG_HASNEXT 0x0002
111 #define CAB_FLAG_RESERVE 0x0004
113 #define CAB_ATTRIB_READONLY 0x0001
114 #define CAB_ATTRIB_HIDDEN 0x0002
115 #define CAB_ATTRIB_SYSTEM 0x0004
116 #define CAB_ATTRIB_VOLUME 0x0008
117 #define CAB_ATTRIB_DIRECTORY 0x0010
118 #define CAB_ATTRIB_ARCHIVE 0x0020
119 #define CAB_ATTRIB_EXECUTE 0x0040
120 #define CAB_ATTRIB_UTF_NAME 0x0080
122 #define CAB_FILE_MAX_FOLDER 0xFFFC
123 #define CAB_FILE_CONTINUED 0xFFFD
124 #define CAB_FILE_SPLIT 0xFFFE
125 #define CAB_FILE_PREV_NEXT 0xFFFF
128 /* Cabinet structures */
130 typedef struct _CFHEADER
132 ULONG Signature
; // File signature 'MSCF' (CAB_SIGNATURE)
133 ULONG Reserved1
; // Reserved field
134 ULONG CabinetSize
; // Cabinet file size
135 ULONG Reserved2
; // Reserved field
136 ULONG FileTableOffset
; // Offset of first CFFILE
137 ULONG Reserved3
; // Reserved field
138 USHORT Version
; // Cabinet version (CAB_VERSION)
139 USHORT FolderCount
; // Number of folders
140 USHORT FileCount
; // Number of files
141 USHORT Flags
; // Cabinet flags (CAB_FLAG_*)
142 USHORT SetID
; // Cabinet set id
143 USHORT CabinetNumber
; // Zero-based cabinet number
144 /* Optional fields (depends on Flags)
145 USHORT CabinetResSize // Per-cabinet reserved area size
146 char FolderResSize // Per-folder reserved area size
147 char FileResSize // Per-file reserved area size
148 char CabinetReserved[] // Per-cabinet reserved area
149 char CabinetPrev[] // Name of previous cabinet file
150 char DiskPrev[] // Name of previous disk
151 char CabinetNext[] // Name of next cabinet file
152 char DiskNext[] // Name of next disk
154 } CFHEADER
, *PCFHEADER
;
157 typedef struct _CFFOLDER
159 ULONG DataOffset
; // Absolute offset of first CFDATA block in this folder
160 USHORT DataBlockCount
; // Number of CFDATA blocks in this folder in this cabinet
161 USHORT CompressionType
; // Type of compression used for all CFDATA blocks in this folder
162 /* Optional fields (depends on Flags)
163 char FolderReserved[] // Per-folder reserved area
165 } CFFOLDER
, *PCFFOLDER
;
168 typedef struct _CFFILE
170 ULONG FileSize
; // Uncompressed file size in bytes
171 ULONG FileOffset
; // Uncompressed offset of file in the folder
172 USHORT FileControlID
; // File control ID (CAB_FILE_*)
173 USHORT FileDate
; // File date stamp, as used by DOS
174 USHORT FileTime
; // File time stamp, as used by DOS
175 USHORT Attributes
; // File attributes (CAB_ATTRIB_*)
176 /* After this is the NULL terminated filename */
180 typedef struct _CFDATA
182 ULONG Checksum
; // Checksum of CFDATA entry
183 USHORT CompSize
; // Number of compressed bytes in this block
184 USHORT UncompSize
; // Number of uncompressed bytes in this block
185 /* Optional fields (depends on Flags)
186 char DataReserved[] // Per-datablock reserved area
190 typedef struct _CFDATA_NODE
192 struct _CFDATA_NODE
*Next
;
193 struct _CFDATA_NODE
*Prev
;
194 ULONG ScratchFilePosition
; // Absolute offset in scratch file
195 ULONG AbsoluteOffset
; // Absolute offset in cabinet
196 ULONG UncompOffset
; // Uncompressed offset in folder
198 } CFDATA_NODE
, *PCFDATA_NODE
;
200 typedef struct _CFFOLDER_NODE
202 struct _CFFOLDER_NODE
*Next
;
203 struct _CFFOLDER_NODE
*Prev
;
204 ULONG UncompOffset
; // File size accumulator
205 ULONG AbsoluteOffset
;
206 ULONG TotalFolderSize
; // Total size of folder in current disk
207 PCFDATA_NODE DataListHead
;
208 PCFDATA_NODE DataListTail
;
210 bool Commit
; // true if the folder should be committed
211 bool Delete
; // true if marked for deletion
213 } CFFOLDER_NODE
, *PCFFOLDER_NODE
;
215 typedef struct _CFFILE_NODE
217 struct _CFFILE_NODE
*Next
;
218 struct _CFFILE_NODE
*Prev
;
221 PCFDATA_NODE DataBlock
; // First data block of file. NULL if not known
222 bool Commit
; // true if the file data should be committed
223 bool Delete
; // true if marked for deletion
224 PCFFOLDER_NODE FolderNode
; // Folder this file belong to
225 } CFFILE_NODE
, *PCFFILE_NODE
;
227 typedef struct _SEARCH_CRITERIA
229 struct _SEARCH_CRITERIA
*Next
; // Pointer to next search criteria
230 struct _SEARCH_CRITERIA
*Prev
; // Pointer to previous search criteria
231 char* Search
; // The actual search criteria
232 } SEARCH_CRITERIA
, *PSEARCH_CRITERIA
;
234 typedef struct _CAB_SEARCH
236 PCFFILE_NODE Next
; // Pointer to next node
237 PCFFILE File
; // Pointer to current CFFILE
238 char* FileName
; // Current filename
239 } CAB_SEARCH
, *PCAB_SEARCH
;
245 #define CAB_STATUS_SUCCESS 0x00000000
246 #define CAB_STATUS_FAILURE 0x00000001
247 #define CAB_STATUS_NOMEMORY 0x00000002
248 #define CAB_STATUS_CANNOT_OPEN 0x00000003
249 #define CAB_STATUS_CANNOT_CREATE 0x00000004
250 #define CAB_STATUS_CANNOT_READ 0x00000005
251 #define CAB_STATUS_CANNOT_WRITE 0x00000006
252 #define CAB_STATUS_FILE_EXISTS 0x00000007
253 #define CAB_STATUS_INVALID_CAB 0x00000008
254 #define CAB_STATUS_NOFILE 0x00000009
255 #define CAB_STATUS_UNSUPPCOMP 0x0000000A
263 /* Default constructor */
265 /* Default destructor */
266 virtual ~CCABCodec() {};
267 /* Compresses a data block */
268 virtual ULONG
Compress(void* OutputBuffer
,
271 PULONG OutputLength
) = 0;
272 /* Uncompresses a data block */
273 virtual ULONG
Uncompress(void* OutputBuffer
,
276 PULONG OutputLength
) = 0;
280 /* Codec status codes */
281 #define CS_SUCCESS 0x0000 /* All data consumed */
282 #define CS_NOMEMORY 0x0001 /* Not enough free memory */
283 #define CS_BADSTREAM 0x0002 /* Bad data stream */
286 /* Codec indentifiers */
287 #define CAB_CODEC_RAW 0x00
288 #define CAB_CODEC_LZX 0x01
289 #define CAB_CODEC_MSZIP 0x02
295 #ifndef CAB_READ_ONLY
297 class CCFDATAStorage
{
299 /* Default constructor */
301 /* Default destructor */
302 virtual ~CCFDATAStorage();
303 ULONG
Create(char* FileName
);
307 ULONG
Seek(LONG Position
);
308 ULONG
ReadBlock(PCFDATA Data
, void* Buffer
, PULONG BytesRead
);
309 ULONG
WriteBlock(PCFDATA Data
, void* Buffer
, PULONG BytesWritten
);
311 char FullName
[MAX_PATH
];
313 FILEHANDLE FileHandle
;
316 #endif /* CAB_READ_ONLY */
320 /* Default constructor */
322 /* Default destructor */
324 /* Determines if a character is a separator */
325 bool IsSeparator(char Char
);
326 /* Replaces \ or / with the one used be the host environment */
327 char* ConvertPath(char* Path
, bool Allocate
);
328 /* Returns a pointer to the filename part of a fully qualified filename */
329 char* GetFileName(char* Path
);
330 /* Removes a filename from a fully qualified filename */
331 void RemoveFileName(char* Path
);
332 /* Normalizes a path */
333 bool NormalizePath(char* Path
, ULONG Length
);
334 /* Returns name of cabinet file */
335 char* GetCabinetName();
336 /* Sets the name of the cabinet file */
337 void SetCabinetName(char* FileName
);
338 /* Sets destination path for extracted files */
339 void SetDestinationPath(char* DestinationPath
);
340 /* Sets cabinet reserved file */
341 bool SetCabinetReservedFile(char* FileName
);
342 /* Returns cabinet reserved file */
343 char* GetCabinetReservedFile();
344 /* Returns destination path */
345 char* GetDestinationPath();
346 /* Returns zero-based current disk number */
347 ULONG
GetCurrentDiskNumber();
348 /* Opens the current cabinet file */
350 /* Closes the current open cabinet file */
352 /* Locates the first file in the current cabinet file that matches a search criteria */
353 ULONG
FindFirst(PCAB_SEARCH Search
);
354 /* Locates the next file in the current cabinet file */
355 ULONG
FindNext(PCAB_SEARCH Search
);
356 /* Extracts a file from the current cabinet file */
357 ULONG
ExtractFile(char* FileName
);
358 /* Select codec engine to use */
359 void SelectCodec(LONG Id
);
360 /* Returns whether a codec engine is selected */
361 bool IsCodecSelected();
362 /* Adds a search criteria for adding files to a simple cabinet, displaying files in a cabinet or extracting them */
363 ULONG
AddSearchCriteria(char* SearchCriteria
);
364 /* Destroys the search criteria list */
365 void DestroySearchCriteria();
366 /* Returns whether we have search criteria */
367 bool HasSearchCriteria();
369 #ifndef CAB_READ_ONLY
370 /* Creates a simple cabinet based on the search criteria data */
371 bool CreateSimpleCabinet();
372 /* Sets the codec to use for compression (based on a string value) */
373 bool SetCompressionCodec(char* CodecName
);
374 /* Creates a new cabinet file */
376 /* Forces a new disk to be created */
378 /* Forces a new folder to be created */
380 /* Writes a file to scratch storage */
381 ULONG
WriteFileToScratchStorage(PCFFILE_NODE FileNode
);
382 /* Forces the current disk to be written */
383 ULONG
WriteDisk(ULONG MoreDisks
);
384 /* Commits the current disk */
385 ULONG
CommitDisk(ULONG MoreDisks
);
386 /* Closes the current disk */
388 /* Closes the current cabinet */
389 ULONG
CloseCabinet();
390 /* Adds a file to the current disk */
391 ULONG
AddFile(char* FileName
);
392 /* Sets the maximum size of the current disk */
393 void SetMaxDiskSize(ULONG Size
);
394 #endif /* CAB_READ_ONLY */
396 /* Default event handlers */
398 /* Handler called when a file is about to be overridden */
399 virtual bool OnOverwrite(PCFFILE Entry
, char* FileName
);
400 /* Handler called when a file is about to be extracted */
401 virtual void OnExtract(PCFFILE Entry
, char* FileName
);
402 /* Handler called when a new disk is to be processed */
403 virtual void OnDiskChange(char* CabinetName
, char* DiskLabel
);
404 #ifndef CAB_READ_ONLY
405 /* Handler called when a file is about to be added */
406 virtual void OnAdd(PCFFILE Entry
, char* FileName
);
407 /* Handler called when a cabinet need a name */
408 virtual bool OnCabinetName(ULONG Number
, char* Name
);
409 /* Handler called when a disk needs a label */
410 virtual bool OnDiskLabel(ULONG Number
, char* Label
);
411 #endif /* CAB_READ_ONLY */
413 PCFFOLDER_NODE
LocateFolderNode(ULONG Index
);
414 ULONG
GetAbsoluteOffset(PCFFILE_NODE File
);
415 ULONG
LocateFile(char* FileName
, PCFFILE_NODE
*File
);
416 ULONG
ReadString(char* String
, LONG MaxLength
);
417 ULONG
ReadFileTable();
418 ULONG
ReadDataBlocks(PCFFOLDER_NODE FolderNode
);
419 PCFFOLDER_NODE
NewFolderNode();
420 PCFFILE_NODE
NewFileNode();
421 PCFDATA_NODE
NewDataNode(PCFFOLDER_NODE FolderNode
);
422 void DestroyDataNodes(PCFFOLDER_NODE FolderNode
);
423 void DestroyFileNodes();
424 void DestroyDeletedFileNodes();
425 void DestroyFolderNodes();
426 void DestroyDeletedFolderNodes();
427 ULONG
ComputeChecksum(void* Buffer
, ULONG Size
, ULONG Seed
);
428 ULONG
ReadBlock(void* Buffer
, ULONG Size
, PULONG BytesRead
);
429 bool MatchFileNamePattern(char* FileName
, char* Pattern
);
430 #ifndef CAB_READ_ONLY
431 ULONG
InitCabinetHeader();
432 ULONG
WriteCabinetHeader(bool MoreDisks
);
433 ULONG
WriteFolderEntries();
434 ULONG
WriteFileEntries();
435 ULONG
CommitDataBlocks(PCFFOLDER_NODE FolderNode
);
436 ULONG
WriteDataBlock();
437 ULONG
GetAttributesOnFile(PCFFILE_NODE File
);
438 ULONG
SetAttributesOnFile(char* FileName
, USHORT FileAttributes
);
439 ULONG
GetFileTimes(FILEHANDLE FileHandle
, PCFFILE_NODE File
);
441 void ConvertDateAndTime(time_t* Time
, PUSHORT DosDate
, PUSHORT DosTime
);
443 #endif /* CAB_READ_ONLY */
444 ULONG CurrentDiskNumber
; // Zero based disk number
445 char CabinetName
[256]; // Filename of current cabinet
446 char CabinetPrev
[256]; // Filename of previous cabinet
447 char DiskPrev
[256]; // Label of cabinet in file CabinetPrev
448 char CabinetNext
[256]; // Filename of next cabinet
449 char DiskNext
[256]; // Label of cabinet in file CabinetNext
450 ULONG TotalHeaderSize
; // Size of header and optional fields
451 ULONG NextFieldsSize
; // Size of next cabinet name and next disk label
452 ULONG TotalFolderSize
; // Size of all folder entries
453 ULONG TotalFileSize
; // Size of all file entries
454 ULONG FolderUncompSize
; // Uncompressed size of folder
455 ULONG BytesLeftInBlock
; // Number of bytes left in current block
457 char DestPath
[MAX_PATH
];
458 char CabinetReservedFile
[MAX_PATH
];
459 void* CabinetReservedFileBuffer
;
460 ULONG CabinetReservedFileSize
;
461 FILEHANDLE FileHandle
;
464 ULONG CabinetReserved
;
465 ULONG FolderReserved
;
467 PCFFOLDER_NODE FolderListHead
;
468 PCFFOLDER_NODE FolderListTail
;
469 PCFFOLDER_NODE CurrentFolderNode
;
470 PCFDATA_NODE CurrentDataNode
;
471 PCFFILE_NODE FileListHead
;
472 PCFFILE_NODE FileListTail
;
473 PSEARCH_CRITERIA CriteriaListHead
;
474 PSEARCH_CRITERIA CriteriaListTail
;
479 void* CurrentIBuffer
; // Current offset in input buffer
480 ULONG CurrentIBufferSize
; // Bytes left in input buffer
482 ULONG TotalCompSize
; // Total size of current CFDATA block
483 void* CurrentOBuffer
; // Current offset in output buffer
484 ULONG CurrentOBufferSize
; // Bytes left in output buffer
485 ULONG BytesLeftInCabinet
;
487 ULONG LastFileOffset
; // Uncompressed offset of last extracted file
488 #ifndef CAB_READ_ONLY
489 ULONG LastBlockStart
; // Uncompressed offset of last block in folder
492 ULONG PrevCabinetNumber
; // Previous cabinet number (where split file starts)
494 bool CreateNewFolder
;
496 CCFDATAStorage
*ScratchFile
;
497 FILEHANDLE SourceFile
;
499 ULONG TotalBytesLeft
;
500 bool BlockIsSplit
; // true if current data block is split
501 ULONG NextFolderNumber
; // Zero based folder number
502 #endif /* CAB_READ_ONLY */
505 #endif /* __CABINET_H */