summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-05 00:47:17 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-05 00:47:17 +0000
commit8c96af8431a78412ce6cdec1f5d0cf2c0a2f1e9a (patch)
tree53feadabd32f0bd444499321bd6ea5cdaa3b6112
parentea9dc9a73e96c97a586c97af2e7a54b851bb1245 (diff)
downloadchromium_src-8c96af8431a78412ce6cdec1f5d0cf2c0a2f1e9a.zip
chromium_src-8c96af8431a78412ce6cdec1f5d0cf2c0a2f1e9a.tar.gz
chromium_src-8c96af8431a78412ce6cdec1f5d0cf2c0a2f1e9a.tar.bz2
In prepartion for switching off the activex control, make WMP always use the new UI on XP even if we couldn't update the ShimInclusionList key because of non-admin install. This change patches RegEnumKey, if needed, so that WMP thinks the key contains chrome.exe
BUG=20259 Review URL: http://codereview.chromium.org/193024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25566 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h6
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_win.cc147
2 files changed, 133 insertions, 20 deletions
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index 1ceb8f5..56d5b6e 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -43,6 +43,7 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
PLUGIN_QUIRK_WINDOWLESS_OFFSET_WINDOW_TO_DRAW = 256, // Linux
PLUGIN_QUIRK_WINDOWLESS_INVALIDATE_AFTER_SET_WINDOW = 512, // Linux
PLUGIN_QUIRK_NO_WINDOWLESS = 1024, // Windows
+ PLUGIN_QUIRK_PATCH_REGENUMKEYEXW = 2048, // Windows
};
static WebPluginDelegateImpl* Create(const FilePath& filename,
@@ -310,6 +311,11 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
// SetCursor interceptor for windowless plugins.
static HCURSOR WINAPI SetCursorPatch(HCURSOR cursor);
+
+ // RegEnumKeyExW interceptor.
+ static LONG WINAPI RegEnumKeyExWPatch(
+ HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved,
+ LPWSTR class_name, LPDWORD class_size, PFILETIME last_write_time);
#endif
#if defined(OS_MACOSX)
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_win.cc b/webkit/glue/plugins/webplugin_delegate_impl_win.cc
index a1e1b18..64b0805 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl_win.cc
+++ b/webkit/glue/plugins/webplugin_delegate_impl_win.cc
@@ -11,8 +11,11 @@
#include "base/iat_patch.h"
#include "base/lazy_instance.h"
#include "base/message_loop.h"
+#include "base/registry.h"
+#include "base/scoped_ptr.h"
#include "base/stats_counters.h"
#include "base/string_util.h"
+#include "base/win_util.h"
#include "webkit/api/public/WebInputEvent.h"
#include "webkit/default_plugin/plugin_impl.h"
#include "webkit/glue/glue_util.h"
@@ -67,6 +70,10 @@ base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_track_popup_menu(
base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_set_cursor(
base::LINKER_INITIALIZED);
+// Helper object for patching the RegEnumKeyExW API.
+base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w(
+ base::LINKER_INITIALIZED);
+
// http://crbug.com/16114
// Enforces providing a valid device context in NPWindow, so that NPP_SetWindow
// is never called with NPNWindoTypeDrawable and NPWindow set to NULL.
@@ -99,6 +106,71 @@ class DrawableContextEnforcer {
bool disposable_dc_;
};
+// These are from ntddk.h
+typedef LONG NTSTATUS;
+
+#ifndef STATUS_SUCCESS
+#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+#endif
+
+#ifndef STATUS_BUFFER_TOO_SMALL
+#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
+#endif
+
+typedef enum _KEY_INFORMATION_CLASS {
+ KeyBasicInformation,
+ KeyNodeInformation,
+ KeyFullInformation,
+ KeyNameInformation,
+ KeyCachedInformation,
+ KeyVirtualizationInformation
+} KEY_INFORMATION_CLASS;
+
+typedef struct _KEY_NAME_INFORMATION {
+ ULONG NameLength;
+ WCHAR Name[1];
+} KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
+
+typedef DWORD (__stdcall *ZwQueryKeyType)(
+ HANDLE key_handle,
+ int key_information_class,
+ PVOID key_information,
+ ULONG length,
+ PULONG result_length);
+
+// Returns a key's full path.
+std::wstring GetKeyPath(HKEY key) {
+ if (key == NULL)
+ return L"";
+
+ HMODULE dll = GetModuleHandle(L"ntdll.dll");
+ if (dll == NULL)
+ return L"";
+
+ ZwQueryKeyType func = reinterpret_cast<ZwQueryKeyType>(
+ ::GetProcAddress(dll, "ZwQueryKey"));
+ if (func == NULL)
+ return L"";
+
+ DWORD size = 0;
+ DWORD result = 0;
+ result = func(key, KeyNameInformation, 0, 0, &size);
+ if (result != STATUS_BUFFER_TOO_SMALL)
+ return L"";
+
+ scoped_array<char> buffer(new char[size]);
+ if (buffer.get() == NULL)
+ return L"";
+
+ result = func(key, KeyNameInformation, buffer.get(), size, &size);
+ if (result != STATUS_SUCCESS)
+ return L"";
+
+ KEY_NAME_INFORMATION* info =
+ reinterpret_cast<KEY_NAME_INFORMATION*>(buffer.get());
+ return std::wstring(info->Name, info->NameLength / sizeof(wchar_t));
+}
+
} // namespace
bool WebPluginDelegateImpl::IsPluginDelegateWindow(HWND window) {
@@ -206,6 +278,9 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
// Windowless mode doesn't work in the WMP NPAPI plugin.
quirks_ |= PLUGIN_QUIRK_NO_WINDOWLESS;
+
+ // Non-admin users on XP couldn't modify the key to force the new UI.
+ quirks_ |= PLUGIN_QUIRK_PATCH_REGENUMKEYEXW;
} else if (instance_->mime_type() == "audio/x-pn-realaudio-plugin" ||
filename == "nppl3260.dll") {
quirks_ |= PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY;
@@ -218,7 +293,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY;
// VLC 0.8.6d and 0.8.6e crash if multiple instances are created.
quirks_ |= PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES;
- } else if (filename == "npctrl.dll") {
+ } else if (filename == "npctrl.dll") { // Silverlight
// Explanation for this quirk can be found in
// WebPluginDelegateImpl::Initialize.
quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
@@ -256,14 +331,12 @@ void WebPluginDelegateImpl::PlatformInitialize() {
plugin_->SetWindowlessPumpEvent(handle_event_pump_messages_event_);
}
- // The windowless version of the Silverlight plugin calls the
- // WindowFromPoint API and passes the result of that to the
- // TrackPopupMenu API call as the owner window. This causes the API
- // to fail as the API expects the window handle to live on the same
- // thread as the caller. It works in the other browsers as the plugin
- // lives on the browser thread. Our workaround is to intercept the
- // TrackPopupMenu API for Silverlight and replace the window handle
- // with the dummy activation window.
+ // Windowless plugins call the WindowFromPoint API and passes the result of
+ // that to the TrackPopupMenu API call as the owner window. This causes the
+ // API to fail as the API expects the window handle to live on the same thread
+ // as the caller. It works in the other browsers as the plugin lives on the
+ // browser thread. Our workaround is to intercept the TrackPopupMenu API and
+ // replace the window handle with the dummy activation window.
if (windowless_ && !g_iat_patch_track_popup_menu.Pointer()->is_patched()) {
g_iat_patch_track_popup_menu.Pointer()->Patch(
GetPluginPath().value().c_str(), "user32.dll", "TrackPopupMenu",
@@ -282,21 +355,37 @@ void WebPluginDelegateImpl::PlatformInitialize() {
GetPluginPath().value().c_str(), "user32.dll", "SetCursor",
WebPluginDelegateImpl::SetCursorPatch);
}
+
+ // On XP, WMP will use its old UI unless a registry key under HKLM has the
+ // name of the current process. We do it in the installer for admin users,
+ // for the rest patch this function.
+ if ((quirks_ & PLUGIN_QUIRK_PATCH_REGENUMKEYEXW) &&
+ win_util::GetWinVersion() == win_util::WINVERSION_XP &&
+ !RegKey().Open(HKEY_LOCAL_MACHINE,
+ L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe") &&
+ !g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) {
+ g_iat_patch_reg_enum_key_ex_w.Pointer()->Patch(
+ L"wmpdxm.dll", "advapi32.dll", "RegEnumKeyExW",
+ WebPluginDelegateImpl::RegEnumKeyExWPatch);
+ }
}
void WebPluginDelegateImpl::PlatformDestroyInstance() {
- if (instance_->plugin_lib()) {
- // Unpatch if this is the last plugin instance.
- if (instance_->plugin_lib()->instance_count() == 1) {
- if (g_iat_patch_set_cursor.Pointer()->is_patched()) {
- g_iat_patch_set_cursor.Pointer()->Unpatch();
- }
+ if (!instance_->plugin_lib())
+ return;
- if (g_iat_patch_track_popup_menu.Pointer()->is_patched()) {
- g_iat_patch_track_popup_menu.Pointer()->Unpatch();
- }
- }
- }
+ // Unpatch if this is the last plugin instance.
+ if (instance_->plugin_lib()->instance_count() != 1)
+ return;
+
+ if (g_iat_patch_set_cursor.Pointer()->is_patched())
+ g_iat_patch_set_cursor.Pointer()->Unpatch();
+
+ if (g_iat_patch_track_popup_menu.Pointer()->is_patched())
+ g_iat_patch_track_popup_menu.Pointer()->Unpatch();
+
+ if (g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched())
+ g_iat_patch_reg_enum_key_ex_w.Pointer()->Unpatch();
}
void WebPluginDelegateImpl::Paint(HDC hdc, const gfx::Rect& rect) {
@@ -1156,3 +1245,21 @@ HCURSOR WINAPI WebPluginDelegateImpl::SetCursorPatch(HCURSOR cursor) {
cursor);
return previous_cursor;
}
+
+LONG WINAPI WebPluginDelegateImpl::RegEnumKeyExWPatch(
+ HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved,
+ LPWSTR class_name, LPDWORD class_size, PFILETIME last_write_time) {
+ DWORD orig_size = *name_size;
+ LONG rv = RegEnumKeyExW(key, index, name, name_size, reserved, class_name,
+ class_size, last_write_time);
+ if (rv == ERROR_SUCCESS &&
+ GetKeyPath(key).find(L"Microsoft\\MediaPlayer\\ShimInclusionList") !=
+ std::wstring::npos) {
+ static const wchar_t kChromeExeName[] = L"chrome.exe";
+ wcsncpy_s(name, orig_size, kChromeExeName, arraysize(kChromeExeName));
+ *name_size =
+ std::min(orig_size, static_cast<DWORD>(arraysize(kChromeExeName)));
+ }
+
+ return rv;
+}