[RunTmChk]
[reactos.git] / reactos / lib / sdk / runtmchk / rtcapi.c
1 /*
2 * PROJECT: MSVC runtime check support library
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * PURPOSE: Provides support functions for MSVC runtime checks
5 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
6 */
7
8 #include <rtcapi.h>
9
10 #if defined(_M_IX86)
11 #pragma comment(linker, "/alternatename:__CRT_RTC_INITW=__CRT_RTC_INITW0")
12 #elif defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM)
13 #pragma comment(linker, "/alternatename:_CRT_RTC_INITW=_CRT_RTC_INITW0")
14 #else
15 #error Unsupported platform
16 #endif
17
18 int
19 __cdecl
20 _RTC_DefaultErrorFuncW(
21 int errType,
22 const wchar_t *file,
23 int line,
24 const wchar_t *module,
25 const wchar_t *format,
26 ...)
27 {
28 /* Simple fallback function */
29 __debugbreak();
30 return 0;
31 }
32
33 _RTC_error_fnW _RTC_pErrorFuncW = _RTC_DefaultErrorFuncW;
34
35 /*
36 Default CRT RTC init, if we don't link to CRT
37 */
38 _RTC_error_fnW
39 __cdecl
40 _CRT_RTC_INITW0(
41 void *_Res0,
42 void **_Res1,
43 int _Res2,
44 int _Res3,
45 int _Res4)
46 {
47 return &_RTC_DefaultErrorFuncW;
48 }
49
50 void
51 __cdecl
52 _RTC_InitBase(void)
53 {
54 static char initialized = 0;
55 _RTC_error_fnW errorFunc;
56
57 if (!initialized)
58 {
59 errorFunc = _CRT_RTC_INITW(0, 0, 0, 1, 0);
60 _RTC_SetErrorFuncW(errorFunc);
61 initialized = 1;
62 }
63 }
64
65 void
66 __cdecl
67 _RTC_Shutdown(void)
68 {
69 __debugbreak();
70 }
71
72 void
73 __cdecl
74 _RTC_Initialize(void)
75 {
76 /* Usually this function would walk an array of function pointers and call
77 each of these, like done with global ctors, but since these are currently
78 only _RTC_InitBase, we simply call that function once. */
79 _RTC_InitBase();
80 }
81
82 void
83 __cdecl
84 _RTC_Failure(
85 void* retaddr,
86 int errnum)
87 {
88 _RTC_pErrorFuncW(errnum,
89 L"unknown file",
90 -1,
91 L"unknown module",
92 L"Invalid stack pointer value caught at %p, error %d\n",
93 retaddr,
94 errnum);
95 }
96
97 void
98 __cdecl
99 _RTC_UninitUse(
100 const char *_Varname)
101 {
102 _RTC_pErrorFuncW(_RTC_UNINIT_LOCAL_USE,
103 L"unknown file",
104 -1,
105 L"unknown module",
106 L"Use of uninitialized variable %S!\n",
107 _Varname);
108 }
109
110 void
111 __fastcall
112 _RTC_CheckStackVars(
113 void *_Esp,
114 _RTC_framedesc *_Fd)
115 {
116 int i, *guard1, *guard2;
117
118 /* Loop all variables in the descriptor */
119 for (i = 0; i < _Fd->varCount; i++)
120 {
121 /* Get the 2 guards below and above the variable */
122 guard1 = (int*)((char*)_Esp + _Fd->variables[i].addr - sizeof(*guard1));
123 guard2 = (int*)((char*)_Esp + _Fd->variables[i].addr +_Fd->variables[i].size);
124
125 /* Check if they contain the guard bytes */
126 if ((*guard1 != 0xCCCCCCCC) || (*guard2 != 0xCCCCCCCC))
127 {
128 _RTC_pErrorFuncW(_RTC_CORRUPT_STACK,
129 L"unknown file",
130 -1,
131 L"unknown module",
132 L"Stack corruption near '%s'\n",
133 _Fd->variables[i].name);
134 }
135 }
136 }
137
138 void
139 __fastcall
140 _RTC_CheckStackVars2(
141 void *_Esp,
142 _RTC_framedesc *_Fd,
143 _RTC_ALLOCA_NODE *_AllocaList)
144 {
145 _RTC_ALLOCA_NODE *current;
146 int *guard;
147
148 /* Process normal variables */
149 _RTC_CheckStackVars(_Esp, _Fd);
150
151 /* Process the alloca list */
152 for (current = _AllocaList; current != 0; current = current->next)
153 {
154 /* Get the upper guard */
155 guard = (int*)((char*)current + current->allocaSize - sizeof(*guard));
156
157 /* Check if all guard locations are still ok */
158 if ((current->guard1 != 0xCCCCCCCC) ||
159 (current->guard2[0] != 0xCCCCCCCC) ||
160 (current->guard2[1] != 0xCCCCCCCC) ||
161 (current->guard2[2] != 0xCCCCCCCC) ||
162 (*guard != 0xCCCCCCCC))
163 {
164 _RTC_pErrorFuncW(_RTC_CORRUPTED_ALLOCA,
165 L"unknown file",
166 -1,
167 L"unknown module",
168 L"Stack corruption in alloca frame\n");
169 }
170 }
171 }
172
173 void
174 __fastcall
175 _RTC_AllocaHelper(
176 _RTC_ALLOCA_NODE *_PAllocaBase,
177 size_t _CbSize,
178 _RTC_ALLOCA_NODE **_PAllocaInfoList)
179 {
180 unsigned long i;
181
182 /* Check if we got any allocation */
183 if ((_PAllocaBase != 0) &&
184 (_CbSize != 0) &&
185 (_PAllocaInfoList != 0))
186 {
187 /* Mark the whole range */
188 char *guard = (char*)_PAllocaBase;
189 for (i = 0; i < _CbSize; i++)
190 {
191 guard[i] = 0xCC;
192 }
193
194 /* Initialize the alloca base frame */
195 _PAllocaBase->allocaSize = _CbSize;
196
197 /* Insert this frame into the alloca list */
198 _PAllocaBase->next = *_PAllocaInfoList;
199 *_PAllocaInfoList = _PAllocaBase;
200 }
201 }
202