diff --git a/src/Build.cmd b/src/Build.cmd
index ae3e46f..0a9056e 100644
--- a/src/Build.cmd
+++ b/src/Build.cmd
@@ -27,7 +27,7 @@ goto:eof
cl /O1 /Os /Oi /GS- /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
+LibMaker.exe FixObj "%~dp0..\\objs\\%Platform%\\%1" /WeakExternFix:__security_cookie=%PointType% /WeakExternFix:__YY_Thunks_Process_Terminating=4 /WeakExternFix:__acrt_atexit_table=%PointType%
LibMaker.exe AppendWeak /MACHINE:%Platform% /DEF:"%~dp0def\\%Platform%\\PSAPI2Kernel32.def" /OUT:"%~dp0..\\objs\\%Platform%\\%1"
diff --git a/src/Thunks/YY_Thunks.h b/src/Thunks/YY_Thunks.h
index 2b187dc..8d724a5 100644
--- a/src/Thunks/YY_Thunks.h
+++ b/src/Thunks/YY_Thunks.h
@@ -396,8 +396,16 @@ static void* __fastcall try_get_function(
#undef _APPLY
+static bool g_bUninitialize/* = false*/;
+
static void __cdecl __YY_uninitialize_winapi_thunks()
{
+ // 值反初始化一次
+ if (g_bUninitialize)
+ return;
+
+ g_bUninitialize = true;
+
//当DLL被强行卸载时,我们什么都不做。
if (auto pRtlDllShutdownInProgress = (decltype(RtlDllShutdownInProgress)*)GetProcAddress(try_get_module_ntdll(), "RtlDllShutdownInProgress"))
{
@@ -466,19 +474,37 @@ static int __cdecl _YY_initialize_winapi_thunks()
return 0;
}
+// 外部weak符号,用于判断当前是否静态
+EXTERN_C extern void* __acrt_atexit_table;
+
static int __cdecl __YY_initialize_winapi_thunks()
{
_YY_initialize_winapi_thunks();
- //只在节点位置插入 atexit 流程,避免CRT还没完全初始化好出现问题。
- atexit(__YY_uninitialize_winapi_thunks);
+ // 如果 == null,那么有2种情况:
+ // 1. 非UCRT,比如2008,VC6,这时,调用 atexit是安全的,因为atexit在 XIA初始化完成了。
+ // 2. UCRT 并且处于MD状态。这时 atexit初始化 会提与 XIA,这时也是没有问题的。
+ // 如果 != null:
+ // 那么说明UCRT处于静态状态(CRT DLL其实也是静态的一种)
+ // 这时,XTY是可以正确执行的,这时就不用调用atexit了
+ // 由于XTY晚于onexit,所以它是可靠的。
+ if (__acrt_atexit_table == nullptr)
+ {
+ atexit(__YY_uninitialize_winapi_thunks);
+ }
return 0;
}
typedef int(__cdecl* _PIFV)(void);
+typedef void(__cdecl* _PVFV)(void);
-#pragma section(".CRT$XID", long, read) // CRT C Initializers
+// CRT C Initializers
+#pragma section(".CRT$XID", long, read)
+// CRT C Terminators(仅稍微之后于XTZ),这是故意的。
+// YY-Thunks属于API底层理应尽可能的滞后,且反初始化工作不依赖与CRT
+#pragma section(".CRT$XTY", long, read)
__declspec(allocate(".CRT$XID")) static _PIFV ___Initialization = __YY_initialize_winapi_thunks;
+__declspec(allocate(".CRT$XTY")) static _PVFV ___Uninitialization = __YY_uninitialize_winapi_thunks;
diff --git a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj
index 92232ec..bf3d61e 100644
--- a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj
+++ b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj
@@ -116,7 +116,7 @@
true
pch.h
Use
- MultiThreadedDebug
+ MultiThreadedDebugDLL
false
@@ -132,7 +132,7 @@
true
pch.h
Use
- MultiThreadedDebug
+ MultiThreadedDebugDLL
false
@@ -176,6 +176,12 @@
+
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+
NotUsing
diff --git a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters
index 085a225..493974a 100644
--- a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters
+++ b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters
@@ -66,6 +66,9 @@
源文件\UnitTest
+
+ 源文件
+
diff --git a/src/YY-Thunks.UnitTest/pch.cpp b/src/YY-Thunks.UnitTest/pch.cpp
index 8799ee5..781d282 100644
--- a/src/YY-Thunks.UnitTest/pch.cpp
+++ b/src/YY-Thunks.UnitTest/pch.cpp
@@ -2,6 +2,4 @@
#include "pch.h"
-// 当使用预编译的头时,需要使用此源文件,编译才能成功。
-
-EXTERN_C BOOL __YY_Thunks_Process_Terminating = 0;
\ No newline at end of file
+// 当使用预编译的头时,需要使用此源文件,编译才能成功。
\ No newline at end of file
diff --git a/src/YY-Thunks.UnitTest/weak.c b/src/YY-Thunks.UnitTest/weak.c
new file mode 100644
index 0000000..d5e8855
--- /dev/null
+++ b/src/YY-Thunks.UnitTest/weak.c
@@ -0,0 +1,4 @@
+
+const int __YY_Thunks_Process_Terminating;
+
+const void* __acrt_atexit_table;