Active
Directory Users and Computers Property Sheets
The Active Directory Users and Computers MMC snap-in is designed
to display a property sheet for various Active Directory objects.
The property sheet contains one or more pages that are used to view
and modify object data. Different object types have different sets
of pages displayed for them. The Active Directory Users and
Computers MMC snap-in also enables third party vendors to add
custom pages to the property sheet for a specific type of object.
For more information, see Property Pages
for Use with Display Specifiers.
Some applications, other than the Active Directory Users and
Computers MMC snap-in, must provide the user with the ability view
and edit attributes for an Active Directory object. The application
could implement its own property sheets, but it is better to offer
a consistent user interface to reduce confusion and learning time.
Fortunately, the Active Directory Users and Computers MMC snap-in
allows any OLE COM application to display a property sheet for an
Active Directory object that is identical to the property sheet
that would be displayed by the Active Directory Users and Computers
MMC snap-in for the same object.
For more information and a code example that hosts an Active
Directory Users and Computers property sheet, see the PropSheetHost
sample in the Platform SDK.
Developer Audience
This documentation assumes that the reader is familiar with COM
operation and component development using C++. It is not currently
possible to create an Active Directory property sheet extension
using Microsoft® Visual Basic®.
Hosting an Active
Directory Users and Computers Property Sheet
To display a
property sheet for an Active Directory object
Create a window that can be used to process messages. This can
be an existing window or a special purpose window. This is known as
the hidden window.
Create an OLE COM object that is derived from
IDataObject. This data object must support the following
data formats:
CFSTR_DSOBJECTNAMES - This
data format contains a DSOBJECTNAMES that identifies the
Active Directory object that the property sheet applies to. When
hosting a property sheet, the more significant members of the
DSOBJECTNAMES structure are shown below:
clsidNamespace
Not currently used. Set this to a GUID for your application
here in case that it is used in the future.
aObjects
Contains an array of DSBOJECT
structures. Each DSBOJECT structure represents a single
directory object. The cItems member contains the number of
elements in the array. Only the first object in this array is used.
Other objects are ignored.
CFSTR_DSDISPLAYSPECOPTIONS
- This data format contains a DSDISPLAYSPECOPTIONS
structure that contains data that will be used by the property
pages, such as where to load the property pages from, the server
and credentials to use, and so on. The more significant members of
the DSDISPLAYSPECOPTIONS are shown below:
offsetAttribPrefix
The attribute prefix string determines where the list of
property pages is obtained from. This must contain one of the
following strings.
Attribute prefix string
Description
"admin"
The property pages are loaded from the
adminPropertyPages attribute.
"shell"
The property pages are loaded from the
shellPropertyPages attribute.
CFSTR_DS_PROPSHEETCONFIG
- This data format contains a PROPSHEETCFG structure that contains
property sheet host data. When hosting a property sheet, the more
significant members of the PROPSHEETCFG structure contain
the following data:
lNotifyHandle
Must be zero.
hwndParentSheet
Contains the handle of the window to receive WM_ADSPROP_NOTIFY_CHANGE
messages when something in one of the pages changes and is applied.
Can be NULL if this message is not desired.
Contains an application-defined identifier that is returned in
the wParam in the WM_DSA_SHEET_CLOSE_NOTIFY message.
If this member is zero, the WM_DSA_SHEET_CLOSE_NOTIFY
message will not be posted to the hidden window.
Initialize the CLSID_DsPropertyPages object by calling
the IShellExtInit::Initialize method. The pidlFolder
and hkeyProgID parameters are not used in this method. The
pdtobj parameter is the pointer to the data object created
in Step 2. When the IShellExtInit::Initialize method is
called, the CLSID_DsPropertyPages object will save a
reference to the data object.
Obtain the IShellPropSheetExt interface for the
CLSID_DsPropertyPages object and call the
IShellPropSheetExt::AddPages method. The lpfnAddPage
parameter is the address of a callback function that you must
implement. The format of this function is shown below. If the
callback function is declared as a member of a C++ class, the
callback function must be declared as static. The
lParam parameter is an application-defined value that can be
used to identify the object that implements the callback function.
When the IShellPropSheetExt::AddPages method is called, the
CLSID_DsPropertyPages object will obtain the data from the
data object and enumerate the property pages registered for the
object display specifiers. The CLSID_DsPropertyPages object
will then enumerate the property page objects, calling each
object’s IShellPropSheetExt::AddPages method.
Each page added by the property page objects will result in
your callback function being called with the handle to the property
page and the application-defined value. Your callback function must
store each property page handle that is passed. When the
CLSID_DsPropertyPages object’s
IShellPropSheetExt::AddPages method returns, all pages will
have been added via your callback function.
Fill in a PROPSHEETHEADER structure to display the
property sheet. The phpage member receives a pointer to an
array of page handles that were collected by your callback
function. The nPages member receives the number of pages in
the page handle array.
Display the property sheet by calling the PropertySheet
function.
If the data in any page is changed and the OK or
Apply buttons are clicked, the window identified by the
hwndParentSheet member of the PROPSHEETCFG structure
will receive a WM_ADSPROP_NOTIFY_CHANGE message. This
message is strictly a notification and requires no specific
action.
When the page is closed, the window identified by the
hwndHidden member of the PROPSHEETCFG structure will
receive a WM_DSA_SHEET_CLOSE_NOTIFY message. This message is
strictly a notification and requires no specific action to be
performed.
In some cases, the existing property sheets will need to display
a secondary property sheet. For example, if you display the
property sheet for a user object and select the Member Of
page, a list of groups that the user is a member of will be
displayed. If you double-click one of these groups in the list, the
property sheet for that group will be displayed. The primary
property sheet does not display the secondary sheet by itself. It
requests that the host display the secondary sheet by sending a
WM_DSA_SHEET_CREATE_NOTIFY message to the window identified
by the hwndHidden member of the PROPSHEETCFG
structure. The wParam of the
WM_DSA_SHEET_CREATE_NOTIFY message is a pointer to a
DSA_SEC_PAGE_INFO
structure that contains information about the secondary property
sheet and the object that it represents. In response to this
message, the property sheet host must display the secondary
property sheet in the same manner as shown above. After processing
the WM_DSA_SHEET_CREATE_NOTIFY message, the message receiver
must free the DSA_SEC_PAGE_INFO structure by passing the
wParam value to the LocalFree function.
Note On Windows 2000, the
wParam of the WM_DSA_SHEET_CREATE_NOTIFY message is a
pointer to a DSA_SEC_PAGE_INFO_WIN2K
structure instead of a DSA_SEC_PAGE_INFO structure.
Duplicating the Behavior
of the CLSID_DsPropertyPages Object
To duplicate
the behavior of the CLSID_DsPropertyPages object
Enumerate the values in the adminPropertyPages or
shellPropertyPages attribute for the display specifier for
the object class. Each value is a string that contains a number,
followed by a comma, followed by the string representation of the
class identifier of the property page extension. For more
information about the format of the property pages display
specifier values, see
Registering the Property Page COM Object in a Display
Specifier.
Convert each class identifier string into a CLSID using
the the CLSIDFromString function.
Sort the extension class identifiers by the number that
precedes each class identifier string in the attribute value. If
two numbers are identical, sort the class identifiers in the order
that the attribute values are obtained from Active Directory.
Enumerate the extension class identifiers, creating an instance
of each extension.
If possible, use the CLSID_DsPropertyPages object to
create the pages rather than do this manually. The
CLSID_DsPropertyPages has been optimized and will correctly
handle failure cases, such as when no display specifier is
available for the current locale. Also, the
CLSID_DsPropertyPages object may change in the future, which
means your property sheets may not exactly match those displayed by
the Active Directory Users and Computers MMC snap-in.
Special Programming Elements
Currently, the following programming elements are not defined in
a published header file. To use these elements, you must define
them yourself in the exact format shown in the particular reference
page.
The following code example shows a safe way to define these
elements that will continue to work even if these elements are
defined in a published header file in the future.