📄 fdi.pas
字号:
* 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!
*
* 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.
}
//** File I/O functions for FDI
type
TFNOPEN_dummy = function (pszFile : PChar; oflag : Integer; pmode : Integer) :
Integer; cdecl;
PFNOPEN = TFNOPEN_dummy;
TFNREAD_dummy = function (hf : Integer; pv : PVoid; cb : TUINT) : TUINT; cdecl;
PFNREAD = TFNREAD_dummy;
TFNWRITE_dummy = function (hf : Integer; pv : PVoid; cb : TUINT) : TUINT; cdecl;
PFNWRITE = TFNWRITE_dummy;
TFNCLOSE_dummy = function (hf : Integer) : Integer; cdecl;
PFNCLOSE = TFNCLOSE_dummy;
TFNSEEK_dummy = function (hf : Integer; dist : Longint; seektype : Integer) :
Longint; cdecl;
PFNSEEK = TFNSEEK_dummy;
{** 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:
* FCI 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.
}
type
TFNFDIDECRYPT_dummy = function (pfdid : PFDIDECRYPT) : Integer; cdecl;
PFNFDIDECRYPT = TFNFDIDECRYPT_dummy;
{ pfnfdid }
{** FDINOTIFICATION - Notification structure for PFNFDINOTIFY
*
* See the FDINOTIFICATIONTYPE definition for information on usage and
* meaning of these fields.
}
type
TFDINOTIFICATION =
record
// long fields
cb : Longint;
psz1 : PChar;
psz2 : PChar;
psz3 : PChar; // Points to a 256 character buffer
pv : PVoid; // Value for client
// int fields
hf : Integer; // short fields
date : TUSHORT;
time : TUSHORT;
attribs : TUSHORT;
setID : TUSHORT; // Cabinet set ID
iCabinet : TUSHORT; // Cabinet number (0-based)
iFolder : TUSHORT; // Folder number (0-based)
fdie : TFDIERROR;
end;
PFDINOTIFICATION = ^TFDINOTIFICATION;
{ 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
* fdintENUMERATE // Starting enumeration
* 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
* ...
* fdintENUMERATE // Ending enumeration
*
* 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
* pfdin->iFolder = file's folder index
* 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->iFolder = file's folder index
* 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!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -