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