windows-nt/Source/XPSP1/NT/admin/dscmd/dsget/display.cpp
2020-09-26 16:20:57 +08:00

1978 lines
59 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000
//
// File: display.cpp
//
// Contents: Defines the functions used to convert values to strings
// for display purposes
//
// History: 17-Oct-2000 JeffJon Created
//
//
//--------------------------------------------------------------------------
#include <pch.h>
#include "cstrings.h"
#include "gettable.h"
#include "display.h"
#include "output.h"
#include "query.h"
#include <lmaccess.h> // UF_* for userAccountControl flags
#include <ntsam.h> // GROUP_TYPE_*
#include <ntdsapi.h> // NTDSSETTINGS_OPT_*
//
// All these functions are of type PGETDISPLAYSTRINGFUNC as defined in
// gettable.h
//
HRESULT CommonDisplayStringFunc(PCWSTR /*pszDN*/,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pRecord,
PADS_ATTR_INFO pAttrInfo,
CComPtr<IDirectoryObject>& /*spDirObject*/,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, CommonDisplayStringFunc, hr);
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pRecord ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pRecord);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
if (pAttrInfo && pAttrInfo->pADsValues)
{
DEBUG_OUTPUT(FULL_LOGGING,
L"Adding %d values:",
pAttrInfo->dwNumValues);
DWORD dwValuesAdded = 0;
for (DWORD dwIdx = 0; dwIdx < pAttrInfo->dwNumValues; dwIdx++)
{
WCHAR* pBuffer = new WCHAR[MAXSTR];
if (!pBuffer)
{
hr = E_OUTOFMEMORY;
break;
}
hr = GetStringFromADs(&(pAttrInfo->pADsValues[dwIdx]),
pAttrInfo->dwADsType,
pBuffer,
MAXSTR);
if (SUCCEEDED(hr))
{
hr = pDisplayInfo->AddValue(pBuffer);
if (FAILED(hr))
{
delete[] pBuffer;
pBuffer = NULL;
break;
}
delete[] pBuffer;
pBuffer = NULL;
dwValuesAdded++;
}
}
}
} while (false);
return hr;
}
HRESULT DisplayCanChangePassword(PCWSTR pszDN,
CDSCmdBasePathsInfo& refBasePathsInfo,
const CDSCmdCredentialObject& refCredentialObject,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pRecord,
PADS_ATTR_INFO /*pAttrInfo*/,
CComPtr<IDirectoryObject>& /*spDirObject*/,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayCanChangePassword, hr);
do // false loop
{
//
// Verify parameters
//
if (!pszDN ||
!pEntry ||
!pRecord ||
!pDisplayInfo)
{
ASSERT(pszDN);
ASSERT(pEntry);
ASSERT(pRecord);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
bool bCanChangePassword = false;
hr = EvaluateCanChangePasswordAces(pszDN,
refBasePathsInfo,
refCredentialObject,
bCanChangePassword);
if (FAILED(hr))
{
break;
}
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Can change password: %s",
bCanChangePassword ? g_pszYes : g_pszNo);
hr = pDisplayInfo->AddValue(bCanChangePassword ? g_pszYes : g_pszNo);
} while (false);
return hr;
}
HRESULT DisplayMustChangePassword(PCWSTR /*pszDN*/,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pRecord,
PADS_ATTR_INFO pAttrInfo,
CComPtr<IDirectoryObject>& /*spDirObject*/,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayMustChangePassword, hr);
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pRecord ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pRecord);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
if (pAttrInfo->pADsValues && pAttrInfo->dwADsType == ADSTYPE_LARGE_INTEGER)
{
DEBUG_OUTPUT(FULL_LOGGING,
L"Adding %d values:",
pAttrInfo->dwNumValues);
bool bMustChangePassword = false;
if (pAttrInfo->pADsValues->LargeInteger.HighPart == 0 &&
pAttrInfo->pADsValues->LargeInteger.LowPart == 0)
{
bMustChangePassword = true;
}
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Must change password: %s",
bMustChangePassword ? g_pszYes : g_pszNo);
hr = pDisplayInfo->AddValue(bMustChangePassword ? g_pszYes : g_pszNo);
}
} while (false);
return hr;
}
HRESULT DisplayAccountDisabled(PCWSTR /*pszDN*/,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pRecord,
PADS_ATTR_INFO pAttrInfo,
CComPtr<IDirectoryObject>& /*spDirObject*/,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayAccountDisabled, hr);
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pRecord ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pRecord);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
if (pAttrInfo->pADsValues && pAttrInfo->dwADsType == ADSTYPE_INTEGER)
{
DEBUG_OUTPUT(FULL_LOGGING,
L"Adding %d values:",
pAttrInfo->dwNumValues);
bool bAccountDisabled = false;
if (pAttrInfo->pADsValues->Integer & UF_ACCOUNTDISABLE)
{
bAccountDisabled = true;
}
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Account disabled: %s",
bAccountDisabled ? g_pszYes : g_pszNo);
hr = pDisplayInfo->AddValue(bAccountDisabled ? g_pszYes : g_pszNo);
}
} while (false);
return hr;
}
HRESULT DisplayPasswordNeverExpires(PCWSTR /*pszDN*/,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pRecord,
PADS_ATTR_INFO pAttrInfo,
CComPtr<IDirectoryObject>& /*spDirObject*/,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayPasswordNeverExpires, hr);
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pRecord ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pRecord);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
if (pAttrInfo->pADsValues && pAttrInfo->dwADsType == ADSTYPE_INTEGER)
{
DEBUG_OUTPUT(FULL_LOGGING,
L"Adding %d values:",
pAttrInfo->dwNumValues);
bool bPwdNeverExpires = false;
if (pAttrInfo->pADsValues->Integer & UF_DONT_EXPIRE_PASSWD)
{
bPwdNeverExpires = true;
}
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Password never expires: %s",
bPwdNeverExpires ? g_pszYes : g_pszNo);
hr = pDisplayInfo->AddValue(bPwdNeverExpires ? g_pszYes : g_pszNo);
}
} while (false);
return hr;
}
HRESULT DisplayReversiblePassword(PCWSTR /*pszDN*/,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pRecord,
PADS_ATTR_INFO pAttrInfo,
CComPtr<IDirectoryObject>& /*spDirObject*/,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayReversiblePassword, hr);
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pRecord ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pRecord);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
if (pAttrInfo->pADsValues && pAttrInfo->dwADsType == ADSTYPE_INTEGER)
{
DEBUG_OUTPUT(FULL_LOGGING,
L"Adding %d values:",
pAttrInfo->dwNumValues);
bool bReversiblePwd = false;
if (pAttrInfo->pADsValues->Integer & UF_DONT_EXPIRE_PASSWD)
{
bReversiblePwd = true;
}
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Password store with reversible encryption: %s",
bReversiblePwd ? g_pszYes : g_pszNo);
hr = pDisplayInfo->AddValue(bReversiblePwd ? g_pszYes : g_pszNo);
}
} while (false);
return hr;
}
// Constants
const unsigned long DSCMD_FILETIMES_PER_MILLISECOND = 10000;
const DWORD DSCMD_FILETIMES_PER_SECOND = 1000 * DSCMD_FILETIMES_PER_MILLISECOND;
const DWORD DSCMD_FILETIMES_PER_MINUTE = 60 * DSCMD_FILETIMES_PER_SECOND;
const __int64 DSCMD_FILETIMES_PER_HOUR = 60 * (__int64)DSCMD_FILETIMES_PER_MINUTE;
const __int64 DSCMD_FILETIMES_PER_DAY = 24 * DSCMD_FILETIMES_PER_HOUR;
const __int64 DSCMD_FILETIMES_PER_MONTH= 30 * DSCMD_FILETIMES_PER_DAY;
HRESULT DisplayAccountExpires(PCWSTR /*pszDN*/,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pRecord,
PADS_ATTR_INFO pAttrInfo,
CComPtr<IDirectoryObject>& /*spDirObject*/,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayAccountExpires, hr);
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pRecord ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pRecord);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
if (pAttrInfo && pAttrInfo->pADsValues)
{
DEBUG_OUTPUT(FULL_LOGGING,
L"Adding %d values:",
pAttrInfo->dwNumValues);
DWORD dwValuesAdded = 0;
for (DWORD dwIdx = 0; dwIdx < pAttrInfo->dwNumValues; dwIdx++)
{
WCHAR* pBuffer = new WCHAR[MAXSTR];
if (!pBuffer)
{
hr = E_OUTOFMEMORY;
break;
}
if (pAttrInfo->pADsValues[dwIdx].LargeInteger.QuadPart == 0 ||
pAttrInfo->pADsValues[dwIdx].LargeInteger.QuadPart == -1 ||
pAttrInfo->pADsValues[dwIdx].LargeInteger.QuadPart == 0x7FFFFFFFFFFFFFFF)
{
wcsncpy(pBuffer, g_pszNever, MAXSTR);
hr = pDisplayInfo->AddValue(pBuffer);
if (FAILED(hr))
{
delete[] pBuffer;
pBuffer = NULL;
break;
}
dwValuesAdded++;
}
else
{
FILETIME ftGMT; // GMT filetime
FILETIME ftLocal; // Local filetime
SYSTEMTIME st;
SYSTEMTIME stGMT;
ZeroMemory(&ftGMT, sizeof(FILETIME));
ZeroMemory(&ftLocal, sizeof(FILETIME));
ZeroMemory(&st, sizeof(SYSTEMTIME));
ZeroMemory(&stGMT, sizeof(SYSTEMTIME));
//Get Local Time in SYSTEMTIME format
ftGMT.dwLowDateTime = pAttrInfo->pADsValues[dwIdx].LargeInteger.LowPart;
ftGMT.dwHighDateTime = pAttrInfo->pADsValues[dwIdx].LargeInteger.HighPart;
FileTimeToSystemTime(&ftGMT, &stGMT);
SystemTimeToTzSpecificLocalTime(NULL, &stGMT,&st);
//For Display Purpose reduce one day
SystemTimeToFileTime(&st, &ftLocal );
pAttrInfo->pADsValues[dwIdx].LargeInteger.LowPart = ftLocal.dwLowDateTime;
pAttrInfo->pADsValues[dwIdx].LargeInteger.HighPart = ftLocal.dwHighDateTime;
pAttrInfo->pADsValues[dwIdx].LargeInteger.QuadPart -= DSCMD_FILETIMES_PER_DAY;
ftLocal.dwLowDateTime = pAttrInfo->pADsValues[dwIdx].LargeInteger.LowPart;
ftLocal.dwHighDateTime = pAttrInfo->pADsValues[dwIdx].LargeInteger.HighPart;
FileTimeToSystemTime(&ftLocal, &st);
// Format the string with respect to locale
if (!GetDateFormat(LOCALE_USER_DEFAULT, 0 ,
&st, NULL,
pBuffer, MAXSTR))
{
hr = GetLastError();
DEBUG_OUTPUT(LEVEL5_LOGGING,
L"Failed to locale string for date: hr = 0x%x",
hr);
}
else
{
hr = pDisplayInfo->AddValue(pBuffer);
if (FAILED(hr))
{
delete[] pBuffer;
pBuffer = NULL;
break;
}
dwValuesAdded++;
}
}
delete[] pBuffer;
pBuffer = NULL;
}
}
} while (false);
return hr;
}
HRESULT DisplayGroupScope(PCWSTR /*pszDN*/,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pRecord,
PADS_ATTR_INFO pAttrInfo,
CComPtr<IDirectoryObject>& /*spDirObject*/,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayGroupScope, hr);
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pRecord ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pRecord);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
if (pAttrInfo->pADsValues && pAttrInfo->dwADsType == ADSTYPE_INTEGER)
{
DEBUG_OUTPUT(FULL_LOGGING,
L"Adding %d values:",
pAttrInfo->dwNumValues);
if (pAttrInfo->pADsValues->Integer & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Display Domain Local
//
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Group scope: domain local");
hr = pDisplayInfo->AddValue(L"domain local");
}
else if (pAttrInfo->pADsValues->Integer & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Display Global
//
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Group scope: global");
hr = pDisplayInfo->AddValue(L"global");
}
else if (pAttrInfo->pADsValues->Integer & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Display Universal
//
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Group scope: universal");
hr = pDisplayInfo->AddValue(L"universal");
}
else
{
//
// Unknown group type???
//
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Group scope: unknown???");
hr = pDisplayInfo->AddValue(L"unknown");
}
}
} while (false);
return hr;
}
HRESULT DisplayGroupSecurityEnabled(PCWSTR /*pszDN*/,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pRecord,
PADS_ATTR_INFO pAttrInfo,
CComPtr<IDirectoryObject>& /*spDirObject*/,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayGroupSecurityEnabled, hr);
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pRecord ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pRecord);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
if (pAttrInfo->pADsValues && pAttrInfo->dwADsType == ADSTYPE_INTEGER)
{
DEBUG_OUTPUT(FULL_LOGGING,
L"Adding %d value:",
1);
bool bSecurityEnabled = false;
if (pAttrInfo->pADsValues->Integer & GROUP_TYPE_SECURITY_ENABLED)
{
bSecurityEnabled = true;
}
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Group security enabled: %s",
bSecurityEnabled ? g_pszYes : g_pszNo);
hr = pDisplayInfo->AddValue(bSecurityEnabled ? g_pszYes : g_pszNo);
}
} while (false);
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: ConvertRIDtoDN
//
// Synopsis: Finds the DN for the group associated with the primary group ID
//
// Arguments: [pObjSID IN] : SID of the object in question
// [priGroupRID IN] : primary group ID of the group to be found
// [refBasePathsInfo IN] : reference to base paths info
// [refCredObject IN] : reference to the credential manager object
// [refsbstrdN OUT] : DN of the group
//
// Returns: S_OK if everthing succeeds and a group was found
// S_FALSE if everthing succeeds but no group was found
// E_INVALIDARG is an argument is incorrect
// Anything else was a result of a failed ADSI call
//
// History: 24-Oct-2000 JeffJon Created
//
//---------------------------------------------------------------------------
HRESULT ConvertRIDtoDN(PSID pObjSID,
DWORD priGroupRID,
CDSCmdBasePathsInfo& refBasePathsInfo,
const CDSCmdCredentialObject& refCredObject,
CComBSTR& refsbstrDN)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, ConvertRIDtoDN, hr);
//
// This needs to be cleaned up no matter how we exit the false loop
//
PWSTR pszSearchFilter = NULL;
do // false loop
{
//
// Verify parameters
//
if (!pObjSID ||
!priGroupRID)
{
ASSERT(pObjSID);
ASSERT(priGroupRID);
hr = E_INVALIDARG;
break;
}
UCHAR * psaCount, i;
PSID pSID = NULL;
PSID_IDENTIFIER_AUTHORITY psia;
DWORD rgRid[8];
psaCount = GetSidSubAuthorityCount(pObjSID);
if (psaCount == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"GetSidSubAuthorityCount failed: hr = 0x%x",
hr);
break;
}
if (*psaCount > 8)
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"The count returned from GetSidSubAuthorityCount was too high: %d",
*psaCount);
hr = E_FAIL;
break;
}
for (i = 0; i < (*psaCount - 1); i++)
{
PDWORD pRid = GetSidSubAuthority(pObjSID, (DWORD)i);
if (pRid == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"GetSidSubAuthority for index %i failed: hr = 0x%x",
i,
hr);
break;
}
rgRid[i] = *pRid;
}
if (FAILED(hr))
{
break;
}
rgRid[*psaCount - 1] = priGroupRID;
for (i = *psaCount; i < 8; i++)
{
rgRid[i] = 0;
}
psia = GetSidIdentifierAuthority(pObjSID);
if (psia == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"GetSidIdentifierAuthority failed: hr = 0x%x",
hr);
break;
}
if (!AllocateAndInitializeSid(psia, *psaCount, rgRid[0], rgRid[1],
rgRid[2], rgRid[3], rgRid[4],
rgRid[5], rgRid[6], rgRid[7], &pSID))
{
hr = HRESULT_FROM_WIN32(GetLastError());
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"AllocateAndInitializeSid failed: hr = 0x%x",
hr);
break;
}
PWSTR rgpwzAttrNames[] = { L"ADsPath" };
const WCHAR wzSearchFormat[] = L"(&(objectCategory=group)(objectSid=%s))";
PWSTR pwzSID;
hr = ADsEncodeBinaryData((PBYTE)pSID, GetLengthSid(pSID), &pwzSID);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"ADsEncodeBinaryData failed: hr = 0x%x",
hr);
break;
}
pszSearchFilter = new WCHAR[wcslen(pwzSID) + wcslen(wzSearchFormat) + 1];
if (!pszSearchFilter)
{
hr = E_OUTOFMEMORY;
break;
}
wsprintf(pszSearchFilter, wzSearchFormat, pwzSID);
FreeADsMem(pwzSID);
//
// Get the domain path
//
CComBSTR sbstrDomainDN;
sbstrDomainDN = refBasePathsInfo.GetDefaultNamingContext();
CComBSTR sbstrDomainPath;
refBasePathsInfo.ComposePathFromDN(sbstrDomainDN, sbstrDomainPath);
//
// Get an IDirectorySearch interface to the domain
//
CComPtr<IDirectorySearch> spDirSearch;
hr = DSCmdOpenObject(refCredObject,
sbstrDomainPath,
IID_IDirectorySearch,
(void**)&spDirSearch,
true);
if (FAILED(hr))
{
break;
}
CDSSearch Search;
hr = Search.Init(spDirSearch);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"Failed to initialize the search object: hr = 0x%x",
hr);
break;
}
Search.SetFilterString(pszSearchFilter);
Search.SetAttributeList(rgpwzAttrNames, 1);
Search.SetSearchScope(ADS_SCOPE_SUBTREE);
hr = Search.DoQuery();
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"Failed to run search: hr = 0x%x",
hr);
break;
}
hr = Search.GetNextRow();
if (hr == S_ADS_NOMORE_ROWS)
{
DEBUG_OUTPUT(LEVEL5_LOGGING,
L"No group was found with primaryGroupID = %d",
priGroupRID);
//
// No object has a matching RID, the primary group must have been
// deleted. Return S_FALSE to denote this condition.
//
hr = S_FALSE;
break;
}
if (FAILED(hr))
{
break;
}
ADS_SEARCH_COLUMN Column;
hr = Search.GetColumn(L"ADsPath", &Column);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"Failed to get the path column: hr = 0x%x",
hr);
break;
}
if (!Column.pADsValues->CaseIgnoreString)
{
hr = E_FAIL;
break;
}
refsbstrDN = Column.pADsValues->CaseIgnoreString;
Search.FreeColumn(&Column);
} while (false);
//
// Cleanup
//
if (pszSearchFilter)
{
delete[] pszSearchFilter;
pszSearchFilter = NULL;
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: AddMemberOfValues
//
// Synopsis: Retrieves the DNs of the objects to which the current object
// is a member
//
// Arguments: [pszDN IN] : DN of object to retrieve member of
// [pszClass IN] : Class of object to retrieve member of
// [refBasePathsInfo IN] : reference to Base paths info object
// [refCredentialObject IN] : reference to Credential management object
// [pDirObject IN] : IDirectoryObject pointer to object
// [pDisplayInfo IN/OUT] : Pointer to display info for this attribute
// [bRecurse IN] : Should we find the memberOf for each memberOf
//
// Returns: S_OK if everthing succeeds
// E_INVALIDARG is an argument is incorrect
// Anything else was a result of a failed ADSI call
//
// History: 24-Oct-2000 JeffJon Created
//
//---------------------------------------------------------------------------
HRESULT AddMemberOfValues(PCWSTR pszDN,
PCWSTR pszClass,
CDSCmdBasePathsInfo& refBasePathsInfo,
const CDSCmdCredentialObject& refCredentialObject,
IDirectoryObject* pDirObject,
PDSGET_DISPLAY_INFO pDisplayInfo,
CManagedStringList& refGroupsDisplayed,
bool bRecurse = false)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, AddMemberOfValues, hr);
//
// These are declared here so that we can free them if we break out of the false loop
//
PADS_ATTR_INFO pAttrInfo = NULL;
PADS_ATTR_INFO pGCAttrInfo = NULL;
PSID pObjSID = NULL;
do // false loop
{
//
// Verify parameters
//
if (!pszDN ||
!pDisplayInfo)
{
ASSERT(pszDN);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
CComPtr<IDirectoryObject> spDirObject;
if (pDirObject)
{
//
// Use the currently bound object
// This should only happen on the first call.
// All recursive calls should have this NULL
//
spDirObject = pDirObject;
}
else
{
//
// We have to open the object
//
CComBSTR sbstrPath;
refBasePathsInfo.ComposePathFromDN(pszDN, sbstrPath);
hr = DSCmdOpenObject(refCredentialObject,
sbstrPath,
IID_IDirectoryObject,
(void**)&spDirObject,
true);
if (FAILED(hr))
{
break;
}
}
CComBSTR sbstrClass;
if (!pszClass)
{
CComPtr<IADs> spIADs;
hr = spDirObject->QueryInterface(IID_IADs, (void**)&spIADs);
if (FAILED(hr))
{
break;
}
hr = spIADs->get_Class(&sbstrClass);
if (FAILED(hr))
{
break;
}
}
else
{
sbstrClass = pszClass;
}
//
// Read the memberOf attribute and any attributes we need for that specific class
//
if (_wcsicmp(sbstrClass, g_pszUser) == 0 ||
_wcsicmp(sbstrClass, g_pszComputer) == 0)
{
DEBUG_OUTPUT(FULL_LOGGING, L"Displaying membership for a group or computer");
static const DWORD dwAttrCount = 3;
PWSTR ppszAttrNames[] = { L"memberOf", L"primaryGroupID", L"objectSID" };
DWORD dwAttrsReturned = 0;
hr = spDirObject->GetObjectAttributes(ppszAttrNames,
dwAttrCount,
&pAttrInfo,
&dwAttrsReturned);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"GetObjectAttributes failed for class %s: hr = 0x%x",
sbstrClass,
hr);
break;
}
if (pAttrInfo && dwAttrsReturned)
{
DWORD priGroupRID = 0;
//
// For each attribute returned do the appropriate thing
//
for (DWORD dwIdx = 0; dwIdx < dwAttrsReturned; dwIdx++)
{
if (_wcsicmp(pAttrInfo[dwIdx].pszAttrName, L"memberOf") == 0)
{
//
// Add each value and recurse if necessary
//
for (DWORD dwValueIdx = 0; dwValueIdx < pAttrInfo[dwIdx].dwNumValues; dwValueIdx++)
{
if (pAttrInfo[dwIdx].pADsValues &&
pAttrInfo[dwIdx].pADsValues[dwValueIdx].DNString)
{
if (!refGroupsDisplayed.Contains(pAttrInfo[dwIdx].pADsValues[dwValueIdx].DNString))
{
refGroupsDisplayed.Add(pAttrInfo[dwIdx].pADsValues[dwValueIdx].DNString);
hr = pDisplayInfo->AddValue(pAttrInfo[dwIdx].pADsValues[dwValueIdx].DNString);
if (FAILED(hr))
{
break; // value for loop
}
if (bRecurse)
{
hr = AddMemberOfValues(pAttrInfo[dwIdx].pADsValues[dwValueIdx].DNString,
NULL,
refBasePathsInfo,
refCredentialObject,
NULL,
pDisplayInfo,
refGroupsDisplayed,
bRecurse);
if (FAILED(hr))
{
break; // value for loop
}
}
}
}
}
if (FAILED(hr))
{
break; // attrs for loop
}
}
else if (_wcsicmp(pAttrInfo[dwIdx].pszAttrName, L"primaryGroupID") == 0)
{
if (pAttrInfo[dwIdx].pADsValues)
{
priGroupRID = pAttrInfo[dwIdx].pADsValues->Integer;
}
}
else if (_wcsicmp(pAttrInfo[dwIdx].pszAttrName, L"objectSID") == 0)
{
pObjSID = new BYTE[pAttrInfo[dwIdx].pADsValues->OctetString.dwLength];
if (!pObjSID)
{
hr = E_OUTOFMEMORY;
break; // attrs for loop
}
memcpy(pObjSID, pAttrInfo[dwIdx].pADsValues->OctetString.lpValue,
pAttrInfo[dwIdx].pADsValues->OctetString.dwLength);
}
} // attrs for loop
//
// if we were able to retrieve the SID and the primaryGroupID,
// then convert that into the DN of the group
//
if (pObjSID &&
priGroupRID)
{
CComBSTR sbstrPath;
hr = ConvertRIDtoDN(pObjSID,
priGroupRID,
refBasePathsInfo,
refCredentialObject,
sbstrPath);
if (SUCCEEDED(hr) &&
hr != S_FALSE)
{
CComBSTR sbstrDN;
hr = CPathCracker::GetDNFromPath(sbstrPath, sbstrDN);
if (SUCCEEDED(hr))
{
if (!refGroupsDisplayed.Contains(sbstrDN))
{
refGroupsDisplayed.Add(sbstrDN);
hr = pDisplayInfo->AddValue(sbstrDN);
if (SUCCEEDED(hr) && bRecurse)
{
hr = AddMemberOfValues(sbstrDN,
NULL,
refBasePathsInfo,
refCredentialObject,
NULL,
pDisplayInfo,
refGroupsDisplayed,
bRecurse);
if (FAILED(hr))
{
break; // false do loop
}
}
}
}
}
}
if (FAILED(hr))
{
break; // false do loop
}
}
if (pAttrInfo)
{
FreeADsMem(pAttrInfo);
pAttrInfo = NULL;
}
}
else if (_wcsicmp(sbstrClass, g_pszGroup) == 0)
{
long lGroupType = 0;
hr = ReadGroupType(pszDN,
refBasePathsInfo,
refCredentialObject,
&lGroupType);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"Could not read group type: hr = 0x%x",
hr);
break;
}
//
// All we want to do is get the memberOf attribute
//
DWORD dwAttrCount = 1;
PWSTR ppszAttrNames[] = { L"memberOf" };
DWORD dwGCAttrsReturned = 0;
if (!(lGroupType & GROUP_TYPE_RESOURCE_GROUP))
{
//
// We also have to get its memberOf attribute from the GC if its not a local group
//
CComBSTR sbstrGCPath;
refBasePathsInfo.ComposePathFromDN(pszDN,
sbstrGCPath,
DSCMD_GC_PROVIDER);
//
// Note: we will continue on as long as we succeed
//
CComPtr<IDirectoryObject> spGCDirObject;
hr = DSCmdOpenObject(refCredentialObject,
sbstrGCPath,
IID_IDirectoryObject,
(void**)&spGCDirObject,
false);
if (SUCCEEDED(hr))
{
//
// Now get the memberOf attribute
//
hr = spGCDirObject->GetObjectAttributes(ppszAttrNames,
dwAttrCount,
&pGCAttrInfo,
&dwGCAttrsReturned);
if (FAILED(hr))
{
DEBUG_OUTPUT(LEVEL3_LOGGING,
L"Could not retrieve memberOf attribute from GC: hr = 0x%x",
hr);
hr = S_OK;
}
}
else
{
DEBUG_OUTPUT(LEVEL3_LOGGING,
L"Could not bind to object in GC: hr = 0x%x",
hr);
hr = S_OK;
}
}
DWORD dwAttrsReturned = 0;
hr = spDirObject->GetObjectAttributes(ppszAttrNames,
dwAttrCount,
&pAttrInfo,
&dwAttrsReturned);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"GetObjectAttributes failed for class %s: hr = 0x%x",
sbstrClass,
hr);
break;
}
if (pAttrInfo && dwAttrsReturned)
{
bool bFirstPass = true;
ASSERT(dwAttrsReturned == 1);
ASSERT(_wcsicmp(pAttrInfo->pszAttrName, L"memberOf") == 0);
//
// Add each value and recurse if necessary
//
for (DWORD dwValueIdx = 0; dwValueIdx < pAttrInfo->dwNumValues; dwValueIdx++)
{
bool bExistsInGCList = false;
if (pAttrInfo->pADsValues &&
pAttrInfo->pADsValues[dwValueIdx].DNString)
{
if (pGCAttrInfo && dwGCAttrsReturned)
{
//
// Only add if it wasn't in the GC list
//
for (DWORD dwGCValueIdx = 0; dwGCValueIdx < pGCAttrInfo->dwNumValues; dwGCValueIdx++)
{
if (_wcsicmp(pAttrInfo->pADsValues[dwValueIdx].DNString,
pGCAttrInfo->pADsValues[dwGCValueIdx].DNString) == 0)
{
bExistsInGCList = true;
if (!bFirstPass)
{
break; // gc value for
}
}
//
// Add all the GC values on the first pass and recurse if necessary
//
if (bFirstPass)
{
if (!refGroupsDisplayed.Contains(pGCAttrInfo->pADsValues[dwGCValueIdx].DNString))
{
refGroupsDisplayed.Add(pGCAttrInfo->pADsValues[dwGCValueIdx].DNString);
hr = pDisplayInfo->AddValue(pGCAttrInfo->pADsValues[dwGCValueIdx].DNString);
//
// We will ignore failures with the GC list
//
if (bRecurse)
{
hr = AddMemberOfValues(pGCAttrInfo->pADsValues[dwGCValueIdx].DNString,
NULL,
refBasePathsInfo,
refCredentialObject,
NULL,
pDisplayInfo,
refGroupsDisplayed,
bRecurse);
}
}
}
}
bFirstPass = false;
}
//
// If it doesn't exist in the GC list then add it.
//
if (!bExistsInGCList)
{
if (!refGroupsDisplayed.Contains(pAttrInfo->pADsValues[dwValueIdx].DNString))
{
refGroupsDisplayed.Add(pAttrInfo->pADsValues[dwValueIdx].DNString);
hr = pDisplayInfo->AddValue(pAttrInfo->pADsValues[dwValueIdx].DNString);
if (FAILED(hr))
{
break; // value for loop
}
if (bRecurse)
{
hr = AddMemberOfValues(pAttrInfo->pADsValues[dwValueIdx].DNString,
NULL,
refBasePathsInfo,
refCredentialObject,
NULL,
pDisplayInfo,
refGroupsDisplayed,
bRecurse);
if (FAILED(hr))
{
break; // value for loop
}
}
}
}
}
} // value for loop
if (FAILED(hr))
{
break; // false do loop
}
}
}
else
{
DEBUG_OUTPUT(MINIMAL_LOGGING, L"Unknown class type: %s", sbstrClass);
ASSERT(false);
hr = E_INVALIDARG;
break;
}
} while (false);
//
// Cleanup
//
if (pAttrInfo)
{
FreeADsMem(pAttrInfo);
pAttrInfo = NULL;
}
if (pGCAttrInfo)
{
FreeADsMem(pGCAttrInfo);
pGCAttrInfo = NULL;
}
if (pObjSID)
{
delete[] pObjSID;
pObjSID = NULL;
}
return hr;
}
HRESULT DisplayUserMemberOf(PCWSTR pszDN,
CDSCmdBasePathsInfo& refBasePathsInfo,
const CDSCmdCredentialObject& refCredentialObject,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pCommandArgs,
PADS_ATTR_INFO pAttrInfo,
CComPtr<IDirectoryObject>& spDirObject,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayUserMemberOf, hr);
do // false loop
{
//
// Verify parameters
//
if (!pszDN ||
!pEntry ||
!pCommandArgs ||
!pAttrInfo ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pCommandArgs);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
//
// This list is used to keep from going into infinite recursion
// if there is circular group membership
//
CManagedStringList groupsDisplayed;
hr = AddMemberOfValues(pszDN,
g_pszUser,
refBasePathsInfo,
refCredentialObject,
spDirObject,
pDisplayInfo,
groupsDisplayed,
(pCommandArgs[eUserExpand].bDefined != 0));
} while (false);
return hr;
}
HRESULT DisplayComputerMemberOf(PCWSTR pszDN,
CDSCmdBasePathsInfo& refBasePathsInfo,
const CDSCmdCredentialObject& refCredentialObject,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pCommandArgs,
PADS_ATTR_INFO /*pAttrInfo*/,
CComPtr<IDirectoryObject>& spDirObject,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayComputerMemberOf, hr);
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pCommandArgs ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pCommandArgs);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
//
// This list is used to keep from going into infinite recursion
// if there is circular group membership
//
CManagedStringList groupsDisplayed;
hr = AddMemberOfValues(pszDN,
g_pszComputer,
refBasePathsInfo,
refCredentialObject,
spDirObject,
pDisplayInfo,
groupsDisplayed,
(pCommandArgs[eComputerExpand].bDefined != 0));
} while (false);
return hr;
}
HRESULT DisplayGroupMemberOf(PCWSTR pszDN,
CDSCmdBasePathsInfo& refBasePathsInfo,
const CDSCmdCredentialObject& refCredentialObject,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pCommandArgs,
PADS_ATTR_INFO /*pAttrInfo*/,
CComPtr<IDirectoryObject>& spDirObject,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayGroupMemberOf, hr);
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pCommandArgs ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pCommandArgs);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
//
// This list is used to keep from going into infinite recursion
// if there is circular group membership
//
CManagedStringList groupsDisplayed;
hr = AddMemberOfValues(pszDN,
g_pszGroup,
refBasePathsInfo,
refCredentialObject,
spDirObject,
pDisplayInfo,
groupsDisplayed,
(pCommandArgs[eGroupExpand].bDefined != 0));
} while (false);
return hr;
}
HRESULT DisplayGrandparentRDN(PCWSTR pszDN,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* /*pEntry*/,
ARG_RECORD* /*pCommandArgs*/,
PADS_ATTR_INFO /*pAttrInfo*/,
CComPtr<IDirectoryObject>& /*spDirObject*/,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayGrandparentRDN, hr);
do // false loop
{
//
// Verify parameters
//
if (!pszDN ||
!pDisplayInfo)
{
ASSERT(pszDN);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
CComBSTR sbstrSiteName;
CPathCracker pathCracker;
hr = pathCracker.Set(const_cast<PWSTR>(pszDN), ADS_SETTYPE_DN);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"IADsPathname::Set failed: hr = 0x%x",
hr);
break;
}
hr = pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"IADsPathname::SetDisplayType failed: hr = 0x%x",
hr);
break;
}
hr = pathCracker.GetElement(2, &sbstrSiteName);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"IADsPathname::GetElement failed: hr = 0x%x",
hr);
break;
}
hr = pDisplayInfo->AddValue(sbstrSiteName);
} while (false);
return hr;
}
HRESULT IsServerGCDisplay(PCWSTR pszDN,
CDSCmdBasePathsInfo& refBasePathsInfo,
const CDSCmdCredentialObject& refCredentialObject,
_DSGetObjectTableEntry* /*pEntry*/,
ARG_RECORD* /*pCommandArgs*/,
PADS_ATTR_INFO /*pAttrInfo*/,
CComPtr<IDirectoryObject>& /*spDirObject*/,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, IsServerGCDisplay, hr);
do // false loop
{
//
// Verify parameters
//
if (!pszDN ||
!pDisplayInfo)
{
ASSERT(pszDN);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
//
// Compose the path to the NTDS settings object from the server DN
//
CComBSTR sbstrNTDSSettingsDN;
sbstrNTDSSettingsDN = L"CN=NTDS Settings,";
sbstrNTDSSettingsDN += pszDN;
CComBSTR sbstrNTDSSettingsPath;
refBasePathsInfo.ComposePathFromDN(sbstrNTDSSettingsDN, sbstrNTDSSettingsPath);
CComPtr<IADs> spADs;
hr = DSCmdOpenObject(refCredentialObject,
sbstrNTDSSettingsPath,
IID_IADs,
(void**)&spADs,
true);
if (FAILED(hr))
{
break;
}
CComVariant var;
hr = spADs->Get(L"options", &var);
if (FAILED(hr))
{
DEBUG_OUTPUT(LEVEL5_LOGGING,
L"Failed to get the options: hr = 0x%x",
hr);
break;
}
ASSERT(var.vt == VT_I4);
bool bGC = false;
if (var.lVal & 0x1)
{
bGC = true;
}
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Server is GC: %s",
bGC ? g_pszYes : g_pszNo);
hr = pDisplayInfo->AddValue(bGC ? g_pszYes : g_pszNo);
} while (false);
return hr;
}
HRESULT FindSiteSettingsOptions(IDirectoryObject* pDirectoryObj,
DWORD& refOptions)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, FindSiteSettingsOptions, hr);
do // false loop
{
//
// Verify parameters
//
if (!pDirectoryObj)
{
ASSERT(pDirectoryObj);
hr = E_INVALIDARG;
break;
}
CComPtr<IDirectorySearch> spSearch;
hr = pDirectoryObj->QueryInterface(IID_IDirectorySearch, (void**)&spSearch);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"QI for IDirectorySearch failed: hr = 0x%x",
hr);
break;
}
CDSSearch Search;
hr = Search.Init(spSearch);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"CDSSearch::Init failed: hr = 0x%x",
hr);
break;
}
PWSTR pszSearchFilter = L"(objectClass=nTDSSiteSettings)";
Search.SetFilterString(pszSearchFilter);
PWSTR rgpwzAttrNames[] = { L"options" };
Search.SetAttributeList(rgpwzAttrNames, 1);
Search.SetSearchScope(ADS_SCOPE_ONELEVEL);
hr = Search.DoQuery();
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"Failed to run search: hr = 0x%x",
hr);
break;
}
hr = Search.GetNextRow();
if (hr == S_ADS_NOMORE_ROWS)
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"No rows found!");
hr = E_FAIL;
break;
}
ADS_SEARCH_COLUMN Column;
hr = Search.GetColumn(L"options", &Column);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"Failed to get the options column: hr = 0x%x",
hr);
break;
}
if (Column.dwADsType != ADSTYPE_INTEGER ||
Column.dwNumValues == 0 ||
!Column.pADsValues)
{
Search.FreeColumn(&Column);
hr = E_FAIL;
break;
}
refOptions = Column.pADsValues->Integer;
Search.FreeColumn(&Column);
} while (false);
return hr;
}
HRESULT IsAutotopologyEnabledSite(PCWSTR /*pszDN*/,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pCommandArgs,
PADS_ATTR_INFO /*pAttrInfo*/,
CComPtr<IDirectoryObject>& spDirObject,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, IsAutotopologyEnabledSite, hr);
bool bAutoTopDisabled = false;
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pCommandArgs ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pCommandArgs);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
//
// Get the options attribute from the nTDSSiteSettings object under the site object
//
DWORD dwOptions = 0;
hr = FindSiteSettingsOptions(spDirObject,
dwOptions);
if (FAILED(hr))
{
break;
}
//
// See if the intersite autotopology is disabled
//
if (dwOptions & NTDSSETTINGS_OPT_IS_INTER_SITE_AUTO_TOPOLOGY_DISABLED)
{
bAutoTopDisabled = true;
}
} while (false);
//
// Add the value for display
//
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Autotopology: %s",
bAutoTopDisabled ? g_pszNo : g_pszYes);
pDisplayInfo->AddValue(bAutoTopDisabled ? g_pszNo : g_pszYes);
return hr;
}
HRESULT IsCacheGroupsEnabledSite(PCWSTR /*pszDN*/,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pCommandArgs,
PADS_ATTR_INFO /*pAttrInfo*/,
CComPtr<IDirectoryObject>& spDirObject,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, IsCacheGroupsEnabledSite, hr);
bool bCacheGroupsEnabled = false;
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pCommandArgs ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pCommandArgs);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
//
// Get the options attribute from the nTDSSiteSettings object under the site object
//
DWORD dwOptions = 0;
hr = FindSiteSettingsOptions(spDirObject,
dwOptions);
if (FAILED(hr))
{
break;
}
//
// See if groups caching is enabled
//
if (dwOptions & NTDSSETTINGS_OPT_IS_GROUP_CACHING_ENABLED)
{
bCacheGroupsEnabled = true;
}
} while (false);
//
// Add the value for display
//
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Cache groups enabled: %s",
bCacheGroupsEnabled ? g_pszYes : g_pszNo);
pDisplayInfo->AddValue(bCacheGroupsEnabled ? g_pszYes : g_pszNo);
return hr;
}
HRESULT FindSiteSettingsPreferredGCSite(IDirectoryObject* pDirectoryObj,
CComBSTR& refsbstrGC)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, FindSiteSettingsPreferredGCSite, hr);
do // false loop
{
//
// Verify parameters
//
if (!pDirectoryObj)
{
ASSERT(pDirectoryObj);
hr = E_INVALIDARG;
break;
}
CComPtr<IDirectorySearch> spSearch;
hr = pDirectoryObj->QueryInterface(IID_IDirectorySearch, (void**)&spSearch);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"QI for IDirectorySearch failed: hr = 0x%x",
hr);
break;
}
CDSSearch Search;
hr = Search.Init(spSearch);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"CDSSearch::Init failed: hr = 0x%x",
hr);
break;
}
PWSTR pszSearchFilter = L"(objectClass=nTDSSiteSettings)";
Search.SetFilterString(pszSearchFilter);
PWSTR rgpwzAttrNames[] = { L"msDS-Preferred-GC-Site" };
Search.SetAttributeList(rgpwzAttrNames, 1);
Search.SetSearchScope(ADS_SCOPE_ONELEVEL);
hr = Search.DoQuery();
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"Failed to run search: hr = 0x%x",
hr);
break;
}
hr = Search.GetNextRow();
if (hr == S_ADS_NOMORE_ROWS)
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"No rows found!");
hr = E_FAIL;
break;
}
ADS_SEARCH_COLUMN Column;
hr = Search.GetColumn(L"msDS-Preferred-GC-Site", &Column);
if (FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"Failed to get the msDS-Preferred-GC-Site column: hr = 0x%x",
hr);
break;
}
if (Column.dwADsType != ADSTYPE_DN_STRING ||
Column.dwNumValues == 0 ||
!Column.pADsValues)
{
Search.FreeColumn(&Column);
hr = E_FAIL;
break;
}
refsbstrGC = Column.pADsValues->DNString;
Search.FreeColumn(&Column);
} while (false);
return hr;
}
HRESULT DisplayPreferredGC(PCWSTR /*pszDN*/,
CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
const CDSCmdCredentialObject& /*refCredentialObject*/,
_DSGetObjectTableEntry* pEntry,
ARG_RECORD* pCommandArgs,
PADS_ATTR_INFO /*pAttrInfo*/,
CComPtr<IDirectoryObject>& spDirObject,
PDSGET_DISPLAY_INFO pDisplayInfo)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DisplayPreferredGC, hr);
CComBSTR sbstrGC;
do // false loop
{
//
// Verify parameters
//
if (!pEntry ||
!pCommandArgs ||
!pDisplayInfo)
{
ASSERT(pEntry);
ASSERT(pCommandArgs);
ASSERT(pDisplayInfo);
hr = E_INVALIDARG;
break;
}
//
// Get the msDS-Preferred-GC-Site attribute from the nTDSSiteSettings
// object under the site object
//
hr = FindSiteSettingsPreferredGCSite(spDirObject,
sbstrGC);
if (FAILED(hr))
{
break;
}
} while (false);
//
// Add the value for display
//
DEBUG_OUTPUT(LEVEL8_LOGGING,
L"Preferred GC Site: %s",
(!sbstrGC) ? g_pszNotConfigured : sbstrGC);
pDisplayInfo->AddValue((!sbstrGC) ? g_pszNotConfigured : sbstrGC);
return hr;
}