Cómo deben usar las aplicaciones especificadores de pantalla
Para mostrar Dominio de Active Directory objetos Service, use especificadores de visualización para obtener datos de visualización localizados para objetos de clase y atributo. Esto permite usar los nombres para mostrar localizados y los iconos y evitar la localización innecesaria de los datos de visualización.
Nombres para mostrar
Las propiedades classDisplayName y attributeDisplayNames de los objetos del especificador de visualización para la configuración regional adecuada deben usarse para obtener texto para mostrar para los nombres de clase y atributo. No use las propiedades cn, classDisplayName o ldapDisplayName de los objetos classSchema o attributeSchema para obtener etiquetas de texto para mostrar porque estos valores no están localizados. Para obtener más información sobre cómo recuperar texto localizado para un objeto de clase, vea el código de ejemplo siguiente.
Iconos
La propiedad iconPath de los objetos del especificador de visualización para la configuración regional adecuada se debe usar para obtener el icono que se va a mostrar para un objeto de clase. Para obtener más información, vea Iconos de clase. Si no se especifica ningún icono localizado para un objeto de clase, se debe mostrar un icono predeterminado para el elemento.
Crear nuevos objetos
Cuando sea posible, use los asistentes de creación de objetos adecuados para crear nuevos objetos. Para obtener más información, consulte Invocación de asistentes para la creación desde la aplicación.
En el ejemplo de código siguiente se muestra cómo obtener el texto para mostrar de una clase y un atributo de una clase.
#include <atlbase.h>
/**************************************************************************
GetClassDisplaySpecifierContainer()
**************************************************************************/
HRESULT GetClassDisplaySpecifierContainer(LPWSTR pwszClass,
LCID locale,
IADs **ppads)
{
if((NULL == pwszClass) || (NULL == ppads))
{
return E_INVALIDARG;
}
*ppads = NULL;
// If no locale is specified, use the default system locale.
if(0 == locale)
{
locale = GetSystemDefaultLCID();
if(0 == locale)
{
return E_FAIL;
}
}
// Verify that it is a valid locale.
if(!IsValidLocale(locale, LCID_SUPPORTED))
{
return E_INVALIDARG;
}
HRESULT hr;
IADs *padsRoot = NULL;
hr = ADsOpenObject( L"LDAP://rootDSE",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)&padsRoot);
if(SUCCEEDED(hr))
{
VARIANT var;
VariantInit(&var);
// Get the DN to the configuration container.
hr = padsRoot->Get(CComBSTR(L"configurationNamingContext"), &var);
if(SUCCEEDED(hr))
{
WCHAR wszPath[MAX_PATH * 2];
// Build the string to bind to the container for the
// specified locale in the DisplaySpecifiers container.
swprintf_s(wszPath,
L"LDAP://cn=%s-Display,cn=%x,cn=DisplaySpecifiers,%s",
pwszClass,
locale,
var.bstrVal);
VariantClear(&var);
// Bind to the container.
hr = ADsOpenObject( wszPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)ppads);
}
padsRoot->Release();
}
return hr;
}
/**************************************************************************
GetClassDisplayLabel()
**************************************************************************/
HRESULT GetClassDisplayLabel(LPWSTR pwszClass,
LCID locale,
BSTR *pbstrClassLabel)
{
if((NULL == pwszClass) || (NULL == pbstrClassLabel))
{
return E_INVALIDARG;
}
*pbstrClassLabel = NULL;
HRESULT hr;
IADs *padsDispSpec;
hr = GetClassDisplaySpecifierContainer(pwszClass, locale, &padsDispSpec);
if(SUCCEEDED(hr))
{
VARIANT var;
VariantInit(&var);
// Get the classDisplayName property value.
hr = padsDispSpec->Get(CComBSTR(L"classDisplayName"), &var);
if(SUCCEEDED(hr))
{
if(VT_BSTR == var.vt)
{
// Do not free the BSTR. The caller will handle it.
*pbstrClassLabel = var.bstrVal;
}
else
{
VariantClear(&var);
hr = E_FAIL;
}
}
padsDispSpec->Release();
}
return hr;
}
/**************************************************************************
GetAttributeDisplayLabel()
**************************************************************************/
HRESULT GetAttributeDisplayLabel(LPWSTR pwszClass,
LPWSTR pwszAttribute,
LCID locale,
BSTR *pbstrAttributeLabel)
{
if( (NULL == pwszClass) ||
(NULL == pwszAttribute) ||
(NULL == pbstrAttributeLabel))
{
return E_INVALIDARG;
}
*pbstrAttributeLabel = NULL;
HRESULT hr;
IADs *padsDispSpec;
hr = GetClassDisplaySpecifierContainer(pwszClass, locale, &padsDispSpec);
if(SUCCEEDED(hr))
{
VARIANT var;
VariantInit(&var);
// Get the attributeDisplayNames property values
hr = padsDispSpec->GetEx(CComBSTR(L"attributeDisplayNames"), &var);
if(SUCCEEDED(hr))
{
LONG lStart,
lEnd,
i;
SAFEARRAY *psa;
VARIANT varItem;
VariantInit(&varItem);
psa = V_ARRAY(&var);
// Get the lower and upper bound.
hr = SafeArrayGetLBound(psa, 1, &lStart);
hr = SafeArrayGetUBound(psa, 1, &lEnd);
/*
The attributeDisplayNames values take the form
"<attribute name>,<display name>". Enumerate the values, looking
for the one that begins with the specified attribute name.
*/
for(i = lStart; i <= lEnd; i++)
{
hr = SafeArrayGetElement(psa, &i, &varItem);
if(SUCCEEDED(hr))
{
WCHAR wszTemp[MAX_PATH];
wcsncpy_s(wszTemp,
V_BSTR(&varItem),
lstrlenW(pwszAttribute) + 1);
if(0 == lstrcmpiW(pwszAttribute, wszTemp))
{
LPWSTR pwszDisplayLabel;
/*
The proper value was found. Now, parse the value, looking
for the first comma, which delimits the attribute name
from the display name.
*/
for( pwszDisplayLabel = V_BSTR(&varItem);
*pwszDisplayLabel;
pwszDisplayLabel = CharNextW(pwszDisplayLabel))
{
if(',' == *pwszDisplayLabel)
{
/*
The delimiter was found. Set the string
pointer to the next character, which is the
first character of the display name.
*/
pwszDisplayLabel = CharNextW(pwszDisplayLabel);
break;
}
}
if(*pwszDisplayLabel)
{
// Copy the display name to the output.
*pbstrAttributeLabel = CComBSTR(pwszDisplayLabel).Detach();
hr = S_OK;
}
/*
Release the item variant because the break prevents
it from getting released by the VariantClear call below.
*/
VariantClear(&varItem);
break;
}
VariantClear(&varItem);
}
}
}
padsDispSpec->Release();
}
return hr;
}