winmain: add newline at the end of file

winmain: move local functions to anonymous namespace
winmain: remove redundant static keyword
winmain: add newline at the end of file
winmain: move UAC related code to anonymous function
winmain: declare MSGFLT_ADD/MSGFLT_ALLOW only if not already defined
winmain: check only for emptiness
parameters: move winKeyDefs & scintKeyDefs & PGNSI to anonymous names
parameters: remove redundant static/inline keywords
misc: remove unused source code

Closes #3030
This commit is contained in:
Damien Gerard 2017-03-09 01:53:57 +09:00 committed by Don Ho
parent a308ea57b7
commit 6947bf3909
5 changed files with 57 additions and 507 deletions

View File

@ -1,265 +0,0 @@
// This file is part of Notepad++ project
// Copyright (C)2003 Don HO <don.h@free.fr>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// Note that the GPL places important restrictions on "derived works", yet
// it does not provide a detailed definition of that term. To avoid
// misunderstandings, we consider an application to constitute a
// "derivative work" for the purpose of this license if it does any of the
// following:
// 1. Integrates source code from Notepad++.
// 2. Integrates/includes/aggregates Notepad++ into a proprietary executable
// installer, such as those produced by InstallShield.
// 3. Links to a library or executes a program that does any of the above.
//
// 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 General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "precompiledHeaders.h"
#include "process.h"
//#include "SysMsg.h"
BOOL Process::run()
{
BOOL result = TRUE;
// stdout & stderr pipes for process to write
HANDLE hPipeOutW = NULL;
HANDLE hPipeErrW = NULL;
HANDLE hListenerStdOutThread = NULL;
HANDLE hListenerStdErrThread = NULL;
HANDLE hListenerEvent[2];
hListenerEvent[0] = NULL;
hListenerEvent[1] = NULL;
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; // inheritable handle
try
{
// Create stdout pipe
if (!::CreatePipe(&_hPipeOutR, &hPipeOutW, &sa, 0))
error(TEXT("CreatePipe"), result, 1000);
// Create stderr pipe
if (!::CreatePipe(&_hPipeErrR, &hPipeErrW, &sa, 0))
error(TEXT("CreatePipe"), result, 1001);
STARTUPINFO startup;
PROCESS_INFORMATION procinfo;
::ZeroMemory(&startup, sizeof(startup));
startup.cb = sizeof(startup);
startup.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
startup.wShowWindow = SW_HIDE; // hidden console window
startup.hStdInput = NULL; // not used
startup.hStdOutput = hPipeOutW;
startup.hStdError = hPipeErrW;
BOOL started = ::CreateProcess(NULL, // command is part of input string
_command, // (writeable) command string
NULL, // process security
NULL, // thread security
TRUE, // inherit handles flag
CREATE_SUSPENDED, // flags
NULL, // inherit environment
_curDir, // inherit directory
&startup, // STARTUPINFO
&procinfo); // PROCESS_INFORMATION
_hProcess = procinfo.hProcess;
_hProcessThread = procinfo.hThread;
if (!started)
error(TEXT("CreateProcess"), result, 1002);
hListenerEvent[0] = ::CreateEvent(NULL, FALSE, FALSE, TEXT("listenerEvent"));
if (!hListenerEvent[0])
error(TEXT("CreateEvent"), result, 1003);
hListenerEvent[1] = ::CreateEvent(NULL, FALSE, FALSE, TEXT("listenerStdErrEvent"));
if (!hListenerEvent[1])
error(TEXT("CreateEvent"), result, 1004);
hListenerStdOutThread = ::CreateThread(NULL, 0, staticListenerStdOut, this, 0, NULL);
if (!hListenerStdOutThread)
error(TEXT("CreateThread"), result, 1005);
hListenerStdErrThread = ::CreateThread(NULL, 0, staticListenerStdErr, this, 0, NULL);
if (!hListenerStdErrThread)
error(TEXT("CreateThread"), result, 1006);
::WaitForSingleObject(_hProcess, INFINITE);
::WaitForMultipleObjects(2, hListenerEvent, TRUE, INFINITE);
}
catch (int /*coderr*/)
{}
// on va fermer toutes les handles
if (hPipeOutW)
::CloseHandle(hPipeOutW);
if (hPipeErrW)
::CloseHandle(hPipeErrW);
if (_hPipeOutR)
::CloseHandle(_hPipeOutR);
if (_hPipeErrR)
::CloseHandle(_hPipeErrR);
if (hListenerStdOutThread)
::CloseHandle(hListenerStdOutThread);
if (hListenerStdErrThread)
::CloseHandle(hListenerStdErrThread);
if (hListenerEvent[0])
::CloseHandle(hListenerEvent[0]);
if (hListenerEvent[1])
::CloseHandle(hListenerEvent[1]);
return result;
}
#define MAX_LINE_LENGTH 1024
void Process::listenerStdOut()
{
DWORD bytesAvail = 0;
BOOL result = 0;
HANDLE hListenerEvent = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("listenerEvent"));
TCHAR bufferOut[MAX_LINE_LENGTH + 1];
int nExitCode = STILL_ACTIVE;
DWORD outbytesRead;
::ResumeThread(_hProcessThread);
bool goOn = true;
while (goOn)
{ // got data
memset(bufferOut,0x00,MAX_LINE_LENGTH + 1);
int size = sizeof(bufferOut) - sizeof(TCHAR);
Sleep(50);
if (!::PeekNamedPipe(_hPipeOutR, bufferOut, size, &outbytesRead, &bytesAvail, NULL))
{
bytesAvail = 0;
goOn = false;
break;
}
if (outbytesRead)
{
result = :: ReadFile(_hPipeOutR, bufferOut, size, &outbytesRead, NULL);
if ((!result) && (outbytesRead == 0))
{
goOn = false;
break;
}
}
bufferOut[outbytesRead] = '\0';
generic_string s;
s.assign(bufferOut);
_stdoutStr += s;
if (::GetExitCodeProcess(_hProcess, (unsigned long*)&nExitCode))
{
if (nExitCode != STILL_ACTIVE)
{
goOn = false;
break; // EOF condition
}
}
//else
//break;
}
_exitCode = nExitCode;
if (!::SetEvent(hListenerEvent))
{
systemMessage(TEXT("Thread listenerStdOut"));
}
}
void Process::listenerStdErr()
{
DWORD bytesAvail = 0;
BOOL result = 0;
HANDLE hListenerEvent = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("listenerStdErrEvent"));
TCHAR bufferErr[MAX_LINE_LENGTH + 1];
int nExitCode = STILL_ACTIVE;
::ResumeThread(_hProcessThread);
bool goOn = true;
while (goOn)
{ // got data
memset(bufferErr, 0x00, MAX_LINE_LENGTH + 1);
size_t size = sizeof(bufferErr) - sizeof(TCHAR);
Sleep(50);
DWORD errbytesRead;
if (!::PeekNamedPipe(_hPipeErrR, bufferErr, size, &errbytesRead, &bytesAvail, NULL))
{
bytesAvail = 0;
goOn = false;
break;
}
if (errbytesRead)
{
result = :: ReadFile(_hPipeErrR, bufferErr, size, &errbytesRead, NULL);
if ((!result) && (errbytesRead == 0))
{
goOn = false;
break;
}
}
bufferErr[errbytesRead] = '\0';
generic_string s;
s.assign(bufferErr);
_stderrStr += s;
if (::GetExitCodeProcess(_hProcess, (unsigned long*)&nExitCode))
{
if (nExitCode != STILL_ACTIVE)
{
goOn = false;
break; // EOF condition
}
}
//else
//break;
}
//_exitCode = nExitCode;
if (!::SetEvent(hListenerEvent))
{
systemMessage(TEXT("Thread stdout listener"));
}
}
void Process::error(const TCHAR *txt2display, BOOL & returnCode, int errCode)
{
systemMessage(txt2display);
returnCode = FALSE;
throw int(errCode);
}

View File

@ -1,98 +0,0 @@
// This file is part of Notepad++ project
// Copyright (C)2003 Don HO <don.h@free.fr>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// Note that the GPL places important restrictions on "derived works", yet
// it does not provide a detailed definition of that term. To avoid
// misunderstandings, we consider an application to constitute a
// "derivative work" for the purpose of this license if it does any of the
// following:
// 1. Integrates source code from Notepad++.
// 2. Integrates/includes/aggregates Notepad++ into a proprietary executable
// installer, such as those produced by InstallShield.
// 3. Links to a library or executes a program that does any of the above.
//
// 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 General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#pragma once
#include <windows.h>
//#include <string>
using namespace std;
class Process
{
public:
Process() {}
Process(const TCHAR *cmd, const TCHAR *cDir)
{
lstrcpy(_command, cmd);
lstrcpy(_curDir, cDir);
}
BOOL run();
const TCHAR * getStdout() const {
return _stdoutStr.c_str();
}
const TCHAR * getStderr() const {
return _stderrStr.c_str();
}
int getExitCode() const {
return _exitCode;
}
bool hasStdout() {
return (_stdoutStr.compare(TEXT("")) != 0);
}
bool hasStderr() {
return (_stderrStr.compare(TEXT("")) != 0);
}
protected:
// LES ENTREES
TCHAR _command[256];
TCHAR _curDir[256];
// LES SORTIES
generic_string _stdoutStr;
generic_string _stderrStr;
int _exitCode = 0;
// LES HANDLES
HANDLE _hPipeOutR = nullptr;
HANDLE _hPipeErrR = nullptr;
HANDLE _hProcess = nullptr;
HANDLE _hProcessThread = nullptr;
//UINT _pid; // process ID assigned by caller
static DWORD WINAPI staticListenerStdOut(void * myself){
static_cast<Process *>(myself)->listenerStdOut();
return 0;
};
static DWORD WINAPI staticListenerStdErr(void * myself) {
static_cast<Process *>(myself)->listenerStdErr();
return 0;
};
void listenerStdOut();
void listenerStdErr();
void error(const TCHAR *txt2display, BOOL & returnCode, int errCode);
};

View File

@ -1,100 +0,0 @@
// This file is part of Notepad++ project
// Copyright (C)2003 Don HO <don.h@free.fr>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// Note that the GPL places important restrictions on "derived works", yet
// it does not provide a detailed definition of that term. To avoid
// misunderstandings, we consider an application to constitute a
// "derivative work" for the purpose of this license if it does any of the
// following:
// 1. Integrates source code from Notepad++.
// 2. Integrates/includes/aggregates Notepad++ into a proprietary executable
// installer, such as those produced by InstallShield.
// 3. Links to a library or executes a program that does any of the above.
//
// 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 General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#ifndef PROCESS_THREAD_H
#define PROCESS_THREAD_H
#include "process.h"
class ProcessThread
{
public:
ProcessThread(const TCHAR *appName, const TCHAR *cmd, const TCHAR *cDir, HWND hwnd)
: _hwnd(hwnd)
{
lstrcpy(_appName, appName);
lstrcpy(_command, cmd);
lstrcpy(_curDir, cDir);
}
BOOL run()
{
HANDLE hEvent = ::CreateEvent(NULL, FALSE, FALSE, TEXT("localVarProcessEvent"));
_hProcessThread = ::CreateThread(NULL, 0, staticLauncher, this, 0, NULL);
::WaitForSingleObject(hEvent, INFINITE);
::CloseHandle(hEvent);
return TRUE;
}
protected:
// ENTREES
TCHAR _appName[256];
TCHAR _command[256];
TCHAR _curDir[256];
HWND _hwnd;
HANDLE _hProcessThread;
static DWORD WINAPI staticLauncher(void *myself)
{
((ProcessThread *)myself)->launch();
return TRUE;
}
bool launch()
{
HANDLE hEvent = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("localVarProcessEvent"));
HWND hwnd = _hwnd;
TCHAR appName[256];
lstrcpy(appName, _appName);
HANDLE hMyself = _hProcessThread;
Process process(_command, _curDir);
if (!::SetEvent(hEvent))
systemMessage(TEXT("Thread launcher"));
process.run();
int code = process.getExitCode();
TCHAR codeStr[256];
generic_sprintf(codeStr, TEXT("%s : %0.4X"), appName, code);
::MessageBox(hwnd, process.getStdout(), codeStr, MB_OK);
if (process.hasStderr())
::MessageBox(hwnd, process.getStderr(), codeStr, MB_OK);
::CloseHandle(hMyself);
return true;
}
};
#endif PROCESS_THREAD_H

View File

@ -39,6 +39,8 @@
using namespace std;
namespace // anonymous namespace
{
struct WinMenuKeyDefinition //more or less matches accelerator table definition, easy copy/paste
@ -513,10 +515,8 @@ typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
namespace // anonymous namespace
{
static int strVal(const TCHAR *str, int base)
int strVal(const TCHAR *str, int base)
{
if (!str) return -1;
if (!str[0]) return 0;
@ -529,17 +529,17 @@ namespace // anonymous namespace
}
static int decStrVal(const TCHAR *str)
int decStrVal(const TCHAR *str)
{
return strVal(str, 10);
}
static int hexStrVal(const TCHAR *str)
int hexStrVal(const TCHAR *str)
{
return strVal(str, 16);
}
static int getKwClassFromName(const TCHAR *str)
int getKwClassFromName(const TCHAR *str)
{
if (!lstrcmp(TEXT("instre1"), str)) return LANG_INDEX_INSTR;
if (!lstrcmp(TEXT("instre2"), str)) return LANG_INDEX_INSTR2;
@ -556,13 +556,13 @@ namespace // anonymous namespace
}
static inline size_t getAsciiLenFromBase64Len(size_t base64StrLen)
size_t getAsciiLenFromBase64Len(size_t base64StrLen)
{
return (base64StrLen % 4) ? 0 : (base64StrLen - base64StrLen / 4);
}
static int base64ToAscii(char *dest, const char *base64Str)
int base64ToAscii(char *dest, const char *base64Str)
{
static const int base64IndexArray[123] =
{

View File

@ -33,9 +33,53 @@
typedef std::vector<const TCHAR*> ParamVector;
namespace
{
void allowWmCopydataMessages(Notepad_plus_Window& notepad_plus_plus, const NppParameters* pNppParameters, winVer ver)
{
#ifndef MSGFLT_ADD
const DWORD MSGFLT_ADD = 1;
#endif
#ifndef MSGFLT_ALLOW
const DWORD MSGFLT_ALLOW = 1;
#endif
// 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 (ver >= WV_VISTA || ver == WV_UNKNOWN)
{
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);
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);
MESSAGEFILTERFUNCEX func = (MESSAGEFILTERFUNCEX)::GetProcAddress( hDll, "ChangeWindowMessageFilterEx" );
if (func)
func(notepad_plus_plus.getHSelf(), WM_COPYDATA, MSGFLT_ALLOW, NULL );
}
}
}
}
bool checkSingleFile(const TCHAR *commandLine)
{
if (!commandLine || lstrlen(commandLine) == 0)
if (!commandLine || commandLine[0] == TEXT('\0'))
return false;
TCHAR fullpath[MAX_PATH] = {0};
@ -242,7 +286,7 @@ const TCHAR FLAG_OPENSESSIONFILE[] = TEXT("-openSession");
const TCHAR FLAG_RECURSIVE[] = TEXT("-r");
static void doException(Notepad_plus_Window & notepad_plus_plus)
void doException(Notepad_plus_Window & notepad_plus_plus)
{
Win32Exception::removeHandler(); //disable exception handler after excpetion, we dont want corrupt data structurs to crash the exception handler
::MessageBox(Notepad_plus_Window::gNppHWND, TEXT("Notepad++ will attempt to save any unsaved data. However, dataloss is very likely."), TEXT("Recovery initiating"), MB_OK | MB_ICONINFORMATION);
@ -264,6 +308,7 @@ static void doException(Notepad_plus_Window & notepad_plus_plus)
}
} // namespace
@ -449,39 +494,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
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 (ver >= WV_VISTA || ver == WV_UNKNOWN)
{
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 );
}
}
}
allowWmCopydataMessages(notepad_plus_plus, pNppParameters, ver);
bool going = true;
while (going)
{
@ -534,4 +547,4 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
}
return static_cast<int>(msg.wParam);
}
}