Platform SDK: Active Directory, ADSI, and Directory Services

Example Code for Binding to a Partitions Container

The following examples bind to the partitions container and enumerate all crossRef objects.

[C++]
// This application enumerates crossrefs in the partitions container.
//
#include <objbase.h>
#include <wchar.h>
#include <activeds.h>
 
//Make sure you define UNICODE
//Need to define version 5 for Windows 2000
#define _WIN32_WINNT 0x0500
 
#include <sddl.h>
 
HRESULT FindCrossRefs(IDirectorySearch *pConfigNC,  //IDirectorySearch pointer to Partitions container.
                      LPOLESTR szFilter, //Filter for finding specific crossrefs.
                                         //NULL returns all attributeSchema objects.
                      LPOLESTR *pszPropertiesToReturn, //Properties to return for crossRef objects found
                                                       //NULL returns all set properties.
                      BOOL bIsVerbose //TRUE means all properties for the found objects are displayed.
                                      //FALSE means only the RDN
                     );
 
 
void wmain( int argc, wchar_t *argv[ ])
{
  //Handle the command line arguments.
  LPOLESTR pszBuffer = new OLECHAR[MAX_PATH*2];
  wcscpy(pszBuffer, L"");
 
  BOOL bReturnVerbose = FALSE;
  wprintf(L"\nFinding all crossRef objects in the Partitions container\n");
 
  //Intialize COM
  CoInitialize(NULL);
  HRESULT hr = S_OK;
 
  //Get rootDSE and the config container's DN.
  IADs *pObject = NULL;
  IDirectorySearch *pConfigNC = NULL;
  LPOLESTR szPath = new OLECHAR[MAX_PATH];
  VARIANT var;
  hr = ADsOpenObject(L"LDAP://rootDSE",
                     NULL,
                     NULL,
                     ADS_SECURE_AUTHENTICATION, //Use Secure Authentication
                     IID_IADs,
                     (void**)&pObject);
 
  if (FAILED(hr))
  {
    wprintf(L"Could not execute query. Could not bind to LDAP://rootDSE. HR: %x\n",hr);
 
    if (pObject)
      pObject->Release();
 
    return;
  }
 
  if (SUCCEEDED(hr))
  {
    hr = pObject->Get(L"configurationNamingContext",&var);
 
    if (SUCCEEDED(hr))
    {
      //Build path to the partitions container.
          wcscpy(szPath,L"LDAP://cn=Partitions,");
          wcscat(szPath,var.bstrVal);
          hr = ADsOpenObject(szPath,
                             NULL,
                             NULL,
                             ADS_SECURE_AUTHENTICATION, //Use Secure Authentication
                             IID_IDirectorySearch,
                             (void**)&pConfigNC);
 
      if (SUCCEEDED(hr))
      {
        hr = FindCrossRefs(pConfigNC, //IDirectorySearch pointer to Partitions container.
                           NULL, //Find all 
                           NULL, //Return all properties
                           TRUE //Display all properties
                          );
 
        if (SUCCEEDED(hr))
        {
          if (S_FALSE==hr)
            wprintf(L"No crossRef object could be found.\n");
        }
        else if (0x8007203e==hr)
          wprintf(L"Could not execute query. An invalid filter was specified.\n");
        else
          wprintf(L"Query failed to run. HRESULT: %x\n",hr);
      }
      else
      {
         wprintf(L"Could not execute query. Could not bind to the schema container.\n");
      }
 
      if (pConfigNC)
        pConfigNC->Release();
 
    }
 
    VariantClear(&var);
 
  }
 
  if (pObject)
    pObject->Release();
 
  // Uninitialize COM
  CoUninitialize();
  return;
}
 
HRESULT FindCrossRefs(IDirectorySearch *pConfigNC,  //IDirectorySearch pointer to Partitions container.
                      LPOLESTR szFilter, //Filter for finding specific crossrefs.
                                         //NULL returns all attributeSchema objects.
                      LPOLESTR *pszPropertiesToReturn, //Properties to return for crossRef objects found
                                                       //NULL returns all set properties.
                      BOOL bIsVerbose //TRUE means all properties for the found objects are displayed.
                                      //FALSE means only the RDN
                     )
{
  if (!pConfigNC)
    return E_POINTER;
 
  //Create search filter
  LPOLESTR pszSearchFilter = new OLECHAR[MAX_PATH*2];
  LPOLESTR szCategory = NULL;
 
  wsprintf(pszSearchFilter, L"(&(objectCategory=crossRef)%s)",szFilter);
 
  //Attributes are one-level deep in the schema container so only need to search one level.
  ADS_SEARCHPREF_INFO SearchPrefs;
  SearchPrefs.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  SearchPrefs.vValue.dwType = ADSTYPE_INTEGER;
  SearchPrefs.vValue.Integer = ADS_SCOPE_ONELEVEL;
  DWORD dwNumPrefs = 1;
 
  // COL for iterations
  LPOLESTR pszColumn = NULL;    
  ADS_SEARCH_COLUMN col;
  HRESULT hr;
 
  // Interface Pointers
  IADs    *pObj = NULL;
  IADs  * pIADs = NULL;
 
  // Handle used for searching
  ADS_SEARCH_HANDLE hSearch = NULL;
 
  // Set the search preference
  hr = pConfigNC->SetSearchPreference( &SearchPrefs, dwNumPrefs);
 
  if (FAILED(hr))
    return hr;
 
  LPOLESTR pszBool = NULL;
  DWORD dwBool;
  PSID pObjectSID = NULL;
  LPOLESTR szSID = NULL;
  LPOLESTR szDSGUID = new WCHAR [39];
  LPGUID pObjectGUID = NULL;
  FILETIME filetime;
  SYSTEMTIME systemtime;
  DATE date;
  VARIANT varDate;
  LARGE_INTEGER liValue;
  LPOLESTR *pszPropertyList = NULL;
  LPOLESTR pszNonVerboseList[] = {L"lDAPDisplayName",L"cn"};
 
  LPOLESTR szCNValue = new OLECHAR[MAX_PATH];
  LPOLESTR szLDAPDispleyNameValue = new OLECHAR[MAX_PATH];
 
  int iCount = 0;
  DWORD x = 0L;
 
  if (!bIsVerbose)
  {
    //Return non-verbose list properties only
    hr = pConfigNC->ExecuteSearch(pszSearchFilter,
                                  pszNonVerboseList,
                                  sizeof(pszNonVerboseList)/sizeof(LPOLESTR),
                                  &hSearch
                                 );
  }
  else
  {
    if (!pszPropertiesToReturn)
    {
      //Return all properties.
      hr = pConfigNC->ExecuteSearch(pszSearchFilter,
                                    NULL,
                                    0L,
                                    &hSearch
                                   );
    }
    else
    {
      //specified subset.
      pszPropertyList = pszPropertiesToReturn;
      //Return specified properties
      hr = pConfigNC->ExecuteSearch(pszSearchFilter,
                                    pszPropertyList,
                                    sizeof(pszPropertyList)/sizeof(LPOLESTR),
                                    &hSearch
                                   );
    }
  }
 
  if ( SUCCEEDED(hr) )
  {    
    // Call IDirectorySearch::GetNextRow() to retrieve the next row 
    //of data
    hr = pConfigNC->GetFirstRow( hSearch);
 
    if (SUCCEEDED(hr))
    {
      while( hr != S_ADS_NOMORE_ROWS )
      {
        //Keep track of count.
        iCount++;
 
        if (bIsVerbose)
          wprintf(L"----------------------------------\n");
 
        // loop through the array of passed column names,
        // print the data for each column
        while( pConfigNC->GetNextColumnName( hSearch, &pszColumn ) != S_ADS_NOMORE_COLUMNS )
        {
          hr = pConfigNC->GetColumn( hSearch, pszColumn, &col );
 
          if ( SUCCEEDED(hr) )
          {
            // Print the data for the column and free the column
            if(bIsVerbose)
            {
              // Get the data for this column
              wprintf(L"%s\n",col.pszAttrName);
 
              switch (col.dwADsType)
              {
                case ADSTYPE_DN_STRING:
                  for (x = 0; x< col.dwNumValues; x++)
                  {
                    wprintf(L"  %s\r\n",col.pADsValues[x].DNString);
                  }
                  break;
 
                  case ADSTYPE_CASE_EXACT_STRING:
                  case ADSTYPE_CASE_IGNORE_STRING:
                  case ADSTYPE_PRINTABLE_STRING:
                  case ADSTYPE_NUMERIC_STRING:
                  case ADSTYPE_TYPEDNAME:
                  case ADSTYPE_FAXNUMBER:
                  case ADSTYPE_PATH:
                  case ADSTYPE_OBJECT_CLASS:
                    for (x = 0; x< col.dwNumValues; x++)
                    {
                      wprintf(L"  %s\r\n",col.pADsValues[x].CaseIgnoreString);
                    }
                    break;
 
                  case ADSTYPE_BOOLEAN:
                    for (x = 0; x< col.dwNumValues; x++)
                    {
                      dwBool = col.pADsValues[x].Boolean;
                      pszBool = dwBool ? L"TRUE" : L"FALSE";
                      wprintf(L"  %s\r\n",pszBool);
                    }
                    break;
 
                  case ADSTYPE_INTEGER:
                    for (x = 0; x< col.dwNumValues; x++)
                    {
                      wprintf(L"  %d\r\n",col.pADsValues[x].Integer);
                    }
                    break;
 
                  case ADSTYPE_OCTET_STRING:
                    if ( _wcsicmp(col.pszAttrName,L"objectSID") == 0 )
                    {
                      for (x = 0; x< col.dwNumValues; x++)
                      {
                        pObjectSID = (PSID)(col.pADsValues[x].OctetString.lpValue);
 
                        //Convert SID to string.
                        ConvertSidToStringSid(pObjectSID, &szSID);
                        wprintf(L"  %s\r\n",szSID);
 
                        LocalFree(szSID);
                      }
                    }
                    else if ( (_wcsicmp(col.pszAttrName,L"objectGUID") == 0)
                      || (_wcsicmp(col.pszAttrName,L"schemaIDGUID") == 0) 
                      || (_wcsicmp(col.pszAttrName,L"attributeSecurityGUID") == 0) )
                    {
                      for (x = 0; x< col.dwNumValues; x++)
                      {
                        //Cast to LPGUID
                        pObjectGUID = (LPGUID)(col.pADsValues[x].OctetString.lpValue);
 
                        //Convert GUID to string.
                        ::StringFromGUID2(*pObjectGUID, szDSGUID, 39); 
 
                        //Print the GUID
                        wprintf(L"  %s\r\n",szDSGUID);
                      }
                    }
                    else if ( _wcsicmp(col.pszAttrName,L"oMObjectClass") == 0 )
                    {
                      //TODO: 
                      wprintf(L"  TODO:No conversion for this.");
                    }
                    else
                      wprintf(L"  Value of type Octet String. No Conversion.");
 
                    break;
 
                  case ADSTYPE_UTC_TIME:
                    for (x = 0; x< col.dwNumValues; x++)
                    {
                      systemtime = col.pADsValues[x].UTCTime;
 
                      if (SystemTimeToVariantTime(&systemtime, &date) != 0) 
                      {
                        //Pack in variant.vt
                        varDate.vt = VT_DATE;
                        varDate.date = date;
                        VariantChangeType(&varDate,&varDate,VARIANT_NOVALUEPROP,VT_BSTR);
                        wprintf(L"  %s\r\n",varDate.bstrVal);
                        VariantClear(&varDate);
                      }
                      else
                        wprintf(L"  Could not convert UTC-Time.\n",pszColumn);
                    }
 
                    break;
 
                  case ADSTYPE_LARGE_INTEGER:
                    for (x = 0; x< col.dwNumValues; x++)
                    {
                      liValue = col.pADsValues[x].LargeInteger;
                      filetime.dwLowDateTime = liValue.LowPart;
                      filetime.dwHighDateTime = liValue.HighPart;
 
                      if((filetime.dwHighDateTime==0) && (filetime.dwLowDateTime==0))
                      {
                        wprintf(L"  No value set.\n");
                      }
                      else
                      {
                        //Check for properties of type LargeInteger that represent time
                        //if TRUE, then convert to variant time.
                        if ((0==wcscmp(L"accountExpires", col.pszAttrName))|
                           (0==wcscmp(L"badPasswordTime", col.pszAttrName))||
                           (0==wcscmp(L"lastLogon", col.pszAttrName))||
                           (0==wcscmp(L"lastLogoff", col.pszAttrName))||
                           (0==wcscmp(L"lockoutTime", col.pszAttrName))||
                           (0==wcscmp(L"pwdLastSet", col.pszAttrName))
                          )
                        {
                          //Handle special case for Never Expires where low part is -1
                          if (filetime.dwLowDateTime==-1)
                          {
                            wprintf(L"  Never Expires.\n");
                          }
                          else
                          {
                            if (FileTimeToLocalFileTime(&filetime, &filetime) != 0) 
                            {
                              if (FileTimeToSystemTime(&filetime,
                                                       &systemtime) != 0)
                              {
                                if (SystemTimeToVariantTime(&systemtime,
                                                            &date) != 0) 
                                {
                                  //Pack in variant.vt
                                  varDate.vt = VT_DATE;
                                  varDate.date = date;
                                  VariantChangeType(&varDate,&varDate,VARIANT_NOVALUEPROP,VT_BSTR);
                                  wprintf(L"  %s\r\n",varDate.bstrVal);
                                  VariantClear(&varDate);
                                }
                                else
                                {
                                  wprintf(L"  FileTimeToVariantTime failed\n");
                                }
 
                              }
                              else
                              {
                                wprintf(L"  FileTimeToSystemTime failed\n");
                              }
 
                            }
                            else
                            {
                              wprintf(L"  FileTimeToLocalFileTime failed\n");
                            }
                          }
                        }
                        else
                        {
                          //Print the LargeInteger.
                          wprintf(L"  high: %d low: %d\r\n",filetime.dwHighDateTime, filetime.dwLowDateTime);
                        }
                      }
                    }
                        break;
 
                  case ADSTYPE_NT_SECURITY_DESCRIPTOR:
                    for (x = 0; x< col.dwNumValues; x++)
                    {
                      wprintf(L"  Security descriptor.\n");
                    }
                    break;
 
                  default:
                    wprintf(L"Unknown type %d.\n",col.dwADsType);
                }
            }
            else
            {
              //Verbose handles only the two single-valued attributes: cn and ldapdisplayname
              //so this is a special case.
              if (0==wcscmp(L"cn", pszColumn))
              {
                wcscpy(szCNValue,col.pADsValues->CaseIgnoreString);
              }
 
              if (0==wcscmp(L"lDAPDisplayName", pszColumn))
              {
                wcscpy(szLDAPDispleyNameValue,col.pADsValues->CaseIgnoreString);
              }
            }
 
            pConfigNC->FreeColumn( &col );
          }
 
        FreeADsMem( pszColumn );
      }
 
      if (!bIsVerbose)
        wprintf(L"%s (%s)\n",szLDAPDispleyNameValue,szCNValue);
        //Get the next row
        hr = pConfigNC->GetNextRow( hSearch);
    }
 
  }
 
  // Close the search handle to clean up
  pConfigNC->CloseSearchHandle(hSearch);
 
  }
 
  if (SUCCEEDED(hr) && 0==iCount)
    hr = S_FALSE;
 
  return hr;
 
}
[VBScript]
 
'''''''''''''''''''''''''''''''''''''''
'Parse the arguments
'''''''''''''''''''''''''''''''''''''''
On Error Resume Next
 
msgbox "This script enumerates crossRef objects in the partitions container."
 
sPrefix = "LDAP://"
 
'Get distinguished name for config container and build ADsPath to partitions container.
  Set root= GetObject(sPrefix & "rootDSE")
  If (Err.Number <> 0) Then
     BailOnFailure Err.Number, "on GetObject method for rootDSE"
  End If
  sConfigDN = root.Get("configurationNamingContext")
  If (Err.Number <> 0) Then
     BailOnFailure Err.Number, "on Get method"
  End If
  sContainerDN = "cn=Partitions," & sConfigDN
 
'''''''''''''''''''''''''''''''''''''''
'Bind to the container
'''''''''''''''''''''''''''''''''''''''
Set cont= GetObject(sPrefix & sContainerDN)
If (Err.Number <> 0) Then
  BailOnFailure Err.Number, "on GetObject method for partitions container"
End If
'''''''''''''''''''''''''''''''''''''''
'Enumerate the container.
''''''''''''''''''''''''''''''''''''''
For Each obj In cont
 strText = strText & "Name: " & obj.Get("name") & vbCrLf
 values = obj.GetEx("objectClass")
 For Each value In values
  sValue = value
 Next
 strText = strText & "  objectClass: " & sValue & vbCrLf
 strText = strText & "  DnsRoot: " & obj.Get("dnsRoot") & vbCrLf
 strText = strText & "  NCName: " & obj.Get("NCName") & vbCrLf
 sTrustParent = obj.Get("trustParent")
 If (Err.Number = 0) Then
   strText = strText & "  TrustParent: " & sTrustParent & vbCrLf
 Else
   Err.Clear
 End If
 sNetBIOSName = obj.Get("nETBIOSName")
 If (Err.Number = 0) Then
   strText = strText & "  NETBIOSName: " & sNetBIOSName & vbCrLf
 Else
   Err.Clear
 End If
 
Next
 show_items strText, "Display crossRef"
'''''''''''''''''''''''''''''''''''''''
'Display subroutines
'''''''''''''''''''''''''''''''''''''''
Sub show_items(strText, strName)
    MsgBox strText, vbInformation, "Create CrossRef"
End Sub
 
Sub BailOnFailure(ErrNum, ErrText)    strText = "Error 0x" & Hex(ErrNum) & " " & ErrText
    MsgBox strText, vbInformation, "ADSI Error"
    WScript.Quit
End Sub