OLD | NEW |
(Empty) | |
| 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 "base/win/shortcut.h" |
| 6 |
| 7 #include <shellapi.h> |
| 8 #include <shlobj.h> |
| 9 |
| 10 #include "base/threading/thread_restrictions.h" |
| 11 #include "base/win/scoped_comptr.h" |
| 12 #include "base/win/win_util.h" |
| 13 #include "base/win/windows_version.h" |
| 14 |
| 15 namespace base { |
| 16 namespace win { |
| 17 |
| 18 bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path, |
| 19 const ShortcutProperties& properties, |
| 20 ShortcutOperation operation) { |
| 21 base::ThreadRestrictions::AssertIOAllowed(); |
| 22 |
| 23 // A target is required when |operation| is SHORTCUT_CREATE_ALWAYS. |
| 24 if (operation == SHORTCUT_CREATE_ALWAYS && |
| 25 !(properties.options & ShortcutProperties::PROPERTIES_TARGET)) { |
| 26 NOTREACHED(); |
| 27 return false; |
| 28 } |
| 29 |
| 30 ScopedComPtr<IShellLink> i_shell_link; |
| 31 ScopedComPtr<IPersistFile> i_persist_file; |
| 32 if (FAILED(i_shell_link.CreateInstance(CLSID_ShellLink, NULL, |
| 33 CLSCTX_INPROC_SERVER)) || |
| 34 FAILED(i_persist_file.QueryFrom(i_shell_link))) { |
| 35 return false; |
| 36 } |
| 37 |
| 38 if (operation == SHORTCUT_UPDATE_EXISTING && |
| 39 FAILED(i_persist_file->Load(shortcut_path.value().c_str(), |
| 40 STGM_READWRITE))) { |
| 41 return false; |
| 42 } |
| 43 |
| 44 if ((properties.options & ShortcutProperties::PROPERTIES_TARGET) && |
| 45 FAILED(i_shell_link->SetPath(properties.target.value().c_str()))) { |
| 46 return false; |
| 47 } |
| 48 |
| 49 if ((properties.options & ShortcutProperties::PROPERTIES_WORKING_DIR) && |
| 50 FAILED(i_shell_link->SetWorkingDirectory( |
| 51 properties.working_dir.value().c_str()))) { |
| 52 return false; |
| 53 } |
| 54 |
| 55 if ((properties.options & ShortcutProperties::PROPERTIES_ARGUMENTS) && |
| 56 FAILED(i_shell_link->SetArguments(properties.arguments.c_str()))) { |
| 57 return false; |
| 58 } |
| 59 |
| 60 if ((properties.options & ShortcutProperties::PROPERTIES_DESCRIPTION) && |
| 61 FAILED(i_shell_link->SetDescription(properties.description.c_str()))) { |
| 62 return false; |
| 63 } |
| 64 |
| 65 if ((properties.options & ShortcutProperties::PROPERTIES_ICON) && |
| 66 FAILED(i_shell_link->SetIconLocation(properties.icon.value().c_str(), |
| 67 properties.icon_index))) { |
| 68 return false; |
| 69 } |
| 70 |
| 71 bool has_app_id = |
| 72 (properties.options & ShortcutProperties::PROPERTIES_APP_ID) != 0; |
| 73 bool has_dual_mode = |
| 74 (properties.options & ShortcutProperties::PROPERTIES_DUAL_MODE) != 0; |
| 75 if ((has_app_id || has_dual_mode) && |
| 76 GetVersion() >= VERSION_WIN7) { |
| 77 ScopedComPtr<IPropertyStore> property_store; |
| 78 if (FAILED(property_store.QueryFrom(i_shell_link)) || !property_store.get()) |
| 79 return false; |
| 80 |
| 81 if (has_app_id && |
| 82 !SetAppIdForPropertyStore(property_store, properties.app_id.c_str())) { |
| 83 return false; |
| 84 } |
| 85 if (has_dual_mode && |
| 86 !SetDualModeForPropertyStore(property_store, properties.dual_mode)) { |
| 87 return false; |
| 88 } |
| 89 } |
| 90 |
| 91 HRESULT result = i_persist_file->Save(shortcut_path.value().c_str(), TRUE); |
| 92 |
| 93 // If we successfully updated the icon, notify the shell that we have done so. |
| 94 if (operation == SHORTCUT_UPDATE_EXISTING && SUCCEEDED(result)) { |
| 95 // Release the interfaces in case the SHChangeNotify call below depends on |
| 96 // the operations above being fully completed. |
| 97 i_persist_file.Release(); |
| 98 i_shell_link.Release(); |
| 99 |
| 100 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); |
| 101 } |
| 102 |
| 103 return SUCCEEDED(result); |
| 104 } |
| 105 |
| 106 bool ResolveShortcut(const FilePath& shortcut_path, |
| 107 FilePath* target_path, |
| 108 string16* args) { |
| 109 base::ThreadRestrictions::AssertIOAllowed(); |
| 110 |
| 111 HRESULT result; |
| 112 ScopedComPtr<IShellLink> i_shell_link; |
| 113 |
| 114 // Get pointer to the IShellLink interface. |
| 115 result = i_shell_link.CreateInstance(CLSID_ShellLink, NULL, |
| 116 CLSCTX_INPROC_SERVER); |
| 117 if (FAILED(result)) |
| 118 return false; |
| 119 |
| 120 ScopedComPtr<IPersistFile> persist; |
| 121 // Query IShellLink for the IPersistFile interface. |
| 122 result = persist.QueryFrom(i_shell_link); |
| 123 if (FAILED(result)) |
| 124 return false; |
| 125 |
| 126 // Load the shell link. |
| 127 result = persist->Load(shortcut_path.value().c_str(), STGM_READ); |
| 128 if (FAILED(result)) |
| 129 return false; |
| 130 |
| 131 WCHAR temp[MAX_PATH]; |
| 132 if (target_path) { |
| 133 // Try to find the target of a shortcut. |
| 134 result = i_shell_link->Resolve(0, SLR_NO_UI); |
| 135 if (FAILED(result)) |
| 136 return false; |
| 137 |
| 138 result = i_shell_link->GetPath(temp, MAX_PATH, NULL, SLGP_UNCPRIORITY); |
| 139 if (FAILED(result)) |
| 140 return false; |
| 141 |
| 142 *target_path = FilePath(temp); |
| 143 } |
| 144 |
| 145 if (args) { |
| 146 result = i_shell_link->GetArguments(temp, MAX_PATH); |
| 147 if (FAILED(result)) |
| 148 return false; |
| 149 |
| 150 *args = string16(temp); |
| 151 } |
| 152 return true; |
| 153 } |
| 154 |
| 155 bool TaskbarPinShortcutLink(const wchar_t* shortcut) { |
| 156 base::ThreadRestrictions::AssertIOAllowed(); |
| 157 |
| 158 // "Pin to taskbar" is only supported after Win7. |
| 159 if (GetVersion() < VERSION_WIN7) |
| 160 return false; |
| 161 |
| 162 int result = reinterpret_cast<int>(ShellExecute(NULL, L"taskbarpin", shortcut, |
| 163 NULL, NULL, 0)); |
| 164 return result > 32; |
| 165 } |
| 166 |
| 167 bool TaskbarUnpinShortcutLink(const wchar_t* shortcut) { |
| 168 base::ThreadRestrictions::AssertIOAllowed(); |
| 169 |
| 170 // "Unpin from taskbar" is only supported after Win7. |
| 171 if (base::win::GetVersion() < base::win::VERSION_WIN7) |
| 172 return false; |
| 173 |
| 174 int result = reinterpret_cast<int>(ShellExecute(NULL, L"taskbarunpin", |
| 175 shortcut, NULL, NULL, 0)); |
| 176 return result > 32; |
| 177 } |
| 178 |
| 179 } // namespace win |
| 180 } // namespace base |
OLD | NEW |