1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // test_utils_win.cpp: Implementation of OS-specific functions for Windows
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker #include "util/test_utils.h"
10*8975f5c5SAndroid Build Coastguard Worker
11*8975f5c5SAndroid Build Coastguard Worker #include <aclapi.h>
12*8975f5c5SAndroid Build Coastguard Worker #include <stdarg.h>
13*8975f5c5SAndroid Build Coastguard Worker #include <windows.h>
14*8975f5c5SAndroid Build Coastguard Worker #include <array>
15*8975f5c5SAndroid Build Coastguard Worker #include <iostream>
16*8975f5c5SAndroid Build Coastguard Worker #include <vector>
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Worker #include "anglebase/no_destructor.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "common/angleutils.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "common/platform_helpers.h"
21*8975f5c5SAndroid Build Coastguard Worker
22*8975f5c5SAndroid Build Coastguard Worker namespace angle
23*8975f5c5SAndroid Build Coastguard Worker {
24*8975f5c5SAndroid Build Coastguard Worker namespace
25*8975f5c5SAndroid Build Coastguard Worker {
26*8975f5c5SAndroid Build Coastguard Worker struct ScopedPipe
27*8975f5c5SAndroid Build Coastguard Worker {
~ScopedPipeangle::__anone4867e320111::ScopedPipe28*8975f5c5SAndroid Build Coastguard Worker ~ScopedPipe()
29*8975f5c5SAndroid Build Coastguard Worker {
30*8975f5c5SAndroid Build Coastguard Worker closeReadHandle();
31*8975f5c5SAndroid Build Coastguard Worker closeWriteHandle();
32*8975f5c5SAndroid Build Coastguard Worker }
closeReadHandleangle::__anone4867e320111::ScopedPipe33*8975f5c5SAndroid Build Coastguard Worker bool closeReadHandle()
34*8975f5c5SAndroid Build Coastguard Worker {
35*8975f5c5SAndroid Build Coastguard Worker if (readHandle)
36*8975f5c5SAndroid Build Coastguard Worker {
37*8975f5c5SAndroid Build Coastguard Worker if (::CloseHandle(readHandle) == FALSE)
38*8975f5c5SAndroid Build Coastguard Worker {
39*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error closing write handle: " << GetLastError();
40*8975f5c5SAndroid Build Coastguard Worker return false;
41*8975f5c5SAndroid Build Coastguard Worker }
42*8975f5c5SAndroid Build Coastguard Worker readHandle = nullptr;
43*8975f5c5SAndroid Build Coastguard Worker }
44*8975f5c5SAndroid Build Coastguard Worker
45*8975f5c5SAndroid Build Coastguard Worker return true;
46*8975f5c5SAndroid Build Coastguard Worker }
closeWriteHandleangle::__anone4867e320111::ScopedPipe47*8975f5c5SAndroid Build Coastguard Worker bool closeWriteHandle()
48*8975f5c5SAndroid Build Coastguard Worker {
49*8975f5c5SAndroid Build Coastguard Worker if (writeHandle)
50*8975f5c5SAndroid Build Coastguard Worker {
51*8975f5c5SAndroid Build Coastguard Worker if (::CloseHandle(writeHandle) == FALSE)
52*8975f5c5SAndroid Build Coastguard Worker {
53*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error closing write handle: " << GetLastError();
54*8975f5c5SAndroid Build Coastguard Worker return false;
55*8975f5c5SAndroid Build Coastguard Worker }
56*8975f5c5SAndroid Build Coastguard Worker writeHandle = nullptr;
57*8975f5c5SAndroid Build Coastguard Worker }
58*8975f5c5SAndroid Build Coastguard Worker
59*8975f5c5SAndroid Build Coastguard Worker return true;
60*8975f5c5SAndroid Build Coastguard Worker }
61*8975f5c5SAndroid Build Coastguard Worker
validangle::__anone4867e320111::ScopedPipe62*8975f5c5SAndroid Build Coastguard Worker bool valid() const { return readHandle != nullptr || writeHandle != nullptr; }
63*8975f5c5SAndroid Build Coastguard Worker
initPipeangle::__anone4867e320111::ScopedPipe64*8975f5c5SAndroid Build Coastguard Worker bool initPipe(SECURITY_ATTRIBUTES *securityAttribs)
65*8975f5c5SAndroid Build Coastguard Worker {
66*8975f5c5SAndroid Build Coastguard Worker if (::CreatePipe(&readHandle, &writeHandle, securityAttribs, 0) == FALSE)
67*8975f5c5SAndroid Build Coastguard Worker {
68*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error creating pipe: " << GetLastError() << "\n";
69*8975f5c5SAndroid Build Coastguard Worker return false;
70*8975f5c5SAndroid Build Coastguard Worker }
71*8975f5c5SAndroid Build Coastguard Worker
72*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_ENABLE_WINDOWS_UWP)
73*8975f5c5SAndroid Build Coastguard Worker // Ensure the read handles to the pipes are not inherited.
74*8975f5c5SAndroid Build Coastguard Worker if (::SetHandleInformation(readHandle, HANDLE_FLAG_INHERIT, 0) == FALSE)
75*8975f5c5SAndroid Build Coastguard Worker {
76*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error setting handle info on pipe: " << GetLastError() << "\n";
77*8975f5c5SAndroid Build Coastguard Worker return false;
78*8975f5c5SAndroid Build Coastguard Worker }
79*8975f5c5SAndroid Build Coastguard Worker #endif // !defined(ANGLE_ENABLE_WINDOWS_UWP)
80*8975f5c5SAndroid Build Coastguard Worker
81*8975f5c5SAndroid Build Coastguard Worker return true;
82*8975f5c5SAndroid Build Coastguard Worker }
83*8975f5c5SAndroid Build Coastguard Worker
84*8975f5c5SAndroid Build Coastguard Worker HANDLE readHandle = nullptr;
85*8975f5c5SAndroid Build Coastguard Worker HANDLE writeHandle = nullptr;
86*8975f5c5SAndroid Build Coastguard Worker };
87*8975f5c5SAndroid Build Coastguard Worker
88*8975f5c5SAndroid Build Coastguard Worker // Returns false on EOF or error.
ReadFromFile(bool blocking,HANDLE handle,std::string * out)89*8975f5c5SAndroid Build Coastguard Worker void ReadFromFile(bool blocking, HANDLE handle, std::string *out)
90*8975f5c5SAndroid Build Coastguard Worker {
91*8975f5c5SAndroid Build Coastguard Worker char buffer[8192];
92*8975f5c5SAndroid Build Coastguard Worker DWORD bytesRead = 0;
93*8975f5c5SAndroid Build Coastguard Worker
94*8975f5c5SAndroid Build Coastguard Worker while (true)
95*8975f5c5SAndroid Build Coastguard Worker {
96*8975f5c5SAndroid Build Coastguard Worker if (!blocking)
97*8975f5c5SAndroid Build Coastguard Worker {
98*8975f5c5SAndroid Build Coastguard Worker BOOL success = ::PeekNamedPipe(handle, nullptr, 0, nullptr, &bytesRead, nullptr);
99*8975f5c5SAndroid Build Coastguard Worker if (success == FALSE || bytesRead == 0)
100*8975f5c5SAndroid Build Coastguard Worker return;
101*8975f5c5SAndroid Build Coastguard Worker }
102*8975f5c5SAndroid Build Coastguard Worker
103*8975f5c5SAndroid Build Coastguard Worker BOOL success = ::ReadFile(handle, buffer, sizeof(buffer), &bytesRead, nullptr);
104*8975f5c5SAndroid Build Coastguard Worker if (success == FALSE || bytesRead == 0)
105*8975f5c5SAndroid Build Coastguard Worker return;
106*8975f5c5SAndroid Build Coastguard Worker
107*8975f5c5SAndroid Build Coastguard Worker out->append(buffer, bytesRead);
108*8975f5c5SAndroid Build Coastguard Worker }
109*8975f5c5SAndroid Build Coastguard Worker
110*8975f5c5SAndroid Build Coastguard Worker // unreachable.
111*8975f5c5SAndroid Build Coastguard Worker }
112*8975f5c5SAndroid Build Coastguard Worker
113*8975f5c5SAndroid Build Coastguard Worker // Returns the Win32 last error code or ERROR_SUCCESS if the last error code is
114*8975f5c5SAndroid Build Coastguard Worker // ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND. This is useful in cases where
115*8975f5c5SAndroid Build Coastguard Worker // the absence of a file or path is a success condition (e.g., when attempting
116*8975f5c5SAndroid Build Coastguard Worker // to delete an item in the filesystem).
ReturnSuccessOnNotFound()117*8975f5c5SAndroid Build Coastguard Worker bool ReturnSuccessOnNotFound()
118*8975f5c5SAndroid Build Coastguard Worker {
119*8975f5c5SAndroid Build Coastguard Worker const DWORD error_code = ::GetLastError();
120*8975f5c5SAndroid Build Coastguard Worker return (error_code == ERROR_FILE_NOT_FOUND || error_code == ERROR_PATH_NOT_FOUND);
121*8975f5c5SAndroid Build Coastguard Worker }
122*8975f5c5SAndroid Build Coastguard Worker
123*8975f5c5SAndroid Build Coastguard Worker // Job objects seems to have problems on the Chromium CI and Windows 7.
ShouldUseJobObjects()124*8975f5c5SAndroid Build Coastguard Worker bool ShouldUseJobObjects()
125*8975f5c5SAndroid Build Coastguard Worker {
126*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_ENABLE_WINDOWS_UWP)
127*8975f5c5SAndroid Build Coastguard Worker return false;
128*8975f5c5SAndroid Build Coastguard Worker #else
129*8975f5c5SAndroid Build Coastguard Worker return IsWindows10OrLater();
130*8975f5c5SAndroid Build Coastguard Worker #endif
131*8975f5c5SAndroid Build Coastguard Worker }
132*8975f5c5SAndroid Build Coastguard Worker
133*8975f5c5SAndroid Build Coastguard Worker class WindowsProcess : public Process
134*8975f5c5SAndroid Build Coastguard Worker {
135*8975f5c5SAndroid Build Coastguard Worker public:
WindowsProcess(const std::vector<const char * > & commandLineArgs,ProcessOutputCapture captureOutput)136*8975f5c5SAndroid Build Coastguard Worker WindowsProcess(const std::vector<const char *> &commandLineArgs,
137*8975f5c5SAndroid Build Coastguard Worker ProcessOutputCapture captureOutput)
138*8975f5c5SAndroid Build Coastguard Worker {
139*8975f5c5SAndroid Build Coastguard Worker mProcessInfo.hProcess = INVALID_HANDLE_VALUE;
140*8975f5c5SAndroid Build Coastguard Worker mProcessInfo.hThread = INVALID_HANDLE_VALUE;
141*8975f5c5SAndroid Build Coastguard Worker
142*8975f5c5SAndroid Build Coastguard Worker std::vector<char> commandLineString;
143*8975f5c5SAndroid Build Coastguard Worker for (const char *arg : commandLineArgs)
144*8975f5c5SAndroid Build Coastguard Worker {
145*8975f5c5SAndroid Build Coastguard Worker if (arg)
146*8975f5c5SAndroid Build Coastguard Worker {
147*8975f5c5SAndroid Build Coastguard Worker if (!commandLineString.empty())
148*8975f5c5SAndroid Build Coastguard Worker {
149*8975f5c5SAndroid Build Coastguard Worker commandLineString.push_back(' ');
150*8975f5c5SAndroid Build Coastguard Worker }
151*8975f5c5SAndroid Build Coastguard Worker commandLineString.insert(commandLineString.end(), arg, arg + strlen(arg));
152*8975f5c5SAndroid Build Coastguard Worker }
153*8975f5c5SAndroid Build Coastguard Worker }
154*8975f5c5SAndroid Build Coastguard Worker commandLineString.push_back('\0');
155*8975f5c5SAndroid Build Coastguard Worker
156*8975f5c5SAndroid Build Coastguard Worker // Set the bInheritHandle flag so pipe handles are inherited.
157*8975f5c5SAndroid Build Coastguard Worker SECURITY_ATTRIBUTES securityAttribs;
158*8975f5c5SAndroid Build Coastguard Worker securityAttribs.nLength = sizeof(SECURITY_ATTRIBUTES);
159*8975f5c5SAndroid Build Coastguard Worker securityAttribs.bInheritHandle = TRUE;
160*8975f5c5SAndroid Build Coastguard Worker securityAttribs.lpSecurityDescriptor = nullptr;
161*8975f5c5SAndroid Build Coastguard Worker
162*8975f5c5SAndroid Build Coastguard Worker STARTUPINFOA startInfo = {};
163*8975f5c5SAndroid Build Coastguard Worker
164*8975f5c5SAndroid Build Coastguard Worker const bool captureStdout = captureOutput != ProcessOutputCapture::Nothing;
165*8975f5c5SAndroid Build Coastguard Worker const bool captureStderr =
166*8975f5c5SAndroid Build Coastguard Worker captureOutput == ProcessOutputCapture::StdoutAndStderrInterleaved ||
167*8975f5c5SAndroid Build Coastguard Worker captureOutput == ProcessOutputCapture::StdoutAndStderrSeparately;
168*8975f5c5SAndroid Build Coastguard Worker const bool pipeStderrToStdout =
169*8975f5c5SAndroid Build Coastguard Worker captureOutput == ProcessOutputCapture::StdoutAndStderrInterleaved;
170*8975f5c5SAndroid Build Coastguard Worker
171*8975f5c5SAndroid Build Coastguard Worker // Create pipes for stdout and stderr.
172*8975f5c5SAndroid Build Coastguard Worker startInfo.cb = sizeof(STARTUPINFOA);
173*8975f5c5SAndroid Build Coastguard Worker startInfo.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
174*8975f5c5SAndroid Build Coastguard Worker if (captureStdout)
175*8975f5c5SAndroid Build Coastguard Worker {
176*8975f5c5SAndroid Build Coastguard Worker if (!mStdoutPipe.initPipe(&securityAttribs))
177*8975f5c5SAndroid Build Coastguard Worker {
178*8975f5c5SAndroid Build Coastguard Worker return;
179*8975f5c5SAndroid Build Coastguard Worker }
180*8975f5c5SAndroid Build Coastguard Worker startInfo.hStdOutput = mStdoutPipe.writeHandle;
181*8975f5c5SAndroid Build Coastguard Worker }
182*8975f5c5SAndroid Build Coastguard Worker else
183*8975f5c5SAndroid Build Coastguard Worker {
184*8975f5c5SAndroid Build Coastguard Worker startInfo.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
185*8975f5c5SAndroid Build Coastguard Worker }
186*8975f5c5SAndroid Build Coastguard Worker
187*8975f5c5SAndroid Build Coastguard Worker if (pipeStderrToStdout)
188*8975f5c5SAndroid Build Coastguard Worker {
189*8975f5c5SAndroid Build Coastguard Worker startInfo.hStdError = startInfo.hStdOutput;
190*8975f5c5SAndroid Build Coastguard Worker }
191*8975f5c5SAndroid Build Coastguard Worker else if (captureStderr)
192*8975f5c5SAndroid Build Coastguard Worker {
193*8975f5c5SAndroid Build Coastguard Worker if (!mStderrPipe.initPipe(&securityAttribs))
194*8975f5c5SAndroid Build Coastguard Worker {
195*8975f5c5SAndroid Build Coastguard Worker return;
196*8975f5c5SAndroid Build Coastguard Worker }
197*8975f5c5SAndroid Build Coastguard Worker startInfo.hStdError = mStderrPipe.writeHandle;
198*8975f5c5SAndroid Build Coastguard Worker }
199*8975f5c5SAndroid Build Coastguard Worker else
200*8975f5c5SAndroid Build Coastguard Worker {
201*8975f5c5SAndroid Build Coastguard Worker startInfo.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
202*8975f5c5SAndroid Build Coastguard Worker }
203*8975f5c5SAndroid Build Coastguard Worker
204*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_ENABLE_WINDOWS_UWP)
205*8975f5c5SAndroid Build Coastguard Worker if (captureStdout || captureStderr)
206*8975f5c5SAndroid Build Coastguard Worker {
207*8975f5c5SAndroid Build Coastguard Worker startInfo.dwFlags |= STARTF_USESTDHANDLES;
208*8975f5c5SAndroid Build Coastguard Worker }
209*8975f5c5SAndroid Build Coastguard Worker
210*8975f5c5SAndroid Build Coastguard Worker if (ShouldUseJobObjects())
211*8975f5c5SAndroid Build Coastguard Worker {
212*8975f5c5SAndroid Build Coastguard Worker // Create job object. Job objects allow us to automatically force child processes to
213*8975f5c5SAndroid Build Coastguard Worker // exit if the parent process is unexpectedly killed. This should prevent ghost
214*8975f5c5SAndroid Build Coastguard Worker // processes from hanging around.
215*8975f5c5SAndroid Build Coastguard Worker mJobHandle = ::CreateJobObjectA(nullptr, nullptr);
216*8975f5c5SAndroid Build Coastguard Worker if (mJobHandle == NULL)
217*8975f5c5SAndroid Build Coastguard Worker {
218*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error creating job object: " << GetLastError() << "\n";
219*8975f5c5SAndroid Build Coastguard Worker return;
220*8975f5c5SAndroid Build Coastguard Worker }
221*8975f5c5SAndroid Build Coastguard Worker
222*8975f5c5SAndroid Build Coastguard Worker JOBOBJECT_EXTENDED_LIMIT_INFORMATION limitInfo = {};
223*8975f5c5SAndroid Build Coastguard Worker limitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
224*8975f5c5SAndroid Build Coastguard Worker if (::SetInformationJobObject(mJobHandle, JobObjectExtendedLimitInformation, &limitInfo,
225*8975f5c5SAndroid Build Coastguard Worker sizeof(limitInfo)) == FALSE)
226*8975f5c5SAndroid Build Coastguard Worker {
227*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error setting job information: " << GetLastError() << "\n";
228*8975f5c5SAndroid Build Coastguard Worker return;
229*8975f5c5SAndroid Build Coastguard Worker }
230*8975f5c5SAndroid Build Coastguard Worker }
231*8975f5c5SAndroid Build Coastguard Worker #endif // !defined(ANGLE_ENABLE_WINDOWS_UWP)
232*8975f5c5SAndroid Build Coastguard Worker
233*8975f5c5SAndroid Build Coastguard Worker // Create the child process.
234*8975f5c5SAndroid Build Coastguard Worker if (::CreateProcessA(nullptr, commandLineString.data(), nullptr, nullptr,
235*8975f5c5SAndroid Build Coastguard Worker TRUE, // Handles are inherited.
236*8975f5c5SAndroid Build Coastguard Worker 0, nullptr, nullptr, &startInfo, &mProcessInfo) == FALSE)
237*8975f5c5SAndroid Build Coastguard Worker {
238*8975f5c5SAndroid Build Coastguard Worker std::cerr << "CreateProcessA Error code: " << GetLastError() << "\n";
239*8975f5c5SAndroid Build Coastguard Worker return;
240*8975f5c5SAndroid Build Coastguard Worker }
241*8975f5c5SAndroid Build Coastguard Worker
242*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_ENABLE_WINDOWS_UWP)
243*8975f5c5SAndroid Build Coastguard Worker if (mJobHandle != nullptr)
244*8975f5c5SAndroid Build Coastguard Worker {
245*8975f5c5SAndroid Build Coastguard Worker if (::AssignProcessToJobObject(mJobHandle, mProcessInfo.hProcess) == FALSE)
246*8975f5c5SAndroid Build Coastguard Worker {
247*8975f5c5SAndroid Build Coastguard Worker std::cerr << "AssignProcessToJobObject failed: " << GetLastError() << "\n";
248*8975f5c5SAndroid Build Coastguard Worker return;
249*8975f5c5SAndroid Build Coastguard Worker }
250*8975f5c5SAndroid Build Coastguard Worker }
251*8975f5c5SAndroid Build Coastguard Worker #endif // !defined(ANGLE_ENABLE_WINDOWS_UWP)
252*8975f5c5SAndroid Build Coastguard Worker
253*8975f5c5SAndroid Build Coastguard Worker // Close the write end of the pipes, so EOF can be generated when child exits.
254*8975f5c5SAndroid Build Coastguard Worker if (!mStdoutPipe.closeWriteHandle() || !mStderrPipe.closeWriteHandle())
255*8975f5c5SAndroid Build Coastguard Worker return;
256*8975f5c5SAndroid Build Coastguard Worker
257*8975f5c5SAndroid Build Coastguard Worker mStarted = true;
258*8975f5c5SAndroid Build Coastguard Worker mTimer.start();
259*8975f5c5SAndroid Build Coastguard Worker }
260*8975f5c5SAndroid Build Coastguard Worker
~WindowsProcess()261*8975f5c5SAndroid Build Coastguard Worker ~WindowsProcess() override
262*8975f5c5SAndroid Build Coastguard Worker {
263*8975f5c5SAndroid Build Coastguard Worker if (mProcessInfo.hProcess != INVALID_HANDLE_VALUE)
264*8975f5c5SAndroid Build Coastguard Worker {
265*8975f5c5SAndroid Build Coastguard Worker ::CloseHandle(mProcessInfo.hProcess);
266*8975f5c5SAndroid Build Coastguard Worker }
267*8975f5c5SAndroid Build Coastguard Worker if (mProcessInfo.hThread != INVALID_HANDLE_VALUE)
268*8975f5c5SAndroid Build Coastguard Worker {
269*8975f5c5SAndroid Build Coastguard Worker ::CloseHandle(mProcessInfo.hThread);
270*8975f5c5SAndroid Build Coastguard Worker }
271*8975f5c5SAndroid Build Coastguard Worker if (mJobHandle != nullptr)
272*8975f5c5SAndroid Build Coastguard Worker {
273*8975f5c5SAndroid Build Coastguard Worker ::CloseHandle(mJobHandle);
274*8975f5c5SAndroid Build Coastguard Worker }
275*8975f5c5SAndroid Build Coastguard Worker }
276*8975f5c5SAndroid Build Coastguard Worker
started()277*8975f5c5SAndroid Build Coastguard Worker bool started() override { return mStarted; }
278*8975f5c5SAndroid Build Coastguard Worker
finish()279*8975f5c5SAndroid Build Coastguard Worker bool finish() override
280*8975f5c5SAndroid Build Coastguard Worker {
281*8975f5c5SAndroid Build Coastguard Worker if (mStdoutPipe.valid())
282*8975f5c5SAndroid Build Coastguard Worker {
283*8975f5c5SAndroid Build Coastguard Worker ReadFromFile(true, mStdoutPipe.readHandle, &mStdout);
284*8975f5c5SAndroid Build Coastguard Worker }
285*8975f5c5SAndroid Build Coastguard Worker
286*8975f5c5SAndroid Build Coastguard Worker if (mStderrPipe.valid())
287*8975f5c5SAndroid Build Coastguard Worker {
288*8975f5c5SAndroid Build Coastguard Worker ReadFromFile(true, mStderrPipe.readHandle, &mStderr);
289*8975f5c5SAndroid Build Coastguard Worker }
290*8975f5c5SAndroid Build Coastguard Worker
291*8975f5c5SAndroid Build Coastguard Worker DWORD result = ::WaitForSingleObject(mProcessInfo.hProcess, INFINITE);
292*8975f5c5SAndroid Build Coastguard Worker mTimer.stop();
293*8975f5c5SAndroid Build Coastguard Worker return result == WAIT_OBJECT_0;
294*8975f5c5SAndroid Build Coastguard Worker }
295*8975f5c5SAndroid Build Coastguard Worker
finished()296*8975f5c5SAndroid Build Coastguard Worker bool finished() override
297*8975f5c5SAndroid Build Coastguard Worker {
298*8975f5c5SAndroid Build Coastguard Worker if (!mStarted)
299*8975f5c5SAndroid Build Coastguard Worker return false;
300*8975f5c5SAndroid Build Coastguard Worker
301*8975f5c5SAndroid Build Coastguard Worker // Pipe stdin and stdout.
302*8975f5c5SAndroid Build Coastguard Worker if (mStdoutPipe.valid())
303*8975f5c5SAndroid Build Coastguard Worker {
304*8975f5c5SAndroid Build Coastguard Worker ReadFromFile(false, mStdoutPipe.readHandle, &mStdout);
305*8975f5c5SAndroid Build Coastguard Worker }
306*8975f5c5SAndroid Build Coastguard Worker
307*8975f5c5SAndroid Build Coastguard Worker if (mStderrPipe.valid())
308*8975f5c5SAndroid Build Coastguard Worker {
309*8975f5c5SAndroid Build Coastguard Worker ReadFromFile(false, mStderrPipe.readHandle, &mStderr);
310*8975f5c5SAndroid Build Coastguard Worker }
311*8975f5c5SAndroid Build Coastguard Worker
312*8975f5c5SAndroid Build Coastguard Worker DWORD result = ::WaitForSingleObject(mProcessInfo.hProcess, 0);
313*8975f5c5SAndroid Build Coastguard Worker if (result == WAIT_OBJECT_0)
314*8975f5c5SAndroid Build Coastguard Worker {
315*8975f5c5SAndroid Build Coastguard Worker mTimer.stop();
316*8975f5c5SAndroid Build Coastguard Worker return true;
317*8975f5c5SAndroid Build Coastguard Worker }
318*8975f5c5SAndroid Build Coastguard Worker if (result == WAIT_TIMEOUT)
319*8975f5c5SAndroid Build Coastguard Worker return false;
320*8975f5c5SAndroid Build Coastguard Worker
321*8975f5c5SAndroid Build Coastguard Worker mTimer.stop();
322*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Unexpected result from WaitForSingleObject: " << result
323*8975f5c5SAndroid Build Coastguard Worker << ". Last error: " << ::GetLastError() << "\n";
324*8975f5c5SAndroid Build Coastguard Worker return false;
325*8975f5c5SAndroid Build Coastguard Worker }
326*8975f5c5SAndroid Build Coastguard Worker
getExitCode()327*8975f5c5SAndroid Build Coastguard Worker int getExitCode() override
328*8975f5c5SAndroid Build Coastguard Worker {
329*8975f5c5SAndroid Build Coastguard Worker if (!mStarted)
330*8975f5c5SAndroid Build Coastguard Worker return -1;
331*8975f5c5SAndroid Build Coastguard Worker
332*8975f5c5SAndroid Build Coastguard Worker if (mProcessInfo.hProcess == INVALID_HANDLE_VALUE)
333*8975f5c5SAndroid Build Coastguard Worker return -1;
334*8975f5c5SAndroid Build Coastguard Worker
335*8975f5c5SAndroid Build Coastguard Worker DWORD exitCode = 0;
336*8975f5c5SAndroid Build Coastguard Worker if (::GetExitCodeProcess(mProcessInfo.hProcess, &exitCode) == FALSE)
337*8975f5c5SAndroid Build Coastguard Worker return -1;
338*8975f5c5SAndroid Build Coastguard Worker
339*8975f5c5SAndroid Build Coastguard Worker return static_cast<int>(exitCode);
340*8975f5c5SAndroid Build Coastguard Worker }
341*8975f5c5SAndroid Build Coastguard Worker
kill()342*8975f5c5SAndroid Build Coastguard Worker bool kill() override
343*8975f5c5SAndroid Build Coastguard Worker {
344*8975f5c5SAndroid Build Coastguard Worker if (!mStarted)
345*8975f5c5SAndroid Build Coastguard Worker return true;
346*8975f5c5SAndroid Build Coastguard Worker
347*8975f5c5SAndroid Build Coastguard Worker HANDLE newHandle;
348*8975f5c5SAndroid Build Coastguard Worker if (::DuplicateHandle(::GetCurrentProcess(), mProcessInfo.hProcess, ::GetCurrentProcess(),
349*8975f5c5SAndroid Build Coastguard Worker &newHandle, PROCESS_ALL_ACCESS, false,
350*8975f5c5SAndroid Build Coastguard Worker DUPLICATE_CLOSE_SOURCE) == FALSE)
351*8975f5c5SAndroid Build Coastguard Worker {
352*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error getting permission to terminate process: " << ::GetLastError()
353*8975f5c5SAndroid Build Coastguard Worker << "\n";
354*8975f5c5SAndroid Build Coastguard Worker return false;
355*8975f5c5SAndroid Build Coastguard Worker }
356*8975f5c5SAndroid Build Coastguard Worker mProcessInfo.hProcess = newHandle;
357*8975f5c5SAndroid Build Coastguard Worker
358*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_ENABLE_WINDOWS_UWP)
359*8975f5c5SAndroid Build Coastguard Worker if (::TerminateThread(mProcessInfo.hThread, 1) == FALSE)
360*8975f5c5SAndroid Build Coastguard Worker {
361*8975f5c5SAndroid Build Coastguard Worker std::cerr << "TerminateThread failed: " << GetLastError() << "\n";
362*8975f5c5SAndroid Build Coastguard Worker return false;
363*8975f5c5SAndroid Build Coastguard Worker }
364*8975f5c5SAndroid Build Coastguard Worker #endif // !defined(ANGLE_ENABLE_WINDOWS_UWP)
365*8975f5c5SAndroid Build Coastguard Worker
366*8975f5c5SAndroid Build Coastguard Worker if (::TerminateProcess(mProcessInfo.hProcess, 1) == FALSE)
367*8975f5c5SAndroid Build Coastguard Worker {
368*8975f5c5SAndroid Build Coastguard Worker std::cerr << "TerminateProcess failed: " << GetLastError() << "\n";
369*8975f5c5SAndroid Build Coastguard Worker return false;
370*8975f5c5SAndroid Build Coastguard Worker }
371*8975f5c5SAndroid Build Coastguard Worker
372*8975f5c5SAndroid Build Coastguard Worker mStarted = false;
373*8975f5c5SAndroid Build Coastguard Worker mTimer.stop();
374*8975f5c5SAndroid Build Coastguard Worker return true;
375*8975f5c5SAndroid Build Coastguard Worker }
376*8975f5c5SAndroid Build Coastguard Worker
377*8975f5c5SAndroid Build Coastguard Worker private:
378*8975f5c5SAndroid Build Coastguard Worker bool mStarted = false;
379*8975f5c5SAndroid Build Coastguard Worker ScopedPipe mStdoutPipe;
380*8975f5c5SAndroid Build Coastguard Worker ScopedPipe mStderrPipe;
381*8975f5c5SAndroid Build Coastguard Worker PROCESS_INFORMATION mProcessInfo = {};
382*8975f5c5SAndroid Build Coastguard Worker HANDLE mJobHandle = nullptr;
383*8975f5c5SAndroid Build Coastguard Worker };
384*8975f5c5SAndroid Build Coastguard Worker } // namespace
385*8975f5c5SAndroid Build Coastguard Worker
Sleep(unsigned int milliseconds)386*8975f5c5SAndroid Build Coastguard Worker void Sleep(unsigned int milliseconds)
387*8975f5c5SAndroid Build Coastguard Worker {
388*8975f5c5SAndroid Build Coastguard Worker ::Sleep(static_cast<DWORD>(milliseconds));
389*8975f5c5SAndroid Build Coastguard Worker }
390*8975f5c5SAndroid Build Coastguard Worker
WriteDebugMessage(const char * format,...)391*8975f5c5SAndroid Build Coastguard Worker void WriteDebugMessage(const char *format, ...)
392*8975f5c5SAndroid Build Coastguard Worker {
393*8975f5c5SAndroid Build Coastguard Worker va_list args;
394*8975f5c5SAndroid Build Coastguard Worker va_start(args, format);
395*8975f5c5SAndroid Build Coastguard Worker int size = vsnprintf(nullptr, 0, format, args);
396*8975f5c5SAndroid Build Coastguard Worker va_end(args);
397*8975f5c5SAndroid Build Coastguard Worker
398*8975f5c5SAndroid Build Coastguard Worker std::vector<char> buffer(size + 2);
399*8975f5c5SAndroid Build Coastguard Worker va_start(args, format);
400*8975f5c5SAndroid Build Coastguard Worker vsnprintf(buffer.data(), size + 1, format, args);
401*8975f5c5SAndroid Build Coastguard Worker va_end(args);
402*8975f5c5SAndroid Build Coastguard Worker
403*8975f5c5SAndroid Build Coastguard Worker OutputDebugStringA(buffer.data());
404*8975f5c5SAndroid Build Coastguard Worker }
405*8975f5c5SAndroid Build Coastguard Worker
LaunchProcess(const std::vector<const char * > & args,ProcessOutputCapture captureOutput)406*8975f5c5SAndroid Build Coastguard Worker Process *LaunchProcess(const std::vector<const char *> &args, ProcessOutputCapture captureOutput)
407*8975f5c5SAndroid Build Coastguard Worker {
408*8975f5c5SAndroid Build Coastguard Worker return new WindowsProcess(args, captureOutput);
409*8975f5c5SAndroid Build Coastguard Worker }
410*8975f5c5SAndroid Build Coastguard Worker
DeleteSystemFile(const char * path)411*8975f5c5SAndroid Build Coastguard Worker bool DeleteSystemFile(const char *path)
412*8975f5c5SAndroid Build Coastguard Worker {
413*8975f5c5SAndroid Build Coastguard Worker if (strlen(path) >= MAX_PATH)
414*8975f5c5SAndroid Build Coastguard Worker return false;
415*8975f5c5SAndroid Build Coastguard Worker
416*8975f5c5SAndroid Build Coastguard Worker const DWORD attr = ::GetFileAttributesA(path);
417*8975f5c5SAndroid Build Coastguard Worker // Report success if the file or path does not exist.
418*8975f5c5SAndroid Build Coastguard Worker if (attr == INVALID_FILE_ATTRIBUTES)
419*8975f5c5SAndroid Build Coastguard Worker {
420*8975f5c5SAndroid Build Coastguard Worker return ReturnSuccessOnNotFound();
421*8975f5c5SAndroid Build Coastguard Worker }
422*8975f5c5SAndroid Build Coastguard Worker
423*8975f5c5SAndroid Build Coastguard Worker // Clear the read-only bit if it is set.
424*8975f5c5SAndroid Build Coastguard Worker if ((attr & FILE_ATTRIBUTE_READONLY) &&
425*8975f5c5SAndroid Build Coastguard Worker !::SetFileAttributesA(path, attr & ~FILE_ATTRIBUTE_READONLY))
426*8975f5c5SAndroid Build Coastguard Worker {
427*8975f5c5SAndroid Build Coastguard Worker // It's possible for |path| to be gone now under a race with other deleters.
428*8975f5c5SAndroid Build Coastguard Worker return ReturnSuccessOnNotFound();
429*8975f5c5SAndroid Build Coastguard Worker }
430*8975f5c5SAndroid Build Coastguard Worker
431*8975f5c5SAndroid Build Coastguard Worker // We don't handle directories right now.
432*8975f5c5SAndroid Build Coastguard Worker if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
433*8975f5c5SAndroid Build Coastguard Worker {
434*8975f5c5SAndroid Build Coastguard Worker return false;
435*8975f5c5SAndroid Build Coastguard Worker }
436*8975f5c5SAndroid Build Coastguard Worker
437*8975f5c5SAndroid Build Coastguard Worker return !!::DeleteFileA(path) ? true : ReturnSuccessOnNotFound();
438*8975f5c5SAndroid Build Coastguard Worker }
439*8975f5c5SAndroid Build Coastguard Worker
GetNativeEGLLibraryNameWithExtension()440*8975f5c5SAndroid Build Coastguard Worker const char *GetNativeEGLLibraryNameWithExtension()
441*8975f5c5SAndroid Build Coastguard Worker {
442*8975f5c5SAndroid Build Coastguard Worker return "libEGL.dll";
443*8975f5c5SAndroid Build Coastguard Worker }
444*8975f5c5SAndroid Build Coastguard Worker } // namespace angle
445