Index: src/ch/FeedbackFileErrorDlg.cpp
===================================================================
diff -u -r671f4b1792a20d98b186f4e0a9cc6a620dede019 -r387751793d274e49253e796ca7cec4f3d0cf07a9
--- src/ch/FeedbackFileErrorDlg.cpp	(.../FeedbackFileErrorDlg.cpp)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
+++ src/ch/FeedbackFileErrorDlg.cpp	(.../FeedbackFileErrorDlg.cpp)	(revision 387751793d274e49253e796ca7cec4f3d0cf07a9)
@@ -6,6 +6,7 @@
 #include "../libchcore/TFileInfo.h"
 #include "FeedbackFileErrorDlg.h"
 #include "FeedbackHandler.h"
+#include "../libchcore/TWin32ErrorFormatter.h"
 
 // CFeedbackFileErrorDlg dialog
 
@@ -18,7 +19,6 @@
 	m_strDstPath(pszDstPath),
 	m_ulSysError(ulSysError)
 {
-
 }
 
 CFeedbackFileErrorDlg::~CFeedbackFileErrorDlg()
@@ -64,18 +64,12 @@
 	strFmt += rResManager.LoadString(IDS_INFO_REASON_STRING);
 
 	// get system error string
-	TCHAR szSystem[1024];
-	DWORD dwPos=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, m_ulSysError, 0, szSystem, 1023, NULL);
-	szSystem[1023] = _T('\0');
+	chcore::TString strError = chcore::TWin32ErrorFormatter::FormatWin32ErrorCode(m_ulSysError, true);
 
-	// get rid of \r\n at the end of szSystem
-	while(--dwPos && (szSystem[dwPos] == 0x0a || szSystem[dwPos] == 0x0d))
-		szSystem[dwPos]=_T('\0');
-
 	ictranslate::CFormat fmt(strFmt);
 	fmt.SetParam(_t("%filename"), m_strSrcPath);
 	fmt.SetParam(_t("%dstfilename"), m_strDstPath);
-	fmt.SetParam(_t("%reason"), szSystem);
+	fmt.SetParam(_t("%reason"), strError.c_str());
 
 	m_ctlErrorInfo.SetWindowText(fmt);
 
Index: src/ch/StringHelpers.cpp
===================================================================
diff -u -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8 -r387751793d274e49253e796ca7cec4f3d0cf07a9
--- src/ch/StringHelpers.cpp	(.../StringHelpers.cpp)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
+++ src/ch/StringHelpers.cpp	(.../StringHelpers.cpp)	(revision 387751793d274e49253e796ca7cec4f3d0cf07a9)
@@ -25,22 +25,6 @@
 #define new DEBUG_NEW
 #endif
 
-#ifdef _MFC_VER
-void ExpandFormatString(CString* pstrFmt, DWORD dwError)
-{
-	// replace strings %errnum & %errdesc to something else
-	TCHAR xx[_MAX_PATH];
-	pstrFmt->Replace(_T("%errnum"), _itot(dwError, xx, 10));
-	
-	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, xx, _MAX_PATH, NULL);
-
-	while (xx[_tcslen(xx)-1] == _T('\n') || xx[_tcslen(xx)-1] == _T('\r'))
-		xx[_tcslen(xx)-1] = _T('\0');
-
-	pstrFmt->Replace(_T("%errdesc"), xx);
-}
-#endif
-
 LPCTSTR GetSizeString(double dData, LPTSTR pszBuffer, size_t stMaxBufferSize)
 {
 	if (dData < 0.0)
Index: src/ch/StringHelpers.h
===================================================================
diff -u -ra5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8 -r387751793d274e49253e796ca7cec4f3d0cf07a9
--- src/ch/StringHelpers.h	(.../StringHelpers.h)	(revision a5f396da5ed5ffb3fcd9fdf22afb5a7fd07e1ab8)
+++ src/ch/StringHelpers.h	(.../StringHelpers.h)	(revision 387751793d274e49253e796ca7cec4f3d0cf07a9)
@@ -19,11 +19,6 @@
 #ifndef __STRINGHELPERS_H__
 #define __STRINGHELPERS_H__
 
-// formatting routines
-#ifdef _MFC_VER
-void ExpandFormatString(CString* pstrFmt, DWORD dwError);
-#endif
-
 LPCTSTR GetSizeString(double dData, LPTSTR pszBuffer, size_t stMaxBufferSize);
 LPCTSTR GetSizeString(ull_t ullData, LPTSTR pszBuffer, size_t stMaxBufferSize, bool bStrict = false);
 
Index: src/ch/UpdateChecker.cpp
===================================================================
diff -u -r5057e08b0cc064972abeb94a488e5f12d9db14a0 -r387751793d274e49253e796ca7cec4f3d0cf07a9
--- src/ch/UpdateChecker.cpp	(.../UpdateChecker.cpp)	(revision 5057e08b0cc064972abeb94a488e5f12d9db14a0)
+++ src/ch/UpdateChecker.cpp	(.../UpdateChecker.cpp)	(revision 387751793d274e49253e796ca7cec4f3d0cf07a9)
@@ -28,6 +28,7 @@
 #include "../libicpf/cfg.h"
 #include "../libicpf/exception.h"
 #include "../libicpf/circ_buffer.h"
+#include "../libchcore/TWin32ErrorFormatter.h"
 
 // timeout used with waiting for events (avoiding hangs)
 #define FORCE_TIMEOUT 60000
@@ -543,31 +544,14 @@
 // ============================================================================
 void CUpdateChecker::SetResult(ECheckResult eCheckResult, DWORD dwError)
 {
-	CString strError;
-
+	chcore::TString 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();
+		strError = chcore::TWin32ErrorFormatter::FormatWin32ErrorCodeWithFallback(dwError, _T("wininet.dll"), true);
 
-		if(strError.IsEmpty())
-		{
-			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(strError.IsEmpty())
-			strError.Format(_T("0x%lx"), dwError);
-	}
-
-	strError.TrimRight(_T("\r\n \t"));
-
 	::EnterCriticalSection(&m_cs);
 	
 	m_eResult = eCheckResult;
-	m_strLastError = strError;
+	m_strLastError = strError.c_str();
 
 	::LeaveCriticalSection(&m_cs);
 }
Index: src/ch/ch.cpp
===================================================================
diff -u -r607e0afdab47aafcab9f123a31869aa908164ce7 -r387751793d274e49253e796ca7cec4f3d0cf07a9
--- src/ch/ch.cpp	(.../ch.cpp)	(revision 607e0afdab47aafcab9f123a31869aa908164ce7)
+++ src/ch/ch.cpp	(.../ch.cpp)	(revision 387751793d274e49253e796ca7cec4f3d0cf07a9)
@@ -36,6 +36,7 @@
 #include "../libchcore/ISerializerRowData.h"
 #include "../libchcore/TFileInfo.h"
 #include "TMsgBox.h"
+#include "../libchcore/TWin32ErrorFormatter.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -577,14 +578,11 @@
 	if(FAILED(hResult))
 	{
 		// normal failure
-		TCHAR szStr[256];
-		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hResult, 0, szStr, 256, NULL);
-		while(szStr[_tcslen(szStr) - 1] == _T('\n') || szStr[_tcslen(szStr) - 1] == _T('\r') || szStr[_tcslen(szStr) - 1] == _T('.'))
-			szStr[_tcslen(szStr)-1] = _T('\0');
+		chcore::TString strError = chcore::TWin32ErrorFormatter::FormatWin32ErrorCode(hResult, true);
 
 		ictranslate::CFormat fmt(GetResManager().LoadString(IDS_REGISTERERR_STRING));
 		fmt.SetParam(_T("%errno"), (ulong_t)hResult);
-		fmt.SetParam(_T("%errdesc"), szStr);
+		fmt.SetParam(_T("%errdesc"), strError.c_str());
 		AfxMessageBox(fmt, MB_ICONERROR | MB_OK);
 	}
 	else if(hResult == S_FALSE)
@@ -617,14 +615,11 @@
 	}
 	else if(FAILED(hResult))
 	{
-		TCHAR szStr[256];
-		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hResult, 0, szStr, 256, NULL);
-		while (szStr[_tcslen(szStr)-1] == _T('\n') || szStr[_tcslen(szStr)-1] == _T('\r') || szStr[_tcslen(szStr)-1] == _T('.'))
-			szStr[_tcslen(szStr)-1] = _T('\0');
+		chcore::TString strError = chcore::TWin32ErrorFormatter::FormatWin32ErrorCode(hResult, true);
 
 		ictranslate::CFormat fmt(GetResManager().LoadString(IDS_UNREGISTERERR_STRING));
 		fmt.SetParam(_T("%errno"), (ulong_t)hResult);
-		fmt.SetParam(_T("%errdesc"), szStr);
+		fmt.SetParam(_T("%errdesc"), strError.c_str());
 
 		AfxMessageBox(fmt, MB_ICONERROR | MB_OK);
 	}
Index: src/libchcore/TWin32ErrorFormatter.cpp
===================================================================
diff -u
--- src/libchcore/TWin32ErrorFormatter.cpp	(revision 0)
+++ src/libchcore/TWin32ErrorFormatter.cpp	(revision 387751793d274e49253e796ca7cec4f3d0cf07a9)
@@ -0,0 +1,62 @@
+// ============================================================================
+//  Copyright (C) 2001-2015 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.
+// ============================================================================
+#include "stdafx.h"
+#include "TWin32ErrorFormatter.h"
+#include <algorithm>
+
+BEGIN_CHCORE_NAMESPACE
+
+TString TWin32ErrorFormatter::FormatWin32ErrorCode(DWORD dwErrorCode, bool bUseNumberFallback)
+{
+	return FormatWin32ErrorCodeWithModule(dwErrorCode, nullptr, bUseNumberFallback);
+}
+
+TString TWin32ErrorFormatter::FormatWin32ErrorCodeWithFallback(DWORD dwErrorCode, const wchar_t* pszModuleName, bool bUseNumberFallback)
+{
+	TString strError = FormatWin32ErrorCode(dwErrorCode, false);
+	if (strError.IsEmpty())
+		return FormatWin32ErrorCodeWithModule(dwErrorCode, GetModuleHandle(pszModuleName), bUseNumberFallback);
+
+	return strError;
+}
+
+TString TWin32ErrorFormatter::FormatWin32ErrorCodeWithModule(DWORD dwErrorCode, HMODULE hModule, bool bUseNumberFallback)
+{
+	const DWORD dwMaxError = 1024;
+
+	TString strData;
+	wchar_t* pszBuffer = strData.GetBuffer(dwMaxError);
+
+	DWORD dwPos = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, hModule, dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), pszBuffer, dwMaxError - 1, NULL);
+	if (dwPos == 0xffffffff)
+	{
+		int iPos = 0;
+		if (bUseNumberFallback)
+			iPos = _sntprintf_s(pszBuffer, dwMaxError, _TRUNCATE, _T("ErrorCode: 0x%lx"), dwErrorCode);
+		strData.ReleaseBufferSetLength(iPos);
+	}
+	else
+		strData.ReleaseBufferSetLength(std::min(dwPos, dwMaxError - 1));
+
+	strData.TrimRightSelf(_T("\r\n"));
+
+	return strData;
+}
+
+END_CHCORE_NAMESPACE
Index: src/libchcore/TWin32ErrorFormatter.h
===================================================================
diff -u
--- src/libchcore/TWin32ErrorFormatter.h	(revision 0)
+++ src/libchcore/TWin32ErrorFormatter.h	(revision 387751793d274e49253e796ca7cec4f3d0cf07a9)
@@ -0,0 +1,39 @@
+// ============================================================================
+//  Copyright (C) 2001-2015 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.
+// ============================================================================
+#ifndef __TWIN32ERRORFORMATTER_H__
+#define __TWIN32ERRORFORMATTER_H__
+
+#include "libchcore.h"
+#include "TString.h"
+
+BEGIN_CHCORE_NAMESPACE
+
+class LIBCHCORE_API TWin32ErrorFormatter
+{
+public:
+	static TString FormatWin32ErrorCode(DWORD dwErrorCode, bool bUseNumberFallback);
+	static TString FormatWin32ErrorCodeWithFallback(DWORD dwErrorCode, const wchar_t* pszModuleName, bool bUseNumberFallback);
+
+private:
+	static TString FormatWin32ErrorCodeWithModule(DWORD dwErrorCode, HMODULE hModule, bool bUseNumberFallback);
+};
+
+END_CHCORE_NAMESPACE
+
+#endif
Index: src/libchcore/libchcore.vc120.vcxproj
===================================================================
diff -u -rea7d62521e78371cff90579749d136cb928c9e88 -r387751793d274e49253e796ca7cec4f3d0cf07a9
--- src/libchcore/libchcore.vc120.vcxproj	(.../libchcore.vc120.vcxproj)	(revision ea7d62521e78371cff90579749d136cb928c9e88)
+++ src/libchcore/libchcore.vc120.vcxproj	(.../libchcore.vc120.vcxproj)	(revision 387751793d274e49253e796ca7cec4f3d0cf07a9)
@@ -601,6 +601,7 @@
     <ClInclude Include="TTaskDefinition.h" />
     <ClInclude Include="TTaskOperationPlan.h" />
     <ClInclude Include="TTimestampProviderTickCount.h" />
+    <ClInclude Include="TWin32ErrorFormatter.h" />
     <ClInclude Include="TWorkerThreadController.h" />
     <ClInclude Include="libchcore.h" />
     <ClInclude Include="stdafx.h" />
@@ -753,6 +754,7 @@
     <ClCompile Include="TTaskDefinition.cpp" />
     <ClCompile Include="TTaskOperationPlan.cpp" />
     <ClCompile Include="TTimestampProviderTickCount.cpp" />
+    <ClCompile Include="TWin32ErrorFormatter.cpp" />
     <ClCompile Include="TWorkerThreadController.cpp" />
     <ClCompile Include="dllmain.cpp">
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
Index: src/libchcore/libchcore.vc120.vcxproj.filters
===================================================================
diff -u -rea7d62521e78371cff90579749d136cb928c9e88 -r387751793d274e49253e796ca7cec4f3d0cf07a9
--- src/libchcore/libchcore.vc120.vcxproj.filters	(.../libchcore.vc120.vcxproj.filters)	(revision ea7d62521e78371cff90579749d136cb928c9e88)
+++ src/libchcore/libchcore.vc120.vcxproj.filters	(.../libchcore.vc120.vcxproj.filters)	(revision 387751793d274e49253e796ca7cec4f3d0cf07a9)
@@ -362,6 +362,9 @@
     <ClInclude Include="RoundingFunctions.h">
       <Filter>Source Files\Tools</Filter>
     </ClInclude>
+    <ClInclude Include="TWin32ErrorFormatter.h">
+      <Filter>Source Files\Tools</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="TSubTaskArray.cpp">
@@ -658,5 +661,8 @@
     <ClCompile Include="IOverlappedDataBufferQueue.cpp">
       <Filter>Source Files\Tools\OverlappedBuffer</Filter>
     </ClCompile>
+    <ClCompile Include="TWin32ErrorFormatter.cpp">
+      <Filter>Source Files\Tools</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file