DragonNest/Client/DnLauncher/DnPatchThread.cpp

2678 lines
76 KiB
C++
Raw Normal View History

2024-12-19 09:48:26 +08:00
#include "stdafx.h"
#include "DnPatchThread.h"
#include "SundriesFunc.h"
#include "MD5Checksum.h"
#include "VarArg.h"
#include "fdi.h"
#include "fcntl.h"
#include <io.h>
#ifdef _USE_RTPATCH
#include "patchwin.h"
#endif // _USE_RTPATCH
#if defined(_KR_NEXON)
#include "DnServiceModule.h"
#endif // _KR_NEXON
#pragma comment (lib, "setupapi.lib")
#pragma comment (lib, "fdi.lib")
extern CString g_szOriginalCmdLine;
#if defined(_KR_NEXON)
extern WiseLog* g_pWiseLog;
#endif // _KR_NEXON
#ifndef _DEBUG
extern HANDLE g_hMutex;
#endif // _DEBUG
stDownloadInfoUpdateData g_DownloadInfoData; // <20><><EFBFBD>μ<EFBFBD><CEBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٿ<EFBFBD><D9BF>ε<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>°<EFBFBD><C2B0><EFBFBD> <20>б<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ÿ
//////////////////////////////////////////////////////////////////////////
// Thread Base Class
//////////////////////////////////////////////////////////////////////////
CThread::CThread() : m_nThreadID( 0 ), m_hHandleThread( INVALID_HANDLE_VALUE )
{
m_bThreadLoop = FALSE;
}
CThread::~CThread()
{
m_bThreadLoop = FALSE;
}
BOOL CThread::Start()
{
if( m_hHandleThread != INVALID_HANDLE_VALUE )
return FALSE;
m_hHandleThread = ::CreateThread( 0, 0, _Runner, ( LPVOID )this, 0, &m_nThreadID );
if( m_hHandleThread == 0 )
{
return FALSE;
}
m_bThreadLoop = TRUE;
return TRUE;
}
BOOL CThread::Terminate( DWORD nExitCode )
{
BOOL ret = FALSE;
if( m_hHandleThread == INVALID_HANDLE_VALUE )
return TRUE;
ret = ( ::TerminateThread( m_hHandleThread, nExitCode ) == TRUE );
m_hHandleThread = INVALID_HANDLE_VALUE;
return ret;
}
void CThread::SetThreadName( DWORD dwThreadID, const char* szThreadName )
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = szThreadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
__try
{
RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info );
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
}
}
BOOL CThread::WaitForTerminate( DWORD nTimeout )
{
if( m_hHandleThread == INVALID_HANDLE_VALUE )
return FALSE;
return ( ::WaitForSingleObject( m_hHandleThread, nTimeout ) == WAIT_OBJECT_0 );
}
DWORD WINAPI CThread::_Runner( LPVOID pParam )
{
CThread* pInstance = static_cast<CThread*>( pParam );
pInstance->Run();
return 0;
}
//////////////////////////////////////////////////////////////////////////
// "First" Patch Download Thread
//////////////////////////////////////////////////////////////////////////
CDnFistPatchDownloadThread * g_pFirstPatchDownloadThread = NULL;
FirstPatchReturn g_nFirstPatchErrorMessage = FPR_OK;
CDnFistPatchDownloadThread::CDnFistPatchDownloadThread()
: m_bTerminateThread( FALSE )
, m_hWnd( NULL )
{
g_pFirstPatchDownloadThread = this;
}
CDnFistPatchDownloadThread::~CDnFistPatchDownloadThread()
{
}
void CDnFistPatchDownloadThread::CloseThread()
{
TerminateThread();
}
BOOL CDnFistPatchDownloadThread::ProcessFullVersionPatch()
{
LogWnd::TraceLog( _T( "ProcessFullVersionPatch" ) );
#ifdef _FIRST_PATCH
g_nFirstPatchErrorMessage = FPR_NEED_FULLPATCH;
#endif
#if defined(_KR_NEXON)
if( g_pServiceModule )
g_pServiceModule->OnForceFullVersionPatch();
SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
return FALSE;
#else // _KR_NEXON
ErrorMessageBoxLog( _S( STR_PATCH_NEED_FULL_VERSION + DNPATCHINFO.GetLanguageOffset() ) );
SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
CloseThread();
return FALSE;
#endif // _KR_NEXON
}
void CDnFistPatchDownloadThread::Run()
{
FirstPatchReturn PatchResult = BegineModulePatch();
switch(PatchResult)
{
case FPR_OK:
{
// * <20><> <20>ѹ<EFBFBD> Pak<61><6B><EFBFBD>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD> *
if( !SaveModuleVersionToPak(DNFIRSTPATCHINFO.GetLocalModuleVersion()) )
{
ErrorMessageBoxLog( _S( STR_PATCH_FAILED + DNPATCHINFO.GetLanguageOffset() ) ); // <20><>ġ <20><><EFBFBD><EFBFBD>.
}
}
break;
case FPR_FAIL:
{
ErrorMessageBoxLog( _S( STR_PATCH_FAILED + DNPATCHINFO.GetLanguageOffset() ) ); // <20><>ġ <20><><EFBFBD><EFBFBD>.
CloseThread();
}
break;
case FPR_NEED_FULLPATCH:
{
ProcessFullVersionPatch();
}
break;
case FPR_LAUNCHER_PATCH:
{
ProcessRebootLauncher();
}
break;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ݱ<EFBFBD>
//CloseThread();
}
void CDnFistPatchDownloadThread::ProcessRebootLauncher()
{
// * <20><> <20>ѹ<EFBFBD> Pak<61><6B><EFBFBD>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD> *
BOOL bSaveResult = SaveModuleVersionToPak(DNFIRSTPATCHINFO.GetLocalModuleVersion());
if(bSaveResult)
{
//if( AfxMessageBox(_T("<22><>ó<EFBFBD><C3B3> <20><>ġ<EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD>ϴ<EFBFBD>.\n<><6E>ó<EFBFBD><C3B3> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>մϴ<D5B4>."), MB_OK, MB_ICONINFORMATION) == IDOK )
{
CString strParam = DNPATCHINFO.GetTotalParameter(); // <20>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>
CString strExeFile = DNPATCHINFO.GetClientPath(); // <20>ٿ<EFBFBD><D9BF>ε<EFBFBD> <20><><EFBFBD><EFBFBD>
strExeFile += DNLAUNCHER_NAME;
#ifdef _USE_COMMAND_LINE
ShellExecute( m_hWnd, NULL, strExeFile, g_szOriginalCmdLine.GetBuffer(), NULL, SW_SHOWNORMAL );
#else
ShellExecute( m_hWnd, NULL, strExeFile, strParam.GetBuffer(), NULL, SW_SHOWNORMAL );
#endif
KillMyProcess(_T(DNLAUNCHER_NAME)); // old<6C><64><EFBFBD>μ<EFBFBD><CEBC><EFBFBD> kill.
}
}
else
{
ErrorMessageBoxLog( _S( STR_PATCH_FAILED+DNPATCHINFO.GetLanguageOffset() ) );
}
}
FirstPatchReturn CDnFistPatchDownloadThread::BegineModulePatch()
{
BOOL bModuleResult = FALSE;
BOOL bLauncherResult = FALSE;
// "<22><><EFBFBD><EFBFBD>" <20><><EFBFBD><EFBFBD>.
int nDownServerVersion = DNPATCHINFO.GetServerVersion();
// "<22><><EFBFBD><EFBFBD>" <20><><EFBFBD><EFBFBD>.
int nLocalModuleVersion = DNFIRSTPATCHINFO.GetLocalModuleVersion();
LogWnd::TraceLog(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: [%d] / <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: [%d]"), nDownServerVersion, nLocalModuleVersion );
if( nLocalModuleVersion == nDownServerVersion ) // * <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ٸ<EFBFBD>, <20><><EFBFBD>̻<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> *
{
LogWnd::Log(LogLevel::Error, _T("ModulePatch - Version is Concur"));
return FPR_OK;
}
else if( nLocalModuleVersion > nDownServerVersion ) // * <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. Ǯ<><C7AE>ġ<EFBFBD><C4A1> <20>ѱ<EFBFBD> *
{
LogWnd::Log(LogLevel::Error, _T("ModulePatch - Version Check Failed, Go to FullPatch"));
return FPR_NEED_FULLPATCH;
}
else if( nLocalModuleVersion == -1 )
{
LogWnd::Log(LogLevel::Error, _T("ModulePatch - Module Version is -1"));
return FPR_NEED_FULLPATCH;
}
// * <20><>ġ <20><><EFBFBD><EFBFBD>! *
for( int i = nLocalModuleVersion ; i < nDownServerVersion ; )
{
if( i < nDownServerVersion )
{
i++;
// <20><><EFBFBD><EFBFBD> <20><>ġ
bModuleResult = DownLoadModulePatch(i); // FirstPatchList.txt <20>ٿ<EFBFBD><D9BF>ε<EFBFBD>.
if(bModuleResult) // FirstPatchList.txt<78><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵٸ<D1B4> <20><><EFBFBD><EFBFBD>.
{
if( !ParsingModuleList() ) // "FirstPatchList.txt" <20>Ľ<EFBFBD>
{
return FPR_FAIL;
}
if( !ChangeModuleFiles(i) ) // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
{
return FPR_FAIL;
}
}
// <20><>ó <20><>ġ
bLauncherResult = PatchLauncherFiles(i); // * Launcher.exe<78><65><EFBFBD><EFBFBD> <20>ٿ<EFBFBD><D9BF>ε<EFBFBD> & <20><><EFBFBD><EFBFBD> *
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. ( <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.. )
DNFIRSTPATCHINFO.SetLocalModuleVersion(i);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
CString szPath;
szPath = DNPATCHINFO.GetClientPath();
szPath += CLIENT_VERSION_NAME;
// version.cfg<66><67><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD>.
if( !SaveModuleVersionFileWithOutPakSave(szPath, i) )
{
return FPR_FAIL;
}
// DnLuancher.exe<78><65> <20><>ġ<EFBFBD><C4A1><EFBFBD>ٸ<EFBFBD>, <20><>ó <20><EFBFBD><E7B1B8>.
if( bLauncherResult )
{
return FPR_LAUNCHER_PATCH;
}
}
} // end of for
return FPR_OK;
}
BOOL CDnFistPatchDownloadThread::DownLoadModulePatch( int nVersion )
{
LogWnd::TraceLog( L"ModuleFile DownLoad Start" );
CString strVersion;
strVersion.Format( _T( "%08d" ), nVersion );
LogWnd::TraceLog( _T("Download Launcher Patch Version [%s]"), strVersion.GetBuffer() );
CString strUrl;
strUrl += DNPATCHINFO.GetPatchUrl();
strUrl += strVersion;
strUrl += _T("/FirstPatch/");
CString szPatchListUrl; // PatchURL / FirstPatch / FirstPatchList.txt
szPatchListUrl.Format( _T( "%s%s" ), strUrl.GetBuffer(), FIRSTPATCHLIST_NAME );
// Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
m_strPatchListFile.Format( _T( "%s%s" ), DNPATCHINFO.GetClientPath().GetBuffer() , FIRSTPATCHLIST_NAME);
BOOL bResult = DeleteUrlCacheEntry( szPatchListUrl.GetBuffer() );
HRESULT hr = DownloadToFile( szPatchListUrl.GetBuffer(), m_strPatchListFile.GetBuffer() );
// <20>ٿ<EFBFBD><D9BF>ε忡 <20><><EFBFBD><EFBFBD><EFBFBD>ߴٸ<DFB4>.
if( hr != S_OK )
{
LogWnd::TraceLog( _T("FirstPatch.txt Download Failed!") );
return FALSE;
}
LogWnd::TraceLog( L"FirstPatch.txt File Download Success" );
// <20><><EFBFBD><EFBFBD> <20>Ӽ<EFBFBD> üũ.
if( ::GetFileAttributes( m_strPatchListFile.GetBuffer() ) == -1 )
{
LogWnd::TraceLog( L"Failed! GetFileAttributes=[%s]", m_strPatchListFile.GetBuffer() );
return FALSE;
}
LogWnd::TraceLog( L"ModuleFile DownLoad End" );
return TRUE;
}
BOOL CDnFistPatchDownloadThread::PatchLauncherFiles( int nVersion )
{
LogWnd::TraceLog( _T("DnLauncher.exe FIle Download Start") );
CString strVersion;
strVersion.Format( _T( "%08d" ), nVersion );
CString strUrl;
strUrl += DNPATCHINFO.GetPatchUrl();
strUrl += strVersion;
strUrl += _T("/FirstPatch/");
// Down URL <20>ּ<EFBFBD>.
CString szPatchListUrl;
szPatchListUrl.Format( _T( "%s%s" ), strUrl.GetBuffer(), _T(DNLAUNCHER_NAME));
if( !IsExistFile( szPatchListUrl ) )
return FALSE;
// Client <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD> <20><><EFBFBD><EFBFBD>)
m_strPatchListFile.Format( _T( "%s%s" ), DNPATCHINFO.GetClientPath().GetBuffer() , _T(DNLAUNCHER_NAME));
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD><EFBFBD> exe<78><65> tmp<6D><70> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
if( _access(DNLAUNCHER_NAME , 0) == 0 )
{
MoveFile(_T(DNLAUNCHER_NAME), _T(DNLAUNCHER_NAME_TMP));
}
HRESULT hr = E_FAIL;
for(int i = 0 ; i < RETRY_MAX_COUNT ; ++i)
{
DeleteUrlCacheEntry( szPatchListUrl.GetBuffer() );
hr = DownloadToFile( szPatchListUrl.GetBuffer(), m_strPatchListFile.GetBuffer() );
if( hr == S_OK )
{
break;
}
}
LogWnd::TraceLog( _T("DnLauncher.exe FIle Download Success") );
// <20>ٿ<EFBFBD><D9BF>ε忡 <20><><EFBFBD><EFBFBD><EFBFBD>ߴٸ<DFB4>.
if( hr != S_OK )
{
MoveFile(_T(DNLAUNCHER_NAME_TMP), _T(DNLAUNCHER_NAME)); // 'tmp' ---> 'exe'<27><> <20>ٽ<EFBFBD> <20><><EFBFBD><EFBFBD>.
LogWnd::TraceLog( _T("Download DnLauncher.exe File Failed!") );
return FALSE;
}
// <20><><EFBFBD><EFBFBD> <20>Ӽ<EFBFBD> üũ.
if( ::GetFileAttributes( m_strPatchListFile.GetBuffer() ) == -1 )
{
LogWnd::TraceLog( L"Failed! GetFileAttributes=[%s]", m_strPatchListFile.GetBuffer() );
return FALSE;
}
return TRUE;
}
int CDnFistPatchDownloadThread::ParsingModuleList()
{
m_vecCopyList.clear();
m_vecDeleteList.clear();
//m_strPostPatchList.Format( _T( "%sFirstPatch%08d.txt" ), DNPATCHINFO.GetClientPath(), m_nServerModuleVersion ); // testLauncher/FirstPatch00000007.txt <20>̷<EFBFBD><CCB7><EFBFBD>.
HANDLE hFile = CreateFile( m_strPatchListFile.GetBuffer(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
LogWnd::TraceLog( _T("%s File Not Found"), m_strPatchListFile.GetBuffer() );
return FALSE;
}
char cPatchCode, szString[1024], *pFindPtr;
int nFileSize = GetFileSize( hFile, NULL );
char* pBuffer = new char [ nFileSize + 3 ]; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> pBuffer + 2 <20><> <20>Ŀ<EFBFBD> pBuffer <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̿<EFBFBD><CCBF><EFBFBD> strchr <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>.
memset( pBuffer, 0, nFileSize + 3 );
char* pBufferBackup = pBuffer;
DWORD dwReadSize;
ReadFile( hFile, pBuffer, nFileSize, &dwReadSize, NULL );
while( 1 )
{
cPatchCode = *pBuffer;
pBuffer += 2;
pFindPtr = strchr( pBuffer, 0x0d );
if( pFindPtr == NULL )
break;
if( (int)( pBuffer - pBufferBackup ) > (int)dwReadSize )
break;
*pFindPtr = 0;
strcpy_s( szString, 1024, pBuffer );
int nStrLength = ( int )strlen( szString );
if( ( szString[ nStrLength - 1 ] == 0x0d ) || ( ( szString[ nStrLength - 1 ] == 0x0a ) ) )
szString[ nStrLength - 1 ] = 0;
pBuffer += nStrLength + 1;
if( *pBuffer == 0x0a )
pBuffer++;
switch( cPatchCode )
{
case 'D':
m_vecDeleteList.push_back( szString );
break;
case 'C':
m_vecCopyList.push_back( szString );
break;
default:
assert( 0 && "Invalid Patch Code" );
SAFE_DELETE_ARRAY( pBufferBackup );
CloseHandle( hFile );
return FALSE;
}
}
CloseHandle( hFile );
SAFE_DELETE_ARRAY( pBufferBackup );
// PostPatchList.txt. <20><><EFBFBD>ϻ<EFBFBD><CFBB><EFBFBD>
DeleteFile(m_strPatchListFile);
return true;
}
int CDnFistPatchDownloadThread::ChangeModuleFiles(int nVer)
{
USES_CONVERSION;
CString strOriginalFileName,strBackUpFileName;
WCHAR wszFileName[_MAX_PATH];
std::vector<std::string>::iterator it = m_vecCopyList.begin();
for( ; it != m_vecCopyList.end() ; ++it )
{
// WCHAR<41><52> <20><>ȯ.
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (*it).c_str(), -1, wszFileName, _MAX_PATH);
// "DnLauncher.exe"<22><> <20><><EFBFBD>⼭ ó<><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
if( wcscmp(wszFileName, _T("DnLauncher.exe")) == 0 )
{
continue;
}
// 1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD≯<EFBFBD> <20><><EFBFBD><EFBFBD>.
strOriginalFileName.Format(_T("%s%s"), DNPATCHINFO.GetClientPath(), wszFileName);
strBackUpFileName.Format(_T("%s%s%s"), DNPATCHINFO.GetClientPath(), _T("BackUp_"), wszFileName);
rename(CT2A(strOriginalFileName), CT2A(strBackUpFileName));
// 2. <20><><EFBFBD>ο<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ٿ<EFBFBD><D9BF>ε<EFBFBD>.
m_strFirstPatchURLPath.Format(_T("%s%08d%s%s"), DNPATCHINFO.GetPatchUrl(), nVer, _T("/FirstPatch/"),wszFileName);
HRESULT hr;
for( int i = 0 ; i < RETRY_MAX_COUNT ; ++i )
{
DeleteUrlCacheEntry( m_strFirstPatchURLPath.GetBuffer() );
hr = DownloadToFile( m_strFirstPatchURLPath.GetBuffer(), CVarArg<__MAX_PATH>(wszFileName)); // DNPATCHINFO.GetClientPath().GetBuffer() );
if(hr == S_OK)
{
ClientDeleteFile(strBackUpFileName); // "BackUp_<70><5F><EFBFBD><EFBFBD>" <20><><EFBFBD><EFBFBD>.
break;
}
}
// 3. <20><><EFBFBD><EFBFBD> : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD> <20><><EFBFBD><EFBFBD>.
if( hr != S_OK )
{
rename(CT2A(strBackUpFileName), CT2A(strOriginalFileName)); // <20><><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
}
}
//-------------------------------------------
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ó<><C3B3>
//-------------------------------------------
std::vector<std::string>::iterator itDelete = m_vecDeleteList.begin();
for( ; itDelete != m_vecDeleteList.end() ; ++itDelete )
{
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (*itDelete).c_str(), _MAX_PATH, wszFileName, _MAX_PATH);
ClientDeleteFile(wszFileName);
}
return true;
}
BOOL CDnFistPatchDownloadThread::SaveModuleVersionToPak( int nVersion )
{
CString szFindPackingFile;
szFindPackingFile = DNPATCHINFO.GetClientPath();
szFindPackingFile += _T("Resource00.pak");
CEtPackingFile *pPackingFile = new CEtPackingFile();
char strVersion[256]={0,};
sprintf_s( strVersion, sizeof(strVersion), "version %d\r\nModule %d", DNPATCHINFO.GetClientVersion(), nVersion );
USES_CONVERSION;
char szTemp[ _MAX_PATH ] = {0,};
char StrVersionName[32]= "\\version.cfg";
WideCharToMultiByte( CP_ACP, 0, szFindPackingFile.GetBuffer(), -1, szTemp, _MAX_PATH, NULL, NULL );
// <20><>¿<EFBFBD><C2BF> <20><><EFBFBD><EFBFBD>. 512M <20>Ѿ<D1BE>°<EFBFBD><C2B0>߿<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0><EFBFBD><EFBFBD><EFBFBD>.
if( pPackingFile->OpenFileSystem( szTemp ) )
{
pPackingFile->Remove( StrVersionName );
pPackingFile->AddFile( StrVersionName, strVersion, sizeof(strVersion) );
}
else
{
AfxMessageBox( _T("Version can not be saved") );
SAFE_DELETE( pPackingFile );
return FALSE;
}
pPackingFile->CloseFileSystem();
SAFE_DELETE( pPackingFile );
return TRUE;
}
BOOL CDnFistPatchDownloadThread::SaveModuleVersionFile( CString& szFilePath, int nVersion )
{
if( !SaveModuleVersionToPak( nVersion ) )
{
return FALSE;
}
char* buffer = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
hFile = CreateFile( szFilePath.GetBuffer(), GENERIC_WRITE, FILE_SHARE_READ , NULL, CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL,NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
LogWnd::Log( LogLevel::Error, L"Save Version File Failed!" );
return FALSE;
}
char szVersion[ 256 ]= {0,};
DWORD dwWriteSize;
sprintf_s( szVersion, sizeof(szVersion), "Version %d\r\nModule %d", DNPATCHINFO.GetClientVersion(), nVersion );
WriteFile( hFile, szVersion,(int)strlen(szVersion)+1 , &dwWriteSize, NULL );
CloseHandle(hFile);
return TRUE;
}
BOOL CDnFistPatchDownloadThread::SaveModuleVersionFileWithOutPakSave( CString& szFilePath, int nVersion )
{
char* buffer = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
hFile = CreateFile( szFilePath.GetBuffer(), GENERIC_WRITE, FILE_SHARE_READ , NULL, CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL,NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
LogWnd::Log( LogLevel::Error, L"Save Version File Failed!" );
return FALSE;
}
char szVersion[ 256 ]= {0,};
DWORD dwWriteSize;
sprintf_s( szVersion, sizeof(szVersion), "Version %d\r\nModule %d", DNPATCHINFO.GetClientVersion(), nVersion );
WriteFile( hFile, szVersion,(int)strlen(szVersion)+1 , &dwWriteSize, NULL );
CloseHandle(hFile);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
// Patch Download Thread
//////////////////////////////////////////////////////////////////////////
CDnPatchDownloadThread* g_pPatchDownloadThread = NULL;
CSyncLock g_PatchThreadLock;
CDnPatchDownloadThread::CDnPatchDownloadThread()
: m_hHttpConnection( NULL )
, m_hWnd( NULL )
, m_bTerminateThread( FALSE )
, m_fRate( 0.0f )
, m_fPercent( 0.0f )
, m_nCurPatchCount( 0 )
, m_nTotalPatchCount( 0 )
, m_dwDownloadFileLength( 0 )
, m_dwTempFileLength( 0 )
, m_dwTotalBytes( 0 )
, m_dwTotalFileLength( 0 )
, m_emDownPatchState( PATCH_NONE )
{
g_pPatchDownloadThread = this;
}
CDnPatchDownloadThread::~CDnPatchDownloadThread()
{
m_bThreadLoop = FALSE;
m_vecPackingFile.clear();
m_vecDeleteList.clear();
m_vecPatchList.clear();
m_vecCopyList.clear();
m_vecReserveIndex.clear();
::TerminateThread( m_hHandleThread, 0 );
CloseHandle( m_hHandleThread );
WaitForTerminate( 1000 );
g_pPatchDownloadThread = NULL;
}
void CDnPatchDownloadThread::SendStatusMsg( DownloadPatchState nPatchState )
{
m_emDownPatchState = nPatchState;
if( m_hWnd )
PostMessage( m_hWnd, WM_STATUS_MSG, m_emDownPatchState, 0 );
}
void CDnPatchDownloadThread::Run()
{
LogWnd::TraceLog( L"<EFBFBD><EFBFBD>Patch Start!" );
if( m_hWnd == NULL )
return;
SetThreadName( m_nThreadID, "CDnPatchDownloadThread" );
ScopeLock<CSyncLock> lock( g_PatchThreadLock );
#if defined(_KR_NEXON)
if( g_pWiseLog ) g_pWiseLog->WriteToWiseLog( "versioncheckstart.aspx" );
#endif // _KR_NEXON
PatchReturn nRet = PR_FAIL;
nRet = BeginPatch();
switch( nRet )
{
case PR_OK:
{
LogWnd::TraceLog( L"<EFBFBD><EFBFBD>Patch Success!" );
SendStatusMsg( PATCH_COMPLETE );
#if defined(_KR_NEXON)
if( g_pWiseLog ) g_pWiseLog->SendWebPost( "patchend.aspx" );
#endif // _KR_NEXON
}
break;
case PR_LAUNCHER_PATCH:
{
LogWnd::TraceLog( _T( "<EFBFBD><EFBFBD>Launcher Restart because Launcher Patched."));
#ifndef _DEBUG
if( g_hMutex )
{
CloseHandle( g_hMutex );
g_hMutex = NULL;
}
#endif // _DEBUG
CString strExeFile = DNPATCHINFO.GetClientPath();
strExeFile += DNLAUNCHER_NAME;
ShellExecute( m_hWnd, NULL, strExeFile, g_szOriginalCmdLine.GetBuffer(), NULL, SW_SHOWNORMAL );
SendStatusMsg( PATCH_LAUNCHER );
}
break;
case PR_FULLPATCH:
{
ProcessFullVersionPatch();
}
break;
case PR_FAIL:
{
LogWnd::TraceLog( L"<EFBFBD><EFBFBD>Patch Failed!" );
SendStatusMsg( PATCH_FAILED );
}
break;
case PR_TERMINATE:
{
LogWnd::TraceLog( L"<EFBFBD><EFBFBD>Patch Terminate!" );
SendStatusMsg( PATCH_TERMINATE );
}
break;
}
}
PatchReturn CDnPatchDownloadThread::BeginPatch()
{
LogWnd::TraceLog( L"BeginPatch - Start" );
PatchReturn nRetValue = PR_FAIL;
SendStatusMsg( PATCH_CHECK_VERSION );
int nCurClientVersion = DNPATCHINFO.GetClientVersion();
int nCurServerVersion = DNPATCHINFO.GetServerVersion();
LogWnd::Log( LogLevel::Info, L"Patch Check Version (Client Ver:%d, Server Ver:%d)", nCurClientVersion, nCurServerVersion );
if( nCurClientVersion == -1 || nCurServerVersion == -1 ) // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD><EFBFBD> <20><><EFBFBD>ߴ<EFBFBD>. Ǯ<><C7AE>ġ<EFBFBD><C4A1> <20>Ѿ<D1BE><EEB0A1><EFBFBD>Ѵ<EFBFBD>.
{
LogWnd::TraceLog( _T("Version Check Failed Run Fullpatch Process"));
SendStatusMsg( PATCH_CHECK_VERSION_FAILED );
return PR_FULLPATCH;
}
#if defined(_KR_NEXON)
if( g_pWiseLog ) g_pWiseLog->WriteToWiseLog( "versioncheckend.aspx" );
#endif // _KR_NEXON
if( nCurClientVersion == nCurServerVersion ) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20>ʿ䰡 <20><><EFBFBD><EFBFBD>.
return PR_OK;
else if( nCurClientVersion > nCurServerVersion ) // Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<><C5A9> Ǯ<><C7AE>ġ
return PR_FULLPATCH;
else // Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ġ <20><><EFBFBD><EFBFBD>
{
int nDownVersion = nCurClientVersion + 1;
#if defined(_KR_NEXON)
if( g_pWiseLog ) g_pWiseLog->WriteToWiseLog("patchstart.aspx");
#endif // _KR_NEXON
for( int i=nDownVersion; i<=nCurServerVersion; i++ )
{
g_DownloadInfoData.m_nCurrentFileCount = i - nCurClientVersion;
g_DownloadInfoData.m_nTotalFileCount = nCurServerVersion - nCurClientVersion;
g_DownloadInfoData.m_nDownloadProgressMin = 0;
g_DownloadInfoData.m_nDownloadProgressMax = 100;
// <20>ѹ<EFBFBD><D1B9><EFBFBD>ġ <20><><EFBFBD><EFBFBD> <20>ٿ<EFBFBD><D9BF><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>׽<EFBFBD> üũ <20>ؼ<EFBFBD> <20><>ŵ<EFBFBD><C5B5> <20><><EFBFBD><EFBFBD><EFBFBD≯<EFBFBD> <20><>ŵ<EFBFBD>Ѵ<EFBFBD>.
std::vector<int>::iterator itSkip = std::find( DNPATCHINFO.GetSkipVersion().begin(), DNPATCHINFO.GetSkipVersion().end(), i );
if( itSkip != DNPATCHINFO.GetSkipVersion().end() )
{
CString szPath;
szPath = DNPATCHINFO.GetClientPath();
szPath += CLIENT_VERSION_NAME;
int gap = nCurServerVersion - i;
if( gap >= 1 ) //<2F><><EFBFBD><EFBFBD> <20><><EFBFBD>̰<EFBFBD> 2<>̻<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ѹ<EFBFBD><D1B9><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٷ<EFBFBD> <20>̵<EFBFBD>
{
DNPATCHINFO.SetClientVersion( i+1 );
SaveVersionFile( szPath, i+1 );
i++;
}
else
{
DNPATCHINFO.SetClientVersion( i );
SaveVersionFile( szPath, i );
}
continue;
}
SendStatusMsg( PATCH_DOWNLOAD_DATA );
int nFailCount = 0;
#ifdef _FIRST_PATCH
BOOL bOnlyFirstPatch = FALSE; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD>
#endif // _FIRST_PATCH
while(1)
{
BOOL bResult = DownLoadPatch( i );
if( bResult )
{
if( m_bTerminateThread ) return PR_TERMINATE; // <20>ٿ<EFBFBD><D9BF>ε<EFBFBD> <20>Ϸ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD> ó<><C3B3> <20>ȵǸ<C8B5> packing<6E><67><EFBFBD><EFBFBD> <20>Ѿ<D1BE><EEB0A1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD> <20>ɸ<EFBFBD>
break;
}
#ifdef _FIRST_PATCH
if( CheckExistFirstPatch( i ) ) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1> <20>ִ<EFBFBD> <20><>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> üũ
{
bOnlyFirstPatch = TRUE;
break;
}
#endif // _FIRST_PATCH
nFailCount++;
if( nFailCount < RETRY_MAX_COUNT )
{
SendStatusMsg( PATCH_DOWNLOAD_DATA );
}
else
{
if( i != nCurServerVersion )
{
// <20><>ġ <20>ٿ<EFBFBD><D9BF>ε<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>߰<EFBFBD>.. <20><><EFBFBD><EFBFBD> <20>ֽ<EFBFBD><D6BD><EFBFBD>ġ <20>ٿ<EFBFBD><D9BF>ε<EFBFBD><CEB5>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>
// <20>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><CCB6><EFBFBD> <20>̹<EFBFBD><CCB9><EFBFBD><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> Ǯ<><C7AE><EFBFBD><EFBFBD> <20>ٿ<EFBFBD><D9BF>ε<EFBFBD><CEB5><EFBFBD> <20>ѱ<EFBFBD><D1B1><EFBFBD>.
CString strPatchFileUrl;
strPatchFileUrl.Format( _T( "%s%08d/Patch%08d.txt" ), DNPATCHINFO.GetPatchUrl().GetBuffer(), nCurServerVersion, nCurServerVersion );
BOOL bResult = DeleteUrlCacheEntry( strPatchFileUrl.GetBuffer() );
HRESULT hr = URLDownload( strPatchFileUrl.GetBuffer(), DNPATCHINFO.GetClientPath().GetBuffer(), _T( "DownTest.tmp" ) );
if( hr == S_OK )
{
ClientDeleteFile( _T( "DownTest.tmp" ) );
LogWnd::TraceLog ( _T("Patch Version too Old Run Fullpatch Process"));
return PR_FULLPATCH;
}
}
LogWnd::TraceLog( _T( "%d Version Patch Download Failed!"), i );
return PR_FAIL;
}
if( m_bTerminateThread ) return PR_TERMINATE;
}
#ifdef _FIRST_PATCH
if( bOnlyFirstPatch ) continue;
#endif // _FIRST_PATCH
nRetValue = PreApplyPakPatch();
if( nRetValue != PR_OK )
return nRetValue;
g_DownloadInfoData.m_nDownloadProgressMin = 0;
g_DownloadInfoData.m_nDownloadProgressMax = 100;
SendStatusMsg( PATCH_APPLY_PAK_FILE ); // <20><>ġ <20><><EFBFBD>α׷<CEB1><D7B7><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>α׷<CEB1><D7B7><EFBFBD> Min/Max <20>ʱ<EFBFBD>ȭ
// <20><><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
nRetValue = ApplyPakPatch();
if( nRetValue == PR_TERMINATE )
break;
#ifdef _USE_RTPATCH
DeleteFolder( m_strRTPatchTempFolder.c_str() ); // RTPatch<63><68><EFBFBD><EFBFBD> <20>ӽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
#endif // _USE_RTPATCH
ClientDeleteFile( m_strPatchListFile.GetBuffer() ); // ApplyPak<61>Ϸ<EFBFBD> <20><> txt<78><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٷ<EFBFBD> <20><><EFBFBD><EFBFBD>
if( nRetValue == PR_OK || nRetValue == PR_LAUNCHER_PATCH )
{
ClientDeleteFile( m_strPatchFile.GetBuffer() ); // <20>ٿ<EFBFBD><D9BF>ε<EFBFBD> <20><><EFBFBD><EFBFBD> Pak<61><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Apply <20><><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD> <20><><EFBFBD><EFBFBD>
LogWnd::TraceLog( _T( "%d Version Patch Apply Success!"), i );
DNPATCHINFO.SetClientVersion( i );
SendStatusMsg( PATCH_APPLY_PAK_FILE_END );
CString szPath;
szPath = DNPATCHINFO.GetClientPath();
szPath += CLIENT_VERSION_NAME;
if( !SaveVersionFile( szPath, i ) ) // Version.cfg<66><67> <20>ٲ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
nRetValue = PR_FAIL;
break;
}
if( nRetValue == PR_LAUNCHER_PATCH ) // <20><>ó <20><>ġ<EFBFBD><C4A1> <20>Ǿ<EFBFBD><C7BE>ٸ<EFBFBD> <20>ߴ<EFBFBD><DFB4>ϰ<EFBFBD> <20><> <20><>ó<EFBFBD><C3B3> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ<EFBFBD>Ѵ<EFBFBD>.
break;
}
else // <20><>ġ<EFBFBD>ϴٰ<CFB4> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.. ÷<><C3B7><EFBFBD><EFBFBD> <20>ٽ<EFBFBD> <20><><EFBFBD>ƾ<EFBFBD> <20>ڴ<EFBFBD>..
{
SendStatusMsg( PATCH_APPLY_PAK_FILE_FAILED );
LogWnd::TraceLog( _T( "%d Version Patch Apply Failed!"), i );
return PR_FULLPATCH;
}
}
}
LogWnd::TraceLog( L"BeginPatch - End" );
return nRetValue;
}
BOOL CDnPatchDownloadThread::DownLoadPatch( int nVersion )
{
LogWnd::TraceLog( L"Patch Step 1 - DownloadPatch Start" );
CString strVersion;
strVersion.Format( _T( "%08d" ), nVersion );
LogWnd::TraceLog( _T("Download Patch Version [%s]"), strVersion.GetBuffer() );
CString strUrl;
strUrl += DNPATCHINFO.GetPatchUrl();
strUrl += strVersion;
strUrl += _T("/");
CString strPatchFileUrl, strPatchFileName;
strPatchFileUrl.Format( _T( "%sPatch%08d.pak" ), strUrl.GetBuffer(), nVersion );
strPatchFileName.Format( _T( "Patch%08d.pak" ), nVersion );
BOOL bResult = DeleteUrlCacheEntry( strPatchFileUrl.GetBuffer() );
HRESULT hr = URLDownload( strPatchFileUrl.GetBuffer(), DNPATCHINFO.GetClientPath().GetBuffer(), strPatchFileName.GetBuffer() );
if( hr != S_OK )
{
#ifdef _USE_SPLIT_COMPRESS_FILE
HRESULT hr = DownLoadSplitFile( strUrl, nVersion );
if( hr != S_OK )
{
LogWnd::Log( LogLevel::Error, L"Download Failed!");
return FALSE;
}
#else // _USE_SPLIT_COMPRESS_FILE
LogWnd::Log( LogLevel::Error, L"Download Failed!");
return FALSE;
#endif // _USE_SPLIT_COMPRESS_FILE
}
if( ::GetFileAttributes( m_strPatchFile.GetBuffer() ) == -1 )
{
LogWnd::Log( LogLevel::Error, L"Failed! GetFileAttributes=[%s]", m_strPatchFile.GetBuffer() );
return FALSE;
}
LogWnd::TraceLog( L"Download txt File");
CString szPatchListUrl;
szPatchListUrl.Format( _T( "%sPatch%08d.txt" ), strUrl.GetBuffer(), nVersion );
m_strPatchListFile.Format( _T( "%sPatch%08d.txt" ), DNPATCHINFO.GetClientPath().GetBuffer(), nVersion );
bResult = DeleteUrlCacheEntry( szPatchListUrl.GetBuffer() );
hr = DownloadToFile( szPatchListUrl.GetBuffer(), m_strPatchListFile.GetBuffer() );
if( hr != S_OK )
{
LogWnd::TraceLog( _T("Download txt File Failed!") );
return FALSE;
}
LogWnd::TraceLog( L"Download txt File Success" );
if( ::GetFileAttributes( m_strPatchListFile.GetBuffer() ) == -1 )
{
LogWnd::TraceLog( L"Failed! GetFileAttributes=[%s]", m_strPatchListFile.GetBuffer() );
return FALSE;
}
LogWnd::TraceLog( _T("Patch Step 1 - DownloadPatch End") );
return TRUE;
}
#ifdef _USE_SPLIT_COMPRESS_FILE
HRESULT CDnPatchDownloadThread::URLDownload( LPCTSTR strPatchFileUrl, LPCTSTR strFilePath, LPCTSTR strFileName,
BOOL bSplitDownload, DWORD dwAlreadyDownloadSize, DWORD dwRemainDownloadFileSize )
#else // _USE_SPLIT_COMPRESS_FILE
HRESULT CDnPatchDownloadThread::URLDownload( LPCTSTR strPatchFileUrl, LPCTSTR strFilePath, LPCTSTR strFileName )
#endif // _USE_SPLIT_COMPRESS_FILE
{
LogWnd::TraceLog( L"URLDownload Start" );
HINTERNET hInternetSession;
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
LogWnd::TraceLog( L"Open Internet Session" );
hInternetSession = InternetOpen( NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
if( hInternetSession == NULL )
{
LogWnd::Log( LogLevel::Error, L"Internet Session Open Failed!" );
return S_FALSE;
}
m_strPatchFileUrl = strPatchFileUrl;
m_strPatchFile.Format( L"%s%s", strFilePath, strFileName );
m_strPatchFileLocal.Format( L"%s.tmp", m_strPatchFile );
// <20>ٿ<EFBFBD><D9BF>ε<EFBFBD> <20>ޱ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> üũ
CFile file;
FileCheck filecheck;
DWORD dwDownloadFileSize;
#ifdef _USE_SPLIT_COMPRESS_FILE
filecheck = CheckPatchFile( hInternetSession, strFileName, file, dwDownloadFileSize, bSplitDownload );
#else // _USE_SPLIT_COMPRESS_FILE
filecheck = CheckPatchFile( hInternetSession, strFileName, file, dwDownloadFileSize );
#endif // _USE_SPLIT_COMPRESS_FILE
if( filecheck == FIlE_EXIST )
return S_OK;
else if( filecheck == FILE_FALSE )
return S_FALSE;
if( m_dwTempFileLength < dwDownloadFileSize )
{
// Http <20><><EFBFBD><EFBFBD>
LogWnd::TraceLog( L"Open Http Connection" );
CString strAddHeader;
strAddHeader.Format( L"Range:bytes=%d-\nCache-Control:no-cache\nPragma:no-cache", m_dwTempFileLength );
m_hHttpConnection = InternetOpenUrl( hInternetSession, m_strPatchFileUrl, strAddHeader, strAddHeader.GetLength(),
INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, 0 );
if( m_hHttpConnection == NULL )
{
LogWnd::Log( LogLevel::Error, L"Http Connection Open Failed!" );
file.Close(); // http connection error
InternetCloseHandle( hInternetSession );
return S_FALSE;
}
TCHAR szBuffer[MAX_PATH]={0,};
DWORD dwBufferSize = MAX_PATH;
DWORD dwIndex = 0;
// <20>ٿ<EFBFBD><D9BF>޾ƾ<DEBE> <20><> <20><><EFBFBD><EFBFBD> ũ<><C5A9> <20><><EFBFBD>ϱ<EFBFBD>
if( HttpQueryInfo( m_hHttpConnection, HTTP_QUERY_CONTENT_LENGTH, (LPVOID)&szBuffer, &dwBufferSize, &dwIndex ) != FALSE )
{
m_dwDownloadFileLength = (DWORD)_wtoi( szBuffer );
#ifdef _USE_SPLIT_COMPRESS_FILE
m_dwTotalFileLength = m_dwTempFileLength + m_dwDownloadFileLength + dwRemainDownloadFileSize;
#else // _USE_SPLIT_COMPRESS_FILE
m_dwTotalFileLength = m_dwTempFileLength + m_dwDownloadFileLength;
#endif // _USE_SPLIT_COMPRESS_FILE
}
LogWnd::TraceLog( L"DownLoad Left File Size : %d", m_dwDownloadFileLength );
// <20>ٿ<EFBFBD><D9BF>ε<EFBFBD> <20><><EFBFBD><EFBFBD> (<28>̾<EFBFBD><CCBE>ޱ<EFBFBD>)
if( m_dwDownloadFileLength > 0 )
{
LogWnd::TraceLog( L"Download File Start" );
DWORD dwRead, dwSize;
DWORD dwStartTick, dwCurrentTick;
m_dwTotalBytes = m_dwTempFileLength;
char szReadBuf[32768]; // 32KiB
dwStartTick = GetTickCount();
BOOL bError = FALSE;
do
{
if( m_bTerminateThread )
break;
if( !InternetQueryDataAvailable( m_hHttpConnection, &dwSize, 0, 0 ) )
{
LogWnd::Log( LogLevel::Error, L"InternetQueryDataAvailable : data not available!" );
bError = TRUE; // error "data not available!"
break;
}
if( !InternetReadFile( m_hHttpConnection, szReadBuf, dwSize, &dwRead ) )
{
LogWnd::Log( LogLevel::Error, L"InternetReadFile : reading file fail!" );
bError = TRUE; // error "reading file fail!"
break;
}
if( dwRead )
{
dwCurrentTick = GetTickCount();
file.Write( szReadBuf, dwRead );
m_dwTotalBytes += dwRead;
if( dwCurrentTick > dwStartTick )
{
float fDivideTick = static_cast<float>( dwCurrentTick - dwStartTick ) / 1000.0f;
m_fRate = static_cast<float>( m_dwTotalBytes ) / 1000.0f / fDivideTick;
m_fPercent = static_cast<float>( m_dwTotalBytes ) / static_cast<float> ( m_dwTotalFileLength ) * 100.0f;
}
#ifdef _USE_SPLIT_COMPRESS_FILE
g_DownloadInfoData.m_nDownloadProgressMin = m_dwTotalBytes + dwAlreadyDownloadSize;
#else // _USE_SPLIT_COMPRESS_FILE
g_DownloadInfoData.m_nDownloadProgressMin = m_dwTotalBytes;
#endif // _USE_SPLIT_COMPRESS_FILE
g_DownloadInfoData.m_nDownloadProgressMax = m_dwTotalFileLength;
g_DownloadInfoData.m_fDownloadRate = m_fRate;
// TRACE( L"Read : [%09d / %09d] --- [%4.2f KB/s] < %4.0f%% >\n", m_dwTotalBytes, m_dwTotalFileLength, m_fRate, m_fPercent );
}
} while( dwRead != 0 );
if( m_bTerminateThread || bError ) // <20>͹̳<CDB9><CCB3><EFBFBD>Ʈ <20>Ǿ<EFBFBD><C7BE>ų<EFBFBD> <20><>Ŷ<EFBFBD><C5B6><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
file.Close();
InternetCloseHandle( m_hHttpConnection );
InternetCloseHandle( hInternetSession );
m_hHttpConnection = NULL;
return S_FALSE;
}
LogWnd::TraceLog( L"Download File Success" );
}
InternetCloseHandle( m_hHttpConnection );
}
file.Close();
#ifdef _USE_SPLIT_COMPRESS_FILE
if( !bSplitDownload )
{
LogWnd::TraceLog( L"MD5 Check Start" );
// <20>ùٸ<C3B9><D9B8><EFBFBD> <20>ٿ<EFBFBD><D9BF>ε<EFBFBD> <20>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD><EFBFBD> MD5 Check
if( !GetMD5Checksum() )
{
LogWnd::Log( LogLevel::Error, L"MD5 Check Failed!" );
SendStatusMsg( PATCH_MD5_CHECK_FAILED );
ClientDeleteFile( m_strPatchFileLocal );
InternetCloseHandle( hInternetSession );
return S_FALSE; // md5 check error
}
LogWnd::TraceLog( L"MD5 Check Success" );
}
#else // _USE_SPLIT_COMPRESS_FILE
LogWnd::TraceLog( L"MD5 Check Start" );
// <20>ùٸ<C3B9><D9B8><EFBFBD> <20>ٿ<EFBFBD><D9BF>ε<EFBFBD> <20>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD><EFBFBD> MD5 Check
#ifndef _USA
if( !GetMD5Checksum() )
{
LogWnd::Log( LogLevel::Error, L"MD5 Check Failed!" );
SendStatusMsg( PATCH_MD5_CHECK_FAILED );
ClientDeleteFile( m_strPatchFileLocal );
InternetCloseHandle( hInternetSession );
return S_FALSE; // md5 check error
}
#endif
LogWnd::TraceLog( L"MD5 Check Success" );
#endif // _USE_SPLIT_COMPRESS_FILE
// <20><><EFBFBD><EFBFBD> tmp -> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ϸ<EFBFBD>
CString strNewPatchFileLocal = m_strPatchFileLocal.Left( m_strPatchFileLocal.GetLength() - 4 );
CFile::Rename( m_strPatchFileLocal, strNewPatchFileLocal );
InternetCloseHandle( hInternetSession );
LogWnd::TraceLog( L"URLDownload End" );
return S_OK;
}
#ifdef _USE_SPLIT_COMPRESS_FILE
FileCheck CDnPatchDownloadThread::CheckPatchFile( HINTERNET hInternetSession, LPCTSTR strFileName,
CFile& file, DWORD& dwDownloadFileSize, BOOL bSplitDownload )
#else // _USE_SPLIT_COMPRESS_FILE
FileCheck CDnPatchDownloadThread::CheckPatchFile( HINTERNET hInternetSession, LPCTSTR strFileName,
CFile& file, DWORD& dwDownloadFileSize )
#endif // _USE_SPLIT_COMPRESS_FILE
{
// <20>ٿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ũ<><C5A9> <20><><EFBFBD>ϱ<EFBFBD>
dwDownloadFileSize = GetDownloadFileSize( hInternetSession, m_strPatchFileUrl );
if( dwDownloadFileSize == 0 )
{
LogWnd::Log( LogLevel::Error, L"Get Download File Size Failed!" );
InternetCloseHandle( hInternetSession );
return FILE_FALSE;
}
LogWnd::TraceLog( L"Download Total File Size : %d", dwDownloadFileSize );
#ifdef _USE_SPLIT_COMPRESS_FILE
if( !bSplitDownload )
{
g_DownloadInfoData.m_strFileName = strFileName;
g_DownloadInfoData.m_nFileSize = dwDownloadFileSize;
}
#else // _USE_SPLIT_COMPRESS_FILE
g_DownloadInfoData.m_strFileName = strFileName;
g_DownloadInfoData.m_nFileSize = dwDownloadFileSize;
#endif // _USE_SPLIT_COMPRESS_FILE
// <20>ٿ<EFBFBD> <20>Ϸ<EFBFBD><CFB7><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȿ<EFBFBD><C8BF> <20>˻<EFBFBD>
LogWnd::TraceLog( L"Check Downloaded Temp File" );
CFileException e;
if( file.Open( m_strPatchFile, CFile::modeRead, &e ) )
{
DWORD dwFileLength = static_cast<DWORD>( file.GetLength() );
file.Close();
if( dwFileLength == dwDownloadFileSize ) // <20>̹<EFBFBD> <20><> <20>޾<EFBFBD><DEBE><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
LogWnd::Log( LogLevel::Error, L"Already Exist Download Temp File!" );
InternetCloseHandle( hInternetSession );
return FIlE_EXIST;
}
else // <20>޾<EFBFBD><DEBE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>ٽ<EFBFBD> <20><><EFBFBD><EFBFBD>
{
LogWnd::Log( LogLevel::Error, L"Already Exist Download Temp File But Delete Wrong File!" );
if( !ClientDeleteFile( m_strPatchFile ) )
{
InternetCloseHandle( hInternetSession );
return FILE_FALSE;
}
}
}
else
{
if( e.m_cause != CFileException::fileNotFound )
RecordFileExceptionLog( e );
}
// <20><><EFBFBD><EFBFBD> <20>ٿ<EFBFBD><D9BF>޴<EFBFBD> tmp <20><><EFBFBD><EFBFBD> üũ
FILE* fp;
fp = _wfopen( m_strPatchFileLocal, _T("r") );
UINT uiFileModeFlag = CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone;
if( fp != NULL ) // <20>ٿ<EFBFBD><D9BF>޴<EFBFBD> tmp<6D><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
fclose( fp );
uiFileModeFlag |= CFile::modeNoTruncate;
}
if( !file.Open( m_strPatchFileLocal, uiFileModeFlag, &e ) )
{
LogWnd::Log( LogLevel::Error, L"Downloaded Temp File Open Failed!" );
RecordFileExceptionLog( e );
InternetCloseHandle( hInternetSession );
return FILE_FALSE; // file open error
}
file.SeekToEnd();
m_dwTempFileLength = static_cast<DWORD>( file.GetLength() );
return FIlE_OK;
}
DWORD CDnPatchDownloadThread::GetDownloadFileSize( HINTERNET hInternetSession, CString strHttpPath )
{
if( hInternetSession == NULL )
return 0;
m_hHttpConnection = InternetOpenUrl( hInternetSession, strHttpPath, NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, 0 );
if( m_hHttpConnection == NULL )
return 0;
if( !IsExistFile( m_hHttpConnection ) )
{
LogWnd::Log( LogLevel::Error, L"Download File Is Not Exist!" );
InternetCloseHandle( m_hHttpConnection );
return 0;
}
TCHAR szBuffer[MAX_PATH]={0,};
DWORD dwBufferSize = MAX_PATH;
DWORD dwIndex = 0;
DWORD dwFileSize = 0;
// <20>ٿ<EFBFBD><D9BF>޾ƾ<DEBE> <20><> <20><><EFBFBD><EFBFBD> ũ<><C5A9> <20><><EFBFBD>ϱ<EFBFBD>
if( HttpQueryInfo( m_hHttpConnection, HTTP_QUERY_CONTENT_LENGTH, (LPVOID)&szBuffer, &dwBufferSize, &dwIndex ) != FALSE )
dwFileSize = (DWORD)_wtoi( szBuffer );
InternetCloseHandle( m_hHttpConnection );
return dwFileSize;
}
BOOL CDnPatchDownloadThread::GetMD5Checksum()
{
SendStatusMsg( PATCH_MD5_CHECK );
CString strHttpMD5 = m_strPatchFileUrl + L".MD5";
CString strLocalMD5 = m_strPatchFileLocal + L".MD5";
HRESULT hr = E_FAIL;
for( int i = 0 ; i < RETRY_MAX_COUNT ; i++ )
{
BOOL bResult = DeleteUrlCacheEntry( strHttpMD5 );
hr = DownloadToFile( strHttpMD5, strLocalMD5 );
if( hr == S_OK )
break;
}
if( FAILED( hr ) )
{
LogWnd::Log( LogLevel::Error, L"MD5 Check File Download Failed!, Error : %ld", hr );
return FALSE;
}
CString strDownloadChecksum;
CFile fileMD5;
CFileException e;
if( !fileMD5.Open( strLocalMD5, CFile::modeRead, &e ) )
return FALSE;
char pBuf[100];
fileMD5.Read( pBuf, 100 );
fileMD5.Close();
ClientDeleteFile( strLocalMD5 );
strDownloadChecksum = pBuf;
int nIndex = strDownloadChecksum.Find('\n');
strDownloadChecksum = strDownloadChecksum.Left( nIndex - 1 );
CString strLocalChecksum = CMD5Checksum::GetMD5( m_strPatchFileLocal );
// MD5 <20><><EFBFBD><EFBFBD>
return wcscmp( strLocalChecksum, strDownloadChecksum ) == 0 ? TRUE : FALSE;
}
BOOL CDnPatchDownloadThread::LoadPatchList()
{
m_vecPackingFile.clear();
m_vecDeleteList.clear();
m_vecPatchList.clear();
m_vecCopyList.clear();
HANDLE hFile = CreateFile( m_strPatchListFile.GetBuffer(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
LogWnd::TraceLog( _T("%s File Not Found"), m_strPatchListFile.GetBuffer() );
return FALSE;
}
char cPatchCode, szString[1024], *pFindPtr;
int nFileSize = GetFileSize( hFile, NULL );
char *pBuffer = new char [ nFileSize + 3 ]; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> pBuffer + 2 <20><> <20>Ŀ<EFBFBD> pBuffer <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̿<EFBFBD><CCBF><EFBFBD> strchr <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>.
memset( pBuffer, 0, nFileSize + 3 );
char *pBufferBackup = pBuffer;
DWORD dwReadSize;
ReadFile( hFile, pBuffer, nFileSize, &dwReadSize, NULL );
while( 1 )
{
cPatchCode = *pBuffer;
pBuffer += 2;
pFindPtr = strchr( pBuffer, 0x0d );
if( pFindPtr == NULL )
break;
if( (int)( pBuffer - pBufferBackup ) > (int)dwReadSize )
break;
*pFindPtr = 0;
strcpy_s( szString, 1024, pBuffer );
int nStrLength = ( int )strlen( szString );
if( ( szString[ nStrLength - 1 ] == 0x0d ) || ( ( szString[ nStrLength - 1 ] == 0x0a ) ) )
szString[ nStrLength - 1 ] = 0;
pBuffer += nStrLength + 1;
if( *pBuffer == 0x0a )
pBuffer++;
switch( cPatchCode )
{
case 'D':
m_vecDeleteList.push_back( szString );
break;
case 'C':
m_vecCopyList.push_back( szString );
break;
default:
assert( 0 && "Invalid Patch Code" );
SAFE_DELETE_ARRAY( pBufferBackup );
CloseHandle( hFile );
return FALSE;
}
}
CloseHandle( hFile );
SAFE_DELETE_ARRAY( pBufferBackup );
return TRUE;
}
PatchReturn CDnPatchDownloadThread::PreApplyPakPatch()
{
LogWnd::TraceLog( L"Patch Step 2 - PreApplyPakPatch Start" );
//<2F><>ġ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>о<EFBFBD><D0BE>´<EFBFBD>.
if( !LoadPatchList() )
{
ErrorMessageBoxLog( _S( STR_PATCH_STATE_LIST_NOT_READ + DNPATCHINFO.GetLanguageOffset() ) );
return PR_FAIL;
}
PatchReturn nRetValue = GetPackingFile(); // <20><><EFBFBD>ҽ<EFBFBD> <20><>ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ã<><C3A3> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if( m_vecPackingFile.empty() )
{
LogWnd::Log( LogLevel::Error, _T( "*.pak File Not Found!") );
return PR_FULLPATCH;
}
LogWnd::TraceLog( _T( "Patch Step 2 - PreApplyPakPatch End") );
return nRetValue;
}
PatchReturn CDnPatchDownloadThread::ApplyPakPatch()
{
LogWnd::TraceLog( L"Patch Step 3 - ApplyPakPatch Start" );
m_nCurPatchCount = 0;
m_nTotalPatchCount = 0;
char szTemp[__MAX_PATH] = {0,};
CEtPackingFile PatchSource;
WideCharToMultiByte( CP_ACP, 0, m_strPatchFile.GetBuffer(), -1, szTemp, __MAX_PATH, NULL, NULL );
if( !PatchSource.OpenFileSystem( szTemp, true ) )
return PR_FAIL;
PatchReturn nRetValue = ApplyDeleteList( PatchSource );
if( nRetValue != PR_OK )
return nRetValue;
#ifdef _USE_RTPATCH
char szString[_MAX_PATH];
CString strClientPath = DNPATCHINFO.GetClientPath();
strClientPath += "RTPatchFileTemp";
WideCharToMultiByte( CP_ACP, 0, strClientPath.GetBuffer(), -1, szString, _MAX_PATH, NULL, NULL );
m_strRTPatchTempFolder = szString;
DeleteFolder( m_strRTPatchTempFolder.c_str() );
CreateFolder( m_strRTPatchTempFolder.c_str() );
char strRTPatchPakFile[_MAX_PATH];
CString strFileName = DNPATCHINFO.GetClientPath();
strFileName += "RTPatchFileTemp\\RTPatch.pak";
WideCharToMultiByte( CP_ACP, 0, strFileName.GetBuffer(), -1, strRTPatchPakFile, _MAX_PATH, NULL, NULL );
CEtPackingFile RTPatchSource;
if( !RTPatchSource.NewFileSystem( strRTPatchPakFile ) )
return PR_FAIL;
nRetValue = ApplyRTPatch( PatchSource, RTPatchSource );
if( nRetValue != PR_OK )
return PR_FAIL;
PatchSource.CloseFileSystem();
nRetValue = ApplyPatchList( RTPatchSource );
if( nRetValue != PR_OK )
return nRetValue;
nRetValue = ApplyCopyList( RTPatchSource );
RTPatchSource.CloseFileSystem();
#else // _USE_RTPATCH
nRetValue = ApplyPatchList( PatchSource );
if( nRetValue != PR_OK )
return nRetValue;
nRetValue = ApplyCopyList( PatchSource );
#endif // _USE_RTPATCH
for( int i=0; i<(int)m_vecPackingFile.size(); i++ )
{
m_vecPackingFile[ i ]->CloseFileSystem();
SAFE_DELETE(m_vecPackingFile[i]);
}
#ifndef _USE_RTPATCH
PatchSource.CloseFileSystem();
#endif // _USE_RTPATCH
LogWnd::TraceLog( _T( "Patch Step 3 - ApplyPakPatch End") );
return nRetValue;
}
PatchReturn CDnPatchDownloadThread::GetPackingFile()
{
LogWnd::TraceLog( L"GetPackingFile" );
PatchReturn nRetValue = PR_OK;
char szTemp[__MAX_PATH] = {0,};
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
CString szFindPackingFile;
szFindPackingFile = DNPATCHINFO.GetClientPath();
szFindPackingFile += "Resource*.pak";
hFind = FindFirstFile( szFindPackingFile.GetBuffer(), &FindFileData );
while( hFind != INVALID_HANDLE_VALUE )
{
if( !( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
{
CString szPackingFile;
szPackingFile = DNPATCHINFO.GetClientPath();
szPackingFile += FindFileData.cFileName;
CEtPackingFile *pPackingFile = new CEtPackingFile();
char szTemp[__MAX_PATH] = {0,};
WideCharToMultiByte( CP_ACP, 0, szPackingFile.GetBuffer(), -1, szTemp, __MAX_PATH, NULL, NULL );
if( pPackingFile->OpenFileSystem( szTemp ) )
{
m_vecPackingFile.push_back( pPackingFile );
}
else
{
if( pPackingFile->OpenFileSystem( szTemp ) )
{
m_vecPackingFile.push_back( pPackingFile );
}
else
{
LogWnd::Log( LogLevel::Error, L"%s Packing File System Open Failed!", szPackingFile );
SAFE_DELETE( pPackingFile );
nRetValue = PR_FAIL;
}
}
}
if( !FindNextFile( hFind, &FindFileData ) ) break;
if( m_bTerminateThread )
{
for( int m=0; m<(int)m_vecPackingFile.size(); m++ )
{
m_vecPackingFile[m]->CloseFileSystem();
SAFE_DELETE( m_vecPackingFile[m] );
}
return PR_TERMINATE;
}
}
FindClose( hFind );
return nRetValue;
}
PatchReturn CDnPatchDownloadThread::ApplyDeleteList( CEtPackingFile& PatchSource )
{
LogWnd::TraceLog( L"ApplyDeleteList" );
m_nTotalPatchCount = (int)m_vecDeleteList.size() + PatchSource.GetFileCount();
for( int i=0; i<(int)m_vecDeleteList.size(); i++ )
{
char szPath[__MAX_PATH+100], szFileName[__MAX_PATH+100], szDelFile[__MAX_PATH] ={ 0,};
_GetPath( szPath, sizeof(szPath), m_vecDeleteList[ i ].c_str() );
_GetFullFileName( szFileName, sizeof(szFileName), m_vecDeleteList[ i ].c_str() );
BOOL bIsNoramlFile = TRUE;
for( int j=0; j<(int)m_vecPackingFile.size(); j++ )
{
m_vecPackingFile[j]->ChangeDir( "\\" );
if( szPath[0] )
m_vecPackingFile[j]->ChangeDir( szPath );
if( m_vecPackingFile[j]->Remove( szFileName ) )
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ϸ<EFBFBD> <20>Ѿ<D1BE><EEB0A3>.
m_nCurPatchCount++;
g_DownloadInfoData.m_nDownloadProgressMin = m_nCurPatchCount;
g_DownloadInfoData.m_nDownloadProgressMax = m_nTotalPatchCount;
bIsNoramlFile = FALSE;
break;
}
}
if( bIsNoramlFile )
{
#ifdef _TEST // <20>׽<EFBFBD>Ʈ<EFBFBD><C6AE> <20><>ó<EFBFBD><C3B3> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ΰ<EFBFBD> <20><><EFBFBD>Ƿ<EFBFBD> <20><><EFBFBD>õ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> <20>Ʒ<EFBFBD>ó<EFBFBD><C3B3> ó<><C3B3>
TCHAR szCurDir[ _MAX_PATH ]={0,};
GetCurrentDirectory( _MAX_PATH, szCurDir );
SetCurrentDirectory( DNPATCHINFO.GetClientPath() );
#endif // _TEST
//<2F>Ϲ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>߰<EFBFBD>.
char CheckExe[256]={0 ,};
_GetExt( CheckExe, sizeof(CheckExe), m_vecDeleteList[i].c_str() );
if( strlen( CheckExe ) == 0 )
{
DeleteFolder( m_vecDeleteList[i].c_str() );
}
else
{
DeleteFileA( CVarArgA<MAX_PATH>(".\\%s", m_vecDeleteList[ i ].c_str()) );
m_nCurPatchCount++;
g_DownloadInfoData.m_nDownloadProgressMin = m_nCurPatchCount;
g_DownloadInfoData.m_nDownloadProgressMax = m_nTotalPatchCount;
}
#ifdef _TEST
SetCurrentDirectory( szCurDir );
#endif // _TEST
}
if( m_bTerminateThread )
{
for( int m=0; m<(int)m_vecPackingFile.size(); m++ )
{
m_vecPackingFile[ m ]->CloseFileSystem();
SAFE_DELETE(m_vecPackingFile[ m ]);
}
PatchSource.CloseFileSystem();
return PR_TERMINATE;
}
}
return PR_OK;
}
PatchReturn CDnPatchDownloadThread::PatchFileExist( int nPatchFileCount, CEtPackingFile& PatchSource, SPackingFileInfo* pFileInfo, BOOL& bPatch )
{
if( pFileInfo == NULL )
return PR_FAIL;
for( int i=0; i<(int)m_vecPackingFile.size(); i++ )
{
int nFindIndex = m_vecPackingFile[i]->FindFile( pFileInfo->szFileName );
if( nFindIndex != -1 )
{
SPackingFileInfo *pFindFileInfo = m_vecPackingFile[i]->GetFileInfo( nFindIndex );
if( pFindFileInfo->dwAllocSize >= pFileInfo->dwCompressSize )
{
CEtFileHandle *pFileHandle = PatchSource.OpenOnly( pFileInfo->szFileName );
if( pFileHandle == NULL )
return PR_FAIL;
m_vecPackingFile[i]->RemoveFileInfo( nFindIndex );
int nFindEmptyIndex = m_vecPackingFile[i]->FindSuitableEmptySpace( pFileInfo->dwCompressSize );
if( nFindEmptyIndex == -1 ) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ɱ<EFBFBD>
{
stFileIndexSet fileIndex;
fileIndex.m_dwPakFileNum = i;
fileIndex.m_dwPatchFileIndex = nPatchFileCount;
fileIndex.m_dwReserveFileIndex = m_vecPackingFile[i]->ReservePatchFile( pFileInfo );
m_vecReserveIndex.push_back( fileIndex );
}
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִٸ<D6B4> <20><>ġ
{
if( !m_vecPackingFile[i]->PatchFileIndex( pFileHandle, nFindEmptyIndex ) )
{
LogWnd::Log( LogLevel::Error, L"Patch File Failed!" );
PatchSource.CloseFile( pFileHandle );
return PR_FAIL;
}
}
PatchSource.CloseFile( pFileHandle );
bPatch = TRUE;
}
else // <20><>ġ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<><20><> Ŭ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
// <20><>ä <20><>ŷ <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD> <20>õ<EFBFBD><C3B5>ϵ<EFBFBD><CFB5><EFBFBD> <20>ٲ<EFBFBD>
BOOL bRemove = FALSE;
for( int j=0; j<(int)m_vecPackingFile.size(); j++ )
{
if( m_vecPackingFile[j]->Remove( pFileInfo->szFileName ) )
bRemove = TRUE;
}
if( !bRemove )
{
LogWnd::Log( LogLevel::Error, L"Remove File Failed!" );
return PR_FAIL;
}
}
break;
}
}
return PR_OK;
}
PatchReturn CDnPatchDownloadThread::PatchFileSuitableSpace( CEtPackingFile& PatchSource, SPackingFileInfo* pFileInfo, BOOL& bPatch )
{
if( pFileInfo == NULL )
return PR_FAIL;
for( int j=0; j<(int)m_vecPackingFile.size(); j++ )
{
int nFindIndex = m_vecPackingFile[j]->FindSuitableEmptySpace( pFileInfo->dwCompressSize );
if( nFindIndex != -1 )
{
CEtFileHandle *pFileHandle = PatchSource.OpenOnly( pFileInfo->szFileName );
if( pFileHandle == NULL )
return PR_FAIL;
if( !m_vecPackingFile[j]->PatchFileIndex( pFileHandle, nFindIndex ) )
{
LogWnd::Log( LogLevel::Error, L"Patch File Failed!" );
PatchSource.CloseFile( pFileHandle );
return PR_FAIL;
}
PatchSource.CloseFile( pFileHandle );
bPatch = TRUE;
break;
}
}
return PR_OK;
}
void CDnPatchDownloadThread::PatchFileReserve( int nPatchFileCount, SPackingFileInfo* pFileInfo )
{
// <20><>ġ<EFBFBD><C4A1> <20><>ġ<EFBFBD><C4A1> ã<><C3A3> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> ã<>Ƽ<EFBFBD> <20>־<EFBFBD><D6BE>ش<EFBFBD>
int nBestIndex = -1;
DWORD dwMinSize = ULONG_MAX;
for( int j=0; j<(int)m_vecPackingFile.size(); j++ )
{
DWORD dwPackingFileSize = m_vecPackingFile[j]->GetFileSystemSize();
// 512<31>ް<EFBFBD> <20><><EFBFBD>ٴ<EFBFBD> <20>۾ƾ<DBBE> <20>о<EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>
if( ( dwPackingFileSize < dwMinSize ) && ( dwPackingFileSize < (DWORD)DEFAULT_PACKING_FILE_SIZE ) )
{
dwMinSize = dwPackingFileSize;
nBestIndex = j;
}
}
if( nBestIndex == -1 )
{
// <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ο<EFBFBD> <20><>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
int nStartFileIndex = ( int )m_vecPackingFile.size();
while( 1 )
{
HANDLE hFind;
WIN32_FIND_DATA FindFileData;
CString szNewPackingFile;
char szTemp[__MAX_PATH] = {0,};
szNewPackingFile.Format( _T( "%sResource%02d.pak" ), DNPATCHINFO.GetClientPath().GetBuffer(), nStartFileIndex );
hFind = FindFirstFile( szNewPackingFile.GetBuffer(), &FindFileData );
if( hFind == INVALID_HANDLE_VALUE )
{
WideCharToMultiByte( CP_ACP, 0, szNewPackingFile.GetBuffer(), -1, szTemp, __MAX_PATH, NULL, NULL );
CEtPackingFile *pNewPackingFile = new CEtPackingFile();
pNewPackingFile->NewFileSystem( szTemp );
m_vecPackingFile.push_back( pNewPackingFile );
nBestIndex = (int)m_vecPackingFile.size() - 1;
break;
}
nStartFileIndex++;
FindClose( hFind );
}
}
if( nBestIndex != -1 )
{
stFileIndexSet fileIndex;
fileIndex.m_dwPakFileNum = nBestIndex;
fileIndex.m_dwPatchFileIndex = nPatchFileCount;
fileIndex.m_dwReserveFileIndex = m_vecPackingFile[ nBestIndex ]->ReservePatchFile( pFileInfo );
m_vecReserveIndex.push_back( fileIndex );
}
}
PatchReturn CDnPatchDownloadThread::ApplyPatchList( CEtPackingFile& PatchSource )
{
LogWnd::TraceLog( L"ApplyPatchList" );
m_vecReserveIndex.clear();
int nPatchFileCount = PatchSource.GetFileCount();
for( int i=0; i<nPatchFileCount; i++ )
{
BOOL bSkip = FALSE;
SPackingFileInfo* pFileInfo = PatchSource.GetFileInfo( i );
if( pFileInfo == NULL )
continue;
for( int j=0; j<(int)m_vecCopyList.size(); j++ )
{
// <20><><EFBFBD><EFBFBD><EFBFBD≯<EFBFBD> <20>տ<EFBFBD>.. \ <20>پ<EFBFBD> <20>־ <20>װ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ȴ<EFBFBD>.
// ī<>Ǹ<EFBFBD><C7B8><EFBFBD>Ʈ<EFBFBD><C6AE> <20>ִ°<D6B4><C2B0><EFBFBD> <20>ѿ<EFBFBD> <20><><EFBFBD><EFBFBD><EEB0A1> <20>ȵ<EFBFBD> <20>н<EFBFBD>
if( _stricmp( m_vecCopyList[j].c_str(), pFileInfo->szFileName + 1 ) == 0 )
{
bSkip = TRUE;
break;
}
}
if( bSkip )
continue;
BOOL bPatch = FALSE;
if( PatchFileExist( i, PatchSource, pFileInfo, bPatch ) == PR_FAIL ) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>˻<EFBFBD><CBBB>ؼ<EFBFBD> <20><>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> <20><>ġ
return PR_FAIL;
if( !bPatch )
{
if( PatchFileSuitableSpace( PatchSource, pFileInfo, bPatch ) == PR_FAIL ) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִٸ<D6B4> <20>װ<EFBFBD><D7B0><EFBFBD> <20><>ġ
return PR_FAIL;
if( !bPatch )
PatchFileReserve( i, pFileInfo ); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Pak<61><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ڿ<EFBFBD> <20><><EFBFBD>̱<EFBFBD> <20><><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD><20>ɾ<EFBFBD><C9BE><EFBFBD>
}
if( bPatch )
{
m_nCurPatchCount++;
g_DownloadInfoData.m_nDownloadProgressMin = m_nCurPatchCount;
g_DownloadInfoData.m_nDownloadProgressMax = m_nTotalPatchCount;
}
if( m_bTerminateThread )
{
for( int m=0; m<(int)m_vecPackingFile.size(); m++ )
{
m_vecPackingFile[m]->CloseFileSystem();
SAFE_DELETE(m_vecPackingFile[m]);
}
PatchSource.CloseFileSystem();
return PR_TERMINATE;
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ΰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Write
for( int j=0; j<(int)m_vecPackingFile.size(); j++ )
m_vecPackingFile[ j ]->WriteReserveFileInfo();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1><EFBFBD>ϵ<EFBFBD> <20><>ġ
std::vector<stFileIndexSet>::iterator iter = m_vecReserveIndex.begin();
for( ; iter != m_vecReserveIndex.end(); iter++ )
{
SPackingFileInfo* pFileInfo = PatchSource.GetFileInfo( (*iter).m_dwPatchFileIndex );
CEtFileHandle* pFileHandle = PatchSource.OpenOnly( pFileInfo->szFileName );
if( pFileHandle == NULL )
return PR_FAIL;
if( !m_vecPackingFile[ (*iter).m_dwPakFileNum ]->PatchFileIndex( pFileHandle, (*iter).m_dwReserveFileIndex, FALSE ) ) // <20>̹<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FileInfo<66>̹Ƿ<CCB9> FileInfo <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
LogWnd::Log( LogLevel::Error, L"Patch File Failed!" );
PatchSource.CloseFile( pFileHandle );
return PR_FAIL;
}
PatchSource.CloseFile( pFileHandle );
m_nCurPatchCount++;
g_DownloadInfoData.m_nDownloadProgressMin = m_nCurPatchCount;
g_DownloadInfoData.m_nDownloadProgressMax = m_nTotalPatchCount;
}
return PR_OK;
}
PatchReturn CDnPatchDownloadThread::ApplyCopyList( CEtPackingFile& PatchSource )
{
PatchReturn nRetValue = PR_OK;
LogWnd::TraceLog( L"ApplyCopyList" );
#ifdef _TEST // <20>׽<EFBFBD>Ʈ<EFBFBD><C6AE> <20><>ó<EFBFBD><C3B3> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ΰ<EFBFBD> <20><><EFBFBD>Ƿ<EFBFBD> <20><><EFBFBD>õ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> <20>Ʒ<EFBFBD>ó<EFBFBD><C3B3> ó<><C3B3>
TCHAR szCurDirectory[ _MAX_PATH ]={0,};
GetCurrentDirectory( _MAX_PATH, szCurDirectory );
SetCurrentDirectory( DNPATCHINFO.GetClientPath() );
#endif // _TEST
for( int i=0; i<(int)m_vecCopyList.size(); i++ )
{
//<2F>Ѿȿ<D1BE><C8BF><EFBFBD> \ <20><><EFBFBD>Ͼտ<CFBE> <20>ٱ⋪<D9B1><E28BAA> <20>񱳸<EFBFBD><F1B1B3B8><EFBFBD><EFBFBD>ؼ<EFBFBD> <20>ٿ<EFBFBD><D9BF>ش<EFBFBD>.
char szAddCopyListName[_MAX_PATH]={0,};
sprintf_s( szAddCopyListName, "\\%s", m_vecCopyList[ i ].c_str() );
CEtFileHandle *pFileHandle = PatchSource.OpenFile( szAddCopyListName );
if( pFileHandle )
{
char szPath[__MAX_PATH] = {0,};
char szCurDir[__MAX_PATH] = {0,};
int nSize1 = (int)strlen( szPath );
int nSize2 = (int)strlen( m_vecCopyList[i].c_str() );
if ( nSize1 > _MAX_PATH || nSize2 > _MAX_PATH )
LogWnd::TraceLog( _T( "nSize1 > _MAX_PATH || nSize2 > _MAX_PATH ") );
_GetPath( szPath, sizeof(szPath), m_vecCopyList[i].c_str() );
RemoveSpaceA( m_vecCopyList[i] );
if( _stricmp( m_vecCopyList[i].c_str(), DNLAUNCHER_NAME ) == NULL )
{
ClientDeleteFile( _T( DNLAUNCHER_NAME_TMP ) );
// DNLAUNCHER_NAME<4D><45> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD><D8BE>ϸ<EFBFBD>, DNLAUNCHER_NAME<4D><45> DNLAUNCHER_NAME_TMP<4D><50> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
if( _access( DNLAUNCHER_NAME, 0 ) == 0 && MoveFile( _T( DNLAUNCHER_NAME ), _T( DNLAUNCHER_NAME_TMP ) ) == 0 ) // <20><>ó <20><><EFBFBD>ϸ<EFBFBD><CFB8><EFBFBD> <20>ٲٰ<D9B2> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD> <20><>ó<EFBFBD><C3B3>ġ<EFBFBD><C4A1> <20>ǵ<EFBFBD><C7B5><EFBFBD> <20><>
{
CString strError;
strError.Format( L"%s %d", _S( STR_LAUNCHER_PATCH_FAIL + DNPATCHINFO.GetLanguageOffset() ), 1 );
ErrorMessageBoxLog( strError );
PatchSource.CloseFile( pFileHandle );
PatchSource.CloseFileSystem();
LogWnd::Log( LogLevel::Error, _T( "Launcher Patch Failed!") );
return PR_FAIL;
}
LogWnd::TraceLog( _T( "Apply Launcher Patch") );
nRetValue = PR_LAUNCHER_PATCH;
}
if( szPath[0] )
{
CreateFolder( szPath );
GetCurrentDirectoryA( __MAX_PATH, szCurDir );
char szTemp[ __MAX_PATH ] = {0,} ;
strcpy_s( szTemp, __MAX_PATH, szCurDir );
strcat_s( szTemp, __MAX_PATH, "\\" );
strcat_s( szTemp, __MAX_PATH, szPath );
SetCurrentDirectoryA( szTemp );
}
#if defined(_KR_NEXON)
if( _stricmp( m_vecCopyList[i].c_str(), "nmcogame.dll" ) == NULL )
MoveFile( _T( "nmcogame.dll" ), _T( "nmcogame.tmp" ) );
if( _stricmp( m_vecCopyList[i].c_str(), "nmconew.dll" ) == NULL )
MoveFile( _T( "nmconew.dll" ), _T( "nmconew.tmp" ) );
#endif // _KR_NEXON
if( !pFileHandle->ExportFile() )
{
if( _stricmp( pFileHandle->GetFileContext()->szFileName, DNLAUNCHER_NAME ) == 0 )
{
CString strError;
strError.Format( L"%s %d", _S( STR_LAUNCHER_PATCH_FAIL + DNPATCHINFO.GetLanguageOffset() ), 2 );
ErrorMessageBoxLog( strError );
}
else
ErrorMessageBoxLog( _S( STR_FILE_COPY_FAIL + DNPATCHINFO.GetLanguageOffset() ) );
LogWnd::TraceLog( _T( "%s File Copy Failed! (%d)"), pFileHandle->GetFileContext()->szFileName, GetLastError() );
PatchSource.CloseFile( pFileHandle );
PatchSource.CloseFileSystem();
return PR_FAIL;
}
if( szPath[0] )
SetCurrentDirectoryA( szCurDir );
PatchSource.CloseFile( pFileHandle );
#if defined(_KR_NEXON)
if( _stricmp( m_vecCopyList[i].c_str(), "nmcogame.dll" ) == NULL )
MoveFile( _T( "nmcogame.dll" ), _T( "nmcogame.new" ) );
if( _stricmp( m_vecCopyList[i].c_str(), "nmconew.dll" ) == NULL )
MoveFile( _T( "nmconew.dll" ), _T( "nmconew.new" ) );
#endif // _KR_NEXON
m_nCurPatchCount++;
g_DownloadInfoData.m_nDownloadProgressMin = m_nCurPatchCount;
g_DownloadInfoData.m_nDownloadProgressMax = m_nTotalPatchCount;
if( m_bTerminateThread )
{
for( int m=0; m<(int)m_vecPackingFile.size(); m++ )
{
m_vecPackingFile[m]->CloseFileSystem();
SAFE_DELETE(m_vecPackingFile[m]);
}
PatchSource.CloseFileSystem();
return PR_TERMINATE;
}
}
}
#ifdef _TEST
SetCurrentDirectory( szCurDirectory );
#endif // _TEST
return nRetValue;
}
BOOL CDnPatchDownloadThread::ProcessFullVersionPatch()
{
LogWnd::TraceLog( _T( "ProcessFullVersionPatch" ) );
#if defined(_KR_NEXON)
if( g_pServiceModule )
g_pServiceModule->OnForceFullVersionPatch();
SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
return FALSE;
#else // _KR_NEXON
ErrorMessageBoxLog( _S( STR_PATCH_NEED_FULL_VERSION + DNPATCHINFO.GetLanguageOffset() ) );
SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
return FALSE;
#endif // _KR_NEXON
}
BOOL CDnPatchDownloadThread::SaveNewVersionToPak( int nVersion )
{
CString szFindPackingFile;
szFindPackingFile = DNPATCHINFO.GetClientPath();
szFindPackingFile += _T("Resource00.pak");
CEtPackingFile *pPackingFile = new CEtPackingFile();
char strVersion[256]={0,};
//sprintf_s( strVersion, sizeof(strVersion), "version %d", nVersion );
sprintf_s( strVersion, sizeof(strVersion), "version %d\r\nModule %d", nVersion , DNFIRSTPATCHINFO.GetLocalModuleVersion() );
USES_CONVERSION;
char szTemp[ _MAX_PATH ] = {0,};
char StrVersionName[32]= "\\version.cfg";
WideCharToMultiByte( CP_ACP, 0, szFindPackingFile.GetBuffer(), -1, szTemp, _MAX_PATH, NULL, NULL );
// <20><>¿<EFBFBD><C2BF> <20><><EFBFBD><EFBFBD>. 512M <20>Ѿ<D1BE>°<EFBFBD><C2B0>߿<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0><EFBFBD><EFBFBD><EFBFBD>.
if( pPackingFile->OpenFileSystem( szTemp ) )
{
pPackingFile->Remove( StrVersionName );
pPackingFile->AddFile( StrVersionName, strVersion, sizeof(strVersion) );
}
else
{
AfxMessageBox( _T("Version can not be saved") );
SAFE_DELETE( pPackingFile );
return FALSE;
}
pPackingFile->CloseFileSystem();
SAFE_DELETE( pPackingFile );
return TRUE;
}
BOOL CDnPatchDownloadThread::SaveVersionFile( CString& szFilePath, int nVersion )
{
if( !SaveNewVersionToPak( nVersion ) )
return FALSE;
char* buffer = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
hFile = CreateFile( szFilePath.GetBuffer(), GENERIC_WRITE, FILE_SHARE_READ , NULL, CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL,NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
LogWnd::Log( LogLevel::Error, L"Save Version File Failed!" );
return FALSE;
}
char szVersion[ 256 ]= {0,};
DWORD dwWriteSize;
//sprintf_s( szVersion, 256, "Version %d\r\n", nVersion );
sprintf_s( szVersion, 256, "Version %d\r\nModule %d", nVersion , DNFIRSTPATCHINFO.GetLocalModuleVersion() );
WriteFile( hFile, szVersion,(int)strlen(szVersion)+1 , &dwWriteSize, NULL );
CloseHandle(hFile);
return TRUE;
}
void CDnPatchDownloadThread::RecordFileExceptionLog( CFileException& e )
{
CString strTmp = _T("");
switch (e.m_cause)
{
case CFileException::genericException:
strTmp = _T("An unspecified error occurred.");
break;
case CFileException::fileNotFound:
strTmp = _T("The file could not be located.");
break;
case CFileException::badPath:
strTmp = _T("All or part of the path is invalid.");
break;
case CFileException::tooManyOpenFiles:
strTmp = _T("The permitted number of open files was exceeded.");
break;
case CFileException::accessDenied:
strTmp = _T("The file could not be accessed.");
break;
case CFileException::invalidFile:
strTmp = _T("There was an attempt to use an invalid file handle.");
break;
case CFileException::removeCurrentDir:
strTmp = _T("The current working directory cannot be removed.");
break;
case CFileException::directoryFull:
strTmp = _T("There are no more directory entries.");
break;
case CFileException::badSeek:
strTmp = _T("There was an error trying to set the file pointer.");
break;
case CFileException::hardIO:
strTmp = _T("There was a hardware error.");
break;
case CFileException::sharingViolation:
strTmp = _T("SHARE.EXE was not loaded, or a shared region was locked.");
break;
case CFileException::lockViolation:
strTmp = _T("There was an attempt to lock a region that was already locked.");
break;
case CFileException::diskFull:
strTmp = _T("The disk is full.");
break;
case CFileException::endOfFile:
strTmp = _T("The end of file was reached.");
break;
default:
strTmp = _T("EOCS - Can't Find Error Description.");
break;
}
LogWnd::Log( LogLevel::Error, L"File Open Exception : %d - %s", e.m_cause, strTmp );
}
#ifdef _USE_RTPATCH
static void far* g_pCallBackParam = NULL;
static BOOL g_bInCallBack = FALSE;
static BOOL g_bAbortPatch = FALSE;
static char g_strOriginFileName[_MAX_PATH] = {0,}; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> ( ApplyPatch32 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CallBack Function<6F><6E><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>. )
LPVOID CALLBACK EXPORT CDnPatchDownloadThread::RTPatchCALLBACK( UINT Id, LPVOID Param )
{
//FARPROC lpProcDlg;
//DLGPROC lpProcDlg;
MSG msg;
UINT MsgCount;
LPVOID RetVal;
g_pCallBackParam = Param;
g_bInCallBack = TRUE;
RetVal = "";
for( MsgCount = MAX_MESSAGES; MsgCount && PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ); MsgCount-- )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
switch( Id )
{
case 1: // Warning message header
case 2: // Warning message text
case 3: // Error message header
break;
case 4: // Error message text
{
CString strErrorMessage( (char*)Param );
LogWnd::Log( LogLevel::Error, L"RTPatchCALLBACK Error %s", strErrorMessage );
}
break;
case 9: // progress message
case 0xa: // help message
case 0xb: // patch file comment
case 0xc: // copyright message
case 5: // % completed
case 6: // Number of patch files PATCHGUI ignores this
break;
case 7: // begin patch
{
sprintf_s( g_strOriginFileName, _MAX_PATH, (char*)Param );
CString strFileName( (char*)Param );
LogWnd::Log( LogLevel::Error, L"RTPatchCALLBACK Begin RTPatch %s", strFileName );
}
break;
case 8: // end patch
{
LogWnd::Log( LogLevel::Error, L"RTPatchCALLBACK End RTPatch!" );
}
break;
case 0xd: // this one shouldn't happen (only occurs if the command line doesn't have a patch file in it, and we insure that it does).
case 0xe: // this one shouldn't happen either (same reason)
case 0xf: // Password Dialog
case 0x10: // Invalid Password Alert
case 0x11: // Disk Change Dialog
case 0x12: // Disk Change Alert
case 0x13: // Confirmation Dialog
case 0x14: // Location Dialog
case 0x16: // Searching Call-back
case 0x15: // Idle...
default:
break;
}
// do a few more messages while we're here...
for( MsgCount = MAX_MESSAGES; MsgCount && PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ); MsgCount-- )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
g_bInCallBack = false;
if( g_bAbortPatch ) // all of our call-back dialogs set this
return NULL;
else
return RetVal;
}
BOOL CDnPatchDownloadThread::ExportFile( CEtPackingFile& PakFile, const char* pExportFileName, const char* pCreateFilePath )
{
CEtFileHandle* pFileHandle = NULL;
pFileHandle = PakFile.OpenFile( pExportFileName );
if( pFileHandle == NULL )
return FALSE;
int nFileSize = pFileHandle->GetFileContext()->dwOriginalSize;
char* pBuff = new char[nFileSize];
if( pFileHandle->Read( pBuff, nFileSize ) == 0 )
return FALSE;
PakFile.CloseFile( pFileHandle );
char szString[_MAX_PATH];
char szFullFileName[_MAX_PATH];
_GetFullFileName( szFullFileName, pExportFileName );
sprintf_s( szString, _MAX_PATH, "%s\\%s", pCreateFilePath, szFullFileName );
WCHAR szCreateFileName[_MAX_PATH];
MultiByteToWideChar( CP_ACP, 0, szString, -1, szCreateFileName, _MAX_PATH );
HANDLE hFile = INVALID_HANDLE_VALUE;
hFile = CreateFile( szCreateFileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE )
return FALSE;
DWORD nWriteSize = 0;
if( WriteFile( hFile, pBuff, nFileSize, &nWriteSize, NULL ) == false )
{
CloseHandle( hFile );
return FALSE;
}
CloseHandle( hFile );
return TRUE;
}
PatchReturn CDnPatchDownloadThread::ApplyRTPatch( CEtPackingFile& PatchSource, CEtPackingFile& RTPatchSource )
{
int nPatchFileCount = PatchSource.GetFileCount();
PatchReturn RetValue = PR_OK;
for( int i=0; i<nPatchFileCount; i++ )
{
SPackingFileInfo* pFileInfo = PatchSource.GetFileInfo( i );
if( pFileInfo == NULL )
continue;
// rtp<74><70><EFBFBD><EFBFBD> export
if( !ExportFile( PatchSource, pFileInfo->szFileName, m_strRTPatchTempFolder.c_str() ) )
{
CString strFileName( pFileInfo->szFileName );
LogWnd::Log( LogLevel::Error, L"Error ExportFile %s", strFileName );
return PR_FAIL;
}
std::string strFullPathRTPFileName( pFileInfo->szFileName ); // /path/xxx.exe.rtp
char strRTPFileName[_MAX_PATH];
char strPath[_MAX_PATH];
_GetPath( strPath, strFullPathRTPFileName.c_str() ); // /path
_GetFullFileName( strRTPFileName, strFullPathRTPFileName.c_str() ); // xxx.exe.rtp
std::string strFullPathOriginFileName( strFullPathRTPFileName.c_str() );
strFullPathOriginFileName.erase( strFullPathOriginFileName.length() - 4, 4 ); // /path/xxx.exe
char strOriginFileName[_MAX_PATH];
_GetFullFileName( strOriginFileName, strFullPathOriginFileName.c_str() ); // xxx.exe
BOOL bFindFile = FALSE;
for( int i=0; i<(int)m_vecPackingFile.size(); i++ )
{
int nFindIndex = m_vecPackingFile[i]->FindFile( strFullPathOriginFileName.c_str() );
if( nFindIndex != -1 ) // rtp<74><70><EFBFBD>Ͽ<EFBFBD> <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִٸ<D6B4> <20><><EFBFBD><EFBFBD>
{
if( !ExportFile( *m_vecPackingFile[i], strFullPathOriginFileName.c_str(), m_strRTPatchTempFolder.c_str() ) )
{
CString strFileName( pFileInfo->szFileName );
LogWnd::Log( LogLevel::Error, L"Error ExportFile %s", strFileName );
return PR_FAIL;
}
bFindFile = TRUE;
break;
}
}
strFullPathOriginFileName.erase( 0, 1 ); // path/xxx.exe
if( !bFindFile ) // pak<61><6B><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><>ã<EFBFBD>Ҵٸ<D2B4> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ã<>ƺ<EFBFBD><C6BA><EFBFBD>.
{
char strClientPath[_MAX_PATH];
WideCharToMultiByte( CP_ACP, 0, DNPATCHINFO.GetClientPath().GetBuffer(), -1, strClientPath, __MAX_PATH, NULL, NULL );
std::vector<std::string> vecResult;
FindFileListInDirectory( strClientPath, "*.*", vecResult, false, true, true );
std::vector<std::string>::iterator iter = vecResult.begin();
for( ; iter!=vecResult.end(); iter++ )
{
char strFullFileName[_MAX_PATH];
_GetFullFileName( strFullFileName, (*iter).c_str() );
std::string strLowerFileName = strFullFileName;
std::transform( strLowerFileName.begin(), strLowerFileName.end(), strLowerFileName.begin(), tolower);
if( strcmp( strOriginFileName, strLowerFileName.c_str() ) == 0 )
{
CString strSourceFile( (*iter).c_str() );
char strString[_MAX_PATH];
sprintf_s( strString, _MAX_PATH, "%s\\%s", m_strRTPatchTempFolder.c_str(), strFullFileName );
WCHAR strDestFile[_MAX_PATH];
MultiByteToWideChar( CP_ACP, 0, strString, -1, strDestFile, _MAX_PATH );
if( !CopyFile( strSourceFile, strDestFile, FALSE ) )
{
CString strFileName( pFileInfo->szFileName );
LogWnd::Log( LogLevel::Error, L"Error CopyFile %s", strFileName );
return PR_FAIL;
}
bFindFile = TRUE;
break;
}
}
}
char szBuildCommand[_MAX_PATH];
sprintf( szBuildCommand, "%s \"%s\\%s\" /u", m_strRTPatchTempFolder.c_str(), m_strRTPatchTempFolder.c_str(), strRTPFileName );
int ret = RTPatchApply32( szBuildCommand, CDnPatchDownloadThread::RTPatchCALLBACK, TRUE );
if( ret != 0 )
return PR_FAIL;
RTPatchSource.ChangeDir( "\\" );
if( strPath[0] )
{
RTPatchSource.ChangeDir( strPath );
}
// RTPatch <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>Ͻý<CFBD><C3BD>ۿ<EFBFBD> <20>ִ´<D6B4>.
char szApplyPatchFileName[_MAX_PATH];
sprintf_s( szApplyPatchFileName, _MAX_PATH, "%s\\%s", m_strRTPatchTempFolder.c_str(), g_strOriginFileName );
if( !RTPatchSource.AddFile( szApplyPatchFileName ) )
return PR_FAIL;
WCHAR strDeleteFileName[_MAX_PATH];
char strString[_MAX_PATH];
sprintf_s( strString, _MAX_PATH, "%s\\%s", m_strRTPatchTempFolder.c_str(), strRTPFileName );
MultiByteToWideChar( CP_ACP, 0, strString, -1, strDeleteFileName, _MAX_PATH );
ClientDeleteFile( strDeleteFileName );
sprintf_s( strString, _MAX_PATH, "%s\\%s", m_strRTPatchTempFolder.c_str(), g_strOriginFileName );
MultiByteToWideChar( CP_ACP, 0, strString, -1, strDeleteFileName, _MAX_PATH );
ClientDeleteFile( strDeleteFileName );
if( m_bTerminateThread )
{
for( int m=0; m<(int)m_vecPackingFile.size(); m++ )
{
m_vecPackingFile[m]->CloseFileSystem();
SAFE_DELETE(m_vecPackingFile[m]);
}
PatchSource.CloseFileSystem();
RTPatchSource.CloseFileSystem();
DeleteFolder( m_strRTPatchTempFolder.c_str() );
return PR_TERMINATE;
}
}
return RetValue;
}
#endif // _USE_RTPATCH
#ifdef _USE_SPLIT_COMPRESS_FILE
HRESULT CDnPatchDownloadThread::DownLoadSplitFile( CString strUrl, int nVersion )
{
LogWnd::TraceLog( L"DownLoadSplitFile Start!" );
CString strSplitTxtUrl, strSplitFile;
strSplitTxtUrl.Format( _T( "%sSplit%08d.txt" ), strUrl.GetBuffer(), nVersion );
strSplitFile.Format( _T( "%sSplit%08d.txt" ), DNPATCHINFO.GetClientPath().GetBuffer(), nVersion );
HRESULT hr = S_FALSE;
BOOL bResult = FALSE;
for( int i=0; i<RETRY_MAX_COUNT; i++ )
{
bResult = DeleteUrlCacheEntry( strSplitTxtUrl.GetBuffer() );
hr = DownloadToFile( strSplitTxtUrl.GetBuffer(), strSplitFile.GetBuffer() );
if( hr == S_OK )
break;
}
if( hr != S_OK )
return S_FALSE;
int nSplitCount = LoadSplitCount( strSplitFile );
ClientDeleteFile( strSplitFile );
if( nSplitCount == 0 )
return S_FALSE;
if( hr == S_OK )
{
LogWnd::Log( LogLevel::Info, L"DownLoadSplitFile Count(%d)", nSplitCount );
int nSplitCountCipher = 1;
if( nSplitCount >= 10 && nSplitCount < 100 )
nSplitCountCipher = 2;
else if( nSplitCount >= 100 ) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 100<30><30> <20>Ѿ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>
nSplitCountCipher = 3;
std::vector<DWORD> vecDwSplitFileSizeList;
DWORD dwTotalSplitFileSize = GetSplitFileSizeList( strUrl, nVersion, nSplitCount, nSplitCountCipher, vecDwSplitFileSizeList );
if( nSplitCount != static_cast<int>( vecDwSplitFileSizeList.size() ) )
{
vecDwSplitFileSizeList.clear();
return S_FALSE;
}
g_DownloadInfoData.m_strFileName.Format( _T( "Patch%08d.pak" ), nVersion );
g_DownloadInfoData.m_nFileSize = dwTotalSplitFileSize;
CString strRARFirstFileName;
for( int i=0; i<nSplitCount; i++ )
{
CString strPatchFileUrl, strPatchFileName;
if( nSplitCountCipher == 1 )
{
strPatchFileUrl.Format( _T( "%sPatch%08d.part%d.rar" ), strUrl.GetBuffer(), nVersion, i+1 );
strPatchFileName.Format( _T( "Patch%08d.part%d.rar" ), nVersion, i+1 );
}
else if( nSplitCountCipher == 2 )
{
strPatchFileUrl.Format( _T( "%sPatch%08d.part%02d.rar" ), strUrl.GetBuffer(), nVersion, i+1 );
strPatchFileName.Format( _T( "Patch%08d.part%02d.rar" ), nVersion, i+1 );
}
else if( nSplitCountCipher == 3 )
{
strPatchFileUrl.Format( _T( "%sPatch%08d.part%03d.rar" ), strUrl.GetBuffer(), nVersion, i+1 );
strPatchFileName.Format( _T( "Patch%08d.part%03d.rar" ), nVersion, i+1 );
}
if( i == 0 )
strRARFirstFileName = strPatchFileName;
DWORD dwAlreadyDownloadFileSize = 0;
DWORD dwRemainDownloadFileSize = 0;
for( int j=0; j<i; j++ )
dwAlreadyDownloadFileSize += vecDwSplitFileSizeList[j];
dwRemainDownloadFileSize = dwAlreadyDownloadFileSize;
for( int j=i+1; j<nSplitCount; j++ )
dwRemainDownloadFileSize += vecDwSplitFileSizeList[j];
bResult = DeleteUrlCacheEntry( strPatchFileUrl.GetBuffer() );
hr = URLDownload( strPatchFileUrl.GetBuffer(), DNPATCHINFO.GetClientPath().GetBuffer(), strPatchFileName.GetBuffer(),
TRUE, dwAlreadyDownloadFileSize, dwRemainDownloadFileSize );
if( hr != S_OK )
{
LogWnd::Log( LogLevel::Error, L"Download SplitFile Failed!");
break;
}
if( ::GetFileAttributes( m_strPatchFile.GetBuffer() ) == -1 )
{
hr = S_FALSE;
LogWnd::Log( LogLevel::Error, L"Failed! GetFileAttributes=[%s]", m_strPatchFile.GetBuffer() );
break;
}
}
vecDwSplitFileSizeList.clear();
if( hr != S_OK )
return hr;
hUnrarDLL = LoadLibrary( _T( "unrar.dll" ) );
hr = UnRARArchive( DNPATCHINFO.GetClientPath(), strRARFirstFileName );
FreeLibrary( hUnrarDLL );
if( hr == S_OK )
{
for( int i=0; i<nSplitCount; i++ )
{
CString strPatchFileName;
if( nSplitCountCipher == 1 )
strPatchFileName.Format( _T( "Patch%08d.part%d.rar" ), nVersion, i+1 );
else if( nSplitCountCipher == 2 )
strPatchFileName.Format( _T( "Patch%08d.part%02d.rar" ), nVersion, i+1 );
else if( nSplitCountCipher == 3 )
strPatchFileName.Format( _T( "Patch%08d.part%03d.rar" ), nVersion, i+1 );
ClientDeleteFile( strPatchFileName );
}
m_strPatchFileUrl.Format( _T( "%sPatch%08d.pak" ), strUrl.GetBuffer(), nVersion );
m_strPatchFileLocal.Format( _T( "Patch%08d.pak" ), nVersion );
m_strPatchFile.Format( L"%s%s", DNPATCHINFO.GetClientPath(), m_strPatchFileLocal );
LogWnd::TraceLog( L"MD5 Check Start" );
// <20>ùٸ<C3B9><D9B8><EFBFBD> <20>ٿ<EFBFBD><D9BF>ε<EFBFBD> <20>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD><EFBFBD> MD5 Check
if( !GetMD5Checksum() )
{
LogWnd::Log( LogLevel::Error, L"MD5 Check Failed!" );
SendStatusMsg( PATCH_MD5_CHECK_FAILED );
ClientDeleteFile( m_strPatchFile );
return S_FALSE; // md5 check error
}
LogWnd::TraceLog( L"MD5 Check Success" );
}
}
return hr;
}
DWORD CDnPatchDownloadThread::GetSplitFileSizeList( CString strUrl, int nVersion, int nSplitCount, int nSplitCountCipher, std::vector<DWORD>& vecSplitFileSizeList )
{
DWORD dwTotalDownloadFileSize = 0;
HINTERNET hInternetSession;
hInternetSession = InternetOpen( NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
if( hInternetSession == NULL )
{
LogWnd::Log( LogLevel::Error, L"Internet Session Open Failed!" );
return 0;
}
for( int i=0; i<nSplitCount; i++ )
{
CString strPatchFileUrl;
if( nSplitCountCipher == 1 )
strPatchFileUrl.Format( _T( "%sPatch%08d.part%d.rar" ), strUrl.GetBuffer(), nVersion, i+1 );
else if( nSplitCountCipher == 2 )
strPatchFileUrl.Format( _T( "%sPatch%08d.part%02d.rar" ), strUrl.GetBuffer(), nVersion, i+1 );
else if( nSplitCountCipher == 3 )
strPatchFileUrl.Format( _T( "%sPatch%08d.part%03d.rar" ), strUrl.GetBuffer(), nVersion, i+1 );
DWORD dwDownloadFileSize = GetDownloadFileSize( hInternetSession, strPatchFileUrl );
dwTotalDownloadFileSize += dwDownloadFileSize;
vecSplitFileSizeList.push_back( dwDownloadFileSize );
}
InternetCloseHandle( hInternetSession );
return dwTotalDownloadFileSize;
}
int CDnPatchDownloadThread::LoadSplitCount( CString& szFilePath )
{
char* buffer = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
int nVersion = 0;
hFile = CreateFile( szFilePath.GetBuffer(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE )
return -1;
DWORD tmp = 0;
DWORD nFileSize = 0;
nFileSize = GetFileSize( hFile, &tmp );
nFileSize++;
buffer = new char[nFileSize+1];
if( buffer == NULL )
return -1;
ZeroMemory( buffer, nFileSize+1 );
DWORD nReadSize = 0;
ReadFile( hFile, buffer, nFileSize, &nReadSize, NULL );
CloseHandle( hFile );
char arg1[256]={0,}, arg2[256]={0,};
char *szToken = NULL, *nextToken = NULL;
char delimiters[] = "\r\n";
szToken = strtok_s( buffer, delimiters, &nextToken );
while( szToken != NULL )
{
if( sscanf_s( szToken, "%s %s", &arg1, sizeof(arg1), &arg2, sizeof(arg2) ) )
{
_strlwr_s( arg1 );
if( _stricmp( arg1, "split" ) == 0 )
nVersion = atol( arg2 );
}
szToken = strtok_s( NULL, delimiters, &nextToken );
}
SAFE_DELETE_ARRAY( buffer );
return nVersion;
}
HRESULT CDnPatchDownloadThread::UnRARArchive( CString strPath, CString strRARFile )
{
// Is the DLL loaded?
if( hUnrarDLL == NULL )
return S_FALSE;
// Get the function pointers we need
(FARPROC&)OpenArchiveEx = GetProcAddress( hUnrarDLL, "RAROpenArchiveEx" );
(FARPROC&)CloseArchive = GetProcAddress( hUnrarDLL, "RARCloseArchive" );
(FARPROC&)ProcessRARFile = GetProcAddress( hUnrarDLL, "RARProcessFile" );
(FARPROC&)ReadRARHeader = GetProcAddress( hUnrarDLL, "RARReadHeader" );
// Set up our RAR archive data
RAROpenArchiveDataEx archiveData;
ZeroMemory( &archiveData, sizeof(archiveData) );
char szTemp[1024] = {0,};
WideCharToMultiByte( CP_ACP, 0, strRARFile.GetBuffer(), -1, szTemp, 1024, NULL, NULL );
archiveData.ArcName = szTemp;
archiveData.CmtBuf = NULL;
archiveData.OpenMode = 1;
// Open the archive into a handle
HANDLE archiveHandle = OpenArchiveEx( &archiveData );
// Did it fail? Update the error and return false
if( archiveData.OpenResult != 0 )
return S_FALSE;
// Simple header data struct
RARHeaderData headerData;
headerData.CmtBuf = NULL;
// Set variables
int readHeaderCode, processFileCode;
HRESULT hr = S_OK;
WideCharToMultiByte( CP_ACP, 0, strPath.GetBuffer(), -1, szTemp, 1024, NULL, NULL );
// While the header data is valid..
while( ( readHeaderCode = ReadRARHeader( archiveHandle, &headerData ) ) == 0 )
{
// UnRAR this file
processFileCode = ProcessRARFile( archiveHandle, 2, szTemp, NULL );
// Did it go okay? If not, we're done
if( processFileCode != 0 )
{
hr = S_FALSE;
break;
}
}
// Close the archive
CloseArchive( archiveHandle );
return hr;
}
#endif // _USE_SPLIT_COMPRESS_FILE
#ifdef _FIRST_PATCH
BOOL CDnPatchDownloadThread::CheckExistFirstPatch( int nVersion )
{
CString strFirtPatchURLPath, strPatchListFile;
strFirtPatchURLPath.Format( _T( "%s%08d%s%s" ), DNPATCHINFO.GetPatchUrl(), nVersion, _T("/FirstPatch/"), FIRSTPATCHLIST_NAME );
strPatchListFile.Format( _T( "%s%s" ), DNPATCHINFO.GetClientPath().GetBuffer() , FIRSTPATCHLIST_NAME );
HRESULT hr;
BOOL bExistFirstPatch = FALSE;
for( int i = 0 ; i < RETRY_MAX_COUNT ; ++i )
{
DeleteUrlCacheEntry( strFirtPatchURLPath.GetBuffer() );
hr = DownloadToFile( strFirtPatchURLPath.GetBuffer(), strPatchListFile.GetBuffer() );
if( hr == S_OK )
{
ClientDeleteFile( strPatchListFile );
bExistFirstPatch = TRUE;
break;
}
}
return bExistFirstPatch;
}
#endif // _FIRST_PATCH