OLD | NEW |
| (Empty) |
1 //========================================== | |
2 // LIBCTINY - Matt Pietrek 2001 | |
3 // MSDN Magazine, January 2001 | |
4 // ========================================== | |
5 | |
6 #include "libctiny.h" | |
7 #include <windows.h> | |
8 #include <malloc.h> | |
9 #include "initterm.h" | |
10 | |
11 #pragma data_seg(".CRT$XCA") | |
12 _PVFV __xc_a[] = { NULL }; | |
13 #pragma data_seg(".CRT$XCZ") | |
14 _PVFV __xc_z[] = { NULL }; | |
15 | |
16 /* | |
17 #pragma data_seg(".CRT$XIA") | |
18 _PVFV __xi_a[] = { NULL }; | |
19 #pragma data_seg(".CRT$XIZ") | |
20 _PVFV __xi_z[] = { NULL }; | |
21 | |
22 #pragma data_seg(".CRT$XTA") | |
23 _PVFV __xt_a[] = { NULL }; | |
24 #pragma data_seg(".CRT$XTZ") | |
25 _PVFV __xt_z[] = { NULL }; | |
26 | |
27 #pragma data_seg(".CRT$XPA") | |
28 _PVFV __xp_a[] = { NULL }; | |
29 #pragma data_seg(".CRT$XPZ") | |
30 _PVFV __xp_z[] = { NULL }; | |
31 */ | |
32 | |
33 #pragma data_seg() /* reset */ | |
34 | |
35 #pragma comment(linker, "/merge:.CRT=.data") | |
36 | |
37 typedef void (__cdecl *_PVFV)(); | |
38 | |
39 void __cdecl _initterm( | |
40 _PVFV * pfbegin, | |
41 _PVFV * pfend | |
42 ) { | |
43 // walk the table of function pointers from the bottom up, until | |
44 // the end is encountered. Do not skip the first entry. The initial | |
45 // value of pfbegin points to the first valid entry. Do not try to | |
46 // execute what pfend points to. Only entries before pfend are valid. | |
47 while (pfbegin < pfend) | |
48 { | |
49 // if current table entry is non-NULL, call thru it. | |
50 if (*pfbegin != NULL) | |
51 (**pfbegin)(); | |
52 ++pfbegin; | |
53 } | |
54 } | |
55 | |
56 static _PVFV * pf_atexitlist = 0; | |
57 static unsigned max_atexitlist_entries = 0; | |
58 static unsigned cur_atexitlist_entries = 0; | |
59 | |
60 void __cdecl _atexit_init() { | |
61 max_atexitlist_entries = 32; | |
62 pf_atexitlist = (_PVFV *)calloc( max_atexitlist_entries, | |
63 sizeof(_PVFV*) ); | |
64 } | |
65 | |
66 int __cdecl atexit(_PVFV func ) { | |
67 if (cur_atexitlist_entries < max_atexitlist_entries) | |
68 { | |
69 pf_atexitlist[cur_atexitlist_entries++] = func; | |
70 return 0; | |
71 } | |
72 | |
73 return -1; | |
74 } | |
75 | |
76 void __cdecl _DoExit() { | |
77 if (cur_atexitlist_entries) | |
78 { | |
79 _initterm( pf_atexitlist, | |
80 // Use ptr math to find the end of the array | |
81 pf_atexitlist + cur_atexitlist_entries ); | |
82 } | |
83 } | |
84 | |
85 // ----------------------------------------------------- | |
86 | |
87 /* | |
88 static HANDLE g_hProcessHeap = NULL; | |
89 | |
90 extern "C" _PVFV* __onexitbegin = NULL; | |
91 extern "C" _PVFV* __onexitend = NULL; | |
92 | |
93 extern "C" _PVFV __xi_a[], __xi_z[]; // C initializers | |
94 extern "C" _PVFV __xc_a[], __xc_z[]; // C++ initializers | |
95 extern "C" _PVFV __xp_a[], __xp_z[]; // C pre-terminators | |
96 extern "C" _PVFV __xt_a[], __xt_z[]; // C terminators | |
97 | |
98 // Critical section to protect initialization/exit code | |
99 static CRITICAL_SECTION g_csInit; | |
100 | |
101 extern "C" void DoInitialization() { | |
102 _PVFV* pf; | |
103 | |
104 // memset(&osi, 0, sizeof(OSVERSIONINFO)); | |
105 // osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); | |
106 // GetVersionEx(&osi); | |
107 // _osplatform = osi.dwPlatformId; | |
108 | |
109 InitializeCriticalSection( &g_csInit ); | |
110 | |
111 EnterCriticalSection( &g_csInit ); | |
112 | |
113 __try | |
114 { | |
115 g_hProcessHeap = GetProcessHeap(); | |
116 | |
117 // Call initialization routines (contructors for globals, etc.) | |
118 for (pf = __xi_a; pf < __xi_z; pf++) | |
119 { | |
120 if (*pf != NULL) | |
121 { | |
122 (**pf)(); | |
123 } | |
124 } | |
125 | |
126 for (pf = __xc_a; pf < __xc_z; pf++) | |
127 { | |
128 if (*pf != NULL) | |
129 { | |
130 (**pf)(); | |
131 } | |
132 } | |
133 } | |
134 __finally | |
135 { | |
136 LeaveCriticalSection(&g_csInit); | |
137 } | |
138 } | |
139 | |
140 extern "C" void DoCleanup() { | |
141 _PVFV* pf; | |
142 | |
143 EnterCriticalSection(&g_csInit); // Protect access to the atexit table | |
144 | |
145 __try | |
146 { | |
147 // Call routines registered with atexit() from most recently registered | |
148 // to least recently registered | |
149 if (__onexitbegin != NULL) | |
150 { | |
151 for (pf = __onexitend-1; pf >= __onexitbegin; pf--) | |
152 { | |
153 if (*pf != NULL) | |
154 (**pf)(); | |
155 } | |
156 } | |
157 | |
158 free(__onexitbegin); | |
159 __onexitbegin = NULL; | |
160 __onexitend = NULL; | |
161 | |
162 for (pf = __xp_a; pf < __xp_z; pf++) | |
163 { | |
164 if (*pf != NULL) | |
165 { | |
166 (**pf)(); | |
167 } | |
168 } | |
169 | |
170 for (pf = __xt_a; pf < __xt_z; pf++) | |
171 { | |
172 if (*pf != NULL) | |
173 { | |
174 (**pf)(); | |
175 } | |
176 } | |
177 } | |
178 __finally | |
179 { | |
180 LeaveCriticalSection(&g_csInit); | |
181 DeleteCriticalSection(&g_csInit); | |
182 } | |
183 } | |
184 | |
185 int __cdecl atexit(_PVFV pf) { | |
186 size_t nCurrentSize; | |
187 int nRet = 0; | |
188 | |
189 EnterCriticalSection(&g_csInit); | |
190 | |
191 __try | |
192 { | |
193 if (__onexitbegin == NULL) | |
194 { | |
195 __onexitbegin = (_PVFV*)malloc(16*sizeof(_PVFV)); | |
196 if (__onexitbegin == NULL) | |
197 { | |
198 LeaveCriticalSection(&g_csInit); | |
199 return(-1); | |
200 } | |
201 __onexitend = __onexitbegin; | |
202 } | |
203 | |
204 nCurrentSize = _msize(__onexitbegin); | |
205 if ((nCurrentSize+sizeof(_PVFV)) < ULONG(((const byte*)__onexitend- | |
206 (const byte*)__onexitbegin))) | |
207 { | |
208 _PVFV* pNew; | |
209 | |
210 pNew = (_PVFV*)realloc(__onexitbegin, 2*nCurrentSize); | |
211 if (pNew == NULL) | |
212 { | |
213 LeaveCriticalSection(&g_csInit); | |
214 return(-1); | |
215 } | |
216 } | |
217 | |
218 *__onexitend = pf; | |
219 __onexitend++; | |
220 } | |
221 __except (1) | |
222 { | |
223 nRet = -1; | |
224 } | |
225 | |
226 LeaveCriticalSection(&g_csInit); | |
227 | |
228 return(nRet); | |
229 } | |
230 */ | |
OLD | NEW |