summaryrefslogtreecommitdiffstats
path: root/public/sdk/inc/diamondd.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--public/sdk/inc/diamondd.h1110
1 files changed, 1110 insertions, 0 deletions
diff --git a/public/sdk/inc/diamondd.h b/public/sdk/inc/diamondd.h
new file mode 100644
index 000000000..981eb5fc0
--- /dev/null
+++ b/public/sdk/inc/diamondd.h
@@ -0,0 +1,1110 @@
+/*** types.h - Common defines for FCI/FDI stuff -- goes into FCI/FDI.H
+ *
+ * Microsoft Confidential
+ * Copyright (C) Microsoft Corporation 1993-1994
+ * All Rights Reserved.
+ *
+ * History:
+ * 03-Mar-1993 chuckst Merged from other files
+ * 08-Mar-1994 bens Changed symbol to control recursive include
+ * 09-Mar-1994 bens Cleanups for RESERVE modifications
+ * 16-Mar-1994 bens Nuke padlong()
+ * 21-Mar-1994 bens Spruce up comments
+ * 22-Mar-1994 bens Add BIT16 test so we can build 16 or 32 bit!
+ * 26-May-1994 bens Added Quantum compression definitions
+ */
+
+#ifndef INCLUDED_TYPES_FCI_FDI
+#define INCLUDED_TYPES_FCI_FDI 1
+
+
+#ifdef BIT16
+
+//** 16-bit build
+#ifndef HUGE
+#define HUGE huge
+#endif
+
+#ifndef FAR
+#define FAR far
+#endif
+
+#else // !BIT16
+
+//** Define away for 32-bit (NT/Chicago) build
+#ifndef HUGE
+#define HUGE
+#endif
+
+#ifndef FAR
+#define FAR
+#endif
+
+#endif // !BIT16
+
+
+#ifndef DIAMONDAPI
+#define DIAMONDAPI __cdecl
+#endif
+
+
+//** Specify structure packing explicitly for clients of FDI
+#include <pshpack4.h>
+
+//** Don't redefine types defined in Win16 WINDOWS.H (_INC_WINDOWS)
+// or Win32 WINDOWS.H (_WINDOWS_)
+//
+#if !defined(_INC_WINDOWS) && !defined(_WINDOWS_)
+typedef int BOOL; /* f */
+typedef unsigned char BYTE; /* b */
+typedef unsigned int UINT; /* ui */
+typedef unsigned short USHORT; /* us */
+typedef unsigned long ULONG; /* ul */
+#endif // _INC_WINDOWS
+
+typedef unsigned long CHECKSUM; /* csum */
+
+typedef unsigned long UOFF; /* uoff - uncompressed offset */
+typedef unsigned long COFF; /* coff - cabinet file offset */
+
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+/*** ERF - Error structure
+ *
+ * This structure returns error information from FCI/FDI. The caller should
+ * not modify this structure.
+ */
+typedef struct {
+ int erfOper; // FCI/FDI error code -- see FDIERROR_XXX
+ // and FCIERR_XXX equates for details.
+
+ int erfType; // Optional error value filled in by FCI/FDI.
+ // For FCI, this is usually the C run-time
+ // *errno* value.
+
+ BOOL fError; // TRUE => error present
+} ERF; /* erf */
+typedef ERF FAR *PERF; /* perf */
+
+#ifdef _DEBUG
+// don't hide statics from map during debugging
+#define STATIC
+#else // !DEBUG
+#define STATIC static
+#endif // !DEBUG
+
+#define CB_MAX_CHUNK 32768U
+#define CB_MAX_DISK 0x7ffffffL
+#define CB_MAX_FILENAME 256
+#define CB_MAX_CABINET_NAME 256
+#define CB_MAX_CAB_PATH 256
+#define CB_MAX_DISK_NAME 256
+
+
+/*** FNALLOC - Memory Allocation
+ * FNFREE - Memory Free
+ *
+ * These are modeled after the C run-time routines malloc() and free()
+ * (16-bit clients please note -- the size is a ULONG, so you may need
+ * to write a wrapper routine for halloc!). FDI expects error
+ * handling to be identical to these C run-time routines.
+ *
+ * As long as you faithfully copy the semantics of malloc() and free(),
+ * you can supply any functions you like!
+ *
+ * WARNING: You should never assume anything about the sequence of
+ * PFNALLOC and PFNFREE calls -- incremental releases of
+ * Diamond/FDI may have radically different numbers of
+ * PFNALLOC calls and allocation sizes!
+ */
+typedef void HUGE * (FAR DIAMONDAPI *PFNALLOC)(ULONG cb); /* pfna */
+#define FNALLOC(fn) void HUGE * FAR DIAMONDAPI fn(ULONG cb)
+
+typedef void (FAR DIAMONDAPI *PFNFREE)(void HUGE *pv); /* pfnf */
+#define FNFREE(fn) void FAR DIAMONDAPI fn(void HUGE *pv)
+
+
+/*** tcompXXX - Diamond 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.
+ */
+
+typedef unsigned short TCOMP; /* tcomp */
+
+#define tcompMASK_TYPE 0x000F // Mask for compression type
+#define tcompTYPE_NONE 0x0000 // No compression
+#define tcompTYPE_MSZIP 0x0001 // MSZIP
+#define tcompTYPE_QUANTUM 0x0002 // Quantum
+#define tcompBAD 0x000F // Unspecified compression type
+
+#define tcompMASK_QUANTUM_LEVEL 0x00F0 // Mask for Quantum Compression Level
+#define tcompQUANTUM_LEVEL_LO 0x0010 // Lowest Quantum Level (1)
+#define tcompQUANTUM_LEVEL_HI 0x0070 // Highest Quantum Level (7)
+#define tcompSHIFT_QUANTUM_LEVEL 4 // Amount to shift over to get int
+
+#define tcompMASK_QUANTUM_MEM 0x1F00 // Mask for Quantum Compression Memory
+#define tcompQUANTUM_MEM_LO 0x0A00 // Lowest Quantum Memory (10)
+#define tcompQUANTUM_MEM_HI 0x1500 // Highest Quantum Memory (21)
+#define tcompSHIFT_QUANTUM_MEM 8 // Amount to shift over to get int
+
+#define tcompMASK_RESERVED 0xE000 // Reserved bits (high 3 bits)
+
+
+
+#define CompressionTypeFromTCOMP(tc) \
+ ((tc) & tcompMASK_TYPE)
+
+#define CompressionLevelFromTCOMP(tc) \
+ (((tc) & tcompMASK_QUANTUM_LEVEL) >> tcompSHIFT_QUANTUM_LEVEL)
+
+#define CompressionMemoryFromTCOMP(tc) \
+ (((tc) & tcompMASK_QUANTUM_MEM) >> tcompSHIFT_QUANTUM_MEM)
+
+#define TCOMPfromTypeLevelMemory(t,l,m) \
+ (((m) << tcompSHIFT_QUANTUM_MEM ) | \
+ ((l) << tcompSHIFT_QUANTUM_LEVEL) | \
+ ( t ))
+
+
+//** Revert to default structure packing
+#include <poppack.h>
+
+#endif // !INCLUDED_TYPES_FCI_FDI
+/*** fdi_int.h - Diamond File Decompression Interface definitions
+ *
+ * Microsoft Confidential
+ * Copyright (C) Microsoft Corporation 1993-1994
+ * All Rights Reserved.
+ *
+ * Author:
+ * Chuck Strouss, Benjamin W. Slivka
+ *
+ * History:
+ * 30-Nov-1993 chuckst Created
+ * 21-Dec-1993 bens Updated with comments from 12/21/93 design review
+ * 09-Mar-1994 bens Add new error code
+ * 17-Mar-1994 bens Specify structure packing explicitly
+ * 21-Mar-1994 bens Spruce up comments
+ * 25-Mar-1994 bens Add fdintCABINET_INFO notification
+ * 31-Mar-1994 bens Clarify handling of open files when errors occur
+ * 01-Apr-1994 bens Add FDIIsCabinet() function.
+ * 07-Apr-1994 bens Add Decryption interfaces; remove fdintPROGRESS
+ * 11-Apr-1994 bens Add more guidance on how to respond to FDI errors.
+ * 13-Apr-1994 bens Add date & time & attribs to fdintCOPY_FILE
+ * 18-Apr-1994 bens Changed CDECL to DIAMONDAPI
+ * 05-May-1994 bens Clarified error handling (billhu/alanr/migueldc)
+ * 11-May-1994 bens Added setId/iCabinet to fdintNEXT_CABINET
+ * 07-Jul-1994 bens Support Quantum virtual file -- PLEASE note the
+ * comments about PFNOPEN/PFNCLOSE changes, and
+ * about reserving memory, if necessary, before
+ * calling FDICreate()!
+ * 19-Aug-1994 bens Add cpuType parameter to FDICreate().
+ * 03-Apr-1995 jeffwe Added chaining indicators to FDICABINETINFO
+ *
+ *
+ * ATTENTION:
+ * This is the only documentation on the Diamond File Decompression
+ * Interface (FDI). Please read it carefully, as there are some subtle
+ * points in FDI that are carefully explained below.
+ *
+ * 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 Diamond concatenates
+ * files together into a single data stream before compressing (actually,
+ * at most one file will span any one cabinet boundary, but Diamond does
+ * not know which file this is, since the mapping from uncompressed bytes
+ * to compressed bytes is pretty obscure. Also, since Diamond compresses
+ * in blocks of 32K (at present), any files with data in a 32K block that
+ * spans a cabinet boundary require Diamond 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
+ * Diamond 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
+ * }
+ * FDIDestroy(hfdi);
+ * ...
+ * }
+ *
+ * // 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
+ * //NOTE: Be sure to see the (sample) code in EXTRACT.C
+ * // for an example of how to do this!
+ * ...
+ * }
+ *
+ * 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.
+ */
+
+#ifndef INCLUDED_FDI
+#define INCLUDED_FDI 1
+
+//** Specify structure packing explicitly for clients of FDI
+#include <pshpack4.h>
+
+
+/*** 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
+ * cabinet file, or cabinet files out of order.
+ *
+ * Description: Summary of error.
+ * Cause: List of possible causes of this error.
+ * Response: How client might respond to this error, or avoid it in
+ * the first place.
+ */
+typedef enum {
+ FDIERROR_NONE,
+ // Description: No error
+ // Cause: Function was successfull.
+ // Response: Keep going!
+
+ FDIERROR_CABINET_NOT_FOUND,
+ // Description: Cabinet not found
+ // Cause: Bad file name or path passed to FDICopy(), or returned
+ // to fdintNEXT_CABINET.
+ // Response: To prevent this error, validate the existence of the
+ // the cabinet *before* passing the path to FDI.
+
+ FDIERROR_NOT_A_CABINET,
+ // Description: Cabinet file does not have the correct format
+ // Cause: File passed to to FDICopy(), or returned to
+ // fdintNEXT_CABINET, is too small to be a cabinet file,
+ // or does not have the cabinet signature in its first
+ // four bytes.
+ // Response: To prevent this error, call FDIIsCabinet() to check a
+ // cabinet before calling FDICopy() or returning the
+ // cabinet path to fdintNEXT_CABINET.
+
+ FDIERROR_UNKNOWN_CABINET_VERSION,
+ // Description: Cabinet file has an unknown version number.
+ // Cause: File passed to to FDICopy(), or returned to
+ // fdintNEXT_CABINET, has what looks like a cabinet file
+ // header, but the version of the cabinet file format
+ // is not one understood by this version of FDI. The
+ // erf.erfType field is filled in with the version number
+ // found in the cabinet file.
+ // Response: To prevent this error, call FDIIsCabinet() to check a
+ // cabinet before calling FDICopy() or returning the
+ // cabinet path to fdintNEXT_CABINET.
+
+ FDIERROR_CORRUPT_CABINET,
+ // Description: Cabinet file is corrupt
+ // Cause: FDI returns this error any time it finds a problem
+ // with the logical format of a cabinet file, and any
+ // time one of the passed-in file I/O calls fails when
+ // operating on a cabinet (PFNOPEN, PFNSEEK, PFNREAD,
+ // or PFNCLOSE). The client can distinguish these two
+ // cases based upon whether the last file I/O call
+ // failed or not.
+ // Response: Assuming this is not a real corruption problem in
+ // a cabinet file, the file I/O functions could attempt
+ // to do retries on failure (for example, if there is a
+ // temporary network connection problem). If this does
+ // not work, and the file I/O call has to fail, then the
+ // FDI client will have to clean up and call the
+ // FDICopy() function again.
+
+ FDIERROR_ALLOC_FAIL,
+ // Description: Could not allocate enough memory
+ // Cause: FDI tried to allocate memory with the PFNALLOC
+ // function, but it failed.
+ // Response: If possible, PFNALLOC should take whatever steps
+ // are possible to allocate the memory requested. If
+ // memory is not immediately available, it might post a
+ // dialog asking the user to free memory, for example.
+ // Note that the bulk of FDI's memory allocations are
+ // made at FDICreate() time and when the first cabinet
+ // file is opened during FDICopy().
+
+ FDIERROR_BAD_COMPR_TYPE,
+ // Description: Unknown compression type in a cabinet folder
+ // Cause: [Should never happen.] A folder in a cabinet has an
+ // unknown compression type. This is probably caused by
+ // a mismatch between the version of Diamond used to
+ // create the cabinet and the FDI. LIB used to read the
+ // cabinet.
+ // Response: Abort.
+
+ FDIERROR_MDI_FAIL,
+ // Description: Failure decompressing data from a cabinet file
+ // Cause: The decompressor found an error in the data coming
+ // from the file cabinet. The cabinet file was corrupted.
+ // [11-Apr-1994 bens When checksuming is turned on, this
+ // error should never occur.]
+ // Response: Probably should abort; only other choice is to cleanup
+ // and call FDICopy() again, and hope there was some
+ // intermittent data error that will not reoccur.
+
+ FDIERROR_TARGET_FILE,
+ // Description: Failure writing to target file
+ // Cause: FDI returns this error any time it gets an error back
+ // from one of the passed-in file I/O calls fails when
+ // writing to a file being extracted from a cabinet.
+ // Response: To avoid or minimize this error, the file I/O functions
+ // could attempt to avoid failing. A common cause might
+ // be disk full -- in this case, the PFNWRITE function
+ // could have a check for free space, and put up a dialog
+ // asking the user to free some disk space.
+
+ FDIERROR_RESERVE_MISMATCH,
+ // Description: Cabinets in a set do not have the same RESERVE sizes
+ // Cause: [Should never happen]. FDI requires that the sizes of
+ // the per-cabinet, per-folder, and per-data block
+ // RESERVE sections be consistent across all the cabinet
+ // in a set. Diamond will only generate cabinet sets
+ // with these properties.
+ // Response: Abort.
+
+ FDIERROR_WRONG_CABINET,
+ // Description: Cabinet returned on fdintNEXT_CABINET is incorrect
+ // Cause: NOTE: THIS ERROR IS NEVER RETURNED BY FDICopy()!
+ // Rather, FDICopy() keeps calling the fdintNEXT_CABINET
+ // callback until either the correct cabinet is specified,
+ // or you return ABORT.
+ // When FDICopy() is extracting a file that crosses a
+ // cabinet boundary, it calls fdintNEXT_CABINET to ask
+ // for the path to the next cabinet. Not being very
+ // trusting, FDI then checks to make sure that the
+ // correct continuation cabinet was supplied! It does
+ // this by checking the "setID" and "iCabinet" fields
+ // in the cabinet. When DIAMOND.EXE creates a set of
+ // cabinets, it constructs the "setID" using the sum
+ // of the bytes of all the destination file names in
+ // the cabinet set. FDI makes sure that the 16-bit
+ // setID of the continuation cabinet matches the
+ // cabinet file just processed. FDI then checks that
+ // the cabinet number (iCabinet) is one more than the
+ // cabinet number for the cabinet just processed.
+ // Response: You need code in your fdintNEXT_CABINET (see below)
+ // handler to do retries if you get recalled with this
+ // error. See the sample code (EXTRACT.C) to see how
+ // this should be handled.
+
+ FDIERROR_USER_ABORT,
+ // Description: FDI aborted.
+ // Cause: An FDI callback returnd -1 (usually).
+ // Response: Up to client.
+
+} FDIERROR;
+
+
+/*** HFDI - Handle to an FDI context
+ *
+ * FDICreate() creates this, and it must be passed to all other FDI
+ * functions.
+ */
+typedef void FAR *HFDI; /* hfdi */
+
+
+/*** FDICABINETINFO - Information about a cabinet
+ *
+ */
+typedef struct {
+ long cbCabinet; // Total length of cabinet file
+ USHORT cFolders; // Count of folders in cabinet
+ USHORT cFiles; // Count of files in cabinet
+ USHORT setID; // Cabinet set ID
+ USHORT iCabinet; // Cabinet number in set (0 based)
+ BOOL fReserve; // TRUE => RESERVE present in cabinet
+ BOOL hasprev; // TRUE => Cabinet is chained prev
+ BOOL hasnext; // TRUE => Cabinet is chained next
+} FDICABINETINFO; /* fdici */
+typedef FDICABINETINFO FAR *PFDICABINETINFO; /* pfdici */
+
+
+/*** FDIDECRYPTTYPE - PFNFDIDECRYPT command types
+ *
+ */
+typedef enum {
+ fdidtNEW_CABINET, // New cabinet
+ fdidtNEW_FOLDER, // New folder
+ fdidtDECRYPT, // Decrypt a data block
+} FDIDECRYPTTYPE; /* fdidt */
+
+
+/*** FDIDECRYPT - Data for PFNFDIDECRYPT function
+ *
+ */
+typedef struct {
+ FDIDECRYPTTYPE fdidt; // Command type (selects union below)
+ void FAR *pvUser; // Decryption context
+ union {
+ struct { // fdidtNEW_CABINET
+ void FAR *pHeaderReserve; // RESERVE section from CFHEADER
+ USHORT cbHeaderReserve; // Size of pHeaderReserve
+ USHORT setID; // Cabinet set ID
+ int iCabinet; // Cabinet number in set (0 based)
+ } cabinet;
+
+ struct { // fdidtNEW_FOLDER
+ void FAR *pFolderReserve; // RESERVE section from CFFOLDER
+ USHORT cbFolderReserve; // Size of pFolderReserve
+ USHORT iFolder; // Folder number in cabinet (0 based)
+ } folder;
+
+ struct { // fdidtDECRYPT
+ void FAR *pDataReserve; // RESERVE section from CFDATA
+ USHORT cbDataReserve; // Size of pDataReserve
+ void FAR *pbData; // Data buffer
+ USHORT cbData; // Size of data buffer
+ BOOL fSplit; // TRUE if this is a split data block
+ USHORT cbPartial; // 0 if this is not a split block, or
+ // the first piece of a split block;
+ // Greater than 0 if this is the
+ // second piece of a split block.
+ } decrypt;
+ };
+} FDIDECRYPT; /* fdid */
+typedef FDIDECRYPT FAR *PFDIDECRYPT; /* pfdid */
+
+
+/*** PFNFDIDECRYPT - FDI Decryption callback
+ *
+ * If this function is passed on the FDICopy() call, then FDI calls it
+ * at various times to update the decryption state and to decrypt FCDATA
+ * blocks.
+ *
+ * Common Entry Conditions:
+ * pfdid->fdidt - Command type
+ * pfdid->pvUser - pvUser value from FDICopy() call
+ *
+ * fdidtNEW_CABINET: //** Notification of a new cabinet
+ * Entry:
+ * pfdid->cabinet.
+ * pHeaderReserve - RESERVE section from CFHEADER
+ * cbHeaderReserve - Size of pHeaderReserve
+ * setID - Cabinet set ID
+ * iCabinet - Cabinet number in set (0 based)
+ * Exit-Success:
+ * returns anything but -1;
+ * Exit-Failure:
+ * returns -1; FDICopy() is aborted.
+ * Notes:
+ * (1) This call allows the decryption code to pick out any information
+ * from the cabinet header reserved area (placed there by DIACRYPT)
+ * needed to perform decryption. If there is no such information,
+ * this call would presumably be ignored.
+ * (2) This call is made very soon after fdintCABINET_INFO.
+ *
+ * fdidtNEW_FOLDER: //** Notification of a new folder
+ * Entry:
+ * pfdid->folder.
+ * pFolderReserve - RESERVE section from CFFOLDER
+ * cbFolderReserve - Size of pFolderReserve
+ * iFolder - Folder number in cabinet (0 based)
+ * Exit-Success:
+ * returns anything but -1;
+ * Exit-Failure:
+ * returns -1; FDICopy() is aborted.
+ * Notes:
+ * This call allows the decryption code to pick out any information
+ * from the folder reserved area (placed there by DIACRYPT) needed
+ * to perform decryption. If there is no such information, this
+ * call would presumably be ignored.
+ *
+ * fdidtDECRYPT: //** Decrypt a data buffer
+ * Entry:
+ * pfdid->folder.
+ * pDataReserve - RESERVE section for this CFDATA block
+ * cbDataReserve - Size of pDataReserve
+ * pbData - Data buffer
+ * cbData - Size of data buffer
+ * fSplit - TRUE if this is a split data block
+ * cbPartial - 0 if this is not a split block, or the first
+ * piece of a split block; Greater than 0 if
+ * this is the second piece of a split block.
+ * Exit-Success:
+ * returns TRUE;
+ * Exit-Failure:
+ * returns FALSE; error during decrypt
+ * returns -1; FDICopy() is aborted.
+ * Notes:
+ * Diamond will split CFDATA blocks across cabinet boundaries if
+ * necessary. To provide maximum flexibility, FDI will call the
+ * fdidtDECRYPT function twice on such split blocks, once when
+ * the first portion is read, and again when the second portion
+ * is read. And, of course, most data blocks will not be split.
+ * So, there are three cases:
+ *
+ * 1) fSplit == FALSE
+ * You have the entire data block, so decrypt it.
+ *
+ * 2) fSplit == TRUE, cbPartial == 0
+ * This is the first portion of a split data block, so cbData
+ * is the size of this portion. You can either choose to decrypt
+ * this piece, or ignore this call and decrypt the full CFDATA
+ * block on the next (second) fdidtDECRYPT call.
+ *
+ * 3) fSplit == TRUE, cbPartial > 0
+ * This is the second portion of a split data block (indeed,
+ * cbPartial will have the same value as cbData did on the
+ * immediately preceeding fdidtDECRYPT call!). If you decrypted
+ * the first portion on the first call, then you can decrypt the
+ * second portion now. If you ignored the first call, then you
+ * can decrypt the entire buffer.
+ * NOTE: pbData points to the second portion of the split data
+ * block in this case, *not* the entire data block. If
+ * you want to wait until the second piece to decrypt the
+ * *entire* block, pbData-cbPartial is the address of the
+ * start of the whole block, and cbData+cbPartial is its
+ * size.
+ */
+typedef int (FAR DIAMONDAPI *PFNFDIDECRYPT)(PFDIDECRYPT pfdid); /* pfnfdid */
+#define FNFDIDECRYPT(fn) int FAR DIAMONDAPI fn(PFDIDECRYPT pfdid)
+
+
+/*** FDINOTIFICATION - Notification structure for PFNFDINOTIFY
+ *
+ * See the FDINOTIFICATIONTYPE definition for information on usage and
+ * meaning of these fields.
+ */
+typedef struct {
+// long fields
+ long cb;
+ char FAR *psz1;
+ char FAR *psz2;
+ char FAR *psz3; // Points to a 256 character buffer
+ void FAR *pv; // Value for client
+
+// int fields
+ int hf;
+
+// short fields
+ USHORT date;
+ USHORT time;
+ USHORT attribs;
+
+ USHORT setID; // Cabinet set ID
+ USHORT iCabinet; // Cabinet number (0-based)
+
+ FDIERROR fdie;
+} FDINOTIFICATION, FAR *PFDINOTIFICATION; /* fdin, pfdin */
+
+
+/*** FDINOTIFICATIONTYPE - FDICopy notification types
+ *
+ * The notification function for FDICopy can be called with the following
+ * values for the fdint parameter. In all cases, the pfdin->pv field is
+ * filled in with the value of the pvUser argument passed in to FDICopy().
+ *
+ * A typical sequence of calls will be something like this:
+ * fdintCABINET_INFO // Info about the cabinet
+ * fdintPARTIAL_FILE // Only if this is not the first cabinet, and
+ * // one or more files were continued from the
+ * // previous cabinet.
+ * ...
+ * fdintPARTIAL_FILE
+ * fdintCOPY_FILE // The first file that starts in this cabinet
+ * ...
+ * fdintCOPY_FILE // Now let's assume you want this file...
+ * // PFNWRITE called multiple times to write to this file.
+ * fdintCLOSE_FILE_INFO // File done, set date/time/attributes
+ *
+ * fdintCOPY_FILE // Now let's assume you want this file...
+ * // PFNWRITE called multiple times to write to this file.
+ * fdintNEXT_CABINET // File was continued to next cabinet!
+ * fdintCABINET_INFO // Info about the new cabinet
+ * // PFNWRITE called multiple times to write to this file.
+ * fdintCLOSE_FILE_INFO // File done, set date/time/attributes
+ * ...
+ *
+ * fdintCABINET_INFO:
+ * Called exactly once for each cabinet opened by FDICopy(), including
+ * continuation cabinets opened due to file(s) spanning cabinet
+ * boundaries. Primarily intended to permit EXTRACT.EXE to
+ * automatically select the next cabinet in a cabinet sequence even if
+ * not copying files that span cabinet boundaries.
+ * Entry:
+ * pfdin->psz1 = name of next cabinet
+ * pfdin->psz2 = name of next disk
+ * pfdin->psz3 = cabinet path name
+ * pfdin->setID = cabinet set ID (a random 16-bit number)
+ * pfdin->iCabinet = Cabinet number within cabinet set (0-based)
+ * Exit-Success:
+ * Return anything but -1
+ * Exit-Failure:
+ * Returns -1 => Abort FDICopy() call
+ * Notes:
+ * This call is made *every* time a new cabinet is examined by
+ * FDICopy(). So if "foo2.cab" is examined because a file is
+ * continued from "foo1.cab", and then you call FDICopy() again
+ * on "foo2.cab", you will get *two* fdintCABINET_INFO calls all
+ * told.
+ *
+ * fdintCOPY_FILE:
+ * Called for each file that *starts* in the current cabinet, giving
+ * the client the opportunity to request that the file be copied or
+ * skipped.
+ * Entry:
+ * pfdin->psz1 = file name in cabinet
+ * pfdin->cb = uncompressed size of file
+ * pfdin->date = file date
+ * pfdin->time = file time
+ * pfdin->attribs = file attributes
+ * Exit-Success:
+ * Return non-zero file handle for destination file; FDI writes
+ * data to this file use the PFNWRITE function supplied to FDICreate,
+ * and then calls fdintCLOSE_FILE_INFO to close the file and set
+ * the date, time, and attributes. NOTE: This file handle returned
+ * must also be closeable by the PFNCLOSE function supplied to
+ * FDICreate, since if an error occurs while writing to this handle,
+ * FDI will use the PFNCLOSE function to close the file so that the
+ * client may delete it.
+ * Exit-Failure:
+ * Returns 0 => Skip file, do not copy
+ * Returns -1 => Abort FDICopy() call
+ *
+ * fdintCLOSE_FILE_INFO:
+ * Called after all of the data has been written to a target file.
+ * This function must close the file and set the file date, time,
+ * and attributes.
+ * Entry:
+ * pfdin->psz1 = file name in cabinet
+ * pfdin->hf = file handle
+ * pfdin->date = file date
+ * pfdin->time = file time
+ * pfdin->attribs = file attributes
+ * pfdin->cb = Run After Extract (0 - don't run, 1 Run)
+ * Exit-Success:
+ * Returns TRUE
+ * Exit-Failure:
+ * Returns FALSE, or -1 to abort;
+ *
+ * IMPORTANT NOTE IMPORTANT:
+ * pfdin->cb is overloaded to no longer be the size of
+ * the file but to be a binary indicated run or not
+ *
+ * IMPORTANT NOTE:
+ * FDI assumes that the target file was closed, even if this
+ * callback returns failure. FDI will NOT attempt to use
+ * the PFNCLOSE function supplied on FDICreate() to close
+ * the file!
+ *
+ * fdintPARTIAL_FILE:
+ * Called for files at the front of the cabinet that are CONTINUED
+ * from a previous cabinet. This callback occurs only when FDICopy is
+ * started on second or subsequent cabinet in a series that has files
+ * continued from a previous cabinet.
+ * Entry:
+ * pfdin->psz1 = file name of file CONTINUED from a PREVIOUS cabinet
+ * pfdin->psz2 = name of cabinet where file starts
+ * pfdin->psz3 = name of disk where file starts
+ * Exit-Success:
+ * Return anything other than -1; enumeration continues
+ * Exit-Failure:
+ * Returns -1 => Abort FDICopy() call
+ *
+ * fdintNEXT_CABINET:
+ * This function is *only* called when fdintCOPY_FILE was told to copy
+ * a file in the current cabinet that is continued to a subsequent
+ * cabinet file. It is important that the cabinet path name (psz3)
+ * be validated before returning! This function should ensure that
+ * the cabinet exists and is readable before returning. So, this
+ * is the function that should, for example, issue a disk change
+ * prompt and make sure the cabinet file exists.
+ *
+ * When this function returns to FDI, FDI will check that the setID
+ * and iCabinet match the expected values for the next cabinet.
+ * If not, FDI will continue to call this function until the correct
+ * cabinet file is specified, or until this function returns -1 to
+ * abort the FDICopy() function. pfdin->fdie is set to
+ * FDIERROR_WRONG_CABINET to indicate this case.
+ *
+ * If you *haven't* ensured that the cabinet file is present and
+ * readable, or the cabinet file has been damaged, pfdin->fdie will
+ * receive other appropriate error codes:
+ *
+ * FDIERROR_CABINET_NOT_FOUND
+ * FDIERROR_NOT_A_CABINET
+ * FDIERROR_UNKNOWN_CABINET_VERSION
+ * FDIERROR_CORRUPT_CABINET
+ * FDIERROR_BAD_COMPR_TYPE
+ * FDIERROR_RESERVE_MISMATCH
+ * FDIERROR_WRONG_CABINET
+ *
+ * Entry:
+ * pfdin->psz1 = name of next cabinet where current file is continued
+ * pfdin->psz2 = name of next disk where current file is continued
+ * pfdin->psz3 = cabinet path name; FDI concatenates psz3 with psz1
+ * to produce the fully-qualified path for the cabinet
+ * file. The 256-byte buffer pointed at by psz3 may
+ * be modified, but psz1 may not!
+ * pfdin->fdie = FDIERROR_WRONG_CABINET if the previous call to
+ * fdintNEXT_CABINET specified a cabinet file that
+ * did not match the setID/iCabinet that was expected.
+ * Exit-Success:
+ * Return anything but -1
+ * Exit-Failure:
+ * Returns -1 => Abort FDICopy() call
+ * Notes:
+ * This call is almost always made when a target file is open and
+ * being written to, and the next cabinet is needed to get more
+ * data for the file.
+ */
+typedef enum {
+ fdintCABINET_INFO, // General information about cabinet
+ fdintPARTIAL_FILE, // First file in cabinet is continuation
+ fdintCOPY_FILE, // File to be copied
+ fdintCLOSE_FILE_INFO, // close the file, set relevant info
+ fdintNEXT_CABINET, // File continued to next cabinet
+} FDINOTIFICATIONTYPE; /* fdint */
+
+typedef int (FAR DIAMONDAPI *PFNFDINOTIFY)(FDINOTIFICATIONTYPE fdint,
+ PFDINOTIFICATION pfdin); /* pfnfdin */
+
+#define FNFDINOTIFY(fn) int FAR DIAMONDAPI fn(FDINOTIFICATIONTYPE fdint, \
+ PFDINOTIFICATION pfdin)
+
+
+/*** PFNOPEN - File I/O callbacks for FDI
+ * PFNREAD
+ * PFNWRITE
+ * PFNCLOSE
+ * PFNSEEK
+ *
+ * These are modeled after the C run-time routines _open, _read,
+ * _write, _close, and _lseek. The values for the PFNOPEN oflag
+ * and pmode calls are those defined for _open. FDI expects error
+ * handling to be identical to these C run-time routines.
+ *
+ * As long as you faithfully copy these aspects, you can supply
+ * any functions you like!
+ *
+ *
+ * SPECIAL NOTE FOR QUANTUM DECOMPRESSION:
+ * When using Quantum compression, at compress time (with Diamond)
+ * you specify how much memory Quantum requires at *decompress* time
+ * to store the decompression history buffer. This can be as large
+ * as *2Mb*, and in an MS-DOS environment, for example, this much
+ * memory may not be available (certainly not under 640K!). To permit
+ * large CompressionMemory settings on any machine, the Quantum
+ * decompressor will attempt to create a "spill file" if there is not
+ * sufficient memory available.
+ *
+ * For PFNOPEN, a special pszFile parameter is passed to indicate that
+ * a temporary "spill file" is requested. The name passed is "*", and
+ * you should cast the pszFile parameter to an FDISPILLFILE pointer,
+ * and get the requested file size. You then need to create a file
+ * of the specified size with read/write access, save the file name and
+ * handle for later use by PFNCLOSE, and then return the handle. If
+ * you cannot create the file of the specified size, you should return
+ * an error (-1). This file should be placed on a fast local hard disk,
+ * to maximize the speed of decompression.
+ *
+ * For PFNCLOSE, you should check the handle to see if it the spill file
+ * created previously by PFNOPEN (FDI will create at most one spill file
+ * per FDICreate() call). If it is the spill file handle, you should
+ * close the handle and then delete the file, using the file name you
+ * saved when you created the spill file in PFNOPEN.
+ *
+ * WARNING: You should never assume you know what file is being
+ * opened at any one point in time! FDI will usually
+ * stick to opening cabinet files, but it is possible
+ * that in a future implementation it may open temporary
+ * files or open cabinet files in a different order.
+ *
+ * Notes for Memory Mapped File fans:
+ * You can write wrapper routines to allow FDI to work on memory
+ * mapped files. You'll have to create your own "handle" type so that
+ * you can store the base memory address of the file and the current
+ * seek position, and then you'll allocate and fill in one of these
+ * structures and return a pointer to it in response to the PFNOPEN
+ * call and the fdintCOPY_FILE call. Your PFNREAD and PFNWRITE
+ * functions will do memcopy(), and update the seek position in your
+ * "handle" structure. PFNSEEK will just change the seek position
+ * in your "handle" structure.
+ */
+typedef int (FAR DIAMONDAPI *PFNOPEN) (char FAR *pszFile, int oflag, int pmode);
+typedef UINT (FAR DIAMONDAPI *PFNREAD) (int hf, void FAR *pv, UINT cb);
+typedef UINT (FAR DIAMONDAPI *PFNWRITE)(int hf, void FAR *pv, UINT cb);
+typedef int (FAR DIAMONDAPI *PFNCLOSE)(int hf);
+typedef long (FAR DIAMONDAPI *PFNSEEK) (int hf, long dist, int seektype);
+
+
+#pragma pack (1)
+
+/** FDISPILLFILE - Pass as pszFile on PFNOPEN to create spill file
+ *
+ * ach - A two byte string to signal to PFNOPEN that a spill file is
+ * requested. Value is '*','\0'.
+ * cbFile - Required spill file size, in bytes.
+ */
+typedef struct {
+ char ach[2]; // Set to { '*', '\0' }
+ long cbFile; // Required spill file size
+} FDISPILLFILE; /* fdisf */
+typedef FDISPILLFILE *PFDISPILLFILE; /* pfdisf */
+
+#pragma pack ()
+
+
+/*** cpuType values for FDICreate()
+ *
+ * WARNING: For 16-bit Windows applications, the CPU detection may not
+ * correctly detect 286 CPUs. Instead, use the following code:
+ *
+ * DWORD flags;
+ * int cpuType;
+ *
+ * flags = GetWinFlags();
+ * if (flags & WF_CPU286)
+ * cpuType = cpu80286;
+ * else
+ * cpuType = cpu80386;
+ *
+ * hfdi = FDICreate(....,cpuType,...);
+ */
+#define cpuUNKNOWN (-1) /* FDI does detection */
+#define cpu80286 (0) /* '286 opcodes only */
+#define cpu80386 (1) /* '386 opcodes used */
+
+
+/*** FDICreate - Create an FDI context
+ *
+ * Entry:
+ * pfnalloc
+ * pfnfree
+ * pfnopen
+ * pfnread
+ * pfnwrite
+ * pfnclose
+ * pfnlseek
+ * cpuType - Select CPU type (auto-detect, 286, or 386+)
+ * WARNING: Don't use auto-detect from a 16-bit Windows
+ * application! Use GetWinFlags()!
+ * NOTE: For the 32-bit FDI.LIB, this parameter is ignored!
+ * perf
+ *
+ * Exit-Success:
+ * Returns non-NULL FDI context handle.
+ *
+ * Exit-Failure:
+ * Returns NULL; perf filled in with error code
+ *
+ * Special notes for Quantum Decompression:
+ * If you have used a high setting for CompressionMemory in creating
+ * the cabinet file(s), then FDI will attempt to allocate a lot of
+ * memory (as much as 2Mb, if you specified 21 for CompressionMemory).
+ * Therefore, if you plan to allocate additional memory *after* the
+ * FDICreate() call, you should reserve some memory *prior* to calling
+ * FDICreate(), and then free it up afterwards (or do all your allocation
+ * before calling FDICreate().
+ */
+HFDI FAR DIAMONDAPI FDICreate(PFNALLOC pfnalloc,
+ PFNFREE pfnfree,
+ PFNOPEN pfnopen,
+ PFNREAD pfnread,
+ PFNWRITE pfnwrite,
+ PFNCLOSE pfnclose,
+ PFNSEEK pfnseek,
+ int cpuType,
+ PERF perf);
+
+
+/*** FDIIsCabinet - Determines if file is a cabinet, returns info if it is
+ *
+ * Entry:
+ * hfdi - Handle to FDI context (created by FDICreate())
+ * hf - File handle suitable for PFNREAD/PFNSEEK, positioned
+ * at offset 0 in the file to test.
+ * pfdici - Buffer to receive info about cabinet if it is one.
+ *
+ * Exit-Success:
+ * Returns TRUE; file is a cabinet, pfdici filled in.
+ *
+ * Exit-Failure:
+ * Returns FALSE, file is not a cabinet; If an error occurred,
+ * perf (passed on FDICreate call!) filled in with error.
+ */
+BOOL FAR DIAMONDAPI FDIIsCabinet(HFDI hfdi,
+ int hf,
+ PFDICABINETINFO pfdici);
+
+
+/*** FDICopy - extracts files from a cabinet
+ *
+ * Entry:
+ * hfdi - handle to FDI context (created by FDICreate())
+ * pszCabinet - main name of cabinet file
+ * pszCabPath - Path to cabinet file(s)
+ * flags - Flags to modify behavior
+ * pfnfdin - Notification function
+ * pfnfdid - Decryption function (pass NULL if not used)
+ * pvUser - User specified value to pass to notification function
+ *
+ * Exit-Success:
+ * Returns TRUE;
+ *
+ * Exit-Failure:
+ * Returns FALSE, perf (passed on FDICreate call!) filled in with
+ * error.
+ *
+ * Notes:
+ * (1) If FDICopy() fails while a target file is being written out, then
+ * FDI will use the PFNCLOSE function to close the file handle for that
+ * target file that was returned from the fdintCOPY_FILE notification.
+ * The client application is then free to delete the target file, since
+ * it will not be in a valid state (since there was an error while
+ * writing it out).
+ */
+BOOL FAR DIAMONDAPI FDICopy(HFDI hfdi,
+ char FAR *pszCabinet,
+ char FAR *pszCabPath,
+ int flags,
+ PFNFDINOTIFY pfnfdin,
+ PFNFDIDECRYPT pfnfdid,
+ void FAR *pvUser);
+
+
+/*** FDIDestroy - Destroy an FDI context
+ *
+ * Entry:
+ * hfdi - handle to FDI context (created by FDICreate())
+ *
+ * Exit-Success:
+ * Returns TRUE;
+ *
+ * Exit-Failure:
+ * Returns FALSE;
+ */
+BOOL FAR DIAMONDAPI FDIDestroy(HFDI hfdi);
+
+
+//** Revert to default structure packing
+#include <poppack.h>
+
+#endif //!INCLUDED_FDI
+