Microsoft KB Archive/302250

= How To Enumerate Properties Associated with an Extended Right Using Visual C++ and ATL =

Article ID: 302250

Article Last Modified on 8/15/2005

-

APPLIES TO


 * Microsoft Windows 2000 Server
 * Microsoft Windows 2000 Advanced Server
 * Microsoft Visual C++ 6.0 Service Pack 5
 * Microsoft Visual Studio 6.0 Enterprise Edition
 * Microsoft Active Directory Service Interfaces 2.5
 * 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:
 * 1) How to use Active Template Library (ATL) to access Active Directory (AD) objects.
 * 2) How to set up a simple LDAP query against a given container.
 * 3) How to properly encode a binary value for use in an LDAP query string.
 * 4) How to display the IDirectorySearch results.
 * 5) How to properly manage Active Directory Services Interface (ADSI) objects and interfaces.
 * 6) How to use the RootDSE object to obtain information about the directory.



How to Use the Code Contained in this Article

 * 1) Create an empty Windows 32 console application in Visual Studio.
 * 2) Click the FileView tab.
 * 3) From the File menu, click New, and then click C++ Source File.
 * 4) In the File name edit control, type main.cpp, and then click OK.
 * 5) Copy the code from the &quot;Main.cpp File Contents&quot; section of this article and paste it into the Main.cpp file in the Visual C++ project.
 * 6) From the File menu, click New, and then click C++ Source File.
 * 7) In the File name edit control, type util.cpp, and then click OK.
 * 8) Copy the code from the &quot;Util.cpp File Contents&quot; section of this article and paste it into the Util.cpp file in the Visual C++ project.
 * 9) From the File menu, click New, and then click C/C++ Header File.
 * 10) In the File name edit control, type util.h, and then click OK.
 * 11) Copy the code from the &quot;Util.h File Contents&quot; section of this article and paste it into the Util.h file in the Visual C++ project.
 * 12) From the Project menu, click Settings, and then click the Link tab.
 * 13) Add Adsiid.lib and Activeds.lib to the Object/library modules.
 * 14) Click the Debug tab.
 * 15) In the Program Arguments edit control, type cn=general-information, and then click OK.
 * 16) Press CTRL+F5 to build and execute the project.

Main.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 //
 * 1) define _WIN32_WINNT 0x0500
 * 2) define UNICODE


 * 1) include 
 * 2) include 
 * 3) include 
 * 4) include 
 * 5) include 
 * 6) include 
 * 7) include 
 * 8) include 
 * 9) include 
 * 10) include &quot;util.h&quot;

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 &quot;cn=ControlAccessRight_Object_Common_Name&quot; //   // 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 oRootDSE; VARIANT vData; VariantInit(&vData); CComBSTR bConfigurationNamingContext; CComBSTR bSchemaNamingContext; CComBSTR bDefaultNamingContext; hr = ADsGetObject( L&quot;LDAP://RootDSE&quot;, IID_IADs, (LPVOID *)&oRootDSE ); if( FAILED( hr ) ) {     printf(&quot;Error %d occured opening RootDSE object\nTerminating Program\n&quot;); return E_FAIL; }  hr = oRootDSE->Get(L&quot;defaultNamingContext&quot;, &vData); bDefaultNamingContext.AppendBSTR( vData.bstrVal ); VariantClear(&vData); hr = oRootDSE->Get(L&quot;SchemaNamingContext&quot;, &vData); bSchemaNamingContext.AppendBSTR( vData.bstrVal); VariantClear(&vData); hr = oRootDSE->Get(L&quot;ConfigurationNamingContext&quot;, &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&quot;LDAP://&quot;; bControlAccessRightPath.AppendBSTR( bArg ); bControlAccessRightPath.Append(L&quot;,CN=Extended-Rights,&quot;); bControlAccessRightPath.AppendBSTR( bConfigurationNamingContext); CComPtr  oControlAccessRight; hr = ADsGetObject( bControlAccessRightPath.m_str, IID_IADs, (LPVOID *) &oControlAccessRight); if( FAILED(hr) ) {     printf(&quot;Unable to open ControlAccessRight object :\n%S\nReceived error %d\nTerminating Program\n&quot;,         bControlAccessRightPath.m_str, hr); //      // CleanUp and exit //      oRootDSE.Release; CoUninitialize; return hr; }  //    // Retrieve the RightsGUID from the ControlAccessRight. // Put it into the form of &quot;{GUID STRING}&quot;... //   oControlAccessRight->Get(L&quot;RightsGUID&quot;, &vData ); CComBSTR bRightsGUID = L&quot;{&quot;; bRightsGUID.AppendBSTR( vData.bstrVal ); bRightsGUID.Append(L&quot;}&quot;); 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&quot;LDAP://&quot;; bSchemaBindString.AppendBSTR( bSchemaNamingContext); CComPtr  oIADsSchema; hr = ADsGetObject( bSchemaBindString.m_str, IID_IADs, (LPVOID *)&oIADsSchema); CComQIPtr  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&quot;(&(objectclass=attributeSchema)(attributeSecurityGUID=&quot;; bLDAPQueryStr.Append( pszEncodedRightsGUID ); bLDAPQueryStr.Append(L&quot;))&quot;); //   // 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&quot;cn&quot;}; 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(&quot;LDAP Search failed with error %d\nTerminating program\n&quot;, hr ); //      // Clean up      // oSearch.Release; FreeADsMem( (LPVOID)pszEncodedRightsGUID); return hr; }  //    // Now enumerate the result //   ADS_SEARCH_COLUMN col; //    &quot;0-1-2-35&quot; 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(&quot;Properties Associated with ControlAccessRight: %S\n&quot;, argv[1]); bFirstTime = FALSE; }        printf(&quot;%S\n&quot;,(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
// // UTIL.CPP // // Implementation of some global helper functions // void PrintUsage( void ) {   printf(&quot;Usage:\nexecutable_name ExtRightCN\nWhere:\n\tExtRightCN-> Common Name for an Extended Right\n&quot;); printf(&quot;\nie: executable_name \&quot;cn=General-Information\&quot; \n\n&quot;); printf(&quot;This utility will perform an LDAP search using the IDirectorySearch\n&quot;); printf(&quot;interface against the Schema container to retrieve all of the \n&quot;); printf(&quot;attributeSchema objects whose attributeSecurityGUID match the \n&quot;); printf(&quot;RightsGUID of the specified Extended Right.\n\n&quot;); }
 * 1) include <stdio.h>

Util.h File Contents
// // This header file contains helper functions definitions for // used by the main ADSI program //

//   // Function Stubs //   void PrintUsage( void );
 * 1) ifndef _UTIL_H
 * 2) define _UTIL_H


 * 1) endif // end of definition for _UTIL_H header

<div class="references_section">