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@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); }