ReactOS 0.4.16-dev-835-gd769f56
invalid_parameter.cpp
Go to the documentation of this file.
1//
2// invalid_parameter.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// The invalid parameter handlers and related functionality
7//
8#include <corecrt_internal.h>
10
11
12static __crt_state_management::dual_state_global<_invalid_parameter_handler> __acrt_invalid_parameter_handler;
13
14
15
16#if defined _M_X64 && !defined _UCRT_ENCLAVE_BUILD
17
18 static void __cdecl capture_current_context(CONTEXT* const context_record) throw()
19 {
20 ULONG64 ControlPc;
22 ULONG64 ImageBase;
23 PRUNTIME_FUNCTION FunctionEntry;
24 PVOID HandlerData;
25
26 RtlCaptureContext(context_record);
27
28 ControlPc = context_record->Rip;
29 FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, nullptr);
30
31 if (FunctionEntry != nullptr)
32 {
35 ImageBase,
36 ControlPc,
37 FunctionEntry,
38 context_record,
39 &HandlerData,
41 nullptr);
42 }
43 }
44
45#endif // _M_X64 && !_UCRT_ENCLAVE_BUILD
46
47#if defined _CRT_GLOBAL_STATE_ISOLATION
48
49 // The legacy Windows CRT (msvcrt) does not terminate the process when an
50 // invalid parameter is passed to a library function. Turning on this
51 // validation for Windows components would be a big app compat problem.
52 //
53 // For OS components the default behavior will be to ignore the invalid parameters
54 // and that is accomplished by providing an empty IPH.
55 static void __cdecl invalid_parameter_handler_continue(
56 wchar_t const * const, // pszExpression
57 wchar_t const * const, // pszFunction
58 wchar_t const * const, // pszFile
59 unsigned int, // nLine
60 uintptr_t // pReserved
61 ) throw()
62 {
63 }
64
65#endif
66
67extern "C" void __cdecl __acrt_initialize_invalid_parameter_handler(void* const encoded_null)
68{
69#if defined _CRT_GLOBAL_STATE_ISOLATION
70 const _invalid_parameter_handler encoded_os_iph = __crt_fast_encode_pointer(invalid_parameter_handler_continue);
71#endif
72 const _invalid_parameter_handler iph[] =
73 {
74 reinterpret_cast<_invalid_parameter_handler>(encoded_null)
75#if defined _CRT_GLOBAL_STATE_ISOLATION
76 ,encoded_os_iph
77#endif
78 };
79
80 __acrt_invalid_parameter_handler.initialize_from_array(iph);
81}
82
83
84
85//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86//
87// _invalid_parameter
88//
89//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91 wchar_t const* const expression,
92 wchar_t const* const function_name,
93 wchar_t const* const file_name,
94 unsigned int const line_number,
95 uintptr_t const reserved,
96 __crt_cached_ptd_host& ptd
97 )
98{
99 __acrt_ptd * const raw_ptd = ptd.get_raw_ptd_noexit();
100 if (raw_ptd && raw_ptd->_thread_local_iph)
101 {
103 return;
104 }
105
106 _invalid_parameter_handler const global_handler = __crt_fast_decode_pointer(__acrt_invalid_parameter_handler.value(ptd));
107 if (global_handler)
108 {
109 global_handler(expression, function_name, file_name, line_number, reserved);
110 return;
111 }
112
113 _invoke_watson(expression, function_name, file_name, line_number, reserved);
114}
115
117 wchar_t const* const expression,
118 wchar_t const* const function_name,
119 wchar_t const* const file_name,
120 unsigned int const line_number,
121 uintptr_t const reserved
122 )
123{
124 __crt_cached_ptd_host ptd;
126}
127
129{
130 _invalid_parameter(nullptr, nullptr, nullptr, 0, 0);
131}
132
133// This is used by inline code in the C++ Standard Library and the SafeInt
134// library. Because it is __declspec(noreturn), the compiler can better
135// optimize use of the invalid parameter handler for inline code.
136extern "C" __declspec(noreturn) void __cdecl _invalid_parameter_noinfo_noreturn()
137{
138 _invalid_parameter(nullptr, nullptr, nullptr, 0, 0);
139 _invoke_watson (nullptr, nullptr, nullptr, 0, 0);
140}
141
142
143
144//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
145//
146// _invoke_watson
147//
148//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149#if (defined _M_IX86 || defined _M_X64) && !defined _UCRT_ENCLAVE_BUILD
150
151 extern "C" void __cdecl __acrt_call_reportfault(
152 int const debugger_hook_code,
154 DWORD const _exception_flags
155 )
156 {
157 // Notify the debugger if attached.
158 if (debugger_hook_code != _CRT_DEBUGGER_IGNORE)
159 {
160 _CRT_DEBUGGER_HOOK(debugger_hook_code);
161 }
162
163 // Fake an exception to call report fault:
164 EXCEPTION_RECORD ExceptionRecord{};
166 EXCEPTION_POINTERS ExceptionPointers = {&ExceptionRecord, &ContextRecord};
167
168 #ifdef _M_IX86
169 #if defined(__GNUC__) || defined(__clang__)
170 __asm__ __volatile__(
171 "movl %%eax, %[CxEax]\n\t"
172 "movl %%ecx, %[CxEcx]\n\t"
173 "movl %%edx, %[CxEdx]\n\t"
174 "movl %%ebx, %[CxEbx]\n\t"
175 "movl %%esi, %[CxEsi]\n\t"
176 "movl %%edi, %[CxEdi]\n\t"
177 : [CxEax] "=m" (ContextRecord.Eax),
178 [CxEcx] "=m" (ContextRecord.Ecx),
179 [CxEdx] "=m" (ContextRecord.Edx),
180 [CxEbx] "=m" (ContextRecord.Ebx),
181 [CxEsi] "=m" (ContextRecord.Esi),
182 [CxEdi] "=m" (ContextRecord.Edi));
183 __asm__ __volatile__(
184 "movw %%ss, %[CxSegSs]\n\t"
185 "movw %%cs, %[CxSegCs]\n\t"
186 "movw %%ds, %[CxSegDs]\n\t"
187 "movw %%es, %[CxSegEs]\n\t"
188 "movw %%fs, %[CxSegFs]\n\t"
189 "movw %%gs, %[CxSegGs]\n\t"
190 : [CxSegSs] "=m" (ContextRecord.SegSs),
191 [CxSegCs] "=m" (ContextRecord.SegCs),
192 [CxSegDs] "=m" (ContextRecord.SegDs),
193 [CxSegEs] "=m" (ContextRecord.SegEs),
194 [CxSegFs] "=m" (ContextRecord.SegFs),
195 [CxSegGs] "=m" (ContextRecord.SegGs));
196 __asm__ __volatile__(
197 "pushfl\n\t"
198 "popl %[CxEFlags]\n\t"
199 : [CxEFlags] "=m" (ContextRecord.EFlags));
200 #else // ^^^ __GNUC__ ^^^ // vvv !__GNUC__ vvv //
201 __asm
202 {
203 mov dword ptr [ContextRecord.Eax ], eax
204 mov dword ptr [ContextRecord.Ecx ], ecx
205 mov dword ptr [ContextRecord.Edx ], edx
206 mov dword ptr [ContextRecord.Ebx ], ebx
207 mov dword ptr [ContextRecord.Esi ], esi
208 mov dword ptr [ContextRecord.Edi ], edi
209 mov word ptr [ContextRecord.SegSs], ss
210 mov word ptr [ContextRecord.SegCs], cs
211 mov word ptr [ContextRecord.SegDs], ds
212 mov word ptr [ContextRecord.SegEs], es
213 mov word ptr [ContextRecord.SegFs], fs
214 mov word ptr [ContextRecord.SegGs], gs
215 pushfd
216 pop [ContextRecord.EFlags]
217 }
218 #endif // !__GNUC__
219
220 ContextRecord.ContextFlags = CONTEXT_CONTROL;
221
225
226 #else // ^^^ _M_IX86 ^^^ // vvv _M_X64 vvv //
227
228 capture_current_context(&ContextRecord);
231
232 #endif // _M_X64
233
234 ExceptionRecord.ExceptionCode = _exception_code;
235 ExceptionRecord.ExceptionFlags = _exception_flags;
236 ExceptionRecord.ExceptionAddress = _ReturnAddress();
237
238 BOOL const was_debugger_present = IsDebuggerPresent();
239
240 // Raises an exception that bypasses all exception handlers:
241#pragma warning(suppress:__WARNING_SETUNHANDLEDEXCEPTIONFILTER_USE) // 28725 Use Watson instead of this SetUnhandledExceptionFilter.
243 DWORD const handler_result = UnhandledExceptionFilter(&ExceptionPointers);
244
245 // If no handler was found and no debugger was previously attached, then
246 // execution must stop into the debugger hook:
247 if (handler_result == EXCEPTION_CONTINUE_SEARCH && !was_debugger_present && debugger_hook_code != _CRT_DEBUGGER_IGNORE)
248 {
249 _CRT_DEBUGGER_HOOK(debugger_hook_code);
250 }
251 }
252
253 extern "C" __declspec(noreturn) void __cdecl _invoke_watson(
254 wchar_t const* const expression,
255 wchar_t const* const function_name,
256 wchar_t const* const file_name,
257 unsigned int const line_number,
258 uintptr_t const reserved
259 )
260 {
261 UNREFERENCED_PARAMETER(expression );
266
268 {
270 }
271
272 // Otherwise, raise a fast-fail exception and termintae the process:
277
280 }
281
282#else // ^^^ (_M_IX86 || _M_X64) && !_UCRT_ENCLAVE_BUILD ^^^ // vvv Newer Architectures vvv //
283
284 extern "C" __declspec(noreturn) void __cdecl _invoke_watson(
285 wchar_t const* const expression,
286 wchar_t const* const function_name,
287 wchar_t const* const file_name,
288 unsigned int const line_number,
290 )
291 {
292 UNREFERENCED_PARAMETER(expression );
297
299 }
300
301#endif
302
303
304
305//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
306//
307// Handler Accessors
308//
309//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
311{
312 _invalid_parameter_handler const old_handler = __crt_fast_decode_pointer(__acrt_invalid_parameter_handler.value());
313 __acrt_invalid_parameter_handler.value() = __crt_fast_encode_pointer(new_handler);
314 return old_handler;
315}
316
318{
319 return __crt_fast_decode_pointer(__acrt_invalid_parameter_handler.value());
320}
321
322
323
325{
326 __acrt_ptd* const ptd = __acrt_getptd();
327
328 _invalid_parameter_handler const old_handler = ptd->_thread_local_iph;
329 ptd->_thread_local_iph = new_handler;
330 return old_handler;
331}
332
334{
336 if (!ptd)
337 {
338 return nullptr;
339 }
340
341 return ptd->_thread_local_iph;
342}
#define __cdecl
Definition: accygwin.h:79
__acrt_ptd *__cdecl __acrt_getptd(void)
void __cdecl __acrt_call_reportfault(int nDbgHookCode, DWORD dwExceptionCode, DWORD dwExceptionFlags)
__acrt_ptd *__cdecl __acrt_getptd_noexit(void)
_In_ size_t const _In_ int _In_ bool const _In_ unsigned const _In_ __acrt_rounding_mode const _Inout_ __crt_cached_ptd_host & ptd
Definition: cvt.cpp:355
#define GetCurrentProcess()
Definition: compat.h:759
LONG WINAPI UnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
Definition: except.c:269
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI DECLSPEC_HOTPATCH SetUnhandledExceptionFilter(IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
Definition: except.c:790
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1532
BOOL WINAPI IsProcessorFeaturePresent(IN DWORD ProcessorFeature)
Definition: sysinfo.c:169
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
void __declspec(noinline) __cdecl _free_base(void *const block)
Definition: free_base.cpp:98
#define UNW_FLAG_NHANDLER
Definition: gs_support.c:32
#define es
Definition: i386-dis.c:440
#define ss
Definition: i386-dis.c:441
#define ds
Definition: i386-dis.c:443
#define cs
Definition: i386-dis.c:442
#define gs
Definition: i386-dis.c:445
void(__cdecl * _invalid_parameter_handler)(const wchar_t *, const wchar_t *, const wchar_t *, unsigned int, uintptr_t)
Definition: stdlib.h:125
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:91
#define _CRT_DEBUGGER_IGNORE
#define _CRT_DEBUGGER_HOOK(x)
#define _CRT_DEBUGGER_INVALIDPARAMETER
#define _ReturnAddress()
Definition: intrin_arm.h:35
#define _AddressOfReturnAddress()
Definition: intrin_ppc.h:40
_invalid_parameter_handler __cdecl _set_invalid_parameter_handler(_invalid_parameter_handler const new_handler)
__fastfail(FAST_FAIL_INVALID_ARG)
wchar_t const *const wchar_t const *const unsigned int const uintptr_t const reserved
wchar_t const *const function_name
_invalid_parameter_handler __cdecl _get_invalid_parameter_handler()
void __cdecl __acrt_initialize_invalid_parameter_handler(void *const encoded_null)
static __crt_state_management::dual_state_global< _invalid_parameter_handler > __acrt_invalid_parameter_handler
wchar_t const *const wchar_t const *const file_name
_invalid_parameter_handler __cdecl _get_thread_local_invalid_parameter_handler()
void __cdecl _invalid_parameter(wchar_t const *const expression, wchar_t const *const function_name, wchar_t const *const file_name, unsigned int const line_number, uintptr_t const reserved)
void __cdecl _invalid_parameter_internal(wchar_t const *const expression, wchar_t const *const function_name, wchar_t const *const file_name, unsigned int const line_number, uintptr_t const reserved, __crt_cached_ptd_host &ptd)
_invalid_parameter_handler __cdecl _set_thread_local_invalid_parameter_handler(_invalid_parameter_handler const new_handler)
void __cdecl _invalid_parameter_noinfo()
wchar_t const *const wchar_t const *const unsigned int const line_number
const WCHAR * word
Definition: lex.c:36
unsigned int uintptr_t
Definition: intrin.h:47
unsigned __int64 ULONG64
Definition: imports.h:198
static PVOID ptr
Definition: dispmode.c:27
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
#define CONTEXT_CONTROL
Definition: nt_native.h:1369
#define UNREACHABLE
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
Definition: ntbasedef.h:661
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:662
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#define STATUS_INVALID_CRUNTIME_PARAMETER
Definition: ntstatus.h:959
#define _exception_code()
Definition: pseh2_64.h:178
__asm__(".p2align 4, 0x90\n" ".seh_proc __seh2_global_filter_func\n" "__seh2_global_filter_func:\n" "\tsub %rbp, %rax\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tsub $32, %rsp\n" "\t.seh_stackalloc 32\n" "\t.seh_endprologue\n" "\tsub %rax, %rdx\n" "\tmov %rdx, %rbp\n" "\tjmp *%r8\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $32, %rsp\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
static calc_node_t * pop(void)
Definition: rpn_ieee.c:90
_invalid_parameter_handler _thread_local_iph
Definition: ffs.h:70
#define EXCEPTION_NONCONTINUABLE
Definition: stubs.h:23
ecx edi movl ebx edx edi decl ecx esi eax jecxz decl eax andl ebx
Definition: synth_sse3d.h:83
ecx edi movl ebx edx edi decl ecx esi eax jecxz decl eax andl eax esi movl edx movl TEMP incl eax andl eax ecx incl ebx testl eax jnz xchgl ecx incl TEMP esp ecx subl ebx pushl ecx ecx edx ecx shrl ecx mm0 mm4 mm0 mm4 mm1 mm5 mm1 mm5 mm2 mm6 mm2 mm6 mm3 mm7 mm3 mm7 paddd mm0 paddd mm4 paddd mm0 paddd mm4 paddd mm0 paddd mm4 movq mm1 movq mm5 psrlq mm1 psrlq mm5 paddd mm0 paddd mm4 psrad mm0 psrad mm4 packssdw mm0 packssdw mm4 mm1 punpckldq mm0 pand mm1 pand mm0 por mm1 movq edi esi edx edi decl ecx jnz popl ecx andl ecx jecxz mm0 mm0 mm1 mm1 mm2 mm2 mm3 mm3 paddd mm0 paddd mm0 paddd mm0 movq mm1 psrlq mm1 paddd mm0 psrad mm0 packssdw mm0 movd eax movw edi esi edx edi
Definition: synth_sse3d.h:185
ecx edi movl ebx edx edi decl ecx esi eax jecxz decl eax andl eax esi movl eax
Definition: synth_sse3d.h:85
ecx edi movl ebx edx edi decl ecx esi eax jecxz decl eax andl eax esi movl edx movl TEMP incl eax andl eax ecx incl ebx testl eax jnz xchgl ecx incl TEMP esi
Definition: synth_sse3d.h:103
ecx edi movl ebx edx edi decl ecx esi eax jecxz decl eax andl eax esi movl edx
Definition: synth_sse3d.h:87
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
PEXCEPTION_ROUTINE NTAPI RtlVirtualUnwind(_In_ ULONG HandlerType, _In_ ULONG64 ImageBase, _In_ ULONG64 ControlPc, _In_ PRUNTIME_FUNCTION FunctionEntry, _Inout_ PCONTEXT Context, _Outptr_ PVOID *HandlerData, _Out_ PULONG64 EstablisherFrame, _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
Definition: unwind.c:478
PRUNTIME_FUNCTION NTAPI RtlLookupFunctionEntry(IN DWORD64 ControlPc, OUT PDWORD64 ImageBase, OUT PUNWIND_HISTORY_TABLE HistoryTable)
Locates the RUNTIME_FUNCTION entry corresponding to a code address. https://learn....
Definition: unwind.c:124
BOOL WINAPI IsDebuggerPresent(void)
Definition: debugger.c:580
#define PF_FASTFAIL_AVAILABLE
Definition: ketypes.h:147
#define FAST_FAIL_INVALID_ARG