Fea #83, Windows XP添加动态DLL TLS兼容

This commit is contained in:
mingkuang
2024-05-25 11:10:52 +08:00
parent 1f01599d91
commit 532d5259a0
10 changed files with 505 additions and 13 deletions
+3
View File
@@ -14,3 +14,6 @@ indent_size = 4
[*.{vcxproj,xml,nuspec,targets}]
indent_style = space
indent_size = 2
[*.cmd]
charset = unset
+2 -2
View File
@@ -132,13 +132,13 @@ jobs:
$RunFaild = 0
&vstest.console src\Release\YY-Thunks.UnitTest.dll "/logger:trx;LogFileName=UnitTestWin32.trx" "/Blame:CollectDump;CollectAlways=false;DumpType=full /Diag:TestResults\Win32.log"
&vstest.console src\Release\YY-Thunks.UnitTest.dll "/logger:trx;LogFileName=UnitTestWin32.trx" "/Blame:CollectDump;CollectAlways=false;DumpType=full" "/Diag:TestResults\Win32.log"
if($lastexitcode -ne 0)
{
$RunFaild = 1
}
&vstest.console src\x64\Release\YY-Thunks.UnitTest.dll "/logger:trx;LogFileName=UnitTestWin64.trx" "/Blame:CollectDump;CollectAlways=false;DumpType=full /Diag:TestResults\Win64.log"
&vstest.console src\x64\Release\YY-Thunks.UnitTest.dll "/logger:trx;LogFileName=UnitTestWin64.trx" "/Blame:CollectDump;CollectAlways=false;DumpType=full" "/Diag:TestResults\Win64.log"
if($lastexitcode -ne 0)
{
$RunFaild = 1
+2 -1
View File
@@ -10,6 +10,7 @@
<MinimumRequiredVersion Condition=" '%(Link.MinimumRequiredVersion)' == '' and '$(PlatformShortName)'=='x86' and '$(YY_Thunks_File)'=='YY_Thunks_for_WinXP.obj' ">5.01</MinimumRequiredVersion>
<MinimumRequiredVersion Condition=" '%(Link.MinimumRequiredVersion)' == '' and '$(PlatformShortName)'=='x64' and '$(YY_Thunks_File)'=='YY_Thunks_for_WinXP.obj' ">5.02</MinimumRequiredVersion>
<AdditionalDependencies>$(MSBuildThisFileDirectory)objs\$(PlatformShortName)\$(YY_Thunks_File);%(AdditionalDependencies)</AdditionalDependencies>
<EntryPointSymbol Condition="'$(ConfigurationType)'=='DynamicLibrary' and ('$(YY_Thunks_File)'=='YY_Thunks_for_WinXP.obj' or '$(YY_Thunks_File)'=='YY_Thunks_for_Win2K.obj')">DllMainCRTStartupForYY_Thunks</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@@ -21,4 +22,4 @@
<Target Name="YY_Thunks_Update_MinimumRequiredVersion" Condition="'$(YY_Thunks_File)'=='YY_Thunks_for_Win2K.obj' and Exists('$(MSBuildThisFileDirectory)objs\$(PlatformShortName)\$(YY_Thunks_File)') and ('$(ConfigurationType)' == 'Application' Or '$(ConfigurationType)' == 'DynamicLibrary') " AfterTargets="AfterLink">
<Exec Command="%22$(MSBuildThisFileDirectory)Bin\MinimumRequiredVersionHelper.exe%22 %22$(TargetPath)%22 /MinimumRequiredVersion:5.0"/>
</Target>
</Project>
</Project>
+17 -2
View File
@@ -6,6 +6,8 @@
[![nuget](https://img.shields.io/nuget/vpre/YY-Thunks)](https://www.nuget.org/packages/YY-Thunks)
[![Build&Test](https://github.com/Chuyu-Team/YY-Thunks/actions/workflows/Build&Test.yml/badge.svg)](https://github.com/Chuyu-Team/YY-Thunks/actions/workflows/Build&Test.yml)
- [英语](Readme.md)
## 1. 关于 YY-Thunks
众所周知,从 Windows 的每次更新又会新增大量 API,这使得兼容不同版本的 Windows
@@ -22,8 +24,20 @@ YY-Thunks(鸭船),存在的目的就是抹平不同系统的差异,编
### 1.1. 原理
使用 `LoadLibrary` 以及 `GetProcAddress` 动态加载 API,不存在时做出补偿措施,
最大限度模拟原始 API 行为,让你的程序正常运行。
最大限度模拟原始 API 行为,让你的程序正常运行。大概就像下面这个`GetTickCount64`函数:
```cpp
// 注意:Windows XP 不支持 GetTickCount64
ULONGLONG WINAPI GetTickCount64(VOID)
{
if (auto const _pfnGetTickCount64 = try_get_GetTickCount64())
{
return _pfnGetTickCount64();
}
// Fallback
return GetTickCount();
}
```
### 1.2. 亮点
* 更快!更安全!`鸭船`内建2级缓存以及按需加载机制,同时自动加密所有函数指针,
@@ -57,7 +71,8 @@ YY-Thunks(鸭船),存在的目的就是抹平不同系统的差异,编
2. 【链接器】-【输入】-【附加依赖项】,添加
`objs\$(PlatformShortName)\YY_Thunks_for_WinXP.obj`。
3. 【链接器】-【系统】-【所需的最低版本】,根据实际情况填写 `5.01`(WinXP 32位) 或者 `5.02`(WinXP x64、2003)。
4. 重新编译代码。
4. 如果是编译DLL,那么【链接器】-【高级】-【自定义入口点】更改为`DllMainCRTStartupForYY_Thunks`(不这样做XP下使用thread_local可能崩溃!)
5. 重新编译代码。
> 温馨提示:如果需要兼容 Vista,【所需的最低版本】无需修改,但是【附加依赖项】请选择
`objs\$(PlatformShortName)\YY_Thunks_for_Vista.obj`。
+6 -6
View File
@@ -1,8 +1,8 @@
@echo off
@echo off
setlocal
::需要设置LibMaker.exe路径到环境变量Path。
::如果你需要LibMaker.exe,请自行到 初雨开源项目交流QQ群(633710173)群文件中下载。
::需要设置LibMaker.exe路径到环境变量Path。
::如果你需要LibMaker.exe,请自行到 初雨开源项目交流QQ群(633710173)群文件中下载。
pushd "%~dp0.."
@@ -12,7 +12,7 @@ if "%Platform%"=="" set Platform=x86
md "objs\\%Platform%"
::先生成 YY_Thunks_List.hpp
::先生成 YY_Thunks_List.hpp
msbuild "%~dp0YY-Thunks.UnitTest\YY-Thunks.UnitTest.vcxproj" -t:Build_YY_Thunks_List_hpp
call:Build%Platform%
@@ -26,8 +26,8 @@ goto:eof
:BuildObj
cl /O1 /Os /Oi /GS- /std:c++17 /arch:IA32 /Z7 /MT /Fo"objs\\%Platform%\\%1" /Zl /c /D "NDEBUG" /D "YY_Thunks_Support_Version=%2" "%~dp0Thunks\YY_Thunks.cpp"
::进行函数名称进行修正 __imp__%s_%u -> __imp__%s@%u
LibMaker.exe FixObj "%~dp0..\\objs\\%Platform%\\%1" /WeakExternFix:__security_cookie=%PointType% /WeakExternFix:__YY_Thunks_Process_Terminating=4 /WeakExternFix:__acrt_atexit_table=%PointType%
::进行函数名称进行修正 __imp__%s_%u -> __imp__%s@%u
LibMaker.exe FixObj "%~dp0..\\objs\\%Platform%\\%1" /WeakExternFix:__security_cookie=%PointType% /WeakExternFix:__YY_Thunks_Process_Terminating=4 /WeakExternFix:__acrt_atexit_table=%PointType% /WeakExternFix:__pfnDllMainCRTStartupForYY_Thunks=%PointType%
LibMaker.exe AppendWeak /MACHINE:%Platform% /DEF:"%~dp0def\\%Platform%\\PSAPI2Kernel32.def" /OUT:"%~dp0..\\objs\\%Platform%\\%1"
+463
View File
@@ -0,0 +1,463 @@
#if defined(YY_Thunks_Implemented)
namespace YY::Thunks::internal
{
extern "C" BOOL WINAPI _DllMainCRTStartup(
HINSTANCE const instance,
DWORD const reason,
LPVOID const reserved
);
// 如果希望自定义函数入口点,可以设置此函数
extern "C" extern decltype(_DllMainCRTStartup)* const __pfnDllMainCRTStartupForYY_Thunks;
#if YY_Thunks_Support_Version < NTDDI_WIN6
extern "C" ULONG _tls_index;
static ULONG _tls_index_old;
#ifdef _WIN64
extern "C" const IMAGE_TLS_DIRECTORY64 _tls_used;
#else
extern "C" const IMAGE_TLS_DIRECTORY _tls_used;
#endif
#pragma section(".CRT$XLB", long, read) // First MS CRT Loader TLS Callback
enum class TlsMode
{
None,
ByFirstCallback,
ByDllMainCRTStartupForYY_Thunks,
};
// 用来记录第一次Tls回调的时机
// 如果来自ByFirstCallback,那么说明当前模块的TLS功能完全正常(模块是EXE或者来自于隐式依赖的DLL),YY-Thunks无需额外修复
// 如果来自ByDllMainCRTStartupForYY_Thunks,那么说明它是动态加载的DLL,TLS没有初始化
static TlsMode g_TlsMode;
static
VOID
NTAPI
FirstCallback(
PVOID DllHandle,
DWORD Reason,
PVOID Reserved
)
{
if (DLL_PROCESS_ATTACH == Reason)
{
if (g_TlsMode == TlsMode::None)
{
g_TlsMode = TlsMode::ByFirstCallback;
}
}
}
struct TlsRawItem
{
TlsRawItem* pNext;
TlsRawItem* pPrev;
BYTE* pBase;
void** pOldTlsIndex;
};
static thread_local TlsRawItem s_CurrentNode;
static volatile LONG uStatus = 0;
static TlsRawItem* volatile pRoot = nullptr;
static ULONG __fastcall GetTlsIndexBufferCount(TEB* _pTeb)
{
auto _ppThreadLocalStoragePointer = (void**)_pTeb->ThreadLocalStoragePointer;
if (!_ppThreadLocalStoragePointer)
return 0;
return HeapSize(_pTeb->ProcessEnvironmentBlock->ProcessHeap, 0, _ppThreadLocalStoragePointer) / sizeof(void*);
}
static PVOID NTAPI RtlImageDirectoryEntryToData(
__in PVOID pBaseAddress,
__in ULONG dwDirectory,
__out PULONG pSize
)
{
auto _pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress;
auto _pNtHerder = reinterpret_cast<PIMAGE_NT_HEADERS>(PBYTE(pBaseAddress) + _pDosHeader->e_lfanew);
auto& _DataDirectory = _pNtHerder->OptionalHeader.DataDirectory[dwDirectory];
*pSize = _DataDirectory.Size;
if (_DataDirectory.Size == 0 || _DataDirectory.VirtualAddress == 0)
return nullptr;
return PBYTE(pBaseAddress) + _DataDirectory.VirtualAddress;
}
static ULONG __fastcall GetMaxTlsIndex() noexcept
{
ULONG uMaxTlsIndex = 0;
auto _pLdr = (_PEB_LDR_DATA_XP*)(TEB*)NtCurrentTeb()->ProcessEnvironmentBlock->Ldr;
auto _pHerder = &_pLdr->InLoadOrderModuleList;
for (auto _pItem = _pHerder->Flink; _pItem != _pHerder; )
{
auto _pEntry = CONTAINING_RECORD(_pItem, _LDR_DATA_TABLE_ENTRY_XP, InLoadOrderModuleList);
_pItem = _pItem->Flink;
__try
{
// XP不会为动态加载的DLL设置这个字段(符合预期,毕竟没有真的初始化)
/*if (!_pEntry->TlsIndex)
continue;*/
ULONG TlsSize;
auto pTlsImage = (PIMAGE_TLS_DIRECTORY)RtlImageDirectoryEntryToData(
_pEntry->BaseAddress,
IMAGE_DIRECTORY_ENTRY_TLS,
&TlsSize);
if (pTlsImage == nullptr || pTlsImage->AddressOfIndex == 0)
{
continue;
}
const auto _TlsIndex = *(ULONG*)pTlsImage->AddressOfIndex;
if (uMaxTlsIndex < _TlsIndex)
uMaxTlsIndex = _TlsIndex;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
}
return uMaxTlsIndex;
}
static SYSTEM_PROCESS_INFORMATION* __fastcall GetCurrentProcessInfo(StringBuffer<char>& _szBuffer)
{
const auto _pfnNtQuerySystemInformation = try_get_NtQuerySystemInformation();
if (!_pfnNtQuerySystemInformation)
return nullptr;
ULONG _cbBuffer = max(4096, _szBuffer.uBufferLength);
ULONG _cbRet = 0;
for (;;)
{
auto _pBuffer = _szBuffer.GetBuffer(_cbBuffer);
if (!_pBuffer)
return nullptr;
LONG _Status = _pfnNtQuerySystemInformation(SystemProcessInformation, _pBuffer, _cbBuffer, &_cbRet);
if (_Status >= 0)
break;
if (STATUS_INFO_LENGTH_MISMATCH != _Status)
return nullptr;
_cbBuffer = _cbRet;
}
const auto _uCurrentProcessId = GetCurrentProcessId();
auto _pInfo = (SYSTEM_PROCESS_INFORMATION*)_szBuffer.GetBuffer(0);
for (;;)
{
if (_pInfo->ProcessId == (HANDLE)_uCurrentProcessId)
return _pInfo;
if (_pInfo->NextEntryDelta == 0)
break;
_pInfo = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(reinterpret_cast<char*>(_pInfo) + _pInfo->NextEntryDelta);
}
return nullptr;
}
static bool __fastcall AllocTlsData(TEB* _pTeb = nullptr) noexcept
{
if (_tls_index == 0)
return false;
if (!_pTeb)
_pTeb = (TEB*)NtCurrentTeb();
auto _pTlsIndex = (void**)_pTeb->ThreadLocalStoragePointer;
void** _pOldTlsIndex = nullptr;
auto _cTlsIndexLength = GetTlsIndexBufferCount(_pTeb);
if (_cTlsIndexLength <= _tls_index)
{
// Index不足,扩充……
auto _cNewTlsIndexLength = _tls_index + 128;
auto _pNewTlsIndex = (void**)Alloc(_cNewTlsIndexLength * sizeof(void*), HEAP_ZERO_MEMORY);
if (!_pNewTlsIndex)
return false;
memcpy(_pNewTlsIndex, _pTlsIndex, _cTlsIndexLength * sizeof(void*));
if ((void*)InterlockedCompareExchange((uintptr_t*)&_pTeb->ThreadLocalStoragePointer, (uintptr_t)_pNewTlsIndex, (uintptr_t)_pTlsIndex) != _pTlsIndex)
{
Free(_pNewTlsIndex);
return false;
}
if (_pTeb == (TEB*)NtCurrentTeb())
{
Free(_pTlsIndex);
}
else
{
// 其他线程的无法直接释放,玩意缓存里恰好正在使用这块那么会崩溃的
_pOldTlsIndex = _pTlsIndex;
}
_pTlsIndex = _pNewTlsIndex;
}
const size_t _cbTlsRaw = _tls_used.EndAddressOfRawData - _tls_used.StartAddressOfRawData;
auto _pRawTlsData = (BYTE*)Alloc(_cbTlsRaw, HEAP_ZERO_MEMORY);
if (!_pRawTlsData)
{
// 释放不是安全的,极小的概率可能野,但是现在现在就这样吧。
Free(_pOldTlsIndex);
return false;
}
memcpy(_pRawTlsData, (void*)_tls_used.StartAddressOfRawData, _cbTlsRaw);
InterlockedExchange((uintptr_t*)&_pTlsIndex[_tls_index], (uintptr_t)_pRawTlsData);
s_CurrentNode.pBase = _pRawTlsData;
s_CurrentNode.pOldTlsIndex = _pOldTlsIndex;
for (;;)
{
if (!_interlockedbittestandset(&uStatus, 0))
{
s_CurrentNode.pNext = pRoot;
if (pRoot)
{
pRoot->pPrev = &s_CurrentNode;
}
pRoot = &s_CurrentNode;
_interlockedbittestandreset(&uStatus, 0);
break;
}
}
return true;
}
static void __fastcall FreeTlsData()
{
if (_tls_index == 0)
return;
auto _pTeb = (TEB*)NtCurrentTeb();
if (_tls_index >= GetTlsIndexBufferCount(_pTeb))
return;
auto _ppTlsIndex = (void**)_pTeb->ThreadLocalStoragePointer;
if (_ppTlsIndex[_tls_index] == nullptr)
return;
if (s_CurrentNode.pBase != _ppTlsIndex[_tls_index])
return;
if (s_CurrentNode.pOldTlsIndex)
{
Free(s_CurrentNode.pOldTlsIndex);
s_CurrentNode.pOldTlsIndex = nullptr;
}
s_CurrentNode.pBase = nullptr;
for (;;)
{
if (!_interlockedbittestandset(&uStatus, 0))
{
auto pPrev = s_CurrentNode.pPrev;
auto pNext = s_CurrentNode.pNext;
if (pPrev)
{
pPrev->pNext = pNext;
}
else
{
pRoot = pNext;
}
if (pNext)
{
pNext->pPrev = pPrev;
}
_interlockedbittestandreset(&uStatus, 0);
auto _pTlsRawData = (void*)InterlockedExchange((uintptr_t*)&_ppTlsIndex[_tls_index], 0);
Free(_pTlsRawData);
break;
}
}
}
static bool __fastcall CreateTlsIndex() noexcept
{
if (_tls_index != 0)
return false;
_tls_index = GetMaxTlsIndex() + 1;
AllocTlsData((TEB*)NtCurrentTeb());
// 同时给所有历史的线程追加新DLL产生的Tls内存
do
{
const auto _pfnNtQueryInformationThread = try_get_NtQueryInformationThread();
if (!_pfnNtQueryInformationThread)
break;
StringBuffer<char> _Buffer;
auto _pProcessInfo = GetCurrentProcessInfo(_Buffer);
if (!_pProcessInfo)
{
break;
}
const auto _uCurrentThreadId = GetCurrentThreadId();
for (ULONG i = 0; i != _pProcessInfo->ThreadCount; ++i)
{
auto& _Thread = _pProcessInfo->Threads[i];
if (_uCurrentThreadId == (DWORD)_Thread.ClientId.UniqueThread)
continue;
auto _hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, (DWORD)_Thread.ClientId.UniqueThread);
if (!_hThread)
{
continue;
}
THREAD_BASIC_INFORMATION _ThreadBasicInfo = {};
LONG _Status = _pfnNtQueryInformationThread(_hThread, ThreadBasicInformation, &_ThreadBasicInfo, sizeof(_ThreadBasicInfo), nullptr);
if (_Status >= 0 && _ThreadBasicInfo.TebBaseAddress)
{
AllocTlsData((TEB*)_ThreadBasicInfo.TebBaseAddress);
}
CloseHandle(_hThread);
}
} while (false);
return true;
}
static void __fastcall FreeTlsIndex() noexcept
{
if (_tls_index == 0)
return;
// 故意不加锁……
for (auto _pItem = pRoot; _pItem;)
{
auto _pNext = _pItem->pNext;
if (_pItem->pOldTlsIndex)
{
Free(_pItem->pOldTlsIndex);
_pItem->pOldTlsIndex = nullptr;
}
Free(_pItem->pBase);
_pItem = _pNext;
}
}
static void __fastcall CallTlsCallback(
HINSTANCE const _hInstance,
DWORD const _uReason)
{
if (_tls_index == 0)
return;
auto _pTeb = (TEB*)NtCurrentTeb();
auto _ppThreadLocalStoragePointer = (void**)_pTeb->ThreadLocalStoragePointer;
if (!_ppThreadLocalStoragePointer)
return;
if (_tls_index >= GetTlsIndexBufferCount(_pTeb))
return;
if (!_ppThreadLocalStoragePointer[_tls_index])
return;
__try
{
auto _pfnTlsCallbacks = reinterpret_cast<PIMAGE_TLS_CALLBACK*>(_tls_used.AddressOfCallBacks);
if (_pfnTlsCallbacks)
{
for (; *_pfnTlsCallbacks; ++_pfnTlsCallbacks)
{
(*_pfnTlsCallbacks)(_hInstance, _uReason, nullptr);
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
}
#endif // YY_Thunks_Support_Version < NTDDI_WIN6
// 我们始终提供DllMainCRTStartupForYY_Thunks函数,虽然理论上Vista(包含)以上就不用修正了,但是为了做到体验统一
// 避免Vista模式设置 DllMainCRTStartupForYY_Thunks 就发生链接失败问题。
// 这个函数的存在意义是修复Windows XP系统显式加载的DLL里无法使用TLS问题。
extern "C" BOOL WINAPI DllMainCRTStartupForYY_Thunks(
HINSTANCE const _hInstance,
DWORD const _uReason,
LPVOID const _pReserved
)
{
const auto _pfnDllMainCRTStartup = __pfnDllMainCRTStartupForYY_Thunks ? __pfnDllMainCRTStartupForYY_Thunks : &_DllMainCRTStartup;
#if YY_Thunks_Support_Version < NTDDI_WIN6
__declspec(allocate(".CRT$XLB")) static const PIMAGE_TLS_CALLBACK s_FirstCallback = FirstCallback;
__foreinclude(s_FirstCallback);
__foreinclude(_tls_used);
if (internal::GetSystemVersion() < internal::MakeVersion(6, 0))
{
// Vista开始已经可以动态的处理TLS问题了,所以这里只针对老系统处理。
switch (_uReason)
{
case DLL_PROCESS_ATTACH:
if (g_TlsMode == TlsMode::None)
{
g_TlsMode = TlsMode::ByDllMainCRTStartupForYY_Thunks;
}
_tls_index_old = _tls_index;
if (_tls_index == 0 && g_TlsMode == TlsMode::ByDllMainCRTStartupForYY_Thunks)
{
CreateTlsIndex();
return _pfnDllMainCRTStartup(_hInstance, _uReason, _pReserved);
}
break;
case DLL_THREAD_ATTACH:
if (_tls_index_old == 0 && g_TlsMode == TlsMode::ByDllMainCRTStartupForYY_Thunks)
{
AllocTlsData();
CallTlsCallback(_hInstance, _uReason);
return _pfnDllMainCRTStartup(_hInstance, _uReason, _pReserved);
}
break;
case DLL_THREAD_DETACH:
if (_tls_index_old == 0 && g_TlsMode == TlsMode::ByDllMainCRTStartupForYY_Thunks)
{
CallTlsCallback(_hInstance, _uReason);
auto _bRet = _pfnDllMainCRTStartup(_hInstance, _uReason, _pReserved);
FreeTlsData();
return _bRet;
}
break;
case DLL_PROCESS_DETACH:
#if (YY_Thunks_Support_Version < NTDDI_WINXP)
__YY_Thunks_Process_Terminating = _pReserved != nullptr;
#endif
if (_tls_index_old == 0 && g_TlsMode == TlsMode::ByDllMainCRTStartupForYY_Thunks)
{
CallTlsCallback(_hInstance, _uReason);
auto _bRet = _pfnDllMainCRTStartup(_hInstance, _uReason, _pReserved);
FreeTlsIndex();
return _bRet;
}
break;
}
}
#endif
return _pfnDllMainCRTStartup(_hInstance, _uReason, _pReserved);
}
}
#endif
+2 -2
View File
@@ -174,11 +174,11 @@ static __forceinline unsigned __int64 __fastcall __crt_rotate_pointer_value(unsi
#ifdef _WIN64
#define __foreinclude(p) \
__pragma(warning(suppress:6031)) \
_bittest64(reinterpret_cast<LONG_PTR*>(&p), 0)
_bittest64((LONG_PTR*)(&p), 0)
#else
#define __foreinclude(p) \
__pragma(warning(suppress:6031)) \
_bittest(reinterpret_cast<LONG_PTR*>(&p), 0)
_bittest((LONG_PTR*)(&p), 0)
#endif
@@ -110,6 +110,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<EntryPointSymbol>DllMainCRTStartupForYY_Thunks</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -128,6 +129,7 @@
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<EntryPointSymbol>DllMainCRTStartupForYY_Thunks</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -146,6 +148,7 @@
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<EntryPointSymbol>DllMainCRTStartupForYY_Thunks</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -168,6 +171,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<EntryPointSymbol>DllMainCRTStartupForYY_Thunks</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@@ -222,6 +226,7 @@
<ClInclude Include="..\Thunks\d3d11.hpp" />
<ClInclude Include="..\Thunks\d3d9.hpp" />
<ClInclude Include="..\Thunks\dbghelp.hpp" />
<ClInclude Include="..\Thunks\DllMainCRTStartup.hpp" />
<ClInclude Include="..\Thunks\dwmapi.hpp" />
<ClInclude Include="..\Thunks\dwrite.hpp" />
<ClInclude Include="..\Thunks\dxgi.hpp" />
@@ -308,6 +308,9 @@
<ClInclude Include="..\Thunks\dbghelp.hpp">
<Filter>Thunks</Filter>
</ClInclude>
<ClInclude Include="..\Thunks\DllMainCRTStartup.hpp">
<Filter>Thunks</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\def\x86\PSAPI2Kernel32.def">
+2
View File
@@ -2,3 +2,5 @@
const int __YY_Thunks_Process_Terminating;
const void* __acrt_atexit_table;
const void* __pfnDllMainCRTStartupForYY_Thunks;