///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity - Singularity ABI
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: ProcessHandle.cs
//
// Note:
//
using System;
using System.Collections;
using System.Runtime.CompilerServices;
using System.Threading;
using Microsoft.Singularity;
using Microsoft.Singularity.Hal;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Loader;
using Microsoft.Singularity.Memory;
using Microsoft.Singularity.V1.Services;
using Microsoft.Singularity.V1.Security;
using Microsoft.Singularity.Security;
using Microsoft.Singularity.V1.Types;
using InternalProcessState = System.Threading.ProcessState;
using ExternalProcessState = Microsoft.Singularity.V1.Processes.ProcessState;
namespace Microsoft.Singularity.V1.Processes
{
public enum ProcessState {
Active,
Suspended,
Stopped,
}
//|
[CLSCompliant(false)]
public struct ProcessHandle
{
public readonly UIntPtr id;
public static readonly ProcessHandle Zero = new ProcessHandle();
internal ProcessHandle(UIntPtr id)
{
this.id = id;
}
[ExternalEntryPoint]
public static unsafe bool CreateImpl(
char *cmdName,
int cmdLength,
char *actionName,
int actionLength,
char *role,
int roleLength,
ProcessHandle *handle)
{
return Create(cmdName, cmdLength, actionName, actionLength,
role, roleLength, out *handle);
}
public static unsafe bool Create(char *cmdName,
int cmdLength,
char *actionName,
int actionLength,
char *role,
int roleLength,
out ProcessHandle handle) {
Kernel.Waypoint(550);
string mycmd = null;
if (cmdName != null && cmdLength > 0) {
mycmd = String.StringCTOR(cmdName, 0, cmdLength);
}
else {
//should never happen
DebugStub.Break();
}
string myrole = null;
if (role != null && roleLength > 0) {
myrole = String.StringCTOR(role, 0, roleLength);
}
string myaction = null;
if (actionName != null && actionLength > 0) {
myaction = String.StringCTOR(actionName, 0, actionLength);
}
Kernel.Waypoint(551);
//
// Find image to run.
//
Manifest appManifest;
IoMemory image = Binder.LoadImage(Thread.CurrentProcess,
mycmd,
out appManifest);
Kernel.Waypoint(552);
if (image != null && image.Length > 0 && appManifest != null) {
//
// Check manifest to see what resources are needed
//
//
// Create a Managed process, and a handle in the current
// process to hold it.
//
// REVIEW: create empty args array so that we
// do not need to change the process constructor;
String[] myargs;
if (myaction != null) {
myargs = new String[2];
myargs[1] = myaction;
}
else myargs = new String[1];
myargs[0] = mycmd;
Process process = new Process(Thread.CurrentProcess,
image,
myrole,
myargs,
appManifest);
//
// Check manifest to see what resources are needed
//
int epCount = appManifest.SetEndpoints(process, myaction);
#if VERBOSE
DebugStub.WriteLine("new process create: endpoints from manifest {0}",
__arglist( epCount));
#endif
int boolCount, longCount, stringCount, stringArrayCount;
bool ok = appManifest.GetParameterCounts(myaction,
out boolCount,
out longCount,
out stringCount,
out stringArrayCount);
//DebugStub.WriteLine("ProcessHandle: args strings={0}, longs={1}, bools={2}",
// __arglist(stringCount, longCount, boolCount));
process.SetBoolArgCount(boolCount);
process.SetLongArgCount(longCount);
process.SetStringArgCount(stringCount);
process.SetStringArrayArgCount(stringArrayCount);
handle = new ProcessHandle(
Thread.CurrentProcess.AllocateHandle(process));
Tracing.Log(Tracing.Debug,
"ProcessHandle.Create(out id={0:x8})",
handle.id);
Kernel.Waypoint(553);
IoMemory.Release(image);
appManifest = null;
return true;
}
Tracing.Log(Tracing.Debug, "ProcessHandle.Create() failed");
handle = new ProcessHandle();
Kernel.Waypoint(554);
return false;
}
[ExternalEntryPoint]
public static unsafe bool CreateImpl(
char *args,
int *argLengths,
int argCount,
char *role,
int roleLength,
int endpointCount,
ProcessHandle * handle)
{
return Create(args, argLengths, argCount, role, roleLength,
endpointCount, out *handle);
}
public static unsafe bool Create(char *args,
int *argLengths,
int argCount,
char *role,
int roleLength,
int endpointCount,
out ProcessHandle handle)
{
Kernel.Waypoint(550);
//
// Create a kernel String[] object populated with the argument
// values passed in from userland.
//
String[] arguments = new String[argCount];
int offset = 0;
for (int argument = 0; argument < argCount; argument++) {
arguments[argument] = String.StringCTOR(
args, offset, argLengths[argument]);
offset += argLengths[argument];
}
string myrole = null;
if (role != null && roleLength > 0) {
myrole = String.StringCTOR(role, 0, roleLength);
}
Kernel.Waypoint(551);
//
// Find image to run.
//
Manifest appManifest;
IoMemory image = Binder.LoadImage(Thread.CurrentProcess,
arguments[0],
out appManifest);
Kernel.Waypoint(552);
if (image != null && image.Length > 0 && appManifest != null) {
//
// Check manifest to see what resources are needed
//
//
// Create a Managed process, and a handle in the current
// process to hold it.
//
Process process = new Process(Thread.CurrentProcess,
image,
myrole,
arguments,
appManifest);
//
// Check manifest to see what resources are needed
//
int epCount = appManifest.SetEndpoints(process,null);
#if VERBOSE
DebugStub.WriteLine("endpoints passed in={0}, endpoints from manifest {1}",
__arglist(endpointCount, epCount));
#endif
if (epCount == 0) {
process.SetEndpointCount(endpointCount);
}
int boolCount, longCount, stringCount, stringArrayCount;
bool ok = appManifest.GetParameterCounts(null,
out boolCount,
out longCount,
out stringCount,
out stringArrayCount);
//DebugStub.WriteLine("ProcessHandle: args strings={0}, longs={1}, bools={2}",
// __arglist(stringCount, longCount, boolCount));
process.SetBoolArgCount(boolCount);
process.SetLongArgCount(longCount);
process.SetStringArgCount(stringCount);
process.SetStringArrayArgCount(stringArrayCount);
handle = new ProcessHandle(
Thread.CurrentProcess.AllocateHandle(process));
Tracing.Log(Tracing.Debug,
"ProcessHandle.Create(out id={0:x8})",
handle.id);
Kernel.Waypoint(553);
IoMemory.Release(image);
appManifest = null;
return true;
}
Tracing.Log(Tracing.Debug, "ProcessHandle.Create() failed");
handle = new ProcessHandle();
Kernel.Waypoint(554);
return false;
}
///
/// Given 2 system types generate and initialize the two endpoints of
/// a channel. The imp side will be set in the processes startup endpoint array
/// at position "index". The exp side will be bound to a service based on global policy
///
[ExternalEntryPoint]
public static unsafe bool BindToService(
ProcessHandle handle,
SystemType impType,
SystemType expType,
char *contractChars,
int contractLen,
int startState,
int index)
{
//convert contract to string
if (contractLen == 0) return false;
Process process = HandleTable.GetHandle(handle.id) as Process;
string contract = String.StringCTOR(contractChars, 0, contractLen);
if (contract == null) return false;
return Binder.BindToService(process,
impType,
expType,
contract,
startState,
index);
}
[ExternalEntryPoint]
public static unsafe bool SetStartupEndpoint(ProcessHandle handle,
int index,
SharedHeapService.Allocation * endpoint)
{
Tracing.Log(Tracing.Debug,
"ProcessHandle.SetStartupEndpoint(id={0:x8}, ndx={1}, ep={2:x8})",
handle.id, (UIntPtr)index, (UIntPtr)endpoint);
//
// Convert the handle to a process; set the endpoint.
//
SharedHeap.Allocation *ep = (SharedHeap.Allocation *)endpoint;
Process process = HandleTable.GetHandle(handle.id) as Process;
return process.SetEndpoint(index, ref ep);
}
[ExternalEntryPoint]
public static void Dispose(ProcessHandle handle)
{
Tracing.Log(Tracing.Debug, "ProcessHandle.Dispose(id={0:x8})",
handle.id);
//
// Releasing the handle will allow the process to be
// garbage-collected.
//
Thread.CurrentProcess.ReleaseHandle(handle.id);
}
[ExternalEntryPoint]
public static bool Start(ProcessHandle handle)
{
Tracing.Log(Tracing.Debug, "ProcessHandle.Start(id={0:x8})",
handle.id);
//
// Convert the handle to a process; call Start method.
//
Process process = HandleTable.GetHandle(handle.id) as Process;
return process.Start();
}
[ExternalEntryPoint]
public static unsafe void JoinImpl(ProcessHandle handle, bool * started)
{
Join(handle, out *started);
}
public static void Join(ProcessHandle handle, out bool started)
{
Tracing.Log(Tracing.Debug, "ProcessHandle.Join(id={0:x8})",
handle.id);
//
// Convert the handle to a process; call Join method.
//
Process process = HandleTable.GetHandle(handle.id) as Process;
process.Join(out started);
}
[ExternalEntryPoint]
public static unsafe bool JoinImpl(
ProcessHandle handle,
TimeSpan timeout,
bool * started)
{
return Join(handle, timeout, out *started);
}
public static bool Join(ProcessHandle handle,
TimeSpan timeout,
out bool started)
{
Tracing.Log(Tracing.Debug, "ProcessHandle.Join(id={0:x8})",
handle.id);
//
// Convert the handle to a process; call Join method.
//
Process process = HandleTable.GetHandle(handle.id) as Process;
bool ret = process.Join(timeout, out started);
return ret;
}
[ExternalEntryPoint]
public static unsafe bool JoinImpl(
ProcessHandle handle,
SchedulerTime stop,
bool * started)
{
return Join(handle, stop, out *started);
}
public static bool Join(ProcessHandle handle,
SchedulerTime stop,
out bool started)
{
Tracing.Log(Tracing.Debug, "ProcessHandle.Join(id={0:x8})",
handle.id);
//
// Convert the handle to a process; call Join method.
//
Process process = HandleTable.GetHandle(handle.id) as Process;
bool ret = process.Join(stop, out started);
return ret;
}
[ExternalEntryPoint]
public static bool Suspend(ProcessHandle handle, bool recursive)
{
Tracing.Log(Tracing.Debug, "ProcessHandle.Suspend(id={0:x8})",
handle.id);
//
// Convert the handle to a process; call Suspend method.
//
Process process = HandleTable.GetHandle(handle.id) as Process;
return process.Suspend(recursive);
}
[ExternalEntryPoint]
public static bool Resume(ProcessHandle handle, bool recursive)
{
Tracing.Log(Tracing.Debug, "ProcessHandle.Resume(id={0:x8})",
handle.id);
//
// Convert the handle to a process; call Resume method.
//
Process process = HandleTable.GetHandle(handle.id) as Process;
return process.Resume(recursive);
}
[ExternalEntryPoint]
public static void Stop(ProcessHandle handle, int exitcode)
{
Tracing.Log(Tracing.Debug, "ProcessHandle.Stop(id={0:x8})",
handle.id);
//
// Convert the handle to a process; call Stop method.
//
Process process = HandleTable.GetHandle(handle.id) as Process;
process.Stop(exitcode);
}
[ExternalEntryPoint]
public static void SuspendBarrier()
{
Process.SuspendBarrier();
}
[ExternalEntryPoint]
public static int GetProcessId(ProcessHandle handle)
{
Tracing.Log(Tracing.Debug, "ProcessHandle.GetProcessId(id={0:x8})",
handle.id);
//
// Convert the handle to a process; retrieve ProcessId.
//
Process process = HandleTable.GetHandle(handle.id) as Process;
return process.ProcessId;
}
[ExternalEntryPoint]
public static int GetExitCode(ProcessHandle handle)
{
Tracing.Log(Tracing.Debug, "ProcessHandle.GetExitCode(id={0:x8})",
handle.id);
//
// Convert the handle to a process; retrieve ExitCode.
//
Process process = HandleTable.GetHandle(handle.id) as Process;
return process.ExitCode;
}
[ExternalEntryPoint]
public static PrincipalHandle GetPrincipalHandle(ProcessHandle handle)
{
Tracing.Log(Tracing.Debug, "ProcessHandle.GetPrincipalHandle(id={0:x8})", handle.id);
Process process = HandleTable.GetHandle(handle.id) as Process;
return new PrincipalHandle(process.Principal.Val);
}
[ExternalEntryPoint]
public static ExternalProcessState GetState(ProcessHandle handle)
{
Process process = HandleTable.GetHandle(handle.id) as Process;
switch (process.State) {
case InternalProcessState.Unstarted:
case InternalProcessState.Running:
return ExternalProcessState.Active;
case InternalProcessState.Suspending:
case InternalProcessState.SuspendingRecursive:
case InternalProcessState.Suspended:
return ExternalProcessState.Suspended;
case InternalProcessState.Stopping:
case InternalProcessState.Stopped:
return ExternalProcessState.Stopped;
default:
// handle new missing case
DebugStub.Break();
return ExternalProcessState.Stopped;
}
}
[ExternalEntryPoint]
public static unsafe ParameterCode SetStartupStringArrayArg (
ProcessHandle handle,
int index,
char *args,
int *argLengths,
int argCount)
{
Process process = HandleTable.GetHandle(handle.id) as Process;
//
// Create a kernel String[] object populated with the argument
// values passed in from userland.
//
String[] arguments = new String[argCount];
int offset = 0;
for (int argument = 0; argument < argCount; argument++) {
arguments[argument] = String.StringCTOR(
args, offset, argLengths[argument]);
offset += argLengths[argument];
}
return (ParameterCode) process.SetStartupStringArrayArg(index, arguments);
}
#if false
[ExternalEntryPoint]
public static int GetStartupStringArgCount(ProcessHandle handle) {
Process process = HandleTable.GetHandle(handle.id) as Process;
return process.GetStartupStringArgCount();
}
[ExternalEntryPoint]
public static unsafe int GetStartupStringArg(ProcessHandle handle, int arg, char * output, int maxput) {
Process process = HandleTable.GetHandle(handle.id) as Process;
string s = process.GetStartupStringArg(arg);
Tracing.Log(Tracing.Debug,
"Process.GetStartupStringArg(arg={0}, out={1:x8}, max={2}) = {3}",
(UIntPtr)unchecked((uint)arg),
(UIntPtr)output,
(UIntPtr)unchecked((uint)maxput),
(UIntPtr)unchecked((uint)(s != null ? s.Length : 0)));
if (s == null) {
return 0;
}
if (output == null) {
return s.Length + 1;
}
return s.InternalGetChars(output, maxput);
}
#endif
[ExternalEntryPoint]
public static unsafe ParameterCode SetStartupStringArg(
ProcessHandle handle, int arg, char * input, int length)
{
string s;
if (length == 0) s = null;
else s = String.StringCTOR(input, 0, length);
Process process = HandleTable.GetHandle(handle.id) as Process;
return (ParameterCode) process.SetStartupStringArg(arg, s);
}
#if false
[ExternalEntryPoint]
public static int GetStartupLongArgCount(ProcessHandle handle) {
Process process = HandleTable.GetHandle(handle.id) as Process;
return process.GetStartupLongArgCount();
}
[ExternalEntryPoint]
public static ParameterCode GetStartupLongArg(ProcessHandle handle, int index, out long value) {
Process process = HandleTable.GetHandle(handle.id) as Process;
return (ParameterCode) process.GetStartupLongArg(index, out value);
}
#endif
[ExternalEntryPoint]
public static ParameterCode SetStartupLongArg(ProcessHandle handle, int index, long value) {
Process process = HandleTable.GetHandle(handle.id) as Process;
return (ParameterCode) process.SetStartupLongArg(index, value);
}
#if false
[ExternalEntryPoint]
public static int GetStartupBoolArgCount(ProcessHandle handle) {
Process process = HandleTable.GetHandle(handle.id) as Process;
return process.GetStartupBoolArgCount();
}
[ExternalEntryPoint]
public static ParameterCode GetStartupBoolArg(ProcessHandle handle, int index, out bool value) {
Process process = HandleTable.GetHandle(handle.id) as Process;
return (ParameterCode)process.GetStartupBoolArg(index, out value);
}
#endif
[ExternalEntryPoint]
public static ParameterCode SetStartupBoolArg(ProcessHandle handle, int index, bool value) {
Process process = HandleTable.GetHandle(handle.id) as Process;
return (ParameterCode) process.SetStartupBoolArg(index, value);
}
}
}