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

📄 cabinet.cpp

📁 cabinet file (.CAB) file handlig.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// 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 + -