DragonNest/Client/DnLauncher3/DnPatchThread.cpp

2687 lines
154 KiB
C++
Raw Normal View History

2024-12-20 16:56:44 +08:00
<EFBFBD><EFBFBD>#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; // Gj<EFBFBD><EFBFBD><EFBFBD>b<EFBFBD><EFBFBD><EFBFBD>O<EFBFBD><EFBFBD> <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD> Y<EFBFBD>m<EFBFBD>[<EFBFBD><EFBFBD>r <EFBFBD>``<<EFBFBD><EFBFBD> lOAb <EFBFBD>V<EFBFBD> <EFBFBD>P_ US^c%<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:
{
// * <EFBFBD><EFBFBD> <EFBFBD><EFBFBD> Pak<EFBFBD><EFBFBD><EFBFBD><EFBFBD>O <EFBFBD>S<EFBFBD>S<EFBFBD><EFBFBD>O *
if( !SaveModuleVersionToPak(DNFIRSTPATCHINFO.GetLocalModuleVersion()) )
{
ErrorMessageBoxLog( _S( STR_PATCH_FAILED + DNPATCHINFO.GetLanguageOffset() ) ); // <EFBFBD><EFBFBD>yd ҉<EFBFBD><EFBFBD>.
}
}
break;
case FPR_FAIL:
{
ErrorMessageBoxLog( _S( STR_PATCH_FAILED + DNPATCHINFO.GetLanguageOffset() ) ); // <EFBFBD><EFBFBD>yd ҉<EFBFBD><EFBFBD>.
CloseThread();
}
break;
case FPR_NEED_FULLPATCH:
{
ProcessFullVersionPatch();
}
break;
case FPR_LAUNCHER_PATCH:
{
ProcessRebootLauncher();
}
break;
}
// <EFBFBD><EFBFBD>m<EFBFBD>[<EFBFBD> gdAb
//CloseThread();
}
void CDnFistPatchDownloadThread::ProcessRebootLauncher()
{
// * <EFBFBD><EFBFBD> <EFBFBD><EFBFBD> Pak<EFBFBD><EFBFBD><EFBFBD><EFBFBD>O <EFBFBD>S<EFBFBD>S<EFBFBD><EFBFBD>O *
BOOL bSaveResult = SaveModuleVersionToPak(DNFIRSTPATCHINFO.GetLocalModuleVersion());
if(bSaveResult)
{
//if( AfxMessageBox(_T("A~8<>JU <00><>yd{ṽ<76>Vj<56><6A>O.\nA~8<>+u <00>r҉R<D289><52><EFBFBD>j<EFBFBD><6A>O."), MB_OK, MB_ICONINFORMATION) == IDOK )
{
CString strParam = DNPATCHINFO.GetTotalParameter(); // <EFBFBD><EFBFBD>|b<EFBFBD>i<EFBFBD>x
CString strExeFile = DNPATCHINFO.GetClientPath(); // <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD> Hr<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)); // oldGj<EFBFBD><EFBFBD><EFBFBD>b<EFBFBD><EFBFBD> kill.
}
}
else
{
ErrorMessageBoxLog( _S( STR_PATCH_FAILED+DNPATCHINFO.GetLanguageOffset() ) );
}
}
FirstPatchReturn CDnFistPatchDownloadThread::BegineModulePatch()
{
BOOL bModuleResult = FALSE;
BOOL bLauncherResult = FALSE;
// "<00><><EFBFBD>n" <EFBFBD>n<EFBFBD>P.
int nDownServerVersion = DNPATCHINFO.GetServerVersion();
// "[<5B><>x" <EFBFBD>n<EFBFBD>P.
int nLocalModuleVersion = DNFIRSTPATCHINFO.GetLocalModuleVersion();
LogWnd::TraceLog(_T("<00><><EFBFBD>n<EFBFBD>n<EFBFBD>P: [%d] / [<5B><>x<EFBFBD>n<EFBFBD>P: [%d]"), nDownServerVersion, nLocalModuleVersion );
if( nLocalModuleVersion == nDownServerVersion ) // * <EFBFBD>n<EFBFBD>P^c <EFBFBD><EFBFBD><EFBFBD>Od, yk^c<EFBFBD>` <EFBFBD>gR<EFBFBD>N ^c!<EFBFBD>JU <EFBFBD>~<EFBFBD>o *
{
LogWnd::Log(LogLevel::Error, _T("ModulePatch - Version is Concur"));
return FPR_OK;
}
else if( nLocalModuleVersion > nDownServerVersion ) // * <EFBFBD>n<EFBFBD>P <EFBFBD><EFBFBD><EFBFBD>p. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>yd<EFBFBD><EFBFBD> <EFBFBD><EFBFBD><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;
}
// * <EFBFBD><EFBFBD>yd <EFBFBD>w/}! *
for( int i = nLocalModuleVersion ; i < nDownServerVersion ; )
{
if( i < nDownServerVersion )
{
i++;
// [<EFBFBD><EFBFBD>x <EFBFBD><EFBFBD>yd
bModuleResult = DownLoadModulePatch(i); // FirstPatchList.txt <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD>.
if(bModuleResult) // FirstPatchList.txt<EFBFBD><EFBFBD><EFBFBD>^c <EFBFBD>|<EFBFBD>r<EFBFBD><EFBFBD>Od ҉R<EFBFBD>.
{
if( !ParsingModuleList() ) // "FirstPatchList.txt" <EFBFBD><EFBFBD>Ye
{
return FPR_FAIL;
}
if( !ChangeModuleFiles(i) ) // [<EFBFBD><EFBFBD>x <EFBFBD><EFBFBD><EFBFBD> <EFBFBD>QHr.
{
return FPR_FAIL;
}
}
// A~8<EFBFBD> <EFBFBD><EFBFBD>yd
bLauncherResult = PatchLauncherFiles(i); // * Launcher.exe<EFBFBD><EFBFBD><EFBFBD> <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD> & )R<EFBFBD>O *
// <EFBFBD>l<EFBFBD>r [<EFBFBD><EFBFBD>x <EFBFBD>n<EFBFBD>P<EFBFBD> <EFBFBD>S<EFBFBD>S. ( <EFBFBD>QP<EFBFBD><EFBFBD>O <EFBFBD>S<EFBFBD>S.. )
DNFIRSTPATCHINFO.SetLocalModuleVersion(i);
// <EFBFBD>n<EFBFBD>P <EFBFBD>QHr
CString szPath;
szPath = DNPATCHINFO.GetClientPath();
szPath += CLIENT_VERSION_NAME;
// version.cfg<EFBFBD><EFBFBD><EFBFBD><EFBFBD>O6r <EFBFBD>S<EFBFBD>S.
if( !SaveModuleVersionFileWithOutPakSave(szPath, i) )
{
return FPR_FAIL;
}
// DnLuancher.exeJU <EFBFBD><EFBFBD>yd Y<EFBFBD>Od, A~8<EFBFBD> <EFBFBD>rY<EFBFBD>`.
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 );
// <EFBFBD>R|b^c+ <EFBFBD><EFBFBD><EFBFBD>b <EFBFBD><EFBFBD><EFBFBD><EFBFBD>S<EFBFBD>S Hr<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() );
// <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD><EFBFBD>O ҉l<EFBFBD>Od.
if( hr != S_OK )
{
LogWnd::TraceLog( _T("FirstPatch.txt Download Failed!") );
return FALSE;
}
LogWnd::TraceLog( L"FirstPatch.txt File Download Success" );
// <EFBFBD><EFBFBD><EFBFBD> <EFBFBD>R<EFBFBD>] w<EFBFBD>Q.
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 <EFBFBD>g<EFBFBD>[.
CString szPatchListUrl;
szPatchListUrl.Format( _T( "%s%s" ), strUrl.GetBuffer(), _T(DNLAUNCHER_NAME));
if( !IsExistFile( szPatchListUrl ) )
return FALSE;
// Client <EFBFBD><EFBFBD><EFBFBD>b Hr<EFBFBD><EFBFBD> (<EFBFBD>S<EFBFBD>S{v<EFBFBD>~ <EFBFBD>S<EFBFBD>[)
m_strPatchListFile.Format( _T( "%s%s" ), DNPATCHINFO.GetClientPath().GetBuffer() , _T(DNLAUNCHER_NAME));
// Ab<EFBFBD>|<EFBFBD>r <EFBFBD>r<EFBFBD>S<EFBFBD>x exe+u tmp<EFBFBD><EFBFBD> <EFBFBD>QHr<EFBFBD><EFBFBD>O.
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") );
// <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD><EFBFBD>O ҉l<EFBFBD>Od.
if( hr != S_OK )
{
MoveFile(_T(DNLAUNCHER_NAME_TMP), _T(DNLAUNCHER_NAME)); // 'tmp' ---> 'exe'<EFBFBD><EFBFBD> <EFBFBD>O<EFBFBD>w WlY.
LogWnd::TraceLog( _T("Download DnLauncher.exe File Failed!") );
return FALSE;
}
// <EFBFBD><EFBFBD><EFBFBD> <EFBFBD>R<EFBFBD>] w<EFBFBD>Q.
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 ^cA~<EFBFBD>O.
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 ]; // <EFBFBD><EFBFBD><EFBFBD> :W^c <EFBFBD>~<EFBFBD>Hr<EFBFBD>_ pBuffer + 2 <EFBFBD> v<EFBFBD><EFBFBD>O pBuffer JU Y<EFBFBD>m<EFBFBD>Ab<<EFBFBD>^c<EFBFBD>T<EFBFBD><EFBFBD> strchr <EFBFBD>O<EFBFBD><EFBFBD> "kg P<> PN<50>O.
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. <EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>R
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<EFBFBD><EFBFBD> <EFBFBD>Q8R.
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (*it).c_str(), -1, wszFileName, _MAX_PATH);
// "DnLauncher.exe"<EFBFBD>~ <EFBFBD>TAb<EFBFBD><EFBFBD> 8<EFBFBD><EFBFBD>^<EFBFBD>z$v <EFBFBD><EFBFBD><EFBFBD>~<EFBFBD>O.
if( wcscmp(wszFileName, _T("DnLauncher.exe")) == 0 )
{
continue;
}
// 1. <EFBFBD>v/Y<EFBFBD><EFBFBD><EFBFBD>^c<EFBFBD>b <EFBFBD>QHr.
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. '<EFBFBD><EFBFBD><EFBFBD>>k <EFBFBD><EFBFBD><EFBFBD> <EFBFBD>O>k<EFBFBD><EFBFBD>[<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_<00><><01>" f<EFBFBD>R.
break;
}
}
// 3. ҉<EFBFBD><EFBFBD> : Ab<EFBFBD>|<EFBFBD><EFBFBD><EFBFBD> ^c<EFBFBD>b Wl<EFBFBD>v.
if( hr != S_OK )
{
rename(CT2A(strBackUpFileName), CT2A(strOriginalFileName)); // <EFBFBD>v0<EFBFBD> ^c<EFBFBD>bh<EFBFBD><EFBFBD> WlY
}
}
//-------------------------------------------
// f<EFBFBD>R<h<EFBFBD>^ 8<EFBFBD><EFBFBD>^
//-------------------------------------------
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 );
// <EFBFBD>~t<EFBFBD>P<EFBFBD> <EFBFBD>~<EFBFBD>O. 512M <EFBFBD><EFBFBD>~JU<EFBFBD>~<EFBFBD>]T<EFBFBD>O <EFBFBD>i|b<EFBFBD><EFBFBD> wJU<EFBFBD>z<EFBFBD>x.
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"n"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"n"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( "n"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"n"Patch Failed!" );
SendStatusMsg( PATCH_FAILED );
}
break;
case PR_TERMINATE:
{
LogWnd::TraceLog( L"n"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 ) // <EFBFBD>l<EFBFBD>r <EFBFBD>n<EFBFBD> <EFBFBD><EFBFBD><EFBFBD>n <EFBFBD>n<EFBFBD>P<EFBFBD> <EFBFBD>rbr<EFBFBD> <EFBFBD>~<EFBFBD>l<EFBFBD>O. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>yd<EFBFBD><EFBFBD> <EFBFBD><EFBFBD>~JUwQ<EFBFBD><EFBFBD>O.
{
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 ) // <EFBFBD><EFBFBD><EFBFBD>n<EFBFBD>[ <EFBFBD>R|b^c+ <EFBFBD>n<EFBFBD>P^c <EFBFBD><EFBFBD>hd <EFBFBD><EFBFBD>ydN <EFBFBD><EFBFBD>8YJU <EFBFBD>~<EFBFBD>O.
return PR_OK;
else if( nCurClientVersion > nCurServerVersion ) // <EFBFBD>R|b^c+ <EFBFBD>n<EFBFBD>P^c <EFBFBD><EFBFBD><EFBFBD>n <EFBFBD>n<EFBFBD>P
q<EFBFBD>O <EFBFBD>Qd <EFBFBD><EFBFBD><EFBFBD><EFBFBD>yd
return PR_FULLPATCH;
else // <EFBFBD>R|b^c+ <EFBFBD>n<EFBFBD>P^c <EFBFBD>d<EFBFBD> Hr<EFBFBD>_ <EFBFBD><EFBFBD>yd <EFBFBD>gR<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;
// 9<EFBFBD>R_<EFBFBD><EFBFBD>yd <EFBFBD> <EFBFBD>O>kP<EFBFBD> <EFBFBD>n`<EFBFBD> <EFBFBD>N<EFBFBD>w w<EFBFBD>Q <EFBFBD>y<EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>N <EFBFBD>n<EFBFBD>P^cd <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>O.
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 ) //<EFBFBD>n` <EFBFBD>w^cJU 2^c<EFBFBD>` 1Ud 9<EFBFBD>R_<EFBFBD> <EFBFBD>n`֜$v <EFBFBD>[<EFBFBD><EFBFBD> ^c<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; // [<EFBFBD><EFBFBD>x<EFBFBD><EFBFBD>yd6r PN<EFBFBD>~ Hr<EFBFBD>_
#endif // _FIRST_PATCH
while(1)
{
BOOL bResult = DownLoadPatch( i );
if( bResult )
{
if( m_bTerminateThread ) return PR_TERMINATE; // <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD> <EFBFBD><EFBFBD>0N <EFBFBD>w <EFBFBD><EFBFBD>0N 8<EFBFBD><EFBFBD>^ Qe{vd packing֜$v <EFBFBD><EFBFBD>~JUAb -<EFBFBD><EFBFBD>]<EFBFBD>O <EFBFBD><EFBFBD>0NJU wW0<EFBFBD> 'T<EFBFBD><EFBFBD>
break;
}
#ifdef _FIRST_PATCH
if( CheckExistFirstPatch( i ) ) // [<EFBFBD><EFBFBD>x<EFBFBD><EFBFBD>yd6r PN<EFBFBD>~ <EFBFBD><EFBFBD>yd<EFBFBD>n<EFBFBD>Pbr$v w<EFBFBD>Q
{
bOnlyFirstPatch = TRUE;
break;
}
#endif // _FIRST_PATCH
nFailCount++;
if( nFailCount < RETRY_MAX_COUNT )
{
SendStatusMsg( PATCH_DOWNLOAD_DATA );
}
else
{
if( i != nCurServerVersion )
{
// <EFBFBD><EFBFBD>yd <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD> ҉l<EFBFBD>~.. JU<EFBFBD>S %_<EFBFBD><EFBFBD><EFBFBD>yd <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD><EFBFBD>y<EFBFBD><EFBFBD> <EFBFBD>]<EFBFBD>P<EFBFBD>zd
// HTlQ wW0<EFBFBD>I{ <EFBFBD>n<EFBFBD>P^c|b<EFBFBD><EFBFBD> ^c<EFBFBD>n<EFBFBD>P<EFBFBD>r <EFBFBD><EFBFBD>ydJU f<EFBFBD>R oph<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD>n<EFBFBD>P <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD>S<EFBFBD>O.
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 ); // rlyd Gj<EFBFBD><EFBFBD>
_0<EFBFBD><EFBFBD><EFBFBD> <EFBFBD>gR<EFBFBD><EFBFBD> <EFBFBD>V<EFBFBD>y Gj<EFBFBD><EFBFBD>
_0<EFBFBD><EFBFBD><EFBFBD> Min/Max <EFBFBD>jAb<EFBFBD>b
// P<EFBFBD>{ <EFBFBD><EFBFBD>yd+u )R<EFBFBD>O<EFBFBD><EFBFBD>O.
nRetValue = ApplyPakPatch();
if( nRetValue == PR_TERMINATE )
break;
#ifdef _USE_RTPATCH
DeleteFolder( m_strRTPatchTempFolder.c_str() ); // RTPatch)R<EFBFBD>O <EFBFBD>p<EFBFBD>w _yk f<EFBFBD>R
#endif // _USE_RTPATCH
ClientDeleteFile( m_strPatchListFile.GetBuffer() ); // ApplyPak<EFBFBD><EFBFBD>0N v<EFBFBD> txt<EFBFBD><EFBFBD><EFBFBD><EFBFBD>{ <EFBFBD>[<EFBFBD><EFBFBD> f<EFBFBD>R
if( nRetValue == PR_OK || nRetValue == PR_LAUNCHER_PATCH )
{
ClientDeleteFile( m_strPatchFile.GetBuffer() ); // <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD> P<EFBFBD>{ Pak<EFBFBD><EFBFBD><EFBFBD><EFBFBD>{ Apply <EFBFBD>]<EFBFBD>P<EFBFBD>w<EFBFBD>O6r f<EFBFBD>R
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<EFBFBD>O <EFBFBD>[<EFBFBD><EFBFBD> <EFBFBD>n<EFBFBD>P <EFBFBD>S<EFBFBD>S
{
nRetValue = PR_FAIL;
break;
}
if( nRetValue == PR_LAUNCHER_PATCH ) // A~8<EFBFBD> <EFBFBD><EFBFBD>ydJU {<EFBFBD>Od T<EFBFBD>z<EFBFBD>z<EFBFBD>~ '<EFBFBD> A~8<EFBFBD>+u AR<EFBFBD>_<EFBFBD>~ <EFBFBD><EFBFBD>yd<EFBFBD><EFBFBD>O.
break;
}
else // <EFBFBD><EFBFBD>yd<EFBFBD>z<EFBFBD>OJU <EFBFBD>O<EFBFBD>w f<EFBFBD><EFBFBD>O.. <EFBFBD>hUO<EFBFBD>x <EFBFBD>O<EFBFBD>w l_R<EFBFBD>wQ Fd<EFBFBD>O..
{
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;
// <EFBFBD>b<EFBFBD><EFBFBD> <EFBFBD>QAb
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 );
// <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD> PAb <EFBFBD>P <EFBFBD><EFBFBD><EFBFBD><EFBFBD>{ R<EFBFBD>S w<EFBFBD>Q
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 <EFBFBD>QAb
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;
// <EFBFBD>O>kPR<EFBFBD>wQ N <EFBFBD><EFBFBD><EFBFBD> <EFBFBD>QAb Y<EFBFBD>zAb
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 );
// <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD> <EFBFBD>w/} (^c<EFBFBD>~PAb)
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 ) // <EFBFBD>x<EFBFBD>VS^ {<EFBFBD><EFBFBD>1U <EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>P<EFBFBD>N P<EFBFBD> -<EFBFBD> wWE^JU PN<EFBFBD> Hr<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" );
// <EFBFBD>h<EFBFBD>[<EFBFBD>y8<EFBFBD> <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD> {<EFBFBD>~$v 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" );
// <EFBFBD>h<EFBFBD>[<EFBFBD>y8<EFBFBD> <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD> {<EFBFBD>~$v 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
// <EFBFBD>l<EFBFBD>^ tmp -> <EFBFBD>v0<EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>u
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
{
// <EFBFBD>O>k P<EFBFBD> <EFBFBD><EFBFBD><EFBFBD> <EFBFBD>QAb Y<EFBFBD>zAb
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
// <EFBFBD>O>k <EFBFBD><EFBFBD>0NI{ <EFBFBD><EFBFBD><EFBFBD>^c PN<EFBFBD> Hr<EFBFBD>_ !<EFBFBD><EFBFBD>t<EFBFBD>] kQd<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 ) // ^c<EFBFBD>V <EFBFBD>O PR<EFBFBD><EFBFBD>g <EFBFBD><EFBFBD><EFBFBD>^c PN<EFBFBD>o
{
LogWnd::Log( LogLevel::Error, L"Already Exist Download Temp File!" );
InternetCloseHandle( hInternetSession );
return FIlE_EXIST;
}
else // P<EFBFBD>uh1U <EFBFBD><EFBFBD><EFBFBD>n<EFBFBD>r <EFBFBD><EFBFBD><EFBFBD> <EFBFBD>l
q<EFBFBD>[ <EFBFBD>`^cN Hr<EFBFBD>_ f<EFBFBD>R v<EFBFBD> <EFBFBD>O<EFBFBD>w P<EFBFBD>o
{
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 );
}
// Ab<EFBFBD>| <EFBFBD>O>kP&^ tmp <EFBFBD><EFBFBD><EFBFBD> w<EFBFBD>Q
FILE* fp;
fp = _wfopen( m_strPatchFileLocal, _T("r") );
UINT uiFileModeFlag = CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone;
if( fp != NULL ) // <EFBFBD>O>kP&^ tmp<EFBFBD><EFBFBD><EFBFBD>^c PN<EFBFBD> Hr<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;
// <EFBFBD>O>kPR<EFBFBD>wQ N <EFBFBD><EFBFBD><EFBFBD> <EFBFBD>QAb Y<EFBFBD>zAb
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 <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 ]; // <EFBFBD><EFBFBD><EFBFBD> :W^c <EFBFBD>~<EFBFBD>Hr<EFBFBD>_ pBuffer + 2 <EFBFBD> v<EFBFBD><EFBFBD>O pBuffer JU Y<EFBFBD>m<EFBFBD>Ab<<EFBFBD>^c<EFBFBD>T<EFBFBD><EFBFBD> strchr <EFBFBD>O<EFBFBD><EFBFBD> "kg P<> PN<50>O.
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" );
//<EFBFBD><EFBFBD>yd <EFBFBD>`` <EFBFBD>^<EFBFBD><EFBFBD>ؘ <EFBFBD>l
q+u lO<EFBFBD>~<EFBFBD>g<EFBFBD>O.
if( !LoadPatchList() )
{
ErrorMessageBoxLog( _S( STR_PATCH_STATE_LIST_NOT_READ + DNPATCHINFO.GetLanguageOffset() ) );
return PR_FAIL;
}
PatchReturn nRetValue = GetPackingFile(); // <EFBFBD>^<EFBFBD>[<EFBFBD><EFBFBD> <EFBFBD><EFBFBD>'k <EFBFBD><EFBFBD><EFBFBD><EFBFBD> +<EFBFBD><EFBFBD>~ <EFBFBD>l
q+u JU<EFBFBD>^<EFBFBD>T
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 ) )
{
// f<EFBFBD>R <EFBFBD>lhd <EFBFBD>O<EFBFBD>o <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD>~<EFBFBD>W<EFBFBD>O.
m_nCurPatchCount++;
g_DownloadInfoData.m_nDownloadProgressMin = m_nCurPatchCount;
g_DownloadInfoData.m_nDownloadProgressMax = m_nTotalPatchCount;
bIsNoramlFile = FALSE;
break;
}
}
if( bIsNoramlFile )
{
#ifdef _TEST // <EFBFBD>b<EFBFBD><EFBFBD>ؘ<EFBFBD>O A~8<EFBFBD><EFBFBD>r Hr<EFBFBD>_ Hr<EFBFBD><EFBFBD>JU <EFBFBD>p<EFBFBD>r<EFBFBD><EFBFBD> <EFBFBD>`<EFBFBD>l<EFBFBD>w P<EFBFBD> PNh<EFBFBD><EFBFBD><EFBFBD><EFBFBD> R<EFBFBD>0<EFBFBD>8<EFBFBD><EFBFBD>p 8<EFBFBD><EFBFBD>^
TCHAR szCurDir[ _MAX_PATH ]={0,};
GetCurrentDirectory( _MAX_PATH, szCurDir );
SetCurrentDirectory( DNPATCHINFO.GetClientPath() );
#endif // _TEST
//<EFBFBD><EFBFBD><EFBFBD> <EFBFBD>S<EFBFBD>lM<EFBFBD><EFBFBD>^ f<EFBFBD>R JU<EFBFBD>t wJU.
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 ) // )R<EFBFBD>[<EFBFBD> <EFBFBD>P<EFBFBD>W^c <EFBFBD>~hd <EFBFBD>'TAb
{
stFileIndexSet fileIndex;
fileIndex.m_dwPakFileNum = i;
fileIndex.m_dwPatchFileIndex = nPatchFileCount;
fileIndex.m_dwReserveFileIndex = m_vecPackingFile[i]->ReservePatchFile( pFileInfo );
m_vecReserveIndex.push_back( fileIndex );
}
else // )R<EFBFBD>[<EFBFBD> <EFBFBD>P<EFBFBD>W^c PN<EFBFBD>Od <EFBFBD><EFBFBD>yd
{
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 // <EFBFBD><EFBFBD>yd <EFBFBD><EFBFBD><EFBFBD><EFBFBD>r <EFBFBD>QAbJU yk <EFBFBD>R Hr<EFBFBD>_ $v<EFBFBD>_<EFBFBD>~ <EFBFBD>r<EFBFBD>T
{
// <EFBFBD>P<EFBFBD>v <EFBFBD><EFBFBD>'k <EFBFBD><EFBFBD><EFBFBD><EFBFBD>O<EFBFBD><EFBFBD> f<EFBFBD>R <EFBFBD>wch<EFBFBD>zch<EFBFBD>^ <EFBFBD>[<EFBFBD>S
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 )
{
// <EFBFBD><EFBFBD>ydN <EFBFBD>Vyd+u +<EFBFBD>$v <EFBFBD>~<EFBFBD>lhd <EFBFBD>R<EFBFBD> )R<EFBFBD>[<EFBFBD> <EFBFBD>Vyd+u +<EFBFBD>R<EFBFBD><EFBFBD><EFBFBD> c<EFBFBD>~<EFBFBD><EFBFBD>O
int nBestIndex = -1;
DWORD dwMinSize = ULONG_MAX;
for( int j=0; j<(int)m_vecPackingFile.size(); j++ )
{
DWORD dwPackingFileSize = m_vecPackingFile[j]->GetFileSystemSize();
// 512<EFBFBD>vJU
q<EFBFBD>O<EFBFBD>~ /}R<EFBFBD>wQ PR<EFBFBD>~ c<EFBFBD> P<EFBFBD> PN<EFBFBD>O
if( ( dwPackingFileSize < dwMinSize ) && ( dwPackingFileSize < (DWORD)DEFAULT_PACKING_FILE_SIZE ) )
{
dwMinSize = dwPackingFileSize;
nBestIndex = j;
}
}
if( nBestIndex == -1 )
{
// <EFBFBD><EFBFBD>ydN )R<EFBFBD>[<EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD>~+<EFBFBD><EFBFBD>uhd '<EFBFBD><EFBFBD><EFBFBD>>k <EFBFBD><EFBFBD>yd<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6r5u<EFBFBD>O.
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++ )
{
// <EFBFBD><EFBFBD><EFBFBD>^c<EFBFBD>b ʃ<EFBFBD>O.. \ ?V<EFBFBD>~ PN<EFBFBD>~<EFBFBD><EFBFBD>
_<EFBFBD><EFBFBD> <EFBFBD>R<EFBFBD>[<EFBFBD> ^c<EFBFBD>bh<EFBFBD><EFBFBD> <EFBFBD><EFBFBD>ywQ <EFBFBD>R<EFBFBD>c<EFBFBD><EFBFBD> I{<EFBFBD>O.
// <EFBFBD>XTN<EFBFBD>^<EFBFBD><EFBFBD>ؘ<EFBFBD>O PN<EFBFBD>~<EFBFBD>]<EFBFBD>{ <EFBFBD><EFBFBD><EFBFBD>O 8u<EFBFBD>~JUd Qe<EFBFBD>Q <EFBFBD><EFBFBD><EFBFBD><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 ) // Ab<EFBFBD>|<EFBFBD>O <EFBFBD>|<EFBFBD>r<EFBFBD>z<EFBFBD>~ <EFBFBD><EFBFBD><EFBFBD>br$v kQd<EFBFBD><EFBFBD>y<EFBFBD><EFBFBD> <EFBFBD><EFBFBD>ydJU<EFBFBD>t<EFBFBD>zd <EFBFBD><EFBFBD>yd
return PR_FAIL;
if( !bPatch )
{
if( PatchFileSuitableSpace( PatchSource, pFileInfo, bPatch ) == PR_FAIL ) // )R<EFBFBD>[<EFBFBD> <EFBFBD>P<EFBFBD>W^c PN<EFBFBD>Od
_Q<EFBFBD><EFBFBD>O <EFBFBD><EFBFBD>yd
return PR_FAIL;
if( !bPatch )
PatchFileReserve( i, pFileInfo ); // Ab<EFBFBD>|<EFBFBD>O <EFBFBD>|<EFBFBD>r<EFBFBD>z$vch )R<EFBFBD>[<EFBFBD> <EFBFBD>P<EFBFBD>Wch <EFBFBD>~<EFBFBD>Od <EFBFBD>P<EFBFBD>W^c <EFBFBD>]<EFBFBD>{ Pak<EFBFBD><EFBFBD><EFBFBD><EFBFBD>r ,{<EFBFBD>O ?V^cAb <EFBFBD>V<EFBFBD>y<EFBFBD><EFBFBD> <EFBFBD>bݍ6r 'T<EFBFBD>~<EFBFBD>r
}
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;
}
}
// <EFBFBD>bݍI{ <EFBFBD>P<EFBFBD>W<EFBFBD> <EFBFBD>S<EFBFBD>Q<EFBFBD>n<EFBFBD>~ <EFBFBD>^yk+u Write
for( int j=0; j<(int)m_vecPackingFile.size(); j++ )
m_vecPackingFile[ j ]->WriteReserveFileInfo();
// <EFBFBD>bݍI{ <EFBFBD><EFBFBD>yd<EFBFBD><EFBFBD><EFBFBD>8u <EFBFBD><EFBFBD>yd
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 ) ) // ^c<EFBFBD>V <EFBFBD>bݍI{ FileInfo^c<EFBFBD><EFBFBD><EFBFBD><EFBFBD> FileInfo <EFBFBD>v<EFBFBD><EFBFBD>z$v <EFBFBD><EFBFBD><EFBFBD>o
{
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 // <EFBFBD>b<EFBFBD><EFBFBD>ؘ<EFBFBD>O A~8<EFBFBD><EFBFBD>r Hr<EFBFBD>_ Hr<EFBFBD><EFBFBD>JU <EFBFBD>p<EFBFBD>r<EFBFBD><EFBFBD> <EFBFBD>`<EFBFBD>l<EFBFBD>w P<EFBFBD> PNh<EFBFBD><EFBFBD><EFBFBD><EFBFBD> R<EFBFBD>0<EFBFBD>8<EFBFBD><EFBFBD>p 8<EFBFBD><EFBFBD>^
TCHAR szCurDirectory[ _MAX_PATH ]={0,};
GetCurrentDirectory( _MAX_PATH, szCurDirectory );
SetCurrentDirectory( DNPATCHINFO.GetClientPath() );
#endif // _TEST
for( int i=0; i<(int)m_vecCopyList.size(); i++ )
{
//<EFBFBD><EFBFBD>Qe<EFBFBD>O<EFBFBD>~ \ <EFBFBD><EFBFBD><EFBFBD>ʃ<EFBFBD>O ?VAb<EFBFBD>Z<EFBFBD>w <EFBFBD>+u<EFBFBD>V<EFBFBD>y<EFBFBD><EFBFBD> ?V<EFBFBD>T<EFBFBD><EFBFBD>O.
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_NAMEJU <EFBFBD>|<EFBFBD>r<EFBFBD>ywQ<EFBFBD>z<EFBFBD>T, DNLAUNCHER_NAME+u DNLAUNCHER_NAME_TMP<EFBFBD><EFBFBD> <EFBFBD>QHr<EFBFBD><EFBFBD>O.
if( _access( DNLAUNCHER_NAME, 0 ) == 0 && MoveFile( _T( DNLAUNCHER_NAME ), _T( DNLAUNCHER_NAME_TMP ) ) == 0 ) // A~8<EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>u<EFBFBD> <EFBFBD>[<EFBFBD>d<EFBFBD>~ ҉R<EFBFBD><EFBFBD>zyk|bch A~8<EFBFBD><EFBFBD><EFBFBD>ydJU {vch<EFBFBD>^ <EFBFBD>z
{
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 );
// <EFBFBD>~t<EFBFBD>P<EFBFBD> <EFBFBD>~<EFBFBD>O. 512M <EFBFBD><EFBFBD>~JU<EFBFBD>~<EFBFBD>]T<EFBFBD>O <EFBFBD>i|b<EFBFBD><EFBFBD> wJU<EFBFBD>z<EFBFBD>x.
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,}; // <EFBFBD>v/Y <EFBFBD><EFBFBD><EFBFBD> <EFBFBD>u ( ApplyPatch32 ҉R<EFBFBD><EFBFBD>w CallBack Function<EFBFBD>O<EFBFBD><EFBFBD> <EFBFBD>`<EFBFBD>l<EFBFBD><EFBFBD>O. )
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<EFBFBD><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<EFBFBD><EFBFBD><EFBFBD><EFBFBD>O <EFBFBD>y<EFBFBD>[<EFBFBD>z<EFBFBD>~ <EFBFBD><EFBFBD><EFBFBD>^c PN<EFBFBD>Od wMQ
{
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<EFBFBD><EFBFBD><EFBFBD><EFBFBD>O<EFBFBD><EFBFBD> <EFBFBD>~+<EFBFBD><EFBFBD>u<EFBFBD>Od <EFBFBD>R|b^c+ _yk<EFBFBD>O<EFBFBD><EFBFBD> +<EFBFBD>R<EFBFBD>/Y<EFBFBD>O.
{
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 )R<EFBFBD>OI{ <EFBFBD><EFBFBD><EFBFBD><EFBFBD> '<EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>w<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>O c<EFBFBD>~<EFBFBD>O.
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 ) // <EFBFBD>vN<EFBFBD><EFBFBD><EFBFBD> 100<EFBFBD>O <EFBFBD><EFBFBD>~<EFBFBD>T <EFBFBD><EFBFBD>{ <EFBFBD>~<EFBFBD> <EFBFBD>]
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" );
// <EFBFBD>h<EFBFBD>[<EFBFBD>y8<EFBFBD> <EFBFBD>O>k<EFBFBD><EFBFBD>[<EFBFBD> {<EFBFBD>~$v 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