#include <windows.h>
#pragma hdrstop
#include <stdio.h>
#include <stdlib.h>
#include "unzip.h"


#ifndef local
#  define local static
#endif

#define SIZECENTRALDIRITEM (0x2e)
#define SIZEZIPLOCALHEADER (0x1e)

static inline size_t zread(void *buffer, size_t size, size_t count, IKpiFile* pFile);
static inline int    zseek(IKpiFile* pFile, long offset, int origin);
static inline long   ztell(IKpiFile* pFile);

static inline size_t zread(void *buffer, size_t size, size_t count, IKpiFile* pFile)
{
    return pFile->Read(buffer, size * count)/size;
}
static inline int zseek(IKpiFile* pFile, long offset, int origin )
{
    return pFile->Seek(offset, origin) == KPI_FILE_EOF;
}
static inline long ztell(IKpiFile* pFile)
{
    return pFile->Seek(0, FILE_CURRENT);
}

#define BUFREADCOMMENT (0x400)
/*
  Locate the Central directory of a zipfile (at the end, just before
    the global comment)
*/
local ULONG unzlocal_SearchCentralDir(IKpiFile *pFile);
local ULONG unzlocal_SearchCentralDir(IKpiFile *pFile)
{
    unsigned char buf[BUFREADCOMMENT+4];
    ULONG uSizeFile;
    ULONG uBackRead;
    ULONG uMaxBack=0xffff; // maximum size of global comment
    ULONG uPosFound=0;

    if(zseek(pFile,0,SEEK_END) != 0){
        return 0;
    }
    uSizeFile = ztell(pFile);

    if (uMaxBack>uSizeFile){
        uMaxBack = uSizeFile;
    }
    uBackRead = 4;
    while (uBackRead<uMaxBack){
        ULONG uReadSize,uReadPos ;
        int i;
        if (uBackRead+BUFREADCOMMENT>uMaxBack)
            uBackRead = uMaxBack;
        else
            uBackRead+=BUFREADCOMMENT;
        uReadPos = uSizeFile-uBackRead ;

        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
        if(zseek(pFile, uReadPos, SEEK_SET) != 0)
            break;

        if(zread(buf,(UINT)uReadSize,1, pFile) != 1)
            break;

        for(i= (int)uReadSize-3; (i--)>0;)
            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)){
                uPosFound = uReadPos+i;
                break;
            }

        if(uPosFound != 0)
            break;
    }
    return uPosFound;
}

KbUnz::KbUnz(void)
{
    ZeroMemory(this, sizeof(KbUnz));
    m_hHeap = HeapCreate(0, 32768, 0);
    m_ppZipInfo = NULL;
    m_dwCount = 0;
    m_pCurrent = NULL;
}
KbUnz::~KbUnz(void)
{
    if(m_file){
        m_file->Release();
    }
    HeapDestroy(m_hHeap);//m_ppZipInfo や unz_file_info::pData がここで全て解放される
}
BOOL __fastcall KbUnz::Open(IKpiFile *pFile)
{
/* appnote.txt
  I.  End of central directory record:
        end of central dir signature    4 bytes  (0x06054b50)
        number of this disk             2 bytes
        number of the disk with the
        start of the central directory  2 bytes
        total number of entries in the
        central directory on this disk  2 bytes
        total number of entries in
        the central directory           2 bytes
        size of the central directory   4 bytes
        offset of start of central
        directory with respect to
        the starting disk number        4 bytes
        .ZIP file comment length        2 bytes
        .ZIP file comment       (variable size)
*/
#pragma pack(push, 1)
    // unz_file_info contain information about a file in the zipfile
    struct end_of_central_directory_record
    {
        DWORD  signature;          // end of central dir signature    4 bytes  (0x06054b50)
        WORD   number_disk;        // number of this disk             2 bytes
        WORD   number_disk_with_CD;// number of the disk with the start of the central directory 2 bytes       
        WORD   number_entry;       // start of the central directory  2 bytes
        WORD   number_entry_CD;    // total number of entries in the central directory 2 bytes
        DWORD  size_central_dir;   // size of the central directory   4 bytes
        DWORD  offset_central_dir; // offset of start of central directory with respect to
                                   // the starting disk number        4 bytes
        WORD   size_comment;       // .ZIP file comment length        2 bytes
        //.ZIP file comment       (variable size)
    };
#pragma pack(pop)
    pFile->Seek(0, FILE_BEGIN);
    ULONG central_pos = unzlocal_SearchCentralDir(pFile);
    if(central_pos == 0){
        return false;
    }
    end_of_central_directory_record record;
    zseek(pFile,central_pos,SEEK_SET);
    if(zread(&record, sizeof(record), 1, pFile) != 1){
        return false;
    }
    if ((record.number_entry_CD != record.number_entry) ||
        (record.number_disk_with_CD != 0) ||
        (record.number_disk != 0) ||
        (record.number_entry == 0) ||
        (central_pos < record.offset_central_dir + record.size_central_dir) ){
        return false;
    }
    m_number_entry = record.number_entry;
    m_size_central_dir = record.size_central_dir;
    m_offset_central_dir = record.offset_central_dir;
    m_byte_before_the_zipfile = central_pos -
                            (m_offset_central_dir + m_size_central_dir);
    m_central_pos = central_pos;
    m_file = pFile;
    m_file->AddRef();
    m_pos_in_central_dir = m_offset_central_dir;

    //格納ファイルの一覧を得る。
    m_ppZipInfo = (unz_file_info**)HeapAlloc(m_hHeap, 
                                             0,
                                             sizeof(unz_file_info*) * record.number_entry);
    unz_file_info *pZipInfo;
    int i;
    for(i = 0; i < record.number_entry; i++){
        pZipInfo = (unz_file_info*)HeapAlloc(m_hHeap,
                                             HEAP_ZERO_MEMORY,
                                             sizeof(unz_file_info));
        if(GetCurrentFileInfoInternal(pZipInfo) != UNZ_OK){
            break;
        }
        pZipInfo->fi.cb = sizeof(KPI_FILEINFO);
        pZipInfo->fi.qwOriginalSize = pZipInfo->header.uncompressed_size;
        pZipInfo->fi.qwCompressedSize = pZipInfo->header.compressed_size;
        pZipInfo->fi.cszFileName = pZipInfo->szFileName;
        static const wchar_t *cszMethods[] = 
        {
            L"Stored",           //0
            L"Shrunk",           //1
            L"Reduce1",          //2
            L"Reduce2",          //3
            L"Reduce3",          //4
            L"Reduce4",          //5
            L"Implode",          //6
            L"Token",            //7
            L"Deflate",          //8
            L"Deflate64",        //9
            L"Implode(PK DCL)",  //10
            L""                  //11
            L"BZIP2"             //12
            L""                  //13
            L"LZMA"              //14
            L""                  //15
        };
        int method = pZipInfo->header.compression_method;
        if(method < 0 || method > 15){
            method = 11;
        }
        pZipInfo->fi.cszMethod = cszMethods[method];
        pZipInfo->fi.bCrypted =  (pZipInfo->header.flag & 0x0001) != 0;
        pZipInfo->fi.bStored = (method == UNZ_STORED);
        WORD wDate = (pZipInfo->header.dosDate >> 16);
        WORD wTime = (pZipInfo->header.dosDate & 0xFFFF);
        DosDateTimeToFileTime(wDate, wTime, &pZipInfo->fi.ft);

        m_ppZipInfo[m_dwCount++] = pZipInfo;
        m_pos_in_central_dir += SIZECENTRALDIRITEM + 
                                pZipInfo->header.size_filename +
                                pZipInfo->header.size_extra_field + 
                                pZipInfo->header.size_file_comment;
    }
    if(i > 0){
        return TRUE;
    }
    else{
        return FALSE;
    }
}
void __fastcall KbUnz::Close(void)
{
}
//
// Get Info about the current file in the zipfile, with internal only info
//
int __fastcall KbUnz::GetCurrentFileInfoInternal(unz_file_info *pfile_info)
{
    zseek(m_file, m_pos_in_central_dir + m_byte_before_the_zipfile, SEEK_SET);
    if(zread(&pfile_info->header, sizeof(pfile_info->header), 1, m_file) != 1){
        return UNZ_ERRNO;
    }
    if(pfile_info->header.signature != 0x02014b50){
        return UNZ_BADZIPFILE;
    }
    int err = UNZ_OK;
    //if(pfile_info->header.size_filename < sizeof(pfile_info->szFileName)){
    if(pfile_info->header.size_filename < MAX_PATH*2){
        char szFileNameA[MAX_PATH*2];
        if(zread(szFileNameA, 
                 pfile_info->header.size_filename, 1, m_file) != 1){
            err = UNZ_ERRNO;
            pfile_info->szFileName[0] = 0;
        }
        else{
            szFileNameA[pfile_info->header.size_filename] = 0;
            if(pfile_info->header.flag & 0x800){//UTF8
                MultiByteToWideChar(CP_UTF8, 0, szFileNameA, -1, pfile_info->szFileName, _countof(pfile_info->szFileName));
            }
            else{
                MultiByteToWideChar(CP_ACP, 0, szFileNameA, -1, pfile_info->szFileName, _countof(pfile_info->szFileName));
            } 
            pfile_info->szFileName[_countof(pfile_info->szFileName)-1] = 0;
        }
    }
    else{//ファイル名が長すぎる
        err = UNZ_ERRNO;
    }
    return err;
}
//  Read the local header of the current zipfile
//  Check the coherency of the local header and info in the end of central
//        directory about this file
//  store in *piSizeVar the size of extra info in local header
//        (filename and size of extra field data)
int __fastcall KbUnz::CheckCurrentFileCoherencyHeader(UINT* piSizeVar,
                                                      ULONG *poffset_local_extrafield,
                                                      UINT  *psize_local_extrafield)
{
    *piSizeVar = 0;
    *poffset_local_extrafield = 0;
    *psize_local_extrafield = 0;
    int err=UNZ_OK;

    zseek(m_file, 
          m_pCurrent->header.offset_curfile + m_byte_before_the_zipfile,
          SEEK_SET);
/*
    appnote.txt
  A.  Local file header:

        local file header signature     4 bytes  (0x04034b50)
        version needed to extract       2 bytes
        general purpose bit flag        2 bytes
        compression method              2 bytes
        last mod file time              2 bytes
        last mod file date              2 bytes
        crc-32                          4 bytes
        compressed size                 4 bytes
        uncompressed size               4 bytes
        file name length                2 bytes
        extra field length              2 bytes

        file name (variable size)
        extra field (variable size)
*/
#pragma pack(push, 1)
    struct zip_local_file_header{
        DWORD signature;            // local file header signature     4 bytes  (0x04034b50)
        WORD  version;              // version needed to extract       2 bytes
        WORD  flag;                 // general purpose bit flag        2 bytes
        WORD  compression_method;   // compression method              2 bytes
        DWORD dosDate;              // last mod file date in Dos fmt   4 bytes
        DWORD crc;                  // crc-32                          4 bytes
        DWORD compressed_size;      // compressed size                 4 bytes
        DWORD uncompressed_size;    // uncompressed size               4 bytes
        WORD  size_filename;        // filename length                 2 bytes
        WORD  size_extra_field;     // extra field length              2 bytes
    }h;
#pragma pack(pop)
    if(zread(&h, sizeof(h), 1, m_file) != 1){
        return UNZ_ERRNO;
    }
    if(h.signature != 0x04034b50){
        return UNZ_ERRNO;
    }
    else if(h.compression_method != m_pCurrent->header.compression_method){
        return UNZ_ERRNO;
    }
    else if(h.crc != m_pCurrent->header.crc && ((h.flag & 8) == 0)){
        return UNZ_ERRNO;
    }
    else if(h.compressed_size != m_pCurrent->header.compressed_size && ((h.flag & 8) == 0)){
        return UNZ_ERRNO;
    }
    else if(h.uncompressed_size != m_pCurrent->header.uncompressed_size && ((h.flag & 8) == 0)){
        return UNZ_ERRNO;
    }
    else if(h.size_filename != m_pCurrent->header.size_filename){
        return UNZ_ERRNO;
    }
    *piSizeVar += h.size_filename;
    *poffset_local_extrafield = m_pCurrent->header.offset_curfile + 
                                SIZEZIPLOCALHEADER + h.size_filename;
    *piSizeVar += h.size_extra_field;
    return err;
}
int __fastcall CheckCurrentFileCoherencyHeader(IKpiFile *pFile,
                                               KbUnz::central_directory_file_header *pHeader,
                                               ULONG  byte_before_the_zipfile,
                                               UINT  *piSizeVar,
                                               ULONG *poffset_local_extrafield,
                                               UINT  *psize_local_extrafield)
{
    *piSizeVar = 0;
    *poffset_local_extrafield = 0;
    *psize_local_extrafield = 0;
    int err=UNZ_OK;

    zseek(pFile, 
          pHeader->offset_curfile + byte_before_the_zipfile,
          SEEK_SET);
/*
    appnote.txt
  A.  Local file header:

        local file header signature     4 bytes  (0x04034b50)
        version needed to extract       2 bytes
        general purpose bit flag        2 bytes
        compression method              2 bytes
        last mod file time              2 bytes
        last mod file date              2 bytes
        crc-32                          4 bytes
        compressed size                 4 bytes
        uncompressed size               4 bytes
        file name length                2 bytes
        extra field length              2 bytes

        file name (variable size)
        extra field (variable size)
*/
#pragma pack(push, 1)
    struct zip_local_file_header{
        DWORD signature;            // local file header signature     4 bytes  (0x04034b50)
        WORD  version;              // version needed to extract       2 bytes
        WORD  flag;                 // general purpose bit flag        2 bytes
        WORD  compression_method;   // compression method              2 bytes
        DWORD dosDate;              // last mod file date in Dos fmt   4 bytes
        DWORD crc;                  // crc-32                          4 bytes
        DWORD compressed_size;      // compressed size                 4 bytes
        DWORD uncompressed_size;    // uncompressed size               4 bytes
        WORD  size_filename;        // filename length                 2 bytes
        WORD  size_extra_field;     // extra field length              2 bytes
    }h;
#pragma pack(pop)
    if(zread(&h, sizeof(h), 1, pFile) != 1){
        return UNZ_ERRNO;
    }
    if(h.signature != 0x04034b50){
        return UNZ_ERRNO;
    }
    else if(h.compression_method != pHeader->compression_method){
        return UNZ_ERRNO;
    }
    else if(h.crc != pHeader->crc && ((h.flag & 8) == 0)){
        return UNZ_ERRNO;
    }
    else if(h.compressed_size != pHeader->compressed_size && ((h.flag & 8) == 0)){
        return UNZ_ERRNO;
    }
    else if(h.uncompressed_size != pHeader->uncompressed_size && ((h.flag & 8) == 0)){
        return UNZ_ERRNO;
    }
    else if(h.size_filename != pHeader->size_filename){
        return UNZ_ERRNO;
    }
    *piSizeVar += h.size_filename;
    *poffset_local_extrafield = pHeader->offset_curfile + 
                                SIZEZIPLOCALHEADER + h.size_filename;
    *piSizeVar += h.size_extra_field;
    return err;
}
//
//  Open for reading data the current file in the zipfile.
//  If there is no error and the file is opened, the return value is UNZ_OK.
//
int __fastcall KbUnz::unzOpenCurrentFile(file_in_zip_read_info_s *pInfo)
{
    file_in_zip_read_info_s* pfile_in_zip_read_info = pInfo;
    int   err=UNZ_OK;
    int   Store;
    UINT  iSizeVar;
    ULONG offset_local_extrafield;// offset of the local extra field
    UINT  size_local_extrafield;  // size of the local extra field

    if(CheckCurrentFileCoherencyHeader(&iSizeVar,
                                       &offset_local_extrafield,
                                       &size_local_extrafield) != UNZ_OK){
        return UNZ_BADZIPFILE;
    }
    pfile_in_zip_read_info->init();
    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
    pfile_in_zip_read_info->pos_local_extrafield=0;
    pfile_in_zip_read_info->stream_initialised=0;

    if ((m_pCurrent->header.compression_method!=0) &&
        (m_pCurrent->header.compression_method!=Z_DEFLATED)){
        err=UNZ_BADZIPFILE;
    }
    Store = m_pCurrent->header.compression_method==0;

    pfile_in_zip_read_info->crc32_wait = m_pCurrent->header.crc;
    pfile_in_zip_read_info->crc32 = 0;
    pfile_in_zip_read_info->compression_method = m_pCurrent->header.compression_method;
    pfile_in_zip_read_info->byte_before_the_zipfile = m_byte_before_the_zipfile;
    pfile_in_zip_read_info->stream.total_out = 0;
    pfile_in_zip_read_info->file = m_file;
    ZeroMemory(&G, sizeof(G));
    if (!Store)
    {
        pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
        pfile_in_zip_read_info->stream.zfree = (free_func)0;
        pfile_in_zip_read_info->stream.opaque = (voidpf)0;

        err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
        if (err == Z_OK)
            pfile_in_zip_read_info->stream_initialised=1;
        // windowBits is passed < 0 to tell that there is no zlib header.
        // Note that in this case inflate *requires* an extra "dummy" byte
        // after the compressed stream in order to complete decompression and
        // return Z_STREAM_END.
        // In unzip, i don't wait absolutely Z_STREAM_END because I known the
        // size of both compressed and uncompressed data
    }
    pfile_in_zip_read_info->rest_read_compressed = m_pCurrent->header.compressed_size;
    pfile_in_zip_read_info->rest_read_uncompressed = m_pCurrent->header.uncompressed_size;
    pfile_in_zip_read_info->pos_in_zipfile =
            m_pCurrent->header.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar;
    pfile_in_zip_read_info->stream.avail_in = (UINT)0;
    return UNZ_OK;
}
int __fastcall KbUnz::unzOpenCurrentFile(void)
{
    file_in_zip_read_info_s* pfile_in_zip_read_info = &m_file_in_zip_read;
    int   err=UNZ_OK;
    int   Store;
    UINT  iSizeVar;
    ULONG offset_local_extrafield;// offset of the local extra field
    UINT  size_local_extrafield;  // size of the local extra field

    if(CheckCurrentFileCoherencyHeader(&iSizeVar,
                                       &offset_local_extrafield,
                                       &size_local_extrafield) != UNZ_OK){
        return UNZ_BADZIPFILE;
    }
    pfile_in_zip_read_info->init();
    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
    pfile_in_zip_read_info->pos_local_extrafield=0;
    pfile_in_zip_read_info->stream_initialised=0;

    if ((m_pCurrent->header.compression_method!=0) &&
        (m_pCurrent->header.compression_method!=Z_DEFLATED)){
        err=UNZ_BADZIPFILE;
    }
    Store = m_pCurrent->header.compression_method==0;

    pfile_in_zip_read_info->crc32_wait = m_pCurrent->header.crc;
    pfile_in_zip_read_info->crc32 = 0;
    pfile_in_zip_read_info->compression_method = m_pCurrent->header.compression_method;
    pfile_in_zip_read_info->byte_before_the_zipfile = m_byte_before_the_zipfile;
    pfile_in_zip_read_info->stream.total_out = 0;
    pfile_in_zip_read_info->file = m_file;

    if (!Store)
    {
        pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
        pfile_in_zip_read_info->stream.zfree = (free_func)0;
        pfile_in_zip_read_info->stream.opaque = (voidpf)0;

        err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
        if (err == Z_OK)
            pfile_in_zip_read_info->stream_initialised=1;
        // windowBits is passed < 0 to tell that there is no zlib header.
        // Note that in this case inflate *requires* an extra "dummy" byte
        // after the compressed stream in order to complete decompression and
        // return Z_STREAM_END.
        // In unzip, i don't wait absolutely Z_STREAM_END because I known the
        // size of both compressed and uncompressed data
    }
    pfile_in_zip_read_info->rest_read_compressed = m_pCurrent->header.compressed_size;
    pfile_in_zip_read_info->rest_read_uncompressed = m_pCurrent->header.uncompressed_size;
    pfile_in_zip_read_info->pos_in_zipfile =
            m_pCurrent->header.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar;
    pfile_in_zip_read_info->stream.avail_in = (UINT)0;
    return UNZ_OK;
}
/*
  Read bytes from the current file.
  buf contain buffer where data must be copied
  len the size of buf.

  return the number of byte copied if somes bytes are copied
  return 0 if the end of file was reached
  return <0 with error code if there is an error
    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
*/
int __fastcall KbUnz::unzReadCurrentFile(BYTE* buf, int len)
{
    int err = UNZ_OK;
    UINT iRead = 0;
    file_in_zip_read_info_s* pfile_in_zip_read_info;
    pfile_in_zip_read_info = &m_file_in_zip_read;

    if(len <= 0){
        return 0;
    }

    pfile_in_zip_read_info->stream.next_out = (BYTE*)buf;
    pfile_in_zip_read_info->stream.avail_out = (UINT)len;

    if(len>pfile_in_zip_read_info->rest_read_uncompressed)
        pfile_in_zip_read_info->stream.avail_out =
          (UINT)pfile_in_zip_read_info->rest_read_uncompressed;

    int old_avail_out = pfile_in_zip_read_info->stream.avail_out;
    while (pfile_in_zip_read_info->stream.avail_out > 0 && err == UNZ_OK)
    {
        if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
            (pfile_in_zip_read_info->rest_read_compressed > 0) &&
            (pfile_in_zip_read_info->compression_method == UNZ_STORED ||
             pfile_in_zip_read_info->compression_method == UNZ_DEFLATED))
        {
            UINT uReadThis = UNZ_BUFSIZE;
            if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
                uReadThis = (UINT)pfile_in_zip_read_info->rest_read_compressed;
            if (uReadThis == 0)
                return UNZ_EOF;
            if (zseek(pfile_in_zip_read_info->file,
                      pfile_in_zip_read_info->pos_in_zipfile +
                      pfile_in_zip_read_info->byte_before_the_zipfile, SEEK_SET)!=0)
                return UNZ_ERRNO;
            if (zread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
                         pfile_in_zip_read_info->file)!=1)
                return UNZ_ERRNO;
            pfile_in_zip_read_info->pos_in_zipfile += uReadThis;

            pfile_in_zip_read_info->rest_read_compressed -= uReadThis;

            pfile_in_zip_read_info->stream.next_in =
                (BYTE*)pfile_in_zip_read_info->read_buffer;
            pfile_in_zip_read_info->stream.avail_in = (UINT)uReadThis;
        }

        if (pfile_in_zip_read_info->compression_method == UNZ_STORED)//Stored
        {//無圧縮
            UINT uDoCopy,i ;
            if (pfile_in_zip_read_info->stream.avail_out <
                            pfile_in_zip_read_info->stream.avail_in)
                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
            else
                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;

            for (i = 0; i < uDoCopy;i++)
                *(pfile_in_zip_read_info->stream.next_out+i) =
                        *(pfile_in_zip_read_info->stream.next_in+i);

            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
                                pfile_in_zip_read_info->stream.next_out,
                                uDoCopy);
            pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
            pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
            pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
            pfile_in_zip_read_info->stream.next_out += uDoCopy;
            pfile_in_zip_read_info->stream.next_in += uDoCopy;
            pfile_in_zip_read_info->stream.total_out += uDoCopy;
            iRead += uDoCopy;
        }
        else if(pfile_in_zip_read_info->compression_method == UNZ_IMPLODED)//Implode
        {
            int true_rest_read_uncompressed = pfile_in_zip_read_info->rest_read_uncompressed;
            err = explode ();
            iRead = len - pfile_in_zip_read_info->stream.avail_out;
            if(iRead < 0)
                iRead = 0;
            else if(iRead> len)
                iRead = len;
            return iRead;
        }
        else if(pfile_in_zip_read_info->compression_method == UNZ_SHRUNK)//shrunk
        {
            iRead = unShrink();
            if(iRead < 0)
                iRead = 0;
            else if(iRead> len)
                iRead = len;
            return iRead;
        }
        else if(pfile_in_zip_read_info->compression_method == UNZ_DEFLATE64)
        {
            if(inflate(1) == 0){
                iRead = pfile_in_zip_read_info->stream.total_out;
            }
            else{
                return iRead;
            }
        }
        else//Deflate
        {
            ULONG uTotalOutBefore,uTotalOutAfter;
            const BYTE *bufBefore;
            ULONG uOutThis;
            int flush=Z_SYNC_FLUSH;

            uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
            bufBefore = pfile_in_zip_read_info->stream.next_out;

            err=::inflate(&pfile_in_zip_read_info->stream,flush);

            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
            uOutThis = uTotalOutAfter-uTotalOutBefore;

            pfile_in_zip_read_info->crc32 =
                crc32(pfile_in_zip_read_info->crc32,bufBefore,
                        (UINT)(uOutThis));

            pfile_in_zip_read_info->rest_read_uncompressed -=
                uOutThis;

            iRead += (UINT)(uTotalOutAfter - uTotalOutBefore);

            if (err==Z_STREAM_END)
                return (iRead==0) ? UNZ_EOF : iRead;
            if (err!=Z_OK)
                break;
        }
        //以下の３行は安全のために実行
        if(old_avail_out <= pfile_in_zip_read_info->stream.avail_out)
            return len;
        old_avail_out = pfile_in_zip_read_info->stream.avail_out;
    }
    if (err==Z_OK)
        return iRead;
    return err;
}
/*
  Close the file in zip opened with unzipOpenCurrentFile
  Return UNZ_CRCERROR if all the file was read but the CRC is not good
*/
int __fastcall KbUnz::unzCloseCurrentFile(void)
{
    int err=UNZ_OK;

    file_in_zip_read_info_s* pfile_in_zip_read_info = &m_file_in_zip_read;
    if(pfile_in_zip_read_info->stream_initialised)
        inflateEnd(&pfile_in_zip_read_info->stream);
    pfile_in_zip_read_info->init();

    return err;
}
//
//Implode を解凍するためのAPI群
//
//* Function prototypes */
//* routines from inflate.c */
int huft_free OF((struct huft *));
/* The implode algorithm uses a sliding 4K or 8K byte window on the
   uncompressed stream to find repeated byte strings.  This is implemented
   here as a circular buffer.  The index is updated simply by incrementing
   and then and'ing with 0x0fff (4K-1) or 0x1fff (8K-1).  Here, the 32K
   buffer of inflate is used, and it works just as well to always have
   a 32K circular buffer, so the index is anded with 0x7fff.  This is
   done to allow the window to also be used as the output buffer. */
/* This must be supplied in an external module useable like "byte slide[8192];"
   or "byte *slide;", where the latter would be malloc'ed.  In unzip, slide[]
   is actually a 32K area for use by inflate, which uses a 32K sliding window.
 */

// Tables for length and distance
const WORD cplen2[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
        18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65};
const WORD cplen3[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
        19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
        36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
        53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66};
const WORD extra[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        8};
const WORD cpdist4[] = {1, 65, 129, 193, 257, 321, 385, 449, 513, 577, 641, 705,
        769, 833, 897, 961, 1025, 1089, 1153, 1217, 1281, 1345, 1409, 1473,
        1537, 1601, 1665, 1729, 1793, 1857, 1921, 1985, 2049, 2113, 2177,
        2241, 2305, 2369, 2433, 2497, 2561, 2625, 2689, 2753, 2817, 2881,
        2945, 3009, 3073, 3137, 3201, 3265, 3329, 3393, 3457, 3521, 3585,
        3649, 3713, 3777, 3841, 3905, 3969, 4033};
const WORD cpdist8[] = {1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153, 1281,
        1409, 1537, 1665, 1793, 1921, 2049, 2177, 2305, 2433, 2561, 2689,
        2817, 2945, 3073, 3201, 3329, 3457, 3585, 3713, 3841, 3969, 4097,
        4225, 4353, 4481, 4609, 4737, 4865, 4993, 5121, 5249, 5377, 5505,
        5633, 5761, 5889, 6017, 6145, 6273, 6401, 6529, 6657, 6785, 6913,
        7041, 7169, 7297, 7425, 7553, 7681, 7809, 7937, 8065};

/* Macros for inflate() bit peeking and grabbing.
   The usage is:

        NEEDBITS(j)
        x = b & mask_bits[j];
        DUMPBITS(j)

   where NEEDBITS makes sure that b has at least j bits in it, and
   DUMPBITS removes the bits from b.  The macros use the variable k
   for the number of bits in b.  Normally, b and k are register
   variables for speed.
 */
#define NEXTBYTE    (ReadByte(&m_bytebuf), m_bytebuf)
#define NEEDBITS(n) {while(k<(n)){b|=((ULONG)NEXTBYTE)<<k;k+=8;}}
#define DUMPBITS(n) {b>>=(n);k-=(n);}

                          //  at least 32K for zip's deflate method
static const WORD mask_bits[] = {
    0x0000,
    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};

int __fastcall KbUnz::get_tree(unsigned *l, unsigned n)
//unsigned *l;            /* bit lengths */
//unsigned n;             /* number expected */
///* Get the bit lengths for a code representation from the compressed
//   stream.  If get_tree() returns 4, then there is an error in the data.
//   Otherwise zero is returned. */
{
  unsigned i;           /* bytes remaining in list */
  unsigned k;           /* lengths entered */
  unsigned j;           /* number of codes */
  unsigned b;           /* bit length for those codes */

  /* get bit lengths */
  ReadByte(&m_bytebuf);
  i = m_bytebuf + 1;                      /* length/count pairs to read */
  k = 0;                                /* next code */
  do {
    ReadByte(&m_bytebuf);
    b = ((j = m_bytebuf) & 0xf) + 1;      /* bits in code (1..16) */
    j = ((j & 0xf0) >> 4) + 1;          /* codes with those bits (1..16) */
    if (k + j > n)
      return 4;                         /* don't overflow l[] */
    do {
      l[k++] = b;
    } while (--j);
  } while (--i);
  return k != n ? 4 : 0;                /* should have read n of them */
}

int __fastcall KbUnz::explode_lit8(huft *tb, huft *tl, huft *td, int bb, int bl, int bd)
//struct huft *tb, *tl, *td;      /* literal, length, and distance tables */
//int bb, bl, bd;                 /* number of bits decoded by those */
///* Decompress the imploded data using coded literals and an 8K sliding
//   window. */
{
  long s;             // bytes to decompress
  register unsigned e;// table entry flag/number of extra bits
  unsigned n, d;      // length and index for copy
  unsigned w;         // current window position
  struct huft *t;     // pointer to table entry
  unsigned mb, ml, md;// masks for bb, bl, and bd bits
  register ULONG b;   // bit buffer
  register unsigned k;// number of bits in bit buffer
  unsigned u;         // true if unflushed

  // explode the coded data
  b = k = w = 0;           // initialize bit buffer, window
  u = 1;                   // buffer unflushed
  mb = mask_bits[bb];      // precompute masks for speed
  ml = mask_bits[bl];
  md = mask_bits[bd];
  s = m_file_in_zip_read.rest_read_uncompressed;

  while (s > 0)                 // do until ucsize bytes uncompressed
  {
    NEEDBITS(1)
    if (b & 1)                  // then literal--decode it
    {
      DUMPBITS(1)
      s--;
      NEEDBITS((unsigned)bb)    // get coded literal
      if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
        do {
          if (e == 99)
            return 1;
          DUMPBITS(t->b)
          e -= 16;
          NEEDBITS(e)
        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
      DUMPBITS(t->b)
      m_area.Slide[w++] = (byte)t->v.n;
      if (w == WSIZE)
      {
        flush(w);
        w = u = 0;
      }
    }
    else                        // else distance/length
    {
      DUMPBITS(1)
      NEEDBITS(7)               // get distance low bits
      d = (unsigned)b & 0x7f;
      DUMPBITS(7)
      NEEDBITS((unsigned)bd)    // get coded distance high bits
      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
        do {
          if (e == 99)
            return 1;
          DUMPBITS(t->b)
          e -= 16;
          NEEDBITS(e)
        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
      DUMPBITS(t->b)
      d = w - d - t->v.n;       // construct offset
      NEEDBITS((unsigned)bl)    // get coded length
      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
        do {
          if (e == 99)
            return 1;
          DUMPBITS(t->b)
          e -= 16;
          NEEDBITS(e)
        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
      DUMPBITS(t->b)
      n = t->v.n;
      if (e)                    // get length extra bits
      {
        NEEDBITS(8)
        n += (unsigned)b & 0xff;
        DUMPBITS(8)
      }

      // do the copy
      s -= n;
      do {
        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
        if (u && w <= d)
        {
          memset(m_area.Slide + w, 0, e);
          w += e;
          d += e;
        }
        else
#ifndef NOMEMCPY
          if (w - d >= e)       // (this test assumes unsigned comparison)
          {
            memcpy(m_area.Slide + w, m_area.Slide + d, e);
            w += e;
            d += e;
          }
          else                  // do it slow to avoid memcpy() overlap
#endif // !NOMEMCPY
            do {
              m_area.Slide[w++] = m_area.Slide[d++];
            } while (--e);
        if (w == WSIZE)
        {
          flush(w);
          w = u = 0;
        }
      } while (n);
    }
  }

  // flush out slide
  flush(w);
  return m_file_in_zip_read.rest_read_compressed ? 5 : 0;// should have read csize bytes
}



int __fastcall KbUnz::explode_lit4(huft *tb, huft *tl, huft *td, int bb, int bl, int bd)
//struct huft *tb, *tl, *td;      /* literal, length, and distance tables */
//int bb, bl, bd;                 /* number of bits decoded by those */
///* Decompress the imploded data using coded literals and a 4K sliding
//   window. */
{
  long s;               /* bytes to decompress */
  register unsigned e;  /* table entry flag/number of extra bits */
  unsigned n, d;        /* length and index for copy */
  unsigned w;           /* current window position */
  struct huft *t;       /* pointer to table entry */
  unsigned mb, ml, md;  /* masks for bb, bl, and bd bits */
  register ULONG b;     /* bit buffer */
  register unsigned k;  /* number of bits in bit buffer */
  unsigned u;           /* true if unflushed */


  /* explode the coded data */
  b = k = w = 0;                /* initialize bit buffer, window */
  u = 1;                        /* buffer unflushed */
  mb = mask_bits[bb];           /* precompute masks for speed */
  ml = mask_bits[bl];
  md = mask_bits[bd];
  s = m_file_in_zip_read.rest_read_uncompressed;
  while (s > 0)                 /* do until ucsize bytes uncompressed */
  {
    NEEDBITS(1)
    if (b & 1)                  /* then literal--decode it */
    {
      DUMPBITS(1)
      s--;
      NEEDBITS((unsigned)bb)    /* get coded literal */
      if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
        do {
          if (e == 99)
            return 1;
          DUMPBITS(t->b)
          e -= 16;
          NEEDBITS(e)
        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
      DUMPBITS(t->b)
      m_area.Slide[w++] = (byte)t->v.n;
      if (w == WSIZE)
      {
        flush(w);
        w = u = 0;
      }
    }
    else                        /* else distance/length */
    {
      DUMPBITS(1)
      NEEDBITS(6)               /* get distance low bits */
      d = (unsigned)b & 0x3f;
      DUMPBITS(6)
      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
        do {
          if (e == 99)
            return 1;
          DUMPBITS(t->b)
          e -= 16;
          NEEDBITS(e)
        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
      DUMPBITS(t->b)
      d = w - d - t->v.n;       /* construct offset */
      NEEDBITS((unsigned)bl)    /* get coded length */
      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
        do {
          if (e == 99)
            return 1;
          DUMPBITS(t->b)
          e -= 16;
          NEEDBITS(e)
        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
      DUMPBITS(t->b)
      n = t->v.n;
      if (e)                    /* get length extra bits */
      {
        NEEDBITS(8)
        n += (unsigned)b & 0xff;
        DUMPBITS(8)
      }

      /* do the copy */
      s -= n;
      do {
        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
        if (u && w <= d)
        {
          memset(m_area.Slide + w, 0, e);
          w += e;
          d += e;
        }
        else
#ifndef NOMEMCPY
          if (w - d >= e)       /* (this test assumes unsigned comparison) */
          {
            memcpy(m_area.Slide + w, m_area.Slide + d, e);
            w += e;
            d += e;
          }
          else                  /* do it slow to avoid memcpy() overlap */
#endif /* !NOMEMCPY */
            do {
              m_area.Slide[w++] = m_area.Slide[d++];
            } while (--e);
        if (w == WSIZE)
        {
          flush(w);
          w = u = 0;
        }
      } while (n);
    }
  }

  /* flush out slide */
  flush(w);
  return m_file_in_zip_read.rest_read_compressed ? 5 : 0;// should have read csize bytes */
}

int __fastcall KbUnz::explode_nolit8(huft *tl, huft *td, int bl, int bd)
//struct huft *tl, *td;   /* length and distance decoder tables */
//int bl, bd;             /* number of bits decoded by tl[] and td[] */
///* Decompress the imploded data using uncoded literals and an 8K sliding
//   window. */
{
  long s;               /* bytes to decompress */
  register unsigned e;  /* table entry flag/number of extra bits */
  unsigned n, d;        /* length and index for copy */
  unsigned w;           /* current window position */
  struct huft *t;       /* pointer to table entry */
  unsigned ml, md;      /* masks for bl and bd bits */
  register ULONG b;     /* bit buffer */
  register unsigned k;  /* number of bits in bit buffer */
  unsigned u;           /* true if unflushed */


  /* explode the coded data */
  b = k = w = 0;                /* initialize bit buffer, window */
  u = 1;                        /* buffer unflushed */
  ml = mask_bits[bl];           /* precompute masks for speed */
  md = mask_bits[bd];
  s = m_file_in_zip_read.rest_read_uncompressed;
  while (s > 0)                 /* do until ucsize bytes uncompressed */
  {
    NEEDBITS(1)
    if (b & 1)                  /* then literal--get eight bits */
    {
      DUMPBITS(1)
      s--;
      NEEDBITS(8)
      m_area.Slide[w++] = (byte)b;
      if (w == WSIZE)
      {
        flush(w);
        w = u = 0;
      }
      DUMPBITS(8)
    }
    else                        /* else distance/length */
    {
      DUMPBITS(1)
      NEEDBITS(7)               /* get distance low bits */
      d = (unsigned)b & 0x7f;
      DUMPBITS(7)
      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
        do {
          if (e == 99)
            return 1;
          DUMPBITS(t->b)
          e -= 16;
          NEEDBITS(e)
        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
      DUMPBITS(t->b)
      d = w - d - t->v.n;       /* construct offset */
      NEEDBITS((unsigned)bl)    /* get coded length */
      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
        do {
          if (e == 99)
            return 1;
          DUMPBITS(t->b)
          e -= 16;
          NEEDBITS(e)
        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
      DUMPBITS(t->b)
      n = t->v.n;
      if (e)                    /* get length extra bits */
      {
        NEEDBITS(8)
        n += (unsigned)b & 0xff;
        DUMPBITS(8)
      }

      /* do the copy */
      s -= n;
      do {
        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
        if (u && w <= d)
        {
          memset(m_area.Slide + w, 0, e);
          w += e;
          d += e;
        }
        else
#ifndef NOMEMCPY
          if (w - d >= e)       /* (this test assumes unsigned comparison) */
          {
            memcpy(m_area.Slide + w, m_area.Slide + d, e);
            w += e;
            d += e;
          }
          else                  /* do it slow to avoid memcpy() overlap */
#endif /* !NOMEMCPY */
            do {
              m_area.Slide[w++] = m_area.Slide[d++];
            } while (--e);
        if (w == WSIZE)
        {
          flush(w);
          w = u = 0;
        }
      } while (n);
    }
  }

  /* flush out slide */
  flush(w);
  return m_file_in_zip_read.rest_read_compressed ? 5 : 0;         /* should have read csize bytes */
}

int __fastcall KbUnz::explode_nolit4(huft *tl, huft *td, int bl, int bd)
{
  long s;            /* bytes to decompress */
  register unsigned e;  /* table entry flag/number of extra bits */
  unsigned n, d;        /* length and index for copy */
  unsigned w;           /* current window position */
  struct huft *t;       /* pointer to table entry */
  unsigned ml, md;      /* masks for bl and bd bits */
  register ULONG b;     /* bit buffer */
  register unsigned k;  /* number of bits in bit buffer */
  unsigned u;           /* true if unflushed */


  /* explode the coded data */
  b = k = w = 0;                /* initialize bit buffer, window */
  u = 1;                        /* buffer unflushed */
  ml = mask_bits[bl];           /* precompute masks for speed */
  md = mask_bits[bd];
  s = m_file_in_zip_read.rest_read_uncompressed;
  while (s > 0)                 /* do until ucsize bytes uncompressed */
  {
    NEEDBITS(1)
    if (b & 1)                  /* then literal--get eight bits */
    {
      DUMPBITS(1)
      s--;
      NEEDBITS(8)
      m_area.Slide[w++] = (byte)b;
      if (w == WSIZE)
      {
        flush(w);
        w = u = 0;
      }
      DUMPBITS(8)
    }
    else                        /* else distance/length */
    {
      DUMPBITS(1)
      NEEDBITS(6)               /* get distance low bits */
      d = (unsigned)b & 0x3f;
      DUMPBITS(6)
      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
        do {
          if (e == 99)
            return 1;
          DUMPBITS(t->b)
          e -= 16;
          NEEDBITS(e)
        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
      DUMPBITS(t->b)
      d = w - d - t->v.n;       /* construct offset */
      NEEDBITS((unsigned)bl)    /* get coded length */
      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
        do {
          if (e == 99)
            return 1;
          DUMPBITS(t->b)
          e -= 16;
          NEEDBITS(e)
        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
      DUMPBITS(t->b)
      n = t->v.n;
      if (e)                    /* get length extra bits */
      {
        NEEDBITS(8)
        n += (unsigned)b & 0xff;
        DUMPBITS(8)
      }

      /* do the copy */
      s -= n;
      do {
        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
        if (u && w <= d)
        {
          memset(m_area.Slide + w, 0, e);
          w += e;
          d += e;
        }
        else
#ifndef NOMEMCPY
          if (w - d >= e)       /* (this test assumes unsigned comparison) */
          {
            memcpy(m_area.Slide + w, m_area.Slide + d, e);
            w += e;
            d += e;
          }
          else                  /* do it slow to avoid memcpy() overlap */
#endif /* !NOMEMCPY */
            do {
              m_area.Slide[w++] = m_area.Slide[d++];
            } while (--e);
        if (w == WSIZE)
        {
          flush(w);
          w = u = 0;
        }
      } while (n);
    }
  }

  /* flush out slide */
  flush(w);
  return m_file_in_zip_read.rest_read_compressed ? 5 : 0;         /* should have read csize bytes */
}

int __fastcall KbUnz::explode(void)
/* Explode an imploded compressed stream.  Based on the general purpose
   bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding
   window.  Construct the literal (if any), length, and distance codes and
   the tables needed to decode them (using huft_build() from inflate.c),
   and call the appropriate routine for the type of data in the remainder
   of the stream.  The four routines are nearly identical, differing only
   in whether the literal is decoded or simply read in, and in how many
   bits are read in, uncoded, for the low distance bits. */
{
  unsigned r;           /* return codes */
  struct huft *tb;      /* literal code table */
  struct huft *tl;      /* length code table */
  struct huft *td;      /* distance code table */
  int bb;               /* bits for tb */
  int bl;               /* bits for tl */
  int bd;               /* bits for td */
  unsigned l[256];      /* bit lengths for codes */

    //初期化
    ZeroMemory(&m_area, sizeof(m_area));// see unzip.h for the definition of work
    m_crc32val = 0;
    m_bytebuf = 0;
    m_bitbuf = 0;
    m_bits_left = 0;
    m_zipeof = 0;
    //ここまで

  /* Tune base table sizes.  Note: I thought that to truly optimize speed,
     I would have to select different bl, bd, and bb values for different
     compressed file sizes.  I was suprised to find out the the values of
     7, 7, and 9 worked best over a very wide range of sizes, except that
     bd = 8 worked marginally better for large compressed sizes. */
  bl = 7;
  bd = m_file_in_zip_read.rest_read_compressed > 200000L ? 8 : 7;


  /* With literal tree--minimum match length is 3 */
  m_hufts = 0;                    /* initialze huft's malloc'ed */
  //if(pUnzip->cur_file_info.flag & 4)
  if(m_pCurrent->header.flag & 4)
  {
    bb = 9;                     /* base table size for literals */
    if ((r = get_tree(l, 256)) != 0)
      return r;
    if ((r = huft_build(l, 256, 256, NULL, (const WORD *)NULL, &tb, &bb)) != 0)
    {
      if (r == 1)
        huft_free(tb);
      return r;
    }
    if ((r = get_tree(l, 64)) != 0)
      return r;
    if ((r = huft_build(l, 64, 0, cplen3, extra, &tl, &bl)) != 0)
    {
      if (r == 1)
        huft_free(tl);
      huft_free(tb);
      return r;
    }
    if ((r = get_tree(l, 64)) != 0)
      return r;
    //if (pUnzip->cur_file_info.flag & 2)      /* true if 8K */
    if(m_pCurrent->header.flag & 2)
    {
      if ((r = huft_build(l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
      {
        if (r == 1)
          huft_free(td);
        huft_free(tl);
        huft_free(tb);
        return r;
      }
      r = explode_lit8(tb, tl, td, bb, bl, bd);
    }
    else                                        /* else 4K */
    {
      if ((r = huft_build(l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
      {
        if (r == 1)
          huft_free(td);
        huft_free(tl);
        huft_free(tb);
        return r;
      }
      r = explode_lit4(tb, tl, td, bb, bl, bd);
    }
    huft_free(td);
    huft_free(tl);
    huft_free(tb);
  }
  else


  /* No literal tree--minimum match length is 2 */
  {
    if ((r = get_tree(l, 64)) != 0)
      return r;
    if ((r = huft_build(l, 64, 0, cplen2, extra, &tl, &bl)) != 0)
    {
      if (r == 1)
        huft_free(tl);
      return r;
    }
    if ((r = get_tree(l, 64)) != 0)
      return r;
    //if (pUnzip->cur_file_info.flag & 2)      /* true if 8K */
    if (m_pCurrent->header.flag & 2)      /* true if 8K */
    {
      if ((r = huft_build(l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
      {
        if (r == 1)
          huft_free(td);
        huft_free(tl);
        return r;
      }
      r = explode_nolit8(tl, td, bl, bd);
    }
    else                                        /* else 4K */
    {
      if ((r = huft_build(l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
      {
        if (r == 1)
          huft_free(td);
        huft_free(tl);
        return r;
      }
      r = explode_nolit4(tl, td, bl, bd);
    }
    huft_free(td);
    huft_free(tl);
  }
  return r;
}


int __fastcall KbUnz::ReadByte(WORD *x)
{
    /*
     * read a byte; return 8 if byte available, 0 if not
     */
    *x = 0;
    file_in_zip_read_info_s* pfile_in_zip_read_info = &m_file_in_zip_read;
    if (pfile_in_zip_read_info->stream.avail_in == 0)
    {
    unsigned int            uReadThis = UNZ_BUFSIZE;

    if (pfile_in_zip_read_info->rest_read_compressed <= 0)
        return 0;
    if (pfile_in_zip_read_info->rest_read_compressed < uReadThis)
        uReadThis = (UINT) pfile_in_zip_read_info->rest_read_compressed;
    if (uReadThis == 0)
        return 0;
    if (zseek (pfile_in_zip_read_info->file,
           pfile_in_zip_read_info->pos_in_zipfile +
    pfile_in_zip_read_info->byte_before_the_zipfile, SEEK_SET) != 0){
        return EOF;
    }
    if (zread (pfile_in_zip_read_info->read_buffer, uReadThis, 1,
           pfile_in_zip_read_info->file) != 1){
        return EOF;
    }
    pfile_in_zip_read_info->pos_in_zipfile += uReadThis;

    pfile_in_zip_read_info->rest_read_compressed -= uReadThis;

    pfile_in_zip_read_info->stream.next_in =
        (BYTE *) pfile_in_zip_read_info->read_buffer;
    pfile_in_zip_read_info->stream.avail_in = (UINT) uReadThis;
    }

    *x = *pfile_in_zip_read_info->stream.next_in++;
    pfile_in_zip_read_info->stream.avail_in--;

    return 8;
}

/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
#define BMAX 16         /* maximum bit length of any code (16 for explode) */
#define N_MAX 288       /* maximum number of codes in any set */

/*int huft_build(b, n, s, d, e, t, m)
unsigned *b;            // code lengths in bits (all assumed <= BMAX)
unsigned n;             // number of codes (assumed <= N_MAX)
unsigned s;             // number of simple-valued codes (0..s-1)
USHORT *d;              // list of base values for non-simple codes
USHORT *e;              // list of extra bits for non-simple codes
struct huft **t;        // result: starting table
int *m;                 // maximum lookup bits, returns actual
// Given a list of code lengths and a maximum table size, make a set of
//   tables to decode that set of codes.  Return zero on success, one if
//   the given code set is incomplete (the tables are still built in this
//   case), two if the input is invalid (all zero length codes or an
//   oversubscribed set of lengths), and three if not enough memory.
*/
int __fastcall KbUnz::huft_build(unsigned *b, unsigned n, unsigned s, const WORD *d,
                                                const WORD *e, huft **t, int *m)
{
  unsigned a;                   // counter for codes of length k
  unsigned c[BMAX+1];           // bit length count table
  unsigned f;                   // i repeats in table every f entries
  int g;                        // maximum code length
  int h;                        // table level
  register unsigned i;          // counter, current code
  register unsigned j;          // counter
  register int k;               // number of bits in current code
  int l;                        // bits per table (returned in m)
  register unsigned *p;         // pointer into c[], b[], or v[]
  register struct huft *q;      // points to current table
  struct huft r;                // table entry for structure assignment
  struct huft *u[BMAX];         // table stack
  unsigned v[N_MAX];            // values in order of bit length
  register int w;               // bits before this table == (l * h)
  unsigned x[BMAX+1];           // bit offsets, then code stack
  unsigned *xp;                 // pointer into x
  int y;                        // number of dummy codes added
  unsigned z;                   // number of entries in current table

  // Generate counts for each bit length
  memset(c, 0, sizeof(c));
  p = b;  i = n;
  do {
    c[*p++]++;                  // assume all entries <= BMAX 
  } while (--i);
  if (c[0] == n)                // null input--all zero length codes
  {
    *t = (struct huft *)NULL;
    *m = 0;
    return 0;
  }


  /* Find minimum and maximum length, bound *m by those */
  l = *m;
  for (j = 1; j <= BMAX; j++)
    if (c[j])
      break;
  k = j;                        /* minimum code length */
  if ((unsigned)l < j)
    l = j;
  for (i = BMAX; i; i--)
    if (c[i])
      break;
  g = i;                        /* maximum code length */
  if ((unsigned)l > i)
    l = i;
  *m = l;


  /* Adjust last length count to fill out codes, if needed */
  for (y = 1 << j; j < i; j++, y <<= 1)
    if ((y -= c[j]) < 0)
      return 2;                 /* bad input: more codes than bits */
  if ((y -= c[i]) < 0)
    return 2;
  c[i] += y;


  /* Generate starting offsets into the value table for each length */
  x[1] = j = 0;
  p = c + 1;  xp = x + 2;
  while (--i) {                 /* note that i == g from above */
    *xp++ = (j += *p++);
  }


  /* Make a table of values in order of bit lengths */
  p = b;  i = 0;
  do {
    if ((j = *p++) != 0)
      v[x[j]++] = i;
  } while (++i < n);


  /* Generate the Huffman codes and for each, make the table entries */
  x[0] = i = 0;                 /* first Huffman code is zero */
  p = v;                        /* grab values in bit order */
  h = -1;                       /* no tables yet--level -1 */
  w = -l;                       /* bits decoded == (l * h) */
  u[0] = (struct huft *)NULL;   /* just to keep compilers happy */
  q = (struct huft *)NULL;      /* ditto */
  z = 0;                        /* ditto */

  /* go through the bit lengths (k already is bits in shortest code) */
  for (; k <= g; k++)
  {
    a = c[k];
    while (a--)
    {
      /* here i is the Huffman code of length k bits for value *p */
      /* make tables up to required level */
      while (k > w + l)
      {
        h++;
        w += l;                 /* previous table always l bits */

        /* compute minimum size table less than or equal to l bits */
        z = (z = g - w) > (unsigned)l ? l : z;  /* upper limit on table size */
        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
        {                       /* too few codes for k-w bit table */
          f -= a + 1;           /* deduct codes from patterns left */
          xp = c + k;
          while (++j < z)       /* try smaller tables up to z bits */
          {
            if ((f <<= 1) <= *++xp)
              break;            /* enough codes to use up j bits */
            f -= *xp;           /* else deduct codes from patterns */
          }
        }
        z = 1 << j;             /* table entries for j-bit table */

        /* allocate and link in new table */
        if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
            (struct huft *)NULL)
        {
          if (h)
            huft_free(u[0]);
          return 3;             /* not enough memory */
        }
        m_hufts += z + 1;         /* track memory usage */
        *t = q + 1;             /* link to list for huft_free() */
        *(t = &(q->v.t)) = (struct huft *)NULL;
        u[h] = ++q;             /* table starts after link */

        /* connect to last table, if there is one */
        if (h)
        {
          x[h] = i;             /* save pattern for backing up */
          r.b = (BYTE)l;         /* bits to dump before this table */
          r.e = (BYTE)(16 + j);  /* bits in this table */
          r.v.t = q;            /* pointer to this table */
          j = i >> (w - l);     /* (get around Turbo C bug) */
          u[h-1][j] = r;        /* connect to last table */
        }
      }

      /* set up table entry in r */
      r.b = (BYTE)(k - w);
      if (p >= v + n)
        r.e = 99;               /* out of values--invalid code */
      else if (*p < s)
      {
        r.e = (BYTE)(*p < 256 ? 16 : 15);    /* 256 is end-of-block code */
        r.v.n = *p++;           /* simple code is just the value */
      }
      else
      {
        r.e = (BYTE)e[*p - s];   /* non-simple--look up in lists */
        r.v.n = d[*p++ - s];
      }

      /* fill code-like entries with r */
      f = 1 << (k - w);
      for (j = i >> w; j < z; j += f)
        q[j] = r;

      /* backwards increment the k-bit code i */
      for (j = 1 << (k - 1); i & j; j >>= 1)
        i ^= j;
      i ^= j;

      /* backup over finished tables */
      while ((i & ((1 << w) - 1)) != x[h])
      {
        h--;                    // don't need to update q
        w -= l;
      }
    }
  }


  // Return true (1) if we were given an incomplete table
  return y != 0 && g != 1;
}

int huft_free(huft *t)
// Free the malloc'ed tables built by huft_build(), which makes a linked
//  list of the tables it made, with the links in a dummy first entry of
//   each table.
{
  register struct huft *p, *q;
  //Go through linked list, freeing from the malloced (t[-1]) address.
  p = t;
  while (p != (struct huft *)NULL)
  {
    q = (--p)->v.t;
    free(p);
    p = q;
  }
  return 0;
}

void __fastcall KbUnz::flush(unsigned w)
//unsigned w;             // number of bytes to flush
// Do the equivalent of OUTB for the bytes slide[0..w-1].
{
    file_in_zip_read_info_s* pfile_in_zip_read_info = &m_file_in_zip_read;
    int d = (int)pfile_in_zip_read_info->stream.avail_out - (int)w;
    if(d < 0){
        w = pfile_in_zip_read_info->stream.avail_out;
    }
    memmove (pfile_in_zip_read_info->stream.next_out, m_area.Slide, w);
    pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32,
                     pfile_in_zip_read_info->stream.next_out, w);
    pfile_in_zip_read_info->stream.next_out += w;
    pfile_in_zip_read_info->stream.avail_out -= w;
    pfile_in_zip_read_info->stream.total_out += w;
}
//**************************//
// Function FillBitBuffer() //
//**************************//
int __fastcall KbUnz::FillBitBuffer(void)
{
    // Fill bitbuf, which is 32 bits.  This function is only used by the
    // READBIT and PEEKBIT macros (which are used by all of the uncompression
    // routines).
    WORD temp;
    m_zipeof = 1;
    while (m_bits_left < 25 && ReadByte(&temp) == 8)
    {
      m_bitbuf |= (ULONG)temp << m_bits_left;
      m_bits_left += 8;
      m_zipeof = 0;
    }
    return 0;
}
//
//shurunk解凍用API群
//
//*************************************/
//*  UnShrink Defines, Globals, etc.  */
//*************************************/

//      MAX_BITS        13   (in unzip.h; defines size of global work area)
#define INIT_BITS       9
#define FIRST_ENT       257
#define CLEAR           256
#define GetCode(dest)   READBIT(codesize,dest)
#define READBIT(nbits,zdest) {if(nbits>m_bits_left) FillBitBuffer();\
  zdest=(int)((WORD)m_bitbuf&mask_bits[nbits]);m_bitbuf>>=nbits;m_bits_left-=nbits;}

//************************
//*  Function unShrink()
//************************
#define BOGUSCODE  256
#define FLAG_BITS  parent        // upper bits of parent[] used as flag bits
#define CODE_MASK  (HSIZE - 1)   // 0x1fff (lower bits are parent's index)
#define FREE_CODE  HSIZE         // 0x2000 (code is unused or was cleared)
#define HAS_CHILD  (HSIZE << 1)  // 0x4000 (code has a child--do not clear)
int __fastcall KbUnz::unShrink(void)
{
    int offset = HSIZE-1;
    int stackp = offset;
    int newstr;
    int codesize=9, len, KwKwK;
    int code, oldcode, freecode, curcode;
    int lastfreecode;
    lastfreecode = BOGUSCODE;
    BYTE *outptr = m_file_in_zip_read.stream.next_out;
    int outbufsiz = m_file_in_zip_read.stream.avail_out;
    int cur = 0;
    //初期化
    ZeroMemory(&m_area, sizeof(m_area));// see unzip.h for the definition of work
    m_crc32val = 0;
    m_bytebuf = 0;
    m_bitbuf = 0;
    m_bits_left = 0;
    m_zipeof = 0;
    //ここまで

    // decompress the file
    //codesize = INIT_BITS;
    for (code = 0;  code < BOGUSCODE;  ++code) {
        m_area.shrink.Suffix_of[code] = (BYTE)code;
        m_area.shrink.Prefix_of[code] = BOGUSCODE;
    }
    for (code = BOGUSCODE+1;  code < HSIZE;  ++code)
        m_area.shrink.Prefix_of[code] = FREE_CODE;
    READBIT(codesize,oldcode);
    if (m_zipeof)
        return cur;
    *outptr++ = (BYTE)oldcode;
    cur++;
    do{
        READBIT(codesize, code)
        if(m_zipeof)
            break;
        if(code == BOGUSCODE){// possible to have consecutive escapes?
            READBIT(codesize, code)
            if(code == 1){
                ++codesize;
            }
            else if(code == 2){
                partial_clear();// clear leafs (nodes with no children)
                lastfreecode = BOGUSCODE;// reset start of free-node search
            }
            continue;
        }
        newstr = stackp;
        curcode = code;
        if(m_area.shrink.Prefix_of[curcode] == FREE_CODE){
            // or (FLAG_BITS[curcode] & FREE_CODE)?
            KwKwK = TRUE;
            --newstr;   // last character will be same as first character
            curcode = oldcode;
        }
        else
            KwKwK = FALSE;

        do{
            m_area.shrink.Stack[newstr--] = m_area.shrink.Suffix_of[curcode];
            curcode = (int)(m_area.shrink.Prefix_of[curcode] & CODE_MASK);
        }while (curcode != BOGUSCODE);

        len = (int)(stackp - newstr++);
        if (KwKwK)
            m_area.shrink.Stack[stackp] = m_area.shrink.Stack[newstr];
    //-----------------------------------------------------------------------
    //    Write expanded string in reverse order to output buffer.
    //-----------------------------------------------------------------------
        {
            register int p;
            for (p = newstr;  p < newstr+len;  ++p) {
                *outptr++ = m_area.shrink.Stack[p];
                if(++cur == outbufsiz) {
                    return cur;
                }
            }
        }

    //-----------------------------------------------------------------------
    //   Add new leaf (first character of newstr) to tree as child of oldcode.
    //-----------------------------------------------------------------------
        // search for freecode
        freecode = (int)(lastfreecode + 1);
        // add if-test before loop for speed?
        while(m_area.shrink.Prefix_of[freecode] != FREE_CODE)
            ++freecode;
        lastfreecode = freecode;
        m_area.shrink.Suffix_of[freecode] = m_area.shrink.Stack[newstr];
        m_area.shrink.Prefix_of[freecode] = oldcode;
        oldcode = code;
    }while (!m_zipeof);
    return cur;
}
//*****************************
//*  Function partial_clear()
//*****************************
void __fastcall KbUnz::partial_clear(void)
{
    register int code;
    for (code = BOGUSCODE+1;  code < HSIZE;  ++code) {
        register int cparent = (int)(m_area.shrink.Prefix_of[code] & CODE_MASK);

        if (cparent > BOGUSCODE && cparent != FREE_CODE)
            m_area.shrink.Prefix_of[cparent] |= HAS_CHILD;//set parent's child-bit
    }
    // second loop:  clear all nodes *not* marked as parents; reset flag bits
    for (code = BOGUSCODE+1;  code < HSIZE;  ++code) {
        if (m_area.shrink.Prefix_of[code] & HAS_CHILD)  // just clear child-bit
            m_area.shrink.Prefix_of[code] &= ~HAS_CHILD;
        else {                              // leaf:  lose it
            m_area.shrink.Prefix_of[code] = FREE_CODE;
        }
    }
}

//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
void* KbZipFile::kbzipfile_alloc(voidpf opaque, uInt items, uInt size)
{
    return HeapAlloc((HANDLE)opaque, 0, items*size);
}
void  KbZipFile::kbzipfile_free(voidpf opaque, voidpf address)
{
    HeapFree((HANDLE)opaque, 0, address);
}
KbZipFile::KbZipFile(IKpiFile *pFile,
                     KbUnz::unz_file_info *pInfo, 
                     UINT byte_before_the_zipfile,
                     UINT64 qwSize)
    :KbKpiFileImpl()
{
    m_hHeap = HeapCreate(0, 32768, 0);
    m_pFile = pFile;
    memcpy(&m_file_info, pInfo, sizeof(m_file_info));
    m_byte_before_the_zipfile = byte_before_the_zipfile;
    m_qwOffset = SEEK_BLOCK;
    m_pContext = NULL;
    m_qwSize = qwSize;
    Init(&m_file_info);
    pFile->AddRef();
}
KbZipFile::~KbZipFile(void)
{
    ZipContext *pContext = m_pContext;
    while(pContext){
        ZipContext *pNext = pContext->pNext;
        inflateEnd(&pContext->info.stream);
        pContext = pNext;
    }
    inflateEnd(&m_read_info.stream);
    HeapDestroy(m_hHeap);
    m_pFile->Release();
}
void __fastcall KbZipFile::Init(KbUnz::unz_file_info *pfile_info)
{
    KbUnz::file_in_zip_read_info_s* pfile_in_zip_read_info = &m_read_info;
    int   err=UNZ_OK;
    int   Store;
    UINT  iSizeVar;
    ULONG offset_local_extrafield;// offset of the local extra field
    UINT  size_local_extrafield;  // size of the local extra field

    pfile_in_zip_read_info->init();
    pfile_in_zip_read_info->file = m_pFile;
    if(CheckCurrentFileCoherencyHeader(m_pFile,
                                       &pfile_info->header,
                                       m_byte_before_the_zipfile,
                                       &iSizeVar,
                                       &offset_local_extrafield,
                                       &size_local_extrafield) != UNZ_OK){
        return;
    }
    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
    pfile_in_zip_read_info->pos_local_extrafield=0;
    pfile_in_zip_read_info->stream_initialised=0;

    if ((pfile_info->header.compression_method!=0) &&
        (pfile_info->header.compression_method!=Z_DEFLATED)){
        err=UNZ_BADZIPFILE;
    }
    Store = pfile_info->header.compression_method==0;

    pfile_in_zip_read_info->crc32_wait = pfile_info->header.crc;
    pfile_in_zip_read_info->crc32 = 0;
    pfile_in_zip_read_info->compression_method = pfile_info->header.compression_method;
    pfile_in_zip_read_info->byte_before_the_zipfile = m_byte_before_the_zipfile;
    pfile_in_zip_read_info->stream.total_out = 0;
    pfile_in_zip_read_info->file = m_pFile;

    if (!Store)
    {
        //pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
        //pfile_in_zip_read_info->stream.zfree = (free_func)0;
        //pfile_in_zip_read_info->stream.opaque = (voidpf)0;
        pfile_in_zip_read_info->stream.zalloc = kbzipfile_alloc;
        pfile_in_zip_read_info->stream.zfree = kbzipfile_free;
        pfile_in_zip_read_info->stream.opaque = (voidpf)m_hHeap;
        err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
        if (err == Z_OK)
            pfile_in_zip_read_info->stream_initialised=1;
        // windowBits is passed < 0 to tell that there is no zlib header.
        // Note that in this case inflate *requires* an extra "dummy" byte
        // after the compressed stream in order to complete decompression and
        // return Z_STREAM_END.
        // In unzip, i don't wait absolutely Z_STREAM_END because I known the
        // size of both compressed and uncompressed data
    }
    pfile_in_zip_read_info->rest_read_compressed = pfile_info->header.compressed_size;
    pfile_in_zip_read_info->rest_read_uncompressed = pfile_info->header.uncompressed_size;
    pfile_in_zip_read_info->pos_in_zipfile =
            pfile_info->header.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar;
    pfile_in_zip_read_info->stream.avail_in = 0;
}

DWORD  WINAPI KbZipFile::Read(void *pBuffer, DWORD dwSize)
{
    int   err = UNZ_OK;
    UINT  iRead = 0;
    KbUnz::file_in_zip_read_info_s* pfile_in_zip_read_info;
    pfile_in_zip_read_info = &m_read_info;

    if(pfile_in_zip_read_info->stream.total_out + dwSize > m_qwSize){
        dwSize = m_qwSize - pfile_in_zip_read_info->stream.total_out;
    }
    if(dwSize == 0){
        return 0;
    }

    pfile_in_zip_read_info->stream.next_out = (BYTE*)pBuffer;
    pfile_in_zip_read_info->stream.avail_out = (UINT)dwSize;

    if(dwSize>pfile_in_zip_read_info->rest_read_uncompressed)
        pfile_in_zip_read_info->stream.avail_out =
          (UINT)pfile_in_zip_read_info->rest_read_uncompressed;

    int old_avail_out = pfile_in_zip_read_info->stream.avail_out;
    while (pfile_in_zip_read_info->stream.avail_out > 0 && err == UNZ_OK)
    {
        if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
            (pfile_in_zip_read_info->rest_read_compressed > 0) &&
            (pfile_in_zip_read_info->compression_method == UNZ_STORED ||
             pfile_in_zip_read_info->compression_method == UNZ_DEFLATED))
        {
            UINT uReadThis = UNZ_BUFSIZE;
            if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
                uReadThis = (UINT)pfile_in_zip_read_info->rest_read_compressed;
            if (uReadThis == 0)
                return 0;
            if (zseek(pfile_in_zip_read_info->file,
                      pfile_in_zip_read_info->pos_in_zipfile +
                      pfile_in_zip_read_info->byte_before_the_zipfile, SEEK_SET)!=0)
                return 0;
            if (zread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
                         pfile_in_zip_read_info->file)!=1)
                return 0;
            pfile_in_zip_read_info->pos_in_zipfile += uReadThis;

            pfile_in_zip_read_info->rest_read_compressed -= uReadThis;

            pfile_in_zip_read_info->stream.next_in =
                (BYTE*)pfile_in_zip_read_info->read_buffer;
            pfile_in_zip_read_info->stream.avail_in = (UINT)uReadThis;
        }

        if (pfile_in_zip_read_info->compression_method == UNZ_STORED)//Stored
        {//無圧縮
            UINT uDoCopy,i ;
            if (pfile_in_zip_read_info->stream.avail_out <
                            pfile_in_zip_read_info->stream.avail_in)
                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
            else
                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;

            for (i = 0; i < uDoCopy;i++)
                *(pfile_in_zip_read_info->stream.next_out+i) =
                        *(pfile_in_zip_read_info->stream.next_in+i);

            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
                                pfile_in_zip_read_info->stream.next_out,
                                uDoCopy);
            pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
            pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
            pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
            pfile_in_zip_read_info->stream.next_out += uDoCopy;
            pfile_in_zip_read_info->stream.next_in += uDoCopy;
            pfile_in_zip_read_info->stream.total_out += uDoCopy;
            iRead += uDoCopy;
        }
        /*else if(pfile_in_zip_read_info->compression_method == UNZ_IMPLODED)//Implode
        {
            int true_rest_read_uncompressed = pfile_in_zip_read_info->rest_read_uncompressed;
            err = explode();
            iRead = len - pfile_in_zip_read_info->stream.avail_out;
            if(iRead < 0)
                iRead = 0;
            else if(iRead> len)
                iRead = len;
            return iRead;
        }
        else if(pfile_in_zip_read_info->compression_method == UNZ_SHRUNK)//shrunk
        {
            iRead = unShrink();
            if(iRead < 0)
                iRead = 0;
            else if(iRead> len)
                iRead = len;
            return iRead;
        }*/
        else//Deflate
        {
            ULONG uTotalOutBefore,uTotalOutAfter;
            const BYTE *bufBefore;
            ULONG uOutThis;
            int flush=Z_SYNC_FLUSH;
            //flush = Z_PARTIAL_FLUSH;
            uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
            bufBefore = pfile_in_zip_read_info->stream.next_out;

            err=inflate(&pfile_in_zip_read_info->stream,flush);

            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
            uOutThis = uTotalOutAfter-uTotalOutBefore;

            pfile_in_zip_read_info->crc32 =
                crc32(pfile_in_zip_read_info->crc32,bufBefore,
                        (UINT)(uOutThis));

            pfile_in_zip_read_info->rest_read_uncompressed -=
                uOutThis;

            iRead += (UINT)(uTotalOutAfter - uTotalOutBefore);

            if (err==Z_STREAM_END){
                return (iRead==0) ? UNZ_EOF : iRead;
            }
            if (err!=Z_OK){
                break;
            }
        }
        //以下の３行は安全のために実行
        if(old_avail_out <= pfile_in_zip_read_info->stream.avail_out){
            return iRead;
        }
        old_avail_out = pfile_in_zip_read_info->stream.avail_out;
        SaveContext(&m_read_info);
    }
    if (err==Z_OK){
        return iRead;
    }
    return 0;
}
UINT64 WINAPI KbZipFile::Seek(__int64 i64Pos, DWORD dwOrigin)
{
    switch(dwOrigin){
        case FILE_BEGIN:
            break;
        case FILE_CURRENT:
            i64Pos += m_read_info.stream.total_out;
            break;
        case FILE_END:
            i64Pos += m_qwSize;
            break;
    }
    if(i64Pos > m_qwSize){
        i64Pos = m_qwSize;
    }
    else if(i64Pos < 0){
        i64Pos = 0;
    }
    RestoreContext(&m_read_info, i64Pos);
    return m_read_info.stream.total_out;
    /*if(i64Pos > m_read_info.stream.total_out){
        BYTE tmp[16384];
        DWORD dwDiscard = i64Pos - m_read_info.stream.total_out;
        while(dwDiscard){
            DWORD dwSize = dwDiscard;
            DWORD dwRet;
            if(dwSize > sizeof(tmp)){
                dwSize = sizeof(tmp);
            }
            dwRet = Read(tmp, dwSize);
            dwDiscard -= dwRet;
            if(dwRet < dwSize){
                break;
            }
        }
        i64Pos -= dwDiscard;
    }
    return i64Pos;
    */
}
UINT64 WINAPI KbZipFile::GetSize(void)
{
    return m_qwSize;
}
DWORD  WINAPI KbZipFile::GetFileName(wchar_t *pszName, DWORD dwSize)
{
    const wchar_t *p = m_file_info.szFileName;
    const wchar_t *last_path_delimiter = wcsrchr(p, L'/');
    if(last_path_delimiter){
         p = last_path_delimiter + 1;
    }
    DWORD dwCopy = wcslen(p) + 1;
    dwCopy *= sizeof(wchar_t);
    if(dwCopy <= dwSize){
        memcpy(pszName, p, dwCopy);
    }
    else{
        pszName[0] = 0;
    }
    return dwCopy;
}
void __fastcall KbZipFile::SaveContext(KbUnz::file_in_zip_read_info_s *pInfo)
{
    if(pInfo->stream.total_out < m_qwOffset){
        return;
    }    
    ZipContext *pContext = (ZipContext*)HeapAlloc(m_hHeap, 
                                                  HEAP_ZERO_MEMORY, 
                                                  sizeof(ZipContext));
    memcpy(&pContext->info, pInfo, sizeof(KbUnz::file_in_zip_read_info_s));
    inflateCopy(&pContext->info.stream, &pInfo->stream);
    pContext->qwFilePointer = pInfo->file->Seek(0, FILE_CURRENT);
    pContext->pNext = m_pContext;
    m_pContext = pContext;
    m_qwOffset += SEEK_BLOCK;
}
void __fastcall KbZipFile::RestoreContext(KbUnz::file_in_zip_read_info_s *pInfo,
                                          UINT64 qwPos)
{
    UINT64 qwCurrentPos = pInfo->stream.total_out;
    if(qwCurrentPos <= qwPos && qwPos < qwCurrentPos + SEEK_BLOCK){
        return;
    }
    ZipContext *pContext = m_pContext;
    while(pContext){
        if(qwPos >= pContext->info.stream.total_out){
            break;
        }
        pContext = pContext->pNext;
    }
    inflateEnd(&pInfo->stream);
    if(pContext){
        memcpy(pInfo, &pContext->info, sizeof(KbUnz::file_in_zip_read_info_s));
        inflateCopy(&pInfo->stream, &pContext->info.stream);
        pInfo->file->Seek(pContext->qwFilePointer, FILE_BEGIN);
    }
    else{
        Init(&m_file_info);
    }
}

//deflate64
#define INVALID_CODE 99
#define UINT_D64 ulg
#define IS_INVALID_CODE(c)  ((c) == INVALID_CODE)
#define wsize WSIZE       /* wsize is a constant */

/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
   stream to find repeated byte strings.  This is implemented here as a
   circular buffer.  The index is updated simply by incrementing and then
   and'ing with 0x7fff (32K-1). */
/* It is left to other modules to supply the 32K area.  It is assumed
   to be usable as if it were declared "uch slide[32768];" or as just
   "uch *slide;" and then malloc'ed in the latter case.  The definition
   must be in unzip.h, included above. */


/* unsigned wp;  moved to globals.h */     /* current position in slide */

/* Tables for deflate from PKZIP's appnote.txt. */
/* - Order of the bit length code lengths */
static ZCONST unsigned border[] = {
        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};

/* - Copy lengths for literal codes 257..285 */
#ifdef USE_DEFLATE64
static ZCONST ush cplens64[] = {
        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 3, 0, 0};
        /* For Deflate64, the code 285 is defined differently. */
#else
#  define cplens32 cplens
#endif
static ZCONST ush cplens32[] = {
        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
        /* note: see note #13 above about the 258 in this list. */
/* - Extra bits for literal codes 257..285 */
#ifdef USE_DEFLATE64
static ZCONST uch cplext64[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16, INVALID_CODE, INVALID_CODE};
#else
#  define cplext32 cplext
#endif
static ZCONST uch cplext32[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, INVALID_CODE, INVALID_CODE};

/* - Copy offsets for distance codes 0..29 (0..31 for Deflate64) */
static ZCONST ush cpdist[] = {
        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
#if (defined(USE_DEFLATE64) || defined(PKZIP_BUG_WORKAROUND))
        8193, 12289, 16385, 24577, 32769, 49153};
#else
        8193, 12289, 16385, 24577};
#endif

/* - Extra bits for distance codes 0..29 (0..31 for Deflate64) */
#ifdef USE_DEFLATE64
static ZCONST uch cpdext64[] = {
        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
        12, 12, 13, 13, 14, 14};
#else
#  define cpdext32 cpdext
#endif
static ZCONST uch cpdext32[] = {
        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
#ifdef PKZIP_BUG_WORKAROUND
        12, 12, 13, 13, INVALID_CODE, INVALID_CODE};
#else
        12, 12, 13, 13};
#endif

#ifdef PKZIP_BUG_WORKAROUND
#  define MAXLITLENS 288
#else
#  define MAXLITLENS 286
#endif

#if (defined(USE_DEFLATE64) || defined(PKZIP_BUG_WORKAROUND))
#  define MAXDISTS 32
#else
#  define MAXDISTS 30
#endif

/* Macros for inflate() bit peeking and grabbing.
   The usage is:

        NEEDBITS(j)
        x = b & mask_bits[j];
        DUMPBITS(j)

   where NEEDBITS makes sure that b has at least j bits in it, and
   DUMPBITS removes the bits from b.  The macros use the variable k
   for the number of bits in b.  Normally, b and k are register
   variables for speed and are initialized at the beginning of a
   routine that uses these macros from a global bit buffer and count.

   In order to not ask for more bits than there are in the compressed
   stream, the Huffman tables are constructed to only ask for just
   enough bits to make up the end-of-block code (value 256).  Then no
   bytes need to be "returned" to the buffer at the end of the last
   block.  See the huft_build() routine.

   Actually, the precautions mentioned above are not sufficient to
   prevent fetches of bits beyound the end of the last block in every
   case. When the last code fetched before the end-of-block code was
   a very short distance code (shorter than "distance-prefetch-bits" -
   "end-of-block code bits"), this last distance code fetch already
   exausts the available data.  To prevent failure of extraction in this
   case, the "read beyond EOF" check delays the raise of the "invalid
   data" error until an actual overflow of "used data" is detected.
   This error condition is only fulfilled when the "number of available
   bits" counter k is found to be negative in the NEEDBITS() macro.

   An alternate fix for that problem adjusts the size of the distance code
   base table so that it does not exceed the length of the end-of-block code
   plus the minimum length of a distance code. This alternate fix can be
   enabled by defining the preprocessor symbol FIX_PAST_EOB_BY_TABLEADJUST.
 */

#define CHECK_EOF   /* default as of 5.13/5.2 */
#define FIX_PAST_EOB_BY_TABLEADJUST

//#define NEXTBYTE (ReadByte(&m_bytebuf) == EOF ? EOF : m_bytebuf)
inline int KbUnz::nextbyte()
{
    if(ReadByte(&m_bytebuf) == EOF){
        return EOF;
    }
    //ReadByte(&m_bytebuf);
    return m_bytebuf;
}
#define NEXTBYTE nextbyte()

#ifndef CHECK_EOF
#  define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
#else
# ifdef FIX_PAST_EOB_BY_TABLEADJUST
#  define NEEDBITS(n) {while(k<(n)){int c=NEXTBYTE;\
    if(c==EOF){retval=1;goto cleanup_and_exit;}\
    b|=((ulg)c)<<k;k+=8;}}
# else
#  define NEEDBITS(n) {while((int)k<(int)(n)){int c=NEXTBYTE;\
    if(c==EOF){if((int)k>=0)break;retval=1;goto cleanup_and_exit;}\
    b|=((ulg)c)<<k;k+=8;}}
# endif
#endif

#define DUMPBITS(n) {b>>=(n);k-=(n);}


/*
   Huffman code decoding is performed using a multi-level table lookup.
   The fastest way to decode is to simply build a lookup table whose
   size is determined by the longest code.  However, the time it takes
   to build this table can also be a factor if the data being decoded
   are not very long.  The most common codes are necessarily the
   shortest codes, so those codes dominate the decoding time, and hence
   the speed.  The idea is you can have a shorter table that decodes the
   shorter, more probable codes, and then point to subsidiary tables for
   the longer codes.  The time it costs to decode the longer codes is
   then traded against the time it takes to make longer tables.

   This results of this trade are in the variables lbits and dbits
   below.  lbits is the number of bits the first level table for literal/
   length codes can decode in one step, and dbits is the same thing for
   the distance codes.  Subsequent tables are also less than or equal to
   those sizes.  These values may be adjusted either when all of the
   codes are shorter than that, in which case the longest code length in
   bits is used, or when the shortest code is *longer* than the requested
   table size, in which case the length of the shortest code in bits is
   used.

   There are two different values for the two tables, since they code a
   different number of possibilities each.  The literal/length table
   codes 286 possible values, or in a flat code, a little over eight
   bits.  The distance table codes 30 possible values, or a little less
   than five bits, flat.  The optimum values for speed end up being
   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
   The optimum values may differ though from machine to machine, and
   possibly even between compilers.  Your mileage may vary.
 */


/* bits in base literal/length lookup table */
static ZCONST unsigned lbits = 9;
/* bits in base distance lookup table */
static ZCONST unsigned dbits = 6;


#ifndef ASM_INFLATECODES

int KbUnz::inflate_codes(struct huft *tl, struct huft *td, unsigned bl, unsigned bd)
//     __GDEF
//struct huft *tl, *td;   /* literal/length and distance decoder tables */
//unsigned bl, bd;        /* number of bits decoded by tl[] and td[] */
///* inflate (decompress) the codes in a deflated (compressed) block.
//   Return an error code or zero if it all goes ok. */
{
  register unsigned e;  /* table entry flag/number of extra bits */
  unsigned d;           /* index for copy */
  UINT_D64 n;           /* length for copy (deflate64: might be 64k+2) */
  UINT_D64 w;           /* current window position (deflate64: up to 64k) */
  struct huft *t;       /* pointer to table entry */
  unsigned ml, md;      /* masks for bl and bd bits */
  register ulg b;       /* bit buffer */
  register unsigned k;  /* number of bits in bit buffer */
  int retval = 0;       /* error code returned: initialized to "no error" */


  /* make local copies of globals */
  b = G.bb;                       /* initialize bit buffer */
  k = G.bk;
  w = G.wp;                       /* initialize window position */


  /* inflate the coded data */
  ml = mask_bits[bl];           /* precompute masks for speed */
  md = mask_bits[bd];
  while (1)                     /* do until end of block */
  {
    NEEDBITS(bl)
    t = tl + ((unsigned)b & ml);
    while (1) {
      DUMPBITS(t->b)

      if ((e = t->e) == 32)     /* then it's a literal */
      {
        m_area.Slide[w++] = (uch)t->v.n;
        if (w == wsize)
        {
            flush(w);
          //if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit;
          w = 0;
        }
        break;
      }

      if (e < 31)               /* then it's a length */
      {
        /* get length of block to copy */
        NEEDBITS(e)
        n = t->v.n + ((unsigned)b & mask_bits[e]);
        DUMPBITS(e)

        /* decode distance of block to copy */
        NEEDBITS(bd)
        t = td + ((unsigned)b & md);
        while (1) {
          DUMPBITS(t->b)
          if ((e = t->e) < 32)
            break;
          if (IS_INVALID_CODE(e))
            return 1;
          e &= 31;
          NEEDBITS(e)
          t = t->v.t + ((unsigned)b & mask_bits[e]);
        }
        NEEDBITS(e)
        d = (unsigned)w - t->v.n - ((unsigned)b & mask_bits[e]);
        DUMPBITS(e)

        /* do the copy */
        do {
#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
          if (G.redirect_slide) {
            /* &= w/ wsize unnecessary & wrong if redirect */
            if ((UINT_D64)d >= wsize)
              return 1;         /* invalid compressed data */
            e = (unsigned)(wsize - (d > (unsigned)w ? (UINT_D64)d : w));
          }
          else
#endif
            e = (unsigned)(wsize -
                           ((d &= (unsigned)(wsize-1)) > (unsigned)w ?
                            (UINT_D64)d : w));
          if ((UINT_D64)e > n) e = (unsigned)n;
          n -= e;
#ifndef NOMEMCPY
          if ((unsigned)w - d >= e)
          /* (this test assumes unsigned comparison) */
          {
            memcpy(m_area.Slide + (unsigned)w, m_area.Slide + d, e);
            w += e;
            d += e;
          }
          else                  /* do it slowly to avoid memcpy() overlap */
#endif /* !NOMEMCPY */
            do {
              m_area.Slide[w++] = m_area.Slide[d++];
            } while (--e);
          if (w == wsize)
          {
            //if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit;
            flush(w);
            w = 0;
          }
        } while (n);
        break;
      }

      if (e == 31)              /* it's the EOB signal */
      {
        /* sorry for this goto, but we have to exit two loops at once */
        goto cleanup_decode;
      }

      if (IS_INVALID_CODE(e))
        return 1;

      e &= 31;
      NEEDBITS(e)
      t = t->v.t + ((unsigned)b & mask_bits[e]);
    }
  }
cleanup_decode:

  /* restore the globals from the locals */
  G.wp = (unsigned)w;             /* restore global window pointer */
  G.bb = b;                       /* restore global bit buffer */
  G.bk = k;

  return retval;
cleanup_and_exit:
  /* done */
  return retval;
}

#endif /* ASM_INFLATECODES */



int KbUnz::inflate_stored()
//     __GDEF
/* "decompress" an inflated type 0 (stored) block. */
{
  UINT_D64 w;           /* current window position (deflate64: up to 64k!) */
  unsigned n;           /* number of bytes in block */
  register ulg b;       /* bit buffer */
  register unsigned k;  /* number of bits in bit buffer */
  int retval = 0;       /* error code returned: initialized to "no error" */


  /* make local copies of globals */
//  Trace((stderr, "\nstored block"));
  b = G.bb;                       /* initialize bit buffer */
  k = G.bk;
  w = G.wp;                       /* initialize window position */


  /* go to byte boundary */
  n = k & 7;
  DUMPBITS(n);


  /* get the length and its complement */
  NEEDBITS(16)
  n = ((unsigned)b & 0xffff);
  DUMPBITS(16)
  NEEDBITS(16)
  if (n != (unsigned)((~b) & 0xffff))
    return 1;                   /* error in compressed data */
  DUMPBITS(16)


  /* read and output the compressed data */
  while (n--)
  {
    NEEDBITS(8)
    m_area.Slide[w++] = (uch)b;
    if (w == wsize)
    {
//      if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit;
      flush(w);
      w = 0;
    }
    DUMPBITS(8)
  }


  /* restore the globals from the locals */
  G.wp = (unsigned)w;             /* restore global window pointer */
  G.bb = b;                       /* restore global bit buffer */
  G.bk = k;
  return retval;
cleanup_and_exit:
  return retval;
}

int KbUnz::inflate_fixed()
//     __GDEF
/* decompress an inflated type 1 (fixed Huffman codes) block.  We should
   either replace this with a custom decoder, or at least precompute the
   Huffman tables. */
{
  /* if first time, set up tables for fixed blocks */
//  Trace((stderr, "\nliteral block"));
  if (G.fixed_tl == (struct huft *)NULL)
  {
    int i;                /* temporary variable */
    unsigned l[288];      /* length list for huft_build */

    /* literal table */
    for (i = 0; i < 144; i++)
      l[i] = 8;
    for (; i < 256; i++)
      l[i] = 9;
    for (; i < 280; i++)
      l[i] = 7;
    for (; i < 288; i++)          /* make a complete, but wrong code set */
      l[i] = 8;
    G.fixed_bl = 7;
#ifdef USE_DEFLATE64
    if ((i = huft_build2(l, 288, 257, G.cplens, (const BYTE*)G.cplext,
                        &G.fixed_tl, (int*)&G.fixed_bl)) != 0)
#else
    if ((i = huft_build2(__G__ l, 288, 257, cplens, cplext,
                        &G.fixed_tl, &G.fixed_bl)) != 0)
#endif
    {
      G.fixed_tl = (struct huft *)NULL;
      return i;
    }

    /* distance table */
    for (i = 0; i < MAXDISTS; i++)      /* make an incomplete code set */
      l[i] = 5;
    G.fixed_bd = 5;
#ifdef USE_DEFLATE64
    if ((i = huft_build2(l, MAXDISTS, 0, cpdist, G.cpdext,
                        &G.fixed_td, (int*)&G.fixed_bd)) > 1)
#else
    if ((i = huft_build2(l, MAXDISTS, 0, cpdist, cpdext,
                        &G.fixed_td, &G.fixed_bd)) > 1)
#endif
    {
      huft_free(G.fixed_tl);
      G.fixed_td = G.fixed_tl = (struct huft *)NULL;
      return i;
    }
  }

  /* decompress until an end-of-block code */
  return inflate_codes(G.fixed_tl, G.fixed_td,
                        G.fixed_bl, G.fixed_bd);
}

int KbUnz::inflate_dynamic()
//  __GDEF
/* decompress an inflated type 2 (dynamic Huffman codes) block. */
{
  unsigned i;           /* temporary variables */
  unsigned j;
  unsigned l;           /* last length */
  unsigned m;           /* mask for bit lengths table */
  unsigned n;           /* number of lengths to get */
  struct huft *tl=NULL; /* literal/length code table */
  struct huft *td=NULL; /* distance code table */
  unsigned bl;          /* lookup bits for tl */
  unsigned bd;          /* lookup bits for td */
  unsigned nb;          /* number of bit length codes */
  unsigned nl;          /* number of literal/length codes */
  unsigned nd;          /* number of distance codes */
  unsigned ll[MAXLITLENS+MAXDISTS]; /* lit./length and distance code lengths */
  register ulg b;       /* bit buffer */
  register unsigned k;  /* number of bits in bit buffer */
  int retval = 0;       /* error code returned: initialized to "no error" */


  /* make local bit buffer */
  //Trace((stderr, "\ndynamic block"));
  b = G.bb;
  k = G.bk;


  /* read in table lengths */
  NEEDBITS(5)
  nl = 257 + ((unsigned)b & 0x1f);      /* number of literal/length codes */
  DUMPBITS(5)
  NEEDBITS(5)
  nd = 1 + ((unsigned)b & 0x1f);        /* number of distance codes */
  DUMPBITS(5)
  NEEDBITS(4)
  nb = 4 + ((unsigned)b & 0xf);         /* number of bit length codes */
  DUMPBITS(4)
  if (nl > MAXLITLENS || nd > MAXDISTS)
    return 1;                   /* bad lengths */


  /* read in bit-length-code lengths */
  for (j = 0; j < nb; j++)
  {
    NEEDBITS(3)
    ll[border[j]] = (unsigned)b & 7;
    DUMPBITS(3)
  }
  for (; j < 19; j++)
    ll[border[j]] = 0;


  /* build decoding table for trees--single level, 7 bit lookup */
  bl = 7;
  retval = huft_build2(ll, 19, 19, NULL, NULL, &tl, (int*)&bl);
  if (bl == 0)                  /* no bit lengths */
    retval = 1;
  if (retval)
  {
    if (retval == 1)
      huft_free(tl);
    return retval;              /* incomplete code set */
  }


  /* read in literal and distance code lengths */
  n = nl + nd;
  m = mask_bits[bl];
  i = l = 0;
  while (i < n)
  {
    NEEDBITS(bl)
    j = (td = tl + ((unsigned)b & m))->b;
    DUMPBITS(j)
    j = td->v.n;
    if (j < 16)                 /* length of code in bits (0..15) */
      ll[i++] = l = j;          /* save last length in l */
    else if (j == 16)           /* repeat last length 3 to 6 times */
    {
      NEEDBITS(2)
      j = 3 + ((unsigned)b & 3);
      DUMPBITS(2)
      if ((unsigned)i + j > n)
        return 1;
      while (j--)
        ll[i++] = l;
    }
    else if (j == 17)           /* 3 to 10 zero length codes */
    {
      NEEDBITS(3)
      j = 3 + ((unsigned)b & 7);
      DUMPBITS(3)
      if ((unsigned)i + j > n)
        return 1;
      while (j--)
        ll[i++] = 0;
      l = 0;
    }
    else                        /* j == 18: 11 to 138 zero length codes */
    {
      NEEDBITS(7)
      j = 11 + ((unsigned)b & 0x7f);
      DUMPBITS(7)
      if ((unsigned)i + j > n)
        return 1;
      while (j--)
        ll[i++] = 0;
      l = 0;
    }
  }


  /* free decoding table for trees */
  huft_free(tl);


  /* restore the global bit buffer */
  G.bb = b;
  G.bk = k;


  /* build the decoding tables for literal/length and distance codes */
  bl = lbits;
#ifdef USE_DEFLATE64
  retval = huft_build2(ll, nl, 257, G.cplens, G.cplext, &tl, (int*)&bl);
#else
  retval = huft_build2(ll, nl, 257, cplens, cplext, &tl, &bl);
#endif
  if (bl == 0)                  /* no literals or lengths */
    retval = 1;
  if (retval)
  {
    if (retval == 1) {
//      if (!uO.qflag)
//        MESSAGE((uch *)"(incomplete l-tree)  ", 21L, 1);
      huft_free(tl);
    }
    return retval;              /* incomplete code set */
  }
#ifdef FIX_PAST_EOB_BY_TABLEADJUST
  /* Adjust the requested distance base table size so that a distance code
     fetch never tries to get bits behind an immediatly following end-of-block
     code. */
  bd = (dbits <= bl+1 ? dbits : bl+1);
#else
  bd = dbits;
#endif
#ifdef USE_DEFLATE64
  retval = huft_build2(ll + nl, nd, 0, cpdist, G.cpdext, &td, (int*)&bd);
#else
  retval = huft_build2(ll + nl, nd, 0, cpdist, cpdext, &td, &bd);
#endif
#ifdef PKZIP_BUG_WORKAROUND
  if (retval == 1)
    retval = 0;
#endif
  if (bd == 0 && nl > 257)    /* lengths but no distances */
    retval = 1;
  if (retval)
  {
    if (retval == 1) {
      //if (!uO.qflag)
      //  MESSAGE((uch *)"(incomplete d-tree)  ", 21L, 1);
      huft_free(td);
    }
    huft_free(tl);
    return retval;
  }

  /* decompress until an end-of-block code */
  retval = inflate_codes(tl, td, bl, bd);

cleanup_and_exit:
  /* free the decoding tables, return */
  huft_free(tl);
  huft_free(td);
  return retval;
}



int KbUnz::inflate_block(int *e)
  //__GDEF
  //int *e;               /* last block flag */
/* decompress an inflated block */
{
  unsigned t;           /* block type */
  register ulg b;       /* bit buffer */
  register unsigned k;  /* number of bits in bit buffer */
  int retval = 0;       /* error code returned: initialized to "no error" */


  /* make local bit buffer */
  b = G.bb;
  k = G.bk;


  /* read in last block bit */
  NEEDBITS(1)
  *e = (int)b & 1;
  DUMPBITS(1)


  /* read in block type */
  NEEDBITS(2)
  t = (unsigned)b & 3;
  DUMPBITS(2)


  /* restore the global bit buffer */
  G.bb = b;
  G.bk = k;


  /* inflate that block type */
  if (t == 2)
    return inflate_dynamic();
  if (t == 0)
    return inflate_stored();
  if (t == 1)
    return inflate_fixed();


  /* bad block type */
  retval = 2;

cleanup_and_exit:
  return retval;
}



int KbUnz::inflate(int is_defl64)
//    __GDEF
//    int is_defl64;
/* decompress an inflated entry */
{
  int e;                /* last block flag */
  int r;                /* result code */
#ifdef DEBUG
  unsigned h = 0;       /* maximum struct huft's malloc'ed */
#endif

#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
  if (G.redirect_slide)
    wsize = G.redirect_size, redirSlide = G.redirect_buffer;
  else
    wsize = WSIZE, redirSlide = slide;   /* how they're #defined if !DLL */
#endif

  /* initialize window, bit buffer */
  G.wp = 0;
  G.bk = 0;
  G.bb = 0;

#ifdef USE_DEFLATE64
  if (is_defl64) {
    G.cplens = cplens64;
    G.cplext = cplext64;
    G.cpdext = cpdext64;
    G.fixed_tl = G.fixed_tl64;
    G.fixed_bl = G.fixed_bl64;
    G.fixed_td = G.fixed_td64;
    G.fixed_bd = G.fixed_bd64;
  } else {
    G.cplens = cplens32;
    G.cplext = cplext32;
    G.cpdext = cpdext32;
    G.fixed_tl = G.fixed_tl32;
    G.fixed_bl = G.fixed_bl32;
    G.fixed_td = G.fixed_td32;
    G.fixed_bd = G.fixed_bd32;
  }
#else /* !USE_DEFLATE64 */
  if (is_defl64) {
    /* This should not happen unless UnZip is built from object files
     * compiled with inconsistent option setting.  Handle this by
     * returning with "bad input" error code.
     */
    Trace((stderr, "\nThis inflate() cannot handle Deflate64!\n"));
    return 2;
  }
#endif /* ?USE_DEFLATE64 */

  /* decompress until the last block */
  do {
#ifdef DEBUG
    G.hufts = 0;
#endif
    if ((r = inflate_block(&e)) != 0)
      return r;
#ifdef DEBUG
    if (G.hufts > h)
      h = G.hufts;
#endif
  } while (!e);

//  Trace((stderr, "\n%u bytes in Huffman tables (%u/entry)\n",
//         h * (unsigned)sizeof(struct huft), (unsigned)sizeof(struct huft)));

#ifdef USE_DEFLATE64
  if (is_defl64) {
    G.fixed_tl64 = G.fixed_tl;
    G.fixed_bl64 = G.fixed_bl;
    G.fixed_td64 = G.fixed_td;
    G.fixed_bd64 = G.fixed_bd;
  } else {
    G.fixed_tl32 = G.fixed_tl;
    G.fixed_bl32 = G.fixed_bl;
    G.fixed_td32 = G.fixed_td;
    G.fixed_bd32 = G.fixed_bd;
  }
#endif
  /* flush out redirSlide and return (success, unless final FLUSH failed) */
  flush(G.wp);
  //return (FLUSH(G.wp));
  return 0;
}



int KbUnz::inflate_free()
//    __GDEF
{
  if (G.fixed_tl != (struct huft *)NULL)
  {
    huft_free(G.fixed_td);
    huft_free(G.fixed_tl);
    G.fixed_td = G.fixed_tl = (struct huft *)NULL;
  }
  return 0;
}

//#endif /* ?USE_ZLIB */


/*
 * GRR:  moved huft_build() and huft_free() down here; used by explode()
 *       and fUnZip regardless of whether USE_ZLIB defined or not
 */


/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
#define BMAX 16         /* maximum bit length of any code (16 for explode) */
#define N_MAX 288       /* maximum number of codes in any set */

int __fastcall KbUnz::huft_build2(unsigned *b, unsigned n, unsigned s, const WORD *d, const BYTE *e, huft **t, int *m)
//  __GDEF
//  ZCONST unsigned *b;   /* code lengths in bits (all assumed <= BMAX) */
//  unsigned n;           /* number of codes (assumed <= N_MAX) */
//  unsigned s;           /* number of simple-valued codes (0..s-1) */
//  ZCONST ush *d;        /* list of base values for non-simple codes */
//  ZCONST uch *e;        /* list of extra bits for non-simple codes */
//  struct huft **t;      /* result: starting table */
//  unsigned *m;          /* maximum lookup bits, returns actual */
/* Given a list of code lengths and a maximum table size, make a set of
   tables to decode that set of codes.  Return zero on success, one if
   the given code set is incomplete (the tables are still built in this
   case), two if the input is invalid (all zero length codes or an
   oversubscribed set of lengths), and three if not enough memory.
   The code with value 256 is special, and the tables are constructed
   so that no bits beyond that code are fetched when that code is
   decoded. */
{
  unsigned a;                   /* counter for codes of length k */
  unsigned c[BMAX+1];           /* bit length count table */
  unsigned el;                  /* length of EOB code (value 256) */
  unsigned f;                   /* i repeats in table every f entries */
  int g;                        /* maximum code length */
  int h;                        /* table level */
  register unsigned i;          /* counter, current code */
  register unsigned j;          /* counter */
  register int k;               /* number of bits in current code */
  int lx[BMAX+1];               /* memory for l[-1..BMAX-1] */
  int *l = lx+1;                /* stack of bits per table */
  register unsigned *p;         /* pointer into c[], b[], or v[] */
  register struct huft *q;      /* points to current table */
  struct huft r;                /* table entry for structure assignment */
  struct huft *u[BMAX];         /* table stack */
  unsigned v[N_MAX];            /* values in order of bit length */
  register int w;               /* bits before this table == (l * h) */
  unsigned x[BMAX+1];           /* bit offsets, then code stack */
  unsigned *xp;                 /* pointer into x */
  int y;                        /* number of dummy codes added */
  unsigned z;                   /* number of entries in current table */


  /* Generate counts for each bit length */
  el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */
  //memzero((char *)c, sizeof(c));
  ZeroMemory((char *)c, sizeof(c));
  p = (unsigned *)b;  i = n;
  do {
    c[*p]++; p++;               /* assume all entries <= BMAX */
  } while (--i);
  if (c[0] == n)                /* null input--all zero length codes */
  {
    *t = (struct huft *)NULL;
    *m = 0;
    return 0;
  }


  /* Find minimum and maximum length, bound *m by those */
  for (j = 1; j <= BMAX; j++)
    if (c[j])
      break;
  k = j;                        /* minimum code length */
  if (*m < j)
    *m = j;
  for (i = BMAX; i; i--)
    if (c[i])
      break;
  g = i;                        /* maximum code length */
  if (*m > i)
    *m = i;


  /* Adjust last length count to fill out codes, if needed */
  for (y = 1 << j; j < i; j++, y <<= 1)
    if ((y -= c[j]) < 0)
      return 2;                 /* bad input: more codes than bits */
  if ((y -= c[i]) < 0)
    return 2;
  c[i] += y;


  /* Generate starting offsets into the value table for each length */
  x[1] = j = 0;
  p = c + 1;  xp = x + 2;
  while (--i) {                 /* note that i == g from above */
    *xp++ = (j += *p++);
  }


  /* Make a table of values in order of bit lengths */
  //memzero((char *)v, sizeof(v));
  ZeroMemory((char *)v, sizeof(v));
  p = (unsigned *)b;  i = 0;
  do {
    if ((j = *p++) != 0)
      v[x[j]++] = i;
  } while (++i < n);
  n = x[g];                     /* set n to length of v */


  /* Generate the Huffman codes and for each, make the table entries */
  x[0] = i = 0;                 /* first Huffman code is zero */
  p = v;                        /* grab values in bit order */
  h = -1;                       /* no tables yet--level -1 */
  w = l[-1] = 0;                /* no bits decoded yet */
  u[0] = (struct huft *)NULL;   /* just to keep compilers happy */
  q = (struct huft *)NULL;      /* ditto */
  z = 0;                        /* ditto */

  /* go through the bit lengths (k already is bits in shortest code) */
  for (; k <= g; k++)
  {
    a = c[k];
    while (a--)
    {
      /* here i is the Huffman code of length k bits for value *p */
      /* make tables up to required level */
      while (k > w + l[h])
      {
        w += l[h++];            /* add bits already decoded */

        /* compute minimum size table less than or equal to *m bits */
        z = (z = g - w) > *m ? *m : z;                  /* upper limit */
        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
        {                       /* too few codes for k-w bit table */
          f -= a + 1;           /* deduct codes from patterns left */
          xp = c + k;
          while (++j < z)       /* try smaller tables up to z bits */
          {
            if ((f <<= 1) <= *++xp)
              break;            /* enough codes to use up j bits */
            f -= *xp;           /* else deduct codes from patterns */
          }
        }
        if ((unsigned)w + j > el && (unsigned)w < el)
          j = el - w;           /* make EOB code end at table */
        z = 1 << j;             /* table entries for j-bit table */
        l[h] = j;               /* set table size in stack */

        /* allocate and link in new table */
        if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
            (struct huft *)NULL)
        {
          if (h)
            huft_free(u[0]);
          return 3;             /* not enough memory */
        }
#ifdef DEBUG
        G.hufts += z + 1;         /* track memory usage */
#endif
        *t = q + 1;             /* link to list for huft_free() */
        *(t = &(q->v.t)) = (struct huft *)NULL;
        u[h] = ++q;             /* table starts after link */

        /* connect to last table, if there is one */
        if (h)
        {
          x[h] = i;             /* save pattern for backing up */
          r.b = (uch)l[h-1];    /* bits to dump before this table */
          r.e = (uch)(32 + j);  /* bits in this table */
          r.v.t = q;            /* pointer to this table */
          j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
          u[h-1][j] = r;        /* connect to last table */
        }
      }

      /* set up table entry in r */
      r.b = (uch)(k - w);
      if (p >= v + n)
        r.e = INVALID_CODE;     /* out of values--invalid code */
      else if (*p < s)
      {
        r.e = (uch)(*p < 256 ? 32 : 31);  /* 256 is end-of-block code */
        r.v.n = (ush)*p++;                /* simple code is just the value */
      }
      else
      {
        r.e = e[*p - s];        /* non-simple--look up in lists */
        r.v.n = d[*p++ - s];
      }

      /* fill code-like entries with r */
      f = 1 << (k - w);
      for (j = i >> w; j < z; j += f)
        q[j] = r;

      /* backwards increment the k-bit code i */
      for (j = 1 << (k - 1); i & j; j >>= 1)
        i ^= j;
      i ^= j;

      /* backup over finished tables */
      while ((i & ((1 << w) - 1)) != x[h])
        w -= l[--h];            /* don't need to update q */
    }
  }


  /* return actual size of base table */
  *m = l[0];


  /* Return true (1) if we were given an incomplete table */
  return y != 0 && g != 1;
}
