Commit 4b56fb46 authored by Sigurður Ásgeirsson's avatar Sigurður Ásgeirsson Committed by Commit Bot

Revert "Move ComBase functions and HSTRING helpers to base/win."

This reverts commit a99f67ed.

Reason for revert: https://crbug.com/770193 - IO assert on main thread in browser startup.

Original change's description:
> Move ComBase functions and HSTRING helpers to base/win.
> 
> Bug: 734095
> Change-Id: Ib984cd7094cf4e075863d692acb59722114e3990
> Reviewed-on: https://chromium-review.googlesource.com/649528
> Reviewed-by: Takashi Toyoshima <toyoshim@chromium.org>
> Reviewed-by: Greg Thompson <grt@chromium.org>
> Reviewed-by: Peter Beverloo <peter@chromium.org>
> Reviewed-by: Daniel Cheng <dcheng@chromium.org>
> Reviewed-by: Robert Liao <robliao@chromium.org>
> Commit-Queue: Finnur Thorarinsson <finnur@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#505163}

TBR=dcheng@chromium.org,peter@chromium.org,toyoshim@chromium.org,finnur@chromium.org,robliao@chromium.org,grt@chromium.org

Change-Id: I150e7825b141b21b37e14ee7ff7089150aa50abb
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 734095
Reviewed-on: https://chromium-review.googlesource.com/692615Reviewed-by: default avatarSigurður Ásgeirsson <siggi@chromium.org>
Commit-Queue: Sigurður Ásgeirsson <siggi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#505368}
parent 21b4a03b
......@@ -1016,8 +1016,6 @@ component("base") {
"win/com_init_check_hook.h",
"win/com_init_util.cc",
"win/com_init_util.h",
"win/core_winrt_util.cc",
"win/core_winrt_util.h",
"win/current_module.h",
"win/enum_variant.cc",
"win/enum_variant.h",
......@@ -1054,8 +1052,6 @@ component("base") {
"win/scoped_handle.h",
"win/scoped_hdc.h",
"win/scoped_hglobal.h",
"win/scoped_hstring.cc",
"win/scoped_hstring.h",
"win/scoped_process_information.cc",
"win/scoped_process_information.h",
"win/scoped_propvariant.h",
......@@ -2231,7 +2227,6 @@ test("base_unittests") {
"vlog_unittest.cc",
"win/com_init_check_hook_unittest.cc",
"win/com_init_util_unittest.cc",
"win/core_winrt_util_unittest.cc",
"win/dllmain.cc",
"win/enum_variant_unittest.cc",
"win/event_trace_consumer_unittest.cc",
......@@ -2245,7 +2240,6 @@ test("base_unittests") {
"win/registry_unittest.cc",
"win/scoped_bstr_unittest.cc",
"win/scoped_handle_unittest.cc",
"win/scoped_hstring_unittest.cc",
"win/scoped_process_information_unittest.cc",
"win/scoped_variant_unittest.cc",
"win/shortcut_unittest.cc",
......
// 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/core_winrt_util.h"
#include <roapi.h>
#include "base/threading/thread_restrictions.h"
namespace {
void* LoadComBaseFunction(const char* function_name) {
static HMODULE const handle = ::LoadLibrary(L"combase.dll");
return handle ? ::GetProcAddress(handle, function_name) : nullptr;
}
decltype(&::RoActivateInstance) GetRoActivateInstanceFunction() {
static decltype(&::RoActivateInstance) const function =
reinterpret_cast<decltype(&::RoActivateInstance)>(
LoadComBaseFunction("RoActivateInstance"));
return function;
}
decltype(&::RoGetActivationFactory) GetRoGetActivationFactoryFunction() {
static decltype(&::RoGetActivationFactory) const function =
reinterpret_cast<decltype(&::RoGetActivationFactory)>(
LoadComBaseFunction("RoGetActivationFactory"));
return function;
}
} // namespace
namespace base {
namespace win {
bool ResolveCoreWinRTDelayload() {
ThreadRestrictions::AssertIOAllowed();
return GetRoActivateInstanceFunction() && GetRoGetActivationFactoryFunction();
}
HRESULT RoGetActivationFactory(HSTRING class_id,
const IID& iid,
void** out_factory) {
decltype(&::RoGetActivationFactory) get_factory_func =
GetRoGetActivationFactoryFunction();
if (!get_factory_func)
return E_FAIL;
return get_factory_func(class_id, iid, out_factory);
}
HRESULT RoActivateInstance(HSTRING class_id, IInspectable** instance) {
decltype(&::RoActivateInstance) activate_instance_func =
GetRoActivateInstanceFunction();
if (!activate_instance_func)
return E_FAIL;
return activate_instance_func(class_id, instance);
}
} // namespace win
} // namespace base
// 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.
#ifndef BASE_WIN_CORE_WINRT_UTIL_H_
#define BASE_WIN_CORE_WINRT_UTIL_H_
#include <hstring.h>
#include <inspectable.h>
#include <windef.h>
#include "base/base_export.h"
namespace base {
namespace win {
// Provides access to Core WinRT functions which may not be available on
// Windows 7. Loads functions dynamically at runtime to prevent library
// dependencies.
BASE_EXPORT bool ResolveCoreWinRTDelayload();
// The following stubs are provided for when component build is enabled, in
// order to avoid the propogation of delay-loading CoreWinRT to other modules.
BASE_EXPORT HRESULT RoGetActivationFactory(HSTRING class_id,
const IID& iid,
void** out_factory);
BASE_EXPORT HRESULT RoActivateInstance(HSTRING class_id,
IInspectable** instance);
} // namespace win
} // namespace base
#endif // BASE_WIN_CORE_WINRT_UTIL_H_
// 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/core_winrt_util.h"
#include "base/win/scoped_com_initializer.h"
#include "base/win/windows_version.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace win {
TEST(CoreWinrtUtilTest, PreloadFunctions) {
ScopedCOMInitializer com_initializer(ScopedCOMInitializer::kMTA);
if (GetVersion() < VERSION_WIN8)
EXPECT_FALSE(ResolveCoreWinRTDelayload());
else
EXPECT_TRUE(ResolveCoreWinRTDelayload());
}
} // namespace win
} // namespace base
// 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"
#include "base/threading/thread_restrictions.h"
namespace base {
namespace {
static bool g_load_succeeded = false;
void* 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() {
ThreadRestrictions::AssertIOAllowed();
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
// 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.
#ifndef BASE_WIN_SCOPED_HSTRING_H_
#define BASE_WIN_SCOPED_HSTRING_H_
#include <hstring.h>
#include "base/scoped_generic.h"
#include "base/strings/string_piece_forward.h"
namespace base {
namespace internal {
// Scoped HSTRING class to maintain lifetime of HSTRINGs allocated with
// WindowsCreateString().
struct BASE_EXPORT ScopedHStringTraits {
static HSTRING InvalidValue() { return nullptr; }
static void Free(HSTRING hstr);
};
} // namespace internal
namespace win {
// ScopedHString is a wrapper around an HSTRING. Note that it requires certain
// functions that are only available on Windows 8 and later, and that these
// functions need to be delayloaded to avoid breaking Chrome on Windows 7.
//
// Callers MUST check the return value of ResolveCoreWinRTStringDelayLoad()
// *before* using ScopedHString.
//
// One-time Initialization for ScopedHString:
//
// bool success = ScopedHString::ResolveCoreWinRTStringDelayload();
// if (!success) {
// // ScopeHString can be used.
// } else {
// // Handle error.
// }
//
// Example use:
//
// ScopedHString string = ScopedHString::Create(L"abc");
//
// Also:
//
// HSTRING win_string;
// HRESULT hr = WindowsCreateString(..., &win_string);
// ScopedHString string(win_string);
//
class BASE_EXPORT ScopedHString
: public ScopedGeneric<HSTRING, internal::ScopedHStringTraits> {
public:
// Constructs a ScopedHString from an HSTRING, and takes ownership of |hstr|.
explicit ScopedHString(HSTRING hstr);
static ScopedHString Create(StringPiece16 str);
static ScopedHString Create(StringPiece str);
// Loads all required HSTRING functions, available from Win8 and onwards.
static bool ResolveCoreWinRTStringDelayload();
StringPiece16 Get() const;
std::string GetAsUTF8() const;
};
} // namespace win
} // namespace base
#endif // BASE_WIN_SCOPED_HSTRING_H_
// 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/utf_string_conversions.h"
#include "base/win/core_winrt_util.h"
#include "base/win/windows_version.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace win {
namespace {
constexpr wchar_t kTestString1[] = L"123";
constexpr wchar_t kTestString2[] = L"456789";
} // namespace
TEST(ScopedHStringTest, Init) {
// ScopedHString requires WinRT core functions, which are not available in
// older versions.
if (GetVersion() < VERSION_WIN8) {
EXPECT_FALSE(ScopedHString::ResolveCoreWinRTStringDelayload());
return;
}
EXPECT_TRUE(ScopedHString::ResolveCoreWinRTStringDelayload());
ScopedHString hstring = ScopedHString::Create(kTestString1);
std::string buffer = hstring.GetAsUTF8();
EXPECT_EQ(kTestString1, base::UTF8ToWide(buffer));
base::StringPiece16 contents = hstring.Get();
EXPECT_EQ(kTestString1, contents);
hstring.reset();
EXPECT_TRUE(hstring == NULL);
EXPECT_EQ(NULL, hstring.get());
ScopedHString hstring2 = ScopedHString::Create(kTestString2);
hstring.swap(hstring2);
EXPECT_TRUE(hstring2 == NULL);
buffer = hstring.GetAsUTF8();
EXPECT_EQ(kTestString2, base::UTF8ToWide(buffer));
contents = hstring.Get();
EXPECT_EQ(kTestString2, contents);
}
} // namespace win
} // namespace base
......@@ -42,12 +42,10 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "base/win/core_winrt_util.h"
#include "base/win/registry.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_handle.h"
#include "base/win/scoped_hstring.h"
#include "base/win/scoped_propvariant.h"
#include "base/win/windows_version.h"
......@@ -102,20 +100,55 @@ bool IsWindows10TabletMode(HWND hwnd) {
if (GetVersion() < VERSION_WIN10)
return false;
if (!ResolveCoreWinRTDelayload() ||
!ScopedHString::ResolveCoreWinRTStringDelayload()) {
return false;
using RoGetActivationFactoryFunction = decltype(&RoGetActivationFactory);
using WindowsCreateStringFunction = decltype(&WindowsCreateString);
static RoGetActivationFactoryFunction get_factory = nullptr;
static WindowsCreateStringFunction create_string = nullptr;
if (!get_factory) {
DCHECK_EQ(create_string, static_cast<WindowsCreateStringFunction>(
nullptr));
HMODULE combase_dll = ::LoadLibrary(L"combase.dll");
if (!combase_dll)
return false;
get_factory = reinterpret_cast<RoGetActivationFactoryFunction>(
::GetProcAddress(combase_dll, "RoGetActivationFactory"));
if (!get_factory) {
CHECK(false);
return false;
}
create_string = reinterpret_cast<WindowsCreateStringFunction>(
::GetProcAddress(combase_dll, "WindowsCreateString"));
if (!create_string) {
CHECK(false);
return false;
}
}
HRESULT hr = E_FAIL;
// This HSTRING is allocated on the heap and is leaked.
static HSTRING view_settings_guid = NULL;
if (!view_settings_guid) {
hr = create_string(
RuntimeClass_Windows_UI_ViewManagement_UIViewSettings,
static_cast<UINT32>(
wcslen(RuntimeClass_Windows_UI_ViewManagement_UIViewSettings)),
&view_settings_guid);
if (FAILED(hr))
return false;
}
ScopedHString view_settings_guid = ScopedHString::Create(
RuntimeClass_Windows_UI_ViewManagement_UIViewSettings);
ScopedComPtr<IUIViewSettingsInterop> view_settings_interop;
HRESULT hr = base::win::RoGetActivationFactory(
view_settings_guid.get(), IID_PPV_ARGS(&view_settings_interop));
base::win::ScopedComPtr<IUIViewSettingsInterop> view_settings_interop;
hr = get_factory(view_settings_guid, IID_PPV_ARGS(&view_settings_interop));
if (FAILED(hr))
return false;
ScopedComPtr<ABI::Windows::UI::ViewManagement::IUIViewSettings> view_settings;
base::win::ScopedComPtr<ABI::Windows::UI::ViewManagement::IUIViewSettings>
view_settings;
// TODO(ananta)
// Avoid using GetForegroundWindow here and pass in the HWND of the window
// intiating the request to display the keyboard.
......@@ -537,7 +570,7 @@ bool IsUser32AndGdi32Available() {
// If win32k syscalls aren't disabled, then user32 and gdi32 are available.
// Can't disable win32k prior to windows 8.
if (GetVersion() < VERSION_WIN8)
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return true;
typedef decltype(
......
......@@ -15,8 +15,6 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/win/core_winrt_util.h"
#include "base/win/scoped_hstring.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_common.h"
#include "chrome/browser/notifications/notification_template_builder.h"
......@@ -32,18 +30,156 @@ namespace winfoundtn = ABI::Windows::Foundation;
namespace winui = ABI::Windows::UI;
namespace winxml = ABI::Windows::Data::Xml;
using base::win::ScopedHString;
using message_center::RichNotificationData;
namespace {
// Provides access to functions in combase.dll which may not be available on
// Windows 7. Loads functions dynamically at runtime to prevent library
// dependencies.
// TODO(finnur): Move this to base/win.
class CombaseFunctions {
public:
static bool LoadFunctions() {
HMODULE 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;
activate_instance_func_ = reinterpret_cast<decltype(&::RoActivateInstance)>(
::GetProcAddress(combase_dll, "RoActivateInstance"));
if (!activate_instance_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;
create_string_ref_func_ =
reinterpret_cast<decltype(&::WindowsCreateStringReference)>(
::GetProcAddress(combase_dll, "WindowsCreateStringReference"));
if (!create_string_ref_func_)
return false;
return true;
}
static HRESULT RoGetActivationFactory(HSTRING class_id,
const IID& iid,
void** out_factory) {
DCHECK(get_factory_func_);
return get_factory_func_(class_id, iid, out_factory);
}
static HRESULT RoActivateInstance(HSTRING class_id, IInspectable** instance) {
DCHECK(activate_instance_func_);
return activate_instance_func_(class_id, instance);
}
static HRESULT WindowsCreateString(const base::char16* src,
uint32_t len,
HSTRING* out_hstr) {
DCHECK(create_string_func_);
return create_string_func_(src, len, out_hstr);
}
static HRESULT WindowsDeleteString(HSTRING hstr) {
DCHECK(delete_string_func_);
return delete_string_func_(hstr);
}
static HRESULT WindowsCreateStringReference(const base::char16* src,
uint32_t len,
HSTRING_HEADER* out_header,
HSTRING* out_hstr) {
DCHECK(create_string_ref_func_);
return create_string_ref_func_(src, len, out_header, out_hstr);
}
private:
CombaseFunctions() = default;
~CombaseFunctions() = default;
static decltype(&::RoGetActivationFactory) get_factory_func_;
static decltype(&::RoActivateInstance) activate_instance_func_;
static decltype(&::WindowsCreateString) create_string_func_;
static decltype(&::WindowsDeleteString) delete_string_func_;
static decltype(&::WindowsCreateStringReference) create_string_ref_func_;
};
decltype(&::RoGetActivationFactory) CombaseFunctions::get_factory_func_ =
nullptr;
decltype(&::RoActivateInstance) CombaseFunctions::activate_instance_func_ =
nullptr;
decltype(&::WindowsCreateString) CombaseFunctions::create_string_func_ =
nullptr;
decltype(&::WindowsDeleteString) CombaseFunctions::delete_string_func_ =
nullptr;
decltype(
&::WindowsCreateStringReference) CombaseFunctions::create_string_ref_func_ =
nullptr;
// Scoped HSTRING class to maintain lifetime of HSTRINGs allocated with
// WindowsCreateString().
// TODO(finnur): Move this to base/win.
class ScopedHStringTraits {
public:
static HSTRING InvalidValue() { return nullptr; }
static void Free(HSTRING hstr) {
CombaseFunctions::WindowsDeleteString(hstr);
}
};
// TODO(finnur): Move this to base/win.
class ScopedHString : public base::ScopedGeneric<HSTRING, ScopedHStringTraits> {
public:
explicit ScopedHString(const base::char16* str) : ScopedGeneric(nullptr) {
HSTRING hstr;
HRESULT hr = CombaseFunctions::WindowsCreateString(
str, static_cast<uint32_t>(wcslen(str)), &hstr);
if (FAILED(hr))
VLOG(1) << "WindowsCreateString failed";
else
reset(hstr);
}
};
// A convenience class for creating HStringReferences.
class HStringRef {
public:
explicit HStringRef(const base::char16* str) {
HRESULT hr = CombaseFunctions::WindowsCreateStringReference(
str, static_cast<uint32_t>(wcslen(str)), &header_, &hstr_);
if (FAILED(hr))
VLOG(1) << "WindowsCreateStringReference failed";
}
HSTRING Get() { return hstr_; }
private:
HSTRING hstr_;
HSTRING_HEADER header_;
DISALLOW_COPY_AND_ASSIGN(HStringRef);
};
// Templated wrapper for winfoundtn::GetActivationFactory().
template <unsigned int size, typename T>
HRESULT CreateActivationFactory(wchar_t const (&class_name)[size], T** object) {
ScopedHString ref_class_name =
ScopedHString::Create(base::StringPiece16(class_name, size - 1));
return base::win::RoGetActivationFactory(ref_class_name.get(),
IID_PPV_ARGS(object));
HStringRef ref_class_name(class_name);
return CombaseFunctions::RoGetActivationFactory(ref_class_name.Get(),
IID_PPV_ARGS(object));
}
// TODO(finnur): Make this a member function of the class and unit test it.
......@@ -54,11 +190,10 @@ HRESULT GetToastNotification(
winui::Notifications::IToastNotification** toast_notification) {
*toast_notification = nullptr;
ScopedHString ref_class_name =
ScopedHString::Create(RuntimeClass_Windows_Data_Xml_Dom_XmlDocument);
HStringRef ref_class_name(RuntimeClass_Windows_Data_Xml_Dom_XmlDocument);
mswr::ComPtr<IInspectable> inspectable;
HRESULT hr =
base::win::RoActivateInstance(ref_class_name.get(), &inspectable);
CombaseFunctions::RoActivateInstance(ref_class_name.Get(), &inspectable);
if (FAILED(hr)) {
LOG(ERROR) << "Unable to activate the XML Document";
return hr;
......@@ -73,8 +208,8 @@ HRESULT GetToastNotification(
base::string16 notification_template =
notification_template_builder.GetNotificationTemplate();
ScopedHString ref_template = ScopedHString::Create(notification_template);
hr = document_io->LoadXml(ref_template.get());
HStringRef ref_template(notification_template.c_str());
hr = document_io->LoadXml(ref_template.Get());
if (FAILED(hr)) {
LOG(ERROR) << "Unable to load the template's XML into the document";
return hr;
......@@ -115,8 +250,7 @@ NotificationPlatformBridge* NotificationPlatformBridge::Create() {
}
NotificationPlatformBridgeWin::NotificationPlatformBridgeWin() {
com_functions_initialized_ = base::win::ResolveCoreWinRTDelayload() &&
ScopedHString::ResolveCoreWinRTStringDelayload();
com_functions_initialized_ = CombaseFunctions::LoadFunctions();
}
NotificationPlatformBridgeWin::~NotificationPlatformBridgeWin() = default;
......@@ -143,7 +277,7 @@ void NotificationPlatformBridgeWin::Display(
base::string16 browser_model_id =
ShellUtil::GetBrowserModelId(InstallUtil::IsPerUserInstall());
ScopedHString application_id = ScopedHString::Create(browser_model_id);
ScopedHString application_id(browser_model_id.c_str());
mswr::ComPtr<winui::Notifications::IToastNotifier> notifier;
hr =
toast_manager->CreateToastNotifierWithId(application_id.get(), &notifier);
......
......@@ -29,9 +29,7 @@
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/timer.h"
#include "base/win/core_winrt_util.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_hstring.h"
#include "media/midi/midi_scheduler.h"
namespace midi {
......@@ -45,7 +43,6 @@ using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Storage::Streams;
using base::win::ScopedComPtr;
using base::win::ScopedHString;
using mojom::PortState;
using mojom::Result;
......@@ -63,20 +60,124 @@ std::ostream& operator<<(std::ostream& os, const PrintHr& phr) {
return os;
}
// Provides access to functions in combase.dll which may not be available on
// Windows 7. Loads functions dynamically at runtime to prevent library
// dependencies.
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;
};
CombaseFunctions* GetCombaseFunctions() {
static CombaseFunctions* functions = new CombaseFunctions();
return functions;
}
// Scoped HSTRING class to maintain lifetime of HSTRINGs allocated with
// WindowsCreateString().
class ScopedHStringTraits {
public:
static HSTRING InvalidValue() { return nullptr; }
static void Free(HSTRING hstr) {
GetCombaseFunctions()->WindowsDeleteString(hstr);
}
};
class ScopedHString : public base::ScopedGeneric<HSTRING, ScopedHStringTraits> {
public:
explicit ScopedHString(const base::char16* str) : ScopedGeneric(nullptr) {
HSTRING hstr;
HRESULT hr = GetCombaseFunctions()->WindowsCreateString(
str, static_cast<uint32_t>(wcslen(str)), &hstr);
if (FAILED(hr))
VLOG(1) << "WindowsCreateString failed: " << PrintHr(hr);
else
reset(hstr);
}
};
// 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;
ScopedHString class_id_hstring = ScopedHString::Create(runtime_class_id);
ScopedHString class_id_hstring(runtime_class_id);
if (!class_id_hstring.is_valid()) {
com_ptr = nullptr;
return com_ptr;
}
HRESULT hr = base::win::RoGetActivationFactory(class_id_hstring.get(),
IID_PPV_ARGS(&com_ptr));
HRESULT hr = GetCombaseFunctions()->RoGetActivationFactory(
class_id_hstring.get(), IID_PPV_ARGS(&com_ptr));
if (FAILED(hr)) {
VLOG(1) << "RoGetActivationFactory failed: " << PrintHr(hr);
com_ptr = nullptr;
......@@ -85,6 +186,16 @@ ScopedComPtr<InterfaceType> WrlStaticsFactory() {
return com_ptr;
}
std::string HStringToString(HSTRING hstr) {
// Note: empty HSTRINGs are represent as nullptr, and instantiating
// std::string with nullptr (in base::WideToUTF8) is undefined behavior.
const base::char16* buffer =
GetCombaseFunctions()->WindowsGetStringRawBuffer(hstr, nullptr);
if (buffer)
return base::WideToUTF8(buffer);
return std::string();
}
template <typename T>
std::string GetIdString(T* obj) {
HSTRING result;
......@@ -93,7 +204,7 @@ std::string GetIdString(T* obj) {
VLOG(1) << "get_Id failed: " << PrintHr(hr);
return std::string();
}
return ScopedHString(result).GetAsUTF8();
return HStringToString(result);
}
template <typename T>
......@@ -104,7 +215,7 @@ std::string GetDeviceIdString(T* obj) {
VLOG(1) << "get_DeviceId failed: " << PrintHr(hr);
return std::string();
}
return ScopedHString(result).GetAsUTF8();
return HStringToString(result);
}
std::string GetNameString(IDeviceInformation* info) {
......@@ -114,7 +225,7 @@ std::string GetNameString(IDeviceInformation* info) {
VLOG(1) << "get_Name failed: " << PrintHr(hr);
return std::string();
}
return ScopedHString(result).GetAsUTF8();
return HStringToString(result);
}
HRESULT GetPointerToBufferData(IBuffer* buffer, uint8_t** out) {
......@@ -480,7 +591,7 @@ class MidiManagerWinrt::MidiPortManager {
port_names_[dev_id] = dev_name;
ScopedHString dev_id_hstring = ScopedHString::Create(dev_id);
ScopedHString dev_id_hstring(base::UTF8ToWide(dev_id).c_str());
if (!dev_id_hstring.is_valid())
return;
......@@ -847,9 +958,10 @@ void MidiManagerWinrt::InitializeOnComThread() {
base::AutoLock auto_lock(lazy_init_member_lock_);
com_thread_checker_.reset(new base::ThreadChecker);
bool preload_success = base::win::ResolveCoreWinRTDelayload() &&
ScopedHString::ResolveCoreWinRTStringDelayload();
if (!preload_success) {
if (!GetCombaseFunctions()->LoadFunctions()) {
VLOG(1) << "Failed loading functions from combase.dll: "
<< PrintHr(HRESULT_FROM_WIN32(GetLastError()));
CompleteInitialization(Result::INITIALIZATION_ERROR);
return;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment