xref: /reactos/sdk/lib/ucrt/heap/new_handler.cpp (revision a6a07059)
1 //
2 // new_handler.cpp
3 //
4 //      Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // Implementation of the new handler and related functions..
7 //
8 #include <corecrt_internal.h>
9 #include <new.h>
10 
11 // The global new handler.  This pointer should only be accessed via the
12 // functions defined in this source file.
13 static __crt_state_management::dual_state_global<_PNH> __acrt_new_handler;
14 
15 
16 
17 // Initializes the new handler to the encoded nullptr value.
18 extern "C" void __cdecl __acrt_initialize_new_handler(void* const encoded_null)
19 {
20     __acrt_new_handler.initialize(reinterpret_cast<_PNH>(encoded_null));
21 }
22 
23 // Sets the new handler to the new new handler and returns the old handler.
24 _PNH __cdecl _set_new_handler(_PNH new_handler)
25 {
26     _PNH result = nullptr;
27 
28     __acrt_lock(__acrt_heap_lock);
29     __try
30     {
31         result = __crt_fast_decode_pointer(__acrt_new_handler.value());
32         __acrt_new_handler.value() = __crt_fast_encode_pointer(new_handler);
33     }
34     __finally
35     {
36         __acrt_unlock(__acrt_heap_lock);
37     }
38     __endtry
39 
40     return result;
41 }
42 
43 // Sets the new handler to nullptr and returns the old handler.  The argument
44 // must be zero.  This overload is used to enable a caller to pass nullptr.
45 _PNH __cdecl _set_new_handler(int const new_handler)
46 {
47     // This is referenced only in the Debug CRT build
48     UNREFERENCED_PARAMETER(new_handler);
49 
50     _ASSERTE(new_handler == 0);
51 
52     return _set_new_handler(__crt_fast_encode_pointer(nullptr));
53 }
54 
55 // Gets the current new handler.
56 _PNH __cdecl _query_new_handler()
57 {
58     _PNH result = nullptr;
59 
60     __acrt_lock(__acrt_heap_lock);
61     __try
62     {
63         result = __crt_fast_decode_pointer(__acrt_new_handler.value());
64     }
65     __finally
66     {
67         __acrt_unlock(__acrt_heap_lock);
68     }
69     __endtry
70 
71     return result;
72 }
73 
74 // Calls the currently registered new handler with the provided size.  If the
75 // new handler succeeds, this function returns 1.  This function returns 0 on
76 // failure.  The new handler may throw std::bad_alloc.
77 extern "C" int __cdecl _callnewh(size_t const size)
78 {
79     _PNH const pnh = _query_new_handler();
80 
81     if (pnh == nullptr || (*pnh)(size) == 0)
82         return 0;
83 
84     return 1;
85 }
86