OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / projectexplorer / winguiprocess.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
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
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
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.
24 **
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.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "winguiprocess.h"
35 #include "consoleprocess.h"
36
37 #include <utils/qtcprocess.h>
38
39 #include <QtCore/QDir>
40
41 using namespace ProjectExplorer::Internal;
42
43 WinGuiProcess::WinGuiProcess(QObject *parent)
44     : QThread(parent)
45 {
46     m_pid = 0;
47     m_exitCode = 0;
48 }
49
50 WinGuiProcess::~WinGuiProcess()
51 {
52     stop();
53 }
54
55 bool WinGuiProcess::start(const QString &program, const QString &args)
56 {
57     m_program = program;
58     m_args = args;
59
60     if (!isRunning()) {
61         QThread::start(QThread::NormalPriority);
62         return true;
63     }
64     return false;
65 }
66
67 void WinGuiProcess::stop()
68 {
69     if (m_pid)
70         TerminateProcess(m_pid->hProcess, 1);
71     wait();
72 }
73
74 bool WinGuiProcess::isRunning() const
75 {
76     return QThread::isRunning();
77 }
78
79 bool WinGuiProcess::setupDebugInterface(HANDLE &bufferReadyEvent, HANDLE &dataReadyEvent, HANDLE &sharedFile, LPVOID &sharedMem)
80 {
81
82     bufferReadyEvent = CreateEvent(NULL, FALSE, FALSE, L"DBWIN_BUFFER_READY");
83     if (!bufferReadyEvent || GetLastError() == ERROR_ALREADY_EXISTS)
84         return false;
85     dataReadyEvent = CreateEvent(NULL, FALSE, FALSE, L"DBWIN_DATA_READY");
86     if (!dataReadyEvent || GetLastError() == ERROR_ALREADY_EXISTS)
87         return false;
88     sharedFile = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, 4096, L"DBWIN_BUFFER");
89     if (!sharedFile || GetLastError() == ERROR_ALREADY_EXISTS)
90         return false;
91     sharedMem = MapViewOfFile(sharedFile, FILE_MAP_READ, 0, 0,  512);
92     if (!sharedMem)
93         return false;
94     return true;
95 }
96
97 void WinGuiProcess::run()
98 {
99     if (m_pid)
100         return;
101
102     STARTUPINFO si;
103     ZeroMemory(&si, sizeof(si));
104     si.cb = sizeof(si);
105
106     m_pid = new PROCESS_INFORMATION;
107     ZeroMemory(m_pid, sizeof(PROCESS_INFORMATION));
108
109     m_exitCode = 0;
110     bool started = false;
111
112     HANDLE bufferReadyEvent = NULL;
113     HANDLE dataReadyEvent = NULL;
114     HANDLE sharedFile = NULL;
115     LPVOID sharedMem = 0;
116
117     do {
118
119         const bool dbgInterface = setupDebugInterface(bufferReadyEvent, dataReadyEvent, sharedFile, sharedMem);
120
121         QString pcmd, pargs;
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,
127                                       env.isEmpty() ? 0
128                                           : createWinEnvironment(fixWinEnvironment(env)).data(),
129                                           workingDirectory().isEmpty() ? 0
130                                               : (WCHAR*)QDir::convertSeparators(workingDirectory()).utf16(),
131                                               &si, m_pid);
132
133         if (!started) {
134             emit processMessage(tr("The process could not be started!"), true);
135             break;
136         }
137
138         if (!dbgInterface) {
139             emit receivedDebugOutput(tr("Cannot retrieve debugging output!"), true);
140             WaitForSingleObject(m_pid->hProcess, INFINITE);
141         } else {
142             LPSTR  message;
143             LPDWORD processId;
144             HANDLE toWaitFor[2];
145
146             message = reinterpret_cast<LPSTR>(sharedMem) + sizeof(DWORD);
147             processId = reinterpret_cast<LPDWORD>(sharedMem);
148
149             SetEvent(bufferReadyEvent);
150
151             toWaitFor[0] = dataReadyEvent;
152             toWaitFor[1] = m_pid->hProcess;
153
154             for (bool stop = false; !stop;) {
155                 DWORD ret = WaitForMultipleObjects(2, toWaitFor, FALSE, INFINITE);
156
157                 switch (ret) {
158                 case WAIT_OBJECT_0 + 0:
159                     if (*processId == m_pid->dwProcessId)
160                         emit receivedDebugOutput(QString::fromLocal8Bit(message), false);
161                     SetEvent(bufferReadyEvent);
162                     break;
163                 case WAIT_OBJECT_0 + 1:
164                     stop = true;
165                     break;
166                 }
167             }
168         }
169     } while (false);
170
171     if (started) {
172         GetExitCodeProcess(m_pid->hProcess, &m_exitCode);
173         emit processFinished(static_cast<int>(m_exitCode));
174     }
175
176     if (sharedMem)
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);
188     delete m_pid;
189     m_pid = 0;
190 }
191
192 qint64 WinGuiProcess::applicationPID() const
193 {
194     if (m_pid)
195         return m_pid->dwProcessId;
196     return 0;
197 }
198
199 int WinGuiProcess::exitCode() const
200 {
201     return static_cast<int>(m_exitCode);
202 }