0x00000010 Ошибка чтения символов строки. ПРОПВАРИАНТНАЯ структура

Вот как я могу получить PROPVARIANT структура с функциями WASAPI API:

//Pointer for stored audio stream
IAudioClient *iac = NULL;

//Endpoint device selection
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice;
IMMDeviceCollection *pCollection = NULL;
CoInitialize(NULL);
hr = CoCreateInstance(
CLSID_MMDeviceEnumerator, NULL,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
(void**)&pEnumerator);

hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pCollection);

//Create vector of IMMDevices
UINT endpointCount = NULL;
(*pCollection).GetCount(&endpointCount);
std::vector<IMMDevice**> IMMDevicePP;   //IMMDevice seems to contain all endpoint devices, so why have a collection here?
for (UINT i = 0; i < (endpointCount); i++)
{
IMMDevice* pp = NULL;
(*pCollection).Item(i, &pp);
IMMDevicePP.assign(1, &pp);
}
UINT IMMDeviceCount = IMMDevicePP.size();

//Enumerate Properties of IMMDevices
std::vector<IPropertyStore*> IMMDeviceProperties;
for (int k = 0; k < IMMDeviceCount; k++) {
IPropertyStore* prop = NULL;
(**IMMDevicePP[k]).OpenPropertyStore(STGM_READ, &prop);
IMMDeviceProperties.assign(1, prop);
}
UINT PropertyStoreCount = IMMDeviceProperties.size();

//Find name property of device
std::vector<PROPVARIANT*> properties;
for (int i = 0; i < PropertyStoreCount; i++) {
DWORD propCount = 1;
HRESULT countResult = (*IMMDeviceProperties[i]).GetCount(&propCount);
if (countResult == S_OK) { }
else {
int x = 5;
}
for (int p = 0; p < propCount; p++) {
PROPERTYKEY key;
HRESULT keyResult = (*IMMDeviceProperties[i]).GetAt(p, &key);
HRESULT getAT;
PROPVARIANT propVari;
HRESULT propVariResult = (*IMMDeviceProperties[i]).GetValue(key, &propVari);
propVari.vt = VT_LPWSTR;
LPWSTR test = propVari.pwszVal;
//char pwszValTest;
//strcpy(&pwszValTest, propVari.pwszVal);
//WCHAR friendlyName = *propVari.pwszVal;
properties.assign(1, &propVari);
}
}

Все HRESULTвозвращаемся S_OK.

Результирующий PROPVARIANT структура правильно отображает на первый взгляд. Однако при дальнейшей проверке с помощью свойства VS наблюдайте, что все свойства строкового типа возвращают ошибку, отраженную в заголовке этого вопроса. Поэтому, когда я пытаюсь получить имя моего аудио конечного устройства, которое содержит pwszVal собственность моего PROPVARIANT структура так:

LPWSTR test = propVari.pwszVal;

Я не могу получить нужные данные. Я попытался скопировать строку с различными методами конвертера безрезультатно. Я знаю, что эта ошибка связана с кучей вопросов, но я не могу ее исправить.

Вот документ для PROPVARIANT и его соответствующие свойства:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa380072(v=vs.85).aspx

В этой документации говорится, чтоPROPVARIANT член vt установлен в VT_LPWSTR» VT_LPWSTR является типом enum и соответствует значению 31. Тогда как VT_BLOB соответствует значению 65. My vt член устанавливается на VT_BLOB или 65 вместо 31 или VT_LPWSTR, Почему это так? Это противоречит значению, указанному в этой документации:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd370812(v=vs.85).aspx

Ручная настройка vt элемент также не изменяет / не исправляет ошибку чтения строки:

propVari.vt = VT_LPWSTR;

PKEY_Device_FriendlyName это то, что я по сути после. Любая помощь / советы высоко ценится.

0

Решение

Следующий код, основанный на вашем, но без запутывающих векторов, работает нормально. При запуске я получаю «FriendlyName: Speakers / HP (IDT High Definition Audio CODEC)», который кажется правильным для этого ноутбука.

При работе с COM и без какого-либо умного указателя будьте очень осторожны, чтобы освободить все указатели. И всегда проверяйте все результаты. Вызовы COM могут не работать по разным причинам.

#define WINVER _WIN32_WINNT_VISTA
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define STRICT
#include <windows.h>
#include <ole2.h>
#include <mmdeviceapi.h>
#include <propsys.h>
#include <propvarutil.h>
#include <stdio.h>
#include <Functiondiscoverykeys_devpkey.h>

#pragma comment(lib, "ole32")
#pragma comment(lib, "propsys")

const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);

static HRESULT
DumpDeviceProperties(IMMDevice *pDevice)
{
IPropertyStore *pStore = NULL;
HRESULT hr = pDevice->OpenPropertyStore(STGM_READ, &pStore);
if (SUCCEEDED(hr))
{
PROPVARIANT prop;
PropVariantInit(&prop);
hr = pStore->GetValue(PKEY_Device_FriendlyName, &prop);
if (SUCCEEDED(hr))
{
if (IsPropVariantString(prop))
wprintf(L"FriendlyName: %s\n", PropVariantToStringWithDefault(prop, L"(missing)"));
else
hr = E_UNEXPECTED;
}
PropVariantClear(&prop);
pStore->Release();
}
return hr;
}

int
wmain(int argc, WCHAR *argv[])
{
HRESULT hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr))
{
IMMDeviceEnumerator *pEnumerator = NULL;
hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast<void **>(&pEnumerator));
if (SUCCEEDED(hr))
{
IMMDeviceCollection *pCollection = NULL;
hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pCollection);
if (SUCCEEDED(hr))
{
UINT cEndpoints = 0;
hr = pCollection->GetCount(&cEndpoints);
if (SUCCEEDED(hr))
{
for (UINT n = 0; SUCCEEDED(hr) && n < cEndpoints; ++n)
{
IMMDevice *pDevice = NULL;
hr = pCollection->Item(n, &pDevice);
if (SUCCEEDED(hr))
{
hr = DumpDeviceProperties(pDevice);
pDevice->Release();
}
}
}
pCollection->Release();
}
pEnumerator->Release();
}
CoUninitialize();
}
return SUCCEEDED(hr) ? 0 : 1;
}

Скомпилировано с использованием: cl -nologo -MDd -Zi -W3 -Od lsdevices.cpp с MSVC 2013.

1

Другие решения

Вы не правильно заполняете свои векторы. Вы храните адреса памяти локальных переменных, а не фактические элементы, на которые ссылаются переменные.

И что еще хуже, вы используете std::vector::assign() добавлять предметы. assign() заменяет все содержимое вектора на указанное значение. Если у вас есть несколько устройств в коллекции, вы не получите вектор из нескольких устройств. Вы должны использовать push_back() вместо assign(),

Вы делаете эти ошибки со всеми вашими векторами.

На заметку, вы должны использовать -> оператор вместо использования (*). при вызове методов объектов. Это сделает код чище и проще для чтения.

Попробуйте это вместо этого:

//Endpoint device selection
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDeviceCollection *pCollection = NULL;

CoInitialize(NULL);
hr = CoCreateInstance(
CLSID_MMDeviceEnumerator, NULL,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
(void**)&pEnumerator);

hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pCollection);
pEnumerator->Release();

//Create vector of IMMDevices
std::vector<IMMDevice*> IMMDevice;
UINT endpointCount = 0;
hr = pCollection->GetCount(&endpointCount);
if (hr == S_OK) {
IMMDevice.reserve(endpointCount);
for (UINT i = 0; i < endpointCount; ++i) {
IMMDevice *pDevice = NULL;
hr = pCollection->Item(i, &pDevice);
if (hr == S_OK) {
IMMDevice.push_back(pDevice);
}
}
}
UINT IMMDeviceCount = IMMDevice.size();

pCollection->Release();

//Enumerate Properties of IMMDevices
std::vector<IPropertyStore*> IMMDeviceProperties;
IMMDeviceProperties.reserve(IMMDeviceCount);
for (int k = 0; k < IMMDeviceCount; k++) {
IPropertyStore* prop = NULL;
hr = IMMDevice[k]->OpenPropertyStore(STGM_READ, &prop);
if (hr == S_OK) {
IMMDeviceProperties.push_back(prop);
}
}
UINT PropertyStoreCount = IMMDeviceProperties.size();

//Find name property of devices
std::vector<std::wstring> MMDeviceFriendlyNames;
MMDeviceFriendlyNames.reserve(IMMDeviceCount);
for (int i = 0; i < PropertyStoreCount; i++) {
PROPVARIANT propVari;
PropVariantInit(&propVari);
hr = IMMDeviceProperties[i]->GetValue(PKEY_Device_FriendlyName, &propVari);
if (hr == S_OK) {
MMDeviceFriendlyNames.push_back(propVari.pwszVal);
PropVariantClear(&propVari);
}
}

// use vectors as needed...

for (UINT i = 0; i < PropertyStoreCount; ++i) {
IMMDeviceProperties[i]->Release();
}
for (UINT i = 0; i < IMMDeviceCount; ++i) {
IMMDevice[i]->Release();
}
1

По вопросам рекламы [email protected]