Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

526 lines
15 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1996
  4. *
  5. * TITLE: BATSTATE.C
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 17 Oct, 1996
  12. *
  13. * DESCRIPTION:
  14. * BATSTATE.C contains helper function which maintain the global battery
  15. * state list.
  16. *
  17. *******************************************************************************/
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h>
  21. #include <windows.h>
  22. #include <commctrl.h>
  23. #include <dbt.h>
  24. #include <devioctl.h>
  25. #include <ntpoapi.h>
  26. #include <poclass.h>
  27. #include "powrprofp.h"
  28. #include "batmeter.h"
  29. // Simulated battery only for debug build.
  30. #ifndef DEBUG
  31. #undef SIM_BATTERY
  32. #endif
  33. /*******************************************************************************
  34. *
  35. * G L O B A L D A T A
  36. *
  37. *******************************************************************************/
  38. // Global battery state list. This list has the composite system battery state
  39. // as it's always present head. individual battery devices are linked to this
  40. // head. Use WalkBatteryState(ALL, ... to walk the entire list, including the
  41. // head. Use WalkBatteryState(DEVICES, ... to walk just the device list. If a
  42. // battery is in this list, it's displayable. g_ulBatCount is the count of
  43. // battery devices in this list. The composite battery is not counted.
  44. extern BATTERY_STATE g_bs;
  45. extern ULONG g_ulBatCount;
  46. extern HWND g_hwndBatMeter;
  47. #ifdef WINNT
  48. /*******************************************************************************
  49. *
  50. * RegisterForDeviceNotification
  51. *
  52. * DESCRIPTION:
  53. * Do registration for WM_DEVICECHANGED.
  54. *
  55. * PARAMETERS:
  56. *
  57. *******************************************************************************/
  58. BOOL RegisterForDeviceNotification(PBATTERY_STATE pbs)
  59. {
  60. DEV_BROADCAST_HANDLE dbh;
  61. memset(&dbh, 0, sizeof(DEV_BROADCAST_HANDLE));
  62. dbh.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
  63. dbh.dbch_devicetype = DBT_DEVTYP_HANDLE;
  64. dbh.dbch_handle = pbs->hDevice;
  65. if (!g_hwndBatMeter) {
  66. BATTRACE(( "RegisterForDeviceNotification, NULL g_hwndBatMeter"));
  67. return FALSE;
  68. }
  69. pbs->hDevNotify = RegisterDeviceNotification(g_hwndBatMeter,
  70. &dbh,
  71. DEVICE_NOTIFY_WINDOW_HANDLE);
  72. if (!pbs->hDevNotify) {
  73. BATTRACE(( "RegisterDeviceNotification failed"));
  74. return FALSE;
  75. }
  76. return TRUE;
  77. }
  78. /*******************************************************************************
  79. *
  80. * UnregisterForDeviceNotification
  81. *
  82. * DESCRIPTION:
  83. *
  84. *
  85. * PARAMETERS:
  86. *
  87. *******************************************************************************/
  88. void UnregisterForDeviceNotification(PBATTERY_STATE pbs)
  89. {
  90. if (pbs->hDevNotify) {
  91. UnregisterDeviceNotification(pbs->hDevNotify);
  92. pbs->hDevNotify = NULL;
  93. }
  94. }
  95. #endif
  96. /*******************************************************************************
  97. *
  98. * SystemPowerStatusToBatteryState
  99. *
  100. * DESCRIPTION:
  101. * Fill in BATTERY_STATE fields based on passed SYSTEM_POWER_STATUS.
  102. *
  103. * PARAMETERS:
  104. *
  105. *******************************************************************************/
  106. void SystemPowerStatusToBatteryState(
  107. LPSYSTEM_POWER_STATUS lpsps,
  108. PBATTERY_STATE pbs
  109. )
  110. {
  111. pbs->ulPowerState = 0;
  112. if (lpsps->ACLineStatus == AC_LINE_ONLINE) {
  113. pbs->ulPowerState |= BATTERY_POWER_ON_LINE;
  114. }
  115. if (lpsps->BatteryFlag & BATTERY_FLAG_CHARGING) {
  116. pbs->ulPowerState |= BATTERY_CHARGING;
  117. }
  118. if (lpsps->BatteryFlag & BATTERY_FLAG_CRITICAL) {
  119. pbs->ulPowerState |= BATTERY_CRITICAL;
  120. }
  121. pbs->ulBatLifePercent = lpsps->BatteryLifePercent;
  122. pbs->ulBatLifeTime = lpsps->BatteryLifeTime;
  123. }
  124. /*******************************************************************************
  125. *
  126. * WalkBatteryState
  127. *
  128. * DESCRIPTION:
  129. *
  130. * PARAMETERS:
  131. *
  132. *******************************************************************************/
  133. BOOL WalkBatteryState(
  134. PBATTERY_STATE pbsStart,
  135. WALKENUMPROC pfnWalkEnumProc,
  136. HWND hWnd,
  137. LPARAM lParam1,
  138. LPARAM lParam2
  139. )
  140. {
  141. PBATTERY_STATE pbsTmp;
  142. while (pbsStart) {
  143. // Save the next entry in case the current one is deleted.
  144. pbsTmp = pbsStart->bsNext;
  145. if (!pfnWalkEnumProc(pbsStart, hWnd, lParam1, lParam2)) {
  146. return FALSE;
  147. }
  148. pbsStart = pbsTmp;
  149. }
  150. return TRUE;
  151. }
  152. /*******************************************************************************
  153. *
  154. * UpdateBatInfoProc
  155. *
  156. * DESCRIPTION:
  157. * Updates battery information for an individual battery device.
  158. *
  159. * PARAMETERS:
  160. *
  161. *******************************************************************************/
  162. BOOL UpdateBatInfoProc(
  163. PBATTERY_STATE pbs,
  164. HWND hWnd,
  165. LPARAM lParam1,
  166. LPARAM lParam2
  167. )
  168. {
  169. DWORD dwByteCount, dwIOCTL, dwWait;
  170. BATTERY_STATUS bs;
  171. BATTERY_WAIT_STATUS bws;
  172. BATTERY_INFORMATION bi;
  173. BATTERY_QUERY_INFORMATION bqi;
  174. if (pbs->hDevice == INVALID_HANDLE_VALUE) {
  175. BATTRACE(( "UpdateBatInfoProc, Bad battery driver handle, LastError: 0x%X", GetLastError()));
  176. return FALSE;
  177. }
  178. // If no tag, then don't update the battery info.
  179. dwIOCTL = IOCTL_BATTERY_QUERY_TAG;
  180. dwWait = 0;
  181. if (DeviceIoControl(pbs->hDevice, dwIOCTL,
  182. &dwWait, sizeof(dwWait),
  183. &(pbs->ulTag), sizeof(ULONG),
  184. &dwByteCount, NULL)) {
  185. bqi.BatteryTag = pbs->ulTag;
  186. bqi.InformationLevel = BatteryInformation;
  187. bqi.AtRate = 0;
  188. dwIOCTL = IOCTL_BATTERY_QUERY_INFORMATION;
  189. if (DeviceIoControl(pbs->hDevice, dwIOCTL,
  190. &bqi, sizeof(bqi),
  191. &bi, sizeof(bi),
  192. &dwByteCount, NULL)) {
  193. if (bi.FullChargedCapacity != UNKNOWN_CAPACITY) {
  194. pbs->ulFullChargedCapacity = bi.FullChargedCapacity;
  195. }
  196. else {
  197. pbs->ulFullChargedCapacity = bi.DesignedCapacity;
  198. }
  199. memset(&bws, 0, sizeof(BATTERY_WAIT_STATUS));
  200. bws.BatteryTag = pbs->ulTag;
  201. dwIOCTL = IOCTL_BATTERY_QUERY_STATUS;
  202. if (DeviceIoControl(pbs->hDevice, dwIOCTL,
  203. &bws, sizeof(BATTERY_WAIT_STATUS),
  204. &bs, sizeof(BATTERY_STATUS),
  205. &dwByteCount, NULL)) {
  206. pbs->ulPowerState = bs.PowerState;
  207. if (pbs->ulFullChargedCapacity < bs.Capacity) {
  208. pbs->ulFullChargedCapacity = bs.Capacity;
  209. BATTRACE(( "UpdateBatInfoProc, unable to calculate ulFullChargedCapacity"));
  210. }
  211. if (pbs->ulFullChargedCapacity == 0) {
  212. pbs->ulBatLifePercent = 0;
  213. }
  214. else {
  215. pbs->ulBatLifePercent =
  216. (100 * bs.Capacity) / pbs->ulFullChargedCapacity;
  217. }
  218. return TRUE;
  219. }
  220. }
  221. }
  222. else {
  223. pbs->ulTag = BATTERY_TAG_INVALID;
  224. // No battery tag, that's ok, the user may have removed the battery.
  225. if (GetLastError() == ERROR_FILE_NOT_FOUND) {
  226. return TRUE;
  227. }
  228. }
  229. BATTRACE(( "UpdateBatInfoProc, IOCTL: %X Failure, BatNum: %d, LastError: %d\n", dwIOCTL, pbs->ulBatNum, GetLastError()));
  230. return FALSE;
  231. }
  232. /*******************************************************************************
  233. *
  234. * SimUpdateBatInfoProc
  235. *
  236. * DESCRIPTION:
  237. * Simulate the update of battery information for an individual batter device.
  238. *
  239. * PARAMETERS:
  240. *
  241. *******************************************************************************/
  242. BOOL SimUpdateBatInfoProc(
  243. PBATTERY_STATE pbs,
  244. HWND hWnd,
  245. LPARAM lParam1,
  246. LPARAM lParam2
  247. )
  248. {
  249. pbs->ulTag = pbs->ulBatNum;
  250. if (pbs->ulBatNum == 1) {
  251. pbs->ulFullChargedCapacity = 2000;
  252. pbs->ulFullChargedCapacity = 1991;
  253. pbs->ulPowerState = BATTERY_CHARGING | BATTERY_POWER_ON_LINE;
  254. pbs->ulBatLifePercent = 75;
  255. }
  256. else {
  257. pbs->ulFullChargedCapacity = 3000;
  258. pbs->ulFullChargedCapacity = 2991;
  259. pbs->ulPowerState = BATTERY_DISCHARGING | BATTERY_CRITICAL;
  260. pbs->ulBatLifePercent = 3;
  261. }
  262. return TRUE;
  263. }
  264. /*******************************************************************************
  265. *
  266. * AddBatteryStateDevice
  267. *
  268. * DESCRIPTION:
  269. * Add only displayable batteries to the battery list. New entry is appended
  270. * to battery state list.
  271. *
  272. * PARAMETERS:
  273. *
  274. *******************************************************************************/
  275. PBATTERY_STATE AddBatteryStateDevice(LPTSTR lpszName, ULONG ulBatNum)
  276. {
  277. PBATTERY_STATE pbs, pbsTemp = &g_bs;
  278. LPTSTR lpsz = NULL;
  279. DWORD strsize;
  280. if (!lpszName) {
  281. return NULL;
  282. }
  283. // Append to end of list
  284. while (pbsTemp->bsNext) {
  285. pbsTemp = pbsTemp->bsNext;
  286. }
  287. // Allocate storage for new battery device state.
  288. if (pbs = LocalAlloc(LPTR, sizeof(BATTERY_STATE))) {
  289. strsize = STRSIZE(lpszName);
  290. if (lpsz = LocalAlloc(0, strsize)) {
  291. lstrcpyn(lpsz, lpszName,strsize);
  292. pbs->lpszDeviceName = lpsz;
  293. pbs->ulSize = sizeof(BATTERY_STATE);
  294. pbs->ulBatNum = ulBatNum;
  295. // Open a handle to the battery driver.
  296. pbs->hDevice = CreateFile(lpszName,
  297. GENERIC_READ | GENERIC_WRITE,
  298. FILE_SHARE_READ | FILE_SHARE_WRITE,
  299. NULL, OPEN_EXISTING,
  300. FILE_ATTRIBUTE_NORMAL, NULL);
  301. #ifdef WINNT
  302. // Setup for notification by PNP when battery goes away.
  303. RegisterForDeviceNotification(pbs);
  304. #endif
  305. // Get the current battery info from the battery driver.
  306. if (UpdateBatInfoProc(pbs, NULL, 0, 0)) {
  307. // Link the new battery device state into the list.
  308. pbsTemp->bsNext = pbs;
  309. pbs->bsPrev = pbsTemp;
  310. return pbs;
  311. }
  312. LocalFree(lpsz);
  313. }
  314. LocalFree(pbs);
  315. }
  316. return NULL;
  317. }
  318. /*******************************************************************************
  319. *
  320. * SimAddBatteryStateDevice
  321. *
  322. * DESCRIPTION:
  323. * Simulate the addition of displayable batteries to the battery list.
  324. * New entry is appended to battery state list.
  325. *
  326. * PARAMETERS:
  327. *
  328. *******************************************************************************/
  329. PBATTERY_STATE SimAddBatteryStateDevice(LPTSTR lpszName, ULONG ulBatNum)
  330. {
  331. PBATTERY_STATE pbs, pbsTemp = &g_bs;
  332. LPTSTR lpsz = NULL;
  333. DWORD strsize;
  334. if (!lpszName) {
  335. return NULL;
  336. }
  337. // Append to end of list
  338. while (pbsTemp->bsNext) {
  339. pbsTemp = pbsTemp->bsNext;
  340. }
  341. // Allocate storage for new battery device state.
  342. if (pbs = LocalAlloc(LPTR, sizeof(BATTERY_STATE))) {
  343. strsize = STRSIZE(lpszName);
  344. if (lpsz = LocalAlloc(0, strsize)) {
  345. lstrcpyn(lpsz, lpszName,strsize);
  346. pbs->lpszDeviceName = lpsz;
  347. pbs->ulSize = sizeof(BATTERY_STATE);
  348. pbs->ulBatNum = ulBatNum;
  349. // Open a handle to the battery driver.
  350. pbs->hDevice = (HANDLE) -1;
  351. // Get the current battery info from the battery driver.
  352. if (SimUpdateBatInfoProc(pbs, NULL, 0, 0)) {
  353. // Link the new battery device state into the list.
  354. pbsTemp->bsNext = pbs;
  355. pbs->bsPrev = pbsTemp;
  356. return pbs;
  357. }
  358. LocalFree(lpsz);
  359. }
  360. LocalFree(pbs);
  361. }
  362. return NULL;
  363. }
  364. /*******************************************************************************
  365. *
  366. * RemoveBatteryStateDevice
  367. *
  368. * DESCRIPTION:
  369. *
  370. * PARAMETERS:
  371. *
  372. *******************************************************************************/
  373. BOOL RemoveBatteryStateDevice(PBATTERY_STATE pbs)
  374. {
  375. // Unlink
  376. if (pbs->bsNext) {
  377. pbs->bsNext->bsPrev = pbs->bsPrev;
  378. }
  379. if (pbs->bsPrev) {
  380. pbs->bsPrev->bsNext = pbs->bsNext;
  381. }
  382. #ifdef winnt
  383. UnregisterForDeviceNotification(pbs);
  384. #endif
  385. // Free the battery driver handle if one was opened.
  386. if (pbs->hDevice != INVALID_HANDLE_VALUE) {
  387. CloseHandle(pbs->hDevice);
  388. }
  389. // Free the device name.
  390. LocalFree(pbs->lpszDeviceName);
  391. // Destroy any icons.
  392. if (pbs->hIconCache) {
  393. DestroyIcon(pbs->hIconCache);
  394. }
  395. if (pbs->hIconCache16) {
  396. DestroyIcon(pbs->hIconCache16);
  397. }
  398. // Free the associated storage.
  399. LocalFree(pbs);
  400. return TRUE;
  401. }
  402. /*******************************************************************************
  403. *
  404. * RemoveMissingProc
  405. *
  406. * DESCRIPTION:
  407. * Remove a battery from the global battery state list.
  408. *
  409. * PARAMETERS:
  410. * lParam2 - REMOVE_MISSING or REMOVE_ALL
  411. *
  412. *******************************************************************************/
  413. BOOL RemoveMissingProc(
  414. PBATTERY_STATE pbs,
  415. HWND hWnd,
  416. LPARAM lParam1,
  417. LPARAM lParam2)
  418. {
  419. UINT i;
  420. LPTSTR *pszDeviceNames;
  421. if (lParam2 == REMOVE_MISSING) {
  422. if ((pszDeviceNames = (LPTSTR *)lParam1) != NULL) {
  423. for (i = 0; i < NUM_BAT; i++) {
  424. if (pszDeviceNames[i]) {
  425. if (!lstrcmp(pbs->lpszDeviceName, pszDeviceNames[i])) {
  426. // Device found in device list, leave it alone.
  427. return TRUE;
  428. }
  429. }
  430. else {
  431. continue;
  432. }
  433. }
  434. }
  435. }
  436. // Device not in the device names list, remove it.
  437. RemoveBatteryStateDevice(pbs);
  438. return TRUE;
  439. }
  440. /*******************************************************************************
  441. *
  442. * FindNameProc
  443. *
  444. * DESCRIPTION:
  445. * Returns FALSE (stop searching) if we find the name, else TRUE.
  446. *
  447. * PARAMETERS:
  448. *
  449. *******************************************************************************/
  450. BOOL FindNameProc(PBATTERY_STATE pbs, HWND hWnd, LPARAM lParam1, LPARAM lParam2)
  451. {
  452. if (lParam1) {
  453. if (!lstrcmp(pbs->lpszDeviceName, (LPTSTR)lParam1)) {
  454. // Device found in device list.
  455. return FALSE;
  456. }
  457. }
  458. return TRUE;
  459. }