Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: base/win/shortcut.cc

Issue 10914109: Refactoring and tests for the highly undertested file_util::CreateOrUpdateShortcutLink() method. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: string16 to FilePath where appropriate Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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
OLDNEW
« base/win/shortcut.h ('K') | « base/win/shortcut.h ('k') | base/win/shortcut_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698