cabsupport.cpp

来自「java调用ie浏览器demo源码,可以用在windows或者linux」· C++ 代码 · 共 1,466 行 · 第 1/3 页

CPP
1,466
字号
            signalNewEntrtyFound(szSyntheticPath);

        }

        break;

    case fdintCOPY_FILE:// file to be copied

        signalNewEntrtyFound(

            pfdin->psz1,

            pfdin->time,

            pfdin->date,

            ACCESS_READ | ACCESS_EXECUTE | ((pfdin->attribs & _A_RDONLY) ? 0 : ACCESS_WRITE),

            pfdin->cb

        );

        {

            CHAR szName[100];        

            ret = file_open(

                ptoa((LONG_PTR)this, szName, 10),

                0, //fake

                0  //fake

            );

        }

        break;

    case fdintCLOSE_FILE_INFO:	// close the file, set relevant info

        file_close(pfdin->hf);

        ::SetEvent(m_hevEndOfEntry);

        {

            //wait here for last read or close

            HANDLE hhSignals[] = { m_hevLastEntryRead, m_hevClose };

            ::WaitForMultipleObjects(

                sizeof(hhSignals)/sizeof(*hhSignals),

                hhSignals,

                FALSE,

                INFINITE);

        }

        ++ret;//TRUE

        break;

    case fdintNEXT_CABINET:	// file continued to next cabinet

        setProperty(cab_next_file, pfdin->psz1);//name of next cabinet where file continued

        setProperty(cab_next_disk, pfdin->psz2);//name of next disk where file continued

        setProperty(cab_path,      pfdin->psz3);//cabinet path name

        

        //signal here that new synthetic folder-section has come

        if(NULL!=pfdin->psz1){

            CHAR szSyntheticPath[1024];

            if( 0 > _snprintf(
                szSyntheticPath, 1024, "cab_next://%s|/%s/", 
                pfdin->psz2,
                pfdin->psz1))
            {
                szSyntheticPath[1023] = 0;

            }

            signalNewEntrtyFound(szSyntheticPath);

        }

        break;

    }



    //no wait, just check

    if( WAIT_OBJECT_0 == ::WaitForSingleObject(m_hevClose,0) ){

        //user cancel if close signaled

        return -1;

    }

    return ret;

}



///////////////////////////////////

// class CCabUnpacker

CCabUnpacker::CCabUnpacker(

    JNIEnv *env, 

    jobject is,

    jlong   hint

)

: CUnpackerExt(env, is, hint),

  m_hevNewEntryFound(::CreateEvent(NULL, FALSE, FALSE, NULL)),

  m_hevLastEntryRead(::CreateEvent(NULL, FALSE, FALSE, NULL)),

  m_hevEndOfEntry(::CreateEvent(NULL, TRUE, TRUE, NULL)), //manual reset, signaled

  m_hevOutWriteReady(::CreateEvent(NULL, FALSE, FALSE, NULL)),

  m_hevOutReadReady(::CreateEvent(NULL, FALSE, FALSE, NULL)),

  m_hevClose(::CreateEvent(NULL, TRUE, FALSE, NULL)), //set ones, can not be re-opened

  m_hmtLock(::CreateMutex(NULL, FALSE, NULL)),

  m_hCabThread(NULL),

  m_CabThreadId(0),

  m_env_nt(NULL),

  m_bFirstRead(TRUE),

  m_outCache(MIN_CACHE_SIZE),

  m_ex(NULL)

{

    m_csize = -1;//compressed, but unknown



    //there is not default entry in CAB

    memset(m_props, 0, sizeof(m_props));

    m_hfdi = FDICreate(

        mem_alloc,

        mem_free,

        file_open,

        file_read,

        file_write,

        file_close,

        file_seek,

        cpu80386,

        &m_erf

    );

    if( NULL==m_hfdi ) {

        JNU_ThrowIOException(env, "FDICreate error");

    }

}



bool CCabUnpacker::checkValid(JNIEnv *env)

{

    if(NULL!=m_ex){

        env->Throw(m_ex);

        releaseGlobal(env, m_ex);

        m_ex = NULL;

        return false;

    }

    return true;

}



void CCabUnpacker::close(JNIEnv *env)

{

    if(m_hCabThread){

        ::SetEvent(m_hevClose);

        ::WaitForSingleObject(m_hCabThread, INFINITE);

        ::CloseHandle(m_hCabThread);

        m_hCabThread = NULL;

    }



    if( NULL!=m_hfdi && !FDIDestroy(m_hfdi) ){

        JNU_ThrowIOException(env, "FDIDestroy error");

    }

    m_hfdi = NULL;



    releaseGlobal(env, m_ex);

    m_ex = NULL;



    m_inCache = NULL;

    CUnpackerExt::close(env);

}



CCabUnpacker::~CCabUnpacker()

{

    for(int i=0; i < sizeof(m_props)/sizeof(*m_props); ++i ){

        free(m_props[i]);

    }

    if(NULL != m_hfdi){

        //alarm message

    }

}





unsigned  __stdcall  CCabUnpacker::ThreadAction(void *pThis)

{

    return ((CCabUnpacker*)pThis)->Run();

}

void CCabUnpacker::CreateThreadIfNeed()

{

    if(m_bFirstRead){

        m_hCabThread = (HANDLE)_beginthreadex(

            NULL, 

            0, 

            ThreadAction, 

            this, 

            0, 

            (unsigned int *)&m_CabThreadId

        );

        m_bFirstRead = FALSE;

    }

}



unsigned int CCabUnpacker::Run()

{

    unsigned int ret = (unsigned int)jvm->AttachCurrentThread(

        (void**)&m_env_nt, 

        NULL

    );

    if( 0 == ret ){

        CHAR szName[64];        

        if( !FDICopy(

            m_hfdi,

            ptoa((LONG_PTR)this, szName, 10),

            "",

            0,

            notification_function,

            NULL,

            this))

        {

             ret = m_erf.erfOper;

            jthrowable lex = m_env_nt->ExceptionOccurred();

            if( NULL == lex ){

                JNU_ThrowIOException(

                    m_env_nt,

                    return_fdi_error_string((FDIERROR)ret)

                );

                lex = m_env_nt->ExceptionOccurred();

            }

            m_ex = (jthrowable) makeGlobal(

                m_env_nt, 

                lex

            );

             //m_env_nt->ExceptionDescribe();

             m_env_nt->ExceptionClear();

        }

        jvm->DetachCurrentThread();   

        m_env_nt = NULL;

    }

    

    signalNewEntrtyFound();//last null-section was found

    return ret; 

}



jobject CCabUnpacker::readNextEntry(

    JNIEnv *env 

){

    CreateThreadIfNeed();

    if(NULL==m_hCabThread){

        JNU_ThrowIOException(env, "Invalid unpacker state");

    } else {

        HANDLE hhSignals[] = { m_hevClose, m_hevNewEntryFound };

        DWORD dwRes = ::WaitForMultipleObjects(

            sizeof(hhSignals)/sizeof(*hhSignals),

            hhSignals,

            FALSE,

            INFINITE

        );

        if( !checkValid(env) || WAIT_OBJECT_0 == dwRes ){

            return NULL;

        }

        return CUnpackerExt::readNextEntry(env);

    }

    return NULL;

}



void CCabUnpacker::setProperty(int iIndex, LPSTR pValue)

{

   free(m_props[iIndex]);

   m_props[iIndex] = _strdup(pValue);

}



void CCabUnpacker::setProperty(int iIndex, LONG_PTR iValue)

{

   CHAR szDig[32];

   setProperty(iIndex, ptoa(iValue, szDig, 16));

}





jstring CCabUnpacker::getProperty(

    JNIEnv *env,

    jint iIndex

){

    if(iIndex < arc_prop_count){

        return CUnpackerExt::getProperty(env, iIndex);

    }



    iIndex -= arc_prop_count;

    LPSTR pValue = NULL;

    if(iIndex < cab_prop_count){

        pValue = m_props[iIndex];

    }

    return pValue

        ? CAB_NewStringPlatform(env, pValue)

        : NULL;

}





/////////////////////////////////////

//   PACKER

/////////////////////////////////////



char *return_fci_error_string(FCIERROR err)

{

    switch(err){

    case FCIERR_NONE:

        return "No error";

    case FCIERR_OPEN_SRC:

        return "Failure opening file to be stored in cabinet";

    case FCIERR_READ_SRC:

        return "Failure reading file to be stored in cabinet";

    case FCIERR_ALLOC_FAIL:

        return "Insufficient memory in FCI";

    case FCIERR_TEMP_FILE:

        return "Could not create a temporary file";

    case FCIERR_BAD_COMPR_TYPE:

        return "Unknown compression type";

    case FCIERR_CAB_FILE:

        return "Could not create cabinet file";

    case FCIERR_USER_ABORT:

        return "Client requested abort";

    case FCIERR_MCI_FAIL:

        return "Failure compressing data";

    default:

        return "Unknown error";

    }

}







///////////////////////////////////

// class CCabPacker

CCabPacker::CCabPacker(

    JNIEnv *env, 

    jobject othis,

    jobject os,

    jlong   hint

)

: CPackerExt(env, othis, os, hint),

  m_hevCreateNewEntry(::CreateEvent(NULL, FALSE, FALSE, NULL)),

  m_hevDropToJavaOS(::CreateEvent(NULL, FALSE, FALSE, NULL)),

  m_hevDropToJavaOSComplite(::CreateEvent(NULL, FALSE, FALSE, NULL)),

  m_hevEndOfEntry(::CreateEvent(NULL, TRUE, TRUE, NULL)), //manual reset, signaled

  m_hevOutWriteReady(::CreateEvent(NULL, FALSE, FALSE, NULL)),

  m_hevOutReadReady(::CreateEvent(NULL, FALSE, FALSE, NULL)),

  m_hevCompressionStarted(::CreateEvent(NULL, FALSE, FALSE, NULL)),

  m_hmtEntryInProgress(::CreateMutex(NULL, FALSE, NULL)),

  m_hevClose(::CreateEvent(NULL, TRUE, FALSE, NULL)), //set ones, can not be re-opened

  m_hmtLock(::CreateMutex(NULL, FALSE, NULL)),

  m_hCabThread(NULL),

  m_CabThreadId(0),

  m_env_nt(NULL),

  m_bFirstRead(TRUE),

  m_inCache(MIN_CACHE_SIZE),

  m_ex(NULL)

{

    m_pEntrySuffixStub = getEntrySuffixStub(env);

    m_compressionType = tcompTYPE_LZX;



    //there is not default entry in CAB

    OLE_TRY

    OLE_HRT(CreateStream(

        &m_outCache,

        m_hint

    ));



    memset(&m_ccab, 0, sizeof(CCAB));



    // When a CAB file reaches this size, a new CAB will be created

    // automatically.  This is useful for fitting CAB files onto disks.

    // If you want to create just one huge CAB file with everything in

    // it, change this to a very very large number.

    m_ccab.cb = 0x7FFFFFFF;//(ULONG)-1; //we want

    //m_ccab.cb = 2000000;//(ULONG)-1; //we want     



    // When a folder has this much compressed data inside it,

    // automatically flush the folder.

    // Flushing the folder hurts compression a little bit, but

    // helps random access significantly.

    m_ccab.cbFolderThresh = 0x7FFFFFFF;//(ULONG)-1; //never try

    //m_ccab.cbFolderThresh = 2000000;//(ULONG)-1; //never try



    //Don't reserve space for any extensions

    m_ccab.cbReserveCFHeader = 0;

    m_ccab.cbReserveCFFolder = 0;

    m_ccab.cbReserveCFData   = 0;



    //We use this to create the cabinet name

    m_ccab.iCab = 1;



    //If you want to use disk names, use this to count disks

    m_ccab.iDisk = 0;



    //Choose your own number

    m_ccab.setID = 0x414A; //"SN"



    //Only important if CABs are spanning multiple

    //disks, in which case you will want to use a

    //real disk name.



    //Can be left as an empty string.

    //strcpy(m_ccab.szDisk, "MyDisk");



    // where to store the created CAB files

    //strcpy(m_ccab.szCabPath, "c:\\");



    // store name of first CAB file 

    //store_cab_name(cab_parms->szCab, cab_parms->iCab);

    strcpy(m_ccab.szCab, OUT_NAME);



    m_hfci = FCICreate(

        &m_erf,

        fci_placed,

        mem_alloc,

        mem_free,

        fci_open,

        fci_read,

        fci_write,

        fci_close,

        fci_seek,

        fci_delete,

        fci_temp_file,

        &m_ccab,

        this

    );

    OLE_CATCH;



    if( NULL==m_hfci || FAILED(OLE_HR) ) {

        if( FAILED(OLE_HR) ){

            HR2CABERR(env, OLE_HR, "FCI create error", 0);

        } else {

            JNU_ThrowIOException(env, "FCI create error");

        }

    }

}



bool CCabPacker::checkValid(JNIEnv *env)

{

    if(NULL!=m_ex){

        env->Throw(m_ex);

        releaseGlobal(env, m_ex);

        m_ex = NULL;

        return false;

    }

    return true;

}



void CCabPacker::finish(JNIEnv *env)

{

    closeEntry(env, -1);//alarm termination, crc unknown

    if( !env->ExceptionCheck() && m_hCabThread){

        ::SetEvent(m_hevDropToJavaOS);

        HANDLE hhSignals[] = { m_hCabThread,  m_hevDropToJavaOSComplite };

        ::WaitForMultipleObjects(

            sizeof(hhSignals)/sizeof(*hhSignals),

            hhSignals,

            FALSE,

            INFINITE);

        checkValid(env);

    }

}



void CCabPacker::close(JNIEnv *env)

{

    if(m_hCabThread){

        ::SetEvent(m_hevClose);

        ::WaitForSingleObject(m_hCabThread, INFINITE);

        ::CloseHandle(m_hCabThread);

        m_hCabThread = NULL;

    }

    if( NULL!=m_hfci && !FCIDestroy(m_hfci) ){

        JNU_ThrowIOException(env, return_fci_error_string((FCIERROR)m_erf.erfOper));

    }

    m_hfci = NULL;



    releaseGlobal(env, m_ex);

    m_ex = NULL;



    m_outCache = NULL;

    CPackerExt::close(env);

}



CCabPacker::~CCabPacker()

{

    free(m_pEntrySuffixStub);

    if(NULL != m_hfci){

        //alarm message

    }

}



unsigned  __stdcall  CCabPacker::ThreadAction(void *pThis)

{

    return ((CCabPacker*)pThis)->Run();

}



void CCabPacker::CreateThreadIfNeed()

{

    if(m_bFirstRead){

        m_hCabThread = (HANDLE)_beginthreadex(

            NULL, 

            0, 

            ThreadAction, 

            this, 

            0, 

            (unsigned int *)&m_CabThreadId

        );

        m_bFirstRead = FALSE;

    }

}



HRESULT CCabPacker::DropJavaStream(JNIEnv *env)

{

    OLE_DECL;

    jbyteArray jba = env->NewByteArray( jsize(1024) );

    if( NULL == jba ){

        OLE_HR = E_OUTOFMEMORY;

    } else {

        //copy to stream

        OLE_HR = m_outCache->Seek(_ZERO64, SEEK_SET, NULL);

        while(SUCCEEDED(OLE_HR)){

            jbyte *pDst = env->GetByteArrayElements(jba, NULL);

            if(NULL==pDst){

                OLE_HR = E_OUTOFMEMORY;

            } else {

                ULONG read;

                OLE_HR = m_outCache->Read(

⌨️ 快捷键说明

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