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 "ui/base/win/shell.h" 6 7#include <dwmapi.h> 8#include <shlobj.h> // Must be before propkey. 9#include <propkey.h> 10#include <shellapi.h> 11 12#include "base/command_line.h" 13#include "base/files/file_path.h" 14#include "base/native_library.h" 15#include "base/strings/string_util.h" 16#include "base/win/metro.h" 17#include "base/win/scoped_comptr.h" 18#include "base/win/win_util.h" 19#include "base/win/windows_version.h" 20#include "ui/base/ui_base_switches.h" 21 22namespace ui { 23namespace win { 24 25namespace { 26 27void SetAppDetailsForWindow(const string16& app_id, 28 const string16& app_icon, 29 const string16& relaunch_command, 30 const string16& relaunch_display_name, 31 HWND hwnd) { 32 // This functionality is only available on Win7+. It also doesn't make sense 33 // to do this for Chrome Metro. 34 if (base::win::GetVersion() < base::win::VERSION_WIN7 || 35 base::win::IsMetroProcess()) 36 return; 37 base::win::ScopedComPtr<IPropertyStore> pps; 38 HRESULT result = SHGetPropertyStoreForWindow( 39 hwnd, __uuidof(*pps), reinterpret_cast<void**>(pps.Receive())); 40 if (S_OK == result) { 41 if (!app_id.empty()) 42 base::win::SetAppIdForPropertyStore(pps, app_id.c_str()); 43 if (!app_icon.empty()) { 44 base::win::SetStringValueForPropertyStore( 45 pps, PKEY_AppUserModel_RelaunchIconResource, app_icon.c_str()); 46 } 47 if (!relaunch_command.empty()) { 48 base::win::SetStringValueForPropertyStore( 49 pps, PKEY_AppUserModel_RelaunchCommand, relaunch_command.c_str()); 50 } 51 if (!relaunch_display_name.empty()) { 52 base::win::SetStringValueForPropertyStore( 53 pps, PKEY_AppUserModel_RelaunchDisplayNameResource, 54 relaunch_display_name.c_str()); 55 } 56 } 57} 58 59} // namespace 60 61// Show the Windows "Open With" dialog box to ask the user to pick an app to 62// open the file with. 63bool OpenItemWithExternalApp(const string16& full_path) { 64 SHELLEXECUTEINFO sei = { sizeof(sei) }; 65 sei.fMask = SEE_MASK_FLAG_DDEWAIT; 66 sei.nShow = SW_SHOWNORMAL; 67 sei.lpVerb = L"openas"; 68 sei.lpFile = full_path.c_str(); 69 return (TRUE == ::ShellExecuteExW(&sei)); 70} 71 72bool OpenAnyViaShell(const string16& full_path, 73 const string16& directory, 74 const string16& args, 75 DWORD mask) { 76 SHELLEXECUTEINFO sei = { sizeof(sei) }; 77 sei.fMask = mask; 78 sei.nShow = SW_SHOWNORMAL; 79 sei.lpFile = full_path.c_str(); 80 sei.lpDirectory = directory.c_str(); 81 if (!args.empty()) 82 sei.lpParameters = args.c_str(); 83 84 if (::ShellExecuteExW(&sei)) 85 return true; 86 if (::GetLastError() == ERROR_NO_ASSOCIATION) 87 return OpenItemWithExternalApp(full_path); 88 return false; 89} 90 91bool OpenItemViaShell(const base::FilePath& full_path) { 92 return OpenAnyViaShell(full_path.value(), full_path.DirName().value(), 93 string16(), 0); 94} 95 96bool OpenItemViaShellNoZoneCheck(const base::FilePath& full_path) { 97 return OpenAnyViaShell(full_path.value(), string16(), string16(), 98 SEE_MASK_NOZONECHECKS | SEE_MASK_FLAG_DDEWAIT); 99} 100 101void SetAppIdForWindow(const string16& app_id, HWND hwnd) { 102 SetAppDetailsForWindow(app_id, string16(), string16(), string16(), hwnd); 103} 104 105void SetAppIconForWindow(const string16& app_icon, HWND hwnd) { 106 SetAppDetailsForWindow(string16(), app_icon, string16(), string16(), hwnd); 107} 108 109void SetRelaunchDetailsForWindow(const string16& relaunch_command, 110 const string16& display_name, 111 HWND hwnd) { 112 SetAppDetailsForWindow(string16(), 113 string16(), 114 relaunch_command, 115 display_name, 116 hwnd); 117} 118 119bool IsAeroGlassEnabled() { 120 // For testing in Win8 (where it is not possible to disable composition) the 121 // user can specify this command line switch to mimic the behavior. In this 122 // mode, cross-HWND transparency is not supported and various types of 123 // widgets fallback to more simplified rendering behavior. 124 if (CommandLine::ForCurrentProcess()->HasSwitch( 125 switches::kDisableDwmComposition)) 126 return false; 127 128 if (base::win::GetVersion() < base::win::VERSION_VISTA) 129 return false; 130 // If composition is not enabled, we behave like on XP. 131 BOOL enabled = FALSE; 132 return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled; 133} 134 135} // namespace win 136} // namespace ui 137