⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fci.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * File Compression Interface
 *
 * Copyright 2002 Patrik Stridvall
 * Copyright 2005 Gerold Jens Wucherpfennig
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

/*

There is still some work to be done:

- no real compression yet
- unknown behaviour if files>=2GB or cabinet >=4GB
- check if the maximum size for a cabinet is too small to store any data
- call pfnfcignc on exactly the same position as MS FCIAddFile in every case
- probably check err

*/



#include "config.h"

#include <stdarg.h>
#include <stdio.h>
#include <string.h>

#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winternl.h"
#include "fci.h"
#include "cabinet.h"
#include "wine/debug.h"


#ifdef WORDS_BIGENDIAN
#define fci_endian_ulong(x) RtlUlongByteSwap(x)
#define fci_endian_uword(x) RtlUshortByteSwap(x)
#else
#define fci_endian_ulong(x) (x)
#define fci_endian_uword(x) (x)
#endif


#define fci_set_error(A,B,C) do {      \
    p_fci_internal->perf->erfOper = A; \
    p_fci_internal->perf->erfType = B; \
    p_fci_internal->perf->fError =  C; \
    if (B) SetLastError(B); } while(0)


typedef struct {
  cab_UBYTE signature[4]; /* !CAB for unfinished cabinets else MSCF */
  cab_ULONG reserved1;
  cab_ULONG cbCabinet;    /*  size of the cabinet file in bytes*/
  cab_ULONG reserved2;
  cab_ULONG coffFiles;    /* offset to first CFFILE section */
  cab_ULONG reserved3;
  cab_UBYTE versionMinor; /* 3 */
  cab_UBYTE versionMajor; /* 1 */
  cab_UWORD cFolders;     /* number of CFFOLDER entries in the cabinet*/
  cab_UWORD cFiles;       /* number of CFFILE entries in the cabinet*/
  cab_UWORD flags;        /* 1=prev cab, 2=next cabinet, 4=reserved setions*/
  cab_UWORD setID;        /* identification number of all cabinets in a set*/
  cab_UWORD iCabinet;     /* number of the cabinet in a set */
  /* additional area if "flags" were set*/
} CFHEADER; /* minimum 36 bytes */

typedef struct {
  cab_ULONG coffCabStart; /* offset to the folder's first CFDATA section */
  cab_UWORD cCFData;      /* number of this folder's CFDATA sections */
  cab_UWORD typeCompress; /* compression type of data in CFDATA section*/
  /* additional area if reserve flag was set */
} CFFOLDER; /* minumum 8 bytes */

typedef struct {
  cab_ULONG cbFile;          /* size of the uncompressed file in bytes */
  cab_ULONG uoffFolderStart; /* offset of the uncompressed file in the folder */
  cab_UWORD iFolder;         /* number of folder in the cabinet 0=first  */
                             /* for special values see below this structure*/
  cab_UWORD date;            /* last modification date*/
  cab_UWORD time;            /* last modification time*/
  cab_UWORD attribs;         /* DOS fat attributes and UTF indicator */
  /* ... and a C string with the name of the file */
} CFFILE; /* 16 bytes + name of file */


typedef struct {
  cab_ULONG csum;          /* checksum of this entry*/
  cab_UWORD cbData;        /* number of compressed bytes  */
  cab_UWORD cbUncomp;      /* number of bytes when data is uncompressed */
  /* optional reserved area */
  /* compressed data */
} CFDATA;


/***********************************************************************
 *		FCICreate (CABINET.10)
 *
 * FCICreate is provided with several callbacks and
 * returns a handle which can be used to create cabinet files.
 *
 * PARAMS
 *   perf       [IO]  A pointer to an ERF structure.  When FCICreate
 *                    returns an error condition, error information may
 *                    be found here as well as from GetLastError.
 *   pfnfiledest [I]  A pointer to a function which is called when a file
 *                    is placed. Only useful for subsequent cabinet files.
 *   pfnalloc    [I]  A pointer to a function which allocates ram.  Uses
 *                    the same interface as malloc.
 *   pfnfree     [I]  A pointer to a function which frees ram.  Uses the
 *                    same interface as free.
 *   pfnopen     [I]  A pointer to a function which opens a file.  Uses
 *                    the same interface as _open.
 *   pfnread     [I]  A pointer to a function which reads from a file into
 *                    a caller-provided buffer.  Uses the same interface
 *                    as _read.
 *   pfnwrite    [I]  A pointer to a function which writes to a file from
 *                    a caller-provided buffer.  Uses the same interface
 *                    as _write.
 *   pfnclose    [I]  A pointer to a function which closes a file handle.
 *                    Uses the same interface as _close.
 *   pfnseek     [I]  A pointer to a function which seeks in a file.
 *                    Uses the same interface as _lseek.
 *   pfndelete   [I]  A pointer to a function which deletes a file.
 *   pfnfcigtf   [I]  A pointer to a function which gets the name of a
 *                    temporary file.
 *   pccab       [I]  A pointer to an initialized CCAB structure.
 *   pv          [I]  A pointer to an application-defined notification
 *                    function which will be passed to other FCI functions
 *                    as a parameter.
 *
 * RETURNS
 *   On success, returns an FCI handle of type HFCI.
 *   On failure, the NULL file handle is returned. Error
 *   info can be retrieved from perf.
 *
 * INCLUDES
 *   fci.h
 *
 */
HFCI __cdecl FCICreate(
	PERF perf,
	PFNFCIFILEPLACED   pfnfiledest,
	PFNFCIALLOC        pfnalloc,
	PFNFCIFREE         pfnfree,
	PFNFCIOPEN         pfnopen,
	PFNFCIREAD         pfnread,
	PFNFCIWRITE        pfnwrite,
	PFNFCICLOSE        pfnclose,
	PFNFCISEEK         pfnseek,
	PFNFCIDELETE       pfndelete,
	PFNFCIGETTEMPFILE  pfnfcigtf,
	PCCAB              pccab,
	void *pv)
{
  HFCI hfci;
  int err;
  PFCI_Int p_fci_internal;

  if ((!perf) || (!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) ||
      (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) ||
      (!pfnfcigtf) || (!pccab)) {
    perf->erfOper = FCIERR_NONE;
    perf->erfType = ERROR_BAD_ARGUMENTS;
    perf->fError = TRUE;

    SetLastError(ERROR_BAD_ARGUMENTS);
    return NULL;
  }

  if (!((hfci = ((HFCI) (*pfnalloc)(sizeof(FCI_Int)))))) {
    perf->erfOper = FCIERR_ALLOC_FAIL;
    perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
    perf->fError = TRUE;

    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
    return NULL;
  }

  p_fci_internal=((PFCI_Int)(hfci));
  p_fci_internal->FCI_Intmagic = FCI_INT_MAGIC;
  p_fci_internal->perf = perf;
  p_fci_internal->pfnfiledest = pfnfiledest;
  p_fci_internal->pfnalloc = pfnalloc;
  p_fci_internal->pfnfree = pfnfree;
  p_fci_internal->pfnopen = pfnopen;
  p_fci_internal->pfnread = pfnread;
  p_fci_internal->pfnwrite = pfnwrite;
  p_fci_internal->pfnclose = pfnclose;
  p_fci_internal->pfnseek = pfnseek;
  p_fci_internal->pfndelete = pfndelete;
  p_fci_internal->pfnfcigtf = pfnfcigtf;
  p_fci_internal->pccab = pccab;
  p_fci_internal->fPrevCab = FALSE;
  p_fci_internal->fNextCab = FALSE;
  p_fci_internal->fSplitFolder = FALSE;
  p_fci_internal->fGetNextCabInVain = FALSE;
  p_fci_internal->pv = pv;
  p_fci_internal->data_in  = NULL;
  p_fci_internal->cdata_in = 0;
  p_fci_internal->data_out = NULL;
  p_fci_internal->cCompressedBytesInFolder = 0;
  p_fci_internal->cFolders = 0;
  p_fci_internal->cFiles = 0;
  p_fci_internal->cDataBlocks = 0;
  p_fci_internal->sizeFileCFDATA1 = 0;
  p_fci_internal->sizeFileCFFILE1 = 0;
  p_fci_internal->sizeFileCFDATA2 = 0;
  p_fci_internal->sizeFileCFFILE2 = 0;
  p_fci_internal->sizeFileCFFOLDER = 0;
  p_fci_internal->sizeFileCFFOLDER = 0;
  p_fci_internal->fNewPrevious = FALSE;
  p_fci_internal->estimatedCabinetSize = 0;
  p_fci_internal->statusFolderTotal = 0;

  memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);
  memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);

  /* CFDATA */
  if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA1,
      CB_MAX_FILENAME)) {
    fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
    return FALSE;
  }
  /* safety */
  if ( strlen(p_fci_internal->szFileNameCFDATA1) >= CB_MAX_FILENAME ) {
    fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
    return FALSE;
  }

  p_fci_internal->handleCFDATA1 = PFCI_OPEN(hfci,
    p_fci_internal->szFileNameCFDATA1, 34050, 384, &err, pv);
  if(p_fci_internal->handleCFDATA1==0){
    fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
    return FALSE;
  }
  /* TODO error checking of err */

  /* array of all CFFILE in a folder */
  if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE1,
      CB_MAX_FILENAME)) {
    fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
    return FALSE;
  }
  /* safety */
  if ( strlen(p_fci_internal->szFileNameCFFILE1) >= CB_MAX_FILENAME ) {
    fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
    return FALSE;
  }
  p_fci_internal->handleCFFILE1 = PFCI_OPEN(hfci,
    p_fci_internal->szFileNameCFFILE1, 34050, 384, &err, pv);
  if(p_fci_internal->handleCFFILE1==0){
    fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
    return FALSE;
  }
  /* TODO error checking of err */

  /* CFDATA with checksum and ready to be copied into cabinet */
  if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA2,
      CB_MAX_FILENAME)) {
    fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE);
    return FALSE;
  }
  /* safety */
  if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
    fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
    return FALSE;
  }
  p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
    p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, pv);
  if(p_fci_internal->handleCFDATA2==0){
    fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
    return FALSE;
  }
  /* TODO error checking of err */

  /* array of all CFFILE in a folder, ready to be copied into cabinet */
  if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
      CB_MAX_FILENAME)) {
    fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
    return FALSE;
  }
  /* safety */
  if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
    fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
    return FALSE;
  }
  p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
    p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, pv);
  if(p_fci_internal->handleCFFILE2==0){
    fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
    return FALSE;
  }
  /* TODO error checking of err */

  /* array of all CFFILE in a folder, ready to be copied into cabinet */
  if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,
      CB_MAX_FILENAME)) {
    fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
    return FALSE;
  }
  /* safety */
  if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
    fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
    return FALSE;
  }
  p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
    p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, pv);
  if(p_fci_internal->handleCFFOLDER==0) {
    fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
    return FALSE;
  }

  /* TODO close and delete new files when return FALSE */
  /* TODO error checking of err */

  return hfci;
} /* end of FCICreate */






static BOOL fci_flush_data_block (HFCI hfci, int* err,
    PFNFCISTATUS pfnfcis) {

  /* attention no hfci checks!!! */
  /* attention no checks if there is data available!!! */
  CFDATA data;
  CFDATA* cfdata=&data;
  char* reserved;
  PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
  UINT cbReserveCFData=p_fci_internal->pccab->cbReserveCFData;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -