Alexandre Julliard : kernel:
Added work-around in UnhandledExceptionFilter for no exec protections.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue May 9 14:15:23 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: feb7276c7366c93da3731a50032ee7526bdacc03
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=feb7276c7366c93da3731a50032ee7526bdacc03
Author: Alexandre Julliard <julliard at winehq.org>
Date: Tue May 9 12:58:46 2006 +0200
kernel: Added work-around in UnhandledExceptionFilter for no exec protections.
---
dlls/kernel/except.c | 54 +++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 46 insertions(+), 8 deletions(-)
diff --git a/dlls/kernel/except.c b/dlls/kernel/except.c
index 95c5ce9..779146e 100644
--- a/dlls/kernel/except.c
+++ b/dlls/kernel/except.c
@@ -392,16 +392,12 @@ static int start_debugger_atomic(PEXCEPT
* If yes, we unprotect the resources to let broken apps continue
* (Windows does this too).
*/
-inline static BOOL check_resource_write( const EXCEPTION_RECORD *rec )
+inline static BOOL check_resource_write( void *addr )
{
- void *addr, *rsrc;
+ void *rsrc;
DWORD size;
MEMORY_BASIC_INFORMATION info;
- if (rec->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) return FALSE;
- if (rec->NumberParameters < 2) return FALSE;
- if (!rec->ExceptionInformation[0]) return FALSE; /* not a write access */
- addr = (void *)rec->ExceptionInformation[1];
if (!VirtualQuery( addr, &info, sizeof(info) )) return FALSE;
if (info.State == MEM_FREE || !(info.Type & MEM_IMAGE)) return FALSE;
if (!(rsrc = RtlImageDirectoryEntryToData( (HMODULE)info.AllocationBase, TRUE,
@@ -415,15 +411,57 @@ inline static BOOL check_resource_write(
/*******************************************************************
+ * check_no_exec
+ *
+ * Check for executing a protected area.
+ */
+inline static BOOL check_no_exec( void *addr )
+{
+ MEMORY_BASIC_INFORMATION info;
+
+ if (!VirtualQuery( addr, &info, sizeof(info) )) return FALSE;
+ if (info.State == MEM_FREE) return FALSE;
+
+ /* prot |= PAGE_EXECUTE would be a lot easier, but MS developers
+ * apparently don't grasp the notion of protection bits */
+ switch(info.Protect)
+ {
+ case PAGE_READONLY: info.Protect = PAGE_EXECUTE_READ; break;
+ case PAGE_READWRITE: info.Protect = PAGE_EXECUTE_READWRITE; break;
+ case PAGE_WRITECOPY: info.Protect = PAGE_EXECUTE_WRITECOPY; break;
+ default: return FALSE;
+ }
+ /* FIXME: we should probably have a per-app option, and maybe a message box */
+ FIXME( "No-exec fault triggered at %p, enabling work-around\n", addr );
+ return VirtualProtect( addr, 1, info.Protect, NULL );
+}
+
+
+/*******************************************************************
* UnhandledExceptionFilter (KERNEL32.@)
*/
DWORD WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers)
{
- if (check_resource_write( epointers->ExceptionRecord )) return EXCEPTION_CONTINUE_EXECUTION;
+ const EXCEPTION_RECORD *rec = epointers->ExceptionRecord;
+
+ if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && rec->NumberParameters >= 2)
+ {
+ switch(rec->ExceptionInformation[0])
+ {
+ case 1: /* write access */
+ if (check_resource_write( (void *)rec->ExceptionInformation[1] ))
+ return EXCEPTION_CONTINUE_EXECUTION;
+ break;
+ case 8: /* execute access */
+ if (check_no_exec( (void *)rec->ExceptionInformation[1] ))
+ return EXCEPTION_CONTINUE_EXECUTION;
+ break;
+ }
+ }
if (!NtCurrentTeb()->Peb->BeingDebugged)
{
- if (epointers->ExceptionRecord->ExceptionCode == CONTROL_C_EXIT)
+ if (rec->ExceptionCode == CONTROL_C_EXIT)
{
/* do not launch the debugger on ^C, simply terminate the process */
TerminateProcess( GetCurrentProcess(), 1 );
More information about the wine-cvs
mailing list