mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
a8ed1e17c2
[ntdll-x86_64_Builtin_Frames] Temporarily disable patchset to improve handling of builtin frames for x86_64 when switching stack. This needs additional work to be compatible with the recent collided unwind upstream changes.
185 lines
7.0 KiB
Diff
185 lines
7.0 KiB
Diff
From cd82af4ce885a2541e75c4adb3527197eb940569 Mon Sep 17 00:00:00 2001
|
|
From: Sebastian Lackner <sebastian@fds-team.de>
|
|
Date: Sun, 28 Sep 2014 22:42:46 +0200
|
|
Subject: ntdll: Throw exception if invalid handle is passed to NtClose and
|
|
debugger enabled.
|
|
|
|
---
|
|
dlls/ntdll/om.c | 27 ++++++++++++++++++
|
|
dlls/ntdll/tests/exception.c | 65 ++++++++++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 92 insertions(+)
|
|
|
|
diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c
|
|
index 1279f2b..35c3672 100644
|
|
--- a/dlls/ntdll/om.c
|
|
+++ b/dlls/ntdll/om.c
|
|
@@ -38,6 +38,7 @@
|
|
#include "winternl.h"
|
|
#include "ntdll_misc.h"
|
|
#include "wine/server.h"
|
|
+#include "wine/exception.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
|
|
|
@@ -377,6 +378,13 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
|
|
return ret;
|
|
}
|
|
|
|
+
|
|
+static LONG WINAPI invalid_handle_exception_handler( EXCEPTION_POINTERS *eptr )
|
|
+{
|
|
+ EXCEPTION_RECORD *rec = eptr->ExceptionRecord;
|
|
+ return (rec->ExceptionCode == EXCEPTION_INVALID_HANDLE) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
|
|
+}
|
|
+
|
|
/* Everquest 2 / Pirates of the Burning Sea hooks NtClose, so we need a wrapper */
|
|
NTSTATUS close_handle( HANDLE handle )
|
|
{
|
|
@@ -390,6 +398,25 @@ NTSTATUS close_handle( HANDLE handle )
|
|
}
|
|
SERVER_END_REQ;
|
|
if (fd != -1) close( fd );
|
|
+
|
|
+ if (ret == STATUS_INVALID_HANDLE && NtCurrentTeb()->Peb->BeingDebugged)
|
|
+ {
|
|
+ __TRY
|
|
+ {
|
|
+ EXCEPTION_RECORD record;
|
|
+ record.ExceptionCode = EXCEPTION_INVALID_HANDLE;
|
|
+ record.ExceptionFlags = 0;
|
|
+ record.ExceptionRecord = NULL;
|
|
+ record.ExceptionAddress = NULL;
|
|
+ record.NumberParameters = 0;
|
|
+ RtlRaiseException( &record );
|
|
+ }
|
|
+ __EXCEPT(invalid_handle_exception_handler)
|
|
+ {
|
|
+ }
|
|
+ __ENDTRY
|
|
+ }
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
|
|
index f1bfee6..3e22bed 100644
|
|
--- a/dlls/ntdll/tests/exception.c
|
|
+++ b/dlls/ntdll/tests/exception.c
|
|
@@ -51,6 +51,7 @@ static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE handle, LONG exit_code);
|
|
static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
|
|
static NTSTATUS (WINAPI *pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);
|
|
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
|
|
+static NTSTATUS (WINAPI *pNtClose)(HANDLE);
|
|
|
|
#if defined(__x86_64__)
|
|
typedef struct
|
|
@@ -989,6 +990,16 @@ static void test_debugger(void)
|
|
|
|
if (stage == 10) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
|
|
}
|
|
+ else if (stage == 11 || stage == 12)
|
|
+ {
|
|
+ ok(de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_INVALID_HANDLE,
|
|
+ "unexpected exception code %08x, expected %08x\n", de.u.Exception.ExceptionRecord.ExceptionCode,
|
|
+ EXCEPTION_INVALID_HANDLE);
|
|
+ ok(de.u.Exception.ExceptionRecord.NumberParameters == 0,
|
|
+ "unexpected number of parameters %d, expected 0\n", de.u.Exception.ExceptionRecord.NumberParameters);
|
|
+
|
|
+ if (stage == 12) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
|
|
+ }
|
|
else
|
|
ok(FALSE, "unexpected stage %x\n", stage);
|
|
|
|
@@ -2194,6 +2205,53 @@ static void test_breakpoint(DWORD numexc)
|
|
pRtlRemoveVectoredExceptionHandler(vectored_handler);
|
|
}
|
|
|
|
+static DWORD invalid_handle_exceptions;
|
|
+
|
|
+static LONG CALLBACK invalid_handle_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
|
|
+{
|
|
+ PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
|
|
+ trace("vect. handler %08x addr:%p\n", rec->ExceptionCode, rec->ExceptionAddress);
|
|
+
|
|
+ ok(rec->ExceptionCode == EXCEPTION_INVALID_HANDLE, "ExceptionCode is %08x instead of %08x\n",
|
|
+ rec->ExceptionCode, EXCEPTION_INVALID_HANDLE);
|
|
+ ok(rec->NumberParameters == 0, "ExceptionParameters is %d instead of 0\n", rec->NumberParameters);
|
|
+
|
|
+ invalid_handle_exceptions++;
|
|
+ return (rec->ExceptionCode == EXCEPTION_INVALID_HANDLE) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
|
|
+}
|
|
+
|
|
+static void test_closehandle(DWORD numexc)
|
|
+{
|
|
+ PVOID vectored_handler;
|
|
+ NTSTATUS status;
|
|
+ DWORD res;
|
|
+
|
|
+ if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler || !pRtlRaiseException)
|
|
+ {
|
|
+ skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or RtlRaiseException not found\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ vectored_handler = pRtlAddVectoredExceptionHandler(TRUE, &invalid_handle_vectored_handler);
|
|
+ ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
|
|
+
|
|
+ invalid_handle_exceptions = 0;
|
|
+ res = CloseHandle((HANDLE)0xdeadbeef);
|
|
+ ok(!res, "CloseHandle(0xdeadbeef) unexpectedly succeeded\n");
|
|
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error code %d instead of %d\n",
|
|
+ GetLastError(), ERROR_INVALID_HANDLE);
|
|
+ ok(invalid_handle_exceptions == numexc, "CloseHandle generated %d exceptions, expected %d\n",
|
|
+ invalid_handle_exceptions, numexc);
|
|
+
|
|
+ invalid_handle_exceptions = 0;
|
|
+ status = pNtClose((HANDLE)0xdeadbeef);
|
|
+ ok(status == STATUS_INVALID_HANDLE, "NtClose(0xdeadbeef) returned status %08x\n", status);
|
|
+ ok(invalid_handle_exceptions == numexc, "NtClose generated %d exceptions, expected %d\n",
|
|
+ invalid_handle_exceptions, numexc);
|
|
+
|
|
+ pRtlRemoveVectoredExceptionHandler(vectored_handler);
|
|
+}
|
|
+
|
|
static void test_vectored_continue_handler(void)
|
|
{
|
|
PVOID handler1, handler2;
|
|
@@ -2245,6 +2303,7 @@ START_TEST(exception)
|
|
pNtGetContextThread = (void *)GetProcAddress( hntdll, "NtGetContextThread" );
|
|
pNtSetContextThread = (void *)GetProcAddress( hntdll, "NtSetContextThread" );
|
|
pNtReadVirtualMemory = (void *)GetProcAddress( hntdll, "NtReadVirtualMemory" );
|
|
+ pNtClose = (void *)GetProcAddress( hntdll, "NtClose" );
|
|
pRtlUnwind = (void *)GetProcAddress( hntdll, "RtlUnwind" );
|
|
pRtlRaiseException = (void *)GetProcAddress( hntdll, "RtlRaiseException" );
|
|
pNtTerminateProcess = (void *)GetProcAddress( hntdll, "NtTerminateProcess" );
|
|
@@ -2315,6 +2374,10 @@ START_TEST(exception)
|
|
test_breakpoint(0);
|
|
test_stage = 10;
|
|
test_breakpoint(1);
|
|
+ test_stage = 11;
|
|
+ test_closehandle(0);
|
|
+ test_stage = 12;
|
|
+ test_closehandle(1);
|
|
}
|
|
else
|
|
skip( "RtlRaiseException not found\n" );
|
|
@@ -2331,6 +2394,7 @@ START_TEST(exception)
|
|
test_ripevent(1);
|
|
test_debug_service(1);
|
|
test_breakpoint(1);
|
|
+ test_closehandle(0);
|
|
test_vectored_continue_handler();
|
|
test_debugger();
|
|
test_simd_exceptions();
|
|
@@ -2355,6 +2419,7 @@ START_TEST(exception)
|
|
test_ripevent(1);
|
|
test_debug_service(1);
|
|
test_breakpoint(1);
|
|
+ test_closehandle(0);
|
|
test_vectored_continue_handler();
|
|
test_virtual_unwind();
|
|
test___C_specific_handler();
|
|
--
|
|
2.9.0
|
|
|