Rob Shearman : rpcrt4: Put the delegating stub thunks in an executable memory page, rather than on the heap.
Alexandre Julliard
julliard at winehq.org
Tue Dec 4 13:25:17 CST 2007
Module: wine
Branch: master
Commit: 6dcc3fe62ebcfba7625eb954e9107d6b36e76c60
URL: http://source.winehq.org/git/wine.git/?a=commit;h=6dcc3fe62ebcfba7625eb954e9107d6b36e76c60
Author: Rob Shearman <rob at codeweavers.com>
Date: Mon Dec 3 16:09:05 2007 +0000
rpcrt4: Put the delegating stub thunks in an executable memory page, rather than on the heap.
---
dlls/rpcrt4/cstub.c | 27 +++++++++++++++++++--------
1 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/dlls/rpcrt4/cstub.c b/dlls/rpcrt4/cstub.c
index 52c11d9..c81408d 100644
--- a/dlls/rpcrt4/cstub.c
+++ b/dlls/rpcrt4/cstub.c
@@ -109,13 +109,15 @@ static CRITICAL_SECTION delegating_vtbl_section = { &critsect_debug, -1, 0, 0, 0
typedef struct
{
DWORD ref;
+ DWORD size;
+ void **methods;
IUnknownVtbl vtbl;
+ /* remaining entries in vtbl */
} ref_counted_vtbl;
static struct
{
ref_counted_vtbl *table;
- DWORD size;
} current_vtbl;
@@ -156,7 +158,7 @@ typedef struct {
} vtbl_method_t;
#include "poppack.h"
-static void fill_table(IUnknownVtbl *vtbl, DWORD num)
+static void fill_table(IUnknownVtbl *vtbl, void **methods, DWORD num)
{
vtbl_method_t *method;
void **entry;
@@ -166,7 +168,7 @@ static void fill_table(IUnknownVtbl *vtbl, DWORD num)
vtbl->AddRef = delegating_AddRef;
vtbl->Release = delegating_Release;
- method = (vtbl_method_t*)((void **)vtbl + num);
+ method = (vtbl_method_t*)methods;
entry = (void**)(vtbl + 1);
for(i = 3; i < num; i++)
@@ -209,19 +211,25 @@ void create_delegating_vtbl(DWORD num_methods)
}
EnterCriticalSection(&delegating_vtbl_section);
- if(num_methods > current_vtbl.size)
+ if(!current_vtbl.table || num_methods > current_vtbl.table->size)
{
DWORD size;
+ DWORD old_protect;
if(current_vtbl.table && current_vtbl.table->ref == 0)
{
TRACE("freeing old table\n");
+ VirtualFree(current_vtbl.table->methods,
+ (current_vtbl.table->size - 3) * sizeof(vtbl_method_t),
+ MEM_RELEASE);
HeapFree(GetProcessHeap(), 0, current_vtbl.table);
}
- size = sizeof(DWORD) + num_methods * sizeof(void*) + (num_methods - 3) * sizeof(vtbl_method_t);
- current_vtbl.table = HeapAlloc(GetProcessHeap(), 0, size);
- fill_table(¤t_vtbl.table->vtbl, num_methods);
+ size = (num_methods - 3) * sizeof(vtbl_method_t);
+ current_vtbl.table = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(ref_counted_vtbl, vtbl) + num_methods * sizeof(void*));
current_vtbl.table->ref = 0;
- current_vtbl.size = num_methods;
+ current_vtbl.table->size = num_methods;
+ current_vtbl.table->methods = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ fill_table(¤t_vtbl.table->vtbl, current_vtbl.table->methods, num_methods);
+ VirtualProtect(current_vtbl.table->methods, size, PAGE_EXECUTE_READ, &old_protect);
}
LeaveCriticalSection(&delegating_vtbl_section);
}
@@ -247,6 +255,9 @@ static void release_delegating_vtbl(IUnknownVtbl *vtbl)
if(table->ref == 0 && table != current_vtbl.table)
{
TRACE("... and we're not current so free'ing\n");
+ VirtualFree(current_vtbl.table->methods,
+ (current_vtbl.table->size - 3) * sizeof(vtbl_method_t),
+ MEM_RELEASE);
HeapFree(GetProcessHeap(), 0, table);
}
LeaveCriticalSection(&delegating_vtbl_section);
More information about the wine-cvs
mailing list