combase: Implement functions for accessing HSTRING objects.

This commit is contained in:
Martin Storsjo 2014-12-15 10:24:49 +02:00 committed by Alexandre Julliard
parent e79460cd5c
commit 998006e41d
4 changed files with 139 additions and 9 deletions

View File

@ -13,14 +13,14 @@
@ stdcall WindowsDeleteString(ptr) combase.WindowsDeleteString @ stdcall WindowsDeleteString(ptr) combase.WindowsDeleteString
@ stub WindowsDeleteStringBuffer @ stub WindowsDeleteStringBuffer
@ stdcall WindowsDuplicateString(ptr ptr) combase.WindowsDuplicateString @ stdcall WindowsDuplicateString(ptr ptr) combase.WindowsDuplicateString
@ stub WindowsGetStringLen @ stdcall WindowsGetStringLen(ptr) combase.WindowsGetStringLen
@ stub WindowsGetStringRawBuffer @ stdcall WindowsGetStringRawBuffer(ptr ptr) combase.WindowsGetStringRawBuffer
@ stub WindowsInspectString @ stub WindowsInspectString
@ stub WindowsIsStringEmpty @ stdcall WindowsIsStringEmpty(ptr) combase.WindowsIsStringEmpty
@ stub WindowsPreallocateStringBuffer @ stub WindowsPreallocateStringBuffer
@ stub WindowsPromoteStringBuffer @ stub WindowsPromoteStringBuffer
@ stub WindowsReplaceString @ stub WindowsReplaceString
@ stub WindowsStringHasEmbeddedNull @ stdcall WindowsStringHasEmbeddedNull(ptr ptr) combase.WindowsStringHasEmbeddedNull
@ stub WindowsSubstring @ stub WindowsSubstring
@ stub WindowsSubstringWithSpecifiedLength @ stub WindowsSubstringWithSpecifiedLength
@ stub WindowsTrimStringEnd @ stub WindowsTrimStringEnd

View File

@ -294,14 +294,14 @@
@ stdcall WindowsDeleteString(ptr) @ stdcall WindowsDeleteString(ptr)
@ stub WindowsDeleteStringBuffer @ stub WindowsDeleteStringBuffer
@ stdcall WindowsDuplicateString(ptr ptr) @ stdcall WindowsDuplicateString(ptr ptr)
@ stub WindowsGetStringLen @ stdcall WindowsGetStringLen(ptr)
@ stub WindowsGetStringRawBuffer @ stdcall WindowsGetStringRawBuffer(ptr ptr)
@ stub WindowsInspectString @ stub WindowsInspectString
@ stub WindowsIsStringEmpty @ stdcall WindowsIsStringEmpty(ptr)
@ stub WindowsPreallocateStringBuffer @ stub WindowsPreallocateStringBuffer
@ stub WindowsPromoteStringBuffer @ stub WindowsPromoteStringBuffer
@ stub WindowsReplaceString @ stub WindowsReplaceString
@ stub WindowsStringHasEmbeddedNull @ stdcall WindowsStringHasEmbeddedNull(ptr ptr)
@ stub WindowsSubstring @ stub WindowsSubstring
@ stub WindowsSubstringWithSpecifiedLength @ stub WindowsSubstringWithSpecifiedLength
@ stub WindowsTrimStringEnd @ stub WindowsTrimStringEnd

View File

@ -33,6 +33,8 @@ struct hstring_private
LONG refcount; LONG refcount;
}; };
static const WCHAR empty[1];
C_ASSERT(sizeof(struct hstring_private) <= sizeof(HSTRING_HEADER)); C_ASSERT(sizeof(struct hstring_private) <= sizeof(HSTRING_HEADER));
static inline struct hstring_private *impl_from_HSTRING(HSTRING string) static inline struct hstring_private *impl_from_HSTRING(HSTRING string)
@ -142,3 +144,68 @@ HRESULT WINAPI WindowsDuplicateString(HSTRING str, HSTRING *out)
*out = str; *out = str;
return S_OK; return S_OK;
} }
/***********************************************************************
* WindowsGetStringLen (combase.@)
*/
UINT32 WINAPI WindowsGetStringLen(HSTRING str)
{
struct hstring_private *priv = impl_from_HSTRING(str);
if (str == NULL)
return 0;
return priv->length;
}
/***********************************************************************
* WindowsGetStringRawBuffer (combase.@)
*/
LPCWSTR WINAPI WindowsGetStringRawBuffer(HSTRING str, UINT32 *len)
{
struct hstring_private *priv = impl_from_HSTRING(str);
if (str == NULL)
{
if (len)
*len = 0;
return empty;
}
if (len)
*len = priv->length;
return priv->buffer;
}
/***********************************************************************
* WindowsStringHasEmbeddedNull (combase.@)
*/
HRESULT WINAPI WindowsStringHasEmbeddedNull(HSTRING str, BOOL *out)
{
UINT32 i;
struct hstring_private *priv = impl_from_HSTRING(str);
if (out == NULL)
return E_INVALIDARG;
if (str == NULL)
{
*out = FALSE;
return S_OK;
}
for (i = 0; i < priv->length; i++)
{
if (priv->buffer[i] == '\0')
{
*out = TRUE;
return S_OK;
}
}
*out = FALSE;
return S_OK;
}
/***********************************************************************
* WindowsIsStringEmpty (combase.@)
*/
BOOL WINAPI WindowsIsStringEmpty(HSTRING str)
{
struct hstring_private *priv = impl_from_HSTRING(str);
if (str == NULL)
return TRUE;
return priv->length == 0;
}

View File

@ -31,6 +31,10 @@ static HRESULT (WINAPI *pWindowsCreateString)(LPCWSTR, UINT32, HSTRING *);
static HRESULT (WINAPI *pWindowsCreateStringReference)(LPCWSTR, UINT32, HSTRING_HEADER *, HSTRING *); static HRESULT (WINAPI *pWindowsCreateStringReference)(LPCWSTR, UINT32, HSTRING_HEADER *, HSTRING *);
static HRESULT (WINAPI *pWindowsDeleteString)(HSTRING); static HRESULT (WINAPI *pWindowsDeleteString)(HSTRING);
static HRESULT (WINAPI *pWindowsDuplicateString)(HSTRING, HSTRING *); static HRESULT (WINAPI *pWindowsDuplicateString)(HSTRING, HSTRING *);
static UINT32 (WINAPI *pWindowsGetStringLen)(HSTRING);
static LPCWSTR (WINAPI *pWindowsGetStringRawBuffer)(HSTRING, UINT32 *);
static BOOL (WINAPI *pWindowsIsStringEmpty)(HSTRING);
static HRESULT (WINAPI *pWindowsStringHasEmbeddedNull)(HSTRING, BOOL *);
#define SET(x) p##x = (void*)GetProcAddress(hmod, #x) #define SET(x) p##x = (void*)GetProcAddress(hmod, #x)
@ -46,14 +50,42 @@ static BOOL init_functions(void)
SET(WindowsCreateStringReference); SET(WindowsCreateStringReference);
SET(WindowsDeleteString); SET(WindowsDeleteString);
SET(WindowsDuplicateString); SET(WindowsDuplicateString);
SET(WindowsGetStringLen);
SET(WindowsGetStringRawBuffer);
SET(WindowsIsStringEmpty);
SET(WindowsStringHasEmbeddedNull);
return TRUE; return TRUE;
} }
#undef SET #undef SET
static const WCHAR input_string[] = { 'a', 'b', 'c', 'd', 'e', 'f', '\0' }; #define check_string(str, content, length, has_null) _check_string(__LINE__, str, content, length, has_null)
static void _check_string(int line, HSTRING str, LPCWSTR content, UINT32 length, BOOL has_null)
{
BOOL out_null;
BOOL empty = length == 0;
UINT32 out_length;
LPCWSTR ptr;
ok_(__FILE__, line)(pWindowsIsStringEmpty(str) == empty, "WindowsIsStringEmpty failed\n");
ok_(__FILE__, line)(pWindowsStringHasEmbeddedNull(str, &out_null) == S_OK, "pWindowsStringHasEmbeddedNull failed\n");
ok_(__FILE__, line)(out_null == has_null, "WindowsStringHasEmbeddedNull failed\n");
ok_(__FILE__, line)(pWindowsGetStringLen(str) == length, "WindowsGetStringLen failed\n");
ptr = pWindowsGetStringRawBuffer(str, &out_length);
/* WindowsGetStringRawBuffer should return a non-null, null terminated empty string
* even if str is NULL. */
ok_(__FILE__, line)(ptr != NULL, "WindowsGetStringRawBuffer returned null\n");
ok_(__FILE__, line)(out_length == length, "WindowsGetStringRawBuffer returned incorrect length\n");
ptr = pWindowsGetStringRawBuffer(str, NULL);
ok_(__FILE__, line)(ptr != NULL, "WindowsGetStringRawBuffer returned null\n");
ok_(__FILE__, line)(ptr[length] == '\0', "WindowsGetStringRawBuffer doesn't return a null terminated buffer\n");
ok_(__FILE__, line)(memcmp(ptr, content, sizeof(*content) * length) == 0, "Incorrect string content\n");
}
static const WCHAR input_string[] = { 'a', 'b', 'c', 'd', 'e', 'f', '\0', '\0' };
static const WCHAR input_empty_string[] = { '\0' }; static const WCHAR input_empty_string[] = { '\0' };
static const WCHAR input_embed_null[] = { 'a', '\0', 'c', '\0', 'e', 'f', '\0' };
static void test_create_delete(void) static void test_create_delete(void)
{ {
@ -62,6 +94,7 @@ static void test_create_delete(void)
/* Test normal creation of a string */ /* Test normal creation of a string */
ok(pWindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string\n"); ok(pWindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string\n");
check_string(str, input_string, 6, FALSE);
ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n"); ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n");
/* Test error handling in WindowsCreateString */ /* Test error handling in WindowsCreateString */
ok(pWindowsCreateString(input_string, 6, NULL) == E_INVALIDARG, "Incorrect error handling\n"); ok(pWindowsCreateString(input_string, 6, NULL) == E_INVALIDARG, "Incorrect error handling\n");
@ -72,6 +105,7 @@ static void test_create_delete(void)
/* Test creation of a string reference */ /* Test creation of a string reference */
ok(pWindowsCreateStringReference(input_string, 6, &header, &str) == S_OK, "Failed to create string ref\n"); ok(pWindowsCreateStringReference(input_string, 6, &header, &str) == S_OK, "Failed to create string ref\n");
check_string(str, input_string, 6, FALSE);
ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string ref\n"); ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string ref\n");
/* Test error handling in WindowsCreateStringReference */ /* Test error handling in WindowsCreateStringReference */
@ -85,6 +119,7 @@ static void test_create_delete(void)
/* Test creating a string without a null-termination at the specified length */ /* 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(pWindowsCreateString(input_string, 3, &str) == S_OK, "Failed to create string\n");
check_string(str, input_string, 3, FALSE);
ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n"); ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n");
/* Test an empty string */ /* Test an empty string */
@ -119,10 +154,38 @@ static void test_duplicate(void)
ok(pWindowsDeleteString(str2) == S_OK, "Failed to delete string\n"); ok(pWindowsDeleteString(str2) == S_OK, "Failed to delete string\n");
} }
static void test_access(void)
{
HSTRING str;
HSTRING_HEADER header;
/* Test handling of a NULL string */
check_string(NULL, NULL, 0, FALSE);
/* Test strings with embedded null chars */
ok(pWindowsCreateString(input_embed_null, 6, &str) == S_OK, "Failed to create string\n");
check_string(str, input_embed_null, 6, TRUE);
ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n");
ok(pWindowsCreateStringReference(input_embed_null, 6, &header, &str) == S_OK, "Failed to create string ref\n");
check_string(str, input_embed_null, 6, TRUE);
ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string ref\n");
/* Test normal creation of a string with trailing null */
ok(pWindowsCreateString(input_string, 7, &str) == S_OK, "Failed to create string\n");
check_string(str, input_string, 7, TRUE);
ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string\n");
ok(pWindowsCreateStringReference(input_string, 7, &header, &str) == S_OK, "Failed to create string ref\n");
check_string(str, input_string, 7, TRUE);
ok(pWindowsDeleteString(str) == S_OK, "Failed to delete string ref\n");
}
START_TEST(string) START_TEST(string)
{ {
if (!init_functions()) if (!init_functions())
return; return;
test_create_delete(); test_create_delete();
test_duplicate(); test_duplicate();
test_access();
} }