Wrapping C++ Classes in a PHP Extension - c++

I m following the tutorial for wrapping c++ classes in a php extension.
I m using wamp server and php 5.4.16.
something going wrong in PHP_METHOD(Car, __construct).
It seems that after calling to
car_object *obj = ( car_object *) zend_object_store_get_object ( object TSRMLS_CC );
then obj ->car is not a valid address. when comment the line obj ->car = car, wamp is not shutting down. so i guess obj ->car is not valid or legal address.
bellow is my code:
vehicles.cc:
#include "php.h"
#include "car.h"
#define PHP_VEHICLES_EXTNAME "vehicles"
#define PHP_VEHICLES_EXTVER "0.1"
zend_object_handlers car_object_handlers;
struct car_object {
zend_object std;
Car *car;
};
zend_class_entry *car_ce;
void car_free_storage(void *object TSRMLS_DC)
{
car_object *obj = (car_object *)object;
delete obj->car;
zend_hash_destroy(obj->std.properties);
FREE_HASHTABLE(obj->std.properties);
delete obj->car;
efree(obj);
}
zend_object_value car_create_handler(zend_class_entry *type TSRMLS_DC)
{
zend_object_value retval;
car_object *obj = (car_object *)emalloc(sizeof(car_object));
memset(obj, 0, sizeof(car_object));
obj->std.ce = type;
ALLOC_HASHTABLE(obj->std.properties);
zend_hash_init(obj->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
#if PHP_VERSION_ID < 50399
zval *tmp;
zend_hash_copy(obj->std.properties, &type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *)&tmp, sizeof(zval *));
#else
object_properties_init(&(obj->std), type);
#endif
retval.handle = zend_objects_store_put(obj, NULL, car_free_storage, NULL TSRMLS_CC);
retval.handlers = &car_object_handlers;
return retval;
}
PHP_METHOD(Car, __construct)
{
long maxGear;
Car *car = NULL;
zval *object = getThis();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &maxGear) == FAILURE) {
RETURN_NULL();
}
car = new Car(maxGear);
car_object *obj = ( car_object *) zend_object_store_get_object(object TSRMLS_CC );
//obj->car = car;
}
...
...
zend_function_entry car_methods[] = {
PHP_ME(Car, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
PHP_ME(Car, shift, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Car, accelerate, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Car, brake, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Car, getCurrentSpeed, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Car, getCurrentGear, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
PHP_MINIT_FUNCTION(vehicles)
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "Car", car_methods);
car_ce = zend_register_internal_class(&ce TSRMLS_CC);
car_ce->create_object = car_create_handler;
memcpy(&car_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
car_object_handlers.clone_obj = NULL;
return SUCCESS;
}
zend_module_entry vehicles_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_VEHICLES_EXTNAME,
NULL, /* Functions */
PHP_MINIT(vehicles),
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
NULL, /* MINFO */
#if ZEND_MODULE_API_NO >= 20010901
PHP_VEHICLES_EXTVER,
#endif
STANDARD_MODULE_PROPERTIES
};
ZEND_GET_MODULE ( vehicles );
car.h car.cc are the same as in the tutorial.
I guess that I'm missing something. maybe the call for "object_properties_init(&(obj->std), type);" in function car_create_handler is not correct..
thanks for your help/.

It seems that in your function car_free_storage, you are calling delete obj->car twice. This might not be a good idea.
Furthermore, when I was recently looking around another php module, I discovered that obj->std.properties is not always set to a valid address. So it might be worth checking if it isn't 0 before passing it to zend_hash_destroy. My code for this was:
if(obj->std.properties){
zend_hash_destroy(obj->std.properties);
FREE_HASHTABLE(obj->std.properties);
}

Related

I get a read access violation **vf** was nullptr (LibVorbis)

I'm getting a read access violation somewhere I say there is something pointing to null I am currently using XAudio2.9 and Libvorbis 1.3.7. I edited this to be more informative this is all of it I hope you guys can find the issue with this I'm new to messing with sound in C++ and been trying to learn how to use this for months now I have some trouble understanding things like this.
#include <xaudio2redist/xaudio2.h>
#include <fileapi.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
#define STREAMING_BUFFER_SIZE 4096
#define MAX_BUFFER_COUNT 4
class SoundDevice
{
public:
bool audio_init();
bool audio_load(const char* filename);
bool play();
bool audio_clean();
private:
IXAudio2* Audio = nullptr;
IXAudio2MasteringVoice* Masteringvoice = nullptr;
IXAudio2SourceVoice* Sourcevoice = nullptr;
WAVEFORMATEX formatex;
XAUDIO2_BUFFER buffer = { 0 };
XAUDIO2_VOICE_STATE state;
HRESULT hr;
// LibVorbis
HANDLE vorbishandle;
OggVorbis_File* vorbisfile;
vorbis_info* vorbisinfo;
char buffers[MAX_BUFFER_COUNT][STREAMING_BUFFER_SIZE];
int sec = 0; // section
DWORD pos = 0; // position
int ret = 0; // return
DWORD currentDiskReadBuffer = 0;
};
bool SoundDevice::audio_init()
{
hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
MessageBoxA(0, "Failed to CoInitialize", "Error:", hr);
return false;
}
if (FAILED(hr = XAudio2Create(&Audio, 0, XAUDIO2_DEFAULT_PROCESSOR)))
{
MessageBoxA(0, "Failed to create XAudio2", "Error:", hr);
return false;
}
if (FAILED(hr = Audio->CreateMasteringVoice(&Masteringvoice, XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_SAMPLERATE, 0, 0, 0)))
{
MessageBoxA(0, "Failed to create Mastering Voice", "Error:", hr);
return false;
}
vorbisinfo = ov_info(vorbisfile, -1);
ZeroMemory(&formatex, sizeof(WAVEFORMATEX));
formatex.wFormatTag = 1;
formatex.nChannels = 2;
formatex.nSamplesPerSec = 44100;
formatex.nAvgBytesPerSec = formatex.nChannels * formatex.nSamplesPerSec * 2;
formatex.nBlockAlign = formatex.nChannels * 2;
formatex.wBitsPerSample = 16;
formatex.cbSize = sizeof(formatex);
ZeroMemory(&buffers[currentDiskReadBuffer], sizeof(DWORD));
buffer.pAudioData = reinterpret_cast<BYTE*>(&buffers[currentDiskReadBuffer]);
buffer.AudioBytes = STREAMING_BUFFER_SIZE;
buffer.Flags = XAUDIO2_END_OF_STREAM;
if (FAILED(hr = Audio->CreateSourceVoice(&Sourcevoice, &formatex, 0, 2.0f, 0, 0, 0)))
{
MessageBoxA(0, "Failed to create Source Voice", "Error:", hr);
return hr;
}
return 0;
}
bool SoundDevice::audio_load(const char* filename)
{
vorbishandle = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, FILE_SHARE_READ, FILE_ATTRIBUTE_NORMAL, vorbishandle);
if (ov_open_callbacks(vorbishandle, vorbisfile, nullptr, 0, OV_CALLBACKS_DEFAULT))
{
CloseHandle(vorbishandle);
return false;
}
while (ret && pos < STREAMING_BUFFER_SIZE)
{
ret = ov_read(vorbisfile, buffers[currentDiskReadBuffer] + pos, STREAMING_BUFFER_SIZE - pos, 0, 2, 1, &sec);
pos += ret;
}
return hr;
}
bool SoundDevice::play()
{
hr = Sourcevoice->SubmitSourceBuffer(&buffer, 0);
hr = Sourcevoice->Start();
return hr;
}
bool SoundDevice::audio_clean()
{
Sourcevoice->Stop(0);
Sourcevoice->FlushSourceBuffers();
Sourcevoice->DestroyVoice();
return hr;
}
I can't seem to find the problem for a few reasons, mainly because I can't see your error message. But also, a tip I can give you is to indent your code properly, for example you could indent everything inside of the class by a tab or a few spaces, it doesn't really matter which as long as it is consistent. Speaking from experience, I found it easier to read my code when I started to indent the code inside definitions like public or private and protected. Just a simple piece of advice to help debugging in general. (Keep in mind, this is my first answer ever so please be nice but don't be afraid to give tips.)

Visual Studio: Getting all certificate issuer details from executable

I want to be able to get all the issuer data that you can get from Windows Explorer like here:
I've been able to get CN from https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certgetnamestringw, but I don't know what it is about that call that targets the CN (if I did, I might be able to figure how to get everything else). I've tried Googling things like "api wintrust issuer CommonName Organization" and "wincrypt organization commonname" but it's like the API washes its hands of all the other issuer data.
You only need to use CertNameToStr and set the &(pCertContext->pCertInfo->Issuer) parameter:
CertNameToStr(
pCertContext->dwCertEncodingType,
&(pCertContext->pCertInfo->Issuer),
CERT_X500_NAME_STR,
pszString,
cbSize);
I modified the official sample for your reference:
#pragma comment(lib, "crypt32.lib")
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <Wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define MY_STRING_TYPE (CERT_OID_NAME_STR)
void MyHandleError(LPTSTR);
void main(void)
{
HCERTSTORE hCertStore;
PCCERT_CONTEXT pCertContext;
if (!(hCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
MY_ENCODING_TYPE,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"MY")))
{
MyHandleError(TEXT("The MY system store did not open."));
}
pCertContext = NULL;
while (pCertContext = CertEnumCertificatesInStore(
hCertStore,
pCertContext))
{
LPTSTR pszString;
LPTSTR pszName;
DWORD cbSize;
CERT_BLOB blobEncodedName;
if (!(cbSize = CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
NULL,
0)))
{
MyHandleError(TEXT("CertGetName 1 failed."));
}
if (!(pszName = (LPTSTR)malloc(cbSize * sizeof(TCHAR))))
{
MyHandleError(TEXT("Memory allocation failed."));
}
if (CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pszName,
cbSize))
{
_tprintf(TEXT("\nSubject -> %s.\n"), pszName);
free(pszName);
}
else
{
MyHandleError(TEXT("CertGetName failed."));
}
if (!(cbSize = CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
NULL,
0)))
{
MyHandleError(TEXT("CertGetName 1 failed."));
}
if (!(pszName = (LPTSTR)malloc(cbSize * sizeof(TCHAR))))
{
MyHandleError(TEXT("Memory allocation failed."));
}
if (CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
pszName,
cbSize))
{
_tprintf(TEXT("Issuer -> %s.\n"), pszName);
free(pszName);
}
else
{
MyHandleError(TEXT("CertGetName failed."));
}
cbSize = CertNameToStr(
pCertContext->dwCertEncodingType,
&(pCertContext->pCertInfo->Subject),
MY_STRING_TYPE,
NULL,
0);
if (1 == cbSize)
{
MyHandleError(TEXT("Subject name is an empty string."));
}
if (!(pszString = (LPTSTR)malloc(cbSize * sizeof(TCHAR))))
{
MyHandleError(TEXT("Memory allocation failed."));
}
cbSize = CertNameToStr(
pCertContext->dwCertEncodingType,
&(pCertContext->pCertInfo->Issuer),
CERT_X500_NAME_STR,
pszString,
cbSize);
if (1 == cbSize)
{
MyHandleError(TEXT("Issuer name is an empty string."));
}
else
{
printf("Issuer String = %ls\n", pszString); //what you want
}
if (!(CertStrToName(
MY_ENCODING_TYPE,
pszString,
MY_STRING_TYPE,
NULL,
NULL, // NULL to get the number of bytes
// needed for the buffer.
&cbSize, // Pointer to a DWORD to hold the
// number of bytes needed for the
// buffer
NULL))) // Optional address of a pointer to
// old the location for an error in the
// input string.
{
MyHandleError(
TEXT("Could not get the length of the BLOB."));
}
if (!(blobEncodedName.pbData = (LPBYTE)malloc(cbSize)))
{
MyHandleError(
TEXT("Memory Allocation for the BLOB failed."));
}
blobEncodedName.cbData = cbSize;
if (CertStrToName(
MY_ENCODING_TYPE,
pszString,
MY_STRING_TYPE,
NULL,
blobEncodedName.pbData,
&blobEncodedName.cbData,
NULL))
{
_tprintf(TEXT("CertStrToName created the BLOB.\n"));
}
else
{
MyHandleError(TEXT("Could not create the BLOB."));
}
free(blobEncodedName.pbData);
free(pszString);
}
_tprintf(
TEXT("\nThere are no more certificates in the store. \n"));
if (CertCloseStore(
hCertStore,
CERT_CLOSE_STORE_CHECK_FLAG))
{
_tprintf(TEXT("The store is closed. ")
TEXT("All certificates are released.\n"));
}
else
{
_tprintf(TEXT("The store was closed, ")
TEXT("but certificates still in use.\n"));
}
_tprintf(TEXT("This demonstration program ran to completion ")
TEXT("without error.\n"));
}
void MyHandleError(LPTSTR psz)
{
_ftprintf(stderr,
TEXT("An error occurred in running the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
_ftprintf(stderr, TEXT("Program terminating. \n"));
exit(1);
}

C++ MapViewOfFile fails

I am trying to memory-map a file on Windows using VS2010.
I am doing this in a DLL.
The first instance of the DLL maps the file just fine.
The second instance within the same process causes
*ppvData = ::MapViewOfFile( *phMapping, FILE_MAP_READ, 0, 0, 0 );
to fail with the error "Not enough memory available for this command".
I am not sure why this happens.
If I map 2 different files instead of twice the same file, all works fine, so I don't trust the "Not enough memory" error message.
Thank you.
hr = MapFile(sPath, &m_hVoiceData, &m_pVoiceData,wsErr );
HRESULT CTTSEngObj::MapFile( wstring uPath, // Value that contains file path
HANDLE * phMapping, // Pointer to file mapping handle
void ** ppvData, // Pointer to the data
wstring &uError)
{
HRESULT hr = S_OK;
CSpDynamicString dstrFilePath(uPath.c_str());
if ( SUCCEEDED( hr ) )
{
bool fWorked = false;
*phMapping = NULL;
*ppvData = NULL;
HANDLE hFile;
#ifdef _WIN32_WCE
hFile = CreateFileForMapping( dstrFilePath, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL );
#else
hFile = CreateFile(CW2T(dstrFilePath), GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL );
#endif
if (hFile != INVALID_HANDLE_VALUE)
{
*phMapping = ::CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
if (*phMapping)
{
*ppvData = ::MapViewOfFile( *phMapping, FILE_MAP_READ, 0, 0, 0 );
if (*ppvData)
{
fWorked = true;
}
else
{
uError=GetLastErrorStdStrW();
}
}
else
{
uError=L"mapfile: fm failed";
}
::CloseHandle( hFile );
}
else
{
uError=L"mapfile: invalidhandle";
}
if (!fWorked)
{
hr = HRESULT_FROM_WIN32(::GetLastError());
if (*phMapping)
{
::CloseHandle(*phMapping);
*phMapping = NULL;
}
}
}
else
{
uError=L"mapfile: dynstr";
}
return hr;
} /* CTTSEngObj::MapFile */
And this is how it is declared:
class ATL_NO_VTABLE CTTSEngObj :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CTTSEngObj, &CLSID_SampleTTSEngine>,
public ISpTTSEngine,
public ISpObjectWithToken
{
private:
CComPtr<ISpObjectToken> m_cpToken;
HANDLE m_hVoiceData;
void* m_pVoiceData;
You request to map the entire file into memory. How big is it? There may very well not be a large enough contiguous range of unallocated process's address space.

Get battery device name

I am trying to get the names of all the battery devices on my computer using this code mostly acquired from a Microsoft tutorial but it isn't working.
#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);
}
i am trying to print the names of all the batteries, but when i run the program it doesnt print anything at all, it does however work when i request a battery_information structure instead of the string BatteryDeviceName please help
The problem is that in your call to DeviceIoControl is wrong. You are passing in garbage, and when you put garbage in you get garbage out.
string bi;
if(DeviceIoControl(hBattery,
IOCTL_BATTERY_QUERY_INFORMATION,
bqi,
sizeof(bqi),
&bi, // Really?!?!?!
sizeof(bi), // WHAT?!?
&dwOut,
NULL))
You are passing the address a std::string object to DeviceIoControl, which knows nothing about std::string and expects the adress of a raw buffer that it can write to. You at least specify the right size for that buffer, but even that is wrong in a sense. Basically, when that function returns, that std::string is junk and accessing it could do just about anything - from crashing the program to playing Vivaldi on your speakers.
Try something like this:
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))

How to get computer manufacturer and model from windows registry in C++?

I am writing my own C++ code to read the computer model and manufacturer on a Windows computer by reading and parsing the registry key
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/services/mssmbios/Data/SMBiosData
Is there any library function in Windows / C++ / Visual Studio that allows me to get this information directly?
The steps you need are explained on Creating a WMI Application Using C++. MSDN even includes a sample program. You just need to change two strings.
Change SELECT * FROM Win32_Process to SELECT * FROM Win32_ComputerSystem
Change Name to Manufacturer and then again for Model.
With the help of the Microsoft example code, I was able to create this method.
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
std::pair<CString,CString> getComputerManufacturerAndModel() {
// Obtain the initial locator to Windows Management on a particular host computer.
IWbemLocator *locator = nullptr;
IWbemServices *services = nullptr;
auto hResult = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&locator);
auto hasFailed = [&hResult]() {
if (FAILED(hResult)) {
auto error = _com_error(hResult);
TRACE(error.ErrorMessage());
TRACE(error.Description().Detach());
return true;
}
return false;
};
auto getValue = [&hResult, &hasFailed](IWbemClassObject *classObject, LPCWSTR property) {
CString propertyValueText = "Not set";
VARIANT propertyValue;
hResult = classObject->Get(property, 0, &propertyValue, 0, 0);
if (!hasFailed()) {
if ((propertyValue.vt == VT_NULL) || (propertyValue.vt == VT_EMPTY)) {
} else if (propertyValue.vt & VT_ARRAY) {
propertyValueText = "Unknown"; //Array types not supported
} else {
propertyValueText = propertyValue.bstrVal;
}
}
VariantClear(&propertyValue);
return propertyValueText;
};
CString manufacturer = "Not set";
CString model = "Not set";
if (!hasFailed()) {
// Connect to the root\cimv2 namespace with the current user and obtain pointer pSvc to make IWbemServices calls.
hResult = locator->ConnectServer(L"ROOT\\CIMV2", nullptr, nullptr, 0, NULL, 0, 0, &services);
if (!hasFailed()) {
// Set the IWbemServices proxy so that impersonation of the user (client) occurs.
hResult = CoSetProxyBlanket(services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE);
if (!hasFailed()) {
IEnumWbemClassObject* classObjectEnumerator = nullptr;
hResult = services->ExecQuery(L"WQL", L"SELECT * FROM Win32_ComputerSystem", WBEM_FLAG_FORWARD_ONLY |
WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, &classObjectEnumerator);
if (!hasFailed()) {
IWbemClassObject *classObject;
ULONG uReturn = 0;
hResult = classObjectEnumerator->Next(WBEM_INFINITE, 1, &classObject, &uReturn);
if (uReturn != 0) {
manufacturer = getValue(classObject, (LPCWSTR)L"Manufacturer");
model = getValue(classObject, (LPCWSTR)L"Model");
}
classObject->Release();
}
classObjectEnumerator->Release();
}
}
}
if (locator) {
locator->Release();
}
if (services) {
services->Release();
}
CoUninitialize();
return { manufacturer, model };
}