#include "Package.h" //////////////////////////////////////////////////////////////////////////////// //函数名:CPackage 构造函数 //功能:初始化 //入口参数: 无 //出口参数:无 //////////////////////////////////////////////////////////////////////////////// CPackage::CPackage() : m_pPackFile(NULL), m_nCurrDataPos(SIZE_PACK_HEAD), m_bModified(false), m_spPackageFileSystem(NULL) { } //////////////////////////////////////////////////////////////////////////////// //函数名:~CPackage 析构函数 //功能:清理 //入口参数: 无 //出口参数:无 //////////////////////////////////////////////////////////////////////////////// CPackage::~CPackage() { ClosePackage(); if ( m_pPackFile!= NULL ) { fclose(m_pPackFile); m_pPackFile = NULL; } m_spPackageFileSystem = NULL; m_bModified = false; m_mapEncryptInfo.clear(); MESSAGE_PRINT("Package destroyed!"); } //////////////////////////////////////////////////////////////////////////////// //函数名:OpenPackage //功能:打开包 //入口参数: string strPackName 包文件绝对路径 // EPackOpenType eOpenType 打开模式,默认为EO_READ // bool bLoadFileSystem 是否载入包系统信息,默认为 是 //出口参数: bool 打开成功返回 true, 失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackage::OpenPackage( string strPackName, EPackOpenType eOpenType,bool bLoadFileSystem ) { if (strPackName.empty()) { ERROR_PRINT("包路径为空:PACKAGE.CPP-OpenPackage",strPackName.c_str()); } m_strPackagePath = strPackName; switch( eOpenType ) { // 只读方式 case EO_READ: m_bModified = false; return _ReadOpen( strPackName,bLoadFileSystem ); // 读写方式 case EO_WRITE: m_bModified = true; return _WriteOpenPackage( strPackName ); default: return false; } return false; } //////////////////////////////////////////////////////////////////////////////// //函数名:ClosePackage //功能:关闭包 //入口参数: 无 //出口参数: 无 //////////////////////////////////////////////////////////////////////////////// bool CPackage::ClosePackage() { // 当包发生改动且包文件合法则重写包头和包系统信息 bool bSuccess = true; if ( (m_pPackFile != NULL ) && m_bModified ) { // 重写包头版本信息 fseek( m_pPackFile,sizeof(UINT),SEEK_SET); if ( fwrite( &m_packageHeader.nVersion, sizeof(UINT),1, m_pPackFile ) != 1 ) { ERROR_PRINT("写入包头版本号错误:PACKAGE.CPP-ClosePackage",NULL); bSuccess = false; } // 重写内容版本信息 if ( fwrite(&m_packageHeader.nContentVersion, sizeof(FILETIME), 1, m_pPackFile) != 1 ) { ERROR_PRINT("写入包头内容版本号错误:PACKAGE.CPP-ClosePackage",NULL); bSuccess = false; } // 重写包尾信息 if ( m_spPackageFileSystem ) { if ( m_spPackageFileSystem->SavePackFileSystemInfo( m_pPackFile,m_nCurrDataPos,m_packageHeader.nContentVersion ) == 0 ) { ERROR_PRINT("关闭包,重写文件信息出错:PACKAGE.CPP-ClosePackage",NULL); bSuccess = false; } } } if (m_pPackFile) { fclose( m_pPackFile ); m_pPackFile = NULL; } m_mapEncryptInfo.clear(); return bSuccess; } bool CPackage::ReopenPackageFile() { if ( !m_pPackFile ) { _ReadOpen( m_strPackagePath, false ); } return true; } void CPackage::ClosePackageFile() { if ( m_pPackFile ) { fclose( m_pPackFile ); m_pPackFile = NULL; } } //////////////////////////////////////////////////////////////////////////////// //函数名:LoadPackageFileSystem //功能:载入包系统信息 //入口参数: 无 //出口参数: bool 打开成功返回 true, 失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackage::_LoadPackageFileSystem() { if ( NULL == m_pPackFile ) { ERROR_PRINT( "包文件未打开:PACKAGE.CPP-_LoadPackageFileSystem" ,NULL); return false; } if ( m_spPackageFileSystem == NULL ) { m_spPackageFileSystem = new CPackageFileSystem(); if ( NULL == m_spPackageFileSystem) { return false; } } if ( m_spPackageFileSystem->LoadPackFileSystem( m_pPackFile, m_packageHeader.nFileSystemInfoPos, m_bModified ) == false ) { m_spPackageFileSystem = NULL; return false; } m_nCurrDataPos = m_spPackageFileSystem->GetPackageDataEndPos(); return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:SetPackageFileSystem //功能:设置包系统信息 //入口参数: CPackageFileSystem* kPackageFileSystem 源包系统信息 //出口参数: 无 //////////////////////////////////////////////////////////////////////////////// bool CPackage::SetPackageFileSystem(CPackageFileSystemPtr spPackageFileSystem ) { // 仅当包未载入系统信息时设置包系统信息 if (NULL == spPackageFileSystem) { ERROR_PRINT("传入系统描述为空失败:PACKAGE.CPP-SetPackageFileSystem",NULL); return false; } if ( !m_spPackageFileSystem ) { m_spPackageFileSystem = spPackageFileSystem; m_nCurrDataPos = m_spPackageFileSystem->GetPackageDataEndPos(); } else { ERROR_PRINT("包已初始化系统信息,不可设置:PACKAGE.CPP-SetPackageFileSystem",NULL); return false; } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:SetPackageRootDir //功能:设置包的根目录路径(相对路径) //入口参数: string strRootDir 路径名 //出口参数: 无 //////////////////////////////////////////////////////////////////////////////// bool CPackage::SetPackageRootDir(string strRootDir) { if (m_bModified == false) { ERROR_PRINT("包为只读模式,不可设置根目录:PACKAGE.CPP-SetPackageRootDir",NULL); return false; } if (strRootDir.empty()) { ERROR_PRINT("路径名为空:PACKAGE.CPP-SetPackageRootDir",NULL); return false; } StringLower( strRootDir ); if ( m_spPackageFileSystem ) { return m_spPackageFileSystem->SetPackageRootDir(strRootDir ); } else { return false; } } //////////////////////////////////////////////////////////////////////////////// //函数名:GetPackageRootDir //功能:设置包的根目录路径(相对路径) //入口参数: 无 //出口参数: string 路径名 //////////////////////////////////////////////////////////////////////////////// string CPackage::GetPackageRootDir() const { if (m_spPackageFileSystem) { return m_spPackageFileSystem->GetPackageRootDir(); } return ""; } //////////////////////////////////////////////////////////////////////////////// //函数名:AddFile //功能:向包中添加文件 //入口参数: string strFileName 文件全路径+文件名(相对路径) // EEncryptType eEncryptType 文件加密类型 // const BYTE* pBuffer 指向文件数据的指针 // UINT nBufferSize 数据大小 // bool bDirect 是否直接插入包,默认为 否 // 设置为ture 则不进行加密、压缩等处理直接将数据加入包,主要用于从已有包向当前包添加数据 // 设置为false 则会按照文件加密及压缩类型标志对数据首先进行处理再加入包中 //出口参数: bool 成功则返回ture,失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackage::_AddFile( string strFileName, EEncryptType eEncryptType, const BYTE* pBuffer, UINT nBufferSize, bool bDirect ) { if (strFileName.empty()) { ERROR_PRINT("文件名为空,添加文件失败:PACKAGE.CPP-AddFile",strFileName.c_str()); return false; } if (m_bModified == false) { ERROR_PRINT("包为只读模式,不可添加文件:PACKAGE.CPP-AddFilee",strFileName.c_str()); return false; } StringLower(strFileName); if (NULL == pBuffer) { ERROR_PRINT("文件数据为空,不能添加文件:PACKAGE.CPP-AddFile",strFileName.c_str()); return false; } if (m_spPackageFileSystem == NULL) { ERROR_PRINT("包系统未初始化,不可添加文件:PACKAGE.CPP-AddFile",strFileName.c_str()); return false; } // 创建文件描述信息 SPackageFileInfo sFileInfo; if (!_CreateFileInfo( sFileInfo, strFileName,eEncryptType,GetFileType(strFileName),nBufferSize, m_nCurrDataPos )) { ERROR_PRINT("创建文件信息描述失败:PACKAGE.CPP-AddFile",strFileName.c_str()); return false; } return AddFile( sFileInfo,pBuffer, bDirect); } //////////////////////////////////////////////////////////////////////////////// //函数名:AddFile 重载 //功能:向包中添加文件 //入口参数: SPackageFileInfo& pFileInfo 文件信息描述 // UINT nBufferSize 数据大小 // bool bDirect 是否直接插入包,默认为 否 // 设置为ture 则不进行加密、压缩等处理直接将数据加入包,主要用于从已有包向当前包添加数据 // 设置为false 则会按照文件加密及压缩类型标志对数据首先进行处理再加入包中 //出口参数: bool 成功则返回ture,失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackage::AddFile( SPackageFileInfo& sFileInfo,const BYTE* pBuffer, bool bDirect ) { if (m_bModified == false) { ERROR_PRINT("包为只读模式,不可添加文件:PACKAGE.CPP-AddFile",sFileInfo.szFullPathName.c_str()); return false; } bool bSuccess = true; StringLower(sFileInfo.szFilename); StringLower(sFileInfo.szFullPathName); string strFileName = sFileInfo.szFullPathName; if (NULL == pBuffer) { ERROR_PRINT("文件数据为空!不能添加文件:PACKAGE.CPP-AddFile",strFileName.c_str()); return false; } if (NULL == m_spPackageFileSystem) { ERROR_PRINT("包系统未初始化,不可添加文件:PACKAGE.CPP-AddFile",strFileName.c_str()); return false; } if ( m_spPackageFileSystem->GetPackFileInfo( strFileName ) != NULL ) { // 文件已存在,首先删除再重新添加 DeletePackFile( strFileName ); } // 从包到包的数据插入或创建差异包 if ( bDirect == true ) { // 写入文件到包,同时更新对应文件描述的nPos信息 if(!_AddFileData( pBuffer,sFileInfo )) { ERROR_PRINT("直接插入数据失败:PACKAGE.CPP-AddFile",strFileName.c_str()); bSuccess = false; } } // 从文件向包添加数据 else { BYTE* pAddBuffer = new BYTE[sFileInfo.nFileOrgSize]; if ( NULL == pAddBuffer ) { ERROR_PRINT("申请内存失败:PACKAGE.CPP-AddFile",strFileName.c_str()); return false; } // bug fix 解决小文件忘记拷贝数据的bug [8/7/2009 hemeng] if ( memcpy_s(pAddBuffer,sFileInfo.nFileOrgSize, pBuffer,sFileInfo.nFileOrgSize ) ) { bSuccess = false; } // 首先进行加密 if ( sFileInfo.eEncryptType == ET_HEADER || sFileInfo.eEncryptType == ET_ZIP_HEADER ) { // 仅当文件大于等于最小加密大小时加密 if ( sFileInfo.nFileOrgSize >= ENCRYPT_PACK_LENGTH ) { if ( !EncryptBuffer( pBuffer,ENCRYPT_PACK_LENGTH,pAddBuffer,ENCRYPT_PACK_LENGTH ) ) { ERROR_PRINT("加密数据失败:PACKAGE.CPP-AddFile",strFileName.c_str()); bSuccess = false; } } } ////////////////////////////////////////////////////////////////////////// // 进行压缩 if ( bSuccess ) { if ( sFileInfo.eEncryptType == ET_ZIP || sFileInfo.eEncryptType == ET_ZIP_HEADER ) { // 仅当文件原始大于ZIP_BLOCK_SIZE进行压缩 if ( sFileInfo.nFileOrgSize > ZIP_BLOCK_SIZE ) { BYTE* pZipBuffer = new BYTE[sFileInfo.nFileOrgSize]; if ( NULL == pZipBuffer ) { ERROR_PRINT("申请内存失败:PACKAGE.CPP-AddFile",strFileName.c_str()); delete [] pAddBuffer; pAddBuffer = NULL; return false; } UINT nZipSize = ZipBuffer( pAddBuffer,sFileInfo.nFileOrgSize,pZipBuffer,sFileInfo.nFileOrgSize); if ( nZipSize != 0 ) { sFileInfo.nFileSize = nZipSize; if ( memcpy_s(pAddBuffer,sFileInfo.nFileSize,pZipBuffer,nZipSize) ) { ERROR_PRINT("拷贝压缩数据出错:PACKAGE.CPP-AddFile",strFileName.c_str()); delete [] pZipBuffer; pZipBuffer = NULL; bSuccess = false; } } else { sFileInfo.nFileSize = sFileInfo.nFileOrgSize; // 压缩失败则不压缩 [8/19/2009 hemeng] if (sFileInfo.eEncryptType == ET_ZIP_HEADER) { sFileInfo.eEncryptType = ET_HEADER; } else { sFileInfo.eEncryptType = ET_NONE; } } delete [] pZipBuffer; pZipBuffer = NULL; } } } // 添加数据到包 // 写入文件到包,同时更新对应文件描述的nPos信息 if ( bSuccess ) { if ( !_AddFileData( pAddBuffer,sFileInfo ) ) { ERROR_PRINT("写入包数据信息失败!" ,strFileName.c_str()); delete [] pAddBuffer; pAddBuffer = NULL; bSuccess = false; } } delete [] pAddBuffer; pAddBuffer = NULL; } if ( bSuccess ) { bSuccess = m_spPackageFileSystem->AddFileInfo( strFileName,sFileInfo ); } // 写入文件描述信息到包 return bSuccess; } //////////////////////////////////////////////////////////////////////////////// //函数名:AddFile 重载 //功能:向包中添加指定路径的文件 //入口参数: string strFileName 插入文件的绝对路径+文件名 // ,string strDirPath 目录 //出口参数: bool 成功则返回ture,失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackage::AddFile( string strFileName,string strDirPath ) { if (strFileName.empty()) { ERROR_PRINT("文件名为空,不可添加:PACKAGE.CPP-AddFile",strFileName.c_str()); return false; } if (m_bModified == false) { ERROR_PRINT("包为只读模式,不可添加:PACKAGE.CPP-AddFile",strFileName.c_str()); return false; } if ( m_spPackageFileSystem == NULL ) { ERROR_PRINT("包系统未初始化,不可添加文件!",strFileName.c_str()); return false; } // 获得文件大小 UINT nBufferSize = GetBufferSize( strFileName ); if ( nBufferSize == -1 ) { ERROR_PRINT("文件大小错误:PACKAGE.CPP-AddFile",strFileName.c_str()); return false; } // 如果是0KB的文件则部打包 [8/6/2009 hemeng] if ( nBufferSize == 0) { return true; } BYTE* pBuffer = new BYTE[nBufferSize]; if ( NULL == pBuffer ) { ERROR_PRINT("申请内存失败:PACKAGE.CPP-AddFile",strFileName.c_str()); return false; } if ( !ReadFileToBuffer( pBuffer,nBufferSize,strFileName.c_str() ) ) { delete [] pBuffer; pBuffer = NULL; return false; } strFileName = _GetRelativePath(strDirPath.c_str(),strFileName.c_str()); EFileType eFileType = GetFileType(strFileName); EEncryptType eEncrypType = _GetFileEncryptType( strFileName, nBufferSize ); if ( !_AddFile( strFileName,eEncrypType,pBuffer,nBufferSize ) ) { ERROR_PRINT("添加文件失败:PACKAGE.CPP-AddFile",strFileName.c_str()); delete [] pBuffer; pBuffer = NULL; return false; } // 清理临时空间 if ( pBuffer ) { delete [] pBuffer; pBuffer = NULL; } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:AddDirFiles //功能:添加指定文件夹所有文件到包 //入口参数: string strDirPath 文件夹绝对路径 //出口参数: bool 成功则返回ture,失败返回 false //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackage::AddDirFiles( string strDirPath ) { if (strDirPath.empty()) { ERROR_PRINT("目录路径为空:PACKAGE.CPP-AddDirFiles",NULL); return false; } if (m_bModified == false) { ERROR_PRINT("包为只读模式,不可添加文件:PACKAGE.CPP-AddDirFiles",NULL); return false; } if ( m_spPackageFileSystem == NULL ) { ERROR_PRINT("包系统未初始化,不可添加文件:PACKAGE.CPP-AddDirFiles",NULL); return false; } vector vFiles; if (!FindAllFiles( strDirPath, vFiles )) { ERROR_PRINT("查找目录下文件出错:PACKAGE.CPP-AddDirFiles",NULL); return false; } /*UINT nFileNum = (UINT)vFiles.size(); for ( UINT uiIndex = 0; uiIndex < nFileNum; uiIndex++ ) { string strPackRootDir = m_spPackageFileSystem->GetPackageRootDir(); string strPath = vFiles[uiIndex]; StringLower(strPath); size_t it = strPath.find( strPackRootDir ); if ( it != string::npos ) { if ( !AddFile( strPath,strDirPath ) ) { ERROR_PRINT("添加目录文件出错:PACKAGE.CPP-AddDirFiles",strPath.c_str()); continue; } } else { ERROR_PRINT("文件不属于当前包根目录!不能添加:PACKAGE.CPP-AddDirFiles",strPath.c_str()); vFiles.clear(); return false; } }*/ while (vFiles.size() > 0) { string strPackRootDir = m_spPackageFileSystem->GetPackageRootDir(); string strPath = vFiles[0]; vFiles.erase(vFiles.begin()); StringLower(strPath); string::size_type sz = strPath.find(strPackRootDir); if ( sz != string::npos) { if ( !AddFile( strPath,strDirPath ) ) { ERROR_PRINT("添加目录文件出错:PACKAGE.CPP-AddDirFiles",strPath.c_str()); continue; } } else { ERROR_PRINT("文件不属于当前包根目录!不能添加:PACKAGE.CPP-AddDirFiles",strPath.c_str()); vFiles.clear(); return false; } } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:DeletePackFile //功能:从包中删除指定文件 //入口参数: string strFileName 删除文件全路径(相对路径)+文件名 //出口参数: 无 //////////////////////////////////////////////////////////////////////////////// bool CPackage::DeletePackFile( string strFileName ) { if (strFileName.empty()) { ERROR_PRINT("文件名为空:PACKAGE.CPP-DeletePackFile",strFileName.c_str()); return false; } if (m_bModified == false) { ERROR_PRINT("包为只读模式,不可删除文件:PACKAGE.CPP-DeletePackFile",strFileName.c_str()); return false; } if ( m_spPackageFileSystem == NULL ) { ERROR_PRINT("包系统未初始化,不可添加文件:PACKAGE.CPP-DeletePackFile",strFileName.c_str()); return false; } StringLower(strFileName); // 找到文件描述 SPackageFileInfo* pFileInfo = m_spPackageFileSystem->GetPackFileInfo( strFileName ); if ( pFileInfo == NULL ) { MESSAGE_PRINT("文件不存在,不可删除:PACKAGE.CPP-DeletePackFile"); return false; } // 标志文件被删除 return m_spPackageFileSystem->DeleteFileInfo( strFileName ); } //////////////////////////////////////////////////////////////////////////////// //函数名:AddFileFromPackage 重载 //功能:从已有包向包中添加文件 //入口参数: string strPackageFileName 源包文件路径 //出口参数: bool 成功则返回true,失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackage::AddFileFromPackage( string strPackageFileName ) { if (strPackageFileName.empty()) { ERROR_PRINT("源包文件名不能为空:PACKAGE.CPP-AddFileFromPackage",NULL); return false; } if (m_bModified == false) { ERROR_PRINT("包为只读模式,不可添加文件:PACKAGE.CPP-AddFileFromPackage",strPackageFileName.c_str()); return false; } if ( m_spPackageFileSystem == NULL ) { ERROR_PRINT("包系统未初始化,不可添加文件:PACKAGE.CPP-AddFileFromPackage",strPackageFileName.c_str()); return false; } if ( !m_pPackFile ) { ERROR_PRINT("本地数据包未打开,不可更新:PACKAGE.CPP-AddFileFromPackage ",strPackageFileName.c_str()); return false; } CPackage* pNewPack = new CPackage(); if ( NULL == pNewPack ) { ERROR_PRINT("申请新包内存失败:PACKAGE.CPP-AddFileFromPackage",strPackageFileName.c_str()); return false; } if ( !pNewPack->OpenPackage( strPackageFileName ) ) { ERROR_PRINT("打开更新包失败:PACKAGE.CPP-AddFileFromPackage ",strPackageFileName.c_str()); delete pNewPack; return false; } if (!AddFileFromPackage( pNewPack )) { delete pNewPack; pNewPack = NULL; ERROR_PRINT("添加更新包失败:PACKAGE.CPP-AddFileFromPackage ",strPackageFileName.c_str()); return false; } delete pNewPack; pNewPack = NULL; return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:AddFileFromPackage //功能:从已有包向包中添加文件 //入口参数: CPackage* pPackage 源包文件流指针 //出口参数: bool 成功则返回true,失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackage::AddFileFromPackage( CPackage* pNewPackage ) { if (m_bModified == false) { ERROR_PRINT("包为只读模式,不可添加文件:PACKAGE.CPP-AddFileFromPackage",NULL); return false; } if ( !pNewPackage || !m_pPackFile ) { ERROR_PRINT("当前包或插入包未打开:PACKAGE.CPP-AddFileFromPackage",NULL); return false; } if ( m_spPackageFileSystem == NULL ) { ERROR_PRINT("包系统未初始化,不可添加文件:PACKAGE.CPP-AddFileFromPackage",NULL); return false; } CPackageFileSystemPtr pNewPackSystem = pNewPackage->GetPackageFileSystem(); if ( pNewPackSystem == NULL ) { ERROR_PRINT("插入包系统未初始化:PACKAGE.CPP-AddFileFromPackage",NULL); return false; } vector vInsertFileInfos; pNewPackSystem->GetAllFilesInfo(vInsertFileInfos); for ( UINT uiIndex = 0; uiIndex < vInsertFileInfos.size(); uiIndex++ ) { UINT nBufferSize = vInsertFileInfos[uiIndex].nFileSize; BYTE* pBuffer = new BYTE[nBufferSize]; if ( NULL == pBuffer ) { ERROR_PRINT("申请内存失败:PACKAGE.CPP-AddFileFromPackage",NULL); return false; } // 获得文件读取指针 CPackageFileReader* pNewPackReader = new CPackageFileReader(pNewPackage,&vInsertFileInfos[uiIndex]); if (NULL == pNewPackReader) { delete [] pBuffer; pBuffer = NULL; return false; } // 读取文件 if ( !pNewPackReader->ReadUnZipBuffer( pBuffer/*,&vDiffFileInfos[uiIndex]*/ ) ) { ERROR_PRINT("读取差异包数据出错:PACKAGE.CPP-AddFileFromPackage",vInsertFileInfos[uiIndex].szFullPathName.c_str()); delete [] pBuffer; pBuffer = NULL; delete pNewPackReader; pNewPackReader = NULL; return false; } if ( !AddFile( vInsertFileInfos[uiIndex],pBuffer,true ) ) { delete [] pBuffer; pBuffer = NULL; delete pNewPackReader; pNewPackReader = NULL; return false; } delete pNewPackReader; pNewPackReader = NULL; delete [] pBuffer; pBuffer = NULL; } vInsertFileInfos.clear(); // 更新包版本信息 m_packageHeader.nVersion = pNewPackage->GetPackCodeVersion(); return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:Deflate //功能:紧缩模式,删除包碎片空间 //入口参数: 无 //出口参数: bool 成功则返回true,失败返回 false //说明:紧缩模式无论再只读或读写模式下都可进行 //////////////////////////////////////////////////////////////////////////////// bool CPackage::Deflate() { if ( !m_pPackFile ) { return false; } if (!m_bModified) { ERROR_PRINT("包以只读模式打开,不可修改:PACKAGE.CPP-Deflate",NULL); return false; } if ( m_spPackageFileSystem == NULL ) { ERROR_PRINT("包系统未初始化,不可添加文件:PACKAGE.CPP-Deflate",NULL); return false; } MESSAGE_PRINT("将关闭包,执行紧缩模式优化:PACKAGE.CPP-Deflate"); // 紧缩模式后文件的大小 if ( !m_spPackageFileSystem->Deflate( m_pPackFile ) ) { ERROR_PRINT("紧缩模式:紧缩程序出错:PACKAGE.CPP-Deflate",NULL); return false; } // 更新文件数据结尾位置 m_nCurrDataPos = m_spPackageFileSystem->GetPackageDataEndPos(); // 重写包文件系统信息 UINT nPackSize = m_spPackageFileSystem->SavePackFileSystemInfo(m_pPackFile,m_nCurrDataPos,m_packageHeader.nContentVersion); if ( nPackSize == 0 ) { ERROR_PRINT("紧缩模式:重写文件系统出错:PACKAGE.CPP-Deflate",NULL); return false; } // 删除包尾多余空间 if ( _chsize_s( _fileno(m_pPackFile),nPackSize) ) { ERROR_PRINT("紧缩模式:删除文件多余空间出错:PACKAGE.CPP-Deflate",NULL); return false; } MESSAGE_PRINT("紧缩OK!"); return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:GetPackageFileReader //功能:获得包读取指针 //入口参数: string strFileName 读取文件全路径(相对路径)+文件名 //出口参数: CPackageFileReader* 指定文件读取指针 //////////////////////////////////////////////////////////////////////////////// CPackageFileReader* CPackage::GetPackageFileReader( string strFileName ) { if (strFileName.empty()) { ERROR_PRINT("文件名不能为空:PACKAGE.CPP-GetPackageFileReader",NULL); return NULL; } if ( m_spPackageFileSystem == NULL ) { ERROR_PRINT("包系统未初始化,不可添加文件:PACKAGE.CPP-GetPackageFileReader",strFileName.c_str()); return NULL; } SPackageFileInfo* pFileInfo = m_spPackageFileSystem->GetPackFileInfo( strFileName ); if ( pFileInfo == NULL ) { ERROR_PRINT( "所读文件不存在,获得读取指针失败:PACKAGE.CPP-GetPackageFileReader" , strFileName.c_str()); return NULL; } CPackageFileReader* pPackageFileReader = new CPackageFileReader( this,pFileInfo ); if ( NULL == pPackageFileReader ) { ERROR_PRINT("申请读取内存失败:PACKAGE.CPP-GetPackageFileReader", strFileName.c_str()); return NULL; } return pPackageFileReader; } bool CPackage::Verify(FILE* pPackFile) { fseek(m_pPackFile, 0,SEEK_SET); UINT nType; UINT nCodeVersion; if ( fread(&nType, sizeof(UINT), 1, pPackFile) != 1 ) { ERROR_PRINT("读取包头数据错误:PACKAGE.CPP-Verify",NULL); return false; } if ( nType != 0x504B /*letter PK*/ ) { #ifdef _DEBUG MessageBox(NULL,"打开文件不是包文件!","Error",MB_OK); #else ERROR_PRINT("打开文件不是包文件:PACKAGE.CPP-Verify",NULL); #endif return false; } if ( fread(&nCodeVersion, sizeof(UINT), 1, pPackFile) != 1) { ERROR_PRINT("读取包头数据错误:PACKAGE.CPP-Verify",NULL); return false; } if ( nCodeVersion != CURRENT_CODE_VERSION ) { #ifdef _DEBUG MessageBox(NULL,"包文件代码版本不符!","Error",MB_OK); #else ERROR_PRINT("包文件代码版本不符:PACKAGE.CPP-Verify",NULL); #endif return false; } return true; } bool CPackage::SpecialOpen(string strPackName,char* pConfigFileBuffer) { if (strPackName.empty()) { ERROR_PRINT("文件名不能为空:PACKAGE.CPP-SpecialOpen",NULL); return false; } m_strPackagePath = strPackName; if (NULL == pConfigFileBuffer) { ERROR_PRINT("配置文件BUFFER不能为空:PACKAGE.CPP-SpecialOpen",NULL); return false; } m_bModified = true; if (_LoadConfigFile(pConfigFileBuffer,m_mapEncryptInfo) == false) { ERROR_PRINT("读取配置文件失败:PACKAGE.CPP-LoadPackFileSystem",NULL); return false; } // 检查包是否可读写 if ( fopen_s( &m_pPackFile, strPackName.c_str(), "rb+") ) { // 新建一个包,包内容根目录为 包路径+报名命名目录 if ( fopen_s( &m_pPackFile,strPackName.c_str(), "wb+" ) ) { return false; } string strRootDir = strPackName.substr( strPackName.find_last_of("\\") + 1); strRootDir = strRootDir.substr(0,strRootDir.find_last_of(".")); _CreatePackage( strRootDir ); } if ( Verify(m_pPackFile) == false) { ERROR_PRINT("包文件不合法:PACKAGE.CPP-_WriteOpenPackage",strPackName.c_str()); return false; } // 读取文件头 if ( !_LoadPackageHeader() ) { ERROR_PRINT("文件头读取失败:PACKAGE.CPP-_WriteOpenPackage",strPackName.c_str()); return false; } if ( !_LoadPackageFileSystem() ) { ERROR_PRINT("文件系统读取失败:PACKAGE.CPP-_WriteOpenPackage",strPackName.c_str()); return false; } m_nCurrDataPos = m_spPackageFileSystem->GetPackageDataEndPos(); return true; } //private function-------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// //函数名:_WriteOpenPackage //功能:读写模式打开包 //入口参数:string strPackagePath 包文件绝对路径 //出口参数:bool 成功则返回true,失败返回 false //说明: 读写模式打开包,打开同时载入包系统信息,如果为新建包在创建包系统信息 //////////////////////////////////////////////////////////////////////////////// bool CPackage::_WriteOpenPackage( string strPackagePath ) { if (strPackagePath.empty()) { ERROR_PRINT("文件名不能为空:PACKAGE.CPP-_WriteOpenPackage",NULL); return false; } string strConfigFilePath = _GetCurrWorkDir(); if (strConfigFilePath.empty()) { return false; } strConfigFilePath += CONFIG_FILE_NAME; if (_LoadConfigFile(strConfigFilePath,m_mapEncryptInfo) == false) { ERROR_PRINT("读取配置文件失败:PACKAGE.CPP-LoadPackFileSystem",NULL); return false; } // 检查包是否可读写 if ( fopen_s( &m_pPackFile, strPackagePath.c_str(), "rb+") ) { // 新建一个包,包内容根目录为 包路径+报名命名目录 if ( fopen_s( &m_pPackFile,strPackagePath.c_str(), "wb+" ) ) { return false; } string strRootDir = strPackagePath.substr( strPackagePath.find_last_of("\\") + 1); strRootDir = strRootDir.substr(0,strRootDir.find_last_of(".")); _CreatePackage( strRootDir ); } if ( Verify(m_pPackFile) == false) { ERROR_PRINT("包文件不合法:PACKAGE.CPP-_WriteOpenPackage",strPackagePath.c_str()); return false; } // 读取文件头 if ( !_LoadPackageHeader() ) { ERROR_PRINT("文件头读取失败:PACKAGE.CPP-_WriteOpenPackage",strPackagePath.c_str()); return false; } if ( !_LoadPackageFileSystem() ) { ERROR_PRINT("文件系统读取失败:PACKAGE.CPP-_WriteOpenPackage",strPackagePath.c_str()); return false; } m_nCurrDataPos = m_spPackageFileSystem->GetPackageDataEndPos(); return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:_ReadOpen //功能:只读模式打开包 //入口参数: string strPackagePath 包文件绝对路径 // bool bLoadFileSystem 是否打开包同时载入包系统信息 //出口参数:bool 成功则返回true,失败返回 false //说明: 如果设置打开包同时不载入系统信息,则在使用包前务必使用 // SetPackageFileSystem函数设置包系统信息再使用 //////////////////////////////////////////////////////////////////////////////// bool CPackage::_ReadOpen( string strPackagePath, bool bLoadFileSystem ) { if (strPackagePath.empty()) { ERROR_PRINT("包名不能为空:PACKAGE.CPP-_ReadOpen",NULL); return false; } // 检查包是否存在 // 以共享模式打开包,不允许写文件 if ( fopen_s( &m_pPackFile,strPackagePath.c_str(),"rb") ) { //不存在则返回 ERROR_PRINT("包不存在,不可读:PACKAGE.CPP-_ReadOpen",strPackagePath.c_str()); return false; } if ( Verify(m_pPackFile) == false) { ERROR_PRINT("包文件不合法:PACKAGE.CPP-_ReadOpen",strPackagePath.c_str()); return false; } StringLower( strPackagePath ); // 读取文件头 if ( !_LoadPackageHeader() ) { ERROR_PRINT("文件头读取失败:PACKAGE.CPP-_ReadOpen",strPackagePath.c_str()); return false; } // 载入包文件系统,如果bLoadFileSystem为false,则应在读取包数据前设置包文件系统 if ( bLoadFileSystem ) { if ( !_LoadPackageFileSystem() ) { ERROR_PRINT("文件系统读取失败:PACKAGE.CPP-_ReadOpen",strPackagePath.c_str()); return false; } } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:_CreatePackage //功能:创建一个空包 //入口参数: string strRootDir 包根目录 //出口参数: bool 成功则返回true,失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackage::_CreatePackage(string strRootDir) { if (strRootDir.empty()) { ERROR_PRINT("路径名不能为空:PACKAGE.CPP-_CreatePackage",NULL); return false; } StringLower( strRootDir ); if ( m_spPackageFileSystem == NULL ) { m_spPackageFileSystem = new CPackageFileSystem(true); if ( NULL == m_spPackageFileSystem ) { ERROR_PRINT("申请系统信息内存失败:PACKAGE.CPP-_CreatePackage",NULL); return false; } } m_spPackageFileSystem->SetPackageRootDir( strRootDir ); _CreatePackageHeaderFile(); if ( !m_pPackFile ) { ERROR_PRINT("包文件未打开:PACKAGE.CPP-_CreatePackage",NULL); return false; } if ( fwrite( &m_packageHeader.nType, SIZE_PACK_HEAD, 1, m_pPackFile ) != 1 ) { ERROR_PRINT("写入包头信息出错:PACKAGE.CPP-_CreatePackage",NULL); return false; } // 生成一个仅存有包头信息的文件 if ( m_spPackageFileSystem->SavePackFileSystemInfo( m_pPackFile,m_packageHeader.nFileSystemInfoPos,m_packageHeader.nContentVersion ) == 0 ) { ERROR_PRINT("写入包系统信息出错 PACKAGE.CPP",NULL); return false; } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:_LoadPackageHeader //功能:从包文件载入包头信息 //入口参数: 无 //出口参数: bool 成功则返回true,失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackage::_LoadPackageHeader() { if ( !m_pPackFile ) { ERROR_PRINT("包文件未打开:PACKAGE.CPP-_LoadPackageHeader",NULL); return false; } fseek(m_pPackFile, 0,SEEK_SET); // 读入包头信息 if ( fread( &m_packageHeader.nType, SIZE_PACK_HEAD,1,m_pPackFile) != 1 ) { ERROR_PRINT("读取包头数据错误:PACKAGE.CPP-_LoadPackageHeader",NULL); return false; } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:_CreatePackageHeaderFile //功能:为当前包创建一个空包头 //入口参数: 无 //出口参数: 无 //////////////////////////////////////////////////////////////////////////////// void CPackage::_CreatePackageHeaderFile() { m_packageHeader.nType = 0x504B; //letter PK m_packageHeader.nVersion = CURRENT_CODE_VERSION; SYSTEMTIME nCurrentTime; FILETIME nFileTime; GetLocalTime(&nCurrentTime); SystemTimeToFileTime(&nCurrentTime, &nFileTime); m_packageHeader.nContentVersion = nFileTime; m_packageHeader.nFileSystemInfoPos = SIZE_PACK_HEAD; // 头结构大小 MESSAGE_PRINT("新建包头OK"); } //////////////////////////////////////////////////////////////////////////////// //函数名:_CreateFileInfo //功能:创建文件信息描述 //入口参数: SPackageFileInfo& sFileInfo 目标文件信息描述的引用 // string strFileName 文件全路径(相对路径+文件名) // EEncryptType eEncryptType 文件加密类型 // EFileType eFileType 文件类型 // UINT nBufferSize 文件数据大小 // UINT nPos 文件数据在包中的存储位置 //出口参数: bool //////////////////////////////////////////////////////////////////////////////// bool CPackage::_CreateFileInfo( SPackageFileInfo& sFileInfo,string strFileName, EEncryptType eEncryptType, EFileType eFileType,UINT nBufferSize, UINT nPos ) { if (strFileName.empty()) { ERROR_PRINT("文件名不能为空:PACKAGE.CPP-_CreateFileInfo",NULL); return false; } StringLower( strFileName ); // add CreateFileInfo code here sFileInfo.nFileSize = nBufferSize; sFileInfo.nFileOrgSize = nBufferSize; sFileInfo.eEncryptType = eEncryptType; sFileInfo.szFullPathName = strFileName/*m_pPackageFileSystem->GetRelPath( strFileName )*/; if (sFileInfo.szFullPathName.empty()) { ERROR_PRINT("获取相对路径失败:PACKAGE.CPP-_CreateFileInfo",strFileName.c_str()); return false; } sFileInfo.szFilename = strFileName.substr( strFileName.find_last_of("\\") + 1 ); sFileInfo.eFileType = eFileType; sFileInfo.nPos = nPos; return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:_AddFileData //功能:向包数据区添加数据 //入口参数: const BYTE* pFileBuffer 指向源数据的指针 // SPackageFileInfo& sPackageFileInfo 数据文件描述信息 //出口参数: bool 成功则返回true,失败返回 false //说明:如果文件已存在则会首先进行删除,然后重新添加 //////////////////////////////////////////////////////////////////////////////// bool CPackage::_AddFileData( const BYTE* pFileBuffer, SPackageFileInfo& sPackageFileInfo ) { if (m_bModified == false) { ERROR_PRINT("包为只读模式,不可添加文件:PACKAGE.CPP-_AddFileData",sPackageFileInfo.szFullPathName.c_str()); return false; } if ( !m_pPackFile ) { return false; } // 查找包中是否有可用空间 SPackageIdleSpaceInfo sIdleInfo; // 初始化碎片空间信息 sIdleInfo.nPos = m_packageHeader.nFileSystemInfoPos; sIdleInfo.nRegionSize = sPackageFileInfo.nFileSize; // 找到可用空间 // 如果有可用空间则写入可用空间 // 首先查找可用碎片空间 if ( m_spPackageFileSystem->GetIdleSpace( sPackageFileInfo.nFileSize ,sIdleInfo ,false) ) { // 将数据写入查找到的空间 fseek( m_pPackFile, sIdleInfo.nPos, SEEK_SET ); if ( fwrite( pFileBuffer,sPackageFileInfo.nFileSize, 1, m_pPackFile ) != 1 ) { ERROR_PRINT("写入数据出错:PACKAGE.CPP-_AddFileData",sPackageFileInfo.szFullPathName.c_str()); return false; } //更新当前文件信息描述 sPackageFileInfo.nPos = sIdleInfo.nPos; // 删除使用的碎片空间信息 m_spPackageFileSystem->GetIdleSpace( sPackageFileInfo.nFileSize ,sIdleInfo ,true); return true; } //如果没有可用空间则添加到数据区尾部 else { sPackageFileInfo.nPos = m_nCurrDataPos; if ( !_AppendFileDataToPackage( m_pPackFile,pFileBuffer, sPackageFileInfo.nFileSize ) ) { ERROR_PRINT("写入数据出错:附加至包数据尾出错:PACKAGE.CPP-_AddFileData",sPackageFileInfo.szFullPathName.c_str()); return false; } } /*cerr << "文件数据 " << sPackageFileInfo.szFullPathName << " 添加成功" << endl;*/ return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:_AppendFileDataToPackage //功能:向包数据区尾部添加数据 //入口参数: FILE* pFile 包文件流指针 // const BYTE* pFileBuffer 指向添加数据的指针 // UINT nFileBufferSize 添加数据的大小 //出口参数: bool 成功则返回true,失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackage::_AppendFileDataToPackage( FILE* pFile,const BYTE* pFileBuffer , UINT nFileBufferSize ) { if (NULL == pFileBuffer) { ERROR_PRINT("源数据不能为空:PACKAGE.CPP-_AppendFileDataToPackage",NULL); return false; } if (m_bModified == false) { ERROR_PRINT("包为只读模式,不可添加文件:PACKAGE.CPP-_AppendFileDataToPackage",NULL); return false; } if ( pFile == NULL ) { ERROR_PRINT("包文件未打开:PACKAGE.CPP-_AppendFileDataToPackage",NULL); return false; } fseek( pFile,m_nCurrDataPos, SEEK_SET ); if ( fwrite( pFileBuffer, nFileBufferSize,1, pFile ) != 1 ) { ERROR_PRINT("写入文件数据到包尾失败:PACKAGE.CPP-_AppendFileDataToPackage",NULL); return false; } // 更新数据尾部指针,即包系统描述写入位置 m_nCurrDataPos += nFileBufferSize; return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:CreateNewFileFromPackage //功能: 从包中读取文件并释放到指定目录 //入口参数: string szFileAbsPath 文件名 // string szFileDir 释放路径 //出口参数: bool 成功返回ture,反之返回false //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackage::CreateNewFileFromPackage( string szFilePath, string szFileOutPath ) { if (szFilePath.empty()) { ERROR_PRINT("文件路径不能为空:PACKAGE.CPP-CreateNewFileFromPackage",NULL); return false; } if ( NULL == m_spPackageFileSystem ) { ERROR_PRINT("文件信息系统未初始化:PACKAGE.CPP-CreateNewFileFromPackage",szFilePath.c_str()); return false; } SPackageFileInfo* pFileInfo = m_spPackageFileSystem->GetPackFileInfo( szFilePath ); if ( pFileInfo == NULL ) { ERROR_PRINT("获取文件信息描述失败:PACKAGE.CPP-CreateNewFileFromPackage",szFilePath.c_str()); return false; } CPackageFileReader* pPackageFileReader = new CPackageFileReader( this,pFileInfo ); if ( NULL == pPackageFileReader ) { ERROR_PRINT( "获取读取指针出错:PACKAGE.CPP-CreateNewFileFromPackage" ,szFilePath.c_str()); pFileInfo = NULL; return false; } // 这里注意,必须用文件的 nFileOrgSize初始化buffer大小,防止文件在包中是压缩模式,而导致解压后空间不足 BYTE* pBuffer = new BYTE[pFileInfo->nFileOrgSize]; if ( NULL == pBuffer ) { ERROR_PRINT("分配内存失败:PACKAGE.CPP-CreateNewFileFromPackage",szFilePath.c_str()); pFileInfo = NULL; delete pPackageFileReader; pPackageFileReader = NULL; return false; } UINT nBufferSize = pPackageFileReader->ReadBuffer( pBuffer); if ( nBufferSize == 0 ) { ERROR_PRINT("读取包数据出错:PACKAGE.CPP-CreateNewFileFromPackage",szFilePath.c_str()); pFileInfo = NULL; delete [] pBuffer; pBuffer = NULL; delete pPackageFileReader; pPackageFileReader = NULL; return false; } _ValidateDirs(szFileOutPath); FILE* pFile; if ( fopen_s( &pFile,szFileOutPath.c_str(), "wb" ) ) { pFileInfo = NULL; delete [] pBuffer; pBuffer = NULL; delete pPackageFileReader; pPackageFileReader = NULL; return false; } if ( fwrite( pBuffer, nBufferSize,1, pFile ) != 1 ) { ERROR_PRINT("写入数据出错:PACKAGE.CPP-CreateNewFileFromPackage",szFilePath.c_str()); pFileInfo = NULL; delete [] pBuffer; pBuffer = NULL; delete pPackageFileReader; pPackageFileReader = NULL; return false; } fclose(pFile); pFileInfo = NULL; delete [] pBuffer; pBuffer = NULL; delete pPackageFileReader; pPackageFileReader = NULL; return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:LoadConfigFile //功能: 获取相对路径 //入口参数: string strFilePath 配置文件路径 // map& matConfig 配置参数 //出口参数:bool //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackage::_LoadConfigFile(string strFilePath,map& mapConfig) { TiXmlDocument xmlDoc(strFilePath.c_str()); if (xmlDoc.LoadFile() == false) { ERROR_PRINT("Open config file failed:PACKAGEFILESYSTEM.CPP-_DeleteIdleSpace",NULL); return false; } TiXmlElement* pRootElement = xmlDoc.RootElement(); if (_LoadXmlFileData(pRootElement,mapConfig) == false) { return false; } return true; } bool CPackage::_LoadConfigFile(char *pBuffer, map& mapConfig) { if (NULL == pBuffer) { return false; } TiXmlDocument* pXmlDoc = new TiXmlDocument(); if (NULL == pXmlDoc) { return false; } pXmlDoc->Parse(pBuffer); TiXmlElement* pRootElement = pXmlDoc->RootElement(); if (_LoadXmlFileData(pRootElement,mapConfig) == false) { delete pXmlDoc; pXmlDoc = NULL; return false; } delete pXmlDoc; pXmlDoc = NULL; return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:LoadXmlFileData //功能: 递归读取文件 //入口参数: TiXmlElement* pRootElement 读取根节点 // map& matConfig 配置参数 //出口参数:bool //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackage::_LoadXmlFileData(TiXmlElement* pRootElement, map& mapConfig) { if (NULL == pRootElement) { return false; } TiXmlElement* pChildElement = pRootElement->FirstChildElement(); while (pChildElement != NULL) { const char* pszName = pChildElement->Value(); if (strcmp(pszName, "EncryptType") == 0) { const char* pFileType = pChildElement->Attribute("FileType"); if (NULL == pFileType) { ERROR_PRINT("Fail to load config file name:PACKAGEFILESYSTEM.CPP-_DeleteIdleSpace",NULL); return false; } int iType = 0; pChildElement->QueryIntAttribute("EncryptNum",&iType); string strFileType = string(pFileType); EEncryptType eType = (EEncryptType)iType; mapConfig[strFileType] = eType; } pChildElement = pChildElement->NextSiblingElement(); } return true; } string CPackage::_GetCurrWorkDir() { char pTemp[MAX_PATH]; GetModuleFileName(NULL,pTemp,MAX_PATH); if (NULL == pTemp) { return ""; } string strConfigFilePath = string(pTemp); strConfigFilePath = strConfigFilePath.substr(0,strConfigFilePath.find_last_of("\\")); strConfigFilePath += "\\"; return strConfigFilePath; } //////////////////////////////////////////////////////////////////////////////// //函数名:GetFileEncryptType //功能:根据文件类型,配置文件压缩及加密类型 //入口参数: string strFileName 文件名 // UINT nFileSize 文件大小 //出口参数:EEncryptType 文件压缩及加密类型 默认为ET_HEADER //////////////////////////////////////////////////////////////////////////////// EEncryptType CPackage::_GetFileEncryptType( string strFileName, UINT nFileSize ) { if (m_mapEncryptInfo.empty()) { ERROR_PRINT("未初始化配置表:PACKAGE.CPP-GetFileEncryptType",NULL); return ET_NONE; } string strFileType = strFileName.substr(strFileName.find_last_of("." )+ 1); StringLower(strFileType); EEncryptType eEncrypType = ET_HEADER; if (nFileSize <= ZIP_BLOCK_SIZE) { eEncrypType = ET_HEADER; } else { map::iterator iter; iter = m_mapEncryptInfo.find(strFileType); if (iter != m_mapEncryptInfo.end()) { eEncrypType = m_mapEncryptInfo[strFileType]; } else { eEncrypType = ET_NONE; } } return eEncrypType; } void GetPackageSubPath( const string& strBasePath, SPackageDirInfo * pPackDirInfo, vector< string >& vSubPaths ) { if ( !pPackDirInfo ) return; map< string, SPackageDirInfo >::iterator iter; for ( iter = pPackDirInfo->vPackageDirInfos.begin(); iter != pPackDirInfo->vPackageDirInfos.end(); iter ++ ) { string strSubPath = strBasePath + iter->first + "\\"; vSubPaths.push_back( strSubPath ); GetPackageSubPath( strSubPath, &iter->second, vSubPaths ); } } bool CPackage::GetSubPath( const char * szPathByRelPackage, vector< string >& vSubPaths ) { if ( !m_spPackageFileSystem || !szPathByRelPackage || szPathByRelPackage[0] == '\0' ) return false; SPackageDirInfo * pPackDirInfo = m_spPackageFileSystem->GetPackDirInfo( szPathByRelPackage ); if ( !pPackDirInfo ) return false; string strBasePath = szPathByRelPackage; if ( strBasePath[strBasePath.length() - 1] != '\\' ) strBasePath += "\\"; GetPackageSubPath( strBasePath, pPackDirInfo, vSubPaths ); return true; }