?
Solved

ADSI multi-valued attribute with one value not returning data

Posted on 2005-03-29
7
Medium Priority
?
334 Views
Last Modified: 2010-05-18
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
Comment
Question by:Pber
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
7 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 13656231
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
 
LVL 26

Author Comment

by:Pber
ID: 13656473

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

On a different computer instead of 7471215:15073473 it's 0:-1
0
 
LVL 26

Author Comment

by:Pber
ID: 13656493
A little clarification on that last message, it's still not returning the valid data.  the SafeArrayGetUBound and Lbound seem to be working.
0
Technology Partners: 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!

 
LVL 26

Author Comment

by:Pber
ID: 13680495
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
 
LVL 26

Author Comment

by:Pber
ID: 13682038
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
 

Accepted Solution

by:
ee_ai_construct earned 0 total points
ID: 13711220
Question answered by asker or dialog deemed valuable.
Closed, 500 points refunded.
ee_ai_construct (replacement part #xm34)
Community Support Admin
0

Featured Post

Enroll in August's Course of the Month

August's CompTIA IT Fundamentals course includes 19 hours of basic computer principle modules and prepares you for the certification exam. It's free for Premium Members, Team Accounts, and Qualified Experts!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
Suggested Courses

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question