summaryrefslogtreecommitdiff
path: root/src/vm/rtlfunctions.cpp
blob: b7cb78761a4aa4df563719cc8fe9edf95cd5f9ec (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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// RtlFunctions.CPP
//

//
// Various functions for interacting with ntdll.
//
//

// Precompiled Header

#include "common.h"

#include "rtlfunctions.h"


#ifdef _TARGET_AMD64_

RtlVirtualUnwindFn*                 RtlVirtualUnwind_Unsafe         = NULL;

HRESULT EnsureRtlFunctions()
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_ANY;
    }
    CONTRACTL_END;

    HMODULE hModuleNtDll = CLRLoadLibrary(W("ntdll"));

    if (hModuleNtDll == NULL)
        return E_FAIL;

#define ENSURE_FUNCTION_RENAME(clrname, ntname)   \
    if (NULL == clrname) { clrname = (ntname##Fn*)GetProcAddress(hModuleNtDll, #ntname); } \
    if (NULL == clrname) { return E_FAIL; } \
    { }

    ENSURE_FUNCTION_RENAME(RtlVirtualUnwind_Unsafe, RtlVirtualUnwind       );

    return S_OK;
}

#else // _TARGET_AMD64_

HRESULT EnsureRtlFunctions()
{
    LIMITED_METHOD_CONTRACT;
    return S_OK;
}

#endif // _TARGET_AMD64_

#if defined(WIN64EXCEPTIONS)

VOID InstallEEFunctionTable (
        PVOID pvTableID,
        PVOID pvStartRange,
        ULONG cbRange,
        PGET_RUNTIME_FUNCTION_CALLBACK pfnGetRuntimeFunctionCallback,
        PVOID pvContext,
        EEDynamicFunctionTableType TableType)
{
    CONTRACTL
    {
        THROWS;
        GC_NOTRIGGER;
        MODE_ANY;
        PRECONDITION(cbRange <= DYNAMIC_FUNCTION_TABLE_MAX_RANGE);
    }
    CONTRACTL_END;

    static LPWSTR wszModuleName = NULL;
    static WCHAR  rgwModuleName[MAX_LONGPATH] = { 0 };

    if (wszModuleName == NULL)        
    {
        StackSString ssTempName;
        DWORD dwTempNameSize;

        // Leaves trailing backslash on path, producing something like "c:\windows\microsoft.net\framework\v4.0.x86dbg\"
        LPCWSTR pszSysDir = GetInternalSystemDirectory(&dwTempNameSize);

        //finish creating complete path and copy to buffer if we can
        if (pszSysDir == NULL)
        {   // The CLR should become unavailable in this case.
            EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
        }

        ssTempName.Set(pszSysDir);
        ssTempName.Append(MAIN_DAC_MODULE_DLL_NAME_W);

        if (ssTempName.GetCount() < MAX_LONGPATH)
        {
            wcscpy_s(rgwModuleName, MAX_LONGPATH, ssTempName.GetUnicode());

            // publish result
            InterlockedExchangeT(&wszModuleName, rgwModuleName);
        }
        else
        {
            NewArrayHolder<WCHAR> wzTempName(DuplicateStringThrowing(ssTempName.GetUnicode()));

            // publish result
            if (InterlockedCompareExchangeT(&wszModuleName, (LPWSTR)wzTempName, nullptr) == nullptr)
            {
                wzTempName.SuppressRelease();
            }
        }
    }

    if (!RtlInstallFunctionTableCallback(
            ((ULONG_PTR)pvTableID) | 3,  // the low 2 bits must be set so NT knows
                                         // it's not really a pointer.  See
                                         // DeleteEEFunctionTable.
            (ULONG_PTR)pvStartRange,
            cbRange,
            pfnGetRuntimeFunctionCallback,
            EncodeDynamicFunctionTableContext(pvContext, TableType),
            wszModuleName))
    {
        COMPlusThrowOM();
    }
}

#endif // WIN64EXCEPTIONS