1 /* 2 * PROJECT: ReactOS API Tests 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Test for exception behavior in dll notifications 5 * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8 #include "precomp.h" 9 10 WCHAR dllpath[MAX_PATH]; 11 12 LONG g_TlsCalled = 0; 13 LONG g_DllMainCalled = 0; 14 15 LONG g_TlsExcept = 0xffffff; 16 LONG g_DllMainExcept = 0xffffff; 17 18 ULONG g_BaseHandlers = 0; 19 20 DWORD g_dwWinVer = 0; 21 22 ULONG CountHandlers(VOID) 23 { 24 EXCEPTION_REGISTRATION_RECORD* exc; 25 ULONG Count = 0; 26 27 exc = NtCurrentTeb()->NtTib.ExceptionList; 28 29 while (exc && exc != (EXCEPTION_REGISTRATION_RECORD*)~0) 30 { 31 Count++; 32 exc = exc->Next; 33 } 34 35 return Count; 36 } 37 38 int g_TLS_ATTACH = 4; 39 int g_TLS_DETACH = 3; 40 41 VOID WINAPI notify_TlsCallback(IN HINSTANCE hDllHandle, IN DWORD dwReason, IN LPVOID lpvReserved) 42 { 43 ULONG handlers = CountHandlers() - g_BaseHandlers; 44 45 InterlockedIncrement(&g_TlsCalled); 46 if (dwReason == DLL_PROCESS_ATTACH) 47 { 48 ok_int(handlers, g_TLS_ATTACH); 49 } 50 else 51 { 52 ok_int(handlers, g_TLS_DETACH); 53 } 54 55 if (InterlockedCompareExchange(&g_TlsExcept, 0xffffff, dwReason) == dwReason) 56 { 57 RaiseException(EXCEPTION_DATATYPE_MISALIGNMENT, EXCEPTION_NONCONTINUABLE, 0, NULL); 58 } 59 } 60 61 int g_DLL_ATTACH = 3; 62 int g_DLL_DETACH = 2; 63 64 BOOL WINAPI notify_DllMain(IN HINSTANCE hDllHandle, IN DWORD dwReason, IN LPVOID lpvReserved) 65 { 66 ULONG handlers = CountHandlers() - g_BaseHandlers; 67 68 InterlockedIncrement(&g_DllMainCalled); 69 if (dwReason == DLL_PROCESS_ATTACH) 70 { 71 ok_int(handlers, g_DLL_ATTACH); 72 } 73 else 74 { 75 ok_int(handlers, g_DLL_DETACH); // For failures, see https://jira.reactos.org/browse/CORE-14857 76 } 77 78 if (InterlockedCompareExchange(&g_DllMainExcept, 0xffffff, dwReason) == dwReason) 79 { 80 RaiseException(EXCEPTION_DATATYPE_MISALIGNMENT, EXCEPTION_NONCONTINUABLE, 0, NULL); 81 } 82 return TRUE; 83 } 84 85 86 static void execute_test(void) 87 { 88 HMODULE mod; 89 DWORD dwErr; 90 _SEH2_TRY 91 { 92 g_TlsExcept = 0xffffff; 93 g_DllMainExcept = 0xffffff; 94 g_DllMainCalled = 0; 95 g_TlsCalled = 0; 96 g_BaseHandlers = CountHandlers(); 97 mod = LoadLibraryW(dllpath); 98 dwErr = GetLastError(); 99 ok(GetModuleHandleW(dllpath) != NULL, "Unable to load module (0x%lx)\n", dwErr); 100 ok_hex(g_DllMainCalled, 1); 101 if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled) 102 ok_hex(g_TlsCalled, 1); 103 if (g_TlsCalled == 0) 104 trace("Tls not active\n"); 105 g_BaseHandlers = CountHandlers(); 106 FreeLibrary(mod); 107 dwErr = GetLastError(); 108 ok(GetModuleHandleW(dllpath) == NULL, "Unable to unload module (0x%lx)\n", dwErr); 109 ok_hex(g_DllMainCalled, 2); 110 if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled) 111 ok_hex(g_TlsCalled, 2); 112 } 113 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 114 { 115 ok(0, "Unable to load it normally\n"); 116 } 117 _SEH2_END; 118 119 120 _SEH2_TRY 121 { 122 g_TlsExcept = 0xffffff; 123 g_DllMainExcept = DLL_PROCESS_ATTACH; 124 g_DllMainCalled = 0; 125 g_TlsCalled = 0; 126 g_BaseHandlers = CountHandlers(); 127 mod = LoadLibraryW(dllpath); 128 dwErr = GetLastError(); 129 ok(GetModuleHandleW(dllpath) == NULL, "Module loaded (0x%lx)\n", dwErr); 130 if (g_dwWinVer <= _WIN32_WINNT_WIN7) 131 ok_hex(dwErr, ERROR_NOACCESS); 132 else 133 ok_hex(dwErr, ERROR_DLL_INIT_FAILED); 134 ok_hex(g_DllMainCalled, 1); 135 if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled) 136 ok_hex(g_TlsCalled, 1); 137 if (mod) 138 { 139 FreeLibrary(mod); 140 dwErr = GetLastError(); 141 ok(GetModuleHandleW(dllpath) == NULL, "Unable to unload module (0x%lx)\n", dwErr); 142 ok_hex(g_DllMainCalled, 1); 143 if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled) 144 ok_hex(g_TlsCalled, 1); 145 } 146 } 147 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 148 { 149 ok(0, "Unable to execute test\n"); 150 } 151 _SEH2_END; 152 153 _SEH2_TRY 154 { 155 g_TlsExcept = 0xffffff; 156 g_DllMainExcept = DLL_PROCESS_DETACH; 157 g_DllMainCalled = 0; 158 g_TlsCalled = 0; 159 g_BaseHandlers = CountHandlers(); 160 mod = LoadLibraryW(dllpath); 161 dwErr = GetLastError(); 162 ok(GetModuleHandleW(dllpath) != NULL, "Unable to load module (0x%lx)\n", dwErr); 163 ok_hex(g_DllMainCalled, 1); 164 if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled) 165 ok_hex(g_TlsCalled, 1); 166 g_BaseHandlers = CountHandlers(); 167 FreeLibrary(mod); 168 dwErr = GetLastError(); 169 ok(GetModuleHandleW(dllpath) == NULL, "Unable to unload module (0x%lx)\n", dwErr); 170 ok_hex(g_DllMainCalled, 2); 171 if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled) 172 ok_hex(g_TlsCalled, 2); 173 } 174 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 175 { 176 ok(0, "Unable to execute test\n"); 177 } 178 _SEH2_END; 179 180 _SEH2_TRY 181 { 182 g_TlsExcept = DLL_PROCESS_ATTACH; 183 g_DllMainExcept = 0xffffff; 184 g_DllMainCalled = 0; 185 g_TlsCalled = 0; 186 g_BaseHandlers = CountHandlers(); 187 mod = LoadLibraryW(dllpath); 188 dwErr = GetLastError(); 189 ok(GetModuleHandleW(dllpath) != NULL, "Unable to load module (0x%lx)\n", dwErr); 190 ok_hex(g_DllMainCalled, 1); 191 if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled) 192 ok_hex(g_TlsCalled, 1); 193 g_BaseHandlers = CountHandlers(); 194 FreeLibrary(mod); 195 dwErr = GetLastError(); 196 ok(GetModuleHandleW(dllpath) == NULL, "Unable to unload module (0x%lx)\n", dwErr); 197 ok_hex(g_DllMainCalled, 2); 198 if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled) 199 ok_hex(g_TlsCalled, 2); 200 } 201 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 202 { 203 ok(0, "Unable to execute test\n"); 204 } 205 _SEH2_END; 206 207 _SEH2_TRY 208 { 209 g_TlsExcept = DLL_PROCESS_DETACH; 210 g_DllMainExcept = 0xffffff; 211 g_DllMainCalled = 0; 212 g_TlsCalled = 0; 213 g_BaseHandlers = CountHandlers(); 214 mod = LoadLibraryW(dllpath); 215 dwErr = GetLastError(); 216 ok(GetModuleHandleW(dllpath) != NULL, "Unable to load module (0x%lx)\n", dwErr); 217 ok_hex(g_DllMainCalled, 1); 218 if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled) 219 ok_hex(g_TlsCalled, 1); 220 g_BaseHandlers = CountHandlers(); 221 FreeLibrary(mod); 222 dwErr = GetLastError(); 223 ok(GetModuleHandleW(dllpath) == NULL, "Unable to unload module (0x%lx)\n", dwErr); 224 ok_hex(g_DllMainCalled, 2); 225 if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled) 226 ok_hex(g_TlsCalled, 2); 227 } 228 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 229 { 230 ok(0, "Unable to execute test\n"); 231 } 232 _SEH2_END; 233 234 } 235 236 237 BOOL extract_resource(const WCHAR* Filename, LPCWSTR ResourceName) 238 { 239 BOOL Success; 240 DWORD dwWritten, Size; 241 HGLOBAL hGlobal; 242 LPVOID pData; 243 HANDLE Handle; 244 HRSRC hRsrc = FindResourceW(GetModuleHandleW(NULL), ResourceName, (LPCWSTR)10); 245 ok(!!hRsrc, "Unable to find %s\n", wine_dbgstr_w(ResourceName)); 246 if (!hRsrc) 247 return FALSE; 248 249 hGlobal = LoadResource(GetModuleHandleW(NULL), hRsrc); 250 Size = SizeofResource(GetModuleHandleW(NULL), hRsrc); 251 pData = LockResource(hGlobal); 252 253 ok(Size && !!pData, "Unable to load %s\n", wine_dbgstr_w(ResourceName)); 254 if (!Size || !pData) 255 return FALSE; 256 257 Handle = CreateFileW(Filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 258 259 if (Handle == INVALID_HANDLE_VALUE) 260 { 261 skip("Failed to create temp file %ls, error %lu\n", Filename, GetLastError()); 262 return FALSE; 263 } 264 Success = WriteFile(Handle, pData, Size, &dwWritten, NULL); 265 ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError()); 266 ok(dwWritten == Size, "WriteFile wrote %lu bytes instead of %lu\n", dwWritten, Size); 267 CloseHandle(Handle); 268 Success = Success && (dwWritten == Size); 269 270 UnlockResource(pData); 271 return Success; 272 } 273 274 275 START_TEST(load_notifications) 276 { 277 WCHAR workdir[MAX_PATH]; 278 BOOL ret; 279 UINT Length; 280 PPEB Peb = NtCurrentPeb(); 281 282 g_dwWinVer = (DWORD)(Peb->OSMajorVersion << 8) | Peb->OSMinorVersion; 283 trace("Winver: 0x%lx\n", g_dwWinVer); 284 285 if (g_dwWinVer <= _WIN32_WINNT_WS03) 286 { 287 g_DLL_ATTACH = 4; 288 g_DLL_DETACH = 1; 289 } 290 else if (g_dwWinVer <= _WIN32_WINNT_WS08) 291 { 292 g_TLS_ATTACH = 5; 293 g_DLL_ATTACH = 4; 294 } 295 else if (g_dwWinVer <= _WIN32_WINNT_WIN7) 296 { 297 g_TLS_ATTACH = 3; 298 g_DLL_ATTACH = 2; 299 } 300 else if (g_dwWinVer <= _WIN32_WINNT_WINBLUE) 301 { 302 g_TLS_DETACH = 5; 303 g_DLL_DETACH = 4; 304 } 305 306 ret = GetTempPathW(_countof(workdir), workdir); 307 ok(ret, "GetTempPathW error: %lu\n", GetLastError()); 308 309 Length = GetTempFileNameW(workdir, L"ntdll", 0, dllpath); 310 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError()); 311 312 if (extract_resource(dllpath, (LPCWSTR)101)) 313 { 314 _SEH2_TRY 315 { 316 execute_test(); 317 } 318 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 319 { 320 ok(0, "Ldr didnt handle exception\n"); 321 } 322 _SEH2_END; 323 } 324 else 325 { 326 ok(0, "Failed to extract resource\n"); 327 } 328 329 DeleteFileW(dllpath); 330 } 331