Discussion:
GetColumn/ExecuteSearch does not return any values for multivalued column
(too old to reply)
n***@gmail.com
2006-03-03 22:27:57 UTC
Permalink
Hi,

I am trying to get distinguished names of mailboxes of a exchange
mailstore. This mailstore has about 2000 mailboxes, and homeMDBBL
multivalue/list attribute has DNs of mailboxes that it holds. The
following code works if this attribute has about 50 values/DNs. It
returns 0 for col.dwNumValues for mail stores that has more than 2000
mailboxes. I have attached the code snippet. Can somebody tell me what
is wrong with this query?

// Search entire subtree from root.
SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
SearchPrefs[0].vValue.Integer = ADS_SCOPE_SUBTREE;

SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
SearchPrefs[1].vValue.Integer = 500;

// Set the search preference.
hr = spGCSearch->SetSearchPreference(SearchPrefs, 2);
if(FAILED(hr))
return hr;

// Set attributes to return.
LPWSTR rgpwszAttributes[] = {L"cn", L"homeMDBBL"};

// Execute the search.
hr = spGCSearch->ExecuteSearch( L"(objectClass=msExchPrivateMDB)",
rgpwszAttributes, 2, &hSearch);
if(FAILED(hr))
return hr;

// Get the first result row.
hr = spGCSearch->GetFirstRow(hSearch);
while(S_OK == hr)
{
ADS_SEARCH_COLUMN col;

// Enumerate the retrieved attributes.
for(DWORD i = 0; i < dwNumAttributes; i++)
{
hr = spGCSearch->GetColumn(hSearch, rgpwszAttributes[i], &col);
if(SUCCEEDED(hr))
{
switch(col.dwADsType)
{
case ADSTYPE_DN_STRING:
if (_wcsicmp(rgpwszAttributes[i], L"homeMDBBL") == 0)
{
// This line returns 0 for large multivalue column result
wprintf(L"homeMDBBL found Items: %d\n", col.dwNumValues);
CExString csTemp;
for (DWORD j = 0L; j < col.dwNumValues; j++)
{
// Exclude any SMTP or SystemMailbox mailboxes
csTemp = col.pADsValues[j].DNString;
wprintf(L"%s\n", (LPCWSTR)csTemp);
}
}
else
{
wprintf(L"%s: %s\n", rgpwszAttributes[i],
col.pADsValues[0].DNString);
}
break;

case ADSTYPE_CASE_IGNORE_STRING:
wprintf(L"%s: %s\n", rgpwszAttributes[i],
col.pADsValues[0].CaseExactString);
break;
}

// Free the column.
spGCSearch->FreeColumn(&col);
}
}

// Get the next row.
hr = spGCSearch->GetNextRow(hSearch);
}

Thanks
soma
Joe Kaplan (MVP - ADSI)
2006-03-03 22:44:41 UTC
Permalink
You probably need to use range retrieval to retrieve the full attribute
list. This is what you have to do with group memberships that contain more
than 1000 (or 1500, depending on AD version) members. The only other place
I've seen this show up in practice is on the homeMDBBL attribute with really
big exchange stores.

I'm positive I've seen an SDK sample for range retrieval with ADSI in C++ in
the SDK somewhere if you search for it.

I'm not sure why the number of values comes back as 0 or why you aren't
getting the first 1000/1500 values. However, I've never used
IDirectorySearch directly like this, only the higher level things that use
it (.NET DirectorySearcher, etc.). The net results should be the same
though.

Joe K.
Post by n***@gmail.com
Hi,
I am trying to get distinguished names of mailboxes of a exchange
mailstore. This mailstore has about 2000 mailboxes, and homeMDBBL
multivalue/list attribute has DNs of mailboxes that it holds. The
following code works if this attribute has about 50 values/DNs. It
returns 0 for col.dwNumValues for mail stores that has more than 2000
mailboxes. I have attached the code snippet. Can somebody tell me what
is wrong with this query?
// Search entire subtree from root.
SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
SearchPrefs[0].vValue.Integer = ADS_SCOPE_SUBTREE;
SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
SearchPrefs[1].vValue.Integer = 500;
// Set the search preference.
hr = spGCSearch->SetSearchPreference(SearchPrefs, 2);
if(FAILED(hr))
return hr;
// Set attributes to return.
LPWSTR rgpwszAttributes[] = {L"cn", L"homeMDBBL"};
// Execute the search.
hr = spGCSearch->ExecuteSearch( L"(objectClass=msExchPrivateMDB)",
rgpwszAttributes, 2, &hSearch);
if(FAILED(hr))
return hr;
// Get the first result row.
hr = spGCSearch->GetFirstRow(hSearch);
while(S_OK == hr)
{
ADS_SEARCH_COLUMN col;
// Enumerate the retrieved attributes.
for(DWORD i = 0; i < dwNumAttributes; i++)
{
hr = spGCSearch->GetColumn(hSearch, rgpwszAttributes[i], &col);
if(SUCCEEDED(hr))
{
switch(col.dwADsType)
{
if (_wcsicmp(rgpwszAttributes[i], L"homeMDBBL") == 0)
{
// This line returns 0 for large multivalue column result
wprintf(L"homeMDBBL found Items: %d\n", col.dwNumValues);
CExString csTemp;
for (DWORD j = 0L; j < col.dwNumValues; j++)
{
// Exclude any SMTP or SystemMailbox mailboxes
csTemp = col.pADsValues[j].DNString;
wprintf(L"%s\n", (LPCWSTR)csTemp);
}
}
else
{
wprintf(L"%s: %s\n", rgpwszAttributes[i],
col.pADsValues[0].DNString);
}
break;
wprintf(L"%s: %s\n", rgpwszAttributes[i],
col.pADsValues[0].CaseExactString);
break;
}
// Free the column.
spGCSearch->FreeColumn(&col);
}
}
// Get the next row.
hr = spGCSearch->GetNextRow(hSearch);
}
Thanks
soma
n***@gmail.com
2006-03-04 00:00:52 UTC
Permalink
Hi Joe K,

Thanks for your quick response/suggestions. I was able to get all the
values using range retrieval. I tried with size limit options, and
expecting the result set to have all the values. I think this is only
way to get large set of multivalued attribute. right?

Thanks
soma
Post by Joe Kaplan (MVP - ADSI)
You probably need to use range retrieval to retrieve the full attribute
list. This is what you have to do with group memberships that contain more
than 1000 (or 1500, depending on AD version) members. The only other place
I've seen this show up in practice is on the homeMDBBL attribute with really
big exchange stores.
I'm positive I've seen an SDK sample for range retrieval with ADSI in C++ in
the SDK somewhere if you search for it.
I'm not sure why the number of values comes back as 0 or why you aren't
getting the first 1000/1500 values. However, I've never used
IDirectorySearch directly like this, only the higher level things that use
it (.NET DirectorySearcher, etc.). The net results should be the same
though.
Joe K.
Post by n***@gmail.com
Hi,
I am trying to get distinguished names of mailboxes of a exchange
mailstore. This mailstore has about 2000 mailboxes, and homeMDBBL
multivalue/list attribute has DNs of mailboxes that it holds. The
following code works if this attribute has about 50 values/DNs. It
returns 0 for col.dwNumValues for mail stores that has more than 2000
mailboxes. I have attached the code snippet. Can somebody tell me what
is wrong with this query?
// Search entire subtree from root.
SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
SearchPrefs[0].vValue.Integer = ADS_SCOPE_SUBTREE;
SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
SearchPrefs[1].vValue.Integer = 500;
// Set the search preference.
hr = spGCSearch->SetSearchPreference(SearchPrefs, 2);
if(FAILED(hr))
return hr;
// Set attributes to return.
LPWSTR rgpwszAttributes[] = {L"cn", L"homeMDBBL"};
// Execute the search.
hr = spGCSearch->ExecuteSearch( L"(objectClass=msExchPrivateMDB)",
rgpwszAttributes, 2, &hSearch);
if(FAILED(hr))
return hr;
// Get the first result row.
hr = spGCSearch->GetFirstRow(hSearch);
while(S_OK == hr)
{
ADS_SEARCH_COLUMN col;
// Enumerate the retrieved attributes.
for(DWORD i = 0; i < dwNumAttributes; i++)
{
hr = spGCSearch->GetColumn(hSearch, rgpwszAttributes[i], &col);
if(SUCCEEDED(hr))
{
switch(col.dwADsType)
{
if (_wcsicmp(rgpwszAttributes[i], L"homeMDBBL") == 0)
{
// This line returns 0 for large multivalue column result
wprintf(L"homeMDBBL found Items: %d\n", col.dwNumValues);
CExString csTemp;
for (DWORD j = 0L; j < col.dwNumValues; j++)
{
// Exclude any SMTP or SystemMailbox mailboxes
csTemp = col.pADsValues[j].DNString;
wprintf(L"%s\n", (LPCWSTR)csTemp);
}
}
else
{
wprintf(L"%s: %s\n", rgpwszAttributes[i],
col.pADsValues[0].DNString);
}
break;
wprintf(L"%s: %s\n", rgpwszAttributes[i],
col.pADsValues[0].CaseExactString);
break;
}
// Free the column.
spGCSearch->FreeColumn(&col);
}
}
// Get the next row.
hr = spGCSearch->GetNextRow(hSearch);
}
Thanks
soma
Joe Kaplan (MVP - ADSI)
2006-03-04 02:28:07 UTC
Permalink
Well, there are really two tricks. Range retrieval works on Win2K, 2K3 and
ADAM. You can also use attribute scope query on 2K3 and ADAM. ASQ is a
cool trick, as you can perform a search on the against the values in the
attribute, applying filters and retrieving additional values from them, in
addition to just getting the DN value. The search that is performed
automatically does the paging required to return large result sets as well.

I think you'll find the samples for ASQ around the same place you found the
ranging samples in the SDK. The mechanics of ASQ with C++ are somewhat
similar and actually a little easier to perform since you don't have to make
multiple requests and keep incrementing your range size.

This "range limitation" in AD occurs only with linked DN syntax attributes,
as the max size for non-linked attributes is less than the range size
policy. Like I said before, in practice it generally applies to the member
attribute, but I too have had to do it on the homeMDBBL as well as some of
our Exchange Stores have pretty absurd numbers of mailboxes on them too. :)

Joe K.
Post by n***@gmail.com
Hi Joe K,
Thanks for your quick response/suggestions. I was able to get all the
values using range retrieval. I tried with size limit options, and
expecting the result set to have all the values. I think this is only
way to get large set of multivalued attribute. right?
Thanks
soma
Post by Joe Kaplan (MVP - ADSI)
You probably need to use range retrieval to retrieve the full attribute
list. This is what you have to do with group memberships that contain more
than 1000 (or 1500, depending on AD version) members. The only other place
I've seen this show up in practice is on the homeMDBBL attribute with really
big exchange stores.
I'm positive I've seen an SDK sample for range retrieval with ADSI in C++ in
the SDK somewhere if you search for it.
I'm not sure why the number of values comes back as 0 or why you aren't
getting the first 1000/1500 values. However, I've never used
IDirectorySearch directly like this, only the higher level things that use
it (.NET DirectorySearcher, etc.). The net results should be the same
though.
Joe K.
Post by n***@gmail.com
Hi,
I am trying to get distinguished names of mailboxes of a exchange
mailstore. This mailstore has about 2000 mailboxes, and homeMDBBL
multivalue/list attribute has DNs of mailboxes that it holds. The
following code works if this attribute has about 50 values/DNs. It
returns 0 for col.dwNumValues for mail stores that has more than 2000
mailboxes. I have attached the code snippet. Can somebody tell me what
is wrong with this query?
// Search entire subtree from root.
SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
SearchPrefs[0].vValue.Integer = ADS_SCOPE_SUBTREE;
SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
SearchPrefs[1].vValue.Integer = 500;
// Set the search preference.
hr = spGCSearch->SetSearchPreference(SearchPrefs, 2);
if(FAILED(hr))
return hr;
// Set attributes to return.
LPWSTR rgpwszAttributes[] = {L"cn", L"homeMDBBL"};
// Execute the search.
hr = spGCSearch->ExecuteSearch( L"(objectClass=msExchPrivateMDB)",
rgpwszAttributes, 2, &hSearch);
if(FAILED(hr))
return hr;
// Get the first result row.
hr = spGCSearch->GetFirstRow(hSearch);
while(S_OK == hr)
{
ADS_SEARCH_COLUMN col;
// Enumerate the retrieved attributes.
for(DWORD i = 0; i < dwNumAttributes; i++)
{
hr = spGCSearch->GetColumn(hSearch, rgpwszAttributes[i], &col);
if(SUCCEEDED(hr))
{
switch(col.dwADsType)
{
if (_wcsicmp(rgpwszAttributes[i], L"homeMDBBL") == 0)
{
// This line returns 0 for large multivalue column result
wprintf(L"homeMDBBL found Items: %d\n", col.dwNumValues);
CExString csTemp;
for (DWORD j = 0L; j < col.dwNumValues; j++)
{
// Exclude any SMTP or SystemMailbox mailboxes
csTemp = col.pADsValues[j].DNString;
wprintf(L"%s\n", (LPCWSTR)csTemp);
}
}
else
{
wprintf(L"%s: %s\n", rgpwszAttributes[i],
col.pADsValues[0].DNString);
}
break;
wprintf(L"%s: %s\n", rgpwszAttributes[i],
col.pADsValues[0].CaseExactString);
break;
}
// Free the column.
spGCSearch->FreeColumn(&col);
}
}
// Get the next row.
hr = spGCSearch->GetNextRow(hSearch);
}
Thanks
soma
Loading...