Source code of Windows XP (NT5)
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.

822 lines
22 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. Author:
  6. Ken Reneris
  7. Environment:
  8. console
  9. --*/
  10. //
  11. // set variable to define global variables
  12. //
  13. #include <tchar.h>
  14. #include <wchar.h>
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <initguid.h>
  20. #include <devguid.h>
  21. #include <errno.h>
  22. #include <malloc.h>
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <batclass.h>
  26. #include <setupapi.h>
  27. //
  28. // Misc constants
  29. //
  30. #define RANGE 1
  31. #define MAX_NUMBER_OF_BATTERIES 8
  32. #define MAX_DEVICE_NAME_LENGTH 100
  33. //
  34. // Battery Device Names
  35. //
  36. PVOID COMPOSITE_NAME = _T("\\Device\\CompositeBattery");
  37. //
  38. // Globals
  39. //
  40. BOOLEAN LongTerm = FALSE;
  41. #pragma pack(1)
  42. typedef struct _ID_MAP {
  43. UCHAR LocalId;
  44. UCHAR ActualId;
  45. } ID_MAP, *PID_MAP;
  46. #pragma pack()
  47. #pragma pack(1)
  48. typedef struct _MFG_DATE {
  49. UCHAR Day; // 1-31
  50. UCHAR Month; // 1-12
  51. USHORT Year; // 1996 - ?
  52. } MFG_DATE, *PMFG_DATE;
  53. #pragma pack()
  54. /*******************************************************************************
  55. *
  56. * GetBatteryDriverNames
  57. *
  58. * DESCRIPTION: Finds all battery class devices
  59. *
  60. * PARAMETERS:
  61. * DriverNames - pointer to an array of UNICODE_STRING structures to fill in
  62. * MaxBatteries - number of elements in DriverNames array
  63. *
  64. * RETURN VALUE: The number of batteries found
  65. * Will always find the Composite battery whether it exists or not
  66. *
  67. *******************************************************************************/
  68. UCHAR GetBatteryDriverNames(UNICODE_STRING * DriverNames, UCHAR MaxBatteries)
  69. {
  70. UCHAR driverCount, index;
  71. DWORD reqSize;
  72. HDEVINFO devInfo;
  73. SP_INTERFACE_DEVICE_DATA interfaceDevData;
  74. PSP_INTERFACE_DEVICE_DETAIL_DATA funcClassDevData;
  75. if ((MaxBatteries == 0) || (DriverNames == NULL)) {
  76. return 0;
  77. }
  78. driverCount = 0;
  79. // Hard code the first battery to be the composite battery.
  80. RtlInitUnicodeString (&DriverNames[driverCount], COMPOSITE_NAME);
  81. driverCount++;
  82. // Use the SETUPAPI.DLL interface to get the
  83. // possible battery driver names.
  84. devInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVICE_BATTERY, NULL, NULL,
  85. DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
  86. if (devInfo != INVALID_HANDLE_VALUE) {
  87. interfaceDevData.cbSize = sizeof(SP_DEVINFO_DATA);
  88. index = 0;
  89. while (driverCount < MaxBatteries) {
  90. if (SetupDiEnumInterfaceDevice(devInfo,
  91. 0,
  92. (LPGUID)&GUID_DEVICE_BATTERY,
  93. index,
  94. &interfaceDevData)) {
  95. // Get the required size of the function class device data.
  96. SetupDiGetInterfaceDeviceDetail(devInfo,
  97. &interfaceDevData,
  98. NULL,
  99. 0,
  100. &reqSize,
  101. NULL);
  102. funcClassDevData = malloc(reqSize);
  103. if (funcClassDevData != NULL) {
  104. funcClassDevData->cbSize =
  105. sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
  106. if (SetupDiGetInterfaceDeviceDetail(devInfo,
  107. &interfaceDevData,
  108. funcClassDevData,
  109. reqSize,
  110. &reqSize,
  111. NULL)) {
  112. reqSize = (lstrlen(funcClassDevData->DevicePath) + 1)
  113. * sizeof(TCHAR);
  114. RtlInitUnicodeString(
  115. &DriverNames[driverCount],
  116. funcClassDevData->DevicePath
  117. );
  118. driverCount++;
  119. }
  120. else {
  121. printf("SetupDiGetInterfaceDeviceDetail, failed: %d", GetLastError());
  122. }
  123. LocalFree(funcClassDevData);
  124. }
  125. } else {
  126. if (ERROR_NO_MORE_ITEMS == GetLastError()) {
  127. break;
  128. }
  129. else {
  130. printf ("SetupDiEnumInterfaceDevice, failed: %d", GetLastError());
  131. }
  132. }
  133. index++;
  134. }
  135. SetupDiDestroyDeviceInfoList(devInfo);
  136. }
  137. else {
  138. printf("SetupDiGetClassDevs on GUID_DEVICE_BATTERY, failed: %d", GetLastError());
  139. }
  140. return driverCount;
  141. }
  142. HANDLE
  143. OpenBattery (PUNICODE_STRING BatteryName)
  144. {
  145. NTSTATUS status;
  146. OBJECT_ATTRIBUTES ObjA;
  147. IO_STATUS_BLOCK IOSB;
  148. HANDLE driverHandle;
  149. DWORD lastError;
  150. // HACK: I can't seems to find the correct device
  151. // names, so I can't open the composite battery using CreateFile()
  152. // and I can't open the detected batteries using NtOpenFile(), so I
  153. // have to use a different method of opening the battery depending on
  154. // which battery it is.
  155. if (BatteryName->Buffer == COMPOSITE_NAME) {
  156. InitializeObjectAttributes(
  157. &ObjA,
  158. BatteryName,
  159. OBJ_CASE_INSENSITIVE,
  160. 0,
  161. 0 );
  162. status = NtOpenFile (
  163. &driverHandle, // return handle
  164. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA, // desired access
  165. &ObjA, // Object
  166. &IOSB, // io status block
  167. FILE_SHARE_READ | FILE_SHARE_WRITE, // share access
  168. FILE_SYNCHRONOUS_IO_ALERT // open options
  169. );
  170. if (!NT_SUCCESS(status)) {
  171. printf ("Error opening %ws: NTSTATUS = 0x%08lx\n",
  172. BatteryName->Buffer, status);
  173. return NULL;
  174. }
  175. } else {
  176. driverHandle = CreateFile (BatteryName->Buffer,
  177. GENERIC_READ | GENERIC_WRITE,
  178. FILE_SHARE_READ | FILE_SHARE_WRITE,
  179. NULL,
  180. OPEN_EXISTING,
  181. FILE_ATTRIBUTE_NORMAL,
  182. NULL);
  183. if (INVALID_HANDLE_VALUE == driverHandle) {
  184. lastError = GetLastError ();
  185. printf ("Error opening %ws: GetLastError = 0x%08lx \n",
  186. BatteryName->Buffer, lastError);
  187. return NULL;
  188. }
  189. }
  190. printf("Opened %ws \n", BatteryName->Buffer);
  191. return driverHandle;
  192. }
  193. ULONG
  194. GetBatteryTag (HANDLE DriverHandle)
  195. {
  196. NTSTATUS Status;
  197. IO_STATUS_BLOCK IOSB;
  198. ULONG BatteryTag;
  199. ULONG Timeout = 0;
  200. if (LongTerm) {
  201. Timeout = (ULONG)-1;
  202. }
  203. Status = NtDeviceIoControlFile(
  204. DriverHandle,
  205. (HANDLE) NULL, // event
  206. (PIO_APC_ROUTINE) NULL,
  207. (PVOID) NULL,
  208. &IOSB,
  209. IOCTL_BATTERY_QUERY_TAG,
  210. &Timeout, // input buffer
  211. sizeof (Timeout),
  212. &BatteryTag, // output buffer
  213. sizeof (BatteryTag)
  214. );
  215. if (!NT_SUCCESS(Status)) {
  216. BatteryTag = BATTERY_TAG_INVALID;
  217. if (Status == STATUS_NO_SUCH_DEVICE) {
  218. printf ("(Battery is not physically present or is not connected)\n");
  219. } else {
  220. printf ("Query Battery tag failed: Status = %x\n", Status);
  221. }
  222. }
  223. printf("Battery Tag = 0x%08lx.\n", BatteryTag);
  224. return BatteryTag;
  225. }
  226. BOOLEAN
  227. GetBatteryInfo (
  228. HANDLE DriverHandle,
  229. ULONG BatteryTag,
  230. IN BATTERY_QUERY_INFORMATION_LEVEL Level,
  231. OUT PVOID Buffer,
  232. IN ULONG BufferLength
  233. )
  234. {
  235. NTSTATUS Status;
  236. IO_STATUS_BLOCK IOSB;
  237. BATTERY_QUERY_INFORMATION BInfo;
  238. memset (Buffer, 0, BufferLength);
  239. BInfo.BatteryTag = BatteryTag;
  240. BInfo.InformationLevel = Level;
  241. BInfo.AtRate = 0; // This is needed for reading estimated time correctly.
  242. Status = NtDeviceIoControlFile(
  243. DriverHandle,
  244. (HANDLE) NULL, // event
  245. (PIO_APC_ROUTINE) NULL,
  246. (PVOID) NULL,
  247. &IOSB,
  248. IOCTL_BATTERY_QUERY_INFORMATION,
  249. &BInfo, // input buffer
  250. sizeof (BInfo),
  251. Buffer, // output buffer
  252. BufferLength
  253. );
  254. if (!NT_SUCCESS(Status)) {
  255. if ((Status == STATUS_INVALID_PARAMETER) ||
  256. (Status == STATUS_INVALID_DEVICE_REQUEST) ||
  257. (Status == STATUS_NOT_SUPPORTED)) {
  258. printf ("Not Supported by Battery, Level %x, Status: %x\n", Level, Status);
  259. } else {
  260. printf ("Query failed: Level %x, Status = %x\n", Level, Status);
  261. }
  262. return FALSE;
  263. }
  264. return TRUE;
  265. }
  266. VOID
  267. GetBatteryStatus (
  268. HANDLE DriverHandle,
  269. IN PBATTERY_WAIT_STATUS WaitStatus,
  270. IN PBATTERY_INFORMATION BInfo,
  271. OUT PBATTERY_STATUS BatteryStatus
  272. )
  273. {
  274. NTSTATUS Status;
  275. IO_STATUS_BLOCK IOSB;
  276. ULONG Volts;
  277. memset (BatteryStatus, 0xAB, sizeof(BatteryStatus));
  278. Status = NtDeviceIoControlFile(
  279. DriverHandle,
  280. (HANDLE) NULL, // event
  281. (PIO_APC_ROUTINE) NULL,
  282. (PVOID) NULL,
  283. &IOSB,
  284. IOCTL_BATTERY_QUERY_STATUS,
  285. WaitStatus, // input buffer
  286. sizeof (BATTERY_WAIT_STATUS),
  287. BatteryStatus, // output buffer
  288. sizeof (BATTERY_STATUS)
  289. );
  290. //
  291. // dump battery status
  292. //
  293. printf ("[Current Status Information]\n");
  294. printf (" Power State...........: ");
  295. if (!NT_SUCCESS(Status)) {
  296. printf ("Query failed: Status = %x\n", Status);
  297. return ;
  298. }
  299. //
  300. // Print the PowerState
  301. //
  302. printf ("%08x ", BatteryStatus->PowerState);
  303. if (BatteryStatus->PowerState & BATTERY_POWER_ON_LINE) {
  304. printf ("Power_Online ");
  305. }
  306. if (BatteryStatus->PowerState & BATTERY_DISCHARGING) {
  307. printf ("Discharging ");
  308. }
  309. if (BatteryStatus->PowerState & BATTERY_CHARGING) {
  310. printf ("Charging ");
  311. }
  312. if (BatteryStatus->PowerState & BATTERY_CRITICAL) {
  313. printf ("Critical! ");
  314. }
  315. if (BatteryStatus->PowerState == 0) {
  316. printf ("No flags set.");
  317. }
  318. printf ("\n");
  319. //
  320. // Print the Voltage
  321. //
  322. Volts = BatteryStatus->Voltage;
  323. if (Volts == BATTERY_UNKNOWN_VOLTAGE) {
  324. printf (" Voltage...............: %08x UNKNOWN\n", Volts);
  325. } else {
  326. printf (" Voltage...............: %08x %d.%03d V\n", Volts, (Volts/1000), Volts - ((Volts/1000)*1000));
  327. }
  328. //
  329. // Print the Rate
  330. //
  331. if (BatteryStatus->Rate == BATTERY_UNKNOWN_RATE) {
  332. printf (" Rate..................: %08x UNKNOWN\n", BatteryStatus->Rate);
  333. } else {
  334. if (BInfo->Capabilities & BATTERY_CAPACITY_RELATIVE) {
  335. printf (" Rate..................: %08x %d % per hour ", BatteryStatus->Rate, BatteryStatus->Rate);
  336. } else {
  337. printf (" Rate..................: %08x %d mW ", BatteryStatus->Rate, BatteryStatus->Rate);
  338. }
  339. if (BatteryStatus->PowerState & BATTERY_CHARGING) {
  340. printf ("(Charging)\n");
  341. } else if (BatteryStatus->PowerState & BATTERY_DISCHARGING) {
  342. printf ("(Discharging)\n");
  343. } else {
  344. printf ("(Quiescent)\n");
  345. }
  346. }
  347. //
  348. // Print the Current Capacity
  349. //
  350. if (BatteryStatus->Capacity == BATTERY_UNKNOWN_CAPACITY) {
  351. printf (" Current Battery Charge: %08x UNKNOWN\n");
  352. } else {
  353. printf (" Current Battery Charge: %08x ", BatteryStatus->Capacity);
  354. if (BatteryStatus->Capacity == 0xFFFF) {
  355. printf ("Invalid");
  356. } else {
  357. printf ("%d mWh ", BatteryStatus->Capacity);
  358. }
  359. if ((BInfo->FullChargedCapacity != 0) &
  360. (BInfo->FullChargedCapacity != BATTERY_UNKNOWN_CAPACITY)){
  361. printf ("(%d%%)",
  362. BatteryStatus->Capacity * 100 / BInfo->FullChargedCapacity);
  363. }
  364. printf ("\n");
  365. }
  366. printf ("\n");
  367. }
  368. void
  369. QueryBattery (PUNICODE_STRING BatteryName)
  370. {
  371. HANDLE driverHandle;
  372. ULONG batteryTag;
  373. BATTERY_INFORMATION BInfo;
  374. ULONG BETime;
  375. UCHAR BDeviceName[50];
  376. MFG_DATE BManDate;
  377. UCHAR BManName[50];
  378. ULONG BETemp;
  379. UCHAR BEUID[50];
  380. BATTERY_REPORTING_SCALE BEGran[4];
  381. BATTERY_WAIT_STATUS WStat;
  382. BATTERY_STATUS BStat;
  383. ULONG i;
  384. ULONG Cent;
  385. ULONG Far;
  386. UCHAR PrivateLevel;
  387. ULONG Bdata;
  388. UCHAR Bblock[50];
  389. if ((driverHandle = OpenBattery (BatteryName)) == NULL) {
  390. return;
  391. }
  392. printf ("Opened driver w/handle %d\n", driverHandle);
  393. batteryTag = GetBatteryTag (driverHandle);
  394. if (batteryTag == BATTERY_TAG_INVALID) {
  395. NtClose(driverHandle);
  396. return;
  397. }
  398. printf ("[Static Information]\n");
  399. printf (" Battery Tag...........: %x\n", batteryTag);
  400. //
  401. // Get generic info
  402. //
  403. if (GetBatteryInfo (driverHandle, batteryTag, BatteryInformation, &BInfo, sizeof(BInfo))) {
  404. //
  405. // Print the Capabilities
  406. //
  407. printf (" Capabilities..........: ");
  408. printf ("%08x ", BInfo.Capabilities);
  409. if (BInfo.Capabilities & BATTERY_SYSTEM_BATTERY) {
  410. printf ("System ");
  411. }
  412. if (BInfo.Capabilities & BATTERY_CAPACITY_RELATIVE) {
  413. printf ("Capacity_Relative ");
  414. }
  415. if (BInfo.Capabilities & BATTERY_IS_SHORT_TERM) {
  416. printf ("Short_Term ");
  417. }
  418. printf ("\n");
  419. //
  420. // Print the Technology
  421. //
  422. printf (" Technology............: %08x ", BInfo.Technology);
  423. if (BInfo.Technology == 0) {
  424. printf ("Primary Battery ");
  425. } else if (BInfo.Technology == 1) {
  426. printf ("Secondary Battery ");
  427. } else {
  428. printf ("Unknown ");
  429. }
  430. printf ("\n");
  431. //
  432. // Print the Chemistry
  433. //
  434. printf (" Chemistry.............: %4.4s\n", BInfo.Chemistry);
  435. //
  436. // Print the Designed Capacity
  437. //
  438. printf (" Designed Capacity.....: ");
  439. if (BInfo.DesignedCapacity == BATTERY_UNKNOWN_CAPACITY) {
  440. printf ("%08x UNKNOWN\n", BInfo.DesignedCapacity);
  441. } else {
  442. if (BInfo.Capabilities & BATTERY_CAPACITY_RELATIVE) {
  443. printf ("%08x %d%%\n", BInfo.DesignedCapacity, BInfo.DesignedCapacity);
  444. } else {
  445. printf ("%08x %d mWh\n", BInfo.DesignedCapacity, BInfo.DesignedCapacity);
  446. }
  447. }
  448. //
  449. // Print the Full Charged Capacity
  450. //
  451. printf (" Full Charged Capacity.: ");
  452. if (BInfo.FullChargedCapacity == BATTERY_UNKNOWN_CAPACITY) {
  453. printf ("%08x UNKNOWN\n", BInfo.FullChargedCapacity);
  454. } else {
  455. if (BInfo.Capabilities & BATTERY_CAPACITY_RELATIVE) {
  456. printf ("%08x %d%%\n", BInfo.FullChargedCapacity, BInfo.FullChargedCapacity);
  457. } else {
  458. printf ("%08x %d mWh\n", BInfo.FullChargedCapacity, BInfo.FullChargedCapacity);
  459. }
  460. }
  461. if ((BInfo.FullChargedCapacity == 0) ||
  462. (BInfo.FullChargedCapacity == BATTERY_UNKNOWN_CAPACITY)){
  463. //
  464. // Print Alert 1
  465. //
  466. printf (" Default Alert1 (crit).: %08x %d mWh\n",
  467. BInfo.DefaultAlert1, BInfo.DefaultAlert1);
  468. //
  469. // Print Alert 2
  470. //
  471. printf (" Default Alert2 (low)..: %08x %d mWh (%d%%)\n",
  472. BInfo.DefaultAlert2, BInfo.DefaultAlert2);
  473. } else {
  474. //
  475. // Print Alert 1
  476. //
  477. printf (" Default Alert1 (crit).: %08x %d mWh (%d%%)\n",
  478. BInfo.DefaultAlert1, BInfo.DefaultAlert1,
  479. (BInfo.DefaultAlert1*100)/BInfo.FullChargedCapacity);
  480. //
  481. // Print Alert 2
  482. //
  483. printf (" Default Alert2 (low)..: %08x %d mWh (%d%%)\n",
  484. BInfo.DefaultAlert2, BInfo.DefaultAlert2,
  485. (BInfo.DefaultAlert2*100)/BInfo.FullChargedCapacity);
  486. }
  487. //
  488. // Print the Critical Bias
  489. //
  490. printf (" Critical Bias.........: %08x\n", BInfo.CriticalBias);
  491. //
  492. // Print the Cycle Count
  493. //
  494. printf (" Cycle Count...........: %08x %d\n", BInfo.CycleCount, BInfo.CycleCount);
  495. }
  496. //
  497. // Print the battery granularity
  498. //
  499. printf (" Granularity...........: ");
  500. if (GetBatteryInfo (driverHandle, batteryTag, BatteryGranularityInformation, BEGran, sizeof(BEGran))) {
  501. printf ("%08x Capacity(1) %08x\n", BEGran[0].Granularity, BEGran[0].Capacity);
  502. for (i = 1; i < 4; i++) {
  503. if ((BEGran[i].Granularity != -1) && (BEGran[i].Granularity != 0)) {
  504. printf (" %08x Capacity(%d) %08x\n",
  505. BEGran[i].Granularity, (i+1), BEGran[i].Capacity);
  506. }
  507. }
  508. }
  509. //
  510. // Print the temperature
  511. //
  512. printf (" Temperature...........: ");
  513. if (GetBatteryInfo (driverHandle, batteryTag, BatteryTemperature, &BETemp, sizeof(BETemp))) {
  514. printf ("%08x", BETemp);
  515. //
  516. // Print temp as something reasonable - Centigrade and Fahrenheit
  517. //
  518. if (BETemp > 0) {
  519. Cent = (BETemp/10) - 273;
  520. Far = ((Cent*2) - (Cent/5)) + 32;
  521. printf (" %d C %d F", Cent, Far);
  522. }
  523. printf ("\n");
  524. }
  525. //
  526. // Print the Unique ID
  527. //
  528. printf (" Unique ID.............: ");
  529. if (GetBatteryInfo (driverHandle, batteryTag, BatteryUniqueID, BEUID, sizeof(BEUID))) {
  530. printf ("%ws\n", BEUID);
  531. }
  532. //
  533. // Print the estimated run time
  534. //
  535. printf (" Estimated Runtime.....: ");
  536. if (GetBatteryInfo (driverHandle, batteryTag, BatteryEstimatedTime, &BETime, sizeof(BETime))) {
  537. printf ("%08x ", BETime);
  538. if (BETime != BATTERY_UNKNOWN_TIME) {
  539. printf ("%d Seconds ", BETime);
  540. printf ("(%d:%d:%d)", BETime / 3600, (BETime % 3600) / 60, (BETime % 3600) % 60);
  541. } else {
  542. printf ("Not Available");
  543. }
  544. printf ("\n");
  545. }
  546. //
  547. // Print the device name
  548. //
  549. printf (" Device Name...........: ");
  550. if (GetBatteryInfo (driverHandle, batteryTag, BatteryDeviceName, BDeviceName, sizeof(BDeviceName))) {
  551. printf ("%ws\n", BDeviceName);
  552. }
  553. //
  554. // Print the manufacture date
  555. //
  556. printf (" Manufacture Date......: ");
  557. if (GetBatteryInfo (driverHandle, batteryTag, BatteryManufactureDate, &BManDate, sizeof(BManDate))) {
  558. printf ("%02X%02X%04X %02d/%02d/%d\n", BManDate.Month, BManDate.Day, BManDate.Year,
  559. BManDate.Month, BManDate.Day, BManDate.Year);
  560. }
  561. //
  562. // Print the manufacturer name
  563. //
  564. printf (" Manufacturer Name.....: ");
  565. if (GetBatteryInfo (driverHandle, batteryTag, BatteryManufactureName, BManName, sizeof(BManName))) {
  566. printf ("%ws\n", BManName);
  567. }
  568. printf ("\n");
  569. //
  570. // Get the battery status and print it out
  571. //
  572. memset (&WStat, 0, sizeof(WStat));
  573. WStat.BatteryTag = batteryTag;
  574. GetBatteryStatus (driverHandle, &WStat, &BInfo, &BStat);
  575. //
  576. // If the user requested it perform a long term status change request
  577. //
  578. if (LongTerm) {
  579. printf ("Starting long-term status change request (5 min.)\n");
  580. WStat.PowerState = BStat.PowerState;
  581. WStat.LowCapacity = BStat.Capacity - RANGE;
  582. WStat.HighCapacity = BStat.Capacity + RANGE;
  583. WStat.Timeout = 50000000; // 5 min
  584. GetBatteryStatus (driverHandle, &WStat, &BInfo, &BStat);
  585. }
  586. NtClose(driverHandle);
  587. }
  588. int
  589. __cdecl
  590. main(USHORT argc, CHAR **argv)
  591. {
  592. ULONG battTag;
  593. ULONG battNum;
  594. ULONG RetVal;
  595. UCHAR param;
  596. UNICODE_STRING batteries [MAX_NUMBER_OF_BATTERIES];
  597. UCHAR numBatts;
  598. RtlZeroMemory (batteries, sizeof(UNICODE_STRING)*MAX_NUMBER_OF_BATTERIES);
  599. _tprintf (_T("Parameters: [L] - Issue Long-term status change request\n"));
  600. if (argc > 1) {
  601. param = argv[1][0];
  602. if ((param == 'l') || param == 'L') {
  603. LongTerm = TRUE;
  604. }
  605. }
  606. while (1) {
  607. numBatts = GetBatteryDriverNames (batteries, MAX_NUMBER_OF_BATTERIES);
  608. printf ("\n");
  609. for (battNum = 0; battNum < numBatts; battNum++) {
  610. _tprintf(_T("Batt#%d: %s \n"), battNum, batteries[battNum].Buffer);
  611. }
  612. printf ("\nBattery Number: ");
  613. if (scanf ("%d", &battNum) != 1) {
  614. return 0; // Program exit
  615. }
  616. printf ("\n");
  617. if (battNum < numBatts) {
  618. QueryBattery (&batteries [battNum]);
  619. } else {
  620. printf ("Invalid Battery Number\n");
  621. }
  622. }
  623. return 0;
  624. }