int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { LPTSTR cmdLine = ::GetCommandLine(); ParamVector params; parseCommandLine(cmdLine, params); MiniDumper mdump; //for debugging purposes. bool TheFirstOne = true; ::SetLastError(NO_ERROR); ::CreateMutex(NULL, false, TEXT("nppInstance")); if (::GetLastError() == ERROR_ALREADY_EXISTS) TheFirstOne = false; bool isParamePresent; bool showHelp = isInList(FLAG_HELP, params); bool isMultiInst = isInList(FLAG_MULTI_INSTANCE, params); CmdLineParams cmdLineParams; cmdLineParams._isNoTab = isInList(FLAG_NOTABBAR, params); cmdLineParams._isNoPlugin = isInList(FLAG_NO_PLUGIN, params); cmdLineParams._isReadOnly = isInList(FLAG_READONLY, params); cmdLineParams._isNoSession = isInList(FLAG_NOSESSION, params); cmdLineParams._isPreLaunch = isInList(FLAG_SYSTRAY, params); cmdLineParams._alwaysOnTop = isInList(FLAG_ALWAYS_ON_TOP, params); cmdLineParams._showLoadingTime = isInList(FLAG_LOADINGTIME, params); cmdLineParams._isSessionFile = isInList(FLAG_OPENSESSIONFILE, params); cmdLineParams._isRecursive = isInList(FLAG_RECURSIVE, params); cmdLineParams._langType = getLangTypeFromParam(params); cmdLineParams._localizationPath = getLocalizationPathFromParam(params); cmdLineParams._line2go = getNumberFromParam('n', params, isParamePresent); cmdLineParams._column2go = getNumberFromParam('c', params, isParamePresent); cmdLineParams._point.x = getNumberFromParam('x', params, cmdLineParams._isPointXValid); cmdLineParams._point.y = getNumberFromParam('y', params, cmdLineParams._isPointYValid); if (showHelp) { ::MessageBox(NULL, COMMAND_ARG_HELP, TEXT("Notepad++ Command Argument Help"), MB_OK); } NppParameters *pNppParameters = NppParameters::getInstance(); if (cmdLineParams._localizationPath != TEXT("")) { pNppParameters->setStartWithLocFileName(cmdLineParams._localizationPath); } pNppParameters->load(); // override the settings if notepad style is present if (pNppParameters->asNotepadStyle()) { isMultiInst = true; cmdLineParams._isNoTab = true; cmdLineParams._isNoSession = true; } // override the settings if multiInst is choosen by user in the preference dialog const NppGUI & nppGUI = pNppParameters->getNppGUI(); if (nppGUI._multiInstSetting == multiInst) { isMultiInst = true; // Only the first launch remembers the session if (!TheFirstOne) cmdLineParams._isNoSession = true; } generic_string quotFileName = TEXT(""); // tell the running instance the FULL path to the new files to load size_t nrFilesToOpen = params.size(); const TCHAR * currentFile; TCHAR fullFileName[MAX_PATH]; for(size_t i = 0; i < nrFilesToOpen; ++i) { currentFile = params.at(i); if (currentFile[0]) { //check if relative or full path. Relative paths dont have a colon for driveletter BOOL isRelative = ::PathIsRelative(currentFile); quotFileName += TEXT("\""); if (isRelative) { ::GetFullPathName(currentFile, MAX_PATH, fullFileName, NULL); quotFileName += fullFileName; } else { if ((currentFile[0] == '\\' && currentFile[1] != '\\') || currentFile[0] == '/') { quotFileName += getDriveLetter(); quotFileName += ':'; } quotFileName += currentFile; } quotFileName += TEXT("\" "); } } //Only after loading all the file paths set the working directory ::SetCurrentDirectory(NppParameters::getInstance()->getNppPath().c_str()); //force working directory to path of module, preventing lock if ((!isMultiInst) && (!TheFirstOne)) { HWND hNotepad_plus = ::FindWindow(Notepad_plus_Window::getClassName(), NULL); for (int i = 0 ;!hNotepad_plus && i < 5 ; ++i) { Sleep(100); hNotepad_plus = ::FindWindow(Notepad_plus_Window::getClassName(), NULL); } if (hNotepad_plus) { // First of all, destroy static object NppParameters pNppParameters->destroyInstance(); MainFileManager->destroyInstance(); int sw = 0; if (::IsZoomed(hNotepad_plus)) sw = SW_MAXIMIZE; else if (::IsIconic(hNotepad_plus)) sw = SW_RESTORE; /* REMOVED else sw = SW_SHOW; // IMPORTANT !!! ::ShowWindow(hNotepad_plus, sw); DEVOMER*/ /* ADDED */ if (sw != 0) ::ShowWindow(hNotepad_plus, sw); /* DEDDA */ ::SetForegroundWindow(hNotepad_plus); if (params.size() > 0) //if there are files to open, use the WM_COPYDATA system { COPYDATASTRUCT paramData; paramData.dwData = COPYDATA_PARAMS; paramData.lpData = &cmdLineParams; paramData.cbData = sizeof(cmdLineParams); COPYDATASTRUCT fileNamesData; fileNamesData.dwData = COPYDATA_FILENAMES; fileNamesData.lpData = (void *)quotFileName.c_str(); fileNamesData.cbData = long(quotFileName.length() + 1)*(sizeof(TCHAR)); ::SendMessage(hNotepad_plus, WM_COPYDATA, (WPARAM)hInstance, (LPARAM)¶mData); ::SendMessage(hNotepad_plus, WM_COPYDATA, (WPARAM)hInstance, (LPARAM)&fileNamesData); } return 0; } } Notepad_plus_Window notepad_plus_plus; NppGUI & nppGui = (NppGUI &)pNppParameters->getNppGUI(); generic_string updaterDir = pNppParameters->getNppPath(); updaterDir += TEXT("\\updater\\"); generic_string updaterFullPath = updaterDir + TEXT("gup.exe"); generic_string version = TEXT("-v"); version += VERSION_VALUE; bool isUpExist = nppGui._doesExistUpdater = (::PathFileExists(updaterFullPath.c_str()) == TRUE); bool doUpdate = nppGui._autoUpdateOpt._doAutoUpdate; if (doUpdate) // check more detail { Date today(0); if (today < nppGui._autoUpdateOpt._nextUpdateDate) doUpdate = false; } if (TheFirstOne && isUpExist && doUpdate) { Process updater(updaterFullPath.c_str(), version.c_str(), updaterDir.c_str()); updater.run(); // Update next update date if (nppGui._autoUpdateOpt._intervalDays < 0) // Make sure interval days value is positive nppGui._autoUpdateOpt._intervalDays = 0 - nppGui._autoUpdateOpt._intervalDays; nppGui._autoUpdateOpt._nextUpdateDate = Date(nppGui._autoUpdateOpt._intervalDays); } MSG msg; msg.wParam = 0; Win32Exception::installHandler(); try { notepad_plus_plus.init(hInstance, NULL, quotFileName.c_str(), &cmdLineParams); // Tell UAC that lower integrity processes are allowed to send WM_COPYDATA messages to this process (or window) // This allows opening new files to already opened elevated Notepad++ process via explorer context menu. if(pNppParameters->getWinVersion() >= WV_VISTA) { HMODULE hDll = GetModuleHandle(TEXT("user32.dll")); if (hDll) { // According to MSDN ChangeWindowMessageFilter may not be supported in future versions of Windows, // that is why we use ChangeWindowMessageFilterEx if it is available (windows version >= Win7). if(pNppParameters->getWinVersion() == WV_VISTA) { typedef BOOL (WINAPI *MESSAGEFILTERFUNC)(UINT message,DWORD dwFlag); const DWORD MSGFLT_ADD = 1; MESSAGEFILTERFUNC func = (MESSAGEFILTERFUNC)::GetProcAddress( hDll, "ChangeWindowMessageFilter" ); if (func) { func(WM_COPYDATA, MSGFLT_ADD); } } else { typedef BOOL (WINAPI *MESSAGEFILTERFUNCEX)(HWND hWnd,UINT message,DWORD action,VOID* pChangeFilterStruct); const DWORD MSGFLT_ALLOW = 1; MESSAGEFILTERFUNCEX func = (MESSAGEFILTERFUNCEX)::GetProcAddress( hDll, "ChangeWindowMessageFilterEx" ); if (func) { func(notepad_plus_plus.getHSelf(), WM_COPYDATA, MSGFLT_ALLOW, NULL ); } } } } bool unicodeSupported = pNppParameters->getWinVersion() >= WV_NT; bool going = true; while (going) { going = (unicodeSupported?(::GetMessageW(&msg, NULL, 0, 0)):(::GetMessageA(&msg, NULL, 0, 0))) != 0; if (going) { // if the message doesn't belong to the notepad_plus_plus's dialog if (!notepad_plus_plus.isDlgsMsg(&msg, unicodeSupported)) { if (::TranslateAccelerator(notepad_plus_plus.getHSelf(), notepad_plus_plus.getAccTable(), &msg) == 0) { ::TranslateMessage(&msg); if (unicodeSupported) ::DispatchMessageW(&msg); else ::DispatchMessage(&msg); } } } } } catch(int i) { TCHAR str[50] = TEXT("God Damned Exception : "); TCHAR code[10]; wsprintf(code, TEXT("%d"), i); ::MessageBox(Notepad_plus_Window::gNppHWND, lstrcat(str, code), TEXT("Int Exception"), MB_OK); doException(notepad_plus_plus); } catch(std::runtime_error & ex) { ::MessageBoxA(Notepad_plus_Window::gNppHWND, ex.what(), "Runtime Exception", MB_OK); doException(notepad_plus_plus); } catch (const Win32Exception & ex) { TCHAR message[1024]; //TODO: sane number wsprintf(message, TEXT("An exception occured. Notepad++ cannot recover and must be shut down.\r\nThe exception details are as follows:\r\n") TEXT("Code:\t0x%08X\r\nType:\t%S\r\nException address: 0x%08X"), ex.code(), ex.what(), ex.where()); ::MessageBox(Notepad_plus_Window::gNppHWND, message, TEXT("Win32Exception"), MB_OK | MB_ICONERROR); mdump.writeDump(ex.info()); doException(notepad_plus_plus); } catch(std::exception & ex) { ::MessageBoxA(Notepad_plus_Window::gNppHWND, ex.what(), "General Exception", MB_OK); doException(notepad_plus_plus); } catch(...) { //this shouldnt ever have to happen ::MessageBoxA(Notepad_plus_Window::gNppHWND, "An exception that we did not yet found its name is just caught", "Unknown Exception", MB_OK); doException(notepad_plus_plus); } return (UINT)msg.wParam; }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { LPTSTR cmdLine = ::GetCommandLine(); ParamVector params; parseCommandLine(cmdLine, params); MiniDumper mdump; //for debugging purposes. bool TheFirstOne = true; ::SetLastError(NO_ERROR); ::CreateMutex(NULL, false, TEXT("nppInstance")); if (::GetLastError() == ERROR_ALREADY_EXISTS) TheFirstOne = false; bool isParamePresent; bool showHelp = isInList(FLAG_HELP, params); bool isMultiInst = isInList(FLAG_MULTI_INSTANCE, params); bool doFunctionListExport = isInList(FLAG_FUNCLSTEXPORT, params); bool doPrintAndQuit = isInList(FLAG_PRINTANDQUIT, params); CmdLineParams cmdLineParams; cmdLineParams._isNoTab = isInList(FLAG_NOTABBAR, params); cmdLineParams._isNoPlugin = isInList(FLAG_NO_PLUGIN, params); cmdLineParams._isReadOnly = isInList(FLAG_READONLY, params); cmdLineParams._isNoSession = isInList(FLAG_NOSESSION, params); cmdLineParams._isPreLaunch = isInList(FLAG_SYSTRAY, params); cmdLineParams._alwaysOnTop = isInList(FLAG_ALWAYS_ON_TOP, params); cmdLineParams._showLoadingTime = isInList(FLAG_LOADINGTIME, params); cmdLineParams._isSessionFile = isInList(FLAG_OPENSESSIONFILE, params); cmdLineParams._isRecursive = isInList(FLAG_RECURSIVE, params); cmdLineParams._langType = getLangTypeFromParam(params); cmdLineParams._localizationPath = getLocalizationPathFromParam(params); cmdLineParams._easterEggName = getEasterEggNameFromParam(params, cmdLineParams._quoteType); cmdLineParams._ghostTypingSpeed = getGhostTypingSpeedFromParam(params); // getNumberFromParam should be run at the end, to not consuming the other params cmdLineParams._line2go = getNumberFromParam('n', params, isParamePresent); cmdLineParams._column2go = getNumberFromParam('c', params, isParamePresent); cmdLineParams._pos2go = getNumberFromParam('p', params, isParamePresent); cmdLineParams._point.x = getNumberFromParam('x', params, cmdLineParams._isPointXValid); cmdLineParams._point.y = getNumberFromParam('y', params, cmdLineParams._isPointYValid); if (showHelp) ::MessageBox(NULL, COMMAND_ARG_HELP, TEXT("Notepad++ Command Argument Help"), MB_OK); NppParameters *pNppParameters = NppParameters::getInstance(); NppGUI & nppGui = const_cast<NppGUI &>(pNppParameters->getNppGUI()); bool doUpdate = nppGui._autoUpdateOpt._doAutoUpdate; if (doFunctionListExport || doPrintAndQuit) // export functionlist feature will serialize fuctionlist on the disk, then exit Notepad++. So it's important to not launch into existing instance, and keep it silent. { isMultiInst = true; doUpdate = false; cmdLineParams._isNoSession = true; } if (cmdLineParams._localizationPath != TEXT("")) { pNppParameters->setStartWithLocFileName(cmdLineParams._localizationPath); } pNppParameters->load(); pNppParameters->setFunctionListExportBoolean(doFunctionListExport); pNppParameters->setPrintAndExitBoolean(doPrintAndQuit); // override the settings if notepad style is present if (pNppParameters->asNotepadStyle()) { isMultiInst = true; cmdLineParams._isNoTab = true; cmdLineParams._isNoSession = true; } // override the settings if multiInst is choosen by user in the preference dialog const NppGUI & nppGUI = pNppParameters->getNppGUI(); if (nppGUI._multiInstSetting == multiInst) { isMultiInst = true; // Only the first launch remembers the session if (!TheFirstOne) cmdLineParams._isNoSession = true; } generic_string quotFileName = TEXT(""); // tell the running instance the FULL path to the new files to load size_t nbFilesToOpen = params.size(); for (size_t i = 0; i < nbFilesToOpen; ++i) { const TCHAR * currentFile = params.at(i).c_str(); if (currentFile[0]) { //check if relative or full path. Relative paths dont have a colon for driveletter quotFileName += TEXT("\""); quotFileName += relativeFilePathToFullFilePath(currentFile); quotFileName += TEXT("\" "); } } //Only after loading all the file paths set the working directory ::SetCurrentDirectory(NppParameters::getInstance()->getNppPath().c_str()); //force working directory to path of module, preventing lock if ((!isMultiInst) && (!TheFirstOne)) { HWND hNotepad_plus = ::FindWindow(Notepad_plus_Window::getClassName(), NULL); for (int i = 0 ;!hNotepad_plus && i < 5 ; ++i) { Sleep(100); hNotepad_plus = ::FindWindow(Notepad_plus_Window::getClassName(), NULL); } if (hNotepad_plus) { // First of all, destroy static object NppParameters pNppParameters->destroyInstance(); MainFileManager->destroyInstance(); int sw = 0; if (::IsZoomed(hNotepad_plus)) sw = SW_MAXIMIZE; else if (::IsIconic(hNotepad_plus)) sw = SW_RESTORE; if (sw != 0) ::ShowWindow(hNotepad_plus, sw); ::SetForegroundWindow(hNotepad_plus); if (params.size() > 0) //if there are files to open, use the WM_COPYDATA system { CmdLineParamsDTO dto = CmdLineParamsDTO::FromCmdLineParams(cmdLineParams); COPYDATASTRUCT paramData; paramData.dwData = COPYDATA_PARAMS; paramData.lpData = &dto; paramData.cbData = sizeof(dto); COPYDATASTRUCT fileNamesData; fileNamesData.dwData = COPYDATA_FILENAMES; fileNamesData.lpData = (void *)quotFileName.c_str(); fileNamesData.cbData = long(quotFileName.length() + 1)*(sizeof(TCHAR)); ::SendMessage(hNotepad_plus, WM_COPYDATA, reinterpret_cast<WPARAM>(hInstance), reinterpret_cast<LPARAM>(¶mData)); ::SendMessage(hNotepad_plus, WM_COPYDATA, reinterpret_cast<WPARAM>(hInstance), reinterpret_cast<LPARAM>(&fileNamesData)); } return 0; } } Notepad_plus_Window notepad_plus_plus; generic_string updaterDir = pNppParameters->getNppPath(); updaterDir += TEXT("\\updater\\"); generic_string updaterFullPath = updaterDir + TEXT("gup.exe"); generic_string updaterParams = TEXT("-v"); updaterParams += VERSION_VALUE; bool isUpExist = nppGui._doesExistUpdater = (::PathFileExists(updaterFullPath.c_str()) == TRUE); if (doUpdate) // check more detail { Date today(0); if (today < nppGui._autoUpdateOpt._nextUpdateDate) doUpdate = false; } // wingup doesn't work with the obsolet security layer (API) under xp since downloadings are secured with SSL on notepad_plus_plus.org winVer ver = pNppParameters->getWinVersion(); bool isGtXP = ver > WV_XP; if (TheFirstOne && isUpExist && doUpdate && isGtXP) { if (pNppParameters->isx64()) { updaterParams += TEXT(" -px64"); } Process updater(updaterFullPath.c_str(), updaterParams.c_str(), updaterDir.c_str()); updater.run(); // Update next update date if (nppGui._autoUpdateOpt._intervalDays < 0) // Make sure interval days value is positive nppGui._autoUpdateOpt._intervalDays = 0 - nppGui._autoUpdateOpt._intervalDays; nppGui._autoUpdateOpt._nextUpdateDate = Date(nppGui._autoUpdateOpt._intervalDays); } MSG msg; msg.wParam = 0; Win32Exception::installHandler(); try { notepad_plus_plus.init(hInstance, NULL, quotFileName.c_str(), &cmdLineParams); allowWmCopydataMessages(notepad_plus_plus, pNppParameters, ver); bool going = true; while (going) { going = ::GetMessageW(&msg, NULL, 0, 0) != 0; if (going) { // if the message doesn't belong to the notepad_plus_plus's dialog if (!notepad_plus_plus.isDlgsMsg(&msg)) { if (::TranslateAccelerator(notepad_plus_plus.getHSelf(), notepad_plus_plus.getAccTable(), &msg) == 0) { ::TranslateMessage(&msg); ::DispatchMessageW(&msg); } } } } } catch (int i) { TCHAR str[50] = TEXT("God Damned Exception : "); TCHAR code[10]; wsprintf(code, TEXT("%d"), i); ::MessageBox(Notepad_plus_Window::gNppHWND, lstrcat(str, code), TEXT("Int Exception"), MB_OK); doException(notepad_plus_plus); } catch (std::runtime_error & ex) { ::MessageBoxA(Notepad_plus_Window::gNppHWND, ex.what(), "Runtime Exception", MB_OK); doException(notepad_plus_plus); } catch (const Win32Exception & ex) { TCHAR message[1024]; //TODO: sane number wsprintf(message, TEXT("An exception occured. Notepad++ cannot recover and must be shut down.\r\nThe exception details are as follows:\r\n") TEXT("Code:\t0x%08X\r\nType:\t%S\r\nException address: 0x%p"), ex.code(), ex.what(), ex.where()); ::MessageBox(Notepad_plus_Window::gNppHWND, message, TEXT("Win32Exception"), MB_OK | MB_ICONERROR); mdump.writeDump(ex.info()); doException(notepad_plus_plus); } catch (std::exception & ex) { ::MessageBoxA(Notepad_plus_Window::gNppHWND, ex.what(), "General Exception", MB_OK); doException(notepad_plus_plus); } catch (...) // this shouldnt ever have to happen { ::MessageBoxA(Notepad_plus_Window::gNppHWND, "An exception that we did not yet found its name is just caught", "Unknown Exception", MB_OK); doException(notepad_plus_plus); } return static_cast<int>(msg.wParam); }