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 | |