va_list args;
va_start (args, format);
- if (g_vasprintf (&msg, format, args) < 0)
+ if (g_vasprintf (&msg, format, args) < 0) {
+ va_end (args);
return;
+ }
va_end (args);
if (!stdout_handler)
va_list args;
va_start (args, format);
- if (g_vasprintf (&msg, format, args) < 0)
+ if (g_vasprintf (&msg, format, args) < 0) {
+ va_end (args);
return;
+ }
va_end (args);
if (!stderr_handler)
Test/resources/test.cs \
Test/resources/Sample.cs \
Test/resources/Sample.vb \
- Test/resources/junk.txt \
- Test/test-config-file*
+ Test/resources/junk.txt
Test/resources/test.dll: Test/resources/test.cs
$(CSCOMPILE) -target:library /out:$@ $<
public void Constructor_StringMode ()
{
string test = "string-filemode";
- IsolatedStorageFileStream isfs = new IsolatedStorageFileStream (test, FileMode.Create);
- CheckCommonDetails (test, isfs, true, true);
+ using (var isfs = new IsolatedStorageFileStream (test, FileMode.Create)) {
+ CheckCommonDetails (test, isfs, true, true);
+ }
}
[Test]
public void Constructor_StringModeAccess ()
{
string test = "string-filemode-fileaccess";
- IsolatedStorageFileStream isfs = new IsolatedStorageFileStream (test, FileMode.Create, FileAccess.ReadWrite);
- CheckCommonDetails (test, isfs, true, true);
+ using (var isfs = new IsolatedStorageFileStream (test, FileMode.Create, FileAccess.ReadWrite)) {
+ CheckCommonDetails (test, isfs, true, true);
+ }
}
[Test]
public void Constructor_StringModeAccessShare ()
{
string test = "string-filemode-fileaccess-fileshare";
- IsolatedStorageFileStream isfs = new IsolatedStorageFileStream (test, FileMode.Create, FileAccess.Write, FileShare.Read);
- CheckCommonDetails (test, isfs, false, true);
+ using (var isfs = new IsolatedStorageFileStream (test, FileMode.Create, FileAccess.Write, FileShare.Read)) {
+ CheckCommonDetails (test, isfs, false, true);
+ }
}
[Test]
[ExpectedException (typeof (IsolatedStorageException))]
public void Handle ()
{
- IsolatedStorageFileStream isfs = new IsolatedStorageFileStream ("handle", FileMode.Create);
- IntPtr p = isfs.Handle;
+ using (var isfs = new IsolatedStorageFileStream ("handle", FileMode.Create)) {
+ IntPtr p = isfs.Handle;
+ }
}
[Test]
public void RootPath ()
{
- new IsolatedStorageFileStream ("/rootpath", FileMode.Create);
+ new IsolatedStorageFileStream ("/rootpath", FileMode.Create).Close ();
}
[Test]
MustTLE (string.Format ("{0}ZZZZ,{1}", typeof (MyRealEnum).FullName, aqn));
}
+ [Test]
+ public void GetTypeExceptionMsg () {
+ string typeName = "system.int32, foo";
+ try {
+ Type.GetType(typeName, true, false);
+ } catch (TypeLoadException ex) {
+ Assert.IsTrue (ex.Message.Contains ("system.int32"));
+ Assert.IsTrue (ex.Message.Contains ("foo"));
+ }
+ }
+
delegate void MyAction<in T>(T ag);
[Test] //bug #668506
+++ /dev/null
-// CS1691: `2' is not a valid warning number
-// Line: 0
-// Compiler options: -warnaserror -warnaserror:1691,2
-
+++ /dev/null
-// CS1691: `20' is not a valid warning number
-// Line: 0
-// Compiler options: -warnaserror -warnaserror-:20
-
+++ /dev/null
-// CS1691: `20' is not a valid warning number
-// Line: 0
-// Compiler options: -warnaserror -nowarn:20
-
+++ /dev/null
-// CS1691: `1' is not a valid warning number
-// Line: 5
-// Compiler options: -warnaserror
-
-#pragma warning disable 1
-
+++ /dev/null
-// CS1904: `4013' is not a valid warning number
-// Line: 0
-// Compiler options: -nowarn:4014,4013
-
-class ClassMain {
- public static void Main () {}
-}
-
8009, 8094
};
- static HashSet<int> AllWarningsHashSet;
-
public Report (CompilerContext context, ReportPrinter printer)
{
if (context == null)
- throw new ArgumentNullException ("settings");
+ throw new ArgumentNullException ("context");
if (printer == null)
throw new ArgumentNullException ("printer");
extra_information.Add (msg);
}
- public bool CheckWarningCode (int code, Location loc)
- {
- if (AllWarningsHashSet == null)
- AllWarningsHashSet = new HashSet<int> (AllWarnings);
-
- if (AllWarningsHashSet.Contains (code))
- return true;
-
- Warning (1691, 1, loc, "`{0}' is not a valid warning number", code);
- return false;
- }
-
public void ExtraInformation (Location loc, string msg)
{
extra_information.Add (String.Format ("{0} {1}", loc, msg));
public void WarningDisable (Location location, int code, Report Report)
{
- if (Report.CheckWarningCode (code, location))
- regions.Add (new Disable (location.Row, code));
+ regions.Add (new Disable (location.Row, code));
}
public void WarningEnable (int line)
public void WarningEnable (Location location, int code, CompilerContext context)
{
- if (!context.Report.CheckWarningCode (code, location))
- return;
-
if (context.Settings.IsWarningDisabledGlobally (code))
context.Report.Warning (1635, 1, location, "Cannot restore warning `CS{0:0000}' because it was disabled globally", code);
public bool ProcessWarningsList (string text, Action<int> action)
{
- bool valid = true;
foreach (string wid in text.Split (numeric_value_separator, StringSplitOptions.RemoveEmptyEntries)) {
var warning = wid;
if (warning.Length == 6 && warning [0] == 'C' && warning [1] == 'S')
continue;
}
- if (report.CheckWarningCode (id, Location.Null)) {
- action (id);
- } else {
- report.Error (1904, "`{0}' is not a valid warning number", wid);
- valid = false;
- }
+ action (id);
}
- return valid;
+ return true;
}
void Error_RequiresArgument (string option)
<Reference Include="System" />\r
<Reference Include="System.Core" />\r
<Reference Include="System.Xml" />\r
- <Reference Include="Mono.Cecil">\r
- <HintPath>..\..\class\lib\net_4_x\Mono.Cecil.dll</HintPath>\r
- </Reference>\r
</ItemGroup>\r
<ItemGroup>\r
<Compile Include="AssemblyResolver.cs" />\r
<Compile Include="..\..\class\Mono.Options\Mono.Options\Options.cs">\r
<Link>Options.cs</Link>\r
</Compile>\r
+\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil.Cil\*.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil.Metadata\*.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil.PE\*.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ArrayType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyFlags.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyHashAlgorithm.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyLinkedResource.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyNameDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyNameReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyReader.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\AssemblyWriter.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\BaseAssemblyResolver.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\CallSite.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\CustomAttribute.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\DefaultAssemblyResolver.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\EmbeddedResource.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\EventAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\EventDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\EventReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ExportedType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\FieldAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\FieldDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\FieldReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\FileAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\FunctionPointerType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\GenericInstanceMethod.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\GenericInstanceType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\GenericParameter.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\GenericParameterAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IConstantProvider.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ICustomAttributeProvider.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IGenericInstance.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IGenericParameterProvider.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IMarshalInfoProvider.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IMemberDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IMetadataScope.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IMetadataTokenProvider.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\IMethodSignature.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\Import.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\LinkedResource.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ManifestResourceAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MarshalInfo.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MemberDefinitionCollection.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MemberReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MetadataResolver.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MetadataSystem.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodCallingConvention.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodImplAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodReturnType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodSemanticsAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\MethodSpecification.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\Modifiers.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ModuleDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ModuleKind.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ModuleReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\NativeType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ParameterAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ParameterDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ParameterDefinitionCollection.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ParameterReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PinnedType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PInvokeAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PInvokeInfo.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PointerType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PropertyAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PropertyDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\PropertyReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\ReferenceType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\Resource.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\SecurityDeclaration.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\SentinelType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TargetRuntime.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\Treatments.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeAttributes.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeDefinition.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeDefinitionCollection.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeParser.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeReference.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeSpecification.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\TypeSystem.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\VariantType.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Cecil\WindowsRuntimeProjections.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Collections.Generic\*.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono.Security.Cryptography\*.cs" />\r
+ <Compile Include="..\..\..\external\cecil\Mono\*.cs" /> \r
</ItemGroup>\r
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
SUBDIRS =
include ../../build/rules.make
-LIB_REFS = Mono.Cecil System.Xml System.Core System System.Xml.Linq
+LIB_REFS = System.Xml System.Core System System.Xml.Linq
LOCAL_MCS_FLAGS =
PROGRAM = mono-api-html.exe
esname = get_escaped_class_name (c);
- if (c->generic_class) {
- MonoGenericClass *gclass = c->generic_class;
+ if (mono_class_is_ginst (c)) {
+ MonoGenericClass *gclass = mono_class_get_generic_class (c);
MonoGenericInst *inst = gclass->context.class_inst;
GString *str = g_string_new ("");
int i;
case 4: /* TypeSpec */
klass = mono_class_get_full (m, MONO_TOKEN_TYPE_SPEC | idx, (MonoGenericContext *) container);
g_assert (klass);
- return klass->generic_class ? klass->generic_class->container_class->generic_container : NULL;
+ return mono_class_is_ginst (klass) ? mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class) : NULL;
}
g_assert_not_reached ();
return NULL;
MonoMethod *mh = NULL;
mh = mono_get_method_checked (m, decl, NULL, (MonoGenericContext *) container, &error);
- if (mh && (mh->klass && (mh->klass->generic_class || mh->klass->generic_container))) {
+ if (mh && (mh->klass && (mono_class_is_ginst (mh->klass) || mono_class_is_gtd (mh->klass)))) {
char *meth_str;
char *ret;
libwapiincludedir = $(includedir)/mono-$(API_VER)/mono/io-layer
OTHER_H = \
- access.h \
context.h \
error.h \
io.h \
io-portability.h \
macros.h \
messages.h \
- processes.h \
security.h \
sockets.h \
status.h \
wapi-remap.h
OTHER_SRC = \
- access.h \
context.c \
context.h \
error.c \
messages.c \
messages.h \
posix.c \
- processes.c \
- processes.h \
- process-private.h \
security.c \
security.h \
sockets.c \
status.h \
timefuncs.c \
timefuncs.h \
- timefuncs-private.h \
types.h \
uglify.h \
versioninfo.c \
+++ /dev/null
-/*
- * access.h: Access control definitions
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_ACCESS_H_
-#define _WAPI_ACCESS_H_
-
-#include <glib.h>
-
-#include <mono/io-layer/wapi.h>
-
-#define SYNCHRONIZE 0x00100000
-#define STANDARD_RIGHTS_REQUIRED 0x000f0000
-
-#endif /* _WAPI_ACCESS_H_ */
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
#include <mono/io-layer/io-private.h>
-#include <mono/io-layer/timefuncs-private.h>
+#include <mono/io-layer/timefuncs.h>
#include <mono/io-layer/io-portability.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/strenc.h>
+++ /dev/null
-/*
- * process-private.h: Private definitions for process handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Novell, Inc.
- */
-
-#ifndef _WAPI_PROCESS_PRIVATE_H_
-#define _WAPI_PROCESS_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-
-#include <mono/utils/mono-os-semaphore.h>
-
-/* There doesn't seem to be a defined symbol for this */
-#define _WAPI_PROCESS_CURRENT (gpointer)0xFFFFFFFF
-
-/*
- * Handles > _WAPI_PROCESS_UNHANDLED are pseudo handles which represent processes
- * not started by the runtime.
- */
-/* This marks a system process that we don't have a handle on */
-/* FIXME: Cope with PIDs > sizeof guint */
-#define _WAPI_PROCESS_UNHANDLED (1 << (8*sizeof(pid_t)-1))
-#define _WAPI_PROCESS_UNHANDLED_PID_MASK (-1 & ~_WAPI_PROCESS_UNHANDLED)
-#define WAPI_IS_PSEUDO_PROCESS_HANDLE(handle) ((GPOINTER_TO_UINT(handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED)
-#define WAPI_PID_TO_HANDLE(pid) GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + (pid))
-#define WAPI_HANDLE_TO_PID(handle) (GPOINTER_TO_UINT ((handle)) - _WAPI_PROCESS_UNHANDLED)
-
-void _wapi_processes_init (void);
-extern gpointer _wapi_process_duplicate (void);
-extern void wapi_processes_cleanup (void);
-
-/*
- * MonoProcess describes processes we create.
- * It contains a semaphore that can be waited on in order to wait
- * for process termination. It's accessed in our SIGCHLD handler,
- * when status is updated (and pid cleared, to not clash with
- * subsequent processes that may get executed).
- */
-struct MonoProcess {
- pid_t pid; /* the pid of the process. This value is only valid until the process has exited. */
- MonoSemType exit_sem; /* this semaphore will be released when the process exits */
- int status; /* the exit status */
- gint32 handle_count; /* the number of handles to this mono_process instance */
- /* we keep a ref to the creating _WapiHandle_process handle until
- * the process has exited, so that the information there isn't lost.
- */
- gpointer handle;
- gboolean freeable;
- struct MonoProcess *next;
-};
-
-typedef struct MonoProcess MonoProcess;
-
-/*
- * _WapiHandle_process is a structure containing all the required information
- * for process handling.
- */
-struct _WapiHandle_process
-{
- pid_t id;
- guint32 exitstatus;
- gpointer main_thread;
- WapiFileTime create_time;
- WapiFileTime exit_time;
- char *proc_name;
- size_t min_working_set;
- size_t max_working_set;
- gboolean exited;
- struct MonoProcess *mono_process;
-};
-
-typedef struct _WapiHandle_process WapiHandle_process;
-
-#endif /* _WAPI_PROCESS_PRIVATE_H_ */
+++ /dev/null
-/*
- * processes.c: Process handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2011 Novell, Inc.
- * Copyright 2011 Xamarin Inc
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-#include <pthread.h>
-#include <sched.h>
-#include <sys/time.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#include <sys/time.h>
-#include <fcntl.h>
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <ctype.h>
-
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-
-/* sys/resource.h (for rusage) is required when using osx 10.3 (but not 10.4) */
-#ifdef __APPLE__
-#include <TargetConditionals.h>
-#include <sys/resource.h>
-#ifdef HAVE_LIBPROC_H
-/* proc_name */
-#include <libproc.h>
-#endif
-#endif
-
-#if defined(PLATFORM_MACOSX)
-#define USE_OSX_LOADER
-#endif
-
-#if ( defined(__OpenBSD__) || defined(__FreeBSD__) ) && defined(HAVE_LINK_H)
-#define USE_BSD_LOADER
-#endif
-
-#if defined(__HAIKU__)
-#define USE_HAIKU_LOADER
-#endif
-
-#if defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER)
-#include <sys/proc.h>
-#include <sys/sysctl.h>
-# if !defined(__OpenBSD__)
-# include <sys/utsname.h>
-# endif
-# if defined(__FreeBSD__)
-# include <sys/user.h> /* struct kinfo_proc */
-# endif
-#endif
-
-#ifdef PLATFORM_SOLARIS
-/* procfs.h cannot be included if this define is set, but it seems to work fine if it is undefined */
-#if _FILE_OFFSET_BITS == 64
-#undef _FILE_OFFSET_BITS
-#include <procfs.h>
-#define _FILE_OFFSET_BITS 64
-#else
-#include <procfs.h>
-#endif
-#endif
-
-#ifdef __HAIKU__
-#include <KernelKit.h>
-#endif
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/process-private.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/strenc.h>
-#include <mono/utils/mono-path.h>
-#include <mono/io-layer/timefuncs-private.h>
-#include <mono/utils/mono-time.h>
-#include <mono/utils/mono-membar.h>
-#include <mono/utils/mono-os-mutex.h>
-#include <mono/utils/mono-signal-handler.h>
-#include <mono/utils/mono-proclib.h>
-#include <mono/utils/mono-once.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/metadata/w32handle.h>
-
-#define STILL_ACTIVE STATUS_PENDING
-
-/* The process' environment strings */
-#if defined(__APPLE__)
-#if defined (TARGET_OSX)
-/* Apple defines this in crt_externs.h but doesn't provide that header for
- * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
- * in fact exist on all implementations (so far)
- */
-gchar ***_NSGetEnviron(void);
-#define environ (*_NSGetEnviron())
-#else
-static char *mono_environ[1] = { NULL };
-#define environ mono_environ
-#endif /* defined (TARGET_OSX) */
-#else
-extern char **environ;
-#endif
-
-static guint32 process_wait (gpointer handle, guint32 timeout, gboolean *alerted);
-static void process_close (gpointer handle, gpointer data);
-static void process_details (gpointer data);
-static const gchar* process_typename (void);
-static gsize process_typesize (void);
-static gboolean is_pid_valid (pid_t pid);
-
-#if !(defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER) || defined(USE_HAIKU_LOADER))
-static FILE *
-open_process_map (int pid, const char *mode);
-#endif
-
-static MonoW32HandleOps _wapi_process_ops = {
- process_close, /* close_shared */
- NULL, /* signal */
- NULL, /* own */
- NULL, /* is_owned */
- process_wait, /* special_wait */
- NULL, /* prewait */
- process_details, /* details */
- process_typename, /* typename */
- process_typesize, /* typesize */
-};
-
-#if HAVE_SIGACTION
-static struct sigaction previous_chld_sa;
-#endif
-static mono_once_t process_sig_chld_once = MONO_ONCE_INIT;
-static void process_add_sigchld_handler (void);
-
-/* The signal-safe logic to use mono_processes goes like this:
- * - The list must be safe to traverse for the signal handler at all times.
- * It's safe to: prepend an entry (which is a single store to 'mono_processes'),
- * unlink an entry (assuming the unlinked entry isn't freed and doesn't
- * change its 'next' pointer so that it can still be traversed).
- * When cleaning up we first unlink an entry, then we verify that
- * the read lock isn't locked. Then we can free the entry, since
- * we know that nobody is using the old version of the list (including
- * the unlinked entry).
- * We also need to lock when adding and cleaning up so that those two
- * operations don't mess with eachother. (This lock is not used in the
- * signal handler)
- */
-static struct MonoProcess *mono_processes = NULL;
-static volatile gint32 mono_processes_cleaning_up = 0;
-static mono_mutex_t mono_processes_mutex;
-static void mono_processes_cleanup (void);
-
-static gpointer current_process;
-static char *cli_launcher;
-
-static WapiHandle_process *
-lookup_process_handle (gpointer handle)
-{
- WapiHandle_process *process_data;
- gboolean ret;
-
- ret = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS,
- (gpointer *)&process_data);
- if (!ret)
- return NULL;
- return process_data;
-}
-
-/* Check if a pid is valid - i.e. if a process exists with this pid. */
-static gboolean
-is_pid_valid (pid_t pid)
-{
- gboolean result = FALSE;
-
-#if defined(HOST_WATCHOS)
- result = TRUE; // TODO: Rewrite using sysctl
-#elif defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__FreeBSD__)
- if (((kill(pid, 0) == 0) || (errno == EPERM)) && pid != 0)
- result = TRUE;
-#elif defined(__HAIKU__)
- team_info teamInfo;
- if (get_team_info ((team_id)pid, &teamInfo) == B_OK)
- result = TRUE;
-#else
- char *dir = g_strdup_printf ("/proc/%d", pid);
- if (!access (dir, F_OK))
- result = TRUE;
- g_free (dir);
-#endif
-
- return result;
-}
-
-static void
-process_set_defaults (WapiHandle_process *process_handle)
-{
- /* These seem to be the defaults on w2k */
- process_handle->min_working_set = 204800;
- process_handle->max_working_set = 1413120;
-
- _wapi_time_t_to_filetime (time (NULL), &process_handle->create_time);
-}
-
-static int
-len16 (const gunichar2 *str)
-{
- int len = 0;
-
- while (*str++ != 0)
- len++;
-
- return len;
-}
-
-static gunichar2 *
-utf16_concat (const gunichar2 *first, ...)
-{
- va_list args;
- int total = 0, i;
- const gunichar2 *s;
- gunichar2 *ret;
-
- va_start (args, first);
- total += len16 (first);
- for (s = va_arg (args, gunichar2 *); s != NULL; s = va_arg(args, gunichar2 *)){
- total += len16 (s);
- }
- va_end (args);
-
- ret = g_new (gunichar2, total + 1);
- if (ret == NULL)
- return NULL;
-
- ret [total] = 0;
- i = 0;
- for (s = first; *s != 0; s++)
- ret [i++] = *s;
- va_start (args, first);
- for (s = va_arg (args, gunichar2 *); s != NULL; s = va_arg (args, gunichar2 *)){
- const gunichar2 *p;
-
- for (p = s; *p != 0; p++)
- ret [i++] = *p;
- }
- va_end (args);
-
- return ret;
-}
-
-static const gunichar2 utf16_space_bytes [2] = { 0x20, 0 };
-static const gunichar2 *utf16_space = utf16_space_bytes;
-static const gunichar2 utf16_quote_bytes [2] = { 0x22, 0 };
-static const gunichar2 *utf16_quote = utf16_quote_bytes;
-
-#ifdef DEBUG_ENABLED
-/* Useful in gdb */
-void
-print_utf16 (gunichar2 *str)
-{
- char *res;
-
- res = g_utf16_to_utf8 (str, -1, NULL, NULL, NULL);
- g_print ("%s\n", res);
- g_free (res);
-}
-#endif
-
-/* Implemented as just a wrapper around CreateProcess () */
-gboolean
-ShellExecuteEx (WapiShellExecuteInfo *sei)
-{
- gboolean ret;
- WapiProcessInformation process_info;
- gunichar2 *args;
-
- if (sei == NULL) {
- /* w2k just segfaults here, but we can do better than
- * that
- */
- SetLastError (ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- if (sei->lpFile == NULL)
- /* w2k returns TRUE for this, for some reason. */
- return TRUE;
-
- /* Put both executable and parameters into the second argument
- * to CreateProcess (), so it searches $PATH. The conversion
- * into and back out of utf8 is because there is no
- * g_strdup_printf () equivalent for gunichar2 :-(
- */
- args = utf16_concat (utf16_quote, sei->lpFile, utf16_quote, sei->lpParameters == NULL ? NULL : utf16_space, sei->lpParameters, NULL);
- if (args == NULL) {
- SetLastError (ERROR_INVALID_DATA);
- return FALSE;
- }
- ret = CreateProcess (NULL, args, NULL, NULL, TRUE,
- CREATE_UNICODE_ENVIRONMENT, NULL,
- sei->lpDirectory, NULL, &process_info);
- g_free (args);
-
- if (!ret && GetLastError () == ERROR_OUTOFMEMORY)
- return ret;
-
- if (!ret) {
- static char *handler;
- static gunichar2 *handler_utf16;
-
- if (handler_utf16 == (gunichar2 *)-1)
- return FALSE;
-
-#ifdef PLATFORM_MACOSX
- handler = g_strdup ("/usr/bin/open");
-#else
- /*
- * On Linux, try: xdg-open, the FreeDesktop standard way of doing it,
- * if that fails, try to use gnome-open, then kfmclient
- */
- handler = g_find_program_in_path ("xdg-open");
- if (handler == NULL){
- handler = g_find_program_in_path ("gnome-open");
- if (handler == NULL){
- handler = g_find_program_in_path ("kfmclient");
- if (handler == NULL){
- handler_utf16 = (gunichar2 *) -1;
- return FALSE;
- } else {
- /* kfmclient needs exec argument */
- char *old = handler;
- handler = g_strconcat (old, " exec",
- NULL);
- g_free (old);
- }
- }
- }
-#endif
- handler_utf16 = g_utf8_to_utf16 (handler, -1, NULL, NULL, NULL);
- g_free (handler);
-
- /* Put quotes around the filename, in case it's a url
- * that contains #'s (CreateProcess() calls
- * g_shell_parse_argv(), which deliberately throws
- * away anything after an unquoted #). Fixes bug
- * 371567.
- */
- args = utf16_concat (handler_utf16, utf16_space, utf16_quote,
- sei->lpFile, utf16_quote,
- sei->lpParameters == NULL ? NULL : utf16_space,
- sei->lpParameters, NULL);
- if (args == NULL) {
- SetLastError (ERROR_INVALID_DATA);
- return FALSE;
- }
- ret = CreateProcess (NULL, args, NULL, NULL, TRUE,
- CREATE_UNICODE_ENVIRONMENT, NULL,
- sei->lpDirectory, NULL, &process_info);
- g_free (args);
- if (!ret) {
- if (GetLastError () != ERROR_OUTOFMEMORY)
- SetLastError (ERROR_INVALID_DATA);
- return FALSE;
- }
- /* Shell exec should not return a process handle when it spawned a GUI thing, like a browser. */
- CloseHandle (process_info.hProcess);
- process_info.hProcess = NULL;
- }
-
- if (sei->fMask & SEE_MASK_NOCLOSEPROCESS)
- sei->hProcess = process_info.hProcess;
- else
- CloseHandle (process_info.hProcess);
-
- return ret;
-}
-
-static gboolean
-is_managed_binary (const char *filename)
-{
- int original_errno = errno;
-#if defined(HAVE_LARGE_FILE_SUPPORT) && defined(O_LARGEFILE)
- int file = open (filename, O_RDONLY | O_LARGEFILE);
-#else
- int file = open (filename, O_RDONLY);
-#endif
- off_t new_offset;
- unsigned char buffer[8];
- off_t file_size, optional_header_offset;
- off_t pe_header_offset, clr_header_offset;
- gboolean managed = FALSE;
- int num_read;
- guint32 first_word, second_word, magic_number;
-
- /* If we are unable to open the file, then we definitely
- * can't say that it is managed. The child mono process
- * probably wouldn't be able to open it anyway.
- */
- if (file < 0) {
- errno = original_errno;
- return FALSE;
- }
-
- /* Retrieve the length of the file for future sanity checks. */
- file_size = lseek (file, 0, SEEK_END);
- lseek (file, 0, SEEK_SET);
-
- /* We know we need to read a header field at offset 60. */
- if (file_size < 64)
- goto leave;
-
- num_read = read (file, buffer, 2);
-
- if ((num_read != 2) || (buffer[0] != 'M') || (buffer[1] != 'Z'))
- goto leave;
-
- new_offset = lseek (file, 60, SEEK_SET);
-
- if (new_offset != 60)
- goto leave;
-
- num_read = read (file, buffer, 4);
-
- if (num_read != 4)
- goto leave;
- pe_header_offset = buffer[0]
- | (buffer[1] << 8)
- | (buffer[2] << 16)
- | (buffer[3] << 24);
-
- if (pe_header_offset + 24 > file_size)
- goto leave;
-
- new_offset = lseek (file, pe_header_offset, SEEK_SET);
-
- if (new_offset != pe_header_offset)
- goto leave;
-
- num_read = read (file, buffer, 4);
-
- if ((num_read != 4) || (buffer[0] != 'P') || (buffer[1] != 'E') || (buffer[2] != 0) || (buffer[3] != 0))
- goto leave;
-
- /*
- * Verify that the header we want in the optional header data
- * is present in this binary.
- */
- new_offset = lseek (file, pe_header_offset + 20, SEEK_SET);
-
- if (new_offset != pe_header_offset + 20)
- goto leave;
-
- num_read = read (file, buffer, 2);
-
- if ((num_read != 2) || ((buffer[0] | (buffer[1] << 8)) < 216))
- goto leave;
-
- optional_header_offset = pe_header_offset + 24;
-
- /* Read the PE magic number */
- new_offset = lseek (file, optional_header_offset, SEEK_SET);
-
- if (new_offset != optional_header_offset)
- goto leave;
-
- num_read = read (file, buffer, 2);
-
- if (num_read != 2)
- goto leave;
-
- magic_number = (buffer[0] | (buffer[1] << 8));
-
- if (magic_number == 0x10B) // PE32
- clr_header_offset = 208;
- else if (magic_number == 0x20B) // PE32+
- clr_header_offset = 224;
- else
- goto leave;
-
- /* Read the CLR header address and size fields. These will be
- * zero if the binary is not managed.
- */
- new_offset = lseek (file, optional_header_offset + clr_header_offset, SEEK_SET);
-
- if (new_offset != optional_header_offset + clr_header_offset)
- goto leave;
-
- num_read = read (file, buffer, 8);
-
- /* We are not concerned with endianness, only with
- * whether it is zero or not.
- */
- first_word = *(guint32 *)&buffer[0];
- second_word = *(guint32 *)&buffer[4];
-
- if ((num_read != 8) || (first_word == 0) || (second_word == 0))
- goto leave;
-
- managed = TRUE;
-
-leave:
- close (file);
- errno = original_errno;
- return managed;
-}
-
-gboolean
-CreateProcessWithLogonW (const gunichar2 *username,
- const gunichar2 *domain,
- const gunichar2 *password,
- const guint32 logonFlags,
- const gunichar2 *appname,
- const gunichar2 *cmdline,
- guint32 create_flags,
- gpointer env,
- const gunichar2 *cwd,
- WapiStartupInfo *startup,
- WapiProcessInformation *process_info)
-{
- /* FIXME: use user information */
- return CreateProcess (appname, cmdline, NULL, NULL, FALSE, create_flags, env, cwd, startup, process_info);
-}
-
-static gboolean
-is_readable_or_executable (const char *prog)
-{
- struct stat buf;
- int a = access (prog, R_OK);
- int b = access (prog, X_OK);
- if (a != 0 && b != 0)
- return FALSE;
- if (stat (prog, &buf))
- return FALSE;
- if (S_ISREG (buf.st_mode))
- return TRUE;
- return FALSE;
-}
-
-static gboolean
-is_executable (const char *prog)
-{
- struct stat buf;
- if (access (prog, X_OK) != 0)
- return FALSE;
- if (stat (prog, &buf))
- return FALSE;
- if (S_ISREG (buf.st_mode))
- return TRUE;
- return FALSE;
-}
-
-static void
-switch_dir_separators (char *path)
-{
- size_t i, pathLength = strlen(path);
-
- /* Turn all the slashes round the right way, except for \' */
- /* There are probably other characters that need to be excluded as well. */
- for (i = 0; i < pathLength; i++) {
- if (path[i] == '\\' && i < pathLength - 1 && path[i+1] != '\'' )
- path[i] = '/';
- }
-}
-
-gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
- WapiSecurityAttributes *process_attrs G_GNUC_UNUSED,
- WapiSecurityAttributes *thread_attrs G_GNUC_UNUSED,
- gboolean inherit_handles, guint32 create_flags,
- gpointer new_environ, const gunichar2 *cwd,
- WapiStartupInfo *startup,
- WapiProcessInformation *process_info)
-{
-#if defined (HAVE_FORK) && defined (HAVE_EXECVE)
- char *cmd = NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL;
- char *dir = NULL, **env_strings = NULL, **argv = NULL;
- guint32 i, env_count = 0;
- gboolean ret = FALSE;
- gpointer handle = NULL;
- WapiHandle_process process_handle = {0}, *process_handle_data;
- GError *gerr = NULL;
- int in_fd, out_fd, err_fd;
- pid_t pid = 0;
- int startup_pipe [2] = {-1, -1};
- int dummy;
- struct MonoProcess *mono_process;
- gboolean fork_failed = FALSE;
-
- mono_once (&process_sig_chld_once, process_add_sigchld_handler);
-
- /* appname and cmdline specify the executable and its args:
- *
- * If appname is not NULL, it is the name of the executable.
- * Otherwise the executable is the first token in cmdline.
- *
- * Executable searching:
- *
- * If appname is not NULL, it can specify the full path and
- * file name, or else a partial name and the current directory
- * will be used. There is no additional searching.
- *
- * If appname is NULL, the first whitespace-delimited token in
- * cmdline is used. If the name does not contain a full
- * directory path, the search sequence is:
- *
- * 1) The directory containing the current process
- * 2) The current working directory
- * 3) The windows system directory (Ignored)
- * 4) The windows directory (Ignored)
- * 5) $PATH
- *
- * Just to make things more interesting, tokens can contain
- * white space if they are surrounded by quotation marks. I'm
- * beginning to understand just why windows apps are generally
- * so crap, with an API like this :-(
- */
- if (appname != NULL) {
- cmd = mono_unicode_to_external (appname);
- if (cmd == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL",
- __func__);
-
- SetLastError (ERROR_PATH_NOT_FOUND);
- goto free_strings;
- }
-
- switch_dir_separators(cmd);
- }
-
- if (cmdline != NULL) {
- args = mono_unicode_to_external (cmdline);
- if (args == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_PATH_NOT_FOUND);
- goto free_strings;
- }
- }
-
- if (cwd != NULL) {
- dir = mono_unicode_to_external (cwd);
- if (dir == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_PATH_NOT_FOUND);
- goto free_strings;
- }
-
- /* Turn all the slashes round the right way */
- switch_dir_separators(dir);
- }
-
-
- /* We can't put off locating the executable any longer :-( */
- if (cmd != NULL) {
- char *unquoted;
- if (g_ascii_isalpha (cmd[0]) && (cmd[1] == ':')) {
- /* Strip off the drive letter. I can't
- * believe that CP/M holdover is still
- * visible...
- */
- g_memmove (cmd, cmd+2, strlen (cmd)-2);
- cmd[strlen (cmd)-2] = '\0';
- }
-
- unquoted = g_shell_unquote (cmd, NULL);
- if (unquoted[0] == '/') {
- /* Assume full path given */
- prog = g_strdup (unquoted);
-
- /* Executable existing ? */
- if (!is_readable_or_executable (prog)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
- __func__, prog);
- g_free (unquoted);
- SetLastError (ERROR_FILE_NOT_FOUND);
- goto free_strings;
- }
- } else {
- /* Search for file named by cmd in the current
- * directory
- */
- char *curdir = g_get_current_dir ();
-
- prog = g_strdup_printf ("%s/%s", curdir, unquoted);
- g_free (curdir);
-
- /* And make sure it's readable */
- if (!is_readable_or_executable (prog)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
- __func__, prog);
- g_free (unquoted);
- SetLastError (ERROR_FILE_NOT_FOUND);
- goto free_strings;
- }
- }
- g_free (unquoted);
-
- args_after_prog = args;
- } else {
- char *token = NULL;
- char quote;
-
- /* Dig out the first token from args, taking quotation
- * marks into account
- */
-
- /* First, strip off all leading whitespace */
- args = g_strchug (args);
-
- /* args_after_prog points to the contents of args
- * after token has been set (otherwise argv[0] is
- * duplicated)
- */
- args_after_prog = args;
-
- /* Assume the opening quote will always be the first
- * character
- */
- if (args[0] == '\"' || args [0] == '\'') {
- quote = args [0];
- for (i = 1; args[i] != '\0' && args[i] != quote; i++);
- if (args [i + 1] == '\0' || g_ascii_isspace (args[i+1])) {
- /* We found the first token */
- token = g_strndup (args+1, i-1);
- args_after_prog = g_strchug (args + i + 1);
- } else {
- /* Quotation mark appeared in the
- * middle of the token. Just give the
- * whole first token, quotes and all,
- * to exec.
- */
- }
- }
-
- if (token == NULL) {
- /* No quote mark, or malformed */
- for (i = 0; args[i] != '\0'; i++) {
- if (g_ascii_isspace (args[i])) {
- token = g_strndup (args, i);
- args_after_prog = args + i + 1;
- break;
- }
- }
- }
-
- if (token == NULL && args[0] != '\0') {
- /* Must be just one token in the string */
- token = g_strdup (args);
- args_after_prog = NULL;
- }
-
- if (token == NULL) {
- /* Give up */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find what to exec", __func__);
-
- SetLastError (ERROR_PATH_NOT_FOUND);
- goto free_strings;
- }
-
- /* Turn all the slashes round the right way. Only for
- * the prg. name
- */
- switch_dir_separators(token);
-
- if (g_ascii_isalpha (token[0]) && (token[1] == ':')) {
- /* Strip off the drive letter. I can't
- * believe that CP/M holdover is still
- * visible...
- */
- g_memmove (token, token+2, strlen (token)-2);
- token[strlen (token)-2] = '\0';
- }
-
- if (token[0] == '/') {
- /* Assume full path given */
- prog = g_strdup (token);
-
- /* Executable existing ? */
- if (!is_readable_or_executable (prog)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
- __func__, token);
- g_free (token);
- SetLastError (ERROR_FILE_NOT_FOUND);
- goto free_strings;
- }
- } else {
- char *curdir = g_get_current_dir ();
-
- /* FIXME: Need to record the directory
- * containing the current process, and check
- * that for the new executable as the first
- * place to look
- */
-
- prog = g_strdup_printf ("%s/%s", curdir, token);
- g_free (curdir);
-
- /* I assume X_OK is the criterion to use,
- * rather than F_OK
- *
- * X_OK is too strict *if* the target is a CLR binary
- */
- if (!is_readable_or_executable (prog)) {
- g_free (prog);
- prog = g_find_program_in_path (token);
- if (prog == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s", __func__, token);
-
- g_free (token);
- SetLastError (ERROR_FILE_NOT_FOUND);
- goto free_strings;
- }
- }
- }
-
- g_free (token);
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Exec prog [%s] args [%s]", __func__, prog,
- args_after_prog);
-
- /* Check for CLR binaries; if found, we will try to invoke
- * them using the same mono binary that started us.
- */
- if (is_managed_binary (prog)) {
- gunichar2 *newapp = NULL, *newcmd;
- gsize bytes_ignored;
-
- if (cli_launcher)
- newapp = mono_unicode_from_external (cli_launcher, &bytes_ignored);
- else
- newapp = mono_unicode_from_external ("mono", &bytes_ignored);
-
- if (newapp != NULL) {
- if (appname != NULL) {
- newcmd = utf16_concat (utf16_quote, newapp, utf16_quote, utf16_space,
- appname, utf16_space,
- cmdline, NULL);
- } else {
- newcmd = utf16_concat (utf16_quote, newapp, utf16_quote, utf16_space,
- cmdline, NULL);
- }
-
- g_free ((gunichar2 *)newapp);
-
- if (newcmd != NULL) {
- ret = CreateProcess (NULL, newcmd,
- process_attrs,
- thread_attrs,
- inherit_handles,
- create_flags, new_environ,
- cwd, startup,
- process_info);
-
- g_free ((gunichar2 *)newcmd);
-
- goto free_strings;
- }
- }
- } else {
- if (!is_executable (prog)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Executable permisson not set on %s", __func__, prog);
- SetLastError (ERROR_ACCESS_DENIED);
- goto free_strings;
- }
- }
-
- if (args_after_prog != NULL && *args_after_prog) {
- char *qprog;
-
- qprog = g_shell_quote (prog);
- full_prog = g_strconcat (qprog, " ", args_after_prog, NULL);
- g_free (qprog);
- } else {
- full_prog = g_shell_quote (prog);
- }
-
- ret = g_shell_parse_argv (full_prog, NULL, &argv, &gerr);
- if (ret == FALSE) {
- g_message ("CreateProcess: %s\n", gerr->message);
- g_error_free (gerr);
- gerr = NULL;
- goto free_strings;
- }
-
- if (startup != NULL && startup->dwFlags & STARTF_USESTDHANDLES) {
- in_fd = GPOINTER_TO_UINT (startup->hStdInput);
- out_fd = GPOINTER_TO_UINT (startup->hStdOutput);
- err_fd = GPOINTER_TO_UINT (startup->hStdError);
- } else {
- in_fd = GPOINTER_TO_UINT (GetStdHandle (STD_INPUT_HANDLE));
- out_fd = GPOINTER_TO_UINT (GetStdHandle (STD_OUTPUT_HANDLE));
- err_fd = GPOINTER_TO_UINT (GetStdHandle (STD_ERROR_HANDLE));
- }
-
- process_handle.proc_name = g_strdup (prog);
-
- process_set_defaults (&process_handle);
-
- handle = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle);
- if (handle == INVALID_HANDLE_VALUE) {
- g_warning ("%s: error creating process handle", __func__);
-
- ret = FALSE;
- SetLastError (ERROR_OUTOFMEMORY);
- goto free_strings;
- }
-
- /* new_environ is a block of NULL-terminated strings, which
- * is itself NULL-terminated. Of course, passing an array of
- * string pointers would have made things too easy :-(
- *
- * If new_environ is not NULL it specifies the entire set of
- * environment variables in the new process. Otherwise the
- * new process inherits the same environment.
- */
- if (new_environ) {
- gunichar2 *new_environp;
-
- /* Count the number of strings */
- for (new_environp = (gunichar2 *)new_environ; *new_environp;
- new_environp++) {
- env_count++;
- while (*new_environp) {
- new_environp++;
- }
- }
-
- /* +2: one for the process handle value, and the last
- * one is NULL
- */
- env_strings = g_new0 (char *, env_count + 2);
-
- /* Copy each environ string into 'strings' turning it
- * into utf8 (or the requested encoding) at the same
- * time
- */
- env_count = 0;
- for (new_environp = (gunichar2 *)new_environ; *new_environp;
- new_environp++) {
- env_strings[env_count] = mono_unicode_to_external (new_environp);
- env_count++;
- while (*new_environp) {
- new_environp++;
- }
- }
- } else {
- for (i = 0; environ[i] != NULL; i++)
- env_count++;
-
- /* +2: one for the process handle value, and the last
- * one is NULL
- */
- env_strings = g_new0 (char *, env_count + 2);
-
- /* Copy each environ string into 'strings' turning it
- * into utf8 (or the requested encoding) at the same
- * time
- */
- env_count = 0;
- for (i = 0; environ[i] != NULL; i++) {
- env_strings[env_count] = g_strdup (environ[i]);
- env_count++;
- }
- }
-
- /* Create a pipe to make sure the child doesn't exit before
- * we can add the process to the linked list of mono_processes */
- if (pipe (startup_pipe) == -1) {
- /* Could not create the pipe to synchroniz process startup. We'll just not synchronize.
- * This is just for a very hard to hit race condition in the first place */
- startup_pipe [0] = startup_pipe [1] = -1;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: new process startup not synchronized. We may not notice if the newly created process exits immediately.", __func__);
- }
-
- switch (pid = fork ()) {
- case -1: /* Error */ {
- SetLastError (ERROR_OUTOFMEMORY);
- ret = FALSE;
- fork_failed = TRUE;
- break;
- }
- case 0: /* Child */ {
- if (startup_pipe [0] != -1) {
- /* Wait until the parent has updated it's internal data */
- ssize_t _i G_GNUC_UNUSED = read (startup_pipe [0], &dummy, 1);
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: child: parent has completed its setup", __func__);
- close (startup_pipe [0]);
- close (startup_pipe [1]);
- }
-
- /* should we detach from the process group? */
-
- /* Connect stdin, stdout and stderr */
- dup2 (in_fd, 0);
- dup2 (out_fd, 1);
- dup2 (err_fd, 2);
-
- if (inherit_handles != TRUE) {
- /* FIXME: do something here */
- }
-
- /* Close all file descriptors */
- for (i = mono_w32handle_fd_reserve - 1; i > 2; i--)
- close (i);
-
-#ifdef DEBUG_ENABLED
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: exec()ing [%s] in dir [%s]", __func__, cmd,
- dir == NULL?".":dir);
- for (i = 0; argv[i] != NULL; i++)
- g_message ("arg %d: [%s]", i, argv[i]);
-
- for (i = 0; env_strings[i] != NULL; i++)
- g_message ("env %d: [%s]", i, env_strings[i]);
-#endif
-
- /* set cwd */
- if (dir != NULL && chdir (dir) == -1) {
- /* set error */
- _exit (-1);
- }
-
- /* exec */
- execve (argv[0], argv, env_strings);
-
- /* set error */
- _exit (-1);
-
- break;
- }
- default: /* Parent */ {
- process_handle_data = lookup_process_handle (handle);
- if (!process_handle_data) {
- g_warning ("%s: error looking up process handle %p", __func__, handle);
- mono_w32handle_unref (handle);
- } else {
- process_handle_data->id = pid;
-
- /* Add our mono_process into the linked list of mono_processes */
- mono_process = (struct MonoProcess *) g_malloc0 (sizeof (struct MonoProcess));
- mono_process->pid = pid;
- mono_process->handle_count = 1;
- mono_os_sem_init (&mono_process->exit_sem, 0);
-
- /* Keep the process handle artificially alive until the process
- * exits so that the information in the handle isn't lost. */
- mono_w32handle_ref (handle);
- mono_process->handle = handle;
-
- process_handle_data->mono_process = mono_process;
-
- mono_os_mutex_lock (&mono_processes_mutex);
- mono_process->next = mono_processes;
- mono_processes = mono_process;
- mono_os_mutex_unlock (&mono_processes_mutex);
-
- if (process_info != NULL) {
- process_info->hProcess = handle;
- process_info->dwProcessId = pid;
-
- /* FIXME: we might need to handle the thread info some day */
- process_info->hThread = INVALID_HANDLE_VALUE;
- process_info->dwThreadId = 0;
- }
- }
-
- break;
- }
- }
-
- if (fork_failed)
- mono_w32handle_unref (handle);
-
- if (startup_pipe [1] != -1) {
- /* Write 1 byte, doesn't matter what */
- ssize_t _i G_GNUC_UNUSED = write (startup_pipe [1], startup_pipe, 1);
- close (startup_pipe [0]);
- close (startup_pipe [1]);
- }
-
-free_strings:
- if (cmd)
- g_free (cmd);
- if (full_prog)
- g_free (full_prog);
- if (prog)
- g_free (prog);
- if (args)
- g_free (args);
- if (dir)
- g_free (dir);
- if (env_strings)
- g_strfreev (env_strings);
- if (argv)
- g_strfreev (argv);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p for pid %d", __func__, handle, pid);
-
- /* Check if something needs to be cleaned up. */
- mono_processes_cleanup ();
-
- return ret;
-#else
- SetLastError (ERROR_NOT_SUPPORTED);
- return FALSE;
-#endif // defined (HAVE_FORK) && defined (HAVE_EXECVE)
-}
-
-static void
-process_set_name (WapiHandle_process *process_handle)
-{
- char *progname, *utf8_progname, *slash;
-
- progname = g_get_prgname ();
- utf8_progname = mono_utf8_from_external (progname);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: using [%s] as prog name", __func__, progname);
-
- if (utf8_progname) {
- slash = strrchr (utf8_progname, '/');
- if (slash)
- process_handle->proc_name = g_strdup (slash+1);
- else
- process_handle->proc_name = g_strdup (utf8_progname);
- g_free (utf8_progname);
- }
-}
-
-void
-_wapi_processes_init (void)
-{
- pid_t pid = wapi_getpid ();
- WapiHandle_process process_handle = {0};
-
- mono_w32handle_register_ops (MONO_W32HANDLE_PROCESS, &_wapi_process_ops);
-
- mono_w32handle_register_capabilities (MONO_W32HANDLE_PROCESS,
- (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SPECIAL_WAIT));
-
- process_handle.id = pid;
-
- process_set_defaults (&process_handle);
- process_set_name (&process_handle);
-
- current_process = mono_w32handle_new (MONO_W32HANDLE_PROCESS,
- &process_handle);
- g_assert (current_process);
-
- mono_os_mutex_init (&mono_processes_mutex);
-}
-
-gpointer
-_wapi_process_duplicate (void)
-{
- mono_w32handle_ref (current_process);
-
- return current_process;
-}
-
-/* Returns a pseudo handle that doesn't need to be closed afterwards */
-gpointer
-GetCurrentProcess (void)
-{
- return _WAPI_PROCESS_CURRENT;
-}
-
-guint32
-GetProcessId (gpointer handle)
-{
- WapiHandle_process *process_handle;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
- /* This is a pseudo handle */
- return WAPI_HANDLE_TO_PID (handle);
-
- process_handle = lookup_process_handle (handle);
- if (!process_handle) {
- SetLastError (ERROR_INVALID_HANDLE);
- return 0;
- }
-
- return process_handle->id;
-}
-
-static gboolean
-process_open_compare (gpointer handle, gpointer user_data)
-{
- pid_t wanted_pid;
- WapiHandle_process *process_handle;
- pid_t checking_pid;
-
- g_assert (!WAPI_IS_PSEUDO_PROCESS_HANDLE (handle));
-
- process_handle = lookup_process_handle (handle);
- g_assert (process_handle);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking at process %d", __func__, process_handle->id);
-
- checking_pid = process_handle->id;
-
- if (checking_pid == 0)
- return FALSE;
-
- wanted_pid = GPOINTER_TO_UINT (user_data);
-
- /* It's possible to have more than one process handle with the
- * same pid, but only the one running process can be
- * unsignalled
- */
- if (checking_pid == wanted_pid &&
- !mono_w32handle_issignalled (handle)) {
- /* If the handle is blown away in the window between
- * returning TRUE here and mono_w32handle_search pinging
- * the timestamp, the search will continue
- */
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-gboolean
-CloseProcess (gpointer handle)
-{
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
- return TRUE;
- return CloseHandle (handle);
-}
-
-/*
- * The caller owns the returned handle and must call CloseProcess () on it to clean it up.
- */
-gpointer
-OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 pid)
-{
- /* Find the process handle that corresponds to pid */
- gpointer handle = NULL;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking for process %d", __func__, pid);
-
- handle = mono_w32handle_search (MONO_W32HANDLE_PROCESS,
- process_open_compare,
- GUINT_TO_POINTER (pid), NULL, TRUE);
- if (handle == 0) {
- if (is_pid_valid (pid)) {
- /* Return a pseudo handle for processes we
- * don't have handles for
- */
- return WAPI_PID_TO_HANDLE (pid);
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find pid %d", __func__, pid);
-
- SetLastError (ERROR_PROC_NOT_FOUND);
-
- return NULL;
- }
- }
-
- /* mono_w32handle_search () already added a ref */
- return handle;
-}
-
-gboolean
-GetExitCodeProcess (gpointer process, guint32 *code)
-{
- WapiHandle_process *process_handle;
- guint32 pid = -1;
- gboolean alerted;
-
- if (!code)
- return FALSE;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- pid = WAPI_HANDLE_TO_PID (process);
- /* This is a pseudo handle, so we don't know what the
- * exit code was, but we can check whether it's alive or not
- */
- if (is_pid_valid (pid)) {
- *code = STILL_ACTIVE;
- return TRUE;
- } else {
- *code = -1;
- return TRUE;
- }
- }
-
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
-
- return FALSE;
- }
-
- if (process_handle->id == wapi_getpid ()) {
- *code = STILL_ACTIVE;
- return TRUE;
- }
-
- /* A process handle is only signalled if the process has exited
- * and has been waited for */
-
- /* Make sure any process exit has been noticed, before
- * checking if the process is signalled. Fixes bug 325463.
- */
- process_wait (process, 0, &alerted);
-
- if (mono_w32handle_issignalled (process))
- *code = process_handle->exitstatus;
- else
- *code = STILL_ACTIVE;
-
- return TRUE;
-}
-
-gboolean
-GetProcessTimes (gpointer process, WapiFileTime *create_time,
- WapiFileTime *exit_time, WapiFileTime *kernel_time,
- WapiFileTime *user_time)
-{
- WapiHandle_process *process_handle;
- gboolean ku_times_set = FALSE;
-
- if (create_time == NULL || exit_time == NULL || kernel_time == NULL ||
- user_time == NULL)
- /* Not sure if w32 allows NULLs here or not */
- return FALSE;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- gpointer pid = GINT_TO_POINTER (WAPI_HANDLE_TO_PID(process));
- gint64 start_ticks, user_ticks, kernel_ticks;
-
- mono_process_get_times (pid, &start_ticks, &user_ticks, &kernel_ticks);
-
- _wapi_guint64_to_filetime (start_ticks, create_time);
- _wapi_guint64_to_filetime (user_ticks, kernel_time);
- _wapi_guint64_to_filetime (kernel_ticks, user_time);
-
- return TRUE;
- }
-
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
-
- return FALSE;
- }
-
- *create_time = process_handle->create_time;
-
- /* A process handle is only signalled if the process has
- * exited. Otherwise exit_time isn't set
- */
- if (mono_w32handle_issignalled (process))
- *exit_time = process_handle->exit_time;
-
-#ifdef HAVE_GETRUSAGE
- if (process_handle->id == getpid ()) {
- struct rusage time_data;
- if (getrusage (RUSAGE_SELF, &time_data) == 0) {
- guint64 tick_val;
- ku_times_set = TRUE;
- tick_val = (guint64)time_data.ru_utime.tv_sec * 10000000 + (guint64)time_data.ru_utime.tv_usec * 10;
- _wapi_guint64_to_filetime (tick_val, user_time);
- tick_val = (guint64)time_data.ru_stime.tv_sec * 10000000 + (guint64)time_data.ru_stime.tv_usec * 10;
- _wapi_guint64_to_filetime (tick_val, kernel_time);
- }
- }
-#endif
- if (!ku_times_set) {
- memset (kernel_time, 0, sizeof (WapiFileTime));
- memset (user_time, 0, sizeof (WapiFileTime));
- }
-
- return TRUE;
-}
-
-typedef struct
-{
- gpointer address_start;
- gpointer address_end;
- char *perms;
- gpointer address_offset;
- guint64 device;
- guint64 inode;
- char *filename;
-} WapiProcModule;
-
-static void free_procmodule (WapiProcModule *mod)
-{
- if (mod->perms != NULL) {
- g_free (mod->perms);
- }
- if (mod->filename != NULL) {
- g_free (mod->filename);
- }
- g_free (mod);
-}
-
-static gint find_procmodule (gconstpointer a, gconstpointer b)
-{
- WapiProcModule *want = (WapiProcModule *)a;
- WapiProcModule *compare = (WapiProcModule *)b;
-
- if ((want->device == compare->device) &&
- (want->inode == compare->inode)) {
- return(0);
- } else {
- return(1);
- }
-}
-
-#if defined(USE_OSX_LOADER)
-#include <mach-o/dyld.h>
-#include <mach-o/getsect.h>
-
-static GSList *load_modules (void)
-{
- GSList *ret = NULL;
- WapiProcModule *mod;
- uint32_t count = _dyld_image_count ();
- int i = 0;
-
- for (i = 0; i < count; i++) {
-#if SIZEOF_VOID_P == 8
- const struct mach_header_64 *hdr;
- const struct section_64 *sec;
-#else
- const struct mach_header *hdr;
- const struct section *sec;
-#endif
- const char *name;
-
- name = _dyld_get_image_name (i);
-#if SIZEOF_VOID_P == 8
- hdr = (const struct mach_header_64*)_dyld_get_image_header (i);
- sec = getsectbynamefromheader_64 (hdr, SEG_DATA, SECT_DATA);
-#else
- hdr = _dyld_get_image_header (i);
- sec = getsectbynamefromheader (hdr, SEG_DATA, SECT_DATA);
-#endif
-
- /* Some dynlibs do not have data sections on osx (#533893) */
- if (sec == 0) {
- continue;
- }
-
- mod = g_new0 (WapiProcModule, 1);
- mod->address_start = GINT_TO_POINTER (sec->addr);
- mod->address_end = GINT_TO_POINTER (sec->addr+sec->size);
- mod->perms = g_strdup ("r--p");
- mod->address_offset = 0;
- mod->device = makedev (0, 0);
- mod->inode = i;
- mod->filename = g_strdup (name);
-
- if (g_slist_find_custom (ret, mod, find_procmodule) == NULL) {
- ret = g_slist_prepend (ret, mod);
- } else {
- free_procmodule (mod);
- }
- }
-
- ret = g_slist_reverse (ret);
-
- return(ret);
-}
-#elif defined(USE_BSD_LOADER)
-#include <link.h>
-static int load_modules_callback (struct dl_phdr_info *info, size_t size, void *ptr)
-{
- if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
- + sizeof (info->dlpi_phnum))
- return (-1);
-
- struct dl_phdr_info *cpy = g_calloc (1, sizeof(struct dl_phdr_info));
- if (!cpy)
- return (-1);
-
- memcpy(cpy, info, sizeof(*info));
-
- g_ptr_array_add ((GPtrArray *)ptr, cpy);
-
- return (0);
-}
-
-static GSList *load_modules (void)
-{
- GSList *ret = NULL;
- WapiProcModule *mod;
- GPtrArray *dlarray = g_ptr_array_new();
- int i;
-
- if (dl_iterate_phdr(load_modules_callback, dlarray) < 0)
- return (ret);
-
- for (i = 0; i < dlarray->len; i++) {
- struct dl_phdr_info *info = g_ptr_array_index (dlarray, i);
-
- mod = g_new0 (WapiProcModule, 1);
- mod->address_start = (gpointer)(info->dlpi_addr + info->dlpi_phdr[0].p_vaddr);
- mod->address_end = (gpointer)(info->dlpi_addr +
- info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr);
- mod->perms = g_strdup ("r--p");
- mod->address_offset = 0;
- mod->inode = i;
- mod->filename = g_strdup (info->dlpi_name);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: inode=%d, filename=%s, address_start=%p, address_end=%p", __func__,
- mod->inode, mod->filename, mod->address_start, mod->address_end);
-
- g_free (info);
-
- if (g_slist_find_custom (ret, mod, find_procmodule) == NULL) {
- ret = g_slist_prepend (ret, mod);
- } else {
- free_procmodule (mod);
- }
- }
-
- g_ptr_array_free (dlarray, TRUE);
-
- ret = g_slist_reverse (ret);
-
- return(ret);
-}
-#elif defined(USE_HAIKU_LOADER)
-
-static GSList *load_modules (void)
-{
- GSList *ret = NULL;
- WapiProcModule *mod;
- int32 cookie = 0;
- image_info imageInfo;
-
- while (get_next_image_info (B_CURRENT_TEAM, &cookie, &imageInfo) == B_OK) {
- mod = g_new0 (WapiProcModule, 1);
- mod->device = imageInfo.device;
- mod->inode = imageInfo.node;
- mod->filename = g_strdup (imageInfo.name);
- mod->address_start = MIN (imageInfo.text, imageInfo.data);
- mod->address_end = MAX ((uint8_t*)imageInfo.text + imageInfo.text_size,
- (uint8_t*)imageInfo.data + imageInfo.data_size);
- mod->perms = g_strdup ("r--p");
- mod->address_offset = 0;
-
- if (g_slist_find_custom (ret, mod, find_procmodule) == NULL) {
- ret = g_slist_prepend (ret, mod);
- } else {
- free_procmodule (mod);
- }
- }
-
- ret = g_slist_reverse (ret);
-
- return ret;
-}
-#else
-static GSList *load_modules (FILE *fp)
-{
- GSList *ret = NULL;
- WapiProcModule *mod;
- char buf[MAXPATHLEN + 1], *p, *endp;
- char *start_start, *end_start, *prot_start, *offset_start;
- char *maj_dev_start, *min_dev_start, *inode_start, prot_buf[5];
- gpointer address_start, address_end, address_offset;
- guint32 maj_dev, min_dev;
- guint64 inode;
- guint64 device;
-
- while (fgets (buf, sizeof(buf), fp)) {
- p = buf;
- while (g_ascii_isspace (*p)) ++p;
- start_start = p;
- if (!g_ascii_isxdigit (*start_start)) {
- continue;
- }
- address_start = (gpointer)strtoul (start_start, &endp, 16);
- p = endp;
- if (*p != '-') {
- continue;
- }
-
- ++p;
- end_start = p;
- if (!g_ascii_isxdigit (*end_start)) {
- continue;
- }
- address_end = (gpointer)strtoul (end_start, &endp, 16);
- p = endp;
- if (!g_ascii_isspace (*p)) {
- continue;
- }
-
- while (g_ascii_isspace (*p)) ++p;
- prot_start = p;
- if (*prot_start != 'r' && *prot_start != '-') {
- continue;
- }
- memcpy (prot_buf, prot_start, 4);
- prot_buf[4] = '\0';
- while (!g_ascii_isspace (*p)) ++p;
-
- while (g_ascii_isspace (*p)) ++p;
- offset_start = p;
- if (!g_ascii_isxdigit (*offset_start)) {
- continue;
- }
- address_offset = (gpointer)strtoul (offset_start, &endp, 16);
- p = endp;
- if (!g_ascii_isspace (*p)) {
- continue;
- }
-
- while(g_ascii_isspace (*p)) ++p;
- maj_dev_start = p;
- if (!g_ascii_isxdigit (*maj_dev_start)) {
- continue;
- }
- maj_dev = strtoul (maj_dev_start, &endp, 16);
- p = endp;
- if (*p != ':') {
- continue;
- }
-
- ++p;
- min_dev_start = p;
- if (!g_ascii_isxdigit (*min_dev_start)) {
- continue;
- }
- min_dev = strtoul (min_dev_start, &endp, 16);
- p = endp;
- if (!g_ascii_isspace (*p)) {
- continue;
- }
-
- while (g_ascii_isspace (*p)) ++p;
- inode_start = p;
- if (!g_ascii_isxdigit (*inode_start)) {
- continue;
- }
- inode = (guint64)strtol (inode_start, &endp, 10);
- p = endp;
- if (!g_ascii_isspace (*p)) {
- continue;
- }
-
- device = makedev ((int)maj_dev, (int)min_dev);
- if ((device == 0) &&
- (inode == 0)) {
- continue;
- }
-
- while(g_ascii_isspace (*p)) ++p;
- /* p now points to the filename */
-
- mod = g_new0 (WapiProcModule, 1);
- mod->address_start = address_start;
- mod->address_end = address_end;
- mod->perms = g_strdup (prot_buf);
- mod->address_offset = address_offset;
- mod->device = device;
- mod->inode = inode;
- mod->filename = g_strdup (g_strstrip (p));
-
- if (g_slist_find_custom (ret, mod, find_procmodule) == NULL) {
- ret = g_slist_prepend (ret, mod);
- } else {
- free_procmodule (mod);
- }
- }
-
- ret = g_slist_reverse (ret);
-
- return(ret);
-}
-#endif
-
-static gboolean match_procname_to_modulename (char *procname, char *modulename)
-{
- char* lastsep = NULL;
- char* lastsep2 = NULL;
- char* pname = NULL;
- char* mname = NULL;
- gboolean result = FALSE;
-
- if (procname == NULL || modulename == NULL)
- return (FALSE);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: procname=\"%s\", modulename=\"%s\"", __func__, procname, modulename);
- pname = mono_path_resolve_symlinks (procname);
- mname = mono_path_resolve_symlinks (modulename);
-
- if (!strcmp (pname, mname))
- result = TRUE;
-
- if (!result) {
- lastsep = strrchr (mname, '/');
- if (lastsep)
- if (!strcmp (lastsep+1, pname))
- result = TRUE;
- if (!result) {
- lastsep2 = strrchr (pname, '/');
- if (lastsep2){
- if (lastsep) {
- if (!strcmp (lastsep+1, lastsep2+1))
- result = TRUE;
- } else {
- if (!strcmp (mname, lastsep2+1))
- result = TRUE;
- }
- }
- }
- }
-
- g_free (pname);
- g_free (mname);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: result is %d", __func__, result);
- return result;
-}
-
-#if !(defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER) || defined(USE_HAIKU_LOADER))
-static FILE *
-open_process_map (int pid, const char *mode)
-{
- FILE *fp = NULL;
- const char *proc_path[] = {
- "/proc/%d/maps", /* GNU/Linux */
- "/proc/%d/map", /* FreeBSD */
- NULL
- };
- int i;
- char *filename;
-
- for (i = 0; fp == NULL && proc_path [i]; i++) {
- filename = g_strdup_printf (proc_path[i], pid);
- fp = fopen (filename, mode);
- g_free (filename);
- }
-
- return fp;
-}
-#endif
-
-static char *get_process_name_from_proc (pid_t pid);
-
-gboolean EnumProcessModules (gpointer process, gpointer *modules,
- guint32 size, guint32 *needed)
-{
- WapiHandle_process *process_handle;
-#if !defined(USE_OSX_LOADER) && !defined(USE_BSD_LOADER)
- FILE *fp;
-#endif
- GSList *mods = NULL;
- WapiProcModule *module;
- guint32 count, avail = size / sizeof(gpointer);
- int i;
- pid_t pid;
- char *proc_name = NULL;
-
- /* Store modules in an array of pointers (main module as
- * modules[0]), using the load address for each module as a
- * token. (Use 'NULL' as an alternative for the main module
- * so that the simple implementation can just return one item
- * for now.) Get the info from /proc/<pid>/maps on linux,
- * /proc/<pid>/map on FreeBSD, other systems will have to
- * implement /dev/kmem reading or whatever other horrid
- * technique is needed.
- */
- if (size < sizeof(gpointer))
- return FALSE;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- pid = WAPI_HANDLE_TO_PID (process);
- proc_name = get_process_name_from_proc (pid);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
-
- return FALSE;
- }
- pid = process_handle->id;
- proc_name = g_strdup (process_handle->proc_name);
- }
-
-#if defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER) || defined(USE_HAIKU_LOADER)
- mods = load_modules ();
- if (!proc_name) {
- modules[0] = NULL;
- *needed = sizeof(gpointer);
- return TRUE;
- }
-#else
- fp = open_process_map (pid, "r");
- if (!fp) {
- /* No /proc/<pid>/maps so just return the main module
- * shortcut for now
- */
- modules[0] = NULL;
- *needed = sizeof(gpointer);
- g_free (proc_name);
- return TRUE;
- }
- mods = load_modules (fp);
- fclose (fp);
-#endif
- count = g_slist_length (mods);
-
- /* count + 1 to leave slot 0 for the main module */
- *needed = sizeof(gpointer) * (count + 1);
-
- /*
- * Use the NULL shortcut, as the first line in
- * /proc/<pid>/maps isn't the executable, and we need
- * that first in the returned list. Check the module name
- * to see if it ends with the proc name and substitute
- * the first entry with it. FIXME if this turns out to
- * be a problem.
- */
- modules[0] = NULL;
- for (i = 0; i < (avail - 1) && i < count; i++) {
- module = (WapiProcModule *)g_slist_nth_data (mods, i);
- if (modules[0] != NULL)
- modules[i] = module->address_start;
- else if (match_procname_to_modulename (proc_name, module->filename))
- modules[0] = module->address_start;
- else
- modules[i + 1] = module->address_start;
- }
-
- for (i = 0; i < count; i++) {
- free_procmodule ((WapiProcModule *)g_slist_nth_data (mods, i));
- }
- g_slist_free (mods);
- g_free (proc_name);
-
- return TRUE;
-}
-
-static char *
-get_process_name_from_proc (pid_t pid)
-{
-#if defined(USE_BSD_LOADER)
- int mib [6];
- size_t size;
- struct kinfo_proc *pi;
-#elif defined(USE_OSX_LOADER)
-#if !(!defined (__mono_ppc__) && defined (TARGET_OSX))
- size_t size;
- struct kinfo_proc *pi;
- int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
-#endif
-#else
- FILE *fp;
- char *filename = NULL;
-#endif
- char buf[256];
- char *ret = NULL;
-
-#if defined(PLATFORM_SOLARIS)
- filename = g_strdup_printf ("/proc/%d/psinfo", pid);
- if ((fp = fopen (filename, "r")) != NULL) {
- struct psinfo info;
- int nread;
-
- nread = fread (&info, sizeof (info), 1, fp);
- if (nread == 1) {
- ret = g_strdup (info.pr_fname);
- }
-
- fclose (fp);
- }
- g_free (filename);
-#elif defined(USE_OSX_LOADER)
-#if !defined (__mono_ppc__) && defined (TARGET_OSX)
- /* No proc name on OSX < 10.5 nor ppc nor iOS */
- memset (buf, '\0', sizeof(buf));
- proc_name (pid, buf, sizeof(buf));
-
- // Fixes proc_name triming values to 15 characters #32539
- if (strlen (buf) >= MAXCOMLEN - 1) {
- char path_buf [PROC_PIDPATHINFO_MAXSIZE];
- char *name_buf;
- int path_len;
-
- memset (path_buf, '\0', sizeof(path_buf));
- path_len = proc_pidpath (pid, path_buf, sizeof(path_buf));
-
- if (path_len > 0 && path_len < sizeof(path_buf)) {
- name_buf = path_buf + path_len;
- for(;name_buf > path_buf; name_buf--) {
- if (name_buf [0] == '/') {
- name_buf++;
- break;
- }
- }
-
- if (memcmp (buf, name_buf, MAXCOMLEN - 1) == 0)
- ret = g_strdup (name_buf);
- }
- }
-
- if (ret == NULL && strlen (buf) > 0)
- ret = g_strdup (buf);
-#else
- if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0)
- return(ret);
-
- if ((pi = g_malloc (size)) == NULL)
- return(ret);
-
- if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
- if (errno == ENOMEM) {
- g_free (pi);
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
- }
- return(ret);
- }
-
- if (strlen (pi->kp_proc.p_comm) > 0)
- ret = g_strdup (pi->kp_proc.p_comm);
-
- g_free (pi);
-#endif
-#elif defined(USE_BSD_LOADER)
-#if defined(__FreeBSD__)
- mib [0] = CTL_KERN;
- mib [1] = KERN_PROC;
- mib [2] = KERN_PROC_PID;
- mib [3] = pid;
- if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
- return(ret);
- }
-
- if ((pi = g_malloc (size)) == NULL)
- return(ret);
-
- if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
- if (errno == ENOMEM) {
- g_free (pi);
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
- }
- return(ret);
- }
-
- if (strlen (pi->ki_comm) > 0)
- ret = g_strdup (pi->ki_comm);
- g_free (pi);
-#elif defined(__OpenBSD__)
- mib [0] = CTL_KERN;
- mib [1] = KERN_PROC;
- mib [2] = KERN_PROC_PID;
- mib [3] = pid;
- mib [4] = sizeof(struct kinfo_proc);
- mib [5] = 0;
-
-retry:
- if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
- return(ret);
- }
-
- if ((pi = g_malloc (size)) == NULL)
- return(ret);
-
- mib[5] = (int)(size / sizeof(struct kinfo_proc));
-
- if ((sysctl (mib, 6, pi, &size, NULL, 0) < 0) ||
- (size != sizeof (struct kinfo_proc))) {
- if (errno == ENOMEM) {
- g_free (pi);
- goto retry;
- }
- return(ret);
- }
-
- if (strlen (pi->p_comm) > 0)
- ret = g_strdup (pi->p_comm);
-
- g_free (pi);
-#endif
-#elif defined(USE_HAIKU_LOADER)
- image_info imageInfo;
- int32 cookie = 0;
-
- if (get_next_image_info ((team_id)pid, &cookie, &imageInfo) == B_OK) {
- ret = g_strdup (imageInfo.name);
- }
-#else
- memset (buf, '\0', sizeof(buf));
- filename = g_strdup_printf ("/proc/%d/exe", pid);
- if (readlink (filename, buf, 255) > 0) {
- ret = g_strdup (buf);
- }
- g_free (filename);
-
- if (ret != NULL) {
- return(ret);
- }
-
- filename = g_strdup_printf ("/proc/%d/cmdline", pid);
- if ((fp = fopen (filename, "r")) != NULL) {
- if (fgets (buf, 256, fp) != NULL) {
- ret = g_strdup (buf);
- }
-
- fclose (fp);
- }
- g_free (filename);
-
- if (ret != NULL) {
- return(ret);
- }
-
- filename = g_strdup_printf ("/proc/%d/stat", pid);
- if ((fp = fopen (filename, "r")) != NULL) {
- if (fgets (buf, 256, fp) != NULL) {
- char *start, *end;
-
- start = strchr (buf, '(');
- if (start != NULL) {
- end = strchr (start + 1, ')');
-
- if (end != NULL) {
- ret = g_strndup (start + 1,
- end - start - 1);
- }
- }
- }
-
- fclose (fp);
- }
- g_free (filename);
-#endif
-
- return ret;
-}
-
-/*
- * wapi_process_get_path:
- *
- * Return the full path of the executable of the process PID, or NULL if it cannot be determined.
- * Returns malloc-ed memory.
- */
-char*
-wapi_process_get_path (pid_t pid)
-{
-#if defined(PLATFORM_MACOSX) && !defined(__mono_ppc__) && defined(TARGET_OSX)
- char buf [PROC_PIDPATHINFO_MAXSIZE];
- int res;
-
- res = proc_pidpath (pid, buf, sizeof (buf));
- if (res <= 0)
- return NULL;
- if (buf [0] == '\0')
- return NULL;
- return g_strdup (buf);
-#else
- return get_process_name_from_proc (pid);
-#endif
-}
-
-/*
- * wapi_process_set_cli_launcher:
- *
- * Set the full path of the runtime executable used to launch managed exe's.
- */
-void
-wapi_process_set_cli_launcher (char *path)
-{
- g_free (cli_launcher);
- cli_launcher = path ? g_strdup (path) : NULL;
-}
-
-static guint32
-get_module_name (gpointer process, gpointer module,
- gunichar2 *basename, guint32 size,
- gboolean base)
-{
- WapiHandle_process *process_handle;
- pid_t pid;
- gunichar2 *procname;
- char *procname_ext = NULL;
- glong len;
- gsize bytes;
-#if !defined(USE_OSX_LOADER) && !defined(USE_BSD_LOADER)
- FILE *fp;
-#endif
- GSList *mods = NULL;
- WapiProcModule *found_module;
- guint32 count;
- int i;
- char *proc_name = NULL;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module base name, process handle %p module %p",
- __func__, process, module);
-
- size = size * sizeof (gunichar2); /* adjust for unicode characters */
-
- if (basename == NULL || size == 0)
- return 0;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- proc_name = get_process_name_from_proc (pid);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__,
- process);
-
- return 0;
- }
- pid = process_handle->id;
- proc_name = g_strdup (process_handle->proc_name);
- }
-
- /* Look up the address in /proc/<pid>/maps */
-#if defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER) || defined(USE_HAIKU_LOADER)
- mods = load_modules ();
-#else
- fp = open_process_map (pid, "r");
- if (fp == NULL) {
- if (errno == EACCES && module == NULL && base == TRUE) {
- procname_ext = get_process_name_from_proc (pid);
- } else {
- /* No /proc/<pid>/maps, so just return failure
- * for now
- */
- g_free (proc_name);
- return 0;
- }
- } else {
- mods = load_modules (fp);
- fclose (fp);
- }
-#endif
- count = g_slist_length (mods);
-
- /* If module != NULL compare the address.
- * If module == NULL we are looking for the main module.
- * The best we can do for now check it the module name end with the process name.
- */
- for (i = 0; i < count; i++) {
- found_module = (WapiProcModule *)g_slist_nth_data (mods, i);
- if (procname_ext == NULL &&
- ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
- (module != NULL && found_module->address_start == module))) {
- if (base)
- procname_ext = g_path_get_basename (found_module->filename);
- else
- procname_ext = g_strdup (found_module->filename);
- }
-
- free_procmodule (found_module);
- }
-
- if (procname_ext == NULL) {
- /* If it's *still* null, we might have hit the
- * case where reading /proc/$pid/maps gives an
- * empty file for this user.
- */
- procname_ext = get_process_name_from_proc (pid);
- }
-
- g_slist_free (mods);
- g_free (proc_name);
-
- if (procname_ext) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Process name is [%s]", __func__,
- procname_ext);
-
- procname = mono_unicode_from_external (procname_ext, &bytes);
- if (procname == NULL) {
- /* bugger */
- g_free (procname_ext);
- return 0;
- }
-
- len = (bytes / 2);
-
- /* Add the terminator */
- bytes += 2;
-
- if (size < bytes) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
-
- memcpy (basename, procname, size);
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d larger than needed (%ld)",
- __func__, size, bytes);
-
- memcpy (basename, procname, bytes);
- }
-
- g_free (procname);
- g_free (procname_ext);
-
- return len;
- }
-
- return 0;
-}
-
-static guint32
-get_module_filename (gpointer process, gpointer module,
- gunichar2 *basename, guint32 size)
-{
- int pid, len;
- gsize bytes;
- char *path;
- gunichar2 *proc_path;
-
- size *= sizeof (gunichar2); /* adjust for unicode characters */
-
- if (basename == NULL || size == 0)
- return 0;
-
- pid = GetProcessId (process);
-
- path = wapi_process_get_path (pid);
- if (path == NULL)
- return 0;
-
- proc_path = mono_unicode_from_external (path, &bytes);
- g_free (path);
-
- if (proc_path == NULL)
- return 0;
-
- len = (bytes / 2);
-
- /* Add the terminator */
- bytes += 2;
-
- if (size < bytes) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
-
- memcpy (basename, proc_path, size);
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d larger than needed (%ld)",
- __func__, size, bytes);
-
- memcpy (basename, proc_path, bytes);
- }
-
- g_free (proc_path);
-
- return len;
-}
-
-guint32
-GetModuleBaseName (gpointer process, gpointer module,
- gunichar2 *basename, guint32 size)
-{
- return get_module_name (process, module, basename, size, TRUE);
-}
-
-guint32
-GetModuleFileNameEx (gpointer process, gpointer module,
- gunichar2 *filename, guint32 size)
-{
- return get_module_filename (process, module, filename, size);
-}
-
-gboolean
-GetModuleInformation (gpointer process, gpointer module,
- WapiModuleInfo *modinfo, guint32 size)
-{
- WapiHandle_process *process_handle;
- pid_t pid;
-#if !defined(USE_OSX_LOADER) && !defined(USE_BSD_LOADER)
- FILE *fp;
-#endif
- GSList *mods = NULL;
- WapiProcModule *found_module;
- guint32 count;
- int i;
- gboolean ret = FALSE;
- char *proc_name = NULL;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module info, process handle %p module %p",
- __func__, process, module);
-
- if (modinfo == NULL || size < sizeof (WapiModuleInfo))
- return FALSE;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- proc_name = get_process_name_from_proc (pid);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__,
- process);
-
- return FALSE;
- }
- pid = process_handle->id;
- proc_name = g_strdup (process_handle->proc_name);
- }
-
-#if defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER) || defined(USE_HAIKU_LOADER)
- mods = load_modules ();
-#else
- /* Look up the address in /proc/<pid>/maps */
- if ((fp = open_process_map (pid, "r")) == NULL) {
- /* No /proc/<pid>/maps, so just return failure
- * for now
- */
- g_free (proc_name);
- return FALSE;
- }
- mods = load_modules (fp);
- fclose (fp);
-#endif
- count = g_slist_length (mods);
-
- /* If module != NULL compare the address.
- * If module == NULL we are looking for the main module.
- * The best we can do for now check it the module name end with the process name.
- */
- for (i = 0; i < count; i++) {
- found_module = (WapiProcModule *)g_slist_nth_data (mods, i);
- if (ret == FALSE &&
- ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
- (module != NULL && found_module->address_start == module))) {
- modinfo->lpBaseOfDll = found_module->address_start;
- modinfo->SizeOfImage = (gsize)(found_module->address_end) - (gsize)(found_module->address_start);
- modinfo->EntryPoint = found_module->address_offset;
- ret = TRUE;
- }
-
- free_procmodule (found_module);
- }
-
- g_slist_free (mods);
- g_free (proc_name);
-
- return ret;
-}
-
-gboolean
-GetProcessWorkingSetSize (gpointer process, size_t *min, size_t *max)
-{
- WapiHandle_process *process_handle;
-
- if (min == NULL || max == NULL)
- /* Not sure if w32 allows NULLs here or not */
- return FALSE;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process))
- /* This is a pseudo handle, so just fail for now */
- return FALSE;
-
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
-
- return FALSE;
- }
-
- *min = process_handle->min_working_set;
- *max = process_handle->max_working_set;
-
- return TRUE;
-}
-
-gboolean
-SetProcessWorkingSetSize (gpointer process, size_t min, size_t max)
-{
- WapiHandle_process *process_handle;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process))
- /* This is a pseudo handle, so just fail for now
- */
- return FALSE;
-
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
-
- return FALSE;
- }
-
- process_handle->min_working_set = min;
- process_handle->max_working_set = max;
-
- return TRUE;
-}
-
-
-gboolean
-TerminateProcess (gpointer process, gint32 exitCode)
-{
-#if defined(HAVE_KILL)
- WapiHandle_process *process_handle;
- int signo;
- int ret;
- pid_t pid;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
- pid = process_handle->id;
- }
-
- signo = (exitCode == -1) ? SIGKILL : SIGTERM;
- ret = kill (pid, signo);
- if (ret == -1) {
- switch (errno) {
- case EINVAL:
- SetLastError (ERROR_INVALID_PARAMETER);
- break;
- case EPERM:
- SetLastError (ERROR_ACCESS_DENIED);
- break;
- case ESRCH:
- SetLastError (ERROR_PROC_NOT_FOUND);
- break;
- default:
- SetLastError (ERROR_GEN_FAILURE);
- }
- }
-
- return (ret == 0);
-#else
- g_error ("kill() is not supported by this platform");
- return FALSE;
-#endif
-}
-
-guint32
-GetPriorityClass (gpointer process)
-{
-#ifdef HAVE_GETPRIORITY
- WapiHandle_process *process_handle;
- int ret;
- pid_t pid;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
- pid = process_handle->id;
- }
-
- errno = 0;
- ret = getpriority (PRIO_PROCESS, pid);
- if (ret == -1 && errno != 0) {
- switch (errno) {
- case EPERM:
- case EACCES:
- SetLastError (ERROR_ACCESS_DENIED);
- break;
- case ESRCH:
- SetLastError (ERROR_PROC_NOT_FOUND);
- break;
- default:
- SetLastError (ERROR_GEN_FAILURE);
- }
- return FALSE;
- }
-
- if (ret == 0)
- return NORMAL_PRIORITY_CLASS;
- else if (ret < -15)
- return REALTIME_PRIORITY_CLASS;
- else if (ret < -10)
- return HIGH_PRIORITY_CLASS;
- else if (ret < 0)
- return ABOVE_NORMAL_PRIORITY_CLASS;
- else if (ret > 10)
- return IDLE_PRIORITY_CLASS;
- else if (ret > 0)
- return BELOW_NORMAL_PRIORITY_CLASS;
-
- return NORMAL_PRIORITY_CLASS;
-#else
- SetLastError (ERROR_NOT_SUPPORTED);
- return 0;
-#endif
-}
-
-gboolean
-SetPriorityClass (gpointer process, guint32 priority_class)
-{
-#ifdef HAVE_SETPRIORITY
- WapiHandle_process *process_handle;
- int ret;
- int prio;
- pid_t pid;
-
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- } else {
- process_handle = lookup_process_handle (process);
- if (!process_handle) {
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
- pid = process_handle->id;
- }
-
- switch (priority_class) {
- case IDLE_PRIORITY_CLASS:
- prio = 19;
- break;
- case BELOW_NORMAL_PRIORITY_CLASS:
- prio = 10;
- break;
- case NORMAL_PRIORITY_CLASS:
- prio = 0;
- break;
- case ABOVE_NORMAL_PRIORITY_CLASS:
- prio = -5;
- break;
- case HIGH_PRIORITY_CLASS:
- prio = -11;
- break;
- case REALTIME_PRIORITY_CLASS:
- prio = -20;
- break;
- default:
- SetLastError (ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- ret = setpriority (PRIO_PROCESS, pid, prio);
- if (ret == -1) {
- switch (errno) {
- case EPERM:
- case EACCES:
- SetLastError (ERROR_ACCESS_DENIED);
- break;
- case ESRCH:
- SetLastError (ERROR_PROC_NOT_FOUND);
- break;
- default:
- SetLastError (ERROR_GEN_FAILURE);
- }
- }
-
- return ret == 0;
-#else
- SetLastError (ERROR_NOT_SUPPORTED);
- return FALSE;
-#endif
-}
-
-static void
-mono_processes_cleanup (void)
-{
- struct MonoProcess *mp;
- struct MonoProcess *prev = NULL;
- GSList *finished = NULL;
- GSList *l;
- gpointer unref_handle;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
-
- /* Ensure we're not in here in multiple threads at once, nor recursive. */
- if (InterlockedCompareExchange (&mono_processes_cleaning_up, 1, 0) != 0)
- return;
-
- for (mp = mono_processes; mp; mp = mp->next) {
- if (mp->pid == 0 && mp->handle) {
- /* This process has exited and we need to remove the artifical ref
- * on the handle */
- mono_os_mutex_lock (&mono_processes_mutex);
- unref_handle = mp->handle;
- mp->handle = NULL;
- mono_os_mutex_unlock (&mono_processes_mutex);
- if (unref_handle)
- mono_w32handle_unref (unref_handle);
- }
- }
-
- /*
- * Remove processes which exited from the mono_processes list.
- * We need to synchronize with the sigchld handler here, which runs
- * asynchronously. The handler requires that the mono_processes list
- * remain valid.
- */
- mono_os_mutex_lock (&mono_processes_mutex);
-
- mp = mono_processes;
- while (mp) {
- if (mp->handle_count == 0 && mp->freeable) {
- /*
- * Unlink the entry.
- * This code can run parallel with the sigchld handler, but the
- * modifications it makes are safe.
- */
- if (mp == mono_processes)
- mono_processes = mp->next;
- else
- prev->next = mp->next;
- finished = g_slist_prepend (finished, mp);
-
- mp = mp->next;
- } else {
- prev = mp;
- mp = mp->next;
- }
- }
-
- mono_memory_barrier ();
-
- for (l = finished; l; l = l->next) {
- /*
- * All the entries in the finished list are unlinked from mono_processes, and
- * they have the 'finished' flag set, which means the sigchld handler is done
- * accessing them.
- */
- mp = (MonoProcess *)l->data;
- mono_os_sem_destroy (&mp->exit_sem);
- g_free (mp);
- }
- g_slist_free (finished);
-
- mono_os_mutex_unlock (&mono_processes_mutex);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s done", __func__);
-
- InterlockedDecrement (&mono_processes_cleaning_up);
-}
-
-static void
-process_close (gpointer handle, gpointer data)
-{
- WapiHandle_process *process_handle;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
-
- process_handle = (WapiHandle_process *) data;
- g_free (process_handle->proc_name);
- process_handle->proc_name = NULL;
- if (process_handle->mono_process)
- InterlockedDecrement (&process_handle->mono_process->handle_count);
- mono_processes_cleanup ();
-}
-
-static void process_details (gpointer data)
-{
- WapiHandle_process *process_handle = (WapiHandle_process *) data;
- g_print ("id: %d, exited: %s, exitstatus: %d",
- process_handle->id, process_handle->exited ? "true" : "false", process_handle->exitstatus);
-}
-
-static const gchar* process_typename (void)
-{
- return "Process";
-}
-
-static gsize process_typesize (void)
-{
- return sizeof (WapiHandle_process);
-}
-
-#if HAVE_SIGACTION
-MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, siginfo_t *info, void *context))
-{
- int status;
- int pid;
- struct MonoProcess *p;
-
- do {
- do {
- pid = waitpid (-1, &status, WNOHANG);
- } while (pid == -1 && errno == EINTR);
-
- if (pid <= 0)
- break;
-
- /*
- * This can run concurrently with the code in the rest of this module.
- */
- for (p = mono_processes; p; p = p->next) {
- if (p->pid == pid) {
- break;
- }
- }
- if (p) {
- p->pid = 0; /* this pid doesn't exist anymore, clear it */
- p->status = status;
- mono_os_sem_post (&p->exit_sem);
- mono_memory_barrier ();
- /* Mark this as freeable, the pointer becomes invalid afterwards */
- p->freeable = TRUE;
- }
- } while (1);
-}
-
-#endif
-
-static void
-process_add_sigchld_handler (void)
-{
-#if HAVE_SIGACTION
- struct sigaction sa;
-
- sa.sa_sigaction = mono_sigchld_signal_handler;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
- g_assert (sigaction (SIGCHLD, &sa, &previous_chld_sa) != -1);
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "Added SIGCHLD handler");
-#endif
-}
-
-static guint32
-process_wait (gpointer handle, guint32 timeout, gboolean *alerted)
-{
- WapiHandle_process *process_handle;
- pid_t pid G_GNUC_UNUSED, ret;
- int status;
- gint64 start, now;
- struct MonoProcess *mp;
-
- /* FIXME: We can now easily wait on processes that aren't our own children,
- * but WaitFor*Object won't call us for pseudo handles. */
- g_assert ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) != _WAPI_PROCESS_UNHANDLED);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u)", __func__, handle, timeout);
-
- if (alerted)
- *alerted = FALSE;
-
- process_handle = lookup_process_handle (handle);
- if (!process_handle) {
- g_warning ("%s: error looking up process handle %p", __func__, handle);
- return WAIT_FAILED;
- }
-
- if (process_handle->exited) {
- /* We've already done this one */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Process already exited", __func__, handle, timeout);
- return WAIT_OBJECT_0;
- }
-
- pid = process_handle->id;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): PID: %d", __func__, handle, timeout, pid);
-
- /* We don't need to lock mono_processes here, the entry
- * has a handle_count > 0 which means it will not be freed. */
- mp = process_handle->mono_process;
- if (!mp) {
- pid_t res;
-
- if (pid == mono_process_current_pid ()) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on current process", __func__, handle, timeout);
- return WAIT_TIMEOUT;
- }
-
- /* This path is used when calling Process.HasExited, so
- * it is only used to poll the state of the process, not
- * to actually wait on it to exit */
- g_assert (timeout == 0);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on non-child process", __func__, handle, timeout);
-
- res = waitpid (pid, &status, WNOHANG);
- if (res == 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process WAIT_TIMEOUT", __func__, handle, timeout);
- return WAIT_TIMEOUT;
- }
- if (res > 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process waited successfully", __func__, handle, timeout);
- return WAIT_OBJECT_0;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process WAIT_FAILED, error : %s (%d))", __func__, handle, timeout, g_strerror (errno), errno);
- return WAIT_FAILED;
- }
-
- start = mono_msec_ticks ();
- now = start;
-
- while (1) {
- if (timeout != INFINITE) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore for %li ms...",
- __func__, handle, timeout, (long)(timeout - (now - start)));
- ret = mono_os_sem_timedwait (&mp->exit_sem, (timeout - (now - start)), alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore forever...",
- __func__, handle, timeout);
- ret = mono_os_sem_wait (&mp->exit_sem, alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
- }
-
- if (ret == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
- /* Success, process has exited */
- mono_os_sem_post (&mp->exit_sem);
- break;
- }
-
- if (ret == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_TIMEOUT (timeout = 0)", __func__, handle, timeout);
- return WAIT_TIMEOUT;
- }
-
- now = mono_msec_ticks ();
- if (now - start >= timeout) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_TIMEOUT", __func__, handle, timeout);
- return WAIT_TIMEOUT;
- }
-
- if (alerted && ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_IO_COMPLETION", __func__, handle, timeout);
- *alerted = TRUE;
- return WAIT_IO_COMPLETION;
- }
- }
-
- /* Process must have exited */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Waited successfully", __func__, handle, timeout);
-
- status = mp ? mp->status : 0;
- if (WIFSIGNALED (status))
- process_handle->exitstatus = 128 + WTERMSIG (status);
- else
- process_handle->exitstatus = WEXITSTATUS (status);
- _wapi_time_t_to_filetime (time (NULL), &process_handle->exit_time);
-
- process_handle->exited = TRUE;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Setting pid %d signalled, exit status %d",
- __func__, handle, timeout, process_handle->id, process_handle->exitstatus);
-
- mono_w32handle_set_signal_state (handle, TRUE, TRUE);
-
- return WAIT_OBJECT_0;
-}
-
-void
-wapi_processes_cleanup (void)
-{
- g_free (cli_launcher);
-}
+++ /dev/null
-/*
- * processes.h: Process handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_PROCESSES_H_
-#define _WAPI_PROCESSES_H_
-
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <glib.h>
-
-#include <mono/io-layer/access.h>
-#include <mono/io-layer/versioninfo.h>
-
-G_BEGIN_DECLS
-
-typedef enum {
- STARTF_USESHOWWINDOW=0x001,
- STARTF_USESIZE=0x002,
- STARTF_USEPOSITION=0x004,
- STARTF_USECOUNTCHARS=0x008,
- STARTF_USEFILLATTRIBUTE=0x010,
- STARTF_RUNFULLSCREEN=0x020,
- STARTF_FORCEONFEEDBACK=0x040,
- STARTF_FORCEOFFFEEDBACK=0x080,
- STARTF_USESTDHANDLES=0x100
-} WapiStartupFlags;
-
-
-typedef struct _WapiStartupInfo WapiStartupInfo;
-
-struct _WapiStartupInfo
-{
- guint32 cb;
- guchar *lpReserved;
- guchar *lpDesktop;
- guchar *lpTitle;
- guint32 dwX;
- guint32 dwY;
- guint32 dwXSize;
- guint32 dwYSize;
- guint32 dwXCountChars;
- guint32 dwYCountChars;
- guint32 dwFillAttribute;
- WapiStartupFlags dwFlags;
- guint16 wShowWindow;
- guint16 cbReserved2;
- guint8 *lpReserved2;
- gpointer hStdInput;
- gpointer hStdOutput;
- gpointer hStdError;
-};
-
-typedef struct _WapiProcessInformation WapiProcessInformation;
-
-struct _WapiProcessInformation
-{
- gpointer hProcess;
- gpointer hThread;
- guint32 dwProcessId;
- guint32 dwThreadId;
-};
-
-typedef enum {
- SEE_MASK_CLASSNAME = 0x01,
- SEE_MASK_CLASSKEY = 0x03,
- SEE_MASK_IDLIST = 0x04,
- SEE_MASK_INVOKEIDLIST = 0x0c,
- SEE_MASK_ICON = 0x10,
- SEE_MASK_HOTKEY = 0x20,
- SEE_MASK_NOCLOSEPROCESS = 0x40,
- SEE_MASK_CONNECTNETDRV = 0x80,
- SEE_MASK_FLAG_DDEWAIT = 0x100,
- SEE_MASK_DOENVSUBST = 0x200,
- SEE_MASK_FLAG_NO_UI = 0x400,
- SEE_MASK_NO_CONSOLE = 0x8000,
- SEE_MASK_UNICODE = 0x10000,
- SEE_MASK_HMONITOR = 0x200000,
- /*SEE_MASK_FLAG_LOG_USAGE,*/
- /*SEE_MASK_NOZONECHECKS,*/
-} WapiShellExecuteInfoFlags;
-
-typedef enum {
- SW_HIDE = 0,
- SW_SHOWNORMAL = 1,
- SW_SHOWMINIMIZED = 2,
- SW_MAXIMIZE = 3,
- SW_SHOWMAXIMIZED = 3,
- SW_SHOWNOACTIVATE = 4,
- SW_SHOW = 5,
- SW_MINIMIZE = 6,
- SW_SHOWMINNOACTIVE = 7,
- SW_SHOWNA = 8,
- SW_RESTORE = 9,
- SW_SHOWDEFAULT = 10,
-} WapiShellExecuteShowFlags;
-
-typedef struct _WapiShellExecuteInfo WapiShellExecuteInfo;
-
-struct _WapiShellExecuteInfo
-{
- guint32 cbSize;
- gulong fMask;
- gpointer hwnd;
- const gunichar2 *lpVerb;
- const gunichar2 *lpFile;
- const gunichar2 *lpParameters;
- const gunichar2 *lpDirectory;
- gulong nShow;
- gpointer hInstApp;
- gpointer lpIDList;
- const gunichar2 *lpClass;
- gpointer hkeyClass;
- guint32 dwHotKey;
- union
- {
- gpointer hIcon;
- gpointer hMonitor;
- } u;
- gpointer hProcess;
-};
-
-
-#define DEBUG_PROCESS 0x00000001
-#define DEBUG_ONLY_THIS_PROCESS 0x00000002
-#define DETACHED_PROCESS 0x00000008
-#define CREATE_NEW_CONSOLE 0x00000010
-#define NORMAL_PRIORITY_CLASS 0x00000020
-#define IDLE_PRIORITY_CLASS 0x00000040
-#define HIGH_PRIORITY_CLASS 0x00000080
-#define REALTIME_PRIORITY_CLASS 0x00000100
-#define CREATE_NEW_PROCESS_GROUP 0x00000200
-#define CREATE_UNICODE_ENVIRONMENT 0x00000400
-#define CREATE_SEPARATE_WOW_VDM 0x00000800
-#define CREATE_SHARED_WOW_VDM 0x00001000
-#define CREATE_FORCEDOS 0x00002000
-#define BELOW_NORMAL_PRIORITY_CLASS 0x00004000
-#define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
-#define CREATE_BREAKAWAY_FROM_JOB 0x01000000
-#define CREATE_WITH_USERPROFILE 0x02000000
-#define CREATE_DEFAULT_ERROR_MODE 0x04000000
-#define CREATE_NO_WINDOW 0x08000000
-
-#ifdef NEW_STUFF
-#define CREATE_PRESERVE_CODE_AUTHZ_LEVEL find out the value for this one...
-#endif
-
-#define PROCESS_TERMINATE 0x0001
-#define PROCESS_CREATE_THREAD 0x0002
-#define PROCESS_SET_SESSIONID 0x0004
-#define PROCESS_VM_OPERATION 0x0008
-#define PROCESS_VM_READ 0x0010
-#define PROCESS_VM_WRITE 0x0020
-#define PROCESS_DUP_HANDLE 0x0040
-#define PROCESS_CREATE_PROCESS 0x0080
-#define PROCESS_SET_QUOTA 0x0100
-#define PROCESS_SET_INFORMATION 0x0200
-#define PROCESS_QUERY_INFORMATION 0x0400
-#define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xfff)
-
-extern gboolean ShellExecuteEx (WapiShellExecuteInfo *sei);
-extern gboolean CreateProcess (const gunichar2 *appname,
- const gunichar2 *cmdline,
- WapiSecurityAttributes *process_attrs,
- WapiSecurityAttributes *thread_attrs,
- gboolean inherit_handles, guint32 create_flags,
- gpointer environ, const gunichar2 *cwd,
- WapiStartupInfo *startup,
- WapiProcessInformation *process_info);
-extern gboolean CreateProcessWithLogonW (const gunichar2 *username,
- const gunichar2 *domain,
- const gunichar2 *password,
- const guint32 logonFlags,
- const gunichar2 *appname,
- const gunichar2 *cmdline,
- guint32 create_flags,
- gpointer environ,
- const gunichar2 *cwd,
- WapiStartupInfo *startup,
- WapiProcessInformation *process_info);
-#define LOGON_WITH_PROFILE 0x00000001
-#define LOGON_NETCREDENTIALS_ONLY 0x00000002
-
-extern gpointer GetCurrentProcess (void);
-extern guint32 GetProcessId (gpointer handle);
-extern gboolean CloseProcess (gpointer handle);
-extern gpointer OpenProcess (guint32 access, gboolean inherit, guint32 pid);
-extern gboolean GetExitCodeProcess (gpointer process, guint32 *code);
-extern gboolean GetProcessTimes (gpointer process, WapiFileTime *create_time,
- WapiFileTime *exit_time,
- WapiFileTime *kernel_time,
- WapiFileTime *user_time);
-extern gboolean EnumProcessModules (gpointer process, gpointer *modules,
- guint32 size, guint32 *needed);
-extern guint32 GetModuleBaseName (gpointer process, gpointer module,
- gunichar2 *basename, guint32 size);
-extern guint32 GetModuleFileNameEx (gpointer process, gpointer module,
- gunichar2 *filename, guint32 size);
-extern gboolean GetModuleInformation (gpointer process, gpointer module,
- WapiModuleInfo *modinfo, guint32 size);
-extern gboolean GetProcessWorkingSetSize (gpointer process, size_t *min,
- size_t *max);
-extern gboolean SetProcessWorkingSetSize (gpointer process, size_t min,
- size_t max);
-
-extern gboolean TerminateProcess (gpointer process, gint32 exitCode);
-
-extern guint32 GetPriorityClass (gpointer process);
-extern gboolean SetPriorityClass (gpointer process, guint32 priority_class);
-
-gchar* wapi_process_get_path (pid_t pid);
-
-void wapi_process_set_cli_launcher (char *path);
-
-G_END_DECLS
-
-#endif /* _WAPI_PROCESSES_H_ */
+++ /dev/null
-/*
- * timefuncs-private.h: performance timer and other time private functions
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_TIMEFUNCS_PRIVATE_H_
-#define _WAPI_TIMEFUNCS_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-#include <sys/time.h>
-
-extern void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime);
-extern void _wapi_guint64_to_filetime (guint64 ticks, WapiFileTime *filetime);
-
-#endif /* _WAPI_TIMEFUNCS_PRIVATE_H_ */
#include <stdio.h>
#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/timefuncs-private.h>
+#include <mono/io-layer/timefuncs.h>
#include "mono/utils/mono-time.h"
#undef DEBUG
filetime->dwLowDateTime = ticks & 0xFFFFFFFF;
filetime->dwHighDateTime = ticks >> 32;
}
-
-void _wapi_guint64_to_filetime (guint64 ticks, WapiFileTime *filetime)
-{
- filetime->dwLowDateTime = ticks & 0xFFFFFFFF;
- filetime->dwHighDateTime = ticks >> 32;
-}
#include <glib.h>
+#include <sys/time.h>
+
#include "mono/io-layer/wapi.h"
G_BEGIN_DECLS
#endif
} WapiFileTime;
+extern void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime);
+
G_END_DECLS
#endif /* _WAPI_TIME_H_ */
typedef WapiFindData *LPWIN32_FIND_DATA;
typedef WapiFileAttributesData WIN32_FILE_ATTRIBUTE_DATA;
typedef WapiGetFileExInfoLevels GET_FILEEX_INFO_LEVELS;
-typedef WapiStartupInfo STARTUPINFO;
-typedef WapiStartupInfo *LPSTARTUPINFO;
-typedef WapiProcessInformation PROCESS_INFORMATION;
typedef WapiFixedFileInfo VS_FIXEDFILEINFO;
typedef WapiModuleInfo MODULEINFO;
typedef WapiModuleInfo *LPMODULEINFO;
typedef WapiImageResourceDirectoryEntry *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
typedef WapiImageResourceDataEntry IMAGE_RESOURCE_DATA_ENTRY;
typedef WapiImageResourceDataEntry *PIMAGE_RESOURCE_DATA_ENTRY;
-typedef WapiShellExecuteInfo SHELLEXECUTEINFO;
-typedef WapiShellExecuteInfo *LPSHELLEXECUTEINFO;
typedef WapiTransmitFileBuffers TRANSMIT_FILE_BUFFERS;
typedef WapiTransmitFileBuffers *PTRANSMIT_FILE_BUFFERS;
typedef WapiTransmitFileBuffers *LPTRANSMIT_FILE_BUFFERS;
#include <mono/io-layer/io-private.h>
#include <mono/io-layer/socket-private.h>
-#include <mono/io-layer/process-private.h>
#include <mono/metadata/w32handle.h>
struct _WapiHandle_shared_ref
#define UnlockFile wapi_UnlockFile
#define GetVolumeInformation wapi_GetVolumeInformation
#define FormatMessage wapi_FormatMessage
-#define ShellExecuteEx wapi_ShellExecuteEx
-#define CreateProcess wapi_CreateProcess
-#define CreateProcessWithLogonW wapi_CreateProcessWithLogonW
-#define GetCurrentProcess wapi_GetCurrentProcess
-#define GetProcessId wapi_GetProcessId
-#define CloseProcess wapi_CloseProcess
-#define OpenProcess wapi_OpenProcess
-#define GetExitCodeProcess wapi_GetExitCodeProcess
-#define GetProcessTimes wapi_GetProcessTimes
-#define EnumProcessModules wapi_EnumProcessModules
-#define GetModuleBaseName wapi_GetModuleBaseName
-#define GetModuleFileNameEx wapi_GetModuleFileNameEx
-#define GetModuleInformation wapi_GetModuleInformation
-#define GetProcessWorkingSetSize wapi_GetProcessWorkingSetSize
-#define SetProcessWorkingSetSize wapi_SetProcessWorkingSetSize
-#define TerminateProcess wapi_TerminateProcess
-#define GetPriorityClass wapi_GetPriorityClass
-#define SetPriorityClass wapi_SetPriorityClass
#define ImpersonateLoggedOnUser wapi_ImpersonateLoggedOnUser
#define RevertToSelf wapi_RevertToSelf
#define WSASetLastError wapi_WSASetLastError
#include "io-trace.h"
#include "io.h"
-#include "process-private.h"
#include "socket-private.h"
#include "mono/utils/mono-lazy-init.h"
wapi_init (void)
{
_wapi_io_init ();
- _wapi_processes_init ();
_wapi_socket_init ();
}
_wapi_has_shut_down = TRUE;
_wapi_error_cleanup ();
- wapi_processes_cleanup ();
_wapi_io_cleanup ();
}
DuplicateHandle (gpointer srcprocess, gpointer src, gpointer targetprocess, gpointer *target,
guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 options G_GNUC_UNUSED)
{
- if (srcprocess != _WAPI_PROCESS_CURRENT || targetprocess != _WAPI_PROCESS_CURRENT) {
- /* Duplicating other process's handles is not supported */
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- if (src == _WAPI_PROCESS_CURRENT) {
- *target = _wapi_process_duplicate ();
- } else {
- mono_w32handle_ref (src);
- *target = src;
- }
-
+ mono_w32handle_ref (src);
+ *target = src;
return TRUE;
}
#include <mono/io-layer/types.h>
#include <mono/io-layer/macros.h>
#include <mono/io-layer/io.h>
-#include <mono/io-layer/access.h>
#include <mono/io-layer/context.h>
#include <mono/io-layer/error.h>
#include <mono/io-layer/messages.h>
-#include <mono/io-layer/processes.h>
#include <mono/io-layer/security.h>
#include <mono/io-layer/sockets.h>
#include <mono/io-layer/status.h>
marshal-windows-internals.h \
mono-security-windows.c \
mono-security-windows-internals.h \
- process-windows.c \
- process-windows-internals.h \
w32mutex-win32.c \
w32semaphore-win32.c \
w32event-win32.c \
+ w32process-win32.c \
+ w32process-win32-internals.h \
socket-io-windows.c
platform_sources = $(win32_sources)
console-unix.c \
w32mutex-unix.c \
w32semaphore-unix.c \
- w32event-unix.c
+ w32event-unix.c \
+ w32process-unix.c \
+ w32process-unix-internals.h \
+ w32process-unix-osx.c \
+ w32process-unix-bsd.c \
+ w32process-unix-haiku.c \
+ w32process-unix-default.c
platform_sources = $(unix_sources)
endif
cil-coff.h \
class.c \
class-internals.h \
+ class-inlines.h \
+ class-accessors.c \
cominterop.c \
cominterop.h \
console-io.h \
opcodes.c \
socket-io.c \
socket-io.h \
- process.c \
- process.h \
- process-internals.h \
+ w32process.c \
+ w32process.h \
+ w32process-internals.h \
profiler.c \
profiler-private.h \
rand.h \
#include "object-internals.h"
#include <mono/metadata/loader.h>
#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/custom-attrs-internals.h>
#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/class-internals.h>
/* Class lazy loading functions */
static GENERATE_TRY_GET_CLASS_WITH_CACHE (internals_visible, System.Runtime.CompilerServices, InternalsVisibleToAttribute)
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (reference_assembly, System.Runtime.CompilerServices, ReferenceAssemblyAttribute)
-
static MonoAssembly*
mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload);
static MonoAssembly*
mono_assemblies_unlock ();
}
+struct HasReferenceAssemblyAttributeIterData {
+ gboolean has_attr;
+};
+
+static gboolean
+has_reference_assembly_attribute_iterator (MonoImage *image, guint32 typeref_scope_token, const char *nspace, const char *name, guint32 method_token, gpointer user_data)
+{
+ gboolean stop_scanning = FALSE;
+ struct HasReferenceAssemblyAttributeIterData *iter_data = (struct HasReferenceAssemblyAttributeIterData*)user_data;
+
+ if (!strcmp (name, "ReferenceAssemblyAttribute") && !strcmp (nspace, "System.Runtime.CompilerServices")) {
+ /* Note we don't check the assembly name, same as coreCLR. */
+ iter_data->has_attr = TRUE;
+ stop_scanning = TRUE;
+ }
+
+ return stop_scanning;
+}
/**
* mono_assembly_has_reference_assembly_attribute:
{
mono_error_init (error);
-/* TODO: mono_custom_attrs_from_assembly_checked returns NULL if a
- * single assembly is missing. The custom attr we want is from
- * corlib, however, so we need a more robust version that doesn't care
- * about missing attributes.
- */
-#if 1
- MonoCustomAttrInfo *attrs = mono_custom_attrs_from_assembly_checked (assembly, TRUE, error);
- return_val_if_nok (error, FALSE);
- if (!attrs)
- return FALSE;
- MonoClass *ref_asm_class = mono_class_try_get_reference_assembly_class ();
- g_assert (ref_asm_class != NULL && ref_asm_class != mono_defaults.object_class && !strcmp(ref_asm_class->name, "ReferenceAssemblyAttribute") );
- gboolean result = mono_custom_attrs_has_attr (attrs, ref_asm_class);
- mono_custom_attrs_free (attrs);
- return result;
-#else
- return FALSE;
-#endif
+ /*
+ * This might be called during assembly loading, so do everything using the low-level
+ * metadata APIs.
+ */
+
+ struct HasReferenceAssemblyAttributeIterData iter_data = { FALSE };
+
+ mono_assembly_metadata_foreach_custom_attr (assembly, &has_reference_assembly_attribute_iterator, &iter_data);
+
+ return iter_data.has_attr;
}
/**
}
}
- mono_assemblies_lock ();
-
- if (image->assembly) {
- /*
- * This means another thread has already loaded the assembly, but not yet
- * called the load hooks so the search hook can't find the assembly.
- */
- mono_assemblies_unlock ();
- ass2 = image->assembly;
- g_free (ass);
- g_free (base_dir);
- mono_image_close (image);
- *status = MONO_IMAGE_OK;
- return ass2;
- }
-
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Prepared to set up assembly '%s' (%s)", ass->aname.name, image->name);
-
- image->assembly = ass;
-
/* We need to check for ReferenceAssmeblyAttribute before we
* mark the assembly as loaded and before we fire the load
* hook. Otherwise mono_domain_fire_assembly_load () in
* this image and we won't be able to look for a different
* candidate. */
- if (!refonly && strcmp (ass->aname.name, "mscorlib") != 0) {
- /* Don't check for reference assmebly attribute for
- * corlib here because if corlib isn't loaded yet,
- * it's too early to set up the
- * ReferenceAssemblyAttribute class. We check that
- * we're not running with a reference corlib in
- * mono_init_internal().
- */
+ if (!refonly) {
MonoError refasm_error;
if (mono_assembly_has_reference_assembly_attribute (ass, &refasm_error)) {
- mono_assemblies_unlock ();
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Image for assembly '%s' (%s) has ReferenceAssemblyAttribute, skipping", ass->aname.name, image->name);
g_free (ass);
g_free (base_dir);
mono_error_cleanup (&refasm_error);
}
+ mono_assemblies_lock ();
+
+ if (image->assembly) {
+ /*
+ * This means another thread has already loaded the assembly, but not yet
+ * called the load hooks so the search hook can't find the assembly.
+ */
+ mono_assemblies_unlock ();
+ ass2 = image->assembly;
+ g_free (ass);
+ g_free (base_dir);
+ mono_image_close (image);
+ *status = MONO_IMAGE_OK;
+ return ass2;
+ }
+
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Prepared to set up assembly '%s' (%s)", ass->aname.name, image->name);
+
+ image->assembly = ass;
+
loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
mono_assemblies_unlock ();
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/tabledefs.h>
+
+
+/* Accessors based on class kind*/
+
+/*
+* mono_class_get_generic_class:
+*
+* Return the MonoGenericClass of @klass, which MUST be a generic instance.
+*/
+MonoGenericClass*
+mono_class_get_generic_class (MonoClass *klass)
+{
+ g_assert (mono_class_is_ginst (klass));
+ return ((MonoClassGenericInst*)klass)->generic_class;
+}
+
+/*
+* mono_class_try_get_generic_class:
+*
+* Return the MonoGenericClass if @klass is a ginst, NULL otherwise
+*/
+MonoGenericClass*
+mono_class_try_get_generic_class (MonoClass *klass)
+{
+ if (mono_class_is_ginst (klass))
+ return ((MonoClassGenericInst*)klass)->generic_class;
+ return NULL;
+}
+
+/**
+ * mono_class_get_flags:
+ * @klass: the MonoClass to act on
+ *
+ * Return the TypeAttributes flags of @klass.
+ * See the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the different values.
+ *
+ * Returns: The type flags
+ */
+guint32
+mono_class_get_flags (MonoClass *klass)
+{
+ switch (klass->class_kind) {
+ case MONO_CLASS_DEF:
+ case MONO_CLASS_GTD:
+ return ((MonoClassDef*)klass)->flags;
+ case MONO_CLASS_GINST:
+ return mono_class_get_flags (((MonoClassGenericInst*)klass)->generic_class->container_class);
+ case MONO_CLASS_GPARAM:
+ return TYPE_ATTRIBUTE_PUBLIC;
+ case MONO_CLASS_ARRAY:
+ /* all arrays are marked serializable and sealed, bug #42779 */
+ return TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
+ case MONO_CLASS_POINTER:
+ return TYPE_ATTRIBUTE_CLASS | (mono_class_get_flags (klass->element_class) & TYPE_ATTRIBUTE_VISIBILITY_MASK);
+ }
+ g_assert_not_reached ();
+}
+
+void
+mono_class_set_flags (MonoClass *klass, guint32 flags)
+{
+ g_assert (klass->class_kind == MONO_CLASS_DEF || klass->class_kind == MONO_CLASS_GTD);
+ ((MonoClassDef*)klass)->flags = flags;
+}
+
+/*
+ * mono_class_get_generic_container:
+ *
+ * Return the generic container of KLASS which should be a generic type definition.
+ */
+MonoGenericContainer*
+mono_class_get_generic_container (MonoClass *klass)
+{
+ g_assert (mono_class_is_gtd (klass));
+
+ return ((MonoClassGtd*)klass)->generic_container;
+}
+
+MonoGenericContainer*
+mono_class_try_get_generic_container (MonoClass *klass)
+{
+ if (mono_class_is_gtd (klass))
+ return ((MonoClassGtd*)klass)->generic_container;
+ return NULL;
+}
+
+
+void
+mono_class_set_generic_container (MonoClass *klass, MonoGenericContainer *container)
+{
+ g_assert (mono_class_is_gtd (klass));
+
+ ((MonoClassGtd*)klass)->generic_container = container;
+}
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef __MONO_METADATA_CLASS_INLINES_H__
+#define __MONO_METADATA_CLASS_INLINES_H__
+
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/tabledefs.h>
+
+static inline gboolean
+mono_class_is_def (MonoClass *class)
+{
+ return class->class_kind == MONO_CLASS_DEF;
+}
+
+static inline gboolean
+mono_class_is_gtd (MonoClass *class)
+{
+ return class->class_kind == MONO_CLASS_GTD;
+}
+
+static inline gboolean
+mono_class_is_ginst (MonoClass *class)
+{
+ return class->class_kind == MONO_CLASS_GINST;
+}
+
+static inline gboolean
+mono_class_is_gparam (MonoClass *class)
+{
+ return class->class_kind == MONO_CLASS_GPARAM;
+}
+
+static inline gboolean
+mono_class_is_array (MonoClass *class)
+{
+ return class->class_kind == MONO_CLASS_ARRAY;
+}
+
+static inline gboolean
+mono_class_is_pointer (MonoClass *class)
+{
+ return class->class_kind == MONO_CLASS_POINTER;
+}
+
+static inline gboolean
+mono_class_is_abstract (MonoClass *class)
+{
+ return mono_class_get_flags (class) & TYPE_ATTRIBUTE_ABSTRACT;
+}
+
+static inline gboolean
+mono_class_is_interface (MonoClass *class)
+{
+ return mono_class_get_flags (class) & TYPE_ATTRIBUTE_INTERFACE;
+}
+
+#endif
\ No newline at end of file
#define MONO_CLASS_IS_ARRAY(c) ((c)->rank)
-#define MONO_CLASS_HAS_STATIC_METADATA(klass) ((klass)->type_token && !(klass)->image->dynamic && !(klass)->generic_class)
+#define MONO_CLASS_HAS_STATIC_METADATA(klass) ((klass)->type_token && !(klass)->image->dynamic && !mono_class_is_ginst (klass))
#define MONO_DEFAULT_SUPERTABLE_SIZE 6
GList *nested_classes;
} MonoClassExt;
+typedef enum {
+ MONO_CLASS_DEF = 1, /* non-generic type */
+ MONO_CLASS_GTD, /* generic type definition */
+ MONO_CLASS_GINST, /* generic instantiation */
+ MONO_CLASS_GPARAM, /* generic parameter */
+ MONO_CLASS_ARRAY, /* vector or array, bounded or not */
+ MONO_CLASS_POINTER, /* pointer of function pointer*/
+} MonoTypeKind;
+
struct _MonoClass {
/* element class for arrays and enum basetype for enums */
MonoClass *element_class;
guint nested_classes_inited : 1; /* Whenever nested_class is initialized */
/* next byte*/
+ guint class_kind : 3; /* One of the values from MonoTypeKind */
guint interfaces_inited : 1; /* interfaces is initialized */
guint simd_type : 1; /* class is a simd intrinsic type */
- guint is_generic : 1; /* class is a generic type definition */
- guint is_inflated : 1; /* class is a generic instance */
guint has_finalize_inited : 1; /* has_finalize is initialized */
guint fields_inited : 1; /* setup_fields () has finished */
guint has_failure : 1; /* See MONO_CLASS_PROP_EXCEPTION_DATA for a MonoErrorBoxed with the details */
/*
* From the TypeDef table
*/
- guint32 flags;
struct {
#if MONO_SMALL_CONFIG
guint16 first, count;
MonoType this_arg;
MonoType byval_arg;
- MonoGenericClass *generic_class;
- MonoGenericContainer *generic_container;
-
MonoGCDescriptor gc_descr;
MonoClassRuntimeInfo *runtime_info;
- /* next element in the class_cache hash list (in MonoImage) */
- MonoClass *next_class_cache;
-
/* Generic vtable. Initialized by a call to mono_class_setup_vtable () */
MonoMethod **vtable;
MonoClassExt *ext;
};
+typedef struct {
+ MonoClass class;
+ guint32 flags;
+ /* next element in the class_cache hash list (in MonoImage) */
+ MonoClass *next_class_cache;
+} MonoClassDef;
+
+typedef struct {
+ MonoClassDef class;
+ MonoGenericContainer *generic_container;
+} MonoClassGtd;
+
+typedef struct {
+ MonoClass class;
+ MonoGenericClass *generic_class;
+} MonoClassGenericInst;
+
+typedef struct {
+ MonoClass class;
+} MonoClassGenericParam;
+
+typedef struct {
+ MonoClass class;
+} MonoClassArray;
+
+typedef struct {
+ MonoClass class;
+} MonoClassPointer;
+
#ifdef COMPRESSED_INTERFACE_BITMAP
int mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size);
int mono_class_interface_match (const uint8_t *bitmap, int id);
MonoGenericContainer*
mono_class_get_generic_container (MonoClass *klass);
-MonoGenericClass*
-mono_class_get_generic_class (MonoClass *klass);
-
gpointer
mono_class_alloc (MonoClass *klass, int size);
gboolean
mono_class_has_failure (const MonoClass *klass);
+/* Kind specific accessors */
+MonoGenericClass*
+mono_class_get_generic_class (MonoClass *klass);
+
+MonoGenericClass*
+mono_class_try_get_generic_class (MonoClass *klass);
+
+void
+mono_class_set_flags (MonoClass *klass, guint32 flags);
+
+MonoGenericContainer*
+mono_class_try_get_generic_container (MonoClass *klass);
+
+void
+mono_class_set_generic_container (MonoClass *klass, MonoGenericContainer *container);
+
+/*Now that everything has been defined, let's include the inline functions */
+#include <mono/metadata/class-inlines.h>
+
#endif /* __MONO_METADATA_CLASS_INTERNALS_H__ */
gboolean mono_align_small_structs = FALSE;
/* Statistics */
-guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
-guint32 classes_size, class_ext_size;
+guint32 inflated_classes_size, inflated_methods_size;
+guint32 classes_size, class_ext_size, class_ext_count;
+guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
/* Low level lock which protects data structures in this module */
static mono_mutex_t classes_mutex;
}
if (is_recursed)
break;
- if (klass->generic_class) {
- MonoGenericClass *gclass = klass->generic_class;
+ if (mono_class_is_ginst (klass)) {
+ MonoGenericClass *gclass = mono_class_get_generic_class (klass);
MonoGenericInst *inst = gclass->context.class_inst;
MonoTypeNameFormat nested_format;
int i;
g_string_append_c (str, '>');
else
g_string_append_c (str, ']');
- } else if (klass->generic_container &&
+ } else if (mono_class_is_gtd (klass) &&
(format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
(format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
int i;
g_string_append_c (str, '<');
else
g_string_append_c (str, '[');
- for (i = 0; i < klass->generic_container->type_argc; i++) {
+ for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
if (i)
g_string_append_c (str, ',');
- g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
+ g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
}
if (format == MONO_TYPE_NAME_FORMAT_IL)
g_string_append_c (str, '>');
return t->data.generic_class->context.class_inst->is_open;
case MONO_TYPE_CLASS:
case MONO_TYPE_VALUETYPE:
- return t->data.klass->generic_container != NULL;
+ return mono_class_is_gtd (t->data.klass);
default:
return FALSE;
}
case MONO_TYPE_CLASS:
case MONO_TYPE_VALUETYPE: {
MonoClass *klass = type->data.klass;
- MonoGenericContainer *container = klass->generic_container;
+ MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
MonoGenericInst *inst;
MonoGenericClass *gclass = NULL;
MonoType *nt;
MonoGenericContext *
mono_class_get_context (MonoClass *klass)
{
- return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
-}
-
-/*
- * mono_class_get_generic_container:
- *
- * Return the generic container of KLASS which should be a generic type definition.
- */
-MonoGenericContainer*
-mono_class_get_generic_container (MonoClass *klass)
-{
- g_assert (klass->is_generic);
-
- return klass->generic_container;
-}
-
-/*
- * mono_class_get_generic_class:
- *
- * Return the MonoGenericClass of KLASS, which should be a generic instance.
- */
-MonoGenericClass*
-mono_class_get_generic_class (MonoClass *klass)
-{
- g_assert (klass->is_inflated);
-
- return klass->generic_class;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ return gklass ? mono_generic_class_get_context (gklass) : NULL;
}
/*
*
*/
if (!((method->is_generic && context->method_inst) ||
- (method->klass->generic_container && context->class_inst)))
+ (mono_class_is_gtd (method->klass) && context->class_inst)))
return method;
iresult = g_new0 (MonoMethodInflated, 1);
iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
if (!context->class_inst) {
- g_assert (!iresult->declaring->klass->generic_class);
- if (iresult->declaring->klass->generic_container)
- iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
- else if (iresult->declaring->klass->generic_class)
- iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
+ g_assert (!mono_class_is_ginst (iresult->declaring->klass));
+ if (mono_class_is_gtd (iresult->declaring->klass))
+ iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
}
/* This can happen with some callers like mono_object_get_virtual_method () */
- if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
+ if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
iresult->context.class_inst = NULL;
MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
}
}
- if (!klass_hint || !klass_hint->generic_class ||
- klass_hint->generic_class->container_class != method->klass ||
- klass_hint->generic_class->context.class_inst != context->class_inst)
- klass_hint = NULL;
+ if (klass_hint) {
+ MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
+ if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
+ klass_hint = NULL;
+ }
- if (method->klass->generic_container)
+ if (mono_class_is_gtd (method->klass))
result->klass = klass_hint;
if (!result->klass) {
return NULL;
if (method->is_generic)
return &(mono_method_get_generic_container (method)->context);
- if (method->klass->generic_container)
- return &method->klass->generic_container->context;
+ if (mono_class_is_gtd (method->klass))
+ return &mono_class_get_generic_container (method->klass)->context;
return NULL;
}
mono_error_init (error);
- if (klass->generic_container)
- container = klass->generic_container;
- else if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ container = mono_class_try_get_generic_container (klass);
+ if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
- container = gklass->generic_container;
+ container = mono_class_get_generic_container (gklass);
g_assert (container);
}
if (!ftype)
goto fail;
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
//FIXME do we leak here?
ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
if (!mono_error_ok (error))
gpointer
mono_class_alloc (MonoClass *klass, int size)
{
- if (klass->generic_class)
- return mono_image_set_alloc (klass->generic_class->owner, size);
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ if (gklass)
+ return mono_image_set_alloc (gklass->owner, size);
else
return mono_image_alloc (klass->image, size);
}
static void
mono_class_setup_basic_field_info (MonoClass *klass)
{
+ MonoGenericClass *gklass;
MonoClassField *field;
MonoClassField *fields;
MonoClass *gtd;
if (klass->fields)
return;
- gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
+ gklass = mono_class_try_get_generic_class (klass);
+ gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
image = klass->image;
- if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
+
+ if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
/*
* This happens when a generic instance of an unfinished generic typebuilder
* is used as an element type for creating an array type. We can't initialize
MonoError error;
MonoImage *m = klass->image;
int top;
- guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
+ guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
int i;
guint32 real_size = 0;
guint32 packing_size = 0;
int instance_size;
gboolean explicit_size;
MonoClassField *field;
- MonoClass *gtd;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
if (klass->fields_inited)
return;
- if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
+ if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
/*
* This happens when a generic instance of an unfinished generic typebuilder
* is used as an element type for creating an array type. We can't initialize
mono_class_setup_basic_field_info (klass);
top = klass->field.count;
- gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
if (gtd) {
mono_class_setup_fields (gtd);
if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
break;
}
- if (klass->generic_container) {
+ if (mono_class_is_gtd (klass)) {
mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
break;
}
{
int i;
const int top = klass->field.count;
- guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
+ guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
guint32 pass, passes, real_size;
gboolean gc_aware_layout = FALSE;
gboolean has_static_fields = FALSE;
if (klass->methods)
return;
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
MonoError error;
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_init (gklass);
if (!mono_class_has_failure (gklass))
mono_class_get_method_by_index (MonoClass *klass, int index)
{
MonoError error;
+
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
/* Avoid calling setup_methods () if possible */
- if (klass->generic_class && !klass->methods) {
- MonoClass *gklass = klass->generic_class->container_class;
+ if (gklass && !klass->methods) {
MonoMethod *m;
m = mono_class_inflate_generic_method_full_checked (
- gklass->methods [index], klass, mono_class_get_context (klass), &error);
+ gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
/*
* If setup_methods () is called later for this class, no duplicates are created,
MonoMethod*
mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
{
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
int i;
g_assert (method->klass == gklass);
return klass->parent->vtable [offset];
}
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
MonoError error;
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_setup_vtable (gklass);
m = gklass->vtable [offset];
if (klass->ext && klass->ext->properties)
return;
- if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_init (gklass);
mono_class_setup_properties (gklass);
if (klass->ext && klass->ext->events)
return;
- if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
MonoGenericContext *context = NULL;
mono_class_setup_events (gklass);
}
mono_bitset_set (global_interface_bitset, iid);
/* set the bit also in the per-image set */
- if (!klass->generic_class) {
+ if (!mono_class_is_ginst (klass)) {
if (klass->image->interface_bitset) {
if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
if (mono_print_vtable) {
int generic_id;
char *type_name = mono_type_full_name (&klass->byval_arg);
- if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
- generic_id = klass->generic_class->context.class_inst->id;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ if (gklass && !gklass->context.class_inst->is_open) {
+ generic_id = gklass->context.class_inst->id;
g_assert (generic_id != 0);
} else {
generic_id = 0;
eclass_is_valuetype = FALSE;
original_rank = eclass->rank;
if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
- if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
/*
* For a Enumerator<T[]> we need to get the list of interfaces for T.
*/
- eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
original_rank = eclass->rank;
if (!eclass->rank)
eclass = eclass->element_class;
for (i = 0; i < num_array_interfaces; ++i) {
int offset;
ic = array_interfaces [i];
- if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
+ if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
offset = ilist_offset;
else if (strcmp (ic->name, "ICollection`1") == 0)
offset = icollection_offset;
{
MonoGenericInst *ginst;
int i;
- if (!klass->generic_class) {
+
+ if (!mono_class_is_ginst (klass)) {
mono_class_setup_vtable_full (klass, in_setup);
return !mono_class_has_failure (klass);
}
mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
- if (mono_class_set_type_load_failure_causedby_class (klass, klass->generic_class->container_class, "Failed to load generic definition vtable"))
+ if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
return FALSE;
- ginst = klass->generic_class->context.class_inst;
+ ginst = mono_class_get_generic_class (klass)->context.class_inst;
for (i = 0; i < ginst->type_argc; ++i) {
MonoClass *arg;
if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
mono_stats.generic_vtable_count ++;
in_setup = g_list_prepend (in_setup, klass);
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
if (!mono_class_check_vtable_constraints (klass, in_setup)) {
mono_loader_unlock ();
g_list_remove (in_setup, klass);
}
context = mono_class_get_context (klass);
- type_token = klass->generic_class->container_class->type_token;
+ type_token = mono_class_get_generic_class (klass)->container_class->type_token;
} else {
- context = (MonoGenericContext *) klass->generic_container;
+ context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
type_token = klass->type_token;
}
DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
/* Optimized version for generic instances */
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
MonoError error;
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
MonoMethod **tmp;
mono_class_setup_vtable_full (gklass, in_setup);
// it can happen (for injected generic array interfaces) that the same slot is
// processed multiple times (those interfaces have overlapping slots), and it
// will not always be the first pass the one that fills the slot.
- if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+ if (!mono_class_is_abstract (klass)) {
for (i = 0; i < klass->interface_offsets_count; i++) {
int ic_offset;
int im_index;
virt_methods = NULL;
/* Ensure that all vtable slots are filled with concrete instance methods */
- if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+ if (!mono_class_is_abstract (klass)) {
for (i = 0; i < cur_slot; ++i) {
if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
char *type_name = mono_type_get_full_name (klass);
}
}
- if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_init (gklass);
MonoClass *gklass;
int i;
- if (!method->klass->generic_class) {
+ if (!mono_class_is_ginst (method->klass)) {
g_assert (method->is_inflated);
return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
}
/* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
- g_assert (method->klass->generic_class);
- gklass = method->klass->generic_class->container_class;
+ g_assert (mono_class_is_ginst (method->klass));
+ gklass = mono_class_get_generic_class (method->klass)->container_class;
mono_class_setup_methods (method->klass);
g_assert (method->klass->methods);
for (i = 0; i < method->klass->method.count; ++i) {
int i;
tmp_context.class_inst = NULL;
- tmp_context.method_inst = iface->generic_class->context.class_inst;
+ tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
//g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
for (i = 0; i < generic_array_method_num; i++) {
goto leave;
}
- if (klass->generic_class && !klass->generic_class->is_dynamic) {
- MonoClass *gklass = klass->generic_class->container_class;
+ mono_stats.initialized_class_count++;
+
+ if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_init (gklass);
if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
} else {
vtable_size = szarray_vtable_size[slot];
}
- } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
- MonoClass *gklass = klass->generic_class->container_class;
+ } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
/* Generic instance case */
ghcimpl = gklass->ghcimpl;
mono_stats.initialized_class_count++;
- if (klass->generic_class && !klass->generic_class->is_dynamic) {
- MonoClass *gklass = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_stats.generic_class_count++;
klass->field = gklass->field;
}
- if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
+ if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
klass->nested_classes_inited = TRUE;
klass->ghcimpl = ghcimpl;
klass->has_cctor = has_cctor;
if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_inheritance (klass);
- if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
+ if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
goto leave;
MonoMethod *cmethod = NULL;
if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
- } else if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ } else if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
has_finalize = mono_class_has_finalizer (gklass);
} else if (klass->parent && klass->parent->has_finalize) {
klass->parent = parent;
- if (parent->generic_class && !parent->name) {
+ if (mono_class_is_ginst (parent) && !parent->name) {
/*
* If the parent is a generic instance, we may get
* called before it is fully initialized, especially
{
MonoClass *gtd = (MonoClass*)user_data;
/* Only try to fix generic instances of @gtd */
- if (gclass->generic_class->container_class != gtd)
+ if (mono_class_get_generic_class (gclass)->container_class != gtd)
return FALSE;
/* Check if the generic instance has no parent. */
name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
- klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
+ if (mono_metadata_has_generic_params (image, type_token)) {
+ klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
+ klass->class_kind = MONO_CLASS_GTD;
+ classes_size += sizeof (MonoClassGtd);
+ ++class_gtd_count;
+ } else {
+ klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
+ klass->class_kind = MONO_CLASS_DEF;
+ classes_size += sizeof (MonoClassDef);
+ ++class_def_count;
+ }
klass->name = name;
klass->name_space = nspace;
klass->image = image;
klass->type_token = type_token;
- klass->flags = cols [MONO_TYPEDEF_FLAGS];
+ mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
- classes_size += sizeof (MonoClass);
-
/*
* Check whether we're a generic type definition.
*/
- klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
- if (klass->generic_container) {
- klass->is_generic = 1;
- klass->generic_container->owner.klass = klass;
- klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
- context = &klass->generic_container->context;
- }
-
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass)) {
+ MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
+ generic_container->owner.klass = klass;
+ generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
+ context = &generic_container->context;
+ mono_class_set_generic_container (klass, generic_container);
enable_gclass_recording ();
+ }
if (cols [MONO_TYPEDEF_EXTENDS]) {
MonoClass *tmp;
mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
goto parent_failure;
}
- if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
+ if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
goto parent_failure;
}
/* uses ->valuetype, which is initialized by mono_class_setup_parent above */
mono_class_setup_mono_type (klass);
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
/*
}
}
- if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
klass->unicode = 1;
#ifdef HOST_WIN32
- if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
klass->unicode = 1;
#endif
* We must do this after the class has been constructed to make certain recursive scenarios
* work.
*/
- if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
+ if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
mono_loader_unlock ();
mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
gboolean
mono_class_is_nullable (MonoClass *klass)
{
- return klass->generic_class != NULL &&
- klass->generic_class->container_class == mono_defaults.generic_nullable_class;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
}
mono_class_get_nullable_param (MonoClass *klass)
{
g_assert (mono_class_is_nullable (klass));
- return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
}
static void
{
if (gtd->parent) {
MonoError error;
- MonoGenericClass *gclass = klass->generic_class;
+ MonoGenericClass *gclass = mono_class_get_generic_class (klass);
klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
if (!mono_error_ok (&error)) {
return gclass->cached_class;
}
- klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
+ klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
gklass = gclass->container_class;
mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
klass->image = gklass->image;
- klass->flags = gklass->flags;
klass->type_token = gklass->type_token;
klass->field.count = gklass->field.count;
- klass->is_inflated = 1;
- klass->generic_class = gclass;
+ klass->class_kind = MONO_CLASS_GINST;
+ //FIXME add setter
+ ((MonoClassGenericInst*)klass)->generic_class = gclass;
klass->byval_arg.type = MONO_TYPE_GENERICINST;
klass->this_arg.type = klass->byval_arg.type;
mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
- inflated_classes ++;
- inflated_classes_size += sizeof (MonoClass);
+ ++class_ginst_count;
+ inflated_classes_size += sizeof (MonoClassGenericInst);
mono_loader_unlock ();
gboolean is_mvar = container->is_method;
gboolean is_anonymous = container->is_anonymous;
- klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
- classes_size += sizeof (MonoClass);
+ klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
+ klass->class_kind = MONO_CLASS_GPARAM;
+ classes_size += sizeof (MonoClassGenericParam);
+ ++class_gparam_count;
if (pinfo) {
CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
klass->inited = TRUE;
CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
- klass->flags = TYPE_ATTRIBUTE_PUBLIC;
klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
klass->this_arg.type = klass->byval_arg.type;
}
mono_image_unlock (image);
- result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
+ result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
- classes_size += sizeof (MonoClass);
+ classes_size += sizeof (MonoClassPointer);
+ ++class_pointer_count;
result->parent = NULL; /* no parent for PTR types */
result->name_space = el_class->name_space;
name = g_strdup_printf ("%s*", el_class->name);
result->name = mono_image_strdup (image, name);
+ result->class_kind = MONO_CLASS_POINTER;
g_free (name);
mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
result->image = el_class->image;
result->inited = TRUE;
- result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
result->cast_class = result->element_class = el_class;
result->blittable = TRUE;
}
result = g_new0 (MonoClass, 1);
+ classes_size += sizeof (MonoClassPointer);
+ ++class_pointer_count;
+
result->parent = NULL; /* no parent for PTR types */
result->name_space = "System";
result->name = "MonoFNPtrFakeClass";
+ result->class_kind = MONO_CLASS_POINTER;
mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
result->image = mono_defaults.corlib; /* need to fix... */
result->inited = TRUE;
- result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
result->cast_class = result->element_class = result;
result->blittable = TRUE;
if (!parent->inited)
mono_class_init (parent);
- klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
+ klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
klass->image = image;
klass->name_space = eclass->name_space;
+ klass->class_kind = MONO_CLASS_ARRAY;
+
nsize = strlen (eclass->name);
name = (char *)g_malloc (nsize + 2 + rank + 1);
memcpy (name, eclass->name, nsize);
mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
- classes_size += sizeof (MonoClass);
+ classes_size += sizeof (MonoClassArray);
+ ++class_array_count;
klass->type_token = 0;
- /* all arrays are marked serializable and sealed, bug #42779 */
- klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
klass->parent = parent;
klass->instance_size = mono_class_instance_size (klass->parent);
mono_class_setup_supertypes (klass);
- if (eclass->generic_class)
+ if (mono_class_is_ginst (eclass))
mono_class_init (eclass);
mono_class_init_sizes (eclass);
mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
klass->this_arg = klass->byval_arg;
klass->this_arg.byref = 1;
- klass->generic_container = eclass->generic_container;
+ //WTF was this? it's wrong
+ // klass->generic_container = eclass->generic_container;
if (rank == 1 && !bounded) {
MonoClass *prev_class;
int i;
MonoGenericContainer *container;
- if (!klass->generic_class)
+ if (!mono_class_is_ginst (klass))
return FALSE;
- container = klass->generic_class->container_class->generic_container;
+ container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
for (i = 0; i < container->type_argc; ++i)
if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
int j;
MonoType **klass_argv, **oklass_argv;
MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
- MonoGenericContainer *container = klass_gtd->generic_container;
+ MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
if (klass == oklass)
return TRUE;
if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
return FALSE;
- klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
- oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
+ klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
+ oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
for (j = 0; j < container->type_argc; ++j) {
MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
int j;
MonoType **klass_argv, **oklass_argv;
MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
- MonoGenericContainer *container = klass_gtd->generic_container;
+ MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
/*Viable candidates are instances of the same generic interface*/
if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
return FALSE;
- klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
- oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
+ klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
+ oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
for (j = 0; j < container->type_argc; ++j) {
MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
return result;
}
- if (klass->generic_class && !klass->methods)
- return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
+ if (mono_class_is_ginst (klass) && !klass->methods)
+ return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
}
return klass->rank;
}
-/**
- * mono_class_get_flags:
- * @klass: the MonoClass to act on
- *
- * The type flags from the TypeDef table from the metadata.
- * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
- * different values.
- *
- * Returns: The flags from the TypeDef table.
- */
-guint32
-mono_class_get_flags (MonoClass *klass)
-{
- return klass->flags;
-}
-
/**
* mono_class_get_name
* @klass: the MonoClass to act on
mono_class_init (klass);
- if (klass->generic_class && !klass->methods) {
- res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
+ if (mono_class_is_ginst (klass) && !klass->methods) {
+ res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
if (res) {
MonoError error;
res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
mono_native_tls_alloc (&setup_fields_tls_id, NULL);
mono_native_tls_alloc (&init_pending_tls_id, NULL);
+ mono_counters_register ("MonoClassDef count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
+ mono_counters_register ("MonoClassGtd count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
+ mono_counters_register ("MonoClassGenericInst count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
+ mono_counters_register ("MonoClassGenericParam count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
+ mono_counters_register ("MonoClassArray count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
+ mono_counters_register ("MonoClassPointer count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
mono_counters_register ("Inflated methods size",
MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
- mono_counters_register ("Inflated classes",
- MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
mono_counters_register ("Inflated classes size",
MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
mono_counters_register ("MonoClass size",
MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
mono_counters_register ("MonoClassExt size",
MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
+
+ mono_counters_register ("MonoClassExt count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
}
/**
MonoClass *
mono_class_get_generic_type_definition (MonoClass *klass)
{
- return klass->generic_class ? klass->generic_class->container_class : klass;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ return gklass ? gklass->container_class : klass;
}
/*
get_generic_definition_class (MonoClass *klass)
{
while (klass) {
- if (klass->generic_class && klass->generic_class->container_class)
- return klass->generic_class->container_class;
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ if (gklass && gklass->container_class)
+ return gklass->container_class;
klass = klass->parent;
}
return NULL;
if (member_klass->element_class && !member_klass->enumtype)
member_klass = member_klass->element_class;
- access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+ access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
return TRUE;
- if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
+ if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
return FALSE;
if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
return TRUE;
- if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
- access_klass->generic_container) &&
+ MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
+ if (((access_gklass && access_gklass->container_class) ||
+ mono_class_is_gtd (access_klass)) &&
(member_generic_def = get_generic_definition_class (member_klass))) {
MonoClass *access_container;
- if (access_klass->generic_container)
+ if (mono_class_is_gtd (access_klass))
access_container = access_klass;
else
- access_container = access_klass->generic_class->container_class;
+ access_container = access_gklass->container_class;
if (can_access_member (access_container, member_generic_def, context_klass, access_level))
return TRUE;
return FALSE;
}
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
return FALSE;
while ((field = mono_class_get_fields (klass, &iter))) {
gboolean
mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
{
- return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
+ return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
}
/*
if (!klass->ext)
klass->ext = ext;
class_ext_size += sizeof (MonoClassExt);
+ ++class_ext_count;
mono_image_unlock (klass->image);
}
if (interface_count > 1)
interfaces [1] = mono_class_bind_generic_parameters (
mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
- } else if (klass->generic_class) {
- MonoClass *gklass = klass->generic_class->container_class;
+ } else if (mono_class_is_ginst (klass)) {
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_class_setup_interfaces (gklass, error);
if (!mono_error_ok (error)) {
interface_count = gklass->interface_count;
interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
for (i = 0; i < interface_count; i++) {
- interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
+ interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
if (!mono_error_ok (error)) {
mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
return;
{
MonoClass *klass = field->parent;
MonoImage *image = klass->image;
- MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
+ MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
int field_idx = field - klass->fields;
mono_error_init (error);
/*FIXME, in theory we do not lazy load SRE fields*/
g_assert (!image_is_dynamic (image));
- if (klass->generic_container) {
- container = klass->generic_container;
+ if (mono_class_is_gtd (klass)) {
+ container = mono_class_get_generic_container (klass);
} else if (gtd) {
- container = gtd->generic_container;
+ container = mono_class_get_generic_container (gtd);
g_assert (container);
}
{
MonoClass *klass = field->parent;
MonoImage *image = klass->image;
- MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
+ MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
int field_idx = field - klass->fields;
static gboolean cominterop_can_support_dispatch (MonoClass* klass)
{
- if (!(klass->flags & TYPE_ATTRIBUTE_PUBLIC) )
+ if (!(mono_class_get_flags (klass) & TYPE_ATTRIBUTE_PUBLIC) )
return FALSE;
if (!cominterop_com_visible (klass))
MonoCustomAttrInfo*
mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs);
+typedef gboolean (*MonoAssemblyMetadataCustomAttrIterFunc) (MonoImage *image, guint32 typeref_scope_token, const gchar* nspace, const gchar* name, guint32 method_token, gpointer user_data);
+
+void
+mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssemblyMetadataCustomAttrIterFunc func, gpointer user_data);
+
#endif /* __MONO_METADATA_REFLECTION_CUSTOM_ATTRS_INTERNALS_H__ */
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
+#include "mono/metadata/assembly.h"
#include "mono/metadata/gc-internals.h"
#include "mono/metadata/mono-endian.h"
#include "mono/metadata/object-internals.h"
/* FIXME: Need to do more checks */
if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
- int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+ int visibility = mono_class_get_flags (cattr->ctor->method->klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
return FALSE;
mono_error_init (error);
- if (klass->generic_class)
- klass = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass))
+ klass = mono_class_get_generic_class (klass)->container_class;
if (image_is_dynamic (klass->image))
return lookup_custom_attr (klass->image, klass);
return result;
}
+
+static gboolean
+custom_attr_class_name_from_methoddef (MonoImage *image, guint32 method_token, const gchar **nspace, const gchar **class_name)
+{
+ /* mono_get_method_from_token () */
+ g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD);
+ guint32 type_token = mono_metadata_typedef_from_method (image, method_token);
+ if (!type_token) {
+ /* Bad method token (could not find corresponding typedef) */
+ return FALSE;
+ }
+ type_token |= MONO_TOKEN_TYPE_DEF;
+ {
+ /* mono_class_create_from_typedef () */
+ MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
+ guint32 cols [MONO_TYPEDEF_SIZE];
+ guint tidx = mono_metadata_token_index (type_token);
+
+ if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
+ /* "Invalid typedef token %x", type_token */
+ return FALSE;
+ }
+
+ mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
+
+ if (class_name)
+ *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
+ if (nspace)
+ *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
+ return TRUE;
+ }
+}
+
+
+/**
+ * custom_attr_class_name_from_method_token:
+ * @image: The MonoImage
+ * @method_token: a token for a custom attr constructor in @image
+ * @assembly_token: out argment set to the assembly ref token of the custom attr
+ * @nspace: out argument set to namespace (a string in the string heap of @image) of the custom attr
+ * @class_name: out argument set to the class name of the custom attr.
+ *
+ * Given an @image and a @method_token (which is assumed to be a
+ * constructor), fills in the out arguments with the assembly ref (if
+ * a methodref) and the namespace and class name of the custom
+ * attribute.
+ *
+ * Returns: TRUE on success, FALSE otherwise.
+ *
+ * LOCKING: does not take locks
+ */
+static gboolean
+custom_attr_class_name_from_method_token (MonoImage *image, guint32 method_token, guint32 *assembly_token, const gchar **nspace, const gchar **class_name)
+{
+ /* This only works with method tokens constructed from a
+ * custom attr token, which can only be methoddef or
+ * memberref */
+ g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD
+ || mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF);
+
+ if (mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF) {
+ /* method_from_memberref () */
+ guint32 cols[6];
+ guint32 nindex, class_index;
+
+ int idx = mono_metadata_token_index (method_token);
+
+ mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], idx-1, cols, 3);
+ nindex = cols [MONO_MEMBERREF_CLASS] >> MONO_MEMBERREF_PARENT_BITS;
+ class_index = cols [MONO_MEMBERREF_CLASS] & MONO_MEMBERREF_PARENT_MASK;
+ if (class_index == MONO_MEMBERREF_PARENT_TYPEREF) {
+ guint32 type_token = MONO_TOKEN_TYPE_REF | nindex;
+ /* mono_class_from_typeref_checked () */
+ {
+ guint32 cols [MONO_TYPEREF_SIZE];
+ MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
+
+ mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
+
+ if (class_name)
+ *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
+ if (nspace)
+ *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
+ if (assembly_token)
+ *assembly_token = cols [MONO_TYPEREF_SCOPE];
+ return TRUE;
+ }
+ } else if (class_index == MONO_MEMBERREF_PARENT_METHODDEF) {
+ guint32 methoddef_token = MONO_TOKEN_METHOD_DEF | nindex;
+ if (assembly_token)
+ *assembly_token = 0;
+ return custom_attr_class_name_from_methoddef (image, methoddef_token, nspace, class_name);
+ } else {
+ /* Attributes can't be generic, so it won't be
+ * a typespec, and they're always
+ * constructors, so it won't be a moduleref */
+ g_assert_not_reached ();
+ }
+ } else {
+ /* must be MONO_TABLE_METHOD */
+ if (assembly_token)
+ *assembly_token = 0;
+ return custom_attr_class_name_from_methoddef (image, method_token, nspace, class_name);
+ }
+}
+
+/**
+ * mono_assembly_metadata_foreach_custom_attr:
+ * @assembly: the assembly to iterate over
+ * @func: the function to call for each custom attribute
+ * @user_data: passed to @func
+ *
+ * Calls @func for each custom attribute type on the given assembly until @func returns TRUE.
+ * Everything is done using low-level metadata APIs, so it is safe to use during assembly loading.
+ *
+ */
+void
+mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssemblyMetadataCustomAttrIterFunc func, gpointer user_data)
+{
+ MonoImage *image;
+ guint32 mtoken, i;
+ guint32 cols [MONO_CUSTOM_ATTR_SIZE];
+ MonoTableInfo *ca;
+ guint32 idx;
+
+ /*
+ * This might be called during assembly loading, so do everything using the low-level
+ * metadata APIs.
+ */
+
+ image = assembly->image;
+ g_assert (!image_is_dynamic (image));
+ idx = 1; /* there is only one assembly */
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
+
+ /* Inlined from mono_custom_attrs_from_index_checked () */
+ ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+ i = mono_metadata_custom_attrs_from_index (image, idx);
+ if (!i)
+ return;
+ i --;
+ gboolean stop_iterating = FALSE;
+ while (!stop_iterating && i < ca->rows) {
+ if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
+ break;
+ mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
+ i ++;
+ mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
+ switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
+ case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
+ mtoken |= MONO_TOKEN_METHOD_DEF;
+ break;
+ case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
+ mtoken |= MONO_TOKEN_MEMBER_REF;
+ break;
+ default:
+ g_warning ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
+ continue;
+ }
+
+ const char *nspace = NULL;
+ const char *name = NULL;
+ guint32 assembly_token = 0;
+
+ if (!custom_attr_class_name_from_method_token (image, mtoken, &assembly_token, &nspace, &name))
+ continue;
+
+ stop_iterating = func (image, assembly_token, nspace, name, mtoken, user_data);
+ }
+}
#include <mono/metadata/w32mutex.h>
#include <mono/metadata/w32semaphore.h>
#include <mono/metadata/w32event.h>
+#include <mono/metadata/w32process.h>
#include <metadata/threads.h>
#include <metadata/profiler-private.h>
#include <mono/metadata/coree.h>
static MonoDomain *domain = NULL;
MonoAssembly *ass = NULL;
MonoImageOpenStatus status = MONO_IMAGE_OK;
- const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
+ const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1] = { NULL };
int n, dummy;
#ifdef DEBUG_DOMAIN_UNLOAD
mono_w32mutex_init ();
mono_w32semaphore_init ();
mono_w32event_init ();
+ mono_w32process_init ();
#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters_init ();
mono_profiler_appdomain_name (domain, domain->friendly_name);
- /* Have to do this quite late so that we at least have System.Object */
- MonoError custom_attr_error;
- if (mono_assembly_has_reference_assembly_attribute (ass, &custom_attr_error)) {
- char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
- g_print ("Could not load file or assembly %s. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context.", corlib_file);
- g_free (corlib_file);
- exit (1);
- }
- mono_error_assert_ok (&custom_attr_error);
-
return domain;
}
mono_native_tls_free (appdomain_thread_id);
mono_coop_mutex_destroy (&appdomains_mutex);
+ mono_w32process_cleanup ();
+
#ifndef HOST_WIN32
wapi_cleanup ();
#endif
} else {
/* the C# code will check and throw the exception */
/* FIXME: missing !klass->blittable test, see bug #61134 */
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
return (gpointer)-1;
return (char*)obj + sizeof (MonoObject);
}
void
mono_icall_write_windows_debug_string (MonoString *message);
-MonoBoolean
-mono_icall_close_process (gpointer handle);
-
gint32
mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds);
#endif /* HOST_WIN32 */
guint32
mono_icall_drive_info_get_drive_type (MonoString *root_path_name);
-
-MonoBoolean
-mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max);
-
-MonoBoolean
-mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max);
-
-gint32
-mono_icall_get_priority_class (gpointer handle);
-
-MonoBoolean
-mono_icall_set_priority_class (gpointer handle, gint32 priorityClass);
#endif /* !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
#endif /* __MONO_METADATA_ICALL_INTERNALS_H__ */
return WAIT_TIMEOUT;
}
-MonoBoolean
-mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("GetProcessWorkingSetSize");
-
- mono_error_set_not_supported(&mono_error, G_UNSUPPORTED_API, "GetProcessWorkingSetSize");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-MonoBoolean
-mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("SetProcessWorkingSetSize");
-
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "SetProcessWorkingSetSize");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-gint32
-mono_icall_get_priority_class (gpointer handle)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("GetPriorityClass");
-
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetPriorityClass");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-MonoBoolean
-mono_icall_set_priority_class (gpointer handle, gint32 priorityClass)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("SetPriorityClass");
-
- mono_error_set_not_supported(&mono_error, G_UNSUPPORTED_API, "SetPriorityClass");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
#ifdef _MSC_VER
OutputDebugString (mono_string_chars (message));
}
-MonoBoolean
-mono_icall_close_process (gpointer handle)
-{
- return (MonoBoolean)(CloseHandle (handle));
-}
#endif /* HOST_WIN32 */
#include <mono/metadata/sysmath.h>
#include <mono/metadata/string-icalls.h>
#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/process.h>
+#include <mono/metadata/w32process.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/locales.h>
klass = mono_class_from_mono_type (handle);
MONO_CHECK_ARG (handle, klass,);
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
return;
vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
}
static MonoReflectionType *
-type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
+type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoAssembly **caller_assembly, MonoError *error)
{
MonoMethod *m, *dest;
} else {
g_warning (G_STRLOC);
}
+ *caller_assembly = assembly;
if (info->assembly.name)
assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
MonoTypeNameParse info;
MonoReflectionType *type = NULL;
gboolean parsedOk;
+ MonoAssembly *caller_assembly;
char *str = mono_string_to_utf8_checked (name, &error);
if (!is_ok (&error))
goto leave;
}
- type = type_from_parsed_name (&info, ignoreCase, &error);
+ type = type_from_parsed_name (&info, ignoreCase, &caller_assembly, &error);
- mono_reflection_free_type_info (&info);
-
- if (!is_ok (&error))
+ if (!is_ok (&error)) {
+ mono_reflection_free_type_info (&info);
goto leave;
+ }
- if (type == NULL){
+ if (type == NULL) {
if (throwOnError) {
- mono_error_set_type_load_name (&error, g_strdup (str), g_strdup (""), "");
- goto leave;
+ char *tname = info.name_space ? g_strdup_printf ("%s.%s", info.name_space, info.name) : g_strdup (info.name);
+ char *aname;
+ if (info.assembly.name)
+ aname = mono_stringify_assembly_name (&info.assembly);
+ else if (caller_assembly)
+ aname = mono_stringify_assembly_name (mono_assembly_get_name (caller_assembly));
+ else
+ aname = g_strdup ("");
+ mono_error_set_type_load_name (&error, tname, aname, "");
}
+ mono_reflection_free_type_info (&info);
+ goto leave;
}
leave:
ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
{
MonoClass *klass = mono_class_from_mono_type (type->type);
- return klass->flags;
+ return mono_class_get_flags (klass);
}
ICALL_EXPORT MonoReflectionMarshalAsAttribute*
MonoType *ftype;
int i;
- if (klass->generic_container ||
- (klass->generic_class && klass->generic_class->context.class_inst->is_open))
+ MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
+ if (mono_class_is_gtd (klass) ||
+ (gklass && gklass->context.class_inst->is_open))
return NULL;
ftype = mono_field_get_type (field->field);
if (!mono_error_ok (data->error))
return;
- if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
+ if (data->context && mono_class_is_ginst (ic) && mono_class_get_generic_class (ic)->context.class_inst->is_open) {
inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
if (!mono_error_ok (data->error))
return;
GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
- if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
+ if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open) {
data.context = mono_class_get_context (klass);
- klass = klass->generic_class->container_class;
+ klass = mono_class_get_generic_class (klass)->container_class;
}
for (parent = klass; parent; parent = parent->parent) {
klass = mono_class_from_mono_type (type->type);
- if (klass->generic_container) {
- MonoGenericContainer *container = klass->generic_container;
+ if (mono_class_is_gtd (klass)) {
+ MonoGenericContainer *container = mono_class_get_generic_container (klass);
res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
if (mono_error_set_pending_exception (&error))
return NULL;
mono_array_setref (res, i, rt);
}
- } else if (klass->generic_class) {
- MonoGenericInst *inst = klass->generic_class->context.class_inst;
+ } else if (mono_class_is_ginst (klass)) {
+ MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
if (mono_error_set_pending_exception (&error))
return NULL;
return FALSE;
klass = mono_class_from_mono_type (type->type);
- return klass->generic_container != NULL;
+ return mono_class_is_gtd (klass);
}
ICALL_EXPORT MonoReflectionType*
klass = mono_class_from_mono_type (type->type);
- if (klass->generic_container) {
+ if (mono_class_is_gtd (klass)) {
return type; /* check this one */
}
- if (klass->generic_class) {
- MonoClass *generic_class = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass)) {
+ MonoClass *generic_class = mono_class_get_generic_class (klass)->container_class;
gpointer tb;
tb = mono_class_get_ref_info (generic_class);
klass = mono_class_from_mono_type (geninst);
/*we might inflate to the GTD*/
- if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
+ if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
return NULL;
}
return FALSE;
klass = mono_class_from_mono_type (type->type);
- return klass->generic_class != NULL || klass->generic_container != NULL;
+ return mono_class_is_ginst (klass) || mono_class_is_gtd (klass);
}
ICALL_EXPORT gint32
return NULL;
}
- if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
+ if (mono_class_is_abstract (m->klass) && !strcmp (m->name, ".ctor") && !this_arg) {
mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
return NULL;
}
* nested types that aren't generic. In any case, the container of that
* nested type would be the generic type definition.
*/
- if (klass->generic_class)
- klass = klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass))
+ klass = mono_class_get_generic_class (klass)->container_class;
res_array = g_ptr_array_new ();
iter = NULL;
while ((nested = mono_class_get_nested_types (klass, &iter))) {
match = 0;
- if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
+ if ((mono_class_get_flags (nested) & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
if (bflags & BFLAGS_Public)
match++;
} else {
MonoGenericContext ctx;
ctx.method_inst = inflated->context.method_inst;
ctx.class_inst = inflated->context.class_inst;
- if (klass->generic_class)
- ctx.class_inst = klass->generic_class->context.class_inst;
- else if (klass->generic_container)
- ctx.class_inst = klass->generic_container->context.class_inst;
+ if (mono_class_is_ginst (klass))
+ ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
+ else if (mono_class_is_gtd (klass))
+ ctx.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
return result;
mono_class_setup_vtable (klass);
vtable = klass->vtable;
- if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (method->klass)) {
gboolean variance_used = FALSE;
/*MS fails with variant interfaces but it's the right thing to do anyway.*/
int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
if (mono_error_set_pending_exception (&error))
return NULL;
- if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+ if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
return NULL;
}
return m;
klass = method->klass;
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
generic_inst = mono_class_get_context (klass);
- klass = klass->generic_class->container_class;
+ klass = mono_class_get_generic_class (klass)->container_class;
}
retry:
return NULL;
}
}
- if (parent->generic_class) {
+ if (mono_class_is_ginst (parent)) {
parent_inst = mono_class_get_context (parent);
- parent = parent->generic_class->container_class;
+ parent = mono_class_get_generic_class (parent)->container_class;
}
mono_class_setup_vtable (parent);
generic_inst = NULL;
}
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
generic_inst = mono_class_get_context (klass);
- klass = klass->generic_class->container_class;
+ klass = mono_class_get_generic_class (klass)->container_class;
}
}
return message;
}
-ICALL_EXPORT gpointer
-ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
-{
- return GetCurrentProcess ();
-}
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
-{
- return GetExitCodeProcess (handle, (guint32*) exitcode);
-}
-
-#ifndef HOST_WIN32
-static inline MonoBoolean
-mono_icall_close_process (gpointer handle)
-{
- return CloseProcess (handle);
-}
-#endif /* !HOST_WIN32 */
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
-{
- return mono_icall_close_process (handle);
-}
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
-{
- return TerminateProcess (handle, exitcode);
-}
-
#ifndef HOST_WIN32
static inline gint32
mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
return mono_icall_wait_for_input_idle (handle, milliseconds);
}
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline MonoBoolean
-mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max)
-{
- return GetProcessWorkingSetSize (handle, min, max);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
-{
- return mono_icall_get_process_working_set_size (handle, min, max);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline MonoBoolean
-mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max)
-{
- return SetProcessWorkingSetSize (handle, min, max);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
-{
- return mono_icall_set_process_working_set_size (handle, min, max);
-}
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
-{
- return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
-}
-
ICALL_EXPORT gint32
ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
{
return mono_process_current_pid ();
}
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline gint32
-mono_icall_get_priority_class (gpointer handle)
-{
- return GetPriorityClass (handle);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-ICALL_EXPORT gint32
-ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
-{
- return mono_icall_get_priority_class (handle);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline MonoBoolean
-mono_icall_set_priority_class (gpointer handle, gint32 priorityClass)
-{
- return SetPriorityClass (handle, priorityClass);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-ICALL_EXPORT MonoBoolean
-ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
-{
- return mono_icall_set_priority_class (handle, priorityClass);
-}
-
ICALL_EXPORT MonoBoolean
ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
{
static gpointer*
class_next_value (gpointer value)
{
- MonoClass *klass = (MonoClass *)value;
+ MonoClassDef *klass = (MonoClassDef *)value;
return (gpointer*)&klass->next_class_cache;
}
}
}
- if (field && field->parent && !field->parent->generic_class && !field->parent->generic_container) {
+ if (field && field->parent && !mono_class_is_ginst (field->parent) && !mono_class_is_gtd (field->parent)) {
mono_image_lock (image);
mono_conc_hashtable_insert (image->field_cache, GUINT_TO_POINTER (token), field);
mono_image_unlock (image);
/* Search directly in the metadata to avoid calling setup_methods () */
mono_error_init (error);
- /* FIXME: !from_class->generic_class condition causes test failures. */
- if (klass->type_token && !image_is_dynamic (klass->image) && !klass->methods && !klass->rank && klass == from_class && !from_class->generic_class) {
+ /* FIXME: !mono_class_is_ginst (from_class) condition causes test failures. */
+ if (klass->type_token && !image_is_dynamic (klass->image) && !klass->methods && !klass->rank && klass == from_class && !mono_class_is_ginst (from_class)) {
for (i = 0; i < klass->method.count; ++i) {
guint32 cols [MONO_METHOD_SIZE];
MonoMethod *method;
return mono_method_signature_checked (method, error);
}
- if (method->klass->generic_class)
+ if (mono_class_is_ginst (method->klass))
return mono_method_signature_checked (method, error);
if (image_is_dynamic (image)) {
type = &klass->byval_arg;
if (type->type != MONO_TYPE_ARRAY && type->type != MONO_TYPE_SZARRAY) {
- MonoClass *in_class = klass->generic_class ? klass->generic_class->container_class : klass;
+ MonoClass *in_class = mono_class_is_ginst (klass) ? mono_class_get_generic_class (klass)->container_class : klass;
method = find_method (in_class, NULL, mname, sig, klass, error);
break;
}
klass = method->klass;
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
g_assert (method->is_inflated);
method = ((MonoMethodInflated *) method)->declaring;
}
- new_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
+ new_context.class_inst = mono_class_is_ginst (klass) ? mono_class_get_generic_class (klass)->context.class_inst : NULL;
new_context.method_inst = inst;
method = mono_class_inflate_generic_method_full_checked (method, klass, &new_context, error);
sig = mono_metadata_blob_heap (image, cols [4]);
/* size = */ mono_metadata_decode_blob_size (sig, &sig);
- container = klass->generic_container;
+ container = mono_class_try_get_generic_container (klass);
/*
* load_generic_params does a binary search so only call it if the method
sig = mono_metadata_blob_heap (img, sig_offset = mono_metadata_decode_row_col (&img->tables [MONO_TABLE_METHOD], idx - 1, MONO_METHOD_SIGNATURE));
- g_assert (!m->klass->generic_class);
+ g_assert (!mono_class_is_ginst (m->klass));
container = mono_method_get_generic_container (m);
if (!container)
- container = m->klass->generic_container;
+ container = mono_class_try_get_generic_container (m->klass);
/* Generic signatures depend on the container so they cannot be cached */
/* icall/pinvoke signatures cannot be cached cause we modify them below */
*/
container = mono_method_get_generic_container (method);
if (!container)
- container = method->klass->generic_container;
+ container = mono_class_try_get_generic_container (method->klass);
return mono_metadata_parse_mh_full (img, container, (const char *)loc, error);
}
static gboolean use_aot_wrappers;
+static int class_marshal_info_count;
+
static void ftnptr_eh_callback_default (guint32 gchandle);
static MonoFtnPtrEHCallback ftnptr_eh_callback = ftnptr_eh_callback_default;
mono_cominterop_init ();
mono_remoting_init ();
+
+ mono_counters_register ("MonoClass::class_marshal_info_count count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_marshal_info_count);
+
}
}
}
if (klass != mono_class_try_get_safehandle_class ()) {
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
char *msg = g_strdup_printf ("Type %s which is passed to unmanaged code must have a StructLayout attribute.",
mono_type_full_name (&klass->byval_arg));
mono_mb_emit_exception_marshal_directive (mb, msg);
* the layout to the managed structure as well.
*/
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) && (usize == 0)) {
+ if (((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) && (usize == 0)) {
if (MONO_TYPE_IS_REFERENCE (info->fields [i].field->type) ||
((!last_field && MONO_TYPE_IS_REFERENCE (info->fields [i + 1].field->type))))
g_error ("Type %s which has an [ExplicitLayout] attribute cannot have a "
MonoMethod *res;
GHashTable *cache;
gpointer cache_key = NULL;
- SignaturePointerPair key;
+ SignaturePointerPair key = { NULL, NULL };
SignaturePointerPair *new_key;
int local_i, local_len, local_delegates, local_d, local_target, local_res;
int pos0, pos1, pos2;
container = mono_method_get_generic_container (method);
if (!container)
- container = method->klass->generic_container;
+ container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
g_assert (container);
invoke_sig = sig = mono_signature_no_pinvoke (method);
break;
}
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+ if (((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
klass->blittable || klass->enumtype)
break;
/* Have to change the signature since the vtype is passed byref */
m->csig->params [argnum - m->csig->hasthis] = &mono_defaults.int_class->byval_arg;
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+ if (((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
klass->blittable || klass->enumtype)
mono_mb_emit_ldarg_addr (mb, argnum);
else
break;
}
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+ if (((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
klass->blittable || klass->enumtype) {
mono_mb_emit_ldarg (mb, argnum);
break;
break;
}
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+ if (((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
klass->blittable || klass->enumtype)
break;
break;
case MARSHAL_ACTION_CONV_RESULT:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+ if (((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
klass->blittable) {
mono_mb_emit_stloc (mb, 3);
break;
break;
case MARSHAL_ACTION_MANAGED_CONV_IN:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+ if (((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
klass->blittable || klass->enumtype) {
conv_arg = 0;
break;
break;
case MARSHAL_ACTION_MANAGED_CONV_OUT:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+ if (((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
klass->blittable || klass->enumtype) {
break;
}
break;
case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+ if (((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
klass->blittable || klass->enumtype) {
mono_mb_emit_stloc (mb, 3);
m->retobj_var = 0;
MonoMethod *ctor = NULL;
int intptr_handle_slot;
- if (t->data.klass->flags & TYPE_ATTRIBUTE_ABSTRACT){
+ if (mono_class_is_abstract (t->data.klass)) {
mono_mb_emit_byte (mb, CEE_POP);
mono_mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract"));
break;
}
/* The class can not have an automatic layout */
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
mono_mb_emit_auto_layout_exception (mb, klass);
break;
}
}
/* The class can not have an automatic layout */
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
mono_mb_emit_auto_layout_exception (mb, klass);
break;
}
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
MonoClass *klass = mono_class_from_mono_type (sig->ret);
mono_class_init (klass);
- if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
+ if (!(((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
/* This is used by emit_marshal_vtype (), but it needs to go right before the call */
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
MonoClass *klass = mono_class_from_mono_type (sig->ret);
mono_class_init (klass);
- if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
+ if (!(((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
/* This is used by emit_marshal_vtype (), but it needs to go right before the call */
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
method = ((MonoMethodInflated*)method)->declaring;
container = mono_method_get_generic_container (method);
if (!container)
- container = method->klass->generic_container;
+ container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
g_assert (container);
}
method = ((MonoMethodInflated*)method)->declaring;
container = mono_method_get_generic_container (method);
if (!container)
- container = method->klass->generic_container;
+ container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
g_assert (container);
}
return FALSE;
element_class = klass->element_class;
- return (element_class->flags & TYPE_ATTRIBUTE_SEALED) || element_class->valuetype;
+ return (mono_class_get_flags (element_class) & TYPE_ATTRIBUTE_SEALED) || element_class->valuetype;
}
static int
/*Arrays are sealed but are covariant on their element type, We can't use any of the fast paths.*/
if (mono_class_is_marshalbyref (element_class) || element_class->rank || mono_class_has_variant_generic_params (element_class))
return STELEMREF_COMPLEX;
- if (element_class->flags & TYPE_ATTRIBUTE_SEALED)
+ if (mono_class_get_flags (element_class) & TYPE_ATTRIBUTE_SEALED)
return STELEMREF_SEALED_CLASS;
return STELEMREF_CLASS;
}
return 0;
}
- layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
+ layout = (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK);
if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) {
return sizeof (gpointer);
count++;
}
- layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
+ layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
/* The mempool is protected by the loader lock */
info = (MonoMarshalType *)mono_image_alloc0 (klass->image, MONO_SIZEOF_MARSHAL_TYPE + sizeof (MonoMarshalField) * count);
/*We do double-checking locking on marshal_info */
mono_memory_barrier ();
klass->marshal_info = info;
+ ++class_marshal_info_count;
}
mono_marshal_unlock ();
klass = t->data.klass;
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
break;
- if (klass->valuetype && (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+ if (klass->valuetype && (((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
klass->blittable || klass->enumtype))
return mono_object_unbox (o);
case MONO_TYPE_VALUETYPE: {
klass = t->data.klass;
- if (klass->valuetype && (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+ if (klass->valuetype && (((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
klass->blittable || klass->enumtype))
break;
static gboolean
mono_metadata_is_type_builder_generic_type_definition (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
{
- MonoGenericContainer *container = container_class->generic_container;
+ MonoGenericContainer *container = mono_class_get_generic_container (container_class);
if (!is_dynamic || container_class->wastypebuilder || container->type_argc != inst->type_argc)
return FALSE;
gclass->context.class_inst = inst;
gclass->context.method_inst = NULL;
gclass->owner = set;
- if (inst == container_class->generic_container->context.class_inst && !is_tb_open)
+ if (inst == mono_class_get_generic_container (container_class)->context.class_inst && !is_tb_open)
gclass->cached_class = container_class;
g_hash_table_insert (set->gclass_cache, gclass, gclass);
return FALSE;
gklass = mono_class_from_mono_type (gtype);
- if (!gklass->generic_container) {
+ if (!mono_class_is_gtd (gklass)) {
mono_error_set_bad_image (error, m, "Generic instance with non-generic definition");
return FALSE;
}
_mono_metadata_generic_class_container_equal (const MonoGenericClass *g1, MonoClass *c2, gboolean signature_only)
{
MonoGenericInst *i1 = g1->context.class_inst;
- MonoGenericInst *i2 = c2->generic_container->context.class_inst;
+ MonoGenericInst *i2 = mono_class_get_generic_container (c2)->context.class_inst;
if (!mono_metadata_class_equal (g1->container_class, c2, signature_only))
return FALSE;
{
if (c1 == c2)
return TRUE;
- if (c1->generic_class && c2->generic_class)
- return _mono_metadata_generic_class_equal (c1->generic_class, c2->generic_class, signature_only);
- if (c1->generic_class && c2->generic_container)
- return _mono_metadata_generic_class_container_equal (c1->generic_class, c2, signature_only);
- if (c1->generic_container && c2->generic_class)
- return _mono_metadata_generic_class_container_equal (c2->generic_class, c1, signature_only);
+ if (mono_class_is_ginst (c1) && mono_class_is_ginst (c2))
+ return _mono_metadata_generic_class_equal (mono_class_get_generic_class (c1), mono_class_get_generic_class (c2), signature_only);
+ if (mono_class_is_ginst (c1) && mono_class_is_gtd (c2))
+ return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c1), c2, signature_only);
+ if (mono_class_is_gtd (c1) && mono_class_is_ginst (c2))
+ return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c2), c1, signature_only);
if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
return mono_metadata_generic_param_equal_internal (
c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
MonoClass *gtd;
int offset;
- if (!field->parent->generic_class)
+ if (!mono_class_is_ginst (field->parent))
return field;
- gtd = field->parent->generic_class->container_class;
+ gtd = mono_class_get_generic_class (field->parent)->container_class;
offset = field - field->parent->fields;
return gtd->fields + offset;
}
MonoClass *gtd;
int offset;
- if (!event->parent->generic_class)
+ if (!mono_class_is_ginst (event->parent))
return event;
- gtd = event->parent->generic_class->container_class;
+ gtd = mono_class_get_generic_class (event->parent)->container_class;
offset = event - event->parent->ext->events;
return gtd->ext->events + offset;
}
MonoClass *gtd;
int offset;
- if (!property->parent->generic_class)
+ if (!mono_class_is_ginst (property->parent))
return property;
- gtd = property->parent->generic_class->container_class;
+ gtd = mono_class_get_generic_class (property->parent)->container_class;
offset = property - property->parent->ext->properties;
return gtd->ext->properties + offset;
}
#define MONO_TYPE_IS_POINTER(t) mono_type_is_pointer (t)
#define MONO_TYPE_IS_REFERENCE(t) mono_type_is_reference (t)
-#define MONO_CLASS_IS_INTERFACE(c) ((c->flags & TYPE_ATTRIBUTE_INTERFACE) || (c->byval_arg.type == MONO_TYPE_VAR) || (c->byval_arg.type == MONO_TYPE_MVAR))
+#define MONO_CLASS_IS_INTERFACE(c) ((mono_class_get_flags (c) & TYPE_ATTRIBUTE_INTERFACE) || (c->byval_arg.type == MONO_TYPE_VAR) || (c->byval_arg.type == MONO_TYPE_MVAR))
-#define MONO_CLASS_IS_IMPORT(c) ((c->flags & TYPE_ATTRIBUTE_IMPORT))
+#define MONO_CLASS_IS_IMPORT(c) ((mono_class_get_flags (c) & TYPE_ATTRIBUTE_IMPORT))
typedef struct _MonoClass MonoClass;
typedef struct _MonoDomain MonoDomain;
for (method_slot_in_interface = 0; method_slot_in_interface < iface->method.count; method_slot_in_interface++) {
MonoMethod *method;
- if (slot_num >= 0 && iface->is_inflated) {
+ if (slot_num >= 0 && mono_class_is_ginst (iface)) {
/*
* The imt slot of the method is the same as for its declaring method,
* see the comment in mono_method_get_imt_slot (), so we can
* avoid inflating methods which will be discarded by
* add_imt_builder_entry anyway.
*/
- method = mono_class_get_method_by_index (iface->generic_class->container_class, method_slot_in_interface);
+ method = mono_class_get_method_by_index (mono_class_get_generic_class (iface)->container_class, method_slot_in_interface);
if (mono_method_get_imt_slot (method) != slot_num) {
vt_slot ++;
continue;
if (!klass->vtable_size)
mono_class_setup_vtable (klass);
- if (klass->generic_class && !klass->vtable)
+ if (mono_class_is_ginst (klass) && !klass->vtable)
mono_class_check_vtable_constraints (klass, NULL);
/* Initialize klass->has_finalize */
pvt->vtable [i] = NULL;
}
- if (klass->flags & TYPE_ATTRIBUTE_ABSTRACT) {
+ if (mono_class_is_abstract (klass)) {
/* create trampolines for abstract methods */
for (k = klass; k; k = k->parent) {
MonoMethod* m;
int i, j;
if (remote_class == NULL) {
- if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (extra_class)) {
key = (void **)g_malloc (sizeof(gpointer) * 3);
key [0] = GINT_TO_POINTER (2);
key [1] = mono_defaults.marshalbyrefobject_class;
key [1] = extra_class;
}
} else {
- if (extra_class != NULL && (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ if (extra_class != NULL && mono_class_is_interface (extra_class)) {
key = (void **)g_malloc (sizeof(gpointer) * (remote_class->interface_count + 3));
key [0] = GINT_TO_POINTER (remote_class->interface_count + 2);
key [1] = remote_class->proxy_class;
g_free (key);
key = mp_key;
- if (proxy_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (proxy_class)) {
rc = (MonoRemoteClass *)mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*));
rc->interface_count = 1;
rc->interfaces [0] = proxy_class;
g_free (key);
key = mp_key;
- if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (extra_class)) {
int i,j;
rc = (MonoRemoteClass *)mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*) * (remote_class->interface_count + 1));
rc->proxy_class = remote_class->proxy_class;
tproxy = (MonoTransparentProxy*) proxy_object;
remote_class = tproxy->remote_class;
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
int i;
redo_vtable = TRUE;
for (i = 0; i < remote_class->interface_count && redo_vtable; i++)
/* check method->slot is a valid index: perform isinstance? */
if (method->slot != -1) {
- if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (method->klass)) {
if (!is_proxy) {
gboolean variance_used = FALSE;
int iface_offset = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
if (!klass->inited)
mono_class_init (klass);
- if (mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ if (mono_class_is_marshalbyref (klass) || mono_class_is_interface (klass)) {
result = mono_object_isinst_mbyref_checked (obj, klass, error);
return result;
}
vt = obj->vtable;
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
if (MONO_VTABLE_IMPLEMENTS_INTERFACE (vt, klass->interface_id)) {
return obj;
}
ji = mono_jit_info_table_find (mono_get_root_domain (), (char *)mono_get_addr_from_ftnptr (addr));
if (ji) {
method = mono_jit_info_get_method (ji);
- g_assert (!method->klass->generic_container);
+ g_assert (!mono_class_is_gtd (method->klass));
}
return mono_delegate_ctor_with_method (this_obj, target, addr, method, error);
+++ /dev/null
-/*
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#ifndef __MONO_METADATA_PROCESS_INTERNALS_H__
-#define __MONO_METADATA_PROCESS_INTERNALS_H__
-
-#include <config.h>
-#include <glib.h>
-
-// On Windows platform implementation of bellow methods are hosted in separate source file
-// process-windows.c or process-windows-*.c. On other platforms the implementation is still keept
-// in process.c still declared as static and in some places even inlined.
-#ifdef HOST_WIN32
-gchar*
-mono_process_quote_path (const gchar *path);
-
-gchar*
-mono_process_unquote_application_name (gchar *path);
-
-gboolean
-mono_process_get_shell_arguments (MonoProcessStartInfo *proc_start_info, gunichar2 **shell_path,
- MonoString **cmd);
-#endif /* HOST_WIN32 */
-
-// On platforms not using classic WIN API support the implementation of bellow methods are hosted in separate source file
-// process-windows-*.c. On platforms using classic WIN API the implementation is still keept in process.c and still declared
-// static and in some places even inlined.
-#if !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-void
-process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error);
-
-void
-mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle,
- HANDLE stderr_handle,STARTUPINFO *startinfo);
-
-gboolean
-mono_process_create_process (MonoProcInfo *mono_process_info, gunichar2 *shell_path, MonoString *cmd,
- guint32 creation_flags, gchar *env_vars, gunichar2 *dir, STARTUPINFO *start_info,
- PROCESS_INFORMATION *process_info);
-#endif /* !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-// Shared between all platforms and implemented in process.c.
-gboolean
-mono_process_complete_path (const gunichar2 *appname, gchar **completed);
-
-#endif /* __MONO_METADATA_PROCESS_INTERNALS_H__ */
+++ /dev/null
-/*
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#ifndef __MONO_METADATA_PROCESS_WINDOWS_INTERNALS_H__
-#define __MONO_METADATA_PROCESS_WINDOWS_INTERNALS_H__
-
-#include <config.h>
-#include <glib.h>
-
-#ifdef HOST_WIN32
-#include "mono/metadata/process.h"
-#include "mono/metadata/process-internals.h"
-#include "mono/metadata/object.h"
-#include "mono/metadata/object-internals.h"
-#include "mono/metadata/exception.h"
-
-// On platforms not using classic WIN API support the implementation of bellow methods are hosted in separate source file
-// process-windows-*.c. On platforms using classic WIN API the implementation is still keept in process.c and still declared
-// static and in some places even inlined.
-#if !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_process_win_enum_processes (DWORD *pids, DWORD count, DWORD *needed);
-#endif /* !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-#endif /* HOST_WIN32 */
-
-#endif /* __MONO_METADATA_PROCESS_WINDOWS_INTERNALS_H__ */
+++ /dev/null
-/*
- * process-windows-uwp.c: UWP process support for Mono.
- *
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
-*/
-#include <config.h>
-#include <glib.h>
-
-#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
-#include <Windows.h>
-#include "mono/metadata/process-windows-internals.h"
-
-gboolean
-mono_process_win_enum_processes (DWORD *pids, DWORD count, DWORD *needed)
-{
- g_unsupported_api ("EnumProcesses");
- *needed = 0;
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-HANDLE
-ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
-{
- HANDLE handle;
-
- /* GetCurrentProcess returns a pseudo-handle, so use
- * OpenProcess instead
- */
- handle = OpenProcess (PROCESS_ALL_ACCESS, TRUE, pid);
- if (handle == NULL)
- /* FIXME: Throw an exception */
- return NULL;
- return handle;
-}
-
-void
-process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error)
-{
- g_unsupported_api ("GetFileVersionInfoSize, GetFileVersionInfo, VerQueryValue, VerLanguageName");
-
- mono_error_init (error);
- mono_error_set_not_supported (error, G_UNSUPPORTED_API, "GetFileVersionInfoSize, GetFileVersionInfo, VerQueryValue, VerLanguageName");
-
- SetLastError (ERROR_NOT_SUPPORTED);
-}
-
-MonoObject*
-process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2 *modulename, MonoClass *proc_class, MonoError *error)
-{
- g_unsupported_api ("GetModuleInformation");
-
- mono_error_init (error);
- mono_error_set_not_supported (error, G_UNSUPPORTED_API, "GetModuleInformation");
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return NULL;
-}
-
-MonoArray *
-ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("EnumProcessModules, GetModuleBaseName, GetModuleFileNameEx");
-
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "EnumProcessModules, GetModuleBaseName, GetModuleFileNameEx");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return NULL;
-}
-
-MonoBoolean
-ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_info)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("ShellExecuteEx");
-
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "ShellExecuteEx");
- mono_error_set_pending_exception (&mono_error);
-
- process_info->pid = (guint32)(-ERROR_NOT_SUPPORTED);
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-MonoString *
-ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process)
-{
- MonoError error;
- MonoString *string;
- gunichar2 name[MAX_PATH];
- guint32 len;
-
- len = GetModuleFileName (NULL, name, G_N_ELEMENTS (name));
- if (len == 0)
- return NULL;
-
- string = mono_string_new_utf16_checked (mono_domain_get (), name, len, &error);
- if (!mono_error_ok (&error))
- mono_error_set_pending_exception (&error);
-
- return string;
-}
-
-void
-mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, STARTUPINFO *startinfo)
-{
- startinfo->cb = sizeof(STARTUPINFO);
- startinfo->dwFlags = 0;
- startinfo->hStdInput = INVALID_HANDLE_VALUE;
- startinfo->hStdOutput = INVALID_HANDLE_VALUE;
- startinfo->hStdError = INVALID_HANDLE_VALUE;
- return;
-}
-
-gboolean
-mono_process_create_process (MonoProcInfo *mono_process_info, gunichar2 *shell_path, MonoString *cmd, guint32 creation_flags,
- gchar *env_vars, gunichar2 *dir, STARTUPINFO *start_info, PROCESS_INFORMATION *process_info)
-{
- MonoError mono_error;
- gchar *api_name = "";
-
- if (mono_process_info->username) {
- api_name = "CreateProcessWithLogonW";
- } else {
- api_name = "CreateProcess";
- }
-
- memset (&process_info, 0, sizeof (PROCESS_INFORMATION));
- g_unsupported_api (api_name);
-
- mono_error_init (&mono_error);
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, api_name);
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return FALSE;
-}
-
-#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
-
-#ifdef _MSC_VER
-// Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty.
-void __mono_win32_process_windows_uwp_quiet_lnk4221(void) {}
-#endif
-#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
+++ /dev/null
-/*
- * process-windows.c: Windows process support.
- *
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-#include <glib.h>
-
-#if defined(HOST_WIN32)
-#include <winsock2.h>
-#include <windows.h>
-#include "mono/metadata/process-windows-internals.h"
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline gboolean
-mono_process_win_enum_processes (DWORD *pids, DWORD count, DWORD *needed)
-{
- return EnumProcesses (pids, count, needed);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-MonoArray *
-ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
-{
- MonoError error;
- MonoArray *procs;
- gboolean ret;
- DWORD needed;
- int count;
- DWORD *pids;
-
- count = 512;
- do {
- pids = g_new0 (DWORD, count);
- ret = mono_process_win_enum_processes (pids, count * sizeof (guint32), &needed);
- if (ret == FALSE) {
- MonoException *exc;
-
- g_free (pids);
- pids = NULL;
- exc = mono_get_exception_not_supported ("This system does not support EnumProcesses");
- mono_set_pending_exception (exc);
- return NULL;
- }
- if (needed < (count * sizeof (guint32)))
- break;
- g_free (pids);
- pids = NULL;
- count = (count * 3) / 2;
- } while (TRUE);
-
- count = needed / sizeof (guint32);
- procs = mono_array_new_checked (mono_domain_get (), mono_get_int32_class (), count, &error);
- if (mono_error_set_pending_exception (&error)) {
- g_free (pids);
- return NULL;
- }
-
- memcpy (mono_array_addr (procs, guint32, 0), pids, needed);
- g_free (pids);
- pids = NULL;
-
- return procs;
-}
-
-gchar*
-mono_process_quote_path (const gchar *path)
-{
- gchar *res = g_shell_quote (path);
- gchar *q = res;
- while (*q) {
- if (*q == '\'')
- *q = '\"';
- q++;
- }
- return res;
-}
-
-gchar*
-mono_process_unquote_application_name (gchar *appname)
-{
- size_t len = strlen (appname);
- if (len) {
- if (appname[len-1] == '\"')
- appname[len-1] = '\0';
- if (appname[0] == '\"')
- appname++;
- }
-
- return appname;
-}
-
-gboolean
-mono_process_get_shell_arguments (MonoProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
-{
- gchar *spath = NULL;
- gchar *new_cmd, *cmd_utf8;
- MonoError mono_error;
-
- *shell_path = NULL;
- *cmd = proc_start_info->arguments;
-
- mono_process_complete_path (mono_string_chars (proc_start_info->filename), &spath);
- if (spath != NULL) {
- /* Seems like our CreateProcess does not work as the windows one.
- * This hack is needed to deal with paths containing spaces */
- if (*cmd) {
- cmd_utf8 = mono_string_to_utf8_checked (*cmd, &mono_error);
- if (!mono_error_set_pending_exception (&mono_error)) {
- new_cmd = g_strdup_printf ("%s %s", spath, cmd_utf8);
- *cmd = mono_string_new_wrapper (new_cmd);
- g_free (cmd_utf8);
- g_free (new_cmd);
- } else {
- *cmd = NULL;
- }
- }
- else {
- *cmd = mono_string_new_wrapper (spath);
- }
-
- g_free (spath);
- }
-
- return (*cmd != NULL) ? TRUE : FALSE;
-}
-#endif /* HOST_WIN32 */
+++ /dev/null
-/*
- * process.c: System.Diagnostics.Process support
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * Copyright 2002 Ximian, Inc.
- * Copyright 2002-2006 Novell, Inc.
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-
-#include <glib.h>
-#include <string.h>
-
-#include <mono/metadata/object-internals.h>
-#include <mono/metadata/process.h>
-#include <mono/metadata/process-internals.h>
-#include <mono/metadata/assembly.h>
-#include <mono/metadata/appdomain.h>
-#include <mono/metadata/image.h>
-#include <mono/metadata/cil-coff.h>
-#include <mono/metadata/exception.h>
-#include <mono/metadata/threadpool-ms-io.h>
-#include <mono/utils/strenc.h>
-#include <mono/utils/mono-proclib.h>
-#include <mono/io-layer/io-layer.h>
-/* FIXME: fix this code to not depend so much on the internals */
-#include <mono/metadata/class-internals.h>
-#include <mono/metadata/w32handle.h>
-
-#define LOGDEBUG(...)
-/* define LOGDEBUG(...) g_message(__VA_ARGS__) */
-
-#if defined(HOST_WIN32) && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-#include <shellapi.h>
-#endif
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-HANDLE
-ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
-{
- HANDLE handle;
-
- /* GetCurrentProcess returns a pseudo-handle, so use
- * OpenProcess instead
- */
- handle = OpenProcess (PROCESS_ALL_ACCESS, TRUE, pid);
- if (handle == NULL)
- /* FIXME: Throw an exception */
- return NULL;
- return handle;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
-
-static MonoImage *system_assembly;
-
-static void
-stash_system_assembly (MonoObject *obj)
-{
- if (!system_assembly)
- system_assembly = obj->vtable->klass->image;
-}
-
-//Hand coded version that loads from system
-static MonoClass*
-mono_class_get_file_version_info_class (void)
-{
- static MonoClass *tmp_class;
- MonoClass *klass = tmp_class;
- if (!klass) {
- klass = mono_class_load_from_name (system_assembly, "System.Diagnostics", "FileVersionInfo");
- mono_memory_barrier ();
- tmp_class = klass;
- }
- return klass;
-}
-
-static MonoClass*
-mono_class_get_process_module_class (void)
-{
- static MonoClass *tmp_class;
- MonoClass *klass = tmp_class;
- if (!klass) {
- klass = mono_class_load_from_name (system_assembly, "System.Diagnostics", "ProcessModule");
- mono_memory_barrier ();
- tmp_class = klass;
- }
- return klass;
-}
-
-static guint32
-unicode_chars (const gunichar2 *str)
-{
- guint32 len;
-
- for (len = 0; str [len] != '\0'; ++len)
- ;
- return len;
-}
-
-static void
-process_set_field_object (MonoObject *obj, const gchar *fieldname,
- MonoObject *data)
-{
- MonoClassField *field;
-
- LOGDEBUG (g_message ("%s: Setting field %s to object at %p", __func__, fieldname, data));
-
- field = mono_class_get_field_from_name (mono_object_class (obj),
- fieldname);
- mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, data);
-}
-
-static void
-process_set_field_string (MonoObject *obj, const gchar *fieldname,
- const gunichar2 *val, guint32 len, MonoError *error)
-{
- MonoClassField *field;
- MonoString *string;
-
- mono_error_init (error);
-
- LOGDEBUG (g_message ("%s: Setting field %s to [%s]", __func__, fieldname, g_utf16_to_utf8 (val, len, NULL, NULL, NULL)));
-
- string = mono_string_new_utf16_checked (mono_object_domain (obj), val, len, error);
-
- field = mono_class_get_field_from_name (mono_object_class (obj),
- fieldname);
- mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, (MonoObject*)string);
-}
-
-static void
-process_set_field_string_char (MonoObject *obj, const gchar *fieldname,
- const gchar *val)
-{
- MonoClassField *field;
- MonoString *string;
-
- LOGDEBUG (g_message ("%s: Setting field %s to [%s]", __func__, fieldname, val));
-
- string = mono_string_new (mono_object_domain (obj), val);
-
- field = mono_class_get_field_from_name (mono_object_class (obj), fieldname);
- mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, (MonoObject*)string);
-}
-
-static void
-process_set_field_int (MonoObject *obj, const gchar *fieldname,
- guint32 val)
-{
- MonoClassField *field;
-
- LOGDEBUG (g_message ("%s: Setting field %s to %d", __func__,fieldname, val));
-
- field = mono_class_get_field_from_name (mono_object_class (obj),
- fieldname);
- *(guint32 *)(((char *)obj) + field->offset)=val;
-}
-
-static void
-process_set_field_intptr (MonoObject *obj, const gchar *fieldname,
- gpointer val)
-{
- MonoClassField *field;
-
- LOGDEBUG (g_message ("%s: Setting field %s to %p", __func__, fieldname, val));
-
- field = mono_class_get_field_from_name (mono_object_class (obj),
- fieldname);
- *(gpointer *)(((char *)obj) + field->offset) = val;
-}
-
-static void
-process_set_field_bool (MonoObject *obj, const gchar *fieldname,
- gboolean val)
-{
- MonoClassField *field;
-
- LOGDEBUG (g_message ("%s: Setting field %s to %s", __func__, fieldname, val ? "TRUE":"FALSE"));
-
- field = mono_class_get_field_from_name (mono_object_class (obj),
- fieldname);
- *(guint8 *)(((char *)obj) + field->offset) = val;
-}
-
-#define SFI_COMMENTS "\\StringFileInfo\\%02X%02X%02X%02X\\Comments"
-#define SFI_COMPANYNAME "\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName"
-#define SFI_FILEDESCRIPTION "\\StringFileInfo\\%02X%02X%02X%02X\\FileDescription"
-#define SFI_FILEVERSION "\\StringFileInfo\\%02X%02X%02X%02X\\FileVersion"
-#define SFI_INTERNALNAME "\\StringFileInfo\\%02X%02X%02X%02X\\InternalName"
-#define SFI_LEGALCOPYRIGHT "\\StringFileInfo\\%02X%02X%02X%02X\\LegalCopyright"
-#define SFI_LEGALTRADEMARKS "\\StringFileInfo\\%02X%02X%02X%02X\\LegalTrademarks"
-#define SFI_ORIGINALFILENAME "\\StringFileInfo\\%02X%02X%02X%02X\\OriginalFilename"
-#define SFI_PRIVATEBUILD "\\StringFileInfo\\%02X%02X%02X%02X\\PrivateBuild"
-#define SFI_PRODUCTNAME "\\StringFileInfo\\%02X%02X%02X%02X\\ProductName"
-#define SFI_PRODUCTVERSION "\\StringFileInfo\\%02X%02X%02X%02X\\ProductVersion"
-#define SFI_SPECIALBUILD "\\StringFileInfo\\%02X%02X%02X%02X\\SpecialBuild"
-#define EMPTY_STRING (gunichar2*)"\000\000"
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static void
-process_module_string_read (MonoObject *filever, gpointer data,
- const gchar *fieldname, guchar lang_hi, guchar lang_lo,
- const gchar *key, MonoError *error)
-{
- gchar *lang_key_utf8;
- gunichar2 *lang_key, *buffer;
- UINT chars;
-
- mono_error_init (error);
-
- lang_key_utf8 = g_strdup_printf (key, lang_lo, lang_hi, 0x04, 0xb0);
-
- LOGDEBUG (g_message ("%s: asking for [%s]", __func__, lang_key_utf8));
-
- lang_key = g_utf8_to_utf16 (lang_key_utf8, -1, NULL, NULL, NULL);
-
- if (VerQueryValue (data, lang_key, (gpointer *)&buffer, &chars) && chars > 0) {
- LOGDEBUG (g_message ("%s: found %d chars of [%s]", __func__, chars, g_utf16_to_utf8 (buffer, chars, NULL, NULL, NULL)));
- /* chars includes trailing null */
- process_set_field_string (filever, fieldname, buffer, chars - 1, error);
- } else {
- process_set_field_string (filever, fieldname, EMPTY_STRING, 0, error);
- }
-
- g_free (lang_key);
- g_free (lang_key_utf8);
-}
-
-typedef struct {
- const char *name;
- const char *id;
-} StringTableEntry;
-
-static StringTableEntry stringtable_entries [] = {
- { "comments", SFI_COMMENTS },
- { "companyname", SFI_COMPANYNAME },
- { "filedescription", SFI_FILEDESCRIPTION },
- { "fileversion", SFI_FILEVERSION },
- { "internalname", SFI_INTERNALNAME },
- { "legalcopyright", SFI_LEGALCOPYRIGHT },
- { "legaltrademarks", SFI_LEGALTRADEMARKS },
- { "originalfilename", SFI_ORIGINALFILENAME },
- { "privatebuild", SFI_PRIVATEBUILD },
- { "productname", SFI_PRODUCTNAME },
- { "productversion", SFI_PRODUCTVERSION },
- { "specialbuild", SFI_SPECIALBUILD }
-};
-
-static void
-process_module_stringtable (MonoObject *filever, gpointer data,
- guchar lang_hi, guchar lang_lo, MonoError *error)
-{
- int i;
-
- for (i = 0; i < G_N_ELEMENTS (stringtable_entries); ++i) {
- process_module_string_read (filever, data, stringtable_entries [i].name, lang_hi, lang_lo,
- stringtable_entries [i].id, error);
- return_if_nok (error);
- }
-}
-
-static void
-process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error)
-{
- DWORD verinfohandle;
- VS_FIXEDFILEINFO *ffi;
- gpointer data;
- DWORD datalen;
- guchar *trans_data;
- gunichar2 *query;
- UINT ffi_size, trans_size;
- BOOL ok;
- gunichar2 lang_buf[128];
- guint32 lang, lang_count;
-
- mono_error_init (error);
-
- datalen = GetFileVersionInfoSize (filename, &verinfohandle);
- if (datalen) {
- data = g_malloc0 (datalen);
- ok = GetFileVersionInfo (filename, verinfohandle, datalen,
- data);
- if (ok) {
- query = g_utf8_to_utf16 ("\\", -1, NULL, NULL, NULL);
- if (query == NULL) {
- g_free (data);
- return;
- }
-
- if (VerQueryValue (data, query, (gpointer *)&ffi,
- &ffi_size)) {
- LOGDEBUG (g_message ("%s: recording assembly: FileName [%s] FileVersionInfo [%d.%d.%d.%d]", __func__, g_utf16_to_utf8 (filename, -1, NULL, NULL, NULL), HIWORD (ffi->dwFileVersionMS), LOWORD (ffi->dwFileVersionMS), HIWORD (ffi->dwFileVersionLS), LOWORD (ffi->dwFileVersionLS)));
-
- process_set_field_int (filever, "filemajorpart", HIWORD (ffi->dwFileVersionMS));
- process_set_field_int (filever, "fileminorpart", LOWORD (ffi->dwFileVersionMS));
- process_set_field_int (filever, "filebuildpart", HIWORD (ffi->dwFileVersionLS));
- process_set_field_int (filever, "fileprivatepart", LOWORD (ffi->dwFileVersionLS));
-
- process_set_field_int (filever, "productmajorpart", HIWORD (ffi->dwProductVersionMS));
- process_set_field_int (filever, "productminorpart", LOWORD (ffi->dwProductVersionMS));
- process_set_field_int (filever, "productbuildpart", HIWORD (ffi->dwProductVersionLS));
- process_set_field_int (filever, "productprivatepart", LOWORD (ffi->dwProductVersionLS));
-
- process_set_field_bool (filever, "isdebug", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_DEBUG) != 0);
- process_set_field_bool (filever, "isprerelease", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PRERELEASE) != 0);
- process_set_field_bool (filever, "ispatched", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PATCHED) != 0);
- process_set_field_bool (filever, "isprivatebuild", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PRIVATEBUILD) != 0);
- process_set_field_bool (filever, "isspecialbuild", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_SPECIALBUILD) != 0);
- }
- g_free (query);
-
- query = g_utf8_to_utf16 ("\\VarFileInfo\\Translation", -1, NULL, NULL, NULL);
- if (query == NULL) {
- g_free (data);
- return;
- }
-
- if (VerQueryValue (data, query,
- (gpointer *)&trans_data,
- &trans_size)) {
- /* use the first language ID we see
- */
- if (trans_size >= 4) {
- LOGDEBUG (g_message("%s: %s has 0x%0x 0x%0x 0x%0x 0x%0x", __func__, g_utf16_to_utf8 (filename, -1, NULL, NULL, NULL), trans_data[0], trans_data[1], trans_data[2], trans_data[3]));
- lang = (trans_data[0]) |
- (trans_data[1] << 8) |
- (trans_data[2] << 16) |
- (trans_data[3] << 24);
- /* Only give the lower 16 bits
- * to VerLanguageName, as
- * Windows gets confused
- * otherwise
- */
- lang_count = VerLanguageName (lang & 0xFFFF, lang_buf, 128);
- if (lang_count) {
- process_set_field_string (filever, "language", lang_buf, lang_count, error);
- return_if_nok (error);
- }
- process_module_stringtable (filever, data, trans_data[0], trans_data[1], error);
- return_if_nok (error);
- }
- } else {
- int i;
-
- for (i = 0; i < G_N_ELEMENTS (stringtable_entries); ++i) {
- /* No strings, so set every field to
- * the empty string
- */
- process_set_field_string (filever,
- stringtable_entries [i].name,
- EMPTY_STRING, 0, error);
- return_if_nok (error);
- }
-
- /* And language seems to be set to
- * en_US according to bug 374600
- */
- lang_count = VerLanguageName (0x0409, lang_buf, 128);
- if (lang_count) {
- process_set_field_string (filever, "language", lang_buf, lang_count, error);
- return_if_nok (error);
- }
- }
-
- g_free (query);
- }
- g_free (data);
- }
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-static void
-process_get_assembly_fileversion (MonoObject *filever, MonoAssembly *assembly)
-{
- process_set_field_int (filever, "filemajorpart", assembly->aname.major);
- process_set_field_int (filever, "fileminorpart", assembly->aname.minor);
- process_set_field_int (filever, "filebuildpart", assembly->aname.build);
-}
-
-static MonoObject*
-get_process_module (MonoAssembly *assembly, MonoClass *proc_class, MonoError *error)
-{
- MonoObject *item, *filever;
- MonoDomain *domain = mono_domain_get ();
- char *filename;
- const char *modulename = assembly->aname.name;
-
- mono_error_init (error);
-
- /* Build a System.Diagnostics.ProcessModule with the data.
- */
- item = mono_object_new_checked (domain, proc_class, error);
- return_val_if_nok (error, NULL);
- filever = mono_object_new_checked (domain, mono_class_get_file_version_info_class (), error);
- return_val_if_nok (error, NULL);
-
- filename = g_strdup_printf ("[In Memory] %s", modulename);
-
- process_get_assembly_fileversion (filever, assembly);
- process_set_field_string_char (filever, "filename", filename);
- process_set_field_object (item, "version_info", filever);
-
- process_set_field_intptr (item, "baseaddr", assembly->image->raw_data);
- process_set_field_int (item, "memory_size", assembly->image->raw_data_len);
- process_set_field_string_char (item, "filename", filename);
- process_set_field_string_char (item, "modulename", modulename);
-
- g_free (filename);
-
- return item;
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static MonoObject*
-process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2 *modulename, MonoClass *proc_class, MonoError *error)
-{
- MonoObject *item, *filever;
- MonoDomain *domain = mono_domain_get ();
- MODULEINFO modinfo;
- BOOL ok;
-
- mono_error_init (error);
-
- /* Build a System.Diagnostics.ProcessModule with the data.
- */
- item = mono_object_new_checked (domain, proc_class, error);
- return_val_if_nok (error, NULL);
- filever = mono_object_new_checked (domain, mono_class_get_file_version_info_class (), error);
- return_val_if_nok (error, NULL);
-
- process_get_fileversion (filever, filename, error);
- return_val_if_nok (error, NULL);
-
- process_set_field_string (filever, "filename", filename,
- unicode_chars (filename), error);
- return_val_if_nok (error, NULL);
- ok = GetModuleInformation (process, mod, &modinfo, sizeof(MODULEINFO));
- if (ok) {
- process_set_field_intptr (item, "baseaddr",
- modinfo.lpBaseOfDll);
- process_set_field_intptr (item, "entryaddr",
- modinfo.EntryPoint);
- process_set_field_int (item, "memory_size",
- modinfo.SizeOfImage);
- }
- process_set_field_string (item, "filename", filename,
- unicode_chars (filename), error);
- return_val_if_nok (error, NULL);
- process_set_field_string (item, "modulename", modulename,
- unicode_chars (modulename), error);
- return_val_if_nok (error, NULL);
- process_set_field_object (item, "version_info", filever);
-
- return item;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-static GPtrArray*
-get_domain_assemblies (MonoDomain *domain)
-{
- GSList *tmp;
- GPtrArray *assemblies;
-
- /*
- * Make a copy of the list of assemblies because we can't hold the assemblies
- * lock while creating objects etc.
- */
- assemblies = g_ptr_array_new ();
- mono_domain_assemblies_lock (domain);
- for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
- MonoAssembly *ass = (MonoAssembly *)tmp->data;
- if (ass->image->fileio_used)
- continue;
- g_ptr_array_add (assemblies, ass);
- }
- mono_domain_assemblies_unlock (domain);
-
- return assemblies;
-}
-
-/* Returns an array of System.Diagnostics.ProcessModule */
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-MonoArray *
-ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process)
-{
- MonoError error;
- MonoArray *temp_arr = NULL;
- MonoArray *arr;
- HMODULE mods[1024];
- gunichar2 filename[MAX_PATH];
- gunichar2 modname[MAX_PATH];
- DWORD needed;
- guint32 count = 0, module_count = 0, assembly_count = 0;
- guint32 i, num_added = 0;
- GPtrArray *assemblies = NULL;
-
- stash_system_assembly (this_obj);
-
- if (GetProcessId (process) == mono_process_current_pid ()) {
- assemblies = get_domain_assemblies (mono_domain_get ());
- assembly_count = assemblies->len;
- }
-
- if (EnumProcessModules (process, mods, sizeof(mods), &needed)) {
- module_count += needed / sizeof(HMODULE);
- }
-
- count = module_count + assembly_count;
- temp_arr = mono_array_new_checked (mono_domain_get (), mono_class_get_process_module_class (), count, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
-
- for (i = 0; i < module_count; i++) {
- if (GetModuleBaseName (process, mods[i], modname, MAX_PATH) &&
- GetModuleFileNameEx (process, mods[i], filename, MAX_PATH)) {
- MonoObject *module = process_add_module (process, mods[i],
- filename, modname, mono_class_get_process_module_class (), &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
- mono_array_setref (temp_arr, num_added++, module);
- }
- }
-
- if (assemblies) {
- for (i = 0; i < assembly_count; i++) {
- MonoAssembly *ass = (MonoAssembly *)g_ptr_array_index (assemblies, i);
- MonoObject *module = get_process_module (ass, mono_class_get_process_module_class (), &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
- mono_array_setref (temp_arr, num_added++, module);
- }
- g_ptr_array_free (assemblies, TRUE);
- }
-
- if (count == num_added) {
- arr = temp_arr;
- } else {
- /* shorter version of the array */
- arr = mono_array_new_checked (mono_domain_get (), mono_class_get_process_module_class (), num_added, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
-
- for (i = 0; i < num_added; i++)
- mono_array_setref (arr, i, mono_array_get (temp_arr, MonoObject*, i));
- }
-
- return arr;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-void
-ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this_obj, MonoString *filename)
-{
- MonoError error;
-
- stash_system_assembly (this_obj);
-
- process_get_fileversion (this_obj, mono_string_chars (filename), &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return;
- }
- process_set_field_string (this_obj, "filename",
- mono_string_chars (filename),
- mono_string_length (filename), &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return;
- }
-}
-
-/* Only used when UseShellExecute is false */
-#ifndef HOST_WIN32
-static inline gchar *
-mono_process_quote_path (const gchar *path)
-{
- return g_shell_quote (path);
-}
-
-static inline gchar *
-mono_process_unquote_application_name (gchar *path)
-{
- return path;
-}
-#endif /* !HOST_WIN32 */
-
-/* Only used when UseShellExecute is false */
-gboolean
-mono_process_complete_path (const gunichar2 *appname, gchar **completed)
-{
- gchar *utf8app, *utf8appmemory;
- gchar *found;
-
- utf8appmemory = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL);
- utf8app = mono_process_unquote_application_name (utf8appmemory);
-
- if (g_path_is_absolute (utf8app)) {
- *completed = mono_process_quote_path (utf8app);
- g_free (utf8appmemory);
- return TRUE;
- }
-
- if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (utf8app, G_FILE_TEST_IS_DIR)) {
- *completed = mono_process_quote_path (utf8app);
- g_free (utf8appmemory);
- return TRUE;
- }
-
- found = g_find_program_in_path (utf8app);
- if (found == NULL) {
- *completed = NULL;
- g_free (utf8appmemory);
- return FALSE;
- }
-
- *completed = mono_process_quote_path (found);
- g_free (found);
- g_free (utf8appmemory);
- return TRUE;
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-MonoBoolean
-ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_info)
-{
- SHELLEXECUTEINFO shellex = {0};
- gboolean ret;
-
- shellex.cbSize = sizeof(SHELLEXECUTEINFO);
- shellex.fMask = (gulong)(SEE_MASK_FLAG_DDEWAIT | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE);
- shellex.nShow = (gulong)proc_start_info->window_style;
- shellex.nShow = (gulong)((shellex.nShow == 0) ? 1 : (shellex.nShow == 1 ? 0 : shellex.nShow));
-
- if (proc_start_info->filename != NULL) {
- shellex.lpFile = mono_string_chars (proc_start_info->filename);
- }
-
- if (proc_start_info->arguments != NULL) {
- shellex.lpParameters = mono_string_chars (proc_start_info->arguments);
- }
-
- if (proc_start_info->verb != NULL &&
- mono_string_length (proc_start_info->verb) != 0) {
- shellex.lpVerb = mono_string_chars (proc_start_info->verb);
- }
-
- if (proc_start_info->working_directory != NULL &&
- mono_string_length (proc_start_info->working_directory) != 0) {
- shellex.lpDirectory = mono_string_chars (proc_start_info->working_directory);
- }
-
- if (proc_start_info->error_dialog) {
- shellex.hwnd = proc_start_info->error_dialog_parent_handle;
- } else {
- shellex.fMask = (gulong)(shellex.fMask | SEE_MASK_FLAG_NO_UI);
- }
-
- ret = ShellExecuteEx (&shellex);
- if (ret == FALSE) {
- process_info->pid = -GetLastError ();
- } else {
- process_info->process_handle = shellex.hProcess;
- process_info->thread_handle = NULL;
-#if !defined(MONO_CROSS_COMPILE)
- process_info->pid = GetProcessId (shellex.hProcess);
-#else
- process_info->pid = 0;
-#endif
- process_info->tid = 0;
- }
-
- return ret;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static inline void
-mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, STARTUPINFO *startinfo)
-{
- startinfo->cb = sizeof(STARTUPINFO);
- startinfo->dwFlags = STARTF_USESTDHANDLES;
- startinfo->hStdInput = stdin_handle;
- startinfo->hStdOutput = stdout_handle;
- startinfo->hStdError = stderr_handle;
- return;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-#ifndef HOST_WIN32
-static gboolean
-mono_process_get_shell_arguments (MonoProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
-{
- gchar *spath = NULL;
-
- *shell_path = NULL;
- *cmd = proc_start_info->arguments;
-
- mono_process_complete_path (mono_string_chars (proc_start_info->filename), &spath);
- if (spath != NULL) {
- *shell_path = g_utf8_to_utf16 (spath, -1, NULL, NULL, NULL);
- g_free (spath);
- }
-
- return (*shell_path != NULL) ? TRUE : FALSE;
-}
-#endif /* !HOST_WIN32 */
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-static gboolean
-mono_process_create_process (MonoProcInfo *mono_process_info, gunichar2 *shell_path,
- MonoString *cmd, guint32 creation_flags, gchar *env_vars,
- gunichar2 *dir, STARTUPINFO *start_info, PROCESS_INFORMATION *process_info)
-{
- gboolean result = FALSE;
-
- if (mono_process_info->username) {
- guint32 logon_flags = mono_process_info->load_user_profile ? LOGON_WITH_PROFILE : 0;
-
- result = CreateProcessWithLogonW (mono_string_chars (mono_process_info->username),
- mono_process_info->domain ? mono_string_chars (mono_process_info->domain) : NULL,
- (const gunichar2 *)mono_process_info->password,
- logon_flags,
- shell_path,
- cmd ? mono_string_chars (cmd) : NULL,
- creation_flags,
- env_vars, dir, start_info, process_info);
-
- } else {
-
- result = CreateProcess (shell_path,
- cmd ? mono_string_chars (cmd): NULL,
- NULL,
- NULL,
- TRUE,
- creation_flags,
- env_vars,
- dir,
- start_info,
- process_info);
-
- }
-
- return result;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-MonoBoolean
-ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoProcessStartInfo *proc_start_info, HANDLE stdin_handle,
- HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_info)
-{
- gboolean ret;
- gunichar2 *dir;
- STARTUPINFO startinfo={0};
- PROCESS_INFORMATION procinfo;
- gunichar2 *shell_path = NULL;
- gchar *env_vars = NULL;
- MonoString *cmd = NULL;
- guint32 creation_flags;
-
- mono_process_init_startup_info (stdin_handle, stdout_handle, stderr_handle, &startinfo);
-
- creation_flags = CREATE_UNICODE_ENVIRONMENT;
- if (proc_start_info->create_no_window)
- creation_flags |= CREATE_NO_WINDOW;
-
- if (mono_process_get_shell_arguments (proc_start_info, &shell_path, &cmd) == FALSE) {
- process_info->pid = -ERROR_FILE_NOT_FOUND;
- return FALSE;
- }
-
- if (process_info->env_keys) {
- gint i, len;
- MonoString *ms;
- MonoString *key, *value;
- gunichar2 *str, *ptr;
- gunichar2 *equals16;
-
- for (len = 0, i = 0; i < mono_array_length (process_info->env_keys); i++) {
- ms = mono_array_get (process_info->env_values, MonoString *, i);
- if (ms == NULL)
- continue;
-
- len += mono_string_length (ms) * sizeof (gunichar2);
- ms = mono_array_get (process_info->env_keys, MonoString *, i);
- len += mono_string_length (ms) * sizeof (gunichar2);
- len += 2 * sizeof (gunichar2);
- }
-
- equals16 = g_utf8_to_utf16 ("=", 1, NULL, NULL, NULL);
- ptr = str = g_new0 (gunichar2, len + 1);
- for (i = 0; i < mono_array_length (process_info->env_keys); i++) {
- value = mono_array_get (process_info->env_values, MonoString *, i);
- if (value == NULL)
- continue;
-
- key = mono_array_get (process_info->env_keys, MonoString *, i);
- memcpy (ptr, mono_string_chars (key), mono_string_length (key) * sizeof (gunichar2));
- ptr += mono_string_length (key);
-
- memcpy (ptr, equals16, sizeof (gunichar2));
- ptr++;
-
- memcpy (ptr, mono_string_chars (value), mono_string_length (value) * sizeof (gunichar2));
- ptr += mono_string_length (value);
- ptr++;
- }
-
- g_free (equals16);
- env_vars = (gchar *) str;
- }
-
- /* The default dir name is "". Turn that into NULL to mean
- * "current directory"
- */
- if (proc_start_info->working_directory == NULL || mono_string_length (proc_start_info->working_directory) == 0)
- dir = NULL;
- else
- dir = mono_string_chars (proc_start_info->working_directory);
-
- ret = mono_process_create_process (process_info, shell_path, cmd, creation_flags, env_vars, dir, &startinfo, &procinfo);
-
- g_free (env_vars);
- if (shell_path != NULL)
- g_free (shell_path);
-
- if (ret) {
- process_info->process_handle = procinfo.hProcess;
- /*process_info->thread_handle=procinfo.hThread;*/
- process_info->thread_handle = NULL;
- if (procinfo.hThread != NULL && procinfo.hThread != INVALID_HANDLE_VALUE)
- CloseHandle (procinfo.hThread);
- process_info->pid = procinfo.dwProcessId;
- process_info->tid = procinfo.dwThreadId;
- } else {
- process_info->pid = -GetLastError ();
- }
-
- return ret;
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-MonoString *
-ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process)
-{
- MonoError error;
- MonoString *string;
- gunichar2 name[MAX_PATH];
- guint32 len;
- gboolean ok;
- HMODULE mod;
- DWORD needed;
-
- ok = EnumProcessModules (process, &mod, sizeof(mod), &needed);
- if (!ok)
- return NULL;
-
- len = GetModuleBaseName (process, mod, name, MAX_PATH);
-
- if (len == 0)
- return NULL;
-
- LOGDEBUG (g_message ("%s: process name is [%s]", __func__, g_utf16_to_utf8 (name, -1, NULL, NULL, NULL)));
-
- string = mono_string_new_utf16_checked (mono_domain_get (), name, len, &error);
- if (!mono_error_ok (&error))
- mono_error_set_pending_exception (&error);
-
- return string;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-#ifndef HOST_WIN32
-/* Returns an array of pids */
-MonoArray *
-ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
-{
- MonoError error;
- MonoArray *procs;
- gpointer *pidarray;
- int i, count;
-
- pidarray = mono_process_list (&count);
- if (!pidarray) {
- mono_set_pending_exception (mono_get_exception_not_supported ("This system does not support EnumProcesses"));
- return NULL;
- }
- procs = mono_array_new_checked (mono_domain_get (), mono_get_int32_class (), count, &error);
- if (mono_error_set_pending_exception (&error)) {
- g_free (pidarray);
- return NULL;
- }
- if (sizeof (guint32) == sizeof (gpointer)) {
- memcpy (mono_array_addr (procs, guint32, 0), pidarray, count * sizeof (gint32));
- } else {
- for (i = 0; i < count; ++i)
- *(mono_array_addr (procs, guint32, i)) = GPOINTER_TO_UINT (pidarray [i]);
- }
- g_free (pidarray);
-
- return procs;
-}
-#endif /* !HOST_WIN32 */
-
-gint64
-ves_icall_System_Diagnostics_Process_GetProcessData (int pid, gint32 data_type, gint32 *error)
-{
- MonoProcessError perror;
- guint64 res;
-
- res = mono_process_get_data_with_error (GINT_TO_POINTER (pid), (MonoProcessData)data_type, &perror);
- if (error)
- *error = perror;
- return res;
-}
+++ /dev/null
-/*
- * process.h: System.Diagnostics.Process support
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _MONO_METADATA_PROCESS_H_
-#define _MONO_METADATA_PROCESS_H_
-
-#include <config.h>
-#include <glib.h>
-
-#include <mono/metadata/object.h>
-#include <mono/io-layer/io-layer.h>
-#include "mono/utils/mono-compiler.h"
-
-typedef struct
-{
- HANDLE process_handle;
- HANDLE thread_handle;
- guint32 pid; /* Contains GetLastError () on failure */
- guint32 tid;
- MonoArray *env_keys;
- MonoArray *env_values;
- MonoString *username;
- MonoString *domain;
- gpointer password; /* BSTR from SecureString in 2.0 profile */
- MonoBoolean load_user_profile;
-} MonoProcInfo;
-
-typedef struct
-{
- MonoObject object;
- MonoString *filename;
- MonoString *arguments;
- MonoString *working_directory;
- MonoString *verb;
- guint32 window_style;
- MonoBoolean error_dialog;
- gpointer error_dialog_parent_handle;
- MonoBoolean use_shell_execute;
- MonoString *username;
- MonoString *domain;
- MonoObject *password; /* SecureString in 2.0 profile, dummy in 1.x */
- MonoString *password_in_clear_text;
- MonoBoolean load_user_profile;
- MonoBoolean redirect_standard_input;
- MonoBoolean redirect_standard_output;
- MonoBoolean redirect_standard_error;
- MonoObject *encoding_stdout;
- MonoObject *encoding_stderr;
- MonoBoolean create_no_window;
- MonoObject *weak_parent_process;
- MonoObject *envVars;
-} MonoProcessStartInfo;
-
-G_BEGIN_DECLS
-
-HANDLE ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid);
-MonoArray *ves_icall_System_Diagnostics_Process_GetProcesses_internal (void);
-MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process);
-void ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this_obj, MonoString *filename);
-MonoBoolean ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_handle);
-MonoBoolean ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoProcessStartInfo *proc_start_info, HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_handle);
-MonoString *ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process);
-gint64 ves_icall_System_Diagnostics_Process_GetProcessData (int pid, gint32 data_type, gint32 *error);
-
-G_END_DECLS
-
-#endif /* _MONO_METADATA_PROCESS_H_ */
-
#include <mono/utils/mono-string.h>
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/checked-build.h>
+#include <mono/utils/mono-counters.h>
static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
+
+static int class_ref_info_handle_count;
+
void
mono_reflection_init (void)
{
mono_reflection_emit_init ();
+
+ mono_counters_register ("MonoClass::ref_info_handle count",
+ MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ref_info_handle_count);
+
}
/*
MONO_REQ_GC_UNSAFE_MODE;
klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
+ ++class_ref_info_handle_count;
g_assert (klass->ref_info_handle != 0);
}
return type;
gtd = gclass->container_class;
- gcontainer = gtd->generic_container;
+ gcontainer = mono_class_get_generic_container (gtd);
argv = g_newa (MonoType*, ginst->type_argc);
for (i = 0; i < ginst->type_argc; ++i) {
}
klass = mono_class_from_mono_type (t);
- if (!klass->generic_container) {
+ if (!mono_class_is_gtd (klass)) {
mono_loader_unlock ();
mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
return NULL;
MonoGenericClass *gclass;
MonoGenericInst *inst;
- g_assert (klass->generic_container);
+ g_assert (mono_class_is_gtd (klass));
inst = mono_metadata_get_generic_inst (type_argc, types);
gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
ginst = mono_metadata_get_generic_inst (count, type_argv);
g_free (type_argv);
- tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
+ tmp_context.class_inst = mono_class_is_ginst (klass) ? mono_class_get_generic_class (klass)->context.class_inst : NULL;
tmp_context.method_inst = ginst;
inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
guint32
mono_declsec_flags_from_class (MonoClass *klass)
{
- if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
+ if (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_HAS_SECURITY) {
if (!klass->ext || !klass->ext->declsec_flags) {
guint32 idx;
fwrite (buffer_orig, 1, buffer - buffer_orig, f);
g_free (buffer_orig);
+ fclose (f);
return TRUE;
}
/* FIXME the bridge check can be quite expensive, cache it at the class level. */
/* An array of a sealed type that is not a bridge will never get to a bridge */
- if ((elem_class->flags & TYPE_ATTRIBUTE_SEALED) && !elem_class->has_references && !bridge_callbacks.bridge_class_kind (elem_class)) {
+ if ((mono_class_get_flags (elem_class) & TYPE_ATTRIBUTE_SEALED) && !elem_class->has_references && !bridge_callbacks.bridge_class_kind (elem_class)) {
SGEN_LOG (6, "class %s is opaque\n", klass->name);
return GC_BRIDGE_OPAQUE_CLASS;
}
/* FIXME the bridge check can be quite expensive, cache it at the class level. */
/* An array of a sealed type that is not a bridge will never get to a bridge */
- if ((elem_class->flags & TYPE_ATTRIBUTE_SEALED) && !elem_class->has_references && !bridge_callbacks.bridge_class_kind (elem_class)) {
+ if ((mono_class_get_flags (elem_class) & TYPE_ATTRIBUTE_SEALED) && !elem_class->has_references && !bridge_callbacks.bridge_class_kind (elem_class)) {
SGEN_LOG (6, "class %s is opaque\n", klass->name);
return GC_BRIDGE_OPAQUE_CLASS;
}
case MONO_TYPE_CLASS: {
MonoClass *k = mono_class_from_mono_type (type);
- if (k->generic_container) {
- MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
+ if (mono_class_is_gtd (k)) {
+ MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, mono_class_get_generic_container (k)->context.class_inst, TRUE);
encode_generic_class (assembly, gclass, buf);
} else {
/*
return idx;
}
case MONO_TYPE_GENERICINST:
- *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
+ *ret_type = mono_class_get_generic_class (val->vtable->klass)->container_class->byval_arg.type;
goto handle_enum;
default:
g_error ("we don't encode constant type 0x%02x yet", *ret_type);
goto fail;
/* encode custom attributes before the type */
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
typespec = create_typespec (assembly, type);
if (typespec) {
MonoGenericClass *gclass;
- gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
+ gclass = mono_metadata_lookup_generic_class (klass, mono_class_get_generic_container (klass)->context.class_inst, TRUE);
encode_generic_class (assembly, gclass, &buf);
} else {
encode_type (assembly, type, &buf);
case MONO_TYPE_CLASS:
case MONO_TYPE_VALUETYPE: {
MonoClass *k = mono_class_from_mono_type (type);
- if (!k || !k->generic_container) {
+ if (!k || !mono_class_is_gtd (k)) {
sigbuffer_free (&buf);
return 0;
}
guint32 *values;
guint32 visib, res;
- visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+ visib = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
return 0;
alloc_table (table, table->rows);
values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
- values [MONO_EXP_TYPE_FLAGS] = klass->flags;
+ values [MONO_EXP_TYPE_FLAGS] = mono_class_get_flags (klass);
values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
if (klass->nested_in)
values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
- if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
+ if (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_PUBLIC)
mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
}
}
} else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
!strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
- g_assert (m->klass->generic_class || m->klass->generic_container);
+ g_assert (mono_class_is_ginst (m->klass) || mono_class_is_gtd (m->klass));
continue;
} else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
g_assert_not_reached ();
return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
ta = klass->image->assembly;
if (assembly_is_dynamic (ta) || (ta == ass)) {
- if (klass->generic_class || klass->generic_container)
+ if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass))
/* For generic type definitions, we want T, while REFLECTION returns T<K> */
return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
else
static gboolean
is_field_on_inst (MonoClassField *field)
{
- return field->parent->generic_class && field->parent->generic_class->is_dynamic;
+ return mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->is_dynamic;
}
#ifndef DISABLE_REFLECTION_EMIT
if (token)
return token;
- if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
+ if (mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->container_class && mono_class_get_generic_class (field->parent)->container_class->fields) {
int index = field - field->parent->fields;
- type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
+ type = mono_field_get_type (&mono_class_get_generic_class (field->parent)->container_class->fields [index]);
} else {
type = mono_field_get_type (field);
}
return_val_if_nok (error, 0);
MonoClass *mc = mono_class_from_mono_type (type);
token = mono_metadata_token_from_dor (
- mono_dynimage_encode_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
+ mono_dynimage_encode_typedef_or_ref_full (assembly, type, !mono_class_is_gtd (mc) || create_open_instance));
} else if (strcmp (klass->name, "MonoCMethod") == 0 ||
strcmp (klass->name, "MonoMethod") == 0) {
MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
else
token = mono_image_get_inflated_method_token (assembly, m->method);
} else if ((m->method->klass->image == &assembly->image) &&
- !m->method->klass->generic_class) {
+ !mono_class_is_ginst (m->method->klass)) {
static guint32 method_table_idx = 0xffffff;
if (m->method->klass->wastypebuilder) {
/* we use the same token as the one that was assigned
MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)(gparam->tbuilder), error);
mono_error_assert_ok (error);
MonoClass *owner = mono_class_from_mono_type (type);
- g_assert (owner->generic_container);
- param->param.owner = owner->generic_container;
+ g_assert (mono_class_is_gtd (owner));
+ param->param.owner = mono_class_get_generic_container (owner);
}
pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
return TRUE;
}
- klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
+ /*
+ * The size calculation here warrants some explaining.
+ * reflection_setup_internal_class is called too early, well before we know whether the type will be a GTD or DEF,
+ * meaning we need to alloc enough space to morth a def into a gtd.
+ */
+ klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, MAX (sizeof (MonoClassDef), sizeof (MonoClassGtd)));
+ klass->class_kind = MONO_CLASS_DEF;
klass->image = &tb->module->dynamic_image->image;
if (!is_ok (error))
goto failure;
klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
- klass->flags = tb->attrs;
+ mono_class_set_flags (klass, tb->attrs);
mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
if (count == 0)
return TRUE;
- klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
+ MonoGenericContainer *generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
+
+ generic_container->owner.klass = klass;
+ generic_container->type_argc = count;
+ generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
- klass->generic_container->owner.klass = klass;
- klass->generic_container->type_argc = count;
- klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
+ klass->class_kind = MONO_CLASS_GTD;
+ mono_class_set_generic_container (klass, generic_container);
- klass->is_generic = 1;
for (i = 0; i < count; i++) {
MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
return_val_if_nok (error, FALSE);
MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
- klass->generic_container->type_params [i] = *param;
+ generic_container->type_params [i] = *param;
/*Make sure we are a diferent type instance */
- klass->generic_container->type_params [i].param.owner = klass->generic_container;
- klass->generic_container->type_params [i].info.pklass = NULL;
- klass->generic_container->type_params [i].info.flags = gparam->attrs;
+ generic_container->type_params [i].param.owner = generic_container;
+ generic_container->type_params [i].info.pklass = NULL;
+ generic_container->type_params [i].info.flags = gparam->attrs;
- g_assert (klass->generic_container->type_params [i].param.owner);
+ g_assert (generic_container->type_params [i].param.owner);
}
- klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
+ generic_container->context.class_inst = mono_get_shared_generic_inst (generic_container);
return TRUE;
}
image = dynamic ? NULL : klass->image;
if (!dynamic)
- g_assert (!klass->generic_class);
+ g_assert (!mono_class_is_ginst (klass));
mono_loader_lock ();
}
}
- if (klass->generic_container) {
- container->parent = klass->generic_container;
- container->context.class_inst = klass->generic_container->context.class_inst;
+ if (mono_class_is_gtd (klass)) {
+ container->parent = mono_class_get_generic_container (klass);
+ container->context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
}
container->context.method_inst = mono_get_shared_generic_inst (container);
}
static gboolean
fix_partial_generic_class (MonoClass *klass, MonoError *error)
{
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
int i;
mono_error_init (error);
return TRUE;
if (klass->parent != gklass->parent) {
- MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
+ MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &mono_class_get_generic_class (klass)->context, error);
if (mono_error_ok (error)) {
MonoClass *parent = mono_class_from_mono_type (parent_type);
mono_metadata_free_type (parent_type);
}
}
- if (!klass->generic_class->need_sync)
+ if (!mono_class_get_generic_class (klass)->need_sync)
return TRUE;
if (klass->method.count != gklass->method.count) {
static gboolean
ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
{
- MonoClass *gklass = klass->generic_class->container_class;
+ MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
mono_error_init (error);
mono_error_init (error);
- if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
+ if (!image_is_dynamic (klass->image) || (!tb && !mono_class_is_ginst (klass)) || klass->wastypebuilder)
return TRUE;
if (klass->parent)
if (!ensure_runtime_vtable (klass->parent, error))
}
klass->interfaces_inited = 1;
}
- } else if (klass->generic_class){
+ } else if (mono_class_is_ginst (klass)){
if (!ensure_generic_class_runtime_vtable (klass, error)) {
mono_class_set_type_load_failure (klass, "Could not initialize vtable for generic class due to: %s", mono_error_get_message (error));
return FALSE;
}
}
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
int slot_num = 0;
for (i = 0; i < klass->method.count; ++i) {
MonoMethod *im = klass->methods [i];
* Fields to set in klass:
* the various flags: delegate/unicode/contextbound etc.
*/
- klass->flags = tb->attrs;
+ mono_class_set_flags (klass, tb->attrs);
klass->has_cctor = 1;
mono_class_setup_parent (klass, klass->parent);
*
* Together with this we must ensure the contents of all instances to match the created type.
*/
- if (domain->type_hash && klass->generic_container) {
+ if (domain->type_hash && mono_class_is_gtd (klass)) {
struct remove_instantiations_user_data data;
data.klass = klass;
data.error = &error;
//g_assert (klass->wastypebuilder);
}
- if (klass->generic_class) {
- MonoGenericInst *inst = klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (klass)) {
+ MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
int i;
for (i = 0; i < inst->type_argc; ++i) {
mono_thread_start_cb = start_cb;
mono_thread_attach_cb = attach_cb;
-
- /* Get a pseudo handle to the current process. This is just a
- * kludge so that wapi can build a process handle if needed.
- * As a pseudo handle is returned, we don't need to clean
- * anything up.
- */
- GetCurrentProcess ();
}
void mono_thread_cleanup (void)
if (klass->byval_arg.type != type->type)
return mono_type_is_valid_type_in_context_full (&klass->byval_arg, context, check_gtd);
- if (check_gtd && klass->generic_container)
+ if (check_gtd && mono_class_is_gtd (klass))
return FALSE;
break;
}
* The type A <K> has a parent B<K>, that is inflated into the GTD B<>.
* Since A<K> is open, thus not instantiatable, this is valid.
*/
- if (paramClass->generic_container && param_type->type != MONO_TYPE_GENERICINST && !ginst->is_open)
+ if (mono_class_is_gtd (paramClass) && param_type->type != MONO_TYPE_GENERICINST && !ginst->is_open)
return FALSE;
/*it's not safe to call mono_class_init from here*/
- if (paramClass->generic_class && !paramClass->inited) {
+ if (mono_class_is_ginst (paramClass) && !paramClass->inited) {
if (!mono_class_is_valid_generic_instantiation (NULL, paramClass))
return FALSE;
}
if (type->type == MONO_TYPE_VAR) {
MonoClass *gtd = method->klass;
- if (gtd->generic_class)
- gtd = gtd->generic_class->container_class;
- gc = gtd->generic_container;
+ if (mono_class_is_ginst (gtd))
+ gtd = mono_class_get_generic_class (gtd)->container_class;
+ gc = mono_class_try_get_generic_container (gtd);
} else { //MVAR
MonoMethod *gmd = method;
if (method->is_inflated)
static gboolean
mono_class_repect_method_constraints (VerifyContext *ctx, MonoClass *klass)
{
- MonoGenericClass *gklass = klass->generic_class;
+ MonoGenericClass *gklass = mono_class_get_generic_class (klass);
MonoGenericInst *ginst = gklass->context.class_inst;
- MonoGenericContainer *gc = gklass->container_class->generic_container;
+ MonoGenericContainer *gc = mono_class_get_generic_container (gklass->container_class);
return !gc || generic_arguments_respect_constraints (ctx, gc, &gklass->context, ginst);
}
static gboolean
mono_class_is_valid_generic_instantiation (VerifyContext *ctx, MonoClass *klass)
{
- MonoGenericClass *gklass = klass->generic_class;
+ MonoGenericClass *gklass = mono_class_get_generic_class (klass);
MonoGenericInst *ginst = gklass->context.class_inst;
- MonoGenericContainer *gc = gklass->container_class->generic_container;
+ MonoGenericContainer *gc = mono_class_get_generic_container (gklass->container_class);
if (ctx && !is_valid_generic_instantiation_in_context (ctx, ginst, TRUE))
return FALSE;
return is_valid_generic_instantiation (gc, &gklass->context, ginst);
klass = mono_class_from_mono_type (type);
mono_class_init (klass);
if (mono_class_has_failure (klass)) {
- if (klass->generic_class && !mono_class_is_valid_generic_instantiation (NULL, klass))
+ if (mono_class_is_ginst (klass) && !mono_class_is_valid_generic_instantiation (NULL, klass))
ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic instantiation of type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
else
ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Could not load type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
return FALSE;
}
- if (klass->generic_class && mono_class_has_failure (klass->generic_class->container_class)) {
+ if (mono_class_is_ginst (klass) && mono_class_has_failure (mono_class_get_generic_class (klass)->container_class)) {
ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Could not load type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
return FALSE;
}
- if (!klass->generic_class)
+ if (!mono_class_is_ginst (klass))
return TRUE;
if (!mono_class_is_valid_generic_instantiation (ctx, klass)) {
if (!(klass = mono_class_from_mono_type (type)))
ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not retrieve type token for %s at 0x%04x", opcode, ctx->ip_offset));
- if (klass->generic_container && type->type != MONO_TYPE_GENERICINST)
+ if (mono_class_is_gtd (klass) && type->type != MONO_TYPE_GENERICINST)
CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use the generic type definition in a boxable type position for %s at 0x%04x", opcode, ctx->ip_offset));
check_unverifiable_type (ctx, type);
if (mono_class_is_assignable_from (target, candidate))
return TRUE;
- if (!MONO_CLASS_IS_INTERFACE (target) || !target->generic_class || candidate->rank != 1)
+ if (!MONO_CLASS_IS_INTERFACE (target) || !mono_class_is_ginst (target) || candidate->rank != 1)
return FALSE;
- iface_gtd = target->generic_class->container_class;
+ iface_gtd = mono_class_get_generic_class (target)->container_class;
if (iface_gtd != mono_defaults.generic_ilist_class && iface_gtd != get_icollection_class () && iface_gtd != get_ienumerable_class ())
return FALSE;
- target = mono_class_from_mono_type (target->generic_class->context.class_inst->type_argv [0]);
+ target = mono_class_from_mono_type (mono_class_get_generic_class (target)->context.class_inst->type_argv [0]);
candidate = candidate->element_class;
return TRUE;
* the object is a this arg (comes from a ldarg.0), and there is no starg.0.
* This rules doesn't apply if the object on stack is a boxed valuetype.
*/
- if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !(method->klass->flags & TYPE_ATTRIBUTE_SEALED) && !stack_slot_is_boxed_value (value)) {
+ if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !(mono_class_get_flags (method->klass) & TYPE_ATTRIBUTE_SEALED) && !stack_slot_is_boxed_value (value)) {
/*A stdarg 0 must not happen, we fail here only in fail fast mode to avoid double error reports*/
if (IS_FAIL_FAST_MODE (ctx) && ctx->has_this_store)
CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid ldftn with virtual function in method with stdarg 0 at 0x%04x", ctx->ip_offset));
if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use call with an abstract method at 0x%04x", ctx->ip_offset));
- if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !(method->klass->flags & TYPE_ATTRIBUTE_SEALED)) {
+ if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !(mono_class_get_flags (method->klass) & TYPE_ATTRIBUTE_SEALED)) {
virt_check_this = TRUE;
ctx->code [ctx->ip_offset].flags |= IL_CODE_CALL_NONFINAL_VIRTUAL;
}
return;
}
- if (method->klass->flags & (TYPE_ATTRIBUTE_ABSTRACT | TYPE_ATTRIBUTE_INTERFACE))
+ if (mono_class_get_flags (method->klass) & (TYPE_ATTRIBUTE_ABSTRACT | TYPE_ATTRIBUTE_INTERFACE))
CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Trying to instantiate an abstract or interface type at 0x%04x", ctx->ip_offset));
if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_method_full (ctx->method, method, NULL)) {
}
/* if old class is an interface that new class implements */
- if (old_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (old_class)) {
if (verifier_class_is_assignable_from (old_class, new_class)) {
match_class = old_class;
goto match_found;
}
}
- if (new_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (new_class)) {
if (verifier_class_is_assignable_from (new_class, old_class)) {
match_class = new_class;
goto match_found;
finish_collect_stats ();
return ctx.list;
}
- if (!method->is_generic && !method->klass->is_generic && ctx.signature->has_type_parameters) {
+ if (!method->is_generic && !mono_class_is_gtd (method->klass) && ctx.signature->has_type_parameters) {
ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Method and signature don't match in terms of genericity"));
finish_collect_stats ();
return ctx.list;
if (ctx.signature->is_inflated)
ctx.generic_context = generic_context = mono_method_get_context (method);
- if (!generic_context && (method->klass->generic_container || method->is_generic)) {
+ if (!generic_context && (mono_class_is_gtd (method->klass) || method->is_generic)) {
if (method->is_generic)
ctx.generic_context = generic_context = &(mono_method_get_generic_container (method)->context);
else
- ctx.generic_context = generic_context = &method->klass->generic_container->context;
+ ctx.generic_context = generic_context = &mono_class_get_generic_container (method->klass)->context;
}
for (i = 0; i < ctx.num_locals; ++i) {
MonoClassField *field;
gboolean is_fulltrust = mono_verifier_is_class_full_trust (klass);
/*We can't skip types with !has_references since this is calculated after we have run.*/
- if (!((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT))
+ if (!((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT))
return TRUE;
MonoClassField *field;
MonoGenericContext *context = mono_class_get_context (klass);
GHashTable *unique_fields = g_hash_table_new_full (&field_hash, &field_equals, NULL, NULL);
- if (klass->generic_container)
- context = &klass->generic_container->context;
+ if (mono_class_is_gtd (klass))
+ context = &mono_class_get_generic_container (klass)->context;
while ((field = mono_class_get_fields (klass, &iter)) != NULL) {
if (!mono_type_is_valid_type_in_context (field->type, context)) {
int i;
for (i = 0; i < klass->interface_count; ++i) {
MonoClass *iface = klass->interfaces [i];
- if (!(iface->flags & TYPE_ATTRIBUTE_INTERFACE))
+ if (!mono_class_get_flags (iface))
return FALSE;
}
return TRUE;
verify_generic_parameters (MonoClass *klass)
{
int i;
- MonoGenericContainer *gc = klass->generic_container;
+ MonoGenericContainer *gc = mono_class_get_generic_container (klass);
MonoBitSet *used_args = mono_bitset_new (gc->type_argc, 0);
for (i = 0; i < gc->type_argc; ++i) {
if (mono_type_is_generic_argument (constraint_type) && !recursive_mark_constraint_args (used_args, gc, constraint_type))
goto fail;
- if (ctr->generic_class && !mono_class_is_valid_generic_instantiation (NULL, ctr))
+ if (mono_class_is_ginst (ctr) && !mono_class_is_valid_generic_instantiation (NULL, ctr))
goto fail;
}
}
if (klass->parent) {
if (MONO_CLASS_IS_INTERFACE (klass->parent))
return FALSE;
- if (!klass->generic_class && klass->parent->generic_container)
+ if (!mono_class_is_ginst (klass) && mono_class_is_gtd (klass->parent))
return FALSE;
- if (klass->parent->generic_class && !klass->generic_class) {
+ if (mono_class_is_ginst (klass->parent) && !mono_class_is_ginst (klass)) {
MonoGenericContext *context = mono_class_get_context (klass);
- if (klass->generic_container)
- context = &klass->generic_container->context;
+ if (mono_class_is_gtd (klass))
+ context = &mono_class_get_generic_container (klass)->context;
if (!mono_type_is_valid_type_in_context (&klass->parent->byval_arg, context))
return FALSE;
}
}
- if (klass->generic_container && (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT)
+ if (mono_class_is_gtd (klass) && (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT)
return FALSE;
- if (klass->generic_container && !verify_generic_parameters (klass))
+ if (mono_class_is_gtd (klass) && !verify_generic_parameters (klass))
return FALSE;
if (!verify_class_for_overlapping_reference_fields (klass))
return FALSE;
- if (klass->generic_class && !mono_class_is_valid_generic_instantiation (NULL, klass))
+ if (mono_class_is_ginst (klass) && !mono_class_is_valid_generic_instantiation (NULL, klass))
return FALSE;
- if (klass->generic_class == NULL && !verify_class_fields (klass))
+ if (!mono_class_is_ginst (klass) && !verify_class_fields (klass))
return FALSE;
if (klass->valuetype && !verify_valuetype_layout (klass))
return FALSE;
--- /dev/null
+
+#ifndef _MONO_METADATA_W32PROCESS_INTERNALS_H_
+#define _MONO_METADATA_W32PROCESS_INTERNALS_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "io-layer/io-layer.h"
+
+#if !defined(HOST_WIN32)
+
+guint32
+mono_w32process_get_pid (gpointer handle);
+
+gboolean
+mono_w32process_try_get_modules (gpointer process, gpointer *modules, guint32 size, guint32 *needed);
+
+guint32
+mono_w32process_module_get_name (gpointer process, gpointer module, gunichar2 *basename, guint32 size);
+
+guint32
+mono_w32process_module_get_filename (gpointer process, gpointer module, gunichar2 *basename, guint32 size);
+
+gboolean
+mono_w32process_module_get_information (gpointer process, gpointer module, MODULEINFO *modinfo, guint32 size);
+
+#endif /* !defined(HOST_WIN32) */
+
+#endif /* _MONO_METADATA_W32PROCESS_INTERNALS_H_ */
--- /dev/null
+
+#include "w32process.h"
+#include "w32process-unix-internals.h"
+
+#ifdef USE_BSD_BACKEND
+
+#include <errno.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#if !defined(__OpenBSD__)
+#include <sys/utsname.h>
+#endif
+#if defined(__FreeBSD__)
+#include <sys/user.h> /* struct kinfo_proc */
+#endif
+
+#include <link.h>
+
+#include "utils/mono-logger-internals.h"
+
+gchar*
+mono_w32process_get_name (pid_t pid)
+{
+ gint mib [6];
+ gsize size;
+ struct kinfo_proc *pi;
+ gchar *ret;
+
+#if defined(__FreeBSD__)
+ mib [0] = CTL_KERN;
+ mib [1] = KERN_PROC;
+ mib [2] = KERN_PROC_PID;
+ mib [3] = pid;
+ if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
+ return NULL;
+ }
+
+ if ((pi = g_malloc (size)) == NULL)
+ return NULL;
+
+ if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
+ if (errno == ENOMEM) {
+ g_free (pi);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
+ }
+ return NULL;
+ }
+
+ ret = strlen (pi->ki_comm) > 0 ? g_strdup (pi->ki_comm) : NULL;
+
+ g_free (pi);
+#elif defined(__OpenBSD__)
+ mib [0] = CTL_KERN;
+ mib [1] = KERN_PROC;
+ mib [2] = KERN_PROC_PID;
+ mib [3] = pid;
+ mib [4] = sizeof(struct kinfo_proc);
+ mib [5] = 0;
+
+retry:
+ if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
+ return NULL;
+ }
+
+ if ((pi = g_malloc (size)) == NULL)
+ return NULL;
+
+ mib[5] = (int)(size / sizeof(struct kinfo_proc));
+
+ if ((sysctl (mib, 6, pi, &size, NULL, 0) < 0) ||
+ (size != sizeof (struct kinfo_proc))) {
+ if (errno == ENOMEM) {
+ g_free (pi);
+ goto retry;
+ }
+ return NULL;
+ }
+
+ ret = strlen (pi->p_comm) > 0 ? g_strdup (pi->p_comm) : NULL;
+
+ g_free (pi);
+#endif
+
+ return ret;
+}
+
+gchar*
+mono_w32process_get_path (pid_t pid)
+{
+ return mono_w32process_get_name (pid);
+}
+
+static gint
+mono_w32process_get_modules_callback (struct dl_phdr_info *info, gsize size, gpointer ptr)
+{
+ if (size < offsetof (struct dl_phdr_info, dlpi_phnum) + sizeof (info->dlpi_phnum))
+ return (-1);
+
+ struct dl_phdr_info *cpy = g_calloc (1, sizeof(struct dl_phdr_info));
+ if (!cpy)
+ return (-1);
+
+ memcpy(cpy, info, sizeof(*info));
+
+ g_ptr_array_add ((GPtrArray *)ptr, cpy);
+
+ return (0);
+}
+
+GSList*
+mono_w32process_get_modules (pid_t pid)
+{
+ GSList *ret = NULL;
+ MonoW32ProcessModule *mod;
+ GPtrArray *dlarray = g_ptr_array_new();
+ gint i;
+
+ if (dl_iterate_phdr (mono_w32process_get_modules_callback, dlarray) < 0)
+ return NULL;
+
+ for (i = 0; i < dlarray->len; i++) {
+ struct dl_phdr_info *info = g_ptr_array_index (dlarray, i);
+
+ mod = g_new0 (MonoW32ProcessModule, 1);
+ mod->address_start = (gpointer)(info->dlpi_addr + info->dlpi_phdr[0].p_vaddr);
+ mod->address_end = (gpointer)(info->dlpi_addr + info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr);
+ mod->perms = g_strdup ("r--p");
+ mod->address_offset = 0;
+ mod->inode = i;
+ mod->filename = g_strdup (info->dlpi_name);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: inode=%d, filename=%s, address_start=%p, address_end=%p",
+ __func__, mod->inode, mod->filename, mod->address_start, mod->address_end);
+
+ g_free (info);
+
+ if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
+ ret = g_slist_prepend (ret, mod);
+ } else {
+ mono_w32process_module_free (mod);
+ }
+ }
+
+ g_ptr_array_free (dlarray, TRUE);
+
+ return g_slist_reverse (ret);
+}
+
+#endif
--- /dev/null
+
+#include "w32process.h"
+#include "w32process-unix-internals.h"
+
+#ifdef USE_DEFAULT_BACKEND
+
+#include <unistd.h>
+
+#ifdef PLATFORM_SOLARIS
+/* procfs.h cannot be included if this define is set, but it seems to work fine if it is undefined */
+#if _FILE_OFFSET_BITS == 64
+#undef _FILE_OFFSET_BITS
+#include <procfs.h>
+#define _FILE_OFFSET_BITS 64
+#else
+#include <procfs.h>
+#endif
+#endif
+
+#include "utils/mono-logger-internals.h"
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 242
+#endif
+
+gchar*
+mono_w32process_get_name (pid_t pid)
+{
+ FILE *fp;
+ gchar *filename;
+ gchar buf[256];
+ gchar *ret = NULL;
+
+#if defined(PLATFORM_SOLARIS)
+ filename = g_strdup_printf ("/proc/%d/psinfo", pid);
+ if ((fp = fopen (filename, "r")) != NULL) {
+ struct psinfo info;
+ int nread;
+
+ nread = fread (&info, sizeof (info), 1, fp);
+ if (nread == 1) {
+ ret = g_strdup (info.pr_fname);
+ }
+
+ fclose (fp);
+ }
+ g_free (filename);
+#else
+ memset (buf, '\0', sizeof(buf));
+ filename = g_strdup_printf ("/proc/%d/exe", pid);
+ if (readlink (filename, buf, 255) > 0) {
+ ret = g_strdup (buf);
+ }
+ g_free (filename);
+
+ if (ret != NULL) {
+ return(ret);
+ }
+
+ filename = g_strdup_printf ("/proc/%d/cmdline", pid);
+ if ((fp = fopen (filename, "r")) != NULL) {
+ if (fgets (buf, 256, fp) != NULL) {
+ ret = g_strdup (buf);
+ }
+
+ fclose (fp);
+ }
+ g_free (filename);
+
+ if (ret != NULL) {
+ return(ret);
+ }
+
+ filename = g_strdup_printf ("/proc/%d/stat", pid);
+ if ((fp = fopen (filename, "r")) != NULL) {
+ if (fgets (buf, 256, fp) != NULL) {
+ char *start, *end;
+
+ start = strchr (buf, '(');
+ if (start != NULL) {
+ end = strchr (start + 1, ')');
+
+ if (end != NULL) {
+ ret = g_strndup (start + 1,
+ end - start - 1);
+ }
+ }
+ }
+
+ fclose (fp);
+ }
+ g_free (filename);
+#endif
+
+ return ret;
+}
+
+gchar*
+mono_w32process_get_path (pid_t pid)
+{
+ return mono_w32process_get_name (pid);
+}
+
+static FILE *
+open_process_map (int pid, const char *mode)
+{
+ gint i;
+ const gchar *proc_path[] = {
+ "/proc/%d/maps", /* GNU/Linux */
+ "/proc/%d/map", /* FreeBSD */
+ NULL
+ };
+
+ for (i = 0; proc_path [i]; i++) {
+ gchar *filename;
+ FILE *fp;
+
+ filename = g_strdup_printf (proc_path[i], pid);
+ fp = fopen (filename, mode);
+ g_free (filename);
+
+ if (fp)
+ return fp;
+ }
+
+ return NULL;
+}
+
+
+GSList*
+mono_w32process_get_modules (pid_t pid)
+{
+ GSList *ret = NULL;
+ FILE *fp;
+ MonoW32ProcessModule *mod;
+ gchar buf[MAXPATHLEN + 1], *p, *endp;
+ gchar *start_start, *end_start, *prot_start, *offset_start;
+ gchar *maj_dev_start, *min_dev_start, *inode_start, prot_buf[5];
+ gpointer address_start, address_end, address_offset;
+ guint32 maj_dev, min_dev;
+ guint64 inode;
+ guint64 device;
+
+ fp = open_process_map (pid, "r");
+ if (!fp)
+ return NULL;
+
+ while (fgets (buf, sizeof(buf), fp)) {
+ p = buf;
+ while (g_ascii_isspace (*p)) ++p;
+ start_start = p;
+ if (!g_ascii_isxdigit (*start_start)) {
+ continue;
+ }
+ address_start = (gpointer)strtoul (start_start, &endp, 16);
+ p = endp;
+ if (*p != '-') {
+ continue;
+ }
+
+ ++p;
+ end_start = p;
+ if (!g_ascii_isxdigit (*end_start)) {
+ continue;
+ }
+ address_end = (gpointer)strtoul (end_start, &endp, 16);
+ p = endp;
+ if (!g_ascii_isspace (*p)) {
+ continue;
+ }
+
+ while (g_ascii_isspace (*p)) ++p;
+ prot_start = p;
+ if (*prot_start != 'r' && *prot_start != '-') {
+ continue;
+ }
+ memcpy (prot_buf, prot_start, 4);
+ prot_buf[4] = '\0';
+ while (!g_ascii_isspace (*p)) ++p;
+
+ while (g_ascii_isspace (*p)) ++p;
+ offset_start = p;
+ if (!g_ascii_isxdigit (*offset_start)) {
+ continue;
+ }
+ address_offset = (gpointer)strtoul (offset_start, &endp, 16);
+ p = endp;
+ if (!g_ascii_isspace (*p)) {
+ continue;
+ }
+
+ while(g_ascii_isspace (*p)) ++p;
+ maj_dev_start = p;
+ if (!g_ascii_isxdigit (*maj_dev_start)) {
+ continue;
+ }
+ maj_dev = strtoul (maj_dev_start, &endp, 16);
+ p = endp;
+ if (*p != ':') {
+ continue;
+ }
+
+ ++p;
+ min_dev_start = p;
+ if (!g_ascii_isxdigit (*min_dev_start)) {
+ continue;
+ }
+ min_dev = strtoul (min_dev_start, &endp, 16);
+ p = endp;
+ if (!g_ascii_isspace (*p)) {
+ continue;
+ }
+
+ while (g_ascii_isspace (*p)) ++p;
+ inode_start = p;
+ if (!g_ascii_isxdigit (*inode_start)) {
+ continue;
+ }
+ inode = (guint64)strtol (inode_start, &endp, 10);
+ p = endp;
+ if (!g_ascii_isspace (*p)) {
+ continue;
+ }
+
+ device = makedev ((int)maj_dev, (int)min_dev);
+ if ((device == 0) && (inode == 0)) {
+ continue;
+ }
+
+ while(g_ascii_isspace (*p)) ++p;
+ /* p now points to the filename */
+
+ mod = g_new0 (MonoW32ProcessModule, 1);
+ mod->address_start = address_start;
+ mod->address_end = address_end;
+ mod->perms = g_strdup (prot_buf);
+ mod->address_offset = address_offset;
+ mod->device = device;
+ mod->inode = inode;
+ mod->filename = g_strdup (g_strstrip (p));
+
+ if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
+ ret = g_slist_prepend (ret, mod);
+ } else {
+ mono_w32process_module_free (mod);
+ }
+ }
+
+ ret = g_slist_reverse (ret);
+
+ fclose (fp);
+
+ return(ret);
+}
+
+#endif
--- /dev/null
+
+#include "w32process.h"
+#include "w32process-unix-internals.h"
+
+#ifdef USE_HAIKU_BACKEND
+
+#include <KernelKit.h>
+
+gchar*
+mono_w32process_get_name (pid_t pid)
+{
+ image_info imageInfo;
+ int32 cookie = 0;
+
+ if (get_next_image_info ((team_id) pid, &cookie, &imageInfo) != B_OK)
+ return NULL;
+
+ return g_strdup (imageInfo.name);
+}
+
+gchar*
+mono_w32process_get_path (pid_t pid)
+{
+ return mono_w32process_get_name (pid);
+}
+
+GSList*
+mono_w32process_get_modules (pid_t pid)
+{
+ GSList *ret = NULL;
+ MonoW32ProcessModule *mod;
+ gint32 cookie = 0;
+ image_info imageInfo;
+
+ while (get_next_image_info (B_CURRENT_TEAM, &cookie, &imageInfo) == B_OK) {
+ mod = g_new0 (MonoW32ProcessModule, 1);
+ mod->device = imageInfo.device;
+ mod->inode = imageInfo.node;
+ mod->filename = g_strdup (imageInfo.name);
+ mod->address_start = MIN (imageInfo.text, imageInfo.data);
+ mod->address_end = MAX ((uint8_t*)imageInfo.text + imageInfo.text_size,
+ (uint8_t*)imageInfo.data + imageInfo.data_size);
+ mod->perms = g_strdup ("r--p");
+ mod->address_offset = 0;
+
+ if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
+ ret = g_slist_prepend (ret, mod);
+ } else {
+ mono_w32process_module_free (mod);
+ }
+ }
+
+ return g_slist_reverse (ret);
+}
+
+#endif
--- /dev/null
+
+#ifndef _MONO_METADATA_W32PROCESS_UNIX_INTERNALS_H_
+#define _MONO_METADATA_W32PROCESS_UNIX_INTERNALS_H_
+
+#include <config.h>
+#include <glib.h>
+
+/*
+ * FOR EXCLUSIVE USE BY w32process-unix.c
+ */
+
+#if defined(PLATFORM_MACOSX)
+#define USE_OSX_BACKEND
+#elif (defined(__OpenBSD__) || defined(__FreeBSD__)) && defined(HAVE_LINK_H)
+#define USE_BSD_BACKEND
+#elif defined(__HAIKU__)
+#define USE_HAIKU_BACKEND
+#else
+#define USE_DEFAULT_BACKEND
+#endif
+
+typedef struct {
+ gpointer address_start;
+ gpointer address_end;
+ gchar *perms;
+ gpointer address_offset;
+ guint64 device;
+ guint64 inode;
+ gchar *filename;
+} MonoW32ProcessModule;
+
+gchar*
+mono_w32process_get_name (pid_t pid);
+
+GSList*
+mono_w32process_get_modules (pid_t pid);
+
+static void
+mono_w32process_module_free (MonoW32ProcessModule *module)
+{
+ g_free (module->perms);
+ g_free (module->filename);
+ g_free (module);
+}
+
+/*
+ * Used to look through the GSList* returned by mono_w32process_get_modules
+ */
+static gint
+mono_w32process_module_equals (gconstpointer a, gconstpointer b)
+{
+ MonoW32ProcessModule *want = (MonoW32ProcessModule *)a;
+ MonoW32ProcessModule *compare = (MonoW32ProcessModule *)b;
+ return (want->device == compare->device && want->inode == compare->inode) ? 0 : 1;
+}
+
+#endif /* _MONO_METADATA_W32PROCESS_UNIX_INTERNALS_H_ */
--- /dev/null
+
+#include "w32process.h"
+#include "w32process-unix-internals.h"
+
+#ifdef USE_OSX_BACKEND
+
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/utsname.h>
+#include <mach-o/dyld.h>
+#include <mach-o/getsect.h>
+
+/* sys/resource.h (for rusage) is required when using osx 10.3 (but not 10.4) */
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#include <sys/resource.h>
+#ifdef HAVE_LIBPROC_H
+/* proc_name */
+#include <libproc.h>
+#endif
+#endif
+
+#include "utils/mono-logger-internals.h"
+
+gchar*
+mono_w32process_get_name (pid_t pid)
+{
+ gchar *ret = NULL;
+
+#if defined (__mono_ppc__) || !defined (TARGET_OSX)
+ size_t size;
+ struct kinfo_proc *pi;
+ gint mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
+
+ if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0)
+ return(ret);
+
+ if ((pi = g_malloc (size)) == NULL)
+ return(ret);
+
+ if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
+ if (errno == ENOMEM) {
+ g_free (pi);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
+ }
+ return(ret);
+ }
+
+ if (strlen (pi->kp_proc.p_comm) > 0)
+ ret = g_strdup (pi->kp_proc.p_comm);
+
+ g_free (pi);
+#else
+ gchar buf[256];
+
+ /* No proc name on OSX < 10.5 nor ppc nor iOS */
+ memset (buf, '\0', sizeof(buf));
+ proc_name (pid, buf, sizeof(buf));
+
+ // Fixes proc_name triming values to 15 characters #32539
+ if (strlen (buf) >= MAXCOMLEN - 1) {
+ gchar path_buf [PROC_PIDPATHINFO_MAXSIZE];
+ gchar *name_buf;
+ gint path_len;
+
+ memset (path_buf, '\0', sizeof(path_buf));
+ path_len = proc_pidpath (pid, path_buf, sizeof(path_buf));
+
+ if (path_len > 0 && path_len < sizeof(path_buf)) {
+ name_buf = path_buf + path_len;
+ for(;name_buf > path_buf; name_buf--) {
+ if (name_buf [0] == '/') {
+ name_buf++;
+ break;
+ }
+ }
+
+ if (memcmp (buf, name_buf, MAXCOMLEN - 1) == 0)
+ ret = g_strdup (name_buf);
+ }
+ }
+
+ if (ret == NULL && strlen (buf) > 0)
+ ret = g_strdup (buf);
+#endif
+
+ return ret;
+}
+
+gchar*
+mono_w32process_get_path (pid_t pid)
+{
+#if defined(__mono_ppc__) || !defined(TARGET_OSX)
+ return mono_w32process_get_name (pid);
+#else
+ gchar buf [PROC_PIDPATHINFO_MAXSIZE];
+ gint res;
+
+ res = proc_pidpath (pid, buf, sizeof (buf));
+ if (res <= 0)
+ return NULL;
+ if (buf [0] == '\0')
+ return NULL;
+ return g_strdup (buf);
+#endif
+}
+
+GSList*
+mono_w32process_get_modules (pid_t pid)
+{
+ GSList *ret = NULL;
+ MonoW32ProcessModule *mod;
+ guint32 count = _dyld_image_count ();
+ int i = 0;
+
+ for (i = 0; i < count; i++) {
+#if SIZEOF_VOID_P == 8
+ const struct mach_header_64 *hdr;
+ const struct section_64 *sec;
+#else
+ const struct mach_header *hdr;
+ const struct section *sec;
+#endif
+ const char *name;
+
+ name = _dyld_get_image_name (i);
+#if SIZEOF_VOID_P == 8
+ hdr = (const struct mach_header_64*)_dyld_get_image_header (i);
+ sec = getsectbynamefromheader_64 (hdr, SEG_DATA, SECT_DATA);
+#else
+ hdr = _dyld_get_image_header (i);
+ sec = getsectbynamefromheader (hdr, SEG_DATA, SECT_DATA);
+#endif
+
+ /* Some dynlibs do not have data sections on osx (#533893) */
+ if (sec == 0)
+ continue;
+
+ mod = g_new0 (MonoW32ProcessModule, 1);
+ mod->address_start = GINT_TO_POINTER (sec->addr);
+ mod->address_end = GINT_TO_POINTER (sec->addr+sec->size);
+ mod->perms = g_strdup ("r--p");
+ mod->address_offset = 0;
+ mod->device = makedev (0, 0);
+ mod->inode = i;
+ mod->filename = g_strdup (name);
+
+ if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
+ ret = g_slist_prepend (ret, mod);
+ } else {
+ mono_w32process_module_free (mod);
+ }
+ }
+
+ return g_slist_reverse (ret);
+}
+
+#endif
--- /dev/null
+/*
+ * process.c: System.Diagnostics.Process support
+ *
+ * Author:
+ * Dick Porter (dick@ximian.com)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * Copyright 2002-2006 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+#include <glib.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <sched.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#include <sys/time.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <ctype.h>
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+#include <mono/metadata/w32process.h>
+#include <mono/metadata/w32process-internals.h>
+#include <mono/metadata/w32process-unix-internals.h>
+#include <mono/metadata/class.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/metadata.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/exception.h>
+#include <mono/io-layer/io-layer.h>
+#include <mono/metadata/w32handle.h>
+#include <mono/utils/mono-membar.h>
+#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/strenc.h>
+#include <mono/utils/mono-proclib.h>
+#include <mono/utils/mono-path.h>
+#include <mono/utils/mono-lazy-init.h>
+#include <mono/utils/mono-signal-handler.h>
+#include <mono/utils/mono-time.h>
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 242
+#endif
+
+#define STILL_ACTIVE ((int) 0x00000103)
+
+#define LOGDEBUG(...)
+/* define LOGDEBUG(...) g_message(__VA_ARGS__) */
+
+/* The process' environment strings */
+#if defined(__APPLE__)
+#if defined (TARGET_OSX)
+/* Apple defines this in crt_externs.h but doesn't provide that header for
+ * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
+ * in fact exist on all implementations (so far)
+ */
+gchar ***_NSGetEnviron(void);
+#define environ (*_NSGetEnviron())
+#else
+static char *mono_environ[1] = { NULL };
+#define environ mono_environ
+#endif /* defined (TARGET_OSX) */
+#else
+extern char **environ;
+#endif
+
+/*
+ * Handles > _WAPI_PROCESS_UNHANDLED are pseudo handles which represent processes
+ * not started by the runtime.
+ */
+/* This marks a system process that we don't have a handle on */
+/* FIXME: Cope with PIDs > sizeof guint */
+#define _WAPI_PROCESS_UNHANDLED (1 << (8*sizeof(pid_t)-1))
+
+#define WAPI_IS_PSEUDO_PROCESS_HANDLE(handle) ((GPOINTER_TO_UINT(handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED)
+#define WAPI_PID_TO_HANDLE(pid) GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + (pid))
+#define WAPI_HANDLE_TO_PID(handle) (GPOINTER_TO_UINT ((handle)) - _WAPI_PROCESS_UNHANDLED)
+
+typedef enum {
+ STARTF_USESHOWWINDOW=0x001,
+ STARTF_USESIZE=0x002,
+ STARTF_USEPOSITION=0x004,
+ STARTF_USECOUNTCHARS=0x008,
+ STARTF_USEFILLATTRIBUTE=0x010,
+ STARTF_RUNFULLSCREEN=0x020,
+ STARTF_FORCEONFEEDBACK=0x040,
+ STARTF_FORCEOFFFEEDBACK=0x080,
+ STARTF_USESTDHANDLES=0x100
+} StartupFlags;
+
+typedef struct {
+ gpointer input;
+ gpointer output;
+ gpointer error;
+} StartupHandles;
+
+typedef struct {
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+ guint32 highDateTime;
+ guint32 lowDateTime;
+#else
+ guint32 lowDateTime;
+ guint32 highDateTime;
+#endif
+} ProcessTime;
+
+/*
+ * MonoProcess describes processes we create.
+ * It contains a semaphore that can be waited on in order to wait
+ * for process termination. It's accessed in our SIGCHLD handler,
+ * when status is updated (and pid cleared, to not clash with
+ * subsequent processes that may get executed).
+ */
+typedef struct _MonoProcess MonoProcess;
+struct _MonoProcess {
+ pid_t pid; /* the pid of the process. This value is only valid until the process has exited. */
+ MonoSemType exit_sem; /* this semaphore will be released when the process exits */
+ int status; /* the exit status */
+ gint32 handle_count; /* the number of handles to this mono_process instance */
+ /* we keep a ref to the creating _WapiHandle_process handle until
+ * the process has exited, so that the information there isn't lost.
+ */
+ gpointer handle;
+ gboolean freeable;
+ MonoProcess *next;
+};
+
+/* MonoW32HandleProcess is a structure containing all the required information for process handling. */
+typedef struct {
+ pid_t id;
+ guint32 exitstatus;
+ gpointer main_thread;
+ WapiFileTime create_time;
+ WapiFileTime exit_time;
+ char *proc_name;
+ size_t min_working_set;
+ size_t max_working_set;
+ gboolean exited;
+ MonoProcess *mono_process;
+} MonoW32HandleProcess;
+
+#if HAVE_SIGACTION
+static mono_lazy_init_t process_sig_chld_once = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
+#endif
+
+static gchar *cli_launcher;
+
+/* The signal-safe logic to use mono_processes goes like this:
+ * - The list must be safe to traverse for the signal handler at all times.
+ * It's safe to: prepend an entry (which is a single store to 'mono_processes'),
+ * unlink an entry (assuming the unlinked entry isn't freed and doesn't
+ * change its 'next' pointer so that it can still be traversed).
+ * When cleaning up we first unlink an entry, then we verify that
+ * the read lock isn't locked. Then we can free the entry, since
+ * we know that nobody is using the old version of the list (including
+ * the unlinked entry).
+ * We also need to lock when adding and cleaning up so that those two
+ * operations don't mess with eachother. (This lock is not used in the
+ * signal handler) */
+static MonoProcess *mono_processes;
+static mono_mutex_t mono_processes_mutex;
+static volatile gint32 mono_processes_cleaning_up;
+
+static gpointer current_process;
+
+static const gunichar2 utf16_space_bytes [2] = { 0x20, 0 };
+static const gunichar2 *utf16_space = utf16_space_bytes;
+static const gunichar2 utf16_quote_bytes [2] = { 0x22, 0 };
+static const gunichar2 *utf16_quote = utf16_quote_bytes;
+
+static void
+process_details (gpointer data)
+{
+ MonoW32HandleProcess *process_handle = (MonoW32HandleProcess *) data;
+ g_print ("id: %d, exited: %s, exitstatus: %d",
+ process_handle->id, process_handle->exited ? "true" : "false", process_handle->exitstatus);
+}
+
+static const gchar*
+process_typename (void)
+{
+ return "Process";
+}
+
+static gsize
+process_typesize (void)
+{
+ return sizeof (MonoW32HandleProcess);
+}
+
+static guint32
+process_wait (gpointer handle, guint32 timeout, gboolean *alerted)
+{
+ MonoW32HandleProcess *process_handle;
+ pid_t pid G_GNUC_UNUSED, ret;
+ int status;
+ gint64 start, now;
+ MonoProcess *mp;
+ gboolean res;
+
+ /* FIXME: We can now easily wait on processes that aren't our own children,
+ * but WaitFor*Object won't call us for pseudo handles. */
+ g_assert ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) != _WAPI_PROCESS_UNHANDLED);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u)", __func__, handle, timeout);
+
+ if (alerted)
+ *alerted = FALSE;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ g_warning ("%s: error looking up process handle %p", __func__, handle);
+ return WAIT_FAILED;
+ }
+
+ if (process_handle->exited) {
+ /* We've already done this one */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Process already exited", __func__, handle, timeout);
+ return WAIT_OBJECT_0;
+ }
+
+ pid = process_handle->id;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): PID: %d", __func__, handle, timeout, pid);
+
+ /* We don't need to lock mono_processes here, the entry
+ * has a handle_count > 0 which means it will not be freed. */
+ mp = process_handle->mono_process;
+ if (!mp) {
+ pid_t res;
+
+ if (pid == mono_process_current_pid ()) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on current process", __func__, handle, timeout);
+ return WAIT_TIMEOUT;
+ }
+
+ /* This path is used when calling Process.HasExited, so
+ * it is only used to poll the state of the process, not
+ * to actually wait on it to exit */
+ g_assert (timeout == 0);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on non-child process", __func__, handle, timeout);
+
+ res = waitpid (pid, &status, WNOHANG);
+ if (res == 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process WAIT_TIMEOUT", __func__, handle, timeout);
+ return WAIT_TIMEOUT;
+ }
+ if (res > 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process waited successfully", __func__, handle, timeout);
+ return WAIT_OBJECT_0;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process WAIT_FAILED, error : %s (%d))", __func__, handle, timeout, g_strerror (errno), errno);
+ return WAIT_FAILED;
+ }
+
+ start = mono_msec_ticks ();
+ now = start;
+
+ while (1) {
+ if (timeout != INFINITE) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore for %li ms...",
+ __func__, handle, timeout, (long)(timeout - (now - start)));
+ ret = mono_os_sem_timedwait (&mp->exit_sem, (timeout - (now - start)), alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore forever...",
+ __func__, handle, timeout);
+ ret = mono_os_sem_wait (&mp->exit_sem, alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
+ }
+
+ if (ret == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
+ /* Success, process has exited */
+ mono_os_sem_post (&mp->exit_sem);
+ break;
+ }
+
+ if (ret == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_TIMEOUT (timeout = 0)", __func__, handle, timeout);
+ return WAIT_TIMEOUT;
+ }
+
+ now = mono_msec_ticks ();
+ if (now - start >= timeout) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_TIMEOUT", __func__, handle, timeout);
+ return WAIT_TIMEOUT;
+ }
+
+ if (alerted && ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_IO_COMPLETION", __func__, handle, timeout);
+ *alerted = TRUE;
+ return WAIT_IO_COMPLETION;
+ }
+ }
+
+ /* Process must have exited */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Waited successfully", __func__, handle, timeout);
+
+ status = mp ? mp->status : 0;
+ if (WIFSIGNALED (status))
+ process_handle->exitstatus = 128 + WTERMSIG (status);
+ else
+ process_handle->exitstatus = WEXITSTATUS (status);
+ _wapi_time_t_to_filetime (time (NULL), &process_handle->exit_time);
+
+ process_handle->exited = TRUE;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Setting pid %d signalled, exit status %d",
+ __func__, handle, timeout, process_handle->id, process_handle->exitstatus);
+
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
+
+ return WAIT_OBJECT_0;
+}
+
+static void
+processes_cleanup (void)
+{
+ MonoProcess *mp;
+ MonoProcess *prev = NULL;
+ GSList *finished = NULL;
+ GSList *l;
+ gpointer unref_handle;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
+
+ /* Ensure we're not in here in multiple threads at once, nor recursive. */
+ if (InterlockedCompareExchange (&mono_processes_cleaning_up, 1, 0) != 0)
+ return;
+
+ for (mp = mono_processes; mp; mp = mp->next) {
+ if (mp->pid == 0 && mp->handle) {
+ /* This process has exited and we need to remove the artifical ref
+ * on the handle */
+ mono_os_mutex_lock (&mono_processes_mutex);
+ unref_handle = mp->handle;
+ mp->handle = NULL;
+ mono_os_mutex_unlock (&mono_processes_mutex);
+ if (unref_handle)
+ mono_w32handle_unref (unref_handle);
+ }
+ }
+
+ /*
+ * Remove processes which exited from the mono_processes list.
+ * We need to synchronize with the sigchld handler here, which runs
+ * asynchronously. The handler requires that the mono_processes list
+ * remain valid.
+ */
+ mono_os_mutex_lock (&mono_processes_mutex);
+
+ mp = mono_processes;
+ while (mp) {
+ if (mp->handle_count == 0 && mp->freeable) {
+ /*
+ * Unlink the entry.
+ * This code can run parallel with the sigchld handler, but the
+ * modifications it makes are safe.
+ */
+ if (mp == mono_processes)
+ mono_processes = mp->next;
+ else
+ prev->next = mp->next;
+ finished = g_slist_prepend (finished, mp);
+
+ mp = mp->next;
+ } else {
+ prev = mp;
+ mp = mp->next;
+ }
+ }
+
+ mono_memory_barrier ();
+
+ for (l = finished; l; l = l->next) {
+ /*
+ * All the entries in the finished list are unlinked from mono_processes, and
+ * they have the 'finished' flag set, which means the sigchld handler is done
+ * accessing them.
+ */
+ mp = (MonoProcess *)l->data;
+ mono_os_sem_destroy (&mp->exit_sem);
+ g_free (mp);
+ }
+ g_slist_free (finished);
+
+ mono_os_mutex_unlock (&mono_processes_mutex);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s done", __func__);
+
+ InterlockedDecrement (&mono_processes_cleaning_up);
+}
+
+static void
+process_close (gpointer handle, gpointer data)
+{
+ MonoW32HandleProcess *process_handle;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
+
+ process_handle = (MonoW32HandleProcess *) data;
+ g_free (process_handle->proc_name);
+ process_handle->proc_name = NULL;
+ if (process_handle->mono_process)
+ InterlockedDecrement (&process_handle->mono_process->handle_count);
+ processes_cleanup ();
+}
+
+static MonoW32HandleOps process_ops = {
+ process_close, /* close_shared */
+ NULL, /* signal */
+ NULL, /* own */
+ NULL, /* is_owned */
+ process_wait, /* special_wait */
+ NULL, /* prewait */
+ process_details, /* details */
+ process_typename, /* typename */
+ process_typesize, /* typesize */
+};
+
+static void
+process_set_defaults (MonoW32HandleProcess *process_handle)
+{
+ /* These seem to be the defaults on w2k */
+ process_handle->min_working_set = 204800;
+ process_handle->max_working_set = 1413120;
+
+ _wapi_time_t_to_filetime (time (NULL), &process_handle->create_time);
+}
+
+static void
+process_set_name (MonoW32HandleProcess *process_handle)
+{
+ char *progname, *utf8_progname, *slash;
+
+ progname = g_get_prgname ();
+ utf8_progname = mono_utf8_from_external (progname);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: using [%s] as prog name", __func__, progname);
+
+ if (utf8_progname) {
+ slash = strrchr (utf8_progname, '/');
+ if (slash)
+ process_handle->proc_name = g_strdup (slash+1);
+ else
+ process_handle->proc_name = g_strdup (utf8_progname);
+ g_free (utf8_progname);
+ }
+}
+
+void
+mono_w32process_init (void)
+{
+ MonoW32HandleProcess process_handle;
+
+ mono_w32handle_register_ops (MONO_W32HANDLE_PROCESS, &process_ops);
+
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_PROCESS,
+ (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SPECIAL_WAIT));
+
+ memset (&process_handle, 0, sizeof (process_handle));
+ process_handle.id = wapi_getpid ();
+ process_set_defaults (&process_handle);
+ process_set_name (&process_handle);
+
+ current_process = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle);
+ g_assert (current_process);
+
+ mono_os_mutex_init (&mono_processes_mutex);
+}
+
+void
+mono_w32process_cleanup (void)
+{
+ g_free (cli_launcher);
+}
+
+/* Check if a pid is valid - i.e. if a process exists with this pid. */
+static gboolean
+is_pid_valid (pid_t pid)
+{
+ gboolean result = FALSE;
+
+#if defined(HOST_WATCHOS)
+ result = TRUE; // TODO: Rewrite using sysctl
+#elif defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__FreeBSD__)
+ if (((kill(pid, 0) == 0) || (errno == EPERM)) && pid != 0)
+ result = TRUE;
+#elif defined(__HAIKU__)
+ team_info teamInfo;
+ if (get_team_info ((team_id)pid, &teamInfo) == B_OK)
+ result = TRUE;
+#else
+ char *dir = g_strdup_printf ("/proc/%d", pid);
+ if (!access (dir, F_OK))
+ result = TRUE;
+ g_free (dir);
+#endif
+
+ return result;
+}
+
+static int
+len16 (const gunichar2 *str)
+{
+ int len = 0;
+
+ while (*str++ != 0)
+ len++;
+
+ return len;
+}
+
+static gunichar2 *
+utf16_concat (const gunichar2 *first, ...)
+{
+ va_list args;
+ int total = 0, i;
+ const gunichar2 *s;
+ const gunichar2 *p;
+ gunichar2 *ret;
+
+ va_start (args, first);
+ total += len16 (first);
+ for (s = va_arg (args, gunichar2 *); s != NULL; s = va_arg(args, gunichar2 *))
+ total += len16 (s);
+ va_end (args);
+
+ ret = g_new (gunichar2, total + 1);
+ if (ret == NULL)
+ return NULL;
+
+ ret [total] = 0;
+ i = 0;
+ for (s = first; *s != 0; s++)
+ ret [i++] = *s;
+ va_start (args, first);
+ for (s = va_arg (args, gunichar2 *); s != NULL; s = va_arg (args, gunichar2 *)){
+ for (p = s; *p != 0; p++)
+ ret [i++] = *p;
+ }
+ va_end (args);
+
+ return ret;
+}
+
+guint32
+mono_w32process_get_pid (gpointer handle)
+{
+ MonoW32HandleProcess *process_handle;
+ gboolean res;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ /* This is a pseudo handle */
+ return WAPI_HANDLE_TO_PID (handle);
+ }
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return 0;
+ }
+
+ return process_handle->id;
+}
+
+static gboolean
+process_open_compare (gpointer handle, gpointer user_data)
+{
+ gboolean res;
+ MonoW32HandleProcess *process_handle;
+ pid_t wanted_pid, checking_pid;
+
+ g_assert (!WAPI_IS_PSEUDO_PROCESS_HANDLE (handle));
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res)
+ g_error ("%s: unknown process handle %p", __func__, handle);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking at process %d", __func__, process_handle->id);
+
+ checking_pid = process_handle->id;
+ if (checking_pid == 0)
+ return FALSE;
+
+ wanted_pid = GPOINTER_TO_UINT (user_data);
+
+ /* It's possible to have more than one process handle with the
+ * same pid, but only the one running process can be
+ * unsignalled.
+ * If the handle is blown away in the window between
+ * returning TRUE here and mono_w32handle_search pinging
+ * the timestamp, the search will continue. */
+ return checking_pid == wanted_pid && !mono_w32handle_issignalled (handle);
+}
+
+HANDLE
+ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
+{
+ gpointer handle;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking for process %d", __func__, pid);
+
+ handle = mono_w32handle_search (MONO_W32HANDLE_PROCESS, process_open_compare, GUINT_TO_POINTER (pid), NULL, TRUE);
+ if (handle) {
+ /* mono_w32handle_search () already added a ref */
+ return handle;
+ }
+
+ if (is_pid_valid (pid)) {
+ /* Return a pseudo handle for processes we don't have handles for */
+ return WAPI_PID_TO_HANDLE (pid);
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find pid %d", __func__, pid);
+
+ SetLastError (ERROR_PROC_NOT_FOUND);
+ return NULL;
+ }
+}
+
+static gboolean
+match_procname_to_modulename (char *procname, char *modulename)
+{
+ char* lastsep = NULL;
+ char* lastsep2 = NULL;
+ char* pname = NULL;
+ char* mname = NULL;
+ gboolean result = FALSE;
+
+ if (procname == NULL || modulename == NULL)
+ return (FALSE);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: procname=\"%s\", modulename=\"%s\"", __func__, procname, modulename);
+ pname = mono_path_resolve_symlinks (procname);
+ mname = mono_path_resolve_symlinks (modulename);
+
+ if (!strcmp (pname, mname))
+ result = TRUE;
+
+ if (!result) {
+ lastsep = strrchr (mname, '/');
+ if (lastsep)
+ if (!strcmp (lastsep+1, pname))
+ result = TRUE;
+ if (!result) {
+ lastsep2 = strrchr (pname, '/');
+ if (lastsep2){
+ if (lastsep) {
+ if (!strcmp (lastsep+1, lastsep2+1))
+ result = TRUE;
+ } else {
+ if (!strcmp (mname, lastsep2+1))
+ result = TRUE;
+ }
+ }
+ }
+ }
+
+ g_free (pname);
+ g_free (mname);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: result is %d", __func__, result);
+ return result;
+}
+
+gboolean
+mono_w32process_try_get_modules (gpointer process, gpointer *modules, guint32 size, guint32 *needed)
+{
+ MonoW32HandleProcess *process_handle;
+ GSList *mods = NULL;
+ MonoW32ProcessModule *module;
+ guint32 count, avail = size / sizeof(gpointer);
+ int i;
+ pid_t pid;
+ char *proc_name = NULL;
+ gboolean res;
+
+ /* Store modules in an array of pointers (main module as
+ * modules[0]), using the load address for each module as a
+ * token. (Use 'NULL' as an alternative for the main module
+ * so that the simple implementation can just return one item
+ * for now.) Get the info from /proc/<pid>/maps on linux,
+ * /proc/<pid>/map on FreeBSD, other systems will have to
+ * implement /dev/kmem reading or whatever other horrid
+ * technique is needed.
+ */
+ if (size < sizeof(gpointer))
+ return FALSE;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
+ pid = WAPI_HANDLE_TO_PID (process);
+ proc_name = mono_w32process_get_name (pid);
+ } else {
+ res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
+ return FALSE;
+ }
+
+ pid = process_handle->id;
+ proc_name = g_strdup (process_handle->proc_name);
+ }
+
+ if (!proc_name) {
+ modules[0] = NULL;
+ *needed = sizeof(gpointer);
+ return TRUE;
+ }
+
+ mods = mono_w32process_get_modules (pid);
+ if (!mods) {
+ modules[0] = NULL;
+ *needed = sizeof(gpointer);
+ g_free (proc_name);
+ return TRUE;
+ }
+
+ count = g_slist_length (mods);
+
+ /* count + 1 to leave slot 0 for the main module */
+ *needed = sizeof(gpointer) * (count + 1);
+
+ /*
+ * Use the NULL shortcut, as the first line in
+ * /proc/<pid>/maps isn't the executable, and we need
+ * that first in the returned list. Check the module name
+ * to see if it ends with the proc name and substitute
+ * the first entry with it. FIXME if this turns out to
+ * be a problem.
+ */
+ modules[0] = NULL;
+ for (i = 0; i < (avail - 1) && i < count; i++) {
+ module = (MonoW32ProcessModule *)g_slist_nth_data (mods, i);
+ if (modules[0] != NULL)
+ modules[i] = module->address_start;
+ else if (match_procname_to_modulename (proc_name, module->filename))
+ modules[0] = module->address_start;
+ else
+ modules[i + 1] = module->address_start;
+ }
+
+ for (i = 0; i < count; i++) {
+ mono_w32process_module_free ((MonoW32ProcessModule *)g_slist_nth_data (mods, i));
+ }
+ g_slist_free (mods);
+ g_free (proc_name);
+
+ return TRUE;
+}
+
+guint32
+mono_w32process_module_get_filename (gpointer process, gpointer module, gunichar2 *basename, guint32 size)
+{
+ gint pid, len;
+ gsize bytes;
+ gchar *path;
+ gunichar2 *proc_path;
+
+ size *= sizeof (gunichar2); /* adjust for unicode characters */
+
+ if (basename == NULL || size == 0)
+ return 0;
+
+ pid = mono_w32process_get_pid (process);
+
+ path = mono_w32process_get_path (pid);
+ if (path == NULL)
+ return 0;
+
+ proc_path = mono_unicode_from_external (path, &bytes);
+ g_free (path);
+
+ if (proc_path == NULL)
+ return 0;
+
+ len = (bytes / 2);
+
+ /* Add the terminator */
+ bytes += 2;
+
+ if (size < bytes) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
+ memcpy (basename, proc_path, size);
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d larger than needed (%ld)", __func__, size, bytes);
+ memcpy (basename, proc_path, bytes);
+ }
+
+ g_free (proc_path);
+
+ return len;
+}
+
+guint32
+mono_w32process_module_get_name (gpointer process, gpointer module, gunichar2 *basename, guint32 size)
+{
+ MonoW32HandleProcess *process_handle;
+ pid_t pid;
+ gunichar2 *procname;
+ char *procname_ext = NULL;
+ glong len;
+ gsize bytes;
+ GSList *mods = NULL;
+ MonoW32ProcessModule *found_module;
+ guint32 count;
+ int i;
+ char *proc_name = NULL;
+ gboolean res;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module base name, process handle %p module %p",
+ __func__, process, module);
+
+ size = size * sizeof (gunichar2); /* adjust for unicode characters */
+
+ if (basename == NULL || size == 0)
+ return 0;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
+ /* This is a pseudo handle */
+ pid = (pid_t)WAPI_HANDLE_TO_PID (process);
+ proc_name = mono_w32process_get_name (pid);
+ } else {
+ res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
+ return 0;
+ }
+
+ pid = process_handle->id;
+ proc_name = g_strdup (process_handle->proc_name);
+ }
+
+ mods = mono_w32process_get_modules (pid);
+ if (!mods) {
+ g_free (proc_name);
+ return 0;
+ }
+
+ count = g_slist_length (mods);
+
+ /* If module != NULL compare the address.
+ * If module == NULL we are looking for the main module.
+ * The best we can do for now check it the module name end with the process name.
+ */
+ for (i = 0; i < count; i++) {
+ found_module = (MonoW32ProcessModule *)g_slist_nth_data (mods, i);
+ if (procname_ext == NULL &&
+ ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
+ (module != NULL && found_module->address_start == module))) {
+ procname_ext = g_path_get_basename (found_module->filename);
+ }
+
+ mono_w32process_module_free (found_module);
+ }
+
+ if (procname_ext == NULL) {
+ /* If it's *still* null, we might have hit the
+ * case where reading /proc/$pid/maps gives an
+ * empty file for this user.
+ */
+ procname_ext = mono_w32process_get_name (pid);
+ }
+
+ g_slist_free (mods);
+ g_free (proc_name);
+
+ if (procname_ext) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Process name is [%s]", __func__,
+ procname_ext);
+
+ procname = mono_unicode_from_external (procname_ext, &bytes);
+ if (procname == NULL) {
+ /* bugger */
+ g_free (procname_ext);
+ return 0;
+ }
+
+ len = (bytes / 2);
+
+ /* Add the terminator */
+ bytes += 2;
+
+ if (size < bytes) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
+
+ memcpy (basename, procname, size);
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d larger than needed (%ld)",
+ __func__, size, bytes);
+
+ memcpy (basename, procname, bytes);
+ }
+
+ g_free (procname);
+ g_free (procname_ext);
+
+ return len;
+ }
+
+ return 0;
+}
+
+gboolean
+mono_w32process_module_get_information (gpointer process, gpointer module, WapiModuleInfo *modinfo, guint32 size)
+{
+ MonoW32HandleProcess *process_handle;
+ pid_t pid;
+ GSList *mods = NULL;
+ MonoW32ProcessModule *found_module;
+ guint32 count;
+ int i;
+ gboolean ret = FALSE;
+ char *proc_name = NULL;
+ gboolean res;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module info, process handle %p module %p",
+ __func__, process, module);
+
+ if (modinfo == NULL || size < sizeof (WapiModuleInfo))
+ return FALSE;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
+ pid = (pid_t)WAPI_HANDLE_TO_PID (process);
+ proc_name = mono_w32process_get_name (pid);
+ } else {
+ res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
+ return FALSE;
+ }
+
+ pid = process_handle->id;
+ proc_name = g_strdup (process_handle->proc_name);
+ }
+
+ mods = mono_w32process_get_modules (pid);
+ if (!mods) {
+ g_free (proc_name);
+ return FALSE;
+ }
+
+ count = g_slist_length (mods);
+
+ /* If module != NULL compare the address.
+ * If module == NULL we are looking for the main module.
+ * The best we can do for now check it the module name end with the process name.
+ */
+ for (i = 0; i < count; i++) {
+ found_module = (MonoW32ProcessModule *)g_slist_nth_data (mods, i);
+ if (ret == FALSE &&
+ ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
+ (module != NULL && found_module->address_start == module))) {
+ modinfo->lpBaseOfDll = found_module->address_start;
+ modinfo->SizeOfImage = (gsize)(found_module->address_end) - (gsize)(found_module->address_start);
+ modinfo->EntryPoint = found_module->address_offset;
+ ret = TRUE;
+ }
+
+ mono_w32process_module_free (found_module);
+ }
+
+ g_slist_free (mods);
+ g_free (proc_name);
+
+ return ret;
+}
+
+static void
+switch_dir_separators (char *path)
+{
+ size_t i, pathLength = strlen(path);
+
+ /* Turn all the slashes round the right way, except for \' */
+ /* There are probably other characters that need to be excluded as well. */
+ for (i = 0; i < pathLength; i++) {
+ if (path[i] == '\\' && i < pathLength - 1 && path[i+1] != '\'' )
+ path[i] = '/';
+ }
+}
+
+#if HAVE_SIGACTION
+
+MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, siginfo_t *info, void *context))
+{
+ int status;
+ int pid;
+ MonoProcess *p;
+
+ do {
+ do {
+ pid = waitpid (-1, &status, WNOHANG);
+ } while (pid == -1 && errno == EINTR);
+
+ if (pid <= 0)
+ break;
+
+ /*
+ * This can run concurrently with the code in the rest of this module.
+ */
+ for (p = mono_processes; p; p = p->next) {
+ if (p->pid == pid) {
+ break;
+ }
+ }
+ if (p) {
+ p->pid = 0; /* this pid doesn't exist anymore, clear it */
+ p->status = status;
+ mono_os_sem_post (&p->exit_sem);
+ mono_memory_barrier ();
+ /* Mark this as freeable, the pointer becomes invalid afterwards */
+ p->freeable = TRUE;
+ }
+ } while (1);
+}
+
+static void
+process_add_sigchld_handler (void)
+{
+ struct sigaction sa;
+
+ sa.sa_sigaction = mono_sigchld_signal_handler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
+ g_assert (sigaction (SIGCHLD, &sa, NULL) != -1);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "Added SIGCHLD handler");
+}
+
+#endif
+
+static gboolean
+is_readable_or_executable (const char *prog)
+{
+ struct stat buf;
+ int a = access (prog, R_OK);
+ int b = access (prog, X_OK);
+ if (a != 0 && b != 0)
+ return FALSE;
+ if (stat (prog, &buf))
+ return FALSE;
+ if (S_ISREG (buf.st_mode))
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+is_executable (const char *prog)
+{
+ struct stat buf;
+ if (access (prog, X_OK) != 0)
+ return FALSE;
+ if (stat (prog, &buf))
+ return FALSE;
+ if (S_ISREG (buf.st_mode))
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+is_managed_binary (const char *filename)
+{
+ int original_errno = errno;
+#if defined(HAVE_LARGE_FILE_SUPPORT) && defined(O_LARGEFILE)
+ int file = open (filename, O_RDONLY | O_LARGEFILE);
+#else
+ int file = open (filename, O_RDONLY);
+#endif
+ off_t new_offset;
+ unsigned char buffer[8];
+ off_t file_size, optional_header_offset;
+ off_t pe_header_offset, clr_header_offset;
+ gboolean managed = FALSE;
+ int num_read;
+ guint32 first_word, second_word, magic_number;
+
+ /* If we are unable to open the file, then we definitely
+ * can't say that it is managed. The child mono process
+ * probably wouldn't be able to open it anyway.
+ */
+ if (file < 0) {
+ errno = original_errno;
+ return FALSE;
+ }
+
+ /* Retrieve the length of the file for future sanity checks. */
+ file_size = lseek (file, 0, SEEK_END);
+ lseek (file, 0, SEEK_SET);
+
+ /* We know we need to read a header field at offset 60. */
+ if (file_size < 64)
+ goto leave;
+
+ num_read = read (file, buffer, 2);
+
+ if ((num_read != 2) || (buffer[0] != 'M') || (buffer[1] != 'Z'))
+ goto leave;
+
+ new_offset = lseek (file, 60, SEEK_SET);
+
+ if (new_offset != 60)
+ goto leave;
+
+ num_read = read (file, buffer, 4);
+
+ if (num_read != 4)
+ goto leave;
+ pe_header_offset = buffer[0]
+ | (buffer[1] << 8)
+ | (buffer[2] << 16)
+ | (buffer[3] << 24);
+
+ if (pe_header_offset + 24 > file_size)
+ goto leave;
+
+ new_offset = lseek (file, pe_header_offset, SEEK_SET);
+
+ if (new_offset != pe_header_offset)
+ goto leave;
+
+ num_read = read (file, buffer, 4);
+
+ if ((num_read != 4) || (buffer[0] != 'P') || (buffer[1] != 'E') || (buffer[2] != 0) || (buffer[3] != 0))
+ goto leave;
+
+ /*
+ * Verify that the header we want in the optional header data
+ * is present in this binary.
+ */
+ new_offset = lseek (file, pe_header_offset + 20, SEEK_SET);
+
+ if (new_offset != pe_header_offset + 20)
+ goto leave;
+
+ num_read = read (file, buffer, 2);
+
+ if ((num_read != 2) || ((buffer[0] | (buffer[1] << 8)) < 216))
+ goto leave;
+
+ optional_header_offset = pe_header_offset + 24;
+
+ /* Read the PE magic number */
+ new_offset = lseek (file, optional_header_offset, SEEK_SET);
+
+ if (new_offset != optional_header_offset)
+ goto leave;
+
+ num_read = read (file, buffer, 2);
+
+ if (num_read != 2)
+ goto leave;
+
+ magic_number = (buffer[0] | (buffer[1] << 8));
+
+ if (magic_number == 0x10B) // PE32
+ clr_header_offset = 208;
+ else if (magic_number == 0x20B) // PE32+
+ clr_header_offset = 224;
+ else
+ goto leave;
+
+ /* Read the CLR header address and size fields. These will be
+ * zero if the binary is not managed.
+ */
+ new_offset = lseek (file, optional_header_offset + clr_header_offset, SEEK_SET);
+
+ if (new_offset != optional_header_offset + clr_header_offset)
+ goto leave;
+
+ num_read = read (file, buffer, 8);
+
+ /* We are not concerned with endianness, only with
+ * whether it is zero or not.
+ */
+ first_word = *(guint32 *)&buffer[0];
+ second_word = *(guint32 *)&buffer[4];
+
+ if ((num_read != 8) || (first_word == 0) || (second_word == 0))
+ goto leave;
+
+ managed = TRUE;
+
+leave:
+ close (file);
+ errno = original_errno;
+ return managed;
+}
+
+static gboolean
+process_create (const gunichar2 *appname, const gunichar2 *cmdline, gpointer new_environ,
+ const gunichar2 *cwd, StartupHandles *startup_handles, MonoW32ProcessInfo *process_info)
+{
+#if defined (HAVE_FORK) && defined (HAVE_EXECVE)
+ char *cmd = NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL;
+ char *dir = NULL, **env_strings = NULL, **argv = NULL;
+ guint32 i, env_count = 0;
+ gboolean ret = FALSE;
+ gpointer handle = NULL;
+ MonoW32HandleProcess process_handle = {0}, *process_handle_data;
+ GError *gerr = NULL;
+ int in_fd, out_fd, err_fd;
+ pid_t pid = 0;
+ int startup_pipe [2] = {-1, -1};
+ int dummy;
+ MonoProcess *mono_process;
+ gboolean fork_failed = FALSE;
+ gboolean res;
+
+#if HAVE_SIGACTION
+ mono_lazy_initialize (&process_sig_chld_once, process_add_sigchld_handler);
+#endif
+
+ /* appname and cmdline specify the executable and its args:
+ *
+ * If appname is not NULL, it is the name of the executable.
+ * Otherwise the executable is the first token in cmdline.
+ *
+ * Executable searching:
+ *
+ * If appname is not NULL, it can specify the full path and
+ * file name, or else a partial name and the current directory
+ * will be used. There is no additional searching.
+ *
+ * If appname is NULL, the first whitespace-delimited token in
+ * cmdline is used. If the name does not contain a full
+ * directory path, the search sequence is:
+ *
+ * 1) The directory containing the current process
+ * 2) The current working directory
+ * 3) The windows system directory (Ignored)
+ * 4) The windows directory (Ignored)
+ * 5) $PATH
+ *
+ * Just to make things more interesting, tokens can contain
+ * white space if they are surrounded by quotation marks. I'm
+ * beginning to understand just why windows apps are generally
+ * so crap, with an API like this :-(
+ */
+ if (appname != NULL) {
+ cmd = mono_unicode_to_external (appname);
+ if (cmd == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL",
+ __func__);
+
+ SetLastError (ERROR_PATH_NOT_FOUND);
+ goto free_strings;
+ }
+
+ switch_dir_separators(cmd);
+ }
+
+ if (cmdline != NULL) {
+ args = mono_unicode_to_external (cmdline);
+ if (args == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ SetLastError (ERROR_PATH_NOT_FOUND);
+ goto free_strings;
+ }
+ }
+
+ if (cwd != NULL) {
+ dir = mono_unicode_to_external (cwd);
+ if (dir == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ SetLastError (ERROR_PATH_NOT_FOUND);
+ goto free_strings;
+ }
+
+ /* Turn all the slashes round the right way */
+ switch_dir_separators(dir);
+ }
+
+
+ /* We can't put off locating the executable any longer :-( */
+ if (cmd != NULL) {
+ char *unquoted;
+ if (g_ascii_isalpha (cmd[0]) && (cmd[1] == ':')) {
+ /* Strip off the drive letter. I can't
+ * believe that CP/M holdover is still
+ * visible...
+ */
+ g_memmove (cmd, cmd+2, strlen (cmd)-2);
+ cmd[strlen (cmd)-2] = '\0';
+ }
+
+ unquoted = g_shell_unquote (cmd, NULL);
+ if (unquoted[0] == '/') {
+ /* Assume full path given */
+ prog = g_strdup (unquoted);
+
+ /* Executable existing ? */
+ if (!is_readable_or_executable (prog)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
+ __func__, prog);
+ g_free (unquoted);
+ SetLastError (ERROR_FILE_NOT_FOUND);
+ goto free_strings;
+ }
+ } else {
+ /* Search for file named by cmd in the current
+ * directory
+ */
+ char *curdir = g_get_current_dir ();
+
+ prog = g_strdup_printf ("%s/%s", curdir, unquoted);
+ g_free (curdir);
+
+ /* And make sure it's readable */
+ if (!is_readable_or_executable (prog)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
+ __func__, prog);
+ g_free (unquoted);
+ SetLastError (ERROR_FILE_NOT_FOUND);
+ goto free_strings;
+ }
+ }
+ g_free (unquoted);
+
+ args_after_prog = args;
+ } else {
+ char *token = NULL;
+ char quote;
+
+ /* Dig out the first token from args, taking quotation
+ * marks into account
+ */
+
+ /* First, strip off all leading whitespace */
+ args = g_strchug (args);
+
+ /* args_after_prog points to the contents of args
+ * after token has been set (otherwise argv[0] is
+ * duplicated)
+ */
+ args_after_prog = args;
+
+ /* Assume the opening quote will always be the first
+ * character
+ */
+ if (args[0] == '\"' || args [0] == '\'') {
+ quote = args [0];
+ for (i = 1; args[i] != '\0' && args[i] != quote; i++);
+ if (args [i + 1] == '\0' || g_ascii_isspace (args[i+1])) {
+ /* We found the first token */
+ token = g_strndup (args+1, i-1);
+ args_after_prog = g_strchug (args + i + 1);
+ } else {
+ /* Quotation mark appeared in the
+ * middle of the token. Just give the
+ * whole first token, quotes and all,
+ * to exec.
+ */
+ }
+ }
+
+ if (token == NULL) {
+ /* No quote mark, or malformed */
+ for (i = 0; args[i] != '\0'; i++) {
+ if (g_ascii_isspace (args[i])) {
+ token = g_strndup (args, i);
+ args_after_prog = args + i + 1;
+ break;
+ }
+ }
+ }
+
+ if (token == NULL && args[0] != '\0') {
+ /* Must be just one token in the string */
+ token = g_strdup (args);
+ args_after_prog = NULL;
+ }
+
+ if (token == NULL) {
+ /* Give up */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find what to exec", __func__);
+
+ SetLastError (ERROR_PATH_NOT_FOUND);
+ goto free_strings;
+ }
+
+ /* Turn all the slashes round the right way. Only for
+ * the prg. name
+ */
+ switch_dir_separators(token);
+
+ if (g_ascii_isalpha (token[0]) && (token[1] == ':')) {
+ /* Strip off the drive letter. I can't
+ * believe that CP/M holdover is still
+ * visible...
+ */
+ g_memmove (token, token+2, strlen (token)-2);
+ token[strlen (token)-2] = '\0';
+ }
+
+ if (token[0] == '/') {
+ /* Assume full path given */
+ prog = g_strdup (token);
+
+ /* Executable existing ? */
+ if (!is_readable_or_executable (prog)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
+ __func__, token);
+ g_free (token);
+ SetLastError (ERROR_FILE_NOT_FOUND);
+ goto free_strings;
+ }
+ } else {
+ char *curdir = g_get_current_dir ();
+
+ /* FIXME: Need to record the directory
+ * containing the current process, and check
+ * that for the new executable as the first
+ * place to look
+ */
+
+ prog = g_strdup_printf ("%s/%s", curdir, token);
+ g_free (curdir);
+
+ /* I assume X_OK is the criterion to use,
+ * rather than F_OK
+ *
+ * X_OK is too strict *if* the target is a CLR binary
+ */
+ if (!is_readable_or_executable (prog)) {
+ g_free (prog);
+ prog = g_find_program_in_path (token);
+ if (prog == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s", __func__, token);
+
+ g_free (token);
+ SetLastError (ERROR_FILE_NOT_FOUND);
+ goto free_strings;
+ }
+ }
+ }
+
+ g_free (token);
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Exec prog [%s] args [%s]",
+ __func__, prog, args_after_prog);
+
+ /* Check for CLR binaries; if found, we will try to invoke
+ * them using the same mono binary that started us.
+ */
+ if (is_managed_binary (prog)) {
+ gunichar2 *newapp, *newcmd;
+ gsize bytes_ignored;
+
+ newapp = mono_unicode_from_external (cli_launcher ? cli_launcher : "mono", &bytes_ignored);
+ if (newapp) {
+ if (appname)
+ newcmd = utf16_concat (utf16_quote, newapp, utf16_quote, utf16_space, appname, utf16_space, cmdline, NULL);
+ else
+ newcmd = utf16_concat (utf16_quote, newapp, utf16_quote, utf16_space, cmdline, NULL);
+
+ g_free (newapp);
+
+ if (newcmd) {
+ ret = process_create (NULL, newcmd, new_environ, cwd, startup_handles, process_info);
+
+ g_free (newcmd);
+
+ goto free_strings;
+ }
+ }
+ } else {
+ if (!is_executable (prog)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Executable permisson not set on %s", __func__, prog);
+ SetLastError (ERROR_ACCESS_DENIED);
+ goto free_strings;
+ }
+ }
+
+ if (args_after_prog != NULL && *args_after_prog) {
+ char *qprog;
+
+ qprog = g_shell_quote (prog);
+ full_prog = g_strconcat (qprog, " ", args_after_prog, NULL);
+ g_free (qprog);
+ } else {
+ full_prog = g_shell_quote (prog);
+ }
+
+ ret = g_shell_parse_argv (full_prog, NULL, &argv, &gerr);
+ if (ret == FALSE) {
+ g_message ("process_create: %s\n", gerr->message);
+ g_error_free (gerr);
+ gerr = NULL;
+ goto free_strings;
+ }
+
+ if (startup_handles) {
+ in_fd = GPOINTER_TO_UINT (startup_handles->input);
+ out_fd = GPOINTER_TO_UINT (startup_handles->output);
+ err_fd = GPOINTER_TO_UINT (startup_handles->error);
+ } else {
+ in_fd = GPOINTER_TO_UINT (GetStdHandle (STD_INPUT_HANDLE));
+ out_fd = GPOINTER_TO_UINT (GetStdHandle (STD_OUTPUT_HANDLE));
+ err_fd = GPOINTER_TO_UINT (GetStdHandle (STD_ERROR_HANDLE));
+ }
+
+ process_handle.proc_name = g_strdup (prog);
+
+ process_set_defaults (&process_handle);
+
+ handle = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle);
+ if (handle == INVALID_HANDLE_VALUE) {
+ g_warning ("%s: error creating process handle", __func__);
+
+ ret = FALSE;
+ SetLastError (ERROR_OUTOFMEMORY);
+ goto free_strings;
+ }
+
+ /* new_environ is a block of NULL-terminated strings, which
+ * is itself NULL-terminated. Of course, passing an array of
+ * string pointers would have made things too easy :-(
+ *
+ * If new_environ is not NULL it specifies the entire set of
+ * environment variables in the new process. Otherwise the
+ * new process inherits the same environment.
+ */
+ if (new_environ) {
+ gunichar2 *new_environp;
+
+ /* Count the number of strings */
+ for (new_environp = (gunichar2 *)new_environ; *new_environp; new_environp++) {
+ env_count++;
+ while (*new_environp)
+ new_environp++;
+ }
+
+ /* +2: one for the process handle value, and the last
+ * one is NULL
+ */
+ env_strings = g_new0 (char *, env_count + 2);
+
+ /* Copy each environ string into 'strings' turning it
+ * into utf8 (or the requested encoding) at the same
+ * time
+ */
+ env_count = 0;
+ for (new_environp = (gunichar2 *)new_environ; *new_environp; new_environp++) {
+ env_strings[env_count] = mono_unicode_to_external (new_environp);
+ env_count++;
+ while (*new_environp) {
+ new_environp++;
+ }
+ }
+ } else {
+ for (i = 0; environ[i] != NULL; i++)
+ env_count++;
+
+ /* +2: one for the process handle value, and the last
+ * one is NULL
+ */
+ env_strings = g_new0 (char *, env_count + 2);
+
+ /* Copy each environ string into 'strings' turning it
+ * into utf8 (or the requested encoding) at the same
+ * time
+ */
+ env_count = 0;
+ for (i = 0; environ[i] != NULL; i++) {
+ env_strings[env_count] = g_strdup (environ[i]);
+ env_count++;
+ }
+ }
+
+ /* Create a pipe to make sure the child doesn't exit before
+ * we can add the process to the linked list of mono_processes */
+ if (pipe (startup_pipe) == -1) {
+ /* Could not create the pipe to synchroniz process startup. We'll just not synchronize.
+ * This is just for a very hard to hit race condition in the first place */
+ startup_pipe [0] = startup_pipe [1] = -1;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: new process startup not synchronized. We may not notice if the newly created process exits immediately.", __func__);
+ }
+
+ switch (pid = fork ()) {
+ case -1: /* Error */ {
+ SetLastError (ERROR_OUTOFMEMORY);
+ ret = FALSE;
+ fork_failed = TRUE;
+ break;
+ }
+ case 0: /* Child */ {
+ if (startup_pipe [0] != -1) {
+ /* Wait until the parent has updated it's internal data */
+ ssize_t _i G_GNUC_UNUSED = read (startup_pipe [0], &dummy, 1);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: child: parent has completed its setup", __func__);
+ close (startup_pipe [0]);
+ close (startup_pipe [1]);
+ }
+
+ /* should we detach from the process group? */
+
+ /* Connect stdin, stdout and stderr */
+ dup2 (in_fd, 0);
+ dup2 (out_fd, 1);
+ dup2 (err_fd, 2);
+
+ /* Close all file descriptors */
+ for (i = mono_w32handle_fd_reserve - 1; i > 2; i--)
+ close (i);
+
+#ifdef DEBUG_ENABLED
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: exec()ing [%s] in dir [%s]", __func__, cmd,
+ dir == NULL?".":dir);
+ for (i = 0; argv[i] != NULL; i++)
+ g_message ("arg %d: [%s]", i, argv[i]);
+
+ for (i = 0; env_strings[i] != NULL; i++)
+ g_message ("env %d: [%s]", i, env_strings[i]);
+#endif
+
+ /* set cwd */
+ if (dir != NULL && chdir (dir) == -1) {
+ /* set error */
+ _exit (-1);
+ }
+
+ /* exec */
+ execve (argv[0], argv, env_strings);
+
+ /* set error */
+ _exit (-1);
+
+ break;
+ }
+ default: /* Parent */ {
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle_data);
+ if (!res) {
+ g_warning ("%s: error looking up process handle %p", __func__, handle);
+ mono_w32handle_unref (handle);
+ } else {
+ process_handle_data->id = pid;
+
+ /* Add our mono_process into the linked list of mono_processes */
+ mono_process = (MonoProcess *) g_malloc0 (sizeof (MonoProcess));
+ mono_process->pid = pid;
+ mono_process->handle_count = 1;
+ mono_os_sem_init (&mono_process->exit_sem, 0);
+
+ /* Keep the process handle artificially alive until the process
+ * exits so that the information in the handle isn't lost. */
+ mono_w32handle_ref (handle);
+ mono_process->handle = handle;
+
+ process_handle_data->mono_process = mono_process;
+
+ mono_os_mutex_lock (&mono_processes_mutex);
+ mono_process->next = mono_processes;
+ mono_processes = mono_process;
+ mono_os_mutex_unlock (&mono_processes_mutex);
+
+ if (process_info != NULL) {
+ process_info->process_handle = handle;
+ process_info->pid = pid;
+
+ /* FIXME: we might need to handle the thread info some day */
+ process_info->thread_handle = INVALID_HANDLE_VALUE;
+ process_info->tid = 0;
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (fork_failed)
+ mono_w32handle_unref (handle);
+
+ if (startup_pipe [1] != -1) {
+ /* Write 1 byte, doesn't matter what */
+ ssize_t _i G_GNUC_UNUSED = write (startup_pipe [1], startup_pipe, 1);
+ close (startup_pipe [0]);
+ close (startup_pipe [1]);
+ }
+
+free_strings:
+ if (cmd)
+ g_free (cmd);
+ if (full_prog)
+ g_free (full_prog);
+ if (prog)
+ g_free (prog);
+ if (args)
+ g_free (args);
+ if (dir)
+ g_free (dir);
+ if (env_strings)
+ g_strfreev (env_strings);
+ if (argv)
+ g_strfreev (argv);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p for pid %d", __func__, handle, pid);
+
+ /* Check if something needs to be cleaned up. */
+ processes_cleanup ();
+
+ return ret;
+#else
+ SetLastError (ERROR_NOT_SUPPORTED);
+ return FALSE;
+#endif // defined (HAVE_FORK) && defined (HAVE_EXECVE)
+}
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStartInfo *proc_start_info, MonoW32ProcessInfo *process_info)
+{
+ const gunichar2 *lpFile;
+ const gunichar2 *lpParameters;
+ const gunichar2 *lpDirectory;
+ gunichar2 *args;
+ gboolean ret;
+
+ if (!proc_start_info->filename) {
+ /* w2k returns TRUE for this, for some reason. */
+ ret = TRUE;
+ goto done;
+ }
+
+ lpFile = proc_start_info->filename ? mono_string_chars (proc_start_info->filename) : NULL;
+ lpParameters = proc_start_info->arguments ? mono_string_chars (proc_start_info->arguments) : NULL;
+ lpDirectory = proc_start_info->working_directory && mono_string_length (proc_start_info->working_directory) != 0 ?
+ mono_string_chars (proc_start_info->working_directory) : NULL;
+
+ /* Put both executable and parameters into the second argument
+ * to process_create (), so it searches $PATH. The conversion
+ * into and back out of utf8 is because there is no
+ * g_strdup_printf () equivalent for gunichar2 :-(
+ */
+ args = utf16_concat (utf16_quote, lpFile, utf16_quote, lpParameters == NULL ? NULL : utf16_space, lpParameters, NULL);
+ if (args == NULL) {
+ SetLastError (ERROR_INVALID_DATA);
+ ret = FALSE;
+ goto done;
+ }
+ ret = process_create (NULL, args, NULL, lpDirectory, NULL, process_info);
+ g_free (args);
+
+ if (!ret && GetLastError () == ERROR_OUTOFMEMORY)
+ goto done;
+
+ if (!ret) {
+ static char *handler;
+ static gunichar2 *handler_utf16;
+
+ if (handler_utf16 == (gunichar2 *)-1) {
+ ret = FALSE;
+ goto done;
+ }
+
+#ifdef PLATFORM_MACOSX
+ handler = g_strdup ("/usr/bin/open");
+#else
+ /*
+ * On Linux, try: xdg-open, the FreeDesktop standard way of doing it,
+ * if that fails, try to use gnome-open, then kfmclient
+ */
+ handler = g_find_program_in_path ("xdg-open");
+ if (handler == NULL){
+ handler = g_find_program_in_path ("gnome-open");
+ if (handler == NULL){
+ handler = g_find_program_in_path ("kfmclient");
+ if (handler == NULL){
+ handler_utf16 = (gunichar2 *) -1;
+ ret = FALSE;
+ goto done;
+ } else {
+ /* kfmclient needs exec argument */
+ char *old = handler;
+ handler = g_strconcat (old, " exec",
+ NULL);
+ g_free (old);
+ }
+ }
+ }
+#endif
+ handler_utf16 = g_utf8_to_utf16 (handler, -1, NULL, NULL, NULL);
+ g_free (handler);
+
+ /* Put quotes around the filename, in case it's a url
+ * that contains #'s (process_create() calls
+ * g_shell_parse_argv(), which deliberately throws
+ * away anything after an unquoted #). Fixes bug
+ * 371567.
+ */
+ args = utf16_concat (handler_utf16, utf16_space, utf16_quote, lpFile, utf16_quote,
+ lpParameters == NULL ? NULL : utf16_space, lpParameters, NULL);
+ if (args == NULL) {
+ SetLastError (ERROR_INVALID_DATA);
+ ret = FALSE;
+ goto done;
+ }
+ ret = process_create (NULL, args, NULL, lpDirectory, NULL, process_info);
+ g_free (args);
+ if (!ret) {
+ if (GetLastError () != ERROR_OUTOFMEMORY)
+ SetLastError (ERROR_INVALID_DATA);
+ ret = FALSE;
+ goto done;
+ }
+ /* Shell exec should not return a process handle when it spawned a GUI thing, like a browser. */
+ CloseHandle (process_info->process_handle);
+ process_info->process_handle = NULL;
+ }
+
+done:
+ if (ret == FALSE) {
+ process_info->pid = -GetLastError ();
+ } else {
+ process_info->thread_handle = NULL;
+#if !defined(MONO_CROSS_COMPILE)
+ process_info->pid = mono_w32process_get_pid (process_info->process_handle);
+#else
+ process_info->pid = 0;
+#endif
+ process_info->tid = 0;
+ }
+
+ return ret;
+}
+
+/* Only used when UseShellExecute is false */
+static gboolean
+process_get_complete_path (const gunichar2 *appname, gchar **completed)
+{
+ gchar *utf8app;
+ gchar *found;
+
+ utf8app = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL);
+
+ if (g_path_is_absolute (utf8app)) {
+ *completed = g_shell_quote (utf8app);
+ g_free (utf8app);
+ return TRUE;
+ }
+
+ if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (utf8app, G_FILE_TEST_IS_DIR)) {
+ *completed = g_shell_quote (utf8app);
+ g_free (utf8app);
+ return TRUE;
+ }
+
+ found = g_find_program_in_path (utf8app);
+ if (found == NULL) {
+ *completed = NULL;
+ g_free (utf8app);
+ return FALSE;
+ }
+
+ *completed = g_shell_quote (found);
+ g_free (found);
+ g_free (utf8app);
+ return TRUE;
+}
+
+static gboolean
+process_get_shell_arguments (MonoW32ProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
+{
+ gchar *spath = NULL;
+
+ *shell_path = NULL;
+ *cmd = proc_start_info->arguments;
+
+ process_get_complete_path (mono_string_chars (proc_start_info->filename), &spath);
+ if (spath != NULL) {
+ *shell_path = g_utf8_to_utf16 (spath, -1, NULL, NULL, NULL);
+ g_free (spath);
+ }
+
+ return (*shell_path != NULL) ? TRUE : FALSE;
+}
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStartInfo *proc_start_info,
+ HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoW32ProcessInfo *process_info)
+{
+ gboolean ret;
+ gunichar2 *dir;
+ StartupHandles startup_handles;
+ gunichar2 *shell_path = NULL;
+ gchar *env_vars = NULL;
+ MonoString *cmd = NULL;
+
+ memset (&startup_handles, 0, sizeof (startup_handles));
+ startup_handles.input = stdin_handle;
+ startup_handles.output = stdout_handle;
+ startup_handles.error = stderr_handle;
+
+ if (process_get_shell_arguments (proc_start_info, &shell_path, &cmd) == FALSE) {
+ process_info->pid = -ERROR_FILE_NOT_FOUND;
+ return FALSE;
+ }
+
+ if (process_info->env_keys) {
+ gint i, len;
+ MonoString *ms;
+ MonoString *key, *value;
+ gunichar2 *str, *ptr;
+ gunichar2 *equals16;
+
+ for (len = 0, i = 0; i < mono_array_length (process_info->env_keys); i++) {
+ ms = mono_array_get (process_info->env_values, MonoString *, i);
+ if (ms == NULL)
+ continue;
+
+ len += mono_string_length (ms) * sizeof (gunichar2);
+ ms = mono_array_get (process_info->env_keys, MonoString *, i);
+ len += mono_string_length (ms) * sizeof (gunichar2);
+ len += 2 * sizeof (gunichar2);
+ }
+
+ equals16 = g_utf8_to_utf16 ("=", 1, NULL, NULL, NULL);
+ ptr = str = g_new0 (gunichar2, len + 1);
+ for (i = 0; i < mono_array_length (process_info->env_keys); i++) {
+ value = mono_array_get (process_info->env_values, MonoString *, i);
+ if (value == NULL)
+ continue;
+
+ key = mono_array_get (process_info->env_keys, MonoString *, i);
+ memcpy (ptr, mono_string_chars (key), mono_string_length (key) * sizeof (gunichar2));
+ ptr += mono_string_length (key);
+
+ memcpy (ptr, equals16, sizeof (gunichar2));
+ ptr++;
+
+ memcpy (ptr, mono_string_chars (value), mono_string_length (value) * sizeof (gunichar2));
+ ptr += mono_string_length (value);
+ ptr++;
+ }
+
+ g_free (equals16);
+ env_vars = (gchar *) str;
+ }
+
+ /* The default dir name is "". Turn that into NULL to mean "current directory" */
+ dir = proc_start_info->working_directory && mono_string_length (proc_start_info->working_directory) > 0 ?
+ mono_string_chars (proc_start_info->working_directory) : NULL;
+
+ ret = process_create (shell_path, cmd ? mono_string_chars (cmd): NULL, env_vars, dir, &startup_handles, process_info);
+
+ g_free (env_vars);
+ if (shell_path != NULL)
+ g_free (shell_path);
+
+ if (!ret)
+ process_info->pid = -GetLastError ();
+
+ return ret;
+}
+
+/* Returns an array of pids */
+MonoArray *
+ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
+{
+ MonoError error;
+ MonoArray *procs;
+ gpointer *pidarray;
+ int i, count;
+
+ pidarray = mono_process_list (&count);
+ if (!pidarray) {
+ mono_set_pending_exception (mono_get_exception_not_supported ("This system does not support EnumProcesses"));
+ return NULL;
+ }
+ procs = mono_array_new_checked (mono_domain_get (), mono_get_int32_class (), count, &error);
+ if (mono_error_set_pending_exception (&error)) {
+ g_free (pidarray);
+ return NULL;
+ }
+ if (sizeof (guint32) == sizeof (gpointer)) {
+ memcpy (mono_array_addr (procs, guint32, 0), pidarray, count * sizeof (gint32));
+ } else {
+ for (i = 0; i < count; ++i)
+ *(mono_array_addr (procs, guint32, i)) = GPOINTER_TO_UINT (pidarray [i]);
+ }
+ g_free (pidarray);
+
+ return procs;
+}
+
+void
+mono_w32process_set_cli_launcher (gchar *path)
+{
+ g_free (cli_launcher);
+ cli_launcher = g_strdup (path);
+}
+
+gpointer
+ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
+{
+ mono_w32handle_ref (current_process);
+ return current_process;
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
+{
+ MonoW32HandleProcess *process_handle;
+ guint32 pid;
+ gboolean res;
+
+ if (!exitcode)
+ return FALSE;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ pid = WAPI_HANDLE_TO_PID (handle);
+ /* This is a pseudo handle, so we don't know what the exit
+ * code was, but we can check whether it's alive or not */
+ if (is_pid_valid (pid)) {
+ *exitcode = STILL_ACTIVE;
+ return TRUE;
+ } else {
+ *exitcode = -1;
+ return TRUE;
+ }
+ }
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ return FALSE;
+ }
+
+ if (process_handle->id == wapi_getpid ()) {
+ *exitcode = STILL_ACTIVE;
+ return TRUE;
+ }
+
+ /* A process handle is only signalled if the process has exited
+ * and has been waited for. Make sure any process exit has been
+ * noticed before checking if the process is signalled.
+ * Fixes bug 325463. */
+ mono_w32handle_wait_one (handle, 0, TRUE);
+
+ *exitcode = mono_w32handle_issignalled (handle) ? process_handle->exitstatus : STILL_ACTIVE;
+ return TRUE;
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
+{
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
+ return TRUE;
+ return CloseHandle (handle);
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
+{
+#ifdef HAVE_KILL
+ MonoW32HandleProcess *process_handle;
+ int ret;
+ pid_t pid;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ /* This is a pseudo handle */
+ pid = (pid_t)WAPI_HANDLE_TO_PID (handle);
+ } else {
+ gboolean res;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ SetLastError (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ pid = process_handle->id;
+ }
+
+ ret = kill (pid, exitcode == -1 ? SIGKILL : SIGTERM);
+ if (ret == 0)
+ return TRUE;
+
+ switch (errno) {
+ case EINVAL: SetLastError (ERROR_INVALID_PARAMETER); break;
+ case EPERM: SetLastError (ERROR_ACCESS_DENIED); break;
+ case ESRCH: SetLastError (ERROR_PROC_NOT_FOUND); break;
+ default: SetLastError (ERROR_GEN_FAILURE); break;
+ }
+
+ return FALSE;
+#else
+ g_error ("kill() is not supported by this platform");
+#endif
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
+{
+ MonoW32HandleProcess *process_handle;
+ gboolean res;
+
+ if (!min || !max)
+ return FALSE;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
+ return FALSE;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ return FALSE;
+ }
+
+ *min = process_handle->min_working_set;
+ *max = process_handle->max_working_set;
+ return TRUE;
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
+{
+ MonoW32HandleProcess *process_handle;
+ gboolean res;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
+ return FALSE;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ return FALSE;
+ }
+
+ process_handle->min_working_set = min;
+ process_handle->max_working_set = max;
+ return TRUE;
+}
+
+gint32
+ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
+{
+#ifdef HAVE_GETPRIORITY
+ MonoW32HandleProcess *process_handle;
+ gint ret;
+ pid_t pid;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ /* This is a pseudo handle */
+ pid = (pid_t)WAPI_HANDLE_TO_PID (handle);
+ } else {
+ gboolean res;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return 0;
+ }
+
+ pid = process_handle->id;
+ }
+
+ errno = 0;
+ ret = getpriority (PRIO_PROCESS, pid);
+ if (ret == -1 && errno != 0) {
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ SetLastError (ERROR_ACCESS_DENIED);
+ break;
+ case ESRCH:
+ SetLastError (ERROR_PROC_NOT_FOUND);
+ break;
+ default:
+ SetLastError (ERROR_GEN_FAILURE);
+ }
+ return 0;
+ }
+
+ if (ret == 0)
+ return MONO_W32PROCESS_PRIORITY_CLASS_NORMAL;
+ else if (ret < -15)
+ return MONO_W32PROCESS_PRIORITY_CLASS_REALTIME;
+ else if (ret < -10)
+ return MONO_W32PROCESS_PRIORITY_CLASS_HIGH;
+ else if (ret < 0)
+ return MONO_W32PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
+ else if (ret > 10)
+ return MONO_W32PROCESS_PRIORITY_CLASS_IDLE;
+ else if (ret > 0)
+ return MONO_W32PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
+
+ return MONO_W32PROCESS_PRIORITY_CLASS_NORMAL;
+#else
+ SetLastError (ERROR_NOT_SUPPORTED);
+ return 0;
+#endif
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
+{
+#ifdef HAVE_SETPRIORITY
+ MonoW32HandleProcess *process_handle;
+ int ret;
+ int prio;
+ pid_t pid;
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ /* This is a pseudo handle */
+ pid = (pid_t)WAPI_HANDLE_TO_PID (handle);
+ } else {
+ gboolean res;
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ pid = process_handle->id;
+ }
+
+ switch (priorityClass) {
+ case MONO_W32PROCESS_PRIORITY_CLASS_IDLE:
+ prio = 19;
+ break;
+ case MONO_W32PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
+ prio = 10;
+ break;
+ case MONO_W32PROCESS_PRIORITY_CLASS_NORMAL:
+ prio = 0;
+ break;
+ case MONO_W32PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
+ prio = -5;
+ break;
+ case MONO_W32PROCESS_PRIORITY_CLASS_HIGH:
+ prio = -11;
+ break;
+ case MONO_W32PROCESS_PRIORITY_CLASS_REALTIME:
+ prio = -20;
+ break;
+ default:
+ SetLastError (ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ ret = setpriority (PRIO_PROCESS, pid, prio);
+ if (ret == -1) {
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ SetLastError (ERROR_ACCESS_DENIED);
+ break;
+ case ESRCH:
+ SetLastError (ERROR_PROC_NOT_FOUND);
+ break;
+ default:
+ SetLastError (ERROR_GEN_FAILURE);
+ }
+ }
+
+ return ret == 0;
+#else
+ SetLastError (ERROR_NOT_SUPPORTED);
+ return FALSE;
+#endif
+}
+
+static void
+ticks_to_processtime (guint64 ticks, ProcessTime *processtime)
+{
+ processtime->lowDateTime = ticks & 0xFFFFFFFF;
+ processtime->highDateTime = ticks >> 32;
+}
+
+static void
+wapifiletime_to_processtime (WapiFileTime wapi_filetime, ProcessTime *processtime)
+{
+ processtime->lowDateTime = wapi_filetime.dwLowDateTime;
+ processtime->highDateTime = wapi_filetime.dwHighDateTime;
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creation_time, gint64 *exit_time, gint64 *kernel_time, gint64 *user_time)
+{
+ MonoW32HandleProcess *process_handle;
+ ProcessTime *creation_processtime, *exit_processtime, *kernel_processtime, *user_processtime;
+ gboolean res;
+
+ if (!creation_time || !exit_time || !kernel_time || !user_time) {
+ /* Not sure if w32 allows NULLs here or not */
+ return FALSE;
+ }
+
+ creation_processtime = (ProcessTime*) creation_time;
+ exit_processtime = (ProcessTime*) exit_time;
+ kernel_processtime = (ProcessTime*) kernel_time;
+ user_processtime = (ProcessTime*) user_time;
+
+ memset (creation_processtime, 0, sizeof (ProcessTime));
+ memset (exit_processtime, 0, sizeof (ProcessTime));
+ memset (kernel_processtime, 0, sizeof (ProcessTime));
+ memset (user_processtime, 0, sizeof (ProcessTime));
+
+ if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ gint64 start_ticks, user_ticks, kernel_ticks;
+
+ mono_process_get_times (GINT_TO_POINTER (WAPI_HANDLE_TO_PID (handle)),
+ &start_ticks, &user_ticks, &kernel_ticks);
+
+ ticks_to_processtime (start_ticks, creation_processtime);
+ ticks_to_processtime (user_ticks, kernel_processtime);
+ ticks_to_processtime (kernel_ticks, user_processtime);
+ return TRUE;
+ }
+
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ return FALSE;
+ }
+
+ wapifiletime_to_processtime (process_handle->create_time, creation_processtime);
+
+ /* A process handle is only signalled if the process has
+ * exited, otherwise exit_processtime isn't set */
+ if (mono_w32handle_issignalled (handle))
+ wapifiletime_to_processtime (process_handle->exit_time, exit_processtime);
+
+#ifdef HAVE_GETRUSAGE
+ if (process_handle->id == getpid ()) {
+ struct rusage time_data;
+ if (getrusage (RUSAGE_SELF, &time_data) == 0) {
+ ticks_to_processtime ((guint64)time_data.ru_utime.tv_sec * 10000000 + (guint64)time_data.ru_utime.tv_usec * 10, user_processtime);
+ ticks_to_processtime ((guint64)time_data.ru_stime.tv_sec * 10000000 + (guint64)time_data.ru_stime.tv_usec * 10, kernel_processtime);
+ }
+ }
+#endif
+
+ return TRUE;
+}
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef __MONO_METADATA_PROCESS_INTERNALS_H__
+#define __MONO_METADATA_PROCESS_INTERNALS_H__
+
+#include <config.h>
+#include <glib.h>
+
+// On platforms not using classic WIN API support the implementation of bellow methods are hosted in separate source file
+// process-windows-*.c. On platforms using classic WIN API the implementation is still keept in process.c and still declared
+// static and in some places even inlined.
+#if !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+void
+mono_w32process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error);
+
+void
+mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle,
+ HANDLE stderr_handle,STARTUPINFO *startinfo);
+
+gboolean
+mono_process_create_process (MonoProcInfo *mono_process_info, gunichar2 *shell_path, MonoString *cmd,
+ guint32 creation_flags, gchar *env_vars, gunichar2 *dir, STARTUPINFO *start_info,
+ PROCESS_INFORMATION *process_info);
+
+MonoBoolean
+mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max);
+
+MonoBoolean
+mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max);
+
+gint32
+mono_icall_get_priority_class (gpointer handle);
+
+MonoBoolean
+mono_icall_set_priority_class (gpointer handle, gint32 priorityClass);
+#endif /* !G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+#endif /* __MONO_METADATA_PROCESS_INTERNALS_H__ */
--- /dev/null
+/*
+ * process-windows-uwp.c: UWP process support for Mono.
+ *
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+*/
+#include <config.h>
+#include <glib.h>
+
+#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
+#include <Windows.h>
+#include "mono/metadata/w32process-win32-internals.h"
+
+gboolean
+mono_process_win_enum_processes (DWORD *pids, DWORD count, DWORD *needed)
+{
+ g_unsupported_api ("EnumProcesses");
+ *needed = 0;
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+HANDLE
+ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
+{
+ HANDLE handle;
+
+ /* GetCurrentProcess returns a pseudo-handle, so use
+ * OpenProcess instead
+ */
+ handle = OpenProcess (PROCESS_ALL_ACCESS, TRUE, pid);
+ if (handle == NULL)
+ /* FIXME: Throw an exception */
+ return NULL;
+ return handle;
+}
+
+void
+mono_w32process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error)
+{
+ g_unsupported_api ("GetFileVersionInfoSize, GetFileVersionInfo, VerQueryValue, VerLanguageName");
+
+ mono_error_init (error);
+ mono_error_set_not_supported (error, G_UNSUPPORTED_API, "GetFileVersionInfoSize, GetFileVersionInfo, VerQueryValue, VerLanguageName");
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+}
+
+MonoObject*
+process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2 *modulename, MonoClass *proc_class, MonoError *error)
+{
+ g_unsupported_api ("GetModuleInformation");
+
+ mono_error_init (error);
+ mono_error_set_not_supported (error, G_UNSUPPORTED_API, "GetModuleInformation");
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return NULL;
+}
+
+MonoArray *
+ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("EnumProcessModules, GetModuleBaseName, GetModuleFileNameEx");
+
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "EnumProcessModules, GetModuleBaseName, GetModuleFileNameEx");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return NULL;
+}
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_info)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("ShellExecuteEx");
+
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "ShellExecuteEx");
+ mono_error_set_pending_exception (&mono_error);
+
+ process_info->pid = (guint32)(-ERROR_NOT_SUPPORTED);
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+MonoString *
+ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process)
+{
+ MonoError error;
+ MonoString *string;
+ gunichar2 name[MAX_PATH];
+ guint32 len;
+
+ len = GetModuleFileName (NULL, name, G_N_ELEMENTS (name));
+ if (len == 0)
+ return NULL;
+
+ string = mono_string_new_utf16_checked (mono_domain_get (), name, len, &error);
+ if (!mono_error_ok (&error))
+ mono_error_set_pending_exception (&error);
+
+ return string;
+}
+
+void
+mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, STARTUPINFO *startinfo)
+{
+ startinfo->cb = sizeof(STARTUPINFO);
+ startinfo->dwFlags = 0;
+ startinfo->hStdInput = INVALID_HANDLE_VALUE;
+ startinfo->hStdOutput = INVALID_HANDLE_VALUE;
+ startinfo->hStdError = INVALID_HANDLE_VALUE;
+ return;
+}
+
+gboolean
+mono_process_create_process (MonoProcInfo *mono_process_info, gunichar2 *shell_path, MonoString *cmd, guint32 creation_flags,
+ gchar *env_vars, gunichar2 *dir, STARTUPINFO *start_info, PROCESS_INFORMATION *process_info)
+{
+ MonoError mono_error;
+ gchar *api_name = "";
+
+ if (mono_process_info->username) {
+ api_name = "CreateProcessWithLogonW";
+ } else {
+ api_name = "CreateProcess";
+ }
+
+ memset (&process_info, 0, sizeof (PROCESS_INFORMATION));
+ g_unsupported_api (api_name);
+
+ mono_error_init (&mono_error);
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, api_name);
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+MonoBoolean
+mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("GetProcessWorkingSetSize");
+
+ mono_error_set_not_supported(&mono_error, G_UNSUPPORTED_API, "GetProcessWorkingSetSize");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+MonoBoolean
+mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("SetProcessWorkingSetSize");
+
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "SetProcessWorkingSetSize");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+gint32
+mono_icall_get_priority_class (gpointer handle)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("GetPriorityClass");
+
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetPriorityClass");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+MonoBoolean
+mono_icall_set_priority_class (gpointer handle, gint32 priorityClass)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("SetPriorityClass");
+
+ mono_error_set_not_supported(&mono_error, G_UNSUPPORTED_API, "SetPriorityClass");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return FALSE;
+}
+
+#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
+
+#ifdef _MSC_VER
+// Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty.
+void __mono_win32_process_windows_uwp_quiet_lnk4221(void) {}
+#endif
+#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
--- /dev/null
+/*
+ * process.c: System.Diagnostics.Process support
+ *
+ * Author:
+ * Dick Porter (dick@ximian.com)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * Copyright 2002-2006 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <string.h>
+
+#include <winsock2.h>
+#include <windows.h>
+
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/w32process.h>
+#include <mono/metadata/w32process-win32-internals.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/image.h>
+#include <mono/metadata/cil-coff.h>
+#include <mono/metadata/exception.h>
+#include <mono/metadata/threadpool-ms-io.h>
+#include <mono/utils/strenc.h>
+#include <mono/utils/mono-proclib.h>
+#include <mono/io-layer/io-layer.h>
+/* FIXME: fix this code to not depend so much on the internals */
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/w32handle.h>
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+#include <shellapi.h>
+#endif
+
+void
+mono_w32process_init (void)
+{
+}
+
+void
+mono_w32process_cleanup (void)
+{
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+HANDLE
+ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
+{
+ HANDLE handle;
+
+ /* GetCurrentProcess returns a pseudo-handle, so use
+ * OpenProcess instead
+ */
+ handle = OpenProcess (PROCESS_ALL_ACCESS, TRUE, pid);
+ if (handle == NULL)
+ /* FIXME: Throw an exception */
+ return NULL;
+ return handle;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
+
+static gchar*
+mono_process_unquote_application_name (gchar *appname)
+{
+ size_t len = strlen (appname);
+ if (len) {
+ if (appname[len-1] == '\"')
+ appname[len-1] = '\0';
+ if (appname[0] == '\"')
+ appname++;
+ }
+
+ return appname;
+}
+
+static gchar*
+mono_process_quote_path (const gchar *path)
+{
+ gchar *res = g_shell_quote (path);
+ gchar *q = res;
+ while (*q) {
+ if (*q == '\'')
+ *q = '\"';
+ q++;
+ }
+ return res;
+}
+
+/* Only used when UseShellExecute is false */
+static gboolean
+mono_process_complete_path (const gunichar2 *appname, gchar **completed)
+{
+ gchar *utf8app, *utf8appmemory;
+ gchar *found;
+
+ utf8appmemory = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL);
+ utf8app = mono_process_unquote_application_name (utf8appmemory);
+
+ if (g_path_is_absolute (utf8app)) {
+ *completed = mono_process_quote_path (utf8app);
+ g_free (utf8appmemory);
+ return TRUE;
+ }
+
+ if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (utf8app, G_FILE_TEST_IS_DIR)) {
+ *completed = mono_process_quote_path (utf8app);
+ g_free (utf8appmemory);
+ return TRUE;
+ }
+
+ found = g_find_program_in_path (utf8app);
+ if (found == NULL) {
+ *completed = NULL;
+ g_free (utf8appmemory);
+ return FALSE;
+ }
+
+ *completed = mono_process_quote_path (found);
+ g_free (found);
+ g_free (utf8appmemory);
+ return TRUE;
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+MonoBoolean
+ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStartInfo *proc_start_info, MonoW32ProcessInfo *process_info)
+{
+ SHELLEXECUTEINFO shellex = {0};
+ gboolean ret;
+
+ shellex.cbSize = sizeof(SHELLEXECUTEINFO);
+ shellex.fMask = (gulong)(SEE_MASK_FLAG_DDEWAIT | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE);
+ shellex.nShow = (gulong)proc_start_info->window_style;
+ shellex.nShow = (gulong)((shellex.nShow == 0) ? 1 : (shellex.nShow == 1 ? 0 : shellex.nShow));
+
+ if (proc_start_info->filename != NULL) {
+ shellex.lpFile = mono_string_chars (proc_start_info->filename);
+ }
+
+ if (proc_start_info->arguments != NULL) {
+ shellex.lpParameters = mono_string_chars (proc_start_info->arguments);
+ }
+
+ if (proc_start_info->verb != NULL &&
+ mono_string_length (proc_start_info->verb) != 0) {
+ shellex.lpVerb = mono_string_chars (proc_start_info->verb);
+ }
+
+ if (proc_start_info->working_directory != NULL &&
+ mono_string_length (proc_start_info->working_directory) != 0) {
+ shellex.lpDirectory = mono_string_chars (proc_start_info->working_directory);
+ }
+
+ if (proc_start_info->error_dialog) {
+ shellex.hwnd = proc_start_info->error_dialog_parent_handle;
+ } else {
+ shellex.fMask = (gulong)(shellex.fMask | SEE_MASK_FLAG_NO_UI);
+ }
+
+ ret = ShellExecuteEx (&shellex);
+ if (ret == FALSE) {
+ process_info->pid = -GetLastError ();
+ } else {
+ process_info->process_handle = shellex.hProcess;
+ process_info->thread_handle = NULL;
+#if !defined(MONO_CROSS_COMPILE)
+ process_info->pid = GetProcessId (shellex.hProcess);
+#else
+ process_info->pid = 0;
+#endif
+ process_info->tid = 0;
+ }
+
+ return ret;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline void
+mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, STARTUPINFO *startinfo)
+{
+ startinfo->cb = sizeof(STARTUPINFO);
+ startinfo->dwFlags = STARTF_USESTDHANDLES;
+ startinfo->hStdInput = stdin_handle;
+ startinfo->hStdOutput = stdout_handle;
+ startinfo->hStdError = stderr_handle;
+ return;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static gboolean
+mono_process_create_process (MonoW32ProcessInfo *mono_process_info, gunichar2 *shell_path,
+ MonoString *cmd, guint32 creation_flags, gchar *env_vars,
+ gunichar2 *dir, STARTUPINFO *start_info, PROCESS_INFORMATION *process_info)
+{
+ gboolean result = FALSE;
+
+ if (mono_process_info->username) {
+ guint32 logon_flags = mono_process_info->load_user_profile ? LOGON_WITH_PROFILE : 0;
+
+ result = CreateProcessWithLogonW (mono_string_chars (mono_process_info->username),
+ mono_process_info->domain ? mono_string_chars (mono_process_info->domain) : NULL,
+ (const gunichar2 *)mono_process_info->password,
+ logon_flags,
+ shell_path,
+ cmd ? mono_string_chars (cmd) : NULL,
+ creation_flags,
+ env_vars, dir, start_info, process_info);
+
+ } else {
+
+ result = CreateProcess (shell_path,
+ cmd ? mono_string_chars (cmd): NULL,
+ NULL,
+ NULL,
+ TRUE,
+ creation_flags,
+ env_vars,
+ dir,
+ start_info,
+ process_info);
+
+ }
+
+ return result;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+static gboolean
+mono_process_get_shell_arguments (MonoW32ProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
+{
+ gchar *spath = NULL;
+ gchar *new_cmd, *cmd_utf8;
+ MonoError mono_error;
+
+ *shell_path = NULL;
+ *cmd = proc_start_info->arguments;
+
+ mono_process_complete_path (mono_string_chars (proc_start_info->filename), &spath);
+ if (spath != NULL) {
+ /* Seems like our CreateProcess does not work as the windows one.
+ * This hack is needed to deal with paths containing spaces */
+ if (*cmd) {
+ cmd_utf8 = mono_string_to_utf8_checked (*cmd, &mono_error);
+ if (!mono_error_set_pending_exception (&mono_error)) {
+ new_cmd = g_strdup_printf ("%s %s", spath, cmd_utf8);
+ *cmd = mono_string_new_wrapper (new_cmd);
+ g_free (cmd_utf8);
+ g_free (new_cmd);
+ } else {
+ *cmd = NULL;
+ }
+ }
+ else {
+ *cmd = mono_string_new_wrapper (spath);
+ }
+
+ g_free (spath);
+ }
+
+ return (*cmd != NULL) ? TRUE : FALSE;
+}
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStartInfo *proc_start_info, HANDLE stdin_handle,
+ HANDLE stdout_handle, HANDLE stderr_handle, MonoW32ProcessInfo *process_info)
+{
+ gboolean ret;
+ gunichar2 *dir;
+ STARTUPINFO startinfo={0};
+ PROCESS_INFORMATION procinfo;
+ gunichar2 *shell_path = NULL;
+ gchar *env_vars = NULL;
+ MonoString *cmd = NULL;
+ guint32 creation_flags;
+
+ mono_process_init_startup_info (stdin_handle, stdout_handle, stderr_handle, &startinfo);
+
+ creation_flags = CREATE_UNICODE_ENVIRONMENT;
+ if (proc_start_info->create_no_window)
+ creation_flags |= CREATE_NO_WINDOW;
+
+ if (mono_process_get_shell_arguments (proc_start_info, &shell_path, &cmd) == FALSE) {
+ process_info->pid = -ERROR_FILE_NOT_FOUND;
+ return FALSE;
+ }
+
+ if (process_info->env_keys) {
+ gint i, len;
+ MonoString *ms;
+ MonoString *key, *value;
+ gunichar2 *str, *ptr;
+ gunichar2 *equals16;
+
+ for (len = 0, i = 0; i < mono_array_length (process_info->env_keys); i++) {
+ ms = mono_array_get (process_info->env_values, MonoString *, i);
+ if (ms == NULL)
+ continue;
+
+ len += mono_string_length (ms) * sizeof (gunichar2);
+ ms = mono_array_get (process_info->env_keys, MonoString *, i);
+ len += mono_string_length (ms) * sizeof (gunichar2);
+ len += 2 * sizeof (gunichar2);
+ }
+
+ equals16 = g_utf8_to_utf16 ("=", 1, NULL, NULL, NULL);
+ ptr = str = g_new0 (gunichar2, len + 1);
+ for (i = 0; i < mono_array_length (process_info->env_keys); i++) {
+ value = mono_array_get (process_info->env_values, MonoString *, i);
+ if (value == NULL)
+ continue;
+
+ key = mono_array_get (process_info->env_keys, MonoString *, i);
+ memcpy (ptr, mono_string_chars (key), mono_string_length (key) * sizeof (gunichar2));
+ ptr += mono_string_length (key);
+
+ memcpy (ptr, equals16, sizeof (gunichar2));
+ ptr++;
+
+ memcpy (ptr, mono_string_chars (value), mono_string_length (value) * sizeof (gunichar2));
+ ptr += mono_string_length (value);
+ ptr++;
+ }
+
+ g_free (equals16);
+ env_vars = (gchar *) str;
+ }
+
+ /* The default dir name is "". Turn that into NULL to mean
+ * "current directory"
+ */
+ if (proc_start_info->working_directory == NULL || mono_string_length (proc_start_info->working_directory) == 0)
+ dir = NULL;
+ else
+ dir = mono_string_chars (proc_start_info->working_directory);
+
+ ret = mono_process_create_process (process_info, shell_path, cmd, creation_flags, env_vars, dir, &startinfo, &procinfo);
+
+ g_free (env_vars);
+ if (shell_path != NULL)
+ g_free (shell_path);
+
+ if (ret) {
+ process_info->process_handle = procinfo.hProcess;
+ /*process_info->thread_handle=procinfo.hThread;*/
+ process_info->thread_handle = NULL;
+ if (procinfo.hThread != NULL && procinfo.hThread != INVALID_HANDLE_VALUE)
+ CloseHandle (procinfo.hThread);
+ process_info->pid = procinfo.dwProcessId;
+ process_info->tid = procinfo.dwThreadId;
+ } else {
+ process_info->pid = -GetLastError ();
+ }
+
+ return ret;
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline gboolean
+mono_process_win_enum_processes (DWORD *pids, DWORD count, DWORD *needed)
+{
+ return EnumProcesses (pids, count, needed);
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+MonoArray *
+ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
+{
+ MonoError error;
+ MonoArray *procs;
+ gboolean ret;
+ DWORD needed;
+ int count;
+ DWORD *pids;
+
+ count = 512;
+ do {
+ pids = g_new0 (DWORD, count);
+ ret = mono_process_win_enum_processes (pids, count * sizeof (guint32), &needed);
+ if (ret == FALSE) {
+ MonoException *exc;
+
+ g_free (pids);
+ pids = NULL;
+ exc = mono_get_exception_not_supported ("This system does not support EnumProcesses");
+ mono_set_pending_exception (exc);
+ return NULL;
+ }
+ if (needed < (count * sizeof (guint32)))
+ break;
+ g_free (pids);
+ pids = NULL;
+ count = (count * 3) / 2;
+ } while (TRUE);
+
+ count = needed / sizeof (guint32);
+ procs = mono_array_new_checked (mono_domain_get (), mono_get_int32_class (), count, &error);
+ if (mono_error_set_pending_exception (&error)) {
+ g_free (pids);
+ return NULL;
+ }
+
+ memcpy (mono_array_addr (procs, guint32, 0), pids, needed);
+ g_free (pids);
+ pids = NULL;
+
+ return procs;
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
+{
+ return CloseHandle (handle);
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
+{
+ return TerminateProcess (handle, exitcode);
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
+{
+ return GetExitCodeProcess (handle, exitcode);
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline MonoBoolean
+mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max)
+{
+ return GetProcessWorkingSetSize (handle, min, max);
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
+{
+ return mono_icall_get_process_working_set_size (handle, min, max);
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline MonoBoolean
+mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max)
+{
+ return SetProcessWorkingSetSize (handle, min, max);
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
+{
+ return mono_icall_set_process_working_set_size (handle, min, max);
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline gint32
+mono_icall_get_priority_class (gpointer handle)
+{
+ return GetPriorityClass (handle);
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+gint32
+ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
+{
+ return mono_icall_get_priority_class (handle);
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline MonoBoolean
+mono_icall_set_priority_class (gpointer handle, gint32 priorityClass)
+{
+ return SetPriorityClass (handle, (guint32) priorityClass);
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
+{
+ return mono_icall_set_priority_class (handle, priorityClass);
+}
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
+{
+ return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
+}
+
+gpointer
+ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
+{
+ return GetCurrentProcess ();
+}
--- /dev/null
+
+#include <glib.h>
+
+#include "w32process.h"
+#include "w32process-internals.h"
+#include "w32process-win32-internals.h"
+#include "object.h"
+#include "object-internals.h"
+#include "class.h"
+#include "class-internals.h"
+#include "image.h"
+#include "utils/mono-proclib.h"
+
+#define LOGDEBUG(...)
+/* define LOGDEBUG(...) g_message(__VA_ARGS__) */
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) && defined(HOST_WIN32)
+
+static guint32
+mono_w32process_get_pid (gpointer handle)
+{
+ return GetProcessId (handle);
+}
+
+static gboolean
+mono_w32process_try_get_modules (gpointer process, gpointer *modules, guint32 size, guint32 *needed)
+{
+ return EnumProcessModules (process, modules, size, &needed);
+}
+
+static guint32
+mono_w32process_module_get_name (gpointer process, gpointer module, gunichar2 *basename, guint32 size)
+{
+ return GetModuleBaseName (process, module, basename, size);
+}
+
+static guint32
+mono_w32process_module_get_filename (gpointer process, gpointer module, gunichar2 *basename, guint32 size)
+{
+ return GetModuleFileNameEx (process, module, basename, size);
+}
+
+static gboolean
+mono_w32process_module_get_information (gpointer process, gpointer module, MODULEINFO *modinfo, guint32 size)
+{
+ return GetModuleInformation (process, module, modinfo, size);
+}
+
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) && defined(HOST_WIN32) */
+
+static MonoImage *system_image;
+
+static void
+stash_system_image (MonoImage *image)
+{
+ system_image = image;
+}
+
+static MonoClass*
+get_file_version_info_class (void)
+{
+ static MonoClass *file_version_info_class;
+
+ if (file_version_info_class)
+ return file_version_info_class;
+
+ g_assert (system_image);
+
+ return file_version_info_class = mono_class_load_from_name (
+ system_image, "System.Diagnostics", "FileVersionInfo");
+}
+
+static MonoClass*
+get_process_module_class (void)
+{
+ static MonoClass *process_module_class;
+
+ if (process_module_class)
+ return process_module_class;
+
+ g_assert (system_image);
+
+ return process_module_class = mono_class_load_from_name (
+ system_image, "System.Diagnostics", "ProcessModule");
+}
+
+static guint32
+unicode_chars (const gunichar2 *str)
+{
+ guint32 len;
+ for (len = 0; str [len] != '\0'; ++len) {}
+ return len;
+}
+
+static void
+process_set_field_object (MonoObject *obj, const gchar *fieldname, MonoObject *data)
+{
+ MonoClass *klass;
+ MonoClassField *field;
+
+ LOGDEBUG (g_message ("%s: Setting field %s to object at %p", __func__, fieldname, data));
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, data);
+}
+
+static void
+process_set_field_string (MonoObject *obj, const gchar *fieldname, const gunichar2 *val, guint32 len, MonoError *error)
+{
+ MonoDomain *domain;
+ MonoClass *klass;
+ MonoClassField *field;
+ MonoString *string;
+
+ mono_error_init (error);
+
+ LOGDEBUG (g_message ("%s: Setting field %s to [%s]", __func__, fieldname, g_utf16_to_utf8 (val, len, NULL, NULL, NULL)));
+
+ domain = mono_object_domain (obj);
+ g_assert (domain);
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ string = mono_string_new_utf16_checked (domain, val, len, error);
+ return_if_nok (error);
+
+ mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, (MonoObject*)string);
+}
+
+static void
+process_set_field_string_char (MonoObject *obj, const gchar *fieldname, const gchar *val)
+{
+ MonoDomain *domain;
+ MonoClass *klass;
+ MonoClassField *field;
+ MonoString *string;
+
+ LOGDEBUG (g_message ("%s: Setting field %s to [%s]", __func__, fieldname, val));
+
+ domain = mono_object_domain (obj);
+ g_assert (domain);
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ string = mono_string_new (domain, val);
+
+ mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, (MonoObject*)string);
+}
+
+static void
+process_set_field_int (MonoObject *obj, const gchar *fieldname, guint32 val)
+{
+ MonoClass *klass;
+ MonoClassField *field;
+
+ LOGDEBUG (g_message ("%s: Setting field %s to %d", __func__,fieldname, val));
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ *(guint32 *)(((char *)obj) + field->offset)=val;
+}
+
+static void
+process_set_field_intptr (MonoObject *obj, const gchar *fieldname, gpointer val)
+{
+ MonoClass *klass;
+ MonoClassField *field;
+
+ LOGDEBUG (g_message ("%s: Setting field %s to %p", __func__, fieldname, val));
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ *(gpointer *)(((char *)obj) + field->offset) = val;
+}
+
+static void
+process_set_field_bool (MonoObject *obj, const gchar *fieldname, gboolean val)
+{
+ MonoClass *klass;
+ MonoClassField *field;
+
+ LOGDEBUG (g_message ("%s: Setting field %s to %s", __func__, fieldname, val ? "TRUE":"FALSE"));
+
+ klass = mono_object_class (obj);
+ g_assert (klass);
+
+ field = mono_class_get_field_from_name (klass, fieldname);
+ g_assert (field);
+
+ *(guint8 *)(((char *)obj) + field->offset) = val;
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+
+#define SFI_COMMENTS "\\StringFileInfo\\%02X%02X%02X%02X\\Comments"
+#define SFI_COMPANYNAME "\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName"
+#define SFI_FILEDESCRIPTION "\\StringFileInfo\\%02X%02X%02X%02X\\FileDescription"
+#define SFI_FILEVERSION "\\StringFileInfo\\%02X%02X%02X%02X\\FileVersion"
+#define SFI_INTERNALNAME "\\StringFileInfo\\%02X%02X%02X%02X\\InternalName"
+#define SFI_LEGALCOPYRIGHT "\\StringFileInfo\\%02X%02X%02X%02X\\LegalCopyright"
+#define SFI_LEGALTRADEMARKS "\\StringFileInfo\\%02X%02X%02X%02X\\LegalTrademarks"
+#define SFI_ORIGINALFILENAME "\\StringFileInfo\\%02X%02X%02X%02X\\OriginalFilename"
+#define SFI_PRIVATEBUILD "\\StringFileInfo\\%02X%02X%02X%02X\\PrivateBuild"
+#define SFI_PRODUCTNAME "\\StringFileInfo\\%02X%02X%02X%02X\\ProductName"
+#define SFI_PRODUCTVERSION "\\StringFileInfo\\%02X%02X%02X%02X\\ProductVersion"
+#define SFI_SPECIALBUILD "\\StringFileInfo\\%02X%02X%02X%02X\\SpecialBuild"
+#define EMPTY_STRING (gunichar2*)"\000\000"
+
+typedef struct {
+ const char *name;
+ const char *id;
+} StringTableEntry;
+
+static StringTableEntry stringtable_entries [] = {
+ { "comments", SFI_COMMENTS },
+ { "companyname", SFI_COMPANYNAME },
+ { "filedescription", SFI_FILEDESCRIPTION },
+ { "fileversion", SFI_FILEVERSION },
+ { "internalname", SFI_INTERNALNAME },
+ { "legalcopyright", SFI_LEGALCOPYRIGHT },
+ { "legaltrademarks", SFI_LEGALTRADEMARKS },
+ { "originalfilename", SFI_ORIGINALFILENAME },
+ { "privatebuild", SFI_PRIVATEBUILD },
+ { "productname", SFI_PRODUCTNAME },
+ { "productversion", SFI_PRODUCTVERSION },
+ { "specialbuild", SFI_SPECIALBUILD }
+};
+
+static void
+process_module_string_read (MonoObject *filever, gpointer data, const gchar *fieldname,
+ guchar lang_hi, guchar lang_lo, const gchar *key, MonoError *error)
+{
+ gchar *lang_key_utf8;
+ gunichar2 *lang_key, *buffer;
+ UINT chars;
+
+ mono_error_init (error);
+
+ lang_key_utf8 = g_strdup_printf (key, lang_lo, lang_hi, 0x04, 0xb0);
+
+ LOGDEBUG (g_message ("%s: asking for [%s]", __func__, lang_key_utf8));
+
+ lang_key = g_utf8_to_utf16 (lang_key_utf8, -1, NULL, NULL, NULL);
+
+ if (VerQueryValue (data, lang_key, (gpointer *)&buffer, &chars) && chars > 0) {
+ LOGDEBUG (g_message ("%s: found %d chars of [%s]", __func__, chars, g_utf16_to_utf8 (buffer, chars, NULL, NULL, NULL)));
+ /* chars includes trailing null */
+ process_set_field_string (filever, fieldname, buffer, chars - 1, error);
+ } else {
+ process_set_field_string (filever, fieldname, EMPTY_STRING, 0, error);
+ }
+
+ g_free (lang_key);
+ g_free (lang_key_utf8);
+}
+
+static void
+process_module_stringtable (MonoObject *filever, gpointer data, guchar lang_hi, guchar lang_lo, MonoError *error)
+{
+ for (int i = 0; i < G_N_ELEMENTS (stringtable_entries); ++i) {
+ process_module_string_read (filever, data, stringtable_entries [i].name,
+ lang_hi, lang_lo, stringtable_entries [i].id, error);
+ return_if_nok (error);
+ }
+}
+
+static void
+mono_w32process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *error)
+{
+ DWORD verinfohandle;
+ VS_FIXEDFILEINFO *ffi;
+ gpointer data;
+ DWORD datalen;
+ guchar *trans_data;
+ gunichar2 *query;
+ UINT ffi_size, trans_size;
+ BOOL ok;
+ gunichar2 lang_buf[128];
+ guint32 lang, lang_count;
+
+ mono_error_init (error);
+
+ datalen = GetFileVersionInfoSize (filename, &verinfohandle);
+ if (datalen) {
+ data = g_malloc0 (datalen);
+ ok = GetFileVersionInfo (filename, verinfohandle, datalen, data);
+ if (ok) {
+ query = g_utf8_to_utf16 ("\\", -1, NULL, NULL, NULL);
+ if (query == NULL) {
+ g_free (data);
+ return;
+ }
+
+ if (VerQueryValue (data, query, (gpointer *)&ffi, &ffi_size)) {
+ LOGDEBUG (g_message ("%s: recording assembly: FileName [%s] FileVersionInfo [%d.%d.%d.%d]", __func__, g_utf16_to_utf8 (filename, -1, NULL, NULL, NULL), HIWORD (ffi->dwFileVersionMS), LOWORD (ffi->dwFileVersionMS), HIWORD (ffi->dwFileVersionLS), LOWORD (ffi->dwFileVersionLS)));
+
+ process_set_field_int (filever, "filemajorpart", HIWORD (ffi->dwFileVersionMS));
+ process_set_field_int (filever, "fileminorpart", LOWORD (ffi->dwFileVersionMS));
+ process_set_field_int (filever, "filebuildpart", HIWORD (ffi->dwFileVersionLS));
+ process_set_field_int (filever, "fileprivatepart", LOWORD (ffi->dwFileVersionLS));
+
+ process_set_field_int (filever, "productmajorpart", HIWORD (ffi->dwProductVersionMS));
+ process_set_field_int (filever, "productminorpart", LOWORD (ffi->dwProductVersionMS));
+ process_set_field_int (filever, "productbuildpart", HIWORD (ffi->dwProductVersionLS));
+ process_set_field_int (filever, "productprivatepart", LOWORD (ffi->dwProductVersionLS));
+
+ process_set_field_bool (filever, "isdebug", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_DEBUG) != 0);
+ process_set_field_bool (filever, "isprerelease", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PRERELEASE) != 0);
+ process_set_field_bool (filever, "ispatched", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PATCHED) != 0);
+ process_set_field_bool (filever, "isprivatebuild", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_PRIVATEBUILD) != 0);
+ process_set_field_bool (filever, "isspecialbuild", ((ffi->dwFileFlags & ffi->dwFileFlagsMask) & VS_FF_SPECIALBUILD) != 0);
+ }
+ g_free (query);
+
+ query = g_utf8_to_utf16 ("\\VarFileInfo\\Translation", -1, NULL, NULL, NULL);
+ if (query == NULL) {
+ g_free (data);
+ return;
+ }
+
+ if (VerQueryValue (data, query, (gpointer *)&trans_data, &trans_size)) {
+ /* use the first language ID we see */
+ if (trans_size >= 4) {
+ LOGDEBUG (g_message("%s: %s has 0x%0x 0x%0x 0x%0x 0x%0x", __func__, g_utf16_to_utf8 (filename, -1, NULL, NULL, NULL), trans_data[0], trans_data[1], trans_data[2], trans_data[3]));
+ lang = (trans_data[0]) | (trans_data[1] << 8) | (trans_data[2] << 16) | (trans_data[3] << 24);
+ /* Only give the lower 16 bits to VerLanguageName, as Windows gets confused otherwise */
+ lang_count = VerLanguageName (lang & 0xFFFF, lang_buf, 128);
+ if (lang_count) {
+ process_set_field_string (filever, "language", lang_buf, lang_count, error);
+ return_if_nok (error);
+ }
+ process_module_stringtable (filever, data, trans_data[0], trans_data[1], error);
+ return_if_nok (error);
+ }
+ } else {
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (stringtable_entries); ++i) {
+ /* No strings, so set every field to the empty string */
+ process_set_field_string (filever, stringtable_entries [i].name, EMPTY_STRING, 0, error);
+ return_if_nok (error);
+ }
+
+ /* And language seems to be set to en_US according to bug 374600 */
+ lang_count = VerLanguageName (0x0409, lang_buf, 128);
+ if (lang_count) {
+ process_set_field_string (filever, "language", lang_buf, lang_count, error);
+ return_if_nok (error);
+ }
+ }
+
+ g_free (query);
+ }
+ g_free (data);
+ }
+}
+
+#endif /* #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+void
+ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this_obj, MonoString *filename)
+{
+ MonoError error;
+
+ stash_system_image (mono_object_class (this_obj)->image);
+
+ mono_w32process_get_fileversion (this_obj, mono_string_chars (filename), &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return;
+ }
+
+ process_set_field_string (this_obj, "filename", mono_string_chars (filename), mono_string_length (filename), &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ }
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+
+static GPtrArray*
+get_domain_assemblies (MonoDomain *domain)
+{
+ GSList *tmp;
+ GPtrArray *assemblies;
+
+ /*
+ * Make a copy of the list of assemblies because we can't hold the assemblies
+ * lock while creating objects etc.
+ */
+ assemblies = g_ptr_array_new ();
+ mono_domain_assemblies_lock (domain);
+ for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
+ MonoAssembly *ass = (MonoAssembly *)tmp->data;
+ if (ass->image->fileio_used)
+ continue;
+ g_ptr_array_add (assemblies, ass);
+ }
+ mono_domain_assemblies_unlock (domain);
+
+ return assemblies;
+}
+
+static MonoObject*
+process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2 *modulename, MonoClass *proc_class, MonoError *error)
+{
+ MonoObject *item, *filever;
+ MonoDomain *domain = mono_domain_get ();
+ MODULEINFO modinfo;
+ BOOL ok;
+
+ mono_error_init (error);
+
+ /* Build a System.Diagnostics.ProcessModule with the data. */
+ item = mono_object_new_checked (domain, proc_class, error);
+ return_val_if_nok (error, NULL);
+
+ filever = mono_object_new_checked (domain, get_file_version_info_class (), error);
+ return_val_if_nok (error, NULL);
+
+ mono_w32process_get_fileversion (filever, filename, error);
+ return_val_if_nok (error, NULL);
+
+ process_set_field_string (filever, "filename", filename, unicode_chars (filename), error);
+ return_val_if_nok (error, NULL);
+
+ ok = mono_w32process_module_get_information (process, mod, &modinfo, sizeof(MODULEINFO));
+ if (ok) {
+ process_set_field_intptr (item, "baseaddr", modinfo.lpBaseOfDll);
+ process_set_field_intptr (item, "entryaddr", modinfo.EntryPoint);
+ process_set_field_int (item, "memory_size", modinfo.SizeOfImage);
+ }
+
+ process_set_field_string (item, "filename", filename, unicode_chars (filename), error);
+ return_val_if_nok (error, NULL);
+
+ process_set_field_string (item, "modulename", modulename, unicode_chars (modulename), error);
+ return_val_if_nok (error, NULL);
+
+ process_set_field_object (item, "version_info", filever);
+
+ return item;
+}
+
+static void
+process_get_assembly_fileversion (MonoObject *filever, MonoAssembly *assembly)
+{
+ process_set_field_int (filever, "filemajorpart", assembly->aname.major);
+ process_set_field_int (filever, "fileminorpart", assembly->aname.minor);
+ process_set_field_int (filever, "filebuildpart", assembly->aname.build);
+}
+
+static MonoObject*
+process_get_module (MonoAssembly *assembly, MonoClass *proc_class, MonoError *error)
+{
+ MonoObject *item, *filever;
+ MonoDomain *domain;
+ gchar *filename;
+ const gchar *modulename;
+
+ mono_error_init (error);
+
+ domain = mono_domain_get ();
+
+ modulename = assembly->aname.name;
+
+ /* Build a System.Diagnostics.ProcessModule with the data. */
+ item = mono_object_new_checked (domain, proc_class, error);
+ return_val_if_nok (error, NULL);
+
+ filever = mono_object_new_checked (domain, get_file_version_info_class (), error);
+ return_val_if_nok (error, NULL);
+
+ filename = g_strdup_printf ("[In Memory] %s", modulename);
+
+ process_get_assembly_fileversion (filever, assembly);
+ process_set_field_string_char (filever, "filename", filename);
+ process_set_field_object (item, "version_info", filever);
+
+ process_set_field_intptr (item, "baseaddr", assembly->image->raw_data);
+ process_set_field_int (item, "memory_size", assembly->image->raw_data_len);
+ process_set_field_string_char (item, "filename", filename);
+ process_set_field_string_char (item, "modulename", modulename);
+
+ g_free (filename);
+
+ return item;
+}
+
+/* Returns an array of System.Diagnostics.ProcessModule */
+MonoArray *
+ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process)
+{
+ MonoError error;
+ MonoArray *temp_arr = NULL;
+ MonoArray *arr;
+ HMODULE mods[1024];
+ gunichar2 filename[MAX_PATH];
+ gunichar2 modname[MAX_PATH];
+ DWORD needed;
+ guint32 count = 0, module_count = 0, assembly_count = 0;
+ guint32 i, num_added = 0;
+ GPtrArray *assemblies = NULL;
+
+ stash_system_image (mono_object_class (this_obj)->image);
+
+ if (mono_w32process_get_pid (process) == mono_process_current_pid ())
+ assemblies = get_domain_assemblies (mono_domain_get ());
+ assembly_count = assemblies->len;
+
+ if (mono_w32process_try_get_modules (process, mods, sizeof(mods), &needed))
+ module_count += needed / sizeof(HMODULE);
+
+ count = module_count + assembly_count;
+ temp_arr = mono_array_new_checked (mono_domain_get (), get_process_module_class (), count, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+
+ for (i = 0; i < module_count; i++) {
+ if (mono_w32process_module_get_name (process, mods[i], modname, MAX_PATH)
+ && mono_w32process_module_get_filename (process, mods[i], filename, MAX_PATH))
+ {
+ MonoObject *module = process_add_module (process, mods[i], filename, modname, get_process_module_class (), &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+ mono_array_setref (temp_arr, num_added++, module);
+ }
+ }
+
+ if (assemblies) {
+ for (i = 0; i < assembly_count; i++) {
+ MonoAssembly *ass = (MonoAssembly *)g_ptr_array_index (assemblies, i);
+ MonoObject *module = process_get_module (ass, get_process_module_class (), &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
+ mono_array_setref (temp_arr, num_added++, module);
+ }
+ g_ptr_array_free (assemblies, TRUE);
+ }
+
+ if (count == num_added) {
+ arr = temp_arr;
+ } else {
+ /* shorter version of the array */
+ arr = mono_array_new_checked (mono_domain_get (), get_process_module_class (), num_added, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+
+ for (i = 0; i < num_added; i++)
+ mono_array_setref (arr, i, mono_array_get (temp_arr, MonoObject*, i));
+ }
+
+ return arr;
+}
+
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+
+MonoString *
+ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process)
+{
+ MonoError error;
+ MonoString *string;
+ gunichar2 name[MAX_PATH];
+ guint32 len;
+ gboolean ok;
+ HMODULE mod;
+ DWORD needed;
+
+ ok = mono_w32process_try_get_modules (process, &mod, sizeof(mod), &needed);
+ if (!ok)
+ return NULL;
+
+ len = mono_w32process_module_get_name (process, mod, name, MAX_PATH);
+ if (len == 0)
+ return NULL;
+
+ string = mono_string_new_utf16_checked (mono_domain_get (), name, len, &error);
+ if (!mono_error_ok (&error))
+ mono_error_set_pending_exception (&error);
+
+ return string;
+}
+
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+gint64
+ves_icall_System_Diagnostics_Process_GetProcessData (int pid, gint32 data_type, gint32 *error)
+{
+ MonoProcessError perror;
+ guint64 res;
+
+ res = mono_process_get_data_with_error (GINT_TO_POINTER (pid), (MonoProcessData)data_type, &perror);
+ if (error)
+ *error = perror;
+ return res;
+}
--- /dev/null
+/*
+ * w32process.h: System.Diagnostics.Process support
+ *
+ * Author:
+ * Dick Porter (dick@ximian.com)
+ *
+ * (C) 2002 Ximian, Inc.
+ */
+
+#ifndef _MONO_METADATA_W32PROCESS_H_
+#define _MONO_METADATA_W32PROCESS_H_
+
+#include <config.h>
+#include <glib.h>
+
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <mono/metadata/object.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ MONO_W32PROCESS_PRIORITY_CLASS_NORMAL = 0x0020,
+ MONO_W32PROCESS_PRIORITY_CLASS_IDLE = 0x0040,
+ MONO_W32PROCESS_PRIORITY_CLASS_HIGH = 0x0080,
+ MONO_W32PROCESS_PRIORITY_CLASS_REALTIME = 0x0100,
+ MONO_W32PROCESS_PRIORITY_CLASS_BELOW_NORMAL = 0x4000,
+ MONO_W32PROCESS_PRIORITY_CLASS_ABOVE_NORMAL = 0x8000,
+} MonoW32ProcessPriorityClass;
+
+typedef struct
+{
+ gpointer process_handle;
+ gpointer thread_handle;
+ guint32 pid; /* Contains GetLastError () on failure */
+ guint32 tid;
+ MonoArray *env_keys;
+ MonoArray *env_values;
+ MonoString *username;
+ MonoString *domain;
+ gpointer password; /* BSTR from SecureString in 2.0 profile */
+ MonoBoolean load_user_profile;
+} MonoW32ProcessInfo;
+
+typedef struct
+{
+ MonoObject object;
+ MonoString *filename;
+ MonoString *arguments;
+ MonoString *working_directory;
+ MonoString *verb;
+ guint32 window_style;
+ MonoBoolean error_dialog;
+ gpointer error_dialog_parent_handle;
+ MonoBoolean use_shell_execute;
+ MonoString *username;
+ MonoString *domain;
+ MonoObject *password; /* SecureString in 2.0 profile, dummy in 1.x */
+ MonoString *password_in_clear_text;
+ MonoBoolean load_user_profile;
+ MonoBoolean redirect_standard_input;
+ MonoBoolean redirect_standard_output;
+ MonoBoolean redirect_standard_error;
+ MonoObject *encoding_stdout;
+ MonoObject *encoding_stderr;
+ MonoBoolean create_no_window;
+ MonoObject *weak_parent_process;
+ MonoObject *envVars;
+} MonoW32ProcessStartInfo;
+
+void
+mono_w32process_init (void);
+
+void
+mono_w32process_cleanup (void);
+
+#ifndef HOST_WIN32
+
+void
+mono_w32process_set_cli_launcher (gchar *path);
+
+gchar*
+mono_w32process_get_path (pid_t pid);
+
+#endif
+
+gpointer
+ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid);
+
+MonoArray*
+ves_icall_System_Diagnostics_Process_GetProcesses_internal (void);
+
+MonoArray*
+ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, gpointer process);
+
+void
+ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this_obj, MonoString *filename);
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStartInfo *proc_start_info, MonoW32ProcessInfo *process_handle);
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStartInfo *proc_start_info, gpointer stdin_handle,
+ gpointer stdout_handle, gpointer stderr_handle, MonoW32ProcessInfo *process_handle);
+
+MonoString*
+ves_icall_System_Diagnostics_Process_ProcessName_internal (gpointer process);
+
+gint64
+ves_icall_System_Diagnostics_Process_GetProcessData (int pid, gint32 data_type, gint32 *error);
+
+gpointer
+ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void);
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode);
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle);
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode);
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max);
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max);
+
+gint32
+ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle);
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass);
+
+MonoBoolean
+ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime);
+
+G_END_DECLS
+
+#endif /* _MONO_METADATA_W32PROCESS_H_ */
+
#elif defined(TARGET_POWERPC)
{
guint8 buf [32];
- guint8 *code;
emit_bytes (acfg, code, mono_arch_get_patch_offset (code));
code = buf;
* information.
*/
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
guint32 token;
g_assert (klass->type_token);
encode_value (MONO_AOT_TYPEREF_TYPESPEC_TOKEN, p, &p);
encode_value (token, p, &p);
} else {
- MonoClass *gclass = klass->generic_class->container_class;
- MonoGenericInst *inst = klass->generic_class->context.class_inst;
+ MonoClass *gclass = mono_class_get_generic_class (klass)->container_class;
+ MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
static int count = 0;
guint8 *p1 = p;
/*
* The encoding of generic instances is large so emit them only once.
*/
- if (klass->generic_class) {
+ if (mono_class_is_ginst (klass)) {
guint32 token;
g_assert (klass->type_token);
MonoMarshalType *info;
int i;
- if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
return FALSE;
info = mono_marshal_load_type_info (klass);
memset (ctx, 0, sizeof (MonoGenericContext));
- if (method->klass->generic_container) {
- shared_context = method->klass->generic_container->context;
+ if (mono_class_is_gtd (method->klass)) {
+ shared_context = mono_class_get_generic_container (method->klass)->context;
inst = shared_context.class_inst;
args = g_new0 (MonoType*, inst->type_argc);
if (!klass->delegate || klass == mono_defaults.delegate_class || klass == mono_defaults.multicastdelegate_class)
continue;
- if (!klass->generic_container) {
+ if (!mono_class_is_gtd (klass)) {
method = mono_get_delegate_invoke (klass);
m = mono_marshal_get_delegate_invoke (method, NULL);
add_method (acfg, del_invoke);
}
}
- } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->generic_container) {
+ } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && mono_class_is_gtd (klass)) {
MonoError error;
MonoGenericContext ctx;
MonoMethod *inst, *gshared;
if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
if (method->is_generic) {
// FIXME:
- } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && method->klass->generic_container) {
+ } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && mono_class_is_gtd (method->klass)) {
MonoError error;
MonoGenericContext ctx;
MonoMethod *inst, *gshared, *m;
continue;
}
- if (klass->valuetype && !klass->generic_container && can_marshal_struct (klass) &&
+ if (klass->valuetype && !mono_class_is_gtd (klass) && can_marshal_struct (klass) &&
!(klass->nested_in && strstr (klass->nested_in->name, "<PrivateImplementationDetails>") == klass->nested_in->name)) {
add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
return TRUE;
if (klass->rank)
return has_type_vars (klass->element_class);
- if (klass->generic_class) {
- MonoGenericContext *context = &klass->generic_class->context;
+ if (mono_class_is_ginst (klass)) {
+ MonoGenericContext *context = &mono_class_get_generic_class (klass)->context;
if (context->class_inst) {
int i;
return TRUE;
}
}
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
return TRUE;
return FALSE;
}
mono_class_init (klass);
- if (klass->generic_class && klass->generic_class->context.class_inst->is_open)
+ if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open)
return;
if (has_type_vars (klass))
return;
- if (!klass->generic_class && !klass->rank)
+ if (!mono_class_is_ginst (klass) && !klass->rank)
return;
if (mono_class_has_failure (klass))
* Use gsharedvt for generic collections with vtype arguments to avoid code blowup.
* Enable this only for some classes since gsharedvt might not support all methods.
*/
- if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && klass->generic_class && klass->generic_class->context.class_inst && is_vt_inst (klass->generic_class->context.class_inst) &&
+ if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst && is_vt_inst (mono_class_get_generic_class (klass)->context.class_inst) &&
(!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1") || !strcmp (klass->name, "ReadOnlyCollection`1")))
use_gsharedvt = TRUE;
*/
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") &&
(!strcmp(klass->name, "ICollection`1") || !strcmp (klass->name, "IEnumerable`1") || !strcmp (klass->name, "IList`1") || !strcmp (klass->name, "IEnumerator`1") || !strcmp (klass->name, "IReadOnlyList`1"))) {
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoClass *array_class = mono_bounded_array_class_get (tclass, 1, FALSE);
gpointer iter;
char *name_prefix;
break;
}
g_assert (nclass);
- nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (klass->generic_class), &error);
+ nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (mono_class_get_generic_class (klass)), &error);
mono_error_assert_ok (&error); /* FIXME don't swallow the error */
add_generic_class (acfg, nclass, FALSE, "ICollection<T>");
}
/* Add an instance of GenericComparer<T> which is created dynamically by Comparer<T> */
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
MonoError error;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoClass *icomparable, *gcomparer, *icomparable_inst;
MonoGenericContext ctx;
MonoType *args [16];
/* Add an instance of GenericEqualityComparer<T> which is created dynamically by EqualityComparer<T> */
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
MonoError error;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoClass *iface, *gcomparer, *iface_inst;
MonoGenericContext ctx;
MonoType *args [16];
/* Add an instance of EnumComparer<T> which is created dynamically by EqualityComparer<T> for enums */
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
MonoClass *enum_comparer;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoGenericContext ctx;
MonoType *args [16];
/* Add an instance of ObjectComparer<T> which is created dynamically by Comparer<T> for enums */
if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
MonoClass *comparer;
- MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+ MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
MonoGenericContext ctx;
MonoType *args [16];
g_free (type_argv);
}
- if (method->is_generic || method->klass->generic_container)
+ if (method->is_generic || mono_class_is_gtd (method->klass))
declaring_method = method;
else
declaring_method = mono_method_get_declaring_generic_method (method);
if (callee_cfg) {
gboolean direct_callable = TRUE;
- if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
+ if (direct_callable && !(!callee_cfg->has_got_slots && (mono_class_get_flags (callee_cfg->method->klass) & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
direct_callable = FALSE;
if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && (!method || method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED))
// FIXME: Maybe call the wrapper directly ?
mono_class_has_finalizer (klass);
- if (klass->generic_container || cant_encode) {
+ if (mono_class_is_gtd (klass) || cant_encode) {
encode_value (-1, p, &p);
} else {
encode_value (klass->vtable_size, p, &p);
- encode_value ((klass->generic_container ? (1 << 8) : 0) | (no_special_static << 7) | (klass->has_static_refs << 6) | (klass->has_references << 5) | ((klass->blittable << 4) | ((klass->ext && klass->ext->nested_classes) ? 1 : 0) << 3) | (klass->has_cctor << 2) | (klass->has_finalize << 1) | klass->ghcimpl, p, &p);
+ encode_value ((mono_class_is_gtd (klass) ? (1 << 8) : 0) | (no_special_static << 7) | (klass->has_static_refs << 6) | (klass->has_references << 5) | ((klass->blittable << 4) | ((klass->ext && klass->ext->nested_classes) ? 1 : 0) << 3) | (klass->has_cctor << 2) | (klass->has_finalize << 1) | klass->ghcimpl, p, &p);
if (klass->has_cctor)
encode_method_ref (acfg, mono_class_get_cctor (klass), p, &p);
if (klass->has_finalize)
if (!MONO_TYPE_ISSTRUCT (t))
return TRUE;
klass = mono_class_from_mono_type (t);
- orig_ctx = &klass->generic_class->context;
+ orig_ctx = &mono_class_get_generic_class (klass)->context;
inst = orig_ctx->class_inst;
if (inst) {
InterlockedIncrement (&acfg->stats.mcount);
#if 0
- if (method->is_generic || method->klass->generic_container) {
+ if (method->is_generic || mono_class_is_gtd (method->klass)) {
InterlockedIncrement (&acfg->stats.genericcount);
return;
}
case MONO_PATCH_INFO_VTABLE: {
MonoClass *klass = patch_info->data.klass;
- if (klass->generic_class && !mini_class_is_generic_sharable (klass))
+ if (mono_class_is_ginst (klass) && !mini_class_is_generic_sharable (klass))
add_generic_class_with_depth (acfg, klass, depth + 5, "vtable");
break;
}
MonoClass *klass = patch_info->data.field->parent;
/* The .cctor needs to run at runtime. */
- if (klass->generic_class && !mono_generic_context_is_sharable_full (&klass->generic_class->context, FALSE, FALSE) && mono_class_get_cctor (klass))
+ if (mono_class_is_ginst (klass) && !mono_generic_context_is_sharable_full (&mono_class_get_generic_class (klass)->context, FALSE, FALSE) && mono_class_get_cctor (klass))
add_extra_method_with_depth (acfg, mono_class_get_cctor (klass), depth + 1);
break;
}
static int
execute_system (const char * command)
{
- int status;
+ int status = 0;
#if _WIN32
// We need an extra set of quotes around the whole command to properly handle commands
sig = mono_method_signature (method);
- if (method->klass->generic_class)
- class_ginst = method->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (method->klass))
+ class_ginst = mono_class_get_generic_class (method->klass)->context.class_inst;
if (method->is_inflated)
ginst = ((MonoMethodInflated*)method)->context.method_inst;
if (!method->wrapper_type) {
char *full_name;
- if (klass->generic_class)
- full_name = mono_type_full_name (&klass->generic_class->container_class->byval_arg);
+ if (mono_class_is_ginst (klass))
+ full_name = mono_type_full_name (&mono_class_get_generic_class (klass)->container_class->byval_arg);
else
full_name = mono_type_full_name (&klass->byval_arg);
}
*/
- if (method->is_generic || method->klass->generic_container)
+ if (method->is_generic || mono_class_is_gtd (method->klass))
/* Compile the ref shared version instead */
method = mini_get_shared_method (method);
method = mono_get_method_checked (acfg->image, token, NULL, NULL, &error);
report_loader_error (acfg, &error, "Failed to load method token 0x%x due to %s\n", i, mono_error_get_message (&error));
- if (method->is_generic || method->klass->generic_container) {
+ if (method->is_generic || mono_class_is_gtd (method->klass)) {
MonoMethod *gshared;
gshared = mini_get_shared_method_full (method, TRUE, TRUE);
gclass = decode_klass_ref (module, p, &p, error);
if (!gclass)
return NULL;
- g_assert (gclass->generic_container);
+ g_assert (mono_class_is_gtd (gclass));
memset (&ctx, 0, sizeof (ctx));
ctx.class_inst = decode_generic_inst (module, p, &p, error);
if (!class_def)
return NULL;
- container = class_def->generic_container;
+ container = mono_class_try_get_generic_container (class_def); //FIXME is this a case for a try_get?
}
} else {
// We didn't decode is_method, so we have to infer it from type enum.
gclass = decode_klass_ref (module, p, &p, error);
if (!gclass)
goto fail;
- g_assert (gclass->generic_container);
+ g_assert (mono_class_is_gtd (gclass));
memset (&ctx, 0, sizeof (ctx));
ctx.class_inst = decode_generic_inst (module, p, &p, error);
if (!type)
goto fail;
klass = mono_class_from_mono_type (type);
- t->data.generic_class = klass->generic_class;
+ t->data.generic_class = mono_class_get_generic_class (klass);
break;
}
case MONO_TYPE_ARRAY: {
memset (&ctx, 0, sizeof (ctx));
- if (FALSE && klass->generic_class) {
- ctx.class_inst = klass->generic_class->context.class_inst;
+ if (FALSE && mono_class_is_ginst (klass)) {
+ ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
ctx.method_inst = NULL;
ref->method = mono_class_inflate_generic_method_full_checked (ref->method, klass, &ctx, error);
gboolean inited_ok = TRUE;
if (init_class)
inited_ok = mono_runtime_class_init_full (mono_class_vtable (domain, init_class), error);
- else if (from_plt && klass_to_run_ctor && !klass_to_run_ctor->generic_container)
+ else if (from_plt && klass_to_run_ctor && !mono_class_is_gtd (klass_to_run_ctor))
inited_ok = mono_runtime_class_init_full (mono_class_vtable (domain, klass_to_run_ctor), error);
if (!inited_ok)
return FALSE;
MonoGenericContext context = { NULL, NULL };
MonoClass *klass = rgctx->class_vtable->klass;
- if (klass->generic_class)
- context.class_inst = klass->generic_class->context.class_inst;
- else if (klass->generic_container)
- context.class_inst = klass->generic_container->context.class_inst;
+ if (mono_class_is_ginst (klass))
+ context.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
+ else if (mono_class_is_gtd (klass))
+ context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
context.method_inst = rgctx->method_inst;
init_llvmonly_method (amodule, method_index, NULL, rgctx->class_vtable->klass, &context);
if (!m->klass->valuetype && !(m->flags & METHOD_ATTRIBUTE_STATIC) && !this_arg) {
if (!strcmp (m->name, ".ctor")) {
- if (m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT)
+ if (mono_class_is_abstract (m->klass))
return ERR_INVALID_ARGUMENT;
else {
MonoError error;
buffer_add_id (buf, 0);
buffer_add_int (buf, klass->type_token);
buffer_add_byte (buf, klass->rank);
- buffer_add_int (buf, klass->flags);
+ buffer_add_int (buf, mono_class_get_flags (klass));
b = 0;
type = &klass->byval_arg;
// FIXME: Can't decide whenever a class represents a byref type
b |= (1 << 3);
if (klass->enumtype)
b |= (1 << 4);
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
b |= (1 << 5);
- if (klass->generic_container || klass->generic_class)
+ if (mono_class_is_gtd (klass) || mono_class_is_ginst (klass))
b |= (1 << 6);
buffer_add_byte (buf, b);
nnested = 0;
while ((nested = mono_class_get_nested_types (klass, &iter)))
buffer_add_typeid (buf, domain, nested);
if (CHECK_PROTOCOL_VERSION (2, 12)) {
- if (klass->generic_container)
+ if (mono_class_is_gtd (klass))
buffer_add_typeid (buf, domain, klass);
- else if (klass->generic_class)
- buffer_add_typeid (buf, domain, klass->generic_class->container_class);
+ else if (mono_class_is_ginst (klass))
+ buffer_add_typeid (buf, domain, mono_class_get_generic_class (klass)->container_class);
else
buffer_add_id (buf, 0);
}
if (CHECK_PROTOCOL_VERSION (2, 15)) {
int count, i;
- if (klass->generic_class) {
- MonoGenericInst *inst = klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (klass)) {
+ MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
count = inst->type_argc;
buffer_add_int (buf, count);
for (i = 0; i < count; i++)
buffer_add_typeid (buf, domain, mono_class_from_mono_type (inst->type_argv [i]));
- } else if (klass->generic_container) {
- MonoGenericContainer *container = klass->generic_container;
+ } else if (mono_class_is_gtd (klass)) {
+ MonoGenericContainer *container = mono_class_get_generic_container (klass);
MonoClass *pklass;
count = container->type_argc;
}
ginst = mono_metadata_get_generic_inst (type_argc, type_argv);
g_free (type_argv);
- tmp_context.class_inst = method->klass->generic_class ? method->klass->generic_class->context.class_inst : NULL;
+ tmp_context.class_inst = mono_class_is_ginst (method->klass) ? mono_class_get_generic_class (method->klass)->context.class_inst : NULL;
tmp_context.method_inst = ginst;
inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
#include <mono/metadata/gc-internals.h>
#include <mono/metadata/coree.h>
#include <mono/metadata/attach.h>
+#include <mono/metadata/w32process.h>
#include "mono/utils/mono-counters.h"
#include "mono/utils/mono-hwcap.h"
#include "mono/utils/mono-logger-internals.h"
(method->flags & METHOD_ATTRIBUTE_ABSTRACT))
continue;
- if (method->klass->generic_container)
+ if (mono_class_is_gtd (method->klass))
continue;
sig = mono_method_signature (method);
if (!sig) {
{
char *runtime_path;
- runtime_path = wapi_process_get_path (getpid ());
+ runtime_path = mono_w32process_get_path (getpid ());
if (runtime_path) {
- wapi_process_set_cli_launcher (runtime_path);
+ mono_w32process_set_cli_launcher (runtime_path);
g_free (runtime_path);
}
}
if (gshared && method->is_inflated && mono_method_get_context (method)->method_inst) {
MonoGenericContext context = { NULL, NULL };
- if (res->klass->generic_class)
- context.class_inst = res->klass->generic_class->context.class_inst;
- else if (res->klass->generic_container)
- context.class_inst = res->klass->generic_container->context.class_inst;
+ if (mono_class_is_ginst (res->klass))
+ context.class_inst = mono_class_get_generic_class (res->klass)->context.class_inst;
+ else if (mono_class_is_gtd (res->klass))
+ context.class_inst = mono_class_get_generic_container (res->klass)->context.class_inst;
context.method_inst = mono_method_get_context (method)->method_inst;
res = mono_class_inflate_generic_method_checked (res, &context, &error);
return NULL;
}
vmethod = mono_object_get_virtual_method (obj, method);
- g_assert (!vmethod->klass->generic_container);
- g_assert (!vmethod->klass->generic_class || !vmethod->klass->generic_class->context.class_inst->is_open);
+ g_assert (!mono_class_is_gtd (vmethod->klass));
+ g_assert (!mono_class_is_ginst (vmethod->klass) || !mono_class_get_generic_class (vmethod->klass)->context.class_inst->is_open);
g_assert (!context->method_inst || !context->method_inst->is_open);
addr = mono_compile_method_checked (vmethod, &error);
mono_error_init (error);
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
MonoObject *this_obj;
/* Have to use the receiver's type instead of klass, the receiver is a ref type */
mono_class_setup_vtable (klass);
g_assert (klass->vtable);
vt_slot = mono_method_get_vtable_slot (cmethod);
- if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (cmethod->klass)) {
iface_offset = mono_class_interface_offset (klass, cmethod->klass);
g_assert (iface_offset != -1);
vt_slot += iface_offset;
else
declaring = m;
- if (m->klass->generic_class)
- context.class_inst = m->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (m->klass))
+ context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
else
- g_assert (!m->klass->generic_container);
+ g_assert (!mono_class_is_gtd (m->klass));
generic_virtual = imt_method;
g_assert (generic_virtual);
else
declaring = m;
- if (m->klass->generic_class)
- context.class_inst = m->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (m->klass))
+ context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
else
- g_assert (!m->klass->generic_container);
+ g_assert (!mono_class_is_gtd (m->klass));
g_assert (generic_virtual->is_inflated);
context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
mono_register_bundled_assemblies ((const MonoBundledAssembly **) assemblies->data);
new_argv = g_new (char *, (*ref_argc)+1);
- for (j = 0; j < *ref_argc; j++)
- new_argv [j] = (*ref_argv)[j];
- new_argv [j] = entry_point;
+ new_argv [0] = (*ref_argv)[0];
+ new_argv [1] = entry_point;
+ for (j = 1; j < *ref_argc; j++)
+ new_argv [j+1] = (*ref_argv)[j];
*ref_argv = new_argv;
(*ref_argc)++;
mini_emit_class_check (cfg, eclass_reg, mono_defaults.enum_class);
} else if (klass->cast_class == mono_defaults.enum_class) {
mini_emit_class_check (cfg, eclass_reg, mono_defaults.enum_class);
- } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ } else if (mono_class_is_interface (klass->cast_class)) {
mini_emit_iface_class_cast (cfg, eclass_reg, klass->cast_class, NULL, NULL);
} else {
// Pass -1 as obj_reg to skip the check below for arrays of arrays
gboolean pass_mrgctx = FALSE;
if (((cmethod->flags & METHOD_ATTRIBUTE_STATIC) || cmethod->klass->valuetype) &&
- (cmethod->klass->generic_class || cmethod->klass->generic_container)) {
+ (mono_class_is_ginst (cmethod->klass) || mono_class_is_gtd (cmethod->klass))) {
gboolean sharable = FALSE;
if (mono_method_is_generic_sharable_full (cmethod, TRUE, TRUE, TRUE))
if (!sig)
sig = mono_method_signature (method);
- if (cfg->llvm_only && (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE))
+ if (cfg->llvm_only && (mono_class_is_interface (method->klass)))
g_assert_not_reached ();
if (rgctx_arg) {
if (cfg->llvm_only && !call_target && virtual_ && (method->flags & METHOD_ATTRIBUTE_VIRTUAL))
return emit_llvmonly_virtual_call (cfg, method, sig, 0, args);
- need_unbox_trampoline = method->klass == mono_defaults.object_class || (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE);
+ need_unbox_trampoline = method->klass == mono_defaults.object_class || mono_class_is_interface (method->klass);
call = mono_emit_call_args (cfg, sig, args, FALSE, virtual_, tail, rgctx_arg ? TRUE : FALSE, need_unbox_trampoline);
} else {
vtable_reg = alloc_preg (cfg);
MONO_EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, vtable_reg, this_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
- if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (method->klass)) {
guint32 imt_slot = mono_method_get_imt_slot (method);
emit_imt_argument (cfg, call, call->method, imt_arg);
slot_reg = vtable_reg;
EMIT_NEW_CLASSCONST (cfg, iargs [1], klass);
alloc_ftn = ves_icall_object_new;
- } else if (cfg->compile_aot && cfg->cbb->out_of_line && klass->type_token && klass->image == mono_defaults.corlib && !klass->generic_class) {
+ } else if (cfg->compile_aot && cfg->cbb->out_of_line && klass->type_token && klass->image == mono_defaults.corlib && !mono_class_is_ginst (klass)) {
/* This happens often in argument checking code, eg. throw new FooException... */
/* Avoid relocations and save some space by calling a helper function specialized to mscorlib */
EMIT_NEW_ICONST (cfg, iargs [0], mono_metadata_token_index (klass->type_token));
MonoGenericContainer *container;
MonoGenericInst *ginst;
- if (klass->generic_class) {
- container = klass->generic_class->container_class->generic_container;
- ginst = klass->generic_class->context.class_inst;
- } else if (klass->generic_container && context_used) {
- container = klass->generic_container;
+ if (mono_class_is_ginst (klass)) {
+ container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
+ ginst = mono_class_get_generic_class (klass)->context.class_inst;
+ } else if (mono_class_is_gtd (klass) && context_used) {
+ container = mono_class_get_generic_container (klass);
ginst = container->context.class_inst;
} else {
return FALSE;
return FALSE;
}
-#define is_complex_isinst(klass) ((klass->flags & TYPE_ATTRIBUTE_INTERFACE) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
+#define is_complex_isinst(klass) (mono_class_is_interface (klass) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
static MonoInst*
emit_isinst_with_cache (MonoCompile *cfg, MonoClass *klass, MonoInst **args)
save_cast_details (cfg, klass, obj_reg, FALSE);
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
mini_emit_iface_cast (cfg, vtable_reg, klass, NULL, NULL);
} else {
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
- if (!klass->rank && !cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && (klass->flags & TYPE_ATTRIBUTE_SEALED)) {
+ if (!klass->rank && !cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_SEALED)) {
/* the remoting code is broken, access the class for now */
if (0) { /*FIXME what exactly is broken? This change refers to r39380 from 2005 and mention some remoting fixes were due.*/
MonoVTable *vt = mono_class_vtable (cfg->domain, klass);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
g_assert (!context_used);
/* the is_null_bb target simply copies the input register to the output */
mini_emit_iface_cast (cfg, vtable_reg, klass, false_bb, is_null_bb);
} else if (klass->cast_class == mono_defaults.enum_class) {
mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class, OP_PBEQ, is_null_bb);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, false_bb);
- } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ } else if (mono_class_is_interface (klass->cast_class)) {
mini_emit_iface_class_cast (cfg, eclass_reg, klass->cast_class, false_bb, is_null_bb);
} else {
if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY)) {
/* the is_null_bb target simply copies the input register to the output */
mini_emit_isninst_cast (cfg, klass_reg, klass->cast_class, false_bb, is_null_bb);
} else {
- if (!cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && (klass->flags & TYPE_ATTRIBUTE_SEALED)) {
+ if (!cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_SEALED)) {
g_assert (!context_used);
/* the remoting code is broken, access the class for now */
if (0) {/*FIXME what exactly is broken? This change refers to r39380 from 2005 and mention some remoting fixes were due.*/
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, false_bb);
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
#ifndef DISABLE_REMOTING
NEW_BBLOCK (cfg, interface_fail_bb);
#endif
save_cast_details (cfg, klass, obj_reg, FALSE);
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (klass)) {
#ifndef DISABLE_REMOTING
NEW_BBLOCK (cfg, interface_fail_bb);
* This is hard to do with the current call code, since we would have to emit a branch and two different calls. So instead, we
* pack the arguments into an array, and do the rest of the work in in an icall.
*/
- if (((cmethod->klass == mono_defaults.object_class) || (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) || (!cmethod->klass->valuetype && cmethod->klass->image != mono_defaults.corlib)) &&
+ if (((cmethod->klass == mono_defaults.object_class) || mono_class_is_interface (cmethod->klass) || (!cmethod->klass->valuetype && cmethod->klass->image != mono_defaults.corlib)) &&
(MONO_TYPE_IS_VOID (fsig->ret) || MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_IS_REFERENCE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mini_is_gsharedvt_type (fsig->ret)) &&
(fsig->param_count == 0 || (!fsig->hasthis && fsig->param_count == 1) || (fsig->param_count == 1 && (MONO_TYPE_IS_REFERENCE (fsig->params [0]) || fsig->params [0]->byref || mini_is_gsharedvt_type (fsig->params [0]))))) {
MonoInst *args [16];
return FALSE;
}
}
- } else if (method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
+ } else if (mono_class_get_flags (method->klass) & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
if (cfg->run_cctors && method->klass->has_cctor) {
/*FIXME it would easier and lazier to just use mono_class_try_get_vtable */
if (!method->klass->runtime_info)
* the cctor will need to be run at aot method load time, for example,
* or at the end of the compilation of the inlining method.
*/
- if (mono_class_needs_cctor_run (method->klass, NULL) && !((method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
+ if (mono_class_needs_cctor_run (method->klass, NULL) && !((mono_class_get_flags (method->klass) & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
return FALSE;
}
return FALSE;
}
- if (klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
+ if (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
if (cfg->method == method)
return FALSE;
}
MonoInst *icall_args [16];
MonoInst *call_target, *ins, *vtable_ins;
int arg_reg, this_reg, vtable_reg;
- gboolean is_iface = cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE;
+ gboolean is_iface = mono_class_is_interface (cmethod->klass);
gboolean is_gsharedvt = cfg->gsharedvt && mini_is_gsharedvt_variable_signature (fsig);
gboolean variant_iface = FALSE;
guint32 slot;
n = fsig->param_count + fsig->hasthis;
- if (!cfg->gshared && cmethod->klass->generic_container)
+ if (!cfg->gshared && mono_class_is_gtd (cmethod->klass))
UNVERIFIED;
if (!cfg->gshared)
if (mini_is_gsharedvt_klass (constrained_class)) {
if ((cmethod->klass != mono_defaults.object_class) && constrained_class->valuetype && cmethod->klass->valuetype) {
/* The 'Own method' case below */
- } else if (cmethod->klass->image != mono_defaults.corlib && !(cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) && !cmethod->klass->valuetype) {
+ } else if (cmethod->klass->image != mono_defaults.corlib && !mono_class_is_interface (cmethod->klass) && !cmethod->klass->valuetype) {
/* 'The type parameter is instantiated as a reference type' case below. */
} else {
ins = handle_constrained_gsharedvt_call (cfg, cmethod, fsig, sp, constrained_class, &emit_widen);
* A simple solution would be to box always and make a normal virtual call, but that would
* be bad performance wise.
*/
- if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE && cmethod->klass->generic_class) {
+ if (mono_class_is_interface (cmethod->klass) && mono_class_is_ginst (cmethod->klass)) {
/*
* The parent classes implement no generic interfaces, so the called method will be a vtype method, so no boxing neccessary.
*/
nonbox_call->dreg = ins->dreg;
goto call_end;
} else {
- g_assert (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE);
+ g_assert (mono_class_is_interface (cmethod->klass));
addr = emit_get_rgctx_virt_method (cfg, mono_class_check_context_used (constrained_class), constrained_class, cmethod, MONO_RGCTX_INFO_VIRT_METHOD_CODE);
ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, NULL);
goto call_end;
* If the callee is a shared method, then its static cctor
* might not get called after the call was patched.
*/
- if (cfg->gshared && cmethod->klass != method->klass && cmethod->klass->generic_class && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
+ if (cfg->gshared && cmethod->klass != method->klass && mono_class_is_ginst (cmethod->klass) && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
emit_class_init (cfg, cmethod->klass);
CHECK_TYPELOAD (cmethod->klass);
}
context_used = mini_method_check_context_used (cfg, cmethod);
- if (context_used && (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ if (context_used && mono_class_is_interface (cmethod->klass)) {
/* Generic method interface
calls are resolved via a
helper function and don't
* This needs to be used for all generic calls, not just ones with a gsharedvt signature, to avoid
* patching gshared method addresses into a gsharedvt method.
*/
- if (cfg->gsharedvt && (mini_is_gsharedvt_signature (fsig) || cmethod->is_inflated || cmethod->klass->generic_class) &&
+ if (cfg->gsharedvt && (mini_is_gsharedvt_signature (fsig) || cmethod->is_inflated || mono_class_is_ginst (cmethod->klass)) &&
!(cmethod->klass->rank && cmethod->klass->byval_arg.type != MONO_TYPE_SZARRAY) &&
(!(cfg->llvm_only && virtual_ && (cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL)))) {
MonoRgctxInfoType info_type;
if (virtual_) {
- //if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
+ //if (mono_class_is_interface (cmethod->klass))
//GSHAREDVT_FAILURE (*ip);
// disable for possible remoting calls
if (fsig->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class))
cmethod, MONO_RGCTX_INFO_METHOD);
/* This is not needed, as the trampoline code will pass one, and it might be passed in the same reg as the imt arg */
vtable_arg = NULL;
- } else if ((cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) && !imt_arg) {
+ } else if (mono_class_is_interface (cmethod->klass) && !imt_arg) {
/* This can happen when we call a fully instantiated iface method */
imt_arg = emit_get_rgctx_method (cfg, context_used,
cmethod, MONO_RGCTX_INFO_METHOD);
if (mono_security_core_clr_enabled ())
ensure_method_is_allowed_to_call_method (cfg, method, cmethod);
- if (cfg->gshared && cmethod && cmethod->klass != method->klass && cmethod->klass->generic_class && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
+ if (cfg->gshared && cmethod && cmethod->klass != method->klass && mono_class_is_ginst (cmethod->klass) && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
emit_class_init (cfg, cmethod->klass);
CHECK_TYPELOAD (cmethod->klass);
}
ret = emit_isinst_with_cache_nonshared (cfg, source, klass);
else
ret = emit_castclass_with_cache_nonshared (cfg, source, klass);
- } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ } else if (!context_used && (mono_class_is_marshalbyref (klass) || mono_class_is_interface (klass))) {
MonoInst *iargs [1];
int costs;
klass = vtable->klass;
}
- //g_assert (!method->klass->generic_container);
- if (method->klass->generic_class)
- method_container_class = method->klass->generic_class->container_class;
+ //g_assert (!mono_class_is_gtd (method->klass));
+ if (mono_class_is_ginst (method->klass))
+ method_container_class = mono_class_get_generic_class (method->klass)->container_class;
else
method_container_class = method->klass;
/* class might refer to a subclass of method's class */
- while (!(klass == method->klass || (klass->generic_class && klass->generic_class->container_class == method_container_class))) {
+ while (!(klass == method->klass || (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->container_class == method_container_class))) {
klass = klass->parent;
g_assert (klass);
}
- if (klass->generic_class || klass->generic_container)
+ if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass))
context.class_inst = mini_class_get_context (klass)->class_inst;
- if (klass->generic_class)
- g_assert (mono_class_has_parent_and_ignore_generics (klass->generic_class->container_class, method_container_class));
+ if (mono_class_is_ginst (klass))
+ g_assert (mono_class_has_parent_and_ignore_generics (mono_class_get_generic_class (klass)->container_class, method_container_class));
else
g_assert (mono_class_has_parent_and_ignore_generics (klass, method_container_class));
if (recursive) {
MonoGenericClass *gclass = type->data.generic_class;
- g_assert (gclass->container_class->generic_container);
+ g_assert (mono_class_is_gtd (gclass->container_class));
return mono_generic_context_check_used (&gclass->context);
} else {
return 0;
context_used |= type_check_context_used (&klass->this_arg, FALSE);
context_used |= type_check_context_used (&klass->byval_arg, FALSE);
- if (klass->generic_class)
- context_used |= mono_generic_context_check_used (&klass->generic_class->context);
- else if (klass->generic_container)
- context_used |= mono_generic_context_check_used (&klass->generic_container->context);
+ if (mono_class_is_ginst (klass))
+ context_used |= mono_generic_context_check_used (&mono_class_get_generic_class (klass)->context);
+ else if (mono_class_is_gtd (klass))
+ context_used |= mono_generic_context_check_used (&mono_class_get_generic_container (klass)->context);
return context_used;
}
g_assert (rgctx_template);
- if (parent->generic_class)
- parent = parent->generic_class->container_class;
+ if (mono_class_is_ginst (parent))
+ parent = mono_class_get_generic_class (parent)->container_class;
if (!generic_subclass_hash)
generic_subclass_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
declaring = method;
m = NULL;
- if (klass->generic_class)
+ if (mono_class_is_ginst (klass))
m = mono_class_get_inflated_method (klass, declaring);
if (!m) {
static MonoClass*
class_uninstantiated (MonoClass *klass)
{
- if (klass->generic_class)
- return klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass))
+ return mono_class_get_generic_class (klass)->container_class;
return klass;
}
DEBUG (printf ("get slot: %s %d\n", mono_type_full_name (&class->byval_arg), slot));
- if (klass->generic_class && !shared) {
+ if (mono_class_is_ginst (klass) && !shared) {
MonoRuntimeGenericContextInfoTemplate oti;
gboolean tmp_do_free;
- oti = class_get_rgctx_template_oti (klass->generic_class->container_class,
+ oti = class_get_rgctx_template_oti (mono_class_get_generic_class (klass)->container_class,
type_argc, slot, TRUE, FALSE, &tmp_do_free);
if (oti.data) {
gpointer info = oti.data;
- oti.data = inflate_info (&oti, &klass->generic_class->context, klass, temporary);
+ oti.data = inflate_info (&oti, &mono_class_get_generic_class (klass)->context, klass, temporary);
if (tmp_do_free)
free_inflated_info (oti.info_type, info);
}
return get_wrapper_shared_type (&mono_defaults.object_class->byval_arg);
klass = mono_class_from_mono_type (t);
- orig_ctx = &klass->generic_class->context;
+ orig_ctx = &mono_class_get_generic_class (klass)->context;
memset (&ctx, 0, sizeof (MonoGenericContext));
args [i] = get_wrapper_shared_type (inst->type_argv [i]);
ctx.method_inst = mono_metadata_get_generic_inst (inst->type_argc, args);
}
- klass = mono_class_inflate_generic_class_checked (klass->generic_class->container_class, &ctx, &error);
+ klass = mono_class_inflate_generic_class_checked (mono_class_get_generic_class (klass)->container_class, &ctx, &error);
mono_error_assert_ok (&error); /* FIXME don't swallow the error */
return &klass->byval_arg;
}
MonoMethod *res, *cached;
WrapperInfo *info;
MonoMethodSignature *csig, *gsharedvt_sig;
- int i, pindex, retval_var;
+ int i, pindex, retval_var = 0;
static GHashTable *cache;
// FIXME: Memory management
mono_class_setup_vtable (info->klass);
// FIXME: Check type load
- if (iface_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (iface_class)) {
ioffset = mono_class_interface_offset (info->klass, iface_class);
g_assert (ioffset != -1);
} else {
mono_class_setup_vtable (info->klass);
// FIXME: Check type load
- if (iface_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_is_interface (iface_class)) {
ioffset = mono_class_interface_offset (info->klass, iface_class);
g_assert (ioffset != -1);
} else {
/* See mono_emit_method_call_full () */
/* The gsharedvt trampoline will recognize this constant */
vcall_offset = MONO_GSHAREDVT_DEL_INVOKE_VT_OFFSET;
- } else if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ } else if (mono_class_is_interface (method->klass)) {
guint32 imt_slot = mono_method_get_imt_slot (method);
vcall_offset = ((gint32)imt_slot - MONO_IMT_SIZE) * SIZEOF_VOID_P;
} else {
MonoRuntimeGenericContextTemplate *parent_template;
MonoRuntimeGenericContextInfoTemplate *oti;
- if (parent->generic_class)
- parent = parent->generic_class->container_class;
+ if (mono_class_is_ginst (parent))
+ parent = mono_class_get_generic_class (parent)->container_class;
parent_template = mono_class_get_runtime_generic_context_template (parent);
oti = rgctx_template_get_other_slot (parent_template, type_argc, i);
int i, first_slot, size;
MonoDomain *domain = class_vtable->domain;
MonoClass *klass = class_vtable->klass;
- MonoGenericContext *class_context = klass->generic_class ? &klass->generic_class->context : NULL;
+ MonoGenericContext *class_context = mono_class_is_ginst (klass) ? &mono_class_get_generic_class (klass)->context : NULL;
MonoRuntimeGenericContextInfoTemplate oti;
MonoGenericContext context = { class_context ? class_context->class_inst : NULL, method_inst };
int rgctx_index;
MonoMethodRuntimeGenericContext *mrgctx;
MonoMethodRuntimeGenericContext key;
- g_assert (!class_vtable->klass->generic_container);
+ g_assert (!mono_class_is_gtd (class_vtable->klass));
g_assert (!method_inst->is_open);
mono_domain_lock (domain);
if not compiled with sharing. */
if (method->wrapper_type != MONO_WRAPPER_NONE)
return FALSE;
- if (method->klass->generic_container)
+ if (mono_class_is_gtd (method->klass))
return TRUE;
return FALSE;
}
}
}
- if (method->klass->generic_class) {
- if (!mono_generic_context_is_sharable_full (&method->klass->generic_class->context, allow_type_vars, allow_partial))
+ if (mono_class_is_ginst (method->klass)) {
+ if (!mono_generic_context_is_sharable_full (&mono_class_get_generic_class (method->klass)->context, allow_type_vars, allow_partial))
return FALSE;
- g_assert (method->klass->generic_class->container_class &&
- method->klass->generic_class->container_class->generic_container);
+ g_assert (mono_class_get_generic_class (method->klass)->container_class &&
+ mono_class_is_gtd (mono_class_get_generic_class (method->klass)->container_class));
- if (has_constraints (method->klass->generic_class->container_class->generic_container))
+ if (has_constraints (mono_class_get_generic_container (mono_class_get_generic_class (method->klass)->container_class)))
return FALSE;
}
- if (method->klass->generic_container && !allow_type_vars)
+ if (mono_class_is_gtd (method->klass) && !allow_type_vars)
return FALSE;
/* This does potentially expensive cattr checks, so do it at the end */
return ((method->flags & METHOD_ATTRIBUTE_STATIC) ||
method->klass->valuetype) &&
- (method->klass->generic_class || method->klass->generic_container);
+ (mono_class_is_ginst (method->klass) || mono_class_is_gtd (method->klass));
}
static MonoGenericInst*
{
MonoGenericContext object_context;
- g_assert (!method->klass->generic_class);
- if (method->klass->generic_container) {
- int type_argc = method->klass->generic_container->type_argc;
+ g_assert (!mono_class_is_ginst (method->klass));
+ if (mono_class_is_gtd (method->klass)) {
+ int type_argc = mono_class_get_generic_container (method->klass)->type_argc;
object_context.class_inst = get_object_generic_inst (type_argc);
} else {
MonoClass*
mini_class_get_container_class (MonoClass *klass)
{
- if (klass->generic_class)
- return klass->generic_class->container_class;
+ if (mono_class_is_ginst (klass))
+ return mono_class_get_generic_class (klass)->container_class;
- g_assert (klass->generic_container);
+ g_assert (mono_class_is_gtd (klass));
return klass;
}
MonoGenericContext*
mini_class_get_context (MonoClass *klass)
{
- if (klass->generic_class)
- return &klass->generic_class->context;
+ if (mono_class_is_ginst (klass))
+ return &mono_class_get_generic_class (klass)->context;
- g_assert (klass->generic_container);
- return &klass->generic_container->context;
+ g_assert (mono_class_is_gtd (klass));
+ return &mono_class_get_generic_container (klass)->context;
}
/*
gboolean
mini_class_is_generic_sharable (MonoClass *klass)
{
- if (klass->generic_class && is_async_state_machine_class (klass))
+ if (mono_class_is_ginst (klass) && is_async_state_machine_class (klass))
return FALSE;
- return (klass->generic_class && mono_generic_context_is_sharable (&klass->generic_class->context, FALSE));
+ return (mono_class_is_ginst (klass) && mono_generic_context_is_sharable (&mono_class_get_generic_class (klass)->context, FALSE));
}
gboolean
memset (&context, 0, sizeof (context));
if (gclass->context.class_inst)
- context.class_inst = get_shared_inst (gclass->context.class_inst, gclass->container_class->generic_container->context.class_inst, NULL, FALSE, FALSE, TRUE);
+ context.class_inst = get_shared_inst (gclass->context.class_inst, mono_class_get_generic_container (gclass->container_class)->context.class_inst, NULL, FALSE, FALSE, TRUE);
if (gclass->context.method_inst)
- context.method_inst = get_shared_inst (gclass->context.method_inst, gclass->container_class->generic_container->context.method_inst, NULL, FALSE, FALSE, TRUE);
+ context.method_inst = get_shared_inst (gclass->context.method_inst, mono_class_get_generic_container (gclass->container_class)->context.method_inst, NULL, FALSE, FALSE, TRUE);
k = mono_class_inflate_generic_class_checked (gclass->container_class, &context, &error);
mono_error_assert_ok (&error); /* FIXME don't swallow the error */
}
}
- if (method->is_generic || (method->klass->generic_container && !method->is_inflated)) {
+ if (method->is_generic || (mono_class_is_gtd (method->klass) && !method->is_inflated)) {
declaring_method = method;
} else {
declaring_method = mono_method_get_declaring_generic_method (method);
if (declaring_method->is_generic)
shared_context = mono_method_get_generic_container (declaring_method)->context;
else
- shared_context = declaring_method->klass->generic_container->context;
+ shared_context = mono_class_get_generic_container (declaring_method->klass)->context;
if (!is_gsharedvt)
partial = mono_method_is_generic_sharable_full (method, FALSE, TRUE, FALSE);
gsharedvt = is_gsharedvt || (!partial && mini_is_gsharedvt_sharable_method (method));
- class_container = declaring_method->klass->generic_container;
+ class_container = mono_class_try_get_generic_container (declaring_method->klass); //FIXME is this a case for a try_get?
method_container = mono_method_get_generic_container (declaring_method);
/*
}
g_assert (vtable);
- if (!vtable->initialized && !(vtable->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) && (method && mono_class_needs_cctor_run (vtable->klass, method)))
+ if (!vtable->initialized && !(mono_class_get_flags (vtable->klass) & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) && (method && mono_class_needs_cctor_run (vtable->klass, method)))
/* Done by the generated code */
;
else {
return NULL;
is_virtual_generic = method->is_inflated && mono_method_get_declaring_generic_method (method)->is_generic;
- is_interface = method->klass->flags & TYPE_ATTRIBUTE_INTERFACE ? TRUE : FALSE;
+ is_interface = mono_class_is_interface (method->klass);
load_imt_reg = is_virtual_generic || is_interface;
if (is_interface)
}
if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
continue;
- if (method->is_generic || method->klass->generic_container)
+ if (method->is_generic || mono_class_is_gtd (method->klass))
continue;
count++;
ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
printf (" ip: %p\n", (gpointer) ip);
+ va_end (ap);
}
/*========================= End of Function ========================*/
/* imt_method->slot might not be set */
impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_declaring_generic_method (imt_method)->slot);
- if (impl->klass->generic_class)
- context.class_inst = impl->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (impl->klass))
+ context.class_inst = mono_class_get_generic_class (impl->klass)->context.class_inst;
context.method_inst = ((MonoMethodInflated*)imt_method)->context.method_inst;
impl = mono_class_inflate_generic_method_checked (impl, &context, error);
mono_error_assert_ok (error);
else
declaring = m;
- if (m->klass->generic_class)
- context.class_inst = m->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (m->klass))
+ context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
else
- g_assert (!m->klass->generic_container);
+ g_assert (!mono_class_is_gtd (m->klass));
generic_virtual = mono_arch_find_imt_method (regs, code);
g_assert (generic_virtual);
else
declaring = m;
- if (klass->generic_class)
- context.class_inst = klass->generic_class->context.class_inst;
- else if (klass->generic_container)
- context.class_inst = klass->generic_container->context.class_inst;
+ if (mono_class_is_ginst (klass))
+ context.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
+ else if (mono_class_is_gtd (klass))
+ context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
context.method_inst = method_inst;
actual_method = mono_class_inflate_generic_method_checked (declaring, &context, error);
gpointer *vtable_slot;
MonoMethod *m;
MonoError error;
- gpointer addr, res;
+ gpointer addr, res = NULL;
trampoline_calls ++;
else
declaring = m;
- if (m->klass->generic_class)
- context.class_inst = m->klass->generic_class->context.class_inst;
+ if (mono_class_is_ginst (m->klass))
+ context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
else
- g_assert (!m->klass->generic_container);
+ g_assert (!mono_class_is_gtd (m->klass));
imt_method = mono_arch_find_imt_method (regs, code);
if (imt_method->is_inflated)
* If the call doesn't return a valuetype, then the vcall uses the same calling
* convention as a normal call.
*/
- if (((method->klass->flags & TYPE_ATTRIBUTE_SEALED) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) && !MONO_TYPE_ISSTRUCT (sig->ret)) {
+ if (((mono_class_get_flags (method->klass) & TYPE_ATTRIBUTE_SEALED) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) && !MONO_TYPE_ISSTRUCT (sig->ret)) {
callvirt = FALSE;
enable_caching = FALSE;
}
if (delegate->target &&
method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
method->flags & METHOD_ATTRIBUTE_ABSTRACT &&
- method->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) {
+ mono_class_is_abstract (method->klass)) {
method = mono_object_get_virtual_method (delegate->target, method);
enable_caching = FALSE;
}
gboolean is_generic = FALSE;
if (cfg->method->is_inflated || mono_method_get_generic_container (cfg->method) ||
- cfg->method->klass->generic_container || cfg->method->klass->generic_class) {
+ mono_class_is_gtd (cfg->method->klass) || mono_class_is_ginst (cfg->method->klass)) {
is_generic = TRUE;
}
cfg->seq_points = g_ptr_array_new ();
mono_error_init (&cfg->error);
- if (cfg->compile_aot && !try_generic_shared && (method->is_generic || method->klass->generic_container || method_is_gshared)) {
+ if (cfg->compile_aot && !try_generic_shared && (method->is_generic || mono_class_is_gtd (method->klass) || method_is_gshared)) {
cfg->exception_type = MONO_EXCEPTION_GENERIC_SHARING_FAILED;
return cfg;
}
#define MONO_INS_IS_PCONST_NULL(ins) ((ins)->opcode == OP_PCONST && (ins)->inst_p0 == 0)
-#define MONO_METHOD_IS_FINAL(m) (((m)->flags & METHOD_ATTRIBUTE_FINAL) || ((m)->klass && ((m)->klass->flags & TYPE_ATTRIBUTE_SEALED)))
+#define MONO_METHOD_IS_FINAL(m) (((m)->flags & METHOD_ATTRIBUTE_FINAL) || ((m)->klass && (mono_class_get_flags ((m)->klass) & TYPE_ATTRIBUTE_SEALED)))
#ifdef MONO_ARCH_SIMD_INTRINSICS
switch (op->op){
case MONO_TRACEOP_ALL:
- inc = 1; break;
+ inc = 1;
+ break;
case MONO_TRACEOP_PROGRAM:
if (trace_spec.assembly && (method->klass->image == mono_assembly_get_image (trace_spec.assembly)))
- inc = 1; break;
+ inc = 1;
+ break;
case MONO_TRACEOP_WRAPPER:
if ((method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) ||
(method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE))
- inc = 1; break;
+ inc = 1;
+ break;
case MONO_TRACEOP_METHOD:
if (mono_method_desc_full_match ((MonoMethodDesc *) op->data, method))
- inc = 1; break;
+ inc = 1;
+ break;
case MONO_TRACEOP_CLASS:
if (strcmp (method->klass->name_space, op->data) == 0)
if (strcmp (method->klass->name, op->data2) == 0)
break;
case MONO_TRACEOP_ASSEMBLY:
if (strcmp (mono_image_get_name (method->klass->image), op->data) == 0)
- inc = 1; break;
+ inc = 1;
+ break;
case MONO_TRACEOP_NAMESPACE:
if (strcmp (method->klass->name_space, op->data) == 0)
inc = 1;
+ break;
case MONO_TRACEOP_EXCEPTION:
break;
}
- if (op->exclude){
+ if (op->exclude) {
if (inc)
include = 0;
- } else if (inc)
+ } else if (inc) {
include = 1;
+ }
}
return include;
}
return GPOINTER_TO_UINT (ptr) >> 3;
}
-#define SGEN_PTR_IN_NURSERY(p,bits,start,end) (((mword)(p) & ~((1 << (bits)) - 1)) == (mword)(start))
+#define SGEN_PTR_IN_NURSERY(p,bits,start,end) (((mword)(p) & ~(((mword)1 << (bits)) - 1)) == (mword)(start))
#ifdef USER_CONFIG
}
void
-mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context)
+mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context)
{
arm_thread_state_t *arch_state = (arm_thread_state_t *) state;
struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context;
}
void
-mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state)
+mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate)
{
arm_thread_state_t *arch_state = (arm_thread_state_t *) state;
struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context;
}
void
-mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context)
{
int i;
arm_thread_state_t *arch_state = (arm_thread_state_t *) state;
return sizeof (arm_thread_state_t);
}
+int
+mono_mach_arch_get_thread_fpstate_size ()
+{
+ g_assert_not_reached ();
+}
+
kern_return_t
-mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count)
+mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount)
{
#if defined(HOST_WATCHOS)
g_error ("thread_get_state() is not supported by this platform");
}
kern_return_t
-mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count)
+mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount)
{
#if defined(HOST_WATCHOS)
g_error ("thread_set_state() is not supported by this platform");
}
void
-mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context)
+mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context)
{
arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context;
}
void
-mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state)
+mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate)
{
arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context;
}
void
-mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context)
{
int i;
arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
return sizeof (arm_unified_thread_state_t);
}
+int
+mono_mach_arch_get_thread_fpstate_size ()
+{
+ g_assert_not_reached ();
+}
+
kern_return_t
-mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count)
+mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount)
{
arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
kern_return_t ret;
}
kern_return_t
-mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count)
+mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount)
{
return thread_set_state (thread, ARM_UNIFIED_THREAD_STATE, state, count);
}
}
void
-mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context)
+mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context)
{
g_assert_not_reached ();
}
void
-mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state)
+mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate)
{
g_assert_not_reached ();
}
void
-mono_mach_arch_thread_state_to_mono_context (thread_state_t state, MonoContext *context)
+mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context)
{
g_assert_not_reached ();
}
g_assert_not_reached ();
}
+int
+mono_mach_arch_get_thread_fpstate_size ()
+{
+ g_assert_not_reached ();
+}
+
kern_return_t
-mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count)
+mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount)
{
g_assert_not_reached ();
}
kern_return_t
-mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count)
+mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount)
{
g_assert_not_reached ();
}
thread_port_t self = mach_thread_self (); \
kern_return_t ret = thread_get_state (self, state_flavor, (thread_state_t) &thread_state, &state_count); \
g_assert (ret == 0); \
- mono_mach_arch_thread_state_to_mono_context ((thread_state_t)&thread_state, &ctx); \
+ mono_mach_arch_thread_states_to_mono_context ((thread_state_t)&thread_state, (thread_state_t)NULL, &ctx); \
mach_port_deallocate (current_task (), self); \
} while (0);
<ClCompile Include="..\mono\metadata\icall-windows.c" />\r
<ClCompile Include="..\mono\metadata\marshal-windows.c" />\r
<ClCompile Include="..\mono\metadata\mono-security-windows.c" />\r
- <ClCompile Include="..\mono\metadata\process-windows.c" />\r
<ClCompile Include="..\mono\metadata\w32mutex-win32.c" />\r
<ClCompile Include="..\mono\metadata\w32semaphore-win32.c" />\r
<ClCompile Include="..\mono\metadata\w32event-win32.c" />\r
+ <ClCompile Include="..\mono\metadata\w32process.c" />\r
+ <ClCompile Include="..\mono\metadata\w32process-win32.c" />\r
<ClCompile Include="..\mono\metadata\coree.c" />\r
<ClCompile Include="..\mono\metadata\custom-attrs.c" />\r
<ClCompile Include="..\mono\metadata\debug-helpers.c" />\r
<ClCompile Include="..\mono\metadata\number-ms.c" />\r
<ClCompile Include="..\mono\metadata\object.c" />\r
<ClCompile Include="..\mono\metadata\opcodes.c" />\r
- <ClCompile Include="..\mono\metadata\process.c" />\r
<ClCompile Include="..\mono\metadata\profiler.c" />\r
<ClCompile Include="..\mono\metadata\rand.c" />\r
<ClCompile Include="..\mono\metadata\reflection.c" />\r
<ClInclude Include="..\mono\metadata\marshal-windows-internals.h" />\r
<ClInclude Include="..\mono\metadata\mono-security-windows-internals.h" />\r
<ClInclude Include="..\mono\metadata\number-ms.h" />\r
- <ClInclude Include="..\mono\metadata\process-internals.h" />\r
- <ClInclude Include="..\mono\metadata\process-windows-internals.h" />\r
+ <ClInclude Include="..\mono\metadata\w32process.h" />\r
+ <ClInclude Include="..\mono\metadata\w32process-internals.h" />\r
+ <ClInclude Include="..\mono\metadata\w32process-win32-internals.h" />\r
<ClInclude Include="..\mono\metadata\remoting.h" />\r
<ClInclude Include="..\mono\metadata\seq-points-data.h" />\r
<ClInclude Include="..\mono\metadata\sgen-bridge-internals.h" />\r
<ClInclude Include="..\mono\metadata\object-internals.h" />\r
<ClInclude Include="..\mono\metadata\object.h" />\r
<ClInclude Include="..\mono\metadata\opcodes.h" />\r
- <ClInclude Include="..\mono\metadata\process.h" />\r
<ClInclude Include="..\mono\metadata\profiler-private.h" />\r
<ClInclude Include="..\mono\metadata\profiler.h" />\r
<ClInclude Include="..\mono\metadata\rand.h" />\r
<ClCompile Include="..\mono\metadata\opcodes.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\process.c">\r
+ <ClCompile Include="..\mono\metadata\w32process.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\w32process-win32.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
<ClCompile Include="..\mono\metadata\profiler.c">\r
<ClCompile Include="..\mono\metadata\mono-security-windows.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\process-windows.c">\r
- <Filter>Source Files</Filter>\r
- </ClCompile>\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="..\mono\metadata\appdomain.h">\r
<ClInclude Include="..\mono\metadata\opcodes.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\mono\metadata\process.h">\r
+ <ClInclude Include="..\mono\metadata\w32process.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\mono\metadata\w32process-internals.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\mono\metadata\w32process-win32-internals.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
<ClInclude Include="..\mono\metadata\profiler.h">\r
<ClInclude Include="..\mono\metadata\mono-security-windows-internals.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\mono\metadata\process-windows-internals.h">\r
- <Filter>Header Files</Filter>\r
- </ClInclude>\r
- <ClInclude Include="..\mono\metadata\process-internals.h">\r
- <Filter>Header Files</Filter>\r
- </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<Filter Include="Header Files">\r
<ClCompile Include="..\mono\metadata\metadata.c" />\r
<ClCompile Include="..\mono\metadata\monitor.c" />\r
<ClCompile Include="..\mono\metadata\mono-config.c" />\r
- <ClCompile Include="..\mono\metadata\process-windows.c" />\r
<ClCompile Include="..\mono\utils\mono-dl.c" />\r
<ClCompile Include="..\mono\metadata\object.c" />\r
- <ClCompile Include="..\mono\metadata\process.c" />\r
+ <ClCompile Include="..\mono\metadata\w32process.c" />\r
+ <ClCompile Include="..\mono\metadata\w32process-win32.c" />\r
<ClCompile Include="..\mono\metadata\profiler.c" />\r
<ClCompile Include="..\mono\metadata\rand.c" />\r
<ClCompile Include="..\mono\metadata\reflection.c" />\r
<ClCompile Include="..\mono\metadata\object.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\process.c">\r
+ <ClCompile Include="..\mono\metadata\w32process.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\w32process-win32.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
<ClCompile Include="..\mono\metadata\profiler.c">\r
<ClCompile Include="..\tools\pedump\pedump.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\process-windows.c">\r
- <Filter>Source Files</Filter>\r
- </ClCompile>\r
<ClCompile Include="..\mono\metadata\marshal-windows.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
if (i == MONO_CEE_CASTCLASS || i == MONO_CEE_ISINST) {
guint32 token = read32 (ip + 1);
MonoClass *k = mono_class_get (method->klass->image, token);
- if (k && k->flags & TYPE_ATTRIBUTE_SEALED)
+ if (k && mono_class_get_flags (k) & TYPE_ATTRIBUTE_SEALED)
cast_sealed++;
- if (k && k->flags & TYPE_ATTRIBUTE_INTERFACE)
+ if (k && mono_class_get_flags (k) & TYPE_ATTRIBUTE_INTERFACE)
cast_iface++;
total_cast++;
}
MonoMethod *cm = mono_get_method (method->klass->image, read32 (ip + 1), NULL);
if (cm && !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
nonvirt_callvirt++;
- if (cm && (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE))
+ if (cm && (mono_class_get_flags (cm->klass) & TYPE_ATTRIBUTE_INTERFACE))
iface_callvirt++;
total_callvirt++;
}
MonoClass *parent;
int depth = 1;
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_INTERFACE) {
num_ifaces++;
return;
}