What's wrong with this GetDefaultAudioEndpoint program? - c++

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.

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;
}

Getting a browser process ID and then using it in the program in C++

I am trying to create a simple word highlighter for browsers (Chrome and Firefox) and I would like my program to use the process name (chrome.exe or firefox.exe) and then get their process ID.
I've found code that lets me get the process ID, but it requires a user to type the process name manually:
#include "pch.h"
#include <iostream>
#include <string>
#include <windows.h>
#include <tlhelp32.h>
DWORD FindProcessId(const std::wstring& processName);
int main()
{
std::wstring processName;
std::wcout << "Enter the process name: ";
std::getline(std::wcin, processName);
DWORD processID = FindProcessId(processName);
if (processID == 0)
std::wcout << "Could not find " << processName.c_str() << std::endl;
else
std::wcout << "Process ID is " << processID << std::endl;
system("PAUSE");
return 0;
}
DWORD FindProcessId(const std::wstring& processName)
{
PROCESSENTRY32 processInfo;
processInfo.dwSize = sizeof(processInfo);
HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (processesSnapshot == INVALID_HANDLE_VALUE)
return 0;
Process32First(processesSnapshot, &processInfo);
if (!processName.compare(processInfo.szExeFile))
{
CloseHandle(processesSnapshot);
return processInfo.th32ProcessID;
}
while (Process32Next(processesSnapshot, &processInfo))
{
if (!processName.compare(processInfo.szExeFile))
{
CloseHandle(processesSnapshot);
return processInfo.th32ProcessID;
}
}
CloseHandle(processesSnapshot);
return 0;
}
Now, is there a way to manipulate this code for it to get the process ID automatically by checking whether the user is running firefox.exe or chrome.exe?
And after getting the process ID, how do I make my program understand that it needs to focus on said ID?
Now, is there a way to manipulate this code for it to get the process ID automatically by checking whether the user is running firefox.exe or chrome.exe?
#include <iostream>
#include <string>
#include <windows.h>
#include <tlhelp32.h>
DWORD FindProcessId(const std::wstring& processName);
int main()
{
std::wstring fifi = L"firefox.exe";
std::wstring gogo = L"chrome.exe";
auto fifi_proc_id = FindProcessId(fifi);
auto gogo_proc_id = FindProcessId(gogo);
if(fifi_proc_id && gogo_proc_id) {
// both runnin O.O what now?
}
else if(fifi_proc_id) {
// firefox running ... do stuff
}
else if(gogo_proc_id) {
// chrome running ... do stuff
}
else {
// none of both :(
}
}
And after getting the process ID, how do I make my program understand that it needs to focus on said ID?
I am sorry, but I don't know what you mean by "make my program understand that it needs to focus on said ID".

IWbemLocator::ConnectServer (WMI) crashes in Windows 7

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.

'RegDeleteTree' not declared // Compilation error

I'm trying to delete a windows registry key and all its subkeys, specifically the 'Open with SHCP' key (which I created) and all its subkeys and values. I have the code, but it throws me this error:
'RegDeleteTree' was not declared in this scope
Code:
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
HKEY hKey;
cout << "Deleting Tree:\n\n";
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Classes\\*\\shell", 0, KEY_ALL_ACCESS, &hKey)== ERROR_SUCCESS)
{
cout << "Successfully opened key\n";
if(RegDeleteTree(hKey,"Open with SHCP") == ERROR_SUCCESS)
{
cout << "Successfully deleted the key\n";
}
else
{
cout << "Failed to delete the tree\n";
}
RegCloseKey(hKey);
}
else
{
cout << "Error, no tree available\n";
}
cin.get();
return 0;
}
I'm using Windows 7 and Dev-C++ 5.6.3.
Also, I'm able to use other functions like RegOpenKeyEx and RegCreateKeyEx.
What am I missing?
You need the SDK for Vista or later, and you need to set _WIN32_WINNT :
#define _WIN32_WINNT 0x0600
#include <Windows.h>
From the MSDN page for RegDeleteTree:
To compile an application that uses this function, define _WIN32_WINNT as 0x0600 or later. For more information, see Using the Windows Headers.

getting external media type

i would like to find a way detecting the type of the media in my optical drive (e.g. DVD+R, DVD-R, DVD-RW, CD+R, etc.) using a simple function in C++ on windows.
The function should not require Admin privilege.
EDIT
I implemented the following code:
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <imapi2.h>
#include <imapi2fs.h>
#include <imapi2error.h>
#include <imapi2fserror.h>
int main(int argc, char *argv[])
{
IDiscFormat2Data* discFormatData = NULL;
HRESULT hr;
CoInitialize ( NULL );
hr = CoCreateInstance( __uuidof(MsftDiscFormat2Data),
NULL,
CLSCTX_ALL,
__uuidof(IDiscFormat2Data),
(void**)&discFormatData);
if ( SUCCEEDED(hr) )
{
IMAPI_MEDIA_PHYSICAL_TYPE mediaType = IMAPI_MEDIA_TYPE_UNKNOWN;
hr = discFormatData->get_CurrentPhysicalMediaType(&mediaType);
if ( SUCCEEDED(hr) )
{
std::cout << "MediaPhysicalType: " << mediaType << std::endl;
}
else
{
std::stringstream str;
str << "get_CurrentPhysicalMediaType() failed with the error: 0x";
str << std::hex << hr << ".";
std::cout << str.str() << std::endl;
}
// Release the interface.
// Tell the COM object that we're done with it.
discFormatData->Release();
}
else
{
std::stringstream str;
str << "CoCreateInstance() failed with the error: 0x" << std::hex << hr;
std::cout << str.str() << std::endl;
}
cin.get();
return 0;
}
at the moment my problem is that i get the following error: E_IMAPI_RECORDER_REQUIRED which means
"The request requires a current disc recorder to be selected."
Assuming i have at least two optical drivers, how can i differ between them?
Any ideas?
On Windows 2000 and later, you can use IOCTL_CDROM_GET_CONFIGURATION with the SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT flag to query an optical device for its current profile, which will tell you which type of disc (CD, DVD+-R/W, HDDVD, BluRay, etc) has been inserted, if any. On earlier versions, you will have to manually send SCSI MMC commands directly to the device to query the same info.