[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