Figure 3   Common Distinguished Name Monikers

Identifier
Description
Common Name (cn)
This is the descriptor that is most often used for objects under organizational objects. Most objects will use this identifier for their object name. For example, cn=bgates is an object with the common name (cn) of bgates.
Organization (o)
Most objects with this identifier are objects of the Organization class. For example, o=microsoft is an organization called Microsoft within the hierarchy.
Organizational Unit (ou)
Most objects with this identifier are objects of the Organizational Unit class. For example, ou=operatingsystems is an organizational unit (usually under an organization) called Operating Systems.
Locality (l)
This represents a city or area. Most objects with this identifier are objects of the Locality class. For example, l=boston is a locality called Boston.
Country (c)
This is the top-level organizational element and signifies that this is an object of the type country class. For example, c=us describes the object that represents the U.S. in the hierarchy.


Figure 11   The IADs Interface

Property
Description
Name
The object's relative name
Class
The name of the object's schema class
GUID
The GUID of the object as stored in the underlying directory store
ADsPath
The object's ADsPath that uniquely identifies this object from all others
Parent
The ADsPath string for the parent of the object
Schema
The ADsPath string to the schema class object for this object
Method
Description
GetInfo
Loads the property values of this object from the underlying directory store
SetInfo
Persists the changes on this object to the underlying directory store
Get
Gets the value for a property by name
Put
Sets the value for a property by name
GetEx
Gets the value for a single or multivalued property by name
PutEx
Sets the value for a single or multivalued property by name
GetInfoEx
Loads specific property values of this object from the underlying directory store


Figure 12   Publication Schema

PublicationItem Class
Attribute
Value
Common name
MSJ-DR-PublicationItem
LDAP display name
mSJ-DRPublicationItem
OID
{YourRootClassOID}.1
Class category
auxiliary
Object category
MSJ-DR-PublicationItem
Parent class
top
Auxiliary classes
none
Possible superiors
none
Mandatory attributes
none
Optional attributes
MSJ-DRPublicationDate
description, notes
Publisher Class
Attribute
Value
Common name
MSJ-DR-Publisher
LDAP display name
mSJ-DRPublisher
OID
{YourRootClassOID}.2
Class category
structural
Object category
MSJ-DR-Publisher
Parent class
organizationalUnit
Auxiliary classes
none
Possible superiors
container
Mandatory attributes
ou
objectClass
Optional attributes
streetaddress
city
st
postalCode
telephoneNumber
description
notes
Publication Class
Attribute
Value
Common name
MSJ-DR-Publication
LDAP display name
mSJ-DRPublication
OID
{YourRootClassOID}.3
Class category
structural
Object category
MSJ-DR-Publication
Parent class
container
Auxiliary classes
MSJ-DR-PublicationItem
Possible superiors
MSJ-DR-Publisher
Mandatory attributes
cn
objectClass
Optional attributes
MSJ-DRPublishedInterval
MSJ-DRIsPeriodical
Volume Class
Attribute
Value
Common name
MSJ-DR-Volume
LDAP display name
mSJ-DRVolume
OID
{YourRootClassOID}.4
Class category
structural
Object category
MSJ-DR-Volume
Parent class
container
Auxiliary classes
MSJ-DR-PublicationItem
Possible superiors
MSJ-DR-Publication
Mandatory attributes
cn
objectClass
Optional attributes
none
Issue Class
Attribute
Value
Common name
MSJ-DR-Issue
LDAP display name
mSJ-DRIssue
OID
{YourRootClassOID}.5
Class category
structural
Object category
MSJ-DR-Issue
Parent class
container
Auxiliary classes
MSJ-DR-PublicationItem
Possible superiors
MSJ-DR-Publication
MSJ-DR-Volume
Mandatory attributes
cn
objectClass
Optional attributes
none
Article Class
Attribute
Value
Common name
MSJ-DR-Article
LDAP display name
mSJ-DRArticle
OID
{YourRootClassOID}.6
Class category
structural
Object category
MSJ-DR-Article
Parent class
container
Auxiliary classes
MSJ-DR-PublicationItem
Possible superiors
MSJ-DR-Publication
MSJ-DR-Volume
MSJ-DR-Issue
Mandatory attributes
cn
objectClass
Optional attributes
url
MSJ-DRAbstractURL
MSJ-DRStartPageNumber
MSJ-DREndPageNumber
MSJ-DRAuthors

PublicationDate Attribute
Attribute
Value
Common name
MSJ-DR-PublicationDate
LDAP display name
mSJ-DRPublicationDate
OID
{YourRootAttributeOID}.1
Syntax
UTCTime
Minimum

Maximum

Is multivalued?
FALSE
Is indexed?
TRUE
PublishedInterval Attribute
Attribute
Value
Common name
MSJ-DR-PublishedInterval
LDAP display name
mSJ-DRPublishedInterval
OID
{YourRootAttributeOID}.2
Syntax
Integer
Minimum

Maximum

Is multivalued?
FALSE
Is indexed?
FALSE
IsPeriodical Attribute
Attribute
Value
Common name
MSJ-DR-IsPeriodical
LDAP display name
mSJ-DRIsPeriodical
OID
{YourRootAttributeOID}.3
Syntax
Boolean
Minimum

Maximum

Is multivalued?
FALSE
Is indexed?
FALSE
AbstractURL Attribute
Attribute
Value
Common name
MSJ-DR-AbstractURL
LDAP display name
mSJ-DRAbstractURL
OID
{YourRootAttributeOID}.4
Syntax
Unicode String
Minimum

Maximum

Is multivalued?
FALSE
Is indexed?
FALSE
StartPageNumber Attribute
Attribute
Value
Common name
MSJ-DR-StartPageNumber
LDAP display name
mSJ-DRStartPageNumber
OID
{YourRootAttributeOID}.5
Syntax
Integer
Minimum

Maximum

Is multivalued?
FALSE
Is indexed?
FALSE
EndPageNumber Attribute
Attribute
Value
Common name
MSJ-DR-EndPageNumber
LDAP display name
mSJ-DREndPageNumber
OID
{YourRootAttributeOID}.6
Syntax
Integer
Minimum

Maximum

Is multivalued?
FALSE
Is indexed?
FALSE
Authors Attribute
Attribute
Value
Common name
MSJ-DR-Authors
LDAP display name
mSJ-DRAuthors
OID
{YourRootAttributeOID}.7
Syntax
Unicode String
Minimum

Maximum

Is multivalued?
TRUE
Is indexed?
FALSE


Figure 14   Viewing Objects


 /////////////////////////////////////////////////////////////////////////
 // How to iterate through the objects created in the previous
 // example of creating new objects
 /////////////////////////////////////////////////////////////////////////
 void CMSJADSIDlg::OnBtnShowobjects() 
 {
     HRESULT hr;
     IADsContainer* pContainer = NULL;
     IADs* pAD = NULL;
     IDispatch* pDisp = NULL;
     
     // Validate Connection
     if (!m_pContainer) 
     {
         AddToLog("Container not open, Please Open Container First");
         return;
     }
 
     // Get the Root Container
     hr = m_pContainer->GetObject(   L"container", 
                                     L"CN=DocRepo",
                                     &pDisp);
     if (FAILED(hr))
     {
         AddToLog("Failed to Get the Container Object, please restart!");
         return;
     }
     hr = pDisp->QueryInterface( IID_IADsContainer, (void**) &pContainer );
     hr = pDisp->QueryInterface (IID_IADs, (void**) &pAD);
     pDisp->Release(); 
 
     // Show the Hierarchy Below the the Container (Recursive Function)
     BSTR bstrName;
     _variant_t varDesc;
     pAD->get_Name(&bstrName);
     pAD->Get(L"description", &varDesc);
     if (varDesc.vt == VT_BSTR)
     {
         AddToLog(CString(bstrName) + " : " + varDesc.bstrVal );
     } 
     else
     {
         AddToLog(CString(bstrName));
     }
     SysFreeString(bstrName);
     pAD->Release();
     ShowHierarchy(pContainer);
      
 }
 
 // Recursive Function to Dump all Objects to the Log
 void CMSJADSIDlg::ShowHierarchy(IADsContainer *pContainer)
 {
     static short    nIndent = 0;
     IEnumVARIANT*   pEnum;
     LPUNKNOWN       pUnk;
     IDispatch*      pDisp;
     ULONG           lFetch;
     IADs*           pAD;
     IADsContainer*  pNewContainer;
     BSTR            bstrName, bstrSchema;
     _variant_t      var, varDesc;
 
     // Start Indenting
     nIndent += 2;
 
     // Create Indentation
     CString csIndent;
     for (int x = 0; x < nIndent; x++) csIndent += " ";
     
     // Get the Enumeration Interface
     pContainer->get__NewEnum(&pUnk);
     pUnk->QueryInterface(IID_IEnumVARIANT, (void**) &pEnum);
     pUnk->Release();
     // Now Enumerate 
     HRESULT hr = pEnum->Next(1, &var, &lFetch);
     while(hr == S_OK)
     {
         if (lFetch == 1)
         {
             pDisp = V_DISPATCH(&var);
             pDisp->QueryInterface(IID_IADs, (void**)&pAD); 
             pAD->get_Name(&bstrName);
             pAD->Get(L"description", &varDesc);
             if (varDesc.vt == VT_BSTR)
             {
                 AddToLog(csIndent + bstrName + " : " + varDesc.bstrVal );
             } 
             else
             {
                 AddToLog(CString(bstrName));
             }
             SysFreeString(bstrName);
             // Recurse if Necessary
             pAD->get_Schema(&bstrSchema);
             IADsClass* pCls;
             ADsGetObject(bstrSchema, IID_IADsClass, (void**)&pCls);
             SysFreeString(bstrSchema);
             VARIANT_BOOL isContainer;
             pCls->get_Container(&isContainer);
             if(isContainer) 
             {
                 pAD->QueryInterface( IID_IADsContainer, 
                                      (void**) &pNewContainer);
                 ShowHierarchy(pNewContainer);                   
                 pNewContainer->Release();
             }
             pCls->Release();            
             // Release the Object
             pAD->Release();
         }
         hr = pEnum->Next(1, &var, &lFetch);
     };
     pEnum->Release();
 
 
     // Reduce the index if possible
     nIndent -= 2;
     return;
}

Figure 15   Searching for Objects


 /////////////////////////////////////////////////////////////////////////
 // Example of how to search for objects in the Active Directory
 /////////////////////////////////////////////////////////////////////////
 void CMSJADSIDlg::OnBtnSearch() 
 {
     UpdateData();
     
     HRESULT hr;
     IDirectorySearch* pSearch = NULL;
     ADS_SEARCH_HANDLE hSearch;
     long nFound = 0;
     ADS_SEARCH_COLUMN col;
     
     // Validate Connection
     if (!m_pContainer) 
     {
         AddToLog("Container not open, Please Open Container First");
         return;
     }
 
     // Get IDirectorySearch Object
     hr = m_pContainer->QueryInterface(IID_IDirectorySearch, 
                                       (void**) &pSearch);
     if (FAILED(hr)) 
     {
         AddToLog("Failed to Get Search Interface!");
         return;
     }
 
     // Set Search Defaults, to search the entire subtree
     ADS_SEARCHPREF_INFO prefInfo[1];
     prefInfo[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
     prefInfo[0].vValue.dwType = ADSTYPE_INTEGER;
     prefInfo[0].vValue.Integer = ADS_SCOPE_SUBTREE;
     hr = pSearch->SetSearchPreference( prefInfo, 1);
         
     // Execute Search
     LPWSTR pszAttr[] = { L"Name", L"description" };
     DWORD dwCount = sizeof(pszAttr)/sizeof(LPWSTR);
     hr = pSearch->ExecuteSearch(
                         m_csSearchCriteria.AllocSysString(),
                         pszAttr,
                         dwCount,
                         &hSearch
                                 );
 
     // Display Contents
     if (SUCCEEDED(hr))
     {
         while( SUCCEEDED(hr = pSearch->GetNextRow(hSearch)) &&
                hr != S_ADS_NOMORE_ROWS   )
         {
             CString csLogItem;
             // Get Name
             if ( SUCCEEDED(pSearch->GetColumn(  hSearch, 
                                                 pszAttr[0], 
                                                 &col ) ) )
             {
                csLogItem = CString("Found: ") + 
                    col.pADsValues->CaseIgnoreString;
                pSearch->FreeColumn( &col );
             }
             // Get Description
             if ( SUCCEEDED(pSearch->GetColumn(  hSearch, 
                                                 pszAttr[1], 
                                                 &col ) ) )
             {
                csLogItem += CString(" : ") +
                    col.pADsValues->CaseIgnoreString;
                pSearch->FreeColumn( &col );
             }
             AddToLog(csLogItem);
             nFound++;
         }
         pSearch->CloseSearchHandle(hSearch);
     }
     
     CString csTemp;
     csTemp.Format("Found %d Items...", nFound);
     AddToLog(csTemp);
 }