2016-02-19 11:08:55 -08:00
|
|
|
From d6ce4357c4a5600f33e24df046e9a24fcfb71bf2 Mon Sep 17 00:00:00 2001
|
2014-09-28 14:54:50 -07:00
|
|
|
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
|
2016-02-18 18:19:21 -08:00
|
|
|
index 1279f2b..35c3672 100644
|
2014-09-28 14:54:50 -07:00
|
|
|
--- 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);
|
|
|
|
|
2015-12-27 18:26:17 -08:00
|
|
|
@@ -377,6 +378,13 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
|
2014-09-28 14:54:50 -07:00
|
|
|
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 )
|
|
|
|
{
|
2015-12-27 18:26:17 -08:00
|
|
|
@@ -390,6 +398,25 @@ NTSTATUS close_handle( HANDLE handle )
|
2014-09-28 14:54:50 -07:00
|
|
|
}
|
|
|
|
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
|
2016-02-19 11:08:55 -08:00
|
|
|
index 64f3dff..56940c3 100644
|
2014-09-28 14:54:50 -07:00
|
|
|
--- a/dlls/ntdll/tests/exception.c
|
|
|
|
+++ b/dlls/ntdll/tests/exception.c
|
2015-12-27 18:26:17 -08:00
|
|
|
@@ -52,6 +52,7 @@ static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE handle, LONG exit_code);
|
2014-09-28 14:54:50 -07:00
|
|
|
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__)
|
|
|
|
static BOOLEAN (CDECL *pRtlAddFunctionTable)(RUNTIME_FUNCTION*, DWORD, DWORD64);
|
2016-02-19 11:08:55 -08:00
|
|
|
@@ -963,6 +964,16 @@ static void test_debugger(void)
|
2016-02-18 18:19:21 -08:00
|
|
|
|
2016-02-19 11:08:55 -08:00
|
|
|
if (stage == 10) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
|
2014-09-28 14:54:50 -07:00
|
|
|
}
|
2016-02-19 11:08:55 -08:00
|
|
|
+ else if (stage == 11 || stage == 12)
|
2014-09-28 14:54:50 -07:00
|
|
|
+ {
|
|
|
|
+ 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);
|
|
|
|
+
|
2016-02-19 11:08:55 -08:00
|
|
|
+ if (stage == 12) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
|
2014-09-28 14:54:50 -07:00
|
|
|
+ }
|
|
|
|
else
|
|
|
|
ok(FALSE, "unexpected stage %x\n", stage);
|
|
|
|
|
2016-02-19 11:08:55 -08:00
|
|
|
@@ -2115,6 +2126,53 @@ static void test_breakpoint(DWORD numexc)
|
2014-09-28 14:54:50 -07:00
|
|
|
pRtlRemoveVectoredExceptionHandler(vectored_handler);
|
|
|
|
}
|
2014-11-14 02:17:24 -08:00
|
|
|
|
2014-09-28 14:54:50 -07:00
|
|
|
+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");
|
2015-08-16 23:37:22 -07:00
|
|
|
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error code %d instead of %d\n",
|
2014-09-28 14:54:50 -07:00
|
|
|
+ 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);
|
|
|
|
+}
|
2014-11-14 02:17:24 -08:00
|
|
|
+
|
|
|
|
static void test_vectored_continue_handler(void)
|
|
|
|
{
|
|
|
|
PVOID handler1, handler2;
|
2016-02-19 11:08:55 -08:00
|
|
|
@@ -2167,6 +2225,7 @@ START_TEST(exception)
|
2014-09-28 14:54:50 -07:00
|
|
|
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" );
|
2016-02-19 11:08:55 -08:00
|
|
|
@@ -2242,6 +2301,10 @@ START_TEST(exception)
|
|
|
|
test_breakpoint(0);
|
|
|
|
test_stage = 10;
|
|
|
|
test_breakpoint(1);
|
|
|
|
+ test_stage = 11;
|
2014-09-28 14:54:50 -07:00
|
|
|
+ test_closehandle(0);
|
2016-02-19 11:08:55 -08:00
|
|
|
+ test_stage = 12;
|
2014-09-28 14:54:50 -07:00
|
|
|
+ test_closehandle(1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
skip( "RtlRaiseException not found\n" );
|
2016-02-19 11:08:55 -08:00
|
|
|
@@ -2258,6 +2321,7 @@ START_TEST(exception)
|
2014-09-28 14:54:50 -07:00
|
|
|
test_ripevent(1);
|
2016-02-18 18:19:21 -08:00
|
|
|
test_debug_service(1);
|
2016-02-19 11:08:55 -08:00
|
|
|
test_breakpoint(1);
|
2014-09-28 14:54:50 -07:00
|
|
|
+ test_closehandle(0);
|
2014-11-14 02:17:24 -08:00
|
|
|
test_vectored_continue_handler();
|
2014-09-28 14:54:50 -07:00
|
|
|
test_debugger();
|
|
|
|
test_simd_exceptions();
|
2016-02-19 11:08:55 -08:00
|
|
|
@@ -2280,6 +2344,7 @@ START_TEST(exception)
|
2014-09-28 14:54:50 -07:00
|
|
|
test_ripevent(1);
|
2016-02-18 18:19:21 -08:00
|
|
|
test_debug_service(1);
|
2016-02-19 11:08:55 -08:00
|
|
|
test_breakpoint(1);
|
2014-09-28 14:54:50 -07:00
|
|
|
+ test_closehandle(0);
|
2014-11-14 02:17:24 -08:00
|
|
|
test_vectored_continue_handler();
|
2014-09-28 14:54:50 -07:00
|
|
|
test_virtual_unwind();
|
|
|
|
|
|
|
|
--
|
2016-02-19 11:08:55 -08:00
|
|
|
2.7.0
|
2014-09-28 14:54:50 -07:00
|
|
|
|