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

Side by Side Diff: base/shell.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 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
« no previous file with comments | « base/shell.h ('k') | base/shell_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2003-2009 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15 //
16 // Shell functions
17
18 #include "omaha/base/shell.h"
19
20 #include <shlobj.h>
21 #include <shellapi.h>
22 #include "omaha/base/app_util.h"
23 #include "omaha/base/browser_utils.h"
24 #include "omaha/base/const_utils.h"
25 #include "omaha/base/debug.h"
26 #include "omaha/base/error.h"
27 #include "omaha/base/file.h"
28 #include "omaha/base/logging.h"
29 #include "omaha/base/path.h"
30 #include "omaha/base/reg_key.h"
31 #include "omaha/base/scoped_any.h"
32 #include "omaha/base/string.h"
33 #include "omaha/base/system.h"
34 #include "omaha/base/utils.h"
35
36 namespace omaha {
37
38 // create and store a shortcut
39 // uses shell IShellLink and IPersistFile interfaces
40 HRESULT Shell::CreateLink(const TCHAR *source,
41 const TCHAR *destination,
42 const TCHAR *working_dir,
43 const TCHAR *arguments,
44 const TCHAR *description,
45 WORD hotkey_virtual_key_code,
46 WORD hotkey_modifiers,
47 const TCHAR *icon) {
48 ASSERT1(source);
49 ASSERT1(destination);
50 ASSERT1(working_dir);
51 ASSERT1(arguments);
52 ASSERT1(description);
53
54 scoped_co_init co_init(COINIT_APARTMENTTHREADED);
55 HRESULT hr = co_init.hresult();
56 if (FAILED(hr) && hr != RPC_E_CHANGED_MODE) {
57 UTIL_LOG(LEVEL_ERROR, (_T("[Shell::CreateLink - failed to co_init]"), hr));
58 return hr;
59 }
60
61 UTIL_LOG(L1, (_T("[Create shell link]")
62 _T("[source %s dest %s dir %s arg %s desc %s hotkey %x:%x]"),
63 source, destination, working_dir, arguments, description,
64 hotkey_modifiers, hotkey_virtual_key_code));
65
66 // Get a pointer to the IShellLink interface
67 CComPtr<IShellLink> shell_link;
68
69 RET_IF_FAILED(shell_link.CoCreateInstance(CLSID_ShellLink));
70 ASSERT(shell_link, (L""));
71
72 // Set the path to the shortcut target and add the description
73 VERIFY1(SUCCEEDED(shell_link->SetPath(source)));
74 VERIFY1(SUCCEEDED(shell_link->SetArguments(arguments)));
75 VERIFY1(SUCCEEDED(shell_link->SetDescription(description)));
76 VERIFY1(SUCCEEDED(shell_link->SetWorkingDirectory(working_dir)));
77
78 // If we are given an icon, then set it
79 // For now, we always use the first icon if this happens to have multiple ones
80 if (icon) {
81 VERIFY1(SUCCEEDED(shell_link->SetIconLocation(icon, 0)));
82 }
83
84 // C4201: nonstandard extension used : nameless struct/union
85 #pragma warning(disable : 4201)
86 union {
87 WORD flags;
88 struct { // little-endian machine:
89 WORD virtual_key:8; // low order byte
90 WORD modifiers:8; // high order byte
91 };
92 } hot_key;
93 #pragma warning(default : 4201)
94
95 hot_key.virtual_key = hotkey_virtual_key_code;
96 hot_key.modifiers = hotkey_modifiers;
97
98 if (hot_key.flags) {
99 shell_link->SetHotkey(hot_key.flags);
100 }
101
102 // Query IShellLink for the IPersistFile interface for saving the shortcut in
103 // persistent storage
104 CComQIPtr<IPersistFile> persist_file(shell_link);
105 if (!persist_file)
106 return E_FAIL;
107
108 // Save the link by calling IPersistFile::Save
109 RET_IF_FAILED(persist_file->Save(destination, TRUE));
110
111 return S_OK;
112 }
113
114 HRESULT Shell::RemoveLink(const TCHAR *link) {
115 ASSERT(link, (L""));
116 ASSERT(*link, (L""));
117
118 return File::Remove(link);
119 }
120
121 // Open a URL in a new browser window
122 HRESULT Shell::OpenLinkInNewWindow(const TCHAR* url, UseBrowser use_browser) {
123 ASSERT1(url);
124
125 HRESULT hr = S_OK;
126 CString browser_path;
127
128 // Try to open with default browser
129 if (use_browser == USE_DEFAULT_BROWSER) {
130 // Load full browser path from regkey
131 hr = GetDefaultBrowserPath(&browser_path);
132
133 // If there is a default browser and it is not AOL, load the url in that
134 // browser
135 if (SUCCEEDED(hr) && !String_Contains(browser_path, _T("aol"))) {
136 if (!browser_path.IsEmpty()) {
137 // Have we figured out how to append the URL onto the browser path?
138 bool acceptable_url = false;
139
140 if (ReplaceCString(browser_path, _T("\"%1\""), url)) {
141 // the "browser.exe "%1"" case
142 acceptable_url = true;
143 } else if (ReplaceCString(browser_path, _T("%1"), url)) {
144 // the "browser.exe %1 "case
145 acceptable_url = true;
146 } else if (ReplaceCString(browser_path, _T("-nohome"), url)) {
147 // the "browser.exe -nohome" case
148 acceptable_url = true;
149 } else {
150 // the browser.exe case.
151 // simply append the quoted url.
152 EnclosePath(&browser_path);
153 browser_path.AppendChar(_T(' '));
154 CString quoted_url(url);
155 EnclosePath(&quoted_url);
156 browser_path.Append(quoted_url);
157 acceptable_url = true;
158 }
159
160 if (acceptable_url) {
161 hr = System::ShellExecuteCommandLine(browser_path, NULL, NULL);
162 if (SUCCEEDED(hr)) {
163 return S_OK;
164 } else {
165 UTIL_LOG(LE, (_T("[Shell::OpenLinkInNewWindow]")
166 _T("[failed to start default browser to open url]")
167 _T("[%s][0x%x]"), url, hr));
168 }
169 }
170 }
171 }
172 }
173
174 // Try to open with IE if can't open with default browser or required
175 if (use_browser == USE_DEFAULT_BROWSER ||
176 use_browser == USE_INTERNET_EXPLORER) {
177 hr = RegKey::GetValue(kRegKeyIeClass, kRegValueIeClass, &browser_path);
178 if (SUCCEEDED(hr)) {
179 hr = System::ShellExecuteProcess(browser_path, url, NULL, NULL);
180 if (SUCCEEDED(hr)) {
181 return S_OK;
182 } else {
183 UTIL_LOG(LE, (_T("[Shell::OpenLinkInNewWindow]")
184 _T("[failed to start IE to open url][%s][0x%x]"),
185 url, hr));
186 }
187 }
188 }
189
190 // Try to open with Firefox if can't open with default browser or required
191 if (use_browser == USE_DEFAULT_BROWSER || use_browser == USE_FIREFOX) {
192 hr = RegKey::GetValue(kRegKeyFirefox, kRegValueFirefox, &browser_path);
193 if (SUCCEEDED(hr) && !browser_path.IsEmpty()) {
194 ReplaceCString(browser_path, _T("%1"), url);
195 hr = System::ShellExecuteCommandLine(browser_path, NULL, NULL);
196 if (SUCCEEDED(hr)) {
197 return S_OK;
198 } else {
199 UTIL_LOG(LE, (_T("[Shell::OpenLinkInNewWindow]")
200 _T("[failed to start Firefox to open url][%s][0x%x]"),
201 url, hr));
202 }
203 }
204 }
205
206 // ShellExecute the url directly as a last resort
207 hr = Shell::Execute(url);
208 if (FAILED(hr)) {
209 UTIL_LOG(LE, (_T("[Shell::OpenLinkInNewWindow]")
210 _T("[failed to run ShellExecute to open url][%s][0x%x]"),
211 url, hr));
212 }
213
214 return hr;
215 }
216
217 HRESULT Shell::Execute(const TCHAR* file) {
218 ASSERT1(file);
219
220 // Prepare everything required for ::ShellExecuteEx().
221 SHELLEXECUTEINFO sei;
222 SetZero(sei);
223 sei.cbSize = sizeof(sei);
224 sei.fMask = SEE_MASK_FLAG_NO_UI | // Do not display an error message box.
225 SEE_MASK_NOZONECHECKS | // Do not perform a zone check.
226 SEE_MASK_NOASYNC; // Wait to complete before returning.
227 // Pass NULL for hwnd. This will have ShellExecuteExEnsureParent()
228 // create a dummy parent window for us.
229 // sei.hwnd = NULL;
230 sei.lpVerb = _T("open");
231 sei.lpFile = file;
232 // No parameters to pass
233 // sei.lpParameters = NULL;
234 // Use parent's starting directory
235 // sei.lpDirectory = NULL;
236 sei.nShow = SW_SHOWNORMAL;
237
238 // Use ShellExecuteExEnsureParent to ensure that we always have a parent HWND.
239 // We need to use the HWND Property to be acknowledged as a Foreground
240 // Application on Vista. Otherwise, the elevation prompt will appear minimized
241 // on the taskbar.
242 if (!ShellExecuteExEnsureParent(&sei)) {
243 HRESULT hr(HRESULTFromLastError());
244 ASSERT(false,
245 (_T("Shell::Execute - ShellExecuteEx failed][%s][0x%x]"), file, hr));
246 return hr;
247 }
248
249 return S_OK;
250 }
251
252 HRESULT Shell::BasicGetSpecialFolder(DWORD csidl, CString* folder_path) {
253 ASSERT1(folder_path);
254
255 // Get a ITEMIDLIST* (called a PIDL in the MSDN documentation) to the
256 // special folder
257 scoped_any<ITEMIDLIST*, close_co_task_free> folder_location;
258 RET_IF_FAILED(::SHGetFolderLocation(NULL,
259 csidl,
260 NULL,
261 0,
262 address(folder_location)));
263 ASSERT(get(folder_location), (_T("")));
264
265 // Get an interface to the Desktop folder
266 CComPtr<IShellFolder> desktop_folder;
267 RET_IF_FAILED(::SHGetDesktopFolder(&desktop_folder));
268 ASSERT1(desktop_folder);
269
270 // Ask the desktop for the display name of the special folder
271 STRRET str_return;
272 SetZero(str_return);
273 str_return.uType = STRRET_WSTR;
274 RET_IF_FAILED(desktop_folder->GetDisplayNameOf(get(folder_location),
275 SHGDN_FORPARSING,
276 &str_return));
277
278 // Get the display name of the special folder and return it
279 scoped_any<wchar_t*, close_co_task_free> folder_name;
280 RET_IF_FAILED(::StrRetToStr(&str_return,
281 get(folder_location),
282 address(folder_name)));
283 *folder_path = get(folder_name);
284
285 return S_OK;
286 }
287
288 HRESULT Shell::GetSpecialFolder(DWORD csidl,
289 bool create_if_missing,
290 CString* folder_path) {
291 ASSERT(folder_path, (L""));
292
293 HRESULT hr = Shell::BasicGetSpecialFolder(csidl, folder_path);
294
295 // If the folder does not exist, ::SHGetFolderLocation may return error
296 // code ERROR_FILE_NOT_FOUND.
297 if (create_if_missing) {
298 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
299 (SUCCEEDED(hr) && !File::Exists(*folder_path))) {
300 hr = Shell::BasicGetSpecialFolder(csidl | CSIDL_FLAG_CREATE, folder_path);
301 }
302 }
303 ASSERT(FAILED(hr) || File::Exists(*folder_path), (_T("")));
304
305 return hr;
306 }
307
308 #pragma warning(disable : 4510 4610)
309 // C4510: default constructor could not be generated
310 // C4610: struct can never be instantiated - user defined constructor required
311 struct {
312 const TCHAR* name;
313 const DWORD csidl;
314 } const folder_mappings[] = {
315 L"APPDATA", CSIDL_APPDATA,
316 L"DESKTOP", CSIDL_DESKTOPDIRECTORY,
317 L"LOCALAPPDATA", CSIDL_LOCAL_APPDATA,
318 L"MYMUSIC", CSIDL_MYMUSIC,
319 L"MYPICTURES", CSIDL_MYPICTURES,
320 L"PROGRAMFILES", CSIDL_PROGRAM_FILES,
321 L"PROGRAMFILESCOMMON", CSIDL_PROGRAM_FILES_COMMON,
322 L"PROGRAMS", CSIDL_PROGRAMS,
323 L"STARTMENU", CSIDL_STARTMENU,
324 L"STARTUP", CSIDL_STARTUP,
325 L"SYSTEM", CSIDL_SYSTEM,
326 L"WINDOWS", CSIDL_WINDOWS,
327 };
328 #pragma warning(default : 4510 4610)
329
330 HRESULT Shell::GetSpecialFolderKeywordsMapping(
331 std::map<CString, CString>* special_folders_map) {
332 ASSERT1(special_folders_map);
333
334 special_folders_map->clear();
335
336 for (size_t i = 0; i < arraysize(folder_mappings); ++i) {
337 CString name(folder_mappings[i].name);
338 DWORD csidl(folder_mappings[i].csidl);
339 CString folder;
340 HRESULT hr = GetSpecialFolder(csidl, false, &folder);
341 if (FAILED(hr)) {
342 UTIL_LOG(LE, (_T("[Shell::GetSpecialFolderKeywordsMapping]")
343 _T("[failed to retrieve %s]"), name));
344 continue;
345 }
346 special_folders_map->insert(std::make_pair(name, folder));
347 }
348
349 // Get the current module directory
350 CString module_dir = app_util::GetModuleDirectory(::GetModuleHandle(NULL));
351 ASSERT1(module_dir.GetLength() > 0);
352 special_folders_map->insert(std::make_pair(_T("CURRENTMODULEDIR"),
353 module_dir));
354
355 return S_OK;
356 }
357
358 HRESULT Shell::DeleteDirectory(const TCHAR* dir) {
359 ASSERT1(dir && *dir);
360
361 if (!SafeDirectoryNameForDeletion(dir)) {
362 return E_INVALIDARG;
363 }
364
365 uint32 dir_len = lstrlen(dir);
366 if (dir_len >= MAX_PATH) {
367 return E_INVALIDARG;
368 }
369
370 // the 'from' must be double-terminated with 0. Reserve space for one more
371 // zero at the end
372 TCHAR from[MAX_PATH + 1] = {0};
373 lstrcpyn(from, dir, MAX_PATH);
374 from[1 + dir_len] = 0; // the second zero terminator.
375
376 SHFILEOPSTRUCT file_op = {0};
377
378 file_op.hwnd = 0;
379 file_op.wFunc = FO_DELETE;
380 file_op.pFrom = from;
381 file_op.pTo = 0;
382 file_op.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
383
384 // ::SHFileOperation returns non-zero on errors
385 return ::SHFileOperation(&file_op) ? HRESULTFromLastError() : S_OK;
386 }
387
388 HRESULT Shell::GetApplicationExecutablePath(const CString& exe,
389 CString* path) {
390 ASSERT1(path);
391
392 CString reg_key_name = AppendRegKeyPath(kRegKeyApplicationPath, exe);
393 return RegKey::GetValue(reg_key_name, kRegKeyPathValue, path);
394 }
395
396 } // namespace omaha
397
OLDNEW
« no previous file with comments | « base/shell.h ('k') | base/shell_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698