How To Enumerate Properties Associated with an Extended Right Using Visual C++ and ATL (302250)
The information in this article applies to:
- Microsoft Windows 2000 Server
- Microsoft Windows 2000 Advanced Server
- Microsoft Visual C++, 32-bit Editions 6.0
- Microsoft Visual Studio, Enterprise Edition 6.0
- Microsoft Active Directory Services Interface, System Component
- Microsoft Active Directory Client Extension
- Microsoft Active Directory Service Interfaces 2.5
This article was previously published under Q302250 SUMMARY
The article shows how to perform a Lightweight Directory Access Protocol (LDAP) search to locate all of the properties in the schema that are part of a given extended right.
The code contained in this article illustrates the following:
- How to use Active Template Library (ATL) to access Active Directory (AD) objects.
- How to set up a simple LDAP query against a given container.
- How to properly encode a binary value for use in an LDAP query string.
- How to display the IDirectorySearch results.
- How to properly manage Active Directory Services Interface (ADSI) objects and interfaces.
- How to use the RootDSE object to obtain information about the directory.
MORE INFORMATIONHow to Use the Code Contained in this Article- Create an empty Windows 32 console application in Visual Studio.
- Click the FileView tab.
- From the File menu, click New, and then click C++ Source File.
- In the File name edit control, type main.cpp, and then click OK.
- Copy the code from the "Main.cpp File Contents" section of this article and paste it into the Main.cpp file in the Visual C++ project.
- From the File menu, click New, and then click C++ Source File.
- In the File name edit control, type util.cpp, and then click OK.
- Copy the code from the "Util.cpp File Contents" section of this article and paste it into the Util.cpp file in the Visual C++ project.
- From the File menu, click New, and then click C/C++ Header File.
- In the File name edit control, type util.h, and then click OK.
- Copy the code from the "Util.h File Contents" section of this article and paste it into the Util.h file in the Visual C++ project.
- From the Project menu, click Settings, and then click the Link tab.
- Add Adsiid.lib and Activeds.lib to the Object/library modules.
- Click the Debug tab.
- In the Program Arguments edit control, type cn=general-information, and then click OK.
- Press CTRL+F5 to build and execute the project.
Visual C++ CodeMain.cpp File Contents
//
// The following code segment illustrates how to enumerate all of the AttributeSchema objects
// whose attributeSecurityGUID matches the RightsGUID of the given extended rights object
//
#define _WIN32_WINNT 0x0500
#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <wchar.h>
#include <stdio.h>
#include <atlbase.h>
#include <objbase.h>
#include <activeds.h>
#include <winnt.h>
#include <sddl.h>
#include "util.h"
int wmain( int argc, wchar_t *argv[ ], wchar_t *envp[ ] )
{
//
// NO error checking is performed. If a call fails, the code
// will end ungracefully. Do not use this code as an example of how
// to properly handle COM errors.
//
// The program expects 1 argument, the LDAP ADsPath of a user object.
// if this path is missing, the code will terminate very ungracefully.
// a sample command line would like:
//
// code_executable "cn=ControlAccessRight_Object_Common_Name"
//
// Assuming of course, that this code was compiled into an executable called
// code_executable.exe
//
// Be sure to include:
// ActiveDS.lib
// Adsiid.lib
// on the Link tab of the project.
//
HRESULT hr = E_FAIL;
//
// Very Important for ADSI interfaces to work proper, must initialize COM
//
CoInitialize(NULL);
//
// Check for the correct number of arguments
//
if( argc < 2 )
{
PrintUsage();
return E_FAIL;
}
//
// Need to bind to the RootDSE to locate the Schema and Configuration Containers
//
CComPtr<IADs> oRootDSE;
VARIANT vData;
VariantInit(&vData);
CComBSTR bConfigurationNamingContext;
CComBSTR bSchemaNamingContext;
CComBSTR bDefaultNamingContext;
hr = ADsGetObject( L"LDAP://RootDSE", IID_IADs, (LPVOID *)&oRootDSE );
if( FAILED( hr ) )
{
printf("Error %d occured opening RootDSE object\nTerminating Program\n");
return E_FAIL;
}
hr = oRootDSE->Get(L"defaultNamingContext", &vData);
bDefaultNamingContext.AppendBSTR( vData.bstrVal );
VariantClear(&vData);
hr = oRootDSE->Get(L"SchemaNamingContext", &vData);
bSchemaNamingContext.AppendBSTR( vData.bstrVal);
VariantClear(&vData);
hr = oRootDSE->Get(L"ConfigurationNamingContext", &vData);
bConfigurationNamingContext.AppendBSTR(vData.bstrVal);
VariantClear(&vData );
oRootDSE.Release();
//
// Build the ControlAccessRight object path from the given Extended Right
// passed as the first argument of the tooll
//
CComBSTR bArg = argv[1];
CComBSTR bControlAccessRightPath = L"LDAP://";
bControlAccessRightPath.AppendBSTR( bArg );
bControlAccessRightPath.Append(L",CN=Extended-Rights,");
bControlAccessRightPath.AppendBSTR( bConfigurationNamingContext);
CComPtr <IADs> oControlAccessRight;
hr = ADsGetObject( bControlAccessRightPath.m_str, IID_IADs, (LPVOID *) &oControlAccessRight);
if( FAILED(hr) )
{
printf("Unable to open ControlAccessRight object :\n%S\nReceived error %d\nTerminating Program\n",
bControlAccessRightPath.m_str, hr);
//
// CleanUp and exit
//
oRootDSE.Release();
CoUninitialize();
return hr;
}
//
// Retrieve the RightsGUID from the ControlAccessRight.
// Put it into the form of "{GUID STRING}"...
//
oControlAccessRight->Get(L"RightsGUID", &vData );
CComBSTR bRightsGUID = L"{";
bRightsGUID.AppendBSTR( vData.bstrVal );
bRightsGUID.Append(L"}");
VariantClear(&vData);
//
// Convert it into its binary equivalent and then Binary Encode it to be used later in
// the LDAP search....
//
// NOTE: The pointer returned by ADsEncodeBinaryData is allocated by the API and must be
// freed when we are done with it using the FreeADsMem API.
//
// We are done with the ControlAccessRight object so we can release the IADs interface
// associated with it.
//
CLSID binaryRightsGUID;
LPWSTR pszEncodedRightsGUID;
CLSIDFromString( bRightsGUID.m_str, &binaryRightsGUID );
ADsEncodeBinaryData( (PBYTE)&binaryRightsGUID, sizeof(CLSID), &pszEncodedRightsGUID);
oControlAccessRight.Release();
//
// Now, bind to the Schema Container and retrieve an IDirectorySearch
// interface to prepare for the LDAP search....
//
CComBSTR bSchemaBindString = L"LDAP://";
bSchemaBindString.AppendBSTR( bSchemaNamingContext);
CComPtr <IADs> oIADsSchema;
hr = ADsGetObject( bSchemaBindString.m_str, IID_IADs, (LPVOID *)&oIADsSchema);
CComQIPtr <IDirectorySearch, &IID_IDirectorySearch> oSearch( oIADsSchema );
oIADsSchema.Release();
//
// Build the LDAP query string that will look someting like:
// LDAP Server : bDefaltNamingContext
// LDAP Query String: (&(objectclass=attributeSchema)(attributeSecurityGUID=BINARY_ENCODED_RIGHTS_GUID))
// LDAP Properties to return: CN
// Search Properties: Paged Search
// Search Scope: Sub Tree ( from the schema container and beyond)
//
//
//
// Build the query string...
//
CComBSTR bLDAPQueryStr;
bLDAPQueryStr = L"(&(objectclass=attributeSchema)(attributeSecurityGUID=";
bLDAPQueryStr.Append( pszEncodedRightsGUID );
bLDAPQueryStr.Append(L"))");
//
// Setup the Attributes and search preferences
//
// Perform a subtree search
//
ADS_SEARCHPREF_INFO prefInfo[2];
prefInfo[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
prefInfo[0].vValue.dwType = ADSTYPE_INTEGER;
prefInfo[0].vValue.Integer = ADS_SCOPE_SUBTREE;
//
// Set the maximum records returned to 1000 ( maximum for AD )
//
prefInfo [1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE ;
prefInfo [1].vValue.dwType = ADSTYPE_INTEGER;
prefInfo [1].vValue.Integer = 1000;
//
// Set bind the search preferences with the IDirectorySearch object...
//
hr = oSearch->SetSearchPreference( prefInfo, 2);
//
// Prepare a list of attributes to return in the query...
// in our case, we want the Common Name only...
//
LPWSTR pszAttr[] = { L"cn"};
ADS_SEARCH_HANDLE hSearch;
DWORD dwCount= sizeof(pszAttr)/sizeof(LPWSTR);
//
// Execute the LDAP Query....
//
hr=oSearch->ExecuteSearch(bLDAPQueryStr.m_str, pszAttr, dwCount, &hSearch );
if (!SUCCEEDED(hr))
{
printf("LDAP Search failed with error %d\nTerminating program\n", hr );
//
// Clean up
//
oSearch.Release();
FreeADsMem( (LPVOID)pszEncodedRightsGUID);
return hr;
}
//
// Now enumerate the result
//
ADS_SEARCH_COLUMN col;
// "0---------1---------2---------3----5"
BOOL bFirstTime = TRUE;
while( oSearch->GetNextRow(hSearch) != S_ADS_NOMORE_ROWS )
{
// Get attributes
//
// CN
//
hr = oSearch->GetColumn( hSearch, pszAttr[0], &col );
if ( SUCCEEDED(hr) )
{
if( bFirstTime )
{
printf("Properties Associated with ControlAccessRight: %S\n", argv[1]);
bFirstTime = FALSE;
}
printf("%S\n",(LPWSTR)col.pADsValues->CaseIgnoreString);
oSearch->FreeColumn( &col );
}
}
oSearch->CloseSearchHandle( hSearch );
oSearch.Release();
//
// Free the binary encoded string received from ADsEncodeBinaryData...
//
FreeADsMem( (LPVOID)pszEncodedRightsGUID);
CoUninitialize();
return 0;
}
Util.cpp File Contents
#include <stdio.h>
//
// UTIL.CPP
//
// Implementation of some global helper functions
//
void PrintUsage( void )
{
printf("Usage:\nexecutable_name ExtRightCN\nWhere:\n\tExtRightCN-> Common Name for an Extended Right\n");
printf("\nie: executable_name \"cn=General-Information\" \n\n");
printf("This utility will perform an LDAP search using the IDirectorySearch\n");
printf("interface against the Schema container to retrieve all of the \n");
printf("attributeSchema objects whose attributeSecurityGUID match the \n");
printf("RightsGUID of the specified Extended Right.\n\n");
}
Util.h File Contents
//
// This header file contains helper functions definitions for
// used by the main ADSI program
//
#ifndef _UTIL_H
#define _UTIL_H
//
// Function Stubs
//
void PrintUsage( void );
#endif // end of definition for _UTIL_H header
REFERENCESFor additional information, click the article numbers below
to view the articles in the Microsoft Knowledge Base:
302515 How To Find All Extended Rights that Apply to a Schema Class Object Using Visual C++
301920 How To Search for a RightsGUID or a SchemaIDGuid
Modification Type: | Minor | Last Reviewed: | 8/15/2005 |
---|
Keywords: | kbDSWADSI2003Swept kbhowto KB302250 kbAudDeveloper |
---|
|