This is all very well, but alert readers may have notice that we have skipped over the $64000 question, namely, what does an Active Directory path look like? And where do we start?
There are actually two forms of pathname supported. One of these is only provided for compatibility with the original COM format for display names. (We saw those in our discussion of monikers in Chapter 2.) For the record, a COM format pathname is basically like this:
@<Namespace>!<Provider-specific stuff>
However, we won't be using this format in our discussions here. The more usual format used in Active Directory is URL format. URL format pathnames look like this:
<Namespace>:
Or:
<Namespace>://<Provider-specific stuff>
Frankly, this gives the system plenty of scope. As you've probably realized by now, my preferred method of gaining insight into what the theory actually means in practice is to throw some code together, and see what it does. So let's run up our directory manager application, and see which paths it takes us down. We do need one major clue as to where to start –that the master namespace of all is called… oh, go on, guess. Yes, it's called "ADS". And that means that the mother of all pathnames is ADS:
. Let's see what happens when we enumerate all the objects in the container starting at ADS:
…
The answer will depend on what sort of directories you have set up on your system, but I'm willing to bet that you have one called WinNT:
and one called LDAP:
, amongst others. For example, this screenshot is from an NT4 Enterprise Edition system:
The result under the NT5 Beta 1 system looks very similar.
We'll steer clear of LDAP:
for the time being, although we'll find out much more about it later. For now, we'll take a look at WinNT:
. Let's make a small change to the application. Wouldn't it be good if you could double click on one of the items in the list box, and if it happens to represent a container, it re-starts the enumeration from there.
Here we go …
void CDirManagerDlg::OnDblclkObjects()
{
// Get currently selected item
CListBox* pObjects = static_cast<CListBox*>(GetDlgItem(IDC_OBJECTS));
int index = pObjects->GetCurSel();
CString csObject;
pObjects->GetText(index, csObject);
// Extract pathname from object
int start = csObject.Find('(');
int end = csObject.Find(')');
CString csPath = csObject.Mid(start + 1, end - start - 1);
// Get hold of object interface
IADsPtr pObject;
HRESULT hr = ADsGetObject(_bstr_t(csPath), IID_IADs,
reinterpret_cast<void**>(&pObject));
if (FAILED(hr))
{
DisplayComError(_T("Failed to get object"), hr);
return;
}
This time around, we don't know if we've got a container interface, so we'd better kick off with the straight object, and QI
for the container …
// Find out if it's a container
IADsContainerPtr pContainer;
hr = pObject->QueryInterface(IID_IADsContainer,
reinterpret_cast<void**>(&pContainer));
if (hr == S_OK)
{
// If it is, move this entry to main field and enumerate again
SetDlgItemText(IDC_PATH, csPath);
OnEnumerate();
return;
}
...
}
If the end result is a leaf object, rather than a container, we'll do something a bit different. But let's leave that for a while. Instead, let's try out the new code to see what happens as we delve into WinNT:
.
If you double click on WinNT:
to make that our enumeration start point, you should see a list of workspace or domain pathnames appear. For example, here's the NT4 enterprise edition one that I showed earlier:
Double-click on this one, and we get a list of whole list of domain-specific objects:
Take a look at some of these, such as Administrator
(pathname WinNT://OVERTHEHILLS/Administrator
). This sounds suspiciously like a user object, but how can we find out for sure? Wouldn't it be nice to be able to find out which class it's in? Even better, wouldn't it be fun to find out more about that class? Well, this is where that Class… button in our dialog box comes in, but more of that later. First, we're going to have to complete our tour of the main ADSI interfaces.