Read and display data from a VT_UNKNOWN variant

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.
Last edited on
Just wanted to mention that using user-mode-only techniques, it's possible that you'll miss some notifications for short-lived processes. The only sure-fire way to get notified when any process starts is to hook the common process entry point at kernel level.
Thanks for replying, how "short-lived" does the process have to be for me to miss its creation? what mostly matters to me is actually processes that stay open, so i probably don't even really care about short-lived processes. Just so I can learn more, since the purpose of this entire project that I'm currently working on is to understand windows more, can u maybe link me some good information on the common process entry point at the kernel level? I haven't really messed with kernel level stuff yet and it's actually something that I would like to look into.
So since u mentioned it, ill probably go look up some stuff related to this now. thanks :)
"Short-lived" could mean, for example, a few milliseconds.

If you don't care about those then disregard my post. Kernel-level hooking is a can of worms that you're better off not opening if you don't have to.
And opening it for education purposes is a bad idea? atm I'm just trying to slowly learn how things work, so if you maybe have some good sources with information I'd still be glad to if you send them to me.
See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff559951(v=vs.85).aspx
The function must be called from a kernel driver. I don't know whether the callback is called synchronously or asynchronously.
For more information, try googling "windows kernel hooking process creation".
Topic archived. No new replies allowed.