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>
29 #define DIR_SEPARATOR_CHAR '\\'
30 #define DIR_SEPARATOR_STRING "\\"
32 #define strcasecmp _stricmp
33 #define strdup _strdup
35 #define AllocateMemory(size) HeapAlloc(GetProcessHeap(), 0, size)
36 #define FreeMemory(buffer) HeapFree(GetProcessHeap(), 0, buffer)
37 #define FILEHANDLE HANDLE
38 #define CloseFile(handle) CloseHandle(handle)
40 #define DIR_SEPARATOR_CHAR '/'
41 #define DIR_SEPARATOR_STRING "/"
43 #define AllocateMemory(size) malloc(size)
44 #define FreeMemory(buffer) free(buffer)
45 #define CloseFile(handle) fclose(handle)
46 #define FILEHANDLE FILE*
51 #define NORMAL_MASK 0x000000FF
52 #define SPECIAL_MASK 0xFFFFFF00
53 #define MIN_TRACE 0x00000001
54 #define MID_TRACE 0x00000002
55 #define MAX_TRACE 0x00000003
57 #define DEBUG_MEMORY 0x00000100
61 extern ULONG DebugTraceLevel
;
64 #define DPRINT(_t_, _x_) \
65 if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \
66 ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \
67 printf("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \
72 #define ASSERT(_b_) { \
74 printf("(%s:%d)(%s) ASSERTION: ", __FILE__, __LINE__, __FUNCTION__); \
83 #define DPRINT(_t_, _x_) do { } while(0)
91 /* Cabinet constants */
93 #define CAB_SIGNATURE 0x4643534D // "MSCF"
94 #define CAB_VERSION 0x0103
95 #define CAB_BLOCKSIZE 32768
97 #define CAB_COMP_MASK 0x00FF
98 #define CAB_COMP_NONE 0x0000
99 #define CAB_COMP_MSZIP 0x0001
100 #define CAB_COMP_QUANTUM 0x0002
101 #define CAB_COMP_LZX 0x0003
103 #define CAB_FLAG_HASPREV 0x0001
104 #define CAB_FLAG_HASNEXT 0x0002
105 #define CAB_FLAG_RESERVE 0x0004
107 #define CAB_ATTRIB_READONLY 0x0001
108 #define CAB_ATTRIB_HIDDEN 0x0002
109 #define CAB_ATTRIB_SYSTEM 0x0004
110 #define CAB_ATTRIB_VOLUME 0x0008
111 #define CAB_ATTRIB_DIRECTORY 0x0010
112 #define CAB_ATTRIB_ARCHIVE 0x0020
113 #define CAB_ATTRIB_EXECUTE 0x0040
114 #define CAB_ATTRIB_UTF_NAME 0x0080
116 #define CAB_FILE_MAX_FOLDER 0xFFFC
117 #define CAB_FILE_CONTINUED 0xFFFD
118 #define CAB_FILE_SPLIT 0xFFFE
119 #define CAB_FILE_PREV_NEXT 0xFFFF
122 /* Cabinet structures */
124 typedef struct _CFHEADER
126 ULONG Signature
; // File signature 'MSCF' (CAB_SIGNATURE)
127 ULONG Reserved1
; // Reserved field
128 ULONG CabinetSize
; // Cabinet file size
129 ULONG Reserved2
; // Reserved field
130 ULONG FileTableOffset
; // Offset of first CFFILE
131 ULONG Reserved3
; // Reserved field
132 USHORT Version
; // Cabinet version (CAB_VERSION)
133 USHORT FolderCount
; // Number of folders
134 USHORT FileCount
; // Number of files
135 USHORT Flags
; // Cabinet flags (CAB_FLAG_*)
136 USHORT SetID
; // Cabinet set id
137 USHORT CabinetNumber
; // Zero-based cabinet number
138 /* Optional fields (depends on Flags)
139 USHORT CabinetResSize // Per-cabinet reserved area size
140 char FolderResSize // Per-folder reserved area size
141 char FileResSize // Per-file reserved area size
142 char CabinetReserved[] // Per-cabinet reserved area
143 char CabinetPrev[] // Name of previous cabinet file
144 char DiskPrev[] // Name of previous disk
145 char CabinetNext[] // Name of next cabinet file
146 char DiskNext[] // Name of next disk
148 } CFHEADER
, *PCFHEADER
;
151 typedef struct _CFFOLDER
153 ULONG DataOffset
; // Absolute offset of first CFDATA block in this folder
154 USHORT DataBlockCount
; // Number of CFDATA blocks in this folder in this cabinet
155 USHORT CompressionType
; // Type of compression used for all CFDATA blocks in this folder
156 /* Optional fields (depends on Flags)
157 char FolderReserved[] // Per-folder reserved area
159 } CFFOLDER
, *PCFFOLDER
;
162 typedef struct _CFFILE
164 ULONG FileSize
; // Uncompressed file size in bytes
165 ULONG FileOffset
; // Uncompressed offset of file in the folder
166 USHORT FileControlID
; // File control ID (CAB_FILE_*)
167 USHORT FileDate
; // File date stamp, as used by DOS
168 USHORT FileTime
; // File time stamp, as used by DOS
169 USHORT Attributes
; // File attributes (CAB_ATTRIB_*)
170 /* After this is the NULL terminated filename */
174 typedef struct _CFDATA
176 ULONG Checksum
; // Checksum of CFDATA entry
177 USHORT CompSize
; // Number of compressed bytes in this block
178 USHORT UncompSize
; // Number of uncompressed bytes in this block
179 /* Optional fields (depends on Flags)
180 char DataReserved[] // Per-datablock reserved area
184 typedef struct _CFDATA_NODE
186 struct _CFDATA_NODE
*Next
;
187 struct _CFDATA_NODE
*Prev
;
188 ULONG ScratchFilePosition
; // Absolute offset in scratch file
189 ULONG AbsoluteOffset
; // Absolute offset in cabinet
190 ULONG UncompOffset
; // Uncompressed offset in folder
192 } CFDATA_NODE
, *PCFDATA_NODE
;
194 typedef struct _CFFOLDER_NODE
196 struct _CFFOLDER_NODE
*Next
;
197 struct _CFFOLDER_NODE
*Prev
;
198 ULONG UncompOffset
; // File size accumulator
199 ULONG AbsoluteOffset
;
200 ULONG TotalFolderSize
; // Total size of folder in current disk
201 PCFDATA_NODE DataListHead
;
202 PCFDATA_NODE DataListTail
;
204 bool Commit
; // true if the folder should be committed
205 bool Delete
; // true if marked for deletion
207 } CFFOLDER_NODE
, *PCFFOLDER_NODE
;
209 typedef struct _CFFILE_NODE
211 struct _CFFILE_NODE
*Next
;
212 struct _CFFILE_NODE
*Prev
;
215 PCFDATA_NODE DataBlock
; // First data block of file. NULL if not known
216 bool Commit
; // true if the file data should be committed
217 bool Delete
; // true if marked for deletion
218 PCFFOLDER_NODE FolderNode
; // Folder this file belong to
219 } CFFILE_NODE
, *PCFFILE_NODE
;
221 typedef struct _SEARCH_CRITERIA
223 struct _SEARCH_CRITERIA
*Next
; // Pointer to next search criteria
224 struct _SEARCH_CRITERIA
*Prev
; // Pointer to previous search criteria
225 char* Search
; // The actual search criteria
226 } SEARCH_CRITERIA
, *PSEARCH_CRITERIA
;
228 typedef struct _CAB_SEARCH
230 PCFFILE_NODE Next
; // Pointer to next node
231 PCFFILE File
; // Pointer to current CFFILE
232 char* FileName
; // Current filename
233 } CAB_SEARCH
, *PCAB_SEARCH
;
239 #define CAB_STATUS_SUCCESS 0x00000000
240 #define CAB_STATUS_FAILURE 0x00000001
241 #define CAB_STATUS_NOMEMORY 0x00000002
242 #define CAB_STATUS_CANNOT_OPEN 0x00000003
243 #define CAB_STATUS_CANNOT_CREATE 0x00000004
244 #define CAB_STATUS_CANNOT_READ 0x00000005
245 #define CAB_STATUS_CANNOT_WRITE 0x00000006
246 #define CAB_STATUS_FILE_EXISTS 0x00000007
247 #define CAB_STATUS_INVALID_CAB 0x00000008
248 #define CAB_STATUS_NOFILE 0x00000009
249 #define CAB_STATUS_UNSUPPCOMP 0x0000000A
257 /* Default constructor */
259 /* Default destructor */
260 virtual ~CCABCodec() {};
261 /* Compresses a data block */
262 virtual ULONG
Compress(void* OutputBuffer
,
265 PULONG OutputLength
) = 0;
266 /* Uncompresses a data block */
267 virtual ULONG
Uncompress(void* OutputBuffer
,
270 PULONG OutputLength
) = 0;
274 /* Codec status codes */
275 #define CS_SUCCESS 0x0000 /* All data consumed */
276 #define CS_NOMEMORY 0x0001 /* Not enough free memory */
277 #define CS_BADSTREAM 0x0002 /* Bad data stream */
280 /* Codec indentifiers */
281 #define CAB_CODEC_RAW 0x00
282 #define CAB_CODEC_LZX 0x01
283 #define CAB_CODEC_MSZIP 0x02
289 #ifndef CAB_READ_ONLY
291 class CCFDATAStorage
{
293 /* Default constructor */
295 /* Default destructor */
296 virtual ~CCFDATAStorage();
297 ULONG
Create(const char* FileName
);
301 ULONG
Seek(LONG Position
);
302 ULONG
ReadBlock(PCFDATA Data
, void* Buffer
, PULONG BytesRead
);
303 ULONG
WriteBlock(PCFDATA Data
, void* Buffer
, PULONG BytesWritten
);
305 char FullName
[MAX_PATH
];
307 FILEHANDLE FileHandle
;
310 #endif /* CAB_READ_ONLY */
314 /* Default constructor */
316 /* Default destructor */
318 /* Determines if a character is a separator */
319 bool IsSeparator(char Char
);
320 /* Replaces \ or / with the one used be the host environment */
321 char* ConvertPath(char* Path
, bool Allocate
);
322 /* Returns a pointer to the filename part of a fully qualified filename */
323 char* GetFileName(char* Path
);
324 /* Removes a filename from a fully qualified filename */
325 void RemoveFileName(char* Path
);
326 /* Normalizes a path */
327 bool NormalizePath(char* Path
, ULONG Length
);
328 /* Returns name of cabinet file */
329 char* GetCabinetName();
330 /* Sets the name of the cabinet file */
331 void SetCabinetName(char* FileName
);
332 /* Sets destination path for extracted files */
333 void SetDestinationPath(char* DestinationPath
);
334 /* Sets cabinet reserved file */
335 bool SetCabinetReservedFile(char* FileName
);
336 /* Returns cabinet reserved file */
337 char* GetCabinetReservedFile();
338 /* Returns destination path */
339 char* GetDestinationPath();
340 /* Returns zero-based current disk number */
341 ULONG
GetCurrentDiskNumber();
342 /* Opens the current cabinet file */
344 /* Closes the current open cabinet file */
346 /* Locates the first file in the current cabinet file that matches a search criteria */
347 ULONG
FindFirst(PCAB_SEARCH Search
);
348 /* Locates the next file in the current cabinet file */
349 ULONG
FindNext(PCAB_SEARCH Search
);
350 /* Extracts a file from the current cabinet file */
351 ULONG
ExtractFile(char* FileName
);
352 /* Select codec engine to use */
353 void SelectCodec(LONG Id
);
354 /* Returns whether a codec engine is selected */
355 bool IsCodecSelected();
356 /* Adds a search criteria for adding files to a simple cabinet, displaying files in a cabinet or extracting them */
357 ULONG
AddSearchCriteria(char* SearchCriteria
);
358 /* Destroys the search criteria list */
359 void DestroySearchCriteria();
360 /* Returns whether we have search criteria */
361 bool HasSearchCriteria();
363 #ifndef CAB_READ_ONLY
364 /* Creates a simple cabinet based on the search criteria data */
365 bool CreateSimpleCabinet();
366 /* Sets the codec to use for compression (based on a string value) */
367 bool SetCompressionCodec(char* CodecName
);
368 /* Creates a new cabinet file */
370 /* Forces a new disk to be created */
372 /* Forces a new folder to be created */
374 /* Writes a file to scratch storage */
375 ULONG
WriteFileToScratchStorage(PCFFILE_NODE FileNode
);
376 /* Forces the current disk to be written */
377 ULONG
WriteDisk(ULONG MoreDisks
);
378 /* Commits the current disk */
379 ULONG
CommitDisk(ULONG MoreDisks
);
380 /* Closes the current disk */
382 /* Closes the current cabinet */
383 ULONG
CloseCabinet();
384 /* Adds a file to the current disk */
385 ULONG
AddFile(char* FileName
);
386 /* Sets the maximum size of the current disk */
387 void SetMaxDiskSize(ULONG Size
);
388 #endif /* CAB_READ_ONLY */
390 /* Default event handlers */
392 /* Handler called when a file is about to be overridden */
393 virtual bool OnOverwrite(PCFFILE Entry
, char* FileName
);
394 /* Handler called when a file is about to be extracted */
395 virtual void OnExtract(PCFFILE Entry
, char* FileName
);
396 /* Handler called when a new disk is to be processed */
397 virtual void OnDiskChange(char* CabinetName
, char* DiskLabel
);
398 #ifndef CAB_READ_ONLY
399 /* Handler called when a file is about to be added */
400 virtual void OnAdd(PCFFILE Entry
, char* FileName
);
401 /* Handler called when a cabinet need a name */
402 virtual bool OnCabinetName(ULONG Number
, char* Name
);
403 /* Handler called when a disk needs a label */
404 virtual bool OnDiskLabel(ULONG Number
, char* Label
);
405 #endif /* CAB_READ_ONLY */
407 PCFFOLDER_NODE
LocateFolderNode(ULONG Index
);
408 ULONG
GetAbsoluteOffset(PCFFILE_NODE File
);
409 ULONG
LocateFile(char* FileName
, PCFFILE_NODE
*File
);
410 ULONG
ReadString(char* String
, LONG MaxLength
);
411 ULONG
ReadFileTable();
412 ULONG
ReadDataBlocks(PCFFOLDER_NODE FolderNode
);
413 PCFFOLDER_NODE
NewFolderNode();
414 PCFFILE_NODE
NewFileNode();
415 PCFDATA_NODE
NewDataNode(PCFFOLDER_NODE FolderNode
);
416 void DestroyDataNodes(PCFFOLDER_NODE FolderNode
);
417 void DestroyFileNodes();
418 void DestroyDeletedFileNodes();
419 void DestroyFolderNodes();
420 void DestroyDeletedFolderNodes();
421 ULONG
ComputeChecksum(void* Buffer
, ULONG Size
, ULONG Seed
);
422 ULONG
ReadBlock(void* Buffer
, ULONG Size
, PULONG BytesRead
);
423 bool MatchFileNamePattern(char* FileName
, char* Pattern
);
424 #ifndef CAB_READ_ONLY
425 ULONG
InitCabinetHeader();
426 ULONG
WriteCabinetHeader(bool MoreDisks
);
427 ULONG
WriteFolderEntries();
428 ULONG
WriteFileEntries();
429 ULONG
CommitDataBlocks(PCFFOLDER_NODE FolderNode
);
430 ULONG
WriteDataBlock();
431 ULONG
GetAttributesOnFile(PCFFILE_NODE File
);
432 ULONG
SetAttributesOnFile(char* FileName
, USHORT FileAttributes
);
433 ULONG
GetFileTimes(FILEHANDLE FileHandle
, PCFFILE_NODE File
);
435 void ConvertDateAndTime(time_t* Time
, PUSHORT DosDate
, PUSHORT DosTime
);
437 #endif /* CAB_READ_ONLY */
438 ULONG CurrentDiskNumber
; // Zero based disk number
439 char CabinetName
[256]; // Filename of current cabinet
440 char CabinetPrev
[256]; // Filename of previous cabinet
441 char DiskPrev
[256]; // Label of cabinet in file CabinetPrev
442 char CabinetNext
[256]; // Filename of next cabinet
443 char DiskNext
[256]; // Label of cabinet in file CabinetNext
444 ULONG TotalHeaderSize
; // Size of header and optional fields
445 ULONG NextFieldsSize
; // Size of next cabinet name and next disk label
446 ULONG TotalFolderSize
; // Size of all folder entries
447 ULONG TotalFileSize
; // Size of all file entries
448 ULONG FolderUncompSize
; // Uncompressed size of folder
449 ULONG BytesLeftInBlock
; // Number of bytes left in current block
451 char DestPath
[MAX_PATH
];
452 char CabinetReservedFile
[MAX_PATH
];
453 void* CabinetReservedFileBuffer
;
454 ULONG CabinetReservedFileSize
;
455 FILEHANDLE FileHandle
;
458 ULONG CabinetReserved
;
459 ULONG FolderReserved
;
461 PCFFOLDER_NODE FolderListHead
;
462 PCFFOLDER_NODE FolderListTail
;
463 PCFFOLDER_NODE CurrentFolderNode
;
464 PCFDATA_NODE CurrentDataNode
;
465 PCFFILE_NODE FileListHead
;
466 PCFFILE_NODE FileListTail
;
467 PSEARCH_CRITERIA CriteriaListHead
;
468 PSEARCH_CRITERIA CriteriaListTail
;
473 void* CurrentIBuffer
; // Current offset in input buffer
474 ULONG CurrentIBufferSize
; // Bytes left in input buffer
476 ULONG TotalCompSize
; // Total size of current CFDATA block
477 void* CurrentOBuffer
; // Current offset in output buffer
478 ULONG CurrentOBufferSize
; // Bytes left in output buffer
479 ULONG BytesLeftInCabinet
;
481 ULONG LastFileOffset
; // Uncompressed offset of last extracted file
482 #ifndef CAB_READ_ONLY
483 ULONG LastBlockStart
; // Uncompressed offset of last block in folder
486 ULONG PrevCabinetNumber
; // Previous cabinet number (where split file starts)
488 bool CreateNewFolder
;
490 CCFDATAStorage
*ScratchFile
;
491 FILEHANDLE SourceFile
;
493 ULONG TotalBytesLeft
;
494 bool BlockIsSplit
; // true if current data block is split
495 ULONG NextFolderNumber
; // Zero based folder number
496 #endif /* CAB_READ_ONLY */