Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

601 lines
19 KiB

/*++
Copyright (c) 2000, Microsoft Corporation
Module Name:
dglogswmi.cpp
Abstract:
The file contains the methods for class CWmi. CWmi retrives information from WMI
--*/
#include "StdAfx.h"
#include "WmiGateway.h"
#include <wbemtime.h>
#include "util.h"
/*++
Routine Description
The worker thread uses this function to check if the main thread has canceled the worker thread.
i.e. the work thread should abort what ever it is doing, clean up and terminate.
Arguments
none
Return Value
TRUE the worker thread has been terminated
FALSE the worker thread has not been terminated
--*/
inline BOOL CWmiGateway::ShouldTerminate()
{
if( m_bTerminate )
{
return TRUE;
}
if (WaitForSingleObject(m_hTerminateThread, 0) == WAIT_OBJECT_0)
{
m_bTerminate = FALSE;
return TRUE;
}
else
{
return FALSE;
}
}
CWmiGateway::CWmiGateway()
/*++
Routine Description
Constructor, initializes member variables and creates the Wbem class object
Arguments
none
Return Value
none
--*/
{
HRESULT hr = S_OK;
m_wstrMachine = L".";
m_pWbemLocater = NULL;
}
BOOL
CWmiGateway::WbemInitialize(INTERFACE_TYPE bInterface)
{
HRESULT hr = E_FAIL;
// Create the WMI object
//
hr = CoCreateInstance(CLSID_WbemLocator,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(void **)&m_pWbemLocater);
if( FAILED(hr) )
{
m_pWbemLocater = NULL;
return FALSE;
}
return TRUE;
}
// Not currently used
VOID CWmiGateway::SetMachine(WCHAR *pszwMachine)
{
EmptyCache();
m_wstrMachine = pszwMachine;
}
//
// SetSecurity - set the Proxy Blanket on an IUnknown* interface so that it can be used by WMI
// cross-machine calls.
//
// Okay for any of pwszDomainName, pwszUserName or pwszPassword to be NULL.
//
// deonb 12/20/2001
//
HRESULT WINAPI SetSecurity(IN OUT IUnknown* pUnk, IN USHORT* pwszDomainName, IN USHORT* pwszUserName, IN USHORT* pwszPassword)
{
HRESULT hr = S_OK;
COAUTHIDENTITY authident;
authident.Domain = pwszDomainName;
authident.DomainLength = pwszDomainName ? wcslen(pwszDomainName) : 0;
authident.Password = pwszPassword;
authident.PasswordLength = pwszPassword ? wcslen(pwszPassword) : 0;
authident.User = pwszUserName;
authident.UserLength = pwszUserName ? wcslen(pwszUserName) : 0;
authident.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
hr = CoSetProxyBlanket(pUnk,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
&authident,
EOAC_NONE);
return hr;
}
IWbemServices *
CWmiGateway::GetWbemService(
IN LPCTSTR pszwService
)
/*++
Routine Description
Connects to a Wbem Service (Repository i.e. root\default). The connection to the Wbem service
is cached so if the Service is requested again, the service is retrived from the cache. When
the class is destroyed the connection to the cached Wbem services is released.
Arguments
pszwService Wbem Service to connect to. (i.e. root\default)
Return Value
A pointer to the Wbem service connection.
If the connection fails, the method returns NULL
--*/
{
WbemServiceCache::iterator iter;
IWbemServices *pWbemServices = NULL;
_bstr_t bstrService;
HRESULT hr;
if( !m_pWbemLocater )
{
// Wbem class object was not created.
//
return NULL;
}
// Check if the wbem service is cached.
//
iter = m_WbemServiceCache.find(pszwService);
if( iter == m_WbemServiceCache.end() )
{
// We did not create and cache the wbem service yet, do it now
//
hr = m_pWbemLocater->ConnectServer(_bstr_t(pszwService),
NULL, // User name
NULL, // user password
NULL,NULL,NULL,NULL,
&pWbemServices);
if( SUCCEEDED(hr) )
{
//
// Set the authentication information for the WbemService
//
hr = SetSecurity(pWbemServices, NULL, NULL,NULL);
if( SUCCEEDED(hr) )
{
// Cache the newly created WbemService
//
m_WbemServiceCache[pszwService] = pWbemServices;
pWbemServices->Release();
return m_WbemServiceCache[pszwService];
}
else
{
// Failed to set the proxy blankey on the service, release the wbem service
//
pWbemServices->Release();
pWbemServices = NULL;
}
}
return pWbemServices;
}
// We found the requested WbemService in our cache, return it
//
return iter->second;
}
IEnumWbemClassObject *
CWmiGateway::GetEnumWbemClassObject(
IN LPCTSTR pszwService,
IN LPCTSTR pszwNameSpace
)
/*++
Routine Description
Creates an IEnumWbemClassObject. The IEnumWbemClassObject contains all of the instance
of a class object. This pointer is not chached, since the instances are a snap shot
of WMI at the time the object is created. So if we reuse the class object the data
will be out-of-date. The caller must release the created IEnumWbemClassObject
(i.e. pEnumWbemClassObject->Release() );
Arguments
pszwService Wbem Service to connect to. (i.e. root\default)
pszwNameSpace Wbem Name space to connect to. (i.e. NetDiagnostics, Win32_NetworkAdapterConfiguration)
Return Value
A pointer to the IEnumWbemClassObject.
If the the class object can not be created, the method reurns NULL
--*/
{
IWbemServices *pWbemServices = NULL;
IEnumWbemClassObject *pEnumWbemClassObject = NULL;
// Get the requested WbemService
//
pWbemServices = GetWbemService(pszwService);
if( pWbemServices )
{
// Create the EnumWbemClassObject. No need to check the
// return value. If this function fails pEnumWbemClassObject
// will be NULL
//
(void)pWbemServices->CreateInstanceEnum(_bstr_t(pszwNameSpace),
0L,
NULL,
&pEnumWbemClassObject);
}
return pEnumWbemClassObject;
}
IWbemClassObject *
CWmiGateway::GetWbemClassObject(
LPCTSTR pszwService,
LPCTSTR pszwNameSpace,
const int nInstance)
/*++
Routine Description
Creates an IWbemClassObject. The IWbemClassObject is an instance of the IEnumWbemClassObject
This pointer is not chached, since the instance is a snap shot of WMI at the time the object
is created. So if we reuse the class object the data will be out-of-date. The caller must release
the IWbemClassObject (i.e. pWbemClassObject->Release() )
Arguments
pszwService Wbem Service to connect to. (i.e. root\default)
pszwNameSpace Wbem Name space to connect to. (i.e. NetDiagnostics, Win32_NetworkAdapterConfiguration)
nInstance The instance of IEnumWbemClassObject to retrive. Default is to grab the first instance (nInstance 0)
Return Value
A pointer to the IWbemClassObject
If the class object can not be created, the method returns NULL.
--*/
{
IEnumWbemClassObject *pEnumWbemClassObject = NULL;
IWbemClassObject *pWbemClassObject = NULL;
ULONG uReturned;
HRESULT hr;
// Get the EnumWbemClass object (Contains all of the instances)
//
pEnumWbemClassObject = GetEnumWbemClassObject(pszwService,pszwNameSpace);
if( pEnumWbemClassObject )
{
// Jump to the nth instance
//
hr = pEnumWbemClassObject->Skip(WBEM_INFINITE, nInstance);
if( WBEM_S_NO_ERROR == hr )
{
// Get the nth classobject (i.e. instance). If this call fails pWbemClassObject is NULL
// Next grabs the instances you skipped to.
//
hr = pEnumWbemClassObject->Next(WBEM_INFINITE,
1,
&pWbemClassObject,
&uReturned);
}
// Release the IEnumWbemClassObject
//
pEnumWbemClassObject->Release();
}
return pWbemClassObject;
}
void CWmiGateway::ReleaseAll(IEnumWbemClassObject *pEnumWbemClassObject, IWbemClassObject *pWbemClassObject[], int nInstances)
{
if( pWbemClassObject )
{
for(ULONG i = 0; i < nInstances; i++)
{
if( pWbemClassObject[i] )
{
pWbemClassObject[i]->Release();
pWbemClassObject[i] = NULL;
}
}
}
if( pEnumWbemClassObject )
{
pEnumWbemClassObject->Release();
}
}
HRESULT
CWmiGateway::GetWbemProperties(
IN OUT EnumWbemProperty &EnumProp
)
{
HRESULT hr = S_OK;
EnumWbemProperty::iterator iter, iter2;
IWbemServices *pWbemServices = NULL;
IEnumWbemClassObject *pEnumWbemClassObject = NULL;
IWbemClassObject *pWbemClassObject[30]; // = NULL;
WCHAR pszwRepository[MAX_PATH + 1] = L"";
WCHAR pszwNamespace[MAX_PATH + 1 ] = L"";
ULONG nInstances = 0;
m_wstrWbemError = L"";
for( iter = EnumProp.begin(); iter != EnumProp.end(); iter++)
{
if( iter->pszwRepository && lstrcmpi(iter->pszwRepository,pszwRepository) != 0 )
{
if( pWbemServices )
{
pWbemServices->Release();
pWbemServices = NULL;
}
lstrcpy(pszwRepository,iter->pszwRepository);
lstrcpy(pszwNamespace, L"");
pWbemServices = GetWbemService(pszwRepository);
if( ShouldTerminate() ) goto End;
if( !pWbemServices )
{
if( !m_wstrWbemError.empty() )
{
m_wstrWbemError += L";";
}
WCHAR wsz[MAX_PATH+1];
_snwprintf(wsz,MAX_PATH,ids(IDS_FAILEDOPENWMIREP),pszwRepository);
m_wstrWbemError += wsz;
}
}
if( iter->pszwNamespace && lstrcmpi(pszwNamespace, iter->pszwNamespace) != 0 )
{
lstrcpy(pszwNamespace, iter->pszwNamespace);
if( pWbemServices )
{
ReleaseAll(pEnumWbemClassObject,pWbemClassObject,nInstances);
pEnumWbemClassObject = NULL;
hr = pWbemServices->CreateInstanceEnum(_bstr_t(pszwNamespace),
0L,
NULL,
&pEnumWbemClassObject);
if( SUCCEEDED(hr) )
{
// With WMI you can not get the number of instances in a class. So I am using a hard coded value of 30
// If there are more than 30 instance their will be a problem displaying all of them.
nInstances = 0;
hr = pEnumWbemClassObject->Next(WBEM_INFINITE,
20, // Get all of the instances
pWbemClassObject,
&nInstances);
if( ShouldTerminate() ) goto End;
if( SUCCEEDED(hr) )
{
for(ULONG i = 0; i< nInstances; i++)
{
(void)pWbemClassObject[i]->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
}
}
}
else
{
if( !m_wstrWbemError.empty() )
{
m_wstrWbemError += L";";
}
WCHAR wsz[MAX_PATH+1];
_snwprintf(wsz,MAX_PATH,ids(IDS_FAILEDOPENWMINAMESPACE),pszwNamespace),
m_wstrWbemError += wsz;
}
}
}
if( pWbemClassObject && nInstances)
{
VARIANT vValue;
VariantInit(&vValue);
if( !iter->pszwName || lstrcmp(iter->pszwName,L"") == 0)
{
BSTR bstrFieldname;
int nProperty = 0;
CIMTYPE CimType;
while( WBEM_S_NO_ERROR == pWbemClassObject[0]->Next(0,&bstrFieldname, NULL, &CimType, NULL) )
{
if( ShouldTerminate() ) goto End;
if( lstrcmp((WCHAR *)bstrFieldname,L"OEMLogoBitmap")==0 ) continue;
// Do not get arrays they are to did handles i.e. bitmaps
if( nProperty == 0 )
{
iter->SetProperty((WCHAR *)bstrFieldname,0);
iter2 = iter;
iter2++;
}
else
{
if( iter2 == EnumProp.end() )
{
EnumProp.push_back(WbemProperty((WCHAR *)bstrFieldname,0,NULL,NULL));
iter2 = EnumProp.end();
}
else
{
iter2 = EnumProp.insert(iter2,WbemProperty((WCHAR *)bstrFieldname,0,NULL,NULL));
iter2++;
}
}
SysFreeString(bstrFieldname);
nProperty++;
}
}
for(ULONG i = 0; i < nInstances; i++)
{
HRESULT hr;
CIMTYPE vtType;
hr = pWbemClassObject[i]->Get(iter->pszwName,0,&vValue,&vtType,NULL);
if( ShouldTerminate() ) goto End;
if( SUCCEEDED(hr) )
{
if( vValue.vt != VT_NULL && vtType == CIM_DATETIME && vValue.bstrVal!= NULL && lstrcmp((WCHAR *)vValue.bstrVal,L"")!=0 )
{
WBEMTime wt(vValue.bstrVal);
WCHAR szBuff[MAX_PATH+1];
WCHAR szwDateTime[MAX_PATH+1];
SYSTEMTIME SysTime;
if( wt.GetSYSTEMTIME(&SysTime) )
{
FILETIME FileTime, LocalFileTime;
SYSTEMTIME UTCTIme, LocalTime;
memcpy(&UTCTIme,&SysTime,sizeof(SYSTEMTIME));
SystemTimeToFileTime(&UTCTIme,&FileTime);
FileTimeToLocalFileTime(&FileTime, &LocalFileTime);
FileTimeToSystemTime(&LocalFileTime, &LocalTime);
memcpy(&SysTime,&LocalTime,sizeof(SYSTEMTIME));
lstrcpy(szwDateTime,L"");
if (0 != GetTimeFormat(LOCALE_USER_DEFAULT, //GetThreadLocale(),
0,
&SysTime,
NULL,
szBuff,
sizeof(szBuff)/sizeof(WCHAR)))
{
//vValue.bstrVal = szBuff;
lstrcpy(szwDateTime,szBuff);
}
if (0 != GetDateFormat(LOCALE_USER_DEFAULT, //GetThreadLocale(),
0,
&SysTime,
NULL,
szBuff,
sizeof(szBuff)/sizeof(WCHAR)))
{
//vValue.bstrVal = szBuff;
_snwprintf(szwDateTime,MAX_PATH,L"%s %s",szwDateTime,szBuff);
}
//SysFreeString(vValue.bstrVal);
VariantClear(&vValue);
vValue.bstrVal = SysAllocString((WCHAR *)szwDateTime);
vValue.vt = VT_BSTR;
}
}
/*
Security: Make sure that the variants in the stack are cleared when the stack is destroyed
*/
iter->Value.push_back(vValue);
VariantClear(&vValue);
}
}
}
}
End:
ReleaseAll(pEnumWbemClassObject,pWbemClassObject,nInstances);
pEnumWbemClassObject = NULL;
return hr;
}
void CWmiGateway::EmptyCache()
{
// Empty the WbemService cache
//
m_WbemServiceCache.erase(m_WbemServiceCache.begin(),
m_WbemServiceCache.end());
}
// Netsh does not free its helpers if it is aborted or the user runs netsh with /?
// The Wbem object dissapears from under neath us. try and except do not work inside
// of the destructor.
//
ReleaseWbemObject(IWbemLocator *p)
{
/*
Security: Need to check if we still need the try catch
*/
__try
{
p->Release();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
//DebugBreak();
}
return 0;
}
CWmiGateway::~CWmiGateway()
/*++
Routine Description
Destructor, free all member variables and release the wbem connection
Arguments
none
Return Value
none
--*/
{
//DebugBreak();
EmptyCache();
if( m_pWbemLocater )
{
ReleaseWbemObject(m_pWbemLocater);
m_pWbemLocater = NULL;
}
}