mirror of
https://github.com/reactos/reactos.git
synced 2024-09-11 05:12:43 +00:00
331 lines
9.2 KiB
C
331 lines
9.2 KiB
C
/*
|
|
* PROJECT: ReactOS API Tests
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: Test for exception behavior in dll notifications
|
|
* COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
WCHAR dllpath[MAX_PATH];
|
|
|
|
LONG g_TlsCalled = 0;
|
|
LONG g_DllMainCalled = 0;
|
|
|
|
LONG g_TlsExcept = 0xffffff;
|
|
LONG g_DllMainExcept = 0xffffff;
|
|
|
|
ULONG g_BaseHandlers = 0;
|
|
|
|
DWORD g_dwWinVer = 0;
|
|
|
|
ULONG CountHandlers(VOID)
|
|
{
|
|
EXCEPTION_REGISTRATION_RECORD* exc;
|
|
ULONG Count = 0;
|
|
|
|
exc = NtCurrentTeb()->NtTib.ExceptionList;
|
|
|
|
while (exc && exc != (EXCEPTION_REGISTRATION_RECORD*)~0)
|
|
{
|
|
Count++;
|
|
exc = exc->Next;
|
|
}
|
|
|
|
return Count;
|
|
}
|
|
|
|
int g_TLS_ATTACH = 4;
|
|
int g_TLS_DETACH = 3;
|
|
|
|
VOID WINAPI notify_TlsCallback(IN HINSTANCE hDllHandle, IN DWORD dwReason, IN LPVOID lpvReserved)
|
|
{
|
|
ULONG handlers = CountHandlers() - g_BaseHandlers;
|
|
|
|
InterlockedIncrement(&g_TlsCalled);
|
|
if (dwReason == DLL_PROCESS_ATTACH)
|
|
{
|
|
ok_int(handlers, g_TLS_ATTACH);
|
|
}
|
|
else
|
|
{
|
|
ok_int(handlers, g_TLS_DETACH);
|
|
}
|
|
|
|
if (InterlockedCompareExchange(&g_TlsExcept, 0xffffff, dwReason) == dwReason)
|
|
{
|
|
RaiseException(EXCEPTION_DATATYPE_MISALIGNMENT, EXCEPTION_NONCONTINUABLE, 0, NULL);
|
|
}
|
|
}
|
|
|
|
int g_DLL_ATTACH = 3;
|
|
int g_DLL_DETACH = 2;
|
|
|
|
BOOL WINAPI notify_DllMain(IN HINSTANCE hDllHandle, IN DWORD dwReason, IN LPVOID lpvReserved)
|
|
{
|
|
ULONG handlers = CountHandlers() - g_BaseHandlers;
|
|
|
|
InterlockedIncrement(&g_DllMainCalled);
|
|
if (dwReason == DLL_PROCESS_ATTACH)
|
|
{
|
|
ok_int(handlers, g_DLL_ATTACH);
|
|
}
|
|
else
|
|
{
|
|
ok_int(handlers, g_DLL_DETACH); // For failures, see https://jira.reactos.org/browse/CORE-14857
|
|
}
|
|
|
|
if (InterlockedCompareExchange(&g_DllMainExcept, 0xffffff, dwReason) == dwReason)
|
|
{
|
|
RaiseException(EXCEPTION_DATATYPE_MISALIGNMENT, EXCEPTION_NONCONTINUABLE, 0, NULL);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static void execute_test(void)
|
|
{
|
|
HMODULE mod;
|
|
DWORD dwErr;
|
|
_SEH2_TRY
|
|
{
|
|
g_TlsExcept = 0xffffff;
|
|
g_DllMainExcept = 0xffffff;
|
|
g_DllMainCalled = 0;
|
|
g_TlsCalled = 0;
|
|
g_BaseHandlers = CountHandlers();
|
|
mod = LoadLibraryW(dllpath);
|
|
dwErr = GetLastError();
|
|
ok(GetModuleHandleW(dllpath) != NULL, "Unable to load module (0x%lx)\n", dwErr);
|
|
ok_hex(g_DllMainCalled, 1);
|
|
if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled)
|
|
ok_hex(g_TlsCalled, 1);
|
|
if (g_TlsCalled == 0)
|
|
trace("Tls not active\n");
|
|
g_BaseHandlers = CountHandlers();
|
|
FreeLibrary(mod);
|
|
dwErr = GetLastError();
|
|
ok(GetModuleHandleW(dllpath) == NULL, "Unable to unload module (0x%lx)\n", dwErr);
|
|
ok_hex(g_DllMainCalled, 2);
|
|
if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled)
|
|
ok_hex(g_TlsCalled, 2);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
ok(0, "Unable to load it normally\n");
|
|
}
|
|
_SEH2_END;
|
|
|
|
|
|
_SEH2_TRY
|
|
{
|
|
g_TlsExcept = 0xffffff;
|
|
g_DllMainExcept = DLL_PROCESS_ATTACH;
|
|
g_DllMainCalled = 0;
|
|
g_TlsCalled = 0;
|
|
g_BaseHandlers = CountHandlers();
|
|
mod = LoadLibraryW(dllpath);
|
|
dwErr = GetLastError();
|
|
ok(GetModuleHandleW(dllpath) == NULL, "Module loaded (0x%lx)\n", dwErr);
|
|
if (g_dwWinVer <= _WIN32_WINNT_WIN7)
|
|
ok_hex(dwErr, ERROR_NOACCESS);
|
|
else
|
|
ok_hex(dwErr, ERROR_DLL_INIT_FAILED);
|
|
ok_hex(g_DllMainCalled, 1);
|
|
if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled)
|
|
ok_hex(g_TlsCalled, 1);
|
|
if (mod)
|
|
{
|
|
FreeLibrary(mod);
|
|
dwErr = GetLastError();
|
|
ok(GetModuleHandleW(dllpath) == NULL, "Unable to unload module (0x%lx)\n", dwErr);
|
|
ok_hex(g_DllMainCalled, 1);
|
|
if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled)
|
|
ok_hex(g_TlsCalled, 1);
|
|
}
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
ok(0, "Unable to execute test\n");
|
|
}
|
|
_SEH2_END;
|
|
|
|
_SEH2_TRY
|
|
{
|
|
g_TlsExcept = 0xffffff;
|
|
g_DllMainExcept = DLL_PROCESS_DETACH;
|
|
g_DllMainCalled = 0;
|
|
g_TlsCalled = 0;
|
|
g_BaseHandlers = CountHandlers();
|
|
mod = LoadLibraryW(dllpath);
|
|
dwErr = GetLastError();
|
|
ok(GetModuleHandleW(dllpath) != NULL, "Unable to load module (0x%lx)\n", dwErr);
|
|
ok_hex(g_DllMainCalled, 1);
|
|
if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled)
|
|
ok_hex(g_TlsCalled, 1);
|
|
g_BaseHandlers = CountHandlers();
|
|
FreeLibrary(mod);
|
|
dwErr = GetLastError();
|
|
ok(GetModuleHandleW(dllpath) == NULL, "Unable to unload module (0x%lx)\n", dwErr);
|
|
ok_hex(g_DllMainCalled, 2);
|
|
if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled)
|
|
ok_hex(g_TlsCalled, 2);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
ok(0, "Unable to execute test\n");
|
|
}
|
|
_SEH2_END;
|
|
|
|
_SEH2_TRY
|
|
{
|
|
g_TlsExcept = DLL_PROCESS_ATTACH;
|
|
g_DllMainExcept = 0xffffff;
|
|
g_DllMainCalled = 0;
|
|
g_TlsCalled = 0;
|
|
g_BaseHandlers = CountHandlers();
|
|
mod = LoadLibraryW(dllpath);
|
|
dwErr = GetLastError();
|
|
ok(GetModuleHandleW(dllpath) != NULL, "Unable to load module (0x%lx)\n", dwErr);
|
|
ok_hex(g_DllMainCalled, 1);
|
|
if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled)
|
|
ok_hex(g_TlsCalled, 1);
|
|
g_BaseHandlers = CountHandlers();
|
|
FreeLibrary(mod);
|
|
dwErr = GetLastError();
|
|
ok(GetModuleHandleW(dllpath) == NULL, "Unable to unload module (0x%lx)\n", dwErr);
|
|
ok_hex(g_DllMainCalled, 2);
|
|
if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled)
|
|
ok_hex(g_TlsCalled, 2);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
ok(0, "Unable to execute test\n");
|
|
}
|
|
_SEH2_END;
|
|
|
|
_SEH2_TRY
|
|
{
|
|
g_TlsExcept = DLL_PROCESS_DETACH;
|
|
g_DllMainExcept = 0xffffff;
|
|
g_DllMainCalled = 0;
|
|
g_TlsCalled = 0;
|
|
g_BaseHandlers = CountHandlers();
|
|
mod = LoadLibraryW(dllpath);
|
|
dwErr = GetLastError();
|
|
ok(GetModuleHandleW(dllpath) != NULL, "Unable to load module (0x%lx)\n", dwErr);
|
|
ok_hex(g_DllMainCalled, 1);
|
|
if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled)
|
|
ok_hex(g_TlsCalled, 1);
|
|
g_BaseHandlers = CountHandlers();
|
|
FreeLibrary(mod);
|
|
dwErr = GetLastError();
|
|
ok(GetModuleHandleW(dllpath) == NULL, "Unable to unload module (0x%lx)\n", dwErr);
|
|
ok_hex(g_DllMainCalled, 2);
|
|
if (g_dwWinVer > _WIN32_WINNT_WS03 || g_TlsCalled)
|
|
ok_hex(g_TlsCalled, 2);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
ok(0, "Unable to execute test\n");
|
|
}
|
|
_SEH2_END;
|
|
|
|
}
|
|
|
|
|
|
BOOL extract_resource(const WCHAR* Filename, LPCWSTR ResourceName)
|
|
{
|
|
BOOL Success;
|
|
DWORD dwWritten, Size;
|
|
HGLOBAL hGlobal;
|
|
LPVOID pData;
|
|
HANDLE Handle;
|
|
HRSRC hRsrc = FindResourceW(GetModuleHandleW(NULL), ResourceName, (LPCWSTR)10);
|
|
ok(!!hRsrc, "Unable to find %s\n", wine_dbgstr_w(ResourceName));
|
|
if (!hRsrc)
|
|
return FALSE;
|
|
|
|
hGlobal = LoadResource(GetModuleHandleW(NULL), hRsrc);
|
|
Size = SizeofResource(GetModuleHandleW(NULL), hRsrc);
|
|
pData = LockResource(hGlobal);
|
|
|
|
ok(Size && !!pData, "Unable to load %s\n", wine_dbgstr_w(ResourceName));
|
|
if (!Size || !pData)
|
|
return FALSE;
|
|
|
|
Handle = CreateFileW(Filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (Handle == INVALID_HANDLE_VALUE)
|
|
{
|
|
skip("Failed to create temp file %ls, error %lu\n", Filename, GetLastError());
|
|
return FALSE;
|
|
}
|
|
Success = WriteFile(Handle, pData, Size, &dwWritten, NULL);
|
|
ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError());
|
|
ok(dwWritten == Size, "WriteFile wrote %lu bytes instead of %lu\n", dwWritten, Size);
|
|
CloseHandle(Handle);
|
|
Success = Success && (dwWritten == Size);
|
|
|
|
UnlockResource(pData);
|
|
return Success;
|
|
}
|
|
|
|
|
|
START_TEST(load_notifications)
|
|
{
|
|
WCHAR workdir[MAX_PATH];
|
|
BOOL ret;
|
|
UINT Length;
|
|
PPEB Peb = NtCurrentPeb();
|
|
|
|
g_dwWinVer = (DWORD)(Peb->OSMajorVersion << 8) | Peb->OSMinorVersion;
|
|
trace("Winver: 0x%lx\n", g_dwWinVer);
|
|
|
|
if (g_dwWinVer <= _WIN32_WINNT_WS03)
|
|
{
|
|
g_DLL_ATTACH = 4;
|
|
g_DLL_DETACH = 1;
|
|
}
|
|
else if (g_dwWinVer <= _WIN32_WINNT_WS08)
|
|
{
|
|
g_TLS_ATTACH = 5;
|
|
g_DLL_ATTACH = 4;
|
|
}
|
|
else if (g_dwWinVer <= _WIN32_WINNT_WIN7)
|
|
{
|
|
g_TLS_ATTACH = 3;
|
|
g_DLL_ATTACH = 2;
|
|
}
|
|
else if (g_dwWinVer <= _WIN32_WINNT_WINBLUE)
|
|
{
|
|
g_TLS_DETACH = 5;
|
|
g_DLL_DETACH = 4;
|
|
}
|
|
|
|
ret = GetTempPathW(_countof(workdir), workdir);
|
|
ok(ret, "GetTempPathW error: %lu\n", GetLastError());
|
|
|
|
Length = GetTempFileNameW(workdir, L"ntdll", 0, dllpath);
|
|
ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError());
|
|
|
|
if (extract_resource(dllpath, (LPCWSTR)101))
|
|
{
|
|
_SEH2_TRY
|
|
{
|
|
execute_test();
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
ok(0, "Ldr didnt handle exception\n");
|
|
}
|
|
_SEH2_END;
|
|
}
|
|
else
|
|
{
|
|
ok(0, "Failed to extract resource\n");
|
|
}
|
|
|
|
DeleteFileW(dllpath);
|
|
}
|