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
14struct ExceptionLocationData
15{
16 LPCUTF8 Namespace;
17 LPCUTF8 Name;
18 LPCUTF8 AssemblySimpleName;
19 LPCUTF8 PublicKeyToken;
20};
21
22static const
23ExceptionLocationData 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.
34MethodTable* 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
90void 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