blob: f00011ddcf1231130284e5fbce6b72af3eff7d4d [file] [log] [blame]
// Copyright (c) 2012 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 "stdafx.h"
#include "winrt_utils.h"
#include <shlobj.h>
#include "base/file_path.h"
#include "base/logging.h"
#include "base/win/scoped_com_initializer.h"
#include "base/win/scoped_comptr.h"
void CheckHR(HRESULT hr, const char* message) {
if (FAILED(hr)) {
if (message)
PLOG(DFATAL) << message << ", hr = " << std::hex << hr;
else
PLOG(DFATAL) << "COM ERROR" << ", hr = " << std::hex << hr;
}
}
HSTRING MakeHString(const string16& str) {
HSTRING hstr;
if (FAILED(::WindowsCreateString(str.c_str(), str.size(), &hstr))) {
PLOG(DFATAL) << "Hstring creation failed";
}
return hstr;
}
string16 MakeStdWString(HSTRING hstring) {
const wchar_t* str;
UINT32 size = 0;
str = ::WindowsGetStringRawBuffer(hstring, &size);
if (!size)
return string16();
return string16(str, size);
}
namespace {
#define IMPLEMENT_CREATE_PROPERTY(Name, Type) \
HRESULT Create ## Name ## Property(Type value, \
winfoundtn::IPropertyValue** prop) { \
mswr::ComPtr<winfoundtn::IPropertyValueStatics> property_value_statics; \
HRESULT hr = winrt_utils::CreateActivationFactory( \
RuntimeClass_Windows_Foundation_PropertyValue, \
property_value_statics.GetAddressOf()); \
CheckHR(hr, "Can't create IPropertyValueStatics"); \
hr = property_value_statics->Create ## Name ## ( \
value, \
reinterpret_cast<IInspectable**>(prop)); \
CheckHR(hr, "Failed to create Property"); \
return hr; \
}
#define COMPARE_ATOMIC_PROPERTY_VALUES(Name, Type) \
Type lhs_value; \
hr = lhs->Get ## Name ##(&lhs_value); \
CheckHR(hr, "Can't get value for lhs"); \
Type rhs_value; \
hr = rhs->Get ## Name ##(&rhs_value); \
CheckHR(hr, "Can't get value for rhs"); \
if (lhs_value < rhs_value) \
*result = -1; \
else if (lhs_value > rhs_value) \
*result = 1; \
else \
*result = 0; \
hr = S_OK
BOOL CALLBACK CoreWindowFinder(HWND hwnd, LPARAM param) {
HWND* window = reinterpret_cast<HWND*>(param);
char classname[128];
if (::GetClassNameA(hwnd, classname, ARRAYSIZE(classname))) {
if (lstrcmpiA("Windows.UI.Core.CoreWindow", classname) == 0) {
*window = hwnd;
return FALSE;
}
}
return TRUE;
}
} // namespace
namespace winrt_utils {
IMPLEMENT_CREATE_PROPERTY(String, HSTRING);
IMPLEMENT_CREATE_PROPERTY(Int16, INT16);
IMPLEMENT_CREATE_PROPERTY(Int32, INT32);
IMPLEMENT_CREATE_PROPERTY(Int64, INT64);
IMPLEMENT_CREATE_PROPERTY(UInt8, UINT8);
IMPLEMENT_CREATE_PROPERTY(UInt16, UINT16);
IMPLEMENT_CREATE_PROPERTY(UInt32, UINT32);
IMPLEMENT_CREATE_PROPERTY(UInt64, UINT64);
HRESULT CompareProperties(winfoundtn::IPropertyValue* lhs,
winfoundtn::IPropertyValue* rhs,
INT32* result) {
if (result == nullptr) {
PLOG(DFATAL) << "Invalid argument to CompareProperties.";
return E_INVALIDARG;
}
if (lhs == rhs) {
*result = 0;
return S_OK;
}
winfoundtn::PropertyType lhs_property_type;
HRESULT hr = lhs->get_Type(&lhs_property_type);
if (FAILED(hr)) {
PLOG(DFATAL) << "Can't get property type for lhs, hr=" << std::hex << hr;
}
winfoundtn::PropertyType rhs_property_type;
hr = rhs->get_Type(&rhs_property_type);
CheckHR(hr, "Can't get property type for rhs");
if (lhs_property_type != rhs_property_type)
return E_INVALIDARG;
switch (lhs_property_type) {
case winfoundtn::PropertyType::PropertyType_String: {
mswrw::HString lhs_string;
hr = lhs->GetString(lhs_string.GetAddressOf());
CheckHR(hr, "Can't get string for lhs");
mswrw::HString rhs_string;
hr = rhs->GetString(rhs_string.GetAddressOf());
CheckHR(hr, "Can't get string for rhs");
hr = WindowsCompareStringOrdinal(
lhs_string.Get(), rhs_string.Get(), result);
break;
}
case winfoundtn::PropertyType::PropertyType_Char16: {
COMPARE_ATOMIC_PROPERTY_VALUES(Char16, wchar_t);
break;
}
case winfoundtn::PropertyType::PropertyType_Double: {
COMPARE_ATOMIC_PROPERTY_VALUES(Double, double);
break;
}
case winfoundtn::PropertyType::PropertyType_Int16: {
COMPARE_ATOMIC_PROPERTY_VALUES(Int16, INT16);
break;
}
case winfoundtn::PropertyType::PropertyType_Int32: {
COMPARE_ATOMIC_PROPERTY_VALUES(Int32, INT32);
break;
}
case winfoundtn::PropertyType::PropertyType_Int64: {
COMPARE_ATOMIC_PROPERTY_VALUES(Int64, INT64);
break;
}
case winfoundtn::PropertyType::PropertyType_UInt8: {
COMPARE_ATOMIC_PROPERTY_VALUES(UInt8, UINT8);
break;
}
case winfoundtn::PropertyType::PropertyType_UInt16: {
COMPARE_ATOMIC_PROPERTY_VALUES(UInt16, UINT16);
break;
}
case winfoundtn::PropertyType::PropertyType_UInt32: {
COMPARE_ATOMIC_PROPERTY_VALUES(UInt32, UINT32);
break;
}
case winfoundtn::PropertyType::PropertyType_UInt64: {
COMPARE_ATOMIC_PROPERTY_VALUES(UInt64, UINT64);
break;
}
default: {
hr = E_NOTIMPL;
}
}
return hr;
}
bool GetArgumentsFromShortcut(const FilePath& shortcut,
string16* arguments) {
HRESULT result;
base::win::ScopedComPtr<IShellLink> i_shell_link;
bool is_resolved = false;
base::win::ScopedCOMInitializer sta_com_initializer;
// Get pointer to the IShellLink interface
result = i_shell_link.CreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER);
if (SUCCEEDED(result)) {
base::win::ScopedComPtr<IPersistFile> persist;
// Query IShellLink for the IPersistFile interface
result = persist.QueryFrom(i_shell_link);
if (SUCCEEDED(result)) {
WCHAR temp_arguments[MAX_PATH];
// Load the shell link
result = persist->Load(shortcut.value().c_str(), STGM_READ);
if (SUCCEEDED(result)) {
result = i_shell_link->GetArguments(temp_arguments, MAX_PATH);
*arguments = temp_arguments;
is_resolved = true;
}
}
}
return is_resolved;
}
string16 ReadArgumentsFromPinnedTaskbarShortcut() {
wchar_t path_buffer[MAX_PATH] = {};
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL,
SHGFP_TYPE_CURRENT, path_buffer))) {
FilePath shortcut(path_buffer);
shortcut = shortcut.Append(
L"Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar");
// TODO(robertshield): Get this stuff from BrowserDistribution.
#if defined(GOOGLE_CHROME_BUILD)
shortcut = shortcut.Append(L"Google Chrome.lnk");
#else
shortcut = shortcut.Append(L"Chromium.lnk");
#endif
string16 arguments;
if (GetArgumentsFromShortcut(shortcut, &arguments)) {
return arguments;
}
}
return L"";
}
HWND FindCoreWindow(DWORD thread_id, int wait_ms) {
HWND window = NULL;
do {
::Sleep(wait_ms);
::EnumThreadWindows(thread_id, &CoreWindowFinder, LPARAM(&window));
} while (window == NULL);
return window;
}
} // namespace winrt_utils