summaryrefslogtreecommitdiff
path: root/src/vm/frameworkexceptionloader.cpp
blob: d181907da2193e33b96c1add83043e4659fec2db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
//

 

// Just the subset of functionality from the MscorlibBinder necessary for exceptions.

#include "common.h"
#include "frameworkexceptionloader.h"


struct ExceptionLocationData
{
    LPCUTF8 Namespace;
    LPCUTF8 Name;
    LPCUTF8 AssemblySimpleName;
    LPCUTF8 PublicKeyToken;
};

static const
ExceptionLocationData g_ExceptionLocationData[] = {
#define DEFINE_EXCEPTION(ns, reKind, bHRformessage, ...)
#define DEFINE_EXCEPTION_HR_WINRT_ONLY(ns, reKind, ...)
#define DEFINE_EXCEPTION_IN_OTHER_FX_ASSEMBLY(ns, reKind, assemblySimpleName, publicKeyToken, bHRformessage, ...) { ns, PTR_CSTR((TADDR) # reKind), assemblySimpleName, publicKeyToken },
#include "rexcep.h"
    {NULL, NULL, NULL, NULL}  // On Silverlight, this table may be empty.  This dummy entry allows us to compile.
};


// Note that some assemblies, like System.Runtime.WindowsRuntime, might not be installed on pre-Windows 8 machines.
// This may return null.
MethodTable* FrameworkExceptionLoader::GetException(RuntimeExceptionKind kind)
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;

        PRECONDITION(kind > kLastExceptionInMscorlib);
        PRECONDITION(kind - (kLastExceptionInMscorlib + 1) < COUNTOF(g_ExceptionLocationData) - 1);
    }
    CONTRACTL_END;

    // This is for loading rarely-used exception objects in arbitrary appdomains.
    // The loader should do caching - let's not create a multi-appdomain cache of these exception types here.
    // Note that some assemblies, like System.Runtime.WindowsRuntime, might not be installed on pre-Windows 8 machines.
    int index = kind - (kLastExceptionInMscorlib + 1);
    ExceptionLocationData exData = g_ExceptionLocationData[index];
    _ASSERTE(exData.Name != NULL && exData.AssemblySimpleName != NULL && exData.PublicKeyToken != NULL);  // Was the exception defined in mscorlib instead?
    StackSString assemblyQualifiedName;
    _ASSERTE(exData.Namespace != NULL);  // If we need to support stuff in a global namespace, fix this.
    assemblyQualifiedName.SetUTF8(exData.Namespace);
    assemblyQualifiedName.AppendUTF8(".");
    assemblyQualifiedName.AppendUTF8(exData.Name);
    assemblyQualifiedName.AppendUTF8(", ");
    assemblyQualifiedName.AppendUTF8(exData.AssemblySimpleName);
    assemblyQualifiedName.AppendUTF8(", PublicKeyToken=");
    assemblyQualifiedName.AppendUTF8(exData.PublicKeyToken);
    assemblyQualifiedName.AppendUTF8(", Version=");
    assemblyQualifiedName.AppendUTF8(VER_ASSEMBLYVERSION_STR);
    assemblyQualifiedName.AppendUTF8(", Culture=neutral");

    MethodTable* pMT = NULL;
    // Loading will either succeed or throw a FileLoadException.  Catch & swallow that exception.
    EX_TRY
    {
        pMT = TypeName::GetTypeFromAsmQualifiedName(assemblyQualifiedName.GetUnicode(), FALSE).GetMethodTable();

        // Since this type is from another assembly, we must ensure that assembly has been sufficiently loaded.
        pMT->EnsureActive();
    }
    EX_CATCH
    {
        Exception *ex = GET_EXCEPTION();

        // Let non-file-not-found execeptions propagate
        if (EEFileLoadException::GetFileLoadKind(ex->GetHR()) != kFileNotFoundException)
            EX_RETHROW;

        // Return COMException if we can't load the assembly we expect.
        pMT = MscorlibBinder::GetException(kCOMException);
    }
    EX_END_CATCH(RethrowTerminalExceptions);

    return pMT;
}

void FrameworkExceptionLoader::GetExceptionName(RuntimeExceptionKind kind, SString & exceptionName)
{
    CONTRACTL {
        THROWS;
        GC_NOTRIGGER;
        MODE_ANY;

        PRECONDITION(kind > kLastExceptionInMscorlib);
        PRECONDITION(kind - (kLastExceptionInMscorlib + 1) < COUNTOF(g_ExceptionLocationData) - 1);
    } CONTRACTL_END;

    exceptionName.SetUTF8(g_ExceptionLocationData[kind].Namespace);
    exceptionName.AppendUTF8(".");
    exceptionName.AppendUTF8(g_ExceptionLocationData[kind].Name);
}