Skip to content

Commit

Permalink
IDispatchImpl : IDispatch implementation for dual interfaces
Browse files Browse the repository at this point in the history
`IDispatchImpl` implements `IDispatch` for interface `T`, where `T` is a
dual interface. The IDispatch implementation relies on the
typelib/typeinfo for interface `T`.

Bug: 1344200
Change-Id: I079ee2da83f4cd7883fa01260b150da0bd9e41a6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3924046
Reviewed-by: Sorin Jianu <sorin@chromium.org>
Auto-Submit: S Ganesh <ganesh@chromium.org>
Reviewed-by: Xiaoling Bao <xiaolingbao@chromium.org>
Commit-Queue: Sorin Jianu <sorin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1052748}
  • Loading branch information
GitHubGanesh authored and Chromium LUCI CQ committed Sep 29, 2022
1 parent 8aee715 commit c058852
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 137 deletions.
113 changes: 3 additions & 110 deletions chrome/updater/app/server/win/com_classes_legacy.cc
Expand Up @@ -105,11 +105,7 @@ std::string GetStringFromValue(const std::vector<std::string>& value) {

// Implements `ICurrentState`. Initialized with a snapshot of the current state
// of the install.
class CurrentStateImpl
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
ICurrentState,
IDispatch> {
class CurrentStateImpl : public updater::IDispatchImpl<ICurrentState> {
public:
CurrentStateImpl() = default;
CurrentStateImpl(const CurrentStateImpl&) = delete;
Expand Down Expand Up @@ -281,32 +277,6 @@ class CurrentStateImpl
return S_OK;
}

// Overrides for IDispatch.
IFACEMETHODIMP GetTypeInfoCount(UINT*) override { return E_NOTIMPL; }

IFACEMETHODIMP GetTypeInfo(UINT, LCID, ITypeInfo**) override {
return E_NOTIMPL;
}

IFACEMETHODIMP GetIDsOfNames(REFIID,
LPOLESTR*,
UINT,
LCID,
DISPID*) override {
return E_NOTIMPL;
}

IFACEMETHODIMP Invoke(DISPID,
REFIID,
LCID,
WORD,
DISPPARAMS*,
VARIANT*,
EXCEPINFO*,
UINT*) override {
return E_NOTIMPL;
}

private:
~CurrentStateImpl() override = default;

Expand Down Expand Up @@ -694,13 +664,8 @@ HRESULT LegacyAppCommandWebImpl::RuntimeClassInitialize(
UpdaterScope scope,
const std::wstring& app_id,
const std::wstring& command_id) {
if (HRESULT hr = AppCommandRunner::LoadAppCommand(scope, app_id, command_id,
app_command_runner_);
FAILED(hr)) {
return hr;
}

return InitializeTypeInfo();
return AppCommandRunner::LoadAppCommand(scope, app_id, command_id,
app_command_runner_);
}

STDMETHODIMP LegacyAppCommandWebImpl::get_status(UINT* status) {
Expand Down Expand Up @@ -761,78 +726,6 @@ STDMETHODIMP LegacyAppCommandWebImpl::execute(VARIANT substitution1,
return app_command_runner_.Run(substitutions, process_);
}

STDMETHODIMP LegacyAppCommandWebImpl::GetTypeInfoCount(UINT* type_info_count) {
*type_info_count = 1;
return S_OK;
}

STDMETHODIMP LegacyAppCommandWebImpl::GetTypeInfo(UINT type_info_index,
LCID locale_id,
ITypeInfo** type_info) {
if (type_info_index != 0)
return E_INVALIDARG;

return type_info_.CopyTo(type_info);
}

STDMETHODIMP LegacyAppCommandWebImpl::GetIDsOfNames(
REFIID iid,
LPOLESTR* names_to_be_mapped,
UINT count_of_names_to_be_mapped,
LCID locale_id,
DISPID* dispatch_ids) {
return type_info_->GetIDsOfNames(names_to_be_mapped,
count_of_names_to_be_mapped, dispatch_ids);
}

STDMETHODIMP LegacyAppCommandWebImpl::Invoke(DISPID dispatch_id,
REFIID iid,
LCID locale_id,
WORD flags,
DISPPARAMS* dispatch_parameters,
VARIANT* result,
EXCEPINFO* exception_info,
UINT* arg_error_index) {
HRESULT hr = type_info_->Invoke(
Microsoft::WRL::ComPtr<IAppCommandWeb>(this).Get(), dispatch_id, flags,
dispatch_parameters, result, exception_info, arg_error_index);
if (FAILED(hr)) {
LOG(ERROR) << __func__ << " type_info_->Invoke failed: " << dispatch_id
<< ": " << std::hex << hr;
}

return hr;
}

HRESULT LegacyAppCommandWebImpl::InitializeTypeInfo() {
base::FilePath typelib_path;
if (!base::PathService::Get(base::DIR_EXE, &typelib_path))
return E_UNEXPECTED;

typelib_path =
typelib_path.Append(GetExecutableRelativePath())
.Append(GetComTypeLibResourceIndex(__uuidof(IAppCommandWeb)));

Microsoft::WRL::ComPtr<ITypeLib> type_lib;
if (HRESULT hr = ::LoadTypeLib(typelib_path.value().c_str(), &type_lib);
FAILED(hr)) {
LOG(ERROR) << __func__ << " ::LoadTypeLib failed: " << typelib_path << ": "
<< std::hex << hr;
return hr;
}

if (HRESULT hr =
type_lib->GetTypeInfoOfGuid(__uuidof(IAppCommandWeb), &type_info_);
FAILED(hr)) {
LOG(ERROR) << __func__ << " ::GetTypeInfoOfGuid failed"
<< ": " << std::hex << hr << ": IID_IAppCommand: "
<< base::win::WStringFromGUID(__uuidof(IAppCommandWeb));
return hr;
}

return S_OK;
}

PolicyStatusImpl::PolicyStatusImpl()
: policy_service_(
AppServerSingletonInstance()->config()->GetPolicyService()) {}
Expand Down
134 changes: 107 additions & 27 deletions chrome/updater/app/server/win/com_classes_legacy.h
Expand Up @@ -12,14 +12,19 @@
#include <vector>

#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/path_service.h"
#include "base/process/process.h"
#include "base/synchronization/lock.h"
#include "base/win/win_util.h"
#include "chrome/updater/app/server/win/updater_legacy_idl.h"
#include "chrome/updater/policy/service.h"
#include "chrome/updater/update_service.h"
#include "chrome/updater/updater_scope.h"
#include "chrome/updater/util.h"
#include "chrome/updater/win/app_command_runner.h"
#include "chrome/updater/win/setup/setup_util.h"
#include "chrome/updater/win/win_util.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

Expand All @@ -32,6 +37,107 @@ class SequencedTaskRunner;

namespace updater {

// Implements `IDispatch` for interface `T`, where `T` is a dual interface. The
// IDispatch implementation relies on the typelib/typeinfo for interface `T`.
//
// Usage: derive your COM class that implements interface `T` from
// `IDispatchImpl<T>`.
template <typename T>
class IDispatchImpl
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
T,
IDispatch> {
public:
IDispatchImpl() : hr_load_typelib_(InitializeTypeInfo()) {}
IDispatchImpl(const IDispatchImpl&) = delete;
IDispatchImpl& operator=(const IDispatchImpl&) = delete;
~IDispatchImpl() override = default;

// Overrides for IDispatch.
IFACEMETHODIMP GetTypeInfoCount(UINT* type_info_count) override {
if (FAILED(hr_load_typelib_))
return hr_load_typelib_;

*type_info_count = 1;
return S_OK;
}

IFACEMETHODIMP GetTypeInfo(UINT type_info_index,
LCID locale_id,
ITypeInfo** type_info) override {
if (FAILED(hr_load_typelib_))
return hr_load_typelib_;

return type_info_index == 0 ? type_info_.CopyTo(type_info) : E_INVALIDARG;
}

IFACEMETHODIMP GetIDsOfNames(REFIID iid,
LPOLESTR* names_to_be_mapped,
UINT count_of_names_to_be_mapped,
LCID locale_id,
DISPID* dispatch_ids) override {
if (FAILED(hr_load_typelib_))
return hr_load_typelib_;

return type_info_->GetIDsOfNames(names_to_be_mapped,
count_of_names_to_be_mapped, dispatch_ids);
}

IFACEMETHODIMP Invoke(DISPID dispatch_id,
REFIID iid,
LCID locale_id,
WORD flags,
DISPPARAMS* dispatch_parameters,
VARIANT* result,
EXCEPINFO* exception_info,
UINT* arg_error_index) override {
if (FAILED(hr_load_typelib_))
return hr_load_typelib_;

HRESULT hr = type_info_->Invoke(Microsoft::WRL::ComPtr<T>(this).Get(),
dispatch_id, flags, dispatch_parameters,
result, exception_info, arg_error_index);

LOG_IF(ERROR, FAILED(hr)) << __func__ << " type_info_->Invoke failed, "
<< dispatch_id << ", " << std::hex << hr;
return hr;
}

// Loads the typelib and typeinfo for interface `T`.
HRESULT InitializeTypeInfo() {
base::FilePath typelib_path;
if (!base::PathService::Get(base::DIR_EXE, &typelib_path))
return E_UNEXPECTED;

typelib_path = typelib_path.Append(GetExecutableRelativePath())
.Append(GetComTypeLibResourceIndex(__uuidof(T)));

Microsoft::WRL::ComPtr<ITypeLib> type_lib;
if (HRESULT hr = ::LoadTypeLib(typelib_path.value().c_str(), &type_lib);
FAILED(hr)) {
LOG(ERROR) << __func__ << " ::LoadTypeLib failed, " << typelib_path
<< ", " << std::hex << hr
<< ", IID: " << base::win::WStringFromGUID(__uuidof(T));
return hr;
}

if (HRESULT hr = type_lib->GetTypeInfoOfGuid(__uuidof(T), &type_info_);
FAILED(hr)) {
LOG(ERROR) << __func__ << " ::GetTypeInfoOfGuid failed"
<< ", " << std::hex << hr
<< ", IID: " << base::win::WStringFromGUID(__uuidof(T));
return hr;
}

return S_OK;
}

private:
Microsoft::WRL::ComPtr<ITypeInfo> type_info_;
const HRESULT hr_load_typelib_;
};

// TODO(crbug.com/1065712): these classes do not have to be visible in the
// updater namespace. Additionally, there is some code duplication for the
// registration and unregistration code in both server and service_main
Expand Down Expand Up @@ -191,11 +297,7 @@ class LegacyProcessLauncherImpl
//
// Placeholders may be embedded within words, and appropriate quoting of
// back-slash, double-quotes, space, and tab is applied if necessary.
class LegacyAppCommandWebImpl
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
IAppCommandWeb,
IDispatch> {
class LegacyAppCommandWebImpl : public IDispatchImpl<IAppCommandWeb> {
public:
LegacyAppCommandWebImpl();
LegacyAppCommandWebImpl(const LegacyAppCommandWebImpl&) = delete;
Expand Down Expand Up @@ -232,33 +334,11 @@ class LegacyAppCommandWebImpl
VARIANT substitution8,
VARIANT substitution9) override;

// Overrides for IDispatch.
IFACEMETHODIMP GetTypeInfoCount(UINT* type_info_count) override;
IFACEMETHODIMP GetTypeInfo(UINT type_info_index,
LCID locale_id,
ITypeInfo** type_info) override;
IFACEMETHODIMP GetIDsOfNames(REFIID iid,
LPOLESTR* names_to_be_mapped,
UINT count_of_names_to_be_mapped,
LCID locale_id,
DISPID* dispatch_ids) override;
IFACEMETHODIMP Invoke(DISPID dispatch_id,
REFIID iid,
LCID locale_id,
WORD flags,
DISPPARAMS* dispatch_parameters,
VARIANT* result,
EXCEPINFO* exception_info,
UINT* arg_error_index) override;

private:
~LegacyAppCommandWebImpl() override;

HRESULT InitializeTypeInfo();

base::Process process_;
AppCommandRunner app_command_runner_;
Microsoft::WRL::ComPtr<ITypeInfo> type_info_;

friend class LegacyAppCommandWebImplTest;
};
Expand Down

0 comments on commit c058852

Please sign in to comment.