Index: src/ch/AsyncHttpFile.cpp =================================================================== diff -u -r50007f112b77cba170e6c427fee5428bda2d9dc5 -r045540c818c374806d09742ef3d7a984d8d757d3 --- src/ch/AsyncHttpFile.cpp (.../AsyncHttpFile.cpp) (revision 50007f112b77cba170e6c427fee5428bda2d9dc5) +++ src/ch/AsyncHttpFile.cpp (.../AsyncHttpFile.cpp) (revision 045540c818c374806d09742ef3d7a984d8d757d3) @@ -33,7 +33,6 @@ CAsyncHttpFile::CAsyncHttpFile() : m_hInternet(NULL), m_hOpenUrl(NULL), - m_dwExpectedState(0), m_hFinishedEvent(NULL), m_dwError(ERROR_SUCCESS) { @@ -86,14 +85,16 @@ m_hFinishedEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); if(!m_hFinishedEvent) { - SetErrorCode(ERROR_INTERNAL_ERROR); + SetErrorCode(GetLastError()); return E_FAIL; } m_hInternet = ::InternetOpen(pszUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC); if(!m_hInternet) { - SetErrorCode(GetLastError()); + DWORD dwError = GetLastError(); + ATLTRACE(L"InternetOpen failed with error: %lu\n", dwError); + SetErrorCode(dwError); ::CloseHandle(m_hFinishedEvent); m_hFinishedEvent = NULL; @@ -103,7 +104,9 @@ if(::InternetSetStatusCallback(m_hInternet, (INTERNET_STATUS_CALLBACK)&CAsyncHttpFile::InternetStatusCallback) == INTERNET_INVALID_STATUS_CALLBACK) { - SetErrorCode(GetLastError()); + DWORD dwError = GetLastError(); + ATLTRACE(L"InternetSetStatusCallback failed with error: %lu\n", dwError); + SetErrorCode(dwError); ::InternetCloseHandle(m_hInternet); ::CloseHandle(m_hFinishedEvent); @@ -112,12 +115,13 @@ return E_FAIL; } - m_dwExpectedState = INTERNET_STATUS_REQUEST_COMPLETE; - HINTERNET hOpenUrl = ::InternetOpenUrl(m_hInternet, pszPath, pszHeaders, (DWORD)-1, INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD, (DWORD_PTR)&m_tOpenRequest); if(!hOpenUrl) { - SetErrorCode(::GetLastError()); + DWORD dwError = GetLastError(); + ATLTRACE(L"InternetOpenUrl failed with error: %lu\n", dwError); + + SetErrorCode(dwError); if(GetErrorCode() != ERROR_IO_PENDING) { ::InternetSetStatusCallback(m_hInternet, NULL); @@ -126,14 +130,12 @@ m_hInternet = NULL; m_hFinishedEvent = NULL; - m_dwExpectedState = 0; return E_FAIL; } } else { - m_dwExpectedState = 0; // everything has been completed ::SetEvent(m_hFinishedEvent); } @@ -194,7 +196,7 @@ if(!::ResetEvent(m_hFinishedEvent)) { - SetErrorCode(ERROR_INTERNAL_ERROR); + SetErrorCode(GetLastError()); return E_FAIL; } @@ -204,13 +206,14 @@ m_internetBuffers.dwBufferTotal = (DWORD)stSize; m_internetBuffers.lpvBuffer = pBuffer; - m_dwExpectedState = INTERNET_STATUS_REQUEST_COMPLETE; - // #WinXP #workaround - in bare WinXP SP3 (i.e. without additional updates), InternetReadFileExW returns // error 120 (not implemented); it was implemented with some later update if(!::InternetReadFileExA(m_hOpenUrl, &m_internetBuffers, IRF_NO_WAIT, (DWORD_PTR)&m_tReadRequest)) { - SetErrorCode(::GetLastError()); + DWORD dwError = GetLastError(); + ATLTRACE(L"InternetReadFileExA failed with error: %lu\n", dwError); + + SetErrorCode(dwError); if(GetErrorCode() == ERROR_IO_PENDING) return S_FALSE; else @@ -219,7 +222,7 @@ if(!::SetEvent(m_hFinishedEvent)) { - SetErrorCode(ERROR_INTERNAL_ERROR); + SetErrorCode(GetLastError()); return E_FAIL; } @@ -258,30 +261,27 @@ SetErrorCode(ERROR_SUCCESS); if(m_hOpenUrl) { - m_dwExpectedState = INTERNET_STATUS_CLOSING_CONNECTION; if(!::InternetCloseHandle(m_hOpenUrl)) { - SetErrorCode(::GetLastError()); + DWORD dwError = GetLastError(); + ATLTRACE(L"InternetCloseHandle failed with error: %lu\n", dwError); + + SetErrorCode(dwError); if(GetErrorCode() == ERROR_IO_PENDING) return S_FALSE; else - { - SetErrorCode(ERROR_INTERNAL_ERROR); return E_FAIL; - } } - // if closing url handle succeeded, we close internet here, if not - // then a separate call to close need to be performed. - m_dwExpectedState = 0; SetUrlHandle(NULL); - if(m_hInternet != nullptr) - { - ::InternetCloseHandle(m_hInternet); - m_hInternet = nullptr; - } } + if(m_hInternet != nullptr) + { + ::InternetCloseHandle(m_hInternet); + m_hInternet = nullptr; + } + if(m_hFinishedEvent) { ::CloseHandle(m_hFinishedEvent); @@ -322,7 +322,10 @@ DWORD dwEffect = WaitForMultipleObjects(2, hHandles, FALSE, FORCE_TIMEOUT); if(dwEffect == 0xffffffff) { - SetErrorCode(::GetLastError()); + DWORD dwError = GetLastError(); + ATLTRACE(L"WaitForMultipleObjects failed with error: %lu\n", dwError); + + SetErrorCode(dwError); return CAsyncHttpFile::eError; } else if(dwEffect == WAIT_OBJECT_0 + 0 || dwEffect == WAIT_ABANDONED_0 + 0) @@ -354,13 +357,16 @@ CString strMsg; strMsg.Format(_T("[CAsyncHttpFile::InternetStatusCallback] hInternet: %p, dwContext: %Iu (operation: %lu), dwInternetStatus: %lu, lpvStatusInformation: %p, dwStatusInformationLength: %lu\n"), hInternet, (size_t)dwContext, pRequest ? pRequest->eOperationType : CONTEXT_REQUEST::eNone, dwInternetStatus, lpvStatusInformation, dwStatusInformationLength); + ATLTRACE(L"%s\n", strMsg); LOG_DEBUG(strMsg); switch(dwInternetStatus) { case INTERNET_STATUS_HANDLE_CREATED: { INTERNET_ASYNC_RESULT* pRes = (INTERNET_ASYNC_RESULT*)lpvStatusInformation; + ATLTRACE(L"INTERNET_STATUS_HANDLE_CREATED error code: %lu\n", pRes->dwError); + pRequest->pHttpFile->SetUrlHandle((HINTERNET)(pRes->dwResult)); break; } @@ -372,6 +378,7 @@ case INTERNET_STATUS_REQUEST_COMPLETE: { INTERNET_ASYNC_RESULT* pResult = (INTERNET_ASYNC_RESULT*)lpvStatusInformation; + ATLTRACE(L"INTERNET_STATUS_REQUEST_COMPLETE error code: %lu\n", pResult->dwError); pRequest->pHttpFile->SetErrorCode(pResult->dwError); break; } @@ -384,6 +391,7 @@ { break; } + default: TRACE(_T("[CAsyncHttpFile::InternetStatusCallback()] Unhandled status: %lu\n"), dwInternetStatus); } @@ -413,6 +421,8 @@ // ============================================================================ void CAsyncHttpFile::SetErrorCode(DWORD dwError) { + ATLTRACE(L"Setting error code : %lu\n", dwError); + m_dwError = dwError; } @@ -429,7 +439,7 @@ if(!m_hFinishedEvent) return E_FAIL; - if(dwCurrentState == m_dwExpectedState || dwCurrentState == INTERNET_STATUS_CLOSING_CONNECTION) + if(dwCurrentState == INTERNET_STATUS_REQUEST_COMPLETE) return ::SetEvent(m_hFinishedEvent) ? S_OK : E_FAIL; return S_FALSE; } Index: src/ch/AsyncHttpFile.h =================================================================== diff -u -r50007f112b77cba170e6c427fee5428bda2d9dc5 -r045540c818c374806d09742ef3d7a984d8d757d3 --- src/ch/AsyncHttpFile.h (.../AsyncHttpFile.h) (revision 50007f112b77cba170e6c427fee5428bda2d9dc5) +++ src/ch/AsyncHttpFile.h (.../AsyncHttpFile.h) (revision 045540c818c374806d09742ef3d7a984d8d757d3) @@ -87,7 +87,6 @@ HINTERNET m_hInternet; HINTERNET m_hOpenUrl; - DWORD m_dwExpectedState; ///< State we are expecting HANDLE m_hFinishedEvent; INTERNET_BUFFERSA m_internetBuffers; Index: src/ch/CfgProperties.h =================================================================== diff -u -rbe569bc86280887eeebb8d3e9489f6fc17c570e6 -r045540c818c374806d09742ef3d7a984d8d757d3 --- src/ch/CfgProperties.h (.../CfgProperties.h) (revision be569bc86280887eeebb8d3e9489f6fc17c570e6) +++ src/ch/CfgProperties.h (.../CfgProperties.h) (revision 045540c818c374806d09742ef3d7a984d8d757d3) @@ -32,8 +32,11 @@ PP_PCLIPBOARDMONITORING = 0, PP_PMONITORSCANINTERVAL, PP_PRELOADAFTERRESTART, + PP_PCHECK_FOR_UPDATES_FREQUENCY, PP_PUPDATECHANNEL, + PP_PUPDATE_USE_SECURE_CONNECTION, + PP_PSHUTDOWNAFTREFINISHED, PP_PTIMEBEFORESHUTDOWN, PP_PFORCESHUTDOWN, @@ -130,6 +133,13 @@ eDNS_HideAndDontRegister = 2 }; +enum EUseSecureConnection +{ + eSecure_No = 0, + eSecure_Yes = 1, + eSecure_Auto = 2 +}; + /////////////////////////////////////////////////////////////////////////////////////////////// // specific branches in configuration @@ -181,6 +191,7 @@ PROPERTY_MINMAX(PP_PCHECK_FOR_UPDATES_FREQUENCY, unsigned int, _T("CHConfig.General.Program.Updates.Frequency"), eFreq_Weekly, eFreq_Never, eFreq_Max - 1); PROPERTY_MINMAX(PP_PUPDATECHANNEL, int, _T("CHConfig.General.Program.Updates.UpdateChannel"), UpdateVersionInfo::eReleaseCandidate, UpdateVersionInfo::eStable, UpdateVersionInfo::eMax - 1); +PROPERTY_MINMAX(PP_PUPDATE_USE_SECURE_CONNECTION, unsigned int, _T("CHConfig.General.Program.Updates.UseSecureConnection"), eSecure_Auto, eSecure_No, eSecure_Auto); PROPERTY(PP_PPROCESSPRIORITYCLASS, int, _T("CHConfig.General.Program.ProcessPriority"), NORMAL_PRIORITY_CLASS); PROPERTY(PP_PLANGUAGE, CString, _T("CHConfig.General.Program.Language"), _T("\\Langs\\English.lng")); Index: src/ch/OptionsDlg.cpp =================================================================== diff -u -rbe569bc86280887eeebb8d3e9489f6fc17c570e6 -r045540c818c374806d09742ef3d7a984d8d757d3 --- src/ch/OptionsDlg.cpp (.../OptionsDlg.cpp) (revision be569bc86280887eeebb8d3e9489f6fc17c570e6) +++ src/ch/OptionsDlg.cpp (.../OptionsDlg.cpp) (revision 045540c818c374806d09742ef3d7a984d8d757d3) @@ -215,8 +215,11 @@ PROP_BOOL(IDS_CLIPBOARDMONITORING_STRING, GetPropValue(GetConfig())); PROP_UINT(IDS_CLIPBOARDINTERVAL_STRING, GetPropValue(GetConfig())); PROP_BOOL(IDS_AUTORUNPROGRAM_STRING, GetPropValue(GetConfig())); + PROP_COMBO(IDS_CFG_CHECK_FOR_UPDATES_FREQUENCY, IDS_UPDATE_FREQUENCIES, GetPropValue(GetConfig())); PROP_COMBO(IDS_CFG_UPDATECHANNEL, IDS_CFGUPDATECHANNELITEMS_STRING, GetPropValue(GetConfig())); + PROP_COMBO(IDS_CFG_USE_SECURE_CONNECTION, IDS_SECURE_CONNECTION_TYPES, GetPropValue(GetConfig())); + PROP_BOOL(IDS_AUTOSHUTDOWN_STRING, GetPropValue(GetConfig())); PROP_UINT(IDS_SHUTDOWNTIME_STRING, GetPropValue(GetConfig())); PROP_COMBO(IDS_FORCESHUTDOWN_STRING, IDS_FORCESHUTDOWNVALUES_STRING, GetPropValue(GetConfig()) ? 1 : 0); @@ -330,8 +333,11 @@ SetPropValue(rConfig, GetBoolProp(iPosition++)); SetPropValue(rConfig, GetUintProp(iPosition++)); SetPropValue(rConfig, GetBoolProp(iPosition++)); + SetPropValue(rConfig, GetIndexProp(iPosition++)); SetPropValue(rConfig, GetBoolProp(iPosition++)); + SetPropValue(rConfig, GetIndexProp(iPosition++)); + SetPropValue(rConfig, GetBoolProp(iPosition++)); SetPropValue(rConfig, GetUintProp(iPosition++)); SetPropValue(rConfig, GetBoolProp(iPosition++)); Index: src/ch/UpdateChecker.cpp =================================================================== diff -u -r50007f112b77cba170e6c427fee5428bda2d9dc5 -r045540c818c374806d09742ef3d7a984d8d757d3 --- src/ch/UpdateChecker.cpp (.../UpdateChecker.cpp) (revision 50007f112b77cba170e6c427fee5428bda2d9dc5) +++ src/ch/UpdateChecker.cpp (.../UpdateChecker.cpp) (revision 045540c818c374806d09742ef3d7a984d8d757d3) @@ -263,9 +263,6 @@ // mark as started pUpdateChecker->SetResult(eResult_Pending, 0); - // get the real address of file to download - CString strSite = pUpdateChecker->GetSiteAddress(); - CAsyncHttpFile::EWaitResult eWaitResult = CAsyncHttpFile::ePending; size_t stFileSize = 0; std::stringstream dataBuffer; @@ -276,6 +273,9 @@ if(pUpdateChecker->GetSendHeaders()) wstrHeaders = pUpdateChecker->m_tUpdateHeaders.GetHeaders((PCTSTR)pUpdateChecker->m_strLanguage, pUpdateChecker->m_eUpdateChannel); + // get the real address of file to download + CString strSite = pUpdateChecker->GetSiteAddress(); + HRESULT hResult = pUpdateChecker->m_httpFile.Open(strSite, wstrUserAgent.c_str(), wstrHeaders.c_str()); if(SUCCEEDED(hResult)) { @@ -284,16 +284,22 @@ { case CAsyncHttpFile::eFinished: break; + case CAsyncHttpFile::eKilled: pUpdateChecker->SetResult(eResult_Killed, 0); + pUpdateChecker->m_httpFile.Close(); return 1; + case CAsyncHttpFile::eError: pUpdateChecker->SetResult(eResult_Error, pUpdateChecker->m_httpFile.GetErrorCode()); + pUpdateChecker->m_httpFile.Close(); return 1; + case CAsyncHttpFile::eTimeout: case CAsyncHttpFile::ePending: default: pUpdateChecker->SetResult(eResult_Error, 0); + pUpdateChecker->m_httpFile.Close(); return 1; } @@ -317,15 +323,19 @@ break; case CAsyncHttpFile::eKilled: pUpdateChecker->SetResult(eResult_Killed, 0); + pUpdateChecker->m_httpFile.Close(); return 1; - break; + case CAsyncHttpFile::eError: pUpdateChecker->SetResult(eResult_Error, pUpdateChecker->m_httpFile.GetErrorCode()); + pUpdateChecker->m_httpFile.Close(); return 1; + case CAsyncHttpFile::eTimeout: case CAsyncHttpFile::ePending: default: pUpdateChecker->SetResult(eResult_Error, 0); + pUpdateChecker->m_httpFile.Close(); return 1; } } @@ -346,6 +356,7 @@ if(FAILED(hResult)) { pUpdateChecker->SetResult(eResult_Error, pUpdateChecker->m_httpFile.GetErrorCode()); + pUpdateChecker->m_httpFile.Close(); return 1; } Index: src/ch/UpdaterDlg.cpp =================================================================== diff -u -r50007f112b77cba170e6c427fee5428bda2d9dc5 -r045540c818c374806d09742ef3d7a984d8d757d3 --- src/ch/UpdaterDlg.cpp (.../UpdaterDlg.cpp) (revision 50007f112b77cba170e6c427fee5428bda2d9dc5) +++ src/ch/UpdaterDlg.cpp (.../UpdaterDlg.cpp) (revision 045540c818c374806d09742ef3d7a984d8d757d3) @@ -340,13 +340,37 @@ EnableUpdateRelatedControls(false); m_eLastState = CUpdateChecker::eResult_Undefined; - bool bIsWinXP = WindowsVersion::IsWindowsXP(); + CString strSite; - CString strSite = _T(UPDATE_CHECK_LINK_SECURE); - if(bIsWinXP) + EUseSecureConnection eUseSecureConnection = (EUseSecureConnection)GetPropValue(GetConfig()); + switch(eUseSecureConnection) + { + case eSecure_No: strSite = _T(UPDATE_CHECK_LINK_NONSECURE); + break; - m_ucChecker.AsyncCheckForUpdates(strSite, GetPropValue(GetConfig()), (UpdateVersionInfo::EVersionType)GetPropValue(GetConfig()), m_bBackgroundMode, !bIsWinXP); + case eSecure_Yes: + strSite = _T(UPDATE_CHECK_LINK_SECURE); + break; + + case eSecure_Auto: + default: + { + bool bUseSecureConnection = WindowsVersion::IsWindows7Or2008R2OrGreater(); + if(bUseSecureConnection) + strSite = _T(UPDATE_CHECK_LINK_SECURE); + else + strSite = _T(UPDATE_CHECK_LINK_NONSECURE); + + break; + } + } + + m_ucChecker.AsyncCheckForUpdates(strSite, + GetPropValue(GetConfig()), + (UpdateVersionInfo::EVersionType)GetPropValue(GetConfig()), + m_bBackgroundMode, + !WindowsVersion::IsWindowsXP()); } void CUpdaterDlg::EnableUpdateRelatedControls(bool bEnable) Index: src/ch/WindowsVersion.cpp =================================================================== diff -u -r50007f112b77cba170e6c427fee5428bda2d9dc5 -r045540c818c374806d09742ef3d7a984d8d757d3 --- src/ch/WindowsVersion.cpp (.../WindowsVersion.cpp) (revision 50007f112b77cba170e6c427fee5428bda2d9dc5) +++ src/ch/WindowsVersion.cpp (.../WindowsVersion.cpp) (revision 045540c818c374806d09742ef3d7a984d8d757d3) @@ -84,6 +84,23 @@ return ovi.dwMinorVersion == 2 && ovi.wProductType == VER_NT_WORKSTATION && si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; } +bool WindowsVersion::IsWindows7Or2008R2OrGreater() +{ + OSVERSIONINFOEX ovi = { 0 }; + ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + if(!GetVersionEx((OSVERSIONINFO*)&ovi)) + return false; + + if(ovi.dwMajorVersion != 6) + return ovi.dwMajorVersion > 6; + + if(ovi.dwMinorVersion >= 1) + return true; + + return false; +} + void WindowsVersion::UpdateCachedData() { if(m_bCacheFilled) Index: src/ch/WindowsVersion.h =================================================================== diff -u -r50007f112b77cba170e6c427fee5428bda2d9dc5 -r045540c818c374806d09742ef3d7a984d8d757d3 --- src/ch/WindowsVersion.h (.../WindowsVersion.h) (revision 50007f112b77cba170e6c427fee5428bda2d9dc5) +++ src/ch/WindowsVersion.h (.../WindowsVersion.h) (revision 045540c818c374806d09742ef3d7a984d8d757d3) @@ -31,6 +31,7 @@ std::wstring GetCpuArch(); static bool IsWindowsXP(); + static bool IsWindows7Or2008R2OrGreater(); private: void UpdateCachedData(); Index: src/ch/ch.rc =================================================================== diff -u -r17518cb4e2c229cb291fc23e58d74c9d9d8c658a -r045540c818c374806d09742ef3d7a984d8d757d3 --- src/ch/ch.rc (.../ch.rc) (revision 17518cb4e2c229cb291fc23e58d74c9d9d8c658a) +++ src/ch/ch.rc (.../ch.rc) (revision 045540c818c374806d09742ef3d7a984d8d757d3) @@ -846,10 +846,12 @@ "Intercept standard Windows operations (experimental/not recommended)" IDS_CFG_CHECK_FOR_UPDATES_FREQUENCY "Check for program updates" IDS_CFG_UPDATECHANNEL "Update channel" + IDS_CFG_USE_SECURE_CONNECTION "Use secure connection when checking for updates" IDS_CFGLOGLEVEL "Log level" IDS_CFGLOGLEVEL_VALUES "Debug!Info!Warning!Error" - IDS_UPDATE_FREQUENCIES "Never!Every startup!Daily!Weekly!Once every 2 weeks!Monthly!Quarterly" - IDS_BUFFER_QUEUE_DEPTH "Buffer queue depth" + IDS_UPDATE_FREQUENCIES "Never!Every startup!Daily!Weekly!Once every 2 weeks!Monthly!Quarterly" + IDS_SECURE_CONNECTION_TYPES "No!Yes!Auto" + IDS_BUFFER_QUEUE_DEPTH "Buffer queue depth" IDS_FASTMOVEBEFOREBLOCK_STRING "Use fast move before blocking" END Index: src/ch/langs/polish.lng =================================================================== diff -u -r17518cb4e2c229cb291fc23e58d74c9d9d8c658a -r045540c818c374806d09742ef3d7a984d8d757d3 Binary files differ Index: src/ch/resource.h =================================================================== diff -u -rd4064fca634707dcae112e5a41ed37e04455dc2a -r045540c818c374806d09742ef3d7a984d8d757d3 --- src/ch/resource.h (.../resource.h) (revision d4064fca634707dcae112e5a41ed37e04455dc2a) +++ src/ch/resource.h (.../resource.h) (revision 045540c818c374806d09742ef3d7a984d8d757d3) @@ -526,6 +526,8 @@ #define IDS_UPDATE_FREQUENCIES 8101 #define IDS_BUFFER_QUEUE_DEPTH 8102 #define IDS_FASTMOVEBEFOREBLOCK_STRING 8103 +#define IDS_CFG_USE_SECURE_CONNECTION 8104 +#define IDS_SECURE_CONNECTION_TYPES 8105 #define IDS_MENUCOPY_STRING 9000 #define IDS_MENUMOVE_STRING 9001 #define IDS_MENUCOPYMOVESPECIAL_STRING 9002 Index: src/libchcore/TWin32ErrorFormatter.cpp =================================================================== diff -u -re96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3 -r045540c818c374806d09742ef3d7a984d8d757d3 --- src/libchcore/TWin32ErrorFormatter.cpp (.../TWin32ErrorFormatter.cpp) (revision e96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3) +++ src/libchcore/TWin32ErrorFormatter.cpp (.../TWin32ErrorFormatter.cpp) (revision 045540c818c374806d09742ef3d7a984d8d757d3) @@ -43,7 +43,7 @@ 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); + DWORD dwPos = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, hModule, dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), pszBuffer, dwMaxError - 1, NULL); if (dwPos == 0xffffffff) { int iPos = 0;