xref: /reactos/sdk/lib/ucrt/inc/internal_shared.h (revision 9c887efa)
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