Cet article explique comment placer les données d'image dans et extraire des données l'attribut thumbNailPhoto d'un objet utilisateur dans Active Directory à l'aide du IDirectoryObject et IADsUser interfaces.
La propriété IADsUser::Picture permet d'accéder à l'attribut thumbNailPhoto d'un objet de classe d'utilisateur dans l'Active Directory (AD). L'attribut thumbNailPhoto contient des données de type chaîne octet. L'annuaire Active Directory interprète les données de type chaîne octet comme un tableau d'octets. L'utilisateur est libre de stocker n'importe quel type de données binaires dans l'attribut thumbNailPhoto. L'utilisateur est chargé des afficher les données d'image et insuring que les données appropriées sont stockées dans l'attribut.
Procédure pour utiliser le code fourni dans cet article
Créez une application console Win32 dans Visual C++. Sélectionnez un type d'application Hello World . Nom de l'application getpicture .
Remplacez le contenu entier du fichier getpicture.cpp par le code fourni à la fin de cet article.
Ajouter les fichiers ADSIID.lib et ACTIVEDS.lib à la liste de liens de projets. Les étapes pour ajouter ces fichiers à liste le projet de bibliothèques liées sont comme suit :
Dans le menu projet , cliquez sur Paramètres .
Cliquez sur l'onglet lien .
Dans la zone de texte Modules objet/bibliothèque , ajoutez les deux bibliothèques suivantes : ADSIID.lib et ACTIVEDS.lib .
Cliquez sur OK .
Désactiver les options d'en-têtes précompilés pour le projet sous Paramètres du projet . Les étapes permettant de modifier les options d'en-tête précompilé sont :
Dans le menu projet , cliquez sur Paramètres .
Cliquez sur l'onglet c/c++ .
Dans la catégorie : zone de liste déroulante, sélectionnez les en-têtes précompilés .
Sélectionnez pas à l'aide en-têtes précompilés .
Cliquez sur OK
Remplacer les chaînes prédéfinies dans getpicture.cpp avec leurs valeurs appropriées.
Remarque : Il existe une limite de la taille de l'image stockée sur l'attribut ThumbNailPhoto, et il est stockée en octets de l'objet attributeSchema « image » dans le schéma Active Directory. Les les attributs qui définissent les limites de taille sont « rangeLower » et « rangeUpper » :
LDAP_USER_PATH - ADsPath LDAP pour un objet utilisateur
PICTURE_LOCAL_PATH - nom de chemin d'accès local pour un fichier image (BMP/jpg/gif)
OUTPUT_PATH - chemin local pour recevoir les données à partir de l'annuaire Active Directory
Compilez et liez le projet.
Exécuter le projet.
Code journal getpicture.cpp
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <stdio.h>
#include <atlbase.h>
#include <activeds.h>
#include <adsiid.h>
//
// Predefined strings to use for examples.
// LDAP_USER_PATH must be set to a valid DN of a user object
// PICTURE_LOCAL_PATH must be set to a pathname of a BMP/JPG/GIF or some other picture format file
// OUTPUT_PATH must be set to a filename to receive data from the AD
//
#define LDAP_USER_PATH L"LDAP://USER_DN"
#define PICTURE_LOCAL_PATH "smile.bmp"
#define OUTPUT_PATH "directory.bmp"
//
// BytesToVariantArry creates an ADSTYPE_OCTET_STRING variant
// from a given set of bytes
//
HRESULT BytesToVariantArray(PBYTE pValue, //Pointer to bytes to put in a variant array.
ULONG cValueElements,//Size of pValue in bytes.
VARIANT *pVariant //Return variant containing octet string (VT_UI1|VT_ARRAY).
);
//
// VariantArrayToBytes -> Assumes a single dimentioned array of bytes passed in the
// Variant parameter as an ADSTYPE_OCTET_STRING, returns an array of bytes. the bytes parameter must be freed
// using the free() api call.
//
HRESULT VariantArrayToBytes(
VARIANT Variant,
LPBYTE *bytes,
long *plcb
);
//
// UseIDirectoryObjectSet-> Takes an IADs inteface of a user object,
// QIs for an IDirectoryObject interface and places the bytes pointed to
// by pBuffer into the thumbNailPhoto attribute.
//
HRESULT UseIDirectoryObjectSet( IADs *oIADs,
LPBYTE pBuffer,
DWORD cbBuffer );
//
// UseIDirectoryObjectGet-> Takes an IADs interface of a user object,
// QIs for an IDirectorObject interface and copies the buffer returned
// from the thumbNailPhoto attribute into the bytes parameter. The bytes
// parameter is allocated by the function and must be free using
// the free() API. The length of the buffer is returned in the plcb parameter.
//
HRESULT UseIDirectoryObjectGet( IADs *pIADs, LPBYTE *bytes, long *plcb );
//
// Main Function
//
int main(int argc, char* argv[])
{
int hFile;
CoInitialize( NULL );
//
// Read in the test file
// and determine how many bytes are in the file
// using _lseek
//
hFile = _open( PICTURE_LOCAL_PATH, _O_BINARY | _O_RDONLY );
long retval = _lseek( hFile, 0l, SEEK_END);
//
// Allocate memory and copy the file contents into memory
//
LPBYTE lpbPicture = (LPBYTE)malloc( retval );
_lseek( hFile, 0l, SEEK_SET);
long bRead = _read( hFile, lpbPicture, retval);
//
// Put the memory into a safe array in order to place it
// into the directory
//
VARIANT vPicture;
HRESULT hr = BytesToVariantArray( lpbPicture, retval, &vPicture);
//
// Retrieve an IADsUser object interface
//
CComPtr <IADsUser> pOusr;
CComPtr <IADs> pIADs;
//
hr = ADsGetObject(LDAP_USER_PATH, IID_IADsUser, (VOID **)&pOusr);
//
// Example of how to call the UseIDirectoryObjectSet function:
//hr = UseIDirectoryObjectSet( pIADs, lpbPicture, retval);
//
// Put the variant data into the directory
//
hr = pOusr->put_Picture( vPicture );
hr = pOusr->SetInfo(); // flush the cache back to the server...
pOusr.Release(); // Release the interface and rebind....
//
// Bind to the directory again, and read the property
//
hr = ADsGetObject(LDAP_USER_PATH, IID_IADsUser, (VOID **)&pOusr);
//
// To retrieve the buffer using UseIDirectoryObjectGet, here are the declarations
// and the call:
//
// CComQIPtr<IADs, &IID_IADs> pds( pOusr);
// LPBYTE bBuffer;
// long cbBuffer;
// hr = UseIDirectoryObjectGet( pds, &bBuffer, &cbBuffer);
// pds.Release();
// .
// .
// .
// free( bBuffer );
//
VariantClear( &vPicture ); // Release the old variant, **very important** to free the
// the safe array before reusing the variable vPicture
hr = pOusr->get_Picture( &vPicture );
pOusr.Release();
//
// Write it back to a file
//
PBYTE lpbADPicture;
long cb;
hr = VariantArrayToBytes( vPicture, &lpbADPicture, &cb);
//
// Copy the data back out to the disk file
//
int hFile2 = _open(OUTPUT_PATH, _O_BINARY | _O_CREAT | _O_RDWR);
retval = _lseek( hFile2, 0l, SEEK_SET );
retval = _write( hFile2, lpbADPicture, cb );
//
// Time to clean up..
//
_close( hFile2 );
_close(hFile );
free( (void *)lpbADPicture );
free( (void *)lpbPicture );
VariantClear( &vPicture );
pOusr.Release();
CoUninitialize( );
printf("Done\n");
return 0;
}
//
// This function can be found in the Platform SDK documention
// It allocates the buffer from heap. The buffer must be freed
// when the caller is finished using it.
//
HRESULT VariantArrayToBytes(
VARIANT Variant,
LPBYTE *bytes,
long *plcb
)
{
HRESULT hr = E_FAIL;
SAFEARRAY *pArrayVal = NULL;
CHAR HUGEP *pArray = NULL;
//
//Retrieve the safe array....
//
pArrayVal = Variant.parray;
if (!(pArrayVal == NULL) )
{
long cSize = pArrayVal->rgsabound[0].cElements;
*bytes = (LPBYTE)malloc( cSize );
if( *bytes == NULL ) return E_FAIL;
hr = SafeArrayAccessData(pArrayVal, (void HUGEP * FAR *) &pArray );
if (SUCCEEDED(hr))
{
//Copy the bytes to the safe array.
memcpy( *bytes, pArray, cSize );
SafeArrayUnaccessData( pArrayVal );
*plcb = cSize;
hr = S_OK;
}
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
//
// This function can be found in the Platform SDK documention
//
HRESULT BytesToVariantArray(
PBYTE pValue, //Pointer to bytes to put in a variant array.
ULONG cValueElements,//Size of pValue in bytes.
VARIANT *pVariant //Return variant containing octet string (VT_UI1|VT_ARRAY).
)
{
HRESULT hr = E_FAIL;
SAFEARRAY *pArrayVal = NULL;
SAFEARRAYBOUND arrayBound;
CHAR HUGEP *pArray = NULL;
//Set bound for array
arrayBound.lLbound = 0;
arrayBound.cElements = cValueElements;
//Create the safe array for the octet string. unsigned char elements;single dimension;aBound size.
pArrayVal = SafeArrayCreate( VT_UI1, 1, &arrayBound );
if (!(pArrayVal == NULL) )
{
hr = SafeArrayAccessData(pArrayVal, (void HUGEP * FAR *) &pArray );
if (SUCCEEDED(hr))
{
//Copy the bytes to the safe array.
memcpy( pArray, pValue, arrayBound.cElements );
SafeArrayUnaccessData( pArrayVal );
//Set type to array of unsigned char
V_VT(pVariant) = VT_ARRAY | VT_UI1;
//Assign the safe array to the array member.
V_ARRAY(pVariant) = pArrayVal;
hr = S_OK;
}
else
{
//Clean up if array can't be accessed.
if ( pArrayVal )
SafeArrayDestroy( pArrayVal );
}
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
//
// Take an IADs interface obtain an IDirectoryObject interface, then
// put the buffer pointed to by pBuffer into the thumbNailPhoto attribute
// of the user object
//
// the IADs interface must have been obtained using the LDAP provider. WinNT
// provided IADs interfaces do not support the IDirectoryObject interface.
//
// IDirectoryObject is supported by the LDAP provider.
//
HRESULT UseIDirectoryObjectSet( IADs *oIADs, LPBYTE pBuffer, DWORD cbBuffer )
{
CComQIPtr<IDirectoryObject, &IID_IDirectoryObject> poDirObj(oIADs);
HRESULT hr;
DWORD dwReturn;
ADSVALUE snValue;
ADS_OCTET_STRING octString = { cbBuffer, pBuffer };
ADS_ATTR_INFO attrInfo[] = { {L"thumbNailPhoto",ADS_ATTR_UPDATE,ADSTYPE_OCTET_STRING,&snValue,1} };
DWORD dwAttrs = sizeof(attrInfo)/sizeof(ADS_ATTR_INFO);
snValue.dwType=ADSTYPE_OCTET_STRING;
snValue.OctetString = octString;
hr=poDirObj->SetObjectAttributes(attrInfo, dwAttrs, &dwReturn);
return hr;
}
//
// Illustration of how to use the IDirectoryObject to retrieve
// the thumbNailPhoto attribute
//
// The method takes an IADs interface pointer obtained from the LDAP
// provider.
// See comments above for information on WinNT and IDirectoryObject.
//
// The buffer pointer returned in the bytes parameter must be freed using
// the free() api.
//
HRESULT UseIDirectoryObjectGet( IADs *pIADs, LPBYTE *bytes, long *plcb )
{
CComQIPtr<IDirectoryObject, &IID_IDirectoryObject> poDirObj( pIADs );
HRESULT hr;
ADS_ATTR_INFO *pAttrInfo=NULL;
DWORD dwReturn;
LPWSTR pAttrNames[]={L"thumbNailPhoto" };
DWORD dwNumAttr=sizeof(pAttrNames)/sizeof(LPWSTR);
/////////////////////////////////////////
// Get attribute values requested
// Note: The order is not necessarily the
// same as requested using pAttrNames.
///////////////////////////////////////////
hr = poDirObj->GetObjectAttributes( pAttrNames,
dwNumAttr,
&pAttrInfo,
&dwReturn );
if ( SUCCEEDED(hr) )
{
for(DWORD idx=0; idx < dwReturn;idx++, pAttrInfo++ )
{
if ( _wcsicmp(pAttrInfo->pszAttrName,L"thumbNailPhoto") == 0 )
{
if (pAttrInfo->dwADsType == ADSTYPE_OCTET_STRING)
{
*bytes = (LPBYTE)malloc( pAttrInfo->pADsValues->OctetString.dwLength);
*plcb = pAttrInfo->pADsValues->OctetString.dwLength;
memcpy( *bytes, pAttrInfo->pADsValues->OctetString.lpValue, *plcb);
}
}
}
}
/////////////////////////////////////////////////////////////
// Use FreeADsMem for all memory obtained from the ADSI call.
/////////////////////////////////////////////////////////////
FreeADsMem( pAttrInfo );
return hr;
}
IMPORTANT : Cet article est issu du système de traduction automatique mis au point par Microsoft (http://support.microsoft.com/gp/mtdetails). Un certain nombre d?articles obtenus par traduction automatique sont en effet mis à votre disposition en complément des articles traduits en langue française par des traducteurs professionnels. Cela vous permet d?avoir accès, dans votre propre langue, à l?ensemble des articles de la base de connaissances rédigés originellement en langue anglaise. Les articles traduits automatiquement ne sont pas toujours parfaits et peuvent comporter des erreurs de vocabulaire, de syntaxe ou de grammaire (probablement semblables aux erreurs que ferait une personne étrangère s?exprimant dans votre langue !). Néanmoins, mis à part ces imperfections, ces articles devraient suffire à vous orienter et à vous aider à résoudre votre problème. Microsoft s?efforce aussi continuellement de faire évoluer son système de traduction automatique.
La version anglaise de cet article est la suivante: 292029
(http://support.microsoft.com/kb/292029/en-us/
)
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.
Exclusion de responsabilité concernant les contenus obsolètes dans la Base de connaissances
Cet article concerne des produits pour lesquels Microsoft n'offre plus de support. Il est par conséquent fourni « en l'état » et ne sera plus mis à jour.
Merci ! Vos commentaires sont très utiles pour l'amélioration de notre contenu d'aide et de support. Si vous avez besoin d'aide complémentaire, veuillez consulter la page d'accueil d'aide et support.