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 17 extern "C" 18 { 19 extern int static_init_counter; 20 21 static int static_init_counter_at_startup; 22 static int static_construct_counter_at_startup; 23 static int m_uninit_at_startup; 24 25 int static_construct_counter = 789; 26 } 27 28 static 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 44 static 45 VOID 46 TestInitStatic(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 59 static 60 VOID 61 TestDllStartup(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 109 struct shared_memory 110 { 111 int init_count; 112 int uninit_count; 113 }; 114 115 static HANDLE g_FileMapping = NULL; 116 static BOOL g_CreatedFileMapping = FALSE; 117 static shared_memory* g_Memory = NULL; 118 119 #define MAPPING_NAME L"crt_apitest_static_construct" 120 121 static 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 152 static 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 164 static 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 182 static 183 VOID 184 TestStaticDestruct(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 216 START_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 } 233