ADsOpenObject(), IDirectorySearch returns excess number of objects than the original count present in AD DC.

Routine User 1 Reputation point
2022-07-28T12:15:55.28+00:00

When we try to fetch all the Users or Computers objects present in AD using the below code which binds with AD using ADsOpenObject(), it returns excessive number of objects which are not really part of the AD.

For e.g. We have around 8000 Users and 9000 Computers in AD. But when we try to fetch them, the total object count finally will be 25000 Users and 67000 Computers.

We tried to verify the returned objects, but they are not like randomly generated objects, have some meaningful names and properties. But unfortunately they are not part of our directory.

Please find the server details below that I have attached for reference.

------------------------------------------------------------

Domain Functional Level --> Windows Server 2012 R2
Forest Functional Level --> Windows Server 2012 R2
Number of DCs --> 3

-----------------------------------------------------------

Kindly help us finding out what we're doing wrong here.

void GetMembers(wchar_t* szFilter, IDirectorySearch* pDirSearch, LPWSTR* attributes, DWORD attributeCount, bool allMembers)  
{  
 HRESULT hr;  
 USES_CONVERSION;  
 ADS_SEARCH_HANDLE hSearch = NULL;  
 ADS_SEARCH_COLUMN col;  
 ADS_SEARCHPREF_INFO SearchPref[2];  
 SearchPref[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;  
 SearchPref[0].vValue.dwType = ADSTYPE_INTEGER;  
 SearchPref[0].vValue.Integer = ADS_SCOPE_SUBTREE;  
 SearchPref[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;  
 SearchPref[1].vValue.dwType = ADSTYPE_INTEGER;  
 SearchPref[1].vValue.Integer = 1000;  
  
 pDirSearch->SetSearchPreference(SearchPref, 2);  
 hr = pDirSearch->ExecuteSearch(szFilter, attributes, attributeCount, &hSearch);  
 int ObjectCount = 0;  
 LPWSTR pszColumn = NULL;  
 PSID pObjectSID = NULL;  
 LPWSTR szSID = NULL;  
 printf("\n\n---------------------------Fetching Object Started--------------------------------\n");  
 while ((hr = pDirSearch->GetNextRow(hSearch)) != S_ADS_NOMORE_ROWS) {  
 ObjectCount++;  
 std::cout << "\n" << ObjectCount << "\n";  
 int index = 0;  
 int co = 0;  
 while (pDirSearch->GetNextColumnName(hSearch, &pszColumn) != S_ADS_NOMORE_COLUMNS)  
 {  
 hr = pDirSearch->GetColumn(hSearch, attributes[index], &col);  
 if (SUCCEEDED(hr)) {  
 if ((_wcsicmp(col.pszAttrName, L"distinguishedName") == 0)) {  
 wprintf(L"%-20s  %-20s\n", attributes[index], col.pADsValues->CaseIgnoreString);  
 }  
 }  
 else {  
 printf("Error null value in %ws\n", attributes[index]);  
 }  
 index++;  
 }  
 }  
 if (hr != 0x00005012) {  
  
 printf("herror in GetMembers of get next row %0x", hr);  
 }  
  
 printf("\n\nTotal ObjectCount : % d\t\n", ObjectCount); // Here we're getting the count as 25000 for users and 67000 for computers objects  
  
 printf("\n\n---------------------------Fetching Object completed--------------------------------\n\n\n");  
 if (hSearch)pDirSearch->CloseSearchHandle(hSearch);  
 pDirSearch->Release();  
 CoUninitialize();  
}  
  
  
void GetObjects()  
{  
 LPWSTR pwd = (LPWSTR)L"password";  
 LPWSTR dcname = (LPWSTR)L"password";  
 LPWSTR distinguishedName = (LPWSTR)L"DC=domain,DC=com";  
 LPWSTR username = (LPWSTR)L"username";  
  
 LPOLESTR rootStr = new OLECHAR[wcslen(L"LDAP://") + wcslen(dcname) + wcslen(L"/") + wcslen((LPWSTR)distinguishedName) + 1];  
 wcscpy(rootStr, L"LDAP://");  
 wcscat(rootStr, dcname);  
 wcscat(rootStr, L"/");  
 wcscat(rootStr, (LPWSTR)distinguishedName);  
 printf("\n\nLDAP DC path = %ws\n\n", rootStr);  
  
 HRESULT hr;  
 USES_CONVERSION;  
 DWORD attributeCount = 1;  
  
 LPWSTR attributes[] = {(LPWSTR)L"distinguishedName"};  
 IDirectorySearch* pDirSearch = NULL;  
 LPWSTR szFilter = new WCHAR[MAX_PATH];  
 wcscpy(szFilter, L"(&(objectCategory=person)(objectClass=user)(!(sAMAccountType=805306370)))");  
 CoInitialize(NULL);  
  
 hr = ADsOpenObject(rootStr,  
 username,  
 pwd,  
 ADS_SECURE_AUTHENTICATION, IID_IDirectorySearch, (void**)&pDirSearch);  
 if (SUCCEEDED(hr)) {  
 GetMembers(szFilter, pDirSearch, attributes, attributeCount, false);  
 }  
 else {  
 if (hr == 0x8007200a) {  
 printf("\nNo View Permission");  
 }  
 else {  
 printf("\n\nAuthentication failure");  
 }  
 printf("\n\nObject Bind Failed, error code : %x", hr);  
 }  
}  
Windows Server
Windows Server
A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.
12,127 questions
Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,422 questions
Active Directory
Active Directory
A set of directory-based technologies included in Windows Server.
5,858 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,527 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Gary Reynolds 9,391 Reputation points
    2022-08-01T09:32:01.853+00:00

    Hi,

    You can use this function count the number of objects in the domain, it will also display how many of the user objects are active, which might be what is shewing you numbers.

    https://nettools.net/object-counts/

    226629-image.png

    Gary.

    1 person found this answer helpful.

  2. Gary Reynolds 9,391 Reputation points
    2022-08-08T09:44:07.89+00:00

    Hi @Routine User

    I have to say I haven't seen this problem before, so personally I would do loads of testing to try and understand what is going on and why, below are some of the steps that I would try to identify the cause of the issue.

    I would dump the database and do a compare to see if the object exist in both databases
    Check the health of the DC with DCdiag /v /c
    Check the health of the replication repadmin /showrepl and repadmin /replsummary
    Check for Lingering Objects - https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/information-lingering-objects
    Check the integrity of the AD database - https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/complete-semantic-database-analysis-ad-db
    I would use the Object Replication option of the NetTools to check if the objects exist on both DCs

    Ultimately the fix might be to dcpromo the affected DC out of the domain and add it back in again.

    Gary.

    1 person found this answer helpful.