[Wine-patches] [4/6] ntoskrnl.exe: Provide access to memory of a process which calls IOCTL.

Alexander Morozov =?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Пт Ноя 14 13:44:11 MSK 2008


----------- следующая часть -----------
From dd26cd12c32edb015625f4238f7ee53941a61773 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Fri, 14 Nov 2008 13:10:10 +0300
Subject: [PATCH] ntoskrnl.exe: Provide access to memory of a process which calls IOCTL.

---
 dlls/ntoskrnl.exe/ntoskrnl.c |   80 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 80 insertions(+), 0 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 91c6ecb..1dcc909 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -64,6 +64,15 @@ struct IrpInstance
     IRP *irp;
 };
 
+static struct list MemoryList = LIST_INIT(MemoryList);
+
+struct MemoryRegion
+{
+    struct list entry;
+    void *ptr;
+    int release;
+};
+
 static DWORD pid; /* ID of the process which calls IOCTL */
 
 #ifdef __i386__
@@ -133,6 +142,72 @@ static LONG CALLBACK vectored_handler( EXCEPTION_POINTERS *ptrs )
     return EXCEPTION_CONTINUE_SEARCH;
 }
 
+static int map_memory( void *addr )
+{
+    struct MemoryRegion *mr;
+    HANDLE process;
+
+    mr = ExAllocatePool( NonPagedPool, sizeof(struct MemoryRegion) );
+    if (mr == NULL)
+        return 1;
+    addr = (void *)((unsigned int)addr & ~0xfff);
+    mr->ptr = VirtualAlloc( addr, 0x1000, MEM_COMMIT | MEM_RESERVE,
+            PAGE_EXECUTE_READWRITE );
+    if (mr->ptr == NULL)
+    {
+        mr->ptr = VirtualAlloc( addr, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
+        if (mr->ptr == NULL)
+        {
+            ExFreePool( mr );
+            return 1;
+        }
+        mr->release = 0;
+    }
+    else
+        mr->release = 1;
+    process = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid );
+    if (process == NULL)
+    {
+        VirtualFree( mr->ptr, 0x1000, mr->release ? MEM_RELEASE : MEM_DECOMMIT );
+        ExFreePool( mr );
+        return 1;
+    }
+    NtReadVirtualMemory( process, mr->ptr, mr->ptr, 0x1000, NULL );
+    CloseHandle( process );
+    list_add_tail( &MemoryList, &mr->entry );
+    return 0;
+}
+
+static void unmap_memory(void)
+{
+    struct MemoryRegion *mr, *mr2;
+    HANDLE process;
+
+    LIST_FOR_EACH_ENTRY_SAFE( mr, mr2, &MemoryList, struct MemoryRegion, entry )
+    {
+        process = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid );
+        if (process != NULL)
+        {
+            NtWriteVirtualMemory( process, mr->ptr, mr->ptr, 0x1000, NULL );
+            CloseHandle( process );
+        }
+        VirtualFree( mr->ptr, 0x1000, mr->release ? MEM_RELEASE : MEM_DECOMMIT );
+        list_remove( &mr->entry );
+        ExFreePool( mr );
+    }
+}
+
+static LONG WINAPI memory_handler( EXCEPTION_POINTERS* except )
+{
+    if (except->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
+    {
+        char *addr = (char *)except->ExceptionRecord->ExceptionInformation[1];
+        if (!map_memory( addr ))
+            return EXCEPTION_CONTINUE_EXECUTION;
+    }
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+
 /* process an ioctl request for a given device */
 static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff, ULONG in_size,
                                void *out_buff, ULONG *out_size )
@@ -144,9 +219,12 @@ static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff,
     NTSTATUS status;
     LARGE_INTEGER count;
     CHAR *buf = NULL;
+    PVOID mem_handler;
 
     TRACE( "ioctl %x device %p in_size %u out_size %u\n", code, device, in_size, *out_size );
 
+    mem_handler = RtlAddVectoredExceptionHandler( FALSE, memory_handler );
+
     irp = IoAllocateIrp( device->StackSize, FALSE );
     if (irp == NULL)
         return STATUS_UNSUCCESSFUL;
@@ -210,6 +288,8 @@ static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff,
         memcpy( out_buff, buf, *out_size );
         ExFreePool( buf );
     }
+    RtlRemoveVectoredExceptionHandler( mem_handler );
+    unmap_memory();
 
     return status;
 }
-- 
1.5.6.5.GIT



Подробная информация о списке рассылки Wine-patches