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