Index: src/ch/ch.cpp =================================================================== diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -rbeeac49d2e0888993bd231a4e5863c7f0741e154 --- src/ch/ch.cpp (.../ch.cpp) (revision d5c3edd0d167db9b5d47d04248820fda49499a5e) +++ src/ch/ch.cpp (.../ch.cpp) (revision beeac49d2e0888993bd231a4e5863c7f0741e154) @@ -36,6 +36,8 @@ static char THIS_FILE[] = __FILE__; #endif +icpf::config CCopyHandlerApp::m_config = icpf::config::eIni; + ///////////////////////////////////////////////////////////////////////////// // CCopyHandlerApp @@ -83,12 +85,10 @@ } CCopyHandlerApp::CCopyHandlerApp() : - m_lfLog(), - m_cfgSettings(icpf::config::eIni), - m_piShellExtControl(NULL) + m_piShellExtControl(NULL), + m_hMapObject(NULL), + m_pMainWindow(NULL) { - m_pMainWindow=NULL; - // this is the one-instance application InitProtection(); } @@ -115,29 +115,24 @@ } } -CCopyHandlerApp* GetApp() +CCopyHandlerApp& GetApp() { - return &theApp; + return theApp; } -ictranslate::CResourceManager* GetResManager() +ictranslate::CResourceManager& GetResManager() { - return &theApp.m_resManager; + return ictranslate::CResourceManager::Acquire(); } -chcore::engine_config* GetConfig() +icpf::config& GetConfig() { - return &theApp.m_cfgSettings; + return CCopyHandlerApp::m_config; } -/* -CLogFile* GetLog() -{ - return &theApp.m_lfLog; -}*/ int MsgBox(UINT uiID, UINT nType, UINT nIDHelp) { - return AfxMessageBox(GetResManager()->LoadString(uiID), nType, nIDHelp); + return AfxMessageBox(GetResManager().LoadString(uiID), nType, nIDHelp); } bool CCopyHandlerApp::UpdateHelpPaths() @@ -148,7 +143,7 @@ TCHAR szBuffer[_MAX_PATH]; _tcscpy(szBuffer, _T("\\Help\\")); ExpandPath(szBuffer); - _tcscat(szBuffer, GetResManager()->m_ld.GetHelpName()); + _tcscat(szBuffer, GetResManager().m_ld.GetHelpName()); if(_tcscmp(szBuffer, m_pszHelpFilePath) != 0) { free((void*)m_pszHelpFilePath); @@ -183,7 +178,13 @@ GetLocalTime(&st); TCHAR szName[_MAX_PATH]; - _sntprintf(szName, _MAX_PATH, _T("%s\\ch_crashdump_%hu-%hu-%hu_%hu_%hu_%hu_%hu.dmp"), (PCTSTR)strPath, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); + _sntprintf(szName, _MAX_PATH, _T("%s\\ch_crashdump-%s-%I64u-%s.dmp"), (PCTSTR)strPath, _T(PRODUCT_VERSION), (ull_t)_time64(NULL), +#ifdef _WIN64 + _T("64") +#else + _T("32") +#endif + ); szPath[_MAX_PATH - 1] = _T('\0'); // Step 2 - create the crash dump in case anything happens later @@ -210,107 +211,142 @@ BOOL CCopyHandlerApp::InitInstance() { - // set the exception handler to catch the crash dumps + // ================================= Crash handling ======================================= SetUnhandledExceptionFilter(&MyUnhandledExceptionFilter); - HRESULT hResult = CoInitializeEx(NULL, COINIT_MULTITHREADED); - if(FAILED(hResult)) - AfxMessageBox(_T("Cannot initialize COM, the application will now exit."), MB_ICONERROR | MB_OK); + // ================================= Configuration ======================================== + CString strPath; + CString strCfgPath; + CString strLogPath; - // InitCommonControlsEx() is required on Windows XP if an application - // manifest specifies use of ComCtl32.dll version 6 or later to enable - // visual styles. Otherwise, any window creation will fail. - INITCOMMONCONTROLSEX InitCtrls; - InitCtrls.dwSize = sizeof(InitCtrls); - // Set this to include all the common control classes you want to use - // in your application. - InitCtrls.dwICC = ICC_WIN95_CLASSES; - InitCommonControlsEx(&InitCtrls); + // note that the GetProgramDataPath() below should create a directory; ExpandPath() could + // depend on the directory to be created earlier + if(!GetProgramDataPath(strPath)) + { + AfxMessageBox(_T("Cannot initialize Copy Handler (data path cannot be established)."), MB_ICONERROR | MB_OK); + return FALSE; + } - EnableHtmlHelp(); - //SetHelpMode(afxHTMLHelp); + strCfgPath = strPath + _T("\\ch.ini"); - CWinApp::InitInstance(); + // initialize configuration file + m_config.set_callback(ConfigPropertyChangedCallback, NULL); - m_hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(CSharedConfigStruct), _T("CHLMFile")); - if (m_hMapObject == NULL) - return FALSE; - - // Get a pointer to the file-mapped shared memory. - g_pscsShared=(CSharedConfigStruct*)MapViewOfFile(m_hMapObject, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); - if (g_pscsShared == NULL) - return FALSE; - - // load configuration - m_cfgSettings.set_callback(ConfigPropertyChangedCallback, NULL); - CString strPath; - // note that the GetProgramDataPath() below should create a directory; ExpandPath() could - // depend on the directory to be created earlier - if(GetProgramDataPath(strPath)) + // read the configuration + try { - strPath += _T("\\ch.ini"); - try - { - m_cfgSettings.read(strPath); - } - catch(...) - { - } + m_config.read(strCfgPath); } + catch(...) + { + } // set working dir for the engine - m_cfgSettings.set_base_path(strPath); + icpf::config& rConfig = GetConfig(); + +// rConfig.SetBasePath(strPath); // register all properties - RegisterProperties(&m_cfgSettings); + RegisterProperties(&rConfig); - // set this process class - HANDLE hProcess=GetCurrentProcess(); - ::SetPriorityClass(hProcess, (DWORD)m_cfgSettings.get_signed_num(PP_PPROCESSPRIORITYCLASS)); + // ================================= Logging ======================================== + // initialize the global log file if it is requested by configuration file + strLogPath = strPath + + _T("\\ch.log"); + chcore::TLogger& rLogger = chcore::TLogger::Acquire(); + try + { + rLogger.init(strLogPath, (int_t)m_config.get_signed_num(PP_LOGMAXSIZE), (int_t)rConfig.get_unsigned_num(PP_LOGLEVEL), false, false); + rLogger.Enable(m_config.get_bool(PP_LOGENABLELOGGING)); + } + catch(...) + { + BOOST_ASSERT(false); + } + + LOG_INFO(_T("============================ Initializing Copy Handler ============================")); + LOG_INFO(_T("")); + + // ================================= COM ======================================== + LOG_INFO(_T("Initializing COM")); + + HRESULT hResult = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if(FAILED(hResult)) + { + CString strMsg; + strMsg.Format(_T("Cannot initialize COM, the application will now exit (result = 0x%lx)"), hResult); + + LOG_ERROR(strMsg); + AfxMessageBox(strMsg, MB_ICONERROR | MB_OK); + return FALSE; + } + + // ================================= Resource manager ======================================== + LOG_INFO(_T("Initializing resource manager...")); + + ictranslate::CResourceManager& rResManager = ictranslate::CResourceManager::Acquire(); + // set current language TCHAR szPath[_MAX_PATH]; - m_resManager.Init(AfxGetInstanceHandle()); - m_resManager.SetCallback(ResManCallback); - m_cfgSettings.get_string(PP_PLANGUAGE, szPath, _MAX_PATH); + + rResManager.Init(AfxGetInstanceHandle()); + rResManager.SetCallback(ResManCallback); + rConfig.get_string(PP_PLANGUAGE, szPath, _MAX_PATH); TRACE(_T("Help path=%s\n"), szPath); - if (!m_resManager.SetLanguage(ExpandPath(szPath))) + if(!rResManager.SetLanguage(ExpandPath(szPath))) { TCHAR szData[2048]; _sntprintf(szData, 2048, _T("Couldn't find the language file specified in configuration file:\n%s\nPlease correct this path to point the language file to use.\nProgram will now exit."), szPath); + LOG_ERROR(szData); AfxMessageBox(szData, MB_ICONSTOP | MB_OK); return FALSE; } UpdateHelpPaths(); // for dialogs - ictranslate::CLanguageDialog::SetResManager(&m_resManager); + ictranslate::CLanguageDialog::SetResManager(&rResManager); - // initialize log file - m_cfgSettings.get_string(PP_LOGPATH, szPath, _MAX_PATH); - m_lfLog.init(ExpandPath(szPath), (int_t)m_cfgSettings.get_signed_num(PP_LOGMAXLIMIT), icpf::log_file::level_debug, false, false); + EnableHtmlHelp(); - // TODO: remove unused properties from configuration -/* m_lfLog.EnableLogging(m_cfgManager.GetBoolValue(PP_LOGENABLELOGGING)); - m_lfLog.SetPreciseLimiting(m_cfgManager.GetBoolValue(PP_LOGPRECISELIMITING)); - m_lfLog.SetSizeLimit(m_cfgManager.GetBoolValue(PP_LOGLIMITATION), m_cfgManager.GetIntValue(PP_LOGMAXLIMIT)); - m_lfLog.SetTruncateBufferSize(m_cfgManager.GetIntValue(PP_LOGTRUNCBUFFERSIZE)); - m_lfLog.Init(ExpandPath(szPath), GetResManager());*/ - -#ifndef _DEBUG // for easier writing the program - doesn't collide with std CH - // set "run with system" registry settings - SetAutorun(m_cfgSettings.get_bool(PP_PRELOADAFTERRESTART)); -#endif - + // ================================= Checking for running instances of CH ======================================== // check instance - return false if it's the second one - if (!IsFirstInstance()) + LOG_INFO(_T("Checking for other running instances of Copy Handler")); + if(!IsFirstInstance()) { + LOG_WARNING(_T("Other instance of Copy Handler is already running. Exiting.")); MsgBox(IDS_ONECOPY_STRING); return FALSE; } + // ================================= Common controls ======================================== + LOG_INFO(_T("Initializing GUI common controls")); + + // InitCommonControlsEx() is required on Windows XP if an application + // manifest specifies use of ComCtl32.dll version 6 or later to enable + // visual styles. Otherwise, any window creation will fail. + INITCOMMONCONTROLSEX InitCtrls; + InitCtrls.dwSize = sizeof(InitCtrls); + // Set this to include all the common control classes you want to use + // in your application. + InitCtrls.dwICC = ICC_WIN95_CLASSES; + InitCommonControlsEx(&InitCtrls); + + // ================================= Shell extension ======================================== + LOG_INFO(_T("Initializing shared memory for communication with shell extension")); + + m_hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(CSharedConfigStruct), _T("CHLMFile")); + if (m_hMapObject == NULL) + return FALSE; + + // Get a pointer to the file-mapped shared memory. + g_pscsShared=(CSharedConfigStruct*)MapViewOfFile(m_hMapObject, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); + if (g_pscsShared == NULL) + return FALSE; + + LOG_INFO(_T("Checking shell extension compatibility")); + // calculate ch version - LONG lCHVersion = PRODUCT_VERSION1 << 24 | PRODUCT_VERSION2 << 16 | PRODUCT_VERSION3 << 8 | PRODUCT_VERSION4; + long lCHVersion = PRODUCT_VERSION1 << 24 | PRODUCT_VERSION2 << 16 | PRODUCT_VERSION3 << 8 | PRODUCT_VERSION4; // check the version of shell extension LONG lVersion = 0; @@ -325,6 +361,10 @@ hResult = m_piShellExtControl->SetFlags(eShellExt_Enabled, eShellExt_Enabled); if(FAILED(hResult) || lCHVersion != lVersion) { + CString strMsg; + strMsg.Format(_T("Shell extension has different version (0x%lx) than Copy Handler (0x%lx). Shell extension will be disabled."), lVersion, lCHVersion); + + LOG_WARNING(strMsg); MsgBox(IDS_SHELL_EXTENSION_MISMATCH_STRING); if(m_piShellExtControl) @@ -334,13 +374,30 @@ if(bstrVersion) ::SysFreeString(bstrVersion); + // ================================= Initial settings ======================================== + LOG_INFO(_T("Applying initial settings")); + + // set this process priority class + HANDLE hProcess=GetCurrentProcess(); + ::SetPriorityClass(hProcess, (DWORD)rConfig.get_signed_num(PP_PPROCESSPRIORITYCLASS)); + +#ifndef _DEBUG // for easier writing the program - doesn't collide with std CH + // set "run with system" registry settings + SetAutorun(rConfig.get_bool(PP_PRELOADAFTERRESTART)); +#endif + + // ================================= Main window ======================================== + LOG_INFO(_T("Creating main application window")); // create main window m_pMainWindow=new CMainWnd; if (!((CMainWnd*)m_pMainWindow)->Create()) return FALSE; // will be deleted at destructor m_pMainWnd = m_pMainWindow; + CWinApp::InitInstance(); + LOG_INFO(_T("Copy Handler initialized successfully")); + return TRUE; } @@ -359,12 +416,37 @@ void CCopyHandlerApp::OnConfigNotify(uint_t uiPropID) { // is this language - if(uiPropID == PP_PLANGUAGE) + switch(uiPropID) { - // update language in resource manager - TCHAR szPath[_MAX_PATH]; - m_cfgSettings.get_string(PP_PLANGUAGE, szPath, _MAX_PATH); - m_resManager.SetLanguage(ExpandPath(szPath)); + case PP_PLANGUAGE: + { + // update language in resource manager + TCHAR szPath[_MAX_PATH]; + GetConfig().get_string(PP_PLANGUAGE, szPath, _MAX_PATH); + GetResManager().SetLanguage(ExpandPath(szPath)); + break; + } + case PP_LOGENABLELOGGING: + { + chcore::TLogger& rLogger = chcore::TLogger::Acquire(); + + rLogger.Enable(GetConfig().get_bool(PP_LOGENABLELOGGING)); + break; + } + case PP_LOGLEVEL: + { + chcore::TLogger& rLogger = chcore::TLogger::Acquire(); + + rLogger.set_log_level((int_t)GetConfig().get_unsigned_num(PP_LOGLEVEL)); + break; + } + case PP_LOGMAXSIZE: + { + chcore::TLogger& rLogger = chcore::TLogger::Acquire(); + + rLogger.set_max_size((int_t)GetConfig().get_signed_num(PP_LOGMAXSIZE)); + break; + } } } @@ -378,7 +460,7 @@ } } -HWND CCopyHandlerApp::HHelp(HWND hwndCaller, LPCTSTR pszFile, UINT uCommand, DWORD dwData) +HWND CCopyHandlerApp::HHelp(HWND hwndCaller, LPCTSTR pszFile, UINT uCommand, DWORD_PTR dwData) { PCTSTR pszPath=NULL; WIN32_FIND_DATA wfd; @@ -449,12 +531,17 @@ int CCopyHandlerApp::ExitInstance() { + LOG_INFO(_T("Pre-exit step - releasing shell extension")); if(m_piShellExtControl) { m_piShellExtControl->Release(); m_piShellExtControl = NULL; } + + LOG_INFO(_T("Pre-exit step - uninitializing COM")); CoUninitialize(); + LOG_INFO(_T("============================ Leaving Copy Handler ============================")); + return __super::ExitInstance(); }