Platform SDK: Active Directory, ADSI, and Directory Services

Directory Object Picker

Using the IDsObjectPicker COM object, an application can display a dialog box that enables a user to select one or more objects from the directory and get back information about the selected objects. Note that the object picker supports only the selection of user, contact, group, and computer objects. Note that well-known security principals (such as Everyone, Anonymous, and so on) can also be included as selectable object in the object picker.

To display an object picker dialog box, call the CoCreateInstance or CoCreateInstanceEx function to create an instance of the system's IDsObjectPicker implementation. Then call the IDsObjectPicker::Initialize method to initialize the dialog box and the IDsObjectPicker::InvokeDialog method to display it.

When you initialize an object picker dialog box, you specify a set of scope types and filters.

The Look in drop-down list contains the scope locations that correspond to the specified scope types. When the user selects a scope from the list, the dialog box applies the filters for that scope type to display a list of objects.

By default, the user can select a single object. To enable multiple selections, set the DSOP_FLAG_MULTISELECT flag in the flOptions member of the DSOP_INIT_INFO structure when you initialize the dialog box.

For more information about the IDsObjectPicker interface and its related structures, see the Platform SDK documentation.

The following functions display the object picker dialog box so that the user can select computer objects. The SelectComputersAndDo function is the main function and calls the InitObjectPicker and ProcessSelectedObjects functions. The InitObjectPicker function initializes the IDsObjectPicker object to search for computers in the current domain. The ProcessSelectedObjects function displays the name, objectClass, and ADsPath of the selected objects in message boxes.

//Need to include objsel.h
UINT g_cfDsObjectPicker; //for clipboard format.
 
HRESULT SelectComputersAndDo(HWND hWnd) //Handle to window that should own the object picker.
{
HRESULT hr = E_FAIL;
IDsObjectPicker *pDsObjectPicker = NULL;
IDataObject *pdo = NULL;
// Create an instance of the object picker.
hr = CoCreateInstance(CLSID_DsObjectPicker,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_IDsObjectPicker,
    (void **) &pDsObjectPicker);
if (SUCCEEDED(hr))
{
    // Initialize the object picker instance.
    hr = InitObjectPicker(pDsObjectPicker);
    // Invoke the modal dialog.
    if (SUCCEEDED(hr))
    {
    hr = pDsObjectPicker->InvokeDialog(hWnd, &pdo);
    if (hr == S_OK) //S_OK means User clicked OK
    {
        //Process the selected objects and display each in a message box.
    ProcessSelectedObjects(pdo);
    if (pdo)
        pdo->Release();
    }
    else if (hr == S_FALSE) //S_FALSE means User clicked Cancel
    MessageBoxA(hWnd,"User canceled object picker dialog\n","Object Picker dialog",MB_OK);
    else
        MessageBoxA(hWnd,"Object picker dialog failed.","Object Picker dialog",MB_OK);
    }
}
if (pDsObjectPicker)
    pDsObjectPicker->Release();
return hr;
}
HRESULT InitObjectPicker(
    IDsObjectPicker *pDsObjectPicker) {
 
g_cfDsObjectPicker =    RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
 
static const int     SCOPE_INIT_COUNT = 1;
DSOP_SCOPE_INIT_INFO aScopeInit[SCOPE_INIT_COUNT];
DSOP_INIT_INFO  InitInfo;
// Initialize the DSOP_SCOPE_INIT_INFO array.
 
ZeroMemory(aScopeInit,
    sizeof(DSOP_SCOPE_INIT_INFO) * SCOPE_INIT_COUNT);
 
// Combine multiple scope types in a single array entry.
 
aScopeInit[0].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
aScopeInit[0].flType = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN
                     | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN;
 
// Set uplevel and downlevel filters to include only computer objects.
// Uplevel filters apply to both mixed and native modes.
// Notice that the uplevel and downlevel flags are different.
 
aScopeInit[0].FilterFlags.Uplevel.flBothModes =
        DSOP_FILTER_COMPUTERS;
aScopeInit[0].FilterFlags.flDownlevel =
        DSOP_DOWNLEVEL_FILTER_COMPUTERS;
 
// Initialize the DSOP_INIT_INFO structure.
 
ZeroMemory(&InitInfo, sizeof(InitInfo));
 
InitInfo.cbSize = sizeof(InitInfo);
InitInfo.pwzTargetComputer = NULL;  // Target is the local computer.
InitInfo.cDsScopeInfos = SCOPE_INIT_COUNT;
InitInfo.aDsScopeInfos = aScopeInit;
InitInfo.flOptions = DSOP_FLAG_MULTISELECT;
 
// You can call Initialize multiple times; last call wins.
// Note that object picker makes its own copy of InitInfo.
 
return pDsObjectPicker->Initialize(&InitInfo);
}
 
void ProcessSelectedObjects(
    IDataObject *pdo  // Data object containing user's selections
)
{
 
CHAR *szText = new CHAR[MAX_PATH*3];
HRESULT hr = S_OK;
BOOL fGotStgMedium = FALSE;
PDS_SELECTION_LIST pDsSelList = NULL;
ULONG i;
STGMEDIUM stgmedium = {
    TYMED_HGLOBAL,
    NULL,
    NULL
};
FORMATETC formatetc = {
    g_cfDsObjectPicker,
    NULL,
    DVASPECT_CONTENT,
    -1,
    TYMED_HGLOBAL
};
 
do {
    // Get the global memory block containing the user's selections.
 
    hr = pdo->GetData(&formatetc, &stgmedium);
    if (FAILED(hr)) break;
    fGotStgMedium = TRUE;
 
    // Retrieve pointer to DS_SELECTION_LIST structure.
 
    pDsSelList = (PDS_SELECTION_LIST) GlobalLock(stgmedium.hGlobal);
    if (!pDsSelList) break;
 
    // Loop through DS_SELECTION array of selected objects.
 
    for (i = 0; i < pDsSelList->cItems; i++) {
        wsprintf(szText,"Object: %u\nName: %ws\nClass: %ws\nADsPath: %ws", 
            i,
                pDsSelList->aDsSelection[i].pwzName,
                pDsSelList->aDsSelection[i].pwzClass,
                pDsSelList->aDsSelection[i].pwzADsPath);
    MessageBox(NULL,szText,"Selection",MB_OK);
    }
 
    GlobalUnlock(stgmedium.hGlobal);
} while (0);
 
if (fGotStgMedium)
    ReleaseStgMedium(&stgmedium);
 
}