HyperPlatform Programmer's Reference
global_object.cpp
Go to the documentation of this file.
1 // Copyright (c) 2015-2017, Satoshi Tanda. All rights reserved.
2 // Use of this source code is governed by a MIT-style license that can be
3 // found in the LICENSE file.
4 
7 
8 #include "global_object.h"
9 
10 // .CRT section is required to invoke ctors and dtors. This pragma embeds a .CRT
11 // section into the .rdata section. Or else, a LNK warning would be raised.
12 #pragma comment(linker, "/merge:.CRT=.rdata")
13 
14 // Create two sections that are used by MSVC to place an array of ctors at a
15 // compile time. It is important to be ordered in alphabetical order.
16 #pragma section(".CRT$XCA", read)
17 #pragma section(".CRT$XCZ", read)
18 
19 extern "C" {
21 //
22 // macro utilities
23 //
24 
26 //
27 // constants and macros
28 //
29 
31 static const ULONG kGlobalObjectpPoolTag = 'jbOG';
32 
34 //
35 // types
36 //
37 
38 using Destructor = void(__cdecl *)();
39 
42  SINGLE_LIST_ENTRY list_entry;
43 };
44 
46 //
47 // prototypes
48 //
49 
50 #if defined(ALLOC_PRAGMA)
51 #pragma alloc_text(INIT, GlobalObjectInitialization)
52 #pragma alloc_text(INIT, atexit)
53 #pragma alloc_text(PAGE, GlobalObjectTermination)
54 #endif
55 
57 //
58 // variables
59 //
60 
61 // Place markers pointing to the beginning and end of the ctors arrays embedded
62 // by MSVC.
63 __declspec(allocate(".CRT$XCA")) static Destructor g_gop_ctors_begin[1] = {};
64 __declspec(allocate(".CRT$XCZ")) static Destructor g_gop_ctors_end[1] = {};
65 
66 // Stores pointers to dtors to be called at the exit.
67 static SINGLE_LIST_ENTRY g_gop_dtors_list_head = {};
68 
70 //
71 // implementations
72 //
73 
74 // Calls all constructors and register all destructor
75 _Use_decl_annotations_ NTSTATUS GlobalObjectInitialization() {
76  PAGED_CODE();
77 
78  // Call all constructors
79  for (auto ctor = g_gop_ctors_begin + 1; ctor < g_gop_ctors_end; ++ctor) {
80  (*ctor)();
81  }
82  return STATUS_SUCCESS;
83 }
84 
85 // Calls all registered destructors
86 _Use_decl_annotations_ void GlobalObjectTermination() {
87  PAGED_CODE();
88 
89  auto entry = PopEntryList(&g_gop_dtors_list_head);
90  while (entry) {
91  const auto element = CONTAINING_RECORD(entry, DestructorEntry, list_entry);
92  element->dtor();
93  ExFreePoolWithTag(element, kGlobalObjectpPoolTag);
94  entry = PopEntryList(&g_gop_dtors_list_head);
95  }
96 }
97 
98 // Registers destructor; this is called through a call to constructor
99 _IRQL_requires_max_(PASSIVE_LEVEL) int __cdecl atexit(_In_ Destructor dtor) {
100  PAGED_CODE();
101 
102  const auto element =
103  reinterpret_cast<DestructorEntry *>(ExAllocatePoolWithTag(
104  PagedPool, sizeof(DestructorEntry), kGlobalObjectpPoolTag));
105  if (!element) {
106  return 1;
107  }
108  element->dtor = dtor;
109  PushEntryList(&g_gop_dtors_list_head, &element->list_entry);
110  return 0;
111 }
112 
113 } // extern "C"
SINGLE_LIST_ENTRY list_entry
Destructor dtor
Declares interfaces to global object functions.
int __cdecl atexit(_In_ Destructor dtor)
void(__cdecl *)() Destructor
__declspec(allocate(".CRT$XCA")) static Destructor g_gop_ctors_begin[1]
static SINGLE_LIST_ENTRY g_gop_dtors_list_head
NTSTATUS GlobalObjectInitialization()
Calls all constructors and register all destructor.
void GlobalObjectTermination()
Calls all destructors.
static const ULONG kGlobalObjectpPoolTag
A pool tag for this module.