Reactos
1/*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for static C++ object construction
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 * Mark Jansen
7 */
8
9#include <apitest.h>
10#include <strsafe.h>
11#include "dll_startup.h"
12
13#ifdef __GNUC__
14#pragma GCC diagnostic ignored "-Wuninitialized"
15#endif
16
17extern "C"
18{
19extern int static_init_counter;
20
21static int static_init_counter_at_startup;
22static int static_construct_counter_at_startup;
23static int m_uninit_at_startup;
24
25int static_construct_counter = 789;
26}
27
28static struct init_static
29{
30 int m_uninit;
31 int m_counter;
32
33 init_static() :
34 m_counter(2)
35 {
36 static_init_counter_at_startup = static_init_counter;
37 static_construct_counter_at_startup = static_construct_counter;
38 m_uninit_at_startup = m_uninit;
39 static_construct_counter++;
40 m_uninit++;
41 }
42} init_static;
43
44static
45VOID
46TestInitStatic(VOID)
47{
48 ok(static_init_counter_at_startup == 123, "static_init_counter at startup: %d\n", static_init_counter_at_startup);
49 ok(static_construct_counter_at_startup == 789, "static_construct_counter at startup: %d\n", static_construct_counter_at_startup);
50 ok(m_uninit_at_startup == 0, "init_static.m_uninit at startup: %d\n", m_uninit_at_startup);
51
52 ok(static_init_counter == 123, "static_init_counter: %d\n", static_init_counter);
53
54 ok(static_construct_counter == 790, "static_construct_counter: %d\n", static_construct_counter);
55 ok(init_static.m_counter == 2, "init_static.m_counter: %d\n", init_static.m_counter);
56 ok(init_static.m_uninit == 1, "init_static.m_uninit: %d\n", init_static.m_uninit);
57}
58
59static
60VOID
61TestDllStartup(VOID)
62{
63#if defined(TEST_MSVCRT)
64 const PCWSTR DllName = L"msvcrt_crt_dll_startup.dll";
65#elif defined(TEST_STATIC_CRT)
66 const PCWSTR DllName = L"static_crt_dll_startup.dll";
67#else
68#error This test only makes sense for static CRT and msvcrt.dll
69#endif
70 WCHAR DllPath[MAX_PATH];
71 GetModuleFileNameW(NULL, DllPath, _countof(DllPath));
72 wcsrchr(DllPath, L'\\')[1] = UNICODE_NULL;
73 StringCchCatW(DllPath, _countof(DllPath), DllName);
74
75 HMODULE hDll = LoadLibraryW(DllPath);
76 if (hDll == NULL)
77 {
78 skip("Helper dll not found\n");
79 return;
80 }
81 SET_COUNTER_VALUES_POINTER *pSetCounterValuesPointer = reinterpret_cast<SET_COUNTER_VALUES_POINTER*>(GetProcAddress(hDll, "SetCounterValuesPointer"));
82 if (pSetCounterValuesPointer == NULL)
83 {
84 skip("Helper function not found\n");
85 FreeLibrary(hDll);
86 return;
87 }
88 counter_values values;
89 pSetCounterValuesPointer(&values);
90 ok(values.m_uninit_at_startup == 0, "m_uninit_at_startup = %d\n", values.m_uninit_at_startup);
91 ok(values.m_uninit == 1, "m_uninit = %d\n", values.m_uninit);
92 ok(values.m_counter == 2, "m_counter = %d\n", values.m_counter);
93 ok(values.static_construct_counter_at_startup == 5656, "static_construct_counter_at_startup = %d\n", values.static_construct_counter_at_startup);
94 ok(values.static_construct_counter == 5657, "static_construct_counter = %d\n", values.static_construct_counter);
95 ok(values.dtor_counter_at_detach == 0, "dtor_counter_at_detach = %d\n", values.dtor_counter_at_detach);
96 ok(values.dtor_counter == 0, "dtor_counter = %d\n", values.dtor_counter);
97 values.dtor_counter_at_detach = 78789;
98 values.dtor_counter = 7878;
99 FreeLibrary(hDll);
100 ok(values.m_uninit_at_startup == 0, "m_uninit_at_startup = %d\n", values.m_uninit_at_startup);
101 ok(values.m_uninit == 1, "m_uninit = %d\n", values.m_uninit);
102 ok(values.m_counter == 2, "m_counter = %d\n", values.m_counter);
103 ok(values.static_construct_counter_at_startup == 5656, "static_construct_counter_at_startup = %d\n", values.static_construct_counter_at_startup);
104 ok(values.static_construct_counter == 5657, "static_construct_counter = %d\n", values.static_construct_counter);
105 ok(values.dtor_counter_at_detach == 7878, "dtor_counter_at_detach = %d\n", values.dtor_counter_at_detach);
106 ok(values.dtor_counter == 7879, "dtor_counter = %d\n", values.dtor_counter);
107}
108
109struct shared_memory
110{
111 int init_count;
112 int uninit_count;
113};
114
115static HANDLE g_FileMapping = NULL;
116static BOOL g_CreatedFileMapping = FALSE;
117static shared_memory* g_Memory = NULL;
118
119#define MAPPING_NAME L"crt_apitest_static_construct"
120
121static void map_memory()
122{
123 if (g_FileMapping)
124 return;
125
126 g_FileMapping = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, MAPPING_NAME);
127 if (g_FileMapping)
128 {
129 g_CreatedFileMapping = FALSE;
130 }
131 else
132 {
133 g_FileMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shared_memory), MAPPING_NAME);
134 g_CreatedFileMapping = TRUE;
135 }
136 if (g_FileMapping == NULL)
137 {
138 skip("Could not map shared memory\n");
139 return;
140 }
141 g_Memory = static_cast<shared_memory*>(MapViewOfFile(g_FileMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(shared_memory)));
142 if (g_Memory == NULL)
143 {
144 skip("Could not map view of shared memory\n");
145 CloseHandle(g_FileMapping);
146 g_FileMapping = NULL;
147 }
148 if (g_CreatedFileMapping)
149 ZeroMemory(g_Memory, sizeof(shared_memory));
150}
151
152static void unmap_memory()
153{
154 // we do not clean the mapping in the child, since we want to count all dtor's!
155 if (g_FileMapping && g_CreatedFileMapping)
156 {
157 UnmapViewOfFile(g_Memory);
158 CloseHandle(g_FileMapping);
159 g_Memory = NULL;
160 g_FileMapping = NULL;
161 }
162}
163
164static struct shared_mem_static
165{
166 shared_mem_static()
167 {
168 map_memory();
169 if (g_Memory)
170 g_Memory->init_count++;
171 }
172
173 ~shared_mem_static()
174 {
175 if (g_Memory)
176 g_Memory->uninit_count++;
177 unmap_memory();
178 }
179
180} shared_mem_static;
181
182static
183VOID
184TestStaticDestruct(VOID)
185{
186 ok(g_Memory != NULL, "Expected the mapping to be in place\n");
187 ok(g_CreatedFileMapping == TRUE, "Expected to create a new shared section!\n");
188 if (g_Memory == NULL)
189 {
190 skip("Can't proceed without file mapping\n");
191 return;
192 }
193 ok(g_Memory->init_count == 1, "Expected init_count to be 1, was: %d\n", g_Memory->init_count);
194 ok(g_Memory->uninit_count == 0, "Expected uninit_count to be 0, was: %d\n", g_Memory->uninit_count);
195
196 WCHAR path[MAX_PATH];
197 // we just need an extra argument to tell the test it's only running to increment the dtor count :)
198 GetModuleFileNameW(NULL, path, _countof(path));
199 WCHAR buf[MAX_PATH+40];
200 StringCchPrintfW(buf, _countof(buf), L"\"%ls\" static_construct dummy", path);
201
202 STARTUPINFOW si = { sizeof(si) };
203 PROCESS_INFORMATION pi;
204 BOOL created = CreateProcessW(NULL, buf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
205 ok(created, "Expected CreateProcess to succeed\n");
206 if (created)
207 {
208 winetest_wait_child_process(pi.hProcess);
209 CloseHandle(pi.hThread);
210 CloseHandle(pi.hProcess);
211 ok(g_Memory->init_count == 2, "Expected init_count to be 2, was: %d\n", g_Memory->init_count);
212 ok(g_Memory->uninit_count == 1, "Expected uninit_count to be 1, was: %d\n", g_Memory->uninit_count);
213 }
214}
215
216START_TEST(static_construct)
217{
218 char **argv;
219 int argc = winetest_get_mainargs(&argv);
220
221 if (argc >= 3)
222 {
223 // we are just here to increment the reference count in the shared section!
224 ok(g_Memory != NULL, "Expected the shared memory to be mapped!\n");
225 ok(g_CreatedFileMapping == FALSE, "Expected the shared memory to be created by my parent!\n");
226 return;
227 }
228
229 TestInitStatic();
230 TestDllStartup();
231 TestStaticDestruct();
232}