summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2016-11-25 06:39:30 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2016-12-23 04:54:35 +0000
commit601bdc416b6ef17498c94fec49164b1b4c38528d (patch)
tree288e261b182ba5e06a19dd761aca08cde39fd12b
parent46d3163f779a43cc7c023a6e8141f990e5d23292 (diff)
tdf#100826: Use parent console for output if possible
This patch uses either passed standard handles, or parent console for output of --help and --version command line switches. Change-Id: Iabbec79d3792ae091ca06d134345c1669eb1ac13 Reviewed-on: https://gerrit.libreoffice.org/31187 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r--desktop/source/app/cmdlinehelp.cxx94
-rw-r--r--desktop/win32/source/officeloader/officeloader.cxx13
2 files changed, 90 insertions, 17 deletions
diff --git a/desktop/source/app/cmdlinehelp.cxx b/desktop/source/app/cmdlinehelp.cxx
index 27e4d8116698..3c904ac3b3b2 100644
--- a/desktop/source/app/cmdlinehelp.cxx
+++ b/desktop/source/app/cmdlinehelp.cxx
@@ -27,6 +27,10 @@
#include "cmdlinehelp.hxx"
#ifdef _WIN32
+#if _WIN32_WINNT < 0x0501
+// For AttachConsole() and MAPVK_VK_TO_VSC
+#define _WIN32_WINNT 0x0501
+#endif
#include "windows.h"
#include "io.h"
#include "fcntl.h"
@@ -172,45 +176,105 @@ namespace desktop
#ifdef _WIN32
namespace{
class lcl_Console {
+ enum eConsoleMode { unknown, attached, allocated };
public:
explicit lcl_Console(short nBufHeight)
+ : mConsoleMode(unknown)
{
- bFreeConsole = AllocConsole() != FALSE;
- CONSOLE_SCREEN_BUFFER_INFO cinfo;
- GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cinfo);
- cinfo.dwSize.Y = nBufHeight;
- SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), cinfo.dwSize);
+ HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE),
+ hOut = GetStdHandle(STD_OUTPUT_HANDLE),
+ hErr = GetStdHandle(STD_ERROR_HANDLE);
+ if (hOut == NULL) // application does not have associated standard handles
+ {
+ STARTUPINFOA aStartupInfo{ sizeof(aStartupInfo) };
+ GetStartupInfoA(&aStartupInfo);
+ if ((aStartupInfo.dwFlags & STARTF_USESTDHANDLES) == STARTF_USESTDHANDLES)
+ {
+ // If standard handles had been passed to this process, use them
+ hIn = aStartupInfo.hStdInput;
+ hOut = aStartupInfo.hStdOutput;
+ hErr = aStartupInfo.hStdError;
+ }
+ else
+ {
+ // Try to attach parent console; on error try to create new.
+ // If this process already has its console, these will simply fail.
+ if (AttachConsole(ATTACH_PARENT_PROCESS) != FALSE)
+ mConsoleMode = attached;
+ else if (AllocConsole() != FALSE)
+ mConsoleMode = allocated;
+
+ hIn = GetStdHandle(STD_INPUT_HANDLE);
+ hOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ hErr = GetStdHandle(STD_ERROR_HANDLE);
+
+ // Ensure that console buffer is enough to hold required data
+ CONSOLE_SCREEN_BUFFER_INFO cinfo;
+ GetConsoleScreenBufferInfo(hOut, &cinfo);
+ if (cinfo.dwSize.Y < nBufHeight)
+ {
+ cinfo.dwSize.Y = nBufHeight;
+ SetConsoleScreenBufferSize(hOut, cinfo.dwSize);
+ }
+ }
+ }
+
// stdin
- intptr_t stdHandle = reinterpret_cast<intptr_t>(GetStdHandle(STD_INPUT_HANDLE));
- int fileHandle = _open_osfhandle(stdHandle, _O_TEXT);
+ int fileHandle = _open_osfhandle(reinterpret_cast<intptr_t>(hIn), _O_TEXT);
FILE *fp = _fdopen(fileHandle, "r");
*stdin = *fp;
setvbuf(stdin, nullptr, _IONBF, 0);
// stdout
- stdHandle = reinterpret_cast<intptr_t>(GetStdHandle(STD_OUTPUT_HANDLE));
- fileHandle = _open_osfhandle(stdHandle, _O_TEXT);
+ fileHandle = _open_osfhandle(reinterpret_cast<intptr_t>(hOut), _O_TEXT);
fp = _fdopen(fileHandle, "w");
*stdout = *fp;
setvbuf(stdout, nullptr, _IONBF, 0);
// stderr
- stdHandle = reinterpret_cast<intptr_t>(GetStdHandle(STD_ERROR_HANDLE));
- fileHandle = _open_osfhandle(stdHandle, _O_TEXT);
+ fileHandle = _open_osfhandle(reinterpret_cast<intptr_t>(hErr), _O_TEXT);
fp = _fdopen(fileHandle, "w");
*stderr = *fp;
setvbuf(stderr, nullptr, _IONBF, 0);
+
+ std::ios::sync_with_stdio(true);
+
+ // In case we use parent's console, emit an empty string
+ // to avoid output on a line with command prompt
+ if (mConsoleMode == attached)
+ fprintf(stdout, "\n");
}
~lcl_Console()
{
- if (bFreeConsole)
+ switch (mConsoleMode) {
+ case unknown:
+ // Don't free the console
+ return;
+ case attached:
{
- fprintf(stdout, "Press Enter to close this console...");
+ // Put Enter keypress to console input buffer to emit next command prompt after the command
+ INPUT_RECORD ir;
+ ir.EventType = KEY_EVENT;
+ KEY_EVENT_RECORD& ke = ir.Event.KeyEvent;
+ ke.bKeyDown = TRUE;
+ ke.wRepeatCount = 1;
+ ke.wVirtualKeyCode = VK_RETURN;
+ ke.wVirtualScanCode = MapVirtualKeyA(VK_RETURN, MAPVK_VK_TO_VSC);
+ ke.uChar.AsciiChar = '\r';
+ ke.dwControlKeyState = 0;
+ DWORD nEvents;
+ WriteConsoleInputA(GetStdHandle(STD_INPUT_HANDLE), &ir, 1, &nEvents);
+ break;
+ }
+ case allocated:
+ fprintf(stdout, "Press Enter to continue...");
fgetc(stdin);
- FreeConsole();
+ break;
}
+
+ FreeConsole();
}
private:
- bool bFreeConsole;
+ eConsoleMode mConsoleMode;
};
}
#endif
diff --git a/desktop/win32/source/officeloader/officeloader.cxx b/desktop/win32/source/officeloader/officeloader.cxx
index 25277f1ff143..25f35374e119 100644
--- a/desktop/win32/source/officeloader/officeloader.cxx
+++ b/desktop/win32/source/officeloader/officeloader.cxx
@@ -23,6 +23,9 @@
#include <cstddef>
#include <cwchar>
+#if _WIN32_WINNT < 0x0501
+#define _WIN32_WINNT 0x0501
+#endif
#define WIN32_LEAN_AND_MEAN
#if defined _MSC_VER
#pragma warning(push, 1)
@@ -71,10 +74,16 @@ int WINAPI _tWinMain( HINSTANCE, HINSTANCE, LPTSTR, int )
ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) );
aStartupInfo.cb = sizeof(aStartupInfo);
- GetStartupInfo( &aStartupInfo );
-
// Create process with same command line, environment and stdio handles which
// are directed to the created pipes
+ GetStartupInfo(&aStartupInfo);
+
+ // If this process hasn't its stdio handles set, then check if its parent
+ // has a console (i.e. this process is launched from command line), and if so,
+ // attach to it. It will enable child process to retrieve this console if it needs
+ // to output to console
+ if ((aStartupInfo.dwFlags & STARTF_USESTDHANDLES) == 0)
+ AttachConsole(ATTACH_PARENT_PROCESS);
DWORD dwExitCode = (DWORD)-1;