Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1132 lines
26 KiB
C++
1132 lines
26 KiB
C++
#include "StdAfx.h"
|
|
#include "updatemanager.h"
|
|
//#include "../RarLib/Rar.h"
|
|
//#include "RYLLoginDlg.h"
|
|
#include "../GlobalScript/Utility/CheckSum/Crc32Static.h"
|
|
#include "RYLLOGIN_DEFINITIONS.H"
|
|
|
|
#include "ZipArchive.h"
|
|
|
|
#include "Patch_Util.h"
|
|
|
|
|
|
//DWORD *CUpdateManager::m_dwZipTotalCount = NULL;
|
|
//DWORD *CUpdateManager::m_dwZipNowCount = NULL;
|
|
|
|
CGradientStatic *CUpdateManager::m_pInfoWnd = NULL;
|
|
CWnd *CUpdateManager::m_pDisplayWnd = NULL;
|
|
BOOL CUpdateManager::m_bUpdateLogin = FALSE;
|
|
|
|
|
|
CUpdateManager::CUpdateManager(void)
|
|
{
|
|
m_bServerClosed = false;
|
|
|
|
m_pDisplayState = NULL;
|
|
|
|
m_nVersion = -1;
|
|
|
|
m_bUpdateLogin = FALSE;
|
|
|
|
m_pfProgressPercentage = NULL;
|
|
m_pfFileProgressPercentage = NULL;
|
|
|
|
m_bTerminate = false;
|
|
}
|
|
|
|
CUpdateManager::~CUpdateManager(void)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CUpdateManager::Init()
|
|
{
|
|
m_HTTPFile.Init();
|
|
|
|
// 강제종료 플래그
|
|
m_bTerminate = false;
|
|
}
|
|
|
|
|
|
//bool IsDirectoryExist( const char* szDirectoryName )
|
|
//{
|
|
// DWORD dwAttr = ::GetFileAttributes( szDirectoryName );
|
|
//
|
|
//
|
|
// if( dwAttr == 0xFFFFFFFF )
|
|
// return false; // file not exists ?
|
|
//
|
|
// if( dwAttr & FILE_ATTRIBUTE_DIRECTORY )
|
|
// return true;
|
|
//
|
|
// return false; // exists but not a directory
|
|
//}
|
|
|
|
bool CUpdateManager::ProcessNoticeFiles()
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 공지사항 파일의 전송 및 압축해제
|
|
|
|
CString strNoticeRoot;
|
|
CString strNoticePath, strNoticeClientPath, strFilename;
|
|
std::vector< int > vecNoticeVer;
|
|
|
|
// 업데이트 버전을 근거로 공지사항 목록(받아할 파일이름 리스트) 생성
|
|
strNoticeRoot = m_strServerPath + "/Notice"; // By Belldandy(2005.02.02)
|
|
|
|
strNoticePath.Format( "%s/NoticeInfo.dat", strNoticeRoot );
|
|
strNoticeClientPath.Format( "%s/NoticeInfo.dat", m_strRootPath );
|
|
bool bRet = m_HTTPFile.TransferFile( strNoticePath, strNoticeClientPath, "NoticeInfo.dat" );
|
|
|
|
FILE* fp = fopen( strNoticeClientPath, "r" );
|
|
if( NULL == fp )
|
|
{
|
|
// NoticeInfo.dat 가 없을 경우,
|
|
// 지금은 단순히 빠져나가는 식으로 처리하지만 추후엔 별도로 파일 목록을
|
|
// FTP로 부터 긁어와 최근 파일을 얻는 식으로 처리도 생각해 볼 수 있겠지?
|
|
AfxMessageBox( RYLLoginGetMessage( LOGIN_MSG_FAIL_TO_GET_NOTICEINFO ) );
|
|
return false;
|
|
}
|
|
|
|
int nNoticeVersion = 0;
|
|
bool bAddAfterAll = false;
|
|
CString strTmp;
|
|
while( !feof(fp) )
|
|
{
|
|
int nReadCount = fscanf( fp, "%d", &nNoticeVersion );
|
|
|
|
// NoticeInfo.dat 말미 공백시 마지막 버전번호가 중복해 들어가는 문제 해결을 위해
|
|
if( nReadCount < 1 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( nNoticeVersion <= 0 )
|
|
{
|
|
// versioninfo.dat 파일이 깨진 경우
|
|
AfxMessageBox( RYLLoginGetMessage( LOGIN_MSG_FAIL_TO_GET_NOTICEINFO ) );
|
|
return false;
|
|
}
|
|
|
|
strTmp.Format( "%s/Notice/%d", m_strRootPath, nNoticeVersion );
|
|
if( !IsDirectoryExist(strTmp) )
|
|
{
|
|
bAddAfterAll = true;
|
|
}
|
|
|
|
if( bAddAfterAll )
|
|
{
|
|
vecNoticeVer.push_back( nNoticeVersion );
|
|
}
|
|
}
|
|
fclose( fp );
|
|
DeleteFile( strNoticeClientPath );
|
|
|
|
DWORD dwNoticeTotalSize = 0;
|
|
int cDown;
|
|
// notice 파일 전송
|
|
for( cDown=0; cDown < vecNoticeVer.size(); cDown++ )
|
|
{
|
|
if( m_bTerminate )
|
|
{
|
|
// 강제종료
|
|
return false;
|
|
}
|
|
|
|
strNoticePath.Format( "%s/%dNotice.zip", strNoticeRoot, vecNoticeVer[cDown] );
|
|
strNoticeClientPath.Format( "%s/%dNotice.zip", m_strRootPath, vecNoticeVer[cDown] );
|
|
strFilename.Format( "%dNotice.zip", vecNoticeVer[cDown] );
|
|
|
|
m_HTTPFile.TransferFile( strNoticePath, strNoticeClientPath, strFilename );
|
|
|
|
// notice 파일 전송에 5% 할당
|
|
*m_pfProgressPercentage = (cDown*5.0f) / vecNoticeVer.size();
|
|
CRect rcUpdate;
|
|
rcUpdate.left = 31;
|
|
rcUpdate.top = 427;
|
|
rcUpdate.right = 31 + 464;
|
|
rcUpdate.bottom = 427 + 16;
|
|
m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
|
|
}
|
|
|
|
// notice 파일 압축 해제
|
|
CZipArchive zipArc;
|
|
for( cDown = 0; cDown < vecNoticeVer.size(); ++cDown )
|
|
{
|
|
if( m_bTerminate )
|
|
{
|
|
for( cDown = 0; cDown < vecNoticeVer.size(); ++cDown )
|
|
{
|
|
strNoticeClientPath.Format( "%s/%dNotice.zip", m_strRootPath, vecNoticeVer[cDown] );
|
|
DeleteFile( strNoticeClientPath );
|
|
}
|
|
// 강제종료
|
|
return false;
|
|
}
|
|
|
|
strNoticeClientPath.Format( "%s/%dNotice.zip", m_strRootPath, vecNoticeVer[cDown] );
|
|
|
|
try
|
|
{
|
|
zipArc.Open( strNoticeClientPath, CZipArchive::zipOpen );
|
|
}
|
|
catch(CException* e)
|
|
{
|
|
if( e->IsKindOf( RUNTIME_CLASS(CZipException) ) )
|
|
{
|
|
CZipException* p = (CZipException*) e;
|
|
|
|
//if( CZipException::badZipFile == p->m_iCause )
|
|
{
|
|
CString strTmp;
|
|
strTmp.Format( "Invalid zip file : %s", p->m_szFileName );
|
|
AfxMessageBox( strTmp, MB_ICONERROR|MB_OK );
|
|
}
|
|
}
|
|
|
|
e->Delete();
|
|
exit(0);
|
|
}
|
|
|
|
for( int i = 0; i < zipArc.GetCount(); ++i )
|
|
{
|
|
CZipFileHeader zfh;
|
|
zipArc.GetFileInfo( zfh, (WORD)i );
|
|
|
|
try
|
|
{
|
|
zipArc.ExtractFile( (WORD)i, m_strRootPath+"\\Notice" );
|
|
}
|
|
catch(CException* e)
|
|
{
|
|
if( e->IsKindOf( RUNTIME_CLASS(CFileException) ) )
|
|
{
|
|
CFileException* p = (CFileException*) e;
|
|
|
|
if( CFileException::accessDenied == p->m_cause )
|
|
{
|
|
// DWORD dwAttr = GetFileAttributes( p->m_strFileName );
|
|
// if( dwAttr & FILE_ATTRIBUTE_SYSTEM )
|
|
// {
|
|
// dwAttr &= (~FILE_ATTRIBUTE_SYSTEM);
|
|
// SetFileAttributes( p->m_strFileName, dwAttr );
|
|
// }
|
|
//
|
|
// if( dwAttr & FILE_ATTRIBUTE_HIDDEN )
|
|
// {
|
|
// dwAttr &= (~FILE_ATTRIBUTE_HIDDEN);
|
|
// SetFileAttributes( p->m_strFileName, dwAttr );
|
|
// }
|
|
//
|
|
// if( dwAttr & FILE_ATTRIBUTE_READONLY )
|
|
// {
|
|
// dwAttr &= (~FILE_ATTRIBUTE_READONLY);
|
|
// SetFileAttributes( p->m_strFileName, dwAttr );
|
|
// }
|
|
//
|
|
// DeleteFile( p->m_strFileName );
|
|
// zipArc.ExtractFile( (WORD)i, m_strRootPath+"\\Notice" );
|
|
}
|
|
}
|
|
|
|
e->Delete();
|
|
}
|
|
}
|
|
|
|
zipArc.Close();
|
|
|
|
DeleteFile( strNoticeClientPath );
|
|
|
|
// notice 파일 압축 해제에 5% 할당
|
|
*m_pfProgressPercentage = (cDown*5.0f) / vecNoticeVer.size() + 5.0f;
|
|
CRect rcUpdate;
|
|
rcUpdate.left = 31;
|
|
rcUpdate.top = 427;
|
|
rcUpdate.right = 31 + 464;
|
|
rcUpdate.bottom = 427 + 16;
|
|
m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool CUpdateManager::LoadServerPatchInfo()
|
|
{
|
|
m_pInfoWnd->SetWindowText( "Get Patchinfo" );
|
|
m_pInfoWnd->Invalidate(FALSE);
|
|
|
|
// PatchInfoV2.zip 파일 전송
|
|
#ifdef _NATION_JP_
|
|
// 일본서버는 얻어온 서버주소 + "/FilePatch/" 가 패치 파일을 가져올 주소다
|
|
// (공지주소 하드코딩을 서버에서 얻어온 주소 이용으로 바꿈)
|
|
m_HTTPFile.TransferFile( m_strServerPath+"/FilePatch/PatchInfoV2.zip", m_strRootPath+"\\PatchInfoV2.zip", "PatchInfoV2.zip" );
|
|
#else
|
|
m_HTTPFile.TransferFile( m_strServerPath+"/PatchInfoV2.zip", m_strRootPath+"\\PatchInfoV2.zip", "PatchInfoV2.zip" );
|
|
#endif
|
|
|
|
// HANDLE hFile = CreateFile( m_strRootPath+"\\PatchInfo.zip",
|
|
// GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
// NULL, OPEN_EXISTING, 0, 0 );
|
|
// if( INVALID_HANDLE_VALUE == hFile )
|
|
if( false == IsFileExist( m_strRootPath+"\\PatchInfoV2.zip" ) )
|
|
{
|
|
// PatchInfo 파일을 받아올 수 없습니다
|
|
AfxMessageBox( RYLLoginGetMessage(LOGIN_MSG_FAIL_TO_GET_PATCHINFO) );
|
|
|
|
return false;
|
|
}
|
|
|
|
// 압축해제
|
|
CZipArchive zipArc;
|
|
try
|
|
{
|
|
zipArc.Open( m_strRootPath+"\\PatchInfoV2.zip", CZipArchive::zipOpen );
|
|
}
|
|
catch(CException* e)
|
|
{
|
|
if( e->IsKindOf( RUNTIME_CLASS(CZipException) ) )
|
|
{
|
|
CZipException* p = (CZipException*) e;
|
|
|
|
//if( CZipException::badZipFile == p->m_iCause )
|
|
{
|
|
CString strTmp;
|
|
strTmp.Format( "Invalid zip file : %s", p->m_szFileName );
|
|
AfxMessageBox( strTmp, MB_ICONERROR|MB_OK );
|
|
}
|
|
}
|
|
|
|
e->Delete();
|
|
exit(0);
|
|
}
|
|
|
|
CString strTmp = m_strRootPath+"\\"+"PatchInfoV2";
|
|
DWORD dwAttr = 0;
|
|
dwAttr = GetFileAttributes( strTmp );
|
|
if( 0xFFFFFFFF != dwAttr )
|
|
{
|
|
if( FILE_ATTRIBUTE_SYSTEM & dwAttr )
|
|
{
|
|
dwAttr &= (~FILE_ATTRIBUTE_SYSTEM);
|
|
SetFileAttributes( strTmp, dwAttr );
|
|
}
|
|
|
|
if( FILE_ATTRIBUTE_HIDDEN & dwAttr )
|
|
{
|
|
dwAttr &= (~FILE_ATTRIBUTE_HIDDEN);
|
|
SetFileAttributes( strTmp, dwAttr );
|
|
}
|
|
|
|
if( FILE_ATTRIBUTE_READONLY & dwAttr )
|
|
{
|
|
dwAttr &= (~FILE_ATTRIBUTE_READONLY);
|
|
SetFileAttributes( strTmp, dwAttr );
|
|
}
|
|
}
|
|
zipArc.ExtractFile( 0, m_strRootPath );
|
|
zipArc.Close();
|
|
|
|
// PatchInfoV2.zip 삭제
|
|
DeleteFile( m_strRootPath+"\\PatchInfoV2.zip" );
|
|
|
|
// PatchInfoV2 로드 후 삭제
|
|
m_ServerFileInfoList.Reset();
|
|
m_ServerFileInfoList.Load( m_strRootPath+"\\PatchInfoV2" );
|
|
DeleteFile( m_strRootPath+"\\PatchInfoV2" );
|
|
|
|
|
|
// 서버측 patchinfo 전송에 5%할당
|
|
*m_pfProgressPercentage = 15.0f;
|
|
CRect rcUpdate;
|
|
rcUpdate.left = 31;
|
|
rcUpdate.top = 427;
|
|
rcUpdate.right = 31 + 464;
|
|
rcUpdate.bottom = 427 + 16;
|
|
m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//bool CUpdateManager::LoadLocalPatchInfoCache()
|
|
//{
|
|
// // 목록 캐시파일이 존재하는지 체크해 불러옴, 없으면 생성
|
|
// HANDLE hFile = CreateFile( m_strRootPath+"\\PatchInfo.cache",
|
|
// GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
// NULL, OPEN_EXISTING, 0, 0 );
|
|
// if( INVALID_HANDLE_VALUE != hFile )
|
|
// {
|
|
// CloseHandle(hFile);
|
|
//
|
|
// CZipArchive zipArc;
|
|
// try
|
|
// {
|
|
// zipArc.Open( m_strRootPath+"\\PatchInfo.cache", CZipArchive::zipOpen );
|
|
// }
|
|
// catch(CException* e)
|
|
// {
|
|
// if( e->IsKindOf( RUNTIME_CLASS(CZipException) ) )
|
|
// {
|
|
// CZipException* p = (CZipException*) e;
|
|
//
|
|
// //if( CZipException::badZipFile == p->m_iCause )
|
|
// {
|
|
// CString strTmp;
|
|
// strTmp.Format( "Invalid zip file : %s", p->m_szFileName );
|
|
// AfxMessageBox( strTmp, MB_ICONERROR|MB_OK );
|
|
// }
|
|
// }
|
|
//
|
|
// e->Delete();
|
|
// exit(0);
|
|
// }
|
|
//
|
|
// CString strTmp = m_strRootPath+"\\"+"PatchInfo.local";
|
|
// DWORD dwAttr = 0;
|
|
// dwAttr = GetFileAttributes( strTmp );
|
|
// if( 0xFFFFFFFF != dwAttr )
|
|
// {
|
|
// if( FILE_ATTRIBUTE_SYSTEM & dwAttr )
|
|
// {
|
|
// dwAttr &= (~FILE_ATTRIBUTE_SYSTEM);
|
|
// SetFileAttributes( strTmp, dwAttr );
|
|
// }
|
|
//
|
|
// if( FILE_ATTRIBUTE_HIDDEN & dwAttr )
|
|
// {
|
|
// dwAttr &= (~FILE_ATTRIBUTE_HIDDEN);
|
|
// SetFileAttributes( strTmp, dwAttr );
|
|
// }
|
|
//
|
|
// if( FILE_ATTRIBUTE_READONLY & dwAttr )
|
|
// {
|
|
// dwAttr &= (~FILE_ATTRIBUTE_READONLY);
|
|
// SetFileAttributes( strTmp, dwAttr );
|
|
// }
|
|
// }
|
|
// zipArc.ExtractFile( 0, m_strRootPath );
|
|
// zipArc.Close();
|
|
//
|
|
// if( false == m_LocalFileInfoList.Load( m_strRootPath+"\\PatchInfo.local" ) )
|
|
// {
|
|
// if( false == CreateFileInfoCache() )
|
|
// {
|
|
// return false;
|
|
// }
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// if( false == CreateFileInfoCache() )
|
|
// {
|
|
// return false;
|
|
// }
|
|
// }
|
|
//
|
|
//
|
|
// // 로컬 파일명으로의 quickfind용 인덱스 맵
|
|
// int nTotal = m_LocalFileInfoList.GetList().GetSize();
|
|
// CString strProgress;
|
|
// for( int i = 0; i < nTotal; ++i )
|
|
// {
|
|
// if( m_bTerminate )
|
|
// {
|
|
// // 강제종료
|
|
// return false;
|
|
// }
|
|
//
|
|
// LocalFileInfoRecord &rLfir = m_LocalFileInfoList.GetList()[i];
|
|
//
|
|
// m_mapLocalFileName2Index[ CString(rLfir.szFileName) ] = i;
|
|
//
|
|
// if( !(i % 100) )
|
|
// {
|
|
// strProgress.Format( "[%d/%d] Building quick search index", i, nTotal );
|
|
// m_pInfoWnd->SetWindowText( strProgress );
|
|
// m_pInfoWnd->Invalidate( FALSE );
|
|
//
|
|
// *m_pfFileProgressPercentage = (100.0f*i) / nTotal;
|
|
// CRect rect;
|
|
// rect.left = 22;
|
|
// rect.right = 536;
|
|
// rect.top = 405;
|
|
// rect.bottom = 440;
|
|
// m_pDisplayWnd->InvalidateRect( rect, FALSE );
|
|
// }
|
|
// }
|
|
//
|
|
//
|
|
// // 로컬측 patchinfo (생성+)로딩에 15%할당
|
|
// *m_pfProgressPercentage = 30.0f;
|
|
// CRect rcUpdate;
|
|
// rcUpdate.left = 31;
|
|
// rcUpdate.top = 427;
|
|
// rcUpdate.right = 31 + 464;
|
|
// rcUpdate.bottom = 427 + 16;
|
|
// m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
|
|
//
|
|
// return true;
|
|
//}
|
|
|
|
|
|
void CUpdateManager::AddToPkg2FileNameBucket( char* szPkgName, char* szFileName )
|
|
{
|
|
std::map< PTR_STRING, std::vector< char* > *, PTR_STRING_LESS >::iterator it;
|
|
std::vector< char* > * pVec;
|
|
|
|
it = m_mapPackageName2FileNameVectorPtr.find( szPkgName );
|
|
|
|
if( m_mapPackageName2FileNameVectorPtr.end() == it )
|
|
{
|
|
pVec = new std::vector< char* >;
|
|
pVec->push_back( szFileName );
|
|
m_mapPackageName2FileNameVectorPtr[szPkgName] = pVec;
|
|
}
|
|
else
|
|
{
|
|
pVec = it->second;
|
|
pVec->push_back( szFileName );
|
|
}
|
|
}
|
|
|
|
|
|
bool CUpdateManager::CollectDownloadFileList( bool bFileCheckMode )
|
|
{
|
|
// 서버측 파일정보 리스트와 로컬측 파일정보 리스트를 비교, 업데이트가 필요한
|
|
// 파일의 목록을 얻어냄
|
|
int i;
|
|
|
|
int nTotal = m_ServerFileInfoList.GetList().size();
|
|
|
|
CString strTmp;
|
|
|
|
for( i = 0; i < nTotal; ++i )
|
|
{
|
|
if( m_bTerminate )
|
|
{
|
|
// 강제종료
|
|
return false;
|
|
}
|
|
|
|
FilePatchInfoRecord &rServerRecord = m_ServerFileInfoList.GetList()[i];
|
|
|
|
|
|
if( !(i% 100) )
|
|
{
|
|
strTmp.Format( "[%d/%d] Comparing %s", i, nTotal, rServerRecord.szFileName );
|
|
m_pInfoWnd->SetWindowText( strTmp );
|
|
m_pInfoWnd->Invalidate(FALSE);
|
|
}
|
|
|
|
|
|
if( bFileCheckMode )
|
|
{
|
|
// File check mode 일 경우 -> 파일이 존재하는지, 존재한다면 CRC/size 일치하는지 체크
|
|
CString strTmp = m_strRootPath+"\\"+rServerRecord.szFileName;
|
|
|
|
if( IsFileExist( strTmp ) )
|
|
{
|
|
DWORD dwSize, dwCRC32;
|
|
|
|
dwSize = GetFileSize( strTmp );
|
|
CCrc32Static::FileCrc32Assembly( strTmp, dwCRC32 );
|
|
|
|
if( rServerRecord.dwCRC32 != dwCRC32 || rServerRecord.dwSize != dwSize )
|
|
{
|
|
AddToPkg2FileNameBucket( rServerRecord.szPackageFileName, rServerRecord.szFileName );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 파일이 존재하지 않을경우 -> 당근 서버에서 갖구와야지
|
|
AddToPkg2FileNameBucket( rServerRecord.szPackageFileName, rServerRecord.szFileName );
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Normal patch mode 일 경우 -> 버전필드와 클라이언트 버전 비교
|
|
// 서버패치파일목록의 버전필드값이 클라이언트 버전값보다 큰 경우 -> 가져와야 할 대상
|
|
if( rServerRecord.dwVersion > m_nVersion )
|
|
{
|
|
AddToPkg2FileNameBucket( rServerRecord.szPackageFileName, rServerRecord.szFileName );
|
|
}
|
|
}
|
|
|
|
|
|
if( !(i% 100) )
|
|
{
|
|
// 서버/로컬측 파일정보 비교에 45% 할당
|
|
*m_pfProgressPercentage = (45.0f*i)/nTotal + 15.0f;
|
|
*m_pfFileProgressPercentage = (i*100.0f)/nTotal;
|
|
CRect rcUpdate;
|
|
rcUpdate.left = 31;
|
|
rcUpdate.top = 408;
|
|
rcUpdate.right = 494;
|
|
rcUpdate.bottom = 442;
|
|
m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool CUpdateManager::DownloadUpdateFile(void)
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 다운로드 해야 할 압축 파일들을 전송
|
|
//
|
|
|
|
char* szPackageFileName;
|
|
|
|
int nTotal = m_mapPackageName2FileNameVectorPtr.size();
|
|
int nCounter = 0;
|
|
|
|
// package 파일 전송
|
|
CString strTotalCount;
|
|
std::map< PTR_STRING, std::vector< char* > *, PTR_STRING_LESS >::iterator it;
|
|
|
|
for( it = m_mapPackageName2FileNameVectorPtr.begin();
|
|
it != m_mapPackageName2FileNameVectorPtr.end(); it++ )
|
|
{
|
|
if( m_bTerminate )
|
|
{
|
|
// 강제종료
|
|
return false;
|
|
}
|
|
|
|
szPackageFileName = it->first.m_pStr;
|
|
|
|
strTotalCount.Format( " [ Total %d / %d files ]", ++nCounter, m_mapPackageName2FileNameVectorPtr.size() );
|
|
|
|
#ifdef _NATION_JP_
|
|
// 일본서버는 얻어온 서버주소 + "/FilePatch/" 가 패치 파일을 가져올 주소다
|
|
// (공지주소 하드코딩을 서버에서 얻어온 주소 이용으로 바꿈)
|
|
m_HTTPFile.TransferFile(
|
|
m_strServerPath+"/FilePatch/"+szPackageFileName+".zip",
|
|
m_strRootPath+"\\"+szPackageFileName+".zip", CString(szPackageFileName)+".zip"+strTotalCount );
|
|
#else
|
|
m_HTTPFile.TransferFile(
|
|
m_strServerPath+"/"+szPackageFileName+".zip",
|
|
m_strRootPath+"\\"+szPackageFileName+".zip", CString(szPackageFileName)+".zip"+strTotalCount );
|
|
#endif
|
|
|
|
// 패키지 파일 전송에 20% 할당
|
|
*m_pfProgressPercentage = (20.0f*nCounter)/nTotal + 60.0f;
|
|
CRect rcUpdate;
|
|
rcUpdate.left = 31;
|
|
rcUpdate.top = 427;
|
|
rcUpdate.right = 31 + 464;
|
|
rcUpdate.bottom = 427 + 16;
|
|
m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool CUpdateManager::ExtractPatchFiles()
|
|
{
|
|
// package 파일에서 필요한 파일 압축 해제
|
|
// 로컬캐시의 CRC, size 항목 업데이트
|
|
// 압축해제 끝난 package 파일 삭제
|
|
|
|
std::map< PTR_STRING, std::vector< char* > *, PTR_STRING_LESS >::iterator it;
|
|
char* szPackageFileName;
|
|
std::vector< char* > * pVec;
|
|
|
|
int nTotal = 0, nCounter = 0;
|
|
|
|
// 총 업데이트할 파일 갯수 합산
|
|
for( it = m_mapPackageName2FileNameVectorPtr.begin();
|
|
it != m_mapPackageName2FileNameVectorPtr.end(); it++ )
|
|
{
|
|
pVec = it->second;
|
|
nTotal += pVec->size();
|
|
}
|
|
|
|
|
|
|
|
CString strTmp;
|
|
CZipArchive zipArc;
|
|
|
|
for( it = m_mapPackageName2FileNameVectorPtr.begin();
|
|
it != m_mapPackageName2FileNameVectorPtr.end(); it++ )
|
|
{
|
|
if( m_bTerminate )
|
|
{
|
|
// 강제종료
|
|
return false;
|
|
}
|
|
|
|
szPackageFileName = it->first.m_pStr;
|
|
pVec = it->second;
|
|
|
|
// package 파일 오픈
|
|
try
|
|
{
|
|
zipArc.Open( m_strRootPath+"\\"+szPackageFileName+".zip", CZipArchive::zipOpen );
|
|
}
|
|
catch(CException* e)
|
|
{
|
|
if( e->IsKindOf( RUNTIME_CLASS(CZipException) ) )
|
|
{
|
|
CZipException* p = (CZipException*) e;
|
|
|
|
//if( CZipException::badZipFile == p->m_iCause )
|
|
{
|
|
CString strTmp;
|
|
strTmp.Format( "Invalid zip file : %s", p->m_szFileName );
|
|
AfxMessageBox( strTmp, MB_ICONERROR|MB_OK );
|
|
}
|
|
}
|
|
|
|
e->Delete();
|
|
exit(0);
|
|
}
|
|
|
|
// 압축 해제
|
|
for( int i = 0; i < pVec->size(); ++i )
|
|
{
|
|
int nIdx = zipArc.FindFile( (*pVec)[i], CZipArchive::ffNoCaseSens );
|
|
if( -1 != nIdx )
|
|
{
|
|
++nCounter;
|
|
|
|
strTmp.Format( "[%d/%d] Extracting %s\\%s", nCounter, nTotal, (*pVec)[i], (*pVec)[i] );
|
|
m_pInfoWnd->SetWindowText( strTmp );
|
|
m_pInfoWnd->Invalidate(FALSE);
|
|
|
|
strTmp = m_strRootPath+"\\"+(*pVec)[i];
|
|
DWORD dwAttr = 0;
|
|
dwAttr = GetFileAttributes( strTmp );
|
|
if( 0xFFFFFFFF != dwAttr )
|
|
{
|
|
if( FILE_ATTRIBUTE_SYSTEM & dwAttr )
|
|
{
|
|
dwAttr &= (~FILE_ATTRIBUTE_SYSTEM);
|
|
SetFileAttributes( strTmp, dwAttr );
|
|
}
|
|
|
|
if( FILE_ATTRIBUTE_HIDDEN & dwAttr )
|
|
{
|
|
dwAttr &= (~FILE_ATTRIBUTE_HIDDEN);
|
|
SetFileAttributes( strTmp, dwAttr );
|
|
}
|
|
|
|
if( FILE_ATTRIBUTE_READONLY & dwAttr )
|
|
{
|
|
dwAttr &= (~FILE_ATTRIBUTE_READONLY);
|
|
SetFileAttributes( strTmp, dwAttr );
|
|
}
|
|
}
|
|
|
|
zipArc.ExtractFile( nIdx, m_strRootPath );
|
|
|
|
// 패치 파일 추출에 20% 할당
|
|
*m_pfProgressPercentage = (20.0f*nCounter)/nTotal + 80.0f;
|
|
CRect rcUpdate;
|
|
rcUpdate.left = 31;
|
|
rcUpdate.top = 427;
|
|
rcUpdate.right = 31 + 464;
|
|
rcUpdate.bottom = 427 + 16;
|
|
m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
|
|
|
|
// 런처 업데이트 체크
|
|
if( 0 == stricmp( "Login.new", (*pVec)[i] ) )
|
|
{
|
|
m_bUpdateLogin = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
zipArc.Close();
|
|
|
|
DeleteFile( m_strRootPath+"\\"+szPackageFileName+".zip" );
|
|
}
|
|
|
|
|
|
m_nVersion = m_ServerFileInfoList.GetVersion();
|
|
return true;
|
|
}
|
|
|
|
|
|
bool CUpdateManager::CleanUp()
|
|
{
|
|
std::map< PTR_STRING, std::vector< char* > *, PTR_STRING_LESS >::iterator it;
|
|
std::vector< char* > * pVec;
|
|
|
|
// 총 업데이트할 파일 갯수 합산
|
|
for( it = m_mapPackageName2FileNameVectorPtr.begin();
|
|
it != m_mapPackageName2FileNameVectorPtr.end(); it++ )
|
|
{
|
|
pVec = it->second;
|
|
delete pVec;
|
|
}
|
|
|
|
m_mapPackageName2FileNameVectorPtr.clear();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//bool CUpdateManager::SaveLocalCache()
|
|
//{
|
|
// // cache 파일을 저장
|
|
// m_LocalFileInfoList.Save( m_strRootPath+"\\PatchInfo.local" );
|
|
//
|
|
// CZipArchive zipArc;
|
|
//
|
|
// try
|
|
// {
|
|
// zipArc.Open( m_strRootPath+"\\PatchInfo.cache", CZipArchive::zipCreate );
|
|
// }
|
|
// catch(CException* e)
|
|
// {
|
|
// if( e->IsKindOf( RUNTIME_CLASS(CZipException) ) )
|
|
// {
|
|
// CZipException* p = (CZipException*) e;
|
|
//
|
|
// //if( CZipException::badZipFile == p->m_iCause )
|
|
// {
|
|
// CString strTmp;
|
|
// strTmp.Format( "Invalid zip file : %s", p->m_szFileName );
|
|
// AfxMessageBox( strTmp, MB_ICONERROR|MB_OK );
|
|
// }
|
|
// }
|
|
//
|
|
// e->Delete();
|
|
// exit(0);
|
|
// }
|
|
// zipArc.AddNewFile( m_strRootPath+"\\PatchInfo.local", "PatchInfo.local" );
|
|
// zipArc.Close();
|
|
//
|
|
// DeleteFile( m_strRootPath+"\\PatchInfo.local" );
|
|
//
|
|
// return true;
|
|
//}
|
|
|
|
|
|
//bool CUpdateManager::CreateFileInfoCache()
|
|
//{
|
|
// long lTotalFileCount = GetFileCountInSubDir( m_strRootPath );
|
|
//
|
|
// WIN32_FIND_DATA w32fd;
|
|
//
|
|
// HANDLE hFind = FindFirstFile( m_strRootPath+"\\*.*", &w32fd );
|
|
//
|
|
// if( INVALID_HANDLE_VALUE == hFind )
|
|
// {
|
|
// return false;
|
|
// }
|
|
//
|
|
// CString strCurrentSubPath("");
|
|
// CStringArray astrSubDirList;
|
|
// CString strFullPathName;
|
|
// CString strTmp;
|
|
// int nCounter = 0;
|
|
// while( 1 )
|
|
// {
|
|
// if( m_bTerminate )
|
|
// {
|
|
// // 강제종료
|
|
// return false;
|
|
// }
|
|
//
|
|
// if( 0 != stricmp( ".", w32fd.cFileName ) &&
|
|
// 0 != stricmp( "..", w32fd.cFileName ) )
|
|
// {
|
|
// if( w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
|
|
// {
|
|
// strTmp.Format( "%s%s", strCurrentSubPath, w32fd.cFileName );
|
|
// astrSubDirList.Add( strTmp );
|
|
// }
|
|
// else
|
|
// {
|
|
// LocalFileInfoRecord lfir;
|
|
// ++nCounter;
|
|
//
|
|
// strcpy( lfir.szFileName, strCurrentSubPath+w32fd.cFileName );
|
|
// strFullPathName = m_strRootPath+"\\"+strCurrentSubPath+w32fd.cFileName;
|
|
//
|
|
// if( !(nCounter % 30) )
|
|
// {
|
|
// strTmp.Format( "[%d/%d] Checking %s", nCounter, lTotalFileCount, strFullPathName );
|
|
// m_pInfoWnd->SetWindowText( strTmp );
|
|
// m_pInfoWnd->InvalidateRect(NULL,FALSE);
|
|
//
|
|
//
|
|
// // 로컬측 patchinfo 생성에 15%할당
|
|
// *m_pfProgressPercentage = (nCounter*15.0f)/lTotalFileCount + 15.0f;
|
|
// *m_pfFileProgressPercentage = (nCounter*100.0f)/lTotalFileCount;
|
|
// CRect rcUpdate;
|
|
// rcUpdate.left = 31;
|
|
// rcUpdate.top = 408;
|
|
// rcUpdate.right = 494;
|
|
// rcUpdate.bottom = 442;
|
|
// m_pDisplayWnd->InvalidateRect( rcUpdate, FALSE );
|
|
// }
|
|
//
|
|
//
|
|
// CCrc32Static::FileCrc32Assembly( strFullPathName, lfir.dwCRC32 );
|
|
// HANDLE hFile = CreateFile( strFullPathName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
// NULL, OPEN_EXISTING, 0, 0 );
|
|
// lfir.dwSize = GetFileSize ( hFile, NULL );
|
|
// CloseHandle( hFile );
|
|
//
|
|
// m_LocalFileInfoList.GetList().Add( lfir );
|
|
// }
|
|
// }
|
|
//
|
|
// if( 0 == FindNextFile( hFind, &w32fd ) )
|
|
// {
|
|
// FindClose( hFind );
|
|
//
|
|
// // sub dir queue 에 순서를 기다리고 있는 놈이 존재하면
|
|
// if( astrSubDirList.GetSize() > 0 )
|
|
// {
|
|
// // 꺼내서 쓰고
|
|
// strCurrentSubPath = astrSubDirList[0] + "\\";
|
|
// astrSubDirList.RemoveAt(0);
|
|
// hFind = FindFirstFile( m_strRootPath+"\\"+strCurrentSubPath+"*.*", &w32fd );
|
|
// }
|
|
// else
|
|
// {
|
|
// // 없음 루프 종료
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// // 생성 직후 한번 저장해줌
|
|
// return SaveLocalCache();
|
|
//}
|
|
|
|
|
|
long CUpdateManager::GetFileCountInSubDir( const char* szSubDirName )
|
|
{
|
|
WIN32_FIND_DATA w32fd;
|
|
CString strSubDirName( szSubDirName );
|
|
|
|
CString strCurrentSubPath("");
|
|
CStringArray astrSubDirList;
|
|
int nCounter = 0;
|
|
|
|
|
|
HANDLE hFind = FindFirstFile( strSubDirName+"\\*.*", &w32fd );
|
|
|
|
if( INVALID_HANDLE_VALUE == hFind )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
while( 1 )
|
|
{
|
|
if( 0 != stricmp( ".", w32fd.cFileName ) &&
|
|
0 != stricmp( "..", w32fd.cFileName ) )
|
|
{
|
|
if( w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
CString strTmp;
|
|
strTmp.Format( "%s%s", strCurrentSubPath, w32fd.cFileName );
|
|
astrSubDirList.Add( strTmp );
|
|
}
|
|
else
|
|
{
|
|
++nCounter;
|
|
}
|
|
}
|
|
|
|
if( 0 == FindNextFile( hFind, &w32fd ) )
|
|
{
|
|
FindClose( hFind );
|
|
|
|
// sub dir queue 에 순서를 기다리고 있는 놈이 존재하면
|
|
if( astrSubDirList.GetSize() > 0 )
|
|
{
|
|
// 꺼내서 쓰고
|
|
strCurrentSubPath = astrSubDirList[0] + "\\";
|
|
astrSubDirList.RemoveAt(0);
|
|
hFind = FindFirstFile( strSubDirName+"\\"+strCurrentSubPath+"*.*", &w32fd );
|
|
}
|
|
else
|
|
{
|
|
// 없음 루프 종료
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nCounter;
|
|
}
|
|
|
|
|
|
// case-insensitive version
|
|
//UINT AFXAPI HashKey(CString& string)
|
|
//{
|
|
// LPCTSTR key = (LPCTSTR) string;
|
|
// UINT nHash = 0;
|
|
//
|
|
// TCHAR tc;
|
|
//
|
|
// while (*key)
|
|
// {
|
|
// if( TCHAR('A') <= *key && *key <= TCHAR('Z') )
|
|
// {
|
|
// tc = *key + ( TCHAR('a') - TCHAR('A') );
|
|
// }
|
|
// else
|
|
// {
|
|
// tc = *key;
|
|
// }
|
|
//
|
|
// nHash = (nHash<<5) + nHash + tc;
|
|
//
|
|
// +++key;
|
|
// }
|
|
//
|
|
// return nHash;
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//void CUpdateManager::ProgressReport(char *pFilename, int nCount)
|
|
//{
|
|
// static int nUpdate = 0;
|
|
// CString strInfo;
|
|
//
|
|
// if( strcmp( pFilename, "Login.new" ) == 0 )
|
|
// {
|
|
// m_bUpdateLogin = TRUE;
|
|
// }
|
|
// //if( ( nUpdate++ ) % 3 == 0 )
|
|
// {
|
|
//
|
|
// strInfo.Format( " %d / %d Extract File = %d", nCount, *m_dwZipTotalCount, pFilename );
|
|
// m_pInfoWnd->SetWindowText( strInfo );
|
|
// m_pInfoWnd->Invalidate( FALSE );
|
|
//
|
|
// CRect rect;
|
|
// rect.left = 22;
|
|
// rect.right = 536;
|
|
// rect.top = 405;
|
|
// rect.bottom = 440;
|
|
//
|
|
// m_pDisplayWnd->InvalidateRect( rect, FALSE );
|
|
// }
|
|
//}
|
|
|
|
|
|
//void CUpdateManager::LoadClientFileInfoCacheList()
|
|
//{
|
|
// FILE* fp;
|
|
//
|
|
// CString strFileName = m_strRootPath + "\\PatchInfo.cache";
|
|
//
|
|
// fp = fopen( strFileName.GetBuffer(0), "rb" );
|
|
//
|
|
// if( NULL == fp )
|
|
// {
|
|
// return;
|
|
// }
|
|
//
|
|
// int nFileNameLength;
|
|
// //DWORD dwSize, dwCRC;
|
|
// ClientFileInfo cfi;
|
|
// char szFileName[1024];
|
|
//
|
|
// int nCount;
|
|
//
|
|
// fread( &nCount, sizeof(int), 1, fp );
|
|
//
|
|
// int nRealCount = 0;
|
|
// while( !feof(fp) )
|
|
// {
|
|
// fread( &nFileNameLength, sizeof(int), 1, fp );
|
|
//
|
|
// fread( szFileName, nFileNameLength, 1, fp );
|
|
// szFileName[nFileNameLength] = '\0';
|
|
//
|
|
// fread( &cfi, sizeof(ClientFileInfo), 1, fp );
|
|
//
|
|
// CString strKey = szFileName;
|
|
// strKey.MakeLower();
|
|
//
|
|
// m_mapFileInfoCache[strKey] = cfi;
|
|
//
|
|
// ++nRealCount;
|
|
//
|
|
// if( m_pInfoWnd )
|
|
// {
|
|
// CString strCacheCount;
|
|
// strCacheCount.Format( "%s %d / %d", RYLLoginGetMessage(LOGIN_MSG_LOADING_PATCHINFO_CACHE), nRealCount, nCount );
|
|
// m_pInfoWnd->SetWindowText( strCacheCount );
|
|
// }
|
|
// }
|
|
//
|
|
// fclose(fp);
|
|
//}
|
|
//
|
|
//
|
|
//void CUpdateManager::SaveClientFileInfoCacheList()
|
|
//{
|
|
// FILE* fp;
|
|
//
|
|
// CString strPatchInfoFileName = m_strRootPath + "\\PatchInfo.cache";
|
|
//
|
|
// fp = fopen( strPatchInfoFileName.GetBuffer(0), "wb" );
|
|
//
|
|
// if( NULL == fp )
|
|
// {
|
|
// return;
|
|
// }
|
|
//
|
|
// int nCount = m_mapFileInfoCache.GetCount();
|
|
//
|
|
// fwrite( &nCount, sizeof(int), 1, fp );
|
|
//
|
|
// int nFileNameLength;
|
|
// ClientFileInfo cfi;
|
|
// CString strFileName;
|
|
//
|
|
// POSITION iter;
|
|
//
|
|
// iter = m_mapFileInfoCache.GetStartPosition();
|
|
//
|
|
// while( NULL != iter )
|
|
// {
|
|
// m_mapFileInfoCache.GetNextAssoc( iter, strFileName, cfi );
|
|
//
|
|
// nFileNameLength = strFileName.GetLength();
|
|
//
|
|
// fwrite( &nFileNameLength, sizeof(int), 1, fp );
|
|
// fwrite( strFileName.GetBuffer(0), nFileNameLength, 1, fp );
|
|
// fwrite( &cfi, sizeof(ClientFileInfo), 1, fp );
|
|
// }
|
|
//}
|