Search code examples
c++comwmivariantwmi-query

Read and display data from variant VT_UNKNOWN


I wanted to retrieve infromation about every process the moment it opens. Instead of just writing a "dumb" loop that just iterates over all the open processes and checks when something changes, I wanted to do something more elegant. I wanted to query the creation events of processes and retrieve the information about the process from the event like this: I used WMI to asynchronously query the __InstanceCreationEvent of Win32_Process instances like this:

hr = pSvc->ExecNotificationQueryAsync(
            _bstr_t("WQL"),
            _bstr_t("SELECT * "
                "FROM __InstanceCreationEvent WITHIN 1 "
                "WHERE TargetInstance ISA 'Win32_Process'"),
            WBEM_FLAG_SEND_STATUS,
            NULL,
            pStubSink);

When ExecNotificationQueryAsync retrieves an event, it calls the user's implementation of the IWbemObjectSink::Indicate method and passes it the event as a IWbemClassObject interface. (it passes a pointer to an array of all these events). Now here's the problem. I used IWbemClassObject::Getin order to get the data from the TargetInstance property (which is the Win32_Process instance). However, the Get function outputs the result into a VARIANT. when checking the vt member of the structure, I found out that the member that contains the valid data is punkVal. punkVal's type is IUnknown. Basically my problem is as follows: How do I get the Win32_Process instance through punkVal? this is my implementation of the Indicate method:

HRESULT EventSink::Indicate(LONG lObjectCount,
IWbemClassObject **apObjArray)
{

    for (int i = 0; i < lObjectCount; i++)
    {
        IWbemClassObject * InstanceCreationEventInterface = apObjArray[i];

        VARIANT v;
        BSTR strClassProp = SysAllocString(L"TargetInstance");
        HRESULT hr;
        hr = InstanceCreationEventInterface->Get(strClassProp, 0, &v, 0, 0);
        SysFreeString(strClassProp);

        if (SUCCEEDED(hr) && (V_VT(&v) == VT_UNKNOWN))
        {
            wcout << (&v)->punkVal << endl; //How do I use punkVal here to get the Win32_Process instance?
        }
        else
        {
            wprintf(L"Error in getting specified object\n");
        }
        VariantClear(&v);
    }

    return WBEM_S_NO_ERROR;
}

Since punkVal's type is IUnknown*, the only method that can really be used to retrieve the instance is IUnknown::QueryInterface however I don't really see any way to use this method to get the Win32_Process instance.

Any help would be greatly appreciated.


Solution

  • TargetInstance is also a IWbemClassObject, so you can QI for IWbemClassObject on the IUnknown that you have.

    This answer here on SO demonstrates this: C++: Monitor process creation and termination in Windows