Directory Programming .NET

Active Directory and ADAM programming support for .NET developers
Welcome to Directory Programming .NET Sign in | Join | Help
in Search

Problems getting VLV to work to ADAM

Last post 06-26-2008, 8:50 AM by bills. 5 replies.
Sort Posts: Previous Next
  •  06-21-2008, 8:55 PM 3995

    Problems getting VLV to work to ADAM

    Can someone offer any suggestions on how I can get a simple program to work using VLV to ADAM.  Here is my info:

    - I'm using this sample app as a starting point: http://msdn.microsoft.com/en-us/library/aa366107(VS.85).aspx

    - I just make minor changes to get it to compile in C. 

    - Whenever I run it to ADAM, the ldap_search_ext_s returns 0xc (UNAVAILABLE_CRIT_EXTENSION).

    Open succeeded
    Bind succeeded
    Create VLV control returned 0x0
    Create Sort control returned 0x0
    Ldap search returned 0xc
    Ldap parse_result returned 0x5e
    Ldap parse vlv control returned 0x5d
    TargetPos = 0
    ListCount = 0

    - ADAM is version 1.1.3790.4281

    - I set bit 6 in searchFlags (0x41) on ADAM for "cn" (which is the attribute I'm trying to index).

    - I am able to get ldp.exe and softerra to use VLV to the ADAM, so I'm suspecting that the ADAM is setup correctly. 

    - If I change the IsCritical parameter of ldap_create_vlv_control and ldap_create_sort_control from TRUE to FALSE, the search succeeds, but ldap_parse_vlv_control (see example in link above) returns 0x5d (LDAP_CONTROL_NOT_FOUND).

    Open succeeded
    Bind succeeded
    Create VLV control returned 0x0
    Create Sort control returned 0x0
    Ldap search returned 0x0
    Ldap parse_result returned 0x0
    Ldap parse vlv control returned 0x5d
    TargetPos = 0
    ListCount = 0
    errcode = 0x0

    Thanks!  Bill

  •  06-22-2008, 3:56 PM 3998 in reply to 3995

    Re: Problems getting VLV to work to ADAM

    ADAM supports the VLV control in all versions if I recall, so it is not a problem with the server.  What is the actual search that you are attempting to send?  Did you remember to use the sort extension as well?  VLV can only work when results are sorted on the server.

    This forum is actually for .NET developers, but we can do our best here for native developers as well.

    Also, how did you get ldp.exe to send a VLV request?  I have actually never done that before...

    Ryan Dunn
    Extemporaneous Mumblings
    The .NET Developer's Guide to Directory Services Programming
  •  06-22-2008, 8:23 PM 4000 in reply to 3998

    Re: Problems getting VLV to work to ADAM

    Ryan, Thanks for the reply.  Here are the answers to your questions.

    Not sure what you mean by "sort extension".  I set the "searchFlags" to 0x41 for the attribute that I'm trying to index (cn) on the ADAM.  I also used the sort control and vlv control calls (see below).

    With ldap.exe, see the Browse/Virtual List View menu.  I used this to do ldp vlv to the ADAM.

    The actual code based on the link in my original message (I've tried many variations with no luck):

    LDAP *ld;
    ULONG ldaperr;

    // Create the VLV control and send it to the server.

    LDAPVLVInfo vlvInfo;
    PLDAPControl pvlvctrl;
    PLDAPControl psortctrl;
    PLDAPControl ctrlArr[
    3];

    // Create a sort control and attach it.

    LDAPSortKey sortkeys;
    PLDAPSortKey sortkeyList[
    2];

    PLDAPMessage pRes;

    PLDAPControl *pvlvresponse = NULL;

    ULONG targetpos
    =0;
    ULONG listcount
    = 0;
    int errcode = LDAP_SUCCESS;
    PBERVAL context
    = NULL;
    char *attrs[] = {"displayName", NULL }; /* Attributes to return */

    ld = ldap_open("myhostname.com", 5500);

    if (ld)
    {
    printf(
    "Open succeeded\n");
    }
    else
    {
    printf(
    "Open failed\n");
    return 1;
    }

    ldaperr
    = ldap_bind_s(ld, "myCredentials", "myPassword", LDAP_AUTH_SIMPLE);

    if (ldaperr == LDAP_SUCCESS)
    {

    printf(
    "Bind succeeded\n");
    }
    else
    {
    printf(
    "Bind failed with 0x%x 0x%x\n", ldaperr, GetLastError);
    ldap_unbind(ld);
    return 1;
    }


    // Enter the members of the VLV control.

    vlvInfo
    .ldvlv_after_count = 1;
    vlvInfo
    .ldvlv_attrvalue = NULL;
    vlvInfo
    .ldvlv_before_count = 1;
    vlvInfo
    .ldvlv_context = NULL;
    vlvInfo
    .ldvlv_count = 0;
    vlvInfo
    .ldvlv_extradata = NULL;
    vlvInfo
    .ldvlv_offset = 2;
    vlvInfo
    .ldvlv_version = LDAP_VLVINFO_VERSION;

    ldaperr
    = ldap_create_vlv_control( ld,
    &vlvInfo,
    TRUE,
    &pvlvctrl);

    printf(
    "Create VLV control returned 0x%x\n",ldaperr);
    if (LDAP_SUCCESS != ldaperr)
    return 1;


    sortkeys
    .sk_attrtype = "cn";
    sortkeys
    .sk_matchruleoid = NULL;
    sortkeys
    .sk_reverseorder = FALSE;

    sortkeyList[
    0] = &sortkeys;
    sortkeyList[
    1] = NULL;

    ldaperr
    = ldap_create_sort_control( ld,
    sortkeyList,
    TRUE,
    &psortctrl
    );

    printf(
    "Create Sort control returned 0x%x\n",ldaperr);
    if (LDAP_SUCCESS != ldaperr)
    return 1;

    ctrlArr[
    0] = psortctrl;
    ctrlArr[
    1] = pvlvctrl;
    ctrlArr[
    2] = NULL;

    // Send the VLV control, with a search request, to the server.


    ldaperr
    = ldap_search_ext_s( ld,
    "myBaseForSearch",
    LDAP_SCOPE_SUBTREE,
    "(cn=joe*)",
    attrs,
    1,
    ctrlArr,
    NULL,
    NULL,
    0,
    &pRes
    );

    printf(
    "Ldap search returned 0x%x\n",ldaperr);

    // Choose the control returned from the server.

    ldaperr = ldap_parse_result( ld,
    pRes,
    NULL,
    NULL,
    NULL,
    NULL,
    &pvlvresponse,
    FALSE
    );

    printf(
    "Ldap parse_result returned 0x%x\n",ldaperr);

    // Parse the VLV control returned from the server.


    ldaperr
    = ldap_parse_vlv_control( ld,
    pvlvresponse,
    &targetpos,
    &listcount,
    &context,
    &errcode
    );

    printf(
    "Ldap parse vlv control returned 0x%x\n",ldaperr);
    printf(
    "TargetPos = %d\n", targetpos);
    printf(
    "ListCount = %d\n", listcount);
    printf(
    "errcode = 0x%x\n", errcode);
    ldap_unbind(ld);
    ldap_control_free(pvlvctrl);
    ldap_control_free(psortctrl);
    ldap_msgfree(pRes);
    ldap_controls_free(pvlvresponse);
    ber_bvfree(context);
    return 0;

  •  06-23-2008, 2:30 PM 4005 in reply to 4000

    Re: Problems getting VLV to work to ADAM

    I meant sort control - and I see you have it.  I am trying to run your code now, so let me look into it more - I will get back to you.

    Ryan Dunn
    Extemporaneous Mumblings
    The .NET Developer's Guide to Directory Services Programming
  •  06-23-2008, 2:53 PM 4007 in reply to 3995

    Re: Problems getting VLV to work to ADAM

    I fixed the code on the sample by using this and it works great for me:

    // VLVConsole.cpp : Defines the entry point for the console application.
    //
    #pragma comment(lib,"Wldap32.lib")

    #include "stdafx.h"


    #define SECURITY_WIN32
    #include <windows.h>
    #include <stdio.h>
    #include <winldap.h>
    #include <rpc.h>
    #include <rpcdce.h>
    #include <security.h>

    void __cdecl main (int argc, char* argv[])
    {
       LDAP *ld;
       ULONG ldaperr;

       ld = ldap_open(L"mycontroller", 389);

       if (ld)
       {
          printf("Open succeeded\n");
       }
       else
       {
          printf("Open failed\n");
          return;
       }

       ldaperr = ldap_bind_s(ld, NULL, NULL, LDAP_AUTH_NEGOTIATE);

       if (ldaperr == LDAP_SUCCESS)
       {

          printf("Bind succeeded\n");
       }
       else
       {
          printf("Bind failed with 0x%x  0x%x\n", ldaperr, GetLastError);
          ldap_unbind(ld);
          return;
       }

       // Create the VLV control and send it to the server.

       LDAPVLVInfo     vlvInfo;
       PLDAPControl    pvlvctrl;
       PLDAPControl    psortctrl;
       PLDAPControl    ctrlArr[3];

       // Enter the members of the VLV control.

       vlvInfo.ldvlv_after_count = 1;
       vlvInfo.ldvlv_attrvalue = NULL;
       vlvInfo.ldvlv_before_count = 1;
       vlvInfo.ldvlv_context = NULL;
       vlvInfo.ldvlv_count = 0;
       vlvInfo.ldvlv_extradata = NULL;
       vlvInfo.ldvlv_offset = 2;
       vlvInfo.ldvlv_version = LDAP_VLVINFO_VERSION;

       ldaperr = ldap_create_vlv_control( ld,
                                          &vlvInfo,
                                          TRUE,
                                          &pvlvctrl);

       printf("Create VLV control returned 0x%x\n",ldaperr);
       if (LDAP_SUCCESS != ldaperr)
       return;

       // Create a sort control and attach it.

       LDAPSortKey sortkeys;
       PLDAPSortKey sortkeyList[2];

       sortkeys.sk_attrtype = L"name";
       sortkeys.sk_matchruleoid = NULL;
       sortkeys.sk_reverseorder = FALSE;

       sortkeyList[0] = &sortkeys;
       sortkeyList[1] = NULL;

       ldaperr = ldap_create_sort_control( ld,
                                           sortkeyList,
                                           TRUE,
                                           &psortctrl
                                           );

       printf("Create Sort control returned 0x%x\n",ldaperr);
       if (LDAP_SUCCESS != ldaperr)
       return;
      
       ctrlArr[0] = psortctrl;
       ctrlArr[1] = pvlvctrl;
       ctrlArr[2] = NULL;

       // Send the VLV control, with a search request, to the server.

       PLDAPMessage pRes;

       ldaperr = ldap_search_ext_s( ld,
                                    L"dc=mydomain,dc=com",
                                    LDAP_SCOPE_SUBTREE,
                                    L"(sn=dunn*)",
                                    NULL,
                                    1,
                                    ctrlArr,
                                    NULL,
                                    NULL,
                                    0,
                                    &pRes
                                    );

       printf("Ldap search returned 0x%x\n",ldaperr);
      
       // Choose the control returned from the server.

       PLDAPControl    *pvlvresponse = NULL;

       ldaperr = ldap_parse_result( ld,
                                    pRes,
                                    NULL,
                                    NULL,
                                    NULL,
                                    NULL,
                                    &pvlvresponse,
                                    FALSE
                                    );

       printf("Ldap parse_result returned 0x%x\n",ldaperr);

       // Parse the VLV control returned from the server.

       ULONG   targetpos =0;
       ULONG   listcount = 0;
       int     errcode = LDAP_SUCCESS;
       PBERVAL context = NULL;

       ldaperr = ldap_parse_vlv_control( ld,
                                         pvlvresponse,
                                         &targetpos,
                                         &listcount,
                                         &context,
                                         &errcode
                                         );

       printf("Ldap parse vlv control returned 0x%x\n",ldaperr);
       printf("TargetPos = %d\n", targetpos);
       printf("ListCount = %d\n", listcount);
       printf("errcode = 0x%x\n", errcode);

       ldap_unbind(ld);
          ldap_control_free(pvlvctrl);
          ldap_control_free(psortctrl);
          ldap_msgfree(pRes);
          ldap_controls_free(pvlvresponse);
       ber_bvfree(context);
    }

    Try running this (change to your specifics) and see what you get.

    Ryan Dunn
    Extemporaneous Mumblings
    The .NET Developer's Guide to Directory Services Programming
  •  06-26-2008, 8:50 AM 4050 in reply to 4007

    Re: Problems getting VLV to work to ADAM

    Thanks Ryan, I'll try that.  Bill

View as RSS news feed in XML