home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 May / Chip_2002-05_cd1.bin / zkuste / delphi / kompon / d5 / CAKDIR.ZIP / fdi.pas < prev    next >
Pascal/Delphi Source File  |  1997-12-26  |  46KB  |  1,123 lines

  1. {++
  2.  
  3. f d i . p a s
  4. Copyright (c) 1997 Alexander Staubo, all rights reserved.
  5.  
  6. Abstract:
  7.  
  8.   Translation of fdi.h, part of the Cabinet SDK.
  9.  
  10. Revision history:
  11.  
  12.   06/07/1997 20:17  alexs  1.0
  13.     Autogenerated by htrans
  14.   26/12/1997 02:55  alexs  1.1
  15.     Fixed declarations of function callbacks, other minor stuff
  16.  
  17. --}
  18.  
  19. unit Fdi;
  20.  
  21. {$A+}
  22. {$MINENUMSIZE 4}
  23. {$WEAKPACKAGEUNIT ON}
  24.  
  25. interface
  26.  
  27. uses
  28.   Windows, SysUtils;
  29.  
  30. type
  31.   PVoid = Pointer;
  32.   USHORT = Word;
  33.  
  34. (*
  35.  *  FDI.H -- File Decompression Interface
  36.  *
  37.  *  Copyright (C) Microsoft Corporation 1993-1997
  38.  *  All Rights Reserved.
  39.  *)
  40.  
  41. type
  42.                                        { f }
  43.   TBYTE = Char;
  44.   
  45.                                        { b }
  46.   TUINT = Integer;
  47.   
  48.                                        { ui }
  49.   TUSHORT = Smallint;
  50.   
  51.                                        { us }
  52.   TULONG = Longint;
  53.   
  54.                                        { ul }
  55.  
  56. type
  57.   TCHECKSUM = Longint;
  58.   
  59.                                        { csum }
  60.   TUOFF = Longint;
  61.   
  62.                                        { uoff - uncompressed offset }
  63.   TCOFF = Longint;
  64.   
  65.                                        { coff - cabinet file offset }
  66.  
  67. {**    ERF - Error structure
  68.  *
  69.  *  This structure returns error information from FCI/FDI.  The caller should
  70.  *  not modify this structure.
  71.  }
  72.  
  73. type
  74.   TERF =     
  75.     record
  76.       erfOper : Integer;  // FCI/FDI error code -- see FDIERROR_XXX
  77.         //  and FCIERR_XXX equates for details.
  78.       erfType : Integer;  // Optional error value filled in by FCI/FDI.
  79.         // For FCI, this is usually the C run-time
  80.         // *errno* value.
  81.       fError : BOOL;  // TRUE => error present
  82.     end;
  83.     
  84.                                        { erf }
  85.   PERF = ^TERF;
  86.   
  87.                                        { perf }
  88.  
  89. const
  90.   CB_MAX_CHUNK = 32768;
  91.   CB_MAX_DISK = $7ffffff;
  92.   CB_MAX_FILENAME = 256;
  93.   CB_MAX_CABINET_NAME = 256;
  94.   CB_MAX_CAB_PATH = 256;
  95.   CB_MAX_DISK_NAME = 256;
  96.  
  97. {**    tcompXXX - Compression types
  98.  *
  99.  *  These are passed to FCIAddFile(), and are also stored in the CFFOLDER
  100.  *  structures in cabinet files.
  101.  *
  102.  *  NOTE: We reserve bits for the TYPE, QUANTUM_LEVEL, and QUANTUM_MEM
  103.  *        to provide room for future expansion.  Since this value is stored
  104.  *        in the CFDATA records in the cabinet file, we don't want to
  105.  *        have to change the format for existing compression configurations
  106.  *        if we add new ones in the future.  This will allows us to read
  107.  *        old cabinet files in the future.
  108.  }
  109.  
  110. type
  111.   TCOMP = Smallint;
  112.   
  113.                                        { tcomp }
  114.  
  115. const
  116.   tcompMASK_TYPE = $000F;
  117.   tcompTYPE_NONE = $0000;
  118.   tcompTYPE_MSZIP = $0001;
  119.   tcompTYPE_QUANTUM = $0002;
  120.   tcompTYPE_LZX = $0003;
  121.   tcompBAD = $000F;
  122.   tcompMASK_LZX_WINDOW = $1F00;
  123.   tcompLZX_WINDOW_LO = $0F00;
  124.   tcompLZX_WINDOW_HI = $1500;
  125.   tcompSHIFT_LZX_WINDOW = 8;
  126.   tcompMASK_QUANTUM_LEVEL = $00F0;
  127.   tcompQUANTUM_LEVEL_LO = $0010;
  128.   tcompQUANTUM_LEVEL_HI = $0070;
  129.   tcompSHIFT_QUANTUM_LEVEL = 4;
  130.   tcompMASK_QUANTUM_MEM = $1F00;
  131.   tcompQUANTUM_MEM_LO = $0A00;
  132.   tcompQUANTUM_MEM_HI = $1500;
  133.   tcompSHIFT_QUANTUM_MEM = 8;
  134.   tcompMASK_RESERVED = $E000;
  135.  
  136. (*
  137.  *  Concepts:
  138.  *      A *cabinet* file contains one or more *folders*.  A folder contains
  139.  *      one or more (pieces of) *files*.  A folder is by definition a
  140.  *      decompression unit, i.e., to extract a file from a folder, all of
  141.  *      the data from the start of the folder up through and including the
  142.  *      desired file must be read and decompressed.
  143.  *
  144.  *      A folder can span one (or more) cabinet boundaries, and by implication
  145.  *      a file can also span one (or more) cabinet boundaries.  Indeed, more
  146.  *      than one file can span a cabinet boundary, since FCI concatenates
  147.  *      files together into a single data stream before compressing (actually,
  148.  *      at most one file will span any one cabinet boundary, but FCI does
  149.  *      not know which file this is, since the mapping from uncompressed bytes
  150.  *      to compressed bytes is pretty obscure.  Also, since FCI compresses
  151.  *      in blocks of 32K (at present), any files with data in a 32K block that
  152.  *      spans a cabinet boundary require FDI to read both cabinet files
  153.  *      to get the two halves of the compressed block).
  154.  *
  155.  *  Overview:
  156.  *      The File Decompression Interface is used to simplify the reading of
  157.  *      cabinet files.  A setup program will proceed in a manner very
  158.  *      similar to the pseudo code below.  An FDI context is created, the
  159.  *      setup program calls FDICopy() for each cabinet to be processed.  For
  160.  *      each file in the cabinet, FDICopy() calls a notification callback
  161.  *      routine, asking the setup program if the file should be copied.
  162.  *      This call-back approach is great because it allows the cabinet file
  163.  *      to be read and decompressed in an optimal manner, and also makes FDI
  164.  *      independent of the run-time environment -- FDI makes *no* C run-time
  165.  *      calls whatsoever.  All memory allocation and file I/O functions are
  166.  *      passed into FDI by the client.
  167.  *
  168.  *      main(...)
  169.  *      {
  170.  *          // Read INF file to construct list of desired files.   
  171.  *          //  Ideally, these would be sorted in the same order as the
  172.  *          //  files appear in the cabinets, so that you can just walk
  173.  *          //  down the list in response to fdintCOPY_FILE notifications.
  174.  *
  175.  *          // Construct list of required cabinets. 
  176.  *
  177.  *          hfdi = FDICreate(...);          // Create FDI context
  178.  *          For (cabinet in List of Cabinets) {
  179.  *              FDICopy(hfdi,cabinet,fdiNotify,...);  // Process each cabinet
  180.  *          [#125]
  181.  *          FDIDestroy(hfdi);
  182.  *          ...
  183.  *      [#125]
  184.  *
  185.  *      // Notification callback function 
  186.  *      fdiNotify(fdint,...)
  187.  *      {
  188.  *          If (User Aborted)               // Permit cancellation
  189.  *              if (fdint == fdintCLOSE_FILE_INFO)
  190.  *                  close open file
  191.  *              return -1;
  192.  *          switch (fdint) {
  193.  *              case fdintCOPY_FILE:        // File to copy, maybe
  194.  *                  // Check file against list of desired files 
  195.  *                  if want to copy file
  196.  *                      open destination file and return handle
  197.  *                  else
  198.  *                      return NULL;        // Skip file
  199.  *              case fdintCLOSE_FILE_INFO:
  200.  *                  close file
  201.  *                  set date, time, and attributes
  202.  *
  203.  *              case fdintNEXT_CABINET:
  204.  *                  if not an error callback
  205.  *                      Tell FDI to use suggested directory name
  206.  *                  else
  207.  *                      Tell user what the problem was, and prompt
  208.  *                          for a new disk and/or path.
  209.  *                      if user aborts
  210.  *                          Tell FDI to abort
  211.  *                      else
  212.  *                          return to FDI to try another cabinet
  213.  *
  214.  *              default:
  215.  *                  return 0;               // more messages may be defined
  216.  *              ...
  217.  *      [#125]
  218.  *
  219.  *  Error Handling Suggestions:
  220.  *      Since you the client have passed in *all* of the functions that
  221.  *      FDI uses to interact with the "outside" world, you are in prime
  222.  *      position to understand and deal with errors.
  223.  *
  224.  *      The general philosophy of FDI is to pass all errors back up to
  225.  *      the client.  FDI returns fairly generic error codes in the case
  226.  *      where one of the callback functions (PFNOPEN, PFNREAD, etc.) fail,
  227.  *      since it assumes that the callback function will save enough
  228.  *      information in a static/global so that when FDICopy() returns
  229.  *      fail, the client can examine this information and report enough
  230.  *      detail about the problem that the user can take corrective action.
  231.  *
  232.  *      For very specific errors (CORRUPT_CABINET, for example), FDI returns
  233.  *      very specific error codes.
  234.  *
  235.  *      THE BEST POLICY IS FOR YOUR CALLBACK ROUTINES TO AVOID RETURNING
  236.  *      ERRORS TO FDI!
  237.  *
  238.  *      Examples:
  239.  *          (1) If the disk is getting full, instead of returning an error
  240.  *              from your PFNWRITE function, you should -- inside your
  241.  *              PFNWRITE function -- put up a dialog telling the user to free
  242.  *              some disk space.
  243.  *          (2) When you get the fdintNEXT_CABINET notification, you should
  244.  *              verify that the cabinet you return is the correct one (call
  245.  *              FDIIsCabinet(), and make sure the setID matches the one for
  246.  *              the current cabinet specified in the fdintCABINET_INFO, and
  247.  *              that the disk number is one greater.
  248.  *
  249.  *              NOTE: FDI will continue to call fdintNEXT_CABINET until it
  250.  *                    gets the cabinet it wants, or until you return -1
  251.  *                    to abort the FDICopy() call.
  252.  *
  253.  *      The documentation below on the FDI error codes provides explicit
  254.  *      guidance on how to avoid each error.
  255.  *
  256.  *      If you find you must return a failure to FDI from one of your
  257.  *      callback functions, then FDICopy() frees all resources it allocated
  258.  *      and closes all files.  If you can figure out how to overcome the
  259.  *      problem, you can call FDICopy() again on the last cabinet, and
  260.  *      skip any files that you already copied.  But, note that FDI does
  261.  *      *not* maintain any state between FDICopy() calls, other than possibly
  262.  *      memory allocated for the decompressor.
  263.  *
  264.  *      See FDIERROR for details on FDI error codes and recommended actions.
  265.  *
  266.  *
  267.  *  Progress Indicator Suggestions:
  268.  *      As above, all of the file I/O functions are supplied by you.  So,
  269.  *      updating a progress indicator is very simple.  You keep track of
  270.  *      the target files handles you have opened, along with the uncompressed
  271.  *      size of the target file.  When you see writes to the handle of a
  272.  *      target file, you use the write count to update your status!
  273.  *      Since this method is available, there is no separate callback from
  274.  *      FDI just for progess indication.
  275.  *)
  276.  
  277. {**    FDIERROR - Error codes returned in erf.erfOper field
  278.  *
  279.  *  In general, FDI will only fail if one of the passed in memory or
  280.  *  file I/O functions fails.  Other errors are pretty unlikely, and are
  281.  *  caused by corrupted cabinet files, passing in a file which is not a
  282.  *  cabinet file, or cabinet files out of order.
  283.  *
  284.  *  Description:    Summary of error.
  285.  *  Cause:          List of possible causes of this error.
  286.  *  Response:       How client might respond to this error, or avoid it in
  287.  *                  the first place.
  288.  }
  289.  
  290. type
  291.   TFDIERROR =     
  292.     (
  293.       FDIERROR_NONE  // Description: No error
  294.         // Cause:       Function was successfull.
  295.         // Response:    Keep going!
  296.       ,
  297.       FDIERROR_CABINET_NOT_FOUND  // Description: Cabinet not found
  298.         // Cause:       Bad file name or path passed to FDICopy(), or returned
  299.         //              to fdintNEXT_CABINET.
  300.         // Response:    To prevent this error, validate the existence of the
  301.         //              the cabinet *before* passing the path to FDI.
  302.       ,
  303.       FDIERROR_NOT_A_CABINET  // Description: Cabinet file does not have the correct format
  304.         // Cause:       File passed to to FDICopy(), or returned to
  305.         //              fdintNEXT_CABINET, is too small to be a cabinet file,
  306.         //              or does not have the cabinet signature in its first
  307.         //              four bytes.
  308.         // Response:    To prevent this error, call FDIIsCabinet() to check a
  309.         //              cabinet before calling FDICopy() or returning the
  310.         //              cabinet path to fdintNEXT_CABINET.
  311.       ,
  312.       FDIERROR_UNKNOWN_CABINET_VERSION  // Description: Cabinet file has an unknown version number.
  313.         // Cause:       File passed to to FDICopy(), or returned to
  314.         //              fdintNEXT_CABINET, has what looks like a cabinet file
  315.         //              header, but the version of the cabinet file format
  316.         //              is not one understood by this version of FDI.  The
  317.         //              erf.erfType field is filled in with the version number
  318.         //              found in the cabinet file.
  319.         // Response:    To prevent this error, call FDIIsCabinet() to check a
  320.         //              cabinet before calling FDICopy() or returning the
  321.         //              cabinet path to fdintNEXT_CABINET.
  322.       ,
  323.       FDIERROR_CORRUPT_CABINET  // Description: Cabinet file is corrupt
  324.         // Cause:       FDI returns this error any time it finds a problem
  325.         //              with the logical format of a cabinet file, and any
  326.         //              time one of the passed-in file I/O calls fails when
  327.         //              operating on a cabinet (PFNOPEN, PFNSEEK, PFNREAD,
  328.         //              or PFNCLOSE).  The client can distinguish these two
  329.         //              cases based upon whether the last file I/O call
  330.         //              failed or not.
  331.         // Response:    Assuming this is not a real corruption problem in
  332.         //              a cabinet file, the file I/O functions could attempt
  333.         //              to do retries on failure (for example, if there is a
  334.         //              temporary network connection problem).  If this does
  335.         //              not work, and the file I/O call has to fail, then the
  336.         //              FDI client will have to clean up and call the
  337.         //              FDICopy() function again.
  338.       ,
  339.       FDIERROR_ALLOC_FAIL  // Description: Could not allocate enough memory
  340.         // Cause:       FDI tried to allocate memory with the PFNALLOC
  341.         //              function, but it failed.
  342.         // Response:    If possible, PFNALLOC should take whatever steps
  343.         //              are possible to allocate the memory requested.  If
  344.         //              memory is not immediately available, it might post a
  345.         //              dialog asking the user to free memory, for example.
  346.         //              Note that the bulk of FDI's memory allocations are
  347.         //              made at FDICreate() time and when the first cabinet
  348.         //              file is opened during FDICopy().
  349.       ,
  350.       FDIERROR_BAD_COMPR_TYPE  // Description: Unknown compression type in a cabinet folder
  351.         // Cause:       [Should never happen.]  A folder in a cabinet has an
  352.         //              unknown compression type.  This is probably caused by
  353.         //              a mismatch between the version of FCI.LIB used to
  354.         //              create the cabinet and the FDI.LIB used to read the
  355.         //              cabinet.
  356.         // Response:    Abort.
  357.       ,
  358.       FDIERROR_MDI_FAIL  // Description: Failure decompressing data from a cabinet file
  359.         // Cause:       The decompressor found an error in the data coming
  360.         //              from the file cabinet.  The cabinet file was corrupted.
  361.         //              [11-Apr-1994 bens When checksuming is turned on, this
  362.         //              error should never occur.]
  363.         // Response:    Probably should abort; only other choice is to cleanup
  364.         //              and call FDICopy() again, and hope there was some
  365.         //              intermittent data error that will not reoccur.
  366.       ,
  367.       FDIERROR_TARGET_FILE  // Description: Failure writing to target file
  368.         // Cause:       FDI returns this error any time it gets an error back
  369.         //              from one of the passed-in file I/O calls fails when
  370.         //              writing to a file being extracted from a cabinet.
  371.         // Response:    To avoid or minimize this error, the file I/O functions
  372.         //              could attempt to avoid failing.  A common cause might
  373.         //              be disk full -- in this case, the PFNWRITE function
  374.         //              could have a check for free space, and put up a dialog
  375.         //              asking the user to free some disk space.
  376.       ,
  377.       FDIERROR_RESERVE_MISMATCH  // Description: Cabinets in a set do not have the same RESERVE sizes
  378.         // Cause:       [Should never happen]. FDI requires that the sizes of
  379.         //              the per-cabinet, per-folder, and per-data block
  380.         //              RESERVE sections be consistent across all the cabinets
  381.         //              in a set.
  382.         // Response:    Abort.
  383.       ,
  384.       FDIERROR_WRONG_CABINET  // Description: Cabinet returned on fdintNEXT_CABINET is incorrect
  385.         // Cause:       NOTE: THIS ERROR IS NEVER RETURNED BY FDICopy()!
  386.         //              Rather, FDICopy() keeps calling the fdintNEXT_CABINET
  387.         //              callback until either the correct cabinet is specified,
  388.         //              or you return ABORT.
  389.         //              When FDICopy() is extracting a file that crosses a
  390.         //              cabinet boundary, it calls fdintNEXT_CABINET to ask
  391.         //              for the path to the next cabinet.  Not being very
  392.         //              trusting, FDI then checks to make sure that the
  393.         //              correct continuation cabinet was supplied!  It does
  394.         //              this by checking the "setID" and "iCabinet" fields
  395.         //              in the cabinet.  When MAKECAB.EXE creates a set of
  396.         //              cabinets, it constructs the "setID" using the sum
  397.         //              of the bytes of all the destination file names in
  398.         //              the cabinet set.  FDI makes sure that the 16-bit
  399.         //              setID of the continuation cabinet matches the
  400.         //              cabinet file just processed.  FDI then checks that
  401.         //              the cabinet number (iCabinet) is one more than the
  402.         //              cabinet number for the cabinet just processed.
  403.         // Response:    You need code in your fdintNEXT_CABINET (see below)
  404.         //              handler to do retries if you get recalled with this
  405.         //              error.  See the sample code (EXTRACT.C) to see how
  406.         //              this should be handled.
  407.       ,
  408.       FDIERROR_USER_ABORT  // Description: FDI aborted.
  409.         // Cause:       An FDI callback returnd -1 (usually).
  410.         // Response:    Up to client.
  411.     );
  412.     
  413. (*
  414.  * FAT file attribute flag used by FCI/FDI to indicate that
  415.  * the filename in the CAB is a UTF string
  416.  *)
  417.  
  418. const
  419.   _A_NAME_IS_UTF = $80;
  420.  
  421. (*
  422.  * FAT file attribute flag used by FCI/FDI to indicate that
  423.  * the file should be executed after extraction
  424.  *)
  425.  
  426. const
  427.   _A_EXEC = $40;
  428.  
  429. {**    HFDI - Handle to an FDI context
  430.  *
  431.  *  FDICreate() creates this, and it must be passed to all other FDI
  432.  *  functions.
  433.  }
  434.  
  435. type
  436.   HFDI = PVoid;
  437.   
  438.                                        { hfdi }
  439.  
  440. {**    FDICABINETINFO - Information about a cabinet
  441.  *
  442.  }
  443.  
  444. type
  445.   TFDICABINETINFO =     
  446.     record
  447.       cbCabinet : Longint;  // Total length of cabinet file
  448.       cFolders : TUSHORT;  // Count of folders in cabinet
  449.       cFiles : TUSHORT;  // Count of files in cabinet
  450.       setID : TUSHORT;  // Cabinet set ID
  451.       iCabinet : TUSHORT;  // Cabinet number in set (0 based)
  452.       fReserve : BOOL;  // TRUE => RESERVE present in cabinet
  453.       hasprev : BOOL;  // TRUE => Cabinet is chained prev
  454.       hasnext : BOOL;  // TRUE => Cabinet is chained next
  455.     end;
  456.  
  457.                                        { fdici }
  458.   TPFDICABINETINFO = ^TFDICABINETINFO;
  459.   
  460.                                        { pfdici }
  461.  
  462. {**    FDIDECRYPTTYPE - PFNFDIDECRYPT command types
  463.  *
  464.  }
  465.  
  466. type
  467.   TFDIDECRYPTTYPE =     
  468.     (
  469.       fdidtNEW_CABINET  // New cabinet
  470.       ,
  471.       fdidtNEW_FOLDER  // New folder
  472.       ,
  473.       fdidtDECRYPT  // Decrypt a data block
  474.     );
  475.     
  476.                                        { fdidt }
  477.  
  478. {**    FDIDECRYPT - Data for PFNFDIDECRYPT function
  479.  *
  480.  }
  481.  
  482. type
  483.   TFDIDECRYPT =     
  484.     record
  485.       fdidt : TFDIDECRYPTTYPE;  // Command type (selects union below)
  486.       pvUser : PVoid;  // Decryption context
  487.       _noname1 :         
  488.         record
  489.           case Integer of
  490.             1 : 
  491.               (
  492.               cabinet :                   
  493.                   record
  494.                       // fdidtNEW_CABINET
  495.                     pHeaderReserve : PVoid;  // RESERVE section from CFHEADER
  496.                     cbHeaderReserve : TUSHORT;  // Size of pHeaderReserve
  497.                     setID : TUSHORT;  // Cabinet set ID
  498.                     iCabinet : Integer;  // Cabinet number in set (0 based)
  499.                   end;
  500.                 );
  501.             2 : 
  502.               (
  503.               folder :                   
  504.                   record
  505.                       // fdidtNEW_FOLDER
  506.                     pFolderReserve : PVoid;  // RESERVE section from CFFOLDER
  507.                     cbFolderReserve : TUSHORT;  // Size of pFolderReserve
  508.                     iFolder : TUSHORT;  // Folder number in cabinet (0 based)
  509.                   end;
  510.                 );
  511.             3 : 
  512.               (
  513.               decrypt :                   
  514.                   record
  515.                       // fdidtDECRYPT
  516.                     pDataReserve : PVoid;  // RESERVE section from CFDATA
  517.                     cbDataReserve : TUSHORT;  // Size of pDataReserve
  518.                     pbData : PVoid;  // Data buffer
  519.                     cbData : TUSHORT;  // Size of data buffer
  520.                     fSplit : BOOL;  // TRUE if this is a split data block
  521.                     cbPartial : TUSHORT;  // 0 if this is not a split block, or
  522.                       //  the first piece of a split block;
  523.                       // Greater than 0 if this is the
  524.                       //  second piece of a split block.
  525.                   end;
  526.                 );
  527.       end;
  528.     end;
  529.     
  530.                                        { fdid }
  531.   PFDIDECRYPT = ^TFDIDECRYPT;
  532.   
  533.                                        { pfdid }
  534.  
  535. {**    FNALLOC - Memory Allocation
  536.  *      FNFREE  - Memory Free
  537.  *
  538.  *  These are modeled after the C run-time routines malloc() and free()
  539.  *  FDI expects error handling to be identical to these C run-time routines.
  540.  *
  541.  *  As long as you faithfully copy the semantics of malloc() and free(),
  542.  *  you can supply any functions you like!
  543.  *
  544.  *  WARNING: You should never assume anything about the sequence of
  545.  *           PFNALLOC and PFNFREE calls -- incremental releases of
  546.  *           FDI may have radically different numbers of
  547.  *           PFNALLOC calls and allocation sizes!
  548.  }
  549.  
  550.   //** Memory functions for FDI
  551.  
  552. type
  553.   TFNALLOC_dummy = function (cb : TULONG) : PVoid; cdecl;
  554.   PFNALLOC = TFNALLOC_dummy;
  555.   
  556.                                        { pfna }
  557.   TFNFREE_dummy = function (pv : PVoid) : Pointer; cdecl;
  558.   PFNFREE = TFNFREE_dummy;
  559.   
  560.                                        { pfnf }
  561.  
  562. {**    PFNOPEN  - File I/O callbacks for FDI
  563.  *      PFNREAD
  564.  *      PFNWRITE
  565.  *      PFNCLOSE
  566.  *      PFNSEEK
  567.  *
  568.  *  These are modeled after the C run-time routines _open, _read,
  569.  *  _write, _close, and _lseek.  The values for the PFNOPEN oflag
  570.  *  and pmode calls are those defined for _open.  FDI expects error
  571.  *  handling to be identical to these C run-time routines.
  572.  *
  573.  *  As long as you faithfully copy these aspects, you can supply
  574.  *  any functions you like!
  575.  *
  576.  *  WARNING: You should never assume you know what file is being
  577.  *           opened at any one point in time!  FDI will usually
  578.  *           stick to opening cabinet files, but it is possible
  579.  *           that in a future implementation it may open temporary
  580.  *           files or open cabinet files in a different order.
  581.  *
  582.  *  Notes for Memory Mapped File fans:
  583.  *      You can write wrapper routines to allow FDI to work on memory
  584.  *      mapped files.  You'll have to create your own "handle" type so that
  585.  *      you can store the base memory address of the file and the current
  586.  *      seek position, and then you'll allocate and fill in one of these
  587.  *      structures and return a pointer to it in response to the PFNOPEN
  588.  *      call and the fdintCOPY_FILE call.  Your PFNREAD and PFNWRITE
  589.  *      functions will do memcopy(), and update the seek position in your
  590.  *      "handle" structure.  PFNSEEK will just change the seek position
  591.  *      in your "handle" structure.
  592.  }
  593.  
  594.   //** File I/O functions for FDI
  595.  
  596. type
  597.   TFNOPEN_dummy = function (pszFile : PChar; oflag : Integer; pmode : Integer) :
  598.     Integer; cdecl;
  599.   PFNOPEN = TFNOPEN_dummy;
  600.  
  601.   TFNREAD_dummy = function (hf : Integer; pv : PVoid; cb : TUINT) : TUINT; cdecl;
  602.   PFNREAD = TFNREAD_dummy;
  603.  
  604.   TFNWRITE_dummy = function (hf : Integer; pv : PVoid; cb : TUINT) : TUINT; cdecl;
  605.   PFNWRITE = TFNWRITE_dummy;
  606.  
  607.   TFNCLOSE_dummy = function (hf : Integer) : Integer; cdecl;
  608.   PFNCLOSE = TFNCLOSE_dummy;
  609.  
  610.   TFNSEEK_dummy = function (hf : Integer; dist : Longint; seektype : Integer) :
  611.     Longint; cdecl;
  612.   PFNSEEK = TFNSEEK_dummy;
  613.  
  614. {**    PFNFDIDECRYPT - FDI Decryption callback
  615.  *
  616.  *  If this function is passed on the FDICopy() call, then FDI calls it
  617.  *  at various times to update the decryption state and to decrypt FCDATA
  618.  *  blocks.
  619.  *
  620.  *  Common Entry Conditions:
  621.  *      pfdid->fdidt  - Command type
  622.  *      pfdid->pvUser - pvUser value from FDICopy() call
  623.  *
  624.  *  fdidtNEW_CABINET:   //** Notification of a new cabinet
  625.  *      Entry:
  626.  *        pfdid->cabinet.
  627.  *          pHeaderReserve  - RESERVE section from CFHEADER
  628.  *          cbHeaderReserve - Size of pHeaderReserve
  629.  *          setID           - Cabinet set ID
  630.  *          iCabinet        - Cabinet number in set (0 based)
  631.  *      Exit-Success:
  632.  *          returns anything but -1;
  633.  *      Exit-Failure:
  634.  *          returns -1; FDICopy() is aborted.
  635.  *      Notes:
  636.  *      (1) This call allows the decryption code to pick out any information
  637.  *          from the cabinet header reserved area (placed there by DIACRYPT)
  638.  *          needed to perform decryption.  If there is no such information,
  639.  *          this call would presumably be ignored.
  640.  *      (2) This call is made very soon after fdintCABINET_INFO.
  641.  *
  642.  *  fdidtNEW_FOLDER:    //** Notification of a new folder
  643.  *      Entry:
  644.  *        pfdid->folder.
  645.  *          pFolderReserve  - RESERVE section from CFFOLDER
  646.  *          cbFolderReserve - Size of pFolderReserve
  647.  *          iFolder         - Folder number in cabinet (0 based)
  648.  *      Exit-Success:
  649.  *          returns anything but -1;
  650.  *      Exit-Failure:
  651.  *          returns -1; FDICopy() is aborted.
  652.  *      Notes:
  653.  *          This call allows the decryption code to pick out any information
  654.  *          from the folder reserved area (placed there by DIACRYPT) needed
  655.  *          to perform decryption.  If there is no such information, this
  656.  *          call would presumably be ignored.
  657.  *
  658.  *  fdidtDECRYPT:       //** Decrypt a data buffer
  659.  *      Entry:
  660.  *        pfdid->folder.
  661.  *          pDataReserve  - RESERVE section for this CFDATA block
  662.  *          cbDataReserve - Size of pDataReserve
  663.  *          pbData        - Data buffer
  664.  *          cbData        - Size of data buffer
  665.  *          fSplit        - TRUE if this is a split data block
  666.  *          cbPartial     - 0 if this is not a split block, or the first
  667.  *                              piece of a split block; Greater than 0 if
  668.  *                              this is the second piece of a split block.
  669.  *      Exit-Success:
  670.  *          returns TRUE;
  671.  *      Exit-Failure:
  672.  *          returns FALSE; error during decrypt
  673.  *          returns -1; FDICopy() is aborted.
  674.  *      Notes:
  675.  *          FCI will split CFDATA blocks across cabinet boundaries if
  676.  *          necessary.  To provide maximum flexibility, FDI will call the
  677.  *          fdidtDECRYPT function twice on such split blocks, once when
  678.  *          the first portion is read, and again when the second portion
  679.  *          is read.  And, of course, most data blocks will not be split.
  680.  *          So, there are three cases:
  681.  *
  682.  *           1) fSplit == FALSE
  683.  *              You have the entire data block, so decrypt it.
  684.  *
  685.  *           2) fSplit == TRUE, cbPartial == 0
  686.  *              This is the first portion of a split data block, so cbData
  687.  *              is the size of this portion.  You can either choose to decrypt
  688.  *              this piece, or ignore this call and decrypt the full CFDATA
  689.  *              block on the next (second) fdidtDECRYPT call.
  690.  *
  691.  *           3) fSplit == TRUE, cbPartial > 0
  692.  *              This is the second portion of a split data block (indeed,
  693.  *              cbPartial will have the same value as cbData did on the
  694.  *              immediately preceeding fdidtDECRYPT call!).  If you decrypted
  695.  *              the first portion on the first call, then you can decrypt the
  696.  *              second portion now.  If you ignored the first call, then you
  697.  *              can decrypt the entire buffer.
  698.  *              NOTE: pbData points to the second portion of the split data
  699.  *                    block in this case, *not* the entire data block.  If
  700.  *                    you want to wait until the second piece to decrypt the
  701.  *                    *entire* block, pbData-cbPartial is the address of the
  702.  *                    start of the whole block, and cbData+cbPartial is its
  703.  *                    size.
  704.  }
  705.  
  706. type
  707.   TFNFDIDECRYPT_dummy = function (pfdid : PFDIDECRYPT) : Integer; cdecl;
  708.   PFNFDIDECRYPT = TFNFDIDECRYPT_dummy;
  709.  
  710.                                        { pfnfdid }
  711.  
  712. {**    FDINOTIFICATION - Notification structure for PFNFDINOTIFY
  713.  *
  714.  *  See the FDINOTIFICATIONTYPE definition for information on usage and
  715.  *  meaning of these fields.
  716.  }
  717.  
  718. type
  719.   TFDINOTIFICATION =
  720.     record
  721.         // long fields
  722.       cb : Longint;
  723.       psz1 : PChar;
  724.       psz2 : PChar;
  725.       psz3 : PChar;  // Points to a 256 character buffer
  726.       pv : PVoid;  // Value for client
  727.         // int fields
  728.       hf : Integer;  // short fields
  729.       date : TUSHORT;
  730.       time : TUSHORT;
  731.       attribs : TUSHORT;
  732.       setID : TUSHORT;  // Cabinet set ID
  733.       iCabinet : TUSHORT;  // Cabinet number (0-based)
  734.       iFolder : TUSHORT;  // Folder number (0-based)
  735.       fdie : TFDIERROR;
  736.     end;
  737.  
  738.   PFDINOTIFICATION = ^TFDINOTIFICATION;
  739.  
  740.                                        { fdin, pfdin }
  741.  
  742. {**    FDINOTIFICATIONTYPE - FDICopy notification types
  743.  *
  744.  *  The notification function for FDICopy can be called with the following
  745.  *  values for the fdint parameter.  In all cases, the pfdin->pv field is
  746.  *  filled in with the value of the pvUser argument passed in to FDICopy().
  747.  *
  748.  *  A typical sequence of calls will be something like this:
  749.  *      fdintCABINET_INFO     // Info about the cabinet
  750.  *      fdintENUMERATE        // Starting enumeration
  751.  *      fdintPARTIAL_FILE     // Only if this is not the first cabinet, and
  752.  *                            // one or more files were continued from the
  753.  *                            // previous cabinet.
  754.  *      ...
  755.  *      fdintPARTIAL_FILE
  756.  *      fdintCOPY_FILE        // The first file that starts in this cabinet
  757.  *      ...
  758.  *      fdintCOPY_FILE        // Now let's assume you want this file...
  759.  *      // PFNWRITE called multiple times to write to this file.
  760.  *      fdintCLOSE_FILE_INFO  // File done, set date/time/attributes
  761.  *
  762.  *      fdintCOPY_FILE        // Now let's assume you want this file...
  763.  *      // PFNWRITE called multiple times to write to this file.
  764.  *      fdintNEXT_CABINET     // File was continued to next cabinet!
  765.  *      fdintCABINET_INFO     // Info about the new cabinet
  766.  *      // PFNWRITE called multiple times to write to this file.
  767.  *      fdintCLOSE_FILE_INFO  // File done, set date/time/attributes
  768.  *      ...
  769.  *      fdintENUMERATE        // Ending enumeration
  770.  *
  771.  *  fdintCABINET_INFO:
  772.  *        Called exactly once for each cabinet opened by FDICopy(), including
  773.  *        continuation cabinets opened due to file(s) spanning cabinet
  774.  *        boundaries. Primarily intended to permit EXTRACT.EXE to
  775.  *        automatically select the next cabinet in a cabinet sequence even if
  776.  *        not copying files that span cabinet boundaries.
  777.  *      Entry:
  778.  *          pfdin->psz1     = name of next cabinet
  779.  *          pfdin->psz2     = name of next disk
  780.  *          pfdin->psz3     = cabinet path name
  781.  *          pfdin->setID    = cabinet set ID (a random 16-bit number)
  782.  *          pfdin->iCabinet = Cabinet number within cabinet set (0-based)
  783.  *      Exit-Success:
  784.  *          Return anything but -1
  785.  *      Exit-Failure:
  786.  *          Returns -1 => Abort FDICopy() call
  787.  *      Notes:
  788.  *          This call is made *every* time a new cabinet is examined by
  789.  *          FDICopy().  So if "foo2.cab" is examined because a file is
  790.  *          continued from "foo1.cab", and then you call FDICopy() again
  791.  *          on "foo2.cab", you will get *two* fdintCABINET_INFO calls all
  792.  *          told.
  793.  *
  794.  *  fdintCOPY_FILE:
  795.  *        Called for each file that *starts* in the current cabinet, giving
  796.  *        the client the opportunity to request that the file be copied or
  797.  *        skipped.
  798.  *      Entry:
  799.  *          pfdin->psz1    = file name in cabinet
  800.  *          pfdin->cb      = uncompressed size of file
  801.  *          pfdin->date    = file date
  802.  *          pfdin->time    = file time
  803.  *          pfdin->attribs = file attributes
  804.  *          pfdin->iFolder = file's folder index
  805.  *      Exit-Success:
  806.  *          Return non-zero file handle for destination file; FDI writes
  807.  *          data to this file use the PFNWRITE function supplied to FDICreate,
  808.  *          and then calls fdintCLOSE_FILE_INFO to close the file and set
  809.  *          the date, time, and attributes.  NOTE: This file handle returned
  810.  *          must also be closeable by the PFNCLOSE function supplied to
  811.  *          FDICreate, since if an error occurs while writing to this handle,
  812.  *          FDI will use the PFNCLOSE function to close the file so that the
  813.  *          client may delete it.
  814.  *      Exit-Failure:
  815.  *          Returns 0  => Skip file, do not copy
  816.  *          Returns -1 => Abort FDICopy() call
  817.  *
  818.  *  fdintCLOSE_FILE_INFO:
  819.  *        Called after all of the data has been written to a target file.
  820.  *        This function must close the file and set the file date, time,
  821.  *        and attributes.
  822.  *      Entry:
  823.  *          pfdin->psz1    = file name in cabinet
  824.  *          pfdin->hf      = file handle
  825.  *          pfdin->date    = file date
  826.  *          pfdin->time    = file time
  827.  *          pfdin->attribs = file attributes
  828.  *          pfdin->iFolder = file's folder index
  829.  *          pfdin->cb      = Run After Extract (0 - don't run, 1 Run)
  830.  *      Exit-Success:
  831.  *          Returns TRUE
  832.  *      Exit-Failure:
  833.  *          Returns FALSE, or -1 to abort;
  834.  *
  835.  *              IMPORTANT NOTE IMPORTANT:
  836.  *                  pfdin->cb is overloaded to no longer be the size of
  837.  *                  the file but to be a binary indicated run or not
  838.  *
  839.  *              IMPORTANT NOTE:
  840.  *                  FDI assumes that the target file was closed, even if this
  841.  *                  callback returns failure.  FDI will NOT attempt to use
  842.  *                  the PFNCLOSE function supplied on FDICreate() to close
  843.  *                  the file!
  844.  *
  845.  *  fdintPARTIAL_FILE:
  846.  *        Called for files at the front of the cabinet that are CONTINUED
  847.  *        from a previous cabinet.  This callback occurs only when FDICopy is
  848.  *        started on second or subsequent cabinet in a series that has files
  849.  *        continued from a previous cabinet.
  850.  *      Entry:
  851.  *          pfdin->psz1 = file name of file CONTINUED from a PREVIOUS cabinet
  852.  *          pfdin->psz2 = name of cabinet where file starts
  853.  *          pfdin->psz3 = name of disk where file starts
  854.  *      Exit-Success:
  855.  *          Return anything other than -1; enumeration continues
  856.  *      Exit-Failure:
  857.  *          Returns -1 => Abort FDICopy() call
  858.  *
  859.  *  fdintENUMERATE:
  860.  *        Called once after a call to FDICopy() starts scanning a CAB's
  861.  *        CFFILE entries, and again when there are no more CFFILE entries.
  862.  *        If CAB spanning occurs, an additional call will occur after the
  863.  *        first spanned file is completed.  If the pfdin->iFolder value is
  864.  *        changed from zero, additional calls will occur next time it reaches
  865.  *        zero.  If iFolder is changed to zero, FDICopy will terminate, as if
  866.  *        there were no more CFFILE entries.  Primarily intended to allow an
  867.  *        application with it's own file list to help FDI advance quickly to
  868.  *        a CFFILE entry of interest.  Can also be used to allow an
  869.  *        application to determine the cb values for each file in the CAB.
  870.  *      Entry:
  871.  *        pfdin->cb        = current CFFILE position
  872.  *        pfdin->iFolder   = number of files remaining
  873.  *        pfdin->setID     = current CAB's setID value
  874.  *      Exit-Don't Care:
  875.  *        Don't change anything.
  876.  *        Return anything but -1.
  877.  *      Exit-Forcing a skip:
  878.  *        pfdin->cb        = desired CFFILE position
  879.  *        pfdin->iFolder   = desired # of files remaining
  880.  *        Return anything but -1.
  881.  *      Exit-Stop:
  882.  *        pfdin->iFolder    = set to 0
  883.  *        Return anything but -1.
  884.  *      Exit-Failure:
  885.  *        Return -1 => Abort FDICopy call ("user aborted".)
  886.  *      Notes:
  887.  *        This call can be ignored by applications which want normal file
  888.  *        searching.  The application can adjust the supplied values to
  889.  *        force FDICopy() to continue it's search at another location, or
  890.  *        to force FDICopy() to terminate the search, by setting iFolder to 0.
  891.  *        (FDICopy() will report no error when terminated this way.)
  892.  *        FDI has no means to verify the supplied cb or iFolder values.
  893.  *        Arbitrary values are likely to cause undesirable results.  An
  894.  *        application should cross-check pfdin->setID to be certain the
  895.  *        external database is in sync with the CAB.  Reverse-skips are OK
  896.  *        (but may be inefficient) unless fdintNEXT_CABINET has been called.
  897.  *
  898.  *  fdintNEXT_CABINET:
  899.  *        This function is *only* called when fdintCOPY_FILE was told to copy
  900.  *        a file in the current cabinet that is continued to a subsequent
  901.  *        cabinet file.  It is important that the cabinet path name (psz3)
  902.  *        be validated before returning!  This function should ensure that
  903.  *        the cabinet exists and is readable before returning.  So, this
  904.  *        is the function that should, for example, issue a disk change
  905.  *        prompt and make sure the cabinet file exists.
  906.  *
  907.  *        When this function returns to FDI, FDI will check that the setID
  908.  *        and iCabinet match the expected values for the next cabinet.
  909.  *        If not, FDI will continue to call this function until the correct
  910.  *        cabinet file is specified, or until this function returns -1 to
  911.  *        abort the FDICopy() function.  pfdin->fdie is set to
  912.  *        FDIERROR_WRONG_CABINET to indicate this case.
  913.  *
  914.  *        If you *haven't* ensured that the cabinet file is present and
  915.  *        readable, or the cabinet file has been damaged, pfdin->fdie will
  916.  *        receive other appropriate error codes:
  917.  *
  918.  *              FDIERROR_CABINET_NOT_FOUND
  919.  *              FDIERROR_NOT_A_CABINET
  920.  *              FDIERROR_UNKNOWN_CABINET_VERSION
  921.  *              FDIERROR_CORRUPT_CABINET
  922.  *              FDIERROR_BAD_COMPR_TYPE
  923.  *              FDIERROR_RESERVE_MISMATCH
  924.  *              FDIERROR_WRONG_CABINET
  925.  *
  926.  *      Entry:
  927.  *          pfdin->psz1 = name of next cabinet where current file is continued
  928.  *          pfdin->psz2 = name of next disk where current file is continued
  929.  *          pfdin->psz3 = cabinet path name; FDI concatenates psz3 with psz1
  930.  *                          to produce the fully-qualified path for the cabinet
  931.  *                          file.  The 256-byte buffer pointed at by psz3 may
  932.  *                          be modified, but psz1 may not!
  933.  *          pfdin->fdie = FDIERROR_WRONG_CABINET if the previous call to
  934.  *                        fdintNEXT_CABINET specified a cabinet file that
  935.  *                        did not match the setID/iCabinet that was expected.
  936.  *      Exit-Success:
  937.  *          Return anything but -1
  938.  *      Exit-Failure:
  939.  *          Returns -1 => Abort FDICopy() call
  940.  *      Notes:
  941.  *          This call is almost always made when a target file is open and
  942.  *          being written to, and the next cabinet is needed to get more
  943.  *          data for the file.
  944.  }
  945.  
  946. type
  947.   TFDINOTIFICATIONTYPE =
  948.     (
  949.       fdintCABINET_INFO  // General information about cabinet
  950.       ,
  951.       fdintPARTIAL_FILE  // First file in cabinet is continuation
  952.       ,
  953.       fdintCOPY_FILE  // File to be copied
  954.       ,
  955.       fdintCLOSE_FILE_INFO  // close the file, set relevant info
  956.       ,
  957.       fdintNEXT_CABINET  // File continued to next cabinet
  958.       ,
  959.       fdintENUMERATE  // Enumeration status
  960.     );
  961.  
  962.                                        { fdint }
  963.   TFNFDINOTIFY_dummy = function (fdint : TFDINOTIFICATIONTYPE;
  964.     pfdin : PFDINOTIFICATION) : Integer; cdecl;
  965.   PFNFDINOTIFY = TFNFDINOTIFY_dummy;
  966.  
  967.                                        { pfnfdin }
  968.  
  969. {** cpuType values for FDICreate()
  970.  *
  971.  *  (Ignored by 32-bit FDI.)
  972.  }
  973.  
  974. const
  975.   cpuUNKNOWN = (-1);
  976.   cpu80286 = (0);
  977.   cpu80386 = (1);
  978.  
  979. {**    FDICreate - Create an FDI context
  980.  *
  981.  *  Entry:
  982.  *      pfnalloc
  983.  *      pfnfree
  984.  *      pfnopen
  985.  *      pfnread
  986.  *      pfnwrite
  987.  *      pfnclose
  988.  *      pfnlseek
  989.  *      cpuType  - Select CPU type (auto-detect, 286, or 386+)
  990.  *                 NOTE: For the 32-bit FDI.LIB, this parameter is ignored!
  991.  *      perf
  992.  *
  993.  *  Exit-Success:
  994.  *      Returns non-NULL FDI context handle.
  995.  *
  996.  *  Exit-Failure:
  997.  *      Returns NULL; perf filled in with error code
  998.  *
  999.  }
  1000.  
  1001.   function FDICreate (pfnalloc : PFNALLOC; pfnfree : PFNFREE; pfnopen : PFNOPEN; 
  1002.     pfnread : PFNREAD; pfnwrite : PFNWRITE; pfnclose : PFNCLOSE; 
  1003.   pfnseek : PFNSEEK; cpuType : Integer; perf : PERF) : HFDI; cdecl;
  1004.  
  1005. {**    FDIIsCabinet - Determines if file is a cabinet, returns info if it is
  1006.  *
  1007.  *  Entry:
  1008.  *      hfdi   - Handle to FDI context (created by FDICreate())
  1009.  *      hf     - File handle suitable for PFNREAD/PFNSEEK, positioned
  1010.  *               at offset 0 in the file to test.
  1011.  *      pfdici - Buffer to receive info about cabinet if it is one.
  1012.  *
  1013.  *  Exit-Success:
  1014.  *      Returns TRUE; file is a cabinet, pfdici filled in.
  1015.  *
  1016.  *  Exit-Failure:
  1017.  *      Returns FALSE, file is not a cabinet;  If an error occurred,
  1018.  *          perf (passed on FDICreate call!) filled in with error.
  1019.  }
  1020.  
  1021. function FDIIsCabinet (hfdi : HFDI; hf : Integer; pfdici : TPFDICABINETINFO) : BOOL; cdecl;
  1022.  
  1023. {**    FDICopy - extracts files from a cabinet
  1024.  *
  1025.  *  Entry:
  1026.  *      hfdi        - handle to FDI context (created by FDICreate())
  1027.  *      pszCabinet  - main name of cabinet file
  1028.  *      pszCabPath  - Path to cabinet file(s)
  1029.  *      flags       - Flags to modify behavior
  1030.  *      pfnfdin     - Notification function
  1031.  *      pfnfdid     - Decryption function (pass NULL if not used)
  1032.  *      pvUser      - User specified value to pass to notification function
  1033.  *
  1034.  *  Exit-Success:
  1035.  *      Returns TRUE;
  1036.  *
  1037.  *  Exit-Failure:
  1038.  *      Returns FALSE, perf (passed on FDICreate call!) filled in with
  1039.  *          error.
  1040.  *
  1041.  *  Notes:
  1042.  *  (1) If FDICopy() fails while a target file is being written out, then
  1043.  *      FDI will use the PFNCLOSE function to close the file handle for that
  1044.  *      target file that was returned from the fdintCOPY_FILE notification.
  1045.  *      The client application is then free to delete the target file, since
  1046.  *      it will not be in a valid state (since there was an error while
  1047.  *      writing it out).
  1048.  }
  1049.  
  1050.   function FDICopy (hfdi : HFDI; pszCabinet : PChar; pszCabPath : PChar; 
  1051.     flags : Integer; pfnfdin : PFNFDINOTIFY; pfnfdid : PFNFDIDECRYPT;
  1052.   pvUser : PVoid) : BOOL; cdecl;
  1053.  
  1054. {**    FDIDestroy - Destroy an FDI context
  1055.  *
  1056.  *  Entry:
  1057.  *      hfdi - handle to FDI context (created by FDICreate())
  1058.  *
  1059.  *  Exit-Success:
  1060.  *      Returns TRUE;
  1061.  *
  1062.  *  Exit-Failure:
  1063.  *      Returns FALSE;
  1064.  }
  1065.  
  1066. function FDIDestroy (hfdi : HFDI) : BOOL; cdecl;
  1067.  
  1068. function CompressionTypeFromTCOMP (tc : TCOMP) : Integer;
  1069.  
  1070. function CompressionLevelFromTCOMP (tc : TCOMP) : Integer;
  1071.  
  1072. function CompressionMemoryFromTCOMP (tc : TCOMP) : Integer;
  1073.  
  1074. function TCOMPfromTypeLevelMemory (t : Integer; l : Integer; m : Integer) : Integer;
  1075.  
  1076. function LZXCompressionWindowFromTCOMP (tc : TCOMP) : Integer;
  1077.  
  1078. function TCOMPfromLZXWindow (w : Integer) : Integer;
  1079.  
  1080. implementation
  1081.  
  1082. const
  1083.   CabinetDll = 'cabinet.dll';
  1084.  
  1085. function FDICreate; external CabinetDll name 'FDICreate';
  1086. function FDIIsCabinet; external CabinetDll name 'FDIIsCabinet';
  1087. function FDICopy; external CabinetDll name 'FDICopy';
  1088. function FDIDestroy; external CabinetDll name 'FDIDestroy';
  1089.  
  1090. function CompressionTypeFromTCOMP (tc : TCOMP) : Integer;
  1091. begin
  1092.   Result:=((tc) and $000F);
  1093. end;
  1094.  
  1095. function CompressionLevelFromTCOMP (tc : TCOMP) : Integer;
  1096. begin
  1097.   Result:=(((tc) and $00F0) shr 4);
  1098. end;
  1099.  
  1100. function CompressionMemoryFromTCOMP (tc : TCOMP) : Integer;
  1101. begin
  1102.   Result:=(((tc) and $1F00) shr 8);
  1103. end;
  1104.  
  1105. function TCOMPfromTypeLevelMemory (t : Integer; l : Integer;
  1106.   m : Integer) : Integer;
  1107. begin
  1108.   Result:=(((m) shl 8) or ((l) shl 4) or (t));
  1109. end;
  1110.  
  1111. function LZXCompressionWindowFromTCOMP (tc : TCOMP) : Integer;
  1112. begin
  1113.   Result:=(((tc) and $1F00) shr 8);
  1114. end;
  1115.  
  1116. function TCOMPfromLZXWindow (w : Integer) : Integer;
  1117. begin
  1118.   Result:=(((w) shl 8) or ($0003));
  1119. end;
  1120.  
  1121. end.
  1122.  
  1123.