VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/win/HostPowerWin.cpp@ 57130

Last change on this file since 57130 was 55401, checked in by vboxsync, 10 years ago

added a couple of missing Id headers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.5 KB
Line 
1/* $Id: HostPowerWin.cpp 55401 2015-04-23 10:03:17Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox interface to host's power notification service
5 */
6
7/*
8 * Copyright (C) 2006-2013 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <windows.h>
23/* Some SDK versions lack the extern "C" and thus cause linking failures.
24 * This workaround isn't pretty, but there are not many options. */
25extern "C" {
26#include <PowrProf.h>
27}
28
29#include <VBox/com/ptr.h>
30#include "HostPower.h"
31#include "Logging.h"
32
33static WCHAR gachWindowClassName[] = L"VBoxPowerNotifyClass";
34
35HostPowerServiceWin::HostPowerServiceWin(VirtualBox *aVirtualBox) : HostPowerService(aVirtualBox), mThread(NIL_RTTHREAD)
36{
37 mHwnd = 0;
38
39 int rc = RTThreadCreate(&mThread, HostPowerServiceWin::NotificationThread, this, 65536,
40 RTTHREADTYPE_GUI, RTTHREADFLAGS_WAITABLE, "MainPower");
41
42 if (RT_FAILURE(rc))
43 {
44 Log(("HostPowerServiceWin::HostPowerServiceWin: RTThreadCreate failed with %Rrc\n", rc));
45 return;
46 }
47}
48
49HostPowerServiceWin::~HostPowerServiceWin()
50{
51 if (mHwnd)
52 {
53 Log(("HostPowerServiceWin::!HostPowerServiceWin: destroy window %x\n", mHwnd));
54
55 /* Is this allowed from another thread? */
56 SetWindowLongPtr(mHwnd, 0, 0);
57 /* Poke the thread out of the event loop and wait for it to clean up. */
58 PostMessage(mHwnd, WM_QUIT, 0, 0);
59 RTThreadWait(mThread, 5000, NULL);
60 mThread = NIL_RTTHREAD;
61 }
62}
63
64
65
66DECLCALLBACK(int) HostPowerServiceWin::NotificationThread(RTTHREAD ThreadSelf, void *pInstance)
67{
68 HostPowerServiceWin *pPowerObj = (HostPowerServiceWin *)pInstance;
69 HWND hwnd = 0;
70
71 /* Create a window and make it a power event notification handler. */
72 int rc = VINF_SUCCESS;
73
74 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
75
76 /* Register the Window Class. */
77 WNDCLASS wc;
78
79 wc.style = CS_NOCLOSE;
80 wc.lpfnWndProc = HostPowerServiceWin::WndProc;
81 wc.cbClsExtra = 0;
82 wc.cbWndExtra = sizeof(void *);
83 wc.hInstance = hInstance;
84 wc.hIcon = NULL;
85 wc.hCursor = NULL;
86 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
87 wc.lpszMenuName = NULL;
88 wc.lpszClassName = gachWindowClassName;
89
90 ATOM atomWindowClass = RegisterClass(&wc);
91
92 if (atomWindowClass == 0)
93 {
94 rc = VERR_NOT_SUPPORTED;
95 Log(("HostPowerServiceWin::NotificationThread: RegisterClassA failed with %x\n", GetLastError()));
96 }
97 else
98 {
99 /* Create the window. */
100 hwnd = pPowerObj->mHwnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
101 gachWindowClassName, gachWindowClassName,
102 WS_POPUPWINDOW,
103 -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
104
105 if (hwnd == NULL)
106 {
107 Log(("HostPowerServiceWin::NotificationThread: CreateWindowExA failed with %x\n", GetLastError()));
108 rc = VERR_NOT_SUPPORTED;
109 }
110 else
111 {
112 SetWindowLongPtr(hwnd, 0, (LONG_PTR)pPowerObj);
113 SetWindowPos(hwnd, HWND_TOPMOST, -200, -200, 0, 0,
114 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
115
116 MSG msg;
117 BOOL fRet;
118 while ((fRet = GetMessage(&msg, NULL, 0, 0)) != 0)
119 {
120 if (fRet != -1)
121 {
122 TranslateMessage(&msg);
123 DispatchMessage(&msg);
124 }
125 else
126 {
127 // handle the error and possibly exit
128 break;
129 }
130 }
131 }
132 }
133
134 Log(("HostPowerServiceWin::NotificationThread: exit thread\n"));
135 if (hwnd)
136 DestroyWindow(hwnd);
137
138 if (atomWindowClass != 0)
139 {
140 UnregisterClass(gachWindowClassName, hInstance);
141 atomWindowClass = 0;
142 }
143
144 return 0;
145}
146
147LRESULT CALLBACK HostPowerServiceWin::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
148{
149 switch (msg)
150 {
151 case WM_POWERBROADCAST:
152 {
153 HostPowerServiceWin *pPowerObj;
154
155 pPowerObj = (HostPowerServiceWin *)GetWindowLongPtr(hwnd, 0);
156 if (pPowerObj)
157 {
158 switch(wParam)
159 {
160 case PBT_APMSUSPEND:
161 pPowerObj->notify(Reason_HostSuspend);
162 break;
163
164 case PBT_APMRESUMEAUTOMATIC:
165 pPowerObj->notify(Reason_HostResume);
166 break;
167
168 case PBT_APMPOWERSTATUSCHANGE:
169 {
170 SYSTEM_POWER_STATUS SystemPowerStatus;
171
172 Log(("PBT_APMPOWERSTATUSCHANGE\n"));
173 if (GetSystemPowerStatus(&SystemPowerStatus) == TRUE)
174 {
175 Log(("PBT_APMPOWERSTATUSCHANGE ACLineStatus=%d BatteryFlag=%d\n", SystemPowerStatus.ACLineStatus,
176 SystemPowerStatus.BatteryFlag));
177
178 if (SystemPowerStatus.ACLineStatus == 0) /* offline */
179 {
180 if (SystemPowerStatus.BatteryFlag == 2 /* low > 33% */)
181 {
182 LONG rc;
183 SYSTEM_BATTERY_STATE BatteryState;
184
185 rc = CallNtPowerInformation(SystemBatteryState, NULL, 0, (PVOID)&BatteryState,
186 sizeof(BatteryState));
187#ifdef LOG_ENABLED
188 if (rc == 0 /* STATUS_SUCCESS */)
189 Log(("CallNtPowerInformation claims %d seconds of power left\n",
190 BatteryState.EstimatedTime));
191#endif
192 if ( rc == 0 /* STATUS_SUCCESS */
193 && BatteryState.EstimatedTime < 60*5)
194 {
195 pPowerObj->notify(Reason_HostBatteryLow);
196 }
197 }
198 else
199 /* If the machine has less than 5% battery left (and is not connected
200 * to the AC), then we should save the state. */
201 if (SystemPowerStatus.BatteryFlag == 4 /* critical battery status; less than 5% */)
202 {
203 pPowerObj->notify(Reason_HostBatteryLow);
204 }
205 }
206 }
207 break;
208 }
209 default:
210 return DefWindowProc(hwnd, msg, wParam, lParam);
211 }
212 }
213 return TRUE;
214 }
215
216 default:
217 return DefWindowProc(hwnd, msg, wParam, lParam);
218 }
219}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette