Jacek Caban : oleaut32: Use a struct for internal BSTR representation to avoid pointer magic.

Alexandre Julliard julliard at winehq.org
Wed May 2 14:30:03 CDT 2012


Module: wine
Branch: master
Commit: 4eebe0bcf099c9b5a41104c531e6ef3d33045df9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=4eebe0bcf099c9b5a41104c531e6ef3d33045df9

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed May  2 16:24:57 2012 +0200

oleaut32: Use a struct for internal BSTR representation to avoid pointer magic.

---

 dlls/oleaut32/oleaut.c |   96 ++++++++++++++++++++++++++++--------------------
 1 files changed, 56 insertions(+), 40 deletions(-)

diff --git a/dlls/oleaut32/oleaut.c b/dlls/oleaut32/oleaut.c
index bb3bac6..b84fdc4 100644
--- a/dlls/oleaut32/oleaut.c
+++ b/dlls/oleaut32/oleaut.c
@@ -81,9 +81,18 @@ static CRITICAL_SECTION_DEBUG cs_bstr_cache_dbg =
 static CRITICAL_SECTION cs_bstr_cache = { &cs_bstr_cache_dbg, -1, 0, 0, 0, 0 };
 
 typedef struct {
+    DWORD size;
+    union {
+        char ptr[1];
+        WCHAR str[1];
+        DWORD dwptr[1];
+    } u;
+} bstr_t;
+
+typedef struct {
     unsigned short head;
     unsigned short cnt;
-    DWORD *buf[6];
+    bstr_t *buf[6];
 } bstr_cache_entry_t;
 
 #define BUCKET_SIZE 16
@@ -92,28 +101,32 @@ static bstr_cache_entry_t bstr_cache[0x10000/BUCKET_SIZE];
 
 static inline size_t bstr_alloc_size(size_t size)
 {
-    return (size+sizeof(DWORD)+BUCKET_SIZE) & ~(BUCKET_SIZE-1);
+    return (FIELD_OFFSET(bstr_t, u.ptr[size]) + sizeof(WCHAR) + BUCKET_SIZE-1) & ~(BUCKET_SIZE-1);
+}
+
+static inline bstr_t *bstr_from_str(BSTR str)
+{
+    return CONTAINING_RECORD(str, bstr_t, u.str);
 }
 
 static inline bstr_cache_entry_t *get_cache_entry(size_t size)
 {
-    unsigned cache_idx = (size+sizeof(DWORD)-1)/BUCKET_SIZE;
+    unsigned cache_idx = FIELD_OFFSET(bstr_t, u.ptr[size-1])/BUCKET_SIZE;
     return bstr_cache_enabled && cache_idx < sizeof(bstr_cache)/sizeof(*bstr_cache)
         ? bstr_cache + cache_idx
         : NULL;
 }
 
-static DWORD *alloc_bstr(size_t size)
+static bstr_t *alloc_bstr(size_t size)
 {
-    bstr_cache_entry_t *cache_entry = get_cache_entry(size);
+    bstr_cache_entry_t *cache_entry = get_cache_entry(size+sizeof(WCHAR));
+    bstr_t *ret;
 
     if(cache_entry) {
-        DWORD *ret = NULL;
-
         EnterCriticalSection(&cs_bstr_cache);
 
         if(!cache_entry->cnt) {
-            cache_entry = get_cache_entry(size+BUCKET_SIZE);
+            cache_entry = get_cache_entry(size+sizeof(WCHAR)+BUCKET_SIZE);
             if(cache_entry && !cache_entry->cnt)
                 cache_entry = NULL;
         }
@@ -126,11 +139,16 @@ static DWORD *alloc_bstr(size_t size)
 
         LeaveCriticalSection(&cs_bstr_cache);
 
-        if(ret)
+        if(cache_entry) {
+            ret->size = size;
             return ret;
+        }
     }
 
-    return HeapAlloc(GetProcessHeap(), 0, bstr_alloc_size(size));
+    ret = HeapAlloc(GetProcessHeap(), 0, bstr_alloc_size(size));
+    if(ret)
+        ret->size = size;
+    return ret;
 }
 
 /******************************************************************************
@@ -152,7 +170,7 @@ static DWORD *alloc_bstr(size_t size)
  */
 UINT WINAPI SysStringLen(BSTR str)
 {
-    return str ? *((DWORD*)str-1)/sizeof(WCHAR) : 0;
+    return str ? bstr_from_str(str)->size/sizeof(WCHAR) : 0;
 }
 
 /******************************************************************************
@@ -171,7 +189,7 @@ UINT WINAPI SysStringLen(BSTR str)
  */
 UINT WINAPI SysStringByteLen(BSTR str)
 {
-    return str ? *((DWORD*)str-1) : 0;
+    return str ? bstr_from_str(str)->size : 0;
 }
 
 /******************************************************************************
@@ -218,19 +236,20 @@ BSTR WINAPI SysAllocString(LPCOLESTR str)
 void WINAPI SysFreeString(BSTR str)
 {
     bstr_cache_entry_t *cache_entry;
-    DWORD *ptr;
+    bstr_t *bstr;
 
     if(!str)
         return;
 
-    ptr = (DWORD*)str-1;
-    cache_entry = get_cache_entry(*ptr+sizeof(WCHAR));
+    bstr = bstr_from_str(str);
+    cache_entry = get_cache_entry(bstr->size+sizeof(WCHAR));
     if(cache_entry) {
         EnterCriticalSection(&cs_bstr_cache);
 
         if(cache_entry->cnt < sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)) {
-            cache_entry->buf[(cache_entry->head+cache_entry->cnt)%((sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)))] = ptr;
+            cache_entry->buf[(cache_entry->head+cache_entry->cnt)%((sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)))] = bstr;
             cache_entry->cnt++;
+
             LeaveCriticalSection(&cs_bstr_cache);
             return;
         }
@@ -238,7 +257,7 @@ void WINAPI SysFreeString(BSTR str)
         LeaveCriticalSection(&cs_bstr_cache);
     }
 
-    HeapFree(GetProcessHeap(), 0, ptr);
+    HeapFree(GetProcessHeap(), 0, bstr);
 }
 
 /******************************************************************************
@@ -259,28 +278,28 @@ void WINAPI SysFreeString(BSTR str)
  */
 BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
 {
-    DWORD size, *ptr;
-    BSTR ret;
+    bstr_t *bstr;
+    DWORD size;
 
     /* Detect integer overflow. */
     if (len >= ((UINT_MAX-sizeof(WCHAR)-sizeof(DWORD))/sizeof(WCHAR)))
 	return NULL;
 
+    TRACE("%s\n", debugstr_wn(str, len));
+
     size = len*sizeof(WCHAR);
-    ptr = alloc_bstr(size + sizeof(WCHAR));
-    if(!ptr)
+    bstr = alloc_bstr(size);
+    if(!bstr)
         return NULL;
 
-    *ptr = size;
-    ret = (BSTR)(ptr+1);
     if(str) {
-        memcpy(ret, str, size);
-        ret[len] = 0;
+        memcpy(bstr->u.str, str, size);
+        bstr->u.str[len] = 0;
     }else {
-        memset(ret, 0, size+sizeof(WCHAR));
+        memset(bstr->u.str, 0, size+sizeof(WCHAR));
     }
 
-    return ret;
+    return bstr->u.str;
 }
 
 /******************************************************************************
@@ -310,9 +329,9 @@ int WINAPI SysReAllocStringLen(BSTR* old, const OLECHAR* str, unsigned int len)
     if (*old!=NULL) {
       BSTR old_copy = *old;
       DWORD newbytelen = len*sizeof(WCHAR);
-      DWORD *ptr = HeapReAlloc(GetProcessHeap(),0,((DWORD*)*old)-1,bstr_alloc_size(newbytelen+sizeof(WCHAR)));
-      *old = (BSTR)(ptr+1);
-      *ptr = newbytelen;
+      bstr_t *bstr = HeapReAlloc(GetProcessHeap(),0,((DWORD*)*old)-1,bstr_alloc_size(newbytelen));
+      *old = bstr->u.str;
+      bstr->size = newbytelen;
       /* Subtle hidden feature: The old string data is still there
        * when 'in' is NULL!
        * Some Microsoft program needs it.
@@ -352,27 +371,24 @@ int WINAPI SysReAllocStringLen(BSTR* old, const OLECHAR* str, unsigned int len)
  */
 BSTR WINAPI SysAllocStringByteLen(LPCSTR str, UINT len)
 {
-    DWORD *ptr;
-    char *ret;
+    bstr_t *bstr;
 
     /* Detect integer overflow. */
     if (len >= (UINT_MAX-sizeof(WCHAR)-sizeof(DWORD)))
 	return NULL;
 
-    ptr = alloc_bstr(len + sizeof(WCHAR));
-    if(!ptr)
+    bstr = alloc_bstr(len);
+    if(!bstr)
         return NULL;
 
-    *ptr = len;
-    ret = (char*)(ptr+1);
     if(str) {
-        memcpy(ret, str, len);
-        ret[len] = ret[len+1] = 0;
+        memcpy(bstr->u.ptr, str, len);
+        bstr->u.ptr[len] = bstr->u.ptr[len+1] = 0;
     }else {
-        memset(ret, 0, len+sizeof(WCHAR));
+        memset(bstr->u.ptr, 0, len+sizeof(WCHAR));
     }
 
-    return (BSTR)ret;
+    return bstr->u.str;
 }
 
 /******************************************************************************




More information about the wine-cvs mailing list