OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 "app/win/shell.h" | |
6 | |
7 #include <shellapi.h> | |
8 #include <shlobj.h> | |
9 | |
10 #include "base/file_path.h" | |
11 #include "base/native_library.h" | |
12 #include "base/string_util.h" | |
13 #include "base/win/scoped_comptr.h" | |
14 #include "base/win/win_util.h" | |
15 #include "base/win/windows_version.h" | |
16 | |
17 namespace app { | |
18 namespace win { | |
19 | |
20 namespace { | |
21 | |
22 const wchar_t kShell32[] = L"shell32.dll"; | |
23 const char kSHGetPropertyStoreForWindow[] = "SHGetPropertyStoreForWindow"; | |
24 | |
25 // Define the type of SHGetPropertyStoreForWindow is SHGPSFW. | |
26 typedef DECLSPEC_IMPORT HRESULT (STDAPICALLTYPE *SHGPSFW)(HWND hwnd, | |
27 REFIID riid, | |
28 void** ppv); | |
29 | |
30 } // namespace | |
31 | |
32 // Open an item via a shell execute command. Error code checking and casting | |
33 // explanation: http://msdn2.microsoft.com/en-us/library/ms647732.aspx | |
34 bool OpenItemViaShell(const FilePath& full_path) { | |
35 HINSTANCE h = ::ShellExecuteW( | |
36 NULL, NULL, full_path.value().c_str(), NULL, | |
37 full_path.DirName().value().c_str(), SW_SHOWNORMAL); | |
38 | |
39 LONG_PTR error = reinterpret_cast<LONG_PTR>(h); | |
40 if (error > 32) | |
41 return true; | |
42 | |
43 if ((error == SE_ERR_NOASSOC)) | |
44 return OpenItemWithExternalApp(full_path.value()); | |
45 | |
46 return false; | |
47 } | |
48 | |
49 bool OpenItemViaShellNoZoneCheck(const FilePath& full_path) { | |
50 SHELLEXECUTEINFO sei = { sizeof(sei) }; | |
51 sei.fMask = SEE_MASK_NOZONECHECKS | SEE_MASK_FLAG_DDEWAIT; | |
52 sei.nShow = SW_SHOWNORMAL; | |
53 sei.lpVerb = NULL; | |
54 sei.lpFile = full_path.value().c_str(); | |
55 if (::ShellExecuteExW(&sei)) | |
56 return true; | |
57 LONG_PTR error = reinterpret_cast<LONG_PTR>(sei.hInstApp); | |
58 if ((error == SE_ERR_NOASSOC)) | |
59 return OpenItemWithExternalApp(full_path.value()); | |
60 return false; | |
61 } | |
62 | |
63 // Show the Windows "Open With" dialog box to ask the user to pick an app to | |
64 // open the file with. | |
65 bool OpenItemWithExternalApp(const string16& full_path) { | |
66 SHELLEXECUTEINFO sei = { sizeof(sei) }; | |
67 sei.fMask = SEE_MASK_FLAG_DDEWAIT; | |
68 sei.nShow = SW_SHOWNORMAL; | |
69 sei.lpVerb = L"openas"; | |
70 sei.lpFile = full_path.c_str(); | |
71 return (TRUE == ::ShellExecuteExW(&sei)); | |
72 } | |
73 | |
74 void SetAppIdForWindow(const string16& app_id, HWND hwnd) { | |
75 // This functionality is only available on Win7+. | |
76 if (base::win::GetVersion() < base::win::VERSION_WIN7) | |
77 return; | |
78 | |
79 // Load Shell32.dll into memory. | |
80 // TODO(brg): Remove this mechanism when the Win7 SDK is available in trunk. | |
81 std::wstring shell32_filename(kShell32); | |
82 FilePath shell32_filepath(shell32_filename); | |
83 base::NativeLibrary shell32_library = base::LoadNativeLibrary( | |
84 shell32_filepath, NULL); | |
85 | |
86 if (!shell32_library) | |
87 return; | |
88 | |
89 // Get the function pointer for SHGetPropertyStoreForWindow. | |
90 void* function = base::GetFunctionPointerFromNativeLibrary( | |
91 shell32_library, | |
92 kSHGetPropertyStoreForWindow); | |
93 | |
94 if (!function) { | |
95 base::UnloadNativeLibrary(shell32_library); | |
96 return; | |
97 } | |
98 | |
99 // Set the application's name. | |
100 base::win::ScopedComPtr<IPropertyStore> pps; | |
101 SHGPSFW SHGetPropertyStoreForWindow = static_cast<SHGPSFW>(function); | |
102 HRESULT result = SHGetPropertyStoreForWindow( | |
103 hwnd, __uuidof(*pps), reinterpret_cast<void**>(pps.Receive())); | |
104 if (S_OK == result) | |
105 base::win::SetAppIdForPropertyStore(pps, app_id.c_str()); | |
106 | |
107 // Cleanup. | |
108 base::UnloadNativeLibrary(shell32_library); | |
109 } | |
110 | |
111 } // namespace win | |
112 } // namespace app | |
OLD | NEW |