ntdll: Throw exception if invalid handle is passed to NtClose and debugger enabled.
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair@hotmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
8f81fa82d5
commit
c61c33ee66
|
@ -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,12 @@ 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 +397,25 @@ NTSTATUS close_handle( HANDLE handle )
|
|||
}
|
||||
SERVER_END_REQ;
|
||||
if (fd != -1) close( fd );
|
||||
|
||||
if (ret == STATUS_INVALID_HANDLE && 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,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
|
||||
|
@ -1091,6 +1092,16 @@ static void test_debugger(void)
|
|||
|
||||
if (stage == 10) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
|
||||
}
|
||||
else if (stage == 11 || stage == 12 || stage == 13)
|
||||
{
|
||||
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|| stage == 13) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
|
||||
}
|
||||
else
|
||||
ok(FALSE, "unexpected stage %x\n", stage);
|
||||
|
||||
|
@ -2895,6 +2906,54 @@ 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, HANDLE handle)
|
||||
{
|
||||
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);
|
||||
|
||||
ok(!res || (is_wow64 && res), "CloseHandle(%p) unexpectedly succeeded\n", handle);
|
||||
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);
|
||||
ok(status == STATUS_INVALID_HANDLE || (is_wow64 && status == 0), "NtClose(%p) returned status %08x\n", handle, 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;
|
||||
|
@ -2949,6 +3008,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" );
|
||||
pRtlCaptureContext = (void *)GetProcAddress( hntdll, "RtlCaptureContext" );
|
||||
|
@ -3020,6 +3080,12 @@ START_TEST(exception)
|
|||
test_breakpoint(0);
|
||||
test_stage = 10;
|
||||
test_breakpoint(1);
|
||||
test_stage = 11;
|
||||
test_closehandle(0, (HANDLE)0xdeadbeef);
|
||||
test_stage = 12;
|
||||
test_closehandle(1, (HANDLE)0xdeadbeef);
|
||||
test_stage = 13;
|
||||
test_closehandle(0, 0); /* Special case. */
|
||||
}
|
||||
else
|
||||
skip( "RtlRaiseException not found\n" );
|
||||
|
@ -3036,6 +3102,7 @@ START_TEST(exception)
|
|||
test_ripevent(1);
|
||||
test_debug_service(1);
|
||||
test_breakpoint(1);
|
||||
test_closehandle(0, (HANDLE)0xdeadbeef);
|
||||
test_vectored_continue_handler();
|
||||
test_debugger();
|
||||
test_simd_exceptions();
|
||||
|
@ -3069,6 +3136,7 @@ START_TEST(exception)
|
|||
test_ripevent(1);
|
||||
test_debug_service(1);
|
||||
test_breakpoint(1);
|
||||
test_closehandle(0, (HANDLE)0xdeadbeef);
|
||||
test_vectored_continue_handler();
|
||||
test_virtual_unwind();
|
||||
test___C_specific_handler();
|
||||
|
|
Loading…
Reference in New Issue