// 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 #include #include #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(data); if (dev_broadcast_hdr->dbch_devicetype == DBT_DEVTYP_VOLUME) { PDEV_BROADCAST_VOLUME dev_broadcast_volume = reinterpret_cast(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(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(wparam), static_cast(lparam)); default: break; } return ::DefWindowProc(hwnd, message, wparam, lparam); }