I am trying to print the names of all the properties of an Active Directory object using the below code:
HRESULT ActiveDirectoryWrapper::PrintAllProperties(IADs *pADs) {
IADsPropertyList *pPList = NULL;
// Getting info of object
pADs->GetInfo();
HRESULT hr = pADs->QueryInterface(IID_IADsPropertyList, (void**)&pPList);
if (SUCCEEDED(hr))
{
// Get the number of properties in the object
LONG lCount = 0;
hr = pPList->get_PropertyCount(&lCount);
if (SUCCEEDED(hr))
{
// Iterate over the object's properties and print their names and values
for (LONG i = 0; i < lCount; i )
{
// Retrieve the property name
VARIANT propertyName;
VariantInit(&propertyName);
propertyName.vt = VT_EMPTY;
hr = pPList->Next(&propertyName);
printf("\tProperty name: %S\n", propertyName.bstrVal);
}
}
}
// Clean up
pPList->Release();
return hr;
}
Currently, the problem I am facing is it's able to loop through all the properties but it's printing the property name empty.
For e.g.
Let's suppose there are 4 properties for an IADs object, so it will print Property name: Property name: Property name: Property name:
It tried to print the Property name as V_BSTR(&propertyName)
but still the results were the same.
Any help would be appreciated.
CodePudding user response:
What if you call the VariantInit() method first? You also need to release it first using VariantClear() as described here: Microsoft VariantClear Function
HRESULT ActiveDirectoryWrapper::PrintAllProperties(IADs *pADs) {
IADsPropertyList *pPList = NULL;
// Getting info of object
pADs->GetInfo();
HRESULT hr = pADs->QueryInterface(IID_IADsPropertyList, (void**)&pPList);
if (SUCCEEDED(hr))
{
// Get the number of properties in the object
LONG lCount = 0;
hr = pPList->get_PropertyCount(&lCount);
if (SUCCEEDED(hr))
{
// Iterate over the object's properties and print their names and values
for (LONG i = 0; i < lCount; i )
{
// Retrieve the property name
VARIANT propertyName;
VariantInit(&propertyName);
propertyName.vt = VT_EMPTY;
hr = pPList->Next(&propertyName);
// Print the property name
if (SUCCEEDED(hr))
{
printf("\tProperty name: %ls\n", propertyName.bstrVal);
VariantClear(&propertyName);
}
}
}
}
// Clean up
pPList->Release();
return hr;
}
Lastly, watch out for printf()
it can be a security vulnerability as cited here: How to exploit printf
CodePudding user response:
From Microsoft learn site, see details below.
The following code example shows how to retrieve a property entry using the GetPropertyItem method. It assumes that the IADsPropertyList interface has been properly retrieved. For more information about how to load the property cache, see the GetPropertyCache example function in IADsPropertyList. https://learn.microsoft.com/en-us/windows/win32/api/iads/nf-iads-iadspropertylist-getpropertyitem
#include <activeds.h>
#include <stdio.h>
/////////////////////////////////////////////////////////
// Function to retrieve a specified property entry
// using the IADsPropertyList::GetPropertyItem method.
/////////////////////////////////////////////////////////
IADsPropertyEntry *GetPropertyItem(
IADsPropertyList *pList,
BSTR entryName,
long entryType)
{
IADsPropertyEntry *pEntry;
VARIANT var;
VariantInit(&var);
if(!pList || !entryName)
{
_tprintf("Invalid argument...");
return NULL;
}
// Get a property entry.
hr = pList->GetPropertyItem(entryName, entryType, &var);
hr = V_DISPATCH(&var)->QueryInterface(IID_IADsPropertyEntry,
(void**)&pEntry);
VariantClear(&var);
return pEntry;
}
///////////////////////////////////////////////////////
// Examine a property entry.
///////////////////////////////////////////////////////
IADsPropertyList *pList = NULL;
IADsPropertyEntry *pEntry = NULL;
pList = GetPropertyCache(L"LDAP://dc01/DC=Fabrikam,DC=COM");
if(pList)
{
pEntry = GetPropertyItem(pList, L"dc", ADSTYPE_CASE_IGNORE_STRING);
}
if(pEntry)
{
BSTR nm;
HRESULT hr = pEntry->get_Name(&nm);
if(SUCCEEDED(hr))
{
printf("Property name = %S\n",nm);
SysFreeString(nm);
}
}
if(pList)
pList->Release();
if(pEntry)
pEntry->Release();