| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/system_message_window_win.h" |
| |
| #include <windows.h> |
| #include <dbt.h> |
| #include <string> |
| |
| #include "base/file_path.h" |
| #include "base/sys_string_conversions.h" |
| #include "base/system_monitor/system_monitor.h" |
| #include "base/win/wrapped_window_proc.h" |
| |
| static const wchar_t* const WindowClassName = L"Chrome_SystemMessageWindow"; |
| |
| namespace { |
| |
| LRESULT GetVolumeName(LPCWSTR drive, |
| LPWSTR volume_name, |
| unsigned int volume_name_len) { |
| return GetVolumeInformation(drive, volume_name, volume_name_len, NULL, NULL, |
| NULL, NULL, 0); |
| } |
| |
| // Returns 0 if the devicetype is not volume. |
| DWORD GetVolumeBitMaskFromBroadcastHeader(DWORD data) { |
| PDEV_BROADCAST_HDR dev_broadcast_hdr = |
| reinterpret_cast<PDEV_BROADCAST_HDR>(data); |
| if (dev_broadcast_hdr->dbch_devicetype == DBT_DEVTYP_VOLUME) { |
| PDEV_BROADCAST_VOLUME dev_broadcast_volume = |
| reinterpret_cast<PDEV_BROADCAST_VOLUME>(dev_broadcast_hdr); |
| return dev_broadcast_volume->dbcv_unitmask; |
| } |
| return 0; |
| } |
| |
| } // namespace |
| |
| |
| SystemMessageWindowWin::SystemMessageWindowWin() |
| : volume_name_func_(&GetVolumeName) { |
| Init(); |
| } |
| |
| SystemMessageWindowWin::SystemMessageWindowWin(VolumeNameFunc volume_name_func) |
| : volume_name_func_(volume_name_func) { |
| Init(); |
| } |
| |
| void SystemMessageWindowWin::Init() { |
| HINSTANCE hinst = GetModuleHandle(NULL); |
| |
| WNDCLASSEX wc = {0}; |
| wc.cbSize = sizeof(wc); |
| wc.lpfnWndProc = |
| base::win::WrappedWindowProc<&SystemMessageWindowWin::WndProcThunk>; |
| wc.hInstance = hinst; |
| wc.lpszClassName = WindowClassName; |
| ATOM clazz = RegisterClassEx(&wc); |
| DCHECK(clazz); |
| |
| window_ = CreateWindow(WindowClassName, |
| 0, 0, 0, 0, 0, 0, 0, 0, hinst, 0); |
| SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)); |
| } |
| |
| SystemMessageWindowWin::~SystemMessageWindowWin() { |
| if (window_) { |
| DestroyWindow(window_); |
| UnregisterClass(WindowClassName, GetModuleHandle(NULL)); |
| } |
| } |
| |
| LRESULT SystemMessageWindowWin::OnDeviceChange(UINT event_type, DWORD data) { |
| base::SystemMonitor* monitor = base::SystemMonitor::Get(); |
| switch (event_type) { |
| case DBT_DEVNODES_CHANGED: |
| monitor->ProcessDevicesChanged(); |
| break; |
| case DBT_DEVICEARRIVAL: { |
| DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data); |
| for (int i = 0; unitmask; ++i, unitmask >>= 1) { |
| if (unitmask & 0x01) { |
| FilePath::StringType drive(L"_:\\"); |
| drive[0] = L'A' + i; |
| WCHAR volume_name[MAX_PATH + 1]; |
| if ((*volume_name_func_)(drive.c_str(), volume_name, MAX_PATH + 1)) { |
| monitor->ProcessMediaDeviceAttached( |
| i, base::SysWideToUTF8(volume_name), FilePath(drive)); |
| } |
| } |
| } |
| break; |
| } |
| case DBT_DEVICEREMOVECOMPLETE: { |
| DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data); |
| for (int i = 0; unitmask; ++i, unitmask >>= 1) { |
| if (unitmask & 0x01) { |
| monitor->ProcessMediaDeviceDetached(i); |
| } |
| } |
| break; |
| } |
| } |
| return TRUE; |
| } |
| |
| LRESULT CALLBACK SystemMessageWindowWin::WndProc(HWND hwnd, UINT message, |
| WPARAM wparam, LPARAM lparam) { |
| switch (message) { |
| case WM_DEVICECHANGE: |
| return OnDeviceChange(static_cast<UINT>(wparam), |
| static_cast<DWORD>(lparam)); |
| default: |
| break; |
| } |
| |
| return ::DefWindowProc(hwnd, message, wparam, lparam); |
| } |