📄 resorgversioncheck.cpp
字号:
/************************************************************************
*
* Resource ID Organiser Core Library
*
* (c) Copyright 2000-2003 by Anna-Jayne Metcalfe (resorg@annasplace.me.uk)
* All rights reserved.
*
************************************************************************
*
* Filename : ResOrgVersionCheck.cpp
*
* Compiler : Microsoft Visual C++ 6.0, Service Pack 3 or later
* Microsoft Visual C++ .NET 2002
*
* Target
* Environment : Windows 98/NT/2000/XP
*
* NOTE:
*
* This software is provided "as is" free for personal use. All
* title and copyrights in and to the software, including but not
* limited to any images, text, etc. incorporated into it, are
* owned by Anna-Jayne Metcalfe, except where acknowledged otherwise.
*
* Your may freely to use this code in your own products, PROVIDED
* this notice is not removed or modified.
*
*
* Visit http://www.annasplace.me.uk/resorg for latest updates
*
************************************************************************
*
* MODIFICATION HISTORY:
*
* This is a controlled document. See project configuration
* control tool for latest version and full version history.
*
* $Archive: /Projects/AddIns/ResOrg/ResOrgCore/ResOrgVersionCheck.cpp $
* $Revision: 10 $
* $Date: 21/06/03 11:31 $
* $Author: Anna $
*
* $History: ResOrgVersionCheck.cpp $
*
* ***************** Version 10 *****************
* User: Anna Date: 21/06/03 Time: 11:31
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Replaced CResOrgVersionCheck::IsNewVersion() with
* CResOrgVersionCheck::CompareVersions(). This allows CResOrgOptions to
* also determine if the installed version is *newer* than the current
* release
*
* ***************** Version 9 *****************
* User: Anna Date: 15/04/03 Time: 20:36
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* 1. Removed unnecessary file guards (#pragma once works well enough)
* 2. Updated file banners
*
* ***************** Version 8 *****************
* User: Anna Date: 15/02/03 Time: 20:53
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Changed big BOOLs into little bools
*
* ***************** Version 7 *****************
* User: Anna Date: 25/11/02 Time: 15:20
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Changed website address in banner
*
* ***************** Version 6 *****************
* User: Anna Date: 22/10/02 Time: 13:24
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Changed name/mail address (at last!)
*
* ***************** Version 5 *****************
* User: Andy Date: 7/06/02 Time: 17:04
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Renamed the ResOrgUtils module to ResOrgCore. Updated file banners
* accordingly
*
*
* $Nokeywords: $
*
************************************************************************/
#include "StdAfx.h"
#include <afxinet.h>
#include "ResOrgVersionCheck.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static int CompareVersions(CString sVersion1, CString sVersion2)
{
int nMajorVer1 = _ttoi(::Chomp(sVersion1, _T(".") ));
int nMajorVer2 = _ttoi(::Chomp(sVersion2, _T(".") ));
int nMinorVer1 = _ttoi(::Chomp(sVersion1, _T(".") ));
int nMinorVer2 = _ttoi(::Chomp(sVersion2, _T(".") ));
int nRevision1 = _ttoi(::Chomp(sVersion1, _T(".") ));
int nRevision2 = _ttoi(::Chomp(sVersion2, _T(".") ));
int nBuildNo1 = _ttoi(::Chomp(sVersion1, _T(".") ));
int nBuildNo2 = _ttoi(::Chomp(sVersion2, _T(".") ));
DWORD dwVer1 = (nMajorVer1 << 24) +
(nMinorVer1 << 16) +
(nRevision1 << 8) +
nBuildNo1;
DWORD dwVer2 = (nMajorVer2 << 24) +
(nMinorVer2 << 16) +
(nRevision2 << 8) +
nBuildNo2;
if (dwVer1 == dwVer2)
{
return 0;
}
return ( (dwVer1 > dwVer2) ? 1 : -1);
}
/////////////////////////////////////////////////////////////////////////////
// CResOrgVersionCheck class
// Static map object used to map from thread data to object instances
// This is needed as the thread function is a static
CMapPtrToPtr CResOrgVersionCheck::m_mapMonitors;
/////////////////////////////////////////////////////////////////////////////
// CResOrgVersionCheck construction/destruction
CResOrgVersionCheck::CResOrgVersionCheck(bool bDisableDialupPrompt)
{
m_sURL = _T("");
m_sTempFileName = _T("");
m_dwContext = 0;
m_ePriority = THREAD_PRIORITY_LOWEST;
m_bDisableDialupPrompt = bDisableDialupPrompt;
m_pThread = NULL;
m_hThread = NULL;
// Create temporary file
TCHAR szPath[_MAX_PATH];
::GetTempPath( _MAX_PATH - 1,
szPath);
LPTSTR pszTempFileName = m_sTempFileName.GetBuffer(_MAX_PATH);
::GetTempFileName( szPath,
_T("ver"),
0,
pszTempFileName);
m_sTempFileName.ReleaseBuffer();
}
CResOrgVersionCheck::~CResOrgVersionCheck(void)
{
// Wait until monitor thread exits
while (NULL != m_hThread)
{
// I don't like doing this but I can't see any other option
Sleep(100);
}
// Delete temporary file
::DeleteFile(m_sTempFileName);
}
/////////////////////////////////////////////////////////////////////////////
// CResOrgVersionCheck virtual overrides
bool CResOrgVersionCheck::OnDownloadCompleted(void)
{
if (::IsWindow(m_hwndTarget))
{
switch (m_uMsg)
{
case WM_COMMAND: // WM_COMMAND pass back uID
return ::PostMessage(m_hwndTarget, m_uMsg, m_uMsgID, 0UL);
default:
return ::PostMessage(m_hwndTarget, m_uMsg, 0L, m_dwErrorCode);
}
}
return false;
}
/////////////////////////////////////////////////////////////////////////////
// CResOrgVersionCheck operations
bool CResOrgVersionCheck::SetNotifyTarget( CWnd* pWnd,
UINT uMsg,
UINT uID /*= 0*/)
{
if (!IsDownloading() )
{
if ( (NULL != pWnd) && ::IsWindow( pWnd->GetSafeHwnd() ) )
{
m_hwndTarget = pWnd->GetSafeHwnd();
m_uMsg = uMsg;
m_uMsgID = uID;
return true;
}
}
return false;
}
bool CResOrgVersionCheck::SetPriority(int ePriority)
{
if (!IsDownloading())
{
m_ePriority = ePriority;
return true;
}
return false;
}
/******************************************************************************
* Start reading
*
******************************************************************************/
bool CResOrgVersionCheck::StartDownload( const CString& sURL,
DWORD dwContext /*= 0*/)
{
if (!IsDownloading())
{
m_sURL = sURL;
m_dwContext = dwContext;
return CreateDownloadThread();
}
return false;
}
CString CResOrgVersionCheck::GetValue( const CString& sSection,
const CString& sEntry,
const CString& sDefault /*= _T("")*/ ) const
{
CString sValue;
LPTSTR pszValue = sValue.GetBuffer(_MAX_PATH);
::GetPrivateProfileString( sSection,
sEntry,
sDefault,
pszValue,
_MAX_PATH - 1,
m_sTempFileName);
sValue.ReleaseBuffer();
return sValue;
}
int CResOrgVersionCheck::CompareVersions( const CString& sSection,
const CString& sExistingVer) const
{
CString sDownloadedVer = GetValue( sSection,
_T("Version"),
_T("0.0.0") );
return (::CompareVersions(sDownloadedVer, sExistingVer) );
}
/////////////////////////////////////////////////////////////////////////////
// CResOrgVersionCheck implementation
bool CResOrgVersionCheck::CreateDownloadThread(void)
{
// Create a worker thread to read the file
//
// First store the address of m_dwContext in a map so
// that ThreadFunc (which is a static) can work out
// which object to pass the call to
m_mapMonitors.SetAt( (LPVOID)&m_dwContext, (LPVOID)this );
CWinThread* pThread = ::AfxBeginThread( CResOrgVersionCheck::ThreadFunc,
(LPVOID)&m_dwContext,
m_ePriority);
if (NULL != pThread)
{
pThread->m_bAutoDelete = true;
m_hThread = pThread->m_hThread;
m_pThread = pThread;
}
else
{
m_mapMonitors.RemoveKey( (LPVOID)&m_dwContext );
}
if (NULL == m_hThread)
{
delete m_pThread;
m_pThread = NULL;
}
return (NULL != m_hThread);
}
// Worker thread function
UINT CResOrgVersionCheck::ThreadFunc(LPVOID pParam)
{
// Lookup corresponding thread object
CResOrgVersionCheck* pThread = NULL;
if ( (m_mapMonitors.Lookup(pParam, (LPVOID&)pThread)) || (NULL != pThread) )
{
m_mapMonitors.RemoveKey(pParam);
return pThread->DoThreadFunc(pParam);
}
return 0;
}
UINT CResOrgVersionCheck::DoThreadFunc(LPVOID pParam)
{
DWORD dwContext = *(DWORD*)pParam;
DWORD dwErrorCode = 0;
CString sValue;
// Try to read the requested data
DownloadTextFile( m_sURL,
m_sTempFileName,
dwContext,
&dwErrorCode);
CCriticalSection cs;
cs.Lock();
m_dwErrorCode = dwErrorCode;
cs.Unlock();
OnDownloadCompleted();
cs.Lock();
m_hwndTarget = NULL;
m_uMsg = 0;
m_uMsgID = 0;
m_pThread = NULL;
m_hThread = NULL;
cs.Unlock();
return 0;
}
bool CResOrgVersionCheck::DownloadTextFile( const CString& sURL,
const CString& sDestination,
DWORD dwContext,
DWORD* pdwError /*= NULL*/)
{
bool bResult = false;
HKEY hKey = NULL;
DWORD dwDial = 0;
DWORD dwDialType = REG_DWORD;
DWORD dwDialSize = sizeof(DWORD);
DWORD dwNew = 0;
if (m_bDisableDialupPrompt)
{
// Disable dial-up networking prompt before attempting to connect
// See www.codeguru.com/mfc/comments/20677.shtml for details
::RegOpenKeyEx( HKEY_CURRENT_USER,
_T("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
0,
KEY_QUERY_VALUE | KEY_SET_VALUE,
&hKey);
::RegQueryValueEx(hKey,
_T("EnableAutodial"),
NULL,
&dwDialType,
(BYTE*)&dwDial,
&dwDialSize);
::RegSetValueEx(hKey,
_T("EnableAutodial"),
NULL,
dwDialType,
(BYTE*)&dwNew,
dwDialSize);
}
try
{
CInternetSession Session;
Sleep(10000);
CStdioFile* pFile = Session.OpenURL(sURL, // URL
dwContext, // Caller defined context ID
INTERNET_FLAG_TRANSFER_ASCII,
// Flags
NULL, // Additional headers
0); // Length of additional headers
if (NULL != pFile)
{
CStdioFile f;
CFileException e;
if ( f.Open(sDestination,
CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite,
&e) )
{
CString sLine;
while (pFile->ReadString(sLine) )
{
f.WriteString(sLine + _T("\n") );
}
pFile->Close();
delete pFile;
bResult = true;
}
f.Close();
}
}
catch (CInternetException* e)
{
#ifdef _DEBUG
// e->ReportError();
#endif
if (NULL != pdwError)
{
*pdwError = e->m_dwError;
}
e->Delete();
}
catch (CFileException* e)
{
#ifdef _DEBUG
// e->ReportError();
#endif
e->Delete();
}
// Restore dial-up networking prompt to its original value
if (m_bDisableDialupPrompt)
{
::RegSetValueEx(hKey,
_T("EnableAutodial"),
NULL,
dwDialType,
(BYTE*)&dwDial,
dwDialSize);
::RegCloseKey(hKey);
}
return bResult;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -