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(&current_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(&current_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