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 + -
显示快捷键?