• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 337
  • Last Modified:

ADSI multi-valued attribute with one value not returning data

I have modified the following code from MSDN (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adsi/adsi/iads_getex.asp)

The code works ok except for one situation.  If the attribute only contains one value it would seem lstart and lend are wrong.  Instead of them being 0:0 respectively, they are huge like 7471215:15073473
e.g.  If the user is a member of two groups, it will display data.  If the user is a member of one group, it screws up

Should this example not work with a single value in a multi-valued attribute?  If not, what do I need to do to return the data if only one value exists?

///////////////////////////////////////////////////////
// Get a multi-valued attribute from a User attribute.
///////////////////////////////////////////////////////
IADs *pSvc = NULL;
 
hr = ADsGetObject(L"LDAP://DC1.test.dom,cn=test,ou=test,dc-test,dc=dom", IID_IADs, (void**) &pSvc );
if ( !SUCCEEDED(hr) )
{
    return hr;
}
 
hr = pSvc->Get(CComBSTR("memberOf"), &var );
if ( SUCCEEDED(hr) )
{
    LONG lstart, lend;
    SAFEARRAY *sa = V_ARRAY( &var );
    VARIANT varItem;
 
    // Get the lower and upper bound.
    hr = SafeArrayGetLBound( sa, 1, &lstart );
    hr = SafeArrayGetUBound( sa, 1, &lend );
 
printf("%d:%d",lstart,lend);

    // Iterate and print the content.
    VariantInit(&varItem);
    printf("Getting memberOF via IADs :\n");
    for ( long idx=lstart; idx <= lend; idx++ )
    {
        hr = SafeArrayGetElement( sa, &idx, &varItem );
        printf("%S ", V_BSTR(&varItem));
        VariantClear(&varItem);
    }
    printf("\n");
 
    VariantClear(&var);
}
 
// Cleanup.
if ( pSvc )
{
    pSvc->Release();
}
0
Pber
Asked:
Pber
  • 4
1 Solution
 
jkrCommented:
Try

lstart = lend = 0;

    // Get the lower and upper bound.
   hr = SafeArrayGetLBound( sa, 1, &lstart );

   if (FAILED(hr)) printf("LBound failed with %d\n", hr);

   hr = SafeArrayGetUBound( sa, 1, &lend );

   if (FAILED(hr)) printf("UBound failed with %d\n", hr);

printf("%d:%d",lstart,lend);

to see if there's something going wrong.
0
 
PberSolutions ArchitectAuthor Commented:

Both results are returning 0.
Everything seems to be working.

On a different computer instead of 7471215:15073473 it's 0:-1
0
 
PberSolutions ArchitectAuthor Commented:
A little clarification on that last message, it's still not returning the valid data.  the SafeArrayGetUBound and Lbound seem to be working.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
PberSolutions ArchitectAuthor Commented:
I tried a few other multivalued attributes and they all seem to product wierd numbers whenever there is only a single value assigned to a multivalued attribute.  I can get around it by using the code below, but that doesn't seem right.

// Get the lower and upper bound.
hr = SafeArrayGetLBound( sa, 1, &lstart );
hr = SafeArrayGetUBound( sa, 1, &lend );

if (lstart != 0)   //single value assigned
{
   printf("%S ", V_BSTR(&var));
}
else
{
    for ( long idx=lstart; idx <= lend; idx++ )
    {
        hr = SafeArrayGetElement( sa, &idx, &varItem );
        printf("%S ", V_BSTR(&varItem));
        VariantClear(&varItem);
    }
}
0
 
PberSolutions ArchitectAuthor Commented:
Maybe I should read MSDN a little better:

Remark (from IADS::Get):
The IADs::Get method requires the caller to handle the single- and multi-valued property values differently. Thus, if you know that the property of interest is either single- or multi-valued, use the IADs::Get method to retrieve the property value. The following code example shows how you, as a caller, can handle single- and multi-valued properties when calling this method.
...
You can also use IADs::GetEx to retrieve property values from the property cache. However, the values are returned as a variant array of VARIANTs, regardless of whether they are single-valued or multi-valued. That is, ADSI attempts to package the returned property values in consistent data formats. This saves you, as a caller, the effort of validating the data types when unsure that the returned data has single or multiple values.

Remark (from IADS::GetEx):
The IADs::Get and IADs::GetEx methods return a different variant structure for a single-valued property value. If the property is a string, IADs::Get returns a variant of string (VT_BSTR), whereas IADs::GetEx returns a variant array of a VARIANT type string with a single element. Thus, if you are not sure that a multi-valued attribute will return a single value or multiple values, use IADs::GetEx. As it does not require you to validate the result's data structures, you may want to use IADs::GetEx to retrieve a property when you are not sure whether it has single or multiple values.
0
 
ee_ai_constructCommented:
Question answered by asker or dialog deemed valuable.
Closed, 500 points refunded.
ee_ai_construct (replacement part #xm34)
Community Support Admin
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now