IWbemLocator::ConnectServer (WMI) crashes in Windows 7 - c++

I am writing a simple x86 application for extracting Harddrive/storage info by using WMI. The development environment is MS Visual Studio 2013 Update 5. However, everytime my code reaches this part :
hr = (*pLoc)->ConnectServer(....);
I receive this error
"Unhandled exception at 0x6C2BD183 (wbemcomn.dll) in HDDExtractor.exe: 0xC0000005: Access violation writing location 0x00DB9CAA"
The funny thing is that, this error occurs on the PCs with Windows 7, however it always works perfectly fine on PCs with Windows 10.
Below is the excerpt of the source code :
#include <iostream>
#include <winsock2.h>
#include <Winbase.h>
#include <Iphlpapi.h>
#include <stdlib.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <WinIoCtl.h>
#pragma comment(lib, "IPHLPAPI.lib")
////////////////////////////////////////
#include <icmpapi.h>
#pragma comment(lib, "ws2_32.lib")
#include <iostream>
#include <strsafe.h>
//////////////////////////////////////
//for WMI
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
/////////////////////////////
#include <sstream>
#include <vector>
#include <algorithm>
#include <conio.h>
std::string WMI_Initialize(IWbemServices **pSvc, IWbemLocator **pLoc)
{
//Initialize COM.
HRESULT hr;
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hr))
{
std::string result;
std::ostringstream out;
out << "Failed to initialize COM library. Error code = 0x"
<< hex << hr << endl;
result = out.str();
return result;
}
hr = CoInitializeSecurity(
NULL, // Security descriptor
-1, // COM negotiates authentication service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication level for proxies
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation level for proxies
NULL, // Authentication info
EOAC_NONE, // Additional capabilities of the client or server
NULL); // Reserved
if (FAILED(hr))
{
std::string result;
std::ostringstream out;
out << "Failed to initialize security. Error code = 0x"
<< hex << hr << endl;
CoUninitialize();
result = out.str();
return result;
}
hr = CoCreateInstance(CLSID_WbemLocator, 0,
CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc[0]);
if (FAILED(hr))
{
string result;
std::ostringstream out;
out << "Failed to create IWbemLocator object. Err code = 0x"
<< hex << hr << endl;
result = out.str();
CoUninitialize();
return result;
}
// Connect to the root\default namespace with the current user.
hr = (*pLoc)->ConnectServer(
BSTR(L"\\\\.\\root\\CIMV2"),
NULL, // User name
NULL, // User password
0, // Locale
NULL, // Security flags
0, // Authority
0, // Context object
&pSvc[0]); // IWbemServices proxy
// The rest/other stuffs below
}
And this is the calling function
std::string WMI_getHDDSN(std::string str)
{
IWbemServices *pSvc = NULL;
IWbemLocator *pLoc = NULL;
HRESULT hr;
std::string result = WMI_Initialize(&pSvc, &pLoc);
//The rest/other stuffs are below
}
And lastly the main function
int main(int argc, char *argv[])
{
std::wcout << "Press AnyKey" << std::endl;
std::string SN = WMI_getHDDSN("C");
std::wcout << "Error Message : " << SN.c_str() << std::endl;
_getch();
_getch();
}
Thank you very much.

Related

Dynamically allocate buffer[] for URLOpenBlockingStreamW() output

I'm super new to C++ and I'm trying to download an executable file from a URL and write it to disk.
I have the below code which successfully downloads the file and stores it in memory. The issue I am having is then writing that to disk.
I am pretty sure this is down to where I am creating the buffer where the downloaded data will be written to before being going to the new file.
char buffer[4096];
The 4096 is an arbitrary number from the template code I got elsewhere. What I can't figure out or don't know is how to dynamically allocate that buffer size based on the size of the data at &pStream.
I have tried using functions such as sizeof() but these just get me the memory address size rather than the value itself.
Alternatively, is there better way to try and accomplish this download and write?
#include <Windows.h>
#include <Urlmon.h> // URLOpenBlockingStreamW()
#include <atlbase.h> // CComPtr
#include <iostream>
#include "download.h"
#include <fstream>
#include <assert.h>
#include <chrono>
#include <thread>
#pragma comment( lib, "Urlmon.lib" )
struct ComInit
{
HRESULT hr;
ComInit() : hr(::CoInitialize(nullptr)) {}
~ComInit() { if (SUCCEEDED(hr)) ::CoUninitialize(); }
};
int download_file()
{
ComInit init;
HRESULT hr;
// use CComPtr so you don't have to manually call Release()
CComPtr<IStream> pStream;
bool success = false;
while (success == false)
{
try {
// Open the HTTP request.
hr = URLOpenBlockingStreamW(nullptr, L"https://www.foo.bar/download/somefile.exe", &pStream, 0, nullptr);
if (FAILED(hr))
{
std::cout << "ERROR: Could not connect. HRESULT: 0x" << std::hex << hr << std::dec << "\n";
}
else
{
success = true;
}
}
catch (const std::exception& ex) {
std::cout << ex.what();
}
}
// Download the response and write it to stdout.
char buffer[4096]; // Issue is here I think
do
{
DWORD bytesRead = 0;
hr = pStream->Read(buffer, sizeof(buffer), &bytesRead);
if (bytesRead > 0)
{
//std::cout.write(buffer, bytesRead);
std::ofstream file;
file.open("some_path_dot_exe", std::ios_base::binary);
assert(file.is_open());
for (int i = 0; i < sizeof(buffer) / sizeof(buffer[0]); ++i)
file.write((char*)(buffer + i * sizeof(buffer[0])), sizeof(buffer[0]));
file.close();
}
} while (SUCCEEDED(hr) && hr != S_FALSE);
if (FAILED(hr))
{
std::cout << "ERROR: Download failed. HRESULT: 0x" << std::hex << hr << std::dec << "\n";
return 2;
}
std::cout << "\n";
return 0;
}
The IStream that URLOpenBlockingStreamW() gives you isn't guaranteed to be able to give you the full file size up front, so if you want to hold the entire file in memory, you will have to use std::vector or other dynamically-growing buffer.
Though, you don't actually need to hold the entire file in memory just to save it to disk, you can use a fixed array and write it to disk as it is being downloaded, as you already are doing.
The real problem is, you are opening and closing the file on every Read(), wiping out all previous data written. And you are ignoring the bytesRead value that Read() gives you.
You need to open the file one time, leave it open until you are done with the download, and don't write more than is actually in the buffer on each write().
Try this:
#include <Windows.h>
#include <Urlmon.h> // URLOpenBlockingStreamW()
#include <atlbase.h> // CComPtr
#include <iostream>
#include "download.h"
#include <fstream>
#include <assert.h>
#include <chrono>
#include <thread>
#pragma comment( lib, "Urlmon.lib" )
struct ComInit
{
HRESULT hr;
ComInit() : hr(::CoInitialize(nullptr)) {}
~ComInit() { if (SUCCEEDED(hr)) ::CoUninitialize(); }
};
int download_file()
{
ComInit init;
HRESULT hr;
// use CComPtr so you don't have to manually call Release()
CComPtr<IStream> pStream;
do
{
try {
// Open the HTTP request.
hr = URLOpenBlockingStreamW(nullptr, L"https://www.foo.bar/download/somefile.exe", &pStream, 0, nullptr);
if (SUCCEEDED(hr)) break;
std::cout << "ERROR: Could not connect. HRESULT: 0x" << std::hex << hr << std::dec << "\n";
}
catch (const std::exception& ex) {
std::cout << ex.what();
}
}
while (true);
std::ofstream file("some_path_dot_exe", std::ios_base::binary);
if (!file.is_open()) {
std::cout << "ERROR: Download failed. Unable to create output file.\n";
return 1;
}
// Download the response and write it to file.
char buffer[4096];
DWORD bytesRead;
do
{
hr = pStream->Read(buffer, sizeof(buffer), &bytesRead);
if (bytesRead > 0)
file.write(buffer, bytesRead);
} while (SUCCEEDED(hr) && hr != S_FALSE);
file.close();
if (FAILED(hr))
{
std::cout << "ERROR: Download failed. HRESULT: 0x" << std::hex << hr << std::dec << "\n";
return 2;
}
std::cout << "\n";
return 0;
}

Trouble printing DIDEVICEINSTANCE tszProductName to Windows Console

I've been following a DirectInput tutorial and am having trouble printing a list of DirectInput device product names to a Windows console.
I'm using VS19's C++ compiler and am compiling with UNICODE defined. Since tszProductName is of type TCHAR which resolves to WCHAR I followed this stack overflow answer to allow the windows console to print unicode while also avoiding mixing wcout with cout in the same program.
Before I made those changes nothing was printed. Now the console prints '쳌' repeatedly for each device name. I tried switching from Unicode to Multibyte and going back to cout to no avail. Here is the code in question.
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#pragma comment (lib,"dinput8.lib")
#pragma comment (lib,"dxguid.lib")
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <locale.h>
#include <clocale>
#include <io.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
IDirectInput8* dev;
std::vector<LPDIRECTINPUTDEVICE8> gameControllers;
BOOL CALLBACK enumGameControllers(LPCDIDEVICEINSTANCE devInst, LPVOID pvRef) {
LPDIRECTINPUTDEVICE8 gameController;
if (FAILED(dev->CreateDevice(devInst->guidInstance, &gameController, NULL)))
return DIENUM_CONTINUE;
else {
gameControllers.push_back(gameController);
return DIENUM_CONTINUE;
}
}
int wmain(int argc, wchar_t* argv[]) {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
char* a = setlocale(LC_ALL, "en-US.UTF8");
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
CONSOLE_FONT_INFOEX fontInfo;
fontInfo.cbSize = sizeof(fontInfo);
fontInfo.FontFamily = 20;
fontInfo.FontWeight = 400;
fontInfo.nFont = 0;
const wchar_t myFont[] = L"Lucida Console";
fontInfo.dwFontSize = { 8, 16 };
std::copy(myFont, myFont + _countof(myFont), fontInfo.FaceName);
SetCurrentConsoleFontEx(hConsole, false, &fontInfo);
if (FAILED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&dev, NULL))) {
std::wcout << L"Critical error: Unable to create the main DirectInput 8 COM object!\n";
return 1;
}
if (FAILED(dev->EnumDevices(DI8DEVCLASS_GAMECTRL, &enumGameControllers, NULL, DIEDFL_ATTACHEDONLY))) {
std::wcout << L"Critical error: Unable to enumerate input devices!\n";
return 1;
}
if (gameControllers.empty()) {
std::wcout << L"No peripherals found\n";
return 1;
}
int count = 1;
std::wcout << L"Number of devices: " << gameControllers.size() << std::endl;
for (LPDIRECTINPUTDEVICE8 i : gameControllers) {
DIDEVICEINSTANCE deviceInfo;
i->GetDeviceInfo(&deviceInfo);
std::wcout << L"Device Number " << count << L": ";
std::wcout << deviceInfo.tszProductName << std::endl;
if (FAILED(i->SetCooperativeLevel(GetConsoleWindow(), DISCL_BACKGROUND | DISCL_EXCLUSIVE))) {
std::wcout << L"Cooperative level could not be set\n";
return 1;
}
++count;
}
return 0;
}
Thanks in advance for any suggestions and/or solutions.
DIDEVICEINSTANCE deviceInfo;
i->GetDeviceInfo(&deviceInfo);
Problems with this code are that:
DIDEVICEINSTANCE::dwSize is not initialized as required, and
the return value of IDirectInputDevice8::GetDeviceInfo is not checked for errors.
Change to the following, instead.
DIDEVICEINSTANCE deviceInfo = { sizeof(DIDEVICEINSTANCE) };
if(i->GetDeviceInfo(&deviceInfo) != DI_OK) { /* call failed, handle error */ }

Linking a C++ project with a form project in visual studio

I have a CLR project that includes a form (Project1), and another General project (Project2) in visual studio, both are in C++ and they both work perfectly by themselves. I'm trying to link them, but I keep getting the following error as soon as the program starts:
Exception thrown at 0x77400A36 (ntdll.dll) in BrailleGUI.exe: 0xC0000005: ?>Access violation reading location 0x029905BB.
If there is a handler for this exception, the program may be safely continued.
I tried adding Project2 to the solution of Project1, I tried adding the .h and .cpp files of Project2 into Project1, I even tried just copying the code into the files that already exist in Project1. I still get the same error. Any ideas?
Thank you in advance, please let me know if you need more info.
Code:
Project2.h
#pragma once
#include <Windows.h>
#include <iostream>
#include <WbemCli.h>
#include <string>
#include <comutil.h>
#include <regex>
#pragma comment(lib, "comsuppw.lib")
#pragma comment (lib, "wbemuuid.lib")
int ReturnCOM();
int FindPort(char *com);
Project2.cpp
#include "ChipCommunication.h"
using namespace std;
int ReturnCOM(){
int COMNumber = 0;
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hRes)){
cout << "Unable to CoInitialize";
return -1;
}
if ((FAILED(hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0))))
{
cout << "Unable to initialize security: 0x" << std::hex << hRes << endl;
return -1;
}
IWbemLocator* pLocator = NULL;
if (FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator)))){
cout << "Unable to create a WbemLocator: " << hRes << endl;
return -1;
}
IWbemServices* pService = NULL;
if (FAILED(hRes = pLocator->ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService))){
pLocator->Release();
cout << "Unable to connect to \"CIMV2\": " << hRes << endl;
return -1;
}
IEnumWbemClassObject* pEnumerator = NULL;
if (FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM Win32_PnPEntity", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator))){
pLocator->Release();
pService->Release();
cout << "Unable to retrive com ports" << hRes << endl;
return -1;
}
IWbemClassObject* clsObj = NULL;
int numElems;
while ((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE){
if (FAILED(hRes))
break;
VARIANT vRet;
VARIANT DeviceName;
VariantInit(&vRet);
VariantInit(&DeviceName);
if (SUCCEEDED(clsObj->Get(L"PNPDeviceID", 0, &vRet, NULL, NULL)) && vRet.vt == VT_BSTR){
if (wcsstr(vRet.bstrVal, L"VID_0525&PID_A4A7") != NULL){
if (SUCCEEDED(clsObj->Get(L"Name", 0, &DeviceName, NULL, NULL)) && DeviceName.vt == VT_BSTR){
char* PointAtCOM = _com_util::ConvertBSTRToString(DeviceName.bstrVal);
COMNumber = FindPort(PointAtCOM);
delete[] PointAtCOM;
}
}
VariantClear(&vRet);
}
clsObj->Release();
}
pEnumerator->Release();
pService->Release();
pLocator->Release();
return COMNumber;
}
int FindPort(char *com){
int ComNumber = 0;
regex FindCOM("\\(COM([0-9]+)");
smatch NumberinString;
string DeviceName (com);
if (regex_search(DeviceName, NumberinString, FindCOM)){
DeviceName = NumberinString[1].str();
ComNumber = stoi (DeviceName);
}
return ComNumber;
}
Project1.h
#pragma once
#include <windows.h>
#include <iostream>
#include <sstream>
#include <msclr\marshal_cppstd.h>
int comNum;
std::ostringstream cmdCHIPStream;
std::string cmdCHIPString;
namespace BrailleGUI {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
public ref class MyForm : public System::Windows::Forms::Form
{
public:
MyForm(void)
{
InitializeComponent();
}
protected:
~MyForm()
{
if (components){
delete components;
}
}
private: System::Windows::Forms::Button^ button1;
protected:
private: System::Windows::Forms::Button^ button2;
private: System::Windows::Forms::Label^ label1;
private: System::Windows::Forms::TextBox^ textBox1;
private: System::Windows::Forms::Label^ label2;
private:
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
...
Project1.cpp
#include "ChipCommunication.h"
#include "MyForm.h"
using namespace System;
using namespace System::Windows::Forms;
[STAThread]
void main(array<String^> ^ args) {
comNum = ReturnCOM();
std::cout << "ReturnCOM is " << comNum << std::endl;
if (comNum == -1) {
std::cout << "Translator not connected" << std::endl;
}
std::ostringstream comConStream;
std::string comConString;
comConStream << "mode com" << comNum << " BAUD=115200 PARITY=n DATA=8" << std::endl;
comConString = comConStream.str();
system(comConString.c_str());
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
BrailleGUI::MyForm form;
Application::Run(%form);
}
I got it to work by removing the [StaThread] line in Project1.cpp and I replaced the _com_util::ConvertBSTRToString() function with one that I found here: https://www.codeproject.com/Articles/1969/BUG-in-com-util-ConvertStringToBSTR-and-com-util

How to use IFileOperation CopyItems for a destination ZIP file

I am using IFileOperation interface's CopyItems method to copy one more files from source folder to a destination folder. This works without any error as long as the destination folder is a standard file system directory. However, my main motivation of using IFileOperation instead of SHFileOperation() method is to allow copying items from / into non-file-system objects as the documentation says (https://msdn.microsoft.com/en-us/library/windows/desktop/bb775771%28v=vs.85%29.aspx).
The following code works perfectly for file-system destination e.g. "g:\my folder" but does not work if the destination is a ZIP file e.g. "g:\Super Cars.zip". For this quick sample please overlook the resource leaks :).
Please note the ZIP file is an existing ZIP file created using standard built-in ZIP capability of Windows and it does not contain the file is am trying to copy.
#include "stdafx.h"
#include <Windows.h>
#include <shellapi.h>
#include <Shlobj.h>
#include <iostream>
#include <atlbase.h>
void CopyFile(LPCTSTR strSource, LPCTSTR strDestination)
{
PIDLIST_ABSOLUTE abSourcePidl = nullptr;
SFGAOF attrs;
HRESULT hr = SHParseDisplayName(strSource, nullptr, &abSourcePidl, 0, &attrs);
if (FAILED(hr))
{
std::wcout << _T("SHParseDisplayName failed for ") << strSource << std::endl;
return;
}
PIDLIST_ABSOLUTE abDestPidl = nullptr;
hr = SHParseDisplayName(strDestination, nullptr, &abDestPidl, 0, &attrs);
if (FAILED(hr))
{
std::wcout << _T("SHParseDisplayName failed for ") << strDestination << std::endl;
return;
}
IShellItem2* pDestShellItem;
hr = SHCreateItemFromIDList(abDestPidl, IID_IShellItem2, reinterpret_cast<LPVOID*>(&pDestShellItem));
if (FAILED(hr))
{
std::wcout << _T("SHCreateItemFromIDList failed") << std::endl;
return;
}
PIDLIST_ABSOLUTE* pPidlRawArray = new PIDLIST_ABSOLUTE[1];
pPidlRawArray[0] = abSourcePidl;
IShellItemArray* pShellItemArr = nullptr;
hr = SHCreateShellItemArrayFromIDLists(1, (LPCITEMIDLIST*)pPidlRawArray, &pShellItemArr);
if (FAILED(hr))
{
std::wcout << _T("SHCreateShellItemArrayFromIDLists failed") << std::endl;
return;
}
CComPtr<IFileOperation> fileOp;
hr = fileOp.CoCreateInstance(CLSID_FileOperation);
if (FAILED(hr))
{
std::wcout << _T("Creation of IFileOperation failed") << std::endl;
return;
}
hr = fileOp->CopyItems(pShellItemArr, pDestShellItem);
if (FAILED(hr))
{
std::wcout << _T("CopyItems fall failed") << std::endl;
return;
}
hr = fileOp->PerformOperations();
if (FAILED(hr))
{
std::wcout << _T("PerformOperations call failed") << std::endl;
return;
}
std::wcout << _T("File copied successfully") << std::endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
CopyFile(_T("D:\\TEMP\\COMTIME.TXT"), _T("G:\\My Folder")); // WORKS!!
CopyFile(_T("D:\\TEMP\\COMTIME.TXT"), _T("G:\\Super Cars.zip")); // DOES NOT WORK!!
CoUninitialize();
return 0;
}

What's wrong with this GetDefaultAudioEndpoint program?

Here's a very simple program using the function:
#include <windows.h>
#include <tchar.h>
#include <atlstr.h>
#include <mmdeviceapi.h>
#include <devicetopology.h>
#include <functiondiscoverykeys.h>
#include <iostream>
using namespace std;
int main()
{
HRESULT hr;
CComPtr<IMMDeviceEnumerator> pMMDeviceEnumerator;
pMMDeviceEnumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, 0);
//cout << hr;
return 0;
}
When I try to run this, I get the following error:
Debug Assertion Failed!
Program: ...
File: c:\program files\microsoft visual studio 8\vc\atlmfc\include\atlcomcli.h
Line: 154
Expression: p!=0
What's wrong with this? I'm just now trying to learn how to use this function. Thanks!
EDIT:
I've changed the program to this:
//#include <windows.h>
//#include <tchar.h>
#include <atlstr.h>
#include <mmdeviceapi.h>
//#include <devicetopology.h>
//#include <functiondiscoverykeys.h>
#include <iostream>
using namespace std;
// helper class to CoInitialize/CoUninitialize
class CCoInitialize {
private:
HRESULT m_hr;
public:
CCoInitialize(PVOID pReserved, HRESULT &hr)
: m_hr(E_UNEXPECTED) { hr = m_hr = CoInitialize(pReserved); }
~CCoInitialize() { if (SUCCEEDED(m_hr)) { CoUninitialize(); } }
};
int main()
{
CComPtr<IMMDeviceEnumerator> pMMDeviceEnumerator;
HRESULT hr = pMMDeviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
if (FAILED(hr)) {
cout << "failed" << endl;
return __LINE__;
}
CCoInitialize ci(NULL, hr);
pMMDeviceEnumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, 0);
//cout << hr;
return 0;
}
When I run it, I get the output of "failed". What's happening?
EDIT:
Alright, now I've changed the code enough to get it running all the way through without any failures. i.e.,
HRESULT hr = S_OK;
cout << hr;
// initialize COM
CCoInitialize ci(NULL, hr);
if (FAILED(hr)) {
cout << "failed1" << endl;
return __LINE__;
}
cout << hr;
// get enumerator
CComPtr<IMMDeviceEnumerator> pMMDeviceEnumerator;
hr = pMMDeviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
if (FAILED(hr)) {
cout << "failed2" << endl;
return __LINE__;
}
cout << hr;
// get default render/capture endpoints
CComPtr<IMMDevice> pRenderEndpoint;
hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pRenderEndpoint);
if (FAILED(hr)) {
cout << "failed3" << endl;
return __LINE__;
}
cout << hr;
return 0;
Some of the trouble I was having earlier with this example (see comments on the answers) was fixed just by removing some of the code. But as I run this new body of the main() function, I get the output "0000", meaning that cout << hr always evaluates to "0". Is this a good thing? What info can I get about the default device now? hr. and hr-> don't really bring up any menus, so I'm kind of in the dark. Thanks!
pMMDeviceEnumerator variable holds a pointer, which is NULL. When you try to call an interface method on this pointer, -> operator checks this nullness and issues an assertion failure.
Windows SDK samples show how to use this function and API, check them under: \Samples\multimedia\audio, e.g. osd sample.
This sample is a Win32-based application that demonstrates the use of the Vista APIs for monitoring the default audio output device and
its current volume setting. The sample is written in C++.
OSD does not run on earlier versions of Windows, including Windows XP, Windows 2000, Windows Me, and Windows 98.
UPD: Things in main one needs to reach the GetDefaultAudioEndpoint API call - Sample: find out if your default audio playback and audio capture devices are on the same hardware.