blob: 1aca1c1c184d960a3822aecac657442c5364f9ff [file] [log] [blame]
[email protected]85538be2012-03-06 00:02:451// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]cd1cd4c02011-11-15 01:59:492// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/system_message_window_win.h"
6
7#include <windows.h>
8#include <dbt.h>
[email protected]85538be2012-03-06 00:02:459#include <string>
[email protected]cd1cd4c02011-11-15 01:59:4910
[email protected]85538be2012-03-06 00:02:4511#include "base/file_path.h"
12#include "base/sys_string_conversions.h"
[email protected]cd1cd4c02011-11-15 01:59:4913#include "base/system_monitor/system_monitor.h"
14#include "base/win/wrapped_window_proc.h"
15
16static const wchar_t* const WindowClassName = L"Chrome_SystemMessageWindow";
17
[email protected]85538be2012-03-06 00:02:4518namespace {
19
20LRESULT GetVolumeName(LPCWSTR drive,
21 LPWSTR volume_name,
22 unsigned int volume_name_len) {
23 return GetVolumeInformation(drive, volume_name, volume_name_len, NULL, NULL,
24 NULL, NULL, 0);
25}
26
27// Returns 0 if the devicetype is not volume.
28DWORD GetVolumeBitMaskFromBroadcastHeader(DWORD data) {
29 PDEV_BROADCAST_HDR dev_broadcast_hdr =
30 reinterpret_cast<PDEV_BROADCAST_HDR>(data);
31 if (dev_broadcast_hdr->dbch_devicetype == DBT_DEVTYP_VOLUME) {
32 PDEV_BROADCAST_VOLUME dev_broadcast_volume =
33 reinterpret_cast<PDEV_BROADCAST_VOLUME>(dev_broadcast_hdr);
34 return dev_broadcast_volume->dbcv_unitmask;
35 }
36 return 0;
37}
38
39} // namespace
40
41
42SystemMessageWindowWin::SystemMessageWindowWin()
43 : volume_name_func_(&GetVolumeName) {
44 Init();
45}
46
47SystemMessageWindowWin::SystemMessageWindowWin(VolumeNameFunc volume_name_func)
48 : volume_name_func_(volume_name_func) {
49 Init();
50}
51
52void SystemMessageWindowWin::Init() {
[email protected]cd1cd4c02011-11-15 01:59:4953 HINSTANCE hinst = GetModuleHandle(NULL);
54
55 WNDCLASSEX wc = {0};
56 wc.cbSize = sizeof(wc);
57 wc.lpfnWndProc =
58 base::win::WrappedWindowProc<&SystemMessageWindowWin::WndProcThunk>;
59 wc.hInstance = hinst;
60 wc.lpszClassName = WindowClassName;
61 ATOM clazz = RegisterClassEx(&wc);
62 DCHECK(clazz);
63
64 window_ = CreateWindow(WindowClassName,
65 0, 0, 0, 0, 0, 0, 0, 0, hinst, 0);
66 SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
67}
68
69SystemMessageWindowWin::~SystemMessageWindowWin() {
70 if (window_) {
71 DestroyWindow(window_);
72 UnregisterClass(WindowClassName, GetModuleHandle(NULL));
73 }
74}
75
76LRESULT SystemMessageWindowWin::OnDeviceChange(UINT event_type, DWORD data) {
77 base::SystemMonitor* monitor = base::SystemMonitor::Get();
[email protected]85538be2012-03-06 00:02:4578 switch (event_type) {
79 case DBT_DEVNODES_CHANGED:
80 monitor->ProcessDevicesChanged();
81 break;
82 case DBT_DEVICEARRIVAL: {
83 DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data);
84 for (int i = 0; unitmask; ++i, unitmask >>= 1) {
85 if (unitmask & 0x01) {
86 FilePath::StringType drive(L"_:\\");
87 drive[0] = L'A' + i;
88 WCHAR volume_name[MAX_PATH + 1];
89 if ((*volume_name_func_)(drive.c_str(), volume_name, MAX_PATH + 1)) {
90 monitor->ProcessMediaDeviceAttached(
91 i, base::SysWideToUTF8(volume_name), FilePath(drive));
92 }
93 }
94 }
95 break;
96 }
97 case DBT_DEVICEREMOVECOMPLETE: {
98 DWORD unitmask = GetVolumeBitMaskFromBroadcastHeader(data);
99 for (int i = 0; unitmask; ++i, unitmask >>= 1) {
100 if (unitmask & 0x01) {
101 monitor->ProcessMediaDeviceDetached(i);
102 }
103 }
104 break;
105 }
106 }
[email protected]cd1cd4c02011-11-15 01:59:49107 return TRUE;
108}
109
110LRESULT CALLBACK SystemMessageWindowWin::WndProc(HWND hwnd, UINT message,
111 WPARAM wparam, LPARAM lparam) {
112 switch (message) {
113 case WM_DEVICECHANGE:
114 return OnDeviceChange(static_cast<UINT>(wparam),
115 static_cast<DWORD>(lparam));
116 default:
117 break;
118 }
119
120 return ::DefWindowProc(hwnd, message, wparam, lparam);
121}