Skip to content

Commit

Permalink
use win32 functions for shimexe
Browse files Browse the repository at this point in the history
  • Loading branch information
lukesampson committed Jan 26, 2014
1 parent 5d94cdf commit 3dd2928
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 33 deletions.
102 changes: 69 additions & 33 deletions supporting/shimexe/shim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,61 @@
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace shim {

class Program {
[DllImport("kernel32.dll", SetLastError=true)]
static extern bool CreateProcess(string lpApplicationName,
string lpCommandLine, IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes, bool bInheritHandles,
uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct STARTUPINFO {
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}

[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION {
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}

[DllImport("kernel32.dll", SetLastError=true)]
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
const UInt32 INFINITE = 0xFFFFFFFF;

[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);

static int Main(string[] args) {
var exe = Assembly.GetExecutingAssembly().Location;
var dir = Path.GetDirectoryName(exe);
Expand All @@ -30,44 +81,29 @@ class Program {
add_args = "";
}

var p = new Process();
p.StartInfo.FileName = path;
p.StartInfo.Arguments = add_args + Serialize(args);
var si = new STARTUPINFO();
var pi = new PROCESS_INFORMATION();
if(!CreateProcess(path, add_args + Serialize(args), IntPtr.Zero, IntPtr.Zero,
bInheritHandles: true,
dwCreationFlags: 0,
lpEnvironment: IntPtr.Zero, // inherit parent
lpCurrentDirectory: null, // inherit parent
lpStartupInfo: ref si,
lpProcessInformation: out pi)) {

p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;

p.Start();
return Marshal.GetLastWin32Error();
}

ReadChars(p.StandardOutput, Console.Out);
ReadChars(p.StandardError, Console.Error);
WaitForSingleObject(pi.hProcess, INFINITE);

p.WaitForExit();
uint exit_code = 0;
GetExitCodeProcess(pi.hProcess, out exit_code);

Console.Write(p.StandardOutput.ReadToEnd());
Console.Error.Write(p.StandardError.ReadToEnd());

return p.ExitCode;
}
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

// Once stdout or stderr starts sending, keep forwarding the stream to the console
// until it stops sending. Otherwise the output from both streams is mixed up.
static object sync = new object();
static async void ReadChars(StreamReader r, TextWriter sendTo) {
var buffer = new char[100];
while(true) {
var read = await r.ReadAsync(buffer, 0, buffer.Length);
lock(sync) { // prevent other streams from writing
while(true) {
sendTo.Write(buffer, 0, read);

if(read < buffer.Length) break; // release lock
read = r.Read(buffer, 0, buffer.Length);
}
if(read == 0) return; // EOF
}
}
return (int)exit_code;
}

static string Serialize(string[] args) {
Expand Down
Binary file modified supporting/shimexe/shim.exe
Binary file not shown.

0 comments on commit 3dd2928

Please sign in to comment.