[PATCH] combase: Reorder hstring_private elements.

Bernhard Kölbl besentv at gmail.com
Thu Dec 23 16:05:19 CST 2021


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51017

Debugging sessions and the official WinRT SDK show, that the
contained string is alligned at the end of the hstring_private
struct and actually no reference counting is used.

Signed-off-by: Bernhard Kölbl <besentv at gmail.com>
---
 dlls/combase/string.c | 92 +++++++++++++++++++++++++------------------
 1 file changed, 53 insertions(+), 39 deletions(-)

diff --git a/dlls/combase/string.c b/dlls/combase/string.c
index 2092e4360a3..559a026fede 100644
--- a/dlls/combase/string.c
+++ b/dlls/combase/string.c
@@ -26,12 +26,15 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(winstring);
 
+#define HSTRING_REFERENCE_FLAG 1
+
 struct hstring_private
 {
-    LPWSTR buffer;
+    UINT32 flags;
     UINT32 length;
-    BOOL   reference;
-    LONG   refcount;
+    UINT32 padding1;
+    UINT32 padding2;
+    LPWSTR ptr;
 };
 
 static const WCHAR empty[1];
@@ -40,30 +43,29 @@ C_ASSERT(sizeof(struct hstring_private) <= sizeof(HSTRING_HEADER));
 
 static inline struct hstring_private *impl_from_HSTRING(HSTRING string)
 {
-   return (struct hstring_private *)string;
+    return (struct hstring_private *)string;
 }
 
 static inline struct hstring_private *impl_from_HSTRING_HEADER(HSTRING_HEADER *header)
 {
-   return (struct hstring_private *)header;
+    return (struct hstring_private *)header;
 }
 
 static inline struct hstring_private *impl_from_HSTRING_BUFFER(HSTRING_BUFFER buffer)
 {
-   return (struct hstring_private *)buffer;
+    return CONTAINING_RECORD(buffer, struct hstring_private, ptr);
 }
 
 static BOOL alloc_string(UINT32 len, HSTRING *out)
 {
     struct hstring_private *priv;
-    priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv) + (len + 1) * sizeof(*priv->buffer));
+    priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv));
     if (!priv)
         return FALSE;
-    priv->buffer = (LPWSTR)(priv + 1);
+    priv->ptr = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*priv->ptr));
     priv->length = len;
-    priv->reference = FALSE;
-    priv->refcount = 1;
-    priv->buffer[len] = '\0';
+    priv->flags = 0;
+    priv->ptr[len] = '\0';
     *out = (HSTRING)priv;
     return TRUE;
 }
@@ -90,7 +92,7 @@ HRESULT WINAPI WindowsCreateString(LPCWSTR ptr, UINT32 len,
     if (!alloc_string(len, out))
         return E_OUTOFMEMORY;
     priv = impl_from_HSTRING(*out);
-    memcpy(priv->buffer, ptr, len * sizeof(*priv->buffer));
+    memcpy(priv->ptr, ptr, len * sizeof(*priv->ptr));
     return S_OK;
 }
 
@@ -115,10 +117,10 @@ HRESULT WINAPI WindowsCreateStringReference(LPCWSTR ptr, UINT32 len,
     }
     if (ptr == NULL)
         return E_POINTER;
-    priv->buffer = (LPWSTR)ptr;
+    priv->ptr = (LPWSTR)ptr;
     priv->length = len;
-    priv->reference = TRUE;
-    *out = (HSTRING)header;
+    priv->flags = TRUE;
+    *out = (HSTRING)priv;
     return S_OK;
 }
 
@@ -127,16 +129,20 @@ HRESULT WINAPI WindowsCreateStringReference(LPCWSTR ptr, UINT32 len,
  */
 HRESULT WINAPI WindowsDeleteString(HSTRING str)
 {
-    struct hstring_private *priv = impl_from_HSTRING(str);
+    struct hstring_private *priv;
 
     TRACE("(%p)\n", str);
 
     if (str == NULL)
         return S_OK;
-    if (priv->reference)
+
+    priv = impl_from_HSTRING(str);
+
+    if(priv->flags == 0)
         return S_OK;
-    if (InterlockedDecrement(&priv->refcount) == 0)
-        HeapFree(GetProcessHeap(), 0, priv);
+
+    HeapFree(GetProcessHeap(), 0, priv);
+
     return S_OK;
 }
 
@@ -156,9 +162,9 @@ HRESULT WINAPI WindowsDuplicateString(HSTRING str, HSTRING *out)
         *out = NULL;
         return S_OK;
     }
-    if (priv->reference)
-        return WindowsCreateString(priv->buffer, priv->length, out);
-    InterlockedIncrement(&priv->refcount);
+    if (priv->flags == HSTRING_REFERENCE_FLAG)
+        return WindowsCreateString(priv->ptr, priv->length, out);
+
     *out = str;
     return S_OK;
 }
@@ -186,8 +192,8 @@ HRESULT WINAPI WindowsPreallocateStringBuffer(UINT32 len, WCHAR **outptr,
     if (!alloc_string(len, &str))
         return E_OUTOFMEMORY;
     priv = impl_from_HSTRING(str);
-    *outptr = priv->buffer;
-    *out = (HSTRING_BUFFER)str;
+    *outptr = priv->ptr;
+    *out = (HSTRING_BUFFER)&priv->ptr;
     return S_OK;
 }
 
@@ -196,9 +202,17 @@ HRESULT WINAPI WindowsPreallocateStringBuffer(UINT32 len, WCHAR **outptr,
  */
 HRESULT WINAPI WindowsDeleteStringBuffer(HSTRING_BUFFER buf)
 {
+
+    struct hstring_private *priv;
+
     TRACE("(%p)\n", buf);
 
-    return WindowsDeleteString((HSTRING)buf);
+    if(buf)
+        priv = impl_from_HSTRING_BUFFER(buf);
+    else
+        priv = NULL;
+
+    return WindowsDeleteString((HSTRING)priv);
 }
 
 /***********************************************************************
@@ -217,9 +231,9 @@ HRESULT WINAPI WindowsPromoteStringBuffer(HSTRING_BUFFER buf, HSTRING *out)
         *out = NULL;
         return S_OK;
     }
-    if (priv->buffer[priv->length] != 0 || priv->reference || priv->refcount != 1)
+    if (priv->ptr[priv->length] != 0 || priv->flags == HSTRING_REFERENCE_FLAG)
         return E_INVALIDARG;
-    *out = (HSTRING)buf;
+    *out = (HSTRING)priv;
     return S_OK;
 }
 
@@ -254,7 +268,7 @@ LPCWSTR WINAPI WindowsGetStringRawBuffer(HSTRING str, UINT32 *len)
     }
     if (len)
         *len = priv->length;
-    return priv->buffer;
+    return priv->ptr;
 }
 
 /***********************************************************************
@@ -276,7 +290,7 @@ HRESULT WINAPI WindowsStringHasEmbeddedNull(HSTRING str, BOOL *out)
     }
     for (i = 0; i < priv->length; i++)
     {
-        if (priv->buffer[i] == '\0')
+        if (priv->ptr[i] == '\0')
         {
             *out = TRUE;
             return S_OK;
@@ -305,7 +319,7 @@ HRESULT WINAPI WindowsSubstring(HSTRING str, UINT32 start, HSTRING *out)
         *out = NULL;
         return S_OK;
     }
-    return WindowsCreateString(&priv->buffer[start], len - start, out);
+    return WindowsCreateString(&priv->ptr[start], len - start, out);
 }
 
 /***********************************************************************
@@ -327,7 +341,7 @@ HRESULT WINAPI WindowsSubstringWithSpecifiedLength(HSTRING str, UINT32 start, UI
         *out = NULL;
         return S_OK;
     }
-    return WindowsCreateString(&priv->buffer[start], len, out);
+    return WindowsCreateString(&priv->ptr[start], len, out);
 }
 
 /***********************************************************************
@@ -355,8 +369,8 @@ HRESULT WINAPI WindowsConcatString(HSTRING str1, HSTRING str2, HSTRING *out)
     if (!alloc_string(priv1->length + priv2->length, out))
         return E_OUTOFMEMORY;
     priv = impl_from_HSTRING(*out);
-    memcpy(priv->buffer, priv1->buffer, priv1->length * sizeof(*priv1->buffer));
-    memcpy(priv->buffer + priv1->length, priv2->buffer, priv2->length * sizeof(*priv2->buffer));
+    memcpy(priv->ptr, priv1->ptr, priv1->length * sizeof(*priv1->ptr));
+    memcpy(priv->ptr + priv1->length, priv2->ptr, priv2->length * sizeof(*priv2->ptr));
     return S_OK;
 }
 
@@ -395,12 +409,12 @@ HRESULT WINAPI WindowsCompareStringOrdinal(HSTRING str1, HSTRING str2, INT32 *re
     }
     if (str1)
     {
-        buf1 = priv1->buffer;
+        buf1 = priv1->ptr;
         len1 = priv1->length;
     }
     if (str2)
     {
-        buf2 = priv2->buffer;
+        buf2 = priv2->ptr;
         len2 = priv2->length;
     }
     *res = CompareStringOrdinal(buf1, len1, buf2, len2, FALSE) - CSTR_EQUAL;
@@ -427,10 +441,10 @@ HRESULT WINAPI WindowsTrimStringStart(HSTRING str1, HSTRING str2, HSTRING *out)
     }
     for (start = 0; start < priv1->length; start++)
     {
-        if (!wmemchr(priv2->buffer, priv1->buffer[start], priv2->length))
+        if (!wmemchr(priv2->ptr, priv1->ptr[start], priv2->length))
             break;
     }
-    return start ? WindowsCreateString(&priv1->buffer[start], priv1->length - start, out) :
+    return start ? WindowsCreateString(&priv1->ptr[start], priv1->length - start, out) :
                    WindowsDuplicateString(str1, out);
 }
 
@@ -454,9 +468,9 @@ HRESULT WINAPI WindowsTrimStringEnd(HSTRING str1, HSTRING str2, HSTRING *out)
     }
     for (len = priv1->length; len > 0; len--)
     {
-        if (!wmemchr(priv2->buffer, priv1->buffer[len - 1], priv2->length))
+        if (!wmemchr(priv2->ptr, priv1->ptr[len - 1], priv2->length))
             break;
     }
-    return (len < priv1->length) ? WindowsCreateString(priv1->buffer, len, out) :
+    return (len < priv1->length) ? WindowsCreateString(priv1->ptr, len, out) :
                                    WindowsDuplicateString(str1, out);
 }
-- 
2.34.1




More information about the wine-devel mailing list