OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/file_util.h" | 5 #include "base/file_util.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <propvarutil.h> | |
9 #include <psapi.h> | 8 #include <psapi.h> |
10 #include <shellapi.h> | 9 #include <shellapi.h> |
11 #include <shlobj.h> | 10 #include <shlobj.h> |
12 #include <time.h> | 11 #include <time.h> |
13 | 12 |
14 #include <limits> | 13 #include <limits> |
15 #include <string> | 14 #include <string> |
16 | 15 |
17 #include "base/file_path.h" | 16 #include "base/file_path.h" |
18 #include "base/logging.h" | 17 #include "base/logging.h" |
19 #include "base/metrics/histogram.h" | 18 #include "base/metrics/histogram.h" |
20 #include "base/process_util.h" | 19 #include "base/process_util.h" |
21 #include "base/string_number_conversions.h" | 20 #include "base/string_number_conversions.h" |
22 #include "base/string_util.h" | 21 #include "base/string_util.h" |
23 #include "base/threading/thread_restrictions.h" | 22 #include "base/threading/thread_restrictions.h" |
24 #include "base/time.h" | 23 #include "base/time.h" |
25 #include "base/utf_string_conversions.h" | 24 #include "base/utf_string_conversions.h" |
26 #include "base/win/pe_image.h" | |
27 #include "base/win/scoped_comptr.h" | |
28 #include "base/win/scoped_handle.h" | 25 #include "base/win/scoped_handle.h" |
29 #include "base/win/win_util.h" | |
30 #include "base/win/windows_version.h" | 26 #include "base/win/windows_version.h" |
31 | 27 |
32 namespace file_util { | 28 namespace file_util { |
33 | 29 |
34 namespace { | 30 namespace { |
35 | 31 |
36 const DWORD kFileShareAll = | 32 const DWORD kFileShareAll = |
37 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; | 33 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; |
38 | 34 |
39 } // namespace | 35 } // namespace |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 | 321 |
326 bool GetFileCreationLocalTime(const std::wstring& filename, | 322 bool GetFileCreationLocalTime(const std::wstring& filename, |
327 LPSYSTEMTIME creation_time) { | 323 LPSYSTEMTIME creation_time) { |
328 base::ThreadRestrictions::AssertIOAllowed(); | 324 base::ThreadRestrictions::AssertIOAllowed(); |
329 base::win::ScopedHandle file_handle( | 325 base::win::ScopedHandle file_handle( |
330 CreateFile(filename.c_str(), GENERIC_READ, kFileShareAll, NULL, | 326 CreateFile(filename.c_str(), GENERIC_READ, kFileShareAll, NULL, |
331 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); | 327 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); |
332 return GetFileCreationLocalTimeFromHandle(file_handle.Get(), creation_time); | 328 return GetFileCreationLocalTimeFromHandle(file_handle.Get(), creation_time); |
333 } | 329 } |
334 | 330 |
335 bool ResolveShortcut(const FilePath& shortcut_path, | |
336 FilePath* target_path, | |
337 string16* args) { | |
338 base::ThreadRestrictions::AssertIOAllowed(); | |
339 | |
340 HRESULT result; | |
341 base::win::ScopedComPtr<IShellLink> i_shell_link; | |
342 | |
343 // Get pointer to the IShellLink interface. | |
344 result = i_shell_link.CreateInstance(CLSID_ShellLink, NULL, | |
345 CLSCTX_INPROC_SERVER); | |
346 if (FAILED(result)) | |
347 return false; | |
348 | |
349 base::win::ScopedComPtr<IPersistFile> persist; | |
350 // Query IShellLink for the IPersistFile interface. | |
351 result = persist.QueryFrom(i_shell_link); | |
352 if (FAILED(result)) | |
353 return false; | |
354 | |
355 // Load the shell link. | |
356 result = persist->Load(shortcut_path.value().c_str(), STGM_READ); | |
357 if (FAILED(result)) | |
358 return false; | |
359 | |
360 WCHAR temp[MAX_PATH]; | |
361 if (target_path) { | |
362 // Try to find the target of a shortcut. | |
363 result = i_shell_link->Resolve(0, SLR_NO_UI); | |
364 if (FAILED(result)) | |
365 return false; | |
366 | |
367 result = i_shell_link->GetPath(temp, MAX_PATH, NULL, SLGP_UNCPRIORITY); | |
368 if (FAILED(result)) | |
369 return false; | |
370 | |
371 *target_path = FilePath(temp); | |
372 } | |
373 | |
374 if (args) { | |
375 result = i_shell_link->GetArguments(temp, MAX_PATH); | |
376 if (FAILED(result)) | |
377 return false; | |
378 | |
379 *args = string16(temp); | |
380 } | |
381 return true; | |
382 } | |
383 | |
384 bool CreateOrUpdateShortcutLink(const wchar_t *source, | |
385 const wchar_t *destination, | |
386 const wchar_t *working_dir, | |
387 const wchar_t *arguments, | |
388 const wchar_t *description, | |
389 const wchar_t *icon, | |
390 int icon_index, | |
391 const wchar_t* app_id, | |
392 uint32 options) { | |
393 base::ThreadRestrictions::AssertIOAllowed(); | |
394 | |
395 bool create = (options & SHORTCUT_CREATE_ALWAYS) != 0; | |
396 | |
397 // |source| is required when SHORTCUT_CREATE_ALWAYS is specified. | |
398 DCHECK(source || !create); | |
399 | |
400 // Length of arguments and description must be less than MAX_PATH. | |
401 DCHECK(lstrlen(arguments) < MAX_PATH); | |
402 DCHECK(lstrlen(description) < MAX_PATH); | |
403 | |
404 base::win::ScopedComPtr<IShellLink> i_shell_link; | |
405 base::win::ScopedComPtr<IPersistFile> i_persist_file; | |
406 | |
407 // Get pointer to the IShellLink interface. | |
408 if (FAILED(i_shell_link.CreateInstance(CLSID_ShellLink, NULL, | |
409 CLSCTX_INPROC_SERVER)) || | |
410 FAILED(i_persist_file.QueryFrom(i_shell_link))) { | |
411 return false; | |
412 } | |
413 | |
414 if (!create && FAILED(i_persist_file->Load(destination, STGM_READWRITE))) | |
415 return false; | |
416 | |
417 if ((source || create) && FAILED(i_shell_link->SetPath(source))) | |
418 return false; | |
419 | |
420 if (working_dir && FAILED(i_shell_link->SetWorkingDirectory(working_dir))) | |
421 return false; | |
422 | |
423 if (arguments && FAILED(i_shell_link->SetArguments(arguments))) | |
424 return false; | |
425 | |
426 if (description && FAILED(i_shell_link->SetDescription(description))) | |
427 return false; | |
428 | |
429 if (icon && FAILED(i_shell_link->SetIconLocation(icon, icon_index))) | |
430 return false; | |
431 | |
432 bool is_dual_mode = (options & SHORTCUT_DUAL_MODE) != 0; | |
433 if ((app_id || is_dual_mode) && | |
434 base::win::GetVersion() >= base::win::VERSION_WIN7) { | |
435 base::win::ScopedComPtr<IPropertyStore> property_store; | |
436 if (FAILED(property_store.QueryFrom(i_shell_link)) || !property_store.get()) | |
437 return false; | |
438 | |
439 if (app_id && !base::win::SetAppIdForPropertyStore(property_store, app_id)) | |
440 return false; | |
441 if (is_dual_mode && | |
442 !base::win::SetDualModeForPropertyStore(property_store)) { | |
443 return false; | |
444 } | |
445 } | |
446 | |
447 HRESULT result = i_persist_file->Save(destination, TRUE); | |
448 | |
449 // If we successfully updated the icon, notify the shell that we have done so. | |
450 if (!create && SUCCEEDED(result)) { | |
451 // Release the interfaces in case the SHChangeNotify call below depends on | |
452 // the operations above being fully completed. | |
453 i_persist_file.Release(); | |
454 i_shell_link.Release(); | |
455 | |
456 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); | |
457 } | |
458 | |
459 return SUCCEEDED(result); | |
460 } | |
461 | |
462 bool TaskbarPinShortcutLink(const wchar_t* shortcut) { | |
463 base::ThreadRestrictions::AssertIOAllowed(); | |
464 | |
465 // "Pin to taskbar" is only supported after Win7. | |
466 if (base::win::GetVersion() < base::win::VERSION_WIN7) | |
467 return false; | |
468 | |
469 int result = reinterpret_cast<int>(ShellExecute(NULL, L"taskbarpin", shortcut, | |
470 NULL, NULL, 0)); | |
471 return result > 32; | |
472 } | |
473 | |
474 bool TaskbarUnpinShortcutLink(const wchar_t* shortcut) { | |
475 base::ThreadRestrictions::AssertIOAllowed(); | |
476 | |
477 // "Unpin from taskbar" is only supported after Win7. | |
478 if (base::win::GetVersion() < base::win::VERSION_WIN7) | |
479 return false; | |
480 | |
481 int result = reinterpret_cast<int>(ShellExecute(NULL, L"taskbarunpin", | |
482 shortcut, NULL, NULL, 0)); | |
483 return result > 32; | |
484 } | |
485 | |
486 bool GetTempDir(FilePath* path) { | 331 bool GetTempDir(FilePath* path) { |
487 base::ThreadRestrictions::AssertIOAllowed(); | 332 base::ThreadRestrictions::AssertIOAllowed(); |
488 | 333 |
489 wchar_t temp_path[MAX_PATH + 1]; | 334 wchar_t temp_path[MAX_PATH + 1]; |
490 DWORD path_len = ::GetTempPath(MAX_PATH, temp_path); | 335 DWORD path_len = ::GetTempPath(MAX_PATH, temp_path); |
491 if (path_len >= MAX_PATH || path_len <= 0) | 336 if (path_len >= MAX_PATH || path_len <= 0) |
492 return false; | 337 return false; |
493 // TODO(evanm): the old behavior of this function was to always strip the | 338 // TODO(evanm): the old behavior of this function was to always strip the |
494 // trailing slash. We duplicate this here, but it shouldn't be necessary | 339 // trailing slash. We duplicate this here, but it shouldn't be necessary |
495 // when everyone is using the appropriate FilePath APIs. | 340 // when everyone is using the appropriate FilePath APIs. |
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1122 HANDLE cp = GetCurrentProcess(); | 967 HANDLE cp = GetCurrentProcess(); |
1123 if (::GetMappedFileNameW(cp, file_view, mapped_file_path, kMaxPathLength)) { | 968 if (::GetMappedFileNameW(cp, file_view, mapped_file_path, kMaxPathLength)) { |
1124 *nt_path = FilePath(mapped_file_path); | 969 *nt_path = FilePath(mapped_file_path); |
1125 success = true; | 970 success = true; |
1126 } | 971 } |
1127 ::UnmapViewOfFile(file_view); | 972 ::UnmapViewOfFile(file_view); |
1128 return success; | 973 return success; |
1129 } | 974 } |
1130 | 975 |
1131 } // namespace file_util | 976 } // namespace file_util |
OLD | NEW |