• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2453
  • Last Modified:

Why is IEnumWbemClassObject->Next returning E_ACCESSDENIED

I am trying to query the WMI information on other computers on the local network.  All of the computers are running Windows XP (with SP) and are on the same local workgroup.  All of the computers have the same administrator password which has been verified by successfully connecting to each computer and mapping to the C$ share using the administrator username/password.  However, the following code works correctly on 3 out of the 4 computers.  On one of the computers the code works up until the call to enumerator->Next which failes with an HRESULT of E_ACCESSDENIED.  First of all, how could the administrator get an access denied result.  Second, why does it only get an access denied on the next and not on any of the prior calls to connect to the computer or to setup the WMI query.  Thirdly, why would this work on 3 other extremely similar computers and not the 4th?

int main(int argc,char** argv)
{
      USES_CONVERSION;
      HRESULT hres;
      char username[]="administrator";
      char password[]="adminPassword";
      char domain[]="";
      char wmiNamespace[]="\\\\ServerName\\ROOT\\CIMV2";

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

      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;
        CoUninitialize();
        return 1;                    // Program has failed.
    }

      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;
            CoUninitialize();
            return 1;                 // Program has failed.
      }

      IWbemServices *pSvc = NULL;
      hres = pLoc->ConnectServer(
            T2W(wmiNamespace),                              // Object path of WMI namespace
            T2W(username),                    // User name. NULL = current user
            T2W(password),                    // User password. NULL = current
            0,                       // Locale. NULL indicates current              
            WBEM_FLAG_CONNECT_USE_MAX_WAIT,                    // 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;
            pLoc->Release();      
            CoUninitialize();
            return 1;                // Program has failed.
      }

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

      SEC_WINNT_AUTH_IDENTITY        authidentity;
      SecureZeroMemory( &authidentity, sizeof(authidentity) );
      authidentity.User = (LPUSTR)T2W( (LPTSTR)(LPCTSTR)username);
      authidentity.UserLength = strlen(username);
      authidentity.Domain = (LPUSTR)T2W( (LPTSTR)(LPCTSTR)domain);
      authidentity.DomainLength = strlen(domain );
      authidentity.Password = (LPUSTR)T2W( (LPTSTR)(LPCTSTR)password);
      authidentity.PasswordLength = strlen(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
            &authidentity,                        // client identity
            EOAC_NONE                    // proxy capabilities
      );

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

      IEnumWbemClassObject* pEnumerator = NULL;
      hres = pSvc->ExecQuery( bstr_t("WQL"),
            bstr_t("SELECT * FROM Win32_Desktop"),
            WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
   
      if (FAILED(hres))
      {
            cout << "Query for operating system name failed."
                  << " Error code = 0x"
                  << hex << hres << endl;
            pSvc->Release();
            pLoc->Release();
            CoUninitialize();
            return 1;               // Program has failed.
      }

      IWbemClassObject *pclsObj=NULL;
      ULONG uReturn = 0;
      while (pEnumerator)
      {
            HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
            if(0 == uReturn) break;
            VARIANT vtProp;
            VariantInit(&vtProp);
            hr = pclsObj->Get(L"ScreenSaverExecutable", 0, &vtProp, 0, 0);    
            cout << "Executable: ";
            char* executableName = W2T(vtProp.bstrVal);
            cout << executableName;
            VariantClear(&vtProp);
            pclsObj->Release();
    }
      cout<<endl<<"End."<<endl;
      pSvc->Release();
      pLoc->Release();
      pEnumerator->Release();
      CoUninitialize();
}
0
gmain
Asked:
gmain
  • 3
  • 2
1 Solution
 
x4uCommented:
>> First of all, how could the administrator get an access denied result.
Administrator accounts do not have access rights to everything on Windows just because they are administrators. It's possible to remove access rights even for adminstrators from files, directories (i.e. by default no access to /System Volume Information) or registry subtrees (i.e. cannot write to HKLM\SYSTEM\CurrentControlSet\Enum\Root by default). Although Administrators can modify all access rights they want and as a consequence of this gain access to everything. Revoking administrators (i.e. your own) access rights is sometimes actually quite usefull, i.e. to prevent programs (or malwale) from modifying certain files or registry entries.
0
 
gmainAuthor Commented:
Just as added info, the following VBScript works on all of the machines:

Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objWMIService = objSWbemLocator.ConnectServer("computerName", _
    "root\CIMV2", "Administrator", "AdminPassword",NULL,NULL)
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Desktop",,48)

For Each objItem in colItems
    Wscript.Echo "ScreenSaverExecutable: " & objItem.ScreenSaverExecutable
Next

The key now is to get this same functionality to work in C++ code
0
 
gmainAuthor Commented:
In an effort to discover the reason for the E_ACCESSDENIED, I have done the following on the computer where the Next operation fails:
   - Ran WmiMgmt.msc and verified that the administrators group has full access to the CIMV2 namespace
   - Enabled WMI verbose logging (in WmiMgmt.msc) and ran the C++ code again and no errors appeared in the generated logs
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
gmainAuthor Commented:
Figured out the problem.... per a Microsoft website, you MUST call CoSetProxyBlanket on EVERY interface you retrieve.  This would include the enumerator class.  Once I successfully called that on the enumerator object I no longer got the E_ACCESSDENIED return from the next function.
0
 
x4uCommented:
I'm happy that gmain found a solution to his problem and refunding the points is perfectly o.k. for me.
0
 
GranModCommented:
PAQ-ing the question and refunding 500 points

Thanks x4u !

GranMod
The Experts Exchange
Community Support Moderator of all Ages
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now