mirror of
https://github.com/reactos/reactos.git
synced 2025-05-18 00:31:27 +00:00
[NTDLL_APITEST] Show behavior with exceptions in DllMain.
CORE-14532
This commit is contained in:
parent
55053f0099
commit
86fe412d5c
7 changed files with 427 additions and 1 deletions
|
@ -1,6 +1,12 @@
|
|||
|
||||
add_subdirectory(load_notifications)
|
||||
|
||||
include_directories($<TARGET_FILE_DIR:load_notifications>)
|
||||
spec2def(ntdll_apitest.exe ntdll_apitest.spec)
|
||||
|
||||
list(APPEND SOURCE
|
||||
LdrEnumResources.c
|
||||
load_notifications.c
|
||||
NtAcceptConnectPort.c
|
||||
NtAllocateVirtualMemory.c
|
||||
NtApphelpCacheControl.c
|
||||
|
@ -62,7 +68,13 @@ if(ARCH STREQUAL "i386")
|
|||
add_asm_files(ntdll_apitest_asm i386/NtContinue.S)
|
||||
endif()
|
||||
|
||||
add_executable(ntdll_apitest ${SOURCE} ${ntdll_apitest_asm} testlist.c)
|
||||
add_rc_deps(testdata.rc ${CMAKE_CURRENT_BINARY_DIR}/load_notifications/load_notifications.dll)
|
||||
add_executable(ntdll_apitest
|
||||
${SOURCE}
|
||||
${ntdll_apitest_asm}
|
||||
testdata.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ntdll_apitest.def
|
||||
testlist.c)
|
||||
target_link_libraries(ntdll_apitest wine uuid ${PSEH_LIB})
|
||||
set_module_type(ntdll_apitest win32cui)
|
||||
add_importlibs(ntdll_apitest msvcrt advapi32 kernel32 ntdll)
|
||||
|
|
330
modules/rostests/apitests/ntdll/load_notifications.c
Normal file
330
modules/rostests/apitests/ntdll/load_notifications.c
Normal file
|
@ -0,0 +1,330 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
add_library(load_notifications SHARED load_notifications.c)
|
||||
set_module_type(load_notifications win32dll ENTRYPOINT DllMain 12)
|
||||
add_importlibs(load_notifications kernel32 ntdll)
|
||||
add_dependencies(load_notifications psdk)
|
||||
add_rostests_file(TARGET load_notifications)
|
|
@ -0,0 +1,72 @@
|
|||
#define WIN32_NO_STATUS
|
||||
#define _INC_WINDOWS
|
||||
#define COM_NO_WINDOWS_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRTALLOC(x) __declspec(allocate(x))
|
||||
#elif defined(__GNUC__)
|
||||
#define _CRTALLOC(x) __attribute__ ((section (x) ))
|
||||
#else
|
||||
#error Your compiler is not supported.
|
||||
#endif
|
||||
|
||||
|
||||
static VOID (WINAPI* pTlsCallback)(IN HINSTANCE hDllHandle, IN DWORD dwReason, IN LPVOID lpvReserved);
|
||||
|
||||
VOID WINAPI
|
||||
TlsCallback(IN HANDLE hDllHandle,
|
||||
IN DWORD dwReason,
|
||||
IN LPVOID lpvReserved)
|
||||
{
|
||||
if (!pTlsCallback)
|
||||
pTlsCallback = (VOID*)GetProcAddress(NULL, "notify_TlsCallback");
|
||||
if (pTlsCallback)
|
||||
{
|
||||
pTlsCallback(hDllHandle, dwReason, lpvReserved);
|
||||
return;
|
||||
}
|
||||
OutputDebugStringA("WARNING: load_notifications.dll loaded from a process without notify_TlsCallback\n");
|
||||
}
|
||||
|
||||
/* Tls magic stolen from sdk/lib/crt/startup/tlssup.c */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma section(".rdata$T",long,read)
|
||||
#pragma section(".tls",long,read,write)
|
||||
#pragma section(".tls$ZZZ",long,read,write)
|
||||
#endif
|
||||
|
||||
_CRTALLOC(".tls") char _tls_start = 0;
|
||||
_CRTALLOC(".tls$ZZZ") char _tls_end = 0;
|
||||
|
||||
PIMAGE_TLS_CALLBACK __xl_a[2] = { &TlsCallback, NULL };
|
||||
|
||||
ULONG _tls_index = 0;
|
||||
|
||||
_CRTALLOC(".rdata$T") const IMAGE_TLS_DIRECTORY _tls_used = {
|
||||
(ULONG_PTR) &_tls_start+1, (ULONG_PTR) &_tls_end,
|
||||
(ULONG_PTR) &_tls_index, (ULONG_PTR) (__xl_a),
|
||||
(ULONG) 0, (ULONG) 0
|
||||
};
|
||||
|
||||
|
||||
static BOOL (WINAPI* pDllMain)(IN HINSTANCE hDllHandle, IN DWORD dwReason, IN LPVOID lpvReserved);
|
||||
|
||||
|
||||
BOOL WINAPI
|
||||
DllMain(IN HINSTANCE hDllHandle,
|
||||
IN DWORD dwReason,
|
||||
IN LPVOID lpvReserved)
|
||||
{
|
||||
if (!pDllMain)
|
||||
pDllMain = (VOID*)GetProcAddress(NULL, "notify_DllMain");
|
||||
if (pDllMain)
|
||||
{
|
||||
return pDllMain(hDllHandle, dwReason, lpvReserved);
|
||||
}
|
||||
OutputDebugStringA("WARNING: load_notifications.dll loaded from a process without notify_DllMain\n");
|
||||
return TRUE;
|
||||
}
|
2
modules/rostests/apitests/ntdll/ntdll_apitest.spec
Normal file
2
modules/rostests/apitests/ntdll/ntdll_apitest.spec
Normal file
|
@ -0,0 +1,2 @@
|
|||
@ stdcall notify_TlsCallback(ptr long ptr)
|
||||
@ stdcall notify_DllMain(ptr long ptr)
|
2
modules/rostests/apitests/ntdll/testdata.rc
Normal file
2
modules/rostests/apitests/ntdll/testdata.rc
Normal file
|
@ -0,0 +1,2 @@
|
|||
|
||||
101 10 "load_notifications.dll"
|
|
@ -4,6 +4,7 @@
|
|||
#include <apitest.h>
|
||||
|
||||
extern void func_LdrEnumResources(void);
|
||||
extern void func_load_notifications(void);
|
||||
extern void func_NtAcceptConnectPort(void);
|
||||
extern void func_NtAllocateVirtualMemory(void);
|
||||
extern void func_NtApphelpCacheControl(void);
|
||||
|
@ -63,6 +64,7 @@ extern void func_TimerResolution(void);
|
|||
const struct test winetest_testlist[] =
|
||||
{
|
||||
{ "LdrEnumResources", func_LdrEnumResources },
|
||||
{ "load_notifications", func_load_notifications },
|
||||
{ "NtAcceptConnectPort", func_NtAcceptConnectPort },
|
||||
{ "NtAllocateVirtualMemory", func_NtAllocateVirtualMemory },
|
||||
{ "NtApphelpCacheControl", func_NtApphelpCacheControl },
|
||||
|
|
Loading…
Reference in a new issue