combase: Implement functions for accessing HSTRING objects.
This commit is contained in:
parent
e79460cd5c
commit
998006e41d
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue