少年修仙传客户端基础资源
hch
2024-04-01 d01413b00ef631ac20347716b23818b0b811f65f
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
133
134
135
136
137
138
#include "il2cpp-config.h"
#include "COMEntryPoints.h"
 
#include "il2cpp-windowsruntime-types.h"
#include "os/Mutex.h"
#include "os/WindowsRuntime.h"
#include "utils/StringUtils.h"
#include "vm/MetadataCache.h"
#include "vm/Runtime.h"
 
#include <map>
 
struct HStringLess
{
    bool operator()(Il2CppHString left, Il2CppHString right) const
    {
        uint32_t lengthLeft = 0;
        uint32_t lengthRight = 0;
 
        const Il2CppChar* charsLeft = il2cpp::os::WindowsRuntime::GetHStringBuffer(left, &lengthLeft);
        const Il2CppChar* charsRight = il2cpp::os::WindowsRuntime::GetHStringBuffer(right, &lengthRight);
 
        if (lengthLeft != lengthRight)
            return lengthLeft < lengthRight;
 
        return memcmp(charsLeft, charsRight, sizeof(Il2CppChar) * lengthLeft) < 0;
    }
};
 
struct ActivationFactoryWrapper
{
    ActivationFactoryWrapper(const std::pair<Il2CppIActivationFactory*, Il2CppHString>& factoryNamePair) :
        m_Factory(factoryNamePair.first),
        m_Name(factoryNamePair.second)
    {
        // NOTE: No add ref here since this constructor is only called with newly created factory
        // Also, name is already pre-duplicated since we cannot deal with hresult failure in a constructor
    }
 
    ActivationFactoryWrapper(const ActivationFactoryWrapper&); // = delete;
    ActivationFactoryWrapper& operator=(const ActivationFactoryWrapper&); // = delete;
 
    ~ActivationFactoryWrapper()
    {
        m_Factory->Release();
 
        il2cpp_hresult_t hr = il2cpp::os::WindowsRuntime::DeleteHString(m_Name);
        IL2CPP_ASSERT(IL2CPP_HR_SUCCEEDED(hr));
    }
 
    operator Il2CppIActivationFactory*() const
    {
        return m_Factory;
    }
 
private:
    Il2CppIActivationFactory* m_Factory;
    Il2CppHString m_Name;
};
 
typedef std::map<Il2CppHString, ActivationFactoryWrapper, HStringLess> FactoryCache;
static FactoryCache s_FactoryCache;
static il2cpp::os::FastMutex s_FactoryCacheMutex;
static bool s_InitializedIl2CppFromWindowsRuntime;
 
typedef Il2CppIActivationFactory* (*FactoryCreationFunction)();
 
// Returns:
//    IL2CPP_S_OK - on success
//    IL2CPP_E_INVALIDARG - if className or factory is null
//    IL2CPP_REGDB_E_CLASSNOTREG - if class was not found
extern "C" IL2CPP_EXPORT il2cpp_hresult_t STDCALL DllGetActivationFactory(Il2CppHString className, Il2CppIActivationFactory** factory)
{
    if (className == nullptr || factory == nullptr)
        return IL2CPP_E_INVALIDARG;
 
    il2cpp::os::FastAutoLock lock(&s_FactoryCacheMutex);
 
    if (!s_InitializedIl2CppFromWindowsRuntime)
    {
        if (!il2cpp::vm::Runtime::Init())
            return IL2CPP_COR_E_EXECUTIONENGINE;
 
        s_InitializedIl2CppFromWindowsRuntime = true;
    }
 
    FactoryCache::iterator it = s_FactoryCache.find(className);
    if (it != s_FactoryCache.end())
    {
        Il2CppIActivationFactory* cachedFactory = it->second;
        cachedFactory->AddRef();
        *factory = cachedFactory;
        return IL2CPP_S_OK;
    }
 
    uint32_t classNameLength;
    const Il2CppChar* classNameUtf16 = il2cpp::os::WindowsRuntime::GetHStringBuffer(className, &classNameLength);
    std::string classNameUtf8 = il2cpp::utils::StringUtils::Utf16ToUtf8(classNameUtf16, classNameLength);
    FactoryCreationFunction factoryCreationFunction = reinterpret_cast<FactoryCreationFunction>(il2cpp::vm::MetadataCache::GetWindowsRuntimeFactoryCreationFunction(classNameUtf8.c_str()));
 
    if (factoryCreationFunction == NULL)
        return IL2CPP_REGDB_E_CLASSNOTREG;
 
    Il2CppHString duplicatedClassName;
    il2cpp_hresult_t hr = il2cpp::os::WindowsRuntime::DuplicateHString(className, &duplicatedClassName);
    if (IL2CPP_HR_FAILED(hr))
        return hr;
 
    std::pair<FactoryCache::iterator, bool> insertionResult = s_FactoryCache.insert(std::make_pair(duplicatedClassName, std::make_pair(factoryCreationFunction(), duplicatedClassName)));
    IL2CPP_ASSERT(insertionResult.second && "Factory was already in the hash map!");
 
    Il2CppIActivationFactory* createdFactory = insertionResult.first->second;
    createdFactory->AddRef();
    *factory = createdFactory;
    return IL2CPP_S_OK;
}
 
extern "C" IL2CPP_EXPORT long STDCALL DllCanUnloadNow()
{
    if (!s_InitializedIl2CppFromWindowsRuntime)
        return IL2CPP_S_OK;
 
    // TO DO: we need to track all instantiated COM objects in order to implement this correctly
    return IL2CPP_S_FALSE;
}
 
void il2cpp::vm::COMEntryPoints::FreeCachedData()
{
    s_FactoryCache.clear();
}
 
// Prevent function name mangling on Windows/x86
// The reason this needs to live here and not os layer is because if this file is not compiled,
// those linker directives will cause unresolved external symbol errors
#if IL2CPP_TARGET_WINDOWS && defined(_M_IX86)
#pragma comment(linker, "/EXPORT:DllGetActivationFactory=_DllGetActivationFactory@8")
#pragma comment(linker, "/EXPORT:DllCanUnloadNow=_DllCanUnloadNow@0")
#endif