WindowsXP-SP1/ds/adsi/ldapc/util.cxx
2020-09-30 16:53:49 +02:00

1035 lines
36 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996
//
// File: util.cxx
//
// Contents: Some misc helper functions
//
// History:
//----------------------------------------------------------------------------
#include "ldapc.hxx"
#pragma hdrstop
#if 0
// ADsGetSearchPreference code
//
// Must explicitly include here since adshlp.h
// is not #included.
//
#ifdef __cplusplus
extern "C" {
#endif
HRESULT WINAPI
ADsGetSearchPreference(
ADS_SEARCH_HANDLE hSearchHandle,
LPWSTR lpszPathName,
PADS_SEARCHPREF_INFO *ppSearchPrefs,
PDWORD pdwNumPrefs
);
#ifdef __cplusplus
}
#endif
HRESULT
UTF8ToUnicodeString(
LPCSTR pUTF8,
LPWSTR *ppUnicode
);
#endif
//
// The following table needs to be sorted
//
SEARCHENTRY g_aSyntaxSearchTable[] =
{
{ TEXT("AccessPointDN"), LDAPTYPE_ACCESSPOINTDN }, // in NTDS, not in LDAP
{ TEXT("AttributeTypeDescription"), LDAPTYPE_ATTRIBUTETYPEDESCRIPTION },
{ TEXT("Audio"), LDAPTYPE_AUDIO },
{ TEXT("Binary"), LDAPTYPE_OCTETSTRING },
{ TEXT("BitString"), LDAPTYPE_BITSTRING },
{ TEXT("Boolean"), LDAPTYPE_BOOLEAN },
{ TEXT("CaseExactString") ,LDAPTYPE_CASEEXACTSTRING },
{ TEXT("CaseIgnoreString"),LDAPTYPE_CASEIGNORESTRING }, // in NTDS, not in LDAP RFC
{ TEXT("Certificate"), LDAPTYPE_CERTIFICATE },
{ TEXT("CertificateList"), LDAPTYPE_CERTIFICATELIST },
{ TEXT("CertificatePair"), LDAPTYPE_CERTIFICATEPAIR },
{ TEXT("Country"), LDAPTYPE_COUNTRYSTRING },
{ TEXT("DataQualitySyntax"),LDAPTYPE_DATAQUALITYSYNTAX },
{ TEXT("DeliveryMethod"), LDAPTYPE_DELIVERYMETHOD },
{ TEXT("DirectoryString"), LDAPTYPE_DIRECTORYSTRING },
{ TEXT("DN"), LDAPTYPE_DN },
{ TEXT("DSAQualitySyntax"),LDAPTYPE_DSAQUALITYSYNTAX },
{ TEXT("EnhancedGuide"), LDAPTYPE_ENHANCEDGUIDE },
{ TEXT("FacsimileTelephoneNumber"), LDAPTYPE_FACSIMILETELEPHONENUMBER },
{ TEXT("Fax"), LDAPTYPE_FAX },
{ TEXT("GeneralizedTime"), LDAPTYPE_GENERALIZEDTIME },
{ TEXT("Guide"), LDAPTYPE_GUIDE },
{ TEXT("IA5String"), LDAPTYPE_IA5STRING },
{ TEXT("INTEGER"), LDAPTYPE_INTEGER },
{ TEXT("INTEGER8"), LDAPTYPE_INTEGER8 }, // in NTDS, not in LDAP RFC
{ TEXT("JPEG"), LDAPTYPE_JPEG },
{ TEXT("MailPreference"), LDAPTYPE_MAILPREFERENCE },
{ TEXT("NameAndOptionalUID"), LDAPTYPE_NAMEANDOPTIONALUID },
{ TEXT("NumericString"), LDAPTYPE_NUMERICSTRING },
{ TEXT("ObjectClassDescription"), LDAPTYPE_OBJECTCLASSDESCRIPTION },
{ TEXT("ObjectSecurityDescriptor"), LDAPTYPE_SECURITY_DESCRIPTOR},
{ TEXT("OctetString"), LDAPTYPE_OCTETSTRING }, // in NTDS, not in LDAP RFC
{ TEXT("OID"), LDAPTYPE_OID },
{ TEXT("ORAddress"), LDAPTYPE_ORADDRESS },
{ TEXT("ORName"), LDAPTYPE_ORNAME }, // in NTDS, not in LDAP RFC
{ TEXT("OtherMailbox"), LDAPTYPE_OTHERMAILBOX },
{ TEXT("Password"), LDAPTYPE_PASSWORD },
{ TEXT("PostalAddress"), LDAPTYPE_POSTALADDRESS },
{ TEXT("PresentationAddress"), LDAPTYPE_PRESENTATIONADDRESS },
{ TEXT("PrintableString"), LDAPTYPE_PRINTABLESTRING },
{ TEXT("TelephoneNumber"), LDAPTYPE_TELEPHONENUMBER },
{ TEXT("TeletexTerminalIdentifier"), LDAPTYPE_TELETEXTERMINALIDENTIFIER },
{ TEXT("TelexNumber"), LDAPTYPE_TELEXNUMBER },
//
// Allegedly, "Time" started out as a bug in the schema (the correct description
// is "GeneralizedTime"). However, we never delete items from the schema, so it
// is still present in the current Whistler schema
// (4/27/2000), so we'll keep in support for it.
//
{ TEXT("Time"), LDAPTYPE_GENERALIZEDTIME },
{ TEXT("UTCTIME"), LDAPTYPE_UTCTIME }
};
DWORD g_nSyntaxSearchTableSize = ARRAY_SIZE(g_aSyntaxSearchTable );
//
// The following table needs to be sorted (lexicographically) on the first field
//
SEARCHENTRY g_aOidSyntaxSearchTable[] = {
// the type is ORName a type of string -> mapped to string.
{ TEXT("1.2.840.113556.1.4.1221"), LDAPTYPE_CASEIGNORESTRING },
// the type is Undefined syntax in the server, so we are defaulting.
{ TEXT("1.2.840.113556.1.4.1222"), LDAPTYPE_OCTETSTRING},
{ TEXT("1.2.840.113556.1.4.1362"), LDAPTYPE_CASEEXACTSTRING},
{ TEXT("1.2.840.113556.1.4.903"), LDAPTYPE_DNWITHBINARY},
{ TEXT("1.2.840.113556.1.4.904"), LDAPTYPE_DNWITHSTRING},
{ TEXT("1.2.840.113556.1.4.905"), LDAPTYPE_CASEIGNORESTRING },
{ TEXT("1.2.840.113556.1.4.906"), LDAPTYPE_INTEGER8 },
{ TEXT("1.2.840.113556.1.4.907"), LDAPTYPE_SECURITY_DESCRIPTOR },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.10"), LDAPTYPE_CERTIFICATEPAIR },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.11"), LDAPTYPE_COUNTRYSTRING },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.12"), LDAPTYPE_DN },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.13"), LDAPTYPE_DATAQUALITYSYNTAX },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.14"), LDAPTYPE_DELIVERYMETHOD },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.15"), LDAPTYPE_DIRECTORYSTRING },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.19"), LDAPTYPE_DSAQUALITYSYNTAX },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.2"), LDAPTYPE_ACCESSPOINTDN },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.21"), LDAPTYPE_ENHANCEDGUIDE },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.22"), LDAPTYPE_FACSIMILETELEPHONENUMBER },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.23"), LDAPTYPE_FAX },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.24"), LDAPTYPE_GENERALIZEDTIME },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.25"), LDAPTYPE_GUIDE },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.26"), LDAPTYPE_IA5STRING },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.27"), LDAPTYPE_INTEGER },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.28"), LDAPTYPE_JPEG },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.3"), LDAPTYPE_ATTRIBUTETYPEDESCRIPTION },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.32"), LDAPTYPE_MAILPREFERENCE },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.33"), LDAPTYPE_ORADDRESS },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.34"), LDAPTYPE_NAMEANDOPTIONALUID },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.36"), LDAPTYPE_NUMERICSTRING },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.37"), LDAPTYPE_OBJECTCLASSDESCRIPTION },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.38"), LDAPTYPE_OID },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.39"), LDAPTYPE_OTHERMAILBOX },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.4"), LDAPTYPE_AUDIO },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.40"), LDAPTYPE_OCTETSTRING },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.41"), LDAPTYPE_POSTALADDRESS },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.43"), LDAPTYPE_PRESENTATIONADDRESS },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.44"), LDAPTYPE_PRINTABLESTRING },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.5"), LDAPTYPE_OCTETSTRING },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.50"), LDAPTYPE_TELEPHONENUMBER },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.51"), LDAPTYPE_TELETEXTERMINALIDENTIFIER },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.52"), LDAPTYPE_TELEXNUMBER },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.53"), LDAPTYPE_UTCTIME },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.6"), LDAPTYPE_BITSTRING },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.7"), LDAPTYPE_BOOLEAN },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.8"), LDAPTYPE_CERTIFICATE },
{ TEXT("1.3.6.1.4.1.1466.115.121.1.9"), LDAPTYPE_CERTIFICATELIST },
};
DWORD g_nOidSyntaxSearchTableSize = ARRAY_SIZE(g_aOidSyntaxSearchTable );
DWORD
GetSyntaxOfAttribute(
LPWSTR pszAttrName,
SCHEMAINFO *pSchemaInfo
)
{
LPWSTR pszTemp = NULL;
// Support for range attributes; for eg., objectClass=Range=0-1 We should
// ignore everything after ';' inclusive.
//
if ((pszTemp = wcschr(pszAttrName, L';')) != NULL ) {
*pszTemp = L'\0';
}
DWORD dwEntry = FindEntryInSearchTable( pszAttrName, pSchemaInfo->aPropertiesSearchTable, pSchemaInfo->nNumOfProperties * 2 );
//
// Put back the ; if we had replaced it.
//
if (pszTemp)
*pszTemp = L';';
if ( dwEntry != -1 )
{
DWORD dwSyntax = FindEntryInSearchTable( pSchemaInfo->aProperties[dwEntry].pszSyntax, g_aSyntaxSearchTable, ARRAY_SIZE(g_aSyntaxSearchTable) );
if ( dwSyntax != -1 )
return dwSyntax;
}
return LDAPTYPE_UNKNOWN;
}
DWORD
LdapGetSyntaxIdFromName(
LPWSTR pszSyntax
)
{
DWORD dwSyntaxId;
dwSyntaxId = FindEntryInSearchTable(
pszSyntax,
g_aSyntaxSearchTable,
g_nSyntaxSearchTableSize );
if ( dwSyntaxId == -1 ) {
//
// We need to look at the OID table before defaulting
//
dwSyntaxId = FindEntryInSearchTable(
pszSyntax,
g_aOidSyntaxSearchTable,
g_nOidSyntaxSearchTableSize
);
}
if (dwSyntaxId == -1 ) {
dwSyntaxId = LDAPTYPE_UNKNOWN;
}
return dwSyntaxId;
}
HRESULT
UnMarshallLDAPToLDAPSynID(
LPWSTR pszAttrName,
ADS_LDP *ld,
LDAPMessage *entry,
DWORD dwSyntax,
LDAPOBJECTARRAY *pldapObjectArray
)
{
HRESULT hr = S_OK;
DWORD dwStatus = 0;
int nNumberOfValues;
switch ( dwSyntax ) {
// The cases below are binary data
case LDAPTYPE_OCTETSTRING:
case LDAPTYPE_SECURITY_DESCRIPTOR:
case LDAPTYPE_CERTIFICATE:
case LDAPTYPE_CERTIFICATELIST:
case LDAPTYPE_CERTIFICATEPAIR:
case LDAPTYPE_PASSWORD:
case LDAPTYPE_TELETEXTERMINALIDENTIFIER:
case LDAPTYPE_AUDIO:
case LDAPTYPE_JPEG:
case LDAPTYPE_FAX:
case LDAPTYPE_UNKNOWN:
{
struct berval **bValues = NULL;
hr = LdapGetValuesLen( ld, entry, pszAttrName,
&bValues, &nNumberOfValues );
BAIL_ON_FAILURE(hr);
pldapObjectArray->fIsString = FALSE;
pldapObjectArray->dwCount = nNumberOfValues;
pldapObjectArray->pLdapObjects = (PLDAPOBJECT) bValues;
break;
}
// otherwise it is a string
default:
{
TCHAR **strValues = NULL;
hr = LdapGetValues( ld, entry, pszAttrName,
&strValues, &nNumberOfValues );
BAIL_ON_FAILURE(hr);
pldapObjectArray->fIsString = TRUE;
pldapObjectArray->dwCount = nNumberOfValues;
pldapObjectArray->pLdapObjects = (PLDAPOBJECT) strValues;
break;
}
}
error:
RRETURN(hr);
}
#if 0
// ADsGetSearchPreference code
HRESULT WINAPI
ADsGetSearchPreference(
ADS_SEARCH_HANDLE hSearchHandle,
LPWSTR lpszPathName,
PADS_SEARCHPREF_INFO *ppSearchPrefs,
PDWORD pdwNumPrefs
)
{
HRESULT hr = S_OK;
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = &ObjectInfo;
PLDAP_SEARCHINFO phSearchInfo= (PLDAP_SEARCHINFO) hSearchHandle;
PLDAP_SEARCH_PREF pSearchPref = NULL;
PADS_SEARCHPREF_INFO pADsSearchPref = NULL;
PBYTE pbExtra = NULL;
DWORD dwNumberPrefs = 0;
DWORD dwNumberExtraBytes = 0;
//
// sanity check
//
if (!lpszPathName || !ppSearchPrefs || !phSearchInfo || !pdwNumPrefs)
RRETURN(E_INVALIDARG);
*ppSearchPrefs = NULL;
*pdwNumPrefs = 0;
//
// Make sure we're being called on an LDAP path
//
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
hr = ADsObject(lpszPathName, pObjectInfo);
BAIL_ON_FAILURE(hr);
if (_tcscmp(pObjectInfo->ProviderName, szProviderName) != 0) {
BAIL_ON_FAILURE(hr = E_NOTIMPL);
}
//
// allocate space for the ADS_SEARCHPREF_INFO array we're
// going to build
//
pSearchPref = &(phSearchInfo->_SearchPref);
hr = CalcSpaceForSearchPrefs(pSearchPref, &dwNumberPrefs, &dwNumberExtraBytes);
BAIL_ON_FAILURE(hr);
// no search prefs were set
if (dwNumberPrefs == 0) {
*ppSearchPrefs = NULL;
FreeObjectInfo(pObjectInfo);
RRETURN(S_OK);
}
pADsSearchPref = (PADS_SEARCHPREF_INFO) AllocADsMem( (dwNumberPrefs * sizeof(ADS_SEARCHPREF_INFO)) + dwNumberExtraBytes);
if (!pADsSearchPref)
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
pbExtra = ((PBYTE)pADsSearchPref) + (dwNumberPrefs * sizeof(ADS_SEARCHPREF_INFO));
//
// construct the array of search prefs
//
hr = ConstructSearchPrefArray(pSearchPref, pADsSearchPref, pbExtra);
BAIL_ON_FAILURE(hr);
*ppSearchPrefs = pADsSearchPref;
*pdwNumPrefs = dwNumberPrefs;
FreeObjectInfo(pObjectInfo);
RRETURN(hr);
error:
if (pADsSearchPref)
FreeADsMem(pADsSearchPref);
if (pObjectInfo) {
FreeObjectInfo(pObjectInfo);
}
RRETURN(hr);
}
HRESULT
ConstructSearchPrefArray(
PLDAP_SEARCH_PREF pPrefs,
PADS_SEARCHPREF_INFO pADsSearchPref,
PBYTE pbExtraBytes
)
{
HRESULT hr = S_OK;
BOOL fDefault;
LPSTR pUTF8 = NULL;
LPWSTR pUnicode = NULL;
if (!pPrefs || !pADsSearchPref || !pbExtraBytes)
RRETURN(E_INVALIDARG);
// ADS_SEARCHPREF_ASYNCHRONOUS
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ASYNCHRONOUS,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_ASYNCHRONOUS;
pADsSearchPref->vValue.dwType = ADSTYPE_BOOLEAN;
pADsSearchPref->vValue.Boolean = pPrefs->_fAsynchronous;
pADsSearchPref++;
}
// ADS_SEARCHPREF_DEREF_ALIASES
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_DEREF_ALIASES,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_DEREF_ALIASES;
pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
pADsSearchPref->vValue.Integer = pPrefs->_dwDerefAliases;
pADsSearchPref++;
}
// ADS_SEARCHPREF_SIZE_LIMIT
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SIZE_LIMIT,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_SIZE_LIMIT;
pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
pADsSearchPref->vValue.Integer = pPrefs->_dwSizeLimit;
pADsSearchPref++;
}
// ADS_SEARCHPREF_TIME_LIMIT
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TIME_LIMIT,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_TIME_LIMIT;
pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
pADsSearchPref->vValue.Integer = pPrefs->_dwTimeLimit;
pADsSearchPref++;
}
// ADS_SEARCHPREF_ATTRIBTYPES_ONLY
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ATTRIBTYPES_ONLY,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_ATTRIBTYPES_ONLY;
pADsSearchPref->vValue.dwType = ADSTYPE_BOOLEAN;
pADsSearchPref->vValue.Boolean = pPrefs->_fAttrsOnly;
pADsSearchPref++;
}
// ADS_SEARCHPREF_SEARCH_SCOPE
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SEARCH_SCOPE,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
switch(pPrefs->_dwSearchScope) {
case LDAP_SCOPE_SUBTREE:
pADsSearchPref->vValue.Integer = ADS_SCOPE_SUBTREE;
break;
case LDAP_SCOPE_ONELEVEL:
pADsSearchPref->vValue.Integer = ADS_SCOPE_ONELEVEL;
break;
case LDAP_SCOPE_BASE:
pADsSearchPref->vValue.Integer = ADS_SCOPE_BASE;
break;
}
pADsSearchPref++;
}
// ADS_SEARCHPREF_TIMEOUT
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TIMEOUT,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_TIMEOUT;
pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
pADsSearchPref->vValue.Integer = pPrefs->_timeout.tv_sec;
pADsSearchPref++;
}
// ADS_SEARCHPREF_PAGESIZE
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_PAGESIZE,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
pADsSearchPref->vValue.Integer = pPrefs->_dwPageSize;
pADsSearchPref++;
}
// ADS_SEARCHPREF_PAGED_TIME_LIMIT
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_PAGED_TIME_LIMIT,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_PAGED_TIME_LIMIT;
pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
pADsSearchPref->vValue.Integer = pPrefs->_dwPagedTimeLimit;
pADsSearchPref++;
}
// ADS_SEARCHPREF_CHASE_REFERRALS
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_CHASE_REFERRALS,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_CHASE_REFERRALS;
pADsSearchPref->vValue.dwType = ADSTYPE_INTEGER;
switch(pPrefs->_dwChaseReferrals) {
case (DWORD) (DWORD_PTR)LDAP_OPT_OFF:
pADsSearchPref->vValue.Integer = ADS_CHASE_REFERRALS_NEVER;
break;
case LDAP_CHASE_SUBORDINATE_REFERRALS:
pADsSearchPref->vValue.Integer = ADS_CHASE_REFERRALS_SUBORDINATE;
break;
case LDAP_CHASE_EXTERNAL_REFERRALS:
pADsSearchPref->vValue.Integer = ADS_CHASE_REFERRALS_EXTERNAL;
break;
case (DWORD) (DWORD_PTR) LDAP_OPT_ON:
pADsSearchPref->vValue.Integer = ADS_CHASE_REFERRALS_ALWAYS;
break;
}
pADsSearchPref++;
}
// ADS_SEARCHPREF_CACHE_RESULTS
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_CACHE_RESULTS,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_CACHE_RESULTS;
pADsSearchPref->vValue.dwType = ADSTYPE_BOOLEAN;
pADsSearchPref->vValue.Boolean = pPrefs->_fCacheResults;
pADsSearchPref++;
}
// ADS_SEARCHPREF_TOMBSTONE
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TOMBSTONE,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_TOMBSTONE;
pADsSearchPref->vValue.dwType = ADSTYPE_BOOLEAN;
pADsSearchPref->vValue.Boolean = pPrefs->_fTombStone;
pADsSearchPref++;
}
// ADS_SEARCHPREF_DIRSYNC
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_DIRSYNC,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_DIRSYNC;
pADsSearchPref->vValue.dwType = ADSTYPE_PROV_SPECIFIC;
pADsSearchPref->vValue.ProviderSpecific.dwLength = 0;
pADsSearchPref->vValue.ProviderSpecific.lpValue = NULL;
if (pPrefs->_pProvSpecific && pPrefs->_pProvSpecific->lpValue) {
memcpy(pbExtraBytes, pPrefs->_pProvSpecific->lpValue, pPrefs->_pProvSpecific->dwLength);
pADsSearchPref->vValue.ProviderSpecific.lpValue = pbExtraBytes;
pADsSearchPref->vValue.ProviderSpecific.dwLength = pPrefs->_pProvSpecific->dwLength;
pbExtraBytes += pPrefs->_pProvSpecific->dwLength;
}
pADsSearchPref++;
}
// ADS_SEARCHPREF_VLV
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_VLV,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_VLV;
pADsSearchPref->vValue.dwType = ADSTYPE_PROV_SPECIFIC;
pADsSearchPref->vValue.ProviderSpecific.dwLength = sizeof(ADS_VLV);
pADsSearchPref->vValue.ProviderSpecific.lpValue = pbExtraBytes;
PADS_VLV pADsVLV = (PADS_VLV) pbExtraBytes;
pbExtraBytes += sizeof(ADS_VLV);
pADsVLV->dwBeforeCount = pPrefs->_pVLVInfo->ldvlv_before_count;
pADsVLV->dwAfterCount = pPrefs->_pVLVInfo->ldvlv_after_count;
pADsVLV->dwOffset = pPrefs->_pVLVInfo->ldvlv_offset;
pADsVLV->dwContentCount = pPrefs->_pVLVInfo->ldvlv_count;
pADsVLV->pszTarget = NULL;
pADsVLV->lpContextID = NULL;
pADsVLV->dwContextIDLength = 0;
if (pPrefs->_pVLVInfo->ldvlv_attrvalue && pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_val) {
// As stored, the attribute is a non-terminated UTF-8 string.
// We need to return a NULL-terminated Unicode string.
// We do this by constructing a NULL-terminated UTF-8 string, and then
// converting that to a Unicode string.
pUTF8 = (PCHAR) AllocADsMem(pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_len + 1);
if (!pUTF8)
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
memcpy(pUTF8,
pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_val,
pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_len);
pUTF8[pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_len] = '\0';
hr = UTF8ToUnicodeString(pUTF8, &pUnicode);
BAIL_ON_FAILURE(hr);
memcpy(pbExtraBytes,
pUnicode,
(wcslen(pUnicode)+1) * sizeof(WCHAR));
pADsVLV->pszTarget = (LPWSTR) pbExtraBytes;
pbExtraBytes += (wcslen(pUnicode)+1) * sizeof(WCHAR);
}
if (pPrefs->_pVLVInfo->ldvlv_context && pPrefs->_pVLVInfo->ldvlv_context->bv_val) {
memcpy(pbExtraBytes,
pPrefs->_pVLVInfo->ldvlv_context->bv_val,
pPrefs->_pVLVInfo->ldvlv_context->bv_len);
pADsVLV->lpContextID = pbExtraBytes;
pADsVLV->dwContextIDLength = pPrefs->_pVLVInfo->ldvlv_context->bv_len;
pbExtraBytes += pPrefs->_pVLVInfo->ldvlv_context->bv_len;
}
pADsSearchPref++;
}
// ADS_SEARCHPREF_SORT_ON
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SORT_ON,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_SORT_ON;
pADsSearchPref->vValue.dwType = ADSTYPE_PROV_SPECIFIC;
pADsSearchPref->vValue.ProviderSpecific.dwLength = sizeof(ADS_SORTKEY) * pPrefs->_nSortKeys;
pADsSearchPref->vValue.ProviderSpecific.lpValue = pbExtraBytes;
PADS_SORTKEY pSortKeys = (PADS_SORTKEY) pbExtraBytes;
pbExtraBytes += (sizeof(ADS_SORTKEY) * pPrefs->_nSortKeys);
DWORD i;
for (i=0; i < pPrefs->_nSortKeys; i++) {
pSortKeys[i].fReverseorder = pPrefs->_pSortKeys[i].sk_reverseorder;
pSortKeys[i].pszReserved = pPrefs->_pSortKeys[i].sk_matchruleoid;
pSortKeys[i].pszAttrType = (LPWSTR) pbExtraBytes;
memcpy(pbExtraBytes,
pPrefs->_pSortKeys[i].sk_attrtype,
(wcslen(pPrefs->_pSortKeys[i].sk_attrtype)+1) * sizeof(WCHAR)
);
pbExtraBytes += (wcslen(pPrefs->_pSortKeys[i].sk_attrtype)+1) * sizeof(WCHAR);
}
pADsSearchPref++;
}
// ADS_SEARCHPREF_ATTRIBUTE_QUERY
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ATTRIBUTE_QUERY,
pPrefs,
&fDefault));
if (!fDefault) {
pADsSearchPref->dwSearchPref = ADS_SEARCHPREF_ATTRIBUTE_QUERY;
pADsSearchPref->vValue.dwType = ADSTYPE_CASE_IGNORE_STRING;
pADsSearchPref->vValue.CaseIgnoreString = pbExtraBytes;
// copy SourceAttribute
DWORD dwLen = (wcslen(pPrefs->_pAttribScoped) + 1) * sizeof(WCHAR);
memcpy(pbExtraBytes,
pPrefs->_pAttribScoped,
dwLen);
pbExtraBytes += dwLen ;
pADsSearchPref++;
}
error:
if (pUTF8)
FreeADsMem(pUTF8);
if (pUnicode)
FreeADsMem(pUnicode);
RRETURN(hr);
}
HRESULT
CalcSpaceForSearchPrefs(
PLDAP_SEARCH_PREF pPrefs,
PDWORD pdwNumberPrefs,
PDWORD pdwNumberExtraBytes
)
{
if (!pPrefs || !pdwNumberPrefs || !pdwNumberExtraBytes)
RRETURN(E_INVALIDARG);
*pdwNumberPrefs = 0;
*pdwNumberExtraBytes = 0;
//
// Calculate the number of ADS_SEARCHPREF_INFOs required
// for search prefs that do _not_ require extra space.
// (Currently, only _SORT_ON, _DIRSYNC, _VLV, _ATTRIBUTE_QUERY
// require extra space).
//
// A ADS_SEARCHPREF_INFO is "required" if the corresponding
// search pref is not set to its default value, as determined
// by IsSearchPrefSetToDefault.
//
BOOL fDefault;
HRESULT hr = S_OK;
// ADS_SEARCHPREF_ASYNCHRONOUS
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ASYNCHRONOUS,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
// ADS_SEARCHPREF_DEREF_ALIASES
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_DEREF_ALIASES,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
// ADS_SEARCHPREF_SIZE_LIMIT
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SIZE_LIMIT,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
// ADS_SEARCHPREF_TIME_LIMIT
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TIME_LIMIT,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
// ADS_SEARCHPREF_ATTRIBTYPES_ONLY
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ATTRIBTYPES_ONLY,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
// ADS_SEARCHPREF_SEARCH_SCOPE
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SEARCH_SCOPE,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
// ADS_SEARCHPREF_TIMEOUT
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TIMEOUT,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
// ADS_SEARCHPREF_PAGESIZE
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_PAGESIZE,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
// ADS_SEARCHPREF_PAGED_TIME_LIMIT
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_PAGED_TIME_LIMIT,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
// ADS_SEARCHPREF_CHASE_REFERRALS
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_CHASE_REFERRALS,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
// ADS_SEARCHPREF_CACHE_RESULTS
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_CACHE_RESULTS,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
// ADS_SEARCHPREF_TOMBSTONE
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_TOMBSTONE,
pPrefs,
&fDefault));
if (!fDefault)
(*pdwNumberPrefs)++;
//
// _VLV, _DIRSYNC, _ATTRIBUTE_QUERY, and _SORT_ON require extra space in addition
// to the ADS_SEARCHPREF_INFO structure.
//
// ADS_SEARCHPREF_DIRSYNC
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_DIRSYNC,
pPrefs,
&fDefault));
if (!fDefault) {
(*pdwNumberPrefs)++;
if (pPrefs->_pProvSpecific && pPrefs->_pProvSpecific->dwLength > 0) {
*pdwNumberExtraBytes += pPrefs->_pProvSpecific->dwLength;
}
}
// ADS_SEARCHPREF_VLV
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_VLV,
pPrefs,
&fDefault));
if (!fDefault) {
(*pdwNumberPrefs)++;
*pdwNumberExtraBytes += sizeof(ADS_VLV);
if (pPrefs->_pVLVInfo->ldvlv_context) {
*pdwNumberExtraBytes += pPrefs->_pVLVInfo->ldvlv_context->bv_len;
}
if (pPrefs->_pVLVInfo->ldvlv_attrvalue) {
// As stored, the string is a UTF-8 string that is not NULL-terminated.
// We need to calculate the size of a NULL-terminated Unicode string.
int cch = MultiByteToWideChar(CP_UTF8,
0,
pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_val,
pPrefs->_pVLVInfo->ldvlv_attrvalue->bv_len,
NULL,
0);
if (!cch)
BAIL_ON_FAILURE(hr = E_FAIL);
// add one WCHAR for NULL terminator
*pdwNumberExtraBytes += ((cch*sizeof(WCHAR)) + sizeof(WCHAR));
}
}
// ADS_SEARCHPREF_SORT_ON
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_SORT_ON,
pPrefs,
&fDefault));
if (!fDefault) {
(*pdwNumberPrefs)++;
*pdwNumberExtraBytes += (sizeof(ADS_SORTKEY) * pPrefs->_nSortKeys);
DWORD i;
for (i=0; i<pPrefs->_nSortKeys; i++) {
*pdwNumberExtraBytes += ((wcslen(pPrefs->_pSortKeys[i].sk_attrtype)+1) * sizeof(WCHAR));
}
}
// ADS_SEARCHPREF_ATTRIBUTE_QUERY
BAIL_ON_FAILURE(hr = IsSearchPrefSetToDefault(ADS_SEARCHPREF_ATTRIBUTE_QUERY,
pPrefs,
&fDefault));
if (!fDefault) {
(*pdwNumberPrefs)++;
*pdwNumberExtraBytes += ((wcslen(pPrefs->_pAttribScoped) + 1) * sizeof(WCHAR));
}
error:
RRETURN(hr);
}
//
// This function tests whether a given search pref is set
// to it's default value.
//
// Important: This function considers the "default value"
// to be the value currently set in CLDAPGenObject::InitSearchPrefs.
// If you ever change those defaults, update this function.
//
HRESULT
IsSearchPrefSetToDefault(
ADS_SEARCHPREF_ENUM pref,
PLDAP_SEARCH_PREF pPrefs,
PBOOL pfDefault
)
{
if (!pPrefs || !pfDefault)
RRETURN(E_INVALIDARG);
*pfDefault = TRUE;
switch(pref) {
case ADS_SEARCHPREF_ASYNCHRONOUS:
// default: not async
if (pPrefs->_fAsynchronous)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_DEREF_ALIASES:
// default: do not deref
if (pPrefs->_dwDerefAliases)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_SIZE_LIMIT:
// default: no size limit
if (pPrefs->_dwSizeLimit)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_TIME_LIMIT:
// default: no time limit
if (pPrefs->_dwTimeLimit)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_ATTRIBTYPES_ONLY:
// default: not attribtypes only
if (pPrefs->_fAttrsOnly)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_SEARCH_SCOPE:
// default: LDAP_SCOPE_SUBTREE
if (pPrefs->_dwSearchScope != LDAP_SCOPE_SUBTREE)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_TIMEOUT:
// default: no timeout
if (pPrefs->_timeout.tv_sec || pPrefs->_timeout.tv_usec)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_PAGESIZE:
// default: no pagesize
if (pPrefs->_dwPageSize)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_PAGED_TIME_LIMIT:
// default: no paged time limit
if (pPrefs->_dwPagedTimeLimit)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_CHASE_REFERRALS:
// default: ADS_CHASE_REFERRALS_EXTERNAL
if (pPrefs->_dwChaseReferrals != ADS_CHASE_REFERRALS_EXTERNAL)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_SORT_ON:
// default: no sorting
if (pPrefs->_pSortKeys)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_CACHE_RESULTS:
// default: cache results
if (!pPrefs->_fCacheResults)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_DIRSYNC:
// default: not a dirsync search
if (pPrefs->_fDirSync)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_TOMBSTONE:
// default: don't include tombstones
if (pPrefs->_fTombStone)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_VLV:
// default: not a VLV search
if (pPrefs->_pVLVInfo)
*pfDefault = FALSE;
break;
case ADS_SEARCHPREF_ATTRIBUTE_QUERY:
// default: not an attribute-scoped query search
if (pPrefs->_pAttribScoped)
*pfDefault = FALSE;
break;
default:
RRETURN(E_INVALIDARG);
}
RRETURN(S_OK);
}
#endif