Click to See Complete Forum and Search --> : can i call wmi in a c++ wmi provider?


tingtong
June 4th, 2005, 01:51 PM
hi all:
i am writing a wmi provider using c++ which in turn call other microsoft provided wmi provider (win32_processor.....) in other machines. i run into a problem that i can't query the objects.
more exactly, i can get connected to the remote namespace
\\machine\root\cimv2
but i am not able to call the query the object
i have set the password and user name in the CoSetProxyBlanket with the approprivate (though i am not sure if the other parameter is correct)
i have tried console program (which i made two additional call coinitializeex and coinitializesecurity) it works.
can anyone help me this?

Mick
June 4th, 2005, 03:11 PM
What is the HRESULT?

tingtong
June 5th, 2005, 06:45 AM
the following is what i coded in the provider

HRESULT hres;

IWbemLocator *pLoc = NULL;

hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);

if (FAILED(hres))
{
DEBUG_MSG(123, L_NOTICE, "Fail to connect to WMI Server.\n");

CoUninitialize();
return -1; // Program has failed.
}

// Step 5: --------------------------------------------------
// Set security levels on a WMI connection ------------------
IWbemServices *pSvc = NULL;

hres = pLoc->ConnectServer(
_bstr_t("\\\\") + _bstr_t(hostName) + _bstr_t("\\root\\cimv2"),
_bstr_t(username), // User name
_bstr_t(password), // User password
_bstr_t("MS_409"), // Locale
NULL, // Security flags
_bstr_t(L"ntlmdomain:"), // Authority
0, // Context object
&pSvc // IWbemServices proxy
);

if (FAILED(hres))
{
DEBUG_MSG(123, L_NOTICE, "Fail to connect to namespace.\n");

pLoc->Release();
CoUninitialize();
return -1; // Program has failed.
}

// Step 5: --------------------------------------------------
// Set security levels on a WMI connection ------------------
// SEC_WINNT_AUTH_IDENTITY_W* pAuthIdentity =
// new SEC_WINNT_AUTH_IDENTITY_W;
SEC_WINNT_AUTH_IDENTITY_W authIdentity;

authIdentity.User = _bstr_t(username);
authIdentity.UserLength = wcslen( authIdentity.User );
authIdentity.Domain = _bstr_t(hostName);
authIdentity.DomainLength = wcslen( authIdentity.Domain );
authIdentity.Password = _bstr_t(password);
authIdentity.PasswordLength = wcslen( authIdentity.Password );
authIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
// NULL, // client identity
&authIdentity, // client identity
EOAC_NONE // proxy capabilities
);

if (FAILED(hres))
{
DEBUG_MSG(123, L_NOTICE, "Fail to set WMI security.\n");

pSvc->Release();
pLoc->Release();
CoUninitialize();
return -1; // Program has failed.
}

// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----

// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("Select * from Win32_Processor"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);

if (FAILED(hres))
{
DEBUG_MSG(123, L_NOTICE, "Fail to execute query.\n");

pSvc->Release();
pLoc->Release();
CoUninitialize();
return -1; // Program has failed.
}

// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------

IWbemClassObject *pclsObj;
ULONG uReturn = 0;


HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
int utilization = 0;

if(0 != uReturn)
{
VARIANT vtProp;
VariantInit(&vtProp);

// Get the value of the LoadPercentage property
hr = pclsObj->Get(L"LoadPercentage",
0, &vtProp, 0, 0);

utilization = vtProp.uintVal;

VariantClear(&vtProp);
}

// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();

if (uReturn != 0)
{
pclsObj->Release();
}
else
{
DEBUG_MSG(123, L_NOTICE, "No Win32_Processor Found.\n");
utilization = -2;
}

CoUninitialize();

return utilization; // Program successfully completed.


the debug showed No Win32_Processor is found
HRESULT 0x80070773

Mick
June 6th, 2005, 06:29 AM
0x80070773:
The users password must be changed before logging on the first time.

Now are you saying you moved your code out into a console program and you can connect fine? Using the same user/auth/query etc. Try it via wmitest.exe and also turn up the logging for wmi via dcomcnfg.exe

This goes over what you need for security:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/securing_a_remote_wmi_connection.asp

This goes over providers:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/using_wmi.asp

I would probably concentrate on how you have the provider configured as far as credentials given the error code that you are getting.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/provider_hosting_and_security.asp

tingtong
June 6th, 2005, 10:17 AM
do you know is it possible to call wmi (via c++ com interface) in a wmi provider?
my project required me to write a wmi provider, which in turn get data from remote system provider, the only requirement is i must stick with the wmi and Com.
i have tried many methods, none of them works.
Previously i write com which is just a wrapper for remote system provider, and i write a wmi provider to use this com object, but it gave me a 0x8007007e error.
and now i use wmi call wmi directly.
which one do you think better?