| 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 |