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