760 lines
21 KiB
C++
760 lines
21 KiB
C++
#include ".\updatemodule.h"
|
|
#include <io.h>
|
|
#include <Tlhelp32.h> //PROCESSENTRY32
|
|
#include <shlwapi.h> //PathIsDirectory
|
|
#include "ScriptParser.h"
|
|
|
|
CUpdateModule::CUpdateModule(void)
|
|
{
|
|
ZeroMemory( &m_UpdateInfo, sizeof(m_UpdateInfo) );
|
|
ZeroMemory( m_szBasicDownDir, MAX_PATH ); //로컬에 다운로드할 기본 경로.
|
|
m_bUpdateStart = TRUE;
|
|
m_fnMsgCallback = NULL;
|
|
}
|
|
|
|
CUpdateModule::~CUpdateModule(void)
|
|
{
|
|
}
|
|
|
|
|
|
BOOL CUpdateModule::ConnectFTP( TCHAR* pszIP, int nPort, TCHAR* pszID, TCHAR* pszPass )
|
|
{
|
|
DWORD ErrorCode = 0;
|
|
return m_FtpNetwork.Connect( pszIP, nPort, pszID, pszPass, ErrorCode );
|
|
}
|
|
|
|
VOID CUpdateModule::DisconnectFTP()
|
|
{
|
|
if( m_FtpNetwork.IsConnectFTP() == TRUE )
|
|
m_FtpNetwork.DisConnect();
|
|
}
|
|
|
|
BOOL CUpdateModule::GetFtpIP( TCHAR* pszIP, int nSize )
|
|
{
|
|
if( pszIP == NULL || (strcmp( pszIP, "" ) == 0) )
|
|
return FALSE;
|
|
|
|
m_FtpNetwork.GetIP( pszIP, nSize );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
int CUpdateModule::GetFtpPort()
|
|
{
|
|
return m_FtpNetwork.GetPort();
|
|
}
|
|
|
|
HANDLE CUpdateModule::MakeLocalFile( const TCHAR* pszLocalFilePath)
|
|
{
|
|
HANDLE hLocalFile = CreateFile(pszLocalFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
|
|
|
if( hLocalFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
//1. 읽기 전용속성인지 체크한다.
|
|
if( GetFileAttributes( pszLocalFilePath ) && FILE_ATTRIBUTE_READONLY )
|
|
{
|
|
if( SetFileAttributes( pszLocalFilePath, FILE_ATTRIBUTE_NORMAL ) )
|
|
{
|
|
hLocalFile = CreateFile(pszLocalFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
|
if( hLocalFile ) return hLocalFile;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
return hLocalFile;
|
|
}
|
|
|
|
//pszRemoteFilePath : 파일이름이 포함된 원격지 경로, 루트부터 시작된 경로여야 한다.
|
|
//pszLocalPath : 파일이름이 포함되지 않은 순수한 로컬 경로
|
|
BOOL CUpdateModule::DownloadFile( const TCHAR* pszRemoteFilePath, TCHAR* pszLocalPath)
|
|
{
|
|
HANDLE hLocalFile = INVALID_HANDLE_VALUE;
|
|
HINTERNET hFtpFile = NULL;
|
|
|
|
//1. 원격서버 경로를 분석한다.
|
|
TCHAR szRemoteDir[MAX_PATH];
|
|
TCHAR szRemoteFileName[MAX_PATH];
|
|
GetSplitFilePath( pszRemoteFilePath, szRemoteDir, szRemoteFileName );
|
|
|
|
CHAR szRealLocalFilePath[MAX_PATH];
|
|
GetLocalFileName( pszLocalPath, szRemoteFileName, szRealLocalFilePath );
|
|
|
|
__try
|
|
{
|
|
hLocalFile = MakeLocalFile( szRealLocalFilePath );
|
|
if(hLocalFile == NULL)
|
|
{
|
|
AddMessage( WM_COMMAND_MESSAGE, "로컬 파일 생성 실패" );
|
|
return FALSE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 원격지 작업 폴더 설정
|
|
if( !SetRemoteDirectory( szRemoteDir ) )
|
|
{
|
|
strncpy( m_UpdateInfo.m_szFileName, szRemoteDir, MAX_PATH );
|
|
AddMessage( WM_FTP_DIRECTORY_NOTFOUND, &m_UpdateInfo );
|
|
return FALSE; //원격지에 해당 디렉토리가 존재하지 않습니다.
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 원격지 파일정보 얻기
|
|
WIN32_FIND_DATA info;
|
|
if( !m_FtpNetwork.GetFileInfo( szRemoteFileName, info ) ) //파일이 존재하지 않으면..
|
|
{
|
|
strncpy( m_UpdateInfo.m_szFileName, szRemoteFileName, MAX_PATH );
|
|
AddMessage( WM_FTP_FILE_NOTFOUND, &m_UpdateInfo );
|
|
return FALSE; //하나라도 파일이 존재하지 않으면 업데이트를 취소한다.
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 3 . 원격지 파일 열기
|
|
hFtpFile = m_FtpNetwork.OpenFtpFile( szRemoteFileName );
|
|
if( hFtpFile == NULL )
|
|
{
|
|
strncpy( m_UpdateInfo.m_szFileName, szRemoteFileName, MAX_PATH );
|
|
AddMessage( WM_FTP_FILE_OPEN_FAIL, &m_UpdateInfo );
|
|
DeleteFile( szRealLocalFilePath );
|
|
return FALSE; // 파일 하나만 실패해도 다운로드를 멈춤다.
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 4. 원격지 파일 다운로드
|
|
strncpy( m_UpdateInfo.m_szFileName, info.cFileName, MAX_PATH );
|
|
AddMessage( WM_FILE_DOWNLOAD_START, &m_UpdateInfo );
|
|
|
|
if( !m_FtpNetwork.DownloadFile( hFtpFile, info, hLocalFile ) )
|
|
{
|
|
// 파일 얻기에 실패하면, 현재 만들어진 로컬 파일도 삭제한다.
|
|
DeleteFile( szRealLocalFilePath );
|
|
AddMessage( WM_FILE_DOWNLOAD_FAIL, &m_UpdateInfo );
|
|
return FALSE;
|
|
}
|
|
|
|
//파일 다운로드 성공
|
|
AddMessage( WM_FILE_DOWNLOAD_END, &m_UpdateInfo );
|
|
}
|
|
__finally
|
|
{
|
|
if ( hFtpFile )
|
|
InternetCloseHandle( hFtpFile );
|
|
if ( hLocalFile != INVALID_HANDLE_VALUE )
|
|
CloseHandle(hLocalFile);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL CUpdateModule::GetSplitFilePath(const TCHAR* pszFilePath, TCHAR* pszDir, TCHAR* pszFile)
|
|
{
|
|
char pszFileName[MAX_PATH];
|
|
char pszFileExt[MAX_PATH];
|
|
|
|
//여기서 서버폴더 조건이 따른다.
|
|
//서버의 폴더는 루트에서 하위 1단계 까지만 존재한다.
|
|
_splitpath(pszFilePath, NULL, pszDir, pszFileName, pszFileExt );
|
|
if(pszDir == NULL || (strcmp(pszDir, "") == 0) )
|
|
wsprintf(pszDir, "\\");
|
|
|
|
wsprintf( pszFile, "%s%s", pszFileName, pszFileExt);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//원격지의 파일리스트 파일의 경로를 구한다.
|
|
void CUpdateModule::GetRemoteFileListPath( char* pszFilePath, int nSize, const char* pszVerFolder )
|
|
{
|
|
TCHAR szCurServer[MAX_PATH];
|
|
GetProcessName( szCurServer, MAX_PATH );
|
|
|
|
if( szCurServer == NULL || strcmp( szCurServer, "" ) == 0 )
|
|
_snprintf( pszFilePath, nSize, "%s\\%s", pszVerFolder, DEFAULT_FILELIST_FILE );
|
|
else
|
|
_snprintf( pszFilePath, nSize, "%s\\%s\\%s", szCurServer, pszVerFolder, DEFAULT_FILELIST_FILE );
|
|
|
|
}
|
|
|
|
|
|
BOOL CUpdateModule::GetLocalFileName(const TCHAR* pszLocalPath, const TCHAR* pszRemoteFileName, TCHAR* pszLocalFilePath)
|
|
{
|
|
// 여기서 로컬 파일이름이 없다면 원격파일이름과 동일하게 만든다.
|
|
if ( (!pszLocalPath) || ( strcmp(pszLocalPath, "") == 0 ) )
|
|
wsprintf( pszLocalFilePath, ".\\%s", pszRemoteFileName );
|
|
else
|
|
{
|
|
// 끝에 \ 이 있는지 없는지 검사해서 적용한다.
|
|
if (pszLocalPath[strlen(pszLocalPath)-1] != '\\')
|
|
wsprintf(pszLocalFilePath, "%s\\%s", pszLocalPath, pszRemoteFileName );
|
|
else
|
|
wsprintf(pszLocalFilePath, "%s%s", pszLocalPath, pszRemoteFileName);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//pszRemoteDir은 루트에 .\ 이런 것이 안붙는다.
|
|
//pszRemoteDir은 루트에서 부터의 경로이다.
|
|
//루트는 아무것도 안 붙는다.
|
|
//만일 .\AgentServer\\sss 경로에 있는 sss 폴더를 세팅하고 싶으면..
|
|
//pszRemoteDir은 AgentServer\\sss 이 되어야 한다.
|
|
BOOL CUpdateModule::SetRemoteDirectory(const TCHAR* pszRemoteDir)
|
|
{
|
|
BOOL bSuccess = FALSE;
|
|
|
|
//1. 루트로 설정
|
|
bSuccess = m_FtpNetwork.SetDirectory( "/" );
|
|
//2. 루트로 부터 디렉토리 설정
|
|
bSuccess = m_FtpNetwork.SetDirectory( pszRemoteDir );
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
//로컬 파일과 서버파일을 비교하여 다운 받을지 안 받을지를 결정한다.
|
|
//TRUE : 파일을 다운 받는다.
|
|
//FALSE : 파일을 다운 받지 않는다.
|
|
BOOL CUpdateModule::CanFileDownload( const TCHAR* pszLocalFilePath, const WIN32_FIND_DATA& remoteFileInfo )
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 현재 이 파일을 다운 받은적이 있는지 체크..
|
|
// 1. 서버파일과 똑같은 로컬파일이 있는지 체크
|
|
HANDLE hFile = CreateFile( pszLocalFilePath, GENERIC_READ, FILE_SHARE_READ,
|
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
|
|
if( hFile != INVALID_HANDLE_VALUE ) //파일이 존재한다.
|
|
{
|
|
//1. 로컬파일 정보 읽어오기
|
|
FILETIME localFileTime, remoteFileTime;
|
|
GetFileTime( hFile, NULL, NULL, &localFileTime );
|
|
|
|
//2. 원격지 파일 시간정보
|
|
remoteFileTime = remoteFileInfo.ftLastWriteTime;
|
|
|
|
// 정보를 다 읽었으니, 핸들을 닫는다.
|
|
CloseHandle( hFile );
|
|
|
|
// 두 파일의 시간이 동일하지 않다.
|
|
if( ( remoteFileTime.dwHighDateTime != localFileTime.dwHighDateTime ) ||
|
|
( remoteFileTime.dwLowDateTime != localFileTime.dwLowDateTime ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
else //시간마져 동일하다면... 파일의 크기 비교
|
|
{
|
|
FILE* pFile = fopen( pszLocalFilePath, "r");
|
|
long nLen = _filelength( _fileno(pFile) );
|
|
fclose(pFile);
|
|
return FALSE;
|
|
if( nLen == remoteFileInfo.nFileSizeLow ) //파일의 크기가 같다면..
|
|
return FALSE; //파일을 다운 받지 않는다.
|
|
else
|
|
return TRUE;
|
|
}
|
|
}
|
|
else //파일이 존재 하지 않으면..
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//파일 리스트에 있는 파일들을 다운 받는다.
|
|
BOOL CUpdateModule::DownloadFilesOnFileList( TCHAR* pszRemoteDirPath )
|
|
{
|
|
// 로컬에 리스트 파일을 다운 받았으면, 반드시 실행파일 경로에 있다. 따라서 이름만 써준다.
|
|
CScriptParser parser;
|
|
TCHAR szPath[MAX_PATH];
|
|
GetModuleDirectory( szPath, MAX_PATH );
|
|
SetCurrentDirectory( szPath );
|
|
|
|
if( !parser.SetFile( DEFAULT_FILELIST_FILE ) )
|
|
{
|
|
AddMessage( WM_UPDATE_ERROR ); //파일 리스트 파일 열기 실패.....
|
|
return FALSE;
|
|
}
|
|
|
|
string strLocalRelativeDirPath; //로컬 저장 디렉토리 상대경로
|
|
|
|
// 파일 리스트를 분석해서, 파일 리스트에 있는 파일들을 다운 받는 구문..
|
|
while( m_bUpdateStart )
|
|
{
|
|
UDTToken Token = parser.GetToken();
|
|
|
|
if( Token == END )
|
|
break;
|
|
|
|
if( Token == NAME ) // 파일이름인 경우
|
|
{
|
|
// 원격지 호스트의 전체경로이름
|
|
CHAR szCurrentRemoteFilePath[MAX_PATH];
|
|
ZeroMemory( szCurrentRemoteFilePath, MAX_PATH );
|
|
_snprintf( szCurrentRemoteFilePath, MAX_PATH, "%s\\%s", pszRemoteDirPath, parser.GetTokenString() );
|
|
|
|
string strAbsoluteDirPath;
|
|
GetAbsolteLocalDownDir( strLocalRelativeDirPath, strAbsoluteDirPath );
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 현재 이 파일을 다운 받은적이 있는지 체크..
|
|
// 1. 서버파일과 똑같은 로컬파일이 있는지 체크
|
|
string strLocalFilePath;
|
|
strLocalFilePath = strAbsoluteDirPath;
|
|
strLocalFilePath += "\\";
|
|
strLocalFilePath += parser.GetTokenString();
|
|
|
|
if ( !DownloadFile( szCurrentRemoteFilePath, const_cast<char*>(strAbsoluteDirPath.c_str()) ) )
|
|
return FALSE;
|
|
}
|
|
|
|
if( Token == NUMBER ) // 폴더이름인 경우
|
|
{
|
|
// 0이면 폴더를 생성하라는 명령이므로, 0 다음에 나오는 값을 읽어야 한다.
|
|
// 그 값이 폴더 명이다.
|
|
Token = parser.GetToken();
|
|
|
|
//1. 기본 로컬 경로 폴더가 있는지 체크. 없으면 생성
|
|
strLocalRelativeDirPath = "\\";
|
|
strLocalRelativeDirPath += parser.GetTokenString();
|
|
string strAbsoluteDirPath;
|
|
GetAbsolteLocalDownDir( strLocalRelativeDirPath, strAbsoluteDirPath );
|
|
strAbsoluteDirPath += "\\";
|
|
|
|
MakeDirectory( (TCHAR*)strAbsoluteDirPath.c_str() );
|
|
}
|
|
}
|
|
|
|
if( m_bUpdateStart == FALSE )
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//상대경로로 부터 로컬의 다운로드 절대 경로를 얻는다.
|
|
void CUpdateModule::GetAbsolteLocalDownDir( string strRelativeDir, string& strAbsolteDir )
|
|
{
|
|
if( strRelativeDir.length() == 0 )
|
|
strRelativeDir = "\\";
|
|
|
|
//만일 m_szBasicDownDir 가 null 이 들어 있을수 있다.. 따라서 그때는..
|
|
//현재 실행중인 디렉토리로 설정한다.
|
|
|
|
// 다운로드 디렉토리에 strRelativeDir(상대경로)를 덧붙여서 저장시킬 현재 로컬의 절대경로를 얻는다.
|
|
if( GetLocalBasicDownDir() == NULL || ( strcmp( GetLocalBasicDownDir(), "" ) == 0 ) )
|
|
{
|
|
char szDir[MAX_PATH];
|
|
GetModuleDirectory( szDir, MAX_PATH );
|
|
strAbsolteDir = szDir;
|
|
strAbsolteDir += strRelativeDir;
|
|
}
|
|
else
|
|
{
|
|
strAbsolteDir = GetLocalBasicDownDir();
|
|
strAbsolteDir += "\\";
|
|
strAbsolteDir += GetProcessName();
|
|
strAbsolteDir += strRelativeDir;
|
|
}
|
|
}
|
|
|
|
|
|
//현재 이 모듈이 위치하고 있는 곳의 절대경로를 리턴한다.
|
|
void CUpdateModule::GetModuleDirectory( TCHAR* pszDirPath, int nSize )
|
|
{
|
|
ZeroMemory( pszDirPath, nSize );
|
|
TCHAR szPath[MAX_PATH];
|
|
TCHAR szDrive[MAX_PATH], szDir[MAX_PATH];
|
|
GetModuleFileName( NULL, szPath, MAX_PATH);
|
|
_splitpath( szPath, szDrive, szDir, NULL, NULL );
|
|
_snprintf( pszDirPath, nSize, "%s%s", szDrive, szDir);
|
|
}
|
|
|
|
// 01.02.03 과 같은 문자열에서 각각의 버전을 뽑아내는 함수.
|
|
void CUpdateModule::GetVersionFromString( char* pszVersion, byte* byVer, int nMaxVerCount )
|
|
{
|
|
// char* szTok;
|
|
string strVersion = pszVersion;
|
|
int nCnt = 0;
|
|
|
|
while( strVersion.size() != 0)
|
|
{
|
|
if( nCnt >= nMaxVerCount )
|
|
break;
|
|
|
|
int nIdx = (int)strVersion.find('.');
|
|
if( nIdx == string::npos )
|
|
{
|
|
if( !strVersion.empty() )
|
|
{
|
|
byVer[nCnt] = atoi( strVersion.c_str() );
|
|
}
|
|
|
|
strVersion.clear();
|
|
}
|
|
else
|
|
{
|
|
string strVer = strVersion.substr( 0, nIdx );
|
|
byVer[nCnt] = atoi( strVer.c_str() );
|
|
strVersion.erase( 0, nIdx + 1);
|
|
nCnt++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//현재 컴퓨터에 업데이트하고 있는 프로그램이 실행중인지 체크.
|
|
//실행중인 프로그램이 하나라도 있으면 TRUE리턴
|
|
//아니면 FASLE를 리턴..
|
|
BOOL CUpdateModule::CheckLiveProcess( TCHAR* pszProcess, BOOL bKillProcess )
|
|
{
|
|
if( !pszProcess || strcmp( pszProcess, "" ) == 0 )
|
|
return FALSE;
|
|
|
|
// 프로세스 체크 런쳐나 게임 클라이언트가 실행중인지 체크한다
|
|
HANDLE hSnapShot;
|
|
|
|
//Get the snapshot of the system
|
|
hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );
|
|
|
|
PROCESSENTRY32 pEntry;
|
|
pEntry.dwSize = sizeof(pEntry);
|
|
|
|
//Get first process
|
|
Process32First (hSnapShot,&pEntry);
|
|
|
|
//Iterate thru all processes
|
|
DWORD dwPID = GetCurrentProcessId();
|
|
|
|
while(TRUE)
|
|
{
|
|
BOOL bRet = Process32Next (hSnapShot,&pEntry);
|
|
if( bRet == FALSE )
|
|
break;
|
|
|
|
//자기 자신은 넘어간다.
|
|
if(dwPID == pEntry.th32ProcessID)
|
|
continue;
|
|
|
|
// 실행 중인지 체크하도록 한다.
|
|
if( strcmp(pEntry.szExeFile, pszProcess ) == 0 ) //현재 같은 프로그램이 실행중이라면..
|
|
{
|
|
if( bKillProcess )
|
|
{
|
|
KillProcess(pEntry.th32ProcessID);
|
|
return FALSE;
|
|
}
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
}// End While
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// 이 함수는 서버의 버전파일을 다운 받아서, 현재 클라이언트의 버전과 비교하여,
|
|
// 업데이트를 할지 안 할지를 결정하는 함수다.
|
|
// 버전체크 실패면, FALSE
|
|
// 업데이트 파일이 없으면, FALSE
|
|
// 성공이면, TRUE
|
|
eRC_VERSION CUpdateModule::CheckVersionFiles( CVersionInfo& rVerInfo )
|
|
{
|
|
// 1 . 서버에 있는 버전 파일을 다운 받는다.
|
|
// 현재 다운받을려는 서버의 폴더에 있는 버전 파일을 다운 받는다. 받은 파일은 로컬에 다운받는다.
|
|
TCHAR szVerFilePath[MAX_PATH];
|
|
GetRemoteVersionFilePath( szVerFilePath, MAX_PATH );
|
|
|
|
//현재 디렉토리 설정..
|
|
TCHAR szPath[MAX_PATH];
|
|
GetModuleDirectory( szPath, MAX_PATH );
|
|
SetCurrentDirectory( szPath );
|
|
|
|
//다운받은 버전파일은 언제 삭제할 것인가?
|
|
if( !DownloadFile( szVerFilePath ) )
|
|
return RC_VERSION_FILE_NOTEXIST;
|
|
|
|
// 2 . 다운 받은 버전 파일에서 현재 클라이언트의 버전과 비교하여 받을 파일이 있으면 해당 폴더에서 목록파일을 받는다.
|
|
if( !GetUpdateFolderCount( rVerInfo, m_byUpdateFolderCount ) )
|
|
{
|
|
return RC_VERSION_PARSING_FAIL;
|
|
}
|
|
|
|
DeleteFile( DEFAULT_VERSION_FILE );
|
|
|
|
if( m_byUpdateFolderCount == 0 ) //업데이트 할 파일이 없다. 현재 최신버전 이다.
|
|
return RC_VERSION_LASTEST;
|
|
|
|
return RC_VERSION_NEED_UPDATE;
|
|
}
|
|
|
|
|
|
//원격지의 버전폴더의 경로를 반환한다.
|
|
void CUpdateModule::GetRemoteVersionFolderPath( TCHAR* pszFolderPath, int nSize, const TCHAR* pszVerFolder )
|
|
{
|
|
TCHAR szCurServer[MAX_PATH];
|
|
GetProcessName( szCurServer, MAX_PATH );
|
|
|
|
if( szCurServer == NULL || strcmp( szCurServer, "" ) == 0 )
|
|
_snprintf( pszFolderPath, nSize, "%s", pszVerFolder );
|
|
else
|
|
_snprintf( pszFolderPath, nSize, "%s\\%s", szCurServer, pszVerFolder );
|
|
}
|
|
|
|
BOOL CUpdateModule::Init()
|
|
{
|
|
m_bUpdateStart = TRUE;
|
|
|
|
m_FtpNetwork.m_fnMsgCallBack = m_fnMsgCallback;
|
|
|
|
AddMessage( WM_UPDATE_MODULE_INIT );
|
|
return TRUE;
|
|
}
|
|
|
|
//기본 디렉토리 경로를 포함하는 FTP서버상의 버전파일 경로를 구한다.
|
|
void CUpdateModule::GetRemoteVersionFilePath( TCHAR* pszVerFilePath, int nSize )
|
|
{
|
|
TCHAR szAppName[MAX_PATH];
|
|
ZeroMemory( szAppName, MAX_PATH );
|
|
GetProcessName( szAppName, MAX_PATH );
|
|
|
|
if( szAppName == NULL || (strcmp( szAppName, "" ) == 0 ) )
|
|
strncpy( pszVerFilePath, DEFAULT_VERSION_FILE, nSize ); //만일 디폴트 디렉토리가 없으면 루트에서 찾는다.
|
|
else
|
|
_snprintf( pszVerFilePath, nSize, "%s\\%s", szAppName, DEFAULT_VERSION_FILE );
|
|
}
|
|
|
|
|
|
//한개의 프로세서내에는 여러개의 패치 버전이 존재한다.
|
|
//서버에서 다운받은 현재 프로세서의(FTP에 존재하는 NAME폴더내의 ) wz_version.dat 파일에서
|
|
//현재의 로컬 버전과 비교하여, 몇개의 버전을 패치하여야 하는지 패치(폴더)의 개수를
|
|
//구하는 함수이다.
|
|
BOOL CUpdateModule::GetUpdateFolderCount( CVersionInfo CurVersion, OUT BYTE& byUpdateFolderCount )
|
|
{
|
|
UDTToken Token;
|
|
CScriptParser parser;
|
|
CVersionInfo NewVersion;
|
|
byUpdateFolderCount = 0; //업데이트 폴더 개수 초기화..
|
|
|
|
TCHAR szPath[MAX_PATH];
|
|
GetModuleDirectory( szPath, MAX_PATH );
|
|
SetCurrentDirectory( szPath );
|
|
|
|
if( !parser.SetFile( DEFAULT_VERSION_FILE ) )
|
|
return FALSE;
|
|
|
|
while(TRUE)
|
|
{
|
|
Token = parser.GetToken();
|
|
if( Token == END )
|
|
break;
|
|
|
|
if( Token == NAME )
|
|
{
|
|
NewVersion.Init();
|
|
NewVersion.SetVersionFromString( parser.GetTokenString() );
|
|
|
|
//새로운 버전이 현재 로컬의 버전보다 크다면..
|
|
//업데이트할 폴더의 정보와 개수를 증가시킨다.
|
|
if( NewVersion.GetTotalVersion() > CurVersion.GetTotalVersion() )
|
|
{
|
|
strncpy( m_UpdateFolderInfo[byUpdateFolderCount].m_szFolderName, parser.GetTokenString(), MAX_FOLDER_NAME );
|
|
m_UpdateFolderInfo[byUpdateFolderCount].m_Version = NewVersion;
|
|
byUpdateFolderCount++;
|
|
}
|
|
|
|
if( byUpdateFolderCount >= MAX_UPDATE_FOLDER_COUNT )
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//한개의 프로세스단위를 업데이트 한다.
|
|
BOOL CUpdateModule::UpdateOneProcess()
|
|
{
|
|
TCHAR szCurLocalDirectory[MAX_PATH]; // 현재 로컬 호스트의 디렉토리 경로
|
|
|
|
// 현재 실행파일의 디렉토리를 구한다.
|
|
GetModuleDirectory( szCurLocalDirectory, MAX_PATH );
|
|
|
|
//1. 현재의 프로세서에 업데이트할 폴더의 개수만큼 루프를 돈다.
|
|
//for (int i = 0; i < m_byUpdateFolderCount; i++ )
|
|
//{
|
|
int i = m_byUpdateFolderCount-1;
|
|
//원격지의 파일리스트 파일의 경로를 얻어온다.
|
|
TCHAR szFileListFilePath[MAX_PATH];
|
|
GetRemoteFileListPath( szFileListFilePath, MAX_PATH, m_UpdateFolderInfo[i].m_szFolderName );
|
|
|
|
TCHAR szLocalListPath[MAX_PATH];
|
|
GetModuleDirectory( szLocalListPath, MAX_PATH );
|
|
|
|
//리스트 파일 다운로드(실행파일 위치에 다운 받는다.)
|
|
if ( !DownloadFile(szFileListFilePath, szLocalListPath) )
|
|
return FALSE;
|
|
|
|
//다운받을 버전의 폴더경로를 가져온다.
|
|
TCHAR szVerFolerPath[MAX_PATH];
|
|
GetRemoteVersionFolderPath( szVerFolerPath, MAX_PATH, m_UpdateFolderInfo[i].m_szFolderName );
|
|
|
|
//해당 버전 폴더에 있는 파일 리스트의 파일들을 다운받는다.
|
|
if( !DownloadFilesOnFileList( szVerFolerPath ) )
|
|
{
|
|
DeleteFile( DEFAULT_FILELIST_FILE ); //로컬에 다운받아 놨던 파일리스트를 삭제한다.
|
|
DeleteFile( DEFAULT_VERSION_FILE ); //로컬에 다운받아 놨던 버전파일을 삭제한다.
|
|
return FALSE; //하나만 잘 못되도, 프로그램을 종료한다.
|
|
}
|
|
|
|
// 여기까지 왔으면 윗 버전으로의 업데이트가 성공한 것이므로 업된 버전 저장
|
|
m_CurVersion = m_UpdateFolderInfo[i].m_Version;
|
|
m_CurVersion.GetStringVersion( m_UpdateInfo.m_szProcessVer, MAX_PATH );
|
|
|
|
// 업데이트 중 프로그램 버전을 알린다.
|
|
AddMessage( WM_UPDATE_VERSION_ALARM, &m_UpdateInfo );
|
|
DeleteFile( DEFAULT_FILELIST_FILE ); //로컬에 다운받아 놨던 파일리스트를 삭제한다.
|
|
DeleteFile( DEFAULT_VERSION_FILE ); //로컬에 다운받아 놨던 버전파일을 삭제한다.
|
|
//}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//파일리스트 파일은 반드시 다운로드 받는 버전폴더에 존재해야 한다.
|
|
//예 : AgentServer\00.00.01\filelist.dat
|
|
void CUpdateModule::GetLocalFileListPath( char* pszFilePath, int nSize, const char* pszVerFolder )
|
|
{
|
|
TCHAR szCurServer[MAX_PATH];
|
|
GetProcessName( szCurServer, MAX_PATH );
|
|
|
|
if( szCurServer == NULL || strcmp( szCurServer, "" ) == 0 )
|
|
_snprintf( pszFilePath, nSize, "%s\\%s", pszVerFolder, DEFAULT_FILELIST_FILE );
|
|
else
|
|
_snprintf( pszFilePath, nSize, "%s\\%s\\%s", szCurServer, pszVerFolder, DEFAULT_FILELIST_FILE );
|
|
}
|
|
|
|
|
|
//로컬의 버전폴더의 경로를 반환한다.
|
|
void CUpdateModule::GetLocalVersionFolderPath( char* OUT pszFolderPath, int IN nSize, const char* IN pszVerFolder )
|
|
{
|
|
if( GetLocalBasicDownDir() == NULL || (strcmp( GetLocalBasicDownDir(), "" ) == 0 ) )
|
|
strncpy( pszFolderPath, pszVerFolder, nSize );
|
|
else
|
|
_snprintf( pszFolderPath, nSize, "%s\\%s", GetLocalBasicDownDir(), pszVerFolder );
|
|
}
|
|
|
|
|
|
void CUpdateModule::SetProcessName( TCHAR* pszName )
|
|
{
|
|
if( !pszName ) return;
|
|
|
|
strncpy( m_UpdateInfo.m_szProcessName, pszName, MAX_PATH );
|
|
}
|
|
|
|
void CUpdateModule::GetProcessName( TCHAR* pszName, int nSize )
|
|
{
|
|
ZeroMemory( pszName, nSize );
|
|
strncpy( pszName, m_UpdateInfo.m_szProcessName, nSize );
|
|
}
|
|
|
|
void CUpdateModule::AddMessage( UINT uMsg, VOID* pData )
|
|
{
|
|
if( !m_fnMsgCallback ) return;
|
|
|
|
m_fnMsgCallback( uMsg, pData );
|
|
}
|
|
|
|
void CUpdateModule::SetLocalBasicDownDir( TCHAR* pszDir )
|
|
{
|
|
if( pszDir == NULL || strcmp( pszDir, "" ) == 0 )
|
|
return;
|
|
|
|
ZeroMemory( m_szBasicDownDir, MAX_PATH );
|
|
strncpy( m_szBasicDownDir, pszDir, MAX_PATH );
|
|
}
|
|
|
|
|
|
void CUpdateModule::GetLocalBasicDownDir( TCHAR* pszDir, int nSize )
|
|
{
|
|
strncpy( pszDir, m_szBasicDownDir, nSize );
|
|
}
|
|
|
|
void CUpdateModule::MakeDirectory( const char* pszDir )
|
|
{
|
|
if( pszDir == NULL || strcmp( pszDir, "" ) == 0 )
|
|
return;
|
|
|
|
int nLen = (int)strlen( pszDir ) + 1;
|
|
char* szBuf = new char[nLen];
|
|
strncpy( szBuf, pszDir, nLen );
|
|
|
|
for( int i = 0; i < nLen; i++ )
|
|
{
|
|
if( szBuf[i] && szBuf[i] != '\\' )
|
|
continue;
|
|
|
|
szBuf[i] = '\0';
|
|
|
|
if( PathIsDirectory(szBuf) == FALSE )
|
|
CreateDirectory( szBuf, NULL );
|
|
|
|
szBuf[i] = '\\';
|
|
}
|
|
|
|
delete[] szBuf;
|
|
}
|
|
|
|
//현재 다운받을 어플리케이션의 기본 디렉토리를 생성한다.
|
|
void CUpdateModule::CreateLocalProcessDownDir( )
|
|
{
|
|
string strDir;
|
|
|
|
if( GetLocalBasicDownDir() == NULL || strcmp( GetLocalBasicDownDir(), "") == 0 )
|
|
strDir = "";
|
|
else
|
|
{
|
|
strDir += GetLocalBasicDownDir();
|
|
strDir += '\\';
|
|
}
|
|
|
|
TCHAR szAppName[MAX_PATH];
|
|
GetProcessName( szAppName, MAX_PATH );
|
|
strDir += szAppName;
|
|
MakeDirectory( strDir.c_str() );
|
|
}
|
|
|
|
void CUpdateModule::SendTerminateProcessMsg()
|
|
{
|
|
AddMessage( WM_TERMINATE_PROCESS );
|
|
}
|
|
|
|
void CUpdateModule::SetCurVerInfo( TCHAR* pszVersion )
|
|
{
|
|
strncpy( m_UpdateInfo.m_szProcessVer, pszVersion, MAX_PATH );
|
|
m_CurVersion.SetVersionFromString( pszVersion );
|
|
}
|
|
|
|
VOID CUpdateModule::KillProcess(DWORD th32ProcessID)
|
|
{
|
|
UINT uExitCode = 0;
|
|
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, th32ProcessID);
|
|
|
|
if(TerminateProcess(hProcess, uExitCode))
|
|
AddMessage( WM_COMMAND_MESSAGE, "프로세스 삭제 성공" );
|
|
else
|
|
AddMessage( WM_COMMAND_MESSAGE, "프로세스 삭제 실패" ) ;
|
|
|
|
CloseHandle(hProcess);
|
|
}
|
|
|
|
VOID CUpdateModule::StopUpdate()
|
|
{
|
|
m_bUpdateStart = FALSE;
|
|
}
|
|
|
|
VOID CUpdateModule::SetMsgCallBack( fnMsgCallBack CallBack )
|
|
{
|
|
if( !CallBack ) return;
|
|
|
|
m_fnMsgCallback = CallBack;
|
|
m_FtpNetwork.SetMsgCallBack( m_fnMsgCallback );
|
|
} |