2025-11-28 00:35:46 +09:00

1818 lines
36 KiB
C++

/*++
Copyright (C) Microsoft Corporation
Module Name:
XXXX
Abstract:
History:
--*/
#include <precomp.h>
#include <objbase.h>
#include <sddl.h>
#include <strsafe.h>
#include "Globals.h"
#include "Service.h"
#define MASK_CLIENT_ACCESS_BIND 1
static GENERIC_MAPPING s_ClientAccessMapping = {
0,
0,
STANDARD_RIGHTS_REQUIRED | MASK_CLIENT_ACCESS_BIND,
STANDARD_RIGHTS_REQUIRED | MASK_CLIENT_ACCESS_BIND
};
/******************************************************************************
*
* Name: g_Contact_Properties
*
*
* Description:
*
* Static snapshot of contact data
*
*****************************************************************************/
Object_Property g_Contact_Properties [] = {
0 , 21 , L"ID" , L"0000000000001" ,
0 , 8 , L"LastName" , L"Mandelshtam" ,
0 , 8 , L"FirstName" , L"Osip" ,
0 , 8 , L"HomePhone" , L"2069424877" ,
0 , 8 , L"WorkPhone" , L"4258649459" ,
1 , 0 , L"NA" , L"NA" ,
0 , 21 , L"ID" , L"0000000000002" ,
0 , 8 , L"LastName" , L"Pasternak" ,
0 , 8 , L"FirstName" , L"Boris" ,
0 , 8 , L"HomePhone" , L"4259434877" ,
0 , 8 , L"WorkPhone" , L"4258964949" ,
1 , 0 , L"NA" , L"NA" ,
0 , 21 , L"ID" , L"0000000000003" ,
0 , 8 , L"LastName" , L"Akhmatova" ,
0 , 8 , L"FirstName" , L"Anna" ,
0 , 8 , L"HomePhone" , L"7186724877" ,
0 , 8 , L"WorkPhone" , L"2128640059" ,
1 , 0 , L"NA" , L"NA" ,
2 , 0 , L"NA" , L"NA"
} ;
/******************************************************************************
*
* Name: g_Process_Properties
*
*
* Description:
*
* Static snapshot of process data
*
*****************************************************************************/
Object_Property g_Process_Properties [] = {
0 , 8 , L"Caption" , L"System Idle Process" ,
0 , 8 , L"CreationClassName" , L"Win32_Process" ,
0 , 8 , L"CSCreationClassName" , L"Win32_ComputerSystem" ,
0 , 8 , L"CSName" , L"STEVM_1" ,
0 , 8 , L"Description" , L"System Idle Process" ,
0 , 8 , L"Handle" , L"0" ,
0 , 19 , L"HandleCount" , L"0" ,
0 , 21 , L"KernelModeTime" , L"1484250781250" ,
0 , 8 , L"Name" , L"System Idle Process" ,
0 , 8 , L"OSCreationClassName" , L"Win32_OperatingSystem" ,
0 , 8 , L"OSName" , L"Microsoft Windows Whistler Server|C:\\WINNT|\\Device\\Harddisk0\\Partition1" ,
0 , 21 , L"OtherOperationCount" , L"0" ,
0 , 21 , L"OtherTransferCount" , L"0" ,
0 , 19 , L"PageFaults" , L"1" ,
0 , 19 , L"PageFileUsage" , L"0" ,
0 , 19 , L"ParentProcessId" , L"0" ,
0 , 19 , L"PeakPageFileUsage" , L"0" ,
0 , 21 , L"PeakVirtualSize" , L"0" ,
0 , 19 , L"PeakWorkingSetSize" , L"20480" ,
0 , 19 , L"Priority" , L"0" ,
0 , 21 , L"PrivatePageCount" , L"0" ,
0 , 19 , L"ProcessId" , L"0" ,
0 , 19 , L"QuotaNonPagedPoolUsage" , L"0" ,
0 , 19 , L"QuotaPagedPoolUsage" , L"0" ,
0 , 19 , L"QuotaPeakNonPagedPoolUsage" , L"0" ,
0 , 19 , L"QuotaPeakPagedPoolUsage" , L"0" ,
0 , 21 , L"ReadOperationCount" , L"0" ,
0 , 21 , L"ReadTransferCount" , L"0" ,
0 , 19 , L"SessionId" , L"0" ,
0 , 19 , L"ThreadCount" , L"2" ,
0 , 21 , L"UserModeTime" , L"0" ,
0 , 21 , L"VirtualSize" , L"0" ,
0 , 8 , L"WindowsVersion" , L"5.1.2496" ,
0 , 21 , L"WorkingSetSize" , L"20480" ,
0 , 21 , L"WriteOperationCount" , L"0" ,
0 , 21 , L"WriteTransferCount" , L"0" ,
1 , 0 , L"NA" , L"NA" ,
0 , 8 , L"Caption" , L"System" ,
0 , 8 , L"CreationClassName" , L"Win32_Process" ,
0 , 8 , L"CSCreationClassName" , L"Win32_ComputerSystem" ,
0 , 8 , L"CSName" , L"STEVM_1" ,
0 , 8 , L"Description" , L"System" ,
0 , 8 , L"Handle" , L"4" ,
0 , 19 , L"HandleCount" , L"1650" ,
0 , 21 , L"KernelModeTime" , L"617031250" ,
0 , 19 , L"MaximumWorkingSetSize" , L"1413120" ,
0 , 19 , L"MinimumWorkingSetSize" , L"0" ,
0 , 8 , L"Name" , L"System" ,
0 , 8 , L"OSCreationClassName" , L"Win32_OperatingSystem" ,
0 , 8 , L"OSName" , L"Microsoft Windows Whistler Server|C:\\WINNT|\\Device\\Harddisk0\\Partition1" ,
0 , 21 , L"OtherOperationCount" , L"29386" ,
0 , 21 , L"OtherTransferCount" , L"508628" ,
0 , 19 , L"PageFaults" , L"7085" ,
0 , 19 , L"PageFileUsage" , L"0" ,
0 , 19 , L"ParentProcessId" , L"0" ,
0 , 19 , L"PeakPageFileUsage" , L"0" ,
0 , 21 , L"PeakVirtualSize" , L"2043904" ,
0 , 19 , L"PeakWorkingSetSize" , L"831488" ,
0 , 19 , L"Priority" , L"8" ,
0 , 21 , L"PrivatePageCount" , L"32768" ,
0 , 19 , L"ProcessId" , L"4" ,
0 , 19 , L"QuotaNonPagedPoolUsage" , L"0" ,
0 , 19 , L"QuotaPagedPoolUsage" , L"0" ,
0 , 19 , L"QuotaPeakNonPagedPoolUsage" , L"0" ,
0 , 19 , L"QuotaPeakPagedPoolUsage" , L"0" ,
0 , 21 , L"ReadOperationCount" , L"92" ,
0 , 21 , L"ReadTransferCount" , L"542740" ,
0 , 19 , L"SessionId" , L"0" ,
0 , 19 , L"ThreadCount" , L"50" ,
0 , 21 , L"UserModeTime" , L"0" ,
0 , 21 , L"VirtualSize" , L"1884160" ,
0 , 8 , L"WindowsVersion" , L"5.1.2496" ,
0 , 21 , L"WorkingSetSize" , L"221184" ,
0 , 21 , L"WriteOperationCount" , L"10189" ,
0 , 21 , L"WriteTransferCount" , L"54440072" ,
1 , 0 , L"NA" , L"NA" ,
2 , 0 , L"NA" , L"NA"
} ;
/******************************************************************************
*
* Name: Set_Uint64
*
*
* Description:
*
* Sets a 64bit value into an instance
*
*****************************************************************************/
HRESULT Set_Uint64 (
IWbemClassObject *a_Instance ,
wchar_t *a_Name ,
const UINT64 &a_Uint64
)
{
wchar_t t_String [ 64 ] ;
StringCbPrintf(t_String, sizeof(t_String), L"%I64u" , a_Uint64 ) ;
VARIANT t_Variant ;
VariantInit ( & t_Variant ) ;
t_Variant.vt = VT_BSTR ;
t_Variant.bstrVal = SysAllocString ( t_String ) ;
if ( t_Variant.bstrVal )
{
HRESULT t_Result = a_Instance->Put ( a_Name , 0 , & t_Variant , 0 ) ;
VariantClear ( & t_Variant ) ;
return t_Result ;
}
else
{
return WBEM_E_OUT_OF_MEMORY ;
}
}
/******************************************************************************
*
* Name: Set_Uint32
*
*
* Description:
*
* Sets a 32bit value into an instance
*
*****************************************************************************/
HRESULT Set_Uint32 (
IWbemClassObject *a_Instance ,
wchar_t *a_Name ,
const DWORD &a_Uint32
)
{
VARIANT t_Variant ;
VariantInit ( & t_Variant ) ;
t_Variant.vt = VT_I4 ;
t_Variant.lVal = a_Uint32 ;
return a_Instance->Put ( a_Name , 0 , & t_Variant , 0 ) ;
}
/******************************************************************************
*
* Name: Set_String
*
*
* Description:
*
* Sets a string value into an instance
*
*****************************************************************************/
HRESULT Set_String (
IWbemClassObject *a_Instance ,
wchar_t *a_Name ,
wchar_t *a_String
)
{
VARIANT t_Variant ;
VariantInit ( & t_Variant ) ;
t_Variant.vt = VT_BSTR ;
t_Variant.bstrVal = SysAllocString ( a_String ) ;
if ( t_Variant.bstrVal )
{
HRESULT t_Result = a_Instance->Put ( a_Name , 0 , & t_Variant , 0 ) ;
VariantClear ( & t_Variant ) ;
return t_Result ;
}
else
{
return WBEM_E_OUT_OF_MEMORY ;
}
}
/******************************************************************************
*
* Name: SetProperty
*
*
* Description:
*
* Set an instance property based on it's type specified in the static
* process data definition.
*
*****************************************************************************/
HRESULT SetProperty (
IWbemClassObject *a_Instance ,
Object_Property &a_Property
)
{
HRESULT t_Result = S_OK ;
switch ( a_Property.m_Type )
{
case CIM_STRING:
{
t_Result = Set_String (
a_Instance ,
a_Property.m_Name ,
a_Property.m_Value
) ;
}
break ;
case CIM_UINT32:
{
ULONG t_Integer ;
swscanf_s ( a_Property.m_Value , L"%lu" , & t_Integer ) ;
t_Result = Set_Uint32 (
a_Instance ,
a_Property.m_Name ,
t_Integer
) ;
}
break ;
case CIM_UINT64:
{
UINT64 t_Integer ;
swscanf_s ( a_Property.m_Value , L"%I64u" , & t_Integer ) ;
t_Result = Set_Uint64 (
a_Instance ,
a_Property.m_Name ,
t_Integer
) ;
}
break ;
default:
{
WBEM_E_INVALID_PARAMETER ;
}
break ;
}
return t_Result ;
}
/******************************************************************************
*
* Name: CheckAccess
*
* Description: Allow provider to evaluate permissions against a security descriptor
*
* This method should be called by WMI providers in scenarios where
* they cannot or should not impersonate the client. This happens in two scenarios:
* a) when the providers access resources that are not protected by ACL's
* b) when the client connects at the impersonation level of RPC_C_IMP_LEVEL_IDENTIFY
*
*****************************************************************************/
HRESULT CheckAccess (SECURITY_DESCRIPTOR *a_SecurityDescriptor ,
DWORD a_Access ,
GENERIC_MAPPING *a_Mapping)
{
HRESULT t_Result = S_OK ;
HANDLE t_Token = NULL ;
BOOL t_Status = OpenThreadToken (
GetCurrentThread () ,
TOKEN_QUERY ,
TRUE ,
& t_Token
) ;
DWORD t_LastError = GetLastError () ;
if ( ! t_Status)
{
//the thread token should always be available
switch ( t_LastError )
{
case E_ACCESSDENIED:
{
return WBEM_E_ACCESS_DENIED ;
}
break ;
default:
{
return WBEM_E_FAILED ;
}
break ;
}
}
DWORD t_Access = 0 ;
BOOL t_AccessStatus = FALSE ;
PRIVILEGE_SET *t_PrivilegeSet = NULL ;
DWORD t_PrivilegeSetSize = 0 ;
MapGenericMask (
& a_Access ,
a_Mapping
) ;
t_Status = AccessCheck (
a_SecurityDescriptor ,
t_Token,
a_Access ,
a_Mapping ,
NULL ,
& t_PrivilegeSetSize ,
& t_Access ,
& t_AccessStatus
) ;
if (!t_Status || !t_AccessStatus )
{
DWORD t_LastError = GetLastError () ;
if ( t_LastError == ERROR_INSUFFICIENT_BUFFER )
{
t_PrivilegeSet = ( PRIVILEGE_SET * ) new BYTE [ t_PrivilegeSetSize ] ;
if ( t_PrivilegeSet )
{
t_Status = AccessCheck (
a_SecurityDescriptor ,
t_Token,
a_Access ,
a_Mapping ,
t_PrivilegeSet ,
& t_PrivilegeSetSize ,
& t_Access ,
& t_AccessStatus
) ;
if ( !t_Status || !t_AccessStatus )
{
t_Result = WBEM_E_ACCESS_DENIED ;
}
delete [] ( BYTE * ) t_PrivilegeSet ;
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
}
else
{
t_Result = WBEM_E_ACCESS_DENIED;
}
}
CloseHandle ( t_Token ) ;
return t_Result ;
}
/******************************************************************************
*
* Name: GetCurrentImpersonationLevel
*
*
* Description:
*
* Get COM impersonation level of caller.
*
*****************************************************************************/
DWORD GetCurrentImpersonationLevel ()
{
DWORD t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
HANDLE t_ThreadToken = NULL ;
BOOL t_Status = OpenThreadToken (
GetCurrentThread() ,
TOKEN_QUERY,
TRUE,
&t_ThreadToken
) ;
if ( t_Status )
{
SECURITY_IMPERSONATION_LEVEL t_Level = SecurityAnonymous ;
DWORD t_Returned = 0 ;
t_Status = GetTokenInformation (
t_ThreadToken ,
TokenImpersonationLevel ,
& t_Level ,
sizeof ( SECURITY_IMPERSONATION_LEVEL ) ,
& t_Returned
) ;
CloseHandle ( t_ThreadToken ) ;
if ( t_Status == FALSE )
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
}
else
{
switch ( t_Level )
{
case SecurityAnonymous:
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
}
break ;
case SecurityIdentification:
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_IDENTIFY ;
}
break ;
case SecurityImpersonation:
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE ;
}
break ;
case SecurityDelegation:
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_DELEGATE ;
}
break ;
default:
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
}
break ;
}
}
}
else
{
ULONG t_LastError = GetLastError () ;
if ( t_LastError == ERROR_NO_IMPERSONATION_TOKEN || t_LastError == ERROR_NO_TOKEN )
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_DELEGATE ;
}
else
{
if ( t_LastError == ERROR_CANT_OPEN_ANONYMOUS )
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
}
else
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
}
}
}
return t_ImpersonationLevel ;
}
/******************************************************************************
*
* Name: CProvider_IWbemServices
*
*
* Description:
*
* Constructor for object. Initialize variables to NULL. Increment global object count
*
*****************************************************************************/
CProvider_IWbemServices :: CProvider_IWbemServices () :
m_ReferenceCount ( 0 ) ,
m_User ( NULL ) ,
m_Locale ( NULL ) ,
m_Namespace ( NULL ) ,
m_CoreService ( NULL ) ,
m_ComputerName ( NULL ) ,
m_OperatingSystemVersion ( NULL ) ,
m_Win32_ProcessEx_Object ( NULL ),
m_ContactInfo_Object (NULL)
{
InitializeCriticalSection ( & m_CriticalSection ) ;
InterlockedIncrement ( & Provider_Globals :: s_ObjectsInProgress ) ;
}
/******************************************************************************
*
* Name: ~CProvider_IWbemServices
*
*
* Description:
*
* Constructor for object. Uninitialize variables . Decrement global object count
*
*****************************************************************************/
CProvider_IWbemServices :: ~CProvider_IWbemServices ()
{
DeleteCriticalSection ( & m_CriticalSection ) ;
if ( m_User )
{
SysFreeString ( m_User ) ;
}
if ( m_Locale )
{
SysFreeString ( m_Locale ) ;
}
if ( m_Namespace )
{
SysFreeString ( m_Namespace ) ;
}
if ( m_CoreService )
{
m_CoreService->Release () ;
}
if ( m_Win32_ProcessEx_Object )
{
m_Win32_ProcessEx_Object->Release () ;
}
if ( m_ContactInfo_Object )
{
m_ContactInfo_Object->Release () ;
}
if ( m_ComputerName )
{
SysFreeString ( m_ComputerName ) ;
}
if ( m_OperatingSystemVersion )
{
SysFreeString ( m_OperatingSystemVersion ) ;
}
InterlockedDecrement ( & Provider_Globals :: s_ObjectsInProgress ) ;
}
/******************************************************************************
*
* Name: AddRef
*
*
* Description:
*
* Perform Locked increment. Keep com object Alive.
*
*****************************************************************************/
STDMETHODIMP_(ULONG) CProvider_IWbemServices :: AddRef ( void )
{
return InterlockedIncrement ( & m_ReferenceCount ) ;
}
/******************************************************************************
*
* Name:
*
* Release
*
* Description:
*
* Perform Locked decrement. Attempt to destroy com object.
*
*****************************************************************************/
STDMETHODIMP_(ULONG) CProvider_IWbemServices :: Release ( void )
{
LONG t_Reference ;
if ( ( t_Reference = InterlockedDecrement ( & m_ReferenceCount ) ) == 0 )
{
/*
* No more outstanding references, delete the object.
*/
delete this ;
}
return t_Reference ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
STDMETHODIMP CProvider_IWbemServices :: QueryInterface (
REFIID a_Riid ,
LPVOID FAR *a_Void
)
{
/*
* Just clean up out parameter first.
*/
*a_Void = NULL ;
if ( a_Riid == IID_IUnknown )
{
*a_Void = ( LPVOID ) this ;
}
else if ( a_Riid == IID_IWbemServices )
{
/*
* Make sure we support event consumer interface IWbemServices
*/
*a_Void = ( LPVOID ) ( IWbemServices * ) this ;
}
else if ( a_Riid == IID_IWbemPropertyProvider )
{
*a_Void = ( LPVOID ) ( IWbemPropertyProvider * ) this ;
}
else if ( a_Riid == IID_IWbemProviderInit )
{
*a_Void = ( LPVOID ) ( IWbemProviderInit * ) this ;
}
else if ( a_Riid == IID_IWbemShutdown )
{
*a_Void = ( LPVOID ) ( IWbemShutdown * ) this ;
}
if ( *a_Void )
{
( ( LPUNKNOWN ) *a_Void )->AddRef () ;
return ResultFromScode ( S_OK ) ;
}
else
{
return ResultFromScode ( E_NOINTERFACE ) ;
}
}
/******************************************************************************
*
* Name: CancelAsyncCall
*
*
* Description:
*
* Allow provider to determine if call was cancelled.
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: CancelAsyncCall (
IWbemObjectSink *a_Sink
)
{
HRESULT t_Result = WBEM_E_NOT_AVAILABLE ;
return t_Result ;
}
/******************************************************************************
*
* Name: GetObjectAsync
*
*
* Description:
*
* Allow provider to respond to a query for a specific object
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: GetObjectAsync (
const BSTR a_ObjectPath ,
long a_Flags ,
IWbemContext *a_Context ,
IWbemObjectSink *a_Sink
)
{
HRESULT t_Result = WBEM_E_NOT_FOUND ;
return t_Result ;
}
/******************************************************************************
*
* Name: PutClassAsync
*
*
* Description:
*
* Not required for instance providers.,
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: PutClassAsync (
IWbemClassObject *a_Object ,
long a_Flags ,
IWbemContext FAR *a_Context ,
IWbemObjectSink *a_Sink
)
{
return WBEM_E_NOT_FOUND ;
}
/******************************************************************************
*
* Name: DeleteClassAsync
*
*
* Description:
*
* Not required for instance providers.,
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: DeleteClassAsync (
const BSTR a_Class ,
long a_Flags,
IWbemContext *a_Context ,
IWbemObjectSink *a_Sink
)
{
return WBEM_E_NOT_AVAILABLE ;
}
/******************************************************************************
*
* Name: CreateClassEnumAsync
*
*
* Description:
*
* Not required for instance providers.,
*
*****************************************************************************/
SCODE CProvider_IWbemServices :: CreateClassEnumAsync (
const BSTR a_SuperClass ,
long a_Flags ,
IWbemContext *a_Context ,
IWbemObjectSink *a_Sink
)
{
return WBEM_E_NOT_FOUND ;
}
/******************************************************************************
*
* Name: PutInstanceAsync
*
*
* Description:
*
* Allow provider to create/update a specific object
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: PutInstanceAsync (
IWbemClassObject *a_Instance ,
long a_Flags ,
IWbemContext *a_Context ,
IWbemObjectSink *a_Sink
)
{
HRESULT t_Result = WBEM_E_NOT_AVAILABLE ;
return t_Result ;
}
/******************************************************************************
*
* Name: DeleteInstanceAsync
*
*
* Description:
*
* Allow provider to delete a specific object
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: DeleteInstanceAsync (
const BSTR a_ObjectPath ,
long a_Flags ,
IWbemContext *a_Context ,
IWbemObjectSink *a_Sink
)
{
HRESULT t_Result = WBEM_E_NOT_AVAILABLE ;
return t_Result ;
}
/******************************************************************************
*
* Name: CreateInstanceEnumAsync
*
*
* Description:
*
* This provider enumerates instances of Win32_ProcessEx and ContactInfo classes.
*
* To access Win32_ProcessEx objects, this provider impersonates the client (modeling the
* scenario where protected OS objects would surfaced by a provider - even though
* in this sample the objects are in fact hard-coded and not protected).
*
* ContactInfo objects surfaced by this provider that are not protected by ACL's, so
* the provider performs access checks only allowing certain groups to view ContactInfo data
* (acts as an Identity-level provider)
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: CreateInstanceEnumAsync (
const BSTR a_Class ,
long a_Flags ,
IWbemContext *a_Context ,
IWbemObjectSink *a_Sink
)
{
//Impersonate the client
HRESULT hr = S_OK ;
if ( _wcsicmp ( a_Class , L"ContactInfo" ) == 0 )
{
//Grant access for built-in admins, local system, local admins, local service and network service.
PSECURITY_DESCRIPTOR secDescriptor = NULL;
BOOL bRes = ConvertStringSecurityDescriptorToSecurityDescriptor //this function is only available on Windows 2000 and above
( L"O:BAG:BAD:(A;;0x10000001;;;BA)(A;;0x10000001;;;SY)(A;;0x10000001;;;LA)(A;;0x10000001;;;SY)(A;;0x10000001;;;S-1-5-20)(A;;0x10000001;;;S-1-5-19)",
SDDL_REVISION_1,
(PSECURITY_DESCRIPTOR *) &secDescriptor,
NULL);
if (! bRes)
{
hr = WBEM_E_ACCESS_DENIED;
a_Sink->SetStatus ( 0 , hr , NULL , NULL ) ;
return hr ;
}
hr = CoImpersonateClient () ;
if ( FAILED ( hr ) )
{
LocalFree(secDescriptor);
a_Sink->SetStatus ( 0 , hr , NULL , NULL ) ;
return hr ;
}
// perform an access check.
hr = CheckAccess((SECURITY_DESCRIPTOR *)secDescriptor,
MASK_CLIENT_ACCESS_BIND,
&s_ClientAccessMapping);
LocalFree(secDescriptor);
// Revert before we perform any operations
CoRevertToSelf () ;
if (FAILED(hr))
{
hr = WBEM_E_ACCESS_DENIED;
a_Sink->SetStatus ( 0 , hr , NULL , NULL ) ;
return hr ;
}
//Enumerate the instances.
hr = CreateInstanceEnumAsync_Contacts (
m_ContactInfo_Object ,
a_Flags ,
a_Context ,
a_Sink
) ;
}
else if ( _wcsicmp ( a_Class , L"Win32_ProcessEx" ) == 0 )
{
hr = CoImpersonateClient () ;
if ( FAILED ( hr ) )
{
a_Sink->SetStatus ( 0 , hr , NULL , NULL ) ;
return hr ;
}
// Check to see if call is at the RPC_C_IMP_LEVEL_IDENTIFY level. If that's the case,
// the provider will not be able to impersonate the client to access the protected Win32_ProcessEx resources.
// However, the provider can decide perform an access check to see if the client is sufficiently privileged.
//
// Please keep in mind that if in the MOF file __Win32Provider instabce sets the HostingModel
// to Decoupled:Com (the default), the original client impersonation level will be lowered to
// RPC_C_IMP_LEVEL_IDENTIFY before calling into provider. To allow original client
// impersonation level through to provider, set the HostingModel to
// Decoupled:Com:FoldIdentity(FALSE}.
// See comments in the MOF file for more info.
DWORD t_CurrentImpersonationLevel = GetCurrentImpersonationLevel () ;
if ( t_CurrentImpersonationLevel < RPC_C_IMP_LEVEL_IMPERSONATE )
{
// Revert before we perform any operations
CoRevertToSelf () ;
hr = WBEM_E_ACCESS_DENIED;
a_Sink->SetStatus ( 0 , hr , NULL , NULL ) ;
return hr ;
}
//Enumerate the instances.
hr = CreateInstanceEnumAsync_Process (
m_Win32_ProcessEx_Object ,
a_Flags ,
a_Context ,
a_Sink
) ;
CoRevertToSelf () ;
}
else
{
hr = WBEM_E_INVALID_CLASS ;
}
/*
* Inform WMI of status of call.
*/
a_Sink->SetStatus ( 0 , hr , NULL , NULL ) ;
return hr ;
}
/******************************************************************************
*
* Name: ExecQueryAsync
*
*
* Description:
*
* Enumerate instances based on a WQL query.
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: ExecQueryAsync (
const BSTR a_QueryFormat,
const BSTR a_Query,
long a_Flags,
IWbemContext *a_Context ,
IWbemObjectSink *a_Sink
)
{
return WBEM_E_NOT_AVAILABLE ;
}
/******************************************************************************
*
* Name: ExecMethodAsync
*
*
* Description:
*
* Allow provider to execute a method.
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: ExecMethodAsync (
const BSTR a_ObjectPath ,
const BSTR a_MethodName ,
long a_Flags ,
IWbemContext *a_Context ,
IWbemClassObject *a_InParams ,
IWbemObjectSink *a_Sink
)
{
HRESULT t_Result = WBEM_E_NOT_AVAILABLE ;
return t_Result ;
}
/******************************************************************************
*
* Name: GettProperty
*
*
* Description:
*
* Place holder for property provider method. Currently not used.
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: GetProperty (
long a_Flags ,
const BSTR a_Locale ,
const BSTR a_ClassMapping ,
const BSTR a_InstanceMapping ,
const BSTR a_PropertyMapping ,
VARIANT *a_Value
)
{
if ( _wcsicmp ( a_PropertyMapping , L"ExtraProperty1" ) == 0 )
{
}
else
{
if ( _wcsicmp ( a_PropertyMapping , L"ExtraProperty2" ) == 0 )
{
}
else
{
}
}
return S_OK ;
}
/******************************************************************************
*
* Name: PutProperty
*
*
* Description:
*
* Place holder for property provider method. Currently not used.
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: PutProperty (
long a_Flags ,
const BSTR a_Locale ,
const BSTR a_ClassMapping ,
const BSTR a_InstanceMapping ,
const BSTR a_PropertyMapping ,
const VARIANT *a_Value
)
{
if ( _wcsicmp ( a_PropertyMapping , L"ExtraProperty1" ) == 0 )
{
}
else
{
if ( _wcsicmp ( a_PropertyMapping , L"ExtraProperty2" ) == 0 )
{
}
else
{
}
}
return S_OK ;
}
/******************************************************************************
*
* Name: Initialize
*
*
* Description:
*
* Wmi calls this optional interface to inform the provider of
* configuration information associated within the client, locale
* and namespace. Provider retains this information for future use.
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: Initialize (
LPWSTR a_User,
LONG a_Flags,
LPWSTR a_Namespace,
LPWSTR a_Locale,
IWbemServices *a_CoreService, // For anybody
IWbemContext *a_Context,
IWbemProviderInitSink *a_Sink // For init signals
)
{
HRESULT t_Result = S_OK ;
if ( m_User )
{
SysFreeString ( m_User ) ;
m_User = NULL ;
}
if ( m_Locale )
{
SysFreeString ( m_Locale ) ;
m_Locale = NULL ;
}
if ( m_Namespace )
{
SysFreeString ( m_Namespace ) ;
m_Namespace = NULL ;
}
if ( m_CoreService )
{
m_CoreService->Release () ;
m_CoreService = NULL ;
}
if ( m_Win32_ProcessEx_Object )
{
m_Win32_ProcessEx_Object->Release () ;
m_Win32_ProcessEx_Object = NULL ;
}
if ( m_ContactInfo_Object )
{
m_Win32_ProcessEx_Object->Release () ;
m_Win32_ProcessEx_Object = NULL ;
}
if ( m_ComputerName )
{
SysFreeString ( m_ComputerName ) ;
m_ComputerName = NULL ;
}
if ( m_OperatingSystemVersion )
{
SysFreeString ( m_OperatingSystemVersion ) ;
m_OperatingSystemVersion = NULL ;
}
/*
* Impersonate and check impersonation level.
*/
t_Result = CoImpersonateClient () ;
if ( SUCCEEDED ( t_Result ) )
{
if ( GetCurrentImpersonationLevel () == RPC_C_IMP_LEVEL_IDENTIFY )
{
CoRevertToSelf () ;
}
}
if ( a_CoreService )
{
m_CoreService = a_CoreService ;
m_CoreService->AddRef () ;
}
else
{
t_Result = WBEM_E_INVALID_PARAMETER ;
}
if ( SUCCEEDED ( t_Result ) )
{
if ( a_User )
{
m_User = SysAllocString ( a_User ) ;
if ( m_User == NULL )
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
}
}
if ( SUCCEEDED ( t_Result ) )
{
if ( a_Locale )
{
m_Locale = SysAllocString ( a_Locale ) ;
if ( m_Locale == NULL )
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
}
}
if ( SUCCEEDED ( t_Result ) )
{
if ( a_Namespace )
{
m_Namespace = SysAllocString ( a_Namespace ) ;
if ( m_Namespace == NULL )
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
}
}
BSTR t_Class;
if ( SUCCEEDED ( t_Result ) )
{
t_Class = SysAllocString ( L"Win32_ProcessEx" ) ;
if ( !t_Class )
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
else
{
t_Result = m_CoreService->GetObject (
t_Class ,
0 ,
a_Context ,
& m_Win32_ProcessEx_Object ,
NULL
) ;
SysFreeString ( t_Class ) ;
}
}
if ( SUCCEEDED ( t_Result ) )
{
t_Class = SysAllocString( L"ContactInfo" );
if ( !t_Class )
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
else
{
t_Result = m_CoreService->GetObject (
t_Class ,
0 ,
a_Context ,
& m_ContactInfo_Object ,
NULL
) ;
SysFreeString ( t_Class ) ;
}
}
if ( SUCCEEDED ( t_Result ) )
{
m_ComputerName = SysAllocStringLen ( NULL , MAX_COMPUTERNAME_LENGTH + 1 ) ;
if ( m_ComputerName )
{
DWORD t_Length = MAX_COMPUTERNAME_LENGTH + 1 ;
if (! GetComputerName ( m_ComputerName , & t_Length ))
{
t_Result = WBEM_E_FAILED ;
}
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
}
if ( SUCCEEDED ( t_Result ) )
{
OSVERSIONINFO t_VersionInfo ;
t_VersionInfo.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO ) ;
if ( GetVersionEx ( & t_VersionInfo ) )
{
m_OperatingSystemVersion = SysAllocStringLen ( NULL , _MAX_PATH ) ;
if ( m_OperatingSystemVersion )
{
StringCbPrintfW(m_OperatingSystemVersion, SysStringByteLen(m_OperatingSystemVersion),
L"%d.%d.%hu", t_VersionInfo.dwMajorVersion , t_VersionInfo.dwMinorVersion , LOWORD ( t_VersionInfo.dwBuildNumber ) ) ;
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
}
else
{
t_Result = WBEM_E_FAILED ;
}
}
CoRevertToSelf () ;
a_Sink->SetStatus ( t_Result , 0 ) ;
return t_Result ;
}
/******************************************************************************
*
* Name: Shutdown
*
*
* Description:
*
* Optional interface and method that informs provider of object implementation
* being released by WMI. Shutdown is not guaranteed to be called on system
* shutdown.
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: Shutdown (
LONG a_Flags ,
ULONG a_MaxMilliSeconds ,
IWbemContext *a_Context
)
{
HRESULT t_Result = S_OK ;
return t_Result ;
}
/******************************************************************************
*
* Name: CreateInstanceEnumAsync_Contacts
*
*
* Description:
*
* Enumerate all static instances of the ContactInfo class.
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: CreateInstanceEnumAsync_Contacts (
IWbemClassObject *a_ClassObject ,
long a_Flags ,
IWbemContext __RPC_FAR *a_Context,
IWbemObjectSink FAR *a_Sink
)
{
HRESULT t_Result = S_OK ;
/*
* Count the instances
*/
ULONG t_Count = 0 ;
Object_Property *t_Property = g_Contact_Properties ;
while ( SUCCEEDED ( t_Result ) && t_Property )
{
BOOL t_Loop = TRUE ;
while ( t_Loop )
{
switch ( t_Property->m_State )
{
case 0:
{
t_Property ++ ;
}
break ;
case 1:
{
t_Loop = FALSE ;
t_Property ++ ;
t_Count ++ ;
}
break ;
case 2:
{
t_Loop = FALSE ;
t_Property = NULL ;
} ;
default:
{
}
break ;
}
}
}
if ( t_Count )
{
/*
* Create the array of instances
*/
ULONG t_Index = 0 ;
IWbemClassObject **t_ObjectArray = new IWbemClassObject * [ t_Count ] ;
if ( t_ObjectArray )
{
for ( ULONG t_ObjectIndex = 0 ; t_ObjectIndex < t_Count ; t_ObjectIndex ++ )
{
t_ObjectArray [ t_ObjectIndex ] = NULL ;
}
t_Result = a_ClassObject->SpawnInstance (
0 ,
& t_ObjectArray [ t_Index ]
) ;
Object_Property *t_Property = g_Contact_Properties ;
while ( SUCCEEDED ( t_Result ) && t_Property )
{
BOOL t_Loop = TRUE ;
while ( t_Loop )
{
switch ( t_Property->m_State )
{
case 0:
{
/*
* Set property value for the current instance
*/
SetProperty ( t_ObjectArray [ t_Index ] , *t_Property ) ;
t_Property ++ ;
}
break ;
case 1:
{
/*
* Create a new instance
*/
t_Loop = FALSE ;
t_Index ++ ;
if ( t_Index < t_Count )
{
t_Result = a_ClassObject->SpawnInstance (
0 ,
& t_ObjectArray [ t_Index ]
) ;
}
t_Property ++ ;
}
break ;
case 2:
{
/*
* Break from loop when we've reached the end of the data
*/
t_Loop = FALSE ;
t_Property = NULL ;
} ;
default:
{
}
break ;
}
}
}
/*
* Send the instances to WMI.
*/
if ( SUCCEEDED ( t_Result ) )
{
t_Result = a_Sink->Indicate ( t_Count , t_ObjectArray ) ;
}
/*
* Discard
*/
for ( t_Index = 0 ; t_Index < t_Count ; t_Index ++ )
{
if ( t_ObjectArray [ t_Index ] )
{
t_ObjectArray [ t_Index ]->Release () ;
}
}
delete [] t_ObjectArray ;
}
}
return t_Result ;
}
/******************************************************************************
*
* Name: CreateInstanceEnumAsync_Process
*
*
* Description:
*
* Enumerate all static instances of the Win32_ProcessEx class.
*
*****************************************************************************/
HRESULT CProvider_IWbemServices :: CreateInstanceEnumAsync_Process (
IWbemClassObject *a_ClassObject ,
long a_Flags ,
IWbemContext __RPC_FAR *a_Context,
IWbemObjectSink FAR *a_Sink
)
{
HRESULT t_Result = S_OK ;
/*
* Count the instances
*/
ULONG t_Count = 0 ;
Object_Property *t_Property = g_Process_Properties ;
while ( SUCCEEDED ( t_Result ) && t_Property )
{
BOOL t_Loop = TRUE ;
while ( t_Loop )
{
switch ( t_Property->m_State )
{
case 0:
{
t_Property ++ ;
}
break ;
case 1:
{
t_Loop = FALSE ;
t_Property ++ ;
t_Count ++ ;
}
break ;
case 2:
{
t_Loop = FALSE ;
t_Property = NULL ;
} ;
default:
{
}
break ;
}
}
}
if ( t_Count )
{
/*
* Create the array of instances
*/
ULONG t_Index = 0 ;
IWbemClassObject **t_ObjectArray = new IWbemClassObject * [ t_Count ] ;
if ( t_ObjectArray )
{
for ( ULONG t_ObjectIndex = 0 ; t_ObjectIndex < t_Count ; t_ObjectIndex ++ )
{
t_ObjectArray [ t_ObjectIndex ] = NULL ;
}
t_Result = a_ClassObject->SpawnInstance (
0 ,
& t_ObjectArray [ t_Index ]
) ;
Object_Property *t_Property = g_Process_Properties ;
while ( SUCCEEDED ( t_Result ) && t_Property )
{
BOOL t_Loop = TRUE ;
while ( t_Loop )
{
switch ( t_Property->m_State )
{
case 0:
{
/*
* Set property value for the current instance
*/
SetProperty ( t_ObjectArray [ t_Index ] , *t_Property ) ;
t_Property ++ ;
}
break ;
case 1:
{
/*
* Create a new instance
*/
t_Loop = FALSE ;
t_Index ++ ;
if ( t_Index < t_Count )
{
t_Result = a_ClassObject->SpawnInstance (
0 ,
& t_ObjectArray [ t_Index ]
) ;
}
t_Property ++ ;
}
break ;
case 2:
{
/*
* Break from loop when we've reached the end of the data
*/
t_Loop = FALSE ;
t_Property = NULL ;
} ;
default:
{
}
break ;
}
}
}
/*
* Send the instances to WMI.
*/
if ( SUCCEEDED ( t_Result ) )
{
t_Result = a_Sink->Indicate ( t_Count , t_ObjectArray ) ;
}
/*
* Discard
*/
for ( t_Index = 0 ; t_Index < t_Count ; t_Index ++ )
{
if ( t_ObjectArray [ t_Index ] )
{
t_ObjectArray [ t_Index ]->Release () ;
}
}
delete [] t_ObjectArray ;
}
}
return t_Result ;
}