Pregunta

I want to retrieve the user AccountName knowing its SID. The SID is obtained using a WMI query: Select * from Win32_UserProfile, and i'm trying to get the user AccountName using the following query:

Select * from Win32_SID where SID='S-1-5-21-3949351935-1180888718-2463404063-9346'

The ExecQuery method succeeds, but the Next method from IEnumWbemClassObject fails with the error: H80041024 (wbemErrProviderNotCapable).

Any help would be great. Thanks.

¿Fue útil?

Solución

As the MSDN documentation states, the Win32_SID WMI class cannot be enumerated.

So, you cannot use the ExecQuery method, instead use the IWbemServices::GetObject function passing the proper WMI object path. something like Win32_SID.SID='S-1-5-82-1036420768-1044797643-1061213386-2937092688-4282445334'

Try this sample

#include "stdafx.h"
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")

#pragma argsused
int main(int argc, char* argv[])
{
    BSTR strNetworkResource;
    strNetworkResource =  L"\\\\.\\root\\CIMV2";

    // Initialize COM. ------------------------------------------

    HRESULT hres;
    hres =  CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;                  // Program has failed.
    }

    // Set general COM security levels --------------------------

        hres =  CoInitializeSecurity(
            NULL,
            -1,                          // COM authentication
            NULL,                        // Authentication services
            NULL,                        // Reserved
            RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
            RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
            NULL,                        // Authentication info
            EOAC_NONE,                   // Additional capabilities
            NULL                         // Reserved
            );


    if (FAILED(hres))
    {
        cout << "Failed to initialize security. Error code = 0x" << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;                    // Program has failed.
    }

    // Obtain the initial locator to WMI -------------------------

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

    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        CoUninitialize();       
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;                 // Program has failed.
    }

    // Connect to WMI through the IWbemLocator::ConnectServer method

    IWbemServices *pSvc = NULL;


    hres = pLoc->ConnectServer(
            _bstr_t(strNetworkResource),      // Object path of WMI namespace
            NULL,                    // User name. NULL = current user
            NULL,                    // User password. NULL = current
            0,                       // Locale. NULL indicates current
            NULL,                    // Security flags.
            0,                       // Authority (e.g. Kerberos)
            0,                       // Context object
            &pSvc                    // pointer to IWbemServices proxy
            );

    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x" << hex << hres << endl;    
        cout << _com_error(hres).ErrorMessage() << endl;
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();          
        return 1;                // Program has failed.
    }

    cout << "Connected to root\\CIMV2 WMI namespace" << endl;

    // Set security levels on the proxy -------------------------

        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
           EOAC_NONE                    // proxy capabilities
        );

    if (FAILED(hres))
    {
        cout << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;               // Program has failed.
    }

    // Use the IWbemServices pointer to make requests of WMI ----

    IWbemClassObject *pclsObj = NULL;
    hres = pSvc->GetObject(L"Win32_SID.SID='S-1-5-82-1036420768-1044797643-1061213386-2937092688-4282445334'",  0, NULL, &pclsObj, NULL);

    if (FAILED(hres))
    {
        cout << "GetObject failed" << " Error code = 0x"    << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;               // Program has failed.
    }
    else
    {

        VARIANT vtProp;

        HRESULT hr = pclsObj->Get(L"AccountName", 0, &vtProp, 0, 0);// String
        if (!FAILED(hr))
        {
            if ((vtProp.vt==VT_NULL) || (vtProp.vt==VT_EMPTY))
            wcout << "AccountName : " << ((vtProp.vt==VT_NULL) ? "NULL" : "EMPTY") << endl;
            else
            wcout << "AccountName : " << vtProp.bstrVal << endl;
        }
        VariantClear(&vtProp);

        pclsObj->Release();
        pclsObj=NULL;
    }

    // Cleanup

    pSvc->Release();
    pLoc->Release();
    if (pclsObj!=NULL)
     pclsObj->Release();

    CoUninitialize();
    cout << "press enter to exit" << endl;
    cin.get();
    return 0;   // Program successfully completed.
}

Otros consejos

This is one of the problems with WMI: it provides a uniform interface, but virtually all the data comes from other code. Some of that other code doesn't provide all data to WMI, even though the data clearly is available. If you need the data anyway, you'll probably need to bypass WMI and obtain it directly from the source.

Fortunately, in this case that's fairly simple: you can call LookupAccountSid to get exactly what you're asking for.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top