📄 fdi.pas
字号:
{++
f d i . p a s
Copyright (c) 1997 Alexander Staubo, all rights reserved.
Abstract:
Translation of fdi.h, part of the Cabinet SDK.
Revision history:
06/07/1997 20:17 alexs 1.0
Autogenerated by htrans
26/12/1997 02:55 alexs 1.1
Fixed declarations of function callbacks, other minor stuff
--}
unit Fdi;
{$A+}
{$MINENUMSIZE 4}
{$WEAKPACKAGEUNIT ON}
interface
uses
Windows, SysUtils;
type
PVoid = Pointer;
USHORT = Word;
(*
* FDI.H -- File Decompression Interface
*
* Copyright (C) Microsoft Corporation 1993-1997
* All Rights Reserved.
*)
type
{ f }
TBYTE = Char;
{ b }
TUINT = Integer;
{ ui }
TUSHORT = Smallint;
{ us }
TULONG = Longint;
{ ul }
type
TCHECKSUM = Longint;
{ csum }
TUOFF = Longint;
{ uoff - uncompressed offset }
TCOFF = Longint;
{ coff - cabinet file offset }
{** ERF - Error structure
*
* This structure returns error information from FCI/FDI. The caller should
* not modify this structure.
}
type
TERF =
record
erfOper : Integer; // FCI/FDI error code -- see FDIERROR_XXX
// and FCIERR_XXX equates for details.
erfType : Integer; // Optional error value filled in by FCI/FDI.
// For FCI, this is usually the C run-time
// *errno* value.
fError : BOOL; // TRUE => error present
end;
{ erf }
PERF = ^TERF;
{ perf }
const
CB_MAX_CHUNK = 32768;
CB_MAX_DISK = $7ffffff;
CB_MAX_FILENAME = 256;
CB_MAX_CABINET_NAME = 256;
CB_MAX_CAB_PATH = 256;
CB_MAX_DISK_NAME = 256;
{** tcompXXX - Compression types
*
* These are passed to FCIAddFile(), and are also stored in the CFFOLDER
* structures in cabinet files.
*
* NOTE: We reserve bits for the TYPE, QUANTUM_LEVEL, and QUANTUM_MEM
* to provide room for future expansion. Since this value is stored
* in the CFDATA records in the cabinet file, we don't want to
* have to change the format for existing compression configurations
* if we add new ones in the future. This will allows us to read
* old cabinet files in the future.
}
type
TCOMP = Smallint;
{ tcomp }
const
tcompMASK_TYPE = $000F;
tcompTYPE_NONE = $0000;
tcompTYPE_MSZIP = $0001;
tcompTYPE_QUANTUM = $0002;
tcompTYPE_LZX = $0003;
tcompBAD = $000F;
tcompMASK_LZX_WINDOW = $1F00;
tcompLZX_WINDOW_LO = $0F00;
tcompLZX_WINDOW_HI = $1500;
tcompSHIFT_LZX_WINDOW = 8;
tcompMASK_QUANTUM_LEVEL = $00F0;
tcompQUANTUM_LEVEL_LO = $0010;
tcompQUANTUM_LEVEL_HI = $0070;
tcompSHIFT_QUANTUM_LEVEL = 4;
tcompMASK_QUANTUM_MEM = $1F00;
tcompQUANTUM_MEM_LO = $0A00;
tcompQUANTUM_MEM_HI = $1500;
tcompSHIFT_QUANTUM_MEM = 8;
tcompMASK_RESERVED = $E000;
(*
* Concepts:
* A *cabinet* file contains one or more *folders*. A folder contains
* one or more (pieces of) *files*. A folder is by definition a
* decompression unit, i.e., to extract a file from a folder, all of
* the data from the start of the folder up through and including the
* desired file must be read and decompressed.
*
* A folder can span one (or more) cabinet boundaries, and by implication
* a file can also span one (or more) cabinet boundaries. Indeed, more
* than one file can span a cabinet boundary, since FCI concatenates
* files together into a single data stream before compressing (actually,
* at most one file will span any one cabinet boundary, but FCI does
* not know which file this is, since the mapping from uncompressed bytes
* to compressed bytes is pretty obscure. Also, since FCI compresses
* in blocks of 32K (at present), any files with data in a 32K block that
* spans a cabinet boundary require FDI to read both cabinet files
* to get the two halves of the compressed block).
*
* Overview:
* The File Decompression Interface is used to simplify the reading of
* cabinet files. A setup program will proceed in a manner very
* similar to the pseudo code below. An FDI context is created, the
* setup program calls FDICopy() for each cabinet to be processed. For
* each file in the cabinet, FDICopy() calls a notification callback
* routine, asking the setup program if the file should be copied.
* This call-back approach is great because it allows the cabinet file
* to be read and decompressed in an optimal manner, and also makes FDI
* independent of the run-time environment -- FDI makes *no* C run-time
* calls whatsoever. All memory allocation and file I/O functions are
* passed into FDI by the client.
*
* main(...)
* {
* // Read INF file to construct list of desired files.
* // Ideally, these would be sorted in the same order as the
* // files appear in the cabinets, so that you can just walk
* // down the list in response to fdintCOPY_FILE notifications.
*
* // Construct list of required cabinets.
*
* hfdi = FDICreate(...); // Create FDI context
* For (cabinet in List of Cabinets) {
* FDICopy(hfdi,cabinet,fdiNotify,...); // Process each cabinet
* [#125]
* FDIDestroy(hfdi);
* ...
* [#125]
*
* // Notification callback function
* fdiNotify(fdint,...)
* {
* If (User Aborted) // Permit cancellation
* if (fdint == fdintCLOSE_FILE_INFO)
* close open file
* return -1;
* switch (fdint) {
* case fdintCOPY_FILE: // File to copy, maybe
* // Check file against list of desired files
* if want to copy file
* open destination file and return handle
* else
* return NULL; // Skip file
* case fdintCLOSE_FILE_INFO:
* close file
* set date, time, and attributes
*
* case fdintNEXT_CABINET:
* if not an error callback
* Tell FDI to use suggested directory name
* else
* Tell user what the problem was, and prompt
* for a new disk and/or path.
* if user aborts
* Tell FDI to abort
* else
* return to FDI to try another cabinet
*
* default:
* return 0; // more messages may be defined
* ...
* [#125]
*
* Error Handling Suggestions:
* Since you the client have passed in *all* of the functions that
* FDI uses to interact with the "outside" world, you are in prime
* position to understand and deal with errors.
*
* The general philosophy of FDI is to pass all errors back up to
* the client. FDI returns fairly generic error codes in the case
* where one of the callback functions (PFNOPEN, PFNREAD, etc.) fail,
* since it assumes that the callback function will save enough
* information in a static/global so that when FDICopy() returns
* fail, the client can examine this information and report enough
* detail about the problem that the user can take corrective action.
*
* For very specific errors (CORRUPT_CABINET, for example), FDI returns
* very specific error codes.
*
* THE BEST POLICY IS FOR YOUR CALLBACK ROUTINES TO AVOID RETURNING
* ERRORS TO FDI!
*
* Examples:
* (1) If the disk is getting full, instead of returning an error
* from your PFNWRITE function, you should -- inside your
* PFNWRITE function -- put up a dialog telling the user to free
* some disk space.
* (2) When you get the fdintNEXT_CABINET notification, you should
* verify that the cabinet you return is the correct one (call
* FDIIsCabinet(), and make sure the setID matches the one for
* the current cabinet specified in the fdintCABINET_INFO, and
* that the disk number is one greater.
*
* NOTE: FDI will continue to call fdintNEXT_CABINET until it
* gets the cabinet it wants, or until you return -1
* to abort the FDICopy() call.
*
* The documentation below on the FDI error codes provides explicit
* guidance on how to avoid each error.
*
* If you find you must return a failure to FDI from one of your
* callback functions, then FDICopy() frees all resources it allocated
* and closes all files. If you can figure out how to overcome the
* problem, you can call FDICopy() again on the last cabinet, and
* skip any files that you already copied. But, note that FDI does
* *not* maintain any state between FDICopy() calls, other than possibly
* memory allocated for the decompressor.
*
* See FDIERROR for details on FDI error codes and recommended actions.
*
*
* Progress Indicator Suggestions:
* As above, all of the file I/O functions are supplied by you. So,
* updating a progress indicator is very simple. You keep track of
* the target files handles you have opened, along with the uncompressed
* size of the target file. When you see writes to the handle of a
* target file, you use the write count to update your status!
* Since this method is available, there is no separate callback from
* FDI just for progess indication.
*)
{** FDIERROR - Error codes returned in erf.erfOper field
*
* In general, FDI will only fail if one of the passed in memory or
* file I/O functions fails. Other errors are pretty unlikely, and are
* caused by corrupted cabinet files, passing in a file which is not a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -