Home | History | Annotate | Download | only in metro_driver
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "stdafx.h"
      6 #include "winrt_utils.h"
      7 
      8 #include <shlobj.h>
      9 
     10 #include "base/files/file_path.h"
     11 #include "base/logging.h"
     12 #include "base/win/scoped_com_initializer.h"
     13 #include "base/win/scoped_comptr.h"
     14 #include "chrome/installer/util/browser_distribution.h"
     15 #include "chrome/installer/util/install_util.h"
     16 
     17 void CheckHR(HRESULT hr, const char* message) {
     18   if (FAILED(hr)) {
     19     if (message)
     20       PLOG(DFATAL) << message << ", hr = " << std::hex << hr;
     21     else
     22       PLOG(DFATAL) << "COM ERROR" << ", hr = " << std::hex << hr;
     23   }
     24 }
     25 
     26 HSTRING MakeHString(const string16& str) {
     27   HSTRING hstr;
     28   if (FAILED(::WindowsCreateString(str.c_str(), static_cast<UINT32>(str.size()),
     29                                    &hstr))) {
     30     PLOG(DFATAL) << "Hstring creation failed";
     31   }
     32   return hstr;
     33 }
     34 
     35 string16 MakeStdWString(HSTRING hstring) {
     36   const wchar_t* str;
     37   UINT32 size = 0;
     38   str = ::WindowsGetStringRawBuffer(hstring, &size);
     39   if (!size)
     40     return string16();
     41   return string16(str, size);
     42 }
     43 
     44 namespace {
     45 
     46 #define IMPLEMENT_CREATE_PROPERTY(Name, Type) \
     47 HRESULT Create ## Name ## Property(Type value, \
     48                                    winfoundtn::IPropertyValue** prop) { \
     49   mswr::ComPtr<winfoundtn::IPropertyValueStatics> property_value_statics; \
     50   HRESULT hr = winrt_utils::CreateActivationFactory( \
     51       RuntimeClass_Windows_Foundation_PropertyValue, \
     52       property_value_statics.GetAddressOf()); \
     53   CheckHR(hr, "Can't create IPropertyValueStatics"); \
     54   hr = property_value_statics->Create ## Name ## ( \
     55       value, \
     56       reinterpret_cast<IInspectable**>(prop)); \
     57   CheckHR(hr, "Failed to create Property"); \
     58   return hr; \
     59 }
     60 
     61 #define COMPARE_ATOMIC_PROPERTY_VALUES(Name, Type) \
     62   Type lhs_value; \
     63   hr = lhs->Get ## Name ##(&lhs_value); \
     64   CheckHR(hr, "Can't get value for lhs"); \
     65   Type rhs_value; \
     66   hr = rhs->Get ## Name ##(&rhs_value); \
     67   CheckHR(hr, "Can't get value for rhs"); \
     68   if (lhs_value < rhs_value) \
     69     *result = -1; \
     70   else if (lhs_value > rhs_value) \
     71     *result = 1; \
     72   else \
     73     *result = 0; \
     74   hr = S_OK
     75 
     76 }  // namespace
     77 
     78 namespace winrt_utils {
     79 
     80 IMPLEMENT_CREATE_PROPERTY(String, HSTRING);
     81 IMPLEMENT_CREATE_PROPERTY(Int16, INT16);
     82 IMPLEMENT_CREATE_PROPERTY(Int32, INT32);
     83 IMPLEMENT_CREATE_PROPERTY(Int64, INT64);
     84 IMPLEMENT_CREATE_PROPERTY(UInt8, UINT8);
     85 IMPLEMENT_CREATE_PROPERTY(UInt16, UINT16);
     86 IMPLEMENT_CREATE_PROPERTY(UInt32, UINT32);
     87 IMPLEMENT_CREATE_PROPERTY(UInt64, UINT64);
     88 
     89 HRESULT CompareProperties(winfoundtn::IPropertyValue* lhs,
     90                           winfoundtn::IPropertyValue* rhs,
     91                           INT32* result) {
     92   if (result == nullptr) {
     93     PLOG(DFATAL) << "Invalid argument to CompareProperties.";
     94     return E_INVALIDARG;
     95   }
     96 
     97   if (lhs == rhs) {
     98     *result = 0;
     99     return S_OK;
    100   }
    101 
    102   winfoundtn::PropertyType lhs_property_type;
    103   HRESULT hr = lhs->get_Type(&lhs_property_type);
    104   if (FAILED(hr)) {
    105     PLOG(DFATAL) << "Can't get property type for lhs, hr=" << std::hex << hr;
    106   }
    107 
    108   winfoundtn::PropertyType rhs_property_type;
    109   hr = rhs->get_Type(&rhs_property_type);
    110   CheckHR(hr, "Can't get property type for rhs");
    111 
    112   if (lhs_property_type != rhs_property_type)
    113     return E_INVALIDARG;
    114 
    115   switch (lhs_property_type) {
    116     case winfoundtn::PropertyType::PropertyType_String: {
    117       mswrw::HString lhs_string;
    118       hr = lhs->GetString(lhs_string.GetAddressOf());
    119       CheckHR(hr, "Can't get string for lhs");
    120 
    121       mswrw::HString rhs_string;
    122       hr = rhs->GetString(rhs_string.GetAddressOf());
    123       CheckHR(hr, "Can't get string for rhs");
    124 
    125       hr = WindowsCompareStringOrdinal(
    126           lhs_string.Get(), rhs_string.Get(), result);
    127       break;
    128     }
    129     case winfoundtn::PropertyType::PropertyType_Char16: {
    130       COMPARE_ATOMIC_PROPERTY_VALUES(Char16, wchar_t);
    131       break;
    132     }
    133     case winfoundtn::PropertyType::PropertyType_Double: {
    134       COMPARE_ATOMIC_PROPERTY_VALUES(Double, double);
    135       break;
    136     }
    137     case winfoundtn::PropertyType::PropertyType_Int16: {
    138       COMPARE_ATOMIC_PROPERTY_VALUES(Int16, INT16);
    139       break;
    140     }
    141     case winfoundtn::PropertyType::PropertyType_Int32: {
    142       COMPARE_ATOMIC_PROPERTY_VALUES(Int32, INT32);
    143       break;
    144     }
    145     case winfoundtn::PropertyType::PropertyType_Int64: {
    146       COMPARE_ATOMIC_PROPERTY_VALUES(Int64, INT64);
    147       break;
    148     }
    149     case winfoundtn::PropertyType::PropertyType_UInt8: {
    150       COMPARE_ATOMIC_PROPERTY_VALUES(UInt8, UINT8);
    151       break;
    152     }
    153     case winfoundtn::PropertyType::PropertyType_UInt16: {
    154       COMPARE_ATOMIC_PROPERTY_VALUES(UInt16, UINT16);
    155       break;
    156     }
    157     case winfoundtn::PropertyType::PropertyType_UInt32: {
    158       COMPARE_ATOMIC_PROPERTY_VALUES(UInt32, UINT32);
    159       break;
    160     }
    161     case winfoundtn::PropertyType::PropertyType_UInt64: {
    162       COMPARE_ATOMIC_PROPERTY_VALUES(UInt64, UINT64);
    163       break;
    164     }
    165     default: {
    166       hr = E_NOTIMPL;
    167     }
    168   }
    169   return hr;
    170 }
    171 
    172 bool GetArgumentsFromShortcut(const base::FilePath& shortcut,
    173                               string16* arguments) {
    174   HRESULT result;
    175   base::win::ScopedComPtr<IShellLink> i_shell_link;
    176   bool is_resolved = false;
    177 
    178 
    179   base::win::ScopedCOMInitializer sta_com_initializer;
    180 
    181   // Get pointer to the IShellLink interface
    182   result = i_shell_link.CreateInstance(CLSID_ShellLink, NULL,
    183                                        CLSCTX_INPROC_SERVER);
    184   if (SUCCEEDED(result)) {
    185     base::win::ScopedComPtr<IPersistFile> persist;
    186     // Query IShellLink for the IPersistFile interface
    187     result = persist.QueryFrom(i_shell_link);
    188     if (SUCCEEDED(result)) {
    189       WCHAR temp_arguments[MAX_PATH];
    190       // Load the shell link
    191       result = persist->Load(shortcut.value().c_str(), STGM_READ);
    192       if (SUCCEEDED(result)) {
    193         result = i_shell_link->GetArguments(temp_arguments, MAX_PATH);
    194         *arguments = temp_arguments;
    195         is_resolved = true;
    196       }
    197     }
    198   }
    199 
    200   return is_resolved;
    201 }
    202 
    203 string16 ReadArgumentsFromPinnedTaskbarShortcut() {
    204   wchar_t path_buffer[MAX_PATH] = {};
    205 
    206   if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL,
    207                                 SHGFP_TYPE_CURRENT, path_buffer))) {
    208     base::FilePath shortcut(path_buffer);
    209     shortcut = shortcut.Append(
    210         L"Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar");
    211 
    212     BrowserDistribution* dist = BrowserDistribution::GetDistribution();
    213     base::string16 link_name = dist->GetShortcutName(
    214         BrowserDistribution::SHORTCUT_CHROME) + installer::kLnkExt;
    215     shortcut = shortcut.Append(link_name);
    216 
    217     string16 arguments;
    218     if (GetArgumentsFromShortcut(shortcut, &arguments)) {
    219       return arguments;
    220     }
    221   }
    222 
    223   return L"";
    224 }
    225 
    226 }  // namespace winrt_utils
    227