Index: src/ch/CfgProperties.cpp
===================================================================
diff -u -r0373359eff650e8cf04a5992711ef9f20347536f -rf34d204b8eecd6817dbe4a1c3b3541cf9a8794b0
--- src/ch/CfgProperties.cpp	(.../CfgProperties.cpp)	(revision 0373359eff650e8cf04a5992711ef9f20347536f)
+++ src/ch/CfgProperties.cpp	(.../CfgProperties.cpp)	(revision f34d204b8eecd6817dbe4a1c3b3541cf9a8794b0)
@@ -33,6 +33,9 @@
 	pManager->register_bool(_t("Program/Enabled clipboard monitoring"), false);
 	pManager->register_signed_num(_t("Program/Monitor scan interval"), 1000, 0, llHour);
 	pManager->register_bool(_t("Program/Reload after restart"), false);
+	pManager->register_bool(_t("Program/Check for updates at startup"), true);
+	pManager->register_bool(_t("Program/Updater checks for beta"), true);
+
 	pManager->register_bool(_t("Program/Shutdown system after finished"), false);
 	pManager->register_signed_num(_t("Program/Time before shutdown"), 10000, 0, 24*llHour);
 	pManager->register_bool(_t("Program/Force shutdown"), false);
Index: src/ch/CfgProperties.h
===================================================================
diff -u -r0373359eff650e8cf04a5992711ef9f20347536f -rf34d204b8eecd6817dbe4a1c3b3541cf9a8794b0
--- src/ch/CfgProperties.h	(.../CfgProperties.h)	(revision 0373359eff650e8cf04a5992711ef9f20347536f)
+++ src/ch/CfgProperties.h	(.../CfgProperties.h)	(revision f34d204b8eecd6817dbe4a1c3b3541cf9a8794b0)
@@ -29,6 +29,8 @@
 	PP_PCLIPBOARDMONITORING = 0,
 	PP_PMONITORSCANINTERVAL,
 	PP_PRELOADAFTERRESTART,
+	PP_PCHECK_FOR_UPDATES_AT_STARTUP,
+	PP_PUPDATE_CHECK_FOR_BETA,
 	PP_PSHUTDOWNAFTREFINISHED,
 	PP_PTIMEBEFORESHUTDOWN,
 	PP_PFORCESHUTDOWN,
Index: src/ch/MainWnd.cpp
===================================================================
diff -u -r0373359eff650e8cf04a5992711ef9f20347536f -rf34d204b8eecd6817dbe4a1c3b3541cf9a8794b0
--- src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision 0373359eff650e8cf04a5992711ef9f20347536f)
+++ src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision f34d204b8eecd6817dbe4a1c3b3541cf9a8794b0)
@@ -177,6 +177,14 @@
 	// start clipboard monitoring
 	CClipboardMonitor::StartMonitor(&m_tasks);
 	
+	if(GetConfig().get_bool(PP_PCHECK_FOR_UPDATES_AT_STARTUP))
+	{
+		CUpdaterDlg* pDlg = new CUpdaterDlg(true);
+		pDlg->m_bAutoDelete = true;
+
+		pDlg->Create();
+	}
+
 	// start saving timer
 	SetTimer(1023, (UINT)GetConfig().get_signed_num(PP_PAUTOSAVEINTERVAL), NULL);
 
@@ -900,7 +908,7 @@
 
 void CMainWnd::OnPopupCheckForUpdates()
 {
-	CUpdaterDlg* pDlg = new CUpdaterDlg;
+	CUpdaterDlg* pDlg = new CUpdaterDlg(false);
 	pDlg->m_bAutoDelete = true;
 	
 	pDlg->Create();
Index: src/ch/OptionsDlg.cpp
===================================================================
diff -u -r0373359eff650e8cf04a5992711ef9f20347536f -rf34d204b8eecd6817dbe4a1c3b3541cf9a8794b0
--- src/ch/OptionsDlg.cpp	(.../OptionsDlg.cpp)	(revision 0373359eff650e8cf04a5992711ef9f20347536f)
+++ src/ch/OptionsDlg.cpp	(.../OptionsDlg.cpp)	(revision f34d204b8eecd6817dbe4a1c3b3541cf9a8794b0)
@@ -228,6 +228,8 @@
 	PROP_BOOL(IDS_CLIPBOARDMONITORING_STRING, GetConfig().get_bool(PP_PCLIPBOARDMONITORING))
 	PROP_UINT(IDS_CLIPBOARDINTERVAL_STRING, GetConfig().get_signed_num(PP_PMONITORSCANINTERVAL))
 	PROP_BOOL(IDS_AUTORUNPROGRAM_STRING, GetConfig().get_bool(PP_PRELOADAFTERRESTART))
+	PROP_BOOL(IDS_CFG_CHECK_FOR_UPDATES_AT_STARTUP, GetConfig().get_bool(PP_PCHECK_FOR_UPDATES_AT_STARTUP))
+	PROP_BOOL(IDS_CFG_UPDATE_CHECK_FOR_BETA, GetConfig().get_bool(PP_PUPDATE_CHECK_FOR_BETA))
 	PROP_BOOL(IDS_AUTOSHUTDOWN_STRING, GetConfig().get_bool(PP_PSHUTDOWNAFTREFINISHED))
 	PROP_UINT(IDS_SHUTDOWNTIME_STRING, GetConfig().get_signed_num(PP_PTIMEBEFORESHUTDOWN))
 	PROP_COMBO(IDS_FORCESHUTDOWN_STRING, IDS_FORCESHUTDOWNVALUES_STRING, GetConfig().get_bool(PP_PFORCESHUTDOWN))
@@ -349,6 +351,8 @@
 	rConfig.set_bool(PP_PCLIPBOARDMONITORING, GetBoolProp(iPosition++));
 	rConfig.set_signed_num(PP_PMONITORSCANINTERVAL, GetUintProp(iPosition++));
 	rConfig.set_bool(PP_PRELOADAFTERRESTART, GetBoolProp(iPosition++));
+	rConfig.set_bool(PP_PCHECK_FOR_UPDATES_AT_STARTUP, GetBoolProp(iPosition++));
+	rConfig.set_bool(PP_PUPDATE_CHECK_FOR_BETA, GetBoolProp(iPosition++));
 	rConfig.set_bool(PP_PSHUTDOWNAFTREFINISHED, GetBoolProp(iPosition++));
 	rConfig.set_signed_num(PP_PTIMEBEFORESHUTDOWN, GetUintProp(iPosition++));
 	rConfig.set_bool(PP_PFORCESHUTDOWN, GetBoolProp(iPosition++));
Index: src/ch/Stdafx.h
===================================================================
diff -u -rf6706e71721e6828e4e3be894caec6808e27630b -rf34d204b8eecd6817dbe4a1c3b3541cf9a8794b0
--- src/ch/Stdafx.h	(.../Stdafx.h)	(revision f6706e71721e6828e4e3be894caec6808e27630b)
+++ src/ch/Stdafx.h	(.../Stdafx.h)	(revision f34d204b8eecd6817dbe4a1c3b3541cf9a8794b0)
@@ -31,6 +31,8 @@
 #include <afxmt.h>
 #include <afxdtctl.h>
 
+#include <afxinet.h>
+
 #pragma warning (disable: 4711) 
 #include "debug.h"
 #include "../libicpf/file.h"
Index: src/ch/UpdateChecker.cpp
===================================================================
diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -rf34d204b8eecd6817dbe4a1c3b3541cf9a8794b0
--- src/ch/UpdateChecker.cpp	(.../UpdateChecker.cpp)	(revision d5c3edd0d167db9b5d47d04248820fda49499a5e)
+++ src/ch/UpdateChecker.cpp	(.../UpdateChecker.cpp)	(revision f34d204b8eecd6817dbe4a1c3b3541cf9a8794b0)
@@ -1,112 +1,755 @@
+// ============================================================================
+//  Copyright (C) 2001-2009 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+/// @file UpdateChecker.cpp
+/// @date 2009/04/18
+/// @brief Contains an implementation of update checker class.
+// ============================================================================
 #include "stdafx.h"
 #include "UpdateChecker.h"
 #include <afxinet.h>
 #include <atlconv.h>
 #include "../common/version.h"
 #include "../libicpf/cfg.h"
 #include "../libicpf/exception.h"
+#include "../libicpf/circ_buffer.h"
 
-CUpdateChecker::ECheckResult CUpdateChecker::CheckForUpdates(const tchar_t* pszSite, bool bCheckBeta)
+// timeout used with waiting for events (avoiding hangs)
+#define FORCE_TIMEOUT 60000
+
+// ============================================================================
+/// CAsyncHttpFile::CAsyncHttpFile
+/// @date 2009/04/18
+///
+/// @brief     Constructs the CAsyncHttpFile object.
+// ============================================================================
+CAsyncHttpFile::CAsyncHttpFile() :
+	m_hInternet(NULL),
+	m_hOpenUrl(NULL),
+	m_dwExpectedState(0),
+	m_hFinishedEvent(NULL),
+	m_dwError(0)
 {
-	try
+	memset(&m_internetBuffers, 0, sizeof(INTERNET_BUFFERS));
+}
+
+// ============================================================================
+/// CAsyncHttpFile::~CAsyncHttpFile
+/// @date 2009/04/18
+///
+/// @brief     Destructs the CASyncHttpFile object.
+// ============================================================================
+CAsyncHttpFile::~CAsyncHttpFile()
+{
+	Close();
+}
+
+// ============================================================================
+/// CAsyncHttpFile::Open
+/// @date 2009/04/18
+///
+/// @brief     Opens the specified internet address (starts those operations).
+/// @param[in] pszPath		Url to be opened (full path to file).
+/// @return    S_OK if opened, S_FALSE if wait for result is needed, E_* for errors.
+// ============================================================================
+HRESULT CAsyncHttpFile::Open(const tchar_t* pszPath)
+{
+	if(!pszPath)
+		return E_INVALIDARG;
+
+	if(m_hInternet || m_hFinishedEvent)
+		return E_FAIL;
+
+	// create event
+	m_hFinishedEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+	if(!m_hFinishedEvent)
+		return E_FAIL;
+
+	m_hInternet = ::InternetOpen(_T(PRODUCT_NAME), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
+	if(!m_hInternet)
 	{
-		CString strSite(pszSite);
-		strSite.Replace(_T("http://"), _T(""));
+		::CloseHandle(m_hFinishedEvent);
+		m_hFinishedEvent = NULL;
 
-		CInternetSession inetSession;
-		CHttpConnection* pHttpConnection = inetSession.GetHttpConnection(strSite, INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, 80);
-		if(!pHttpConnection)
-		{
-			m_eResult = eResult_Error;
-			return m_eResult;
-		}
+		m_dwError = GetLastError();
+		return E_FAIL;
+	}
 
-		CString strAddr = _T("chver.ini");
-		CHttpFile* pHttpFile = pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_GET, strAddr);
-		if(!pHttpFile)
+	if(::InternetSetStatusCallback(m_hInternet, (INTERNET_STATUS_CALLBACK)&CAsyncHttpFile::InternetStatusCallback) == INTERNET_INVALID_STATUS_CALLBACK)
+	{
+		m_dwError = GetLastError();
+		::InternetCloseHandle(m_hInternet);
+		::CloseHandle(m_hFinishedEvent);
+
+		m_hFinishedEvent = NULL;
+		return E_FAIL;
+	}
+
+	m_dwExpectedState = INTERNET_STATUS_REQUEST_COMPLETE;
+	m_hOpenUrl = ::InternetOpenUrl(m_hInternet, pszPath, NULL, 0, INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD, (DWORD_PTR)this);
+	if(!m_hOpenUrl)
+	{
+		m_dwError = ::GetLastError();
+		if(m_dwError != ERROR_IO_PENDING)
 		{
-			m_eResult = eResult_Error;
-			return m_eResult;
+			::InternetSetStatusCallback(m_hInternet, NULL);
+			::InternetCloseHandle(m_hInternet);
+			::CloseHandle(m_hFinishedEvent);
+			m_hInternet = NULL;
+			m_hFinishedEvent = NULL;
+			m_dwExpectedState = 0;
+
+			return E_FAIL;
 		}
+	}
+	else
+		m_dwExpectedState = 0;		// everything has been completed
 
-		if(!pHttpFile->SendRequest())
+	if(m_hOpenUrl)
+		::SetEvent(m_hFinishedEvent);
+
+	return m_hOpenUrl ? S_OK : S_FALSE;
+}
+
+// ============================================================================
+/// CAsyncHttpFile::GetFileSize
+/// @date 2009/04/18
+///
+/// @brief     Retrieves the size of file opened with CAsyncHttpFile::Open()
+//				(if such information exists in http headers).
+/// @param[out] stSize  Receives the size of file (receives 65536 if http headers
+///                     did not contain the information).
+/// @return		Result of the operation.
+// ============================================================================
+HRESULT CAsyncHttpFile::GetFileSize(size_t& stSize)
+{
+	if(!m_hInternet || !m_hOpenUrl)
+		return E_FAIL;
+
+	DWORD dwContentLengthSize = sizeof(DWORD);
+	if(!HttpQueryInfo(m_hOpenUrl, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &stSize, &dwContentLengthSize, NULL) || stSize == 0 || stSize > 1*1024UL*1024UL)
+	{
+		stSize = 65536;		// safe fallback
+		return S_FALSE;
+	}
+
+	return S_OK;
+}
+
+// ============================================================================
+/// CAsyncHttpFile::RequestData
+/// @date 2009/04/18
+///
+/// @brief     Requests the data from already opened url.
+/// @param[in]	pBuffer  Buffer for the data.
+/// @param[in]  stSize   Buffer size.
+/// @return	   S_OK if completed, S_FALSE if needs waiting, E_* on error.
+// ============================================================================
+HRESULT CAsyncHttpFile::RequestData(void* pBuffer, size_t stSize)
+{
+	if(!pBuffer)
+		return E_INVALIDARG;
+	if(!m_hInternet || !m_hOpenUrl || !m_hFinishedEvent)
+		return E_FAIL;
+
+	if(!::ResetEvent(m_hFinishedEvent))
+		return E_FAIL;
+
+	memset(&m_internetBuffers, 0, sizeof(INTERNET_BUFFERS));
+	m_internetBuffers.dwStructSize = sizeof(INTERNET_BUFFERS);
+	m_internetBuffers.dwBufferLength = stSize;
+	m_internetBuffers.dwBufferTotal = stSize;
+	m_internetBuffers.lpvBuffer = pBuffer;
+
+	m_dwExpectedState = INTERNET_STATUS_REQUEST_COMPLETE;
+	if(!::InternetReadFileEx(m_hOpenUrl, &m_internetBuffers, IRF_NO_WAIT, (DWORD_PTR)this))
+	{
+		if((m_dwError = ::GetLastError()) == ERROR_IO_PENDING)
+			return S_FALSE;
+		else
+			return E_FAIL;
+	}
+
+	if(!::SetEvent(m_hFinishedEvent))
+		return E_FAIL;
+
+	return S_OK;
+}
+
+// ============================================================================
+/// CAsyncHttpFile::RetrieveRequestedData
+/// @date 2009/04/18
+///
+/// @brief     Retrieves the size of data retrieved.
+/// @param[out] stSize  Receives the size of data read from file.
+/// @return    Result of the operation.
+// ============================================================================
+HRESULT CAsyncHttpFile::GetRetrievedDataSize(size_t& stSize)
+{
+	if(!m_hInternet)
+		return E_FAIL;
+
+	stSize = m_internetBuffers.dwBufferLength;
+
+	return S_OK;
+}
+
+// ============================================================================
+/// CAsyncHttpFile::Close
+/// @date 2009/04/18
+///
+/// @brief     Closes the file.
+/// @return    Result of the operation.
+// ============================================================================
+HRESULT CAsyncHttpFile::Close()
+{
+	if(m_hOpenUrl)
+	{
+		m_dwExpectedState = INTERNET_STATUS_CLOSING_CONNECTION;
+		if(!::InternetCloseHandle(m_hOpenUrl))
 		{
-			m_eResult = eResult_Error;
-			return m_eResult;
+			if(::GetLastError() == ERROR_IO_PENDING)
+				return S_FALSE;
+			else
+				return E_FAIL;
 		}
 
-		const size_t stBufferSize(65536);
-		tchar_t* pszBuf = new tchar_t[stBufferSize];
-		UINT uiRD = pHttpFile->Read(pszBuf, stBufferSize - 1);
-		if(uiRD > 0)
-			pszBuf[uiRD] = _T('\0');
+		// if closing url handle succeeded, we close internet here, if not
+		// then a separate call to close need to be performed.
+		m_dwExpectedState = 0;
+		m_hOpenUrl = NULL;
+		::InternetCloseHandle(m_hInternet);
+	}
 
-		// convert text to unicode
-		icpf::config cfg(icpf::config::eIni);
-		const uint_t uiVersionNumeric = cfg.register_string(_t("Version/Numeric"), _t(""));
-		const uint_t uiVersionReadable = cfg.register_string(_t("Version/Human Readable"), _t(""));
-		const uint_t uiDownloadAddress = cfg.register_string(_t("Version/Download Address"), pszSite);
-		const uint_t uiBetaVersionNumeric = cfg.register_string(_t("Version/Numeric Beta"), _t(""));
-		const uint_t uiBetaVersionReadable = cfg.register_string(_t("Version/Human Readable Beta"), _t(""));
-		const uint_t uiBetaDownloadAddress = cfg.register_string(_t("Version/Download Address Beta"), pszSite);
-		try
+	if(m_hFinishedEvent)
+	{
+		::CloseHandle(m_hFinishedEvent);
+		m_hFinishedEvent = NULL;
+	}
+
+
+	return S_OK;
+}
+
+// ============================================================================
+/// CAsyncHttpFile::GetResult
+/// @date 2009/04/18
+///
+/// @brief     Retrieves the last call result (blocking call).
+/// @return    Result of the last call.
+// ============================================================================
+CAsyncHttpFile::EWaitResult CAsyncHttpFile::GetResult()
+{
+	HANDLE hHandles[] = { m_hFinishedEvent };
+	DWORD dwEffect = WaitForMultipleObjects(1, hHandles, FALSE, 0);
+	if(dwEffect == WAIT_OBJECT_0 + 0 || dwEffect == WAIT_ABANDONED_0 + 0)
+		return m_dwError == ERROR_SUCCESS ? CAsyncHttpFile::eFinished : CAsyncHttpFile::eError;
+	else
+		return CAsyncHttpFile::ePending;
+}
+
+// ============================================================================
+/// CAsyncHttpFile::WaitForResult
+/// @date 2009/04/18
+///
+/// @brief     Waits for the result with additional 'kill' event.
+/// @param[in] hKillEvent  Event handle that would break waiting for result.
+/// @return    Result of waiting.
+// ============================================================================
+CAsyncHttpFile::EWaitResult CAsyncHttpFile::WaitForResult(HANDLE hKillEvent)
+{
+	HANDLE hHandles[] = { hKillEvent, m_hFinishedEvent };
+	DWORD dwEffect = WaitForMultipleObjects(2, hHandles, FALSE, FORCE_TIMEOUT);
+	if(dwEffect == 0xffffffff)
+	{
+		TRACE(_T("[CAsyncHttpFile::WaitForResult()] Wait failed with system error %lu\n"), ::GetLastError());
+		return CAsyncHttpFile::eError;
+	}
+	else if(dwEffect == WAIT_OBJECT_0 + 0 || dwEffect == WAIT_ABANDONED_0 + 0)
+		return CAsyncHttpFile::eKilled;
+	else if(dwEffect == WAIT_OBJECT_0 + 1 || dwEffect == WAIT_ABANDONED_0 + 1)
+		return m_dwError == ERROR_SUCCESS ? CAsyncHttpFile::eFinished : CAsyncHttpFile::eError;
+	else
+		return CAsyncHttpFile::eTimeout;
+}
+
+// ============================================================================
+/// CAsyncHttpFile::InternetStatusCallback
+/// @date 2009/04/18
+///
+/// @brief     Callback for use with internet API.
+/// @param[in] hInternet				Internet handle.
+/// @param[in] dwContext				Context value.
+/// @param[in] dwInternetStatus			Internet status.
+/// @param[in] lpvStatusInformation		Additional status information.
+/// @param[in] dwStatusInformationLength Length of lpvStatusInformation.
+// ============================================================================
+void CAsyncHttpFile::InternetStatusCallback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD /*dwStatusInformationLength*/)
+{
+	TRACE(_T("[InternetStatusCallback] hInternet: %p, dwInternetStatus: %lu\n"), hInternet, dwInternetStatus);
+	CAsyncHttpFile* pAsyncHttpFile = (CAsyncHttpFile*)dwContext;
+	BOOST_ASSERT(pAsyncHttpFile);
+	if(!pAsyncHttpFile)
+		return;
+
+	DWORD dwError = ERROR_SUCCESS;
+	switch(dwInternetStatus)
+	{
+	case INTERNET_STATUS_HANDLE_CREATED:
 		{
-			cfg.read_from_buffer(pszBuf, uiRD);
+			INTERNET_ASYNC_RESULT* res = (INTERNET_ASYNC_RESULT*)lpvStatusInformation;
+			pAsyncHttpFile->SetUrlHandle((HINTERNET)(res->dwResult));
+			break;
 		}
-		catch(icpf::exception& e)
+	case INTERNET_STATUS_REQUEST_COMPLETE:
 		{
-			m_strLastError = e.get_desc();
-
-			delete [] pszBuf;
-			m_eResult = eResult_Error;
-			return m_eResult;
+			INTERNET_ASYNC_RESULT* pResult = (INTERNET_ASYNC_RESULT*)lpvStatusInformation;
+			dwError = pResult->dwError;
+			break;
 		}
-		delete [] pszBuf;
+	case INTERNET_STATUS_CLOSING_CONNECTION:
+		{
+			pAsyncHttpFile->SetUrlHandle(NULL);
+			break;
+		}
+	case INTERNET_STATUS_CONNECTION_CLOSED:
+		{
+			break;
+		}
+	default:
+		TRACE(_T("[CAsyncHttpFile::InternetStatusCallback()] Unhandled status: %lu\n"), dwInternetStatus);
+	}
 
-		if(bCheckBeta)
+	pAsyncHttpFile->SetErrorCode(dwError);
+	pAsyncHttpFile->SetCompletionStatus(dwInternetStatus);
+}
+
+
+// ============================================================================
+/// CAsyncHttpFile::SetUrlHandle
+/// @date 2009/04/18
+///
+/// @brief     Sets the url handle.
+/// @param[in] hOpenUrl  Handle to be set.
+// ============================================================================
+void CAsyncHttpFile::SetUrlHandle(HANDLE hOpenUrl)
+{
+	m_hOpenUrl = hOpenUrl;
+}
+
+// ============================================================================
+/// CAsyncHttpFile::SetErrorCode
+/// @date 2009/04/18
+///
+/// @brief     Sets the error code.
+/// @param[in] dwError  Error code to be set.
+// ============================================================================
+void CAsyncHttpFile::SetErrorCode(DWORD dwError)
+{
+	m_dwError = dwError;
+}
+
+// ============================================================================
+/// CAsyncHttpFile::SetCompletionStatus
+/// @date 2009/04/18
+///
+/// @brief     Sets the completion status.
+/// @param[in] dwCurrentState  State to be set.
+/// @return    Result of the operation.
+// ============================================================================
+HRESULT CAsyncHttpFile::SetCompletionStatus(DWORD dwCurrentState)
+{
+	if(!m_hFinishedEvent)
+		return E_FAIL;
+
+	if(dwCurrentState == m_dwExpectedState || dwCurrentState == INTERNET_STATUS_CLOSING_CONNECTION)
+		return ::SetEvent(m_hFinishedEvent) ? S_OK : E_FAIL;
+	return S_FALSE;
+}
+
+// ============================================================================
+/// CUpdateChecker::CUpdateChecker
+/// @date 2009/04/18
+///
+/// @brief     Constructs the update checker object.
+// ============================================================================
+CUpdateChecker::CUpdateChecker() :
+	m_hThread(NULL),
+	m_hKillEvent(NULL),
+	m_eResult(eResult_Undefined),
+	m_bCheckForBeta(false)
+{
+	m_hKillEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+	BOOST_ASSERT(m_hKillEvent);
+	::InitializeCriticalSection(&m_cs);
+}
+
+// ============================================================================
+/// CUpdateChecker::~CUpdateChecker
+/// @date 2009/04/18
+///
+/// @brief     Destroys the update checker object.
+// ============================================================================
+CUpdateChecker::~CUpdateChecker()
+{
+	Cleanup();
+
+	::DeleteCriticalSection(&m_cs);
+}
+
+// ============================================================================
+/// CUpdateChecker::AsyncCheckForUpdates
+/// @date 2009/04/18
+///
+/// @brief     Starts the asynchronous checking for updates.
+/// @param[in] pszSite	    Site where to search for updates (without file name).
+/// @param[in] bCheckBeta   States if we are interested in beta products.
+/// @return    True if operation started, false otherwise.
+// ============================================================================
+bool CUpdateChecker::AsyncCheckForUpdates(const tchar_t* pszSite, bool bCheckBeta, bool bOnlyIfConnected)
+{
+	if(!pszSite)
+		return false;
+
+	DWORD dwConnectionFlags = 0;
+
+	if(bOnlyIfConnected && !InternetGetConnectedState(&dwConnectionFlags, 0))
+		return false;
+
+	m_strSite = pszSite;
+	m_eResult = eResult_Undefined;
+	m_bCheckForBeta = bCheckBeta;
+
+	::ResetEvent(m_hKillEvent);
+
+	m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&CUpdateChecker::UpdateCheckThread, (void*)this, 0, NULL);
+	if(!m_hThread)
+	{
+		m_strSite.Empty();
+		m_eResult = eResult_Undefined;
+		m_bCheckForBeta = false;
+		return false;
+	}
+
+	return true;
+}
+
+// ============================================================================
+/// CUpdateChecker::Cleanup
+/// @date 2009/04/18
+///
+/// @brief     Stops scanning for updates and clears the object.
+// ============================================================================
+void CUpdateChecker::Cleanup()
+{
+	if(m_hThread)
+	{
+		if(m_hKillEvent)
+			::SetEvent(m_hKillEvent);
+		WaitForSingleObject(m_hThread, 5000);
+		if(m_hKillEvent)
+			::CloseHandle(m_hKillEvent);
+	}
+
+	m_httpFile.Close();
+
+	::EnterCriticalSection(&m_cs);
+	m_hThread = NULL;
+	m_hKillEvent = NULL;
+	m_strSite.Empty();
+	m_bCheckForBeta = false;
+	m_strLastError.Empty();
+	m_strNumericVersion.Empty();
+	m_strReadableVersion.Empty();
+	m_strDownloadAddress.Empty();
+	m_eResult = CUpdateChecker::eResult_Undefined;
+	::LeaveCriticalSection(&m_cs);
+}
+
+// ============================================================================
+/// CUpdateChecker::SetResult
+/// @date 2009/04/18
+///
+/// @brief     Sets the result of checking.
+/// @param[in] eCheckResult  Result to be set.
+/// @param[in] dwError       Error code (if any).
+// ============================================================================
+void CUpdateChecker::SetResult(ECheckResult eCheckResult, DWORD dwError)
+{
+	CString strError;
+
+	if(eCheckResult == eResult_Error && dwError != 0)
+	{
+		PTSTR pszBuffer = strError.GetBufferSetLength(_MAX_PATH);
+		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), pszBuffer, _MAX_PATH, NULL);
+		strError.ReleaseBuffer();
+
+		if(strError.IsEmpty())
 		{
-			m_strReadableVersion = cfg.get_string(uiBetaVersionReadable);
-			m_strNumericVersion = cfg.get_string(uiBetaVersionNumeric);
-			m_strDownloadAddress = cfg.get_string(uiBetaDownloadAddress);
+			pszBuffer = strError.GetBufferSetLength(_MAX_PATH);
+			FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, GetModuleHandle(_T("wininet.dll")), dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), pszBuffer, _MAX_PATH, NULL);
+			strError.ReleaseBuffer();
 		}
 
-		if(!bCheckBeta || m_strNumericVersion.IsEmpty())
+		if(strError.IsEmpty())
+			strError.Format(_T("0x%lx"), dwError);
+	}
+
+	strError.TrimRight(_T("\r\n \t"));
+
+	::EnterCriticalSection(&m_cs);
+	
+	m_eResult = eCheckResult;
+	m_strLastError = strError;
+
+	::LeaveCriticalSection(&m_cs);
+}
+
+// ============================================================================
+/// CUpdateChecker::SetLastError
+/// @date 2009/04/18
+///
+/// @brief     Sets last error.
+/// @param[in] pszError  String containing the last error description.
+// ============================================================================
+void CUpdateChecker::SetLastError(PCTSTR pszError)
+{
+	::EnterCriticalSection(&m_cs);
+	m_strLastError = pszError;
+	::LeaveCriticalSection(&m_cs);
+}
+
+// ============================================================================
+/// CUpdateChecker::SetVersionsAndAddress
+/// @date 2009/04/18
+///
+/// @brief     Sets the download address and version information.
+/// @param[in] pszAddress            Download address.
+/// @param[in] pszNumericVersion     Numeric version number.
+/// @param[in] pszReadableVersion    Human readable version number.
+// ============================================================================
+void CUpdateChecker::SetVersionsAndAddress(PCTSTR pszAddress, PCTSTR pszNumericVersion, PCTSTR pszReadableVersion)
+{
+	::EnterCriticalSection(&m_cs);
+	m_strDownloadAddress = pszAddress;
+	m_strNumericVersion = pszNumericVersion;
+	m_strReadableVersion = pszReadableVersion;
+	::LeaveCriticalSection(&m_cs);
+}
+
+// ============================================================================
+/// CUpdateChecker::GetSiteAddress
+/// @date 2009/04/18
+///
+/// @brief     Retrieves the address of a site to check the updates at.
+/// @param[out] rstrAddress  Receives the address.
+// ============================================================================
+void CUpdateChecker::GetSiteAddress(CString& rstrAddress) const
+{
+	::EnterCriticalSection(&m_cs);
+	rstrAddress = m_strSite;
+	::LeaveCriticalSection(&m_cs);
+}
+
+// ============================================================================
+/// CUpdateChecker::CheckForBeta
+/// @date 2009/04/18
+///
+/// @brief     Returns information, if update should check for beta versions.
+/// @return    True if beta versions should be processed, false otherwise.
+// ============================================================================
+bool CUpdateChecker::CheckForBeta()
+{
+	::EnterCriticalSection(&m_cs);
+	bool bCheckForBeta = m_bCheckForBeta;
+	::LeaveCriticalSection(&m_cs);
+
+	return bCheckForBeta;
+}
+
+// ============================================================================
+/// CUpdateChecker::GetResult
+/// @date 2009/04/18
+///
+/// @brief     Retrieves the result of checking for updates.
+/// @return    Check for updates result.
+// ============================================================================
+CUpdateChecker::ECheckResult CUpdateChecker::GetResult() const
+{
+	::EnterCriticalSection(&m_cs);
+	ECheckResult eResult = m_eResult;
+	::LeaveCriticalSection(&m_cs);
+	return eResult;
+}
+
+// ============================================================================
+/// CUpdateChecker::UpdateCheckThread
+/// @date 2009/04/18
+///
+/// @brief     Main thread function.
+/// @param[in] pParam  Pointer to the thread parameter (pointer to the CUpdateChecker object).
+/// @return    Thread execution status.
+// ============================================================================
+DWORD CUpdateChecker::UpdateCheckThread(LPVOID pParam)
+{
+	CUpdateChecker* pUpdateChecker = (CUpdateChecker*)pParam;
+
+	// mark as started
+	pUpdateChecker->SetResult(eResult_Pending, 0);
+
+	// get the real address of file to download
+	CString strSite;
+	pUpdateChecker->GetSiteAddress(strSite);
+	strSite += _T("/chver.ini");
+
+	CAsyncHttpFile::EWaitResult eWaitResult = CAsyncHttpFile::ePending;
+	size_t stFileSize = 0;
+	byte_t* pbyBuffer = NULL;
+	icpf::circular_buffer circBuffer;
+
+	// open the connection and try to get to the file
+	HRESULT hResult = pUpdateChecker->m_httpFile.Open(strSite);
+	if(SUCCEEDED(hResult))
+	{
+		eWaitResult = pUpdateChecker->m_httpFile.WaitForResult(pUpdateChecker->m_hKillEvent);
+		switch(eWaitResult)
 		{
-			m_strNumericVersion = cfg.get_string(uiVersionNumeric);
-			m_strReadableVersion = cfg.get_string(uiVersionReadable);
-			m_strDownloadAddress = cfg.get_string(uiDownloadAddress);
+		case CAsyncHttpFile::eFinished:
+			break;
+		case CAsyncHttpFile::eKilled:
+			pUpdateChecker->SetResult(eResult_Killed, 0);
+			return 1;
+			break;
+		case CAsyncHttpFile::eError:
+			pUpdateChecker->SetResult(eResult_Error, pUpdateChecker->m_httpFile.GetErrorCode());
+			return 1;
+		case CAsyncHttpFile::eTimeout:
+		case CAsyncHttpFile::ePending:
+		default:
+			pUpdateChecker->SetResult(eResult_Error, 0);
+			return 1;
 		}
+	}
+	if(SUCCEEDED(hResult))
+		hResult = pUpdateChecker->m_httpFile.GetFileSize(stFileSize);
 
-		// and compare to current version
-		ushort_t usVer[4];
-		if(_stscanf(m_strNumericVersion, _t("%hu.%hu.%hu.%hu"), &usVer[0], &usVer[1], &usVer[2], &usVer[3]) != 4)
+	if(SUCCEEDED(hResult))
+	{
+		bool bIsClosed = false;
+		pbyBuffer = new byte_t[stFileSize];
+		do 
 		{
-			TRACE(_T("Error parsing retrieved version number."));
-			m_eResult = eResult_Error;
-			return m_eResult;
+			hResult = pUpdateChecker->m_httpFile.RequestData(pbyBuffer, stFileSize);
+			if(SUCCEEDED(hResult))
+			{
+				eWaitResult = pUpdateChecker->m_httpFile.WaitForResult(pUpdateChecker->m_hKillEvent);
+				switch(eWaitResult)
+				{
+				case CAsyncHttpFile::eFinished:
+					break;
+				case CAsyncHttpFile::eKilled:
+					pUpdateChecker->SetResult(eResult_Killed, 0);
+					return 1;
+					break;
+				case CAsyncHttpFile::eError:
+					pUpdateChecker->SetResult(eResult_Error, pUpdateChecker->m_httpFile.GetErrorCode());
+					return 1;
+				case CAsyncHttpFile::eTimeout:
+				case CAsyncHttpFile::ePending:
+				default:
+					pUpdateChecker->SetResult(eResult_Error, 0);
+					return 1;
+				}
+			}
+
+			if(SUCCEEDED(hResult))
+				hResult = pUpdateChecker->m_httpFile.GetRetrievedDataSize(stFileSize);
+
+			if(SUCCEEDED(hResult) && stFileSize)
+				circBuffer.push_data(pbyBuffer, stFileSize);
+
+			bIsClosed = pUpdateChecker->m_httpFile.IsClosed();
 		}
+		while(stFileSize && !bIsClosed && SUCCEEDED(hResult));
 
-		ull_t ullCurrentVersion = ((ull_t)PRODUCT_VERSION1) << 48 | ((ull_t)PRODUCT_VERSION2) << 32 | ((ull_t)PRODUCT_VERSION3) << 16 | ((ull_t)PRODUCT_VERSION4);
-		ull_t ullSiteVersion = ((ull_t)usVer[0]) << 48 | ((ull_t)usVer[1]) << 32 | ((ull_t)usVer[2]) << 16 | ((ull_t)usVer[3]);
+		delete [] pbyBuffer;
+	}
 
-		if(ullCurrentVersion < ullSiteVersion)
-			m_eResult = eResult_VersionNewer;
-		else if(ullCurrentVersion == ullSiteVersion)
-			m_eResult = eResult_VersionCurrent;
-		else
-			m_eResult = eResult_VersionOlder;
+	if(FAILED(hResult))
+	{
+		pUpdateChecker->SetResult(eResult_Error, pUpdateChecker->m_httpFile.GetErrorCode());
+		return 1;
+	}
 
-		return m_eResult;
+	pUpdateChecker->m_httpFile.Close();
+
+	// convert text to unicode
+	icpf::config cfg(icpf::config::eIni);
+	const uint_t uiVersionNumeric = cfg.register_string(_t("Version/Numeric"), _t(""));
+	const uint_t uiVersionReadable = cfg.register_string(_t("Version/Human Readable"), _t(""));
+	const uint_t uiDownloadAddress = cfg.register_string(_t("Version/Download Address"), strSite);
+	const uint_t uiBetaVersionNumeric = cfg.register_string(_t("Version/Numeric Beta"), _t(""));
+	const uint_t uiBetaVersionReadable = cfg.register_string(_t("Version/Human Readable Beta"), _t(""));
+	const uint_t uiBetaDownloadAddress = cfg.register_string(_t("Version/Download Address Beta"), strSite);
+	try
+	{
+		cfg.read_from_buffer((TCHAR*)circBuffer.get_buffer(), (circBuffer.get_datasize() + 1) / 2);
 	}
-	catch(CInternetException* e)
+	catch(icpf::exception& e)
 	{
-		TCHAR* pszBuffer = m_strLastError.GetBufferSetLength(1024);
-		e->GetErrorMessage(pszBuffer, 1023);
-		pszBuffer[1023] = _T('\0');
-		m_strLastError.ReleaseBuffer();
-		m_strLastError.TrimRight();
+		pUpdateChecker->SetResult(eResult_Error, 0);
+		pUpdateChecker->SetLastError(e.get_desc());
 
-		m_eResult = eResult_Error;
-		return m_eResult;
+		return 0xffffffff;
 	}
+
+	CString strVersionNumeric;
+	bool bCheckForBeta = pUpdateChecker->CheckForBeta();
+	if(bCheckForBeta)
+	{
+		strVersionNumeric = cfg.get_string(uiBetaVersionNumeric);
+		pUpdateChecker->SetVersionsAndAddress(cfg.get_string(uiBetaDownloadAddress), strVersionNumeric, cfg.get_string(uiBetaVersionReadable));
+	}
+
+	if(!bCheckForBeta || strVersionNumeric.IsEmpty())
+	{
+		strVersionNumeric = cfg.get_string(uiVersionNumeric);
+		pUpdateChecker->SetVersionsAndAddress(cfg.get_string(uiDownloadAddress), strVersionNumeric, cfg.get_string(uiVersionReadable));
+	}
+
+	// and compare to current version
+	ushort_t usVer[4];
+	if(_stscanf(strVersionNumeric, _t("%hu.%hu.%hu.%hu"), &usVer[0], &usVer[1], &usVer[2], &usVer[3]) != 4)
+	{
+		TRACE(_T("Error parsing retrieved version number."));
+		pUpdateChecker->SetResult(eResult_Error, 0);
+		return 0xffffffff;
+	}
+
+	ull_t ullCurrentVersion = ((ull_t)PRODUCT_VERSION1) << 48 | ((ull_t)PRODUCT_VERSION2) << 32 | ((ull_t)PRODUCT_VERSION3) << 16 | ((ull_t)PRODUCT_VERSION4);
+	ull_t ullSiteVersion = ((ull_t)usVer[0]) << 48 | ((ull_t)usVer[1]) << 32 | ((ull_t)usVer[2]) << 16 | ((ull_t)usVer[3]);
+
+	if(ullCurrentVersion < ullSiteVersion)
+		pUpdateChecker->SetResult(eResult_RemoteVersionNewer, 0);
+	else if(ullCurrentVersion == ullSiteVersion)
+		pUpdateChecker->SetResult(eResult_VersionCurrent, 0);
+	else
+		pUpdateChecker->SetResult(eResult_RemoteVersionOlder, 0);
+
+	return 0;
 }
Index: src/ch/UpdateChecker.h
===================================================================
diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -rf34d204b8eecd6817dbe4a1c3b3541cf9a8794b0
--- src/ch/UpdateChecker.h	(.../UpdateChecker.h)	(revision d5c3edd0d167db9b5d47d04248820fda49499a5e)
+++ src/ch/UpdateChecker.h	(.../UpdateChecker.h)	(revision f34d204b8eecd6817dbe4a1c3b3541cf9a8794b0)
@@ -1,37 +1,145 @@
+// ============================================================================
+//  Copyright (C) 2001-2009 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+/// @file UpdateChecker.h
+/// @date 2009/04/18
+/// @brief Contains declaration of update checker class.
+// ============================================================================
 #ifndef __UPDATECHECKER_H__
 #define __UPDATECHECKER_H__
 
-class CUpdateChecker
+class CAsyncHttpFile
 {
 public:
+	enum EWaitResult
+	{
+		eKilled,
+		eFinished,
+		eTimeout,
+		ePending,
+		eError
+	};
+
+public:
+	CAsyncHttpFile();
+	~CAsyncHttpFile();
+
+	HRESULT Open(const tchar_t* pszPath);
+	HRESULT GetFileSize(size_t& stSize);
+
+	HRESULT RequestData(void* pBuffer, size_t stSize);
+	HRESULT GetRetrievedDataSize(size_t& stSize);
+
+	HRESULT Close();
+
+	EWaitResult GetResult();
+	DWORD GetErrorCode() { return m_dwError; }
+
+	EWaitResult WaitForResult(HANDLE hKillEvent);
+
+	bool IsClosed() const { return m_hOpenUrl == NULL; }
+
+protected:
+	static void InternetStatusCallback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength);
+
+	void SetUrlHandle(HANDLE hOpenUrl);
+	void SetErrorCode(DWORD dwError);
+
+	/// Sets the completion event
+	HRESULT SetCompletionStatus(DWORD dwCurrentState);
+
+protected:
+	HINTERNET m_hInternet;
+	HINTERNET m_hOpenUrl;
+
+	DWORD m_dwExpectedState;		///< State we are expecting
+	HANDLE m_hFinishedEvent;
+
+	INTERNET_BUFFERS m_internetBuffers;
+
+	DWORD m_dwError;
+};
+
+class CUpdateChecker : protected CInternetSession
+{
+public:
 	enum ECheckResult
 	{
 		eResult_Undefined,
-		eResult_VersionOlder,
+		eResult_Pending,
+		eResult_Killed,
+		eResult_Error,
+		eResult_RemoteVersionOlder,
 		eResult_VersionCurrent,
-		eResult_VersionNewer,
-		eResult_Error
+		eResult_RemoteVersionNewer
 	};
+
 public:
-	CUpdateChecker() : m_eResult(eResult_Undefined) { };
-	~CUpdateChecker() { };
+	/// Constructs the update checker object
+	CUpdateChecker();
+	/// Destructs the update checker object
+	~CUpdateChecker();
 
-	ECheckResult CheckForUpdates(const tchar_t* pszSite, bool bCheckBeta);
+	/// Starts the 'check for updates' thread
+	bool AsyncCheckForUpdates(const tchar_t* pszSite, bool bCheckBeta, bool bOnlyIfConnected);
 
+	/// Stops checking and cleanups the object
+	void Cleanup();
+
+	/// Retrieves the update result
+	ECheckResult GetResult() const;
+
+	// methods for retrieving state
 	const tchar_t* GetNumericVersion() const { return (const tchar_t*)m_strNumericVersion; }
 	const tchar_t* GetReadableVersion() const { return (const tchar_t*)m_strReadableVersion; }
 	const tchar_t* GetLastError() const { return (const tchar_t*)m_strLastError; }
 	const tchar_t* GetDownloadAddress() const { return m_strDownloadAddress; }
 
-	ECheckResult GetResult() const { return m_eResult; }
+protected:
+	/// Thread function (handles most of the internet connection operation)
+	static DWORD WINAPI UpdateCheckThread(LPVOID pParam);
 
+	/// Sets the result in mt-safe way
+	void SetResult(ECheckResult eCheckResult, DWORD dwError);
+	/// Sets the last error
+	void SetLastError(PCTSTR pszError);
+	/// Sets the versions and download address
+	void SetVersionsAndAddress(PCTSTR pszAddress, PCTSTR pszNumericVersion, PCTSTR pszReadableVersion);
+	/// Retrieves the site address
+	void GetSiteAddress(CString& rstrAddress) const;
+
+	/// Returns information if we're interested in beta versions
+	bool CheckForBeta();
+
 protected:
 	CString m_strSite;
+	bool m_bCheckForBeta;
 	CString m_strLastError;
 	CString m_strNumericVersion;
 	CString m_strReadableVersion;
 	CString m_strDownloadAddress;
+	
 	ECheckResult m_eResult;
+
+	CAsyncHttpFile m_httpFile;
+	HANDLE m_hThread;
+	HANDLE m_hKillEvent;
+	mutable CRITICAL_SECTION m_cs;
 };
 
 #endif
Index: src/ch/UpdaterDlg.cpp
===================================================================
diff -u -r449a5b399ab21ca0d06050b47b264f2f704af966 -rf34d204b8eecd6817dbe4a1c3b3541cf9a8794b0
--- src/ch/UpdaterDlg.cpp	(.../UpdaterDlg.cpp)	(revision 449a5b399ab21ca0d06050b47b264f2f704af966)
+++ src/ch/UpdaterDlg.cpp	(.../UpdaterDlg.cpp)	(revision f34d204b8eecd6817dbe4a1c3b3541cf9a8794b0)
@@ -19,13 +19,16 @@
 
 IMPLEMENT_DYNAMIC(CUpdaterDlg, ictranslate::CLanguageDialog)
 
-CUpdaterDlg::CUpdaterDlg(CWnd* pParent /*=NULL*/)
-: ictranslate::CLanguageDialog(CUpdaterDlg::IDD, pParent)
+CUpdaterDlg::CUpdaterDlg(bool bBackgroundMode, CWnd* pParent /*=NULL*/) :
+	ictranslate::CLanguageDialog(CUpdaterDlg::IDD, pParent),
+	m_eLastState(CUpdateChecker::eResult_Undefined),
+	m_bBackgroundMode(bBackgroundMode)
 {
 }
 
 CUpdaterDlg::~CUpdaterDlg()
 {
+	m_ucChecker.Cleanup();
 }
 
 void CUpdaterDlg::DoDataExchange(CDataExchange* pDX)
@@ -42,44 +45,19 @@
 	fmt.SetParam(_t("%site"), _T(PRODUCT_SITE));
 	m_ctlText.SetWindowText(fmt);
 
+	if(!m_bBackgroundMode)
+		ShowWindow(SW_SHOW);
+
+	// start the updater
+	m_ucChecker.AsyncCheckForUpdates(_T(PRODUCT_SITE), GetConfig().get_bool(PP_PUPDATE_CHECK_FOR_BETA), m_bBackgroundMode);
+
+	// start a timer to display progress
 	SetTimer(UPDATER_TIMER, 10, NULL);
 
 	return TRUE;  // return TRUE unless you set the focus to a control
 	// EXCEPTION: OCX Property Pages should return FALSE
 }
 
-void CUpdaterDlg::StartChecking()
-{
-	m_ucChecker.CheckForUpdates(_T(PRODUCT_SITE), false);
-
-	ictranslate::CResourceManager& rResManager = GetResManager();
-	ictranslate::CFormat fmt;
-
-	CString strFmt;
-	switch(m_ucChecker.GetResult())
-	{
-	case CUpdateChecker::eResult_Error:
-		strFmt = rResManager.LoadString(IDS_UPDATER_ERROR_STRING);
-		break;
-	case CUpdateChecker::eResult_VersionNewer:
-		strFmt = rResManager.LoadString(IDS_UPDATER_NEW_VERSION_STRING);
-		break;
-	case CUpdateChecker::eResult_VersionCurrent:
-		strFmt = rResManager.LoadString(IDS_UPDATER_EQUAL_VERSION_STRING);
-		break;
-	case CUpdateChecker::eResult_VersionOlder:
-		strFmt = rResManager.LoadString(IDS_UPDATER_OLD_VERSION_STRING);
-		break;
-	}
-
-	fmt.SetFormat(strFmt);
-	fmt.SetParam(_t("%errdesc"), m_ucChecker.GetLastError());
-	fmt.SetParam(_t("%thisver"), _T(PRODUCT_VERSION));
-	fmt.SetParam(_t("%officialver"), m_ucChecker.GetReadableVersion());
-
-	m_ctlText.SetWindowText(fmt);
-}
-
 void CUpdaterDlg::OnBnClickedOpenWebpageButton()
 {
 	ShellExecute(NULL, _T("open"), m_ucChecker.GetDownloadAddress(), NULL, NULL, SW_SHOW);
@@ -89,8 +67,86 @@
 {
 	if(nIDEvent == UPDATER_TIMER)
 	{
-		KillTimer(UPDATER_TIMER);
-		StartChecking();
+		ictranslate::CResourceManager& rResManager = GetResManager();
+		ictranslate::CFormat fmt;
+		CUpdateChecker::ECheckResult eResult = m_ucChecker.GetResult();
+		CString strFmt;
+		EBkModeResult eBkMode = eRes_None;
+
+		if(eResult != m_eLastState)
+		{
+			switch(m_ucChecker.GetResult())
+			{
+			case CUpdateChecker::eResult_Undefined:
+				TRACE(_T("CUpdateChecker::eResult_Undefined\n"));
+				eBkMode = eRes_Exit;
+				strFmt = rResManager.LoadString(IDS_UPDATER_WAITING_STRING);
+				break;
+			case CUpdateChecker::eResult_Pending:
+				TRACE(_T("CUpdateChecker::eResult_Pending\n"));
+				strFmt = rResManager.LoadString(IDS_UPDATER_WAITING_STRING);
+				break;
+			case CUpdateChecker::eResult_Killed:
+				TRACE(_T("CUpdateChecker::eResult_Killed\n"));
+				eBkMode = eRes_Exit;
+				strFmt = rResManager.LoadString(IDS_UPDATER_ERROR_STRING);
+				break;
+			case CUpdateChecker::eResult_Error:
+				TRACE(_T("CUpdateChecker::eResult_Error\n"));
+				eBkMode = eRes_Exit;
+				strFmt = rResManager.LoadString(IDS_UPDATER_ERROR_STRING);
+				break;
+			case CUpdateChecker::eResult_RemoteVersionOlder:
+				TRACE(_T("CUpdateChecker::eResult_RemoteVersionOlder\n"));
+//				eBkMode = eRes_Exit;
+				eBkMode = eRes_Show;		// for debugging purposes only
+				strFmt = rResManager.LoadString(IDS_UPDATER_OLD_VERSION_STRING);
+				break;
+			case CUpdateChecker::eResult_VersionCurrent:
+				TRACE(_T("CUpdateChecker::eResult_VersionCurrent\n"));
+				eBkMode = eRes_Exit;
+				strFmt = rResManager.LoadString(IDS_UPDATER_EQUAL_VERSION_STRING);
+				break;
+			case CUpdateChecker::eResult_RemoteVersionNewer:
+				TRACE(_T("CUpdateChecker::eResult_RemoteVersionNewer\n"));
+				eBkMode = eRes_Show;
+				strFmt = rResManager.LoadString(IDS_UPDATER_NEW_VERSION_STRING);
+				break;
+			default:
+				_ASSERTE(FALSE);
+				eBkMode = eRes_Exit;
+				return;
+			}
+
+			fmt.SetFormat(strFmt);
+			fmt.SetParam(_t("%site"), _t(PRODUCT_SITE));
+			fmt.SetParam(_t("%errdesc"), m_ucChecker.GetLastError());
+			fmt.SetParam(_t("%thisver"), _T(PRODUCT_VERSION));
+			fmt.SetParam(_t("%officialver"), m_ucChecker.GetReadableVersion());
+
+			m_ctlText.SetWindowText(fmt);
+
+			m_eLastState = eResult;
+
+			// handle background mode
+			if(m_bBackgroundMode)
+			{
+				switch(eBkMode)
+				{
+				case eRes_None:
+					break;
+				case eRes_Exit:
+					KillTimer(UPDATER_TIMER);
+					EndDialog(IDCANCEL);
+					return;
+				case eRes_Show:
+					ShowWindow(SW_SHOW);
+					break;
+				default:
+					BOOST_ASSERT(FALSE);
+				}
+			}
+		}
 	}
 
 	CLanguageDialog::OnTimer(nIDEvent);
Index: src/ch/UpdaterDlg.h
===================================================================
diff -u -r449a5b399ab21ca0d06050b47b264f2f704af966 -rf34d204b8eecd6817dbe4a1c3b3541cf9a8794b0
--- src/ch/UpdaterDlg.h	(.../UpdaterDlg.h)	(revision 449a5b399ab21ca0d06050b47b264f2f704af966)
+++ src/ch/UpdaterDlg.h	(.../UpdaterDlg.h)	(revision f34d204b8eecd6817dbe4a1c3b3541cf9a8794b0)
@@ -7,15 +7,20 @@
 {
 	DECLARE_DYNAMIC(CUpdaterDlg)
 
+	enum EBkModeResult
+	{
+		eRes_None,
+		eRes_Exit,
+		eRes_Show
+	};
 public:
-	CUpdaterDlg(CWnd* pParent = NULL);   // standard constructor
+	CUpdaterDlg(bool bBackgroundMode, CWnd* pParent = NULL);   // standard constructor
 	virtual ~CUpdaterDlg();
 
 	// Dialog Data
 	enum { IDD = IDD_UPDATER_DIALOG };
 
 	virtual BOOL OnInitDialog();
-	void StartChecking();
 
 	afx_msg void OnBnClickedOpenWebpageButton();
 	afx_msg void OnTimer(UINT_PTR nIDEvent);
@@ -28,5 +33,6 @@
 protected:
 	CStatic m_ctlText;
 	CUpdateChecker m_ucChecker;
-
+	CUpdateChecker::ECheckResult m_eLastState;
+	bool m_bBackgroundMode;		///< Do we operate in standard mode (false), or in background mode (true)
 };
Index: src/ch/ch.rc
===================================================================
diff -u -r0373359eff650e8cf04a5992711ef9f20347536f -rf34d204b8eecd6817dbe4a1c3b3541cf9a8794b0
--- src/ch/ch.rc	(.../ch.rc)	(revision 0373359eff650e8cf04a5992711ef9f20347536f)
+++ src/ch/ch.rc	(.../ch.rc)	(revision f34d204b8eecd6817dbe4a1c3b3541cf9a8794b0)
@@ -461,8 +461,8 @@
 END
 
 IDD_UPDATER_DIALOG DIALOGEX 0, 0, 259, 83
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Version information"
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Copy Handler Update Information"
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
     DEFPUSHBUTTON   "&Close",IDOK,202,62,50,14
@@ -754,8 +754,8 @@
     IDS_CFGSHELL_STRING     "Shell"
     IDS_CFGSCCOUNT_STRING   "Defined shortcuts' count"
     IDS_CFGRPCOUNT_STRING   "Count of recent paths"
-    IDS_CFGINTERCEPTKEYACTION_STRING "Intercept shell keyboard actions (experimental)"
-	IDS_CFGINTERCEPTCONTEXTMENU_STRING "Intercept standard Windows operations (experimental/not recommended)"
+    IDS_CFGINTERCEPTKEYACTION_STRING 
+                            "Intercept shell keyboard actions (experimental)"
     IDS_CFGPRIORITYCLASS_STRING "Application's priority class"
     IDS_CFGDISABLEPRIORITYBOOST_STRING "Disable priority boosting"
     IDS_BOOLTEXT_STRING     "No!Yes"
@@ -767,6 +767,15 @@
 
 STRINGTABLE 
 BEGIN
+    IDS_CFGINTERCEPTCONTEXTMENU_STRING 
+                            "Intercept standard Windows operations (experimental/not recommended)"
+    IDS_CFG_CHECK_FOR_UPDATES_AT_STARTUP 
+                            "Automatically check for program updates at startup"
+    IDS_CFG_UPDATE_CHECK_FOR_BETA "Check for updates - include beta versions"
+END
+
+STRINGTABLE 
+BEGIN
     IDS_MINIVIEWAUTOHIDE_STRING "Hide when empty"
     IDS_PROCESSINGTHREAD_STRING "Copying/moving thread"
     IDS_AUTOCOPYREST_STRING "Auto ""copy-rest"" of files"
Index: src/ch/resource.h
===================================================================
diff -u -r0373359eff650e8cf04a5992711ef9f20347536f -rf34d204b8eecd6817dbe4a1c3b3541cf9a8794b0
--- src/ch/resource.h	(.../resource.h)	(revision 0373359eff650e8cf04a5992711ef9f20347536f)
+++ src/ch/resource.h	(.../resource.h)	(revision f34d204b8eecd6817dbe4a1c3b3541cf9a8794b0)
@@ -424,6 +424,8 @@
 #define IDS_LANGSFOLDERCHOOSE_STRING    8094
 #define IDS_ABOUT_LANGUAGE_STRING       8095
 #define IDS_CFGINTERCEPTCONTEXTMENU_STRING 8096
+#define IDS_CFG_CHECK_FOR_UPDATES_AT_STARTUP 8097
+#define IDS_CFG_UPDATE_CHECK_FOR_BETA 8098
 #define IDS_MENUCOPY_STRING             9000
 #define IDS_MENUMOVE_STRING             9001
 #define IDS_MENUCOPYMOVESPECIAL_STRING  9002