1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "winguiprocess.h"
35 #include "consoleprocess.h"
37 #include <utils/qtcprocess.h>
38 #include <utils/winutils.h>
40 #include <QtCore/QDir>
42 using namespace ProjectExplorer::Internal;
44 WinGuiProcess::WinGuiProcess(QObject *parent)
51 WinGuiProcess::~WinGuiProcess()
56 bool WinGuiProcess::start(const QString &program, const QString &args)
62 QThread::start(QThread::NormalPriority);
68 void WinGuiProcess::stop()
71 TerminateProcess(m_pid->hProcess, 1);
75 bool WinGuiProcess::isRunning() const
77 return QThread::isRunning();
80 bool WinGuiProcess::setupDebugInterface(HANDLE &bufferReadyEvent, HANDLE &dataReadyEvent, HANDLE &sharedFile, LPVOID &sharedMem)
83 bufferReadyEvent = CreateEvent(NULL, FALSE, FALSE, L"DBWIN_BUFFER_READY");
84 if (!bufferReadyEvent || GetLastError() == ERROR_ALREADY_EXISTS)
86 dataReadyEvent = CreateEvent(NULL, FALSE, FALSE, L"DBWIN_DATA_READY");
87 if (!dataReadyEvent || GetLastError() == ERROR_ALREADY_EXISTS)
89 sharedFile = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, 4096, L"DBWIN_BUFFER");
90 if (!sharedFile || GetLastError() == ERROR_ALREADY_EXISTS)
92 sharedMem = MapViewOfFile(sharedFile, FILE_MAP_READ, 0, 0, 512);
98 void WinGuiProcess::run()
104 ZeroMemory(&si, sizeof(si));
107 m_pid = new PROCESS_INFORMATION;
108 ZeroMemory(m_pid, sizeof(PROCESS_INFORMATION));
111 bool started = false;
113 HANDLE bufferReadyEvent = NULL;
114 HANDLE dataReadyEvent = NULL;
115 HANDLE sharedFile = NULL;
116 LPVOID sharedMem = 0;
120 const bool dbgInterface = setupDebugInterface(bufferReadyEvent, dataReadyEvent, sharedFile, sharedMem);
123 QtcProcess::prepareCommand(m_program, m_args, &pcmd, &pargs, &m_environment, &m_workingDir);
124 const QString cmdLine = createWinCommandline(pcmd, pargs);
125 const QStringList env = m_environment.toStringList();
126 started = CreateProcessW(0, (WCHAR*)cmdLine.utf16(),
127 0, 0, TRUE, CREATE_UNICODE_ENVIRONMENT,
129 : createWinEnvironment(fixWinEnvironment(env)).data(),
130 workingDirectory().isEmpty() ? 0
131 : (WCHAR*)QDir::convertSeparators(workingDirectory()).utf16(),
135 emit processMessage(tr("The process could not be started: %1").
136 arg(Utils::winErrorMessage(GetLastError())), true);
137 emit processFinished(0);
142 // Text is filtered in qmlengine.cpp
143 emit receivedDebugOutput(Utils::AbstractProcess::msgWinCannotRetrieveDebuggingOutput(), true);
144 WaitForSingleObject(m_pid->hProcess, INFINITE);
150 message = reinterpret_cast<LPSTR>(sharedMem) + sizeof(DWORD);
151 processId = reinterpret_cast<LPDWORD>(sharedMem);
153 SetEvent(bufferReadyEvent);
155 toWaitFor[0] = dataReadyEvent;
156 toWaitFor[1] = m_pid->hProcess;
158 for (bool stop = false; !stop;) {
159 DWORD ret = WaitForMultipleObjects(2, toWaitFor, FALSE, INFINITE);
162 case WAIT_OBJECT_0 + 0:
163 if (*processId == m_pid->dwProcessId)
164 emit receivedDebugOutput(QString::fromLocal8Bit(message), false);
165 SetEvent(bufferReadyEvent);
167 case WAIT_OBJECT_0 + 1:
176 GetExitCodeProcess(m_pid->hProcess, &m_exitCode);
177 emit processFinished(static_cast<int>(m_exitCode));
181 UnmapViewOfFile(sharedMem);
182 if (sharedFile != NULL)
183 CloseHandle(sharedFile);
184 if (bufferReadyEvent != NULL)
185 CloseHandle(bufferReadyEvent);
186 if (dataReadyEvent != NULL)
187 CloseHandle(dataReadyEvent);
188 if (m_pid->hProcess != NULL)
189 CloseHandle(m_pid->hProcess);
190 if (m_pid->hThread != NULL)
191 CloseHandle(m_pid->hThread);
196 qint64 WinGuiProcess::applicationPID() const
199 return m_pid->dwProcessId;
203 int WinGuiProcess::exitCode() const
205 return static_cast<int>(m_exitCode);