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