combase: Implement creation and deletion of HSTRING objects.

This commit is contained in:
Martin Storsjo 2014-12-15 10:24:48 +02:00 committed by Alexandre Julliard
parent e85db0891b
commit e79460cd5c
9 changed files with 289 additions and 9 deletions

1
configure vendored
View File

@ -16942,6 +16942,7 @@ wine_fn_config_dll cards enable_cards implib
wine_fn_config_dll cfgmgr32 enable_cfgmgr32 implib
wine_fn_config_dll clusapi enable_clusapi implib
wine_fn_config_dll combase enable_combase
wine_fn_config_test dlls/combase/tests combase_test
wine_fn_config_dll comcat enable_comcat
wine_fn_config_test dlls/comcat/tests comcat_test
wine_fn_config_dll comctl32 enable_comctl32 implib,po

View File

@ -2767,6 +2767,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])

View File

@ -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

View File

@ -2,4 +2,5 @@ MODULE = combase.dll
IMPORTS = ole32
C_SRCS = \
roapi.c
roapi.c \
string.c

View File

@ -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

144
dlls/combase/string.c Normal file
View File

@ -0,0 +1,144 @@
/*
* 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 <string.h>
#include "windows.h"
#include "winerror.h"
#include "hstring.h"
#include "wine/debug.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;
}

View File

@ -0,0 +1,4 @@
TESTDLL = combase.dll
C_SRCS = \
string.c

128
dlls/combase/tests/string.c Normal file
View File

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

View File

@ -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",
],
);