From: Vibhav Pant vibhavp@gmail.com
--- dlls/vccorlib140/private.h | 2 + dlls/vccorlib140/tests/vccorlib.c | 31 +++++----- dlls/vccorlib140/vccorlib.c | 97 ++++++++++++++++++++++++++++++- 3 files changed, 112 insertions(+), 18 deletions(-)
diff --git a/dlls/vccorlib140/private.h b/dlls/vccorlib140/private.h index f5cb3fc69fb..e71abcc56f3 100644 --- a/dlls/vccorlib140/private.h +++ b/dlls/vccorlib140/private.h @@ -94,3 +94,5 @@ void WINAPI DECLSPEC_NORETURN __abi_WinRTraiseOutOfMemoryException(void); DEFINE_IINSPECTABLE_(pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, &impl->base_iface) #define DEFINE_IINSPECTABLE_OUTER(pfx, iface_type, impl_type, outer_iface) \ DEFINE_IINSPECTABLE_(pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, impl->outer_iface) + +DEFINE_GUID(IID_IPrintable,0xde0cbaeb,0x8065,0x4a45,0x96,0xb1,0xc9,0xd4,0x43,0xf9,0xba,0xb3); diff --git a/dlls/vccorlib140/tests/vccorlib.c b/dlls/vccorlib140/tests/vccorlib.c index 85f487a7002..14370e56f74 100644 --- a/dlls/vccorlib140/tests/vccorlib.c +++ b/dlls/vccorlib140/tests/vccorlib.c @@ -1138,8 +1138,7 @@ static void test___abi_make_type_id(void)
str = p__abi_ObjectToString(type_obj, FALSE); buf = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(buf && !wcscmp(buf, L"Platform.Type"), "got buf %s != %s\n", debugstr_w(buf), - debugstr_w(L"Platform.Type")); + ok(buf && !wcscmp(buf, L"Platform.Type"), "got buf %s != %s\n", debugstr_w(buf), debugstr_w(L"Platform.Type")); WindowsDeleteString(str);
str = p__abi_ObjectToString(type_obj, TRUE); @@ -1327,12 +1326,12 @@ static void test_CreateValue(void) { str = p__abi_ObjectToString(obj, FALSE); buf = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(buf, exp_str), "got str %s != %s\n", debugstr_hstring(str), debugstr_w(exp_str)); + ok(!wcscmp(buf, exp_str), "got str %s != %s\n", debugstr_hstring(str), debugstr_w(exp_str)); WindowsDeleteString(str);
str = p__abi_ObjectToString(obj, TRUE); buf = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(buf, exp_str), "got str %s != %s\n", debugstr_hstring(str), debugstr_w(exp_str)); + ok(!wcscmp(buf, exp_str), "got str %s != %s\n", debugstr_hstring(str), debugstr_w(exp_str)); WindowsDeleteString(str); } if (name) WindowsDeleteString(name); @@ -1426,12 +1425,12 @@ static void test_CreateValue(void)
str = p__abi_ObjectToString(obj, TRUE); buf = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(buf, L"foo"), "got buf %s\n", debugstr_w(buf)); + ok(!wcscmp(buf, L"foo"), "got buf %s\n", debugstr_w(buf)); WindowsDeleteString(str);
str = p__abi_ObjectToString(obj, FALSE); buf = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(buf, L"foo"), "got buf %s\n", debugstr_w(buf)); + ok(!wcscmp(buf, L"foo"), "got buf %s\n", debugstr_w(buf)); WindowsDeleteString(str);
count = IPropertyValue_Release(obj); @@ -1632,8 +1631,8 @@ static void test_exceptions(void) str = p__abi_ObjectToString(obj, FALSE); ok(hr == S_OK, "got hr %#lx\n", hr); bufW = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(cur_test->exp_winrt_name, bufW), "got str %s != %s\n", debugstr_hstring(str), - debugstr_w(cur_test->exp_winrt_name)); + ok(!wcscmp(cur_test->exp_winrt_name, bufW), "got str %s != %s\n", debugstr_hstring(str), + debugstr_w(cur_test->exp_winrt_name)); WindowsDeleteString(str);
/* Verify control block fields. */ @@ -1794,8 +1793,8 @@ static void test_exceptions(void)
str = p__abi_ObjectToString(inspectable, FALSE); bufW = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(cur_test->exp_winrt_name, bufW), "got str %s != %s\n", debugstr_hstring(str), - debugstr_w(cur_test->exp_winrt_name)); + ok(!wcscmp(cur_test->exp_winrt_name, bufW), "got str %s != %s\n", debugstr_hstring(str), + debugstr_w(cur_test->exp_winrt_name)); WindowsDeleteString(str);
str = p__abi_ObjectToString(inspectable, TRUE); @@ -2150,11 +2149,11 @@ static void test___abi_ObjectToString(void) impl.have_inspectable = TRUE; str = p__abi_ObjectToString(&impl.IUnknown_iface, TRUE); buf = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(buf, class_name), "Got str %s\n", debugstr_hstring(str)); + ok(!wcscmp(buf, class_name), "Got str %s\n", debugstr_hstring(str)); WindowsDeleteString(str); str = p__abi_ObjectToString(&impl.IUnknown_iface, FALSE); buf = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(buf, class_name), "Got str %s\n", debugstr_hstring(str)); + ok(!wcscmp(buf, class_name), "Got str %s\n", debugstr_hstring(str)); WindowsDeleteString(str);
/* The second parameter controls whether the IStringable/IPrintable interfaces should be used for getting the string @@ -2162,11 +2161,11 @@ static void test___abi_ObjectToString(void) impl.have_stringable = TRUE; str = p__abi_ObjectToString(&impl.IUnknown_iface, TRUE); buf = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(buf, stringable_val), "Got str %s\n", debugstr_hstring(str)); + ok(!wcscmp(buf, stringable_val), "Got str %s\n", debugstr_hstring(str)); WindowsDeleteString(str); str = p__abi_ObjectToString(&impl.IUnknown_iface, FALSE); buf = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(buf, class_name), "Got str %s\n", debugstr_hstring(str)); + ok(!wcscmp(buf, class_name), "Got str %s\n", debugstr_hstring(str)); WindowsDeleteString(str);
/* IPrintable seems to be a C++/CX specific alias for IStringable. */ @@ -2174,11 +2173,11 @@ static void test___abi_ObjectToString(void) impl.have_printable = TRUE; str = p__abi_ObjectToString(&impl.IUnknown_iface, TRUE); buf = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(buf, stringable_val), "Got str %s\n", debugstr_hstring(str)); + ok(!wcscmp(buf, stringable_val), "Got str %s\n", debugstr_hstring(str)); WindowsDeleteString(str); str = p__abi_ObjectToString(&impl.IUnknown_iface, FALSE); buf = WindowsGetStringRawBuffer(str, NULL); - todo_wine ok(!wcscmp(buf, class_name), "Got str %s\n", debugstr_hstring(str)); + ok(!wcscmp(buf, class_name), "Got str %s\n", debugstr_hstring(str)); WindowsDeleteString(str);
ok(impl.ref == 1, "got ref %lu\n", impl.ref); diff --git a/dlls/vccorlib140/vccorlib.c b/dlls/vccorlib140/vccorlib.c index b875801176b..a437c5f590c 100644 --- a/dlls/vccorlib140/vccorlib.c +++ b/dlls/vccorlib140/vccorlib.c @@ -613,8 +613,101 @@ void *WINAPI CreateValue(int typecode, const void *val)
HSTRING WINAPI __abi_ObjectToString(IUnknown *obj, bool try_stringable) { - FIXME("(%p, %d): stub!\n", obj, try_stringable); - return NULL; + IInspectable *inspectable; + IPropertyValue *propval; + IStringable *stringable; + HSTRING val = NULL; + HRESULT hr = S_OK; + + TRACE("(%p, %d)\n", obj, try_stringable); + + if (!obj) return NULL; + /* If try_stringable is true, native will first query for IStringable, and then IPrintable (which is just an alias + * for IStringable). */ + if (try_stringable && (SUCCEEDED(IUnknown_QueryInterface(obj, &IID_IStringable, (void **)&stringable)) || + SUCCEEDED(IUnknown_QueryInterface(obj, &IID_IPrintable, (void **)&stringable)))) + { + hr = IStringable_ToString(stringable, &val); + IStringable_Release(stringable); + } + /* Next, native checks if this is an boxed type (IPropertyValue) storing a numeric-like or string value. */ + else if (SUCCEEDED(IUnknown_QueryInterface(obj, &IID_IPropertyValue, (void **)&propval))) + { + PropertyType type; + WCHAR buf[100]; + int len; + + if (SUCCEEDED((hr = IPropertyValue_get_Type(propval, &type)))) + { +#define PROPVAL_SIMPLE(prop_type, c_type, fmt) \ + case PropertyType_##prop_type: \ + { \ + c_type prop_type_##val; \ + if (SUCCEEDED(hr = IPropertyValue_Get##prop_type(propval, &prop_type_##val))) \ + { \ + len = swprintf(buf, ARRAY_SIZE(buf), (fmt), prop_type_##val); \ + hr = WindowsCreateString(buf, len, &val); \ + } \ + break; \ + } + switch (type) + { + PROPVAL_SIMPLE(Char16, WCHAR, L"%c") + PROPVAL_SIMPLE(UInt8, UINT8, L"%hhu") + PROPVAL_SIMPLE(Int16, INT16, L"%hd") + PROPVAL_SIMPLE(UInt16, UINT16, L"%hu") + PROPVAL_SIMPLE(Int32, INT32, L"%I32d") + PROPVAL_SIMPLE(UInt32, UINT32, L"%I32u") + PROPVAL_SIMPLE(Int64, INT64, L"%I64d") + PROPVAL_SIMPLE(UInt64, UINT64, L"%I64u") + PROPVAL_SIMPLE(Single, FLOAT, L"%g") + PROPVAL_SIMPLE(Double, DOUBLE, L"%g") + case PropertyType_Boolean: + { + boolean bool_val; + + if (SUCCEEDED(hr = IPropertyValue_GetBoolean(propval, &bool_val))) + { + len = swprintf(buf, ARRAY_SIZE(buf), bool_val ? L"true" : L"false"); + hr = WindowsCreateString(buf, len, &val); + } + break; + } + case PropertyType_String: + hr = IPropertyValue_GetString(propval, &val); + break; + case PropertyType_Guid: + { + GUID guid; + + if (SUCCEEDED(hr = IPropertyValue_GetGuid(propval, &guid))) + { + len = swprintf(buf, ARRAY_SIZE(buf), L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], + guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); + hr = WindowsCreateString(buf, len, &val); + } + break; + } + default: + /* For other types, use the WinRT class name. */ + hr = IPropertyValue_GetRuntimeClassName(propval, &val); + } +#undef PROPVAL_SIMPLE + } + IPropertyValue_Release(propval); + } + /* Finally, if this is an IInspectable, use the WinRT class name. Otherwise, return NULL. */ + else if (SUCCEEDED(IUnknown_QueryInterface(obj, &IID_IInspectable, (void **)&inspectable))) + { + hr = IInspectable_GetRuntimeClassName(inspectable, &val); + IInspectable_Release(inspectable); + } + + if (FAILED(hr)) + __abi_WinRTraiseCOMException(hr); + + return val; }
HSTRING __cdecl Guid_ToString(const GUID *this)