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