ST3
ST3

Reputation: 8946

Deleting WMI instance with C++

I have found some samples with C# and VBS for WMI instance deletion, however I need this implemented with C++.

My sample code:

CoInitialize(NULL);

HRESULT hRes;

//Obtain the initial locator to WMI
CComPtr<IWbemLocator> pLoc = NULL;
hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*) &pLoc);
if(FAILED(hRes))
    return 1;

//Connect to WMI through the IWbemLocator::ConnectServer method
CComPtr<IWbemServices> pSvc = NULL;
//Connect to the root namespace with the current user and obtain pointer pSvc to make IWbemServices calls.
hRes = pLoc->ConnectServer(L"ROOT\\SUBSCRIPTION", NULL, NULL, 0, NULL, 0, 0, &pSvc);
if(FAILED(hRes))
    return 1;

hRes = pSvc->DeleteInstance(
           L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'",
           WBEM_FLAG_RETURN_IMMEDIATELY, NULL, NULL);

return 0;

According to that I've found here and here, my code should work. I surely have CommandLineEventConsumer named {709782F3-E860-488E-BD8A-89FBC8C1495C}

And my code fails on IWbemServices::DeleteInstance, error code 0x80041008 (One of the parameters to the call is not correct).

I would appreciate if someone spot mistake in my code. Or maybe some privileges are required to do that?

Upvotes: 2

Views: 1099

Answers (2)

ST3
ST3

Reputation: 8946

I have found two solutions:

1.Remove WBEM_FLAG_RETURN_IMMEDIATELY flag.

_bstr_t objPath(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(objPath, 0, NULL, NULL);

2.Pass IWbemCallResult for result.

_bstr_t objPath(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
CComPtr<IWbemCallResult> pRes = NULL;
hRes = pSvc->DeleteInstance(objPath, WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pRes);

Didn't investigate a lot, but it works both ways. Looks like specs aren't 100% correct.

Upvotes: 3

IInspectable
IInspectable

Reputation: 51464

The first parameter to IWbemServices::DeleteInstance is a BSTR. A BSTR is different from a UTF-16 encoded C-style string in that it stores an explicit length argument. Even though BSTR is of type wchar_t*, you cannot pass a plain string literal in place of a BSTR.

To create a BSTR from a string literal you need to call SysAllocString:

BSTR objPath = ::SysAllocString(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(
       objPath,
       WBEM_FLAG_RETURN_IMMEDIATELY, NULL, NULL);
::SysFreeString(objPath);

Alternatively, since you are already using ATL for CComPtr you could use CComBSTR to make your life easier:

CComBSTR objPath(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(
       objPath,
       WBEM_FLAG_RETURN_IMMEDIATELY, NULL, NULL);


Note: IWbemLocator::ConnectServer also needs BSTRs as parameters. The sample provided on the documentation page does pass a plain C-style string, so maybe the IWbemLocator interface is more forgiving when presented invalid parameters.

Upvotes: 3

Related Questions