xref: /aosp_15_r20/external/angle/util/windows/test_utils_win.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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