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.
5 #include "ui/base/win/shell.h"
8 #include <shlobj.h> // Must be before propkey.
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"
25 // Show the Windows "Open With" dialog box to ask the user to pick an app to
26 // open the file with.
27 bool OpenItemWithExternalApp(const base::string16
& full_path
) {
28 SHELLEXECUTEINFO sei
= { sizeof(sei
) };
29 sei
.fMask
= SEE_MASK_FLAG_DDEWAIT
;
30 sei
.nShow
= SW_SHOWNORMAL
;
31 sei
.lpVerb
= L
"openas";
32 sei
.lpFile
= full_path
.c_str();
33 return (TRUE
== ::ShellExecuteExW(&sei
));
36 bool OpenAnyViaShell(const base::string16
& full_path
,
37 const base::string16
& directory
,
38 const base::string16
& args
,
40 SHELLEXECUTEINFO sei
= { sizeof(sei
) };
42 sei
.nShow
= SW_SHOWNORMAL
;
43 sei
.lpFile
= full_path
.c_str();
44 sei
.lpDirectory
= directory
.c_str();
46 sei
.lpParameters
= args
.c_str();
48 if (::ShellExecuteExW(&sei
))
50 if (::GetLastError() == ERROR_NO_ASSOCIATION
)
51 return OpenItemWithExternalApp(full_path
);
55 bool OpenItemViaShell(const base::FilePath
& full_path
) {
56 return OpenAnyViaShell(full_path
.value(), full_path
.DirName().value(),
60 bool OpenItemViaShellNoZoneCheck(const base::FilePath
& full_path
) {
61 return OpenAnyViaShell(full_path
.value(), base::string16(), base::string16(),
62 SEE_MASK_NOZONECHECKS
| SEE_MASK_FLAG_DDEWAIT
);
65 bool PreventWindowFromPinning(HWND hwnd
) {
66 // This functionality is only available on Win7+. It also doesn't make sense
67 // to do this for Chrome Metro.
68 if (base::win::GetVersion() < base::win::VERSION_WIN7
||
69 base::win::IsMetroProcess())
71 base::win::ScopedComPtr
<IPropertyStore
> pps
;
72 HRESULT result
= SHGetPropertyStoreForWindow(
73 hwnd
, __uuidof(*pps
), reinterpret_cast<void**>(pps
.Receive()));
77 return base::win::SetBooleanValueForPropertyStore(
78 pps
, PKEY_AppUserModel_PreventPinning
, true);
81 // TODO(calamity): investigate moving this out of the UI thread as COM
82 // operations may spawn nested message loops which can cause issues.
83 void SetAppDetailsForWindow(const base::string16
& app_id
,
84 const base::string16
& app_icon
,
85 const base::string16
& relaunch_command
,
86 const base::string16
& relaunch_display_name
,
88 // This functionality is only available on Win7+. It also doesn't make sense
89 // to do this for Chrome Metro.
90 if (base::win::GetVersion() < base::win::VERSION_WIN7
||
91 base::win::IsMetroProcess())
93 base::win::ScopedComPtr
<IPropertyStore
> pps
;
94 HRESULT result
= SHGetPropertyStoreForWindow(
95 hwnd
, __uuidof(*pps
), reinterpret_cast<void**>(pps
.Receive()));
98 base::win::SetAppIdForPropertyStore(pps
, app_id
.c_str());
99 if (!app_icon
.empty()) {
100 base::win::SetStringValueForPropertyStore(
101 pps
, PKEY_AppUserModel_RelaunchIconResource
, app_icon
.c_str());
103 if (!relaunch_command
.empty()) {
104 base::win::SetStringValueForPropertyStore(
105 pps
, PKEY_AppUserModel_RelaunchCommand
, relaunch_command
.c_str());
107 if (!relaunch_display_name
.empty()) {
108 base::win::SetStringValueForPropertyStore(
109 pps
, PKEY_AppUserModel_RelaunchDisplayNameResource
,
110 relaunch_display_name
.c_str());
115 void SetAppIdForWindow(const base::string16
& app_id
, HWND hwnd
) {
116 SetAppDetailsForWindow(app_id
,
123 void SetAppIconForWindow(const base::string16
& app_icon
, HWND hwnd
) {
124 SetAppDetailsForWindow(base::string16(),
131 void SetRelaunchDetailsForWindow(const base::string16
& relaunch_command
,
132 const base::string16
& display_name
,
134 SetAppDetailsForWindow(base::string16(),
141 bool IsAeroGlassEnabled() {
142 // For testing in Win8 (where it is not possible to disable composition) the
143 // user can specify this command line switch to mimic the behavior. In this
144 // mode, cross-HWND transparency is not supported and various types of
145 // widgets fallback to more simplified rendering behavior.
146 if (CommandLine::ForCurrentProcess()->HasSwitch(
147 switches::kDisableDwmComposition
))
150 if (base::win::GetVersion() < base::win::VERSION_VISTA
)
152 // If composition is not enabled, we behave like on XP.
153 BOOL enabled
= FALSE
;
154 return SUCCEEDED(DwmIsCompositionEnabled(&enabled
)) && enabled
;