remote query works in vbs, but not in C++

273 views
Skip to first unread message

August Quint

unread,
Apr 27, 2006, 6:29:58 AM4/27/06
to
Hi,

I'm new here and new to WMI but with some years of experience in
programming.

I'm playing with WMI in C++ and I got my first results. But when I query a
remote PC I encounter a problem ...

So let me describe what I'm doing:
CoInitializeEx() --> S_OK
CoInitializeSecurity() --> S_OK
CoCreateInstance() --> S_OK
ConnectServer() --> S_OK
so I should be on the remote machin. Next step:
ExecQuery() --> Error

The error-number is 0x80041003 which is ACCESS_DENIED (I think).
So what's the problem here?

When I modify my program to access the local machine (removing IP-adress,
connecting to 'root/CIMV2' only, no user-name, no password) everything works
fine.
And also I can access the remote machine via the command-line:
C:\>wmic /node:10.3.9.163 /user:LisaG /password:Autobus1 BIOS get
biosversion

and get the information (different from the BIOS-version of my local
machine).

Using the WMICodeCreator I can create a little script in VBScript that
accesses the remote machine and queries it.

So the access should work, at least it does via VBScript and the WMIC. But
it does not work in C++.

Can someone please give me a tip. Thanks.

August


August Quint

unread,
Apr 27, 2006, 8:00:35 AM4/27/06
to
Hi,

I found this example here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/example__getting_wmi_data_from_a_remote_computer.asp

copied it, compiled it and: same result.
This piece of code:

hres = pSvc->ExecQuery(
bstr_t("WQL"),

bstr_t("Select * from Win32_OperatingSystem"),

WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,

NULL,

&pEnumerator);

returns: hres 0x80041003 HRESULT


Any ideas?

August


Sean

unread,
Apr 27, 2006, 12:36:06 PM4/27/06
to
Are you calling CoSetProxyBlanket on pSvc? This is basically how the
you specify security settings and user/password information for remote
WMI connections.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/html/c2e5e681-8fa5-4b02-b59d-ba796eb0dccf.asp

Also, Microsoft's examples don't cover remote connections very well,
and always use an authentication level of RPC_C_AUTHN_LEVEL_CONNECT or
RPC_C_AUTHN_LEVEL_CALL. Anything newer than Windows 2000 needs at
least RPC_C_AUTHN_LEVEL_PKT. The difference is that CONNECT only
requires remote users to authenticate once per connection, where PKT
requires user authentication for every transaction.
http://groups.google.com/group/microsoft.public.win32.programmer.wmi/browse_thread/thread/6fde0736b7cf6c41/d065424586fb611a#d065424586fb611a">http://groups.google.com/group/microsoft.public.win32.programmer.wmi/browse_thread/thread/6fde0736b7cf6c41/d065424586fb611a#d065424586fb611a

Hope this helps,
-Sean

August Quint

unread,
Apr 28, 2006, 3:35:48 AM4/28/06
to
Hello Sean,

I've taken the example found here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/example__getting_wmi_data_from_a_remote_computer.asp
and only removed the part with the call to CredUIPromptForCredentials(); the
user+password is hardcoded in my test-program.
This works locally but fails when I query the remote machine with the
error-code: hres 0x80041003 HRESULT
And after the call ConnectServer() you can see that CoSetProxyBlanket() is
called before ExecQuery().

I've played with some of the parameters, e.g. replaced
RPC_C_AUTHN_LEVEL_DEFAULT with RPC_C_AUTHN_LEVEL_PKT in
CoInitializeSecurity() and CoSetProxyBlanket(): nothing changes, I still get
this return-code on ExecQuery().

August

"Sean" <spfr...@gmail.com> schrieb im Newsbeitrag
news:1146155766.0...@u72g2000cwu.googlegroups.com...

Sean

unread,
Apr 28, 2006, 9:45:36 AM4/28/06
to
Hi, you're probably on the right track... you definitely need to find
just the right combination of authentication parameters for everything
to work. Are you passing a SEC_WINNT_AUTH_IDENTITY_W structure into
CoSetProxyBlanket? This is where you specify the remote credentials,
not in the ConnectServer call. The second example on this web page
shows how to create it:

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

By the way, what versions of windows are you using? You can use
wbemtest.exe to check what settings will work to connect

August Quint

unread,
May 2, 2006, 5:33:52 AM5/2/06
to
Hello Sean,

thanks for the URL. I'm 1 step further.

I'm using this code as my basis:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/example__getting_wmi_data_from_a_remote_computer.asp

I looked on the page you mentioned and found a difference to my call of
CoSetProxyBlanket():
the parameter RPC_AUTH_IDENTITY_HANDLE pAuthInfo, was NULL in my little
program (as it is in the example MS provided).

So I added the code from the page you menitoned: it works, at least for one
step, I can execute the query.
But now it stops in the next step: fetching the data. This is the code
following the ExecQuery():
// Step 7: -------------------------------------------------

// Get the data from the query in step 6 -------------------


IWbemClassObject *pclsObj;

ULONG uReturn = 0;


while (pEnumerator)

{

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


The value of hr is 0x80041003 (=E_ACCESSDENIED).
Hmmmmmm.....

August
PS: I'm using win XP Pro SP2 with Novell-Clients on both machines.

"Sean" <spfr...@gmail.com> schrieb im Newsbeitrag

news:1146231936....@j33g2000cwa.googlegroups.com...

Sean

unread,
May 2, 2006, 3:15:44 PM5/2/06
to
Hmmm, running out of ideas.... so you're calling
CoSetProxyBlanket(pEnumerator ...) before where it says Step 7 right?
And passing in the Unicode string values for username/password as the
pAuthInfo?

Also, here's another MSDN webpage that lists the authentication levels
required by different versions of windows:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/connecting_between_different_operating_systems.asp

Also try using RPC_C_AUTHN_GSS_NEGOTIATE instead of RPC_C_AUTHN_WINNT.
I think because you're using Windows XP it should be using Kerberos
instead of NTML for the authentication service, so setting this to
Negotiate might make sure it uses the correct service.

Sean

unread,
May 2, 2006, 3:34:23 PM5/2/06
to
Sorry, one more thing about CoSetProxyBlanket,
According to MSDN, when you're using Kerberos as the authentication you
should also use COLE_DEFAULT_PRINCIPAL for the Server Principal Name
(it's NULL in the examples)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/setting_the_security_on_iwbemservices_and_other_proxies.asp

maggie...@gmail.com

unread,
May 2, 2006, 6:47:47 PM5/2/06
to
I've been reading this thread since I had the same problem.

I also read the other one that Sean recommended:
http://groups.google.com/group/microsoft.public.win32.programmer.wmi/browse_thread/thread/6fde0736b7cf6c41/d065424586fb611a#d065424586fb611a

When I put CoSetProxyBlanket after ExecQuery, it works.

Thanks,
Maggie

------------------------

IEnumWbemClassObject* pEnumerator = NULL;

HRESULT hResult = pSvc->ExecQuery(
bstr_t( "WQL" ),
bstr_t( "SELECT * FROM Win32_OperatingSystem" ),


WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator );

if( FAILED( hResult ) )
{
// ... some clean up
return 1;
}

hResult = CoSetProxyBlanket(
pEnumerator,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
pAuthIdentity,
EOAC_NONE );

if( FAILED( hResult ) )
{
// ... some clean up
return 1;
}

// Get the data from the query

IWbemClassObject* pclsObj = NULL;
ULONG uReturn = 0;

while( pEnumerator )
{
HRESULT hr = pEnumerator->Next( WBEM_INFINITE, 1, &pclsObj, &uReturn
);

// ... more processing
}

August Quint

unread,
May 3, 2006, 4:42:12 AM5/3/06
to
Maggie,

thanks a lot!!! It works now, this was the last step. I've added a different
reply to describe the working code.

August

<maggie...@gmail.com> schrieb im Newsbeitrag
news:1146610067.6...@e56g2000cwe.googlegroups.com...

August Quint

unread,
May 3, 2006, 4:50:36 AM5/3/06
to
Hi,

a big THANK YOU to Sean and Maggie for their help.

Here is a short description how to make it work:

basis is the example found here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/example__getting_wmi_data_from_a_remote_computer.asp

I had to modify this to make it work.
These are the steps:
step 1:
hres = CoInitializeEx(...)
if (FAILED(hres)) { ....}

step 2:

hres = CoInitializeSecurity( ... )

if (FAILED(hres)) { ....}

step 3:

hres = CoCreateInstance( ... )

if (FAILED(hres)) { ....}

step 4:

hres = pLoc->ConnectServer( ... )

if (FAILED(hres)) { ....}

step 5:

hres = CoSetProxyBlanket(pSvc, ....)

if (FAILED(hres)) { ....}

step 6:

hres = pSvc->ExecQuery( ... )

if (FAILED(hres)) { ....}

step 7:

hres = CoSetProxyBlanket(pEnumerator, ... )

if (FAILED(hres)) { ....}

step 8:

while (pEnumerator)

{

HRESULT hr = pEnumerator->Next(.....)

if (FAILED(hres)) { ....}

OK, at least for me here it works now.

August


Sam Hobbs

unread,
May 3, 2006, 3:12:56 PM5/3/06
to
This is how a C/C++ programmer should diagnose the problem, but this is
generally useful for all WMI programmers.

The first thing to do is to put the error code (80041003 ) into the "Error
Lookup" tool. You can find it in the Visual Studio "Tools" menu. It does not
help with this error, but at least that tells us that it is not a normal
ERROR_ACCESS_DENIED error. An ERROR_ACCESS_DENIED error has 5 in the
low-order 16 bits, whereas 0x80041003 has 0x1003 in the low-order 16 bits.
Look in winerror.h for the format of error codes. There are places in the
MSDN that provide the same information formatted for use by programmers that
are not C/C++ programmers.

Another critical (often useful and when useful is probably the asnwer) step
is to search the KB for the error code (0x80041003). When I search for
0x80041003 I get results that look relevant.


"August Quint" <acq...@hotmail.com> wrote in message
news:11461337...@zombie.lexware.de...

Reply all
Reply to author
Forward
0 new messages