ThumbNailPhoto Attribut eines Benutzerobjekts in Active Directory bearbeiten

Veralteter Haftungsausschluss für KB-Inhalte

Dieser Artikel wurde für Produkte geschrieben, für die Microsoft keinen Support mehr anbietet. Deshalb wird dieser Artikel im vorliegenden Zustand bereitgestellt und nicht mehr aktualisiert.

Zusammenfassung

Dieser Artikel veranschaulicht das Bild Daten in Daten aus und das ThumbNailPhoto Attribut eines Benutzerobjekts in Active Directory mithilfe der IDirectoryObject und die IAD -Schnittstellen.

Weitere Informationen

IADsUser::Picture -Eigenschaft bietet Zugriff auf das ThumbNailPhoto Attribut einer Klasse Benutzerobjekt in Active Directory (AD). ThumbNailPhoto Attribut enthält Zeichenfolgendaten Oktett. Anzeige interpretiert als Bytearray Oktett Zeichenfolgendaten. Der Benutzer hat die Freiheit, beliebige Binärdaten im ThumbNailPhoto Attribut speichern. Der Benutzer ist verantwortlich für die Bilddaten Rendern und versichern, dass die entsprechenden Daten im Attribut gespeichert.

Der Code in diesem Artikel beschriebenen Schritte

  1. Erstellen Sie eine neue Win32-in Visual C++. Wählen Sie eine Hello World -Anwendung. Name der Anwendung Getpicture.
  2. Ersetzen Sie den gesamten Inhalt der Getpicture.cpp-Datei mit dem Code am Ende dieses Artikels.
  3. Link-Projektliste ADSIID.lib und ACTIVEDS.lib-Dateien hinzufügen. Die Schritte zum Hinzufügen dieser Dateien Projektliste verknüpften Bibliotheken sind wie folgt:

    1. Wählen Sie im Menü Projekt Einstellungen.
    2. Klicken Sie auf die Registerkarte Verknüpfung .
    3. Textfeld Objekt-/Bibliotheksmodule hinzufügen die folgenden zwei Bibliotheken: ADSIID.lib und ACTIVEDS.lib.
    4. Klicken Sie auf OK.
  4. Deaktivieren Sie die Optionen Vorkompilierte Header für das Projekt unter Projekt. Die Schritte zum Ändern der Optionen für vorkompilierte Header sind:

    1. Klicken Sie im Menü Projekt auf Settings.
    2. Klicken Sie auf die Registerkarte C/c++ .
    3. In der Kategorie: Dropdown-Feld, wählen Sie Vorkompilierte Header.
    4. Wählen Sie Vorkompilierte Header nicht verwenden.
    5. Klicken Sie auf OK
  5. Ersetzen Sie die vordefinierten Zeichenfolgen in Getpicture.cpp mit den entsprechenden Werten.

    Hinweis: Ist beschränkt auf Bildgröße ThumbNailPhoto Attribut gespeichert und werden in Byte auf "Bild" AttributeSchema-Objekts im Active Directory-Schema. Die Attribute, die definieren die Größe sind "RangeLower" und "RangeUpper":
    • LDAP_USER_PATH - LDAP ADsPath für ein Benutzerobjekt
    • PICTURE_LOCAL_PATH - lokaler Pfadname für eine Bilddatei (JPG/BMP/GIF)
    • OUTPUT_PATH - lokaler Pfadname Datenempfang vom AD
  6. Kompilieren Sie und verknüpfen Sie das Projekt.
  7. Führen Sie das Projekt.

GetPicture.cpp-Quellcode

#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;
}

Eigenschaften

Artikelnummer: 292029 – Letzte Überarbeitung: 20.01.2017 – Revision: 1

Feedback