[PATCH v3 5/7] combase: Implement creation and deletion of HSTRING objects.

Martin Storsjo martin at martin.st
Tue Dec 9 02:36:48 CST 2014


---
No changes since v2.
---
 configure.ac                                       |   1 +
 .../api-ms-win-core-winrt-string-l1-1-0.spec       |   8 +-
 dlls/combase/Makefile.in                           |   3 +-
 dlls/combase/combase.spec                          |   8 +-
 dlls/combase/string.c                              | 143 +++++++++++++++++++++
 dlls/combase/tests/Makefile.in                     |   4 +
 dlls/combase/tests/string.c                        | 128 ++++++++++++++++++
 tools/make_specfiles                               |   1 +
 8 files changed, 287 insertions(+), 9 deletions(-)
 create mode 100644 dlls/combase/string.c
 create mode 100644 dlls/combase/tests/Makefile.in
 create mode 100644 dlls/combase/tests/string.c

diff --git a/configure.ac b/configure.ac
index 8f28e0f..97da0d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2758,6 +2758,7 @@ WINE_CONFIG_DLL(cards,,[implib])
 WINE_CONFIG_DLL(cfgmgr32,,[implib])
 WINE_CONFIG_DLL(clusapi,,[implib])
 WINE_CONFIG_DLL(combase)
+WINE_CONFIG_TEST(dlls/combase/tests)
 WINE_CONFIG_DLL(comcat)
 WINE_CONFIG_TEST(dlls/comcat/tests)
 WINE_CONFIG_DLL(comctl32,,[implib,po])
diff --git a/dlls/api-ms-win-core-winrt-string-l1-1-0/api-ms-win-core-winrt-string-l1-1-0.spec b/dlls/api-ms-win-core-winrt-string-l1-1-0/api-ms-win-core-winrt-string-l1-1-0.spec
index bc9035c..7658867 100644
--- a/dlls/api-ms-win-core-winrt-string-l1-1-0/api-ms-win-core-winrt-string-l1-1-0.spec
+++ b/dlls/api-ms-win-core-winrt-string-l1-1-0/api-ms-win-core-winrt-string-l1-1-0.spec
@@ -8,11 +8,11 @@
 @ stub HSTRING_UserUnmarshal64
 @ stub WindowsCompareStringOrdinal
 @ stub WindowsConcatString
-@ stub WindowsCreateString
-@ stub WindowsCreateStringReference
-@ stub WindowsDeleteString
+@ stdcall WindowsCreateString(ptr long ptr) combase.WindowsCreateString
+@ stdcall WindowsCreateStringReference(wstr long ptr ptr) combase.WindowsCreateStringReference
+@ stdcall WindowsDeleteString(ptr) combase.WindowsDeleteString
 @ stub WindowsDeleteStringBuffer
-@ stub WindowsDuplicateString
+@ stdcall WindowsDuplicateString(ptr ptr) combase.WindowsDuplicateString
 @ stub WindowsGetStringLen
 @ stub WindowsGetStringRawBuffer
 @ stub WindowsInspectString
diff --git a/dlls/combase/Makefile.in b/dlls/combase/Makefile.in
index 79d22a1..c5ab8d2 100644
--- a/dlls/combase/Makefile.in
+++ b/dlls/combase/Makefile.in
@@ -2,4 +2,5 @@ MODULE    = combase.dll
 IMPORTS   = ole32
 
 C_SRCS = \
-	roapi.c
+	roapi.c \
+	string.c
diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec
index 652eff6..f399d25 100644
--- a/dlls/combase/combase.spec
+++ b/dlls/combase/combase.spec
@@ -289,11 +289,11 @@
 @ stub WdtpInterfacePointer_UserUnmarshal64
 @ stub WindowsCompareStringOrdinal
 @ stub WindowsConcatString
-@ stub WindowsCreateString
-@ stub WindowsCreateStringReference
-@ stub WindowsDeleteString
+@ stdcall WindowsCreateString(ptr long ptr)
+@ stdcall WindowsCreateStringReference(wstr long ptr ptr)
+@ stdcall WindowsDeleteString(ptr)
 @ stub WindowsDeleteStringBuffer
-@ stub WindowsDuplicateString
+@ stdcall WindowsDuplicateString(ptr ptr)
 @ stub WindowsGetStringLen
 @ stub WindowsGetStringRawBuffer
 @ stub WindowsInspectString
diff --git a/dlls/combase/string.c b/dlls/combase/string.c
new file mode 100644
index 0000000..ee2f5c0
--- /dev/null
+++ b/dlls/combase/string.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2014 Martin Storsjo
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "winerror.h"
+#include "hstring.h"
+#include "windows.h"
+#include "wine/debug.h"
+#include <string.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(combase);
+
+struct hstring_private
+{
+    LPWSTR buffer;
+    UINT32 length;
+    BOOL   reference;
+    LONG   refcount;
+};
+
+C_ASSERT(sizeof(struct hstring_private) <= sizeof(HSTRING_HEADER));
+
+static inline struct hstring_private *impl_from_HSTRING(HSTRING string)
+{
+   return (struct hstring_private *)string;
+}
+
+static inline struct hstring_private *impl_from_HSTRING_HEADER(HSTRING_HEADER *header)
+{
+   return (struct hstring_private *)header;
+}
+
+static BOOL alloc_string(UINT32 len, HSTRING *out)
+{
+    struct hstring_private *priv;
+    priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv) + (len + 1) * sizeof(*priv->buffer));
+    if (!priv)
+        return FALSE;
+    priv->buffer = (LPWSTR)(priv + 1);
+    priv->length = len;
+    priv->reference = FALSE;
+    priv->refcount = 1;
+    priv->buffer[len] = '\0';
+    *out = (HSTRING)priv;
+    return TRUE;
+}
+
+/***********************************************************************
+ *      WindowsCreateString (combase.@)
+ */
+HRESULT WINAPI WindowsCreateString(LPCWSTR ptr, UINT32 len,
+                                   HSTRING *out)
+{
+    struct hstring_private *priv;
+    if (out == NULL)
+        return E_INVALIDARG;
+    if (ptr == NULL && len > 0)
+        return E_POINTER;
+    if (len == 0)
+    {
+        *out = NULL;
+        return S_OK;
+    }
+    if (!alloc_string(len, out))
+        return E_OUTOFMEMORY;
+    priv = impl_from_HSTRING(*out);
+    memcpy(priv->buffer, ptr, len * sizeof(*priv->buffer));
+    return S_OK;
+}
+
+/***********************************************************************
+ *      WindowsCreateStringReference (combase.@)
+ */
+HRESULT WINAPI WindowsCreateStringReference(LPCWSTR ptr, UINT32 len,
+                                            HSTRING_HEADER *header, HSTRING *out)
+{
+    struct hstring_private *priv = impl_from_HSTRING_HEADER(header);
+    if (out == NULL || header == NULL)
+        return E_INVALIDARG;
+    if (ptr == NULL && len > 0)
+        return E_POINTER;
+    if (ptr[len] != '\0')
+        return E_INVALIDARG;
+    if (len == 0)
+    {
+        *out = NULL;
+        return S_OK;
+    }
+    priv->buffer = (LPWSTR)ptr;
+    priv->length = len;
+    priv->reference = TRUE;
+    *out = (HSTRING)header;
+    return S_OK;
+}
+
+/***********************************************************************
+ *      WindowsDeleteString (combase.@)
+ */
+HRESULT WINAPI WindowsDeleteString(HSTRING str)
+{
+    struct hstring_private *priv = impl_from_HSTRING(str);
+    if (str == NULL)
+        return S_OK;
+    if (priv->reference)
+        return S_OK;
+    if (InterlockedDecrement(&priv->refcount) == 0)
+        HeapFree(GetProcessHeap(), 0, priv);
+    return S_OK;
+}
+
+/***********************************************************************
+ *      WindowsDuplicateString (combase.@)
+ */
+HRESULT WINAPI WindowsDuplicateString(HSTRING str, HSTRING *out)
+{
+    struct hstring_private *priv = impl_from_HSTRING(str);
+    if (out == NULL)
+        return E_INVALIDARG;
+    if (str == NULL)
+    {
+        *out = NULL;
+        return S_OK;
+    }
+    if (priv->reference)
+        return WindowsCreateString(priv->buffer, priv->length, out);
+    InterlockedIncrement(&priv->refcount);
+    *out = str;
+    return S_OK;
+}
diff --git a/dlls/combase/tests/Makefile.in b/dlls/combase/tests/Makefile.in
new file mode 100644
index 0000000..3e7ecab
--- /dev/null
+++ b/dlls/combase/tests/Makefile.in
@@ -0,0 +1,4 @@
+TESTDLL   = combase.dll
+
+C_SRCS = \
+	string.c
diff --git a/dlls/combase/tests/string.c b/dlls/combase/tests/string.c
new file mode 100644
index 0000000..01a63f7
--- /dev/null
+++ b/dlls/combase/tests/string.c
@@ -0,0 +1,128 @@
+/*
+ * Unit tests for Windows String functions
+ *
+ * Copyright (c) 2014 Martin Storsjo
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winstring.h"
+
+#include "wine/test.h"
+
+static HRESULT (WINAPI *pWindowsCreateString)(LPCWSTR, UINT32, HSTRING *);
+static HRESULT (WINAPI *pWindowsCreateStringReference)(LPCWSTR, UINT32, HSTRING_HEADER *, HSTRING *);
+static HRESULT (WINAPI *pWindowsDeleteString)(HSTRING);
+static HRESULT (WINAPI *pWindowsDuplicateString)(HSTRING, HSTRING *);
+
+#define SET(x) p##x = (void*)GetProcAddress(hmod, #x)
+
+static BOOL init_functions(void)
+{
+    HMODULE hmod = LoadLibraryA("combase.dll");
+    if (!hmod)
+    {
+        win_skip("Failed to load combase.dll, skipping tests\n");
+        return FALSE;
+    }
+    SET(WindowsCreateString);
+    SET(WindowsCreateStringReference);
+    SET(WindowsDeleteString);
+    SET(WindowsDuplicateString);
+    return TRUE;
+}
+
+#undef SET
+
+
+static const WCHAR input_string[] = { 'a', 'b', 'c', 'd', 'e', 'f', '\0' };
+static const WCHAR input_empty_string[] = { '\0' };
+
+static void test_create_delete(void)
+{
+    HSTRING str;
+    HSTRING_HEADER header;
+
+    /* Test normal creation of a string */
+    ok(pWindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string\n");
+    ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n");
+    /* Test error handling in WindowsCreateString */
+    ok(pWindowsCreateString(input_string, 6, NULL) == E_INVALIDARG, "Incorrect error handling\n");
+    ok(pWindowsCreateString(NULL, 6, &str) == E_POINTER, "Incorrect error handling\n");
+
+    /* Test handling of a NULL string */
+    ok(pWindowsDeleteString(NULL) == S_OK, "Failed to delete null string\n");
+
+    /* Test creation of a string reference */
+    ok(pWindowsCreateStringReference(input_string, 6, &header, &str) == S_OK, "Failed to create string ref\n");
+    ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string ref\n");
+
+    /* Test error handling in WindowsCreateStringReference */
+    /* Strings to CreateStringReference must be null terminated with the correct
+     * length. According to MSDN this should be E_INVALIDARG, but it returns
+     * 0x80000017 in practice. */
+    ok(FAILED(pWindowsCreateStringReference(input_string, 5, &header, &str)), "Incorrect error handling\n");
+    ok(pWindowsCreateStringReference(input_string, 6, NULL, &str) == E_INVALIDARG, "Incorrect error handling\n");
+    ok(pWindowsCreateStringReference(input_string, 6, &header, NULL) == E_INVALIDARG, "Incorrect error handling\n");
+    ok(pWindowsCreateStringReference(NULL, 6, &header, &str) == E_POINTER, "Incorrect error handling\n");
+
+    /* Test creating a string without a null-termination at the specified length */
+    ok(pWindowsCreateString(input_string, 3, &str) == S_OK, "Failed to create string\n");
+    ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n");
+
+    /* Test an empty string */
+    ok(pWindowsCreateString(input_empty_string, 0, &str) == S_OK, "Failed to create string\n");
+    ok(str == NULL, "Empty string not a null string\n");
+    ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n");
+
+    ok(pWindowsCreateStringReference(input_empty_string, 0, &header, &str) == S_OK, "Failed to create string\n");
+    ok(str == NULL, "Empty string not a null string\n");
+    ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n");
+}
+
+static void test_duplicate(void)
+{
+    HSTRING str, str2;
+    HSTRING_HEADER header;
+    ok(pWindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string\n");
+    ok(pWindowsDuplicateString(str, NULL) == E_INVALIDARG, "Incorrect error handling\n");
+    ok(pWindowsDuplicateString(str, &str2) == S_OK, "Failed to duplicate string\n");
+    ok(str == str2, "Duplicated string created new string\n");
+    ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n");
+    ok(pWindowsDeleteString(str2) == S_OK, "Failed to delete string\n");
+
+    ok(pWindowsCreateStringReference(input_string, 6, &header, &str) == S_OK, "Failed to create string ref\n");
+    ok(pWindowsDuplicateString(str, &str2) == S_OK, "Failed to duplicate string\n");
+    ok(str != str2, "Duplicated string ref didn't create new string\n");
+    ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n");
+    ok(pWindowsDeleteString(str2) == S_OK, "Failed to delete string ref\n");
+
+    ok(pWindowsDuplicateString(NULL, &str2) == S_OK, "Failed to duplicate NULL string\n");
+    ok(str2 == NULL, "Duplicated string created new string\n");
+    ok(pWindowsDeleteString(str2) == S_OK, "Failed to delete string\n");
+}
+
+START_TEST(string)
+{
+    if (!init_functions())
+        return;
+    test_create_delete();
+    test_duplicate();
+}
diff --git a/tools/make_specfiles b/tools/make_specfiles
index 3c4f2b6..9fa4440 100755
--- a/tools/make_specfiles
+++ b/tools/make_specfiles
@@ -215,6 +215,7 @@ my @dll_groups =
  [
   "combase",
   "api-ms-win-core-winrt-l1-1-0",
+  "api-ms-win-core-winrt-string-l1-1-0",
  ],
 );
 
-- 
1.8.1.2




More information about the wine-patches mailing list