| 1 | // Licensed to the .NET Foundation under one or more agreements. |
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | |
| 5 | |
| 6 | |
| 7 | // Just the subset of functionality from the MscorlibBinder necessary for exceptions. |
| 8 | |
| 9 | #include "common.h" |
| 10 | #include "frameworkexceptionloader.h" |
| 11 | #include "typeparse.h" |
| 12 | |
| 13 | |
| 14 | struct ExceptionLocationData |
| 15 | { |
| 16 | LPCUTF8 Namespace; |
| 17 | LPCUTF8 Name; |
| 18 | LPCUTF8 AssemblySimpleName; |
| 19 | LPCUTF8 PublicKeyToken; |
| 20 | }; |
| 21 | |
| 22 | static const |
| 23 | ExceptionLocationData g_ExceptionLocationData[] = { |
| 24 | #define DEFINE_EXCEPTION(ns, reKind, bHRformessage, ...) |
| 25 | #define DEFINE_EXCEPTION_HR_WINRT_ONLY(ns, reKind, ...) |
| 26 | #define DEFINE_EXCEPTION_IN_OTHER_FX_ASSEMBLY(ns, reKind, assemblySimpleName, publicKeyToken, bHRformessage, ...) { ns, PTR_CSTR((TADDR) # reKind), assemblySimpleName, publicKeyToken }, |
| 27 | #include "rexcep.h" |
| 28 | {NULL, NULL, NULL, NULL} // On Silverlight, this table may be empty. This dummy entry allows us to compile. |
| 29 | }; |
| 30 | |
| 31 | |
| 32 | // Note that some assemblies, like System.Runtime.WindowsRuntime, might not be installed on pre-Windows 8 machines. |
| 33 | // This may return null. |
| 34 | MethodTable* FrameworkExceptionLoader::GetException(RuntimeExceptionKind kind) |
| 35 | { |
| 36 | CONTRACTL |
| 37 | { |
| 38 | THROWS; |
| 39 | GC_TRIGGERS; |
| 40 | |
| 41 | PRECONDITION(kind > kLastExceptionInMscorlib); |
| 42 | PRECONDITION(kind - (kLastExceptionInMscorlib + 1) < COUNTOF(g_ExceptionLocationData) - 1); |
| 43 | } |
| 44 | CONTRACTL_END; |
| 45 | |
| 46 | // This is for loading rarely-used exception objects in arbitrary appdomains. |
| 47 | // The loader should do caching - let's not create a multi-appdomain cache of these exception types here. |
| 48 | // Note that some assemblies, like System.Runtime.WindowsRuntime, might not be installed on pre-Windows 8 machines. |
| 49 | int index = kind - (kLastExceptionInMscorlib + 1); |
| 50 | ExceptionLocationData exData = g_ExceptionLocationData[index]; |
| 51 | _ASSERTE(exData.Name != NULL && exData.AssemblySimpleName != NULL && exData.PublicKeyToken != NULL); // Was the exception defined in mscorlib instead? |
| 52 | StackSString assemblyQualifiedName; |
| 53 | _ASSERTE(exData.Namespace != NULL); // If we need to support stuff in a global namespace, fix this. |
| 54 | assemblyQualifiedName.SetUTF8(exData.Namespace); |
| 55 | assemblyQualifiedName.AppendUTF8("." ); |
| 56 | assemblyQualifiedName.AppendUTF8(exData.Name); |
| 57 | assemblyQualifiedName.AppendUTF8(", " ); |
| 58 | assemblyQualifiedName.AppendUTF8(exData.AssemblySimpleName); |
| 59 | assemblyQualifiedName.AppendUTF8(", PublicKeyToken=" ); |
| 60 | assemblyQualifiedName.AppendUTF8(exData.PublicKeyToken); |
| 61 | assemblyQualifiedName.AppendUTF8(", Version=" ); |
| 62 | assemblyQualifiedName.AppendUTF8(VER_ASSEMBLYVERSION_STR); |
| 63 | assemblyQualifiedName.AppendUTF8(", Culture=neutral" ); |
| 64 | |
| 65 | MethodTable* pMT = NULL; |
| 66 | // Loading will either succeed or throw a FileLoadException. Catch & swallow that exception. |
| 67 | EX_TRY |
| 68 | { |
| 69 | pMT = TypeName::GetTypeFromAsmQualifiedName(assemblyQualifiedName.GetUnicode()).GetMethodTable(); |
| 70 | |
| 71 | // Since this type is from another assembly, we must ensure that assembly has been sufficiently loaded. |
| 72 | pMT->EnsureActive(); |
| 73 | } |
| 74 | EX_CATCH |
| 75 | { |
| 76 | Exception *ex = GET_EXCEPTION(); |
| 77 | |
| 78 | // Let non-file-not-found exceptions propagate |
| 79 | if (EEFileLoadException::GetFileLoadKind(ex->GetHR()) != kFileNotFoundException) |
| 80 | EX_RETHROW; |
| 81 | |
| 82 | // Return COMException if we can't load the assembly we expect. |
| 83 | pMT = MscorlibBinder::GetException(kCOMException); |
| 84 | } |
| 85 | EX_END_CATCH(RethrowTerminalExceptions); |
| 86 | |
| 87 | return pMT; |
| 88 | } |
| 89 | |
| 90 | void FrameworkExceptionLoader::GetExceptionName(RuntimeExceptionKind kind, SString & exceptionName) |
| 91 | { |
| 92 | CONTRACTL { |
| 93 | THROWS; |
| 94 | GC_NOTRIGGER; |
| 95 | MODE_ANY; |
| 96 | |
| 97 | PRECONDITION(kind > kLastExceptionInMscorlib); |
| 98 | PRECONDITION(kind - (kLastExceptionInMscorlib + 1) < COUNTOF(g_ExceptionLocationData) - 1); |
| 99 | } CONTRACTL_END; |
| 100 | |
| 101 | exceptionName.SetUTF8(g_ExceptionLocationData[kind].Namespace); |
| 102 | exceptionName.AppendUTF8("." ); |
| 103 | exceptionName.AppendUTF8(g_ExceptionLocationData[kind].Name); |
| 104 | } |
| 105 | |