923 lines
22 KiB
C++
923 lines
22 KiB
C++
//---------------------------------------------------------------------------
|
|
#include <vcl.h>
|
|
#include <System.Hash.hpp>
|
|
#include <System.IOUtils.hpp>
|
|
#include <wininet.h>
|
|
#include <Tlhelp32.h>
|
|
#include <vector>
|
|
|
|
#include "UpgradeThread.h"
|
|
|
|
#pragma hdrstop
|
|
|
|
#pragma package(smart_init)
|
|
#pragma comment(lib, "wininet")
|
|
//---------------------------------------------------------------------------
|
|
|
|
#define UPDATE_APP_NAME "AppUpgrade.exe"
|
|
#define MD5_FILE_NAME "filemd5.lst"
|
|
//#define GLOBAL_VAR_FILE "glbvrf.cnf"
|
|
//#define DEFAULT_SERVER "23.236.66.46:88" //"127.0.0.1" //
|
|
#define GLOBAL_VAR_VERSION 0x03
|
|
|
|
extern String MAIN_APP_NAME;
|
|
|
|
typedef struct tGVFHeader{
|
|
char head[4];
|
|
WORD idSoftware;
|
|
WORD iUpdate;
|
|
|
|
tGVFHeader(){
|
|
head[0] = 'G';
|
|
head[1] = 'V';
|
|
head[2] = 'F';
|
|
head[3] = GLOBAL_VAR_VERSION;
|
|
iUpdate = 0;
|
|
}
|
|
} TGVFHEADER;
|
|
|
|
typedef struct tGetUrlParam
|
|
{
|
|
char server[128];
|
|
int idSoft;
|
|
int errCode;
|
|
HINTERNET hSession,
|
|
hRequest;
|
|
|
|
int sizeOut;
|
|
char *dataOut;
|
|
|
|
tGetUrlParam(){
|
|
memset( this, 0, sizeof(tGetUrlParam) );
|
|
};
|
|
} TGetUrlParam;
|
|
|
|
typedef struct tDownloadParam
|
|
{
|
|
char url[256];
|
|
char filename[256];
|
|
|
|
HWND hWnd;
|
|
int errCode;
|
|
HINTERNET hSession,
|
|
hRequest;
|
|
|
|
tDownloadParam(){
|
|
memset( this, 0, sizeof(tDownloadParam) );
|
|
};
|
|
} TDownloadParam;
|
|
|
|
using namespace std;
|
|
|
|
//---------------------------------------------------------------------------
|
|
DWORD WINAPI GetUrlProc(LPVOID args)
|
|
{
|
|
TGetUrlParam* param = (TGetUrlParam*)args;
|
|
|
|
param->hSession = InternetOpen( L"RookIE/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
|
|
if( param->hSession ){
|
|
String api = L"http://" + (String)param->server + L"/Api/getUpgradeUrl?sid=" + IntToStr(param->idSoft);
|
|
|
|
param->hRequest = InternetOpenUrl( param->hSession, api.c_str(), NULL, 0,
|
|
INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_RELOAD|INTERNET_FLAG_PRAGMA_NOCACHE, 0 );
|
|
if( param->hRequest ){
|
|
int pos = 0;
|
|
DWORD dwByteRead = 0;
|
|
char szBuffer[1024];
|
|
|
|
ZeroMemory(szBuffer, sizeof(szBuffer));
|
|
ZeroMemory(param->dataOut, param->sizeOut);
|
|
|
|
// 循环读取缓冲区内容直到结束
|
|
while( InternetReadFile(param->hRequest, szBuffer, sizeof(szBuffer), &dwByteRead) && dwByteRead > 0){
|
|
if( pos + dwByteRead > param->sizeOut ){
|
|
param->errCode = ERROR_SIZE;
|
|
break;
|
|
}
|
|
|
|
// 复制输出数据
|
|
memcpy( param->dataOut+pos, szBuffer, dwByteRead );
|
|
pos += dwByteRead;
|
|
|
|
// 清空缓冲区以备下一次读取
|
|
ZeroMemory(szBuffer, sizeof(szBuffer));
|
|
}
|
|
|
|
param->dataOut[pos] = 0;
|
|
param->sizeOut = pos;
|
|
}
|
|
else
|
|
param->errCode = ERROR_INTERNET_REQ;
|
|
}
|
|
else
|
|
param->errCode = ERROR_INTERNET_OPEN;
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD WINAPI DownloadProc(LPVOID args)
|
|
{
|
|
TDownloadParam* param = (TDownloadParam*)args;
|
|
|
|
param->hSession = InternetOpen( L"RookIE/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
|
|
if( param->hSession ){
|
|
param->hRequest = InternetOpenUrl( param->hSession, ((String)param->url).c_str(), NULL, 0,
|
|
INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_RELOAD|INTERNET_FLAG_PRAGMA_NOCACHE, 0 );
|
|
if( param->hRequest ){
|
|
int pos = 0;
|
|
DWORD dwAllBytes = 0,
|
|
dwSize = 4;
|
|
|
|
if( param->hWnd ){
|
|
HttpQueryInfo( param->hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER,
|
|
&dwAllBytes, &dwSize, NULL );
|
|
}
|
|
|
|
FILE* fp = fopen( param->filename, "wb" );
|
|
if( fp ){
|
|
char szBuffer[2048] = "\0";
|
|
DWORD dwByteRead = 0, dwReceived = 0;
|
|
|
|
ZeroMemory(szBuffer, sizeof(szBuffer));
|
|
|
|
// 循环读取缓冲区内容直到结束
|
|
while (InternetReadFile(param->hRequest, szBuffer, sizeof(szBuffer), &dwByteRead) && dwByteRead > 0){
|
|
fwrite( szBuffer, 1, dwByteRead, fp );
|
|
|
|
if( param->hWnd ){
|
|
//显示进度
|
|
dwReceived += dwByteRead;
|
|
int pos = (int)( dwReceived * 100.0 / dwAllBytes + 0.5 );
|
|
SendMessage( param->hWnd, UM_PROGRESS, 1, pos );
|
|
}
|
|
|
|
// 清空缓冲区以备下一次读取
|
|
ZeroMemory(szBuffer, sizeof(szBuffer));
|
|
}
|
|
|
|
fclose( fp );
|
|
|
|
if( dwReceived==dwAllBytes ){
|
|
SendMessage( param->hWnd, UM_PROGRESS, 1, 100 );
|
|
param->errCode = 0;
|
|
}
|
|
else
|
|
param->errCode = ERROR_FILE_SIZE;
|
|
}
|
|
else
|
|
param->errCode = ERROR_OPEN_FILE;
|
|
}
|
|
else
|
|
param->errCode = ERROR_INTERNET_REQ;
|
|
}
|
|
else
|
|
param->errCode = ERROR_INTERNET_OPEN;
|
|
|
|
return 0;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
__fastcall TUpgradeThread::TUpgradeThread(bool CreateSuspended, int mode, int sid, String sVar, HWND hWnd)
|
|
: TThread(CreateSuspended)
|
|
{
|
|
m_iMode = mode;
|
|
m_idSoft = sid;
|
|
m_hWnd = hWnd;
|
|
m_lstFile = NULL;
|
|
m_bUpdateSelf = false;
|
|
|
|
m_AppPath = TPath::GetFullPath(ExtractFilePath(Application->ExeName));
|
|
m_PathName = m_AppPath + MAIN_APP_NAME;
|
|
// m_Server = DEFAULT_SERVER;
|
|
m_hSema = CreateSemaphore( NULL, 0, 1, NULL );
|
|
|
|
m_GlobalFile = m_AppPath + sVar;// GLOBAL_VAR_FILE;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
void __fastcall TUpgradeThread::Cancel()
|
|
{
|
|
Terminate();
|
|
ReleaseSemaphore( m_hSema, 1, NULL );
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
void __fastcall TUpgradeThread::Execute()
|
|
{
|
|
int ret = 0;
|
|
//获取列表文件
|
|
//对比文件MD5码=>更新列表
|
|
//下载更新列表中的文件
|
|
if( m_iMode==3 ){
|
|
Sleep(1000); //等待app完全退出
|
|
if( UpdateFiles() ){
|
|
RegUpdateFlag( 0 );
|
|
RestartApp();
|
|
}
|
|
}
|
|
else if( m_iMode==1 ){
|
|
MakeMD5File();
|
|
}
|
|
else{
|
|
String strText, strProg1, strProg2;
|
|
//清空目录
|
|
ClearUpdateDir();
|
|
|
|
Randomize();
|
|
|
|
if( m_hWnd ){
|
|
strText = "正在获取更新列表";
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 0, (LPARAM)strText.c_str() );
|
|
|
|
strProg1 = L"——";
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 1, (LPARAM)strProg1.c_str() );
|
|
|
|
strProg2 = L"正在下载列表文件";
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 2, (LPARAM)strProg2.c_str() );
|
|
}
|
|
|
|
String umdfile = GetUpdateMD5File();
|
|
if( umdfile.Length()>0 && !Terminated ){
|
|
if( m_hWnd ){
|
|
strText = "正在检查更新列表";
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 0, (LPARAM)strText.c_str() );
|
|
}
|
|
|
|
TStringList* ufnLst = new TStringList;
|
|
int ret = GetUpdateFileList( umdfile, ufnLst );
|
|
if( ret==0 && !Terminated ){
|
|
int count = ufnLst->Count;
|
|
if( count > 0 ){
|
|
if( m_hWnd ){
|
|
strText = "正在下载更新文件";
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 0, (LPARAM)strText.c_str() );
|
|
}
|
|
|
|
for( int i=0; i<count && !Terminated; i++ ){
|
|
if( m_hWnd ){
|
|
strProg1 = L"文件数 " + IntToStr( i ) + L"/" + IntToStr( count );
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 1, (LPARAM)strProg1.c_str() );
|
|
|
|
int pos = (int)( i*100.0/count + 0.5 );
|
|
SendMessage( m_hWnd, UM_PROGRESS, 0, pos );
|
|
|
|
strProg2 = L"当前下载文件 " + (*ufnLst)[i];
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 2, (LPARAM)strProg2.c_str() );
|
|
}
|
|
|
|
// String ufn = (*ufnLst)[i];
|
|
|
|
if( !(*ufnLst)[i].CompareIC( UPDATE_APP_NAME ) )
|
|
m_bUpdateSelf = true;
|
|
|
|
int ran = Random( 1000000 );
|
|
String url = m_UpdateUrl + (*ufnLst)[i];
|
|
url += "?" + IntToStr( ran );
|
|
ret = DownloadFile( url, (*ufnLst)[i] );
|
|
|
|
if( ret!=0 )
|
|
break;
|
|
}
|
|
|
|
if( ret==0 ){
|
|
if( m_hWnd ){
|
|
SendMessage( m_hWnd, UM_PROGRESS, 0, 100 );
|
|
}
|
|
|
|
if( m_iMode==2 || m_bUpdateSelf ){
|
|
RegUpdateFlag( 1 );
|
|
}
|
|
|
|
if( m_iMode==0 ){
|
|
if( UpdateFiles() )
|
|
RestartApp();
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
if( m_hWnd ){
|
|
strText = "未发现需要更新的文件";
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 0, (LPARAM)strText.c_str() );
|
|
}
|
|
}
|
|
}
|
|
|
|
delete ufnLst;
|
|
}
|
|
else
|
|
ret = ERROR_FILELIST_GET;
|
|
}
|
|
|
|
if( !Terminated && m_hWnd )
|
|
PostMessage( m_hWnd, UM_COMPLETE, ret, 0 );
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool __fastcall TUpgradeThread::MakeMD5File()
|
|
{
|
|
String strText, strProg1, strProg2;
|
|
|
|
if( m_hWnd ){
|
|
strText = "正在生成MD5校验文件";
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 0, (LPARAM)strText.c_str() );
|
|
}
|
|
|
|
m_lstFile = new TStringList();
|
|
m_lstMD5 = new TStringList();
|
|
|
|
if( GetFileList( m_lstFile ) ){
|
|
String fname = m_AppPath + MD5_FILE_NAME;
|
|
FILE* fp = fopen( ((AnsiString)fname).c_str(), "wb" );
|
|
if( fp ){
|
|
for( int i=0; i<m_lstFile->Count && !Terminated; i++ ){
|
|
if( m_hWnd ){
|
|
strProg1 = L"文件数 " + IntToStr( i )
|
|
+ L"/" + IntToStr( m_lstFile->Count );
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 1, (LPARAM)strProg1.c_str() );
|
|
|
|
int pos = (int)( i*100.0/m_lstFile->Count + 0.5 );
|
|
SendMessage( m_hWnd, UM_PROGRESS, 0, pos );
|
|
|
|
strProg2 = L"当前文件 " + (*m_lstFile)[i];
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 2, (LPARAM)strProg2.c_str() );
|
|
}
|
|
|
|
String md5;
|
|
if( !GenerateFileMD5( (*m_lstFile)[i], md5 ) )
|
|
break;
|
|
|
|
if( m_hWnd )
|
|
SendMessage( m_hWnd, UM_PROGRESS, 1, 100 );
|
|
|
|
char text[256];
|
|
sprintf( text, "%s\t%s\n",
|
|
((AnsiString)(*m_lstFile)[i]).c_str(),
|
|
((AnsiString)md5).c_str() );
|
|
|
|
fwrite( text, 1, strlen(text), fp );
|
|
}
|
|
|
|
if( !Terminated && m_hWnd )
|
|
SendMessage( m_hWnd, UM_PROGRESS, 0, 100 );
|
|
|
|
fclose( fp );
|
|
}
|
|
}
|
|
|
|
delete m_lstFile;
|
|
delete m_lstMD5;
|
|
m_lstFile = NULL;
|
|
|
|
return !Terminated;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool __fastcall TUpgradeThread::GenerateFileMD5( String fname, String& md5 )
|
|
{
|
|
String strName = m_AppPath + fname;
|
|
THashMD5* pMD5 = new THashMD5();
|
|
TFileStream* fs = new TFileStream( strName, fmOpenRead | fmShareDenyNone );
|
|
fs->Position = 0;
|
|
|
|
int sizeBuf = 1024 * 1024;
|
|
char* buf = (char*)malloc( sizeBuf );
|
|
while( !Terminated && fs->Position < fs->Size ){
|
|
if( fs->Position + sizeBuf > fs->Size )
|
|
sizeBuf = fs->Size - fs->Position;
|
|
fs->ReadBuffer( buf, sizeBuf );
|
|
|
|
pMD5->Update( buf, sizeBuf );
|
|
|
|
if( m_hWnd ){
|
|
//显示进度
|
|
int pos = (int)( fs->Position * 100.0 / fs->Size + 0.5 );
|
|
SendMessage( m_hWnd, UM_PROGRESS, 1, pos );
|
|
}
|
|
}
|
|
|
|
if( !Terminated ){
|
|
md5 = pMD5->HashAsString();
|
|
}
|
|
|
|
free( buf );
|
|
|
|
delete fs;
|
|
delete pMD5;
|
|
|
|
return !Terminated;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
int __fastcall TUpgradeThread::DownloadFile( String url, String filename )
|
|
{
|
|
int ret = -1;
|
|
String path = m_AppPath + L"upgrade\\";
|
|
|
|
if(!DirectoryExists(path, false))
|
|
ForceDirectories(path);
|
|
|
|
DeleteUrlCacheEntry(url.c_str());
|
|
|
|
path += filename;
|
|
|
|
for( int i=0; i<3; i++ ){ //尝试3次
|
|
TDownloadParam param;
|
|
param.hWnd = m_hWnd;
|
|
strcpy( param.url, ((AnsiString)url).c_str() );
|
|
strcpy( param.filename, ((AnsiString)path).c_str() );
|
|
|
|
DWORD id;
|
|
HANDLE hThread = CreateThread( NULL, 0, DownloadProc, ¶m, 0, &id );
|
|
if( hThread ){
|
|
HANDLE aHandle[2] = { m_hSema, hThread };
|
|
|
|
DWORD dwRet = WaitForMultipleObjects( 2, aHandle, FALSE, INFINITE );
|
|
if( param.hRequest )
|
|
InternetCloseHandle( param.hRequest );
|
|
if( param.hSession )
|
|
InternetCloseHandle( param.hSession );
|
|
|
|
WaitForSingleObject( hThread, 200 );
|
|
CloseHandle( hThread );
|
|
|
|
if( dwRet==WAIT_OBJECT_0 ) //用户退出
|
|
break;
|
|
else if( dwRet==WAIT_OBJECT_0+1 ){ //线程正常退出
|
|
if( param.errCode==0 ){
|
|
ret = 0;
|
|
break;
|
|
}
|
|
else if( param.errCode==ERROR_OPEN_FILE )
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool __fastcall TUpgradeThread::GetFileList( TStringList* pList )
|
|
{
|
|
TSearchRec sr;
|
|
int iAttr = 0;
|
|
String strPath = m_AppPath;
|
|
|
|
if( FindFirst(strPath + L"*.*", iAttr, sr)==0 ){
|
|
do{
|
|
if( !(iAttr & faDirectory) /*iAttr & faNormal*/
|
|
//&& !sr.Name.Pos(".log")
|
|
//&& !sr.Name.Pos(".txt")
|
|
//&& !sr.Name.Pos(".ico")
|
|
//&& !sr.Name.Pos(".cnf")
|
|
//&& !sr.Name.Pos("agcdstdt")
|
|
&& !sr.Name.Pos(".lst")){
|
|
pList->Add( sr.Name );
|
|
}
|
|
}
|
|
while( !Terminated && FindNext(sr)==0 );
|
|
|
|
FindClose(sr);
|
|
}
|
|
|
|
return !Terminated;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
String __fastcall TUpgradeThread::GetUpdateMD5File()
|
|
{
|
|
String locFile;
|
|
|
|
m_UpdateUrl = GetUpdateURL();
|
|
if( m_UpdateUrl.Length()>0 ){
|
|
int ran = Random( 1000000 );
|
|
String url = m_UpdateUrl + MD5_FILE_NAME;
|
|
url += "?" + IntToStr( ran );
|
|
int ret = DownloadFile( url, MD5_FILE_NAME );
|
|
if( ret==0 ){
|
|
locFile = m_AppPath + L"upgrade/" + MD5_FILE_NAME;
|
|
}
|
|
}
|
|
|
|
return locFile;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
int __fastcall TUpgradeThread::GetServers( TStringList* pList )
|
|
{
|
|
char szBuffer[2048] = "";
|
|
// bool bSave = false;
|
|
FILE* fp = NULL;
|
|
|
|
//读取文件配置
|
|
fp = fopen( ((AnsiString)m_GlobalFile).c_str(), "rb" );
|
|
if( fp ){
|
|
TGVFHEADER header;
|
|
header.idSoftware = m_idSoft;
|
|
int ret = fread( (void*)szBuffer, 1, sizeof(header), fp );
|
|
|
|
if( ret==sizeof(header) && !memcmp(szBuffer, header.head, sizeof(header.head)) ){
|
|
fseek( fp, 0, SEEK_END );
|
|
int size = ftell( fp ) - sizeof(header);
|
|
if( size>2048 )
|
|
size = 2048;
|
|
|
|
fseek( fp, sizeof(header), SEEK_SET );
|
|
fread( szBuffer, 1, size, fp );
|
|
|
|
char srvs[1024] = "";
|
|
char *tokenPtr=strtok(szBuffer,"\n");
|
|
while( tokenPtr ){
|
|
if( strstr(tokenPtr, "srv=") ){
|
|
strcpy( srvs, tokenPtr+4 );
|
|
break;
|
|
}
|
|
tokenPtr=strtok(NULL,"\n");
|
|
}
|
|
|
|
if( strlen(srvs) ){
|
|
char *tkn = strtok( srvs, ";" );
|
|
while( tkn!=NULL ){
|
|
pList->Add( tkn );
|
|
tkn = strtok(NULL, ";");
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose( fp );
|
|
}
|
|
// else{
|
|
// pList->Add( m_Server );
|
|
// }
|
|
|
|
return 0;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
String __fastcall TUpgradeThread::GetUpdateURL()
|
|
{
|
|
String url;
|
|
TStringList* pServers = new TStringList;
|
|
GetServers( pServers );
|
|
|
|
for( int i=0; i<pServers->Count; i++ ){
|
|
int sizeOut = 2048;
|
|
char dataOut[2048];
|
|
|
|
TGetUrlParam param;
|
|
param.idSoft = m_idSoft;
|
|
param.sizeOut = sizeOut;
|
|
param.dataOut = dataOut;
|
|
strcpy( param.server, ((AnsiString)(*pServers)[i]).c_str() );
|
|
|
|
DWORD id;
|
|
HANDLE hThread = CreateThread( NULL, 0, GetUrlProc, ¶m, 0, &id );
|
|
if( hThread ){
|
|
HANDLE aHandle[2] = { m_hSema, hThread };
|
|
|
|
DWORD dwRet = WaitForMultipleObjects( 2, aHandle, FALSE, 10000 );
|
|
if( param.hRequest )
|
|
InternetCloseHandle( param.hRequest );
|
|
if( param.hSession )
|
|
InternetCloseHandle( param.hSession );
|
|
|
|
WaitForSingleObject( hThread, 200 );
|
|
CloseHandle( hThread );
|
|
|
|
if( dwRet==WAIT_OBJECT_0 ) //用户退出
|
|
break;
|
|
else if( dwRet==WAIT_OBJECT_0+1 && param.errCode==0 ){ //线程正常退出
|
|
if(dataOut[0]=='\"' && dataOut[param.sizeOut-1]=='\"')
|
|
dataOut[param.sizeOut-1] = 0;
|
|
|
|
char* p = strstr( dataOut, "url:" );
|
|
if( p ){
|
|
m_Server = (*pServers)[i];
|
|
|
|
char* str = p+4;
|
|
url = L"http://" + m_Server + L"/" + str;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
delete pServers;
|
|
|
|
return url;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
int __fastcall TUpgradeThread::GetUpdateFileList( String ufile, TStringList* ufnLst )
|
|
{
|
|
int err = 0;
|
|
String lfname = m_AppPath + MD5_FILE_NAME;
|
|
|
|
FILE *ufp = fopen( ((AnsiString)ufile).c_str(), "rb" ),
|
|
*lfp = fopen( ((AnsiString)lfname).c_str(), "rb" );
|
|
|
|
if( !ufp ){
|
|
err = -1;
|
|
goto exit_line;
|
|
}
|
|
else if( !lfp ){
|
|
if( !MakeMD5File() || !(lfp=fopen( ((AnsiString)lfname).c_str(), "rb" )) ){
|
|
err = -2;
|
|
goto exit_line;
|
|
}
|
|
}
|
|
|
|
{
|
|
char lbuf[4096] = "",
|
|
ubuf[4096] = "";
|
|
|
|
fseek( lfp, 0, SEEK_END );
|
|
fseek( ufp, 0, SEEK_END );
|
|
|
|
int lsize = ftell( lfp );
|
|
int usize = ftell( ufp );
|
|
|
|
if(usize==0)
|
|
goto exit_line;
|
|
|
|
fseek( lfp, 0, SEEK_SET );
|
|
fseek( ufp, 0, SEEK_SET );
|
|
fread( lbuf, 1, lsize, lfp );
|
|
fread( ubuf, 1, usize, ufp );
|
|
|
|
fclose( lfp );
|
|
fclose( ufp );
|
|
lfp = ufp = NULL;
|
|
|
|
TStringList *lfnLst = new TStringList,
|
|
*lmdLst = new TStringList,
|
|
*umdLst = new TStringList;
|
|
|
|
char *tokenPtr=strtok(lbuf,"\n");
|
|
while( tokenPtr ){
|
|
char* pos = strstr( tokenPtr, "\t" );
|
|
|
|
if( pos ){
|
|
char buf[256];
|
|
memcpy( buf, tokenPtr, pos-tokenPtr );
|
|
buf[pos-tokenPtr] = 0;
|
|
lfnLst->Add( buf );
|
|
lmdLst->Add( pos+1 );
|
|
}
|
|
|
|
tokenPtr=strtok(NULL,"\n");
|
|
}
|
|
|
|
tokenPtr=strtok(ubuf,"\n");
|
|
while( tokenPtr ){
|
|
char* pos = strstr( tokenPtr, "\t" );
|
|
|
|
if( pos ){
|
|
char buf[256];
|
|
memcpy( buf, tokenPtr, pos-tokenPtr );
|
|
buf[pos-tokenPtr] = 0;
|
|
ufnLst->Add( buf );
|
|
umdLst->Add( pos+1 );
|
|
}
|
|
|
|
tokenPtr=strtok(NULL,"\n");
|
|
}
|
|
|
|
String strProg1, strProg2;
|
|
int count = ufnLst->Count;
|
|
for( int i=ufnLst->Count-1; i>=0; i-- ){
|
|
if( m_hWnd ){
|
|
strProg1 = L"文件数 " + IntToStr( count-i-1 ) + L"/" + IntToStr(count);
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 1, (LPARAM)strProg1.c_str() );
|
|
|
|
int pos = (int)( (count-i-1)*100.0/count + 0.5 );
|
|
SendMessage( m_hWnd, UM_PROGRESS, 0, pos );
|
|
|
|
strProg2 = L"当前比对文件 " + (*ufnLst)[i];
|
|
SendMessage( m_hWnd, UM_SHOWTEXT, 2, (LPARAM)strProg2.c_str() );
|
|
}
|
|
|
|
int count2 = lfnLst->Count;
|
|
for( int j=lfnLst->Count-1; j>=0; j-- ){
|
|
if( m_hWnd ){
|
|
int pos = (int)( (count2-j)*100.0/count2 + 0.5 );
|
|
SendMessage( m_hWnd, UM_PROGRESS, 1, pos );
|
|
}
|
|
|
|
// String ufn = (*ufnLst)[i],
|
|
// lfn = (*lfnLst)[j];
|
|
|
|
if( !(*ufnLst)[i].CompareIC( (*lfnLst)[j] ) ){
|
|
// String umd = (*umdLst)[i],
|
|
// lmd = (*lmdLst)[j];
|
|
|
|
if( !(*umdLst)[i].CompareIC( (*lmdLst)[j] ) ){
|
|
ufnLst->Delete( i );
|
|
umdLst->Delete( i );
|
|
}
|
|
|
|
lfnLst->Delete( j );
|
|
lmdLst->Delete( j );
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
delete lfnLst;
|
|
delete lmdLst;
|
|
delete umdLst;
|
|
}
|
|
|
|
exit_line:
|
|
if( ufp )
|
|
fclose( ufp );
|
|
if( lfp )
|
|
fclose( lfp );
|
|
|
|
return err;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
int __fastcall TUpgradeThread::RegUpdateFlag( int iUpdate )
|
|
{
|
|
FILE* fp = fopen( ((AnsiString)m_GlobalFile).c_str(), "r+b" );
|
|
if( fp ){
|
|
TGVFHEADER header;
|
|
header.idSoftware = m_idSoft;
|
|
header.iUpdate = iUpdate;
|
|
|
|
fseek( fp, 0, SEEK_SET );
|
|
fwrite( (void*)&header, sizeof(header), 1, fp );
|
|
|
|
fclose( fp );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
int __fastcall TUpgradeThread::ClearUpdateDir()
|
|
{
|
|
TSearchRec sr;
|
|
int iAttr = 0;
|
|
String strPath = m_AppPath + L"upgrade\\";
|
|
|
|
if( FindFirst(strPath + L"*.*", iAttr, sr)==0 ){
|
|
do{
|
|
if( !(iAttr & faDirectory) ){
|
|
DeleteFile( strPath + sr.Name );
|
|
}
|
|
}
|
|
while( FindNext(sr)==0 );
|
|
|
|
FindClose(sr);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool __fastcall TUpgradeThread::UpdateFiles()
|
|
{
|
|
bool bSuccess = true;
|
|
TSearchRec sr;
|
|
int iAttr = 0;
|
|
String strPath = m_AppPath + L"upgrade\\";
|
|
|
|
//先关闭主程序
|
|
StopApp();
|
|
|
|
Sleep(1000); //等待app完全退出
|
|
|
|
if( FindFirst(strPath + L"*.*", iAttr, sr)==0 ){
|
|
do{
|
|
if( !(iAttr & faDirectory) && sr.Name.CompareIC(UPDATE_APP_NAME) ){
|
|
String fOld = strPath + sr.Name,
|
|
fNew = m_AppPath + sr.Name;
|
|
|
|
if( !MoveFileEx( fOld.c_str(), fNew.c_str(), MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH ) ){
|
|
bSuccess = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while( FindNext(sr)==0 );
|
|
|
|
FindClose(sr);
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
int __fastcall TUpgradeThread::RestartApp()
|
|
{
|
|
//启动主程序
|
|
HANDLE hToken = NULL,
|
|
hTokenDup = NULL;
|
|
if(OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken)){
|
|
if(DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS,NULL, SecurityIdentification,
|
|
TokenPrimary, &hTokenDup)){
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
ZeroMemory(&si,sizeof(STARTUPINFO));
|
|
ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
|
|
si.cb = sizeof(STARTUPINFO);
|
|
si.lpDesktop = NULL;
|
|
si.lpReserved = NULL;
|
|
si.lpTitle = NULL;
|
|
si.cbReserved2 = NULL;
|
|
si.lpReserved2 = NULL;
|
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
|
si.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
String command = "\"" + m_AppPath + MAIN_APP_NAME + "\"";
|
|
CreateProcessAsUser(hTokenDup,NULL,command.c_str(),NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool __fastcall TUpgradeThread::StopApp()
|
|
{
|
|
HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS,0 ); //获取进程快照
|
|
if( hSnapshot ){
|
|
DWORD idProcess = 0;
|
|
PROCESSENTRY32 pe32;
|
|
pe32.dwSize = sizeof( PROCESSENTRY32 );
|
|
|
|
if(!Process32First( hSnapshot, &pe32 )){ //指向第一个进程
|
|
CloseHandle(hSnapshot);
|
|
return false;
|
|
}
|
|
|
|
do{
|
|
if( lstrcmpi( pe32.szExeFile, MAIN_APP_NAME.c_str() )==0 ){ //查找进程
|
|
if( SameModulePath( pe32.th32ProcessID )){
|
|
idProcess = pe32.th32ProcessID;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while( Process32Next(hSnapshot, &pe32) ); // 循环直到取不到进程
|
|
|
|
if( idProcess ){
|
|
HANDLE hApp= OpenProcess( PROCESS_ALL_ACCESS, FALSE, idProcess ); //根据进程ID获取程序的句柄
|
|
if( hApp ){
|
|
if( WaitForSingleObject( hApp, 2000 )==WAIT_TIMEOUT )// 等待程序关闭2秒
|
|
TerminateProcess( hApp, 0 );
|
|
|
|
CloseHandle( hApp );
|
|
}
|
|
}
|
|
|
|
CloseHandle( hSnapshot );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
#define PSAPI_VERSION 1
|
|
#include <psapi.h>
|
|
#pragma comment(lib,"psapi")
|
|
bool __fastcall TUpgradeThread::SameModulePath(DWORD dwPID)
|
|
{
|
|
TCHAR sFilename[MAX_PATH];
|
|
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID);
|
|
if (hProcess == NULL)
|
|
return false;
|
|
|
|
bool bSame = false;
|
|
HMODULE hModule;
|
|
DWORD cbNeeded;
|
|
if (EnumProcessModules(hProcess, &hModule, sizeof(hModule), &cbNeeded)){
|
|
if (GetModuleFileNameEx(hProcess, hModule, sFilename, MAX_PATH)){
|
|
if(wcslen(sFilename)>0){
|
|
String sFullName = TPath::GetFullPath(sFilename);
|
|
if( !m_PathName.CompareIC( sFilename ) )
|
|
bSame = true;
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
DWORD size = MAX_PATH;
|
|
if (QueryFullProcessImageName(hProcess, 0, sFilename, &size)){
|
|
if( !m_PathName.CompareIC( sFilename ) )
|
|
bSame = true;
|
|
}
|
|
}
|
|
CloseHandle(hProcess);
|
|
|
|
return bSame;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|