| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/win/scoped_hstring.h" |
| |
| #include <winstring.h> |
| |
| #include "base/strings/string_piece.h" |
| #include "base/strings/utf_string_conversions.h" |
| |
| namespace base { |
| |
| namespace { |
| |
| static bool g_load_succeeded = false; |
| |
| FARPROC LoadComBaseFunction(const char* function_name) { |
| static HMODULE const handle = ::LoadLibrary(L"combase.dll"); |
| return handle ? ::GetProcAddress(handle, function_name) : nullptr; |
| } |
| |
| decltype(&::WindowsCreateString) GetWindowsCreateString() { |
| static decltype(&::WindowsCreateString) const function = |
| reinterpret_cast<decltype(&::WindowsCreateString)>( |
| LoadComBaseFunction("WindowsCreateString")); |
| return function; |
| } |
| |
| decltype(&::WindowsDeleteString) GetWindowsDeleteString() { |
| static decltype(&::WindowsDeleteString) const function = |
| reinterpret_cast<decltype(&::WindowsDeleteString)>( |
| LoadComBaseFunction("WindowsDeleteString")); |
| return function; |
| } |
| |
| decltype(&::WindowsGetStringRawBuffer) GetWindowsGetStringRawBuffer() { |
| static decltype(&::WindowsGetStringRawBuffer) const function = |
| reinterpret_cast<decltype(&::WindowsGetStringRawBuffer)>( |
| LoadComBaseFunction("WindowsGetStringRawBuffer")); |
| return function; |
| } |
| |
| HRESULT WindowsCreateString(const base::char16* src, |
| uint32_t len, |
| HSTRING* out_hstr) { |
| decltype(&::WindowsCreateString) create_string_func = |
| GetWindowsCreateString(); |
| if (!create_string_func) |
| return E_FAIL; |
| return create_string_func(src, len, out_hstr); |
| } |
| |
| HRESULT WindowsDeleteString(HSTRING hstr) { |
| decltype(&::WindowsDeleteString) delete_string_func = |
| GetWindowsDeleteString(); |
| if (!delete_string_func) |
| return E_FAIL; |
| return delete_string_func(hstr); |
| } |
| |
| const base::char16* WindowsGetStringRawBuffer(HSTRING hstr, uint32_t* out_len) { |
| decltype(&::WindowsGetStringRawBuffer) get_string_raw_buffer_func = |
| GetWindowsGetStringRawBuffer(); |
| if (!get_string_raw_buffer_func) { |
| *out_len = 0; |
| return nullptr; |
| } |
| return get_string_raw_buffer_func(hstr, out_len); |
| } |
| |
| } // namespace |
| |
| namespace internal { |
| |
| // static |
| void ScopedHStringTraits::Free(HSTRING hstr) { |
| base::WindowsDeleteString(hstr); |
| } |
| |
| } // namespace internal |
| |
| namespace win { |
| |
| // static |
| ScopedHString ScopedHString::Create(StringPiece16 str) { |
| DCHECK(g_load_succeeded); |
| HSTRING hstr; |
| HRESULT hr = base::WindowsCreateString(str.data(), str.length(), &hstr); |
| if (SUCCEEDED(hr)) |
| return ScopedHString(hstr); |
| DLOG(ERROR) << "Failed to create HSTRING" << std::hex << hr; |
| return ScopedHString(nullptr); |
| } |
| |
| ScopedHString ScopedHString::Create(StringPiece str) { |
| return Create(UTF8ToWide(str)); |
| } |
| |
| ScopedHString::ScopedHString(HSTRING hstr) : ScopedGeneric(hstr) { |
| DCHECK(g_load_succeeded); |
| } |
| |
| // static |
| bool ScopedHString::ResolveCoreWinRTStringDelayload() { |
| // TODO(finnur): Add AssertIOAllowed once crbug.com/770193 is fixed. |
| |
| static const bool load_succeeded = []() { |
| bool success = GetWindowsCreateString() && GetWindowsDeleteString() && |
| GetWindowsGetStringRawBuffer(); |
| g_load_succeeded = success; |
| return success; |
| }(); |
| return load_succeeded; |
| } |
| |
| StringPiece16 ScopedHString::Get() const { |
| UINT32 length = 0; |
| const wchar_t* buffer = base::WindowsGetStringRawBuffer(get(), &length); |
| return StringPiece16(buffer, length); |
| } |
| |
| std::string ScopedHString::GetAsUTF8() const { |
| std::string result; |
| const StringPiece16 wide_string = Get(); |
| WideToUTF8(wide_string.data(), wide_string.length(), &result); |
| return result; |
| } |
| |
| } // namespace win |
| } // namespace base |