VirtualBox

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

最後變更 在這個檔案從50369是 49938,由 vboxsync 提交於 11 年 前

Main/src-server/win/HostPowerWin.cpp: fix long standing bug which caused VBoxSVC to hang around for 5 seconds as the thread termination notification wasn't posted properly
Main/src-server/win/svcmain.cpp: reduced "just in case" sleep, shouldn't be necessary at all, when threads using COM are present the server shouldn't ever get to this place
Runtime/common/log/log.cpp: if there are sharing problems with the log file to be opened, wait for up to 10 seconds, maybe the previous user goes away (helps with VBoxSVC release log which can cause trouble, when the previous process is not quite terminated and some API client triggers the launch of a new one), effectively Windows only

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

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