1//===- Win32/Program.cpp - Win32 Program Implementation ------- -*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file provides the Win32 specific implementation of the Program class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Windows.h"
15#include <cstdio>
16#include <fcntl.h>
17#include <io.h>
18#include <malloc.h>
19
20//===----------------------------------------------------------------------===//
21//=== WARNING: Implementation here must contain only Win32 specific code
22//===          and must not be UNIX code
23//===----------------------------------------------------------------------===//
24
25namespace {
26  struct Win32ProcessInfo {
27    HANDLE hProcess;
28    DWORD  dwProcessId;
29  };
30}
31
32namespace llvm {
33using namespace sys;
34
35Program::Program() : Data_(0) {}
36
37Program::~Program() {
38  if (Data_) {
39    Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
40    CloseHandle(wpi->hProcess);
41    delete wpi;
42    Data_ = 0;
43  }
44}
45
46// This function just uses the PATH environment variable to find the program.
47Path
48Program::FindProgramByName(const std::string& progName) {
49
50  // Check some degenerate cases
51  if (progName.length() == 0) // no program
52    return Path();
53  Path temp;
54  if (!temp.set(progName)) // invalid name
55    return Path();
56  // Return paths with slashes verbatim.
57  if (progName.find('\\') != std::string::npos ||
58      progName.find('/') != std::string::npos)
59    return temp;
60
61  // At this point, the file name is valid and does not contain slashes.
62  // Let Windows search for it.
63  char buffer[MAX_PATH];
64  char *dummy = NULL;
65  DWORD len = SearchPath(NULL, progName.c_str(), ".exe", MAX_PATH,
66                         buffer, &dummy);
67
68  // See if it wasn't found.
69  if (len == 0)
70    return Path();
71
72  // See if we got the entire path.
73  if (len < MAX_PATH)
74    return Path(buffer);
75
76  // Buffer was too small; grow and retry.
77  while (true) {
78    char *b = reinterpret_cast<char *>(_alloca(len+1));
79    DWORD len2 = SearchPath(NULL, progName.c_str(), ".exe", len+1, b, &dummy);
80
81    // It is unlikely the search failed, but it's always possible some file
82    // was added or removed since the last search, so be paranoid...
83    if (len2 == 0)
84      return Path();
85    else if (len2 <= len)
86      return Path(b);
87
88    len = len2;
89  }
90}
91
92static HANDLE RedirectIO(const Path *path, int fd, std::string* ErrMsg) {
93  HANDLE h;
94  if (path == 0) {
95    DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd),
96                    GetCurrentProcess(), &h,
97                    0, TRUE, DUPLICATE_SAME_ACCESS);
98    return h;
99  }
100
101  const char *fname;
102  if (path->isEmpty())
103    fname = "NUL";
104  else
105    fname = path->c_str();
106
107  SECURITY_ATTRIBUTES sa;
108  sa.nLength = sizeof(sa);
109  sa.lpSecurityDescriptor = 0;
110  sa.bInheritHandle = TRUE;
111
112  h = CreateFile(fname, fd ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ,
113                 &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS,
114                 FILE_ATTRIBUTE_NORMAL, NULL);
115  if (h == INVALID_HANDLE_VALUE) {
116    MakeErrMsg(ErrMsg, std::string(fname) + ": Can't open file for " +
117        (fd ? "input: " : "output: "));
118  }
119
120  return h;
121}
122
123/// ArgNeedsQuotes - Check whether argument needs to be quoted when calling
124/// CreateProcess.
125static bool ArgNeedsQuotes(const char *Str) {
126  return Str[0] == '\0' || strpbrk(Str, "\t \"&\'()*<>\\`^|") != 0;
127}
128
129/// CountPrecedingBackslashes - Returns the number of backslashes preceding Cur
130/// in the C string Start.
131static unsigned int CountPrecedingBackslashes(const char *Start,
132                                              const char *Cur) {
133  unsigned int Count = 0;
134  --Cur;
135  while (Cur >= Start && *Cur == '\\') {
136    ++Count;
137    --Cur;
138  }
139  return Count;
140}
141
142/// EscapePrecedingEscapes - Append a backslash to Dst for every backslash
143/// preceding Cur in the Start string.  Assumes Dst has enough space.
144static char *EscapePrecedingEscapes(char *Dst, const char *Start,
145                                    const char *Cur) {
146  unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Cur);
147  while (PrecedingEscapes > 0) {
148    *Dst++ = '\\';
149    --PrecedingEscapes;
150  }
151  return Dst;
152}
153
154/// ArgLenWithQuotes - Check whether argument needs to be quoted when calling
155/// CreateProcess and returns length of quoted arg with escaped quotes
156static unsigned int ArgLenWithQuotes(const char *Str) {
157  const char *Start = Str;
158  bool Quoted = ArgNeedsQuotes(Str);
159  unsigned int len = Quoted ? 2 : 0;
160
161  while (*Str != '\0') {
162    if (*Str == '\"') {
163      // We need to add a backslash, but ensure that it isn't escaped.
164      unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Str);
165      len += PrecedingEscapes + 1;
166    }
167    // Note that we *don't* need to escape runs of backslashes that don't
168    // precede a double quote!  See MSDN:
169    // http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx
170
171    ++len;
172    ++Str;
173  }
174
175  if (Quoted) {
176    // Make sure the closing quote doesn't get escaped by a trailing backslash.
177    unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Str);
178    len += PrecedingEscapes + 1;
179  }
180
181  return len;
182}
183
184
185bool
186Program::Execute(const Path& path,
187                 const char** args,
188                 const char** envp,
189                 const Path** redirects,
190                 unsigned memoryLimit,
191                 std::string* ErrMsg) {
192  if (Data_) {
193    Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
194    CloseHandle(wpi->hProcess);
195    delete wpi;
196    Data_ = 0;
197  }
198
199  if (!path.canExecute()) {
200    if (ErrMsg)
201      *ErrMsg = "program not executable";
202    return false;
203  }
204
205  // Windows wants a command line, not an array of args, to pass to the new
206  // process.  We have to concatenate them all, while quoting the args that
207  // have embedded spaces (or are empty).
208
209  // First, determine the length of the command line.
210  unsigned len = 0;
211  for (unsigned i = 0; args[i]; i++) {
212    len += ArgLenWithQuotes(args[i]) + 1;
213  }
214
215  // Now build the command line.
216  char *command = reinterpret_cast<char *>(_alloca(len+1));
217  char *p = command;
218
219  for (unsigned i = 0; args[i]; i++) {
220    const char *arg = args[i];
221    const char *start = arg;
222
223    bool needsQuoting = ArgNeedsQuotes(arg);
224    if (needsQuoting)
225      *p++ = '"';
226
227    while (*arg != '\0') {
228      if (*arg == '\"') {
229        // Escape all preceding escapes (if any), and then escape the quote.
230        p = EscapePrecedingEscapes(p, start, arg);
231        *p++ = '\\';
232      }
233
234      *p++ = *arg++;
235    }
236
237    if (needsQuoting) {
238      // Make sure our quote doesn't get escaped by a trailing backslash.
239      p = EscapePrecedingEscapes(p, start, arg);
240      *p++ = '"';
241    }
242    *p++ = ' ';
243  }
244
245  *p = 0;
246
247  // The pointer to the environment block for the new process.
248  char *envblock = 0;
249
250  if (envp) {
251    // An environment block consists of a null-terminated block of
252    // null-terminated strings. Convert the array of environment variables to
253    // an environment block by concatenating them.
254
255    // First, determine the length of the environment block.
256    len = 0;
257    for (unsigned i = 0; envp[i]; i++)
258      len += strlen(envp[i]) + 1;
259
260    // Now build the environment block.
261    envblock = reinterpret_cast<char *>(_alloca(len+1));
262    p = envblock;
263
264    for (unsigned i = 0; envp[i]; i++) {
265      const char *ev = envp[i];
266      size_t len = strlen(ev) + 1;
267      memcpy(p, ev, len);
268      p += len;
269    }
270
271    *p = 0;
272  }
273
274  // Create a child process.
275  STARTUPINFO si;
276  memset(&si, 0, sizeof(si));
277  si.cb = sizeof(si);
278  si.hStdInput = INVALID_HANDLE_VALUE;
279  si.hStdOutput = INVALID_HANDLE_VALUE;
280  si.hStdError = INVALID_HANDLE_VALUE;
281
282  if (redirects) {
283    si.dwFlags = STARTF_USESTDHANDLES;
284
285    si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg);
286    if (si.hStdInput == INVALID_HANDLE_VALUE) {
287      MakeErrMsg(ErrMsg, "can't redirect stdin");
288      return false;
289    }
290    si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg);
291    if (si.hStdOutput == INVALID_HANDLE_VALUE) {
292      CloseHandle(si.hStdInput);
293      MakeErrMsg(ErrMsg, "can't redirect stdout");
294      return false;
295    }
296    if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) {
297      // If stdout and stderr should go to the same place, redirect stderr
298      // to the handle already open for stdout.
299      DuplicateHandle(GetCurrentProcess(), si.hStdOutput,
300                      GetCurrentProcess(), &si.hStdError,
301                      0, TRUE, DUPLICATE_SAME_ACCESS);
302    } else {
303      // Just redirect stderr
304      si.hStdError = RedirectIO(redirects[2], 2, ErrMsg);
305      if (si.hStdError == INVALID_HANDLE_VALUE) {
306        CloseHandle(si.hStdInput);
307        CloseHandle(si.hStdOutput);
308        MakeErrMsg(ErrMsg, "can't redirect stderr");
309        return false;
310      }
311    }
312  }
313
314  PROCESS_INFORMATION pi;
315  memset(&pi, 0, sizeof(pi));
316
317  fflush(stdout);
318  fflush(stderr);
319  BOOL rc = CreateProcess(path.c_str(), command, NULL, NULL, TRUE, 0,
320                          envblock, NULL, &si, &pi);
321  DWORD err = GetLastError();
322
323  // Regardless of whether the process got created or not, we are done with
324  // the handles we created for it to inherit.
325  CloseHandle(si.hStdInput);
326  CloseHandle(si.hStdOutput);
327  CloseHandle(si.hStdError);
328
329  // Now return an error if the process didn't get created.
330  if (!rc) {
331    SetLastError(err);
332    MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") +
333               path.str() + "'");
334    return false;
335  }
336  Win32ProcessInfo* wpi = new Win32ProcessInfo;
337  wpi->hProcess = pi.hProcess;
338  wpi->dwProcessId = pi.dwProcessId;
339  Data_ = wpi;
340
341  // Make sure these get closed no matter what.
342  ScopedCommonHandle hThread(pi.hThread);
343
344  // Assign the process to a job if a memory limit is defined.
345  ScopedJobHandle hJob;
346  if (memoryLimit != 0) {
347    hJob = CreateJobObject(0, 0);
348    bool success = false;
349    if (hJob) {
350      JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
351      memset(&jeli, 0, sizeof(jeli));
352      jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
353      jeli.ProcessMemoryLimit = uintptr_t(memoryLimit) * 1048576;
354      if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation,
355                                  &jeli, sizeof(jeli))) {
356        if (AssignProcessToJobObject(hJob, pi.hProcess))
357          success = true;
358      }
359    }
360    if (!success) {
361      SetLastError(GetLastError());
362      MakeErrMsg(ErrMsg, std::string("Unable to set memory limit"));
363      TerminateProcess(pi.hProcess, 1);
364      WaitForSingleObject(pi.hProcess, INFINITE);
365      return false;
366    }
367  }
368
369  return true;
370}
371
372int
373Program::Wait(const Path &path,
374              unsigned secondsToWait,
375              std::string* ErrMsg) {
376  if (Data_ == 0) {
377    MakeErrMsg(ErrMsg, "Process not started!");
378    return -1;
379  }
380
381  Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
382  HANDLE hProcess = wpi->hProcess;
383
384  // Wait for the process to terminate.
385  DWORD millisecondsToWait = INFINITE;
386  if (secondsToWait > 0)
387    millisecondsToWait = secondsToWait * 1000;
388
389  if (WaitForSingleObject(hProcess, millisecondsToWait) == WAIT_TIMEOUT) {
390    if (!TerminateProcess(hProcess, 1)) {
391      MakeErrMsg(ErrMsg, "Failed to terminate timed-out program.");
392      // -2 indicates a crash or timeout as opposed to failure to execute.
393      return -2;
394    }
395    WaitForSingleObject(hProcess, INFINITE);
396  }
397
398  // Get its exit status.
399  DWORD status;
400  BOOL rc = GetExitCodeProcess(hProcess, &status);
401  DWORD err = GetLastError();
402
403  if (!rc) {
404    SetLastError(err);
405    MakeErrMsg(ErrMsg, "Failed getting status for program.");
406    // -2 indicates a crash or timeout as opposed to failure to execute.
407    return -2;
408  }
409
410  if (!status)
411    return 0;
412
413  // Pass 10(Warning) and 11(Error) to the callee as negative value.
414  if ((status & 0xBFFF0000U) == 0x80000000U)
415    return (int)status;
416
417  if (status & 0xFF)
418    return status & 0x7FFFFFFF;
419
420  return 1;
421}
422
423error_code Program::ChangeStdinToBinary(){
424  int result = _setmode( _fileno(stdin), _O_BINARY );
425  if (result == -1)
426    return error_code(errno, generic_category());
427  return make_error_code(errc::success);
428}
429
430error_code Program::ChangeStdoutToBinary(){
431  int result = _setmode( _fileno(stdout), _O_BINARY );
432  if (result == -1)
433    return error_code(errno, generic_category());
434  return make_error_code(errc::success);
435}
436
437error_code Program::ChangeStderrToBinary(){
438  int result = _setmode( _fileno(stderr), _O_BINARY );
439  if (result == -1)
440    return error_code(errno, generic_category());
441  return make_error_code(errc::success);
442}
443
444bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) {
445  // The documented max length of the command line passed to CreateProcess.
446  static const size_t MaxCommandStringLength = 32768;
447  size_t ArgLength = 0;
448  for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end();
449       I != E; ++I) {
450    // Account for the trailing space for every arg but the last one and the
451    // trailing NULL of the last argument.
452    ArgLength += ArgLenWithQuotes(*I) + 1;
453    if (ArgLength > MaxCommandStringLength) {
454      return false;
455    }
456  }
457  return true;
458}
459
460}
461