aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/utils/process_ctrlc_stub.cpp
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>2011-08-12 21:06:05 +0200
committerJoerg Bornemann <joerg.bornemann@nokia.com>2011-08-15 10:42:00 +0200
commit65317deaf98883eb36e9ccd9243fac523cb23559 (patch)
tree7734752e22b2f9eb7f12e9ced4b367778ac71bf1 /src/libs/utils/process_ctrlc_stub.cpp
parent9e20d6df04f5a7cdc185a558aecd254a29751046 (diff)
move qtcbuildhelper where it belongs and rename it accordingly
this is not a creator tool, but a helper of qtcprocess, just like the existing stub. Change-Id: Ice7c60a1dee0b132c6063747f82ea35699f4127d Reviewed-on: http://codereview.qt.nokia.com/2918 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Joerg Bornemann <joerg.bornemann@nokia.com>
Diffstat (limited to 'src/libs/utils/process_ctrlc_stub.cpp')
-rw-r--r--src/libs/utils/process_ctrlc_stub.cpp192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/libs/utils/process_ctrlc_stub.cpp b/src/libs/utils/process_ctrlc_stub.cpp
new file mode 100644
index 0000000000..b7e29fd4ba
--- /dev/null
+++ b/src/libs/utils/process_ctrlc_stub.cpp
@@ -0,0 +1,192 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+
+/* A stub for Windows console processes (like nmake) that is able to terminate
+ * its child process via a generated Ctrl-C event.
+ * The termination is triggered by sending a custom message to the HWND of
+ * this process. */
+
+#ifndef WINVER
+#define WINVER 0x0501
+#endif
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <shellapi.h>
+#include <wchar.h>
+#include <cstdlib>
+#include <cstdio>
+
+const wchar_t szTitle[] = L"qtcbuildhelper";
+const wchar_t szWindowClass[] = L"wcqtcbuildhelper";
+UINT uiShutDownWindowMessage;
+HWND hwndMain = 0;
+
+LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+BOOL WINAPI ctrlHandler(DWORD dwCtrlType);
+bool findFirst(const wchar_t *str, const size_t strLength, const size_t startPos, const wchar_t *chars, size_t &pos);
+bool startProcess(wchar_t pCommandLine[]);
+
+int main(int argc, char **)
+{
+ if (argc < 2) {
+ fprintf(stderr, "This is an internal helper of Qt Creator. Do not run it manually.\n");
+ return 1;
+ }
+
+ SetConsoleCtrlHandler(ctrlHandler, TRUE);
+ uiShutDownWindowMessage = RegisterWindowMessage(L"qtcbuildhelper_shutdown");
+
+ WNDCLASSEX wcex;
+ ZeroMemory(&wcex, sizeof(wcex));
+ wcex.cbSize = sizeof(wcex);
+ wcex.lpfnWndProc = WndProc;
+ wcex.hInstance = GetModuleHandle(0);
+ wcex.lpszClassName = szWindowClass;
+ if (!RegisterClassEx(&wcex))
+ return 1;
+
+ hwndMain = CreateWindow(szWindowClass, szTitle, WS_DISABLED,
+ 0, 0, 0, 0, NULL, NULL, wcex.hInstance, NULL);
+ if (!hwndMain)
+ return FALSE;
+
+ // Get the command line and remove the call to this executable.
+ // Note: We trust Qt Creator at this point to quote the call to this tool in a sensible way.
+ // Strange things like C:\Q"t Crea"tor\bin\qtcbuildhelper.exe are not supported.
+ wchar_t *strCommandLine = _wcsdup(GetCommandLine());
+ const size_t strCommandLineLength = wcslen(strCommandLine);
+ size_t pos = 1;
+ if (strCommandLine[0] == L'"')
+ if (!findFirst(strCommandLine, strCommandLineLength, pos, L"\"", pos))
+ return 1;
+ if (!findFirst(strCommandLine, strCommandLineLength, pos, L" \t", pos))
+ return 1;
+#ifdef Q_CC_MSVC
+ wmemmove_s(strCommandLine, strCommandLineLength, strCommandLine + pos + 1, strCommandLineLength - pos);
+#else
+ wmemmove(strCommandLine, strCommandLine + pos + 1, strCommandLineLength - pos);
+#endif
+ bool bSuccess = startProcess(strCommandLine);
+ free(strCommandLine);
+
+ if (!bSuccess)
+ return 1;
+
+ MSG msg;
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ return (int) msg.wParam;
+}
+
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (message == uiShutDownWindowMessage) {
+ GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
+ PostQuitMessage(0);
+ return 0;
+ }
+
+ switch (message)
+ {
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ return 0;
+}
+
+bool findFirst(const wchar_t *str, const size_t strLength, const size_t startPos, const wchar_t *chars, size_t &pos)
+{
+ for (size_t i=startPos; i < strLength; ++i) {
+ for (size_t j=0; chars[j]; ++j) {
+ if (str[i] == chars[j]) {
+ pos = i;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+BOOL WINAPI ctrlHandler(DWORD /*dwCtrlType*/)
+{
+ PostMessage(hwndMain, WM_DESTROY, 0, 0);
+ return TRUE;
+}
+
+DWORD WINAPI processWatcherThread(LPVOID lpParameter)
+{
+ HANDLE hProcess = reinterpret_cast<HANDLE>(lpParameter);
+ WaitForSingleObject(hProcess, INFINITE);
+ PostMessage(hwndMain, WM_DESTROY, 0, 0);
+ return 0;
+}
+
+bool startProcess(wchar_t *pCommandLine)
+{
+ SECURITY_ATTRIBUTES sa;
+ ZeroMemory(&sa, sizeof(sa));
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+
+ STARTUPINFO si;
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+
+ PROCESS_INFORMATION pi;
+ DWORD dwCreationFlags = 0;
+ BOOL bSuccess = CreateProcess(NULL, pCommandLine, &sa, &sa, TRUE, dwCreationFlags, NULL, NULL, &si, &pi);
+ if (!bSuccess) {
+ fwprintf(stderr, L"qtcbuildhelper: Command line failed: %s\n", pCommandLine);
+ return false;
+ }
+
+ HANDLE hThread = CreateThread(NULL, 0, processWatcherThread, reinterpret_cast<void*>(pi.hProcess), 0, NULL);
+ if (!hThread) {
+ fwprintf(stderr, L"qtcbuildhelper: The watch dog thread cannot be started.\n");
+ return false;
+ }
+ CloseHandle(hThread);
+ return true;
+}
+