Я пытаюсь получить имена всех аккумуляторных устройств на моем компьютере, используя этот код, полученный в основном из руководства Microsoft, но он не работает.
#define INITGUID
#include <windows.h>
#include<batclass.h>
#include<setupapi.h>
#define GBS_HASBATTERY 0x1
#define GBS_ONBATTERY 0x2
#include<iostream>
using namespace std;
int main()
{
DWORD dwResult = GBS_ONBATTERY;
HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVICE_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
for (int idev = 0; idev < 100; idev++)
{
SP_DEVICE_INTERFACE_DATA did = {0};
did.cbSize = sizeof(did);
if (SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVICE_BATTERY, idev, &did))
{
DWORD cbRequired = 0;
SetupDiGetDeviceInterfaceDetail(hdev, &did, 0, 0, &cbRequired, 0);
if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
{
PSP_DEVICE_INTERFACE_DETAIL_DATA pdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR,cbRequired);
if (pdidd)
{
pdidd->cbSize = sizeof(*pdidd);
if (SetupDiGetDeviceInterfaceDetail(hdev,&did,pdidd,cbRequired,&cbRequired,0))
{
HANDLE hBattery = CreateFile(pdidd->DevicePath,GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (INVALID_HANDLE_VALUE != hBattery)
{
BATTERY_QUERY_INFORMATION bqi = {0};
DWORD dwWait = 0;
DWORD dwOut;
if (DeviceIoControl(hBattery,
IOCTL_BATTERY_QUERY_TAG,
&dwWait,
sizeof(dwWait),
&bqi.BatteryTag,
sizeof(bqi.BatteryTag),
&dwOut,
NULL)
&& bqi.BatteryTag)
{////////////////////////////////////////problem around here///////
string bi;
bqi.InformationLevel = BatteryDeviceName;
if (DeviceIoControl(hBattery,
IOCTL_BATTERY_QUERY_INFORMATION,
&bqi,
sizeof(bqi),
&bi,
sizeof(bi),
&dwOut,
NULL))
{
cout<<bi;
BATTERY_WAIT_STATUS bws = {0};
bws.BatteryTag = bqi.BatteryTag;
BATTERY_STATUS bs;
if (DeviceIoControl(hBattery,
IOCTL_BATTERY_QUERY_STATUS,
&bws,
sizeof(bws),
&bs,
sizeof(bs),
&dwOut,
NULL))
{
if (bs.PowerState & BATTERY_POWER_ON_LINE)
{
dwResult &= ~GBS_ONBATTERY;
}
}
}
}
CloseHandle(hBattery);
}
}
LocalFree(pdidd);
}
}
}
else if (ERROR_NO_MORE_ITEMS == GetLastError())
{
break;
}
}
SetupDiDestroyDeviceInfoList(hdev);
}
я пытаюсь напечатать имена всех батарей, но когда я запускаю программу, она вообще ничего не печатает, однако она работает, когда я запрашиваю структуру battery_information вместо строки BatteryDeviceName, пожалуйста, помогите
Проблема в том, что в вашем звонке DeviceIoControl
неправильно. Вы попадаете в мусор, а когда вы кладете мусор, вы вывозите мусор.
string bi;
if(DeviceIoControl(hBattery,
IOCTL_BATTERY_QUERY_INFORMATION,
bqi,
sizeof(bqi),
&bi, // Really?!?!?!
sizeof(bi), // WHAT?!?
&dwOut,
NULL))
Вы передаете адрес std::string
Возражать DeviceIoControl
, который ничего не знает о std::string
и ожидает адрес необработанного буфера, в который он может записать. Вы по крайней мере указываете правильный размер для этого буфера, но даже это в некотором смысле неверно. По сути, когда эта функция возвращается, std::string
Это мусор, и доступ к нему может сделать практически все — от сбоя программы до воспроизведения Vivaldi на ваших динамиках.
Попробуйте что-то вроде этого:
WCHAR szBuf[_MAX_PATH] = { 0 }; // In a real program you'd dynamically
// allocate an appropriately sized buffer
// instead.
if(DeviceIoControl(hBattery,
IOCTL_BATTERY_QUERY_INFORMATION,
bqi,
sizeof(bqi),
szBuf,
sizeof(szBuf),
&dwOut,
NULL))
Других решений пока нет …