291 lines
10 KiB
C++
291 lines
10 KiB
C++
//
|
|
|
|
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
#define _WIN32_WINNT 0x0500
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
|
|
#include <objbase.h>
|
|
#include <wbemcli.h>
|
|
|
|
|
|
// These are the declarations for the functions that have sample code for various operations
|
|
void GetAClass(IWbemServices *pServices);
|
|
void EnumerateSubClassesOfAClass(IWbemServices *pServices);
|
|
void GetAnInstance(IWbemServices *pServices);
|
|
void DeleteAnInstance(IWbemServices *pServices);
|
|
void CreateAnInstance(IWbemServices *pServices);
|
|
void EnumerateInstancesOfAClass(IWbemServices *pServices);
|
|
void ExecuteAQuery(IWbemServices *pServices);
|
|
|
|
|
|
void main()
|
|
{
|
|
// Initialize COM. Remember the DS Provider needs impersonation to be called
|
|
// so you have to call the COM function CoInitializeSecurity()
|
|
// For this, you must #define _WIN32_WINNT to be greater than 0x0400. See top of file.
|
|
if(SUCCEEDED(CoInitialize(NULL)) && SUCCEEDED(CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0)))
|
|
{
|
|
// Create the IWbemLocator object
|
|
IWbemLocator *t_pLocator = NULL;
|
|
if (SUCCEEDED(CoCreateInstance(CLSID_WbemLocator,
|
|
0,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator, (LPVOID *) &t_pLocator)))
|
|
{
|
|
// Connect to the correct namespace
|
|
// The DS Provider operates in the root\directory\LDAP namespace
|
|
IWbemServices *t_pNamespace = NULL;
|
|
BSTR strNamespace = SysAllocString(L"root\\directory\\LDAP");
|
|
if(SUCCEEDED(t_pLocator->ConnectServer(strNamespace, NULL, NULL, NULL, 0, NULL, NULL, &t_pNamespace)))
|
|
{
|
|
|
|
// This is *very important* since the DSProvider goes accross the process
|
|
// Every IWbemServices interface obtained form the IWbemLocator has to
|
|
// have the COM interface function IClientSecutiry::SetBlanket() called on it
|
|
// for the DS Provider to work
|
|
IClientSecurity *t_pSecurity = NULL ;
|
|
if(SUCCEEDED(t_pNamespace->QueryInterface ( IID_IClientSecurity , (LPVOID *) & t_pSecurity )))
|
|
{
|
|
t_pSecurity->SetBlanket(
|
|
t_pNamespace ,
|
|
RPC_C_AUTHN_WINNT,
|
|
RPC_C_AUTHZ_NONE,
|
|
NULL,
|
|
RPC_C_AUTHN_LEVEL_CONNECT ,
|
|
RPC_C_IMP_LEVEL_IMPERSONATE,
|
|
NULL,
|
|
EOAC_NONE
|
|
);
|
|
t_pSecurity->Release () ;
|
|
}
|
|
|
|
/**************************************************************
|
|
*
|
|
* THESE FUNCTIONS BELOW SHOW HOW TO DO THE VARIOUS OPERATIONS
|
|
* THEY ARE GROUPED ACCORDING TO THE VARIOUS DS PROVIDERS
|
|
*
|
|
**************************************************************/
|
|
|
|
/************************************************************
|
|
* DS CLASS OPERATIONS - USING THE DS CLASS PROVIDER
|
|
************************************************************/
|
|
GetAClass(t_pNamespace);
|
|
EnumerateSubClassesOfAClass(t_pNamespace);
|
|
|
|
|
|
/************************************************************
|
|
* DS INSTANCE OPERATIONS - USING THE DS INSTANCE PROVIDER
|
|
************************************************************/
|
|
GetAnInstance(t_pNamespace);
|
|
DeleteAnInstance(t_pNamespace);
|
|
EnumerateInstancesOfAClass(t_pNamespace);
|
|
ExecuteAQuery(t_pNamespace);
|
|
|
|
/************************************************************
|
|
* CLASS ASSOCIATIONS - USING THE DS CLASS ASSOCIATIONS PROVIDER
|
|
************************************************************/
|
|
|
|
/************************************************************
|
|
* INSTANCE ASSOCIATIONS - USING THE DS INSTANCE ASSOCIATIONS PROVIDER
|
|
************************************************************/
|
|
|
|
|
|
t_pNamespace->Release();
|
|
}
|
|
SysFreeString(strNamespace);
|
|
t_pLocator->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void GetAClass(IWbemServices *pServices)
|
|
{
|
|
HRESULT result = S_OK;
|
|
|
|
// Get an Active Directory class from the DS Provider
|
|
// Let's get the AD class "person". This will prefixed with "ds_" when it maps to WMI
|
|
// Hence we should get the class "ds_person" in WMI
|
|
|
|
BSTR strClassName = SysAllocString(L"ds_person");
|
|
IWbemClassObject *pClass = NULL;
|
|
if(SUCCEEDED(result = pServices->GetObject(strClassName, 0, NULL, &pClass, NULL)))
|
|
{
|
|
wprintf(L"Got the class %s successfully!\n", strClassName);
|
|
|
|
// Now browse the properties of the class by using the
|
|
// functions on IWbemClassbject ...
|
|
|
|
|
|
|
|
// Then release it
|
|
pClass->Release();
|
|
|
|
}
|
|
else
|
|
wprintf(L"Get class operation on %s failed because of WMI error %x\n", strClassName, result);
|
|
SysFreeString(strClassName);
|
|
}
|
|
|
|
void EnumerateSubClassesOfAClass(IWbemServices *pServices)
|
|
{
|
|
HRESULT result = S_OK;
|
|
|
|
// Let's try to see what classes are derived in the Active Directoy Schema
|
|
// from the Active Directory class "person"
|
|
// Hence from WMI, we will have to do a deep enumeration of
|
|
// all the subclasses of the WMI class "ds_user"
|
|
BSTR strSuperClassName = SysAllocString(L"ds_person");
|
|
IEnumWbemClassObject *pEnumClasses = NULL;
|
|
if( SUCCEEDED(result = pServices->CreateClassEnum(strSuperClassName, WBEM_FLAG_DEEP, NULL, &pEnumClasses)))
|
|
{
|
|
// Walk thru the enumeration and examine each class
|
|
IWbemClassObject *pNextSubClass = NULL;
|
|
ULONG dwCount = 0;
|
|
ULONG dwNextReturned = 0;
|
|
while(SUCCEEDED(result = pEnumClasses->Next( WBEM_INFINITE, 1, &pNextSubClass, &dwNextReturned)) &&
|
|
dwNextReturned == 1)
|
|
{
|
|
|
|
// Now browse the properties of the sub class by using the
|
|
// functions on IWbemClassbject ...
|
|
|
|
pNextSubClass->Release();
|
|
dwCount ++;
|
|
}
|
|
wprintf(L"The class %s has %d subclasses!\n", strSuperClassName, dwCount);
|
|
// Release the enumerator when done
|
|
pEnumClasses->Release();
|
|
}
|
|
else
|
|
wprintf(L"The subclass enumeration operation failed on %s because of WMI error %x\n", strSuperClassName, result);
|
|
SysFreeString(strSuperClassName);
|
|
}
|
|
|
|
void GetAnInstance(IWbemServices *pServices)
|
|
{
|
|
// Let's get an instance of the Active Directory class "user"
|
|
// A user called "administrator" typically exists in
|
|
|
|
// You will have to change this string to actually contain the ADSI path to the
|
|
// user object for Administrator on your domain.
|
|
BSTR strInstancePath = SysAllocString(L"ds_user.ADSIPath=\"LDAP://CN=Administrator,CN=Users,DC=dsprovider,DC=nttest,DC=microsoft,DC=com\"");
|
|
IWbemClassObject *pInstance = NULL;
|
|
HRESULT result = WBEM_E_FAILED;
|
|
if(SUCCEEDED(result = pServices->GetObject(strInstancePath, 0, NULL, &pInstance, NULL)))
|
|
{
|
|
// Go through some properties on the user
|
|
// Remember all properties get prefixed with "ds_"
|
|
BSTR strSamAccountName = SysAllocString(L"DS_sAMAccountName");
|
|
BSTR strLogonCount = SysAllocString(L"DS_logonCount");
|
|
|
|
VARIANT vSamAccountNameValue;
|
|
VARIANT vLogonCountValue;
|
|
VariantClear(&vSamAccountNameValue);
|
|
VariantClear(&vLogonCountValue);
|
|
if(SUCCEEDED(pInstance->Get(strSamAccountName, 0, &vSamAccountNameValue, NULL, NULL)) &&
|
|
SUCCEEDED(pInstance->Get(strLogonCount, 0, &vLogonCountValue, NULL, NULL)) )
|
|
{
|
|
wprintf(L"The user object for user %s was successfully retrieved! ", vSamAccountNameValue.bstrVal);
|
|
wprintf(L"It has a Logon Count of %d\n", vLogonCountValue.lVal);
|
|
}
|
|
else
|
|
wprintf(L"The GetObject() operation failed to get the required properties on the user object\n");
|
|
|
|
pInstance->Release();
|
|
}
|
|
else
|
|
wprintf(L"The GetObject() operation failed on %s because of WMI error %x\n", strInstancePath, result);
|
|
SysFreeString(strInstancePath);
|
|
}
|
|
|
|
void DeleteAnInstance(IWbemServices *pServices)
|
|
{
|
|
// Let's delete an instance of the Active Directory class "user"
|
|
// Create a user called "dummy" before executing this
|
|
|
|
// You will have to change this string to actually contain the ADSI path to the
|
|
// user object for "dummy" on your domain.
|
|
BSTR strInstancePath = SysAllocString(L"ds_user.ADSIPath=\"LDAP://CN=dummy,CN=Users,DC=dsprovider,DC=nttest,DC=microsoft,DC=com\"");
|
|
|
|
HRESULT result = WBEM_E_FAILED;
|
|
if(SUCCEEDED(result = pServices->DeleteInstance(strInstancePath, 0, NULL, NULL)))
|
|
wprintf(L"Deleted the user %s successfully!\n", strInstancePath);
|
|
else
|
|
wprintf(L"Could not delete the user %s due to WMI error %x\n", strInstancePath, result);
|
|
|
|
SysFreeString(strInstancePath);
|
|
}
|
|
|
|
void EnumerateInstancesOfAClass(IWbemServices *pServices)
|
|
{
|
|
HRESULT result = S_OK;
|
|
|
|
// Let's try to see how many users are in the domain
|
|
// For this, we have to enumerate the instances of the class "ds_user"
|
|
BSTR strClassName = SysAllocString(L"ds_user");
|
|
IEnumWbemClassObject *pEnumInstances = NULL;
|
|
if( SUCCEEDED(result = pServices->CreateInstanceEnum(strClassName, WBEM_FLAG_SHALLOW, NULL, &pEnumInstances)))
|
|
{
|
|
// Walk thru the enumeration and print the class names
|
|
IWbemClassObject *pNextInstance = NULL;
|
|
ULONG dwCount = 0;
|
|
ULONG dwNextReturned = 0;
|
|
pEnumInstances->Reset();
|
|
while(SUCCEEDED(result = pEnumInstances->Next( WBEM_INFINITE, 1, &pNextInstance, &dwNextReturned)) &&
|
|
dwNextReturned == 1)
|
|
{
|
|
|
|
// Now browse the properties of the instance by using the
|
|
// functions on IWbemClassbject ...
|
|
|
|
pNextInstance->Release();
|
|
dwCount ++;
|
|
}
|
|
wprintf(L"There are %d users in the domain!\n", dwCount);
|
|
}
|
|
else
|
|
wprintf(L"The instance enumeration operation failed on %s because of WMI error %x\n", strClassName, result);
|
|
SysFreeString(strClassName);
|
|
}
|
|
|
|
void ExecuteAQuery(IWbemServices *pServices)
|
|
{
|
|
// Let's try to find those users who have logged on more than 4 times since their accounts were created.
|
|
// The Query is formulated like this
|
|
BSTR strQuery = SysAllocString(L"select * from ds_user where ds_logonCount>4");
|
|
|
|
// For this, the query language is WQL
|
|
BSTR strQueryLanguage = SysAllocString(L"WQL");
|
|
|
|
IEnumWbemClassObject *pEnumerator = NULL;
|
|
HRESULT result = WBEM_E_FAILED;
|
|
if(SUCCEEDED(result = pServices->ExecQuery(strQueryLanguage, strQuery, WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
|
|
{
|
|
// Walk thru the enumeration and examine each object
|
|
IWbemClassObject *pNextInstance = NULL;
|
|
ULONG dwCount = 0;
|
|
ULONG dwNextReturned = 0;
|
|
while(SUCCEEDED(result = pEnumerator->Next( WBEM_INFINITE, 1, &pNextInstance, &dwNextReturned)) &&
|
|
dwNextReturned == 1)
|
|
{
|
|
|
|
// Now browse the properties of each user instance by using the
|
|
// functions of IWbemClassbject ...
|
|
|
|
// Releasse it when done
|
|
pNextInstance->Release();
|
|
dwCount ++;
|
|
}
|
|
wprintf(L"There are %d users who have logged in more than 4 times!\n", dwCount);
|
|
|
|
// Release the enumerator when done
|
|
pEnumerator->Release();
|
|
}
|
|
}
|
|
|
|
|