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 #define _VALIDATE_RETURN(expr, errorcode, retexpr) \
79 if (!(expr)) return (retexpr);
80
81 #define _VALIDATE_RETURN_VOID(expr, errorcode) \
82 if (!(expr)) return;
83
84 #define _VALIDATE_RETURN_NOERRNO(expr, retexpr) \
85 if (!(expr)) return (retexpr);
86
87 #define _VALIDATE_RETURN_ERRCODE(expr, errorcode) \
88 if (!(expr)) return (errorcode);
89
90 #define _VALIDATE_CLEAR_OSSERR_RETURN(expr, errorcode, retexpr) \
91 if (!(expr)) return (retexpr);
92
93 #define _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE(expr, errorcode) \
94 if (!(expr)) return (errorcode);
95
96 #define _VALIDATE_RETURN_NOEXC(expr, errorcode, retexpr) \
97 if (!(expr)) return (retexpr);
98
99 #define _VALIDATE_RETURN_ERRCODE_NOEXC(expr, errorcode) \
100 if (!(expr)) return (errorcode);
101
102 #define _malloc_crt malloc
103 #define _free_crt free
104 #define _calloc_crt calloc
105 #define _recalloc_crt _recalloc
106 #define _malloca_crt _malloca
107 #define _freea_crt _freea
108
109 #ifdef __cplusplus
110 } // extern "C"
111
112 template<typename T>
113 __forceinline
__crt_fast_encode_pointer(T Ptr)114 T __crt_fast_encode_pointer(T Ptr)
115 {
116 // FIXME: use cookie
117 return Ptr;
118 }
119
120 template<typename T>
121 __forceinline
__crt_fast_decode_pointer(T Ptr)122 T __crt_fast_decode_pointer(T Ptr)
123 {
124 // FIXME: use cookie
125 return Ptr;
126 }
127
128 template<typename T>
__crt_interlocked_read(const T volatile * ptr)129 T __crt_interlocked_read(const T volatile* ptr)
130 {
131 return *ptr;
132 }
133
134 template<typename T>
__crt_interlocked_read_pointer(const T volatile * ptr)135 T __crt_interlocked_read_pointer(const T volatile* ptr)
136 {
137 return *ptr;
138 }
139
140 template<typename T>
__crt_interlocked_exchange_pointer(T * ptr,void * value)141 T __crt_interlocked_exchange_pointer(T *ptr, void* value)
142 {
143 return (T)_InterlockedExchangePointer((void* volatile*)ptr, value);
144 }
145
146 template<typename T>
147 struct __crt_seh_guarded_call
148 {
149 template<typename Init, typename Action, typename Cleanup>
operator__crt_seh_guarded_call150 T operator()(Init init, Action action, Cleanup cleanup)
151 {
152 init();
153 __try
154 {
155 return action();
156 }
157 __finally
158 {
159 cleanup();
160 }
161 __endtry
162 }
163 };
164
165 template<typename FuncPtr>
__crt_get_proc_address(HMODULE module,const char * name)166 FuncPtr __crt_get_proc_address(HMODULE module, const char* name)
167 {
168 return (FuncPtr)GetProcAddress(module, name);
169 }
170
171 template<typename Action, typename Cleanup>
__crt_call_and_cleanup(Action action,Cleanup cleanup)172 void __crt_call_and_cleanup(Action action, Cleanup cleanup)
173 {
174 action();
175 cleanup();
176 }
177
178 struct __crt_malloc_free_policy
179 {
180 template<typename T>
operator__crt_malloc_free_policy181 void operator()(T* const ptr) throw()
182 {
183 _free_crt((void*)ptr);
184 }
185 };
186
187 struct __crt_public_free_policy
188 {
189 template<typename T>
operator__crt_public_free_policy190 void operator()(T* const ptr) throw()
191 {
192 _free_crt((void*)ptr);
193 }
194 };
195
196 struct __crt_malloca_free_policy
197 {
operator__crt_malloca_free_policy198 void operator()(void* const ptr) throw()
199 {
200 _freea_crt(ptr);
201 }
202 };
203
204 template <typename T, typename FreePolicy = __crt_malloc_free_policy>
205 class __crt_unique_heap_ptr
206 {
207 T* _ptr;
208 public:
__crt_unique_heap_ptr()209 __crt_unique_heap_ptr() : _ptr(nullptr) {}
__crt_unique_heap_ptr(T * ptr)210 __crt_unique_heap_ptr(T* ptr) : _ptr(ptr) {}
__crt_unique_heap_ptr(__crt_unique_heap_ptr && from)211 __crt_unique_heap_ptr(__crt_unique_heap_ptr&& from) : _ptr(from._ptr) { from._ptr = nullptr; }
~__crt_unique_heap_ptr()212 ~__crt_unique_heap_ptr() { FreePolicy()(_ptr); }
attach(T * ptr)213 void attach(T* ptr) { FreePolicy()(_ptr); _ptr = ptr; }
detach()214 T* detach() { T* ptr = _ptr; _ptr = nullptr; return ptr; }
215 operator bool() const { return _ptr != nullptr; }
get()216 T* get() const { return _ptr; }
get_address_of()217 T** get_address_of() { return &_ptr; }
218
219 // Move assignment
220 __crt_unique_heap_ptr& operator=(__crt_unique_heap_ptr&& from)
221 {
222 FreePolicy()(_ptr);
223 _ptr = from._ptr;
224 from._ptr = nullptr;
225 return *this;
226 }
227 };
228
229 template <typename T>
230 using __crt_scoped_stack_ptr = __crt_unique_heap_ptr<T, __crt_malloca_free_policy>;
231
232 #define _malloc_crt_t(t, n) (__crt_unique_heap_ptr<t>(static_cast<t*>(_malloc_crt((n) * sizeof(t)))))
233 #define _calloc_crt_t(t, n) (__crt_unique_heap_ptr<t>(static_cast<t*>(_calloc_crt((n), sizeof(t)))))
234 #define _recalloc_crt_t(t, p, n) (__crt_unique_heap_ptr<t>(static_cast<t*>(_recalloc_crt(p, (n), sizeof(t)))))
235 #define _malloca_crt_t(t, n) (__crt_scoped_stack_ptr<t>(static_cast<t*>(_malloca_crt((n) * sizeof(t)))))
236
237 #endif // __cplusplus
238