:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / apps / utils / cabman / cabinet.h
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS cabinet manager
4  * FILE:        apps/cabman/cabinet.h
5  * PURPOSE:     Cabinet definitions
6  */
7 #ifndef __CABINET_H
8 #define __CABINET_H
9
10 #include <string.h>
11
12 /* Debugging */
13
14 #define DBG
15
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
21
22 #define DEBUG_MEMORY   0x00000100
23
24 #ifdef DBG
25
26 extern DWORD DebugTraceLevel;
27
28 #define DPRINT(_t_, _x_) \
29     if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \
30         ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \
31         printf("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \
32         printf _x_ ; \
33     }
34
35 #define ASSERT(_b_) { \
36     if (!(_b_)) { \
37         printf("(%s:%d)(%s) ASSERTION: ", __FILE__, __LINE__, __FUNCTION__); \
38         printf(#_b_); \
39         ExitProcess(0); \
40     } \
41 }
42
43 #else /* DBG */
44
45 #define DPRINT(_t_, _x_)
46
47 #define ASSERT(_x_)
48
49 #endif /* DBG */
50
51
52 /* Macros */
53
54 #ifndef CopyMemory
55 #define CopyMemory(destination, source, length) memcpy(destination, source, length)
56 #endif /* CopyMemory */
57
58 /* Cabinet constants */
59
60 #define CAB_SIGNATURE        0x4643534D // "MSCF"
61 #define CAB_VERSION          0x0103
62 #define CAB_BLOCKSIZE        32768
63
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
69
70 #define CAB_FLAG_HASPREV     0x0001
71 #define CAB_FLAG_HASNEXT     0x0002
72 #define CAB_FLAG_RESERVE     0x0004
73
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
82
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
87
88
89 /* Cabinet structures */
90
91 typedef struct _CFHEADER
92 {
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
114  */
115 } CFHEADER, *PCFHEADER;
116
117
118 typedef struct _CFFOLDER
119 {
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
125  */
126 } CFFOLDER, *PCFFOLDER;
127
128
129 typedef struct _CFFILE
130 {
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 */
138 } CFFILE, *PCFFILE;
139
140
141 typedef struct _CFDATA
142 {
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
148  */
149 } CFDATA, *PCFDATA;
150
151 typedef struct _CFDATA_NODE
152 {
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
158     CFDATA              Data;
159 } CFDATA_NODE, *PCFDATA_NODE;
160
161 typedef struct _CFFOLDER_NODE
162 {
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;
170     DWORD                 Index;
171     BOOL                  Commit;           // TRUE if the folder should be committed
172     BOOL                  Delete;           // TRUE if marked for deletion
173     CFFOLDER              Folder;
174 } CFFOLDER_NODE, *PCFFOLDER_NODE;
175
176 typedef struct _CFFILE_NODE
177 {
178     struct _CFFILE_NODE *Next;
179     struct _CFFILE_NODE *Prev;
180     CFFILE              File;
181     LPTSTR              FileName;
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;
187
188
189 typedef struct _CAB_SEARCH
190 {
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;
196
197
198 /* Constants */
199
200 /* Status codes */
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
212
213
214
215 /* Codecs */
216
217 class CCABCodec {
218 public:
219     /* Default constructor */
220     CCABCodec() {};
221     /* Default destructor */
222     virtual ~CCABCodec() {};
223     /* Compresses a data block */
224     virtual ULONG Compress(PVOID OutputBuffer,
225                            PVOID InputBuffer,
226                            DWORD InputLength,
227                            PDWORD OutputLength) = 0;
228     /* Uncompresses a data block */
229     virtual ULONG Uncompress(PVOID OutputBuffer,
230                              PVOID InputBuffer,
231                              DWORD InputLength,
232                              PDWORD OutputLength) = 0;
233 };
234
235
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 */
240
241
242 /* Codec indentifiers */
243 #define CAB_CODEC_RAW   0x00
244 #define CAB_CODEC_LZX   0x01
245 #define CAB_CODEC_MSZIP 0x02
246
247
248
249 /* Classes */
250
251 #ifndef CAB_READ_ONLY
252
253 class CCFDATAStorage {
254 public:
255     /* Default constructor */
256     CCFDATAStorage();
257     /* Default destructor */
258     virtual ~CCFDATAStorage();
259     ULONG Create(LPTSTR FileName);
260     ULONG Destroy();
261     ULONG Truncate();
262     ULONG Position();
263     ULONG Seek(LONG Position);
264     ULONG ReadBlock(PCFDATA Data, PVOID Buffer, PDWORD BytesRead);
265     ULONG WriteBlock(PCFDATA Data, PVOID Buffer, PDWORD BytesWritten);
266 private:
267     BOOL FileCreated;
268     HANDLE FileHandle;
269 };
270
271 #endif /* CAB_READ_ONLY */
272
273 class CCabinet {
274 public:
275     /* Default constructor */
276     CCabinet();
277     /* Default destructor */
278     virtual ~CCabinet();
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 */
296     ULONG Open();
297     /* Closes the current open cabinet file */
298     VOID Close();
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 */
309     ULONG NewCabinet();
310     /* Forces a new disk to be created */
311     ULONG NewDisk();
312     /* Forces a new folder to be created */
313     ULONG NewFolder();
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 */
321     ULONG CloseDisk();
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 */
329
330     /* Default event handlers */
331
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 */
346 private:
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
385     BOOL ReuseBlock;
386     TCHAR DestPath[MAX_PATH];
387     HANDLE FileHandle;
388     BOOL FileOpen;
389     CFHEADER CABHeader;
390     ULONG CabinetReserved;
391     ULONG FolderReserved;
392     ULONG DataReserved;
393     PCFFOLDER_NODE FolderListHead;
394     PCFFOLDER_NODE FolderListTail;
395     PCFFOLDER_NODE CurrentFolderNode;
396     PCFDATA_NODE CurrentDataNode;
397     PCFFILE_NODE FileListHead;
398     PCFFILE_NODE FileListTail;
399     CCABCodec *Codec;
400     ULONG CodecId;
401     BOOL CodecSelected;
402     PVOID InputBuffer;
403     PVOID CurrentIBuffer;       // Current offset in input buffer
404     DWORD CurrentIBufferSize;   // Bytes left in input buffer
405     PVOID OutputBuffer;
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;
410     BOOL RestartSearch;
411     DWORD LastFileOffset;       // Uncompressed offset of last extracted file
412 #ifndef CAB_READ_ONLY
413     DWORD LastBlockStart;       // Uncompressed offset of last block in folder
414     DWORD MaxDiskSize;
415     DWORD DiskSize;
416     DWORD PrevCabinetNumber;    // Previous cabinet number (where split file starts)
417     BOOL CreateNewDisk;
418     BOOL CreateNewFolder;
419
420     CCFDATAStorage *ScratchFile;
421     HANDLE SourceFile;
422     BOOL ContinueFile;
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 */
427 };
428
429 #endif /* __CABINET_H */
430
431 /* EOF */