1 //
2 // internal_shared.h
3 //
4 // Copyright (c) 2024 Timo Kreuzer
5 //
6 // Header for definitions shared between vcruntime and UCRT.
7 //
8 // SPDX-License-Identifier: MIT
9 //
10
11 #pragma once
12
13 #include <suppress.h>
14 #include <intrin.h>
15 #include <corecrt_startup.h>
16 #include <crtdbg.h>
17 #include <windows.h> // for HMODULE
18 #include <malloc.h>
19
20 #ifdef __cplusplus
21 extern "C" {
22 #endif // __cplusplus
23
24 #if defined(_MSC_VER)
25 #define _CRTALLOC(x) __declspec(allocate(x))
26 #else
27 #define _CRTALLOC(x) __attribute__((section(x)))
28 #endif
29
30 #ifdef _MSC_VER
31 #pragma section(".CRT$XIC", long, read)
32 #pragma section(".CRT$XPX", long, read)
33 #pragma section(".CRT$XPXA", long, read)
34
35 #pragma section(".CRT$XIA", long, read)
36 #pragma section(".CRT$XIZ", long, read)
37 #pragma section(".CRT$XCA", long, read)
38 #pragma section(".CRT$XCZ", long, read)
39 #pragma section(".CRT$XPA", long, read)
40 #pragma section(".CRT$XPZ", long, read)
41 #pragma section(".CRT$XTA", long, read)
42 #pragma section(".CRT$XTZ", long, read)
43 #endif
44
45 extern _PIFV __xi_a[];
46 extern _PIFV __xi_z[];
47 extern _PVFV __xc_a[];
48 extern _PVFV __xc_z[];
49 extern _PVFV __xp_a[];
50 extern _PVFV __xp_z[];
51 extern _PVFV __xt_a[];
52 extern _PVFV __xt_z[];
53
54 extern char __ImageBase;
55
56 #define CRT_WARNING_DISABLE_PUSH(wn, message) \
57 __pragma(warning(push)) \
58 __pragma(warning(disable: wn))
59
60 #define CRT_WARNING_POP \
61 __pragma(warning(pop))
62
63 #define _BEGIN_SECURE_CRT_DEPRECATION_DISABLE \
64 __pragma(warning(push)) \
65 __pragma(warning(disable: 4996))
66
67 #define _END_SECURE_CRT_DEPRECATION_DISABLE \
68 __pragma(warning(pop))
69
70 #define _CRT_DEBUGGER_IGNORE -1
71 #define _CRT_DEBUGGER_GSFAILURE 1
72 #define _CRT_DEBUGGER_INVALIDPARAMETER 2
73 #define _CRT_DEBUGGER_ABORT 3
74
75 #define _CRT_DEBUGGER_HOOK(x)
76
77 #define _CRT_SECURITYCRITICAL_ATTRIBUTE
78 #define _CRT_SECURITYSAFECRITICAL_ATTRIBUTE
79
80 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81 //
82 // Parameter validation macros
83 // Partly duplicated in corecrt_internal_strtox.h
84 //
85 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86
87 #ifdef _DEBUG
88 #define _INVALID_PARAMETER(expr) _invalid_parameter(expr, __FUNCTIONW__, __FILEW__, __LINE__, 0)
89 #else
90 #define _INVALID_PARAMETER(expr) _invalid_parameter_noinfo()
91 #endif
92
93 #define _VALIDATE_RETURN(expr, errorcode, retexpr) \
94 { \
95 int _Expr_val = !!(expr); \
96 _ASSERT_EXPR((_Expr_val), _CRT_WIDE(#expr)); \
97 if (!(_Expr_val)) \
98 { \
99 *_errno() = (errorcode); \
100 _INVALID_PARAMETER(_CRT_WIDE(#expr)); \
101 return (retexpr); \
102 } \
103 }
104
105 #define _VALIDATE_RETURN_VOID(expr, errorcode) \
106 { \
107 int _Expr_val = !!(expr); \
108 _ASSERT_EXPR((_Expr_val), _CRT_WIDE(#expr)); \
109 if (!(_Expr_val)) \
110 { \
111 *_errno() = (errorcode); \
112 _INVALID_PARAMETER(_CRT_WIDE(#expr)); \
113 return; \
114 } \
115 }
116
117 #define _VALIDATE_RETURN_NOERRNO(expr, retexpr) \
118 { \
119 int _Expr_val = !!(expr); \
120 _ASSERT_EXPR((_Expr_val), _CRT_WIDE(#expr)); \
121 if (!(_Expr_val)) \
122 { \
123 _INVALID_PARAMETER(_CRT_WIDE(#expr)); \
124 return (retexpr); \
125 } \
126 }
127
128 #define _VALIDATE_RETURN_ERRCODE(expr, errorcode) \
129 _VALIDATE_RETURN(expr, errorcode, errorcode)
130
131 #define _VALIDATE_CLEAR_OSSERR_RETURN(expr, errorcode, retexpr) \
132 { \
133 int _Expr_val = !!(expr); \
134 _ASSERT_EXPR((_Expr_val), _CRT_WIDE(#expr)); \
135 if (!(_Expr_val)) \
136 { \
137 *__doserrno() = 0L; \
138 *_errno() = errorcode; \
139 _INVALID_PARAMETER(_CRT_WIDE(#expr) ); \
140 return (retexpr); \
141 } \
142 }
143
144 #define _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE(expr, errorcode) \
145 _VALIDATE_CLEAR_OSSERR_RETURN(expr, errorcode, errorcode)
146
147 #define _VALIDATE_RETURN_NOEXC(expr, errorcode, retexpr) \
148 { \
149 if (!(expr)) \
150 { \
151 *_errno() = errorcode; \
152 return (retexpr); \
153 } \
154 }
155
156 #define _VALIDATE_RETURN_ERRCODE_NOEXC(expr, errorcode) \
157 _VALIDATE_RETURN_NOEXC(expr, errorcode, errorcode)
158
159 #define _malloc_crt malloc
160 #define _free_crt free
161 #define _calloc_crt calloc
162 #define _recalloc_crt _recalloc
163 #define _malloca_crt _malloca
164 #define _freea_crt _freea
165
166 #ifdef __cplusplus
167 } // extern "C"
168
169 template<typename T>
170 __forceinline
__crt_fast_encode_pointer(T ptr)171 T __crt_fast_encode_pointer(T ptr)
172 {
173 union { T Ptr; uintptr_t Uint; } u = { ptr };
174 u.Uint ^= __security_cookie;
175 return u.Ptr;
176 }
177
178 template<typename T>
179 __forceinline
__crt_fast_decode_pointer(T ptr)180 T __crt_fast_decode_pointer(T ptr)
181 {
182 union { T Ptr; uintptr_t Uint; } u = { ptr };
183 u.Uint ^= __security_cookie;
184 return u.Ptr;
185 }
186
187 template<typename T>
__crt_interlocked_read(const T volatile * ptr)188 T __crt_interlocked_read(const T volatile* ptr)
189 {
190 return *ptr;
191 }
192
193 template<typename T>
__crt_interlocked_read_pointer(const T volatile * ptr)194 T __crt_interlocked_read_pointer(const T volatile* ptr)
195 {
196 return *ptr;
197 }
198
199 template<typename T>
__crt_interlocked_exchange_pointer(T * ptr,void * value)200 T __crt_interlocked_exchange_pointer(T *ptr, void* value)
201 {
202 return (T)_InterlockedExchangePointer((void* volatile*)ptr, value);
203 }
204
205 template<typename T>
206 struct __crt_seh_guarded_call
207 {
208 template<typename Init, typename Action, typename Cleanup>
operator__crt_seh_guarded_call209 T operator()(Init init, Action action, Cleanup cleanup)
210 {
211 T result;
212 init();
213 __try
214 {
215 result = action();
216 }
217 __finally
218 {
219 cleanup();
220 }
221 __endtry
222 return result;
223 }
224 };
225
226 template<>
227 struct __crt_seh_guarded_call<void>
228 {
229 template<typename Init, typename Action, typename Cleanup>
230 void operator()(Init init, Action action, Cleanup cleanup)
231 {
232 init();
233 __try
234 {
235 action();
236 }
237 __finally
238 {
239 cleanup();
240 }
241 __endtry
242 }
243 };
244
245 template<typename FuncPtr>
246 FuncPtr __crt_get_proc_address(HMODULE module, const char* name)
247 {
248 return (FuncPtr)GetProcAddress(module, name);
249 }
250
251 template<typename Action, typename Cleanup>
252 void __crt_call_and_cleanup(Action action, Cleanup cleanup)
253 {
254 action();
255 cleanup();
256 }
257
258 struct __crt_malloc_free_policy
259 {
260 template<typename T>
261 void operator()(T* const ptr) throw()
262 {
263 _free_crt((void*)ptr);
264 }
265 };
266
267 struct __crt_public_free_policy
268 {
269 template<typename T>
270 void operator()(T* const ptr) throw()
271 {
272 _free_crt((void*)ptr);
273 }
274 };
275
276 struct __crt_malloca_free_policy
277 {
278 void operator()(void* const ptr) throw()
279 {
280 _freea_crt(ptr);
281 }
282 };
283
284 template <typename T, typename FreePolicy = __crt_malloc_free_policy>
285 class __crt_unique_heap_ptr
286 {
287 T* _ptr;
288 public:
289 __crt_unique_heap_ptr() : _ptr(nullptr) {}
290 __crt_unique_heap_ptr(T* ptr) : _ptr(ptr) {}
291 __crt_unique_heap_ptr(__crt_unique_heap_ptr&& from) : _ptr(from._ptr) { from._ptr = nullptr; }
292 ~__crt_unique_heap_ptr() { FreePolicy()(_ptr); }
293 void attach(T* ptr) { FreePolicy()(_ptr); _ptr = ptr; }
294 T* detach() { T* ptr = _ptr; _ptr = nullptr; return ptr; }
295 operator bool() const { return _ptr != nullptr; }
296 T* get() const { return _ptr; }
297 T** get_address_of() { return &_ptr; }
298
299 // Move assignment
300 __crt_unique_heap_ptr& operator=(__crt_unique_heap_ptr&& from)
301 {
302 FreePolicy()(_ptr);
303 _ptr = from._ptr;
304 from._ptr = nullptr;
305 return *this;
306 }
307 };
308
309 template <typename T>
310 using __crt_scoped_stack_ptr = __crt_unique_heap_ptr<T, __crt_malloca_free_policy>;
311
312 #define _malloc_crt_t(t, n) (__crt_unique_heap_ptr<t>(static_cast<t*>(_malloc_crt((n) * sizeof(t)))))
313 #define _calloc_crt_t(t, n) (__crt_unique_heap_ptr<t>(static_cast<t*>(_calloc_crt((n), sizeof(t)))))
314 #define _recalloc_crt_t(t, p, n) (__crt_unique_heap_ptr<t>(static_cast<t*>(_recalloc_crt(p, (n), sizeof(t)))))
315 #define _malloca_crt_t(t, n) (__crt_scoped_stack_ptr<t>(static_cast<t*>(_malloca_crt((n) * sizeof(t)))))
316
317 #endif // __cplusplus
318