Files
2022-10-26 12:25:11 +08:00

352 lines
9.5 KiB
C++

#include ".\launcherupdate.h"
#include <io.h>
#include <windows.h>
#include "MyFolder.h"
CLauncherUpdate::CLauncherUpdate(void)
{
SetUpdateType( UPDATE_TYPE_LAUNCHER );
}
CLauncherUpdate::~CLauncherUpdate(void)
{
}
//중간에 종료되어야 할 상황이면, FALSE
//모든것이 완료 되었을 때는 TRUE를 리턴한다.
BOOL CLauncherUpdate::StartUpdate()
{
// 기본 다운로드 디렉토리 설정
PROCESS_INFO_MAP_ITER iter;
BYTE byUpdateSeq = 0;
for( iter = m_mapProcessInfo.begin(); iter != m_mapProcessInfo.end(); ++iter )
{
PROCESS_INFO* pInfo = iter->second;
if( !pInfo ) continue;
pInfo->m_byUpdateSequence = byUpdateSeq;
byUpdateSeq++;
if( m_byUpdateNumber != 0 ) //일정한 서버만 업데이트 면..
{
if( pInfo->m_byUpdateNumber != m_byUpdateNumber )
continue;
}
if( GetStartType() != START_TYPE_LAUNCHER ) //런처가 실행했을 경우에는 프로세서 체크를 하지 않는다.
{
if( !CheckLiveProcess( pInfo->m_szCheckProcess ) )
{
AddMessage( WM_UPDATE_LIVE_PROCESS, pInfo );
return FALSE;
}
}
//1. 기본정보 세팅.
m_UpdateModule.SetUpdateNumber( pInfo->m_byUpdateNumber );
m_UpdateModule.SetCurVerInfo( pInfo->m_szProcessVer );
m_UpdateModule.SetProcessName( pInfo->m_szProcessName );
m_UpdateModule.SetUpdateSequence( pInfo->m_byUpdateSequence );
//1. 다운받을 프로세서의 로컬 디렉토리를 생성한다.
m_UpdateModule.CreateLocalProcessDownDir();
//2. 버전을 체크한다.
eRC_VERSION RcVersion = m_UpdateModule.CheckVersionFiles( m_UpdateModule.GetCurVersion() );
if( RcVersion == RC_VERSION_FILE_NOTEXIST || RcVersion == RC_VERSION_PARSING_FAIL )
{
AddMessage( WM_UPDATE_VERSION_CHECK_FAIL, pInfo );
return FALSE;
}
else if( RcVersion == RC_VERSION_LASTEST ) //최신버전이면. 넘어간다.
{
AddMessage( WM_UPDATE_LASTEST_VERSION, pInfo );
continue;
}
//3. 현재 실행 상태를 체크해서, 런처가 실행 시킨게 아닌데 업데이트를 해야하는 상황이면..
if( GetStartType() != START_TYPE_LAUNCHER )
{
//아래 명령이 실패든 성공이든, 무조건 프로세스는 종료되어야 한다.
CopyAndExcute();
return FALSE;
}
// 한개의 프로세서를 업데이트 한다.
if( m_UpdateModule.UpdateOneProcess() ) //필요정보, 프로세서이름과 최종버전
{
m_UpdateModule.GetCurVersion().GetStringVersion( pInfo->m_szProcessVer, MAX_PATH );
AddMessage( WM_UPDATE_END_SUCCESS, pInfo );
}
else
{
AddMessage( WM_UPDATE_END_FAIL, pInfo );
DeleteFile( DEFAULT_FILELIST_FILE ); //로컬에 다운받아 놨던 파일리스트를 삭제한다.
DeleteFile( DEFAULT_VERSION_FILE ); //로컬에 다운받아 놨던 버전파일을 삭제한다.
return FALSE;
}
if( GetStartType() == START_TYPE_LAUNCHER )
OnLauncherDownloadComplete( );
}
return TRUE;
}
//기본 다운로드 디렉토리에 Copy하고 실행한다.
BOOL CLauncherUpdate::CopyAndExcute()
{
DisconnectFTP();
//런처 업데이트에서는 프로세서 체크를 하기 전에
//먼저 현재의 실행 폴더를 템프 폴더에 복사 작업을 먼저해야 한다.
TCHAR szFromDir[MAX_PATH];
m_UpdateModule.GetModuleDirectory( szFromDir, MAX_PATH );
BYTE byCount = GetProcessInfoCount();
for( int i = 0; i < byCount ; i++ )
{
PROCESS_INFO* pInfo = GetProcessInfo( i+ 1 );
if( !pInfo ) return FALSE;
// TempFolder를 초기화 한다.
if( !InitTempFolder( pInfo ) ) return FALSE;
TCHAR szToPath[MAX_PATH];
if( !GetCopyFolderPath( pInfo, szToPath, MAX_PATH, FALSE ) ) return FALSE;
DeleteLastPathSep( szFromDir, MAX_PATH ); // 끝에 "\\" 가 있으면 삭제한다.
DeleteLastPathSep( szToPath, MAX_PATH ); // 끝에 "\\" 가 있으면 삭제한다.
//현재 런처 디렉토리의 내용을 Copy폴더로 복사한다.
if( !MyFolder::CopyFoler( szFromDir, szToPath ) )
{
m_UpdateModule.AddMessage( WM_COMMAND_MESSAGE, "템프 카피 폴더로 런처폴더 복사 실패");
return FALSE;
}
//복사가 다 되었으면.. 해당 프로세서를 실행한다.
string strFile = szToPath;
strFile += "\\";
strFile += pInfo->m_szProcessName;
strFile += "\\";
strFile += pInfo->m_szCheckProcess;
if( _access( strFile.c_str(), 0 ) != -1 ) //파일이 존재하면..
{
strFile += " <LAUNCHER> ";
strFile += m_szExecuteParameter;
if( !ExcuteProcess( (TCHAR*)strFile.c_str() ) )
return FALSE;
}
static TCHAR szLog[MAX_PATH];
_snprintf( szLog, MAX_PATH, "[Copy Folder Success] From : %s, To : %s", szFromDir, szToPath );
m_UpdateModule.AddMessage( WM_COMMAND_MESSAGE, szLog );
}
return TRUE;
}
//런처 업데이트가 완료시 실행되는 함수
BOOL CLauncherUpdate::OnLauncherDownloadComplete()
{
// 현재 런처의 업데이트가 아니면 리턴한다.
if( GetUpdateType() != UPDATE_TYPE_LAUNCHER )
return FALSE;
//런처 업데이트 완료시
//1. Down 폴더에서 원본폴더로 복사하고,
//2. 원본에 버전을 올린다.
//3. 업데이트된 런처를 실행하고
//4. 현재 프로세서를 종료한다.
for( int i = 0; i < GetProcessInfoCount(); i++ )
{
PROCESS_INFO* pInfo = GetProcessInfo( i + 1 );
TCHAR szBasicDownDir[MAX_PATH];
GetLocalBasicDownDir( szBasicDownDir, MAX_PATH );
//1. 런처가 다운로드된 곳에서 런처가 실행되는곳으로 복사( TempDown에서 실행위치로 복사 )
TCHAR szDownPath[MAX_PATH];
if( !GetDownFolderPath( pInfo, szDownPath, MAX_PATH ) ) return FALSE;
TCHAR szExecuteDir[MAX_PATH];
GetLocalBasicExecuteDir( szExecuteDir, MAX_PATH );
if( !MyFolder::CopyFoler( szDownPath, szExecuteDir ) )
m_UpdateModule.AddMessage( WM_COMMAND_MESSAGE, "폴더 복사 실패" );
else
{
static char szCopyFolder[MAX_PATH];
_snprintf( szCopyFolder, MAX_PATH, "[Copy Folder Success] From : %s, To : %s", szDownPath, szExecuteDir );
m_UpdateModule.AddMessage( WM_COMMAND_MESSAGE, szCopyFolder );
}
//2. INI 파일 복사( Copy에서 실행버전으로.. )
string strFromFile;
strFromFile = szBasicDownDir;
strFromFile += "\\Copy\\";
strFromFile += pInfo->m_szProcessName;
strFromFile += "\\";
strFromFile += DEFAULT_UPDEATEINFO_FILE;
string strToFile = szExecuteDir;
strToFile += "\\";
strToFile += pInfo->m_szProcessName;
strToFile += "\\";
strToFile += DEFAULT_UPDEATEINFO_FILE;
if( !CopyFile( strFromFile.c_str(), strToFile.c_str(), FALSE ) )
{
TCHAR szMsg[MAX_PATH];
wsprintf( szMsg, "From = %s, To = %s, ErrorCode = %d", strFromFile.c_str(), strToFile.c_str(), GetLastError() );
AddMessage( WM_COMMAND_MESSAGE, szMsg );
}
else
{
static char szCopyFile[MAX_PATH];
_snprintf( szCopyFile, MAX_PATH, "[Copy File Success] From : %s, To : %s", strFromFile.c_str(), strToFile.c_str() );
m_UpdateModule.AddMessage( WM_COMMAND_MESSAGE, szCopyFile );
}
//3. 업데이트된 런처 실행
string strFile = szExecuteDir;
strFile += "\\";
strFile += pInfo->m_szProcessName;
strFile += "\\";
strFile += pInfo->m_szCheckProcess;
if( _access( strFile.c_str(), 0 ) != -1 ) //파일이 존재하면..
{
strFile += " <APPLICATION>";
strFile += m_szExecuteParameter;
if( !ExcuteProcess( (TCHAR*)strFile.c_str() ) )
return FALSE;
}
}
return TRUE;
}
BOOL CLauncherUpdate::ExcuteProcess( TCHAR* pszPath )
{
if( pszPath == NULL )
return FALSE;
if( WinExec( pszPath, SW_SHOW ) > 31 ) //성공이면..
m_UpdateModule.SendTerminateProcessMsg();
else
{
m_UpdateModule.AddMessage( WM_COMMAND_MESSAGE, "실행실패" );
return FALSE; //실패했으면, 실패 처리..
}
return TRUE;
}
BOOL CLauncherUpdate::InitTempFolder( PROCESS_INFO* pInfo )
{
if( !pInfo ) return FALSE;
string strCopyPath, strDownPath, strTempPath;
//1. 기존의 Copy 폴더가 있으면 Copy폴더 삭제
TCHAR szCopyFolderPath[MAX_PATH];
if( !GetCopyFolderPath( pInfo, szCopyFolderPath, MAX_PATH ) ) return FALSE;
if( _access( szCopyFolderPath, 0 ) != -1 ) //파일이나 폴더가 존재하면..
{
if( !DeleteFolder( szCopyFolderPath ) )
{
m_UpdateModule.AddMessage( WM_COMMAND_MESSAGE, "Temp Copy 폴더 삭제 실패");
return FALSE;
}
}
//2. 기본의 Down 디렉토리가 있으면 Down폴더 삭제.
TCHAR szDownFolderPath[MAX_PATH];
if( !GetDownFolderPath( pInfo, szDownFolderPath, MAX_PATH ) ) return FALSE;
if( _access( szDownFolderPath, 0 ) != -1 ) //파일이나 폴더가 존재하면..
{
if( !DeleteFolder( szDownFolderPath ) )
{
m_UpdateModule.AddMessage( WM_COMMAND_MESSAGE, "Temp Down 폴더 삭제 실패");
return FALSE;
}
}
//3. Temp Copy 디렉토리를 만든다.
if( !CreateDirectory( szCopyFolderPath, NULL ) )
{
m_UpdateModule.AddMessage( WM_COMMAND_MESSAGE, "Temp Copy 폴더 생성 실패");
return FALSE;
}
return TRUE;
}
BOOL CLauncherUpdate::GetCopyFolderPath( PROCESS_INFO* pInfo, OUT TCHAR* pszPath, int nSize, BOOL bIncludeProcessName )
{
if( !pInfo || !pszPath ) return FALSE;
TCHAR szBasicDownDir[MAX_PATH];
m_UpdateModule.GetLocalBasicDownDir( szBasicDownDir, MAX_PATH );
string strTempPath = szBasicDownDir;
int nPos = (int)strTempPath.find( "Down" );
if( nPos == std::string::npos )
{
AddMessage( WM_COMMAND_MESSAGE, "Down 찾기 실패" );
return FALSE;
}
strTempPath.erase( nPos, strTempPath.length() - nPos );
strTempPath += "Copy";
if( bIncludeProcessName == TRUE )
{
strTempPath += "\\";
strTempPath += pInfo->m_szProcessName;
}
strncpy( pszPath, strTempPath.c_str(), nSize );
return TRUE;
}
BOOL CLauncherUpdate::GetDownFolderPath( PROCESS_INFO* pInfo, OUT TCHAR* pszPath, int nSize, BOOL bIncludeProcessName )
{
if( !pInfo ) return FALSE;
TCHAR szBasicDownDir[MAX_PATH];
m_UpdateModule.GetLocalBasicDownDir( szBasicDownDir, MAX_PATH );
if( bIncludeProcessName == TRUE )
_snprintf( pszPath, nSize, "%s\\%s", szBasicDownDir, pInfo->m_szProcessName );
else
strncpy( pszPath, szBasicDownDir, nSize );
return TRUE;
}
VOID CLauncherUpdate::DeleteLastPathSep( IN OUT TCHAR* pszPath, int nSize )
{
string strPath = pszPath;
int nPathSize = (int)strPath.size();
if( nPathSize > 0 )
{
string strEnd = strPath.substr( nPathSize - 1, 1 );
if( strEnd.compare("\\") == 0 )
strPath.erase( nPathSize - 1, 1 );
}
strncpy( pszPath, strPath.c_str(), nSize );
}