Merge pull request #2768 from lambdageek/dev/monoerror-cominterop
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Thu, 24 Mar 2016 15:19:42 +0000 (11:19 -0400)
committerAleksey Kliger (λgeek) <akliger@gmail.com>
Thu, 24 Mar 2016 15:19:42 +0000 (11:19 -0400)
[com] MonoError-ize cominterop.c

93 files changed:
README.md
acceptance-tests/SUBMODULES.json
acceptance-tests/ms-test-suite.mk
acceptance-tests/roslyn.mk
configure.ac
external/referencesource
man/mono.1
mcs/build/Makefile
mcs/build/common/AssemblyRef.cs [new file with mode: 0644]
mcs/build/common/SR.cs
mcs/class/Makefile
mcs/class/Microsoft.Build/Microsoft.Build.Execution/BuildManager.cs
mcs/class/Microsoft.Build/Microsoft.Build.Execution/ProjectInstance.cs
mcs/class/Microsoft.Build/Microsoft.Build.Internal/BuildNodeManager.cs
mcs/class/Mono.Security/Makefile
mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsProvider.cs
mcs/class/SMDiagnostics/Assembly/AssemblyInfo.cs
mcs/class/System.Data.Entity/System.Data.Entity.dll.sources
mcs/class/System.Data/mobile_System.Data.dll.sources
mcs/class/System.Data/net_4_x_System.Data.dll.sources
mcs/class/System.IO.Compression.FileSystem/Makefile
mcs/class/System.IO.Compression/Makefile
mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs
mcs/class/System.Runtime.Remoting/Makefile
mcs/class/System.Runtime.Remoting/xammac_net_4_5_System.Runtime.Remoting.dll.sources [new file with mode: 0644]
mcs/class/System.ServiceModel.Internals/System.ServiceModel.Internals.dll.sources
mcs/class/System.ServiceModel.Internals/mobile_System.ServiceModel.Internals.dll.sources
mcs/class/System.XML/Assembly/AssemblyInfo.cs
mcs/class/System.XML/System.Xml.dll.sources
mcs/class/System.XML/mobile_System.Xml.dll.sources
mcs/class/System/Mono.Net.Security/ChainValidationHelper.cs
mcs/class/System/Mono.Net.Security/SystemCertificateValidator.cs
mcs/class/System/System.Diagnostics/Process.cs
mcs/class/System/System.Net/HttpListenerRequest.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X500DistinguishedName.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs [new file with mode: 0644]
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs [new file with mode: 0644]
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Chain.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImpl.cs [new file with mode: 0644]
mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs [new file with mode: 0644]
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs [new file with mode: 0644]
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Store.cs
mcs/class/System/System.dll.sources
mcs/class/System/Test/System.Net/HttpListener2Test.cs
mcs/class/System/Test/System.Net/HttpListenerRequestTest.cs
mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X509Certificate2Test.cs
mcs/class/System/mobile_System.dll.sources
mcs/class/corlib/Assembly/AssemblyInfo.cs
mcs/class/corlib/System.IO/FileInfo.cs
mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Certificate.cs
mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509CertificateImpl.cs
mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509CertificateImplMono.cs
mcs/class/corlib/Test/System.IO/FileInfoTest.cs
mcs/class/corlib/corlib.dll.sources
mcs/mcs/constant.cs
mcs/tests/test-nameof-05.cs
mcs/tests/ver-il-net_4_x.xml
mcs/tools/cil-stringreplacer/Makefile
mcs/tools/cil-stringreplacer/cil-stringreplacer.cs
mcs/tools/cil-stringreplacer/cil-stringreplacer.csproj [new file with mode: 0644]
mcs/tools/cil-stringreplacer/cil-stringreplacer.exe.sources
mcs/tools/compiler-tester/compiler-tester.cs
mcs/tools/corcompare/Makefile
mcs/tools/gacutil/driver.cs
mono/metadata/class.c
mono/metadata/domain.c
mono/metadata/handle.h
mono/metadata/icall-def.h
mono/metadata/icall.c
mono/metadata/image.c
mono/metadata/marshal.c
mono/metadata/object-internals.h
mono/metadata/reflection-internals.h
mono/metadata/reflection.c
mono/metadata/reflection.h
mono/metadata/sgen-bridge.c
mono/mini/Makefile.am.in
mono/mini/aot-runtime.c
mono/mini/gshared.cs
mono/mini/method-to-ir.c
mono/mini/mini-arm.c
mono/mini/mini-llvm.c
mono/mini/mini-runtime.c
mono/tests/libtest.c
mono/tests/pinvoke3.cs
mono/utils/checked-build.c
mono/utils/checked-build.h
mono/utils/mono-threads-coop.c
mono/utils/mono-threads-state-machine.c
runtime/Makefile.am
scripts/.gitignore
scripts/Makefile.am

index 7a7f3639f28ccefebc994e5d5f03cb0ae41f2ce1..d3ff65bda20411879d323a6aa9e14d4c38efbcfa 100644 (file)
--- a/README.md
+++ b/README.md
@@ -104,6 +104,8 @@ See the man pages for mono(1), mcs(1) and monodis(1) for further details.
 Directory Roadmap
 =================
 
+* `acceptance-tests/` - Optional third party test suites used to validate Mono against a wider range of test cases.
+
 * `data/` - Configuration files installed as part of the Mono runtime.
 
 * `docs/` - Technical documents about the Mono runtime.
index 9bb324948f7574a942bc284d9c46aeecfc593445..7a9de16bc374515f3f926267bfcfc27645a232cd 100644 (file)
@@ -18,7 +18,7 @@
   {
     "name": "ms-test-suite", 
     "url": "git@github.com:xamarin/ms-test-suite.git", 
-    "rev": "1ab0d4972937bf0451fc164f39a67475776a9edf", 
+    "rev": "4a95604fdf2c0523e68eaad64a17d22eebb051b3", 
     "remote-branch": "origin/master", 
     "branch": "master", 
     "directory": "ms-test-suite"
index 05f99482a28f1634fac2c37860d06136fe33328a..c1c16199481352d873f6df2c7a077a43197dcbe3 100644 (file)
@@ -1,9 +1,10 @@
 check-ms-test-suite:
        @if $(MAKE) validate-ms-test-suite RESET_VERSIONS=1; then \
-               $(MAKE) -C $(MSTESTSUITE_PATH)/conformance build MCS="$(MCS) -t:library -warn:1 -r:nunit.framework"; \
-               $(MAKE) -C $(MSTESTSUITE_PATH)/conformance run NUNIT-CONSOLE="$(RUNTIME) $(CLASS)/nunit-console.exe -nologo -exclude=MonoBug,BadTest" NUNIT_XML_RESULT=$(abs_top_builddir)/acceptance-tests/TestResult-ms-test-suite-conformance.xml; \
-               $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup build MCS="$(MCS) -debug -warn:1"; \
-               $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup run MONO="$(RUNTIME)"; \
+               $(MAKE) -C $(MSTESTSUITE_PATH)/conformance build MCS="$(MCS) -t:library -warn:1 -r:nunit.framework" && \
+               $(MAKE) -C $(MSTESTSUITE_PATH)/conformance run NUNIT-CONSOLE="$(RUNTIME) $(CLASS)/nunit-console.exe -nologo -exclude=MonoBug,BadTest" NUNIT_XML_RESULT=$(abs_top_builddir)/acceptance-tests/TestResult-ms-test-suite-conformance.xml || EXIT_CODE=1; \
+               $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup build MCS="$(MCS) -debug -warn:1" && \
+               $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup run MONO="$(RUNTIME)" || EXIT_CODE=1; \
+               exit $$EXIT_CODE; \
        else \
                echo "*** [ms-test-suite] Getting the repository failed, you probably don't have access to this Xamarin-internal resource. Skipping."; \
        fi
\ No newline at end of file
index e20b01e4979a0c05a239578a0d5bd6cb1af5fa32..17e0e4ce67580a5f3a762dbd89ca5d8bb8ab667f 100644 (file)
@@ -19,5 +19,6 @@ check-roslyn:
        cd $(ROSLYN_PATH); \
        sed -i -e 'N; s/bootstrapArg=".*\n.*"/bootstrapArg=""/g' cibuild.sh; \
        sed -i -e 's#-xml Binaries/\$$BUILD_CONFIGURATION/xUnitResults/#-nunit $(abs_top_builddir)/acceptance-tests/TestResult-#g' cibuild.sh; \
-       ./cibuild.sh --mono-path $$PREFIX/bin; \
-       sed -i -e 's/\\4.5"/\\4.5-api"/g' $$PREFIX/lib/mono/xbuild-frameworks/.NETFramework/v4.5/RedistList/FrameworkList.xml;
+       ./cibuild.sh --mono-path $$PREFIX/bin || EXIT_CODE=1; \
+       sed -i -e 's/\\4.5"/\\4.5-api"/g' $$PREFIX/lib/mono/xbuild-frameworks/.NETFramework/v4.5/RedistList/FrameworkList.xml; \
+       exit $$EXIT_CODE
index bf0e910961bee936d8a8ccaea91b02d2472813ae..5d9bfe8244ff44f3ca0394fb766ab3b9c7fe4d75 100644 (file)
@@ -3583,35 +3583,34 @@ AC_ARG_WITH(cooperative_gc, [  --with-cooperative-gc=yes|no      Enable cooperat
        fi
 ], [with_cooperative_gc=no])
 
-AC_ARG_WITH(checked_build, [  --with-checked-build=yes|no      Enable checked build (expensive asserts)) (defaults to no)],[
-       if test x$with_checked_build != xno ; then
-               AC_DEFINE(CHECKED_BUILD,1,[Enable checked build.])
-       fi
-], [with_checked_build=no])
+AC_ARG_ENABLE(checked_build, [  --enable-checked-build=LIST      To enable checked build (expensive asserts), configure with a comma-separated LIST of checked build modules and then include that same list in the environment variable MONO_CHECK_MODE at runtime. Recognized checked build modules: all, gc, metadata, thread],[
 
-if test x$with_checked_build != xno ; then
-       DISABLED_CHECKED_BUILD_TEST=none
+       if test x$enable_checked_build != x ; then
+               AC_DEFINE(ENABLE_CHECKED_BUILD,1,[Enable checked build])
+       fi
+       for feature in `echo "$enable_checked_build" | sed -e "s/,/ /g"`; do
+               eval "mono_checked_build_test_enable_$feature='yes'"
+       done
 
-       AC_ARG_ENABLE(checked_build_test, [  --enable-checked-build-test=LIST      drop support for LIST checked build tests. LIST is a comma-separated list from: gc, metadata, thread.],
-       [
-               for feature in `echo "$enable_checked_build_test" | sed -e "s/,/ /g"`; do
-                       eval "mono_checked_build_test_disable_$feature='yes'"
-               done
-               DISABLED_CHECKED_BUILD_TEST=$enable_checked_build_test
-       ],[])
+       if test "x$mono_checked_build_test_enable_all" = "xyes"; then
+               eval "mono_checked_build_test_enable_gc='yes'"
+               eval "mono_checked_build_test_enable_metadata='yes'"
+               eval "mono_checked_build_test_enable_thread='yes'"
+       fi
 
-       if test "x$mono_checked_build_test_disable_gc" = "xyes"; then
-               AC_DEFINE(DISABLE_CHECKED_BUILD_GC, 1, [Disable GC checked build])
+       if test "x$mono_checked_build_test_enable_gc" = "xyes"; then
+               AC_DEFINE(ENABLE_CHECKED_BUILD_GC, 1, [Enable GC checked build])
        fi
 
-       if test "x$mono_checked_build_test_disable_metadata" = "xyes"; then
-               AC_DEFINE(DISABLE_CHECKED_BUILD_METADATA, 1, [Disable metadata checked build])
+       if test "x$mono_checked_build_test_enable_metadata" = "xyes"; then
+               AC_DEFINE(ENABLE_CHECKED_BUILD_METADATA, 1, [Enable metadata checked build])
        fi
 
-       if test "x$mono_checked_build_test_disable_thread" = "xyes"; then
-               AC_DEFINE(DISABLE_CHECKED_BUILD_THREAD, 1, [Disable thread checked build])
+       if test "x$mono_checked_build_test_enable_thread" = "xyes"; then
+               AC_DEFINE(ENABLE_CHECKED_BUILD_THREAD, 1, [Enable thread checked build])
        fi
-fi
+
+], [])
 
 AC_CHECK_HEADER([malloc.h], 
                [AC_DEFINE([HAVE_USR_INCLUDE_MALLOC_H], [1], 
index 35b7594b5498e9712522e0556ec290415691dddd..df1c00441047e7cc439608aa1aa083f585f5ace0 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 35b7594b5498e9712522e0556ec290415691dddd
+Subproject commit df1c00441047e7cc439608aa1aa083f585f5ace0
index f29f4d1601ee83055ad10cd9599067f4042107ab..a3829ae79a54741d8f8d047999c82b9977c6c923 100644 (file)
@@ -1094,11 +1094,6 @@ find spots that need to be tuned for this mode of operation.   Alternatively,
 this mode can be enabled at compile time by using the --with-cooperative-gc
 flag when calling configure.
 .TP
-\fBMONO_ENABLE_SHM\fR
-Unix only: Enable support for cross-process handles.  Cross-process
-handles are used to expose process handles, thread handles, named
-mutexes, named events and named semaphores across Unix processes.
-.TP
 \fBMONO_ENV_OPTIONS\fR
 This environment variable allows you to pass command line arguments to
 a Mono process through the environment.   This is useful for example
index 8048c5fdf3beb54fe2bdcdd761616bf177795d5b..f33fcccf2d7635f498496404d5ed0dbadd8f1d56 100644 (file)
@@ -28,7 +28,8 @@ COMMON_SRCS = \
        Locale.cs                       \
        MonoTODOAttribute.cs \
        basic-profile-check.cs          \
-       SR.cs
+       SR.cs   \
+       AssemblyRef.cs
 
 DISTFILES = \
        README.makefiles                \
diff --git a/mcs/build/common/AssemblyRef.cs b/mcs/build/common/AssemblyRef.cs
new file mode 100644 (file)
index 0000000..a38d371
--- /dev/null
@@ -0,0 +1,25 @@
+static class AssemblyRef
+{
+       // FIXME
+       internal const string SystemConfiguration = "System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
+       internal const string System = "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
+
+       public const string EcmaPublicKey = "b77a5c561934e089";
+#if NET_2_1
+       public const string FrameworkPublicKeyFull = "0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9";
+       public const string FrameworkPublicKeyFull2 = "00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB";
+#else
+       public const string FrameworkPublicKeyFull = "00000000000000000400000000000000";
+       public const string FrameworkPublicKeyFull2 = "00000000000000000400000000000000";
+#endif
+       public const string MicrosoftPublicKey = "b03f5f7f11d50a3a";
+       public const string MicrosoftJScript = Consts.AssemblyMicrosoft_JScript;
+       public const string MicrosoftVSDesigner = Consts.AssemblyMicrosoft_VSDesigner;
+       public const string SystemData = Consts.AssemblySystem_Data;
+       public const string SystemDesign = Consts.AssemblySystem_Design;
+       public const string SystemDrawing = Consts.AssemblySystem_Drawing;
+       public const string SystemWeb = Consts.AssemblySystem_Web;
+       public const string SystemWebExtensions =  "System.Web.Extensions, Version=" + Consts.FxVersion + ", Culture=neutral, PublicKeyToken=31bf3856ad364e35";
+       public const string SystemWindowsForms = Consts.AssemblySystem_Windows_Forms;
+}
\ No newline at end of file
index 836910f2ecf21ac2833f2f601287dd061b5e12ca..0685edb53bca0127edb3c2ef8f5847a7dfc2498f 100644 (file)
@@ -1,31 +1,5 @@
 using System.Globalization;
 
-static class AssemblyRef
-{
-       // FIXME
-       internal const string SystemConfiguration = "System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
-       internal const string System = "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
-
-       public const string EcmaPublicKey = "b77a5c561934e089";
-#if NET_2_1
-       public const string FrameworkPublicKeyFull = "0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9";
-       public const string FrameworkPublicKeyFull2 = "00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB";
-#else
-       public const string FrameworkPublicKeyFull = "00000000000000000400000000000000";
-       public const string FrameworkPublicKeyFull2 = "00000000000000000400000000000000";
-#endif
-       public const string MicrosoftPublicKey = "b03f5f7f11d50a3a";
-       public const string MicrosoftJScript = Consts.AssemblyMicrosoft_JScript;
-       public const string MicrosoftVSDesigner = Consts.AssemblyMicrosoft_VSDesigner;
-       public const string SystemData = Consts.AssemblySystem_Data;
-       public const string SystemDesign = Consts.AssemblySystem_Design;
-       public const string SystemDrawing = Consts.AssemblySystem_Drawing;
-       public const string SystemWeb = Consts.AssemblySystem_Web;
-       public const string SystemWebExtensions =  "System.Web.Extensions, Version=" + Consts.FxVersion + ", Culture=neutral, PublicKeyToken=31bf3856ad364e35";
-       public const string SystemWindowsForms = Consts.AssemblySystem_Windows_Forms;
-}
-
 static partial class SR
 {
        internal static string GetString(string name, params object[] args)
index ee6e39dcc86cb40c84c98bcbdc0d8f55beacdf35..6bf570842e7757c2ba86d3e6c1a7bbe7b90ba30d 100644 (file)
@@ -14,7 +14,9 @@ build_SUBDIRS :=  \
        System.XML \
        System Mono.Security \
        Mono.Posix \
-       System.Core
+       System.Core \
+       Mono.Cecil \
+       Mono.Cecil.Mdb
 
 pcl_facade_dirs := Facades
 
index bd3c641856d7cd133f9488a37de707a989fff58c..c295d3ba67f30a6ead7b70938f594380a009c5f6 100644 (file)
@@ -54,7 +54,8 @@ namespace Microsoft.Build.Execution
                
                public void Dispose ()
                {
-                       WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
+                       if (submissions.Count > 0)
+                               WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
                        BuildNodeManager.Stop ();
                }
 
index d4414a9b8a5da54340028545decaf7a2ce21c9b4..64cfacd9a49d4b57e4e7db27609369035deda62c 100644 (file)
@@ -427,6 +427,7 @@ namespace Microsoft.Build.Execution
                        };
                        var requestData = new BuildRequestData (this, targets ?? DefaultTargets.ToArray ());
                        var result = manager.Build (parameters, requestData);
+                       manager.Dispose ();
                        targetOutputs = result.ResultsByTarget;
                        return result.OverallResult == BuildResultCode.Success;
                }
index ebfad5ba752ff0ec11cd51eb452d64bb8a186b62..322006a4e849fadd25b24ad978fb62530d9fe27e 100644 (file)
@@ -41,7 +41,10 @@ namespace Microsoft.Build.Internal
                public BuildNodeManager (BuildManager buildManager)
                {
                        BuildManager = buildManager;
-                       new Thread (RunLoop).Start ();
+                       new Thread (RunLoop) {
+                               IsBackground = true,
+                               Name = "xbuild request handler"
+                       }.Start ();
                }
 
                ~BuildNodeManager ()
index d0e7294f80f06e2087f936e029f71a4711d9988b..8a873fa9a47f0ca2085f41ca0a1e712ce04a1b3b 100644 (file)
@@ -21,5 +21,5 @@ EXTRA_DISTFILES = Mono.Security.Interface/README.md
 
 #
 # Update this comment to trigger a build in System
-# +2
+# +3
 #
index 753cd97e5a23952166c2f74f6effd7524a407c6d..8b7c6ddecfc28a375c64139d08d003fb67f6a2ce 100644 (file)
@@ -144,7 +144,7 @@ namespace Mono.Security.Interface
                 */
                public virtual bool InvokeSystemCertificateValidator (
                        ICertificateValidator validator, string targetHost, bool serverMode,
-                       X509CertificateCollection certificates, X509Chain chain, out bool success,
+                       X509CertificateCollection certificates, ref X509Chain chain, out bool success,
                        ref MonoSslPolicyErrors errors, ref int status11)
                {
                        success = false;
index e83ceb3e1d1990375796bb3cb5ab9a33141ae120..561d2fef4b2a656d5dde288fab45d8d9ca8cdd83 100644 (file)
@@ -48,7 +48,6 @@ using System.Runtime.InteropServices;
 [assembly: ComCompatibleVersion (1, 0, 3300, 0)]
 [assembly: SecurityCritical (SecurityCriticalScope.Explicit)]
 #endif
-[assembly: InternalsVisibleTo ("System.Runtime.Serialization, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull)]
 [assembly: InternalsVisibleTo ("System.IdentityModel, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull)]
 [assembly: InternalsVisibleTo ("System.IdentityModel.Selectors, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull)]
 [assembly: InternalsVisibleTo ("System.ServiceModel, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull)]
index 13ab7daa6d13d3dc3347053fdb639b28ce4f1539..59a7f8b139e5d1501eabf69f48924799d275e4d0 100644 (file)
@@ -1,6 +1,7 @@
 Assembly/AssemblyInfo.cs
 ../../build/common/Consts.cs
 ../../build/common/SR.cs
+../../build/common/AssemblyRef.cs
 EntityRes.cs
 EntityResCategoryAttribute.cs
 EntityResDescriptionAttribute.cs
index 1315e15e184338ef0f5639d41128c7e35cf9a53b..a5b2a2f1492a695f255fbb5c8aaf165e5c297848 100644 (file)
@@ -3,6 +3,7 @@ Assembly/AssemblyInfo.cs
 ../../build/common/Locale.cs
 ../../build/common/SR.cs
 ../../build/common/MonoTODOAttribute.cs
+../../build/common/AssemblyRef.cs
 
 ReferenceSources/NativeOledbWrapper.cs
 ReferenceSources/Res.cs
index 9622fcee668d3525c1dc49fa7a44053d20c8a983..76b642b8849fda23403711d3dbc810bb48a6171a 100644 (file)
@@ -3,6 +3,7 @@ Assembly/AssemblyInfo.cs
 ../../build/common/Locale.cs
 ../../build/common/SR.cs
 ../../build/common/MonoTODOAttribute.cs
+../../build/common/AssemblyRef.cs
 
 ReferenceSources/NativeOledbWrapper.cs
 ReferenceSources/Res.cs
index d8b918ebce307242c16d0e3383b39fa948badb2c..abc4e30ee80dea672bbb6ae14cfdd90449b6d521 100644 (file)
@@ -5,6 +5,6 @@ include ../../build/rules.make
 LIBRARY = System.IO.Compression.FileSystem.dll
 LIB_REFS = System System.IO.Compression
 LIB_MCS_FLAGS =
-TEST_MCS_FLAGS = /r:System /r:System.Core /r:System.IO.Compression.dll
+TEST_MCS_FLAGS = /r:System.dll /r:System.Core.dll /r:System.IO.Compression.dll
 
 include ../../build/library.make
index 7b2bd8144fb4fe6c7e7ad159dde706049e957825..3ca6899dacde9f589312031a31c0a8622a766770 100644 (file)
@@ -5,6 +5,6 @@ include ../../build/rules.make
 LIBRARY = System.IO.Compression.dll
 LIB_REFS = System System.Core
 LIB_MCS_FLAGS = /unsafe
-TEST_MCS_FLAGS = /r:System /r:System.Core
+TEST_MCS_FLAGS = /r:System.dll /r:System.Core.dll
 
 include ../../build/library.make
index 52a64788971e226d362bf1cf43a8a090ed8a9204..4d9265a6ac76f8e3640e82e2e75e1fa6189b8ee6 100644 (file)
@@ -152,15 +152,16 @@ namespace MonoTests.System.Net.Http
 
                const int WaitTimeout = 5000;
 
-               string port, TestHost, LocalServer;
+               string TestHost, LocalServer;
+               int port;
 
                [SetUp]
                public void SetupFixture ()
                {
                        if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
-                               port = "810";
+                               port = 810;
                        } else {
-                               port = "8810";
+                               port = 8810;
                        }
 
                        TestHost = "localhost:" + port;
@@ -1080,9 +1081,20 @@ namespace MonoTests.System.Net.Http
                                var response = l.Response;
 
                                response.StatusCode = (int)HttpStatusCode.Moved;
-                               response.RedirectLocation = "http://xamarin.com/";
+                               response.RedirectLocation = "http://localhost:8811/";
                        });
 
+                       var listener2 = CreateListener (l => {
+                               var response = l.Response;
+
+                               response.StatusCode = (int)HttpStatusCode.OK;
+                               response.OutputStream.WriteByte (0x68);
+                               response.OutputStream.WriteByte (0x65);
+                               response.OutputStream.WriteByte (0x6c);
+                               response.OutputStream.WriteByte (0x6c);
+                               response.OutputStream.WriteByte (0x6f);
+                       }, 8811);
+
                        try {
                                var chandler = new HttpClientHandler ();
                                chandler.AllowAutoRedirect = true;
@@ -1091,10 +1103,13 @@ namespace MonoTests.System.Net.Http
                                var r = client.GetAsync (LocalServer);
                                Assert.IsTrue (r.Wait (WaitTimeout), "#1");
                                var resp = r.Result;
-                               Assert.AreEqual ("http://xamarin.com/", resp.RequestMessage.RequestUri.AbsoluteUri, "#2");
+                               Assert.AreEqual ("http://localhost:8811/", resp.RequestMessage.RequestUri.AbsoluteUri, "#2");
+                               Assert.AreEqual ("hello", resp.Content.ReadAsStringAsync ().Result, "#3");
                        } finally {
                                listener.Abort ();
                                listener.Close ();
+                               listener2.Abort ();
+                               listener2.Close ();
                        }
                }
 
@@ -1151,6 +1166,11 @@ namespace MonoTests.System.Net.Http
                }
 
                HttpListener CreateListener (Action<HttpListenerContext> contextAssert)
+               {
+                       return CreateListener (contextAssert, port);
+               }
+
+               HttpListener CreateListener (Action<HttpListenerContext> contextAssert, int port)
                {
                        var l = new HttpListener ();
                        l.Prefixes.Add (string.Format ("http://+:{0}/", port));
index 344d5669236655ba19abb49663689453c3d71af9..eeb73d0894eefe4d3fa471d20c063fb544c3abad 100644 (file)
@@ -4,9 +4,13 @@ include ../../build/rules.make
 
 LIBRARY = System.Runtime.Remoting.dll
 
-LIB_REFS = System System.Web System.Xml System.Runtime.Serialization.Formatters.Soap
+LIB_REFS = System System.Xml System.Runtime.Serialization.Formatters.Soap
 LIB_MCS_FLAGS = /r:$(corlib)
 
+ifndef NO_SYSTEM_WEB_DEPENDENCY
+LIB_REFS += System.Web
+endif
+
 TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) -nowarn:618 /r:System.Runtime.Remoting.dll
 
 TEST_MONO_PATH = .
diff --git a/mcs/class/System.Runtime.Remoting/xammac_net_4_5_System.Runtime.Remoting.dll.sources b/mcs/class/System.Runtime.Remoting/xammac_net_4_5_System.Runtime.Remoting.dll.sources
new file mode 100644 (file)
index 0000000..cadd275
--- /dev/null
@@ -0,0 +1,56 @@
+Assembly/AssemblyInfo.cs
+../../build/common/Consts.cs
+../../build/common/Locale.cs
+../../build/common/MonoTODOAttribute.cs
+System.Runtime.Remoting.Channels/BinaryClientFormatterSink.cs
+System.Runtime.Remoting.Channels/BinaryClientFormatterSinkProvider.cs
+System.Runtime.Remoting.Channels/BinaryCore.cs
+System.Runtime.Remoting.Channels/BinaryServerFormatterSink.cs
+System.Runtime.Remoting.Channels/BinaryServerFormatterSinkProvider.cs
+System.Runtime.Remoting.Channels/ChannelCore.cs
+System.Runtime.Remoting.Channels/CommonTransportKeys.cs
+System.Runtime.Remoting.Channels/IAuthorizeRemotingConnection.cs
+System.Runtime.Remoting.Channels/RemotingThreadPool.cs
+System.Runtime.Remoting.Channels/SoapClientFormatterSink.cs
+System.Runtime.Remoting.Channels/SoapCore.cs
+System.Runtime.Remoting.Channels/SoapServerFormatterSink.cs
+System.Runtime.Remoting.Channels/SoapClientFormatterSinkProvider.cs
+System.Runtime.Remoting.Channels/SoapServerFormatterSinkProvider.cs
+System.Runtime.Remoting.Channels/SoapMessageFormatter.cs
+System.Runtime.Remoting.Channels/SocketCachePolicy.cs
+System.Runtime.Remoting.Channels.Ipc/IpcChannel.cs
+System.Runtime.Remoting.Channels.Ipc/IpcClientChannel.cs
+System.Runtime.Remoting.Channels.Ipc/IpcServerChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/IpcTransport.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/IpcChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/IpcChannelHelper.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/IpcClientChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/IpcServerChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeClient.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeException.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeHelper.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeListener.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs
+System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeStream.cs
+System.Runtime.Remoting.Channels.Ipc.Unix/IpcChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Unix/IpcClientChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Unix/IpcServerChannel.cs
+System.Runtime.Remoting.Channels.Ipc.Unix/UnixChannelLoader.cs
+System.Runtime.Remoting.Channels.Tcp/TcpChannel.cs
+System.Runtime.Remoting.Channels.Tcp/TcpClientChannel.cs
+System.Runtime.Remoting.Channels.Tcp/TcpMessageIO.cs
+System.Runtime.Remoting.Channels.Tcp/TcpServerChannel.cs
+System.Runtime.Remoting.Channels.Tcp/TcpServerTransportSink.cs
+System.Runtime.Remoting.Channels.Tcp/TcpClientTransportSinkProvider.cs
+System.Runtime.Remoting.Channels.Tcp/TcpClientTransportSink.cs
+System.Runtime.Remoting.Channels.Tcp/TcpConnectionPool.cs
+System.Runtime.Remoting.MetadataServices/MetaData.cs
+System.Runtime.Remoting.MetadataServices/MetaDataExporter.cs
+System.Runtime.Remoting.MetadataServices/MetaDataCodeGenerator.cs
+System.Runtime.Remoting.MetadataServices/SdlChannelSinkProvider.cs
+System.Runtime.Remoting.MetadataServices/ServiceType.cs
+System.Runtime.Remoting.MetadataServices/SUDSParserException.cs
+System.Runtime.Remoting.MetadataServices/SdlChannelSink.cs
+System.Runtime.Remoting.MetadataServices/SdlType.cs
+System.Runtime.Remoting.MetadataServices/SUDSGeneratorException.cs
+System.Runtime.Remoting.Services/RemotingClientProxy.cs
index 99b323b2ab87b039f8e4d4c379c55ff66dd9fb4d..c9371adcc7403240c954b4a66007148ccf1aeb6c 100644 (file)
@@ -1,5 +1,6 @@
 ../../build/common/Consts.cs
 ../../build/common/SR.cs
+../../build/common/AssemblyRef.cs
 EventLogEntryType.cs
 InternalSR.cs
 Assembly/AssemblyInfo.cs
index a2290a9efeaf3b0ae14f737112d1aebd49cb4be0..d788a69db7c339cf3c567efc9aec7dceb8fd62f1 100644 (file)
@@ -1,5 +1,6 @@
 ../../build/common/Consts.cs
 ../../build/common/SR.cs
+../../build/common/AssemblyRef.cs
 EventLogEntryType.cs
 InternalSR.cs
 MobileStubs.cs
index 355a3941c49773033d6a5496df503c5a8a417a99..3b61fe6384ad5cb0384fd7b329d1f7ac1133b281 100644 (file)
@@ -63,12 +63,9 @@ using System.Runtime.InteropServices;
 
 #if NET_2_1
        [assembly: InternalsVisibleTo ("System.ServiceModel.Web, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")]
-       // System.Xml.Serialization (from Microsoft Silverlight 2.0 SDK) requires access to System.Xml internals
-       [assembly: InternalsVisibleTo ("System.Xml.Serialization, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull)]
 #else
        [assembly: AllowPartiallyTrustedCallers]
 #endif
-       [assembly: InternalsVisibleTo ("System.Runtime.Serialization, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull, AllInternalsVisible = false)]
        [assembly: InternalsVisibleTo ("System.Xml.Linq, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull, AllInternalsVisible = false)]
 
 [assembly: AssemblyFileVersion (Consts.FxFileVersion)]
index 267719b871e93571b74c4c277a04a15e98a32845..be7f6099f6c4f6eeaa005c179dd27b8e738ba2d8 100644 (file)
@@ -1,6 +1,7 @@
 Assembly/AssemblyInfo.cs
 ../../build/common/Consts.cs
 ../../build/common/SR.cs
+../../build/common/AssemblyRef.cs
 ReferenceSources/Res.cs
 ReferenceSources/LocalAppContextSwitches.cs
 ReferenceSources/ThisAssembly.cs
index 9306044810f02c3f1491fa556fd8b522c9813452..253beb6470688707f66711f03749fc80fb4cb3ea 100644 (file)
@@ -2,6 +2,7 @@ Assembly/AssemblyInfo.cs
 ../../build/common/Consts.cs
 ../../build/common/MonoTODOAttribute.cs
 ../../build/common/SR.cs
+../../build/common/AssemblyRef.cs
 ReferenceSources/Res.cs
 ReferenceSources/LocalAppContextSwitches.cs
 ReferenceSources/ThisAssembly.cs
index 63a781dbdf5a7d37628af8efb85473e6692d486e..617fbdefd531e5d2e6686ce7cc15f85348498a34 100644 (file)
@@ -296,7 +296,8 @@ namespace Mono.Net.Security
                        if (provider != null && provider.HasCustomSystemCertificateValidator) {
                                var xerrors = (MonoSslPolicyErrors)errors;
                                var xchain = (XX509Chain)(object)chain;
-                               providerValidated = provider.InvokeSystemCertificateValidator (this, host, server, certs, xchain, out result, ref xerrors, ref status11);
+                               providerValidated = provider.InvokeSystemCertificateValidator (this, host, server, certs, ref xchain, out result, ref xerrors, ref status11);
+                               chain = (X509Chain)(object)xchain;
                                errors = (SslPolicyErrors)xerrors;
                        }
 
index dd67b660bef8f9212278f53c7bf6fecb62210068..8cd1ca0b6fac8de068150a1b0e18f3342ce8a7c0 100644 (file)
@@ -121,7 +121,9 @@ namespace Mono.Net.Security
                static bool CheckUsage (XX509CertificateCollection certs, string host, ref SslPolicyErrors errors, ref int status11)
                {
 #if !MONOTOUCH
-                       var leaf = (X509Certificate2)certs[0];
+                       var leaf = certs[0] as X509Certificate2;
+                       if (leaf == null)
+                               leaf = new X509Certificate2 (certs[0]);
                        // for OSX and iOS we're using the native API to check for the SSL server policy and host names
                        if (!is_macosx) {
                                if (!CheckCertificateUsage (leaf)) {
index 57b8e669160aca8d9934afb06f6d77f839158532..41cf0d8c8c455930dfc4e5c8bbd84c9fa5308d74 100644 (file)
@@ -302,7 +302,7 @@ namespace System.Diagnostics
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The session ID for this process.")]
                public int SessionId {
-                       get { throw new NotImplementedException (); }
+                       get { return 0; }
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
index 769195a2b3ec4c965278d9ed8aa7670388d5e800..f1c47802cb94bef9e16534919ff1d10aba148b8c 100644 (file)
@@ -403,7 +403,7 @@ namespace System.Net {
                }
 
                public bool IsLocal {
-                       get { return IPAddress.IsLoopback (RemoteEndPoint.Address); }
+                       get { return LocalEndPoint.Address.Equals (RemoteEndPoint.Address); }
                }
 
                public bool IsSecureConnection {
index 0681e9eb5d7c6c4056b0c3008d8c34104f9db8ee..795f0d04b21acfabb51a09db288cfa3ccfecd274 100644 (file)
@@ -52,6 +52,7 @@ namespace System.Security.Cryptography.X509Certificates {
                        X500DistinguishedNameFlags.UseT61Encoding | X500DistinguishedNameFlags.ForceUTF8Encoding;
 
                private string name;
+               private byte[] canonEncoding;
 
 
                public X500DistinguishedName (AsnEncodedData encodedDistinguishedName)
@@ -122,6 +123,20 @@ namespace System.Security.Cryptography.X509Certificates {
                        name = distinguishedName.name;
                }
 
+               internal X500DistinguishedName (byte[] encoded, byte[] canonEncoding, string name)
+                       : this (encoded)
+               {
+                       this.canonEncoding = canonEncoding;
+                       this.name = name;
+
+                       Oid = new Oid ();
+                       RawData = encoded;
+               }
+
+               internal byte[] CanonicalEncoding {
+                       get { return canonEncoding; }
+               }
+
 
                public string Name {
                        get { return name; }
@@ -215,6 +230,16 @@ namespace System.Security.Cryptography.X509Certificates {
                        if (name2 == null)
                                return false;
 
+                       if (name1.canonEncoding != null && name2.canonEncoding != null) {
+                               if (name1.canonEncoding.Length != name2.canonEncoding.Length)
+                                       return false;
+                               for (int i = 0; i < name1.canonEncoding.Length; i++) {
+                                       if (name1.canonEncoding[i] != name2.canonEncoding[2])
+                                               return false;
+                               }
+                               return true;
+                       }
+
                        X500DistinguishedNameFlags flags = X500DistinguishedNameFlags.UseNewLines | X500DistinguishedNameFlags.DoNotUseQuotes;
                        string[] split = new string[] { Environment.NewLine };
                        string[] parts1 = name1.Decode (flags).Split (split, StringSplitOptions.RemoveEmptyEntries);
index afb81cb1ab77e0488174477741d71bf0e3d766c3..29decab439faa252aeb371c167e754684e7f9ec9 100644 (file)
@@ -44,11 +44,13 @@ using MX = Mono.Security.X509;
 
 using System.IO;
 using System.Text;
+using System.Collections;
 
 namespace System.Security.Cryptography.X509Certificates {
 
        [Serializable]
        public class X509Certificate2 : X509Certificate {
+       
 #if !SECURITY_DEP
                // Used in Mono.Security HttpsClientStream
                public X509Certificate2 (byte[] rawData)
@@ -56,24 +58,20 @@ namespace System.Security.Cryptography.X509Certificates {
                }
 #endif
 #if SECURITY_DEP
-               private bool _archived;
-               private X509ExtensionCollection _extensions;
-               private string _name = String.Empty;
-               private string _serial;
-               private PublicKey _publicKey;
-               private X500DistinguishedName issuer_name;
-               private X500DistinguishedName subject_name;
-               private Oid signature_algorithm;
-
-               private MX.X509Certificate _cert;
+               new internal X509Certificate2Impl Impl {
+                       get {
+                               var impl2 = base.Impl as X509Certificate2Impl;
+                               X509Helper2.ThrowIfContextInvalid (impl2);
+                               return impl2;
+                       }
+               }
 
-               private static string empty_error = Locale.GetText ("Certificate instance is empty.");
+               string friendlyName = string.Empty;
 
                // constructors
 
                public X509Certificate2 ()
                {
-                       _cert = null;
                }
 
                public X509Certificate2 (byte[] rawData)
@@ -128,206 +126,88 @@ namespace System.Security.Cryptography.X509Certificates {
 
                public X509Certificate2 (IntPtr handle) : base (handle) 
                {
-                       _cert = new MX.X509Certificate (base.GetRawCertData ());
+                       throw new NotImplementedException ();
                }
 
                public X509Certificate2 (X509Certificate certificate) 
-                       : base (certificate)
+                       : base (X509Helper2.Import (certificate))
+               {
+               }
+
+               internal X509Certificate2 (X509Certificate2Impl impl)
+                       : base (impl)
                {
-                       _cert = new MX.X509Certificate (base.GetRawCertData ());
                }
 
                // properties
 
                public bool Archived {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               return _archived;
-                       }
-                       set {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               _archived = value;
-                       }
+                       get { return Impl.Archived; }
+                       set { Impl.Archived = true; }
                }
 
                public X509ExtensionCollection Extensions {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               if (_extensions == null)
-                                       _extensions = new X509ExtensionCollection (_cert);
-                               return _extensions;
-                       }
+                       get { return Impl.Extensions; }
                }
 
                public string FriendlyName {
                        get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               return _name;
+                               ThrowIfContextInvalid ();
+                               return friendlyName;
                        }
                        set {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               _name = value;
+                               ThrowIfContextInvalid ();
+                               friendlyName = value;
                        }
                }
 
-               // FIXME - Could be more efficient
                public bool HasPrivateKey {
-                       get { return PrivateKey != null; }
+                       get { return Impl.HasPrivateKey; }
                }
 
                public X500DistinguishedName IssuerName {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               if (issuer_name == null)
-                                       issuer_name = new X500DistinguishedName (_cert.GetIssuerName ().GetBytes ());
-                               return issuer_name;
-                       }
+                       get { return Impl.IssuerName; }
                } 
 
                public DateTime NotAfter {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               return _cert.ValidUntil.ToLocalTime ();
-                       }
+                       get { return Impl.GetValidUntil ().ToLocalTime (); }
                }
 
                public DateTime NotBefore {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               return _cert.ValidFrom.ToLocalTime ();
-                       }
+                       get { return Impl.GetValidFrom ().ToLocalTime (); }
                }
 
                public AsymmetricAlgorithm PrivateKey {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               try {
-                                       if (_cert.RSA != null) {
-                                               RSACryptoServiceProvider rcsp = _cert.RSA as RSACryptoServiceProvider;
-                                               if (rcsp != null)
-                                                       return rcsp.PublicOnly ? null : rcsp;
-
-                                               RSAManaged rsam = _cert.RSA as RSAManaged;
-                                               if (rsam != null)
-                                                       return rsam.PublicOnly ? null : rsam;
-
-                                               _cert.RSA.ExportParameters (true);
-                                               return _cert.RSA;
-                                       } else if (_cert.DSA != null) {
-                                               DSACryptoServiceProvider dcsp = _cert.DSA as DSACryptoServiceProvider;
-                                               if (dcsp != null)
-                                                       return dcsp.PublicOnly ? null : dcsp;
-
-                                               _cert.DSA.ExportParameters (true);
-                                               return _cert.DSA;
-                                       }
-                               }
-                               catch {
-                               }
-                               return null;
-                       }
-                       set {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               // allow NULL so we can "forget" the key associated to the certificate
-                               // e.g. in case we want to export it in another format (see bug #396620)
-                               if (value == null) {
-                                       _cert.RSA = null;
-                                       _cert.DSA = null;
-                               } else  if (value is RSA)
-                                       _cert.RSA = (RSA) value;
-                               else if (value is DSA)
-                                       _cert.DSA = (DSA) value;
-                               else
-                                       throw new NotSupportedException ();
-                       }
+                       get { return Impl.PrivateKey; }
+                       set { Impl.PrivateKey = value; }
                } 
 
                public PublicKey PublicKey {
-                       get { 
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               if (_publicKey == null) {
-                                       try {
-                                               _publicKey = new PublicKey (_cert);
-                                       }
-                                       catch (Exception e) {
-                                               string msg = Locale.GetText ("Unable to decode public key.");
-                                               throw new CryptographicException (msg, e);
-                                       }
-                               }
-                               return _publicKey;
-                       }
+                       get { return Impl.PublicKey; }
                } 
 
                public byte[] RawData {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               return base.GetRawCertData ();
-                       }
-               } 
+                       get { return GetRawCertData (); }
+               }
 
                public string SerialNumber {
-                       get { 
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               if (_serial == null) {
-                                       StringBuilder sb = new StringBuilder ();
-                                       byte[] serial = _cert.SerialNumber;
-                                       for (int i=serial.Length - 1; i >= 0; i--)
-                                               sb.Append (serial [i].ToString ("X2"));
-                                       _serial = sb.ToString ();
-                               }
-                               return _serial; 
-                       }
+                       get { return GetSerialNumberString (); }
                } 
 
                public Oid SignatureAlgorithm {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               if (signature_algorithm == null)
-                                       signature_algorithm = new Oid (_cert.SignatureAlgorithm);
-                               return signature_algorithm;
-                       }
+                       get { return Impl.SignatureAlgorithm; }
                } 
 
                public X500DistinguishedName SubjectName {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-
-                               if (subject_name == null)
-                                       subject_name = new X500DistinguishedName (_cert.GetSubjectName ().GetBytes ());
-                               return subject_name;
-                       }
+                       get { return Impl.SubjectName; }
                } 
 
                public string Thumbprint {
-                       get { return base.GetCertHashString (); }
+                       get { return GetCertHashString (); }
                } 
 
                public int Version {
-                       get {
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               return _cert.Version;
-                       }
+                       get { return Impl.Version; }
                }
 
                // methods
@@ -335,135 +215,7 @@ namespace System.Security.Cryptography.X509Certificates {
                [MonoTODO ("always return String.Empty for UpnName, DnsFromAlternativeName and UrlName")]
                public string GetNameInfo (X509NameType nameType, bool forIssuer) 
                {
-                       switch (nameType) {
-                       case X509NameType.SimpleName:
-                               if (_cert == null)
-                                       throw new CryptographicException (empty_error);
-                               // return CN= or, if missing, the first part of the DN
-                               ASN1 sn = forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ();
-                               ASN1 dn = Find (commonName, sn);
-                               if (dn != null)
-                                       return GetValueAsString (dn);
-                               if (sn.Count == 0)
-                                       return String.Empty;
-                               ASN1 last_entry = sn [sn.Count - 1];
-                               if (last_entry.Count == 0)
-                                       return String.Empty;
-                               return GetValueAsString (last_entry [0]);
-                       case X509NameType.EmailName:
-                               // return the E= part of the DN (if present)
-                               ASN1 e = Find (email, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
-                               if (e != null)
-                                       return GetValueAsString (e);
-                               return String.Empty;
-                       case X509NameType.UpnName:
-                               // FIXME - must find/create test case
-                               return String.Empty;
-                       case X509NameType.DnsName:
-                               // return the CN= part of the DN (if present)
-                               ASN1 cn = Find (commonName, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
-                               if (cn != null)
-                                       return GetValueAsString (cn);
-                               return String.Empty;
-                       case X509NameType.DnsFromAlternativeName:
-                               // FIXME - must find/create test case
-                               return String.Empty;
-                       case X509NameType.UrlName:
-                               // FIXME - must find/create test case
-                               return String.Empty;
-                       default:
-                               throw new ArgumentException ("nameType");
-                       }
-               }
-
-               static byte[] commonName = { 0x55, 0x04, 0x03 };
-               static byte[] email = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 };
-
-               private ASN1 Find (byte[] oid, ASN1 dn)
-               {
-                       if (dn.Count == 0)
-                               return null;
-
-                       // process SET
-                       for (int i = 0; i < dn.Count; i++) {
-                               ASN1 set = dn [i];
-                               for (int j = 0; j < set.Count; j++) {
-                                       ASN1 pair = set [j];
-                                       if (pair.Count != 2)
-                                               continue;
-
-                                       ASN1 poid = pair [0];
-                                       if (poid == null)
-                                               continue;
-
-                                       if (poid.CompareValue (oid))
-                                               return pair;
-                               }
-                       }
-                       return null;
-               }
-
-               private string GetValueAsString (ASN1 pair)
-               {
-                       if (pair.Count != 2)
-                               return String.Empty;
-
-                       ASN1 value = pair [1];
-                       if ((value.Value == null) || (value.Length == 0))
-                               return String.Empty;
-
-                       if (value.Tag == 0x1E) {
-                               // BMPSTRING
-                               StringBuilder sb = new StringBuilder ();
-                               for (int j = 1; j < value.Value.Length; j += 2)
-                                       sb.Append ((char)value.Value [j]);
-                               return sb.ToString ();
-                       } else {
-                               return Encoding.UTF8.GetString (value.Value);
-                       }
-               }
-
-               private MX.X509Certificate ImportPkcs12 (byte[] rawData, string password)
-               {
-                       MX.PKCS12 pfx = null;
-                       if (string.IsNullOrEmpty (password)) {
-                               try {
-                                       // Support both unencrypted PKCS#12..
-                                       pfx = new MX.PKCS12 (rawData, (string)null);
-                               } catch {
-                                       // ..and PKCS#12 encrypted with an empty password
-                                       pfx = new MX.PKCS12 (rawData, string.Empty);
-                               }
-                       } else {
-                               pfx = new MX.PKCS12 (rawData, password);
-                       }
-
-                       if (pfx.Certificates.Count == 0) {
-                               // no certificate was found
-                               return null;
-                       } else if (pfx.Keys.Count == 0) {
-                               // no key were found - pick the first certificate
-                               return pfx.Certificates [0];
-                       } else {
-                               // find the certificate that match the first key
-                               MX.X509Certificate cert = null;
-                               var keypair = (pfx.Keys [0] as AsymmetricAlgorithm);
-                               string pubkey = keypair.ToXmlString (false);
-                               foreach (var c in pfx.Certificates) {
-                                       if (((c.RSA != null) && (pubkey == c.RSA.ToXmlString (false))) ||
-                                               ((c.DSA != null) && (pubkey == c.DSA.ToXmlString (false)))) {
-                                               cert = c;
-                                               break;
-                                       }
-                               }
-                               if (cert == null) {
-                                       cert = pfx.Certificates [0]; // no match, pick first certificate without keys
-                               } else {
-                                       cert.RSA = (keypair as RSA);
-                                       cert.DSA = (keypair as DSA);
-                               }
-                               return cert;
-                       }
+                       return Impl.GetNameInfo (nameType, forIssuer);
                }
 
                public override void Import (byte[] rawData) 
@@ -474,37 +226,8 @@ namespace System.Security.Cryptography.X509Certificates {
                [MonoTODO ("missing KeyStorageFlags support")]
                public override void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
                {
-                       MX.X509Certificate cert = null;
-                       if (password == null) {
-                               try {
-                                       cert = new MX.X509Certificate (rawData);
-                               }
-                               catch (Exception e) {
-                                       try {
-                                               cert = ImportPkcs12 (rawData, null);
-                                       }
-                                       catch {
-                                               string msg = Locale.GetText ("Unable to decode certificate.");
-                                               // inner exception is the original (not second) exception
-                                               throw new CryptographicException (msg, e);
-                                       }
-                               }
-                       } else {
-                               // try PKCS#12
-                               try {
-                                       cert = ImportPkcs12 (rawData, password);
-                               }
-                               catch {
-                                       // it's possible to supply a (unrequired/unusued) password
-                                       // fix bug #79028
-                                       cert = new MX.X509Certificate (rawData);
-                               }
-                       }
-                       // we do not have to fully re-decode the certificate since X509Certificate does not deal with keys
-                       if (cert != null) {
-                               base.Import (cert.RawData, (string) null, keyStorageFlags);
-                               _cert = cert; // becuase base call will call Reset!
-                       }
+                       var impl = X509Helper2.Import (rawData, password, keyStorageFlags);
+                       ImportHandle (impl);
                }
 
                [MonoTODO ("SecureString is incomplete")]
@@ -536,64 +259,25 @@ namespace System.Security.Cryptography.X509Certificates {
                [MonoTODO ("X509ContentType.SerializedCert is not supported")]
                public override byte[] Export (X509ContentType contentType, string password)
                {
-                       if (_cert == null)
-                               throw new CryptographicException (empty_error);
-
-                       switch (contentType) {
-                       case X509ContentType.Cert:
-                               return _cert.RawData;
-                       case X509ContentType.Pfx: // this includes Pkcs12
-                               return ExportPkcs12 (password);
-                       case X509ContentType.SerializedCert:
-                               // TODO
-                               throw new NotSupportedException ();
-                       default:
-                               string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
-                               throw new CryptographicException (msg);
-                       }
-               }
-
-               byte[] ExportPkcs12 (string password)
-               {
-                       var pfx = new MX.PKCS12 ();
-                       try {
-                               if (password != null)
-                                       pfx.Password = password;
-                               pfx.AddCertificate (_cert);
-                               var privateKey = PrivateKey;
-                               if (privateKey != null)
-                                       pfx.AddPkcs8ShroudedKeyBag (privateKey);
-                               return pfx.GetBytes ();
-                       } finally {
-                               pfx.Password = null;
-                       }
+                       return Impl.Export (contentType, password);
                }
 
                public override void Reset () 
                {
-                       _cert = null;
-                       _archived = false;
-                       _extensions = null;
-                       _name = String.Empty;
-                       _serial = null;
-                       _publicKey = null;
-                       issuer_name = null;
-                       subject_name = null;
-                       signature_algorithm = null;
+                       friendlyName = string.Empty;
                        base.Reset ();
                }
 
                public override string ToString ()
                {
-                       if (_cert == null)
+                       if (!IsValid)
                                return "System.Security.Cryptography.X509Certificates.X509Certificate2";
-
                        return base.ToString (true);
                }
 
                public override string ToString (bool verbose)
                {
-                       if (_cert == null)
+                       if (!IsValid)
                                return "System.Security.Cryptography.X509Certificates.X509Certificate2";
 
                        // the non-verbose X509Certificate2 == verbose X509Certificate
@@ -643,14 +327,7 @@ namespace System.Security.Cryptography.X509Certificates {
                [MonoTODO ("by default this depends on the incomplete X509Chain")]
                public bool Verify ()
                {
-                       if (_cert == null)
-                               throw new CryptographicException (empty_error);
-
-                       X509Chain chain = X509Chain.Create ();
-                       if (!chain.Build (this))
-                               return false;
-                       // TODO - check chain and other stuff ???
-                       return true;
+                       return Impl.Verify (this);
                }
 
                // static methods
@@ -717,8 +394,14 @@ namespace System.Security.Cryptography.X509Certificates {
                // internal stuff because X509Certificate2 isn't complete enough
                // (maybe X509Certificate3 will be better?)
 
+               [Obsolete ("KILL")]
                internal MX.X509Certificate MonoCertificate {
-                       get { return _cert; }
+                       get {
+                               var monoImpl = Impl as X509Certificate2ImplMono;
+                               if (monoImpl == null)
+                                       throw new NotSupportedException ();
+                               return monoImpl.MonoCertificate;
+                       }
                }
 
 #else
diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs
new file mode 100644 (file)
index 0000000..60e256a
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// X509Certificate2Impl.cs
+//
+// Authors:
+//     Martin Baulig  <martin.baulig@xamarin.com>
+//
+// Copyright (C) 2016 Xamarin, Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+namespace System.Security.Cryptography.X509Certificates
+{
+       internal abstract class X509Certificate2Impl : X509CertificateImpl
+       {
+#if SECURITY_DEP
+
+               public abstract bool Archived {
+                       get; set;
+               }
+
+               public abstract X509ExtensionCollection Extensions {
+                       get;
+               }
+
+               public abstract bool HasPrivateKey {
+                       get;
+               }
+
+               public abstract X500DistinguishedName IssuerName {
+                       get;
+               }
+
+               public abstract AsymmetricAlgorithm PrivateKey {
+                       get; set;
+               }
+
+               public abstract PublicKey PublicKey {
+                       get;
+               }
+
+               public abstract Oid SignatureAlgorithm {
+                       get;
+               }
+
+               public abstract X500DistinguishedName SubjectName {
+                       get;
+               }
+
+               public abstract int Version {
+                       get;
+               }
+
+               public abstract string GetNameInfo (X509NameType nameType, bool forIssuer);
+
+               public abstract void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags);
+
+               public abstract byte[] Export (X509ContentType contentType, string password);
+
+               public abstract bool Verify (X509Certificate2 thisCertificate);
+
+               public abstract void Reset ();
+
+#endif
+       }
+}
diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs
new file mode 100644 (file)
index 0000000..87fd8a1
--- /dev/null
@@ -0,0 +1,694 @@
+//
+// X509Certificate2ImplMono
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//     Martin Baulig  <martin.baulig@xamarin.com>
+//
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
+// Copyright (C) 2015-2016 Xamarin, Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if SECURITY_DEP
+
+#if MONO_SECURITY_ALIAS
+extern alias MonoSecurity;
+using MonoSecurity::Mono.Security;
+using MonoSecurity::Mono.Security.Cryptography;
+using MX = MonoSecurity::Mono.Security.X509;
+#else
+using Mono.Security;
+using Mono.Security.Cryptography;
+using MX = Mono.Security.X509;
+#endif
+
+using System.IO;
+using System.Text;
+using System.Collections;
+
+namespace System.Security.Cryptography.X509Certificates
+{
+       internal class X509Certificate2ImplMono : X509Certificate2Impl
+       {
+               bool _archived;
+               X509ExtensionCollection _extensions;
+               string _serial;
+               PublicKey _publicKey;
+               X500DistinguishedName issuer_name;
+               X500DistinguishedName subject_name;
+               Oid signature_algorithm;
+
+               MX.X509Certificate _cert;
+
+               static string empty_error = Locale.GetText ("Certificate instance is empty.");
+
+               public override bool IsValid {
+                       get {
+                               return _cert != null;
+                       }
+               }
+
+               public override IntPtr Handle {
+                       get { return IntPtr.Zero; }
+               }
+
+               internal X509Certificate2ImplMono (MX.X509Certificate cert)
+               {
+                       this._cert = cert;
+               }
+
+               public override X509CertificateImpl Clone ()
+               {
+                       ThrowIfContextInvalid ();
+                       return new X509Certificate2ImplMono (_cert);
+               }
+
+               #region Implemented X509CertificateImpl members
+
+               public override string GetIssuerName (bool legacyV1Mode)
+               {
+                       ThrowIfContextInvalid ();
+                       if (legacyV1Mode)
+                               return _cert.IssuerName;
+                       else
+                               return MX.X501.ToString (_cert.GetIssuerName (), true, ", ", true);
+               }
+
+               public override string GetSubjectName (bool legacyV1Mode)
+               {
+                       ThrowIfContextInvalid ();
+                       if (legacyV1Mode)
+                               return _cert.SubjectName;
+                       else
+                               return MX.X501.ToString (_cert.GetSubjectName (), true, ", ", true);
+               }
+
+               public override byte[] GetRawCertData ()
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.RawData;
+               }
+
+               protected override byte[] GetCertHash (bool lazy)
+               {
+                       ThrowIfContextInvalid ();
+                       SHA1 sha = SHA1.Create ();
+                       return sha.ComputeHash (_cert.RawData);
+               }
+
+               public override DateTime GetValidFrom ()
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.ValidFrom;
+               }
+
+               public override DateTime GetValidUntil ()
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.ValidUntil;
+               }
+
+               public override bool Equals (X509CertificateImpl other, out bool result)
+               {
+                       // Use default implementation
+                       result = false;
+                       return false;
+               }
+
+               public override string GetKeyAlgorithm () 
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.KeyAlgorithm;
+               }
+
+               public override byte[] GetKeyAlgorithmParameters () 
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.KeyAlgorithmParameters;
+               }
+
+               public override byte[] GetPublicKey ()
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.PublicKey;
+               }
+
+               public override byte[] GetSerialNumber ()
+               {
+                       ThrowIfContextInvalid ();
+                       return _cert.SerialNumber;
+               }
+
+               public override byte[] Export (X509ContentType contentType, byte[] password)
+               {
+                       ThrowIfContextInvalid ();
+
+                       switch (contentType) {
+                       case X509ContentType.Cert:
+                               return GetRawCertData ();
+                       case X509ContentType.Pfx: // this includes Pkcs12
+                               // TODO
+                               throw new NotSupportedException ();
+                       case X509ContentType.SerializedCert:
+                               // TODO
+                               throw new NotSupportedException ();
+                       default:
+                               string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
+                               throw new CryptographicException (msg);
+                       }
+               }
+
+               #endregion
+
+               // constructors
+
+               public X509Certificate2ImplMono ()
+               {
+                       _cert = null;
+               }
+
+               // properties
+
+               public override bool Archived {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               return _archived;
+                       }
+                       set {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               _archived = value;
+                       }
+               }
+
+               public override X509ExtensionCollection Extensions {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               if (_extensions == null)
+                                       _extensions = new X509ExtensionCollection (_cert);
+                               return _extensions;
+                       }
+               }
+
+               // FIXME - Could be more efficient
+               public override bool HasPrivateKey {
+                       get { return PrivateKey != null; }
+               }
+
+               public override X500DistinguishedName IssuerName {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               if (issuer_name == null)
+                                       issuer_name = new X500DistinguishedName (_cert.GetIssuerName ().GetBytes ());
+                               return issuer_name;
+                       }
+               } 
+
+               public override AsymmetricAlgorithm PrivateKey {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               try {
+                                       if (_cert.RSA != null) {
+                                               RSACryptoServiceProvider rcsp = _cert.RSA as RSACryptoServiceProvider;
+                                               if (rcsp != null)
+                                                       return rcsp.PublicOnly ? null : rcsp;
+
+                                               RSAManaged rsam = _cert.RSA as RSAManaged;
+                                               if (rsam != null)
+                                                       return rsam.PublicOnly ? null : rsam;
+
+                                               _cert.RSA.ExportParameters (true);
+                                               return _cert.RSA;
+                                       } else if (_cert.DSA != null) {
+                                               DSACryptoServiceProvider dcsp = _cert.DSA as DSACryptoServiceProvider;
+                                               if (dcsp != null)
+                                                       return dcsp.PublicOnly ? null : dcsp;
+
+                                               _cert.DSA.ExportParameters (true);
+                                               return _cert.DSA;
+                                       }
+                               }
+                               catch {
+                               }
+                               return null;
+                       }
+                       set {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+
+                               // allow NULL so we can "forget" the key associated to the certificate
+                               // e.g. in case we want to export it in another format (see bug #396620)
+                               if (value == null) {
+                                       _cert.RSA = null;
+                                       _cert.DSA = null;
+                               } else  if (value is RSA)
+                                       _cert.RSA = (RSA) value;
+                               else if (value is DSA)
+                                       _cert.DSA = (DSA) value;
+                               else
+                                       throw new NotSupportedException ();
+                       }
+               } 
+
+               public override PublicKey PublicKey {
+                       get { 
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+
+                               if (_publicKey == null) {
+                                       try {
+                                               _publicKey = new PublicKey (_cert);
+                                       }
+                                       catch (Exception e) {
+                                               string msg = Locale.GetText ("Unable to decode public key.");
+                                               throw new CryptographicException (msg, e);
+                                       }
+                               }
+                               return _publicKey;
+                       }
+               }
+
+               public override Oid SignatureAlgorithm {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+
+                               if (signature_algorithm == null)
+                                       signature_algorithm = new Oid (_cert.SignatureAlgorithm);
+                               return signature_algorithm;
+                       }
+               } 
+
+               public override X500DistinguishedName SubjectName {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+
+                               if (subject_name == null)
+                                       subject_name = new X500DistinguishedName (_cert.GetSubjectName ().GetBytes ());
+                               return subject_name;
+                       }
+               } 
+
+               public override int Version {
+                       get {
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               return _cert.Version;
+                       }
+               }
+
+               // methods
+
+               [MonoTODO ("always return String.Empty for UpnName, DnsFromAlternativeName and UrlName")]
+               public override string GetNameInfo (X509NameType nameType, bool forIssuer) 
+               {
+                       switch (nameType) {
+                       case X509NameType.SimpleName:
+                               if (_cert == null)
+                                       throw new CryptographicException (empty_error);
+                               // return CN= or, if missing, the first part of the DN
+                               ASN1 sn = forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ();
+                               ASN1 dn = Find (commonName, sn);
+                               if (dn != null)
+                                       return GetValueAsString (dn);
+                               if (sn.Count == 0)
+                                       return String.Empty;
+                               ASN1 last_entry = sn [sn.Count - 1];
+                               if (last_entry.Count == 0)
+                                       return String.Empty;
+                               return GetValueAsString (last_entry [0]);
+                       case X509NameType.EmailName:
+                               // return the E= part of the DN (if present)
+                               ASN1 e = Find (email, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
+                               if (e != null)
+                                       return GetValueAsString (e);
+                               return String.Empty;
+                       case X509NameType.UpnName:
+                               // FIXME - must find/create test case
+                               return String.Empty;
+                       case X509NameType.DnsName:
+                               // return the CN= part of the DN (if present)
+                               ASN1 cn = Find (commonName, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
+                               if (cn != null)
+                                       return GetValueAsString (cn);
+                               return String.Empty;
+                       case X509NameType.DnsFromAlternativeName:
+                               // FIXME - must find/create test case
+                               return String.Empty;
+                       case X509NameType.UrlName:
+                               // FIXME - must find/create test case
+                               return String.Empty;
+                       default:
+                               throw new ArgumentException ("nameType");
+                       }
+               }
+
+               static byte[] commonName = { 0x55, 0x04, 0x03 };
+               static byte[] email = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 };
+
+               private ASN1 Find (byte[] oid, ASN1 dn)
+               {
+                       if (dn.Count == 0)
+                               return null;
+
+                       // process SET
+                       for (int i = 0; i < dn.Count; i++) {
+                               ASN1 set = dn [i];
+                               for (int j = 0; j < set.Count; j++) {
+                                       ASN1 pair = set [j];
+                                       if (pair.Count != 2)
+                                               continue;
+
+                                       ASN1 poid = pair [0];
+                                       if (poid == null)
+                                               continue;
+
+                                       if (poid.CompareValue (oid))
+                                               return pair;
+                               }
+                       }
+                       return null;
+               }
+
+               private string GetValueAsString (ASN1 pair)
+               {
+                       if (pair.Count != 2)
+                               return String.Empty;
+
+                       ASN1 value = pair [1];
+                       if ((value.Value == null) || (value.Length == 0))
+                               return String.Empty;
+
+                       if (value.Tag == 0x1E) {
+                               // BMPSTRING
+                               StringBuilder sb = new StringBuilder ();
+                               for (int j = 1; j < value.Value.Length; j += 2)
+                                       sb.Append ((char)value.Value [j]);
+                               return sb.ToString ();
+                       } else {
+                               return Encoding.UTF8.GetString (value.Value);
+                       }
+               }
+
+               private MX.X509Certificate ImportPkcs12 (byte[] rawData, string password)
+               {
+                       MX.PKCS12 pfx = null;
+                       if (string.IsNullOrEmpty (password)) {
+                               try {
+                                       // Support both unencrypted PKCS#12..
+                                       pfx = new MX.PKCS12 (rawData, (string)null);
+                               } catch {
+                                       // ..and PKCS#12 encrypted with an empty password
+                                       pfx = new MX.PKCS12 (rawData, string.Empty);
+                               }
+                       } else {
+                               pfx = new MX.PKCS12 (rawData, password);
+                       }
+
+                       if (pfx.Certificates.Count == 0) {
+                               // no certificate was found
+                               return null;
+                       } else if (pfx.Keys.Count == 0) {
+                               // no key were found - pick the first certificate
+                               return pfx.Certificates [0];
+                       } else {
+                               // find the certificate that match the first key
+                               MX.X509Certificate cert = null;
+                               var keypair = (pfx.Keys [0] as AsymmetricAlgorithm);
+                               string pubkey = keypair.ToXmlString (false);
+                               foreach (var c in pfx.Certificates) {
+                                       if (((c.RSA != null) && (pubkey == c.RSA.ToXmlString (false))) ||
+                                               ((c.DSA != null) && (pubkey == c.DSA.ToXmlString (false)))) {
+                                               cert = c;
+                                               break;
+                                       }
+                               }
+                               if (cert == null) {
+                                       cert = pfx.Certificates [0]; // no match, pick first certificate without keys
+                               } else {
+                                       cert.RSA = (keypair as RSA);
+                                       cert.DSA = (keypair as DSA);
+                               }
+                               return cert;
+                       }
+               }
+
+               [MonoTODO ("missing KeyStorageFlags support")]
+               public override void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
+               {
+                       MX.X509Certificate cert = null;
+                       if (password == null) {
+                               try {
+                                       cert = new MX.X509Certificate (rawData);
+                               }
+                               catch (Exception e) {
+                                       try {
+                                               cert = ImportPkcs12 (rawData, null);
+                                       }
+                                       catch {
+                                               string msg = Locale.GetText ("Unable to decode certificate.");
+                                               // inner exception is the original (not second) exception
+                                               throw new CryptographicException (msg, e);
+                                       }
+                               }
+                       } else {
+                               // try PKCS#12
+                               try {
+                                       cert = ImportPkcs12 (rawData, password);
+                               }
+                               catch {
+                                       // it's possible to supply a (unrequired/unusued) password
+                                       // fix bug #79028
+                                       cert = new MX.X509Certificate (rawData);
+                               }
+                       }
+                       _cert = cert;
+               }
+
+               [MonoTODO ("X509ContentType.SerializedCert is not supported")]
+               public override byte[] Export (X509ContentType contentType, string password)
+               {
+                       if (_cert == null)
+                               throw new CryptographicException (empty_error);
+
+                       switch (contentType) {
+                       case X509ContentType.Cert:
+                               return _cert.RawData;
+                       case X509ContentType.Pfx: // this includes Pkcs12
+                               return ExportPkcs12 (password);
+                       case X509ContentType.SerializedCert:
+                               // TODO
+                               throw new NotSupportedException ();
+                       default:
+                               string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
+                               throw new CryptographicException (msg);
+                       }
+               }
+
+               byte[] ExportPkcs12 (string password)
+               {
+                       var pfx = new MX.PKCS12 ();
+                       try {
+                               var attrs = new Hashtable ();
+                               var localKeyId = new ArrayList ();
+                               localKeyId.Add (new byte[] { 1, 0, 0, 0 });
+                               attrs.Add (MX.PKCS9.localKeyId, localKeyId);
+
+                               if (password != null)
+                                       pfx.Password = password;
+                               pfx.AddCertificate (_cert, attrs);
+                               var privateKey = PrivateKey;
+                               if (privateKey != null)
+                                       pfx.AddPkcs8ShroudedKeyBag (privateKey, attrs);
+                               return pfx.GetBytes ();
+                       } finally {
+                               pfx.Password = null;
+                       }
+               }
+
+               public override void Reset () 
+               {
+                       _cert = null;
+                       _archived = false;
+                       _extensions = null;
+                       _serial = null;
+                       _publicKey = null;
+                       issuer_name = null;
+                       subject_name = null;
+                       signature_algorithm = null;
+               }
+
+               public override string ToString ()
+               {
+                       if (_cert == null)
+                               return "System.Security.Cryptography.X509Certificates.X509Certificate2";
+
+                       return ToString (true);
+               }
+
+               public override string ToString (bool verbose)
+               {
+                       if (_cert == null)
+                               return "System.Security.Cryptography.X509Certificates.X509Certificate2";
+
+                       string nl = Environment.NewLine;
+                       StringBuilder sb = new StringBuilder ();
+
+                       // the non-verbose X509Certificate2 == verbose X509Certificate
+                       if (!verbose) {
+                               sb.AppendFormat ("[Subject]{0}  {1}{0}{0}", nl, GetSubjectName (false));
+                               sb.AppendFormat ("[Issuer]{0}  {1}{0}{0}", nl, GetIssuerName (false));
+                               sb.AppendFormat ("[Not Before]{0}  {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ());
+                               sb.AppendFormat ("[Not After]{0}  {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ());
+                               sb.AppendFormat ("[Thumbprint]{0}  {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
+                               sb.Append (nl);
+                               return sb.ToString ();
+                       }
+
+                       sb.AppendFormat ("[Version]{0}  V{1}{0}{0}", nl, Version);
+                       sb.AppendFormat ("[Subject]{0}  {1}{0}{0}", nl, GetSubjectName (false));
+                       sb.AppendFormat ("[Issuer]{0}  {1}{0}{0}", nl, GetIssuerName (false));
+                       sb.AppendFormat ("[Serial Number]{0}  {1}{0}{0}", nl, GetSerialNumber ());
+                       sb.AppendFormat ("[Not Before]{0}  {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ());
+                       sb.AppendFormat ("[Not After]{0}  {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ());
+                       sb.AppendFormat ("[Thumbprint]{0}  {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
+                       sb.AppendFormat ("[Signature Algorithm]{0}  {1}({2}){0}{0}", nl, SignatureAlgorithm.FriendlyName, 
+                               SignatureAlgorithm.Value);
+
+                       AsymmetricAlgorithm key = PublicKey.Key;
+                       sb.AppendFormat ("[Public Key]{0}  Algorithm: ", nl);
+                       if (key is RSA)
+                               sb.Append ("RSA");
+                       else if (key is DSA)
+                               sb.Append ("DSA");
+                       else
+                               sb.Append (key.ToString ());
+                       sb.AppendFormat ("{0}  Length: {1}{0}  Key Blob: ", nl, key.KeySize);
+                       AppendBuffer (sb, PublicKey.EncodedKeyValue.RawData);
+                       sb.AppendFormat ("{0}  Parameters: ", nl);
+                       AppendBuffer (sb, PublicKey.EncodedParameters.RawData);
+                       sb.Append (nl);
+
+                       return sb.ToString ();
+               }
+
+               private static void AppendBuffer (StringBuilder sb, byte[] buffer)
+               {
+                       if (buffer == null)
+                               return;
+                       for (int i=0; i < buffer.Length; i++) {
+                               sb.Append (buffer [i].ToString ("x2"));
+                               if (i < buffer.Length - 1)
+                                       sb.Append (" ");
+                       }
+               }
+
+               [MonoTODO ("by default this depends on the incomplete X509Chain")]
+               public override bool Verify (X509Certificate2 thisCertificate)
+               {
+                       if (_cert == null)
+                               throw new CryptographicException (empty_error);
+
+                       X509Chain chain = X509Chain.Create ();
+                       if (!chain.Build (thisCertificate))
+                               return false;
+                       // TODO - check chain and other stuff ???
+                       return true;
+               }
+
+               // static methods
+
+               private static byte[] signedData = new byte[] { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02 };
+
+               [MonoTODO ("Detection limited to Cert, Pfx, Pkcs12, Pkcs7 and Unknown")]
+               public static X509ContentType GetCertContentType (byte[] rawData)
+               {
+                       if ((rawData == null) || (rawData.Length == 0))
+                               throw new ArgumentException ("rawData");
+
+                       X509ContentType type = X509ContentType.Unknown;
+                       try {
+                               ASN1 data = new ASN1 (rawData);
+                               if (data.Tag != 0x30) {
+                                       string msg = Locale.GetText ("Unable to decode certificate.");
+                                       throw new CryptographicException (msg);
+                               }
+
+                               if (data.Count == 0)
+                                       return type;
+
+                               if (data.Count == 3) {
+                                       switch (data [0].Tag) {
+                                       case 0x30:
+                                               // SEQUENCE / SEQUENCE / BITSTRING
+                                               if ((data [1].Tag == 0x30) && (data [2].Tag == 0x03))
+                                                       type = X509ContentType.Cert;
+                                               break;
+                                       case 0x02:
+                                               // INTEGER / SEQUENCE / SEQUENCE
+                                               if ((data [1].Tag == 0x30) && (data [2].Tag == 0x30))
+                                                       type = X509ContentType.Pkcs12;
+                                               // note: Pfx == Pkcs12
+                                               break;
+                                       }
+                               }
+                               // check for PKCS#7 (count unknown but greater than 0)
+                               // SEQUENCE / OID (signedData)
+                               if ((data [0].Tag == 0x06) && data [0].CompareValue (signedData))
+                                       type = X509ContentType.Pkcs7;
+                       }
+                       catch (Exception e) {
+                               string msg = Locale.GetText ("Unable to decode certificate.");
+                               throw new CryptographicException (msg, e);
+                       }
+
+                       return type;
+               }
+
+               [MonoTODO ("Detection limited to Cert, Pfx, Pkcs12 and Unknown")]
+               public static X509ContentType GetCertContentType (string fileName)
+               {
+                       if (fileName == null)
+                               throw new ArgumentNullException ("fileName");
+                       if (fileName.Length == 0)
+                               throw new ArgumentException ("fileName");
+
+                       byte[] data = File.ReadAllBytes (fileName);
+                       return GetCertContentType (data);
+               }
+
+               // internal stuff because X509Certificate2 isn't complete enough
+               // (maybe X509Certificate3 will be better?)
+
+               internal MX.X509Certificate MonoCertificate {
+                       get { return _cert; }
+               }
+       }
+}
+
+#endif
index 9910f3982705c9187eb3a6e9415a507cd9b3e61a..a7c24d385f8fe38d227f6609085127b4bf604c6a 100644 (file)
@@ -42,23 +42,27 @@ using System.Text;
 
 namespace System.Security.Cryptography.X509Certificates {
 
-       public class X509Chain {
+       public class X509Chain : IDisposable {
 
-               private StoreLocation location;
-               private X509ChainElementCollection elements;
-               private X509ChainPolicy policy;
-               private X509ChainStatus[] status;
+               X509ChainImpl impl;
 
                static X509ChainStatus[] Empty = new X509ChainStatus [0];
 
-               // RFC3280 variables
-               private int max_path_length;
-               private X500DistinguishedName working_issuer_name;
-//             private string working_public_key_algorithm;
-               private AsymmetricAlgorithm working_public_key;
+               internal X509ChainImpl Impl {
+                       get {
+                               X509Helper2.ThrowIfContextInvalid (impl);
+                               return impl;
+                       }
+               }
 
-               // other flags
-               private X509ChainElement bce_restriction;
+               internal bool IsValid {
+                       get { return X509Helper2.IsValid (impl); }
+               }
+
+               internal void ThrowIfContextInvalid ()
+               {
+                       X509Helper2.ThrowIfContextInvalid (impl);
+               }
 
                // constructors
 
@@ -69,9 +73,13 @@ namespace System.Security.Cryptography.X509Certificates {
 
                public X509Chain (bool useMachineContext) 
                {
-                       location = useMachineContext ? StoreLocation.LocalMachine : StoreLocation.CurrentUser;
-                       elements = new X509ChainElementCollection ();
-                       policy = new X509ChainPolicy ();
+                       impl = X509Helper2.CreateChainImpl (useMachineContext);
+               }
+
+               internal X509Chain (X509ChainImpl impl)
+               {
+                       X509Helper2.ThrowIfContextInvalid (impl);
+                       this.impl = impl;
                }
 
                [MonoTODO ("Mono's X509Chain is fully managed. All handles are invalid.")]
@@ -85,153 +93,37 @@ namespace System.Security.Cryptography.X509Certificates {
 
                [MonoTODO ("Mono's X509Chain is fully managed. Always returns IntPtr.Zero.")]
                public IntPtr ChainContext {
-                       get { return IntPtr.Zero; }
+                       get {
+                               if (impl != null && impl.IsValid)
+                                       return impl.Handle;
+                               return IntPtr.Zero;
+                       }
                }
 
                public X509ChainElementCollection ChainElements {
-                       get { return elements; }
+                       get { return Impl.ChainElements; }
                }
 
                public X509ChainPolicy ChainPolicy {
-                       get { return policy; }
-                       set { policy = value; }
+                       get { return Impl.ChainPolicy; }
+                       set { Impl.ChainPolicy = value; }
                }
 
                public X509ChainStatus[] ChainStatus {
-                       get { 
-                               if (status == null)
-                                       return Empty;
-                               return status;
-                       }
-               } 
+                       get { return Impl.ChainStatus; }
+               }
 
                // methods
 
                [MonoTODO ("Not totally RFC3280 compliant, but neither is MS implementation...")]
                public bool Build (X509Certificate2 certificate)
                {
-                       if (certificate == null)
-                               throw new ArgumentException ("certificate");
-
-                       Reset ();
-                       X509ChainStatusFlags flag;
-                       try {
-                               flag = BuildChainFrom (certificate);
-                               ValidateChain (flag);
-                       }
-                       catch (CryptographicException ce) {
-                               throw new ArgumentException ("certificate", ce);
-                       }
-
-                       X509ChainStatusFlags total = X509ChainStatusFlags.NoError;
-                       ArrayList list = new ArrayList ();
-                       // build "global" ChainStatus from the ChainStatus of every ChainElements
-                       foreach (X509ChainElement ce in elements) {
-                               foreach (X509ChainStatus cs in ce.ChainElementStatus) {
-                                       // we MUST avoid duplicates in the "global" list
-                                       if ((total & cs.Status) != cs.Status) {
-                                               list.Add (cs);
-                                               total |= cs.Status;
-                                       }
-                               }
-                       }
-                       // and if required add some
-                       if (flag != X509ChainStatusFlags.NoError) {
-                               list.Insert (0, new X509ChainStatus (flag));
-                       }
-                       status = (X509ChainStatus[]) list.ToArray (typeof (X509ChainStatus));
-
-                       // (fast path) this ignore everything we have checked
-                       if ((status.Length == 0) || (ChainPolicy.VerificationFlags == X509VerificationFlags.AllFlags))
-                               return true;
-
-                       bool result = true;
-                       // now check if exclude some verification for the "end result" (boolean)
-                       foreach (X509ChainStatus cs in status) {
-                               switch (cs.Status) {
-                               case X509ChainStatusFlags.UntrustedRoot:
-                               case X509ChainStatusFlags.PartialChain:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.AllowUnknownCertificateAuthority) != 0);
-                                       break;
-                               case X509ChainStatusFlags.NotTimeValid:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeValid) != 0);
-                                       break;
-                               // FIXME - from here we needs new test cases for all cases
-                               case X509ChainStatusFlags.NotTimeNested:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeNested) != 0);
-                                       break;
-                               case X509ChainStatusFlags.InvalidBasicConstraints:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidBasicConstraints) != 0);
-                                       break;
-                               case X509ChainStatusFlags.InvalidPolicyConstraints:
-                               case X509ChainStatusFlags.NoIssuanceChainPolicy:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidPolicy) != 0);
-                                       break;
-                               case X509ChainStatusFlags.InvalidNameConstraints:
-                               case X509ChainStatusFlags.HasNotSupportedNameConstraint:
-                               case X509ChainStatusFlags.HasNotPermittedNameConstraint:
-                               case X509ChainStatusFlags.HasExcludedNameConstraint:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidName) != 0);
-                                       break;
-                               case X509ChainStatusFlags.InvalidExtension:
-                                       // not sure ?!?
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
-                                       break;
-                               //
-                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreRootRevocationUnknown) != 0)
-                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreEndRevocationUnknown) != 0)
-                               case X509ChainStatusFlags.CtlNotTimeValid:
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlNotTimeValid) != 0);
-                                       break;
-                               case X509ChainStatusFlags.CtlNotSignatureValid:
-                                       // ?
-                                       break;
-                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlSignerRevocationUnknown) != 0);
-                               case X509ChainStatusFlags.CtlNotValidForUsage:
-                                       // FIXME - does IgnoreWrongUsage apply to CTL (it doesn't have Ctl in it's name like the others)
-                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
-                                       break;
-                               default:
-                                       result = false;
-                                       break;
-                               }
-                               // once we have one failure there's no need to check further
-                               if (!result)
-                                       return false;
-                       }
-
-                       // every "problem" was excluded
-                       return true;
+                       return Impl.Build (certificate);
                }
 
                public void Reset () 
                {
-                       // note: this call doesn't Reset the X509ChainPolicy
-                       if ((status != null) && (status.Length != 0))
-                               status = null;
-                       if (elements.Count > 0)
-                               elements.Clear ();
-                       if (user_root_store != null) {
-                               user_root_store.Close ();
-                               user_root_store = null;
-                       }
-                       if (root_store != null) {
-                               root_store.Close ();
-                               root_store = null;
-                       }
-                       if (user_ca_store != null) {
-                               user_ca_store.Close ();
-                               user_ca_store = null;
-                       }
-                       if (ca_store != null) {
-                               ca_store.Close ();
-                               ca_store = null;
-                       }
-                       roots = null;
-                       cas = null;
-                       collection = null;
-                       bce_restriction = null;
-                       working_public_key = null;
+                       Impl.Reset ();
                }
 
                // static methods
@@ -245,717 +137,23 @@ namespace System.Security.Cryptography.X509Certificates {
 #endif
                }
 
-               // private stuff
-
-               private X509Certificate2Collection roots;
-               private X509Certificate2Collection cas;
-               private X509Store root_store;
-               private X509Store ca_store;
-               private X509Store user_root_store;
-               private X509Store user_ca_store;
-
-               private X509Certificate2Collection Roots {
-                       get {
-                               if (roots == null) {
-                                       X509Certificate2Collection c = new X509Certificate2Collection ();
-                                       X509Store store = LMRootStore;
-                                       if (location == StoreLocation.CurrentUser)
-                                               c.AddRange (UserRootStore.Certificates);
-                                       c.AddRange (store.Certificates);
-                                       roots = c;
-                               }
-                               return roots;
-                       }
-               }
-
-               private X509Certificate2Collection CertificateAuthorities {
-                       get {
-                               if (cas == null) {
-                                       X509Certificate2Collection c = new X509Certificate2Collection ();
-                                       X509Store store = LMCAStore;
-                                       if (location == StoreLocation.CurrentUser)
-                                               c.AddRange (UserCAStore.Certificates);
-                                       c.AddRange (store.Certificates);
-                                       cas = c;
-                               }
-                               return cas;
-                       }
-               }
-
-               private X509Store LMRootStore {
-                       get {
-                               if (root_store == null) {
-                                       root_store = new X509Store (StoreName.Root, StoreLocation.LocalMachine);
-                                       try {
-                                               root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
-                                       } catch {
-                                       }
-                               }
-                               return root_store;
-                       }
-               }
-
-               private X509Store UserRootStore {
-                       get {
-                               if (user_root_store == null) {
-                                       user_root_store = new X509Store (StoreName.Root, StoreLocation.CurrentUser);
-                                       try {
-                                               user_root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
-                                       } catch {
-                                       }
-                               }
-                               return user_root_store;
-                       }
-               }
-
-               private X509Store LMCAStore {
-                       get {
-                               if (ca_store == null) {
-                                       ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.LocalMachine);
-                                       try {
-                                               ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
-                                       } catch {
-                                       }
-                               }
-                               return ca_store;
-                       }
-               }
-
-               private X509Store UserCAStore {
-                       get {
-                               if (user_ca_store == null) {
-                                       user_ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.CurrentUser);
-                                       try {
-                                               user_ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
-                                       } catch {
-                                       }
-                               }
-                               return user_ca_store;
-                       }
-               }
-               // *** certificate chain/path building stuff ***
-
-               private X509Certificate2Collection collection;
-
-               // we search local user (default) or machine certificate store 
-               // and in the extra certificate supplied in ChainPolicy.ExtraStore
-               private X509Certificate2Collection CertificateCollection {
-                       get {
-                               if (collection == null) {
-                                       collection = new X509Certificate2Collection (ChainPolicy.ExtraStore);
-                                       collection.AddRange (Roots);
-                                       collection.AddRange (CertificateAuthorities);
-                               }
-                               return collection;
-                       }
-               }
-
-               // This is a non-recursive chain/path building algorithm. 
-               //
-               // At this stage we only checks for PartialChain, Cyclic and UntrustedRoot errors are they
-               // affect the path building (other errors are verification errors).
-               //
-               // Note that the order match the one we need to match MS and not the one defined in RFC3280,
-               // we also include the trusted root certificate (trust anchor in RFC3280) in the list.
-               // (this isn't an issue, just keep that in mind if you look at the source and the RFC)
-               private X509ChainStatusFlags BuildChainFrom (X509Certificate2 certificate)
-               {
-                       elements.Add (certificate);
-
-                       while (!IsChainComplete (certificate)) {
-                               certificate = FindParent (certificate);
-
-                               if (certificate == null)
-                                       return X509ChainStatusFlags.PartialChain;
-
-                               if (elements.Contains (certificate))
-                                       return X509ChainStatusFlags.Cyclic;
-
-                               elements.Add (certificate);
-                       }
-
-                       // roots may be supplied (e.g. in the ExtraStore) so we need to confirm their
-                       // trustiness (what a cute word) in the trusted root collection
-                       if (!Roots.Contains (certificate))
-                               elements [elements.Count - 1].StatusFlags |= X509ChainStatusFlags.UntrustedRoot;
-
-                       return X509ChainStatusFlags.NoError;
-               }
-
-
-               private X509Certificate2 SelectBestFromCollection (X509Certificate2 child, X509Certificate2Collection c)
-               {
-                       switch (c.Count) {
-                       case 0:
-                               return null;
-                       case 1:
-                               return c [0];
-                       default:
-                               // multiple candidate, keep only the ones that are still valid
-                               X509Certificate2Collection time_valid = c.Find (X509FindType.FindByTimeValid, ChainPolicy.VerificationTime, false);
-                               switch (time_valid.Count) {
-                               case 0:
-                                       // that's too restrictive, let's revert and try another thing...
-                                       time_valid = c;
-                                       break;
-                               case 1:
-                                       return time_valid [0];
-                               default:
-                                       break;
-                               }
-
-                               // again multiple candidates, let's find the AKI that match the SKI (if we have one)
-                               string aki = GetAuthorityKeyIdentifier (child);
-                               if (String.IsNullOrEmpty (aki)) {
-                                       return time_valid [0]; // FIXME: out of luck, you get the first one
-                               }
-                               foreach (X509Certificate2 parent in time_valid) {
-                                       string ski = GetSubjectKeyIdentifier (parent);
-                                       // if both id are available then they must match
-                                       if (aki == ski)
-                                               return parent;
-                               }
-                               return time_valid [0]; // FIXME: out of luck, you get the first one
-                       }
-               }
-
-               private X509Certificate2 FindParent (X509Certificate2 certificate)
-               {
-                       X509Certificate2Collection subset = CertificateCollection.Find (X509FindType.FindBySubjectDistinguishedName, certificate.Issuer, false);
-                       string aki = GetAuthorityKeyIdentifier (certificate);
-                       if ((aki != null) && (aki.Length > 0)) {
-                               subset.AddRange (CertificateCollection.Find (X509FindType.FindBySubjectKeyIdentifier, aki, false));
-                       }
-                       X509Certificate2 parent = SelectBestFromCollection (certificate, subset);
-                       // if parent==certificate we're looping but it's not (probably) a bug and not a true cyclic (over n certs)
-                       return certificate.Equals (parent) ? null : parent;
-               }
-
-               private bool IsChainComplete (X509Certificate2 certificate)
+               public void Dispose ()
                {
-                       // the chain is complete if we have a self-signed certificate
-                       if (!IsSelfIssued (certificate))
-                               return false;
-
-                       // we're very limited to what we can do without certificate extensions
-                       if (certificate.Version < 3)
-                               return true;
-
-                       // check that Authority Key Identifier == Subject Key Identifier
-                       // e.g. it will be different if a self-signed certificate is part (not the end) of the chain
-                       string ski = GetSubjectKeyIdentifier (certificate);
-                       if (String.IsNullOrEmpty (ski))
-                               return true;
-                       string aki = GetAuthorityKeyIdentifier (certificate);
-                       if (String.IsNullOrEmpty (aki))
-                               return true;
-                       // if both id are available then they must match
-                       return (aki == ski);
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
                }
 
-               // check for "self-issued" certificate - without verifying the signature
-               // note that self-issued doesn't always mean it's a root certificate!
-               private bool IsSelfIssued (X509Certificate2 certificate)
+               protected virtual void Dispose (bool disposing)
                {
-                       return (certificate.Issuer == certificate.Subject);
-               }
-
-
-               // *** certificate chain/path validation stuff ***
-
-               // Currently a subset of RFC3280 (hopefully a full implementation someday)
-               private void ValidateChain (X509ChainStatusFlags flag)
-               {
-                       // 'n' should be the root certificate... 
-                       int n = elements.Count - 1;
-                       X509Certificate2 certificate = elements [n].Certificate;
-
-                       // ... and, if so, must be treated outside the chain... 
-                       if (((flag & X509ChainStatusFlags.PartialChain) == 0)) {
-                               Process (n);
-                               // deal with the case where the chain == the root certificate 
-                               // (which isn't for RFC3280) part of the chain
-                               if (n == 0) {
-                                       elements [0].UncompressFlags ();
-                                       return;
-                               }
-                               // skip the root certificate when processing the chain (in 6.1.3)
-                               n--;
-                       }
-                       // ... unless the chain is a partial one (then we start with that one)
-
-                       // 6.1.1 - Inputs
-                       // 6.1.1.a - a prospective certificate path of length n (i.e. elements)
-                       // 6.1.1.b - the current date/time (i.e. ChainPolicy.VerificationTime)
-                       // 6.1.1.c - user-initial-policy-set (i.e. ChainPolicy.CertificatePolicy)
-                       // 6.1.1.d - the trust anchor information (i.e. certificate, unless it's a partial chain)
-                       // 6.1.1.e - initial-policy-mapping-inhibit (NOT SUPPORTED BY THE API)
-                       // 6.1.1.f - initial-explicit-policy (NOT SUPPORTED BY THE API)
-                       // 6.1.1.g - initial-any-policy-inhibit (NOT SUPPORTED BY THE API)
-
-                       // 6.1.2 - Initialization (incomplete)
-                       // 6.1.2.a-f - policy stuff, some TODO, some not supported
-                       // 6.1.2.g - working public key algorithm
-//                     working_public_key_algorithm = certificate.PublicKey.Oid.Value;
-                       // 6.1.2.h-i - our key contains both the "working public key" and "working public key parameters" data
-                       working_public_key = certificate.PublicKey.Key;
-                       // 6.1.2.j - working issuer name
-                       working_issuer_name = certificate.IssuerName;
-                       // 6.1.2.k - this integer is initialized to n, is decremented for each non-self-issued, certificate and
-                       //           may be reduced to the value in the path length constraint field
-                       max_path_length = n;
-
-                       // 6.1.3 - Basic Certificate Processing
-                       // note: loop looks reversed (the list is) but we process this part just like RFC3280 does
-                       for (int i = n; i > 0; i--) {
-                               Process (i);
-                               // 6.1.4 - preparation for certificate i+1 (for not with i+1, or i-1 in our loop)
-                               PrepareForNextCertificate (i);
+                       if (impl != null) {
+                               impl.Dispose ();
+                               impl = null;
                        }
-                       Process (0);
-
-                       // 6.1.3.a.3 - revocation checks
-                       CheckRevocationOnChain (flag);
-
-                       // 6.1.5 - Wrap-up procedure
-                       WrapUp ();
                }
 
-               private void Process (int n)
+               ~X509Chain ()
                {
-                       X509ChainElement element = elements [n];
-                       X509Certificate2 certificate = element.Certificate;
-
-                       // pre-step: DSA certificates may inherit the parameters of their CA
-                       if ((n != elements.Count - 1) && (certificate.MonoCertificate.KeyAlgorithm == "1.2.840.10040.4.1")) {
-                               if (certificate.MonoCertificate.KeyAlgorithmParameters == null) {
-                                       X509Certificate2 parent = elements [n+1].Certificate;
-                                       certificate.MonoCertificate.KeyAlgorithmParameters = parent.MonoCertificate.KeyAlgorithmParameters;
-                               }
-                       }
-
-                       bool root = (working_public_key == null);
-                       // 6.1.3.a.1 - check signature (with special case to deal with root certificates)
-                       if (!IsSignedWith (certificate, root ? certificate.PublicKey.Key : working_public_key)) {
-                               // another special case where only an end-entity is available and can't be verified.
-                               // In this case we do not report an invalid signature (since this is unknown)
-                               if (root || (n != elements.Count - 1) || IsSelfIssued (certificate)) {
-                                       element.StatusFlags |= X509ChainStatusFlags.NotSignatureValid;
-                               }
-                       }
-
-                       // 6.1.3.a.2 - check validity period
-                       if ((ChainPolicy.VerificationTime < certificate.NotBefore) ||
-                               (ChainPolicy.VerificationTime > certificate.NotAfter)) {
-                               element.StatusFlags |= X509ChainStatusFlags.NotTimeValid;
-                       }
-                       // TODO - for X509ChainStatusFlags.NotTimeNested (needs global structure)
-
-                       // note: most of them don't apply to the root certificate
-                       if (root) {
-                               return;
-                       }
-
-                       // 6.1.3.a.3 - revocation check (we're doing at the last stage)
-                       // note: you revoke a trusted root by removing it from your trusted store (i.e. no CRL can do this job)
-
-                       // 6.1.3.a.4 - check certificate issuer name
-                       if (!X500DistinguishedName.AreEqual (certificate.IssuerName, working_issuer_name)) {
-                               // NOTE: this is not the "right" error flag, but it's the closest one defined
-                               element.StatusFlags |= X509ChainStatusFlags.InvalidNameConstraints;
-                       }
-
-                       if (!IsSelfIssued (certificate) && (n != 0)) {
-                               // TODO 6.1.3.b - subject name in the permitted_subtrees ...
-                               // TODO 6.1.3.c - subject name not within excluded_subtrees...
-
-                               // TODO - check for X509ChainStatusFlags.InvalidNameConstraint
-                               // TODO - check for X509ChainStatusFlags.HasNotSupportedNameConstraint
-                               // TODO - check for X509ChainStatusFlags.HasNotPermittedNameConstraint
-                               // TODO - check for X509ChainStatusFlags.HasExcludedNameConstraint
-                       }
-
-                       // TODO 6.1.3.d - check if certificate policies extension is present
-                       //if (false) {
-                               // TODO - for X509ChainStatusFlags.InvalidPolicyConstraints
-                               //      using X509ChainPolicy.ApplicationPolicy and X509ChainPolicy.CertificatePolicy
-
-                               // TODO - check for X509ChainStatusFlags.NoIssuanceChainPolicy
-
-                       //} else {
-                               // TODO 6.1.3.e - set valid_policy_tree to NULL
-                       //}
-
-                       // TODO 6.1.3.f - verify explict_policy > 0 if valid_policy_tree != NULL
-               }
-
-               // CTL == Certificate Trust List / NOT SUPPORTED
-               // TODO - check for X509ChainStatusFlags.CtlNotTimeValid
-               // TODO - check for X509ChainStatusFlags.CtlNotSignatureValid
-               // TODO - check for X509ChainStatusFlags.CtlNotValidForUsage
-
-               private void PrepareForNextCertificate (int n) 
-               {
-                       X509ChainElement element = elements [n];
-                       X509Certificate2 certificate = element.Certificate;
-
-                       // TODO 6.1.4.a-b
-
-                       // 6.1.4.c
-                       working_issuer_name = certificate.SubjectName;
-                       // 6.1.4.d-e - our key includes both the public key and it's parameters
-                       working_public_key = certificate.PublicKey.Key;
-                       // 6.1.4.f
-//                     working_public_key_algorithm = certificate.PublicKey.Oid.Value;
-
-                       // TODO 6.1.4.g-j
-
-                       // 6.1.4.k - Verify that the certificate is a CA certificate
-                       X509BasicConstraintsExtension bce = (certificate.Extensions["2.5.29.19"] as X509BasicConstraintsExtension);
-                       if (bce != null) {
-                               if (!bce.CertificateAuthority) {
-                                       element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
-                               }
-                       } else if (certificate.Version >= 3) {
-                               // recent (v3+) CA certificates must include BCE
-                               element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
-                       }
-
-                       // 6.1.4.l - if the certificate isn't self-issued...
-                       if (!IsSelfIssued (certificate)) {
-                               // ... verify that max_path_length > 0
-                               if (max_path_length > 0) {
-                                       max_path_length--;
-                               } else {
-                                       // to match MS the reported status must be against the certificate 
-                                       // with the BCE and not where the path is too long. It also means
-                                       // that this condition has to be reported only once
-                                       if (bce_restriction != null) {
-                                               bce_restriction.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
-                                       }
-                               }
-                       }
-
-                       // 6.1.4.m - if pathLengthConstraint is present...
-                       if ((bce != null) && (bce.HasPathLengthConstraint)) {
-                               // ... and is less that max_path_length, set max_path_length to it's value
-                               if (bce.PathLengthConstraint < max_path_length) {
-                                       max_path_length = bce.PathLengthConstraint;
-                                       bce_restriction = element;
-                               }
-                       }
-
-                       // 6.1.4.n - if key usage extension is present...
-                       X509KeyUsageExtension kue = (certificate.Extensions["2.5.29.15"] as X509KeyUsageExtension);
-                       if (kue != null) {
-                               // ... verify keyCertSign is set
-                               X509KeyUsageFlags success = X509KeyUsageFlags.KeyCertSign;
-                               if ((kue.KeyUsages & success) != success)
-                                       element.StatusFlags |= X509ChainStatusFlags.NotValidForUsage;
-                       }
-
-                       // 6.1.4.o - recognize and process other critical extension present in the certificate
-                       ProcessCertificateExtensions (element);
-               }
-
-               private void WrapUp ()
-               {
-                       X509ChainElement element = elements [0];
-                       X509Certificate2 certificate = element.Certificate;
-
-                       // 6.1.5.a - TODO if certificate n (our 0) wasn't self issued and explicit_policy != 0
-                       if (IsSelfIssued (certificate)) {
-                               // TODO... decrement explicit_policy by 1
-                       }
-
-                       // 6.1.5.b - TODO
-
-                       // 6.1.5.c,d,e - not required by the X509Chain implementation
-
-                       // 6.1.5.f - recognize and process other critical extension present in the certificate
-                       ProcessCertificateExtensions (element);
-
-                       // 6.1.5.g - TODO
-
-                       // uncompressed the flags into several elements
-                       for (int i = elements.Count - 1; i >= 0; i--) {
-                               elements [i].UncompressFlags ();
-                       }
-               }
-
-               private void ProcessCertificateExtensions (X509ChainElement element)
-               {
-                       foreach (X509Extension ext in element.Certificate.Extensions) {
-                               if (ext.Critical) {
-                                       switch (ext.Oid.Value) {
-                                       case "2.5.29.15": // X509KeyUsageExtension
-                                       case "2.5.29.19": // X509BasicConstraintsExtension
-                                               // we processed this extension
-                                               break;
-                                       default:
-                                               // note: Under Windows XP MS implementation seems to ignore 
-                                               // certificate with unknown critical extensions.
-                                               element.StatusFlags |= X509ChainStatusFlags.InvalidExtension;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-
-               private bool IsSignedWith (X509Certificate2 signed, AsymmetricAlgorithm pubkey)
-               {
-                       if (pubkey == null)
-                               return false;
-                       // Sadly X509Certificate2 doesn't expose the signature nor the tbs (to be signed) structure
-                       MX.X509Certificate mx = signed.MonoCertificate;
-                       return (mx.VerifySignature (pubkey));
-               }
-
-               private string GetSubjectKeyIdentifier (X509Certificate2 certificate)
-               {
-                       X509SubjectKeyIdentifierExtension ski = (certificate.Extensions["2.5.29.14"] as X509SubjectKeyIdentifierExtension);
-                       return (ski == null) ? String.Empty : ski.SubjectKeyIdentifier;
-               }
-
-               // System.dll v2 doesn't have a class to deal with the AuthorityKeyIdentifier extension
-               static string GetAuthorityKeyIdentifier (X509Certificate2 certificate)
-               {
-                       return GetAuthorityKeyIdentifier (certificate.MonoCertificate.Extensions ["2.5.29.35"]);
-               }
-
-               // but anyway System.dll v2 doesn't expose CRL in any way so...
-               static string GetAuthorityKeyIdentifier (MX.X509Crl crl)
-               {
-                       return GetAuthorityKeyIdentifier (crl.Extensions ["2.5.29.35"]);
-               }
-
-               static string GetAuthorityKeyIdentifier (MX.X509Extension ext)
-               {
-                       if (ext == null)
-                               return String.Empty;
-                       MX.Extensions.AuthorityKeyIdentifierExtension aki = new MX.Extensions.AuthorityKeyIdentifierExtension (ext);
-                       byte[] id = aki.Identifier;
-                       if (id == null) 
-                               return String.Empty;
-                       StringBuilder sb = new StringBuilder ();
-                       foreach (byte b in id)
-                               sb.Append (b.ToString ("X02"));
-                       return sb.ToString ();
-               }
-
-               // we check the revocation only once we have built the complete chain
-               private void CheckRevocationOnChain (X509ChainStatusFlags flag)
-               {
-                       bool partial = ((flag & X509ChainStatusFlags.PartialChain) != 0);
-                       bool online;
-
-                       switch (ChainPolicy.RevocationMode) {
-                       case X509RevocationMode.Online:
-                               // default
-                               online = true;
-                               break;
-                       case X509RevocationMode.Offline:
-                               online = false;
-                               break;
-                       case X509RevocationMode.NoCheck:
-                               return;
-                       default:
-                               throw new InvalidOperationException (Locale.GetText ("Invalid revocation mode."));
-                       }
-
-                       bool unknown = partial;
-                       // from the root down to the end-entity
-                       for (int i = elements.Count - 1; i >= 0; i--) {
-                               bool check = true;
-
-                               switch (ChainPolicy.RevocationFlag) {
-                               case X509RevocationFlag.EndCertificateOnly:
-                                       check = (i == 0);
-                                       break;
-                               case X509RevocationFlag.EntireChain:
-                                       check = true;
-                                       break;
-                               case X509RevocationFlag.ExcludeRoot:
-                                       // default
-                                       check = (i != (elements.Count - 1));
-                                       // anyway, who's gonna sign that the root is invalid ?
-                                       break;
-                               }
-
-                               X509ChainElement element = elements [i];
-
-                               // we can't assume the revocation status if the certificate is bad (e.g. invalid signature)
-                               if (!unknown)
-                                       unknown |= ((element.StatusFlags & X509ChainStatusFlags.NotSignatureValid) != 0);
-
-                               if (unknown) {
-                                       // we can skip the revocation checks as we can't be sure of them anyway
-                                       element.StatusFlags |= X509ChainStatusFlags.RevocationStatusUnknown;
-                                       element.StatusFlags |= X509ChainStatusFlags.OfflineRevocation;
-                               } else if (check && !partial && !IsSelfIssued (element.Certificate)) {
-                                       // check for revocation (except for the trusted root and self-issued certs)
-                                       element.StatusFlags |= CheckRevocation (element.Certificate, i+1, online);
-                                       // if revoked, then all others following in the chain are unknown...
-                                       unknown |= ((element.StatusFlags & X509ChainStatusFlags.Revoked) != 0);
-                               }
-                       }
-               }
-
-               // This isn't how RFC3280 (section 6.3) deals with CRL, but then we don't (yet) support DP, deltas...
-               private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, int ca, bool online)
-               {
-                       X509ChainStatusFlags result = X509ChainStatusFlags.RevocationStatusUnknown;
-                       X509ChainElement element = elements [ca];
-                       X509Certificate2 ca_cert = element.Certificate;
-
-                       // find the CRL from the "right" CA
-                       while (IsSelfIssued (ca_cert) && (ca < elements.Count - 1)) {
-                               // try with this self-issued
-                               result = CheckRevocation (certificate, ca_cert, online);
-                               if (result != X509ChainStatusFlags.RevocationStatusUnknown)
-                                       break;
-                               ca++;
-                               element = elements [ca];
-                               ca_cert = element.Certificate;
-                       }
-                       if (result == X509ChainStatusFlags.RevocationStatusUnknown)
-                               result = CheckRevocation (certificate, ca_cert, online);
-                       return result;
-               }
-
-               private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, X509Certificate2 ca_cert, bool online)
-               {
-                       // change this if/when we support OCSP
-                       X509KeyUsageExtension kue = (ca_cert.Extensions["2.5.29.15"] as X509KeyUsageExtension);
-                       if (kue != null) {
-                               // ... verify CrlSign is set
-                               X509KeyUsageFlags success = X509KeyUsageFlags.CrlSign;
-                               if ((kue.KeyUsages & success) != success) {
-                                       // FIXME - we should try to find an alternative CA that has the CrlSign bit
-                                       return X509ChainStatusFlags.RevocationStatusUnknown;
-                               }
-                       }
-
-                       MX.X509Crl crl = FindCrl (ca_cert);
-
-                       if ((crl == null) && online) {
-                               // FIXME - download and install new CRL
-                               // then you get a second chance
-                               // crl = FindCrl (ca_cert, ref valid, ref out_of_date);
-
-                               // We need to get the subjectAltName and an URI from there (or use OCSP)        
-                               // X509KeyUsageExtension subjectAltName = (ca_cert.Extensions["2.5.29.17"] as X509KeyUsageExtension);
-                       }
-
-                       if (crl != null) {
-                               // validate the digital signature on the CRL using the CA public key
-                               // note #1: we can't use X509Crl.VerifySignature(X509Certificate) because it duplicates
-                               // checks and we loose the "why" of the failure
-                               // note #2: we do this before other tests as an invalid signature could be a hacked CRL
-                               // (so anything within can't be trusted)
-                               if (!crl.VerifySignature (ca_cert.PublicKey.Key)) {
-                                       return X509ChainStatusFlags.RevocationStatusUnknown;
-                               }
-
-                               MX.X509Crl.X509CrlEntry entry = crl.GetCrlEntry (certificate.MonoCertificate);
-                               if (entry != null) {
-                                       // We have an entry for this CRL that includes an unknown CRITICAL extension
-                                       // See [X.509 7.3] NOTE 4
-                                       if (!ProcessCrlEntryExtensions (entry))
-                                               return X509ChainStatusFlags.Revoked;
-
-                                       // FIXME - a little more is involved
-                                       if (entry.RevocationDate <= ChainPolicy.VerificationTime)
-                                               return X509ChainStatusFlags.Revoked;
-                               }
-
-                               // are we overdue for a CRL update ? if so we can't be sure of any certificate status
-                               if (crl.NextUpdate < ChainPolicy.VerificationTime)
-                                       return X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation;
-
-                               // we have a CRL that includes an unknown CRITICAL extension
-                               // we put this check at the end so we do not "hide" any Revoked flags
-                               if (!ProcessCrlExtensions (crl)) {
-                                       return X509ChainStatusFlags.RevocationStatusUnknown;
-                               }
-                       } else {
-                               return X509ChainStatusFlags.RevocationStatusUnknown;
-                       }
-
-                       return X509ChainStatusFlags.NoError;
-               }
-
-               static MX.X509Crl CheckCrls (string subject, string ski, MX.X509Store store)
-               {
-                       if (store == null)
-                               return null;
-
-                       var crls = store.Crls;
-                       foreach (MX.X509Crl crl in crls) {
-                               if (crl.IssuerName == subject && (ski.Length == 0 || ski == GetAuthorityKeyIdentifier (crl)))
-                                       return crl;
-                       }
-                       return null; // No CRL found
-               }
-
-               private MX.X509Crl FindCrl (X509Certificate2 caCertificate)
-               {
-                       string subject = caCertificate.SubjectName.Decode (X500DistinguishedNameFlags.None);
-                       string ski = GetSubjectKeyIdentifier (caCertificate);
-
-                       // consider that the LocalMachine directories could not exists... and cannot be created by the user
-                       MX.X509Crl result = CheckCrls (subject, ski, LMCAStore.Store);
-                       if (result != null)
-                               return result;
-                       if (location == StoreLocation.CurrentUser) {
-                               result = CheckCrls (subject, ski, UserCAStore.Store);
-                               if (result != null)
-                                       return result;
-                       }
-
-                       // consider that the LocalMachine directories could not exists... and cannot be created by the user
-                       result = CheckCrls (subject, ski, LMRootStore.Store);
-                       if (result != null)
-                               return result;
-                       if (location == StoreLocation.CurrentUser) {
-                               result = CheckCrls (subject, ski, UserRootStore.Store);
-                               if (result != null)
-                                       return result;
-                       }
-                       return null;
-               }
-
-               private bool ProcessCrlExtensions (MX.X509Crl crl)
-               {
-                       foreach (MX.X509Extension ext in crl.Extensions) {
-                               if (ext.Critical) {
-                                       switch (ext.Oid) {
-                                       case "2.5.29.20": // cRLNumber
-                                       case "2.5.29.35": // authorityKeyIdentifier
-                                               // we processed/know about this extension
-                                               break;
-                                       default:
-                                               return false;
-                                       }
-                               }
-                       }
-                       return true;
-               }
-
-               private bool ProcessCrlEntryExtensions (MX.X509Crl.X509CrlEntry entry)
-               {
-                       foreach (MX.X509Extension ext in entry.Extensions) {
-                               if (ext.Critical) {
-                                       switch (ext.Oid) {
-                                       case "2.5.29.21": // cRLReason
-                                               // we processed/know about this extension
-                                               break;
-                                       default:
-                                               return false;
-                                       }
-                               }
-                       }
-                       return true;
+                       Dispose (false);
                }
        }
 }
diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImpl.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImpl.cs
new file mode 100644 (file)
index 0000000..2a4c9cf
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// X509ChainImpl.cs
+//
+// Authors:
+//     Martin Baulig  <martin.baulig@xamarin.com>
+//
+// Copyright (C) 2016 Xamarin, Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+#if SECURITY_DEP
+
+namespace System.Security.Cryptography.X509Certificates
+{
+       internal abstract class X509ChainImpl : IDisposable
+       {
+               public abstract bool IsValid {
+                       get;
+               }
+
+               public abstract IntPtr Handle {
+                       get;
+               }
+
+               protected void ThrowIfContextInvalid ()
+               {
+                       if (!IsValid)
+                               throw X509Helper2.GetInvalidChainContextException ();
+               }
+
+               public abstract X509ChainElementCollection ChainElements {
+                       get;
+               }
+
+               public abstract X509ChainPolicy ChainPolicy {
+                       get; set;
+               }
+
+               public abstract X509ChainStatus[] ChainStatus {
+                       get;
+               }
+
+               public abstract bool Build (X509Certificate2 certificate);
+
+               public abstract void Reset ();
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+               }
+
+               ~X509ChainImpl ()
+               {
+                       Dispose (false);
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs
new file mode 100644 (file)
index 0000000..210bd8f
--- /dev/null
@@ -0,0 +1,954 @@
+//
+// System.Security.Cryptography.X509Certificates.X509ChainImplMono
+//
+// Author:
+//     Sebastien Pouliot  <sebastien@ximian.com>
+//
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
+// Copyright (C) 2011 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if SECURITY_DEP
+
+#if MONO_SECURITY_ALIAS
+extern alias MonoSecurity;
+using MX = MonoSecurity::Mono.Security.X509;
+#else
+using MX = Mono.Security.X509;
+#endif
+
+using System.Collections;
+using System.Text;
+
+namespace System.Security.Cryptography.X509Certificates {
+
+       internal class X509ChainImplMono : X509ChainImpl
+       {
+               private StoreLocation location;
+               private X509ChainElementCollection elements;
+               private X509ChainPolicy policy;
+               private X509ChainStatus[] status;
+
+               static X509ChainStatus[] Empty = new X509ChainStatus [0];
+
+               // RFC3280 variables
+               private int max_path_length;
+               private X500DistinguishedName working_issuer_name;
+//             private string working_public_key_algorithm;
+               private AsymmetricAlgorithm working_public_key;
+
+               // other flags
+               private X509ChainElement bce_restriction;
+
+               // constructors
+
+               public X509ChainImplMono ()
+                       : this (false)
+               {
+               }
+
+               public X509ChainImplMono (bool useMachineContext) 
+               {
+                       location = useMachineContext ? StoreLocation.LocalMachine : StoreLocation.CurrentUser;
+                       elements = new X509ChainElementCollection ();
+                       policy = new X509ChainPolicy ();
+               }
+
+               [MonoTODO ("Mono's X509Chain is fully managed. All handles are invalid.")]
+               public X509ChainImplMono (IntPtr chainContext)
+               {
+                       // CryptoAPI compatibility (unmanaged handle)
+                       throw new NotSupportedException ();
+               }
+
+               public override bool IsValid {
+                       get { return true; }
+               }
+
+               public override IntPtr Handle {
+                       get { return IntPtr.Zero; }
+               }
+
+               // properties
+
+               public override X509ChainElementCollection ChainElements {
+                       get { return elements; }
+               }
+
+               public override X509ChainPolicy ChainPolicy {
+                       get { return policy; }
+                       set { policy = value; }
+               }
+
+               public override X509ChainStatus[] ChainStatus {
+                       get { 
+                               if (status == null)
+                                       return Empty;
+                               return status;
+                       }
+               } 
+
+               // methods
+
+               [MonoTODO ("Not totally RFC3280 compliant, but neither is MS implementation...")]
+               public override bool Build (X509Certificate2 certificate)
+               {
+                       if (certificate == null)
+                               throw new ArgumentException ("certificate");
+
+                       Reset ();
+                       X509ChainStatusFlags flag;
+                       try {
+                               flag = BuildChainFrom (certificate);
+                               ValidateChain (flag);
+                       }
+                       catch (CryptographicException ce) {
+                               throw new ArgumentException ("certificate", ce);
+                       }
+
+                       X509ChainStatusFlags total = X509ChainStatusFlags.NoError;
+                       ArrayList list = new ArrayList ();
+                       // build "global" ChainStatus from the ChainStatus of every ChainElements
+                       foreach (X509ChainElement ce in elements) {
+                               foreach (X509ChainStatus cs in ce.ChainElementStatus) {
+                                       // we MUST avoid duplicates in the "global" list
+                                       if ((total & cs.Status) != cs.Status) {
+                                               list.Add (cs);
+                                               total |= cs.Status;
+                                       }
+                               }
+                       }
+                       // and if required add some
+                       if (flag != X509ChainStatusFlags.NoError) {
+                               list.Insert (0, new X509ChainStatus (flag));
+                       }
+                       status = (X509ChainStatus[]) list.ToArray (typeof (X509ChainStatus));
+
+                       // (fast path) this ignore everything we have checked
+                       if ((status.Length == 0) || (ChainPolicy.VerificationFlags == X509VerificationFlags.AllFlags))
+                               return true;
+
+                       bool result = true;
+                       // now check if exclude some verification for the "end result" (boolean)
+                       foreach (X509ChainStatus cs in status) {
+                               switch (cs.Status) {
+                               case X509ChainStatusFlags.UntrustedRoot:
+                               case X509ChainStatusFlags.PartialChain:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.AllowUnknownCertificateAuthority) != 0);
+                                       break;
+                               case X509ChainStatusFlags.NotTimeValid:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeValid) != 0);
+                                       break;
+                               // FIXME - from here we needs new test cases for all cases
+                               case X509ChainStatusFlags.NotTimeNested:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeNested) != 0);
+                                       break;
+                               case X509ChainStatusFlags.InvalidBasicConstraints:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidBasicConstraints) != 0);
+                                       break;
+                               case X509ChainStatusFlags.InvalidPolicyConstraints:
+                               case X509ChainStatusFlags.NoIssuanceChainPolicy:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidPolicy) != 0);
+                                       break;
+                               case X509ChainStatusFlags.InvalidNameConstraints:
+                               case X509ChainStatusFlags.HasNotSupportedNameConstraint:
+                               case X509ChainStatusFlags.HasNotPermittedNameConstraint:
+                               case X509ChainStatusFlags.HasExcludedNameConstraint:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidName) != 0);
+                                       break;
+                               case X509ChainStatusFlags.InvalidExtension:
+                                       // not sure ?!?
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
+                                       break;
+                               //
+                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreRootRevocationUnknown) != 0)
+                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreEndRevocationUnknown) != 0)
+                               case X509ChainStatusFlags.CtlNotTimeValid:
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlNotTimeValid) != 0);
+                                       break;
+                               case X509ChainStatusFlags.CtlNotSignatureValid:
+                                       // ?
+                                       break;
+                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlSignerRevocationUnknown) != 0);
+                               case X509ChainStatusFlags.CtlNotValidForUsage:
+                                       // FIXME - does IgnoreWrongUsage apply to CTL (it doesn't have Ctl in it's name like the others)
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
+                                       break;
+                               default:
+                                       result = false;
+                                       break;
+                               }
+                               // once we have one failure there's no need to check further
+                               if (!result)
+                                       return false;
+                       }
+
+                       // every "problem" was excluded
+                       return true;
+               }
+
+               public override void Reset () 
+               {
+                       // note: this call doesn't Reset the X509ChainPolicy
+                       if ((status != null) && (status.Length != 0))
+                               status = null;
+                       if (elements.Count > 0)
+                               elements.Clear ();
+                       if (user_root_store != null) {
+                               user_root_store.Close ();
+                               user_root_store = null;
+                       }
+                       if (root_store != null) {
+                               root_store.Close ();
+                               root_store = null;
+                       }
+                       if (user_ca_store != null) {
+                               user_ca_store.Close ();
+                               user_ca_store = null;
+                       }
+                       if (ca_store != null) {
+                               ca_store.Close ();
+                               ca_store = null;
+                       }
+                       roots = null;
+                       cas = null;
+                       collection = null;
+                       bce_restriction = null;
+                       working_public_key = null;
+               }
+
+               // private stuff
+
+               private X509Certificate2Collection roots;
+               private X509Certificate2Collection cas;
+               private X509Store root_store;
+               private X509Store ca_store;
+               private X509Store user_root_store;
+               private X509Store user_ca_store;
+
+               private X509Certificate2Collection Roots {
+                       get {
+                               if (roots == null) {
+                                       X509Certificate2Collection c = new X509Certificate2Collection ();
+                                       X509Store store = LMRootStore;
+                                       if (location == StoreLocation.CurrentUser)
+                                               c.AddRange (UserRootStore.Certificates);
+                                       c.AddRange (store.Certificates);
+                                       roots = c;
+                               }
+                               return roots;
+                       }
+               }
+
+               private X509Certificate2Collection CertificateAuthorities {
+                       get {
+                               if (cas == null) {
+                                       X509Certificate2Collection c = new X509Certificate2Collection ();
+                                       X509Store store = LMCAStore;
+                                       if (location == StoreLocation.CurrentUser)
+                                               c.AddRange (UserCAStore.Certificates);
+                                       c.AddRange (store.Certificates);
+                                       cas = c;
+                               }
+                               return cas;
+                       }
+               }
+
+               private X509Store LMRootStore {
+                       get {
+                               if (root_store == null) {
+                                       root_store = new X509Store (StoreName.Root, StoreLocation.LocalMachine);
+                                       try {
+                                               root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
+                                       } catch {
+                                       }
+                               }
+                               return root_store;
+                       }
+               }
+
+               private X509Store UserRootStore {
+                       get {
+                               if (user_root_store == null) {
+                                       user_root_store = new X509Store (StoreName.Root, StoreLocation.CurrentUser);
+                                       try {
+                                               user_root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
+                                       } catch {
+                                       }
+                               }
+                               return user_root_store;
+                       }
+               }
+
+               private X509Store LMCAStore {
+                       get {
+                               if (ca_store == null) {
+                                       ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.LocalMachine);
+                                       try {
+                                               ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
+                                       } catch {
+                                       }
+                               }
+                               return ca_store;
+                       }
+               }
+
+               private X509Store UserCAStore {
+                       get {
+                               if (user_ca_store == null) {
+                                       user_ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.CurrentUser);
+                                       try {
+                                               user_ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
+                                       } catch {
+                                       }
+                               }
+                               return user_ca_store;
+                       }
+               }
+               // *** certificate chain/path building stuff ***
+
+               private X509Certificate2Collection collection;
+
+               // we search local user (default) or machine certificate store 
+               // and in the extra certificate supplied in ChainPolicy.ExtraStore
+               private X509Certificate2Collection CertificateCollection {
+                       get {
+                               if (collection == null) {
+                                       collection = new X509Certificate2Collection (ChainPolicy.ExtraStore);
+                                       collection.AddRange (Roots);
+                                       collection.AddRange (CertificateAuthorities);
+                               }
+                               return collection;
+                       }
+               }
+
+               // This is a non-recursive chain/path building algorithm. 
+               //
+               // At this stage we only checks for PartialChain, Cyclic and UntrustedRoot errors are they
+               // affect the path building (other errors are verification errors).
+               //
+               // Note that the order match the one we need to match MS and not the one defined in RFC3280,
+               // we also include the trusted root certificate (trust anchor in RFC3280) in the list.
+               // (this isn't an issue, just keep that in mind if you look at the source and the RFC)
+               private X509ChainStatusFlags BuildChainFrom (X509Certificate2 certificate)
+               {
+                       elements.Add (certificate);
+
+                       while (!IsChainComplete (certificate)) {
+                               certificate = FindParent (certificate);
+
+                               if (certificate == null)
+                                       return X509ChainStatusFlags.PartialChain;
+
+                               if (elements.Contains (certificate))
+                                       return X509ChainStatusFlags.Cyclic;
+
+                               elements.Add (certificate);
+                       }
+
+                       // roots may be supplied (e.g. in the ExtraStore) so we need to confirm their
+                       // trustiness (what a cute word) in the trusted root collection
+                       if (!Roots.Contains (certificate))
+                               elements [elements.Count - 1].StatusFlags |= X509ChainStatusFlags.UntrustedRoot;
+
+                       return X509ChainStatusFlags.NoError;
+               }
+
+
+               private X509Certificate2 SelectBestFromCollection (X509Certificate2 child, X509Certificate2Collection c)
+               {
+                       switch (c.Count) {
+                       case 0:
+                               return null;
+                       case 1:
+                               return c [0];
+                       default:
+                               // multiple candidate, keep only the ones that are still valid
+                               X509Certificate2Collection time_valid = c.Find (X509FindType.FindByTimeValid, ChainPolicy.VerificationTime, false);
+                               switch (time_valid.Count) {
+                               case 0:
+                                       // that's too restrictive, let's revert and try another thing...
+                                       time_valid = c;
+                                       break;
+                               case 1:
+                                       return time_valid [0];
+                               default:
+                                       break;
+                               }
+
+                               // again multiple candidates, let's find the AKI that match the SKI (if we have one)
+                               string aki = GetAuthorityKeyIdentifier (child);
+                               if (String.IsNullOrEmpty (aki)) {
+                                       return time_valid [0]; // FIXME: out of luck, you get the first one
+                               }
+                               foreach (X509Certificate2 parent in time_valid) {
+                                       string ski = GetSubjectKeyIdentifier (parent);
+                                       // if both id are available then they must match
+                                       if (aki == ski)
+                                               return parent;
+                               }
+                               return time_valid [0]; // FIXME: out of luck, you get the first one
+                       }
+               }
+
+               private X509Certificate2 FindParent (X509Certificate2 certificate)
+               {
+                       X509Certificate2Collection subset = CertificateCollection.Find (X509FindType.FindBySubjectDistinguishedName, certificate.Issuer, false);
+                       string aki = GetAuthorityKeyIdentifier (certificate);
+                       if ((aki != null) && (aki.Length > 0)) {
+                               subset.AddRange (CertificateCollection.Find (X509FindType.FindBySubjectKeyIdentifier, aki, false));
+                       }
+                       X509Certificate2 parent = SelectBestFromCollection (certificate, subset);
+                       // if parent==certificate we're looping but it's not (probably) a bug and not a true cyclic (over n certs)
+                       return certificate.Equals (parent) ? null : parent;
+               }
+
+               private bool IsChainComplete (X509Certificate2 certificate)
+               {
+                       // the chain is complete if we have a self-signed certificate
+                       if (!IsSelfIssued (certificate))
+                               return false;
+
+                       // we're very limited to what we can do without certificate extensions
+                       if (certificate.Version < 3)
+                               return true;
+
+                       // check that Authority Key Identifier == Subject Key Identifier
+                       // e.g. it will be different if a self-signed certificate is part (not the end) of the chain
+                       string ski = GetSubjectKeyIdentifier (certificate);
+                       if (String.IsNullOrEmpty (ski))
+                               return true;
+                       string aki = GetAuthorityKeyIdentifier (certificate);
+                       if (String.IsNullOrEmpty (aki))
+                               return true;
+                       // if both id are available then they must match
+                       return (aki == ski);
+               }
+
+               // check for "self-issued" certificate - without verifying the signature
+               // note that self-issued doesn't always mean it's a root certificate!
+               private bool IsSelfIssued (X509Certificate2 certificate)
+               {
+                       return (certificate.Issuer == certificate.Subject);
+               }
+
+
+               // *** certificate chain/path validation stuff ***
+
+               // Currently a subset of RFC3280 (hopefully a full implementation someday)
+               private void ValidateChain (X509ChainStatusFlags flag)
+               {
+                       // 'n' should be the root certificate... 
+                       int n = elements.Count - 1;
+                       X509Certificate2 certificate = elements [n].Certificate;
+
+                       // ... and, if so, must be treated outside the chain... 
+                       if (((flag & X509ChainStatusFlags.PartialChain) == 0)) {
+                               Process (n);
+                               // deal with the case where the chain == the root certificate 
+                               // (which isn't for RFC3280) part of the chain
+                               if (n == 0) {
+                                       elements [0].UncompressFlags ();
+                                       return;
+                               }
+                               // skip the root certificate when processing the chain (in 6.1.3)
+                               n--;
+                       }
+                       // ... unless the chain is a partial one (then we start with that one)
+
+                       // 6.1.1 - Inputs
+                       // 6.1.1.a - a prospective certificate path of length n (i.e. elements)
+                       // 6.1.1.b - the current date/time (i.e. ChainPolicy.VerificationTime)
+                       // 6.1.1.c - user-initial-policy-set (i.e. ChainPolicy.CertificatePolicy)
+                       // 6.1.1.d - the trust anchor information (i.e. certificate, unless it's a partial chain)
+                       // 6.1.1.e - initial-policy-mapping-inhibit (NOT SUPPORTED BY THE API)
+                       // 6.1.1.f - initial-explicit-policy (NOT SUPPORTED BY THE API)
+                       // 6.1.1.g - initial-any-policy-inhibit (NOT SUPPORTED BY THE API)
+
+                       // 6.1.2 - Initialization (incomplete)
+                       // 6.1.2.a-f - policy stuff, some TODO, some not supported
+                       // 6.1.2.g - working public key algorithm
+//                     working_public_key_algorithm = certificate.PublicKey.Oid.Value;
+                       // 6.1.2.h-i - our key contains both the "working public key" and "working public key parameters" data
+                       working_public_key = certificate.PublicKey.Key;
+                       // 6.1.2.j - working issuer name
+                       working_issuer_name = certificate.IssuerName;
+                       // 6.1.2.k - this integer is initialized to n, is decremented for each non-self-issued, certificate and
+                       //           may be reduced to the value in the path length constraint field
+                       max_path_length = n;
+
+                       // 6.1.3 - Basic Certificate Processing
+                       // note: loop looks reversed (the list is) but we process this part just like RFC3280 does
+                       for (int i = n; i > 0; i--) {
+                               Process (i);
+                               // 6.1.4 - preparation for certificate i+1 (for not with i+1, or i-1 in our loop)
+                               PrepareForNextCertificate (i);
+                       }
+                       Process (0);
+
+                       // 6.1.3.a.3 - revocation checks
+                       CheckRevocationOnChain (flag);
+
+                       // 6.1.5 - Wrap-up procedure
+                       WrapUp ();
+               }
+
+               private void Process (int n)
+               {
+                       X509ChainElement element = elements [n];
+                       X509Certificate2 certificate = element.Certificate;
+
+                       // pre-step: DSA certificates may inherit the parameters of their CA
+                       if ((n != elements.Count - 1) && (certificate.MonoCertificate.KeyAlgorithm == "1.2.840.10040.4.1")) {
+                               if (certificate.MonoCertificate.KeyAlgorithmParameters == null) {
+                                       X509Certificate2 parent = elements [n+1].Certificate;
+                                       certificate.MonoCertificate.KeyAlgorithmParameters = parent.MonoCertificate.KeyAlgorithmParameters;
+                               }
+                       }
+
+                       bool root = (working_public_key == null);
+                       // 6.1.3.a.1 - check signature (with special case to deal with root certificates)
+                       if (!IsSignedWith (certificate, root ? certificate.PublicKey.Key : working_public_key)) {
+                               // another special case where only an end-entity is available and can't be verified.
+                               // In this case we do not report an invalid signature (since this is unknown)
+                               if (root || (n != elements.Count - 1) || IsSelfIssued (certificate)) {
+                                       element.StatusFlags |= X509ChainStatusFlags.NotSignatureValid;
+                               }
+                       }
+
+                       // 6.1.3.a.2 - check validity period
+                       if ((ChainPolicy.VerificationTime < certificate.NotBefore) ||
+                               (ChainPolicy.VerificationTime > certificate.NotAfter)) {
+                               element.StatusFlags |= X509ChainStatusFlags.NotTimeValid;
+                       }
+                       // TODO - for X509ChainStatusFlags.NotTimeNested (needs global structure)
+
+                       // note: most of them don't apply to the root certificate
+                       if (root) {
+                               return;
+                       }
+
+                       // 6.1.3.a.3 - revocation check (we're doing at the last stage)
+                       // note: you revoke a trusted root by removing it from your trusted store (i.e. no CRL can do this job)
+
+                       // 6.1.3.a.4 - check certificate issuer name
+                       if (!X500DistinguishedName.AreEqual (certificate.IssuerName, working_issuer_name)) {
+                               // NOTE: this is not the "right" error flag, but it's the closest one defined
+                               element.StatusFlags |= X509ChainStatusFlags.InvalidNameConstraints;
+                       }
+
+                       if (!IsSelfIssued (certificate) && (n != 0)) {
+                               // TODO 6.1.3.b - subject name in the permitted_subtrees ...
+                               // TODO 6.1.3.c - subject name not within excluded_subtrees...
+
+                               // TODO - check for X509ChainStatusFlags.InvalidNameConstraint
+                               // TODO - check for X509ChainStatusFlags.HasNotSupportedNameConstraint
+                               // TODO - check for X509ChainStatusFlags.HasNotPermittedNameConstraint
+                               // TODO - check for X509ChainStatusFlags.HasExcludedNameConstraint
+                       }
+
+                       // TODO 6.1.3.d - check if certificate policies extension is present
+                       //if (false) {
+                               // TODO - for X509ChainStatusFlags.InvalidPolicyConstraints
+                               //      using X509ChainPolicy.ApplicationPolicy and X509ChainPolicy.CertificatePolicy
+
+                               // TODO - check for X509ChainStatusFlags.NoIssuanceChainPolicy
+
+                       //} else {
+                               // TODO 6.1.3.e - set valid_policy_tree to NULL
+                       //}
+
+                       // TODO 6.1.3.f - verify explict_policy > 0 if valid_policy_tree != NULL
+               }
+
+               // CTL == Certificate Trust List / NOT SUPPORTED
+               // TODO - check for X509ChainStatusFlags.CtlNotTimeValid
+               // TODO - check for X509ChainStatusFlags.CtlNotSignatureValid
+               // TODO - check for X509ChainStatusFlags.CtlNotValidForUsage
+
+               private void PrepareForNextCertificate (int n) 
+               {
+                       X509ChainElement element = elements [n];
+                       X509Certificate2 certificate = element.Certificate;
+
+                       // TODO 6.1.4.a-b
+
+                       // 6.1.4.c
+                       working_issuer_name = certificate.SubjectName;
+                       // 6.1.4.d-e - our key includes both the public key and it's parameters
+                       working_public_key = certificate.PublicKey.Key;
+                       // 6.1.4.f
+//                     working_public_key_algorithm = certificate.PublicKey.Oid.Value;
+
+                       // TODO 6.1.4.g-j
+
+                       // 6.1.4.k - Verify that the certificate is a CA certificate
+                       X509BasicConstraintsExtension bce = (certificate.Extensions["2.5.29.19"] as X509BasicConstraintsExtension);
+                       if (bce != null) {
+                               if (!bce.CertificateAuthority) {
+                                       element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
+                               }
+                       } else if (certificate.Version >= 3) {
+                               // recent (v3+) CA certificates must include BCE
+                               element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
+                       }
+
+                       // 6.1.4.l - if the certificate isn't self-issued...
+                       if (!IsSelfIssued (certificate)) {
+                               // ... verify that max_path_length > 0
+                               if (max_path_length > 0) {
+                                       max_path_length--;
+                               } else {
+                                       // to match MS the reported status must be against the certificate 
+                                       // with the BCE and not where the path is too long. It also means
+                                       // that this condition has to be reported only once
+                                       if (bce_restriction != null) {
+                                               bce_restriction.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
+                                       }
+                               }
+                       }
+
+                       // 6.1.4.m - if pathLengthConstraint is present...
+                       if ((bce != null) && (bce.HasPathLengthConstraint)) {
+                               // ... and is less that max_path_length, set max_path_length to it's value
+                               if (bce.PathLengthConstraint < max_path_length) {
+                                       max_path_length = bce.PathLengthConstraint;
+                                       bce_restriction = element;
+                               }
+                       }
+
+                       // 6.1.4.n - if key usage extension is present...
+                       X509KeyUsageExtension kue = (certificate.Extensions["2.5.29.15"] as X509KeyUsageExtension);
+                       if (kue != null) {
+                               // ... verify keyCertSign is set
+                               X509KeyUsageFlags success = X509KeyUsageFlags.KeyCertSign;
+                               if ((kue.KeyUsages & success) != success)
+                                       element.StatusFlags |= X509ChainStatusFlags.NotValidForUsage;
+                       }
+
+                       // 6.1.4.o - recognize and process other critical extension present in the certificate
+                       ProcessCertificateExtensions (element);
+               }
+
+               private void WrapUp ()
+               {
+                       X509ChainElement element = elements [0];
+                       X509Certificate2 certificate = element.Certificate;
+
+                       // 6.1.5.a - TODO if certificate n (our 0) wasn't self issued and explicit_policy != 0
+                       if (IsSelfIssued (certificate)) {
+                               // TODO... decrement explicit_policy by 1
+                       }
+
+                       // 6.1.5.b - TODO
+
+                       // 6.1.5.c,d,e - not required by the X509Chain implementation
+
+                       // 6.1.5.f - recognize and process other critical extension present in the certificate
+                       ProcessCertificateExtensions (element);
+
+                       // 6.1.5.g - TODO
+
+                       // uncompressed the flags into several elements
+                       for (int i = elements.Count - 1; i >= 0; i--) {
+                               elements [i].UncompressFlags ();
+                       }
+               }
+
+               private void ProcessCertificateExtensions (X509ChainElement element)
+               {
+                       foreach (X509Extension ext in element.Certificate.Extensions) {
+                               if (ext.Critical) {
+                                       switch (ext.Oid.Value) {
+                                       case "2.5.29.15": // X509KeyUsageExtension
+                                       case "2.5.29.19": // X509BasicConstraintsExtension
+                                               // we processed this extension
+                                               break;
+                                       default:
+                                               // note: Under Windows XP MS implementation seems to ignore 
+                                               // certificate with unknown critical extensions.
+                                               element.StatusFlags |= X509ChainStatusFlags.InvalidExtension;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               private bool IsSignedWith (X509Certificate2 signed, AsymmetricAlgorithm pubkey)
+               {
+                       if (pubkey == null)
+                               return false;
+                       // Sadly X509Certificate2 doesn't expose the signature nor the tbs (to be signed) structure
+                       MX.X509Certificate mx = signed.MonoCertificate;
+                       return (mx.VerifySignature (pubkey));
+               }
+
+               private string GetSubjectKeyIdentifier (X509Certificate2 certificate)
+               {
+                       X509SubjectKeyIdentifierExtension ski = (certificate.Extensions["2.5.29.14"] as X509SubjectKeyIdentifierExtension);
+                       return (ski == null) ? String.Empty : ski.SubjectKeyIdentifier;
+               }
+
+               // System.dll v2 doesn't have a class to deal with the AuthorityKeyIdentifier extension
+               static string GetAuthorityKeyIdentifier (X509Certificate2 certificate)
+               {
+                       return GetAuthorityKeyIdentifier (certificate.MonoCertificate.Extensions ["2.5.29.35"]);
+               }
+
+               // but anyway System.dll v2 doesn't expose CRL in any way so...
+               static string GetAuthorityKeyIdentifier (MX.X509Crl crl)
+               {
+                       return GetAuthorityKeyIdentifier (crl.Extensions ["2.5.29.35"]);
+               }
+
+               static string GetAuthorityKeyIdentifier (MX.X509Extension ext)
+               {
+                       if (ext == null)
+                               return String.Empty;
+                       MX.Extensions.AuthorityKeyIdentifierExtension aki = new MX.Extensions.AuthorityKeyIdentifierExtension (ext);
+                       byte[] id = aki.Identifier;
+                       if (id == null) 
+                               return String.Empty;
+                       StringBuilder sb = new StringBuilder ();
+                       foreach (byte b in id)
+                               sb.Append (b.ToString ("X02"));
+                       return sb.ToString ();
+               }
+
+               // we check the revocation only once we have built the complete chain
+               private void CheckRevocationOnChain (X509ChainStatusFlags flag)
+               {
+                       bool partial = ((flag & X509ChainStatusFlags.PartialChain) != 0);
+                       bool online;
+
+                       switch (ChainPolicy.RevocationMode) {
+                       case X509RevocationMode.Online:
+                               // default
+                               online = true;
+                               break;
+                       case X509RevocationMode.Offline:
+                               online = false;
+                               break;
+                       case X509RevocationMode.NoCheck:
+                               return;
+                       default:
+                               throw new InvalidOperationException (Locale.GetText ("Invalid revocation mode."));
+                       }
+
+                       bool unknown = partial;
+                       // from the root down to the end-entity
+                       for (int i = elements.Count - 1; i >= 0; i--) {
+                               bool check = true;
+
+                               switch (ChainPolicy.RevocationFlag) {
+                               case X509RevocationFlag.EndCertificateOnly:
+                                       check = (i == 0);
+                                       break;
+                               case X509RevocationFlag.EntireChain:
+                                       check = true;
+                                       break;
+                               case X509RevocationFlag.ExcludeRoot:
+                                       // default
+                                       check = (i != (elements.Count - 1));
+                                       // anyway, who's gonna sign that the root is invalid ?
+                                       break;
+                               }
+
+                               X509ChainElement element = elements [i];
+
+                               // we can't assume the revocation status if the certificate is bad (e.g. invalid signature)
+                               if (!unknown)
+                                       unknown |= ((element.StatusFlags & X509ChainStatusFlags.NotSignatureValid) != 0);
+
+                               if (unknown) {
+                                       // we can skip the revocation checks as we can't be sure of them anyway
+                                       element.StatusFlags |= X509ChainStatusFlags.RevocationStatusUnknown;
+                                       element.StatusFlags |= X509ChainStatusFlags.OfflineRevocation;
+                               } else if (check && !partial && !IsSelfIssued (element.Certificate)) {
+                                       // check for revocation (except for the trusted root and self-issued certs)
+                                       element.StatusFlags |= CheckRevocation (element.Certificate, i+1, online);
+                                       // if revoked, then all others following in the chain are unknown...
+                                       unknown |= ((element.StatusFlags & X509ChainStatusFlags.Revoked) != 0);
+                               }
+                       }
+               }
+
+               // This isn't how RFC3280 (section 6.3) deals with CRL, but then we don't (yet) support DP, deltas...
+               private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, int ca, bool online)
+               {
+                       X509ChainStatusFlags result = X509ChainStatusFlags.RevocationStatusUnknown;
+                       X509ChainElement element = elements [ca];
+                       X509Certificate2 ca_cert = element.Certificate;
+
+                       // find the CRL from the "right" CA
+                       while (IsSelfIssued (ca_cert) && (ca < elements.Count - 1)) {
+                               // try with this self-issued
+                               result = CheckRevocation (certificate, ca_cert, online);
+                               if (result != X509ChainStatusFlags.RevocationStatusUnknown)
+                                       break;
+                               ca++;
+                               element = elements [ca];
+                               ca_cert = element.Certificate;
+                       }
+                       if (result == X509ChainStatusFlags.RevocationStatusUnknown)
+                               result = CheckRevocation (certificate, ca_cert, online);
+                       return result;
+               }
+
+               private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, X509Certificate2 ca_cert, bool online)
+               {
+                       // change this if/when we support OCSP
+                       X509KeyUsageExtension kue = (ca_cert.Extensions["2.5.29.15"] as X509KeyUsageExtension);
+                       if (kue != null) {
+                               // ... verify CrlSign is set
+                               X509KeyUsageFlags success = X509KeyUsageFlags.CrlSign;
+                               if ((kue.KeyUsages & success) != success) {
+                                       // FIXME - we should try to find an alternative CA that has the CrlSign bit
+                                       return X509ChainStatusFlags.RevocationStatusUnknown;
+                               }
+                       }
+
+                       MX.X509Crl crl = FindCrl (ca_cert);
+
+                       if ((crl == null) && online) {
+                               // FIXME - download and install new CRL
+                               // then you get a second chance
+                               // crl = FindCrl (ca_cert, ref valid, ref out_of_date);
+
+                               // We need to get the subjectAltName and an URI from there (or use OCSP)        
+                               // X509KeyUsageExtension subjectAltName = (ca_cert.Extensions["2.5.29.17"] as X509KeyUsageExtension);
+                       }
+
+                       if (crl != null) {
+                               // validate the digital signature on the CRL using the CA public key
+                               // note #1: we can't use X509Crl.VerifySignature(X509Certificate) because it duplicates
+                               // checks and we loose the "why" of the failure
+                               // note #2: we do this before other tests as an invalid signature could be a hacked CRL
+                               // (so anything within can't be trusted)
+                               if (!crl.VerifySignature (ca_cert.PublicKey.Key)) {
+                                       return X509ChainStatusFlags.RevocationStatusUnknown;
+                               }
+
+                               MX.X509Crl.X509CrlEntry entry = crl.GetCrlEntry (certificate.MonoCertificate);
+                               if (entry != null) {
+                                       // We have an entry for this CRL that includes an unknown CRITICAL extension
+                                       // See [X.509 7.3] NOTE 4
+                                       if (!ProcessCrlEntryExtensions (entry))
+                                               return X509ChainStatusFlags.Revoked;
+
+                                       // FIXME - a little more is involved
+                                       if (entry.RevocationDate <= ChainPolicy.VerificationTime)
+                                               return X509ChainStatusFlags.Revoked;
+                               }
+
+                               // are we overdue for a CRL update ? if so we can't be sure of any certificate status
+                               if (crl.NextUpdate < ChainPolicy.VerificationTime)
+                                       return X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation;
+
+                               // we have a CRL that includes an unknown CRITICAL extension
+                               // we put this check at the end so we do not "hide" any Revoked flags
+                               if (!ProcessCrlExtensions (crl)) {
+                                       return X509ChainStatusFlags.RevocationStatusUnknown;
+                               }
+                       } else {
+                               return X509ChainStatusFlags.RevocationStatusUnknown;
+                       }
+
+                       return X509ChainStatusFlags.NoError;
+               }
+
+               static MX.X509Crl CheckCrls (string subject, string ski, MX.X509Store store)
+               {
+                       if (store == null)
+                               return null;
+
+                       var crls = store.Crls;
+                       foreach (MX.X509Crl crl in crls) {
+                               if (crl.IssuerName == subject && (ski.Length == 0 || ski == GetAuthorityKeyIdentifier (crl)))
+                                       return crl;
+                       }
+                       return null; // No CRL found
+               }
+
+               private MX.X509Crl FindCrl (X509Certificate2 caCertificate)
+               {
+                       string subject = caCertificate.SubjectName.Decode (X500DistinguishedNameFlags.None);
+                       string ski = GetSubjectKeyIdentifier (caCertificate);
+
+                       // consider that the LocalMachine directories could not exists... and cannot be created by the user
+                       MX.X509Crl result = CheckCrls (subject, ski, LMCAStore.Store);
+                       if (result != null)
+                               return result;
+                       if (location == StoreLocation.CurrentUser) {
+                               result = CheckCrls (subject, ski, UserCAStore.Store);
+                               if (result != null)
+                                       return result;
+                       }
+
+                       // consider that the LocalMachine directories could not exists... and cannot be created by the user
+                       result = CheckCrls (subject, ski, LMRootStore.Store);
+                       if (result != null)
+                               return result;
+                       if (location == StoreLocation.CurrentUser) {
+                               result = CheckCrls (subject, ski, UserRootStore.Store);
+                               if (result != null)
+                                       return result;
+                       }
+                       return null;
+               }
+
+               private bool ProcessCrlExtensions (MX.X509Crl crl)
+               {
+                       foreach (MX.X509Extension ext in crl.Extensions) {
+                               if (ext.Critical) {
+                                       switch (ext.Oid) {
+                                       case "2.5.29.20": // cRLNumber
+                                       case "2.5.29.35": // authorityKeyIdentifier
+                                               // we processed/know about this extension
+                                               break;
+                                       default:
+                                               return false;
+                                       }
+                               }
+                       }
+                       return true;
+               }
+
+               private bool ProcessCrlEntryExtensions (MX.X509Crl.X509CrlEntry entry)
+               {
+                       foreach (MX.X509Extension ext in entry.Extensions) {
+                               if (ext.Critical) {
+                                       switch (ext.Oid) {
+                                       case "2.5.29.21": // cRLReason
+                                               // we processed/know about this extension
+                                               break;
+                                       default:
+                                               return false;
+                                       }
+                               }
+                       }
+                       return true;
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs
new file mode 100644 (file)
index 0000000..544f67c
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// X509Helper2.cs
+//
+// Authors:
+//     Martin Baulig  <martin.baulig@xamarin.com>
+//
+// Copyright (C) 2016 Xamarin, Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+#if SECURITY_DEP
+namespace System.Security.Cryptography.X509Certificates
+{
+       internal static class X509Helper2
+       {
+               internal static void ThrowIfContextInvalid (X509CertificateImpl impl)
+               {
+                       X509Helper.ThrowIfContextInvalid (impl);
+               }
+
+               internal static X509Certificate2Impl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
+               {
+                       var impl = new X509Certificate2ImplMono ();
+                       impl.Import (rawData, password, keyStorageFlags);
+                       return impl;
+               }
+
+               internal static X509Certificate2Impl Import (X509Certificate cert)
+               {
+                       var impl2 = cert.Impl as X509Certificate2Impl;
+                       if (impl2 != null)
+                               return (X509Certificate2Impl)impl2.Clone ();
+                       return Import (cert.GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet);
+               }
+
+               internal static X509ChainImpl CreateChainImpl (bool useMachineContext)
+               {
+                       return new X509ChainImplMono (useMachineContext);
+               }
+
+               public static bool IsValid (X509ChainImpl impl)
+               {
+                       return impl != null && impl.IsValid;
+               }
+
+               internal static void ThrowIfContextInvalid (X509ChainImpl impl)
+               {
+                       if (!IsValid (impl))
+                               throw GetInvalidChainContextException ();
+               }
+
+               internal static Exception GetInvalidChainContextException ()
+               {
+                       return new CryptographicException (Locale.GetText ("Chain instance is empty."));
+               }
+       }
+}
+#endif
index 904142e3595e4737c60cddab3376e306953daa84..42b6c6e3d44dc65bdbf2d8838f498fdd51ed0c33 100644 (file)
@@ -40,7 +40,7 @@ using System.Security.Permissions;
 
 namespace System.Security.Cryptography.X509Certificates {
 
-       public sealed class X509Store : IDisposable {
+       public sealed class X509Store {
 
                private string _name;
                private StoreLocation _location;
@@ -107,10 +107,6 @@ namespace System.Security.Cryptography.X509Certificates {
                        _location = storeLocation;
                }
 
-               public void Dispose ()
-               {
-               }
-
                // properties
 
                public X509Certificate2Collection Certificates {
index e2c0718b8ab6f55f7f1581d43a55e380b5f8fe98..1d37b1294e573b833968429100e92c98aedcff57 100644 (file)
@@ -536,11 +536,15 @@ System.Security.Cryptography.X509Certificates/X509BasicConstraintsExtension.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2Collection.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2Enumerator.cs
+System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs
+System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs
 System.Security.Cryptography.X509Certificates/X509CertificateCollection.cs
 System.Security.Cryptography.X509Certificates/X509Chain.cs
 System.Security.Cryptography.X509Certificates/X509ChainElementCollection.cs
 System.Security.Cryptography.X509Certificates/X509ChainElement.cs
 System.Security.Cryptography.X509Certificates/X509ChainElementEnumerator.cs
+System.Security.Cryptography.X509Certificates/X509ChainImpl.cs
+System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs
 System.Security.Cryptography.X509Certificates/X509ChainPolicy.cs
 System.Security.Cryptography.X509Certificates/X509ChainStatus.cs
 System.Security.Cryptography.X509Certificates/X509ChainStatusFlags.cs
@@ -550,6 +554,7 @@ System.Security.Cryptography.X509Certificates/X509Extension.cs
 System.Security.Cryptography.X509Certificates/X509ExtensionEnumerator.cs
 System.Security.Cryptography.X509Certificates/X509FindType.cs
 System.Security.Cryptography.X509Certificates/X509IncludeOption.cs
+System.Security.Cryptography.X509Certificates/X509Helper2.cs
 System.Security.Cryptography.X509Certificates/X509KeyUsageExtension.cs
 System.Security.Cryptography.X509Certificates/X509KeyUsageFlags.cs
 System.Security.Cryptography.X509Certificates/X509NameType.cs
index 45649b8ad51a173ed0a658892fbf07fd0330042f..77fb73e3f00ed1404dbe81fe1a68294f5d7068a2 100644 (file)
@@ -81,13 +81,23 @@ namespace MonoTests.System.Net {
 
                public static MyNetworkStream CreateNS (int port)
                {
-                       return CreateNS (port, 5000);
+                       return CreateNS (IPAddress.Loopback, port, 5000);
                }
 
                public static MyNetworkStream CreateNS (int port, int timeout_ms)
+               {
+                       return CreateNS (IPAddress.Loopback, port, timeout_ms);
+               }
+
+               public static MyNetworkStream CreateNS (IPAddress ip, int port)
+               {
+                       return CreateNS (ip, port, 5000);
+               }
+
+               public static MyNetworkStream CreateNS (IPAddress ip, int port, int timeout_ms)
                {
                        Socket sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-                       sock.Connect (new IPEndPoint (IPAddress.Loopback, port));
+                       sock.Connect (new IPEndPoint (ip, port));
                        sock.SendTimeout = timeout_ms;
                        sock.ReceiveTimeout = timeout_ms;
                        return new MyNetworkStream (sock);
index 06b756d387b2fae9ed04d69b2a44261ca8863c64..c088e4e14e2ddeb71509bbda356c4d7761d12c66 100644 (file)
@@ -32,6 +32,7 @@ using System.IO;
 using System.Net;
 using System.Net.Sockets;
 using System.Text;
+using System.Collections.Generic;
 
 using NUnit.Framework;
 
@@ -190,6 +191,26 @@ namespace MonoTests.System.Net
                        listener.Close ();
                }
 
+               [Test]
+               public void HttpRequestIsLocal ()
+               {
+                       var ips = new List<IPAddress> (Dns.GetHostAddresses (Dns.GetHostName ()));
+                       ips.Add (IPAddress.Loopback);
+                       foreach (var ip in ips) {
+                               if (ip.AddressFamily != AddressFamily.InterNetwork)
+                                       continue;
+
+                               HttpListener listener = HttpListener2Test.CreateAndStartListener (
+                                       "http://" + ip + ":9000/HttpRequestIsLocal/");
+                               NetworkStream ns = HttpListener2Test.CreateNS (ip, 9000);
+                               HttpListener2Test.Send (ns, "GET /HttpRequestIsLocal/ HTTP/1.0\r\n\r\n");
+                               HttpListenerContext ctx = listener.GetContext ();
+                               HttpListenerRequest request = ctx.Request;
+                               Assert.AreEqual (true, request.IsLocal, "IP " + ip + " is not local");
+                               listener.Close ();
+                       }
+               }
+
                [Test] // #29927
                public void HttpRequestUriUnescape ()
                {
index e642d688f3c59c8d62dd075b49ad48e36176f470..a7e48646d05dcf3b87af070d4ee4cb66ac045634 100644 (file)
@@ -1465,17 +1465,35 @@ WYpnKQqsKIzlSqv9wwXs7B1iA7ZdvHk3TAnSnLP1o2H7ME05UnZPKCvraONdezon
                }
 
                [Test]
-               [ExpectedException (typeof (ArgumentException))]
                public void GetNameInfo_Invalid_True ()
                {
-                       new X509Certificate2 ().GetNameInfo ((X509NameType) Int32.MinValue, true);
+                       try {
+                               // MS throws ArgumentException, Mono's new implementation throws
+                               // CryptographicException, which is consistent with other "certificate
+                               // instance is empty" situations.
+                               new X509Certificate2 ().GetNameInfo ((X509NameType) Int32.MinValue, true);
+                               Assert.Fail ("Expected exception.");
+                       } catch (ArgumentException) {
+                       } catch (CryptographicException) {
+                       } catch (Exception ex) {
+                               Assert.Fail ("Expected 'ArgumentException' or 'CryptographicException', got '{0}'", ex.GetType ());
+                       }
                }
 
                [Test]
-               [ExpectedException (typeof (ArgumentException))]
                public void GetNameInfo_Invalid_False ()
                {
-                       new X509Certificate2 ().GetNameInfo ((X509NameType) Int32.MinValue, false);
+                       try {
+                               // MS throws ArgumentException, Mono's new implementation throws
+                               // CryptographicException, which is consistent with other "certificate
+                               // instance is empty" situations.
+                               new X509Certificate2 ().GetNameInfo ((X509NameType) Int32.MinValue, false);
+                               Assert.Fail ("Expected exception.");
+                       } catch (ArgumentException) {
+                       } catch (CryptographicException) {
+                       } catch (Exception ex) {
+                               Assert.Fail ("Expected 'ArgumentException' or 'CryptographicException', got '{0}'", ex.GetType ());
+                       }
                }
 
                [Test]
@@ -1486,10 +1504,19 @@ WYpnKQqsKIzlSqv9wwXs7B1iA7ZdvHk3TAnSnLP1o2H7ME05UnZPKCvraONdezon
                }
 
                [Test]
-               [ExpectedException (typeof (NullReferenceException))]
                public void Empty_GetNameInfo_DnsName ()
                {
-                       new X509Certificate2 ().GetNameInfo (X509NameType.DnsName, true);
+                       try {
+                               // MS throws NullReferenceException, Mono's new implementation throws
+                               // CryptographicException, which is consistent with other "certificate
+                               // instance is empty" situations.
+                               new X509Certificate2 ().GetNameInfo (X509NameType.DnsName, true);
+                               Assert.Fail ("Expected exception.");
+                       } catch (NullReferenceException) {
+                       } catch (CryptographicException) {
+                       } catch (Exception ex) {
+                               Assert.Fail ("Expected 'NullReferenceException' or 'CryptographicException', got '{0}'", ex.GetType ());
+                       }
                }
 
                [Test]
index 42aae6ea158c8a8c299debefa02cc4bed9c01cd5..9fe0be90027bb9eb94769947fa80d510910e3281 100644 (file)
@@ -300,11 +300,15 @@ System.Security.Cryptography.X509Certificates/X509BasicConstraintsExtension.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2Collection.cs
 System.Security.Cryptography.X509Certificates/X509Certificate2Enumerator.cs
+System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs
+System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs
 System.Security.Cryptography.X509Certificates/X509CertificateCollection.cs
 System.Security.Cryptography.X509Certificates/X509Chain.cs
 System.Security.Cryptography.X509Certificates/X509ChainElement.cs
 System.Security.Cryptography.X509Certificates/X509ChainElementCollection.cs
 System.Security.Cryptography.X509Certificates/X509ChainElementEnumerator.cs
+System.Security.Cryptography.X509Certificates/X509ChainImpl.cs
+System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs
 System.Security.Cryptography.X509Certificates/X509ChainPolicy.cs
 System.Security.Cryptography.X509Certificates/X509ChainStatus.cs
 System.Security.Cryptography.X509Certificates/X509ChainStatusFlags.cs
@@ -314,6 +318,7 @@ System.Security.Cryptography.X509Certificates/X509ExtensionCollection.cs
 System.Security.Cryptography.X509Certificates/X509ExtensionEnumerator.cs
 System.Security.Cryptography.X509Certificates/X509FindType.cs
 System.Security.Cryptography.X509Certificates/X509IncludeOption.cs
+System.Security.Cryptography.X509Certificates/X509Helper2.cs
 System.Security.Cryptography.X509Certificates/X509KeyUsageExtension.cs
 System.Security.Cryptography.X509Certificates/X509KeyUsageFlags.cs
 System.Security.Cryptography.X509Certificates/X509NameType.cs
index b3284ea78796be7b38531510d7a79ffb72f7b7b2..cf95aee80ea0e92aa4eec92c3b2ce8c4a6bf8ccd 100644 (file)
@@ -73,13 +73,9 @@ using System.Runtime.InteropServices;
 [assembly: DefaultDependency (LoadHint.Always)]
 [assembly: StringFreezing]
 
-#if NET_2_1
-[assembly: InternalsVisibleTo ("System, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")]
-[assembly: InternalsVisibleTo ("System.Core, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")]
-#else
-[assembly: InternalsVisibleTo ("System, PublicKey=00000000000000000400000000000000")]
-[assembly: InternalsVisibleTo ("System.Core, PublicKey=00000000000000000400000000000000")]
-#endif
+[assembly: InternalsVisibleTo ("System, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull2)]
+[assembly: InternalsVisibleTo ("System.Core, PublicKey=" + AssemblyRef.FrameworkPublicKeyFull2)]
+
 [assembly: InternalsVisibleTo ("System.Numerics, PublicKey=00000000000000000400000000000000")]
 
 #if MONOTOUCH
index 1e53bade58fbf5653b11b0d124bbbe31e7ead55b..69e1f32ffdd74bcf0f4b446b145468b9301769b1 100644 (file)
@@ -48,6 +48,7 @@ namespace System.IO {
        public sealed class FileInfo : FileSystemInfo
        {
                private bool exists;
+               private string displayPath;
 
                public FileInfo (string fileName)
                {
@@ -59,11 +60,14 @@ namespace System.IO {
 
                        OriginalPath = fileName;
                        FullPath = Path.GetFullPath (fileName);
+                       
+                       displayPath = OriginalPath;
                }
 
                private FileInfo (SerializationInfo info, StreamingContext context)
                        : base (info, context)
                {
+                       displayPath = OriginalPath;
                }
 
                internal override void InternalRefresh ()
@@ -241,6 +245,8 @@ namespace System.IO {
 
                        File.Move (FullPath, destFullPath);
                        this.FullPath = destFullPath;
+
+                       displayPath = destFileName;
                }
 
                public FileInfo CopyTo (string destFileName)
@@ -267,7 +273,7 @@ namespace System.IO {
 
                public override string ToString ()
                {
-                       return OriginalPath;
+                       return displayPath;
                }
 
 #if !MOBILE
index 144997e573b63c0cb211a47596cdbb0e676228ac..3ff0a2adeada877f4a4a3cf241de95b182e76217 100644 (file)
@@ -109,6 +109,14 @@ namespace System.Security.Cryptography.X509Certificates {
                        impl = X509Helper.InitFromHandle (handle);
                }
 
+               internal X509Certificate (X509CertificateImpl impl)
+               {
+                       if (impl == null)
+                               throw new ArgumentNullException ("impl");
+
+                       this.impl = X509Helper.InitFromCertificate (impl);
+               }
+
                public X509Certificate (System.Security.Cryptography.X509Certificates.X509Certificate cert) 
                {
                        if (cert == null)
@@ -120,6 +128,27 @@ namespace System.Security.Cryptography.X509Certificates {
                        hideDates = false;
                }
 
+               internal void ImportHandle (X509CertificateImpl impl)
+               {
+                       Reset ();
+                       this.impl = impl;
+               }
+
+               internal X509CertificateImpl Impl {
+                       get {
+                               X509Helper.ThrowIfContextInvalid (impl);
+                               return impl;
+                       }
+               }
+
+               internal bool IsValid {
+                       get { return X509Helper.IsValid (impl); }
+               }
+
+               internal void ThrowIfContextInvalid ()
+               {
+                       X509Helper.ThrowIfContextInvalid (impl);
+               }
 
                // public methods
        
@@ -161,7 +190,7 @@ namespace System.Security.Cryptography.X509Certificates {
                                return null;
                        X509Helper.ThrowIfContextInvalid (impl);
 
-                       return impl.GetEffectiveDateString ().ToString ();
+                       return impl.GetValidFrom ().ToLocalTime ().ToString ();
                }
        
                // strangly there are no DateTime returning function
@@ -171,7 +200,7 @@ namespace System.Security.Cryptography.X509Certificates {
                                return null;
                        X509Helper.ThrowIfContextInvalid (impl);
 
-                       return impl.GetExpirationDateString ().ToString ();
+                       return impl.GetValidUntil ().ToLocalTime ().ToString ();
                }
        
                // well maybe someday there'll be support for PGP or SPKI ?
index e3dc5b36201f71a1dec2488dcea7effa4d3e8135..7178bedaa547e5ace0afd2186a5cae5d30d5483e 100644 (file)
@@ -45,17 +45,15 @@ namespace System.Security.Cryptography.X509Certificates
 
                public abstract X509CertificateImpl Clone ();
 
-               public abstract string GetSubjectSummary ();
-
                public abstract string GetIssuerName (bool legacyV1Mode);
 
                public abstract string GetSubjectName (bool legacyV1Mode);
 
                public abstract byte[] GetRawCertData ();
 
-               public abstract DateTime GetEffectiveDateString ();
+               public abstract DateTime GetValidFrom ();
 
-               public abstract DateTime GetExpirationDateString ();
+               public abstract DateTime GetValidUntil ();
 
                byte[] cachedCertificateHash;
 
index 85985c5d303cef3e3beebb05c1fb9f9c51eba7cd..056bf561ee5a31a719907724b41b6e11cf4ef5ab 100644 (file)
@@ -66,12 +66,6 @@ namespace System.Security.Cryptography.X509Certificates
                                return MX.X501.ToString (x509.GetIssuerName (), true, ", ", true);
                }
 
-               public override string GetSubjectSummary ()
-               {
-                       ThrowIfContextInvalid ();
-                       return x509.SubjectName;
-               }
-
                public override string GetSubjectName (bool legacyV1Mode)
                {
                        ThrowIfContextInvalid ();
@@ -94,16 +88,16 @@ namespace System.Security.Cryptography.X509Certificates
                        return sha.ComputeHash (x509.RawData);
                }
 
-               public override DateTime GetEffectiveDateString ()
+               public override DateTime GetValidFrom ()
                {
                        ThrowIfContextInvalid ();
-                       return x509.ValidFrom.ToLocalTime ();
+                       return x509.ValidFrom;
                }
 
-               public override DateTime GetExpirationDateString ()
+               public override DateTime GetValidUntil ()
                {
                        ThrowIfContextInvalid ();
-                       return x509.ValidUntil.ToLocalTime ();
+                       return x509.ValidUntil;
                }
 
                public override bool Equals (X509CertificateImpl other, out bool result)
@@ -164,8 +158,8 @@ namespace System.Security.Cryptography.X509Certificates
                        StringBuilder sb = new StringBuilder ();
                        sb.AppendFormat ("[Subject]{0}  {1}{0}{0}", nl, GetSubjectName (false));
                        sb.AppendFormat ("[Issuer]{0}  {1}{0}{0}", nl, GetIssuerName (false));
-                       sb.AppendFormat ("[Not Before]{0}  {1}{0}{0}", nl, GetEffectiveDateString ());
-                       sb.AppendFormat ("[Not After]{0}  {1}{0}{0}", nl, GetExpirationDateString ());
+                       sb.AppendFormat ("[Not Before]{0}  {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ());
+                       sb.AppendFormat ("[Not After]{0}  {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ());
                        sb.AppendFormat ("[Thumbprint]{0}  {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
                        sb.Append (nl);
                        return sb.ToString ();
index 0068c4643b8fdcae08e5070ee5ed340ab9d64cdf..db33ec75f0febdaa5cecfef8d4ce7b4975ba9cc8 100644 (file)
@@ -880,6 +880,29 @@ namespace MonoTests.System.IO
                        }
                }
 
+               [Test] //Covers #38796
+               public void ToStringAfterMoveTo ()
+               {
+                       string name1 = "FIT.ToStringAfterMoveTo.Test";
+                       string name2 = "FIT.ToStringAfterMoveTo.Test.Alt";
+                       string path1 = TempFolder + DSC + name1;
+                       string path2 = TempFolder + DSC + name2;
+                       DeleteFile (path1);
+                       DeleteFile (path2);
+                       
+                       try {
+                               File.Create (path1).Close ();
+                               FileInfo info = new FileInfo (path1);
+                               Assert.AreEqual (path1, info.ToString (), "#A");
+
+                               info.MoveTo (path2);
+                               Assert.AreEqual (path2, info.ToString (), "#B");
+                       } finally {
+                               DeleteFile (path1);
+                               DeleteFile (path2);
+                       }
+               }
+
 #if !MOBILE
                [Test]
                public void Replace1 ()
index 464ac076432cab4506909b77961da47cf926fde9..35ed33617c26884fa55a28c2d058cfb533a30179 100644 (file)
@@ -1,6 +1,7 @@
 Assembly/AssemblyInfo.cs
 ../../build/common/Consts.cs
 ../../build/common/Locale.cs
+../../build/common/AssemblyRef.cs
 Microsoft.Win32/IRegistryApi.cs
 Microsoft.Win32/RegistryKey.cs
 Microsoft.Win32/RegistryKeyPermissionCheck.cs
index 68477b3c1ed34bf07220b57999433d23dfc004a4..a0ae78cdf518e42737b571c830e08a99adf00747 100644 (file)
@@ -2245,7 +2245,7 @@ namespace Mono.CSharp {
                                return IsLeftResolvedExpressionValid (dmb.Arguments [0].Expr);
                        }
 
-                       if (expr is ConstantExpr || expr is TypeExpr || expr is NamespaceExpression || expr is This)
+                       if (expr is ConstantExpr || expr is TypeExpr || expr is NamespaceExpression || expr is VariableReference)
                                return true;
 
                        return false;
index ea92d6af0de4bb188050d29921e7dc39cb32227d..4ad5cdf547e8c744dbad0e1b154e95d8ce16d2d0 100644 (file)
@@ -29,6 +29,11 @@ public class MainClass
        public static event Action Act = null;
        public static dynamic BBB = null;
 
+       void ParameterTest (Person ParPerson)
+       {
+               Console.WriteLine (nameof (ParPerson.MyCar.Year));
+       }
+
        public static int Main ()
        {
                string name;
@@ -61,6 +66,11 @@ public class MainClass
                if (name != "ToString")
                        return 7;
 
+               Person LocPerson = null;
+               name = nameof (LocPerson.MyCar.Year);
+               if (name != "Year")
+                       return 8;
+
                return 0;
        }
 }
index 3cc0ea315382acaa4f7e2726f79714b6d3bab297..576a15ddb738d3d6612dffbf80fa5a75ce29346a 100644 (file)
         <size>40</size>
       </method>
       <method name="Int32 Main()" attrs="150">
-        <size>213</size>
+        <size>244</size>
       </method>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
         <size>7</size>
       </method>
     </type>
+    <type name="MainClass">
+      <method name="Void ParameterTest(Person)" attrs="129">
+        <size>12</size>
+      </method>
+    </type>
   </test>
   <test name="test-null-operator-01.cs">
     <type name="S">
index 93153cb19b9dbcd34613f62ff8565663e92e37e8..9b07560ab3997c9f56a23edbc71e127d02ca7a34 100644 (file)
@@ -5,6 +5,6 @@ include ../../build/rules.make
 PROGRAM = cil-stringreplacer.exe
 NO_INSTALL = yes
 
-LOCAL_MCS_FLAGS = -r:System.dll
+LOCAL_MCS_FLAGS = -r:System.dll -r:Mono.Cecil.dll
 
 include ../../build/executable.make
index f86922be2bf58e3560dcd3e318ec0d80a0d2f2a1..2414206c692ef2023b30b34d7ca16ebceebc8306 100644 (file)
@@ -100,7 +100,8 @@ public class Program
 
        static void RewriteAssembly (string assemblyLocation, Dictionary<string, string> resourcesStrings, CmdOptions options)
        {
-               var assembly = AssemblyDefinition.ReadAssembly (assemblyLocation);
+               var readerParameters = new ReaderParameters { ReadSymbols = true };
+               var assembly = AssemblyDefinition.ReadAssembly (assemblyLocation, readerParameters);
                foreach (var module in assembly.Modules) {
                        foreach (var type in module.GetTypes ()) {
                                foreach (var method in type.Methods) {
@@ -124,7 +125,8 @@ public class Program
                        }
                }
 
-               assembly.Write (assemblyLocation);
+               var writerParameters = new WriterParameters { WriteSymbols = true };
+               assembly.Write (assemblyLocation, writerParameters);
        }
 
        static bool LoadGetResourceStrings (Dictionary<string, string> resourcesStrings, CmdOptions options)
diff --git a/mcs/tools/cil-stringreplacer/cil-stringreplacer.csproj b/mcs/tools/cil-stringreplacer/cil-stringreplacer.csproj
new file mode 100644 (file)
index 0000000..230cd62
--- /dev/null
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>\r
+    <ProjectGuid>{7A08A2B6-5AC3-4268-8566-B07648B50D01}</ProjectGuid>\r
+    <OutputType>Exe</OutputType>\r
+    <RootNamespace>cilstringreplacer</RootNamespace>\r
+    <AssemblyName>cilstringreplacer</AssemblyName>\r
+    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <DebugType>full</DebugType>\r
+    <Optimize>false</Optimize>\r
+    <OutputPath>bin\Debug</OutputPath>\r
+    <DefineConstants>DEBUG;</DefineConstants>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+    <ExternalConsole>false</ExternalConsole>\r
+    <PlatformTarget>x86</PlatformTarget>\r
+    <Commandlineparameters>--resourcestrings:/Users/marek/git/mono/external/referencesource/mscorlib/mscorlib.txt /Users/marek/git/mono/mcs/class/lib/net_4_x/mscorlib.dll</Commandlineparameters>\r
+    <ConsolePause>false</ConsolePause>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">\r
+    <Optimize>true</Optimize>\r
+    <OutputPath>bin\Release</OutputPath>\r
+    <ErrorReport>prompt</ErrorReport>\r
+    <WarningLevel>4</WarningLevel>\r
+    <ExternalConsole>true</ExternalConsole>\r
+    <PlatformTarget>x86</PlatformTarget>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="System" />\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="cil-stringreplacer.cs">\r
+      <Link>cil-stringreplacer.cs</Link>\r
+    </Compile>\r
+    <Compile Include="..\..\class\Mono.Options\Mono.Options\Options.cs">\r
+      <Link>Options.cs</Link>\r
+    </Compile>\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />\r
+</Project>
\ No newline at end of file
index 90536b886aa757b695ba77603c6a0efb5eb912b7..c16659f2b39c76efd24a0756765ea42799ef42b1 100644 (file)
@@ -1,9 +1,2 @@
 cil-stringreplacer.cs
 ../../class/Mono.Options/Mono.Options/Options.cs
-../../../external/cecil/Mono.Cecil/*.cs
-../../../external/cecil/Mono.Cecil.Cil/*.cs
-../../../external/cecil/Mono.Cecil.Metadata/*.cs
-../../../external/cecil/Mono.Cecil.PE/*.cs
-../../../external/cecil/Mono.Collections.Generic/*.cs
-../../../external/cecil/Mono/Empty.cs
-../../../external/cecil/Mono.Security.Cryptography/*.cs
index ca804a604328da8b57efed3e0ae0ed9066fd9951..beafdfa555778472afda9b56e0d11d2fd3d52845 100644 (file)
@@ -1439,6 +1439,7 @@ namespace TestRunner {
 
                static bool TryToMatchErrorMessage (string actual, string expected)
                {
+                       actual = actual.Replace ("\\", "/");
                        var path_mask_start = expected.IndexOf ("*PATH*");
                        if (path_mask_start > 0 && actual.Length > path_mask_start) {
                                var path_mask_continue = expected.Substring (path_mask_start + 6);
index 17d843975055ef2db7672acb490f7a395f57f953..760f9cf5045c92e217bbb7edcdb66d7e8aa86b20 100644 (file)
@@ -2,21 +2,36 @@ thisdir = tools/corcompare
 SUBDIRS =
 include ../../build/rules.make
 
-ALL_PROGRAMS = mono-api-info.exe
-
-COMMON_SOURCES = \
-       AssemblyResolver.cs     \
-       Util.cs \
-       WellFormedXmlWriter.cs
+ALL_PROGRAMS = mono-api-info.exe mono-api-html.exe
 
 PROGRAM_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)
 
 APIINFO_SOURCES = \
        mono-api-info.cs \
-       ../../class/Mono.Options/Mono.Options/Options.cs \
-       $(COMMON_SOURCES)
+       AssemblyResolver.cs     \
+       Util.cs \
+       WellFormedXmlWriter.cs \
+       ../../class/Mono.Options/Mono.Options/Options.cs
+
+APIHTML_SOURCES = \
+       mono-api-html/ApiChange.cs \
+       mono-api-html/ApiDiff.cs \
+       mono-api-html/AssemblyComparer.cs \
+       mono-api-html/ClassComparer.cs \
+       mono-api-html/Comparer.cs \
+       mono-api-html/ConstructorComparer.cs \
+       mono-api-html/EventComparer.cs \
+       mono-api-html/FieldComparer.cs \
+       mono-api-html/Helpers.cs \
+       mono-api-html/InterfaceComparer.cs \
+       mono-api-html/MemberComparer.cs \
+       mono-api-html/MethodComparer.cs \
+       mono-api-html/NamespaceComparer.cs \
+       mono-api-html/PropertyComparer.cs \
+       ../../class/Mono.Options/Mono.Options/Options.cs
 
-DISTFILES= $(COMMON_SOURCES) $(APIINFO_SOURCES)
+
+DISTFILES= $(APIINFO_SOURCES) $(APIHTML_SOURCES)
 
 all-local: $(ALL_PROGRAMS)
 
@@ -42,5 +57,8 @@ clean-local:
 
 dist-local: dist-default
 
-mono-api-info.exe: $(APIINFO_SOURCES) ../../class/Mono.Options/Mono.Options/Options.cs
+mono-api-info.exe: $(APIINFO_SOURCES)
        $(CSCOMPILE) -r:Mono.Cecil.dll -r:System.Xml.dll -r:System.Core.dll -r:System.dll -out:$@ $^
+
+mono-api-html.exe: $(APIHTML_SOURCES)
+       $(CSCOMPILE) -r:Mono.Cecil.dll -r:System.Xml.dll -r:System.Core.dll -r:System.dll -r:System.Xml.Linq.dll -out:$@ $^
index 3446b6f74c0afdbc912a571af8cb900b089945f8..13f686e22c64ec5dadc09c136838db3ed7c74a43 100644 (file)
@@ -324,6 +324,11 @@ namespace Mono.Tools {
 
                        Copy (name, asmb_path, true);
 
+                       var name_pdb = Path.ChangeExtension (name, ".pdb");
+                       if (File.Exists (name_pdb)) {
+                               Copy (name_pdb, Path.ChangeExtension (asmb_path, ".pdb"), true);
+                       }
+
                        foreach (string ext in siblings) {
                                string sibling = String.Concat (name, ext);
                                if (File.Exists (sibling))
@@ -356,9 +361,23 @@ namespace Mono.Tools {
                                        string pkg_path = AbsoluteToRelativePath (ref_dir, pkg_path_abs);
                                        symlink (pkg_path, ref_path);
 
+                                       var pdb_pkg_path = Path.ChangeExtension (pkg_path, ".pdb");
+                                       var pdb_ref_path = Path.ChangeExtension (ref_path, ".pdb");
+
+                                       if (File.Exists (pdb_pkg_path)) {
+                                               symlink (pdb_pkg_path, pdb_ref_path);
+                                       } else {
+                                               try {
+                                                       File.Delete (pdb_ref_path);
+                                               } catch {
+                                                       // Ignore error, just delete files that should not be there.
+                                               }
+                                       }
+
                                        foreach (string ext in siblings) {
                                                string sibling = String.Concat (pkg_path, ext);
                                                string sref = String.Concat (ref_path, ext);
+
                                                if (File.Exists (sibling))
                                                        symlink (sibling, sref);
                                                else {
index d264ea32ba65bb24b09f9e54628227e7023f5d0f..952bea941afeee6256826b7ad6e0ea0fceebf8c3 100644 (file)
@@ -3792,6 +3792,7 @@ mono_class_setup_vtable (MonoClass *klass)
 static void
 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
 {
+       MonoError error;
        MonoMethod **overrides;
        MonoGenericContext *context;
        guint32 type_token;
@@ -3842,7 +3843,14 @@ mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
                 * This is true since we don't do layout all over again for them, we simply inflate
                 * the layout of the parent.
                 */
-               mono_reflection_get_dynamic_overrides (klass, &overrides, &onum);
+               mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
+               if (!is_ok (&error)) {
+                       mono_loader_unlock ();
+                       g_list_remove (in_setup, klass);
+                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf("Could not load list of method overrides due to %s", mono_error_get_message (&error)));
+                       mono_error_cleanup (&error);
+                       return;
+               }
        } else {
                /* The following call fails if there are missing methods in the type */
                /* FIXME it's probably a good idea to avoid this for generic instances. */
@@ -8317,6 +8325,7 @@ mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
 gboolean
 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
 {
+       MonoError error;
        /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
        if (!klass->inited)
                mono_class_init (klass);
@@ -8350,12 +8359,18 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
                }
 
                /* interface_offsets might not be set for dynamic classes */
-               if (oklass->ref_info_handle && !oklass->interface_bitmap)
+               if (oklass->ref_info_handle && !oklass->interface_bitmap) {
                        /* 
                         * oklass might be a generic type parameter but they have 
                         * interface_offsets set.
                         */
-                       return mono_reflection_call_is_assignable_to (oklass, klass);
+                       gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
+                       if (!is_ok (&error)) {
+                               mono_error_cleanup (&error);
+                               return FALSE;
+                       }
+                       return result;
+               }
                if (!oklass->interface_bitmap)
                        /* Happens with generic instances of not-yet created dynamic types */
                        return FALSE;
@@ -8363,7 +8378,6 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
                        return TRUE;
 
                if (mono_class_has_variant_generic_params (klass)) {
-                       MonoError error;
                        int i;
                        mono_class_setup_interfaces (oklass, &error);
                        if (!mono_error_ok (&error)) {
index 9f2d9fbd81433be9d715311d2d995efc214b61c4..ab021003394f58b85d425213a51cff84e4afa042 100644 (file)
@@ -886,8 +886,8 @@ mono_cleanup (void)
        mono_loader_cleanup ();
        mono_classes_cleanup ();
        mono_assemblies_cleanup ();
-       mono_images_cleanup ();
        mono_debug_cleanup ();
+       mono_images_cleanup ();
        mono_metadata_cleanup ();
 
        mono_native_tls_free (appdomain_thread_id);
index b933039b0b0ed222b08aaa2df015b7f947e13b04..e5807a1796c0b6cdfc32ee5e411fede54f956a03 100644 (file)
@@ -94,7 +94,7 @@ mono_handle_elevate (MonoHandle handle)
        return mono_handle_arena_elevate (mono_handle_arena_current (), handle);
 }
 
-#ifndef CHECKED_BUILD
+#ifndef ENABLE_CHECKED_BUILD
 
 #define mono_handle_obj(handle) ((handle)->__private_obj)
 
index 68702706b533ca9d878797a0012d0705ea485595..b8a9cd97a80f46892e8128e4095bd79a7d749337 100644 (file)
@@ -503,7 +503,7 @@ ICALL(ASSEMB_1, "InternalAddModule", ves_icall_System_Reflection_Emit_AssemblyBu
 ICALL(ASSEMB_2, "basic_init", mono_image_basic_init)
 
 ICALL_TYPE(CATTRB, "System.Reflection.Emit.CustomAttributeBuilder", CATTRB_1)
-ICALL(CATTRB_1, "GetBlob", mono_reflection_get_custom_attrs_blob)
+ICALL(CATTRB_1, "GetBlob", ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob)
 
 #ifndef DISABLE_REFLECTION_EMIT
 ICALL_TYPE(DERIVEDTYPE, "System.Reflection.Emit.DerivedType", DERIVEDTYPE_1)
index 4f4a90e6684a35207c236b580fd804addd1136b4..54ef7c8916168083762d55d56a37db29416a90b4 100644 (file)
@@ -1256,6 +1256,15 @@ ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflecti
        return result;
 }
 
+ICALL_EXPORT MonoArray*
+ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
+{
+       MonoError error;
+       MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
+}
+
 static gboolean
 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
 {
@@ -2701,10 +2710,12 @@ ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
                types [i] = t->type;
        }
 
-       geninst = mono_reflection_bind_generic_parameters (type, count, types);
+       geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
        g_free (types);
-       if (!geninst)
+       if (!geninst) {
+               mono_error_set_pending_exception (&error);
                return NULL;
+       }
 
        klass = mono_class_from_mono_type (geninst);
 
@@ -5516,7 +5527,6 @@ mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **excepti
                if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
                        klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
                        mono_loader_assert_no_error (); /* Plug any leaks */
-                       mono_error_assert_ok (error);
                        
                        if (klass) {
                                rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
index c99de7aa04f344b980db02069a46a38a274f5bfc..b16cd7cc2e88dd4fecb216b724ad1a14793503b2 100644 (file)
@@ -509,9 +509,19 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo)
 
        i = ((MonoImageLoader*)image->loader)->load_tables (image);
        g_assert (image->heap_guid.data);
-       g_assert (image->heap_guid.size >= 16);
 
-       image->guid = mono_guid_to_string ((guint8*)image->heap_guid.data);
+       if (!image->metadata_only) {
+               g_assert (image->heap_guid.size >= 16);
+
+               image->guid = mono_guid_to_string ((guint8*)image->heap_guid.data);
+       } else {
+               /* PPDB files have no guid */
+               guint8 empty_guid [16];
+
+               memset (empty_guid, 0, sizeof (empty_guid));
+
+               image->guid = mono_guid_to_string (empty_guid);
+       }
 
        return i;
 }
@@ -1070,13 +1080,13 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
                goto done;
        }
 
-       if (image->loader == &pe_loader && !mono_verifier_verify_cli_data (image, &errors))
+       if (image->loader == &pe_loader && !image->metadata_only && !mono_verifier_verify_cli_data (image, &errors))
                goto invalid_image;
 
        if (!mono_image_load_cli_data (image))
                goto invalid_image;
 
-       if (image->loader == &pe_loader && !mono_verifier_verify_table_data (image, &errors))
+       if (image->loader == &pe_loader && !image->metadata_only && !mono_verifier_verify_table_data (image, &errors))
                goto invalid_image;
 
        mono_image_load_names (image);
index 696b97deca31c7385e56335cb44f4c2af65aa062..c2362db3de954e95eed36aa5968e89567c667942 100644 (file)
@@ -352,7 +352,7 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate)
        if (delegate->method_is_virtual)
                method = mono_object_get_virtual_method (delegate->target, method);
 
-       if (mono_method_signature (method)->pinvoke) {
+       if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
                const char *exc_class, *exc_arg;
                gpointer ftnptr;
 
@@ -8226,7 +8226,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
        EmitMarshalContext m;
 
        g_assert (method != NULL);
-       g_assert (!mono_method_signature (method)->pinvoke);
+       g_assert (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL));
 
        /* 
         * FIXME: Should cache the method+delegate type pair, since the same method
index b7ab37ea690fac711a97b23898f462e9312ca9b1..25f033d4fc80ac33011b7e34ca2aa0fe174e99bb 100644 (file)
@@ -1411,7 +1411,7 @@ void        mono_reflection_create_generic_class  (MonoReflectionTypeBuilder *tb
 
 MonoReflectionType* mono_reflection_create_runtime_class  (MonoReflectionTypeBuilder *tb);
 
-void        mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides);
+void        mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error);
 
 void mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *m);
 void mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb);
@@ -1428,7 +1428,7 @@ MonoArray* mono_param_get_objects_internal  (MonoDomain *domain, MonoMethod *met
 MonoClass*
 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic);
 MonoType*
-mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types);
+mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error);
 MonoReflectionMethod*
 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *method, MonoArray *types);
 void
@@ -1446,7 +1446,7 @@ gpointer
 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context);
 
 gboolean
-mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass);
+mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error);
 
 gboolean
 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token);
index af5ba0afdb0b0a6420e1f309712fb928d04cf811..04417c82b714856c00bd88020cc484a2b4b4bf55 100644 (file)
@@ -27,6 +27,9 @@ mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error
 MonoArray*
 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error);
 
+MonoArray*
+mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error);
+
 MonoCustomAttrInfo*
 mono_custom_attrs_from_index_checked    (MonoImage *image, uint32_t idx, MonoError *error);
 MonoCustomAttrInfo*
index a3ea522b1cf5e1cccdccde76bbd134070ae6fe9f..d0ec44bbcb578434c4d77ade662ee4fa378d1a2c 100644 (file)
@@ -151,7 +151,7 @@ static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, M
 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
-static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
+static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
@@ -7773,7 +7773,7 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
 {
        MonoError error;
        MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
-       mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
+       mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
        return result;
 }
 
@@ -7802,7 +7802,7 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
 
        /* for compatibility with .net */
        if (method_is_dynamic (method)) {
-               mono_error_set_exception_instance (error, mono_get_exception_invalid_operation (NULL));
+               mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
                return NULL;
        }
 
@@ -7842,7 +7842,8 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
                local_var_sig_token = 0; //FIXME
 
        ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
-       return_val_if_nok (error, NULL);
+       if (!is_ok (error))
+               goto fail;
 
        ret->init_locals = header->init_locals;
        ret->max_stack = header->max_stack;
@@ -7854,10 +7855,12 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
        MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
        for (i = 0; i < header->num_locals; ++i) {
                MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
-               return_val_if_nok (error, NULL);
+               if (!is_ok (error))
+                       goto fail;
 
                rt = mono_type_get_object_checked (domain, header->locals [i], error);
-               return_val_if_nok (error, NULL);
+               if (!is_ok (error))
+                       goto fail;
 
                MONO_OBJECT_SETREF (info, local_type, rt);
 
@@ -7870,7 +7873,8 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
        MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
        for (i = 0; i < header->num_clauses; ++i) {
                MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
-               return_val_if_nok (error, NULL);
+               if (!is_ok (error))
+                       goto fail;
                MonoExceptionClause *clause = &header->clauses [i];
 
                info->flags = clause->flags;
@@ -7882,7 +7886,8 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
                        info->filter_offset = clause->data.filter_offset;
                else if (clause->data.catch_class) {
                        rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
-                       return_val_if_nok (error, NULL);
+                       if (!is_ok (error))
+                               goto fail;
 
                        MONO_OBJECT_SETREF (info, catch_type, rt);
                }
@@ -7893,6 +7898,10 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
        mono_metadata_free_mh (header);
        CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
        return ret;
+
+fail:
+       mono_metadata_free_mh (header);
+       return NULL;
 }
 
 /**
@@ -8571,7 +8580,7 @@ mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoT
                        return NULL;
 
                instance = mono_reflection_bind_generic_parameters (
-                       the_type, info->type_arguments->len, type_args);
+                       the_type, info->type_arguments->len, type_args, error);
 
                g_free (type_args);
                if (!instance)
@@ -10663,7 +10672,7 @@ mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
                        }
                }
 
-               res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
+               res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
                g_free (types);
                g_assert (res);
                gclass->type.type = res;
@@ -10682,17 +10691,20 @@ mono_reflection_create_unmanaged_type (MonoReflectionType *type)
        mono_error_set_pending_exception (&error);
 }
 
-void
-mono_reflection_register_with_runtime (MonoReflectionType *type)
+static gboolean
+reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
 {
-       MonoError error;
-       MonoType *res = mono_reflection_type_get_handle (type, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
        MonoDomain *domain = mono_object_domain ((MonoObject*)type);
        MonoClass *klass;
 
-       if (!res)
-               mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
+       mono_error_init (error);
+
+       MonoType *res = mono_reflection_type_get_handle (type, error);
+
+       if (!res && is_ok (error)) {
+               mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
+       }
+       return_val_if_nok (error, FALSE);
 
        klass = mono_class_from_mono_type (res);
 
@@ -10709,25 +10721,39 @@ mono_reflection_register_with_runtime (MonoReflectionType *type)
        }
        mono_domain_unlock (domain);
        mono_loader_unlock ();
+
+       return TRUE;
+}
+
+void
+mono_reflection_register_with_runtime (MonoReflectionType *type)
+{
+       MonoError error;
+       (void) reflection_register_with_runtime (type, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 /**
  * LOCKING: Assumes the loader lock is held.
  */
 static MonoMethodSignature*
-parameters_to_signature (MonoImage *image, MonoArray *parameters) {
-       MonoError error;
+parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
        MonoMethodSignature *sig;
        int count, i;
 
+       mono_error_init (error);
+
        count = parameters? mono_array_length (parameters): 0;
 
        sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
        sig->param_count = count;
        sig->sentinelpos = -1; /* FIXME */
        for (i = 0; i < count; ++i) {
-               sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
+               if (!is_ok (error)) {
+                       image_g_free (image, sig);
+                       return NULL;
+               }
        }
        return sig;
 }
@@ -10736,10 +10762,13 @@ parameters_to_signature (MonoImage *image, MonoArray *parameters) {
  * LOCKING: Assumes the loader lock is held.
  */
 static MonoMethodSignature*
-ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
+ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
        MonoMethodSignature *sig;
 
-       sig = parameters_to_signature (image, ctor->parameters);
+       mono_error_init (error);
+
+       sig = parameters_to_signature (image, ctor->parameters, error);
+       return_val_if_nok (error, NULL);
        sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
        sig->ret = &mono_defaults.void_class->byval_arg;
        return sig;
@@ -10749,15 +10778,20 @@ ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
  * LOCKING: Assumes the loader lock is held.
  */
 static MonoMethodSignature*
-method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
-       MonoError error;
+method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
        MonoMethodSignature *sig;
 
-       sig = parameters_to_signature (image, method->parameters);
+       mono_error_init (error);
+
+       sig = parameters_to_signature (image, method->parameters, error);
+       return_val_if_nok (error, NULL);
        sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
        if (method->rtype) {
-               sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
+               if (!is_ok (error)) {
+                       image_g_free (image, sig);
+                       return NULL;
+               }
        } else {
                sig->ret = &mono_defaults.void_class->byval_arg;
        }
@@ -10766,15 +10800,20 @@ method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *meth
 }
 
 static MonoMethodSignature*
-dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
-       MonoError error;
+dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
        MonoMethodSignature *sig;
 
-       sig = parameters_to_signature (NULL, method->parameters);
+       mono_error_init (error);
+
+       sig = parameters_to_signature (NULL, method->parameters, error);
+       return_val_if_nok (error, NULL);
        sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
        if (method->rtype) {
-               sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               sig->ret = mono_reflection_type_get_handle (method->rtype, error);
+               if (!is_ok (error)) {
+                       g_free (sig);
+                       return NULL;
+               }
        } else {
                sig->ret = &mono_defaults.void_class->byval_arg;
        }
@@ -10783,15 +10822,14 @@ dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
 }
 
 static void
-get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
+get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
 {
-       MonoError error;
+       mono_error_init (error);
        MonoClass *klass = mono_object_class (prop);
        if (strcmp (klass->name, "PropertyBuilder") == 0) {
                MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
                *name = mono_string_to_utf8 (pb->name);
-               *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
        } else {
                MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
                *name = g_strdup (p->property->name);
@@ -10803,15 +10841,14 @@ get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
 }
 
 static void
-get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
+get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
 {
-       MonoError error;
+       mono_error_init (error);
        MonoClass *klass = mono_object_class (field);
        if (strcmp (klass->name, "FieldBuilder") == 0) {
                MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
                *name = mono_string_to_utf8 (fb->name);
-               *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
        } else {
                MonoReflectionField *f = (MonoReflectionField *)field;
                *name = g_strdup (mono_field_get_name (f->field));
@@ -10914,7 +10951,8 @@ mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *er
 
        return type;
 }
-/*
+/**
+ * encode_cattr_value:
  * Encode a value in a custom attribute stream of bytes.
  * The value to encode is either supplied as an object in argument val
  * (valuetypes are boxed), or as a pointer to the data in the
@@ -10925,13 +10963,14 @@ mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *er
  * @buflen contains the size of the buffer and is used to return the new buffer size
  * if this needs to be realloced.
  * @retbuffer and @retp return the start and the position of the buffer
+ * @error set on error.
  */
 static void
-encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
+encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
 {
-       MonoError error;
        MonoTypeEnum simple_type;
        
+       mono_error_init (error);
        if ((p-buffer) + 10 >= *buflen) {
                char *newbuf;
                *buflen *= 2;
@@ -11010,8 +11049,9 @@ handle_enum:
                        break;
                }
 handle_type:
-               arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
+               return_if_nok (error);
+
                str = type_get_qualified_name (arg_type, NULL);
                slen = strlen (str);
                if ((p-buffer) + 10 + slen >= *buflen) {
@@ -11054,19 +11094,22 @@ handle_type:
                        char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
                        int elsize = mono_class_array_element_size (arg_eclass);
                        for (i = 0; i < len; ++i) {
-                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
+                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
+                               return_if_nok (error);
                                elptr += elsize;
                        }
                } else if (eclass->valuetype && arg_eclass->valuetype) {
                        char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
                        int elsize = mono_class_array_element_size (eclass);
                        for (i = 0; i < len; ++i) {
-                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
+                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
+                               return_if_nok (error);
                                elptr += elsize;
                        }
                } else {
                        for (i = 0; i < len; ++i) {
-                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
+                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
+                               return_if_nok (error);
                        }
                }
                break;
@@ -11106,7 +11149,8 @@ handle_type:
                                *p++ = 0x51;
                        else
                                *p++ = klass->element_class->byval_arg.type;
-                       encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
+                       encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
+                       return_if_nok (error);
                        break;
                } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
                        *p++ = simple_type = klass->byval_arg.type;
@@ -11171,9 +11215,12 @@ encode_field_or_prop_type (MonoType *type, char *p, char **retp)
 
 #ifndef DISABLE_REFLECTION_EMIT
 static void
-encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
+encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
 {
        int len;
+
+       mono_error_init (error);
+
        /* Preallocate a large enough buffer */
        if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
                char *str = type_get_qualified_name (type, NULL);
@@ -11203,12 +11250,13 @@ encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char
        mono_metadata_encode_value (len, p, &p);
        memcpy (p, name, len);
        p += len;
-       encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
+       encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
+       return_if_nok (error);
        *retp = p;
        *retbuffer = buffer;
 }
 
-/*
+/**
  * mono_reflection_get_custom_attrs_blob:
  * @ctor: custom attribute constructor
  * @ctorArgs: arguments o the constructor
@@ -11224,15 +11272,44 @@ encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char
 MonoArray*
 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
 {
-       MonoArray *result;
+       MonoError error;
+       MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
+       mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
+       return result;
+}
+
+/**
+ * mono_reflection_get_custom_attrs_blob_checked:
+ * @ctor: custom attribute constructor
+ * @ctorArgs: arguments o the constructor
+ * @properties:
+ * @propValues:
+ * @fields:
+ * @fieldValues:
+ * @error: set on error
+ * 
+ * Creates the blob of data that needs to be saved in the metadata and that represents
+ * the custom attributed described by @ctor, @ctorArgs etc.
+ * Returns: a Byte array representing the blob of data.  On failure returns NULL and sets @error.
+ */
+MonoArray*
+mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error) 
+{
+       MonoArray *result = NULL;
        MonoMethodSignature *sig;
        MonoObject *arg;
        char *buffer, *p;
        guint32 buflen, i;
 
+       mono_error_init (error);
+
        if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
                /* sig is freed later so allocate it in the heap */
-               sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
+               sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
+               if (!is_ok (error)) {
+                       g_free (sig);
+                       return NULL;
+               }
        } else {
                sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
        }
@@ -11245,7 +11322,8 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
        *p++ = 0;
        for (i = 0; i < sig->param_count; ++i) {
                arg = mono_array_get (ctorArgs, MonoObject*, i);
-               encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
+               encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
+               if (!is_ok (error)) goto leave;
        }
        i = 0;
        if (properties)
@@ -11261,10 +11339,12 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
                        char *pname;
 
                        prop = (MonoObject *)mono_array_get (properties, gpointer, i);
-                       get_prop_name_and_type (prop, &pname, &ptype);
+                       get_prop_name_and_type (prop, &pname, &ptype, error);
+                       if (!is_ok (error)) goto leave;
                        *p++ = 0x54; /* PROPERTY signature */
-                       encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
+                       encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
                        g_free (pname);
+                       if (!is_ok (error)) goto leave;
                }
        }
 
@@ -11275,10 +11355,12 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
                        char *fname;
 
                        field = (MonoObject *)mono_array_get (fields, gpointer, i);
-                       get_field_name_and_type (field, &fname, &ftype);
+                       get_field_name_and_type (field, &fname, &ftype, error);
+                       if (!is_ok (error)) goto leave;
                        *p++ = 0x53; /* FIELD signature */
-                       encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
+                       encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
                        g_free (fname);
+                       if (!is_ok (error)) goto leave;
                }
        }
 
@@ -11287,36 +11369,40 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
        result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
        p = mono_array_addr (result, char, 0);
        memcpy (p, buffer, buflen);
+leave:
        g_free (buffer);
        if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
                g_free (sig);
        return result;
 }
 
-/*
- * mono_reflection_setup_internal_class:
+/**
+ * reflection_setup_internal_class:
  * @tb: a TypeBuilder object
+ * @error: set on error
  *
  * Creates a MonoClass that represents the TypeBuilder.
  * This is a trick that lets us simplify a lot of reflection code
  * (and will allow us to support Build and Run assemblies easier).
+ *
+ * Returns TRUE on success. On failure, returns FALSE and sets @error.
  */
-void
-mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
+static gboolean
+reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
 {
-       MonoError error;
        MonoClass *klass, *parent;
 
-       RESOLVE_TYPE (tb->parent, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_error_init (error);
+       RESOLVE_TYPE (tb->parent, error);
+       return_val_if_nok (error, FALSE);
 
        mono_loader_lock ();
 
        if (tb->parent) {
-               MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
-               if (!is_ok (&error)) {
+               MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
+               if (!is_ok (error)) {
                        mono_loader_unlock ();
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return FALSE;
                }
                /* check so we can compile corlib correctly */
                if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
@@ -11338,7 +11424,7 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
                mono_class_setup_parent (klass, parent);
                mono_class_setup_mono_type (klass);
                mono_loader_unlock ();
-               return;
+               return TRUE;
        }
 
        klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
@@ -11346,11 +11432,11 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
        klass->image = &tb->module->dynamic_image->image;
 
        klass->inited = 1; /* we lie to the runtime */
-       klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
-       if (!mono_error_ok (&error))
+       klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
+       if (!is_ok (error))
                goto failure;
-       klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
-       if (!mono_error_ok (&error))
+       klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
+       if (!is_ok (error))
                goto failure;
        klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
        klass->flags = tb->attrs;
@@ -11411,8 +11497,8 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
 
        if (tb->nesting_type) {
                g_assert (tb->nesting_type->type);
-               MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
-               if (!is_ok (&error)) goto failure;
+               MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
+               if (!is_ok (error)) goto failure;
                klass->nested_in = mono_class_from_mono_type (nesting_type);
        }
 
@@ -11421,11 +11507,29 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
        mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
        
        mono_loader_unlock ();
-       return;
+       return TRUE;
 
 failure:
        mono_loader_unlock ();
-       mono_error_raise_exception (&error);
+       return FALSE;
+}
+
+/**
+ * mono_reflection_setup_internal_class:
+ * @tb: a TypeBuilder object
+ *
+ * (icall)
+ * Creates a MonoClass that represents the TypeBuilder.
+ * This is a trick that lets us simplify a lot of reflection code
+ * (and will allow us to support Build and Run assemblies easier).
+ *
+ */
+void
+mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
+{
+       MonoError error;
+       (void) reflection_setup_internal_class (tb, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 /*
@@ -11486,18 +11590,22 @@ mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
        klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
 }
 
-/*
- * mono_reflection_create_internal_class:
+/**
+ * reflection_create_internal_class:
  * @tb: a TypeBuilder object
+ * @error: set on error
  *
  * Actually create the MonoClass that is associated with the TypeBuilder.
+ * On success returns TRUE, on failure returns FALSE and sets @error.
+ *
  */
-void
-mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
+static gboolean
+reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
 {
-       MonoError error;
+
        MonoClass *klass;
 
+       mono_error_init (error);
        klass = mono_class_from_mono_type (tb->type.type);
 
        mono_loader_lock ();
@@ -11511,20 +11619,20 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
 
                fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
 
-               MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
-               if (!is_ok (&error)) {
+               MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+               if (!is_ok (error)) {
                        mono_loader_unlock ();
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return FALSE;
                }
                if (!mono_type_is_valid_enum_basetype (field_type)) {
                        mono_loader_unlock ();
-                       return;
+                       return TRUE;
                }
 
-               enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
-               if (!is_ok (&error)) {
+               enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+               if (!is_ok (error)) {
                        mono_loader_unlock ();
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return FALSE;
                }
                klass->element_class = mono_class_from_mono_type (enum_basetype);
                if (!klass->element_class)
@@ -11544,15 +11652,32 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
                mono_class_setup_vtable_general (klass, NULL, 0, NULL);
        }
        mono_loader_unlock ();
+       return TRUE;
+}
+
+/**
+ * mono_reflection_create_internal_class:
+ * @tb: a TypeBuilder object
+ *
+ * (icall)
+ * Actually create the MonoClass that is associated with the TypeBuilder.
+ */
+void
+mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
+{
+       MonoError error;
+       (void) reflection_create_internal_class (tb, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 static MonoMarshalSpec*
 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
-                                                               MonoReflectionMarshal *minfo)
+                               MonoReflectionMarshal *minfo, MonoError *error)
 {
-       MonoError error;
        MonoMarshalSpec *res;
 
+       mono_error_init (error);
+
        res = image_g_new0 (image, MonoMarshalSpec, 1);
        res->native = (MonoMarshalNative)minfo->type;
 
@@ -11578,8 +11703,11 @@ mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
 
        case MONO_NATIVE_CUSTOM:
                if (minfo->marshaltyperef) {
-                       MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
+                       if (!is_ok (error)) {
+                               image_g_free (image, res);
+                               return NULL;
+                       }
                        res->data.custom_data.custom_name =
                                type_get_fully_qualified_name (marshaltyperef);
                }
@@ -11900,7 +12028,12 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                                        if (specs == NULL)
                                                specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
                                        specs [pb->position] = 
-                                               mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
+                                               mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, &error);
+                                       if (!is_ok (&error)) {
+                                               mono_loader_unlock ();
+                                               image_g_free (image, specs);
+                                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                                       }
                                }
                        }
                }
@@ -11925,8 +12058,10 @@ ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, Mon
        MonoMethodSignature *sig;
 
        mono_loader_lock ();
-       sig = ctor_builder_to_signature (klass->image, mb);
+       g_assert (klass->image != NULL);
+       sig = ctor_builder_to_signature (klass->image, mb, error);
        mono_loader_unlock ();
+       return_val_if_nok (error, NULL);
 
        if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
                return NULL;
@@ -11952,8 +12087,10 @@ methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb,
        mono_error_init (error);
 
        mono_loader_lock ();
-       sig = method_builder_to_signature (klass->image, mb);
+       g_assert (klass->image != NULL);
+       sig = method_builder_to_signature (klass->image, mb, error);
        mono_loader_unlock ();
+       return_val_if_nok (error, NULL);
 
        if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
                return NULL;
@@ -11970,39 +12107,40 @@ methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb,
 }
 
 static MonoClassField*
-fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
+fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
 {
        MonoClassField *field;
        MonoType *custom;
-       MonoError error;
+
+       mono_error_init (error);
 
        field = g_new0 (MonoClassField, 1);
 
-       field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
-       g_assert (mono_error_ok (&error));
+       field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
+       mono_error_assert_ok (error);
        if (fb->attrs || fb->modreq || fb->modopt) {
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
-               if (!is_ok (&error)) {
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+               if (!is_ok (error)) {
                        g_free (field);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return NULL;
                }
                field->type = mono_metadata_type_dup (NULL, type);
                field->type->attrs = fb->attrs;
 
                g_assert (image_is_dynamic (klass->image));
-               custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, &error);
+               custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
                g_free (field->type);
-               if (!is_ok (&error)) {
+               if (!is_ok (error)) {
                        g_free (field);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return NULL;
                }
                field->type = mono_metadata_type_dup (klass->image, custom);
                g_free (custom);
        } else {
-               field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
-               if (!is_ok (&error)) {
+               field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
+               if (!is_ok (error)) {
                        g_free (field);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return NULL;
                }
        }
        if (fb->offset != -1)
@@ -12016,15 +12154,26 @@ fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder*
 }
 #endif
 
+/**
+ * mono_reflection_bind_generic_parameters:
+ * @type: a managed type object (which should be some kind of generic (instance? definition?))
+ * @type_args: the number of type arguments to bind
+ * @types: array of type arguments
+ * @error: set on error
+ *
+ * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
+ * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
+ */
 MonoType*
-mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
+mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
 {
-       MonoError error;
        MonoClass *klass;
        MonoReflectionTypeBuilder *tb = NULL;
        gboolean is_dynamic = FALSE;
        MonoClass *geninst;
 
+       mono_error_init (error);
+       
        mono_loader_lock ();
 
        if (is_sre_type_builder (mono_object_class (type))) {
@@ -12045,12 +12194,16 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc
        if (tb && tb->generic_container)
                mono_reflection_create_generic_class (tb);
 
-       MonoType *t = mono_reflection_type_get_handle (type, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       MonoType *t = mono_reflection_type_get_handle (type, error);
+       if (!is_ok (error)) {
+               mono_loader_unlock ();
+               return NULL;
+       }
 
        klass = mono_class_from_mono_type (t);
        if (!klass->generic_container) {
                mono_loader_unlock ();
+               mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
                return NULL;
        }
 
@@ -12259,29 +12412,30 @@ inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
 }
 
 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
-void
-mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
+static gboolean
+reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
 {
-       MonoError error;
        MonoGenericClass *gclass;
        MonoDynamicGenericClass *dgclass;
        MonoClass *klass, *gklass;
        MonoType *gtype;
        int i;
 
-       gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_error_init (error);
+
+       gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
+       return_val_if_nok (error, FALSE);
        klass = mono_class_from_mono_type (gtype);
        g_assert (gtype->type == MONO_TYPE_GENERICINST);
        gclass = gtype->data.generic_class;
 
        if (!gclass->is_dynamic)
-               return;
+               return TRUE;
 
        dgclass = (MonoDynamicGenericClass *) gclass;
 
        if (dgclass->initialized)
-               return;
+               return TRUE;
 
        gklass = gclass->container_class;
        mono_class_init (gklass);
@@ -12293,13 +12447,13 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
        dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
 
        for (i = 0; i < dgclass->count_fields; i++) {
-               MonoError error;
                MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
                MonoClassField *field, *inflated_field = NULL;
 
-               if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
-                       inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
-               else if (!strcmp (obj->vtable->klass->name, "MonoField"))
+               if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
+                       inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
+                       return_val_if_nok (error, FALSE);
+               } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
                        field = ((MonoReflectionField *) obj)->field;
                else {
                        field = NULL; /* prevent compiler warning */
@@ -12309,8 +12463,8 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
                dgclass->fields [i] = *field;
                dgclass->fields [i].parent = klass;
                dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
-                       field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
-               mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+                       field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
+               mono_error_assert_ok (error); /* FIXME don't swallow the error */
                dgclass->field_generic_types [i] = field->type;
                MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
                dgclass->field_objects [i] = obj;
@@ -12323,6 +12477,15 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
        }
 
        dgclass->initialized = TRUE;
+       return TRUE;
+}
+
+void
+mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
+{
+       MonoError error;
+       (void) reflection_generic_class_initialize (type, fields, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 void
@@ -12342,21 +12505,34 @@ mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
        }
 }
 
-static void
-fix_partial_generic_class (MonoClass *klass)
+/**
+ * fix_partial_generic_class:
+ * @klass: a generic instantiation MonoClass
+ * @error: set on error
+ *
+ * Assumes that the generic container of @klass has its vtable
+ * initialized, and updates the parent class, insterfaces, methods and
+ * fields of @klass by inflating the types using the generic context.
+ *
+ * On success returns TRUE, on failure returns FALSE and sets @error.
+ *
+ */
+static gboolean
+fix_partial_generic_class (MonoClass *klass, MonoError *error)
 {
        MonoClass *gklass = klass->generic_class->container_class;
        MonoDynamicGenericClass *dgclass;
        int i;
 
+       mono_error_init (error);
+
        if (klass->wastypebuilder)
-               return;
+               return TRUE;
 
        dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
        if (klass->parent != gklass->parent) {
-               MonoError error;
-               MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
-               if (mono_error_ok (&error)) {
+               MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
+               if (mono_error_ok (error)) {
                        MonoClass *parent = mono_class_from_mono_type (parent_type);
                        mono_metadata_free_type (parent_type);
                        if (parent != klass->parent) {
@@ -12365,26 +12541,23 @@ fix_partial_generic_class (MonoClass *klass)
                                mono_class_setup_parent (klass, parent);
                        }
                } else {
-                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
-                       mono_error_cleanup (&error);
                        if (gklass->wastypebuilder)
                                klass->wastypebuilder = TRUE;
-                       return;
+                       return FALSE;
                }
        }
 
        if (!dgclass->initialized)
-               return;
+               return TRUE;
 
        if (klass->method.count != gklass->method.count) {
                klass->method.count = gklass->method.count;
                klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
 
                for (i = 0; i < klass->method.count; i++) {
-                       MonoError error;
                        klass->methods [i] = mono_class_inflate_generic_method_full_checked (
-                               gklass->methods [i], klass, mono_class_get_context (klass), &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                               gklass->methods [i], klass, mono_class_get_context (klass), error);
+                       mono_error_assert_ok (error);
                }
        }
 
@@ -12394,15 +12567,14 @@ fix_partial_generic_class (MonoClass *klass)
                klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
 
                for (i = 0; i < gklass->interface_count; ++i) {
-                       MonoError error;
-                       MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
+                       return_val_if_nok (error, FALSE);
 
                        klass->interfaces [i] = mono_class_from_mono_type (iface_type);
                        mono_metadata_free_type (iface_type);
 
-                       ensure_runtime_vtable (klass->interfaces [i], &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       if (!ensure_runtime_vtable (klass->interfaces [i], error))
+                               return FALSE;
                }
                klass->interfaces_inited = 1;
        }
@@ -12412,18 +12584,17 @@ fix_partial_generic_class (MonoClass *klass)
                klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
 
                for (i = 0; i < klass->field.count; i++) {
-                       MonoError error;
                        klass->fields [i] = gklass->fields [i];
                        klass->fields [i].parent = klass;
-                       klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
+                       return_val_if_nok (error, FALSE);
                }
        }
 
        /*We can only finish with this klass once it's parent has as well*/
        if (gklass->wastypebuilder)
                klass->wastypebuilder = TRUE;
-       return;
+       return TRUE;
 }
 
 /**
@@ -12444,9 +12615,7 @@ ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
        if (!ensure_runtime_vtable (gklass, error))
                return FALSE;
 
-       fix_partial_generic_class (klass);
-
-       return TRUE;
+       return fix_partial_generic_class (klass, error);
 }
 
 /**
@@ -12505,8 +12674,10 @@ ensure_runtime_vtable (MonoClass *klass, MonoError *error)
                        klass->interfaces_inited = 1;
                }
        } else if (klass->generic_class){
-               if (!ensure_generic_class_runtime_vtable (klass, error))
+               if (!ensure_generic_class_runtime_vtable (klass, error)) {
+                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        return FALSE;
+               }
        }
 
        if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
@@ -12537,9 +12708,9 @@ ensure_runtime_vtable (MonoClass *klass, MonoError *error)
 }
 
 static MonoMethod*
-mono_reflection_method_get_handle (MonoObject *method)
+mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
 {
-       MonoError error;
+       mono_error_init (error);
        MonoClass *klass = mono_object_class (method);
        if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
                MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
@@ -12554,11 +12725,10 @@ mono_reflection_method_get_handle (MonoObject *method)
                MonoMethod *result;
                /*FIXME move this to a proper method and unify with resolve_object*/
                if (m->method_args) {
-                       result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       result = mono_reflection_method_on_tb_inst_get_handle (m, error);
                } else {
-                       MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
+                       return_val_if_nok (error, NULL);
                        MonoClass *inflated_klass = mono_class_from_mono_type (type);
                        MonoMethod *mono_method;
 
@@ -12579,12 +12749,13 @@ mono_reflection_method_get_handle (MonoObject *method)
 }
 
 void
-mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
+mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
 {
        MonoReflectionTypeBuilder *tb;
        int i, j, onum;
        MonoReflectionMethod *m;
 
+       mono_error_init (error);
        *overrides = NULL;
        *num_overrides = 0;
 
@@ -12618,7 +12789,8 @@ mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides
                                for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
                                        m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
 
-                                       (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
+                                       (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
+                                       return_if_nok (error);
                                        (*overrides) [onum * 2 + 1] = mb->mhandle;
 
                                        g_assert (mb->mhandle);
@@ -12775,15 +12947,19 @@ typebuilder_setup_properties (MonoClass *klass, MonoError *error)
        }
 }
 
-MonoReflectionEvent *
-mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
+static MonoReflectionEvent *
+reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
 {
-       MonoError error;
+       mono_error_init (error);
+
        MonoEvent *event = g_new0 (MonoEvent, 1);
        MonoClass *klass;
 
-       MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
+       if (!is_ok (error)) {
+               g_free (event);
+               return NULL;
+       }
        klass = mono_class_from_mono_type (type);
 
        event->parent = klass;
@@ -12809,11 +12985,26 @@ mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, Mon
        }
 #endif
 
-       MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
+       if (!is_ok (error)) {
+#ifndef MONO_SMALL_CONFIG
+               g_free (event->other);
+#endif
+               g_free (event);
+               return NULL;
+       }
        return ev_obj;
 }
 
+MonoReflectionEvent *
+mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
+{
+       MonoError error;
+       MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
+}
+
 static void
 typebuilder_setup_events (MonoClass *klass, MonoError *error)
 {
@@ -12863,16 +13054,34 @@ typebuilder_setup_events (MonoClass *klass, MonoError *error)
        }
 }
 
+struct remove_instantiations_user_data
+{
+       MonoClass *klass;
+       MonoError *error;
+};
+
 static gboolean
 remove_instantiations_of_and_ensure_contents (gpointer key,
                                                  gpointer value,
                                                  gpointer user_data)
 {
+       struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
        MonoType *type = (MonoType*)key;
-       MonoClass *klass = (MonoClass*)user_data;
+       MonoClass *klass = data->klass;
+       gboolean already_failed = !is_ok (data->error);
+       MonoError lerror;
+       MonoError *error = already_failed ? &lerror : data->error;
 
        if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
-               fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
+               MonoClass *inst_klass = mono_class_from_mono_type (type);
+               //Ensure it's safe to use it.
+               if (!fix_partial_generic_class (inst_klass, error)) {
+                       mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       // Marked the class with failure, but since some other instantiation already failed,
+                       // just report that one, and swallow the error from this one.
+                       if (already_failed)
+                               mono_error_cleanup (error);
+               }
                return TRUE;
        } else
                return FALSE;
@@ -12903,6 +13112,8 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        MonoReflectionType* res;
        int i, j;
 
+       mono_error_init (&error);
+
        domain = mono_object_domain (tb);
        klass = mono_class_from_mono_type (tb->type.type);
 
@@ -12910,22 +13121,28 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
         * Check for user defined Type subclasses.
         */
        RESOLVE_TYPE (tb->parent, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       if (!is_ok (&error))
+               goto failure_unlocked;
        check_array_for_usertypes (tb->interfaces, &error);
-       mono_error_raise_exception (&error); /*FIXME don't raise here */
+       if (!is_ok (&error))
+               goto failure_unlocked;
        if (tb->fields) {
                for (i = 0; i < mono_array_length (tb->fields); ++i) {
                        MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
                        if (fb) {
                                RESOLVE_TYPE (fb->type, &error);
-                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                check_array_for_usertypes (fb->modreq, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                check_array_for_usertypes (fb->modopt, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
                                        RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
-                                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                                       if (!is_ok (&error))
+                                               goto failure_unlocked;
                                }
                        }
                }
@@ -12935,22 +13152,28 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
                        MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
                        if (mb) {
                                RESOLVE_TYPE (mb->rtype, &error);
-                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                check_array_for_usertypes (mb->return_modreq, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                check_array_for_usertypes (mb->return_modopt, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                check_array_for_usertypes (mb->parameters, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                if (mb->param_modreq)
                                        for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
                                                check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
-                                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                                               if (!is_ok (&error))
+                                                       goto failure_unlocked;
                                        }
                                if (mb->param_modopt)
                                        for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
                                                check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
-                                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                                               if (!is_ok (&error))
+                                                       goto failure_unlocked;
                                        }
                        }
                }
@@ -12960,16 +13183,19 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
                        MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
                        if (mb) {
                                check_array_for_usertypes (mb->parameters, &error);
-                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                               if (!is_ok (&error))
+                                       goto failure_unlocked;
                                if (mb->param_modreq)
                                        for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
                                                check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
-                                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                                               if (!is_ok (&error))
+                                                       goto failure_unlocked;
                                        }
                                if (mb->param_modopt)
                                        for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
                                                check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
-                                               mono_error_raise_exception (&error); /*FIXME don't raise here */
+                                               if (!is_ok (&error))
+                                                       goto failure_unlocked;
                                        }
                        }
                }
@@ -12988,7 +13214,7 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
                mono_loader_unlock ();
 
                res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_error_set_pending_exception (&error);
 
                return res;
        }
@@ -13016,7 +13242,7 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
                        mono_domain_unlock (domain);
 
                        res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_error_set_pending_exception (&error);
 
                        return res;
                }
@@ -13077,19 +13303,28 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
         *
         * Together with this we must ensure the contents of all instances to match the created type.
         */
-       if (domain->type_hash && klass->generic_container)
-               mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
+       if (domain->type_hash && klass->generic_container) {
+               struct remove_instantiations_user_data data;
+               data.klass = klass;
+               data.error = &error;
+               mono_error_assert_ok (&error);
+               mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
+               if (!is_ok (&error))
+                       goto failure;
+       }
 
        mono_domain_unlock (domain);
        mono_loader_unlock ();
 
        if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
-               mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
+               mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
+               goto failure_unlocked;
        }
 
        res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       if (!is_ok (&error))
+               goto failure_unlocked;
 
        g_assert (res != (MonoReflectionType*)tb);
 
@@ -13100,30 +13335,32 @@ failure:
        klass->wastypebuilder = TRUE;
        mono_domain_unlock (domain);
        mono_loader_unlock ();
-       mono_error_raise_exception (&error);
+failure_unlocked:
+       mono_error_set_pending_exception (&error);
        return NULL;
 }
 
-void
-mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
+static gboolean
+reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
 {
        MonoGenericParamFull *param;
        MonoImage *image;
        MonoClass *pklass;
-       MonoError error;
+
+       mono_error_init (error);
 
        image = &gparam->tbuilder->module->dynamic_image->image;
 
        param = mono_image_new0 (image, MonoGenericParamFull, 1);
 
-       param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
-       g_assert (mono_error_ok (&error));
+       param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
+       mono_error_assert_ok (error);
        param->param.num = gparam->index;
 
        if (gparam->mbuilder) {
                if (!gparam->mbuilder->generic_container) {
-                       MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
+                       return_val_if_nok (error, FALSE);
 
                        MonoClass *klass = mono_class_from_mono_type (tb);
                        gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
@@ -13138,8 +13375,8 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam
                param->param.owner = gparam->mbuilder->generic_container;
        } else if (gparam->tbuilder) {
                if (!gparam->tbuilder->generic_container) {
-                       MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
+                       return_val_if_nok (error, FALSE);
                        MonoClass *klass = mono_class_from_mono_type (tb);
                        gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
                        gparam->tbuilder->generic_container->owner.klass = klass;
@@ -13153,8 +13390,19 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam
 
        mono_class_set_ref_info (pklass, gparam);
        mono_image_append_class_to_reflection_info_set (pklass);
+
+       return TRUE;
 }
 
+void
+mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
+{
+       MonoError error;
+       (void) reflection_initialize_generic_parameter (gparam, &error);
+       mono_error_set_pending_exception (&error);
+}
+
+
 MonoArray *
 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
 {
@@ -13256,10 +13504,9 @@ free_dynamic_method (void *dynamic_method)
        g_free (data);
 }
 
-void 
-mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
+static gboolean
+reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
 {
-       MonoError error;
        MonoReferenceQueue *queue;
        MonoMethod *handle;
        DynamicMethodReleaseData *release_data;
@@ -13270,8 +13517,12 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
        GSList *l;
        int i;
 
-       if (mono_runtime_is_shutting_down ())
-               mono_raise_exception (mono_get_exception_invalid_operation (""));
+       mono_error_init (error);
+
+       if (mono_runtime_is_shutting_down ()) {
+               mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
+               return FALSE;
+       }
 
        if (!(queue = dynamic_method_queue)) {
                mono_loader_lock ();
@@ -13280,7 +13531,8 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
                mono_loader_unlock ();
        }
 
-       sig = dynamic_method_to_signature (mb);
+       sig = dynamic_method_to_signature (mb, error);
+       return_val_if_nok (error, FALSE);
 
        reflection_methodbuilder_from_dynamic_method (&rmb, mb);
 
@@ -13318,7 +13570,11 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
                        handle_class = mono_defaults.methodhandle_class;
                } else {
                        MonoException *ex = NULL;
-                       ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
+                       ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
+                       if (!is_ok  (error)) {
+                               g_free (rmb.refs);
+                               return FALSE;
+                       }
                        if (!ref)
                                ex = mono_get_exception_type_load (NULL, NULL);
                        else if (mono_security_core_clr_enabled ())
@@ -13326,8 +13582,8 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
 
                        if (ex) {
                                g_free (rmb.refs);
-                               mono_raise_exception (ex);
-                               return;
+                               mono_error_set_exception_instance (error, ex);
+                               return FALSE;
                        }
                }
 
@@ -13336,10 +13592,10 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
        }               
 
        if (mb->owner) {
-               MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
-               if (!is_ok (&error)) {
+               MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
+               if (!is_ok (error)) {
                        g_free (rmb.refs);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       return FALSE;
                }
                klass = mono_class_from_mono_type (owner_type);
        } else {
@@ -13380,6 +13636,16 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
                domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
        g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
        mono_domain_unlock (domain);
+
+       return TRUE;
+}
+
+void
+mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
+{
+       MonoError error;
+       (void) reflection_create_dynamic_method (mb, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 #endif /* DISABLE_REFLECTION_EMIT */
@@ -13427,6 +13693,7 @@ mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32
 gpointer
 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
 {
+       MonoError error;
        MonoDynamicImage *assembly = (MonoDynamicImage*)image;
        MonoObject *obj;
        MonoClass *klass;
@@ -13441,7 +13708,9 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean
 
        if (!handle_class)
                handle_class = &klass;
-       return resolve_object (image, obj, handle_class, context);
+       gpointer result = resolve_object (image, obj, handle_class, context, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       return result;
 }
 
 /*
@@ -13451,15 +13720,15 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean
  * dynamic types.
  */
 static void
-ensure_complete_type (MonoClass *klass)
+ensure_complete_type (MonoClass *klass, MonoError *error)
 {
-       MonoError error;
+       mono_error_init (error);
 
        if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
 
-               mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+               return_if_nok (error);
 
                // Asserting here could break a lot of code
                //g_assert (klass->wastypebuilder);
@@ -13470,32 +13739,36 @@ ensure_complete_type (MonoClass *klass)
                int i;
 
                for (i = 0; i < inst->type_argc; ++i) {
-                       ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
+                       ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
+                       return_if_nok (error);
                }
        }
 }
 
 static gpointer
-resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
+resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
 {
-       MonoError error;
        gpointer result = NULL;
 
+       mono_error_init (error);
+
        if (strcmp (obj->vtable->klass->name, "String") == 0) {
-               result = mono_string_intern_checked ((MonoString*)obj, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               result = mono_string_intern_checked ((MonoString*)obj, error);
+               return_val_if_nok (error, NULL);
                *handle_class = mono_defaults.string_class;
                g_assert (result);
        } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
+               return_val_if_nok (error, NULL);
                MonoClass *mc = mono_class_from_mono_type (type);
-               if (!mono_class_init (mc))
-                       mono_raise_exception (mono_class_get_exception_for_failure (mc));
+               if (!mono_class_init (mc)) {
+                       mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
+                       return NULL;
+               }
 
                if (context) {
-                       MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
+                       return_val_if_nok (error, NULL);
 
                        result = mono_class_from_mono_type (inflated);
                        mono_metadata_free_type (inflated);
@@ -13510,9 +13783,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                   strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
                result = ((MonoReflectionMethod*)obj)->method;
                if (context) {
-                       MonoError error;
-                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+                       mono_error_assert_ok (error);
                }
                *handle_class = mono_defaults.methodhandle_class;
                g_assert (result);
@@ -13523,8 +13795,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                        /* Type is not yet created */
                        MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
 
-                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+                       return_val_if_nok (error, NULL);
 
                        /*
                         * Hopefully this has been filled in by calling CreateType() on the
@@ -13537,9 +13809,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                        result = mb->mhandle;
                }
                if (context) {
-                       MonoError error;
-                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+                       mono_error_assert_ok (error);
                }
                *handle_class = mono_defaults.methodhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
@@ -13549,23 +13820,24 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                if (!result) {
                        MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
 
-                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+                       return_val_if_nok (error, NULL);
                        result = cb->mhandle;
                }
                if (context) {
-                       MonoError error;
-                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                       result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+                       mono_error_assert_ok (error);
                }
                *handle_class = mono_defaults.methodhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
                MonoClassField *field = ((MonoReflectionField*)obj)->field;
 
-               ensure_complete_type (field->parent);
+               ensure_complete_type (field->parent, error);
+               return_val_if_nok (error, NULL);
+
                if (context) {
-                       MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
+                       return_val_if_nok (error, NULL);
 
                        MonoClass *klass = mono_class_from_mono_type (inflated);
                        MonoClassField *inflated_field;
@@ -13589,15 +13861,15 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                if (!result) {
                        MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
 
-                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+                       return_val_if_nok (error, NULL);
                        result = fb->handle;
                }
 
                if (fb->handle && fb->handle->parent->generic_container) {
                        MonoClass *klass = fb->handle->parent;
-                       MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
+                       return_val_if_nok (error, NULL);
 
                        MonoClass *inflated = mono_class_from_mono_type (type);
 
@@ -13608,8 +13880,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                *handle_class = mono_defaults.fieldhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
+               return_val_if_nok (error, NULL);
                MonoClass *klass;
 
                klass = type->data.klass;
@@ -13618,8 +13890,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                        result = klass;
                }
                else {
-                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
+                       return_val_if_nok (error, NULL);
                        result = type->data.klass;
                        g_assert (result);
                }
@@ -13651,8 +13923,11 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                /* TODO: Copy type ? */
                sig->ret = helper->return_type->type;
                for (i = 0; i < nargs; ++i) {
-                       sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
+                       if (!is_ok (error)) {
+                               image_g_free (image, sig);
+                               return NULL;
+                       }
                }
 
                result = sig;
@@ -13664,20 +13939,20 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                result = method->mhandle;
                *handle_class = mono_defaults.methodhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
-               type = mono_class_inflate_generic_type_checked (type, context, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
+               return_val_if_nok (error, NULL);
+               type = mono_class_inflate_generic_type_checked (type, context, error);
+               return_val_if_nok (error, NULL);
 
                result = mono_class_from_mono_type (type);
                *handle_class = mono_defaults.typehandle_class;
                g_assert (result);
                mono_metadata_free_type (type);
        } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
-               type = mono_class_inflate_generic_type_checked (type, context, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
+               return_val_if_nok (error, NULL);
+               type = mono_class_inflate_generic_type_checked (type, context, error);
+               return_val_if_nok (error, NULL);
 
                result = mono_class_from_mono_type (type);
                *handle_class = mono_defaults.typehandle_class;
@@ -13696,24 +13971,29 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                else
                        g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
 
-               MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
-               type = mono_class_inflate_generic_type_checked (finst, context, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
+               return_val_if_nok (error, NULL);
+               type = mono_class_inflate_generic_type_checked (finst, context, error);
+               return_val_if_nok (error, NULL);
 
                inflated = mono_class_from_mono_type (type);
 
                result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
-               ensure_complete_type (field->parent);
+               ensure_complete_type (field->parent, error);
+               if (!is_ok (error)) {
+                       mono_metadata_free_type (type);
+                       return NULL;
+               }
+
                g_assert (result);
                mono_metadata_free_type (type);
                *handle_class = mono_defaults.fieldhandle_class;
        } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
                MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
-               MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
-               MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
+               return_val_if_nok (error, NULL);
+               MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
+               return_val_if_nok (error, NULL);
 
                MonoClass *inflated_klass = mono_class_from_mono_type (type);
                MonoMethod *method;
@@ -13731,17 +14011,17 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
        } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
                MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
                if (m->method_args) {
-                       result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       result = mono_reflection_method_on_tb_inst_get_handle (m, error);
+                       return_val_if_nok (error, NULL);
                        if (context) {
-                               result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
-                               mono_error_assert_ok (&error);
+                               result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
+                               mono_error_assert_ok (error);
                        }
                } else {
-                       MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
-                       MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
+                       return_val_if_nok (error, NULL);
+                       MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
+                       return_val_if_nok (error, NULL);
 
                        MonoClass *inflated_klass = mono_class_from_mono_type (type);
                        MonoMethod *method;
@@ -13765,8 +14045,8 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                gpointer iter;
                char *name;
 
-               mtype = mono_reflection_type_get_handle (m->parent, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mtype = mono_reflection_type_get_handle (m->parent, error);
+               return_val_if_nok (error, NULL);
                klass = mono_class_from_mono_type (mtype);
 
                /* Find the method */
@@ -13789,12 +14069,12 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, Mon
                                is_sre_byref (mono_object_get_class(obj)) ||
                                is_sre_pointer (mono_object_get_class(obj))) {
                MonoReflectionType *ref_type = (MonoReflectionType *)obj;
-               MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *type = mono_reflection_type_get_handle (ref_type, error);
+               return_val_if_nok (error, NULL);
 
                if (context) {
-                       MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
+                       return_val_if_nok (error, NULL);
 
                        result = mono_class_from_mono_type (inflated);
                        mono_metadata_free_type (inflated);
@@ -13901,8 +14181,9 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono
 }
 
 void
-mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
+mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
 {
+       mono_error_init (error);
        *overrides = NULL;
        *num_overrides = 0;
 }
@@ -14395,13 +14676,14 @@ mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDe
 }
 
 gboolean
-mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
+mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
 {
-       MonoError error;
        MonoObject *res, *exc;
        void *params [1];
        static MonoMethod *method = NULL;
 
+       mono_error_init (error);
+
        if (method == NULL) {
                method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
                g_assert (method);
@@ -14414,13 +14696,13 @@ mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
        g_assert (mono_class_get_ref_info (klass));
        g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
 
-       params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
+       return_val_if_nok (error, FALSE);
 
-       res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
+       res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
 
-       if (exc || !mono_error_ok (&error)) {
-               mono_error_cleanup (&error);
+       if (exc || !mono_error_ok (error)) {
+               mono_error_cleanup (error);
                return FALSE;
        } else
                return *(MonoBoolean*)mono_object_unbox (res);
index 164cc4ae87cfe996d18bbeabdea99255c6ca867c..af85ac1b3c3eb1c8423c252eed10cf9fa82f77d9 100644 (file)
@@ -77,6 +77,7 @@ MONO_API MonoArray*  mono_reflection_get_custom_attrs_by_type (MonoObject *obj,
 MONO_API MonoArray*  mono_reflection_get_custom_attrs (MonoObject *obj);
 MONO_RT_EXTERNAL_ONLY
 MONO_API MonoArray*  mono_reflection_get_custom_attrs_data (MonoObject *obj);
+MONO_RT_EXTERNAL_ONLY
 MONO_API MonoArray*  mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *porpValues, MonoArray *fields, MonoArray* fieldValues);
 
 MONO_RT_EXTERNAL_ONLY
index 5e4fa165ab0efc72fd2d09482953ab52b8ee1289..93d5b0858a9f90267acaaea99ad30ca163f3e68a 100644 (file)
@@ -77,7 +77,7 @@ mono_gc_register_bridge_callbacks (MonoGCBridgeCallbacks *callbacks)
        bridge_callbacks = *callbacks;
 
        if (!bridge_processor.reset_data)
-               sgen_old_bridge_init (&bridge_processor);
+               sgen_new_bridge_init (&bridge_processor);
 }
 
 static gboolean
index 6d5feb04e017d390c3a279bf372d1fff13cd8e0c..2366d17c3377b188fad1685e65a70182d3a17d61 100755 (executable)
@@ -1,6 +1,13 @@
 count=100000
 mtest=for_loop
 monodir=$(top_builddir)
+mono=$(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),mono)
+
+if HOST_WIN32
+PLATFORM_PATH_SEPARATOR=;
+else
+PLATFORM_PATH_SEPARATOR=:
+endif
 
 # This is needed for automake dependency generation
 libgc_libs=$(monodir)/libgc/libmonogc.la
@@ -39,7 +46,7 @@ CLASS=$(mcs_topdir)/class/lib/$(DEFAULT_PROFILE)
 RUNTIME_EXECUTABLE = $(if $(BOEHM),$(top_builddir)/mono/mini/mono-boehm,$(top_builddir)/runtime/mono-wrapper)
 
 MINI_RUNTIME = MONO_PATH=$(CLASS) $(RUNTIME_EXECUTABLE)
-RUNTIME_AOTCHECK = MONO_PATH=$(CLASS):. $(RUNTIME_EXECUTABLE)
+RUNTIME_AOTCHECK = MONO_PATH="$(CLASS)$(PLATFORM_PATH_SEPARATOR)." $(RUNTIME_EXECUTABLE)
 
 MCS = $(MINI_RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe -unsafe -nowarn:0162
 ILASM = $(MINI_RUNTIME) $(CLASS)/ilasm.exe
@@ -715,13 +722,13 @@ FULLAOT_LIBS = \
        Mono.Simd.dll
 
 # This currently only works on amd64/arm
-fullaotcheck: mono $(fullaot_regtests)
+fullaotcheck: $(mono) $(fullaot_regtests)
        rm -rf fullaot-tmp
        mkdir fullaot-tmp
        $(MAKE) fullaot-libs AOT_FLAGS=full GSHAREDVT=$(GSHAREDVT)
        cp $(regtests) $(fullaot_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
        MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot=full fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
-       ln -s $$PWD/mono fullaot-tmp/
+       ln -s $(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),$$PWD/mono) fullaot-tmp/
        for i in $(fullaot_regtests); do echo $$i; MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --full-aot fullaot-tmp/$$i --exclude '!FULLAOT' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done
 
 # This can run in parallel
@@ -730,7 +737,7 @@ fullaot-libs: $(patsubst %,fullaot-tmp/%.dylib,$(FULLAOT_LIBS))
 fullaot-tmp/%.dylib: $(CLASS)/%
        cp $(CLASS)/$* fullaot-tmp/
        mkdir fullaot-tmp/$*-tmp
-       MONO_PATH=fullaot-tmp/:$(CLASS) $(top_builddir)/runtime/mono-wrapper $(if $(GSHAREDVT),-O=gsharedvt) --aot=$(AOT_FLAGS),temp-path=fullaot-tmp/$*-tmp fullaot-tmp/$*
+       MONO_PATH="fullaot-tmp/$(PLATFORM_PATH_SEPARATOR)$(CLASS)" $(top_builddir)/runtime/mono-wrapper $(if $(GSHAREDVT),-O=gsharedvt) --aot=$(AOT_FLAGS),temp-path=fullaot-tmp/$*-tmp fullaot-tmp/$*
        rm -rf fullaot-tmp/$*-tmp
 
 llvmfullaotcheck:
index 93756b108b33cb4402a0ca57601aa8b0bb9a25cc..70995807817dd3cf50f4978b046bcf45404f5724 100644 (file)
@@ -1986,7 +1986,10 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
                                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module '%s' not found: %s\n", aot_name, err);
                                g_free (err);
 
-                               aot_name = g_strdup_printf ("%s/mono/aot-cache/%s/%s%s", mono_assembly_getrootdir(), MONO_ARCHITECTURE, g_path_get_basename (assembly->image->name), MONO_SOLIB_EXT);
+                               g_free (aot_name);
+                               char *basename = g_path_get_basename (assembly->image->name);
+                               aot_name = g_strdup_printf ("%s/mono/aot-cache/%s/%s%s", mono_assembly_getrootdir(), MONO_ARCHITECTURE, basename, MONO_SOLIB_EXT);
+                               g_free (basename);
                                sofile = mono_dl_open (aot_name, MONO_DL_LAZY, &err);
                                if (!sofile) {
                                        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module '%s' not found: %s\n", aot_name, err);
index a8bfee03414ab95fe515d69c2dce3f7b178af86a..88f8c2ebb22b780a3c461daf2d8b62e6370f3e68 100644 (file)
@@ -1716,6 +1716,23 @@ public class Tests
                return 0;
        }
 
+       interface ISmallArg {
+               T foo<T> (string s1, string s2, string s3, string s4, string s5, string s6, string s7, string s8,
+                                 string s9, string s10, string s11, string s12, string s13, T t);
+       }
+
+       class SmallArgClass : ISmallArg {
+                       public T foo<T> (string s1, string s2, string s3, string s4, string s5, string s6, string s7, string s8,
+                                                        string s9, string s10, string s11, string s12, string s13, T t) {
+                               return t;
+                       }
+               }
+
+       public static int test_1_small_gsharedvt_stack_arg_ios () {
+               ISmallArg o = new SmallArgClass ();
+               return o.foo<int> ("", "", "", "", "", "", "", "", "", "", "", "", "", 1);
+       }
+
        // Passing vtype normal arguments on the stack
        public static int test_0_arm64_vtype_stack_args () {
                IFoo3<EmptyStruct> o = (IFoo3<EmptyStruct>)Activator.CreateInstance (typeof (Foo3<>).MakeGenericType (new Type [] { typeof (EmptyStruct) }));
index 3d295db2a358a479cdce82160444b1066145b036..87dad9d0c6fa56137e7524682ab406c4dda1a374 100644 (file)
@@ -11649,7 +11649,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                                INLINE_FAILURE ("class init");
                                                        if (!mono_runtime_class_init_full (vtable, &cfg->error)) {
                                                                mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
-                                                               g_assert_not_reached ();
                                                                goto exception_exit;
                                                        }
                                                }
index 66fd8c083b302ec723f148e1f7130b0a1104c9dc..a85047f3873a62ed1c107d74e184b3b21bf867d1 100644 (file)
@@ -2375,6 +2375,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                                        } else {
                                                int creg;
 
+                                               cfg->param_area = MAX (cfg->param_area, 8);
                                                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, ARMREG_SP, (cfg->param_area - 8), in->dreg);
                                                creg = mono_alloc_ireg (cfg);
                                                MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, creg, ARMREG_SP, (cfg->param_area - 8));
@@ -2396,6 +2397,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                                        } else {
                                                int creg;
 
+                                               cfg->param_area = MAX (cfg->param_area, 8);
                                                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, ARMREG_SP, (cfg->param_area - 8), in->dreg);
                                                creg = mono_alloc_ireg (cfg);
                                                MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, creg, ARMREG_SP, (cfg->param_area - 8));
@@ -2467,6 +2469,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
 
                                /* This should work for soft-float as well */
 
+                               cfg->param_area = MAX (cfg->param_area, 8);
                                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, ARMREG_SP, (cfg->param_area - 8), in->dreg);
                                creg = mono_alloc_ireg (cfg);
                                mono_call_inst_add_outarg_reg (cfg, call, creg, ARMREG_R3, FALSE);
index 9e8596e7bf135c3a31b057172fff8588306cdbb7..558db05357e9a8a6085d952badbdbb1b470e6339 100644 (file)
@@ -24,8 +24,6 @@
 #define __STDC_CONSTANT_MACROS
 #endif
 
-#include "llvm-c/Core.h"
-#include "llvm-c/ExecutionEngine.h"
 #include "llvm-c/BitWriter.h"
 #include "llvm-c/Analysis.h"
 
index 6a9f054864b68efb5c4915a9b234c442443ec58e..cce368bdcffebb3489011cd609228d17131ab67e 100644 (file)
@@ -2007,7 +2007,9 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *er
                        MonoVTable *vtable;
 
                        mono_jit_stats.methods_lookups++;
-                       vtable = mono_class_vtable (domain, method->klass);
+                       vtable = mono_class_vtable_full (domain, method->klass, error);
+                       if (!is_ok (error))
+                               return NULL;
                        g_assert (vtable);
                        if (!mono_runtime_class_init_full (vtable, error))
                                return NULL;
index c0d094fc56f1f2a262d9a42d77ccf0e67c01fff2..dbd2e9ad1cc108d8ee2ebbb383738f9b84999af4 100644 (file)
@@ -1117,6 +1117,14 @@ mono_test_marshal_virtual_delegate (VirtualDelegate del)
        return del (42);
 }
 
+typedef char* (STDCALL *IcallDelegate) (const char *);
+LIBTEST_API int STDCALL
+mono_test_marshal_icall_delegate (IcallDelegate del)
+{
+       char *res = del ("ABC");
+       return strcmp (res, "ABC") == 0 ? 0 : 1;
+}
+
 LIBTEST_API int STDCALL  
 mono_test_marshal_stringbuilder (char *s, int n)
 {
index 376e2000187f834b4b5ce0516fa1249cb5ced8cb..29ed8ea7eee8498f00e11aaf06d54b7109a8150d 100644 (file)
@@ -194,6 +194,11 @@ public class Tests {
        [DllImport ("libtest", EntryPoint="mono_test_marshal_virtual_delegate")]
        public static extern int mono_test_marshal_virtual_delegate (VirtualDelegate del);
 
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_icall_delegate")]
+       public static extern int mono_test_marshal_icall_delegate (IcallDelegate del);
+
+       public delegate string IcallDelegate (IntPtr p);
+
        public delegate int TestDelegate (int a, ref SimpleStruct ss, int b);
 
        public delegate SimpleStruct SimpleDelegate2 (SimpleStruct ss);
@@ -1161,4 +1166,10 @@ public class Tests {
 
                return mono_test_marshal_virtual_delegate (b.get_del ());
        }
+
+       public static int test_0_icall_delegate () {
+               var m = typeof (Marshal).GetMethod ("PtrToStringAnsi", new Type[] { typeof (IntPtr) });
+
+               return mono_test_marshal_icall_delegate ((IcallDelegate)Delegate.CreateDelegate (typeof (IcallDelegate), m));
+       }
 }
index 624d1b88b8eb595500bcdad638d007d56f026ffe..f4ae1b54100e4550201e99c71ecf673951f815a8 100644 (file)
@@ -8,7 +8,7 @@
  */
 #include <config.h>
 
-#ifdef CHECKED_BUILD
+#ifdef ENABLE_CHECKED_BUILD
 
 #include <mono/utils/checked-build.h>
 #include <mono/utils/mono-threads.h>
 #include <execinfo.h>
 #endif
 
+// Selective-enable support
+
+// Returns true for check modes which are allowed by both the current DISABLE_ macros and the MONO_CHECK_MODE env var.
+// Argument may be a bitmask; if so, result is true if at least one specified mode is enabled.
+mono_bool
+mono_check_mode_enabled (MonoCheckMode query)
+{
+       static MonoCheckMode check_mode = MONO_CHECK_MODE_UNKNOWN;
+       if (G_UNLIKELY (check_mode == MONO_CHECK_MODE_UNKNOWN))
+       {
+               MonoCheckMode env_check_mode = MONO_CHECK_MODE_NONE;
+               const gchar *env_string = g_getenv ("MONO_CHECK_MODE");
+
+               if (env_string)
+               {
+                       gchar **env_split = g_strsplit (env_string, ",", 0);
+                       for (gchar **env_component = env_split; *env_component; env_component++)
+                       {
+                               mono_bool check_all = g_str_equal (*env_component, "all");
+#ifdef ENABLE_CHECKED_BUILD_GC
+                               if (check_all || g_str_equal (*env_component, "gc"))
+                                       env_check_mode |= MONO_CHECK_MODE_GC;
+#endif
+#ifdef ENABLE_CHECKED_BUILD_METADATA
+                               if (check_all || g_str_equal (*env_component, "metadata"))
+                                       env_check_mode |= MONO_CHECK_MODE_METADATA;
+#endif
+#ifdef ENABLE_CHECKED_BUILD_THREAD
+                               if (check_all || g_str_equal (*env_component, "thread"))
+                                       env_check_mode |= MONO_CHECK_MODE_THREAD;
+#endif
+                       }
+                       g_strfreev (env_split);
+               }
+
+               check_mode = env_check_mode;
+       }
+       return check_mode & query;
+}
+
+static int
+mono_check_transition_limit (void)
+{
+       static int transition_limit = -1;
+       if (transition_limit < 0) {
+               const gchar *env_string = g_getenv ("MONO_CHECK_THREAD_TRANSITION_HISTORY");
+               if (env_string)
+                       transition_limit = atoi (env_string);
+               else
+                       transition_limit = 3;
+       }
+       return transition_limit;
+}
+
 typedef struct {
        GPtrArray *transitions;
        guint32 in_gc_critical_region;
@@ -34,7 +88,9 @@ static MonoNativeTlsKey thread_status;
 void
 checked_build_init (void)
 {
-       mono_native_tls_alloc (&thread_status, NULL);
+       // Init state for get_state, which can be called either by gc or thread mode
+       if (mono_check_mode_enabled (MONO_CHECK_MODE_GC | MONO_CHECK_MODE_THREAD))
+               mono_native_tls_alloc (&thread_status, NULL);
 }
 
 static CheckState*
@@ -50,11 +106,11 @@ get_state (void)
        return state;
 }
 
-#if !defined(DISABLE_CHECKED_BUILD_THREAD)
+#ifdef ENABLE_CHECKED_BUILD_THREAD
 
 #define MAX_NATIVE_BT 6
 #define MAX_NATIVE_BT_PROBE (MAX_NATIVE_BT + 5)
-#define MAX_TRANSITIONS 3
+#define MAX_TRANSITIONS (mono_check_transition_limit ())
 
 #ifdef HAVE_BACKTRACE_SYMBOLS
 
@@ -124,6 +180,9 @@ free_transition (ThreadTransition *t)
 void
 checked_build_thread_transition (const char *transition, void *info, int from_state, int suspend_count, int next_state, int suspend_count_delta)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_THREAD))
+               return;
+
        MonoThreadInfo *cur = mono_thread_info_current_unchecked ();
        CheckState *state = get_state ();
        /* We currently don't record external changes as those are hard to reason about. */
@@ -143,16 +202,11 @@ checked_build_thread_transition (const char *transition, void *info, int from_st
        g_ptr_array_add (state->transitions, t);
 }
 
-#endif /* !defined(DISABLE_CHECKED_BUILD_THREAD) */
-
-#if !defined(DISABLE_CHECKED_BUILD_GC)
-
-static void
-assertion_fail (const char *msg, ...)
+void
+mono_fatal_with_history (const char *msg, ...)
 {
        int i;
        GString* err = g_string_sized_new (100);
-       CheckState *state = get_state ();
 
        g_string_append_printf (err, "Assertion failure in thread %p due to: ", mono_native_thread_id_get ());
 
@@ -161,52 +215,67 @@ assertion_fail (const char *msg, ...)
        g_string_append_vprintf (err, msg, args);
        va_end (args);
 
-       g_string_append_printf (err, "\nLast %d state transitions: (most recent first)\n", state->transitions->len);
-
-       for (i = state->transitions->len - 1; i >= 0; --i) {
-               ThreadTransition *t = state->transitions->pdata [i];
-               char *bt = translate_backtrace (t->backtrace, t->size);
-               g_string_append_printf (err, "[%s] %s -> %s (%d) %s%d at:\n%s",
-                       t->name,
-                       mono_thread_state_name (t->from_state),
-                       mono_thread_state_name (t->next_state),
-                       t->suspend_count,
-                       t->suspend_count_delta > 0 ? "+" : "", //I'd like to see this sort of values: -1, 0, +1
-                       t->suspend_count_delta,
-                       bt);
-               g_free (bt);
+       if (mono_check_mode_enabled (MONO_CHECK_MODE_THREAD))
+       {
+               CheckState *state = get_state ();
+
+               g_string_append_printf (err, "\nLast %d state transitions: (most recent first)\n", state->transitions->len);
+
+               for (i = state->transitions->len - 1; i >= 0; --i) {
+                       ThreadTransition *t = state->transitions->pdata [i];
+                       char *bt = translate_backtrace (t->backtrace, t->size);
+                       g_string_append_printf (err, "[%s] %s -> %s (%d) %s%d at:\n%s",
+                               t->name,
+                               mono_thread_state_name (t->from_state),
+                               mono_thread_state_name (t->next_state),
+                               t->suspend_count,
+                               t->suspend_count_delta > 0 ? "+" : "", //I'd like to see this sort of values: -1, 0, +1
+                               t->suspend_count_delta,
+                               bt);
+                       g_free (bt);
+               }
        }
 
        g_error (err->str);
        g_string_free (err, TRUE);
 }
 
+#endif /* defined(ENABLE_CHECKED_BUILD_THREAD) */
+
+#ifdef ENABLE_CHECKED_BUILD_GC
+
 void
 assert_gc_safe_mode (void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        MonoThreadInfo *cur = mono_thread_info_current ();
        int state;
 
        if (!cur)
-               assertion_fail ("Expected GC Safe mode but thread is not attached");
+               mono_fatal_with_history ("Expected GC Safe mode but thread is not attached");
 
        switch (state = mono_thread_info_current_state (cur)) {
        case STATE_BLOCKING:
        case STATE_BLOCKING_AND_SUSPENDED:
                break;
        default:
-               assertion_fail ("Expected GC Safe mode but was in %s state", mono_thread_state_name (state));
+               mono_fatal_with_history ("Expected GC Safe mode but was in %s state", mono_thread_state_name (state));
        }
 }
 
 void
 assert_gc_unsafe_mode (void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        MonoThreadInfo *cur = mono_thread_info_current ();
        int state;
 
        if (!cur)
-               assertion_fail ("Expected GC Unsafe mode but thread is not attached");
+               mono_fatal_with_history ("Expected GC Unsafe mode but thread is not attached");
 
        switch (state = mono_thread_info_current_state (cur)) {
        case STATE_RUNNING:
@@ -214,18 +283,21 @@ assert_gc_unsafe_mode (void)
        case STATE_SELF_SUSPEND_REQUESTED:
                break;
        default:
-               assertion_fail ("Expected GC Unsafe mode but was in %s state", mono_thread_state_name (state));
+               mono_fatal_with_history ("Expected GC Unsafe mode but was in %s state", mono_thread_state_name (state));
        }
 }
 
 void
 assert_gc_neutral_mode (void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        MonoThreadInfo *cur = mono_thread_info_current ();
        int state;
 
        if (!cur)
-               assertion_fail ("Expected GC Neutral mode but thread is not attached");
+               mono_fatal_with_history ("Expected GC Neutral mode but thread is not attached");
 
        switch (state = mono_thread_info_current_state (cur)) {
        case STATE_RUNNING:
@@ -235,13 +307,16 @@ assert_gc_neutral_mode (void)
        case STATE_BLOCKING_AND_SUSPENDED:
                break;
        default:
-               assertion_fail ("Expected GC Neutral mode but was in %s state", mono_thread_state_name (state));
+               mono_fatal_with_history ("Expected GC Neutral mode but was in %s state", mono_thread_state_name (state));
        }
 }
 
 void *
 critical_gc_region_begin(void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return NULL;
+
        CheckState *state = get_state ();
        state->in_gc_critical_region++;
        return state;
@@ -251,6 +326,9 @@ critical_gc_region_begin(void)
 void
 critical_gc_region_end(void* token)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        CheckState *state = get_state();
        g_assert (state == token);
        state->in_gc_critical_region--;
@@ -259,23 +337,29 @@ critical_gc_region_end(void* token)
 void
 assert_not_in_gc_critical_region(void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        CheckState *state = get_state();
        if (state->in_gc_critical_region > 0) {
-               assertion_fail("Expected GC Unsafe mode, but was in %s state", mono_thread_state_name (mono_thread_info_current_state (mono_thread_info_current ())));
+               mono_fatal_with_history("Expected GC Unsafe mode, but was in %s state", mono_thread_state_name (mono_thread_info_current_state (mono_thread_info_current ())));
        }
 }
 
 void
 assert_in_gc_critical_region (void)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_GC))
+               return;
+
        CheckState *state = get_state();
        if (state->in_gc_critical_region == 0)
-               assertion_fail("Expected GC critical region");
+               mono_fatal_with_history("Expected GC critical region");
 }
 
-#endif /* !defined(DISABLE_CHECKED_BUILD_GC) */
+#endif /* defined(ENABLE_CHECKED_BUILD_GC) */
 
-#if !defined(DISABLE_CHECKED_BUILD_METADATA)
+#ifdef ENABLE_CHECKED_BUILD_METADATA
 
 // check_metadata_store et al: The goal of these functions is to verify that if there is a pointer from one mempool into
 // another, that the pointed-to memory is protected by the reference count mechanism for MonoImages.
@@ -543,6 +627,9 @@ mono_find_mempool_owner (void *ptr)
 static void
 check_mempool_may_reference_mempool (void *from_ptr, void *to_ptr, gboolean require_local)
 {
+       if (!mono_check_mode_enabled (MONO_CHECK_MODE_METADATA))
+               return;
+
        // Null pointers are OK
        if (!to_ptr)
                return;
@@ -610,6 +697,6 @@ check_metadata_store_local (void *from, void *to)
     check_mempool_may_reference_mempool (from, to, TRUE);
 }
 
-#endif /* !defined(DISABLE_CHECKED_BUILD_METADATA) */
+#endif /* defined(ENABLE_CHECKED_BUILD_METADATA) */
 
-#endif /* CHECKED_BUILD */
+#endif /* ENABLE_CHECKED_BUILD */
index 28932d8c630204ff83e6bae5d3cd46cb49f2c062..25e663177ef39760a804e16eae34add0147f2f7a 100644 (file)
 
 #include <config.h>
 #include <mono/utils/atomic.h>
+#include <mono/utils/mono-publib.h>
+
+typedef enum {
+       MONO_CHECK_MODE_NONE = 0,
+       MONO_CHECK_MODE_GC = 0x1,
+       MONO_CHECK_MODE_METADATA = 0x2,
+       MONO_CHECK_MODE_THREAD = 0x4,
+       MONO_CHECK_MODE_ALL = MONO_CHECK_MODE_GC | MONO_CHECK_MODE_METADATA | MONO_CHECK_MODE_THREAD,
+       MONO_CHECK_MODE_UNKNOWN = 0x8
+} MonoCheckMode;
+
+mono_bool mono_check_mode_enabled (MonoCheckMode query);
 
 // This is for metadata writes which we have chosen not to check at the current time.
 // Because in principle this should never happen, we still use a macro so that the exemptions will be easier to find, and remove, later.
 // The current reason why this is needed is for pointers to constant strings, which the checker cannot verify yet.
 #define CHECKED_METADATA_WRITE_PTR_EXEMPT(ptr, val) do { (ptr) = (val); } while (0)
 
-#if defined(CHECKED_BUILD)
+#ifdef ENABLE_CHECKED_BUILD
 
 #define g_assert_checked g_assert
 
@@ -45,10 +57,9 @@ void checked_build_init (void);
 
 #define CHECKED_MONO_INIT()
 
-#endif /* CHECKED_BUILD */
-
-#if defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_GC)
+#endif /* ENABLE_CHECKED_BUILD */
 
+#ifdef ENABLE_CHECKED_BUILD_GC
 /*
 GC runtime modes rules:
 
@@ -149,9 +160,9 @@ void assert_in_gc_critical_region (void);
 #define MONO_REQ_GC_NOT_CRITICAL
 #define MONO_REQ_GC_CRITICAL
 
-#endif /* defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_GC) */
+#endif /* defined(ENABLE_CHECKED_BUILD_GC) */
 
-#if defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_METADATA)
+#ifdef ENABLE_CHECKED_BUILD_METADATA
 
 // Use when writing a pointer from one image or imageset to another.
 #define CHECKED_METADATA_WRITE_PTR(ptr, val) do {    \
@@ -180,9 +191,9 @@ void check_metadata_store_local(void *from, void *to);
 #define CHECKED_METADATA_WRITE_PTR_LOCAL(ptr, val) do { (ptr) = (val); } while (0)
 #define CHECKED_METADATA_WRITE_PTR_ATOMIC(ptr, val) do { mono_atomic_store_release (&(ptr), (val)); } while (0)
 
-#endif /* defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_METADATA) */
+#endif /* defined(ENABLE_CHECKED_BUILD_METADATA) */
 
-#if defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_THREAD)
+#ifdef ENABLE_CHECKED_BUILD_THREAD
 
 #define CHECKED_BUILD_THREAD_TRANSITION(transition, info, from_state, suspend_count, next_state, suspend_count_delta) do {     \
        checked_build_thread_transition (transition, info, from_state, suspend_count, next_state, suspend_count_delta); \
@@ -190,10 +201,14 @@ void check_metadata_store_local(void *from, void *to);
 
 void checked_build_thread_transition(const char *transition, void *info, int from_state, int suspend_count, int next_state, int suspend_count_delta);
 
+void mono_fatal_with_history(const char *msg, ...);
+
 #else
 
 #define CHECKED_BUILD_THREAD_TRANSITION(transition, info, from_state, suspend_count, next_state, suspend_count_delta)
 
-#endif /* defined(CHECKED_BUILD) && !defined(DISABLE_CHECKED_BUILD_THREAD) */
+#define mono_fatal_with_history g_error
+
+#endif /* defined(ENABLE_CHECKED_BUILD_THREAD) */
 
 #endif /* __CHECKED_BUILD_H__ */
index 3b11148aafe3af5d8c7ff2d93368bb3033da1e10..20740b3dcd1d330bc943bc5ca3320b9cacd39f77 100644 (file)
@@ -25,6 +25,7 @@
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-threads-coop.h>
 #include <mono/utils/mono-threads-api.h>
+#include <mono/utils/checked-build.h>
 
 #ifdef TARGET_OSX
 #include <mono/utils/mach-support.h>
 
 volatile size_t mono_polling_required;
 
+// FIXME: This would be more efficient if instead of instantiating the stack it just pushed a simple depth counter up and down,
+// perhaps with a per-thread cookie in the high bits.
+#ifdef ENABLE_CHECKED_BUILD_GC
+// Maintains a single per-thread stack of ints, used to ensure nesting is not violated
+MonoNativeTlsKey coop_reset_count_stack_key;
+static int coop_tls_push (int v) {
+       GArray *stack = mono_native_tls_get_value (coop_reset_count_stack_key);
+       if (!stack) {
+               stack = g_array_new (FALSE,FALSE,sizeof(int));
+               mono_native_tls_set_value (coop_reset_count_stack_key, stack);
+       }
+       g_array_append_val (stack, v);
+       return stack->len;
+}
+static int coop_tls_pop (int *v) {
+       GArray *stack = mono_native_tls_get_value (coop_reset_count_stack_key);
+       if (!stack || 0 == stack->len)
+               return -1;
+       stack->len--;
+       *v = g_array_index (stack, int, stack->len);
+       int len = stack->len;
+       if (0 == len) {
+               g_array_free (stack,TRUE);
+               mono_native_tls_set_value (coop_reset_count_stack_key, NULL);
+       }
+       return len;
+}
+#endif
+
 static int coop_reset_blocking_count;
 static int coop_try_blocking_count;
 static int coop_do_blocking_count;
@@ -193,9 +223,18 @@ mono_threads_reset_blocking_start (void* stackdata)
        if (!mono_threads_is_coop_enabled ())
                return NULL;
 
+       info = mono_thread_info_current_unchecked ();
+
+#ifdef ENABLE_CHECKED_BUILD_GC
+       int reset_blocking_count = InterlockedIncrement (&coop_reset_blocking_count);
+       // In this mode, the blocking count is used as the reset cookie. We would prefer
+       // (but do not require) this to be unique across invocations and threads.
+       if (reset_blocking_count == 0) // We *do* require it be nonzero
+               reset_blocking_count = coop_reset_blocking_count = 1;
+#else
        ++coop_reset_blocking_count;
+#endif
 
-       info = mono_thread_info_current_unchecked ();
        /* If the thread is not attached, it doesn't make sense prepare for suspend. */
        if (!info || !mono_thread_info_is_live (info))
                return NULL;
@@ -211,28 +250,50 @@ mono_threads_reset_blocking_start (void* stackdata)
                return NULL;
        case AbortBlockingOk:
                info->thread_saved_state [SELF_SUSPEND_STATE_INDEX].valid = FALSE;
-               return info;
+               break;
        case AbortBlockingOkAndPool:
                mono_threads_state_poll ();
-               return info;
+               break;
        default:
                g_error ("Unknown thread state");
        }
+
+#ifdef ENABLE_CHECKED_BUILD_GC
+       if (mono_check_mode_enabled (MONO_CHECK_MODE_GC)) {
+               int level = coop_tls_push (reset_blocking_count);
+               //g_warning("Entering reset nest; level %d; cookie %d\n", level, reset_blocking_count);
+               return (void *)(intptr_t)reset_blocking_count;
+       }
+#endif
+
+       return info;
 }
 
 void
 mono_threads_reset_blocking_end (void *cookie, void* stackdata)
 {
-       MonoThreadInfo *info;
-
        if (!mono_threads_is_coop_enabled ())
                return;
 
-       info = (MonoThreadInfo *)cookie;
-       if (!info)
+       if (!cookie)
                return;
 
-       g_assert (info == mono_thread_info_current_unchecked ());
+#ifdef ENABLE_CHECKED_BUILD_GC
+       if (mono_check_mode_enabled (MONO_CHECK_MODE_GC)) {
+               int received_cookie = (int)(intptr_t)cookie;
+               int desired_cookie;
+               int level = coop_tls_pop (&desired_cookie);
+               //g_warning("Leaving reset nest; back to level %d; desired cookie %d; received cookie %d\n", level, desired_cookie, received_cookie);
+               if (level < 0)
+                       mono_fatal_with_history ("Expected cookie %d but found no stack at all\n", desired_cookie);
+               if (desired_cookie != received_cookie)
+                       mono_fatal_with_history ("Expected cookie %d but received %d\n", desired_cookie, received_cookie);
+       } else // Notice this matches the line after the endif
+#endif
+       {
+               g_assert (((MonoThreadInfo *)cookie) == mono_thread_info_current_unchecked ());
+       }
+
        mono_threads_prepare_blocking (stackdata);
 }
 
@@ -248,6 +309,10 @@ mono_threads_init_coop (void)
        mono_counters_register ("Coop Do Polling", MONO_COUNTER_GC | MONO_COUNTER_INT, &coop_do_polling_count);
        mono_counters_register ("Coop Save Count", MONO_COUNTER_GC | MONO_COUNTER_INT, &coop_save_count);
        //See the above for what's wrong here.
+
+#ifdef ENABLE_CHECKED_BUILD_GC
+       mono_native_tls_alloc (&coop_reset_count_stack_key, NULL);
+#endif
 }
 
 void
index d130a13613de89b78e4ee113cec9bc4806f74c9f..32491a4ca225229e622799504f8d7cc6012c031c 100644 (file)
@@ -113,7 +113,7 @@ retry_state_change:
                trace_state_change ("ATTACH", info, raw_state, STATE_RUNNING, 0);
                break;
        default:
-               g_error ("Cannot transition current thread from %s with ATTACH", state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition current thread from %s with ATTACH", state_name (cur_state));
        }
 }
 
@@ -148,7 +148,7 @@ STATE_BLOCKING: This is a bug in the coop code that forgot to do a finish blocki
 STATE_BLOCKING_AND_SUSPENDED: This is a bug in coop x suspend that resulted the thread in an undetachable state.
 */
        default:
-               g_error ("Cannot transition current thread %p from %s with DETACH", info, state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition current thread %p from %s with DETACH", info, state_name (cur_state));
        }
 }
 
@@ -190,7 +190,7 @@ STATE_BLOCKING_AND_SUSPENDED: Self suspension cannot be started when the thread
 If this turns to be an issue we can introduce a new suspend request state for when both have been requested.
 */
        default:
-               g_error ("Cannot transition thread %p from %s with SUSPEND_REQUEST", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with SUSPEND_REQUEST", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -252,7 +252,7 @@ The expected behavior is that the target should poll its state very soon so the
 STATE_ASYNC_SUSPEND_REQUESTED: Since there can only be one async suspend in progress and it must finish, it should not be possible to witness this.
 */
        default:
-               g_error ("Cannot transition thread %p from %s with ASYNC_SUSPEND_REQUESTED", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with ASYNC_SUSPEND_REQUESTED", mono_thread_info_get_tid (info), state_name (cur_state));
        }
        return (MonoRequestAsyncSuspendResult) FALSE;
 }
@@ -301,7 +301,7 @@ STATE_BLOCKING:
 STATE_BLOCKING_AND_SUSPENDED: Pool is a local state transition. No VM activities are allowed while in blocking mode.
 */
        default:
-               g_error ("Cannot transition thread %p from %s with STATE_POLL", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with STATE_POLL", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -401,7 +401,7 @@ If this turns to be a problem we should either implement [2] or make this an inv
 
 */
        default:
-               g_error ("Cannot transition thread %p from %s with REQUEST_RESUME", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with REQUEST_RESUME", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -437,7 +437,7 @@ STATE_SELF_SUSPEND_REQUESTED: When self suspend and async suspend happen togethe
 STATE_BLOCKING: Async suspend only begins if a transition to async suspend requested happened. Blocking would have put us into blocking with positive suspend count if it raced with async finish.
 */
        default:
-               g_error ("Cannot transition thread %p from %s with FINISH_ASYNC_SUSPEND", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with FINISH_ASYNC_SUSPEND", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -481,7 +481,7 @@ STATE_BLOCKING_AND_SUSPENDED
 STATE_SELF_SUSPEND_REQUESTED: All those are invalid end states of a sucessfull finish async suspend
 */
        default:
-               g_error ("Cannot transition thread %p from %s with COMPENSATE_FINISH_ASYNC_SUSPEND", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with COMPENSATE_FINISH_ASYNC_SUSPEND", mono_thread_info_get_tid (info), state_name (cur_state));
 
        }
 }
@@ -526,7 +526,7 @@ STATE_BLOCKING:
 STATE_BLOCKING_AND_SUSPENDED: Blocking is not nestabled
 */
        default:
-               g_error ("Cannot transition thread %p from %s with DO_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with DO_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -574,7 +574,7 @@ STATE_SELF_SUSPEND_REQUESTED: A blocking operation must not be done while trying
 STATE_BLOCKING_AND_SUSPENDED: This an exit state of done blocking
 */
        default:
-               g_error ("Cannot transition thread %p from %s with DONE_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with DONE_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
@@ -624,7 +624,7 @@ STATE_SELF_SUSPEND_REQUESTED: A blocking operation must not be done while trying
 STATE_BLOCKING_AND_SUSPENDED: This is an exit state of done blocking, can't happen here.
 */
        default:
-               g_error ("Cannot transition thread %p from %s with DONE_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
+               mono_fatal_with_history ("Cannot transition thread %p from %s with DONE_BLOCKING", mono_thread_info_get_tid (info), state_name (cur_state));
        }
 }
 
index 7fdb42da30f9b14b6a27af1ed0953777ae946d31..223b73852dcbf3762ccd27934beb22ddf5e87687 100644 (file)
@@ -88,7 +88,7 @@ clean-local:
 
 endif BUILD_MCS
 
-TEST_SUPPORT_FILES = $(tmpinst)/bin/mono $(tmpinst)/bin/ilasm $(tmpinst)/bin/mcs $(tmpinst)/bin/dmcs $(tmpinst)/bin/al2 $(tmpinst)/bin/al
+TEST_SUPPORT_FILES = $(tmpinst)/bin/mono $(tmpinst)/bin/ilasm $(tmpinst)/bin/mcs $(tmpinst)/bin/al
 
 mcs-do-test-profiles:
        cd $(mcs_topdir) && $(MAKE) NO_DIR_CHECK=1 PROFILES='$(test_profiles)' test-profiles
@@ -168,24 +168,12 @@ $(tmpinst)/bin/mcs: $(tmpinst)/bin/mono Makefile
        echo 'exec "'"$$r/$(tmpinst)/bin/mono"'" "'"$$m/class/lib/build/mcs.exe"'" "$$@"' >> $@ ; \
        chmod +x $@
 
-$(tmpinst)/bin/dmcs: $(tmpinst)/bin/mono Makefile
-       echo '#! /bin/sh' > $@ ; \
-       r=`pwd`; m=`cd $(mcs_topdir) && pwd`; \
-       echo 'exec "'"$$r/$(tmpinst)/bin/mono"'" "'"$$m/class/lib/build/mcs.exe -sdk:4"'" "$$@"' >> $@ ; \
-       chmod +x $@
-
 $(tmpinst)/bin/ilasm: $(tmpinst)/bin/mono Makefile
        echo '#! /bin/sh' > $@ ; \
        r=`pwd`; m=`cd $(mcs_topdir) && pwd`; \
        echo 'exec "'"$$r/$(tmpinst)/bin/mono"'" "'"$$m/ilasm/ilasm.exe"'" "$$@"' >> $@ ; \
        chmod +x $@
 
-$(tmpinst)/bin/al2: $(tmpinst)/bin/mono Makefile
-       echo '#! /bin/sh' > $@ ; \
-       r=`pwd`; m=`cd $(mcs_topdir) && pwd`; \
-       echo 'exec "'"$$r/$(tmpinst)/bin/mono"'" "'"$$m/class/lib/net_2_0/al.exe"'" "$$@"' >> $@ ; \
-       chmod +x $@
-
 $(tmpinst)/bin/al: $(tmpinst)/bin/mono Makefile
        echo '#! /bin/sh' > $@ ; \
        r=`pwd`; m=`cd $(mcs_topdir) && pwd`; \
index ff7bc4bfdadb8ed3536d91b0887d16f9a6a2e0d4..a036cf1f8dbc283329b0c3c07ec21baf97d9f750 100644 (file)
@@ -50,6 +50,7 @@
 /mono-abi-info
 /mono-api-diff
 /mono-api-info
+/mono-api-html
 /mono-api-info1
 /mono-api-info2
 /mono-cil-strip
index d23bb676601ade72453fbacac11f8fba9996f1a7..be4d6b164a009018668e73beac1c186eb1666e03 100644 (file)
@@ -84,6 +84,7 @@ scripts_4_0 = \
        mod$(SCRIPT_SUFFIX)                     \
        monolinker$(SCRIPT_SUFFIX)              \
        mono-api-info$(SCRIPT_SUFFIX)           \
+       mono-api-html$(SCRIPT_SUFFIX)           \
        mono-shlib-cop$(SCRIPT_SUFFIX)          \
        mozroots$(SCRIPT_SUFFIX)                \
        permview$(SCRIPT_SUFFIX)                \