[RunTmChk]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 18 Oct 2014 21:22:52 +0000 (21:22 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 18 Oct 2014 21:22:52 +0000 (21:22 +0000)
- Implement _RTC_GetErrDesc, _RTC_SetErrorFuncW, add stubs for _RTC_NumErrors, _RTC_SetErrorType, _RTC_SetErrorFunc
- Implement _RTC_DefaultErrorFuncW which will be used, when no other error func was set
- Implement _RTC_InitBase, which will be called from _RTC_Initialize, and which in turn calls either _CRT_RTC_INITW, if CRT was linked, or a local _CRT_RTC_INITW0, which in turn will return the error function to use. This allows us to use a custom error function for all modules that link to (MSV)CRT. Only user32 does not really fit into here, since it uses the same startup code but does not link to MSVCRT.

[CRT]
- Call _RTC_Initialize from __main before initializing the global constructors, but fall back to a dummy _RTC_NoInitialize(), when RunTmChk.lib was not linked. Now we properly initialize both our own as well as MS RunTmChk lib.

svn path=/trunk/; revision=64816

reactos/lib/sdk/crt/startup/mscmain.c
reactos/lib/sdk/runtmchk/CMakeLists.txt
reactos/lib/sdk/runtmchk/rtcapi.c
reactos/lib/sdk/runtmchk/rtcuserapi.c [new file with mode: 0644]

index 4eba46f..a7f57a4 100644 (file)
@@ -6,6 +6,18 @@
 
 #include <windows.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <rtcapi.h>
+#include <assert.h>
+
+#if defined(_M_IX86)
+#pragma comment(linker, "/alternatename:__RTC_Initialize=__RTC_NoInitialize")
+#elif defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM)
+#pragma comment(linker, "/alternatename:_RTC_Initialize=_RTC_NoInitialize")
+#else
+#error Unsupported platform
+#endif
 
 void _pei386_runtime_relocator(void)
 {
@@ -36,16 +48,39 @@ _CRT_INIT0(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
     return TRUE;
 }
 
-void Catch_RTC_Failure(int errType, const wchar_t *file, int line, 
-                       const wchar_t *module, const wchar_t *format, ...)
+int
+__cdecl
+Catch_RTC_Failure(
+    int errType,
+    const wchar_t *file,
+    int line,
+    const wchar_t *module,
+    const wchar_t *format,
+    ...)
 {
     /* FIXME: better failure routine */
     __debugbreak();
+    return 0;
 }
 
-void* __cdecl _CRT_RTC_INITW(void *res0, void **res1, int res2, int res3, int res4)
+extern
+void
+__cdecl
+_RTC_NoInitialize(void)
 {
-    return &Catch_RTC_Failure; 
+    /* Do nothing, if RunTmChk.lib is not pulled in */
+}
+
+_RTC_error_fnW
+__cdecl
+_CRT_RTC_INITW(
+    void *_Res0,
+    void **_Res1,
+    int _Res2,
+    int _Res3,
+    int _Res4)
+{
+    return &Catch_RTC_Failure;
 }
 
 static int initialized = 0;
@@ -56,6 +91,9 @@ __main(void)
     if (!initialized)
     {
         initialized = 1;
+
+        _RTC_Initialize();
+
         __do_global_ctors ();
     }
 }
index 4b55bc3..2cd8430 100644 (file)
@@ -1,5 +1,8 @@
 
-list(APPEND SOURCE rtcapi.c)
+list(APPEND SOURCE
+    rtcapi.c
+    rtcuserapi.c
+)
 
 if(ARCH STREQUAL "i386")
     list(APPEND ASM_SOURCE i386/_RTC_CheckEsp.S)
index 1e9bbf5..96631ca 100644 (file)
@@ -7,30 +7,91 @@
 
 #include <rtcapi.h>
 
-unsigned long
+#if defined(_M_IX86)
+#pragma comment(linker, "/alternatename:__CRT_RTC_INITW=__CRT_RTC_INITW0")
+#elif defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM)
+#pragma comment(linker, "/alternatename:_CRT_RTC_INITW=_CRT_RTC_INITW0")
+#else
+#error Unsupported platform
+#endif
+
+int
 __cdecl
-DbgPrint(
-    const char *fmt, ...);
+_RTC_DefaultErrorFuncW(
+    int errType,
+    const wchar_t *file,
+    int line,
+    const wchar_t *module,
+    const wchar_t *format,
+    ...)
+{
+    /* Simple fallback function */
+    __debugbreak();
+    return 0;
+}
+
+_RTC_error_fnW _RTC_pErrorFuncW = _RTC_DefaultErrorFuncW;
+
+/*
+    Default CRT RTC init, if we don't link to CRT
+*/
+_RTC_error_fnW
+__cdecl
+_CRT_RTC_INITW0(
+    void *_Res0,
+    void **_Res1,
+    int _Res2,
+    int _Res3,
+    int _Res4)
+{
+    return &_RTC_DefaultErrorFuncW;
+}
 
 void
+__cdecl
 _RTC_InitBase(void)
 {
-    __debugbreak();
+    static char initialized = 0;
+    _RTC_error_fnW errorFunc;
+
+    if (!initialized)
+    {
+        errorFunc = _CRT_RTC_INITW(0, 0, 0, 1, 0);
+        _RTC_SetErrorFuncW(errorFunc);
+        initialized = 1;
+    }
 }
 
 void
+__cdecl
 _RTC_Shutdown(void)
 {
     __debugbreak();
 }
 
+void
+__cdecl
+_RTC_Initialize(void)
+{
+    /* Usually this function would walk an array of function pointers and call
+       each of these, like done with global ctors, but since these are currently
+       only _RTC_InitBase, we simply call that function once. */
+    _RTC_InitBase();
+}
+
 void
 __cdecl
 _RTC_Failure(
     void* retaddr,
     int errnum)
 {
-    __debugbreak();
+    _RTC_pErrorFuncW(errnum,
+                     L"unknown file",
+                     -1,
+                     L"unknown module",
+                     L"Invalid stack pointer value caught at %p, error %d\n",
+                     retaddr,
+                     errnum);
 }
 
 void
@@ -38,7 +99,12 @@ __cdecl
 _RTC_UninitUse(
     const char *_Varname)
 {
-    __debugbreak();
+    _RTC_pErrorFuncW(_RTC_UNINIT_LOCAL_USE,
+                     L"unknown file",
+                     -1,
+                     L"unknown module",
+                     L"Use of uninitialized variable %S!\n",
+                     _Varname);
 }
 
 void
@@ -59,7 +125,12 @@ _RTC_CheckStackVars(
         /* Check if they contain the guard bytes */
         if ((*guard1 != 0xCCCCCCCC) || (*guard2 != 0xCCCCCCCC))
         {
-            __debugbreak();
+            _RTC_pErrorFuncW(_RTC_CORRUPT_STACK,
+                             L"unknown file",
+                             -1,
+                             L"unknown module",
+                             L"Stack corruption near '%s'\n",
+                             _Fd->variables[i].name);
         }
     }
 }
@@ -90,7 +161,11 @@ _RTC_CheckStackVars2(
             (current->guard2[2] != 0xCCCCCCCC) ||
             (*guard != 0xCCCCCCCC))
         {
-            __debugbreak();
+            _RTC_pErrorFuncW(_RTC_CORRUPTED_ALLOCA,
+                             L"unknown file",
+                             -1,
+                             L"unknown module",
+                             L"Stack corruption in alloca frame\n");
         }
     }
 }
@@ -124,3 +199,4 @@ _RTC_AllocaHelper(
         *_PAllocaInfoList = _PAllocaBase;
     }
 }
+
diff --git a/reactos/lib/sdk/runtmchk/rtcuserapi.c b/reactos/lib/sdk/runtmchk/rtcuserapi.c
new file mode 100644 (file)
index 0000000..5ae7a9c
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * PROJECT:         MSVC runtime check support library
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * PURPOSE:         Provides support functions for MSVC runtime checks
+ * PROGRAMMER:      Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+#include <rtcapi.h>
+
+extern _RTC_error_fnW _RTC_pErrorFuncW;
+
+int
+__cdecl
+_RTC_DefaultErrorFuncW(
+    int errType,
+    const wchar_t *file,
+    int line,
+    const wchar_t *module,
+    const wchar_t *format,
+    ...);
+
+static
+char*
+_RTC_ErrorDescription[] =
+{
+    "The stack pointer was wrong after returning from a function call.", /* _RTC_CHKSTK */
+    "Data was lost when a type was converted to a smaller type.",        /* _RTC_CVRT_LOSS_INFO */
+    "The stack near a local variable was corrupted.",                    /* _RTC_CORRUPT_STACK */
+    "An uninitialized local variable was used.",                         /* _RTC_UNINIT_LOCAL_USE */
+    "The stack around an alloca was corrupted.",                         /* _RTC_CORRUPTED_ALLOCA */
+};
+
+int
+__cdecl
+_RTC_NumErrors(void)
+{
+    /* Not supported yet */
+    __debugbreak();
+    return 0;
+}
+
+const char *
+__cdecl
+_RTC_GetErrDesc(
+    _RTC_ErrorNumber _Errnum)
+{
+    if (_Errnum < (sizeof(_RTC_ErrorDescription) / sizeof(_RTC_ErrorDescription[0])))
+    {
+        return _RTC_ErrorDescription[_Errnum];
+    }
+
+    return "Invalid/Unknown error.";
+}
+
+int
+__cdecl
+_RTC_SetErrorType(
+    _RTC_ErrorNumber _Errnum,
+    int _ErrType)
+{
+    /* Not supported yet */
+    __debugbreak();
+    return 0;
+}
+
+_RTC_error_fn
+__cdecl
+_RTC_SetErrorFunc(
+    _RTC_error_fn new_fn)
+{
+    /* Not supported yet */
+    __debugbreak();
+    return 0;
+}
+
+_RTC_error_fnW
+__cdecl
+_RTC_SetErrorFuncW(_RTC_error_fnW new_fn)
+{
+    _RTC_error_fnW old_fn;
+
+    /* Get the current error func */
+    old_fn = _RTC_pErrorFuncW;
+
+    /* Set the new function or reset when 0 was passed */
+    _RTC_pErrorFuncW = new_fn ? new_fn : _RTC_DefaultErrorFuncW;
+
+    /* Return the old error func, or 0, if none was set */
+    return old_fn != _RTC_DefaultErrorFuncW ? old_fn : 0;
+}
+