【问题标题】:WMI call from C++ results in HRESULT=0x80041003来自 C++ 的 WMI 调用导致 HRESULT=0x80041003
【发布时间】:2012-02-11 13:56:13
【问题描述】:

我不确定为什么会得到这个奇怪的结果。有人可以解释一下吗?

我正在使用来自 C++ 程序的 WMI 调用来导出 Windows 事件日志的“应用程序”部分。

这是通过本地服务完成的,并且代码在 Windows 7 下运行良好。当我在 Windows XP 上运行它时会出现问题。由于某些奇怪的原因,WMI 接口的 ExecMethod() 返回 HRESULT=0x80041003,即拒绝访问。

但是,如果我将完全相同的代码放入一个简单的用户进程并从那里运行它,一切都会很好。怎么可能,代码无法从特权更高的本地服务运行,而是从简单的用户进程运行?

PS。我会很感激任何想法,因为我已经为此工作了几天无济于事....

PS2。我启用了以下权限(例如,如果我需要为本地服务执行此操作),但仍然没有帮助: SE_SECURITY_NAME SE_BACKUP_NAME

编辑:我想添加示例代码不会有什么坏处。 (很抱歉,很长的部分,但是这个该死的 WMI/COM 也不是一个美丽的东西......)我在下面标记了我得到错误的地方:

// Initialize COM. ------------------------------------------
hr =  CoInitializeEx(0, COINIT_MULTITHREADED);

if(SUCCEEDED(hr))
{
    // Set general COM security levels --------------------------
    // Note: If you are using Windows 2000, you need to specify -
    // the default authentication credentials for a user by using
    // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
    // parameter of CoInitializeSecurity ------------------------
    hr =  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(SUCCEEDED(hr))
    {
        // Obtain the initial locator to WMI -------------------------
        IWbemLocator *pLoc = NULL;
        hr = CoCreateInstance(
            CLSID_WbemLocator,             
            0, 
            CLSCTX_INPROC_SERVER, 
            IID_IWbemLocator, (LPVOID *) &pLoc);

        if(SUCCEEDED(hr))
        {
            // Connect to WMI through the IWbemLocator::ConnectServer method
            IWbemServices *pSvc = NULL;

            // Connect to the root\cimv2 namespace with
            // the current user and obtain pointer pSvc
            // to make IWbemServices calls.
            hr = pLoc->ConnectServer(
                 _bstr_t(L"\\\\.\\ROOT\\CIMV2"), // 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(SUCCEEDED(hr))
            {
                // Set security levels on the proxy -------------------------
                hr = 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(SUCCEEDED(hr))
                {
                    // Use the IWbemServices pointer to make requests of WMI ----
                    // For example, get the name of the operating system
                    IEnumWbemClassObject* pEnumerator = NULL;

                    hr = pSvc->ExecQuery(
                        bstr_t("WQL"), 
                        bstr_t("Select * from Win32_NTEventLogFile Where LogFileName='Application'"),
                        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
                        NULL,
                        &pEnumerator);

                    if(SUCCEEDED(hr))
                    {
                        IWbemClassObject *pclsObj = NULL;
                        int nCnt = -1;

                        //Go through all results
                        while (pEnumerator)
                        {
                            ULONG uReturn = 0;
                            hr = pEnumerator->Next(WBEM_INFINITE, 1, 
                                &pclsObj, &uReturn);

                            if(0 == uReturn)
                            {
                                break;
                            }

                            //Go to next iteration
                            nCnt++;

                            // Get a reference to the Win32_Printer class so we can find
                            // the RenamePrinter method.  This lets us create an object
                            // representing the input parameter block to be passed to the
                            // method when we call it.
                            IWbemClassObject *pNTEventLogFile = NULL;
                            IWbemClassObject *params = NULL;
                            IWbemClassObject *paramsInst = NULL;

                            hr = pSvc->GetObject( _bstr_t( L"Win32_NTEventLogFile" ), 0, NULL,
                                               &pNTEventLogFile, NULL );

                            if(SUCCEEDED(hr))
                            {
                                hr = pNTEventLogFile->GetMethod( _bstr_t( "BackupEventLog" ), 0, &params,
                                               NULL );
                                if(SUCCEEDED(hr))
                                {
                                    hr = params->SpawnInstance( 0, &paramsInst );
                                    if(SUCCEEDED(hr))
                                    {

                                        // Now that we've got an instance representing the input
                                        // parameters, we can fill in the parameter values
                                        _bstr_t paramValue( L"C:\\Users\\UserName\\Documents\\application.evt" );
                                        VARIANT paramVt;
                                        paramVt.vt = VT_BSTR;
                                        paramVt.bstrVal = paramValue;
                                        hr = paramsInst->Put( L"ArchiveFileName", 0, &paramVt, NULL );
                                        if(SUCCEEDED(hr))
                                        {
                                            // Get the "this" pointer to our object instance so that we
                                            // can call the RenamePrinter method on it
                                            CIMTYPE type;
                                            LONG flavor;
                                            VARIANT var;
                                            hr = pclsObj->Get( L"__PATH", 0, &var, &type, &flavor );

                                            if(SUCCEEDED(hr))
                                            {
                                                // Execute the RenamePrinter method on our object instance
                                                IWbemClassObject *results = NULL;
                                                hr = pSvc->ExecMethod( var.bstrVal, _bstr_t( L"BackupEventLog" ), 0,
                                                    NULL, paramsInst, &results, NULL );

**///////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////// THIS IS WHERE hr = 0x80041003 or wbemErrAccessDenied
//////////////////////////////////////////////// only when this code is run from a local service
//////////////////////////////////////////////// on a Windows XP machine, but if I run the exact same
//////////////////////////////////////////////// code from a user process on XP machine, it works!
//////////////////////////////////////////////// Note that this works fine on Windows Vista/7 in any configuration.
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////**

                                                if(SUCCEEDED(hr))
                                                {
                                                    //Get result code from the BackupEventLog method
                                                    VARIANT vtProp;
                                                    hr = results->Get(L"ReturnValue", 0, &vtProp, 0, 0);
                                                    if(SUCCEEDED(hr))
                                                    {
                                                        if(vtProp.vt == VT_I4)
                                                        {
                                                            //Check
                                                            // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384808(v=vs.85).aspx

                                                            //0 = Success
                                                            //8 = Privilege missing
                                                            //21 = Invalid parameter
                                                            //80 = Archive file name already exists. This value is returned starting with Windows Vista.
                                                            int nResV = vtProp.intVal;
                                                            //_tprintf(_T("result2 : %d\n"), nResV);

                                                        }
                                                        else
                                                        {
                                                            //Error
                                                        }

                                                        //Free
                                                        VariantClear(&vtProp);  
                                                    }
                                                    else
                                                    {
                                                        //Error
                                                    }

                                                }
                                                else
                                                {
                                                    //Error
                                                }


                                                //Free
                                                if(results)
                                                {
                                                    results->Release();
                                                    results = NULL;
                                                }

                                                //Clear
                                                VariantClear(&var);
                                            }
                                            else
                                            {
                                                //Error
                                            }

                                            //Clear
                                            VariantClear(&paramVt);
                                        }
                                        else
                                        {
                                            //Error
                                        }
                                    }
                                    else
                                    {
                                        //Error
                                    }
                                }
                                else
                                {
                                    //Error
                                }
                            }
                            else
                            {
                                //Error
                            }


                            //Free
                            if(pNTEventLogFile)
                            {
                                pNTEventLogFile->Release();
                                pNTEventLogFile = NULL;
                            }
                            if(params)
                            {
                                params->Release();
                                params = NULL;
                            }
                            if(paramsInst)
                            {
                                paramsInst->Release();
                                paramsInst = NULL;
                            }

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


                        //Free
                        if(pclsObj)
                        {
                            pclsObj->Release();
                            pclsObj = NULL;
                        }


                    }
                    else
                    {
                        //Error
                    }


                    //Free
                    if(pEnumerator)
                    {
                        pEnumerator->Release();
                        pEnumerator = NULL;
                    }
                }
                else
                {
                    //Error
                }

            }
            else
            {
                //Error
            }


            //Free
            if(pSvc)
            {
                pSvc->Release();
                pSvc = NULL;
            }


        }
        else
        {
            //Error
        }


        //Free
        if(pLoc)
        {
            pLoc->Release();
            pLoc = NULL;
        }

    }
    else
    {
        //Error
    }

    //Uninit
    CoUninitialize();
}
else
{
    //Error
}

【问题讨论】:

    标签: c++ wmi event-log access-denied


    【解决方案1】:

    我想我明白了...对于那些不想浪费 3 天时间在这里寻找答案的人来说,它是:在 Windows XP 上,在对 CoInitializeSecurity() 和 CoSetProxyBlanket() 的调用中将 RPC_C_IMP_LEVEL_IMPERSONATE 替换为 RPC_C_IMP_LEVEL_DELEGATE。我不知道它到底做了什么,但它使上面的代码工作!耶!!!

    【讨论】:

    • 感谢您发布解决方案。你为我节省了大量时间。
    • 这帮助我快速解决了问题。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2010-09-13
    • 2014-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 2013-05-26
    相关资源
    最近更新 更多