Chromium Code Reviews| Index: media/midi/midi_manager_winrt.cc |
| diff --git a/media/midi/midi_manager_winrt.cc b/media/midi/midi_manager_winrt.cc |
| index 11841cbde431cb09c8c6a70dee481c8fe16a081d..ac1dd24d4aedaf3aeaf1a08e4fa11a0a460c598d 100644 |
| --- a/media/midi/midi_manager_winrt.cc |
| +++ b/media/midi/midi_manager_winrt.cc |
| @@ -15,6 +15,7 @@ |
| #include <unordered_set> |
| #include "base/bind.h" |
| +#include "base/lazy_instance.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/threading/thread_checker.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| @@ -50,17 +51,125 @@ std::ostream& operator<<(std::ostream& os, const PrintHr& phr) { |
| return os; |
| } |
| +class CombaseFunctions { |
| + public: |
| + CombaseFunctions() = default; |
| + |
| + ~CombaseFunctions() { |
| + if (combase_dll_) |
| + ::FreeLibrary(combase_dll_); |
| + } |
| + |
| + bool LoadFunctions() { |
| + combase_dll_ = ::LoadLibrary(L"combase.dll"); |
| + if (!combase_dll_) |
| + return false; |
| + |
| + get_factory_func_ = reinterpret_cast<decltype(&::RoGetActivationFactory)>( |
| + ::GetProcAddress(combase_dll_, "RoGetActivationFactory")); |
| + if (!get_factory_func_) |
| + return false; |
| + |
| + create_string_func_ = reinterpret_cast<decltype(&::WindowsCreateString)>( |
| + ::GetProcAddress(combase_dll_, "WindowsCreateString")); |
| + if (!create_string_func_) |
| + return false; |
| + |
| + delete_string_func_ = reinterpret_cast<decltype(&::WindowsDeleteString)>( |
| + ::GetProcAddress(combase_dll_, "WindowsDeleteString")); |
| + if (!delete_string_func_) |
| + return false; |
| + |
| + get_string_raw_buffer_func_ = |
| + reinterpret_cast<decltype(&::WindowsGetStringRawBuffer)>( |
| + ::GetProcAddress(combase_dll_, "WindowsGetStringRawBuffer")); |
| + if (!get_string_raw_buffer_func_) |
| + return false; |
| + |
| + return true; |
| + } |
| + |
| + HRESULT RoGetActivationFactory(HSTRING class_id, |
| + const IID& iid, |
| + void** out_factory) { |
| + DCHECK(get_factory_func_); |
| + return get_factory_func_(class_id, iid, out_factory); |
| + } |
| + |
| + HRESULT WindowsCreateString(const base::char16* src, |
| + uint32_t len, |
| + HSTRING* out_hstr) { |
| + DCHECK(create_string_func_); |
| + return create_string_func_(src, len, out_hstr); |
| + } |
| + |
| + HRESULT WindowsDeleteString(HSTRING hstr) { |
| + DCHECK(delete_string_func_); |
| + return delete_string_func_(hstr); |
| + } |
| + |
| + const base::char16* WindowsGetStringRawBuffer(HSTRING hstr, |
| + uint32_t* out_len) { |
| + DCHECK(get_string_raw_buffer_func_); |
| + return get_string_raw_buffer_func_(hstr, out_len); |
| + } |
| + |
| + private: |
| + HMODULE combase_dll_ = nullptr; |
| + |
| + decltype(&::RoGetActivationFactory) get_factory_func_ = nullptr; |
| + decltype(&::WindowsCreateString) create_string_func_ = nullptr; |
| + decltype(&::WindowsDeleteString) delete_string_func_ = nullptr; |
| + decltype(&::WindowsGetStringRawBuffer) get_string_raw_buffer_func_ = nullptr; |
| +}; |
| + |
| +base::LazyInstance<CombaseFunctions> g_combase_functions = |
| + LAZY_INSTANCE_INITIALIZER; |
| + |
| +// Minimalist HSTRING wrapper class to properly maintain HSTRING lifetime. |
|
Takashi Toyoshima
2016/08/31 10:10:29
Can you use base/scoped_generic.h infra to impleme
Shao-Chuan Lee
2016/09/01 03:06:44
Done.
|
| +class HStringWrapper { |
| + public: |
| + HStringWrapper() = default; |
| + ~HStringWrapper() { Release(); } |
| + |
| + HSTRING Get() { return hstring_; } |
| + |
| + HRESULT Set(const base::char16* str) { |
| + Release(); |
| + return g_combase_functions.Get().WindowsCreateString( |
| + str, static_cast<uint32_t>(wcslen(str)), &hstring_); |
| + } |
| + |
| + private: |
| + void Release() { |
| + if (hstring_) |
| + g_combase_functions.Get().WindowsDeleteString(hstring_); |
| + hstring_ = nullptr; |
| + } |
| + |
| + HSTRING hstring_ = nullptr; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(HStringWrapper); |
| +}; |
| + |
| // Factory functions that activate and create WinRT components. The caller takes |
| // ownership of the returning ComPtr. |
| template <typename InterfaceType, base::char16 const* runtime_class_id> |
| ScopedComPtr<InterfaceType> WrlStaticsFactory() { |
| ScopedComPtr<InterfaceType> com_ptr; |
| - HRESULT hr = GetActivationFactory( |
| - WRL::Wrappers::HStringReference(runtime_class_id).Get(), |
| - com_ptr.Receive()); |
| + HStringWrapper class_id_hstring; |
| + HRESULT hr = class_id_hstring.Set(runtime_class_id); |
|
Shao-Chuan Lee
2016/08/31 09:52:13
Here we create new HSTRINGs with WindowsCreateStri
|
| + if (FAILED(hr)) { |
| + VLOG(1) << "WindowsCreateString failed: " << PrintHr(hr); |
| + com_ptr = nullptr; |
| + return com_ptr; |
| + } |
| + |
| + hr = g_combase_functions.Get().RoGetActivationFactory( |
| + class_id_hstring.Get(), __uuidof(InterfaceType), com_ptr.ReceiveVoid()); |
| if (FAILED(hr)) { |
| - VLOG(1) << "GetActivationFactory failed: " << PrintHr(hr); |
| + VLOG(1) << "RoGetActivationFactory failed: " << PrintHr(hr); |
| com_ptr = nullptr; |
| } |
| @@ -78,7 +187,8 @@ std::string GetStringFromObjectMethod(T* obj) { |
| // Note: empty HSTRINGs are represent as nullptr, and instantiating |
| // std::string with nullptr (in base::WideToUTF8) is undefined behavior. |
| - const base::char16* buffer = WindowsGetStringRawBuffer(result, nullptr); |
| + const base::char16* buffer = |
| + g_combase_functions.Get().WindowsGetStringRawBuffer(result, nullptr); |
| if (buffer) |
| return base::WideToUTF8(buffer); |
| return std::string(); |
| @@ -361,7 +471,7 @@ class MidiManagerWinrt::MidiPortManager { |
| port_names_[dev_id] = dev_name; |
| - WRL::Wrappers::HString dev_id_hstring; |
| + HStringWrapper dev_id_hstring; |
| HRESULT hr = dev_id_hstring.Set(base::UTF8ToWide(dev_id).c_str()); |
| if (FAILED(hr)) { |
| VLOG(1) << "Set failed: " << PrintHr(hr); |
| @@ -691,6 +801,13 @@ void MidiManagerWinrt::StartInitialization() { |
| return; |
| } |
| + if (!g_combase_functions.Get().LoadFunctions()) { |
| + VLOG(1) << "Failed loading functions from Combase.dll: " |
| + << PrintHr(HRESULT_FROM_WIN32(GetLastError())); |
| + CompleteInitialization(Result::INITIALIZATION_ERROR); |
| + return; |
| + } |
| + |
| com_thread_.init_com_with_mta(true); |
| com_thread_.Start(); |