📄 cabinet.cpp
字号:
// Globals :
// I/O :
// Task : Open a file 4 decompression interface
//-------------------------------------------------------------------------
int FAR DIAMONDAPI CCabinetExtractor::FileOpen(char FAR *pszFile, int oFlag, int pMode)
{
return CCabinetBase::FileOpen(pszFile,oFlag,pMode,&errno,NULL);
}
#endif
#ifdef __CAB_EXTRACT__
//-------------------------------------------------------------------------
// Pre :
// Post :
// Globals :
// I/O :
// Task : Read cbRead bytes from file specified by handle into buffer ptrBuffer at
// decompression interface request
//-------------------------------------------------------------------------
UINT FAR DIAMONDAPI CCabinetExtractor::FileRead(int hFile, void FAR *ptrBuffer, UINT cbRead)
{
return CCabinetBase::FileRead(hFile,ptrBuffer,cbRead,&errno,NULL);
}
#endif
#ifdef __CAB_EXTRACT__
//-------------------------------------------------------------------------
// Pre :
// Post :
// Globals :
// I/O :
// Task : Write cbWrite bytes from buffer ptrBuffer int file specified by handle at
// decompression interface request
//-------------------------------------------------------------------------
UINT FAR DIAMONDAPI CCabinetExtractor::FileWrite(int hFile, void FAR *ptrBuffer, UINT cbWrite)
{
return CCabinetBase::FileWrite(hFile,ptrBuffer,cbWrite,&errno,NULL);
}
#endif
#ifdef __CAB_EXTRACT__
//-------------------------------------------------------------------------
// Pre :
// Post :
// Globals :
// I/O :
// Task : Compression interface wants 2 seek the file pointer
//-------------------------------------------------------------------------
long FAR DIAMONDAPI CCabinetExtractor::FileSeek(int hFile, long offset, int seekType)
{
return CCabinetBase::FileSeek(hFile,offset,seekType,&errno,NULL);
}
#endif
#ifdef __CAB_EXTRACT__
//-------------------------------------------------------------------------
// Pre :
// Post :
// Globals :
// I/O :
// Task : Decompression interface wants 2 close this file
//-------------------------------------------------------------------------
int FAR DIAMONDAPI CCabinetExtractor::FileClose(int hFile)
{
return CCabinetBase::FileClose(hFile,&errno,NULL);
}
#endif
#ifdef __CAB_EXTRACT__
//-------------------------------------------------------------------------
// Pre : If lpInfo is NULL, then no information is returned on the cabinet
// only checking 2 see if it's a valid cabinet file
// Post : Return TRUE if info extracted OK, FALSE if not a cabinet file or
// there was some error
// Globals :
// I/O :
// Task : Return info about a cabinet file
//-------------------------------------------------------------------------
BOOL CCabinetExtractor::GetCabinetInfo(LPCTSTR lpcszCabFile, CABINETINFO *lpInfo)
{
// Check our internal status
if(!m_bStatus)
return FALSE;
// Open file because the decompression interface
// wants an open file 2 get info about
TCHAR szCabFile[MAX_PATH];
STRCPY(szCabFile,lpcszCabFile);
int hFile =FileOpen(szCabFile,_O_RDONLY | _O_SEQUENTIAL,0);
if(hFile == -1)
// Could not open file
return FALSE;
// Get info...
FDICABINETINFO info;
BOOL is_cabinet =FDIIsCabinet(m_hContext,hFile,&info);
if(is_cabinet && lpInfo)
{
// Store info about the cabinet
lpInfo->m_cbSize =info.cbCabinet;
lpInfo->m_nFolders =info.cFolders;
lpInfo->m_nFiles =info.cFiles;
lpInfo->m_nID =info.setID;
lpInfo->m_nIndex =info.iCabinet;
lpInfo->m_bHasReservedSpace =info.fReserve;
lpInfo->m_bChainedPrev =info.hasprev;
lpInfo->m_bChainedNext =info.hasnext;
}
// Close the file we've got info from
FileClose(hFile);
return is_cabinet;
}
#endif
#ifdef __CAB_EXTRACT__
//-------------------------------------------------------------------------
// Pre :
// Post :
// Globals :
// I/O :
// Task : Store a default extraction folder
//-------------------------------------------------------------------------
void CCabinetExtractor::SetDefaultExtractPath(LPCTSTR lpcszDefExtractPath)
{
if(lpcszDefExtractPath)
{
string str(lpcszDefExtractPath);
EnsureTrailingBackslash(str);
m_DefaultExtractPath =str.c_str();
}
}
#endif
#ifdef __CAB_EXTRACT__
//-------------------------------------------------------------------------
// Pre : lpcszCabFile is the full path 2 the first .cab file in set
// bContinuous specifies whether 2 attempt processing possible following
// cabinets in set (if any), or only extract files from the specified .cab file
// Post : Return TRUE if file(s) extracted OK, FALSE if not a cabinet file or
// there was some error
// Globals :
// I/O :
// Task : Extract one or more files from a cabinet. Clients must implement
// notification members, so that they can supply the extractor object
// with info on each file 2 extract (e.g. if extract, where 2 extract etc.)
//-------------------------------------------------------------------------
BOOL CCabinetExtractor::ExtractFiles(LPCTSTR lpcszCabFile, BOOL bContinuous)
{
// Check our internal status
if(!m_bStatus)
return FALSE;
// Make sure we've got a valid cabinet file
CABINETINFO cabinfo;
if(!GetCabinetInfo(lpcszCabFile,&cabinfo))
return FALSE;
// Store the path and name of cabinet being extracted
m_bNextCabinetReady =TRUE;
m_CabinetPath =lpcszCabFile;
m_CabinetPath.GetNameExtension(m_strCabinetName);
m_CabinetPath.SetNameExtension(_T(""));
BOOL bResult =TRUE;
while(bResult)
{
// Start extraction...
// This will extract all files in this .cab file, including the
// ones which are continued in successive cabinets
TCHAR sz_cabinet_path[MAX_PATH];
TCHAR sz_cabinet_name[MAX_PATH];
STRCPY(sz_cabinet_path,(LPCTSTR)m_CabinetPath);
STRCPY(sz_cabinet_name,m_strCabinetName.c_str());
// Make sure the required cabinet is available
// Only do this 4 second or subsequent passes
string strNextCabinetPath((LPCTSTR)m_CabinetPath);
m_CabinetError.erfOper =FDIERROR_NONE;
while(!m_bNextCabinetReady)
{
// Got a cabinet, see if cabinet is already available at the expected location
// and if not, ask our client 2 provide us with the path 2 the next cabinet
CPath CabinetValidator;
CabinetValidator.SetDriveDirectory(strNextCabinetPath.c_str());
CabinetValidator.SetNameExtension(m_strCabinetName.c_str());
if(CabinetValidator.Exists())
{
// Check if file is a real cabinet
if(GetCabinetInfo(CabinetValidator,&cabinfo))
{
// Check if the cabinet we got is the one we want
if(cabinfo.m_nIndex == m_nContinueIndex)
{
#pragma message(Reminder(_T("Also check set ID")))
// Yeah, we have the cabinet we need
m_bNextCabinetReady =TRUE;
}
else
{
// Cabinet is the wrong one, again
m_CabinetError.erfOper =FDIERROR_WRONG_CABINET;
}
}
else
{
// File is not a cabinet, again
m_CabinetError.erfOper =FDIERROR_NOT_A_CABINET;
}
}
else
{
// No such file, again
m_CabinetError.erfOper =FDIERROR_CABINET_NOT_FOUND;
}
if(m_bNextCabinetReady)
{
// Yeah, if we got here, then we have the cabinet we need
m_CabinetError.erfOper =FDIERROR_NONE;
m_CabinetPath.SetDriveDirectory(strNextCabinetPath.c_str());
STRCPY(sz_cabinet_path,(LPCTSTR)m_CabinetPath);
}
else
{
// We'll call NotifyNextCabinet until we get it right
// or client aborts
if(!NotifyNextCabinet(m_strCabinetName.c_str(),m_strContinueDisk.c_str(),strNextCabinetPath,m_CabinetError.erfOper))
{
// Aborted
m_CabinetError.erfOper =FDIERROR_USER_ABORT;
m_CabinetError.fError =TRUE;
return FALSE;
}
}
}
// Make sure that cabinet is available at the expected location
// find out the index of the cabinet which is first 2 be extracted from
m_strNextDisk.erase();
m_NextCabinet =m_CabinetPath;
m_NextCabinet.SetNameExtension(m_strCabinetName.c_str());
ASSERTX(m_NextCabinet.Exists());
ASSERTX(GetCabinetInfo(m_NextCabinet,&cabinfo));
m_nNextIndex =cabinfo.m_nIndex;
m_nContinueIndex =-1;
// Some internal initializations
m_nLastFileStartCabinetIndex =-1;
m_nLastFileEndCabinetIndex =-1;
m_bLastFileSkipped =FALSE;
m_bCabinetSetFinished =FALSE;
m_bNextCabinetReady =FALSE;
// Extract files in this cabinet and any file that starts
// in this cabinet but spans across cabinet boundaries
// This might result in more than one cabinet file 2 be processed
bResult =FDICopy(m_hContext,
sz_cabinet_name,
sz_cabinet_path,
0,
NotifyProgressProc(),
NULL,
this);
if(!bContinuous)
// Extraction ends after one cabinet (and all cabinets
// linked 2 this one by files spanning across cabinet boundaries)
break;
if(bResult)
{
// Check if we already processed all cabinets in this set
// Also check that there was no file extracted from the last cabinet
// Otherwise, we might get here when we just finished extracting the last
// chunk of a file spanning across cabinet boundaries, having its
// last chunk in the last cabinet, but the last cabinet also contains other files
// and these won't get extracted if we stop now
if(m_bCabinetSetFinished && (m_nLastFileStartCabinetIndex == m_nLastFileEndCabinetIndex))
// Yeah, we processed them all
break;
// Advancing 2 the next one
// Here we should figure out which is the cabinet we should continue with
if(m_bLastFileSkipped)
{
// The last file in this cabinet was skipped
// We should continue with the next cabinet
ASSERTX(!m_bCabinetSetFinished);
m_ContinueCabinet =m_NextCabinet;
m_strContinueDisk =m_strNextDisk;
m_nContinueIndex =m_nNextIndex;
}
// Check if any file extracted from this cabinet
if((m_nLastFileStartCabinetIndex == -1) && (m_nLastFileEndCabinetIndex == -1))
{
// No files extracted, probably because this cabinet only
// contains a chunk of a file spanning multiple cabinets
// which is being skipped
m_ContinueCabinet =m_NextCabinet;
m_strContinueDisk =m_strNextDisk;
m_nContinueIndex =m_nNextIndex;
}
m_CabinetPath =m_ContinueCabinet;
m_CabinetPath.GetNameExtension(m_strCabinetName);
m_CabinetPath.SetNameExtension(_T(""));
m_bNextCabinetReady =FALSE;
}
}
return bResult;
}
#endif
#ifdef __CAB_EXTRACT__
//---------------------------------------------------------------------------
// Pre : nID is the ID of cabinet set
// lpcszCabPath is cabinet path
// lpcszCabName is next cabinet's name (might be empty)
// lpcszDiskName is next disk's name (might be empty)
// nCabIndex is 0-based index of cabinet being processed
// Post : Return FALSE 2 abort
// Globals :
// I/O :
// Task : Simple notification that the decompression interface wants info
// about the next cabinet
// If overridden by clients, they should also call this
//---------------------------------------------------------------------------
BOOL CCabinetExtractor::NotifyCabinetInfo(USHORT nID, LPCTSTR lpcszCabPath, LPCTSTR lpcszCabName, LPCTSTR lpcszDiskName, USHORT nCabIndex)
{
#ifdef __TRACE_CAB_EXTRACTION__
TRACEFN(_T("CCabinetExtractor::NotifyCabinetInfo(%u,%s,%s,%s,%u)\n"),nID,lpcszCabPath,lpcszCabName,lpcszDiskName,nCabIndex);
#endif
// Some additional check, this should be an empty
// string if this is the last cabinet in the set
if(!STRLEN(lpcszDiskName))
m_bCabinetSetFinished =TRUE;
m_ContinueCabinet =m_NextCabinet;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -