【发布时间】: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, ¶ms,
NULL );
if(SUCCEEDED(hr))
{
hr = params->SpawnInstance( 0, ¶msInst );
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, ¶mVt, 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(¶mVt);
}
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