//--------------------------------------------------------------------------- // // 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_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