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>
39 #include <QtCore/QDir>
41 using namespace ProjectExplorer::Internal;
43 WinGuiProcess::WinGuiProcess(QObject *parent)
50 WinGuiProcess::~WinGuiProcess()
55 bool WinGuiProcess::start(const QString &program, const QString &args)
61 QThread::start(QThread::NormalPriority);
67 void WinGuiProcess::stop()
70 TerminateProcess(m_pid->hProcess, 1);
74 bool WinGuiProcess::isRunning() const
76 return QThread::isRunning();
79 bool WinGuiProcess::setupDebugInterface(HANDLE &bufferReadyEvent, HANDLE &dataReadyEvent, HANDLE &sharedFile, LPVOID &sharedMem)
82 bufferReadyEvent = CreateEvent(NULL, FALSE, FALSE, L"DBWIN_BUFFER_READY");
83 if (!bufferReadyEvent || GetLastError() == ERROR_ALREADY_EXISTS)
85 dataReadyEvent = CreateEvent(NULL, FALSE, FALSE, L"DBWIN_DATA_READY");
86 if (!dataReadyEvent || GetLastError() == ERROR_ALREADY_EXISTS)
88 sharedFile = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, 4096, L"DBWIN_BUFFER");
89 if (!sharedFile || GetLastError() == ERROR_ALREADY_EXISTS)
91 sharedMem = MapViewOfFile(sharedFile, FILE_MAP_READ, 0, 0, 512);
97 void WinGuiProcess::run()
103 ZeroMemory(&si, sizeof(si));
106 m_pid = new PROCESS_INFORMATION;
107 ZeroMemory(m_pid, sizeof(PROCESS_INFORMATION));
110 bool started = false;
112 HANDLE bufferReadyEvent = NULL;
113 HANDLE dataReadyEvent = NULL;
114 HANDLE sharedFile = NULL;
115 LPVOID sharedMem = 0;
119 const bool dbgInterface = setupDebugInterface(bufferReadyEvent, dataReadyEvent, sharedFile, sharedMem);
122 QtcProcess::prepareCommand(m_program, m_args, &pcmd, &pargs, &m_environment, &m_workingDir);
123 const QString cmdLine = createWinCommandline(pcmd, pargs);
124 const QStringList env = m_environment.toStringList();
125 started = CreateProcessW(0, (WCHAR*)cmdLine.utf16(),
126 0, 0, TRUE, CREATE_UNICODE_ENVIRONMENT,
128 : createWinEnvironment(fixWinEnvironment(env)).data(),
129 workingDirectory().isEmpty() ? 0
130 : (WCHAR*)QDir::convertSeparators(workingDirectory()).utf16(),
134 emit processMessage(tr("The process could not be started!"), true);
139 emit receivedDebugOutput(tr("Cannot retrieve debugging output!"), true);
140 WaitForSingleObject(m_pid->hProcess, INFINITE);
146 message = reinterpret_cast<LPSTR>(sharedMem) + sizeof(DWORD);
147 processId = reinterpret_cast<LPDWORD>(sharedMem);
149 SetEvent(bufferReadyEvent);
151 toWaitFor[0] = dataReadyEvent;
152 toWaitFor[1] = m_pid->hProcess;
154 for (bool stop = false; !stop;) {
155 DWORD ret = WaitForMultipleObjects(2, toWaitFor, FALSE, INFINITE);
158 case WAIT_OBJECT_0 + 0:
159 if (*processId == m_pid->dwProcessId)
160 emit receivedDebugOutput(QString::fromLocal8Bit(message), false);
161 SetEvent(bufferReadyEvent);
163 case WAIT_OBJECT_0 + 1:
172 GetExitCodeProcess(m_pid->hProcess, &m_exitCode);
173 emit processFinished(static_cast<int>(m_exitCode));
177 UnmapViewOfFile(sharedMem);
178 if (sharedFile != NULL)
179 CloseHandle(sharedFile);
180 if (bufferReadyEvent != NULL)
181 CloseHandle(bufferReadyEvent);
182 if (dataReadyEvent != NULL)
183 CloseHandle(dataReadyEvent);
184 if (m_pid->hProcess != NULL)
185 CloseHandle(m_pid->hProcess);
186 if (m_pid->hThread != NULL)
187 CloseHandle(m_pid->hThread);
192 qint64 WinGuiProcess::applicationPID() const
195 return m_pid->dwProcessId;
199 int WinGuiProcess::exitCode() const
201 return static_cast<int>(m_exitCode);