Visual C++, Windows Update Interface (IUpdate) <wuapi.h>, get_MsrcSeverity - c++

I'm probably just blind, but I cannot see any errors here (and I am looking on this issue already for days now...)
I am trying to get the Patch Priority (Severity) from the Windows Update Interface using the following piece of code in Visual Studio:
#include "stdafx.h"
#include <wuapi.h>
#include <iostream>
#include <ATLComTime.h>
#include <wuerror.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr;
hr = CoInitialize(NULL);
IUpdateSession* iUpdate;
IUpdateSearcher* searcher;
ISearchResult* results;
BSTR criteria = SysAllocString(L"IsInstalled=0");
hr = CoCreateInstance(CLSID_UpdateSession, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateSession, (LPVOID*)&iUpdate);
hr = iUpdate->CreateUpdateSearcher(&searcher);
wcout << L"Searching for updates ..."<<endl;
hr = searcher->Search(criteria, &results);
SysFreeString(criteria);
switch(hr)
{
case S_OK:
wcout<<L"List of applicable items on the machine:"<<endl;
break;
case WU_E_LEGACYSERVER:
wcout<<L"No server selection enabled"<<endl;
return 0;
case WU_E_INVALID_CRITERIA:
wcout<<L"Invalid search criteria"<<endl;
return 0;
}
IUpdateCollection *updateList;
IUpdateCollection *bundledUpdates;
IUpdate *updateItem;
IUpdate *bundledUpdateItem;
LONG updateSize;
LONG bundledUpdateSize;
BSTR updateName;
BSTR severity;
results->get_Updates(&updateList);
updateList->get_Count(&updateSize);
if (updateSize == 0)
{
wcout << L"No updates found"<<endl;
}
for (LONG i = 0; i < updateSize; i++)
{
updateList->get_Item(i,&updateItem);
updateItem->get_Title(&updateName);
severity = NULL;
updateItem->get_MsrcSeverity(&severity);
if (severity != NULL)
{
wcout << L"update severity: " << severity << endl;
}
wcout<<i+1<<" - " << updateName << endl;
// bundled updates
updateItem->get_BundledUpdates(&bundledUpdates);
bundledUpdates->get_Count(&bundledUpdateSize);
if (bundledUpdateSize != 0)
{
// iterate through bundled updates
for (LONG ii = 0; ii < bundledUpdateSize; ii++)
{
bundledUpdates->get_Item(ii, &bundledUpdateItem);
severity = NULL;
bundledUpdateItem->get_MsrcSeverity(&severity);
if (severity != NULL)
{
wcout << L" bundled update severity: " << severity << endl;
}
}
}
}
::CoUninitialize();
wcin.get();
return 0;
}
So here's the issue: updateItem->get_MsrcSeverity(&severity); is not returning anything. If I catch the result code with an HRESULT it always returns S_OK.
Link to MSDN IUpdate MsrcSeverity: http://msdn.microsoft.com/en-us/library/windows/desktop/aa386906(v=vs.85).aspx
Can you see what I am doing obviously wrong or is the get_MsrcSeverity function currently broken?
#EDIT: Changed the code to iterate through "BundledUpdates" as suggested.
#EDIT2: the code now outputs the severity value of the updateItem as well as the bundledUpdatesItem, but it's always NULL.
I also know there is one important update waiting for my computer - regarding to Windows Update in the control panel. It is KB2858725.
#EDIT3: Okay, it turns out, KB2858725 is no security update and therefore has no severity rating by Microsoft. But how does Microsoft Windows Update now categorize the updates in "important" and "optional" like you can see it in control panel's update?
Thank you for any hints!
// Markus

I've been struggling with the exact same problem for hours now... I finally figured out that Microsoft only seems to set the MsrcSeverity value on some updates. For general Windows updates, it's usually null. For most security updates it's set to one of:
"Critical"
"Moderate"
"Important"
"Low"
It seems as though the "Unspecified" value is never used, though it is documented in MSDN (http://msdn.microsoft.com/en-us/library/microsoft.updateservices.administration.msrcseverity(v=vs.85).aspx).
I wrote a small C# program to list all available updates and their reported severity. It requires a reference to WUApiLib:
using System;
using WUApiLib;
namespace EnumerateUpdates
{
class Program
{
static void Main(string[] args)
{
var session = new UpdateSession();
var searcher = session.CreateUpdateSearcher();
searcher.Online = false;
// Find all updates that have not yet been installed
var result = searcher.Search("IsInstalled=0 And IsHidden=0");
foreach (dynamic update in result.Updates)
{
Console.WriteLine(update.Title + ": " + update.Description);
Console.WriteLine("Severity is " + update.MsrcSeverity);
Console.WriteLine();
}
Console.ReadLine();
}
}
}
Hope this helps someone!

Look for bundled updates in the list. The bundled updates does not have some properties or methods as described on this page.
Remarks
If the BundledUpdates property contains an IUpdateCollection, some
properties and methods of the update may only be available on the
bundled updates, for example, DownloadContents or CopyFromCache.
The update you are processing in is a bundled update. Extract the individual updates from this bundle, it will have the property you are looking out for.
The IUpdate interface has a method get_BundledUpdates which gets you a IUpdateCollection if the size of this collection is greater then 0, this is a bundled update.

Related

How to get a human readable process name (like in the task manager) via Win32 API? [duplicate]

I want to get the description of a process (the description that is seen in task manager) in Windows using C++.
You most likely want to get the FileDesription field from the version resources of the main .exe file of the program, using the VerQueryValue() API call. Here is an example from that document:
The following example shows how to enumerate the available version languages and retrieve the FileDescription string-value for each language.
Be sure to call the GetFileVersionInfoSize and GetFileVersionInfo functions before calling VerQueryValue to properly initialize the pBlock buffer.
// Structure used to store enumerated languages and code pages.
HRESULT hr;
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
// Read the list of languages and code pages.
VerQueryValue(pBlock,
TEXT("\\VarFileInfo\\Translation"),
(LPVOID*)&lpTranslate,
&cbTranslate);
// Read the file description for each language and code page.
for( i=0; i < (cbTranslate/sizeof(struct LANGANDCODEPAGE)); i++ )
{
hr = StringCchPrintf(SubBlock, 50,
TEXT("\\StringFileInfo\\%04x%04x\\FileDescription"),
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
if (FAILED(hr))
{
// TODO: write error handler.
}
// Retrieve file description for language and code page "i".
VerQueryValue(pBlock,
SubBlock,
&lpBuffer,
&dwBytes);
}
Although I read this question, the accepted answer, and the documentation for VerQueryValue, I spent quite a while to understand how to use that VerQueryValue function (since the code example in the docs has no declarations of variables and isn't clear for me at all).
So I decided to put here the code that can be easily run as a working example of the usage of VerQueryValue to get a process description.
#pragma comment(lib,"Version.lib")
#include <iostream>
#include <windows.h>
#include <winver.h>
using namespace std;
int printFileDescriptions(const wchar_t* filename)
{
int versionInfoSize = GetFileVersionInfoSize(filename, NULL);
if (!versionInfoSize) {
return 0;
}
auto versionInfo = new BYTE[versionInfoSize];
std::unique_ptr<BYTE[]> versionInfo_automatic_cleanup(versionInfo);
if (!GetFileVersionInfo(filename, NULL, versionInfoSize, versionInfo)) {
return 0;
}
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *translationArray;
UINT translationArrayByteLength = 0;
if (!VerQueryValue(versionInfo, L"\\VarFileInfo\\Translation", (LPVOID*)&translationArray, &translationArrayByteLength)) {
return 0;
}
// You may check GetSystemDefaultUILanguage() == translationArray[i].wLanguage
// if only the system language required
for (unsigned int i = 0; i < (translationArrayByteLength / sizeof(LANGANDCODEPAGE)); i++) {
wchar_t fileDescriptionKey[256];
wsprintf(
fileDescriptionKey,
L"\\StringFileInfo\\%04x%04x\\FileDescription",
translationArray[i].wLanguage,
translationArray[i].wCodePage
);
wchar_t* fileDescription = NULL;
UINT fileDescriptionSize;
if (VerQueryValue(versionInfo, fileDescriptionKey, (LPVOID*)&fileDescription, &fileDescriptionSize)) {
wcout << endl << fileDescription << endl;
}
}
return TRUE;
}
int main()
{
// Set locale of the console to print non-ASCII symbols
SetConsoleOutputCP(GetACP());
SetConsoleCP(GetACP());
wcout.imbue(std::locale("")); // set default global locale
// ----------------------------------------------------
auto path = L"C:\\Windows\\explorer.exe";
printFileDescriptions(path);
wcin.get(); // to prevent console close
}
It's supposed that all WinAPI functions on your system use wchar_t, that is VerQueryValueW is actually used.
The initial version of the code I took here Retrieve File Description an Application VerQueryValue

C++ code: Logical error in finding the Kinect sensor

I want to get depth and RGB data from Kinect V2 by Windows SDK 2.0 in Viual Studio 2013. So I write these codes:
#include <Kinect.h>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <Windows.h>
#include <iostream>
using namespace std;
const int width = 512;
const int height = 424;
const int colorwidth = 1920;
const int colorheight = 1080;
// Kinect Variables
IKinectSensor* sensor; // Kinect sensor
IMultiSourceFrameReader* reader; // Kinect data source
ICoordinateMapper* mapper;
int main(int argc, char* argv[]) {
if (FAILED(GetDefaultKinectSensor(&sensor))) {
printf("not found sensor");
getchar();
return -100;
}
if (sensor) {
sensor->get_CoordinateMapper(&mapper);
sensor->Open();
sensor->OpenMultiSourceFrameReader(
FrameSourceTypes::FrameSourceTypes_Depth | FrameSourceTypes::FrameSourceTypes_Color,
&reader);
IMultiSourceFrame* framesource;
cout << "Find!!!";
getchar();
return 100;
}
else {
return -100;
}
getchar();
return 10;
}
Logically, when I do not plug Kinect sensor to my Laptop, in Console should be printed: "not found sensor",isn't it? But, in console printed: "Find!!!". what is the problem?
No, Since SDK v2, You can debug an application by using KinectStudio, even without a physical kinect is connected to the system. If you want to check whether the actual Kinect is connected, you need to use IsAvailable property of the sensor itself. GetDefaultKinectSensor will always give you S_OK unless you have runtime or installation issues. GetDefaultKinectSensor won't check whether is this stream comes from actual physical kinect sensor or from KinectStudio.
The following is a code snippet from my project. If you want more examples about Kinect, please refer my project in github https://github.com/shanilfernando/VRInteraction or comment here. I'm more than happy to help you.
HRESULT CDepthBasics::InitializeDefaultSensor()
{
HRESULT hr;
hr = GetDefaultKinectSensor(&m_pKinectSensor);
if (FAILED(hr))
{
return hr;
}
if (m_pKinectSensor)
{
if (SUCCEEDED(hr))
{
hr = m_pKinectSensor->get_CoordinateMapper(&m_pCoordinateMapper);
}
if (SUCCEEDED(hr))
{
hr = m_pKinectSensor->Open();
}
if (SUCCEEDED(hr))
{
hr = m_pKinectSensor->OpenMultiSourceFrameReader(
FrameSourceTypes::FrameSourceTypes_Depth | FrameSourceTypes::FrameSourceTypes_Color | FrameSourceTypes::FrameSourceTypes_Body | FrameSourceTypes::FrameSourceTypes_BodyIndex,
&m_pMultiSourceFrameReader);
}
}
if (!m_pKinectSensor || FAILED(hr))
{
std::cout << "No ready Kinect found!" << std::endl;
return E_FAIL;
}
else
{
std::cout << "Kinect found!" << std::endl;
}
return hr;
}
https://github.com/shanilfernando/VRInteraction/blob/master/DepthBasics.cpp
Edit
I didn't use IsAvailable since it doesn't matter for me where that stream comes from. Sometimes I used KinectStudio to get the streams while Kinect is not with me. I said GetDefaultKinectSensor will return S_OK unless you have runtime or installation issues, I did NOT said GetDefaultKinectSensor will always give you a valid m_pKinectSensor. Since we don't have access to the implementation of the GetDefaultKinectSensor and as a good practice, it is better to check it null or not before using it. This is the official answer for your question from the Microsoft

get_accChildCount returns 0 when it shouldn't

I'm trying to enumerate tabs of IE from an extension and from a standalone application. For one of the MSAA nodes get_accChildCount returns 0 when called from extension, while it should return 1 according to inspect and a call from standalone application.
The problem was described previously at StackOverflow, yet it was solved via a hack that doesn't work for me. /clr and /MT are incompatible.
Also there was a topic on MSDN with the same issue. There's no single answer there.
If you run IE with administrator privileges, it works properly.
API Monitor shows several thousand calls in a minimal example, and it's unclear which of these are related. The minimal example is attached below.
What are the undocumented cases when get_accChildCount returns wrong child count?
What other method could I use to activate the tab by URL in most versions of IE?
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
#include <atltypes.h>
#include <atlsafe.h>
#include <io.h>
#include <fcntl.h>
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <boost/format.hpp>
#include <fstream>
using namespace std;
CComPtr<IAccessible> get_acc_by_hwnd(HWND hwnd) {
CComPtr<IAccessible> ret;
HRESULT hr = ::AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void**) &ret);
if (FAILED(hr) || !ret) {
wcout << L"Accessible::Accessible invalid hwnd" << endl;
}
return ret;
}
std::vector<CComPtr<IAccessible>> get_acc_children(CComPtr<IAccessible> acc) {
std::vector<CComPtr<IAccessible>> ret;
long count;
if (FAILED(acc->get_accChildCount(&count))) return ret;
long count_obtained = 0;
if (!count) return ret;
std::vector<CComVariant> accessors(count);
if (FAILED(::AccessibleChildren(acc, 0, count, &*accessors.begin(), &count_obtained))) return ret;
accessors.resize(count_obtained);
for (auto vtChild : accessors) {
if (vtChild.vt != VT_DISPATCH) continue;
CComQIPtr<IAccessible> pChild = vtChild.pdispVal;
if (pChild) ret.push_back(pChild);
}
return ret;
}
bool is_client(CComPtr<IAccessible> acc) {
CComVariant var;
HRESULT hr = acc->get_accRole(CComVariant(CHILDID_SELF), &var);
return SUCCEEDED(hr) && var.vt == VT_I4 && var.lVal == 0xA;
}
std::wstring get_descr(CComPtr<IAccessible> acc) {
CComBSTR str;
HRESULT hr = acc->get_accDescription(CComVariant(CHILDID_SELF), &str);
return SUCCEEDED(hr) && str ? std::wstring(str) : L"";
}
int main() {
::CoInitialize(nullptr);
_setmode(_fileno(stdout), _O_U16TEXT);
// put HWND of the window that contains tab labels
// it's hardcoded to minimize quantity of API calls
HWND hwnd = reinterpret_cast<HWND>(0x002D0696);
CComPtr<IAccessible> iaccessible;
HRESULT hr = ::AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void**) &iaccessible);
if (FAILED(hr) || !iaccessible) {
wcout << L"AccessibleBrowser::activate_tab " L"failed to get IAccessible for IE" << endl;
return EXIT_FAILURE;
}
wstring const sentinel = L"\r\n";
for (auto child : get_acc_children(iaccessible)) if (is_client(child)) {
for (auto child1 : get_acc_children(child)) { // fails here in extension
for (auto child2 : get_acc_children(child1)) {
std::wstring descr = get_descr(child2);
auto pos = descr.find(sentinel);
if (pos == string::npos) continue;
auto tab_url = descr.substr(pos + sentinel.size());
wcout << tab_url << endl;
}
}
}
}
I poked at your program for a while without having much to show for it. Perhaps I realized too late that it was not supposed to reproduce the problem :( I can only provide some possibly helpful hints to get you to look under the right kind of rock.
yet it was solved via a hack that doesn't work for me
These programmers made a simple mistake, they forgot to call CoInitialize/Ex(). A very common oversight. Using the /clr build option works around that mistake because it is now the CLR that calls it. You can easily repro this mishap, just comment out the CoInitialize() call. Unfortunately it works for a while without any loud errors being produced, but you do get 0 for certain accobjects. You'll notice your program no longer finds the tabs.
Not so sure I can cleanly explain this, certain COM-style object models don't actually use the COM infrastructure. DirectX is the best example, we can add UIAutomation to that list. I assume it will silently fail like this when the client app's component is COM-based. Unclear if it is, DirectUIHWnd is quite undocumented.
So stop looking for that as a workaround, you did not forget to call CoInitialize() and it will be taken care of by IE before it activates your extension.
If you run IE with administrator privileges, it works properly.
That's a better rock. Many programmers run VS elevated all the time, the roles might be reversed in the case of UIA. Do keep in mind that your extension runs in a sandbox inside IE. No real idea how elevating IE affects this. One thing you cannot do from code running in the low-integrity sandbox is poke at UI components owned by a code that runs in a higher integrity mode. Google "disable IE enhanced protected mode" and follow the guideline to see what effect that has on your addin.

CLR ICLRControl::GetCLRManager fails with error HOST_E_INVALIDOPERATION

I have a native process which uses .NET component via COM interop. Once the process is up, I am trying to get interface pointers to the various CLR managers such as ICLRDebugManager, ICLRGCManager, etc. using the ICLRControl interface pointer. I'm able to reach up to acquiring ICLRControl interface without a glitch. ICLRRuntimeInfo also correctly tells me that it is 4.0.x .net version when I call GetVersionString on it.
It is only that the ICLRControl::GetCLRManager keeps failing with error 0x80130122, which error code stands for HOST_E_INVALIDOPERATION. Searched the internet, but could not get information as to why this might be failing. Any help is much appreciated.
TIA.
WinCPP
Edit 1. Adding code snippet.
// ICLRRuntimeInfo interface pointer
CComQIPtr<ICLRRuntimeInfo> pCLRRuntimeInfo = pUnk;
if (!pCLRRuntimeInfo)
{
cout << "failed to get run time info interface pointer" << endl;
return;
}
TCHAR version[128];
memset(version, 0, 128);
DWORD count = 127;
pCLRRuntimeInfo->GetVersionString(version, &count);
cout << version << endl;
// ICLRRuntimeHost
CComPtr<ICLRRuntimeHost> pCLRRuntimeHost = 0;
hr = pCLRRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID *)&pCLRRuntimeHost);
if (FAILED(hr))
{
cout << "failed to get run time host interface pointer" << endl;
return;
}
// ICLRControl
CComPtr<ICLRControl> pCLRControl = 0;
hr = pCLRRuntimeHost->GetCLRControl(&pCLRControl);
if (FAILED(hr))
{
cout << "failed to get clr control interface pointer" << endl;
return;
}
///////////////////////////////////////////
// Everything is successful upto this point
///////////////////////////////////////////
// ICLRGCManager
CComPtr<ICLRGCManager> pCLRGCManager = 0;
hr = pCLRControl->GetCLRManager(IID_ICLRGCManager, (LPVOID *)&pCLRGCManager);
if (FAILED(hr))
{
cout << "failed to get GC manager interface pointer" << endl;
return;
}
// Above call fails with the error 0x81031022, though everything is as per the MSDN documentation for the API
Looking at this source code on GitHub, it looks like CCorCLRControl::GetCLRManager will return HOST_E_INVALIDOPERATION if the runtime has already been started.
This explains why you are receiving that error code when attempting to "latch on to already loaded CLR instance," but that you meet with success when you create a CLR instance explicitly.

How to get process description?

I want to get the description of a process (the description that is seen in task manager) in Windows using C++.
You most likely want to get the FileDesription field from the version resources of the main .exe file of the program, using the VerQueryValue() API call. Here is an example from that document:
The following example shows how to enumerate the available version languages and retrieve the FileDescription string-value for each language.
Be sure to call the GetFileVersionInfoSize and GetFileVersionInfo functions before calling VerQueryValue to properly initialize the pBlock buffer.
// Structure used to store enumerated languages and code pages.
HRESULT hr;
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
// Read the list of languages and code pages.
VerQueryValue(pBlock,
TEXT("\\VarFileInfo\\Translation"),
(LPVOID*)&lpTranslate,
&cbTranslate);
// Read the file description for each language and code page.
for( i=0; i < (cbTranslate/sizeof(struct LANGANDCODEPAGE)); i++ )
{
hr = StringCchPrintf(SubBlock, 50,
TEXT("\\StringFileInfo\\%04x%04x\\FileDescription"),
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
if (FAILED(hr))
{
// TODO: write error handler.
}
// Retrieve file description for language and code page "i".
VerQueryValue(pBlock,
SubBlock,
&lpBuffer,
&dwBytes);
}
Although I read this question, the accepted answer, and the documentation for VerQueryValue, I spent quite a while to understand how to use that VerQueryValue function (since the code example in the docs has no declarations of variables and isn't clear for me at all).
So I decided to put here the code that can be easily run as a working example of the usage of VerQueryValue to get a process description.
#pragma comment(lib,"Version.lib")
#include <iostream>
#include <windows.h>
#include <winver.h>
using namespace std;
int printFileDescriptions(const wchar_t* filename)
{
int versionInfoSize = GetFileVersionInfoSize(filename, NULL);
if (!versionInfoSize) {
return 0;
}
auto versionInfo = new BYTE[versionInfoSize];
std::unique_ptr<BYTE[]> versionInfo_automatic_cleanup(versionInfo);
if (!GetFileVersionInfo(filename, NULL, versionInfoSize, versionInfo)) {
return 0;
}
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *translationArray;
UINT translationArrayByteLength = 0;
if (!VerQueryValue(versionInfo, L"\\VarFileInfo\\Translation", (LPVOID*)&translationArray, &translationArrayByteLength)) {
return 0;
}
// You may check GetSystemDefaultUILanguage() == translationArray[i].wLanguage
// if only the system language required
for (unsigned int i = 0; i < (translationArrayByteLength / sizeof(LANGANDCODEPAGE)); i++) {
wchar_t fileDescriptionKey[256];
wsprintf(
fileDescriptionKey,
L"\\StringFileInfo\\%04x%04x\\FileDescription",
translationArray[i].wLanguage,
translationArray[i].wCodePage
);
wchar_t* fileDescription = NULL;
UINT fileDescriptionSize;
if (VerQueryValue(versionInfo, fileDescriptionKey, (LPVOID*)&fileDescription, &fileDescriptionSize)) {
wcout << endl << fileDescription << endl;
}
}
return TRUE;
}
int main()
{
// Set locale of the console to print non-ASCII symbols
SetConsoleOutputCP(GetACP());
SetConsoleCP(GetACP());
wcout.imbue(std::locale("")); // set default global locale
// ----------------------------------------------------
auto path = L"C:\\Windows\\explorer.exe";
printFileDescriptions(path);
wcin.get(); // to prevent console close
}
It's supposed that all WinAPI functions on your system use wchar_t, that is VerQueryValueW is actually used.
The initial version of the code I took here Retrieve File Description an Application VerQueryValue