int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT) { CMessageLoop theLoop; _Module.AddMessageLoop(&theLoop); CMainFrame& wndMain = CMainFrame::Instance(); if(wndMain.CreateEx() == NULL) { ATLTRACE(_T("Main window creation failed!\n")); return 0; } _Module.Lock(); wndMain.ShowWindow(nCmdShow); int nRet = theLoop.Run(); _Module.RemoveMessageLoop(); return nRet; }
DWORD __stdcall FactoryThreadProc(LPVOID pv) { HRESULT hr; HANDLE hShutdownEvent = (HANDLE)pv; hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); ATLASSERT(SUCCEEDED(hr)); hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE); ATLASSERT(SUCCEEDED(hr)); DWORD dwRet = WaitForSingleObject(hShutdownEvent, INFINITE); ATLASSERT(dwRet == WAIT_OBJECT_0); hr = _Module.RevokeClassObjects(); ATLASSERT(SUCCEEDED(hr)); CoUninitialize(); return 0; }
int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT) { CMessageLoop theLoop; _Module.AddMessageLoop(&theLoop); [!output WTL_MAINDLG_CLASS] dlgMain; if(dlgMain.Create(NULL) == NULL) { ATLTRACE(_T("Main dialog creation failed!\n")); return 0; } [!if WTL_COM_SERVER] _Module.Lock(); [!endif] dlgMain.ShowWindow(nCmdShow); int nRet = theLoop.Run(); _Module.RemoveMessageLoop(); return nRet; }
LONG WINAPI GenerateDump(EXCEPTION_POINTERS* pExceptionPointers) { BOOL bMiniDumpSuccessful; HANDLE hDumpFile; SYSTEMTIME stLocalTime; MINIDUMP_EXCEPTION_INFORMATION ExpParam; GetLocalTime( &stLocalTime ); TCHAR strExePath[MAX_PATH]; ::GetModuleFileName(_Module.GetModuleInstance(), strExePath, MAX_PATH); ::PathRemoveFileSpec(strExePath); // 以前のダンプファイルを削除する MTL::MtlForEachFile(strExePath, [](const CString& strPath) { if (Misc::GetFileExt(strPath) == _T("dmp")) ::DeleteFile(strPath); }); TCHAR strDmpFilePath[MAX_PATH]; StringCchPrintf(strDmpFilePath, MAX_PATH, _T("%s\\%s-%s %04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp"), strExePath, app::cnt_AppName, app::cnt_AppVersion, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, GetCurrentProcessId(), GetCurrentThreadId()); hDumpFile = CreateFile(strDmpFilePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); ExpParam.ThreadId = GetCurrentThreadId(); ExpParam.ExceptionPointers = pExceptionPointers; ExpParam.ClientPointers = TRUE; bMiniDumpSuccessful = funcMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL); CloseHandle(hDumpFile); enum { STATUS_INSUFFICIENT_MEM = 0xE0000001 }; CString strError = _T("例外が発生しました。\n例外:"); switch (pExceptionPointers->ExceptionRecord->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: strError += _T("スレッドが適切なアクセス権を持たない仮想アドレスに対して、読み取りまたは書き込みを試みました。"); break; case EXCEPTION_FLT_DIVIDE_BY_ZERO: case EXCEPTION_INT_DIVIDE_BY_ZERO: strError += _T(" 0 で除算しようとしました。"); break; case EXCEPTION_INT_OVERFLOW: strError += _T("整数演算結果の最上位ビットが繰り上がりました。"); break; case EXCEPTION_STACK_OVERFLOW: strError += _T("スタックオーバーフローしました。"); break; case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: strError += _T("スレッドが範囲外の配列要素にアクセスしようとしました。使用中のハードウェアは境界チェックをサポートしています。"); break; case STATUS_INSUFFICIENT_MEM: strError += _T("メモリが不足しています。"); break; default: strError += _T("その他の例外が発生しました。"); break; }; MessageBox(NULL, strError, NULL, MB_ICONERROR); return EXCEPTION_CONTINUE_SEARCH; }
int RunWinMain(HINSTANCE hInstance, LPTSTR lpstrCmdLine, int nCmdShow) { // DLL攻撃対策 SetDllDirectory(_T("")); #if 0 #if defined (_DEBUG) && defined(_CRTDBG_MAP_ALLOC) //メモリリーク検出用 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_ALWAYS_DF ); //_CrtSetBreakAlloc(874); #endif #endif #if defined (_DEBUG) && defined(_CRTDBG_MAP_ALLOC) _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif #ifdef _DEBUG // ATLTRACEで日本語を使うために必要 _tsetlocale( LC_ALL, _T("japanese") ); #endif Misc::setHeapAllocLowFlagmentationMode(); //+++ // 設定ファイルのフルパスを取得する MtlIniFileNameInit(g_szIniFileName, MAX_PATH); // 複数起動の確認 if (CheckOneInstance(lpstrCmdLine)) return 0; g_pMainWnd = NULL; // HRESULT hRes = ::CoInitialize(NULL); HRESULT hRes = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // ATLASSERT( SUCCEEDED(hRes) ); // If you are running on NT 4.0 or higher you can use the following call instead to // make the EXE free threaded. This means that calls come in on a random RPC thread // HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); hRes = ::OleInitialize(NULL); ATLASSERT( SUCCEEDED(hRes) ); ATLTRACE(_T("tWinMain\n") _T("CommandLine : %s\n"), lpstrCmdLine); /* コモンコントロールを初期化 */ INITCOMMONCONTROLSEX iccx; iccx.dwSize = sizeof (iccx); iccx.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_USEREX_CLASSES; int ret = ::InitCommonControlsEx(&iccx); ATLASSERT(ret); hRes = _Module.Init(ObjectMap, hInstance, &LIBID_ATLLib); //hRes = _Module.Init(NULL, hInstance); ATLASSERT( SUCCEEDED(hRes) ); int nRet = 0; bool bRun = true; bool bAutomation = false; bool bTray = false; bool bRet = _PrivateInit(); if (!bRet) { ErrorLogPrintf(_T("_PrivateInitでエラー\n")); nRet = -1; } // Init CEF CefSettings settings; settings.multi_threaded_message_loop = true; std::wstring strCachePath = CMainOption::s_strCacheFolderPath; if (strCachePath.empty()) { strCachePath = static_cast<LPCWSTR>(Misc::GetExeDirectory() + _T("cache")); } CefString(&settings.cache_path).FromWString(strCachePath); CefString(&settings.locale).FromWString(std::wstring(L"ja")); //settings.auto_detect_proxy_settings_enabled = true; ATLVERIFY(CefInitialize(settings, nullptr)); if (nRet < 0) goto END_APP; // ActiveXコントロールをホストするための準備 //AtlAxWinInit(); // コマンドライン入力によってはCOMサーバー登録及び解除を行う nRet = RegisterCOMServer(nRet, bRun, bAutomation, bTray); if (FAILED(nRet)) { ErrorLogPrintf(_T("RegisterCOMServerでエラー\n")); nRet = -1; goto END_APP; } CDonutSimpleEventManager::RaiseEvent(EVENT_PROCESS_START); if (bRun) { _Module.StartMonitor(); hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED); ATLASSERT( SUCCEEDED(hRes) ); hRes = ::CoResumeClassObjects(); ATLASSERT( SUCCEEDED(hRes) ); if (bAutomation) { CMessageLoop theLoop; nRet = theLoop.Run(); } else { //+++ 起動時の環境ファイルチェック. unDonut.iniがなく // 環境ファイルが足りてなかったら起動ページをabout:warningにする. if (lpstrCmdLine == 0 || lpstrCmdLine[0] == 0) { if (HaveEnvFiles() == false) lpstrCmdLine = _T("about:warning"); } //\\nRet = Run(lpstrCmdLine, nCmdShow, bTray); //nRet = MultiThreadManager::Run(lpstrCmdLine, nCmdShow, bTray); //int nRet = 0; { CMessageLoop theLoop; _Module.AddMessageLoop(&theLoop); CMainFrame wndMain; if (wndMain.CreateEx() == NULL) { ATLTRACE( _T("Main window creation failed!\n") ); return 0; } // load windowplacement wndMain.startupMainFrameStayle(nCmdShow, /*bTray*/false); _Module.Lock(); if (CStartUpOption::s_dwParam) CStartUpOption::StartUp(wndMain); if (lpstrCmdLine && lpstrCmdLine[0] != _T('\0')) CommandLineArg(wndMain, lpstrCmdLine); wndMain.SetAutoBackUp(); //自動更新するなら、開始. // 実際のメインループ. nRet = theLoop.Run(); _Module.RemoveMessageLoop(); } } #if 1 //+++ WTLのメイン窓クローズが正常終了時に、終了コードとして1を返す... //+++ OSに返す値なので0のほうがよいはずで、 //+++ donutの他の部分では0にしているようなので //+++ しかたないので、強制的に変換. if (nRet == 1) nRet = 0; #endif _Module.RevokeClassObjects(); ::Sleep(_Module.m_dwPause); } //_PrivateTerm(); ATLTRACE(_T("正常終了しました。\n")); END_APP: _Module.Term(); ::OleUninitialize(); ::CoUninitialize(); // Shut down CEF. DWORD dwTime = ::timeGetTime(); boost::thread terminateWatch([dwTime]() { while (dwTime + (5 * 1000) > ::timeGetTime()) { if (g_bSefShutDown) return ; ::Sleep(0); } if (g_bSefShutDown == false) ExitProcess(-5); }); CefShutdown(); g_bSefShutDown = true; CDonutSimpleEventManager::RaiseEvent(EVENT_PROCESS_END); return nRet; }
// コマンドライン引数からCOMサーバー登録/削除を行う static int RegisterCOMServer(int &nRet, bool &bRun, bool &bAutomation, bool &bTray) { HRESULT hRes; TCHAR szTokens[] = _T("-/"); LPCTSTR lpszToken = _Module.FindOneOf(::GetCommandLine(), szTokens); while (lpszToken) { CString strToken = Misc::GetStrWord(lpszToken, &lpszToken); if (strToken.CompareNoCase(_T("UnregServer") ) == 0) { nRet = _Module.UnregisterServer(); nRet = UnRegisterCLSIDInCategory(CLSID_API, CATID_SafeForInitializing); if ( FAILED(nRet) ) return nRet; nRet = UnRegisterCLSIDInCategory(CLSID_API, CATID_SafeForScripting); if ( FAILED(nRet) ) return nRet; ::MessageBox(NULL, _T("COMサーバー削除しました。"), _T("unDonut"), 0); bRun = false; break; } else if (strToken.CompareNoCase(_T("RegServer") ) == 0) { nRet = _Module.RegisterServer(TRUE, &CLSID_API); if (nRet == S_OK) { // Mark the control as safe for initializing. hRes = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data"); if ( FAILED(hRes) ) return hRes; hRes = RegisterCLSIDInCategory(CLSID_API, CATID_SafeForInitializing); if ( FAILED(hRes) ) return hRes; // Mark the control as safe for scripting. hRes = CreateComponentCategory(CATID_SafeForScripting, L"Controls that are safely scriptable"); if ( FAILED(hRes) ) return hRes; hRes = RegisterCLSIDInCategory(CLSID_API, CATID_SafeForScripting); if ( FAILED(hRes) ) return hRes; ::MessageBox(NULL, _T("COMサーバー登録しました。"), _T("unDonut"), 0); } else ::MessageBox(NULL, _T("COMサーバー登録失敗しました。"), _T("unDonut"), 0); bRun = false; break; } else if (strToken.CompareNoCase(_T("Automation")) == 0 || (strToken.CompareNoCase(_T("Embedding" )) == 0) ) { bAutomation = true; break; #if 1 //+++ } else if (strToken.CompareNoCase(_T("tray") ) == 0) { bTray = true; break; #endif } lpszToken = _Module.FindOneOf(lpszToken, szTokens); } return S_OK; }
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) { HRESULT hRes = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); ATLASSERT(SUCCEEDED(hRes)); #if (_WIN32_IE >= 0x0300) INITCOMMONCONTROLSEX iccx; iccx.dwSize = sizeof(iccx); iccx.dwICC = ICC_BAR_CLASSES; // change to support other controls BOOL bRet = ::InitCommonControlsEx(&iccx); bRet; ATLASSERT(bRet); #else ::InitCommonControls(); #endif hRes = _Module.Init(ObjectMap, hInstance); ATLASSERT(SUCCEEDED(hRes)); int nRet = 0; TCHAR szTokens[] = _T("-/"); bool bRun = true; bool bAutomation = false; LPCTSTR lpszToken = _Module.FindOneOf(::GetCommandLine(), szTokens); while(lpszToken != NULL) { if(lstrcmpi(lpszToken, _T("UnregServer")) == 0) { _Module.UpdateRegistryFromResource(IDR_DP, FALSE); nRet = _Module.UnregisterServer(TRUE); bRun = false; break; } else if(lstrcmpi(lpszToken, _T("RegServer")) == 0) { // Already registered... bRun = false; break; } else if((lstrcmpi(lpszToken, _T("Automation")) == 0) || (lstrcmpi(lpszToken, _T("Embedding")) == 0)) { bAutomation = true; break; } lpszToken = _Module.FindOneOf(lpszToken, szTokens); } if(bRun) { if(!bAutomation && CSingleInstance::Instance().IsAlreadyRunning()) { // Only attempt this if manually started, i.e. allow automation // clients to start multiple instances, for what it's worth if(!CSingleInstance::Instance().ActivateRunningInstance()) { MessageBox(NULL, _T("Failed to activate running instance of Developer Playground.\nPlease use Task Manager or similar to terminate rogue DP processes."), _T("DP Error"), MB_OK); } } else { if(!bAutomation) { // Auto-register self at startup, if manually started _Module.UpdateRegistryFromResource(IDR_DP, TRUE); nRet = _Module.RegisterServer(TRUE); } DWORD dwThreadId = 0; SmartHandle hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); SmartHandle hThread = CreateThread(NULL, 0, FactoryThreadProc, hEvent, 0, &dwThreadId); _Module.StartMonitor(); if(bAutomation) { CMessageLoop theLoop; nRet = theLoop.Run(); } else { nRet = Run(lpstrCmdLine, nCmdShow); } SetEvent(hEvent); ::Sleep(_Module.m_dwPause); } } _Module.Term(); ::CoUninitialize(); return nRet; }