gpt4 book ai didi

c++ - 来自 C++ 的 WMI 调用导致 HRESULT=0x80041003

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:56:26 24 4
gpt4 key购买 nike

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

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

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

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

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

PS2。我启用了以下权限(比如我是否需要为本地服务执行此操作)但仍然没有帮助:SE_SECURITY_NAMESE_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
}

最佳答案

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

关于c++ - 来自 C++ 的 WMI 调用导致 HRESULT=0x80041003,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9222809/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com